-
Notifications
You must be signed in to change notification settings - Fork 248
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added ton-connect documentation into docs
- Loading branch information
1 parent
fb6c407
commit 94e99b2
Showing
8 changed files
with
838 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Protocol specifications | ||
|
||
## Who is this section for? | ||
|
||
- If you implement an SDK | ||
- If you implement a wallet | ||
- If you want to learn how TON Connect works | ||
|
||
## Sections overview | ||
|
||
* [Protocol workflow](/develop/dapps/ton-connect/protocol/workflow): an overview of all the protocols. | ||
* [Bridge API](/develop/dapps/ton-connect/protocol/bridge) specifies how the data is transmitted between the app and the wallet. | ||
* [Session protocol](/develop/dapps/ton-connect/protocol/session) ensures end-to-end encrypted communication over the bridge. | ||
* [Requests protocol](/develop/dapps/ton-connect/protocol/requests-responses) defines requests and responses for the app and the wallet. | ||
* [Wallet guidelines](/develop/dapps/ton-connect/protocol/wallet-guidelines) defines guidelines for wallet developers. | ||
|
||
## FAQ | ||
|
||
#### I am building an HTML/JS app, what should I read? | ||
|
||
Simply use the [Supported SDKs](/develop/dapps/ton-connect/developers) and do not worry about the underlying protocols. | ||
|
||
#### I need an SDK in my favorite language | ||
|
||
Please take the [JS SDK](/develop/dapps/ton-connect/developers) as a reference and check out the protocol docs above. | ||
|
||
#### How do you detect whether the app is embedded in the wallet? | ||
|
||
JS SDK does that for you; just get wallets list `connector.getWallets()` and check `embedded` property of the corresponding list item. If you build your own SDK you should check `window.[targetWalletJsBridgeKey].tonconnect.isWalletBrowser`. | ||
|
||
#### How do you detect if the wallet is a browser extension? | ||
|
||
Like with embedded apps (see above), JS SDK detects it for you via `injected` property of the corresponding `connector.getWallets()` list item. If you build your own SDK you should check that `window.[targetWalletJsBridgeKey].tonconnect` exists. | ||
|
||
#### How to implement backend authorization with tonconnect? | ||
|
||
[See an example of dapp-backend](https://github.com/ton-connect/demo-dapp-backend) | ||
|
||
#### How do I make my own bridge? | ||
|
||
You don’t need to, unless you are building a wallet. | ||
|
||
If you build a wallet, you will need to provide a bridge. See our [reference implementation in Go](https://github.com/ton-connect/bridge). | ||
|
||
Keep in mind that the wallet’s side of the bridge API is not mandated. | ||
|
||
For a quick start you can use the common TON Connect bridge https://bridge.tonapi.io/bridge. | ||
|
||
#### I make a wallet, how do I add it to the list of wallets? | ||
|
||
Submit a pull request for the [wallets-list](https://github.com/ton-blockchain/wallets-list) repository and fill our all the necessary metadata. | ||
|
||
Apps may also add wallets directly through the SDK. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
# Bridge API | ||
|
||
Bridge is a transport mechanism to deliver messages from the app to the wallet and vice versa. | ||
|
||
* **Bridge is maintained by the wallet provider**. App developers do not have to choose or build a bridge. Each wallet’s bridge is listed in the [wallets-list](https://github.com/ton-blockchain/wallets-list) config. | ||
* **Messages are end-to-end encrypted.** Bridge does not see the contents or long-term identifiers of the app or wallet. | ||
* **Communication is symmetrical.** Bridge does not distinguish between apps and wallets: both are simply clients. | ||
* Bridge keeps separate queues of messages for each recipient’s **Client ID**. | ||
|
||
Bridge comes in two flavors: | ||
|
||
- [HTTP Bridge](#http-bridge): for the external apps and services. | ||
- [JS Bridge](#js-bridge): for apps opened within the wallet; or when the wallet is a browser extension. | ||
|
||
## HTTP Bridge | ||
|
||
Client with ID **A** connects to the bridge to listen to incoming requests. | ||
|
||
**Client ID is semi-private:** apps and wallets are not supposed to share their IDs with other entities to avoid having their messages removed unexpectedly. | ||
|
||
**Client can subscribe on few Client IDs** - in this case it should enumerate IDs separated with commas. For example: `?client_id=<A1>,<A2>,<A3>` | ||
|
||
```tsx | ||
request | ||
GET /events?client_id=<to_hex_str(A)> | ||
|
||
Accept: text/event-stream | ||
``` | ||
|
||
**Subscribing to the bridge second (any other) time** | ||
|
||
```tsx | ||
request | ||
GET /events?client_id=<to_hex_str(A)>&last_event_id=<lastEventId> | ||
Accept: text/event-stream | ||
``` | ||
|
||
**lastEventId** – the eventId of the last SSE event wallet got over the bridge. In this case wallet will fetch all the events which happened after the last connection. | ||
|
||
Sending message from client A to client B. Bridge returns error if ttl is too high. | ||
|
||
```tsx | ||
request | ||
POST /message?client_id=<to_hex_str(A)>?to=<to_hex_str(B)>&ttl=300&topic=<sendTransaction|signData> | ||
body: <base64_encoded_message> | ||
``` | ||
|
||
|
||
The `topic` [optional] query parameter can be used by the bridge to deliver the push notification to the wallet. If the parameter is given, it must correspond to the RPC method called inside the encrypted `message`. | ||
|
||
Bridge buffers messages up to TTL (in secs), but removes them as soon as the recipient receives the message. | ||
|
||
If the TTL exceeds the hard limit of the bridge server, it should respond with HTTP 400. Bridges should support at least 300 seconds TTL. | ||
|
||
When the bridge receives a message `base64_encoded_message` from client `A` addressed to client `B`, it generates a message `BridgeMessage`: | ||
|
||
```js | ||
{ | ||
"from": <to_hex_str(A)>, | ||
"message": <base64_encoded_message> | ||
} | ||
``` | ||
|
||
and sends it to the client B via SSE connection | ||
```js | ||
resB.write(BridgeMessage) | ||
``` | ||
|
||
### Heartbeat | ||
|
||
To keep the connection, bridge server should periodically send a "heartbeat" message to the SSE channel. Client should ignore such messages. | ||
So, the bridge heartbeat message is a string with word `heartbeat`. | ||
|
||
|
||
## Universal link | ||
|
||
When the app initiates the connection it sends it directly to the wallet via the QR code or a universal link. | ||
|
||
```bash | ||
https://<wallet-universal-url>? | ||
v=2& | ||
id=<to_hex_str(A)>& | ||
r=<urlsafe(json.stringify(ConnectRequest))>& | ||
ret=back | ||
``` | ||
|
||
Parameter **v** specifies the protocol version. Unsupported versions are not accepted by the wallets. | ||
|
||
Parameter **id** specifies app’s Client ID encoded as hex (without '0x' prefix). | ||
|
||
Parameter **r** specifies URL-safe json [ConnectRequest](/develop/dapps/ton-connect/protocol/requests-responses#initiating-connection). | ||
|
||
Parameter **ret** (optional) specifies return strategy for the deeplink when user signs/declines the request. | ||
- 'back' (default) means return to the app which initialized deeplink jump (e.g. browser, native app, ...), | ||
- 'none' means no jumps after user action; | ||
- a URL: wallet will open this URL after completing the user's action. Note, that you shouldn't pass your app's URL if it is a webpage. This option should be used for native apps to work around possible OS-specific issues with `'back'` option. | ||
|
||
`ret` parameter should be supported for empty deeplinks -- it might be used to specify the wallet behavior after other actions confirmation (send transaction, sign raw, ...). | ||
```bash | ||
https://<wallet-universal-url>?ret=back | ||
``` | ||
|
||
|
||
The link may be embedded in a QR code or clicked directly. | ||
|
||
The initial request is unencrypted because (1) there is no personal data being communicated yet, (2) app does not even know the identity of the wallet. | ||
|
||
### Unified deeplink `tc` | ||
In addition to its own universal link, the wallet must support the unified deeplink. | ||
|
||
This allows applications to create a single qr code, which can be used to connect to any wallet. | ||
|
||
More specifically, the wallet must support `tc://` deeplink as well as its own `<wallet-universal-url>`. | ||
|
||
Therefore, the following `connect request` must be processed by the wallet: | ||
|
||
```bash | ||
tc://? | ||
v=2& | ||
id=<to_hex_str(A)>& | ||
r=<urlsafe(json.stringify(ConnectRequest))>& | ||
ret=back | ||
``` | ||
|
||
|
||
## JS bridge | ||
|
||
Used by the embedded apps via the injected binding `window.<wallet-js-bridge-key>.tonconnect`. | ||
|
||
`wallet-js-bridge-key` can be specified in the [wallets list](https://github.com/ton-blockchain/wallets-list) | ||
|
||
JS bridge runs on the same device as the wallet and the app, so communication is not encrypted. | ||
|
||
The app works directly with plaintext requests and responses, without session keys and encryption. | ||
|
||
```tsx | ||
interface TonConnectBridge { | ||
deviceInfo: DeviceInfo; // see Requests/Responses spec | ||
walletInfo?: WalletInfo; | ||
protocolVersion: number; // max supported Ton Connect version (e.g. 2) | ||
isWalletBrowser: boolean; // if the page is opened into wallet's browser | ||
connect(protocolVersion: number, message: ConnectRequest): Promise<ConnectEvent>; | ||
restoreConnection(): Promise<ConnectEvent>; | ||
send(message: AppRequest): Promise<WalletResponse>; | ||
listen(callback: (event: WalletEvent) => void): () => void; | ||
} | ||
``` | ||
|
||
Just like with the HTTP bridge, wallet side of the bridge does not receive the app requests except for [ConnectRequest](/develop/dapps/ton-connect/protocol/requests-responses#initiating-connection) until the session is confirmed by the user. Technically, the messages arrive from the webview into the bridge controller, but they are silently ignored. | ||
|
||
SDK around the implements **autoconnect()** and **connect()** as silent and non-silent attempts at establishing the connection. | ||
|
||
### walletInfo (optional) | ||
Represents wallet metadata. Might be defined to make an injectable wallet works with TonConnect even if the wallet is not listed in the [wallets-list.json](https://github.com/ton-blockchain/wallets-list). | ||
|
||
Wallet metadata format: | ||
```ts | ||
interface WalletInfo { | ||
name: string; | ||
image: <png image url>; | ||
tondns?: string; | ||
about_url: <about page url>; | ||
} | ||
``` | ||
|
||
Detailed properties description: https://github.com/ton-blockchain/wallets-list#entry-format. | ||
|
||
If `TonConnectBridge.walletInfo` is defined and the wallet is listed in the [wallets-list.json](https://github.com/ton-blockchain/wallets-list), `TonConnectBridge.walletInfo` properties will override corresponding wallet properties from the wallets-list.json. | ||
|
||
|
||
### connect() | ||
|
||
Initiates connect request, this is analogous to QR/link when using the HTTP bridge. | ||
|
||
If the app was previously approved for the current account — connects silently with ConnectEvent. Otherwise shows confirmation dialog to the user. | ||
|
||
You shouldn't use the `connect` method without explicit user action (e.g. connect button click). If you want automatically try to restore previous connection, you should use the `restoreConnection` method. | ||
|
||
### restoreConnection() | ||
|
||
Attempts to restore the previous connection. | ||
|
||
If the app was previously approved for the current account — connects silently with the new `ConnectEvent` with only a `ton_addr` data item. | ||
|
||
|
||
Otherwise returns `ConnectEventError` with error code 100 (Unknown app). | ||
|
||
|
||
### send() | ||
|
||
Sends a [message](/develop/dapps/ton-connect/protocol/requests-responses#messages) to the bridge, excluding the ConnectRequest (that goes into QR code when using HTTP bridge and into connect when using JS Bridge). | ||
Directly returns promise with WalletResponse, do you don't need to wait for responses with `listen`; | ||
|
||
### listen() | ||
|
||
Registers a listener for events from the wallet. | ||
|
||
Returns unsubscribe function. | ||
|
||
Currently, only `disconnect` event is available. Later there will be a switch account event and other wallet events. |
Oops, something went wrong.