Skip to content

Commit

Permalink
added ton-connect documentation into docs
Browse files Browse the repository at this point in the history
  • Loading branch information
SwiftAdviser committed Aug 7, 2023
1 parent fb6c407 commit 94e99b2
Show file tree
Hide file tree
Showing 8 changed files with 838 additions and 38 deletions.
25 changes: 6 additions & 19 deletions docs/develop/dapps/ton-connect/integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ In this tutorial, we’ll create a sample web app that supports TON Connect 2.0

## Documentation links

1. [TON Connect SDK documentation](https://www.npmjs.com/package/@tonconnect/sdk)
2. [Wallet-application message exchange protocol](https://github.com/ton-connect/docs/blob/main/requests-responses.md), includes manifest format.
1. [@tonconnect/sdk documentation](https://www.npmjs.com/package/@tonconnect/sdk)
2. [Wallet-application message exchange protocol](https://github.com/ton-connect/docs/blob/main/requests-responses.md)
3. [Tonkeeper implementation of wallet side](https://github.com/tonkeeper/wallet/tree/main/src/tonconnect)

## Prerequisites
Expand All @@ -14,7 +14,7 @@ In order for connectivity to be fluent between apps and wallets, the web app mus

## Getting wallets support list

To increase the overall adoption of TON Blockchain, it is necessary that TON Connect 2.0 is able to facilitate a vast number of application and wallet connectivity integrations. Of late and of significant importance, the ongoing development of TON Connect 2.0 has allowed for the connection of the Tonkeeper and OpenMask wallets with various TON Ecosystem Apps. It is our mission to eventually allow for the exchange of data between applications and all wallet types built on TON via the TON Connect protocol. For now, this is realized by providing the ability for TON Connect to load an extensive list of available wallets currently operating within the TON Ecosystem.
To increase the overall adoption of TON Blockchain, it is necessary that TON Connect 2.0 is able to facilitate a vast number of application and wallet connectivity integrations. Of late and of significant importance, the ongoing development of TON Connect 2.0 has allowed for the connection of the Tonkeeper, TonHub, MyTonWallet and other wallets with various TON Ecosystem Apps. It is our mission to eventually allow for the exchange of data between applications and all wallet types built on TON via the TON Connect protocol. For now, this is realized by providing the ability for TON Connect to load an extensive list of available wallets currently operating within the TON Ecosystem.

At the moment our sample web app enables the following:

Expand Down Expand Up @@ -46,7 +46,7 @@ For learning purposes, let's take a looks at the HTML page described by the foll

If you load this page in browser and look into console, you may get something like that:

```js
```bash
> Array [ {…}, {…} ]

0: Object { name: "Tonkeeper", imageUrl: "https://tonkeeper.com/assets/tonconnect-icon.png", aboutUrl: "https://tonkeeper.com", … }
Expand All @@ -60,15 +60,6 @@ If you load this page in browser and look into console, you may get something li
name: "Tonkeeper"
tondns: "tonkeeper.ton"
universalLink: "https://app.tonkeeper.com/ton-connect"

1: Object { name: "OpenMask", imageUrl: "https://raw.githubusercontent.com/OpenProduct/openmask-extension/main/public/openmask-logo-288.png", aboutUrl: "https://www.openmask.app/", … }
aboutUrl: "https://www.openmask.app/"
embedded: false
imageUrl: "https://raw.githubusercontent.com/OpenProduct/openmask-extension/main/public/openmask-logo-288.png"
injected: false
jsBridgeKey: "openmask"
name: "OpenMask"
tondns: undefined
```
According to TON Connect 2.0 specifications, wallet app information always makes use of the following format:
Expand Down Expand Up @@ -240,11 +231,7 @@ Upon clicking the mobile phone link, Tonkeeper automatically opens and then clos
`Error: [TON_CONNECT_SDK_ERROR] Can't get null/tonconnect-manifest.json`.

This means the application manifest must be available for download.

### Logging in with OpenMask

OpenMask didn't inject its information in the window, so connecting with it failed. The most probable reason is because a local page for the web app was used.


## Connection with using app manifest

Starting from this point forward, it is necessary to host user files (mostly tonconnect-manifest.json) somewhere. In this instance we’ll use the manifest from another web application. This however is not recommended for production environments, but allowed for testing purposes.
Expand Down Expand Up @@ -292,7 +279,7 @@ Therefore, the user is able to accept the same login request if the link is save
Afterwards, the login request is accepted and is immediately reflected in the browser console as follows:
```js
```bash
22:40:13.887 Connection status:
Object { device: {…}, provider: "http", account: {…} }
account: Object { address: "0:b2a1ec...", chain: "-239", walletStateInit: "te6cckECFgEAAwQAAgE0ARUBFP8A9..." }
Expand Down
53 changes: 53 additions & 0 deletions docs/develop/dapps/ton-connect/protocol/README.md
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.
202 changes: 202 additions & 0 deletions docs/develop/dapps/ton-connect/protocol/bridge.md
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 apps 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 accountconnects 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 accountconnects 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.
Loading

0 comments on commit 94e99b2

Please sign in to comment.