Skip to content

Commit fad8dd9

Browse files
committed
improve integrating wallet doc
1 parent 17c414d commit fad8dd9

File tree

1 file changed

+188
-5
lines changed

1 file changed

+188
-5
lines changed

docs/develop/dapps/ton-connect/protocol/integrating-wallet.md

Lines changed: 188 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111
## How to Use
1212

1313
### Step 1: Review Specifications
14-
Begin by familiarizing yourself with the core specifications and documentation:
14+
15+
:::caution **IMPORTANT**
16+
17+
The main answers to your questions are emphasized within the specification. Be sure to refer to these highlighted sections for critical information.
18+
19+
:::
20+
1521
- [TON Connect Specification](https://github.com/ton-blockchain/ton-connect)
1622
- [Protocol Workflow](https://github.com/ton-blockchain/ton-connect/blob/main/workflows.md)
1723
- [Bridge API](https://github.com/ton-blockchain/ton-connect/blob/main/bridge.md)
@@ -39,7 +45,46 @@ Use the [@tonconnect/protocol package](https://github.com/ton-connect/sdk/tree/m
3945
Also, pay close attention to the creation of encrypted communication channels between the wallet and the dApp. You can find detailed information in the [Session Protocol documentation](https://github.com/ton-blockchain/ton-connect/blob/main/session.md). For a practical implementation reference, check out the [@tonconnect/protocol package](https://github.com/ton-connect/sdk/blob/main/packages/protocol/src/crypto/session-crypto.ts).
4046

4147
### Step 4: Implement Wallet State Init
42-
Generate the StateInit for your wallet using parameters like wallet ID and public key. An example implementation can be found in the guide.
48+
49+
The wallet state init is a base64-encoded BOC containing the standard `StateInit` structure for all contracts in TON.
50+
51+
To create the `StateInit` for the wallet, you will need various parameters depending on the wallet version, but the data set always includes the wallet ID and the public key.
52+
53+
- **Wallet ID**: Set the wallet ID to `698983191`. This value is the sum of the "magic number" `698983191` (which is the first 4 bytes of the reversed hash of the zero state) and the workchain number (0 for users).
54+
- **Public Key**: Generate the public key from the seed.
55+
- **Wallet Version**: Determine which version of the wallet is being used. TON has several wallet versions, but most often `v4r2` or `v3r2` is used.
56+
57+
Regardless of the version, the `StateInit` is formed in the same way:
58+
59+
```ts
60+
import { beginCell, storeStateInit } from '@ton/core';
61+
62+
const stateInitCell = beginCell().store(storeStateInit(walletContract.init)).endCell();
63+
const stateInitBocBase64 = stateInitCell.toBoc().toString('base64');
64+
```
65+
66+
Here, walletContract.init is a JS structure in the format { code: codeCell, data: dataCell }. If you are using @ton/core, you can generate such structures automatically:
67+
68+
```ts
69+
import { WalletContractV4, WalletContractV3R2 } from '@ton/core';
70+
71+
const walletContractV4 = WalletContractV4.create({ workchain: 0, publicKey: publicKey });
72+
const walletContractV3R2 = WalletContractV3R2.create({ workchain: 0, publicKey: publicKey });
73+
```
74+
#### Creating a Signature for TON Proof
75+
To create a signature for the TON proof, you need to compute the required payload according to the [TON Connect Address Proof Signature Documentation](https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#address-proof-signature-ton_proof), or use the [TON Proof Service Example](https://github.com/ton-connect/demo-dapp-with-react-ui/blob/master/src/server/services/ton-proof-service.ts#L29-L116), and then sign it using the secret key.
76+
77+
#### Creating a Signature for a Message
78+
For creating a signature for a message, you can either use the ready-made method of the wallet contract [v4 Wallet Contract Signature Method](https://github.com/ton-org/ton/blob/master/src/wallets/WalletContractV4.ts#L93-L112), or use it as a reference for your own implementation.
79+
80+
#### Resources
81+
82+
Here are the links to the wallet contracts implementations:
83+
84+
- [v4 Wallet Contract](https://github.com/ton-org/ton/blob/master/src/wallets/WalletContractV4.ts)
85+
- [v3r2 Wallet Contract](https://github.com/ton-org/ton/blob/master/src/wallets/WalletContractV3R2.ts)
86+
87+
We also have a guide on wallet smart contracts that can be useful for many other questions: [TON Wallet Smart Contracts Guide](https://docs.ton.org/develop/smart-contracts/tutorials/wallet).
4388

4489
### Step 5: Validate Parameters
4590
In addition to the guidelines, here is further information for validating request fields. Please review the [guidelines](https://github.com/ton-blockchain/ton-connect/blob/main/wallet-guidelines.md) before examining the information below.
@@ -64,14 +109,152 @@ In addition to the guidelines, here is further information for validating reques
64109
- **`ret` Contains an Unknown Value:** The wallet should follow the strategy as if `ret` was `none`.
65110

66111
### Step 6: Demo Integration
67-
To test and demonstrate the integration, use the [demo dapp with wallet](https://github.com/ton-connect/demo-dapp-with-wallet). This repository provides a starting point for setting up a demo environment. Also try some real world examples:
112+
To test and demonstrate the integration, you can use the following resources:
113+
- [Demo Dapp](https://github.com/ton-connect/demo-dapp-with-wallet) with Wallet: This repository provides a starting point for setting up a demo environment to test wallet integration.
114+
- [TON Proof Demo App](https://github.com/liketurbo/demo-dapp-with-backend/tree/js-demo): This app allows you to verify TON proof functionality in a practical setting.
115+
116+
For real-world testing and examples, try the following platforms:
68117

69118
- **[TON Stakers](https://app.tonstakers.com):** Test wallet connection, stake, and unstake TON.
70119
- **[STON.fi](https://app.ston.fi):** Test wallet connection, swap TON for USDT, and manage liquidity.
71120
- **[GetGems](https://getgems.io):** Test wallet connection, mint, list, and purchase NFTs.
72121

73122
### Emulating Transactions
74-
Use the `/v2/wallet/emulate` method from [tonapi.io](https://tonapi.io/api-v2) to emulate transaction chains. This helps in testing and verifying the transaction flow without using real assets.
123+
#### Handling Messages from TON Connect
124+
125+
When using TON Connect, you will receive multiple messages, each containing a `body` and `init`. Simply displaying these messages as they are might be acceptable for basic functionality, but it is not sufficient for ensuring security.
126+
127+
#### Initial Implementation
128+
129+
For the first version, displaying the messages as they are may be sufficient. However, in future updates, it would be beneficial to parse these messages or emulate a transaction chain to provide the user with more detailed and useful information.
130+
131+
#### Recommended Approaches
132+
133+
You can enhance your implementation by using the following methods:
134+
135+
- **TON API**: Utilize the `/v2/wallet/emulate` method from [TON API v2](https://tonapi.io/api-v2).
136+
137+
:::tip
138+
139+
When emulating transactions, it's essential to keep the following points in mind:
140+
141+
1. **Do Not Use the Real Wallet’s Secret Key**: Always avoid using the actual wallet's secret key during emulation. Instead, sign the transaction with a fake key, such as an empty buffer, to ensure security.
142+
143+
2. **Ensure the Real Wallet Balance is Used for Emulation**: For accurate emulation, the real wallet balance must be provided. If the balance is empty, the emulation process will fail and return an error. During testing, you may uncomment the line to specify a larger balance than what actually exists, but remember to revert to the real balance in production.
144+
145+
:::
146+
147+
<details>
148+
<summary>Example</summary>
149+
150+
```ts
151+
152+
import { Address, beginCell, external, internal, SendMode, storeMessage, toNano, TonClient4, WalletContractV4 } from '@ton/ton';
153+
import { mnemonicToWalletKey } from '@ton/crypto';
154+
import fetch from 'node-fetch';
155+
156+
// place your mnemonic here
157+
const mnemonic = [
158+
'hill', 'silly', 'large', 'favorite', 'bottom', 'embody',
159+
'entry', 'blame', 'timber', 'garden', 'humor', 'copper',
160+
'advance', 'cargo', 'unveil', 'clock', 'narrow', 'conduct',
161+
'begin', 'price', 'receive', 'nose', 'public', 'fury'
162+
];
163+
164+
async function main() {
165+
// get ton client
166+
const client = new TonClient4({
167+
endpoint: 'https://mainnet-v4.tonhubapi.com'
168+
});
169+
170+
// create key pair from mnemonic and open wallet
171+
const keyPair = await mnemonicToWalletKey(mnemonic);
172+
const wallet = client.open(WalletContractV4.create({
173+
workchain: 0,
174+
publicKey: keyPair.publicKey
175+
}));
176+
177+
// log wallet address
178+
const friendlyAddress = wallet.address.toString({ urlSafe: true, bounceable: false });
179+
console.log(friendlyAddress);
180+
181+
// get seqno
182+
const seqno = await wallet.getSeqno();
183+
// place recipient address here
184+
const recipient = Address.parse('EQCKWpx7cNMpvmcN5ObM5lLUZHZRFKqYA4xmw9jOry0ZsF9M');
185+
186+
/** DANGER ZONE */
187+
// ⚠️ FOR EMULATION PURPOSES USE EMPTY BUFFER
188+
// ⚠️ DON'T USE THE REAL SECRET KEY FOR EMULATION!!!!
189+
const fakeSecretKey = Buffer.alloc(64);
190+
/** DANGER ZONE */
191+
192+
// build transfer body for external message
193+
const body = wallet.createTransfer({
194+
seqno: seqno,
195+
secretKey: fakeSecretKey,
196+
sendMode: SendMode.IGNORE_ERRORS + SendMode.PAY_GAS_SEPARATELY,
197+
messages: [internal({
198+
to: recipient,
199+
value: toNano('0.01')
200+
})]
201+
});
202+
// build external message
203+
const extMsg = beginCell()
204+
.store(storeMessage(external({
205+
to: wallet.address,
206+
body: body,
207+
init: seqno === 0 ? wallet.init : null
208+
})))
209+
.endCell();
210+
// base64 encode external message
211+
const extMsgBocBase64 = extMsg.toBoc().toString('base64');
212+
213+
// get wallet balance for emulation, must be not empty
214+
let walletBalance = Number(await wallet.getBalance());
215+
// you can uncomment this line for testing purposes, BUT DON'T FORGET TO COMMENT IT BACK FOR REAL USAGE
216+
// walletBalance = 1_000_000_000;
217+
const result = await fetch(`https://tonapi.io/v2/wallet/emulate`, {
218+
method: 'POST',
219+
headers: {
220+
Accept: 'application/json',
221+
'Content-Type': 'application/json'
222+
},
223+
body: JSON.stringify({
224+
boc: extMsgBocBase64,
225+
params: [
226+
{
227+
address: wallet.address.toRawString(),
228+
balance: walletBalance
229+
}
230+
]
231+
})
232+
}).then(p => p.json());
233+
// log emulation result
234+
console.log(result);
235+
}
236+
237+
main().catch();
238+
239+
```
240+
</details>
241+
242+
- **Tongo Library**: Explore the [Tongo library on GitHub](https://github.com/tonkeeper/tongo).
243+
- **Custom Parser**: Consider implementing your own parser, similar to the one in [tlb-abi](https://github.com/TrueCarry/tlb-abi) (please note that this version is not stable).
244+
- **Transaction Emulation**: Look at the emulation example in [this GitHub repository](https://github.com/thekiba/multisig/tree/main/apps/ui) (primarily for research purposes).
245+
246+
#### Emulating Transactions with TON API
247+
248+
If you choose to use the `/v2/wallet/emulate` method, here’s an example of how to implement it. However, keep in mind the following critical points:
249+
250+
1. **Avoid Using the Real Wallet’s Secret Key**: When emulating transactions, never use the actual wallet's secret key. Instead, sign the message with a fake key, such as an empty buffer.
251+
252+
2. **Use the Real Wallet Balance for Emulation**: You must pass the real wallet balance when performing the emulation. If the balance is empty, the emulation will fail and return an error. For testing, you can temporarily specify a larger balance by uncommenting the corresponding line, but always remember to use the real balance in production.
253+
254+
#### Code Example
255+
256+
Here is the relevant code snippet for your reference:
257+
75258

76259
### Step 7: Get an Audit
77260
To add your wallet to the wallets-list repository, please submit a pull request and ensure that all the necessary metadata is filled out. Additionally, applications can integrate wallets directly through the SDK.
@@ -81,6 +264,6 @@ To add your wallet to the wallets-list repository, please submit a pull request
81264
- [Protocol Package](https://github.com/ton-connect/sdk/tree/main/packages/protocol)
82265
- [Encrypted Communication Channels](https://github.com/ton-blockchain/ton-connect/blob/main/session.md)
83266
- [Bridge Specification](https://github.com/ton-blockchain/ton-connect/blob)
84-
- [Ton Proof](https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#address-proof-signature-ton_proof)
267+
- [Ton Proof](https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#address-proof-signature-ton_proof)
85268
- [Wallet Smart Contracts Tutorial](https://docs.ton.org/develop/smart-contracts/tutorials/wallet)
86269

0 commit comments

Comments
 (0)