Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 228 additions & 3 deletions requests-responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,12 @@ type DeviceInfo = {
appVersion: string; // e.g. "2.3.367"
maxProtocolVersion: number;
features: Feature[]; // list of supported features and methods in RPC
// Currently there is only one feature -- 'SendTransaction';
}

type Feature = { name: 'SendTransaction', maxMessages: number } | // `maxMessages` is maximum number of messages in one `SendTransaction` that the wallet supports
{ name: 'SignData' };
type Feature =
| { name: 'SendTransaction'; maxMessages: number } // `maxMessages` is the maximum number of messages in a single `SendTransaction` that the wallet supports
| { name: 'SignData'; types: ('text' | 'binary' | 'cell')[] } // `types` specifies the supported data types for the `SignData` method
| { name: 'Subscription'; versions: { v2: boolean } }; // `versions` indicates which subscription versions are supported for `CreateSubscription` and `CancelSubscription` methods (currently only 'v2' is supported)

type ConnectItemReply = TonAddressItemReply | TonProofItemReply ...;

Expand Down Expand Up @@ -217,6 +218,8 @@ The signature must be verified by public key:
- sendTransaction
- signData
- disconnect
- createSubscriptionV2
- cancelSubscriptionV2

**Available events:**

Expand Down Expand Up @@ -306,9 +309,11 @@ Message structure:

<details>
<summary>Common cases</summary>

1. No payload, no stateInit: simple transfer without a message.
2. payload is prefixed with 32 zero bits, no stateInit: simple transfer with a text message.
3. No payload or prefixed with 32 zero bits; stateInit is present: deployment of the contract.

</details>

<details>
Expand Down Expand Up @@ -365,6 +370,7 @@ interface SendTransactionResponseError {
| 300 | User declined the transaction |
| 400 | Method not supported |

* Wallet MUST NOT allow signing a message whose destination is any wallet plugin via TonConnect (i.e., if the dApp requests the wallet to sign a message addressed to its plugin)

#### Sign Data

Expand Down Expand Up @@ -549,6 +555,225 @@ If the data needs to be human-readable—but is not textual—use the **Cell** f

Otherwise, use Binary format.

#### Subscriptions

##### Create subscription (v2)

App sends **CreateSubscriptionV2Request**:

```tsx
interface CreateSubscriptionV2Request {
method: 'createSubscriptionV2';
params: [<subscription-v2-payload>];
id: string;
}
```

Where `<subscription-v2-payload>` is JSON with the following properties:

* `valid_until` (integer, optional): UNIX timestamp. After this moment the transaction is invalid.
* `network` (NETWORK, optional): The network (mainnet or testnet) where DApp intends to send the transaction. If not set, the transaction is sent to the network currently set in the wallet, but this is not safe and DApp should always strive to set the network. If the `network` parameter is set, but the wallet has a different network set, the wallet should show an alert and DO NOT ALLOW TO SEND this transaction.
* `from` (string in <wc>:<hex> format, optional) - The sender address from which DApp intends to send the transaction. If not set, wallet allows user to select the sender's address at the moment of transaction approval. If `from` parameter is set, the wallet should DO NOT ALLOW user to select the sender's address; If sending from the specified address is impossible, the wallet should show an alert and DO NOT ALLOW TO SEND this transaction.
* `subscription` (object): Subscription details (see **Subscription structure** below).

Subscription structure:

* `beneficiary` (string): TON address that receives the subscription payments (`0:<hex>` raw or user-friendly base64).
* `id` (number): Subscription identifier. Set by the initiator of the subscription. This field, together with beneficiary and from, forms a quasi-unique key identifying the subscription and is used to derive the initial state of the subscription extension. Can be reused to update an existing subscription
* `period` (integer): Billing period in **seconds**; **MUST** be a multiple of `604800` (7 days), `2592000` (30 days), `2629800` (calendar month), or `31557600` (calendar year) and **MUST NOT be** `0`.
* `amount` (decimal string): Number of nanocoins debited on each charge.
* `first_charge_date` (integer, optional): UNIX timestamp (seconds) of the first charge. If omitted, the wallet charges immediately after user confirmation.
* `metadata` (object, optional): Human-readable information about the plan:

* `logo` (string): URL of the plan’s PNG/SVG logo.
* `name` (string): Plan name.
* `description` (string): Description shown in the wallet.
* `link` (string): Public URL with detailed information.
* `tos` (string): Terms-of-Service URL.
* `merchant` (string): Merchant name shown in the wallet.
* `website` (string): Merchant website.
* `category` (string, optional): Category slug such as `"video"` or `"games"`.

<details>
<summary>Example — request payload</summary>

```json5
{
"valid_until": 1721011200,
"network": "-239", // enum NETWORK { MAINNET = '-239', TESTNET = '-3'}
"from": "0:348bcf827469c5fc38541c77fdd91d4e347eac200f6f2d9fd62dc08885f0415f",
"subscription": {
"beneficiary": "EQApwowlR6X54bXoso6orKCzCNm9ily8pAFy5vTwmsQ2Wqin",
"id": 1,
"period": 1209600, // once every 14 days
"amount": "60000000",
"first_charge_date": 1754006400,
"metadata": {
"logo": "https://myapp.com/logo.png",
"name": "Pro Plan",
"description": "Access to all premium features.",
"link": "https://myapp.com/plan-details",
"tos": "https://myapp.com/terms",
"merchant": "Example Service",
"website": "https://myapp.com",
"category": "productivity"
}
}
}
```
</details>

Wallet replies with **CreateSubscriptionV2Response**:

```tsx
type CreateSubscriptionV2Response =
| CreateSubscriptionV2ResponseSuccess
| CreateSubscriptionV2ResponseError;

interface CreateSubscriptionV2ResponseSuccess {
result: {
boc: string; // base64-encoded BoC of the created transaction for create subscription
},
id: string;
}

interface CreateSubscriptionV2ResponseError {
error: { code: number; message: string };
id: string;
}
```

**Error codes**

| code | description |
| ---- | ------------------------- |
| 0 | Unknown error |
| 1 | Bad request |
| 100 | Unknown app |
| 300 | User declined the request |
| 400 | Method not supported |

<details>
<summary>Example&nbsp;— success / error</summary>

**Success**

```json5
{
"result": { "boc": "te6ccgEBAQEAXwAA…" },
"id": "42"
}
```

**Error (300 User declined)**

```json5
{
"error": { "code": 300, "message": "User declined the transaction" },
"id": "42"
}
```
</details>

> **Wallet behaviour.** After user approval, the wallet **MUST**:
> - Deploy the subscription-extension contract with the supplied parameters. TODO: add link to contract
> - Add the deployed extension address to the wallet-contract’s allowed-plugins list.
> - **MUST NOT** store unencrypted metadata on-chain. Metadata **MUST** be encrypted inside the wallet with a symmetric key derived locally. TODO: add link to encryption scheme (to be specified in a future revision)

---

##### Cancel subscription (v2)

App sends **CancelSubscriptionV2Request**:

```tsx
interface CancelSubscriptionV2Request {
method: 'cancelSubscriptionV2';
params: [<cancel-subscription-v2-payload>];
id: string;
}
```

Where `<cancel-subscription-v2-payload>` is JSON with the following properties:

* `valid_until` (integer, optional): UNIX timestamp. After this moment the transaction is invalid.
* `network` (NETWORK, optional): The network (mainnet or testnet) where DApp intends to send the transaction. If not set, the transaction is sent to the network currently set in the wallet, but this is not safe and DApp should always strive to set the network. If the `network` parameter is set, but the wallet has a different network set, the wallet should show an alert and DO NOT ALLOW TO SEND this transaction.
* `from` (string in <wc>:<hex> format, optional) - The sender address from which DApp intends to send the transaction. If not set, wallet allows user to select the sender's address at the moment of transaction approval. If `from` parameter is set, the wallet should DO NOT ALLOW user to select the sender's address; If sending from the specified address is impossible, the wallet should show an alert and DO NOT ALLOW TO SEND this transaction.
- `extensionAddress` (string) — address of the deployed subscription‑extension contract (raw `0:<hex>` or user‑friendly base64).

Wallet replies with **CancelSubscriptionV2Response**:

```tsx
type CancelSubscriptionV2Response =
| CancelSubscriptionV2ResponseSuccess
| CancelSubscriptionV2ResponseError;

interface CancelSubscriptionV2ResponseSuccess {
result: {
boc: string; // base64-encoded BoC of the created transaction for cancel subscription
},
id: string;
}

interface CancelSubscriptionV2ResponseError {
error: { code: number; message: string };
id: string;
}
```

**Error codes**

| code | description |
| ---- | ------------------------- |
| 0 | Unknown error |
| 1 | Bad request |
| 100 | Unknown app |
| 300 | User declined the request |
| 400 | Method not supported |
| 404 | Extension not found |

<details>
<summary>Example&nbsp;— request / success / error</summary>

**Request**

```json5
{
"method": "cancelSubscriptionV2",
"params": [{
"valid_until": 1721011200,
"network": "-239", // enum NETWORK { MAINNET = '-239', TESTNET = '-3'}
"from": "0:348bcf827469c5fc38541c77fdd91d4e347eac200f6f2d9fd62dc08885f0415f",
"extensionAddress": "EQApwowlR6X54bXoso6orKCzCNm9ily8pAFy5vTwmsQ2Wqin"
}],
"id": "43"
}
````

**Success**

```json5
{
"result": { "boc": "te6ccgEBAQEAKAAA…" },
"id": "43"
}
```

**Error (404 Extension not found)**

```json5
{
"error": { "code": 404, "message": "Extension not found" },
"id": "43"
}
```
</details>

> **Wallet behaviour.** After user approval, the wallet **MUST**:
> - Send a cancellation message to the subscription-extension contract.
> - Remove the extension address from the wallet-contract’s allowed-plugins list.
> - **MUST NOT** store unencrypted metadata on-chain. Metadata **MUST** be encrypted inside the wallet with a symmetric key derived locally. TODO: add link to encryption scheme (to be specified in a future revision)

#### Disconnect operation
When user disconnects the wallet in the dApp, dApp should inform the wallet to help the wallet save resources and delete unnecessary session.
Allows the wallet to update its interface to the disconnected state.
Expand Down