From 9dd1a63d84f551ec0dc0eff643df1ae35fbc9aaa Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Wed, 5 Nov 2025 12:40:13 +0300
Subject: [PATCH 01/28] draft
---
payments/toncoin.mdx | 74 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 72 insertions(+), 2 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 852268608..f5b89a5b4 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -3,6 +3,76 @@ title: "Toncoin payments processing"
sidebarTitle: "Toncoin"
---
-import { Stub } from '/snippets/stub.jsx';
+import { Aside } from "/snippets/aside.jsx";
-
+Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
+
+## Invoice-based deposits
+
+Invoice-based processing uses a single wallet address to receive payments from multiple users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.
+
+The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
+
+Transaction comments in TON use the text message format with opcode `0x00000000` (first 32 bits of incoming internal message body) followed by UTF-8 encoded text. When parsing incoming messages, check the message body's first 32 bits for this opcode before reading the comment. Some wallets may send empty comments or messages without text format, so handle these cases gracefully.
+
+
+ Users can send transactions with arbitrary comments, including duplicates of valid invoice identifiers. Validate that invoice identifiers haven't been used previously and match expected formats. Implement amount verification to ensure deposits meet minimum requirements. Mark invoices as used immediately after crediting to prevent double-spending if the same invoice appears in multiple transactions.
+
+
+
+**Advantages**:
+- Single wallet simplifies key management
+- Reduced gas costs for deployments
+- Withdrawals can batch multiple user requests into one transaction using a Highload wallet
+- The approach scales well for high transaction volumes
+
+**Disadvantages**:
+- Privacy is reduced since all users deposit to the same observable address
+- Users must correctly input the invoice identifier, and mistakes result in lost or misdirected funds
+- Comment parsing adds complexity
+- Some wallets don't support comments, limiting accessibility
+
+Reference education-only implementation: [Invoice-based Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits.ts).
+
+## Unique deposit addresses
+
+Unique address deposits generate a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
+
+Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypairs per user, though this increases key management complexity. (TODO: security!)
+
+Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the undeployed address, send the transaction in non-bounceable mode. The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
+
+Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
+
+TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead. TODO: ton/core prefix
+
+
+ Each wallet requires separate key management. Store private keys encrypted and implement access controls. Lazy deployment means undeployed addresses can receive funds but cannot send them until deployment completes. Monitor for deployment status and automate deployment when deposits arrive. Validate that incoming transactions genuinely target the user's address and not another address with a similar hash.
+
+
+Withdrawal processing must gather funds from multiple wallets. Either maintain a minimum balance in each wallet for gas fees or implement a fund collection system that periodically sweeps deposits to a central hot wallet. Highload wallets handle batch withdrawals efficiently, while standard V4/V5 wallets process messages sequentially using `seqno`, creating bottlenecks under high load.
+
+**Advantages**:
+- No comment parsing removes a major source of user error
+- Better privacy since each user has a unique address
+- Transaction monitoring is straightforward - any incoming transaction to a user's address is their deposit
+
+**Disadvantages**:
+- Higher operational complexity managing multiple wallets
+- Deployment costs multiply by the number of users
+- Withdrawal processing requires coordination across wallets
+- Storage fees apply to each deployed contract (currently ~0.001 TON per year per contract)
+
+## Withdrawal batching
+
+[Highload wallets](/standard/wallets/highload/overview) support parallel message processing by storing processed request identifiers instead of sequential `seqno`. This enables batching multiple withdrawals into one transaction, reducing fees and improving throughput.
+
+## Monitoring best practices
+
+Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When `getTransactions` fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
+
+Store transaction state persistently. Record the last processed `lt` value and transaction hash to resume monitoring after restarts without reprocessing transactions. This prevents duplicate deposit credits.
+
+Use multiple RPC endpoints for reliability. TON has several public API providers and liteserver networks. Implement fallback logic to switch endpoints if the primary becomes unavailable. Compare results across endpoints to detect potential inconsistencies.
+
+Log all processing decisions including deposit credits, withdrawal submissions, and failed transactions. These logs are essential for debugging user reports and auditing system behavior. Include transaction hashes, logical times, amounts, and user identifiers in logs.
From fe1d096625e71efa4885ef5ae65f154b85cbda82 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Thu, 6 Nov 2025 12:53:58 +0300
Subject: [PATCH 02/28] review
---
payments/toncoin.mdx | 51 +++++++++++++++++++++++++++++++++-----------
1 file changed, 38 insertions(+), 13 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index f5b89a5b4..3e0f5cdea 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -5,21 +5,34 @@ sidebarTitle: "Toncoin"
import { Aside } from "/snippets/aside.jsx";
-Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
+Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address, common to all users or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
+
+**Invoice-based flow**
+
+```mermaid
+graph LR
+ U1[User A] -- invoice UUID --> SW[Shared Wallet]
+ U2[User B] -- invoice UUID --> SW
+ SW --> EX[Exchange Ledger]
+```
+
+**Unique deposit address flow**
+```mermaid
+graph LR
+ U1[User A] --> W1[Wallet A]
+ W1 --> EX[Exchange Ledger]
+ U2[User B] --> W2[Wallet B]
+ W2 --> EX
+```
## Invoice-based deposits
-Invoice-based processing uses a single wallet address to receive payments from multiple users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.
+Invoice-based processing uses one wallet address to receive payments from all users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.
-The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
+The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. TODO: link. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
Transaction comments in TON use the text message format with opcode `0x00000000` (first 32 bits of incoming internal message body) followed by UTF-8 encoded text. When parsing incoming messages, check the message body's first 32 bits for this opcode before reading the comment. Some wallets may send empty comments or messages without text format, so handle these cases gracefully.
-
- Users can send transactions with arbitrary comments, including duplicates of valid invoice identifiers. Validate that invoice identifiers haven't been used previously and match expected formats. Implement amount verification to ensure deposits meet minimum requirements. Mark invoices as used immediately after crediting to prevent double-spending if the same invoice appears in multiple transactions.
-
-
-
**Advantages**:
- Single wallet simplifies key management
- Reduced gas costs for deployments
@@ -27,10 +40,11 @@ Transaction comments in TON use the text message format with opcode `0x00000000`
- The approach scales well for high transaction volumes
**Disadvantages**:
-- Privacy is reduced since all users deposit to the same observable address
+- Access leak to the singlew hot wallet could lead to all user funds loss
- Users must correctly input the invoice identifier, and mistakes result in lost or misdirected funds
- Comment parsing adds complexity
-- Some wallets don't support comments, limiting accessibility
+- Some user wallet applications don't support comments, limiting accessibility
+- Single wallet network load [won't be sharded](/foundations/shards)
Reference education-only implementation: [Invoice-based Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits.ts).
@@ -38,11 +52,15 @@ Reference education-only implementation: [Invoice-based Toncoin deposits](https:
Unique address deposits generate a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
-Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypairs per user, though this increases key management complexity. (TODO: security!)
+Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypairs per user, though this increases key management complexity.
+
+
+ In Ton funds sent to the non-existent address are not recoverable, be careful with wallet generation code
+
Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the undeployed address, send the transaction in non-bounceable mode. The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
-Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
+Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request. TODO: batch
TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead. TODO: ton/core prefix
@@ -54,7 +72,7 @@ Withdrawal processing must gather funds from multiple wallets. Either maintain a
**Advantages**:
- No comment parsing removes a major source of user error
-- Better privacy since each user has a unique address
+- Better security since each user has a unique keypair
- Transaction monitoring is straightforward - any incoming transaction to a user's address is their deposit
**Disadvantages**:
@@ -67,6 +85,13 @@ Withdrawal processing must gather funds from multiple wallets. Either maintain a
[Highload wallets](/standard/wallets/highload/overview) support parallel message processing by storing processed request identifiers instead of sequential `seqno`. This enables batching multiple withdrawals into one transaction, reducing fees and improving throughput.
+## Common abuse patterns
+
+- Reusing a previously settled invoice identifier to trigger duplicate credits when the backend does not invalidate the invoice after first use.
+- Changing the Toncoin amount but leaving the original invoice identifier to obtain services at a lower price if expected amounts are not enforced.
+- Crafting comments that mimic another users invoice identifier in order to hijack their pending credit.
+- Submitting large numbers of dust payments to inflate processing costs or exhaust rate limits on transaction polling.
+
## Monitoring best practices
Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When `getTransactions` fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
From b5596bfebc465e09d88eeba4aeb5483373f333f1 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Thu, 6 Nov 2025 13:09:11 +0300
Subject: [PATCH 03/28] todos
---
payments/toncoin.mdx | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 3e0f5cdea..c66a58967 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -29,9 +29,9 @@ graph LR
Invoice-based processing uses one wallet address to receive payments from all users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.
-The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. TODO: link. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
+The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
-Transaction comments in TON use the text message format with opcode `0x00000000` (first 32 bits of incoming internal message body) followed by UTF-8 encoded text. When parsing incoming messages, check the message body's first 32 bits for this opcode before reading the comment. Some wallets may send empty comments or messages without text format, so handle these cases gracefully.
+Transaction comments in TON use the text message format, read more about them [here](/standard/wallets/how-it-works#transfer-comments).
**Advantages**:
- Single wallet simplifies key management
@@ -60,9 +60,9 @@ Implementation requires a wallet generation strategy. The most common approach u
Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the undeployed address, send the transaction in non-bounceable mode. The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
-Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request. TODO: batch
+Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
-TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead. TODO: ton/core prefix
+TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead.
Each wallet requires separate key management. Store private keys encrypted and implement access controls. Lazy deployment means undeployed addresses can receive funds but cannot send them until deployment completes. Monitor for deployment status and automate deployment when deposits arrive. Validate that incoming transactions genuinely target the user's address and not another address with a similar hash.
From 0eda5f55131d60d16c2fba63976871953d1871b2 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Thu, 6 Nov 2025 13:33:04 +0300
Subject: [PATCH 04/28] links
---
payments/toncoin.mdx | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index c66a58967..2f910e5c3 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -7,6 +7,8 @@ import { Aside } from "/snippets/aside.jsx";
Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address, common to all users or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
+## Deposit methods compatison
+
**Invoice-based flow**
```mermaid
@@ -25,6 +27,18 @@ graph LR
W2 --> EX
```
+**Comparison table**
+
+| Criteria | Invoice-based deposits | Unique deposit addresses |
+|------------------------------|-------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
+| Security exposure | One shared hot wallet; a key leak drains the full pool | Each wallet isolates funds; compromise affects only the impacted user |
+| User input requirements | User must include an invoice ID comment; missing or malformed comments need manual recovery workflows | User only needs the destination address |
+| Parsing and validation | Backend parses comments on every deposit and matches to invoices | No parsing; deposit attribution is address-based |
+| Deployment and storage costs | Deploy and maintain a single wallet; storage rent limited to that contract | Deploy many wallets; storage rent and deployment gas scale with user count |
+| Monitoring workload | Poll one address; comment parsing adds CPU but RPC calls stay low | Track many addresses; RPC queries and state tracking grow with the active user base |
+| Withdrawal handling | Highload wallet can batch withdrawals from one balance | Need sweeps or coordinated withdrawals from many wallets; extra gas and sequencing logic |
+| Sharding behavior | All activity hits one shard; throughput limited by that shard | Wallets are distributed across shards; helps spread load |
+
## Invoice-based deposits
Invoice-based processing uses one wallet address to receive payments from all users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.
@@ -40,13 +54,13 @@ Transaction comments in TON use the text message format, read more about them [h
- The approach scales well for high transaction volumes
**Disadvantages**:
-- Access leak to the singlew hot wallet could lead to all user funds loss
+- Access leak to the single hot wallet could lead to all user funds loss
- Users must correctly input the invoice identifier, and mistakes result in lost or misdirected funds
- Comment parsing adds complexity
- Some user wallet applications don't support comments, limiting accessibility
- Single wallet network load [won't be sharded](/foundations/shards)
-Reference education-only implementation: [Invoice-based Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits.ts).
+Reference education-only implementation: [Invoice-based Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits/invoices.ts).
## Unique deposit addresses
@@ -81,6 +95,8 @@ Withdrawal processing must gather funds from multiple wallets. Either maintain a
- Withdrawal processing requires coordination across wallets
- Storage fees apply to each deployed contract (currently ~0.001 TON per year per contract)
+Reference education-only implementation: [Unique address Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits/unique-addresses.ts).
+
## Withdrawal batching
[Highload wallets](/standard/wallets/highload/overview) support parallel message processing by storing processed request identifiers instead of sequential `seqno`. This enables batching multiple withdrawals into one transaction, reducing fees and improving throughput.
From 132059e57e924dd200b0d35d536a13801a8bca25 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Thu, 6 Nov 2025 13:37:35 +0300
Subject: [PATCH 05/28] lint
---
payments/toncoin.mdx | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 2f910e5c3..fcd10f528 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -7,7 +7,7 @@ import { Aside } from "/snippets/aside.jsx";
Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address, common to all users or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
-## Deposit methods compatison
+## Deposit methods comparison
**Invoice-based flow**
@@ -19,6 +19,7 @@ graph LR
```
**Unique deposit address flow**
+
```mermaid
graph LR
U1[User A] --> W1[Wallet A]
@@ -30,14 +31,14 @@ graph LR
**Comparison table**
| Criteria | Invoice-based deposits | Unique deposit addresses |
-|------------------------------|-------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
+| ---------------------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| Security exposure | One shared hot wallet; a key leak drains the full pool | Each wallet isolates funds; compromise affects only the impacted user |
| User input requirements | User must include an invoice ID comment; missing or malformed comments need manual recovery workflows | User only needs the destination address |
| Parsing and validation | Backend parses comments on every deposit and matches to invoices | No parsing; deposit attribution is address-based |
| Deployment and storage costs | Deploy and maintain a single wallet; storage rent limited to that contract | Deploy many wallets; storage rent and deployment gas scale with user count |
| Monitoring workload | Poll one address; comment parsing adds CPU but RPC calls stay low | Track many addresses; RPC queries and state tracking grow with the active user base |
| Withdrawal handling | Highload wallet can batch withdrawals from one balance | Need sweeps or coordinated withdrawals from many wallets; extra gas and sequencing logic |
-| Sharding behavior | All activity hits one shard; throughput limited by that shard | Wallets are distributed across shards; helps spread load |
+| Sharding behavior | All activity hits one shard; throughput limited by that shard | Wallets are distributed across shards; helps spread load |
## Invoice-based deposits
@@ -48,12 +49,14 @@ The implementation deploys one wallet contract (typically [Highload](/standard/w
Transaction comments in TON use the text message format, read more about them [here](/standard/wallets/how-it-works#transfer-comments).
**Advantages**:
+
- Single wallet simplifies key management
- Reduced gas costs for deployments
- Withdrawals can batch multiple user requests into one transaction using a Highload wallet
- The approach scales well for high transaction volumes
**Disadvantages**:
+
- Access leak to the single hot wallet could lead to all user funds loss
- Users must correctly input the invoice identifier, and mistakes result in lost or misdirected funds
- Comment parsing adds complexity
@@ -66,34 +69,38 @@ Reference education-only implementation: [Invoice-based Toncoin deposits](https:
Unique address deposits generate a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
-Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypairs per user, though this increases key management complexity.
+Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypair per user, though this increases key management complexity.
-
+
In Ton funds sent to the non-existent address are not recoverable, be careful with wallet generation code
-Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the undeployed address, send the transaction in non-bounceable mode. The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
+Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the un-deployed address, send the transaction in non-bounceable mode. The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead.
-
- Each wallet requires separate key management. Store private keys encrypted and implement access controls. Lazy deployment means undeployed addresses can receive funds but cannot send them until deployment completes. Monitor for deployment status and automate deployment when deposits arrive. Validate that incoming transactions genuinely target the user's address and not another address with a similar hash.
+
+ Each wallet requires separate key management. Store private keys encrypted and implement access controls. Lazy deployment means un-deployed addresses can receive funds but cannot send them until deployment completes. Monitor for deployment status and automate deployment when deposits arrive. Validate that incoming transactions genuinely target the user's address and not another address with a similar hash.
Withdrawal processing must gather funds from multiple wallets. Either maintain a minimum balance in each wallet for gas fees or implement a fund collection system that periodically sweeps deposits to a central hot wallet. Highload wallets handle batch withdrawals efficiently, while standard V4/V5 wallets process messages sequentially using `seqno`, creating bottlenecks under high load.
**Advantages**:
+
- No comment parsing removes a major source of user error
- Better security since each user has a unique keypair
- Transaction monitoring is straightforward - any incoming transaction to a user's address is their deposit
**Disadvantages**:
+
- Higher operational complexity managing multiple wallets
- Deployment costs multiply by the number of users
- Withdrawal processing requires coordination across wallets
-- Storage fees apply to each deployed contract (currently ~0.001 TON per year per contract)
+- Storage fees apply to each deployed contract (currently \~0.001 TON per year per contract)
Reference education-only implementation: [Unique address Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits/unique-addresses.ts).
From 9c38c1925c4af1076bc8401cdd354adbfde55fb9 Mon Sep 17 00:00:00 2001
From: Kaladin13 <80884234+Kaladin13@users.noreply.github.com>
Date: Thu, 6 Nov 2025 13:51:13 +0300
Subject: [PATCH 06/28] Update payments/toncoin.mdx
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
payments/toncoin.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index fcd10f528..bfbcec5a9 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -46,7 +46,7 @@ Invoice-based processing uses one wallet address to receive payments from all us
The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
-Transaction comments in TON use the text message format, read more about them [here](/standard/wallets/how-it-works#transfer-comments).
+Transaction comments in TON use the text message format; read more in [How TON wallets work](/standard/wallets/how-it-works).
**Advantages**:
From 9d68b17bd7331a65d1898f19c082bf6360c2fbb4 Mon Sep 17 00:00:00 2001
From: Kaladin13 <80884234+Kaladin13@users.noreply.github.com>
Date: Thu, 6 Nov 2025 13:51:24 +0300
Subject: [PATCH 07/28] Update payments/toncoin.mdx
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
payments/toncoin.mdx | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index bfbcec5a9..0ad2629c2 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -71,10 +71,11 @@ Unique address deposits generate a separate wallet contract for each user. The u
Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypair per user, though this increases key management complexity.
-
- In Ton funds sent to the non-existent address are not recoverable, be careful with wallet generation code
+
+ Risk: funds sent to a non‑existent or wrong address are irrecoverable.
+ Scope: deposit address derivation and the first transfer to an undeployed wallet.
+ Mitigation: derive addresses deterministically; verify checksum/ownership; send a small test transfer on testnet; use non‑bounceable for the first deposit; deploy immediately after receipt.
+ Environment: validate the full flow on testnet before using mainnet.
Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the un-deployed address, send the transaction in non-bounceable mode. The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
From 65a497a4f9335f33e704c1e9d3af139bf30d9d47 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Thu, 6 Nov 2025 14:02:23 +0300
Subject: [PATCH 08/28] lint
---
payments/toncoin.mdx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 0ad2629c2..6f8840a78 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -71,7 +71,10 @@ Unique address deposits generate a separate wallet contract for each user. The u
Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypair per user, though this increases key management complexity.
-
+
Risk: funds sent to a non‑existent or wrong address are irrecoverable.
Scope: deposit address derivation and the first transfer to an undeployed wallet.
Mitigation: derive addresses deterministically; verify checksum/ownership; send a small test transfer on testnet; use non‑bounceable for the first deposit; deploy immediately after receipt.
From 147113d402e89a03be0d03f70751d28e2059b37d Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Thu, 6 Nov 2025 14:04:01 +0300
Subject: [PATCH 09/28] fix
---
payments/toncoin.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 6f8840a78..b7b566585 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -76,7 +76,7 @@ Implementation requires a wallet generation strategy. The most common approach u
title="Funds at risk"
>
Risk: funds sent to a non‑existent or wrong address are irrecoverable.
- Scope: deposit address derivation and the first transfer to an undeployed wallet.
+ Scope: deposit address derivation and the first transfer to an un-deployed wallet.
Mitigation: derive addresses deterministically; verify checksum/ownership; send a small test transfer on testnet; use non‑bounceable for the first deposit; deploy immediately after receipt.
Environment: validate the full flow on testnet before using mainnet.
From 5dca467a61eb379e145a5d288f450403d43871d1 Mon Sep 17 00:00:00 2001
From: Kaladin13 <80884234+Kaladin13@users.noreply.github.com>
Date: Thu, 6 Nov 2025 14:16:34 +0300
Subject: [PATCH 10/28] Update payments/toncoin.mdx
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
payments/toncoin.mdx | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index b7b566585..e8d6ce346 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -48,6 +48,13 @@ The implementation deploys one wallet contract (typically [Highload](/standard/w
Transaction comments in TON use the text message format; read more in [How TON wallets work](/standard/wallets/how-it-works).
+
+ Risk: deposits without the correct invoice identifier may be misattributed or lost.
+ Scope: incoming transfers to the shared deposit address.
+ Mitigation: enforce invoice format; reject or hold unmatched deposits; provide a recovery workflow; document comment entry in the UI.
+ Environment: validate the full flow on testnet before enabling mainnet.
+
+
**Advantages**:
- Single wallet simplifies key management
From d9220324e501895b405c3a8d31ff06c17f6f5385 Mon Sep 17 00:00:00 2001
From: Kaladin13 <80884234+Kaladin13@users.noreply.github.com>
Date: Thu, 6 Nov 2025 14:16:42 +0300
Subject: [PATCH 11/28] Update payments/toncoin.mdx
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
payments/toncoin.mdx | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index e8d6ce346..c49832002 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -94,8 +94,11 @@ Monitor all user wallets by maintaining a list of deployed addresses and polling
TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead.
-
- Each wallet requires separate key management. Store private keys encrypted and implement access controls. Lazy deployment means un-deployed addresses can receive funds but cannot send them until deployment completes. Monitor for deployment status and automate deployment when deposits arrive. Validate that incoming transactions genuinely target the user's address and not another address with a similar hash.
+
+ Risk: leaked or mishandled private keys enable wallet takeover and fund loss.
+ Scope: generation, storage, and access to per-user wallet keys and deployment workflow.
+ Mitigation: encrypt keys at rest; restrict access; rotate keys; monitor deployment status; verify destination addresses before crediting deposits.
+ Environment: validate key management and deployment flow on testnet before mainnet.
Withdrawal processing must gather funds from multiple wallets. Either maintain a minimum balance in each wallet for gas fees or implement a fund collection system that periodically sweeps deposits to a central hot wallet. Highload wallets handle batch withdrawals efficiently, while standard V4/V5 wallets process messages sequentially using `seqno`, creating bottlenecks under high load.
From 0f885ab32315cb79ab7174626eeb56da54bca8ef Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Thu, 6 Nov 2025 14:21:09 +0300
Subject: [PATCH 12/28] lint
---
payments/toncoin.mdx | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index c49832002..d24156f5d 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -48,7 +48,10 @@ The implementation deploys one wallet contract (typically [Highload](/standard/w
Transaction comments in TON use the text message format; read more in [How TON wallets work](/standard/wallets/how-it-works).
-
+
Risk: deposits without the correct invoice identifier may be misattributed or lost.
Scope: incoming transfers to the shared deposit address.
Mitigation: enforce invoice format; reject or hold unmatched deposits; provide a recovery workflow; document comment entry in the UI.
@@ -94,7 +97,10 @@ Monitor all user wallets by maintaining a list of deployed addresses and polling
TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead.
-
+
Risk: leaked or mishandled private keys enable wallet takeover and fund loss.
Scope: generation, storage, and access to per-user wallet keys and deployment workflow.
Mitigation: encrypt keys at rest; restrict access; rotate keys; monitor deployment status; verify destination addresses before crediting deposits.
From 03b740729b21bbde9344467bf9768adcb298a947 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Thu, 6 Nov 2025 14:23:24 +0300
Subject: [PATCH 13/28] fix
---
payments/toncoin.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index d24156f5d..a3278f081 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -52,7 +52,7 @@ Transaction comments in TON use the text message format; read more in [How TON w
type="danger"
title="Funds at risk"
>
- Risk: deposits without the correct invoice identifier may be misattributed or lost.
+ Risk: deposits without the correct invoice identifier may be lost.
Scope: incoming transfers to the shared deposit address.
Mitigation: enforce invoice format; reject or hold unmatched deposits; provide a recovery workflow; document comment entry in the UI.
Environment: validate the full flow on testnet before enabling mainnet.
From dde6c894f2592e8aada91584d8327509697f91d1 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Mon, 10 Nov 2025 12:44:34 +0300
Subject: [PATCH 14/28] fixes
---
payments/toncoin.mdx | 40 ++++++++++++++++++++++++++--------------
1 file changed, 26 insertions(+), 14 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index a3278f081..0731f99a5 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -7,6 +7,10 @@ import { Aside } from "/snippets/aside.jsx";
Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address, common to all users or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
+
+ Wallets in Ton are smart-contracts, not external accounts [like in Ethereum](/from-ethereum#account-model). Each wallet has its own address, code, and storage. Deposits are incoming messages to these wallet contracts.
+
+
## Deposit methods comparison
**Invoice-based flow**
@@ -35,10 +39,10 @@ graph LR
| Security exposure | One shared hot wallet; a key leak drains the full pool | Each wallet isolates funds; compromise affects only the impacted user |
| User input requirements | User must include an invoice ID comment; missing or malformed comments need manual recovery workflows | User only needs the destination address |
| Parsing and validation | Backend parses comments on every deposit and matches to invoices | No parsing; deposit attribution is address-based |
-| Deployment and storage costs | Deploy and maintain a single wallet; storage rent limited to that contract | Deploy many wallets; storage rent and deployment gas scale with user count |
-| Monitoring workload | Poll one address; comment parsing adds CPU but RPC calls stay low | Track many addresses; RPC queries and state tracking grow with the active user base |
-| Withdrawal handling | Highload wallet can batch withdrawals from one balance | Need sweeps or coordinated withdrawals from many wallets; extra gas and sequencing logic |
-| Sharding behavior | All activity hits one shard; throughput limited by that shard | Wallets are distributed across shards; helps spread load |
+| Deployment and storage costs | Deploy and maintain a single wallet; [storage rent](/foundations/fees#storage-fee) limited to that contract | Deploy many wallets; storage rent and deployment gas scale with user count |
+| Monitoring workload | Poll one address; comment parsing adds CPU but [RPC calls](/ecosystem/rpc/overview) stay low | Track many addresses; RPC queries and state tracking grow with the active user base |
+| Withdrawal handling | [Highload wallet](/standard/wallets/highload/overview) can batch withdrawals from one balance | Need sweeps or coordinated withdrawals from many wallets; extra gas and sequencing logic |
+| Sharding behavior | All activity hits [one shard](/foundations/shards); throughput limited by that shard | Wallets are distributed across shards; helps spread load |
## Invoice-based deposits
@@ -63,7 +67,6 @@ Transaction comments in TON use the text message format; read more in [How TON w
- Single wallet simplifies key management
- Reduced gas costs for deployments
- Withdrawals can batch multiple user requests into one transaction using a Highload wallet
-- The approach scales well for high transaction volumes
**Disadvantages**:
@@ -73,11 +76,15 @@ Transaction comments in TON use the text message format; read more in [How TON w
- Some user wallet applications don't support comments, limiting accessibility
- Single wallet network load [won't be sharded](/foundations/shards)
-Reference education-only implementation: [Invoice-based Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits/invoices.ts).
+
+ Not production-ready code, use only for educational purposes
+
+
+To understand this approach in greater detail, see the following TypeScript implementation: [Invoice-based Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits/invoices.ts).
## Unique deposit addresses
-Unique address deposits generate a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
+Unique address deposits use a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypair per user, though this increases key management complexity.
@@ -85,13 +92,13 @@ Implementation requires a wallet generation strategy. The most common approach u
type="danger"
title="Funds at risk"
>
- Risk: funds sent to a non‑existent or wrong address are irrecoverable.
+ Risk: funds sent to a [non-existent or wrong address](/foundations/addresses/overview) are irrecoverable.
Scope: deposit address derivation and the first transfer to an un-deployed wallet.
- Mitigation: derive addresses deterministically; verify checksum/ownership; send a small test transfer on testnet; use non‑bounceable for the first deposit; deploy immediately after receipt.
+ Mitigation: derive addresses deterministically; verify checksum/ownership; send a small test transfer on testnet; use non-bounceable for the first deposit; deploy immediately after receipt.
Environment: validate the full flow on testnet before using mainnet.
-Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the un-deployed address, send the transaction in non-bounceable mode. The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
+Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the un-deployed address, send the transaction in [non-bounceable mode](/foundations/messages/overview). The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
@@ -122,7 +129,12 @@ Withdrawal processing must gather funds from multiple wallets. Either maintain a
- Withdrawal processing requires coordination across wallets
- Storage fees apply to each deployed contract (currently \~0.001 TON per year per contract)
-Reference education-only implementation: [Unique address Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits/unique-addresses.ts).
+
+
+ Not production-ready code, use only for educational purposes
+
+
+To understand this approach in greater detail, see the following TypeScript implementation: [Unique address Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits/unique-addresses.ts).
## Withdrawal batching
@@ -130,16 +142,16 @@ Reference education-only implementation: [Unique address Toncoin deposits](https
## Common abuse patterns
-- Reusing a previously settled invoice identifier to trigger duplicate credits when the backend does not invalidate the invoice after first use.
+- Reusing a previously settled invoice identifier to trigger duplicate credits when the backend does not invalidate the invoice after the first use.
- Changing the Toncoin amount but leaving the original invoice identifier to obtain services at a lower price if expected amounts are not enforced.
- Crafting comments that mimic another users invoice identifier in order to hijack their pending credit.
- Submitting large numbers of dust payments to inflate processing costs or exhaust rate limits on transaction polling.
## Monitoring best practices
-Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When `getTransactions` fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
+Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When [getTransactions](/ecosystem/rpc/toncenter/v2/accounts/list-account-transactions) fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
-Store transaction state persistently. Record the last processed `lt` value and transaction hash to resume monitoring after restarts without reprocessing transactions. This prevents duplicate deposit credits.
+Store transaction state persistently. Record the last processed `lt` value (`lt` here is logical time) and transaction hash to resume monitoring after restarts without reprocessing transactions. This prevents duplicate deposit credits.
Use multiple RPC endpoints for reliability. TON has several public API providers and liteserver networks. Implement fallback logic to switch endpoints if the primary becomes unavailable. Compare results across endpoints to detect potential inconsistencies.
From 087a2a6bc29883d8da8816d2d5a07f95b721e3f2 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Mon, 10 Nov 2025 13:44:54 +0300
Subject: [PATCH 15/28] more review
---
payments/toncoin.mdx | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 0731f99a5..a79314d3d 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -86,7 +86,7 @@ To understand this approach in greater detail, see the following TypeScript impl
Unique address deposits use a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
-Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypair per user, though this increases key management complexity.
+Implementation requires a wallet generation strategy. A common approach uses a deterministic scheme based on a single master [keypair](/standard/wallets/mnemonics) and user identifiers, deriving unique addresses for V4 and V5 wallets using different [subwallet_id](/standard/wallets/how-it-works#subwallet-id) values. Alternatively, generate a unique keypair per user, though this increases key management complexity.
+ Sending unbounceable messages to nonexistent accounts without testing it first is particularly bad practice. Always test to ensure the address is correct and the deployment flow works as expected.
+
+
Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead.
From a4599a154a7c5f976038181b2801d70ec4f6085e Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Mon, 10 Nov 2025 13:46:00 +0300
Subject: [PATCH 16/28] lint
---
payments/toncoin.mdx | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index a79314d3d..9eee4f1f0 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -7,7 +7,7 @@ import { Aside } from "/snippets/aside.jsx";
Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address, common to all users or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
-
+
Wallets in Ton are smart-contracts, not external accounts [like in Ethereum](/from-ethereum#account-model). Each wallet has its own address, code, and storage. Deposits are incoming messages to these wallet contracts.
@@ -34,15 +34,15 @@ graph LR
**Comparison table**
-| Criteria | Invoice-based deposits | Unique deposit addresses |
-| ---------------------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
-| Security exposure | One shared hot wallet; a key leak drains the full pool | Each wallet isolates funds; compromise affects only the impacted user |
-| User input requirements | User must include an invoice ID comment; missing or malformed comments need manual recovery workflows | User only needs the destination address |
-| Parsing and validation | Backend parses comments on every deposit and matches to invoices | No parsing; deposit attribution is address-based |
-| Deployment and storage costs | Deploy and maintain a single wallet; [storage rent](/foundations/fees#storage-fee) limited to that contract | Deploy many wallets; storage rent and deployment gas scale with user count |
-| Monitoring workload | Poll one address; comment parsing adds CPU but [RPC calls](/ecosystem/rpc/overview) stay low | Track many addresses; RPC queries and state tracking grow with the active user base |
-| Withdrawal handling | [Highload wallet](/standard/wallets/highload/overview) can batch withdrawals from one balance | Need sweeps or coordinated withdrawals from many wallets; extra gas and sequencing logic |
-| Sharding behavior | All activity hits [one shard](/foundations/shards); throughput limited by that shard | Wallets are distributed across shards; helps spread load |
+| Criteria | Invoice-based deposits | Unique deposit addresses |
+| ---------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
+| Security exposure | One shared hot wallet; a key leak drains the full pool | Each wallet isolates funds; compromise affects only the impacted user |
+| User input requirements | User must include an invoice ID comment; missing or malformed comments need manual recovery workflows | User only needs the destination address |
+| Parsing and validation | Backend parses comments on every deposit and matches to invoices | No parsing; deposit attribution is address-based |
+| Deployment and storage costs | Deploy and maintain a single wallet; [storage rent](/foundations/fees#storage-fee) limited to that contract | Deploy many wallets; storage rent and deployment gas scale with user count |
+| Monitoring workload | Poll one address; comment parsing adds CPU but [RPC calls](/ecosystem/rpc/overview) stay low | Track many addresses; RPC queries and state tracking grow with the active user base |
+| Withdrawal handling | [Highload wallet](/standard/wallets/highload/overview) can batch withdrawals from one balance | Need sweeps or coordinated withdrawals from many wallets; extra gas and sequencing logic |
+| Sharding behavior | All activity hits [one shard](/foundations/shards); throughput limited by that shard | Wallets are distributed across shards; helps spread load |
## Invoice-based deposits
@@ -86,7 +86,7 @@ To understand this approach in greater detail, see the following TypeScript impl
Unique address deposits use a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
-Implementation requires a wallet generation strategy. A common approach uses a deterministic scheme based on a single master [keypair](/standard/wallets/mnemonics) and user identifiers, deriving unique addresses for V4 and V5 wallets using different [subwallet_id](/standard/wallets/how-it-works#subwallet-id) values. Alternatively, generate a unique keypair per user, though this increases key management complexity.
+Implementation requires a wallet generation strategy. A common approach uses a deterministic scheme based on a single master [keypair](/standard/wallets/mnemonics) and user identifiers, deriving unique addresses for V4 and V5 wallets using different [subwallet\_id](/standard/wallets/how-it-works#subwallet-id) values. Alternatively, generate a unique keypair per user, though this increases key management complexity.
Not production-ready code, use only for educational purposes
From 565c6c46a58550ac2f139e0312773edc0e024de4 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Mon, 10 Nov 2025 13:50:14 +0300
Subject: [PATCH 17/28] fix
---
payments/toncoin.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 9eee4f1f0..45e44ec60 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -101,7 +101,7 @@ Implementation requires a wallet generation strategy. A common approach uses a d
Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the un-deployed address, send the transaction in [non-bounceable mode](/foundations/messages/overview). The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
- Sending unbounceable messages to nonexistent accounts without testing it first is particularly bad practice. Always test to ensure the address is correct and the deployment flow works as expected.
+ Sending un-bounceable messages to nonexistent accounts without testing it first is particularly bad practice. Always test to ensure the address is correct and the deployment flow works as expected.
Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
From 14bb84ab66ba281a9a2be08d4f0e6689eb231205 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Mon, 10 Nov 2025 13:52:15 +0300
Subject: [PATCH 18/28] links
---
payments/toncoin.mdx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 45e44ec60..0de9a08d1 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -40,7 +40,7 @@ graph LR
| User input requirements | User must include an invoice ID comment; missing or malformed comments need manual recovery workflows | User only needs the destination address |
| Parsing and validation | Backend parses comments on every deposit and matches to invoices | No parsing; deposit attribution is address-based |
| Deployment and storage costs | Deploy and maintain a single wallet; [storage rent](/foundations/fees#storage-fee) limited to that contract | Deploy many wallets; storage rent and deployment gas scale with user count |
-| Monitoring workload | Poll one address; comment parsing adds CPU but [RPC calls](/ecosystem/rpc/overview) stay low | Track many addresses; RPC queries and state tracking grow with the active user base |
+| Monitoring workload | Poll one address; comment parsing adds CPU but [RPC calls](/ecosystem/api/overview) stay low | Track many addresses; RPC queries and state tracking grow with the active user base |
| Withdrawal handling | [Highload wallet](/standard/wallets/highload/overview) can batch withdrawals from one balance | Need sweeps or coordinated withdrawals from many wallets; extra gas and sequencing logic |
| Sharding behavior | All activity hits [one shard](/foundations/shards); throughput limited by that shard | Wallets are distributed across shards; helps spread load |
@@ -152,7 +152,7 @@ To understand this approach in greater detail, see the following TypeScript impl
## Monitoring best practices
-Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When [getTransactions](/ecosystem/rpc/toncenter/v2/accounts/list-account-transactions) fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
+Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When [getTransactions](/ecosystem/api/toncenter/v2/accounts/list-account-transactions) fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
Store transaction state persistently. Record the last processed `lt` value (`lt` here is logical time) and transaction hash to resume monitoring after restarts without reprocessing transactions. This prevents duplicate deposit credits.
From 2d545f3539eeab911c8d741614df3c06fefa611c Mon Sep 17 00:00:00 2001
From: Kaladin13 <80884234+Kaladin13@users.noreply.github.com>
Date: Mon, 10 Nov 2025 15:04:10 +0300
Subject: [PATCH 19/28] Update payments/toncoin.mdx
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
payments/toncoin.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 0de9a08d1..6b182d36a 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -7,7 +7,7 @@ import { Aside } from "/snippets/aside.jsx";
Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address, common to all users or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
-
+
Wallets in Ton are smart-contracts, not external accounts [like in Ethereum](/from-ethereum#account-model). Each wallet has its own address, code, and storage. Deposits are incoming messages to these wallet contracts.
From 6b9048b94d30261a2c740604c094598115f6b24a Mon Sep 17 00:00:00 2001
From: Kaladin13 <80884234+Kaladin13@users.noreply.github.com>
Date: Mon, 10 Nov 2025 15:04:24 +0300
Subject: [PATCH 20/28] Update payments/toncoin.mdx
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
payments/toncoin.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 6b182d36a..d4cb9d093 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -76,7 +76,7 @@ Transaction comments in TON use the text message format; read more in [How TON w
- Some user wallet applications don't support comments, limiting accessibility
- Single wallet network load [won't be sharded](/foundations/shards)
-
+
Not production-ready code, use only for educational purposes
From c8527ecb17196f360595661164f08729d6df54c4 Mon Sep 17 00:00:00 2001
From: Kaladin13 <80884234+Kaladin13@users.noreply.github.com>
Date: Mon, 10 Nov 2025 15:04:39 +0300
Subject: [PATCH 21/28] Update payments/toncoin.mdx
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
payments/toncoin.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index d4cb9d093..662952cf7 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -86,7 +86,7 @@ To understand this approach in greater detail, see the following TypeScript impl
Unique address deposits use a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
-Implementation requires a wallet generation strategy. A common approach uses a deterministic scheme based on a single master [keypair](/standard/wallets/mnemonics) and user identifiers, deriving unique addresses for V4 and V5 wallets using different [subwallet\_id](/standard/wallets/how-it-works#subwallet-id) values. Alternatively, generate a unique keypair per user, though this increases key management complexity.
+Implementation requires a wallet generation strategy. A common approach uses a deterministic scheme based on a single master [keypair](/standard/wallets/mnemonics) and user identifiers, deriving unique addresses for V4 and V5 wallets using different [`subwallet_id`](/standard/wallets/how-it-works#subwallet-id) values. Alternatively, generate a unique keypair per user, though this increases key management complexity.
Date: Mon, 10 Nov 2025 15:14:29 +0300
Subject: [PATCH 22/28] Update payments/toncoin.mdx
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
payments/toncoin.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 662952cf7..2a223359d 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -133,7 +133,7 @@ Withdrawal processing must gather funds from multiple wallets. Either maintain a
- Withdrawal processing requires coordination across wallets
- Storage fees apply to each deployed contract (currently \~0.001 TON per year per contract)
-
+
Not production-ready code, use only for educational purposes
From d0e6e1cae048d94f6ec80ad17a59dc0d3994f986 Mon Sep 17 00:00:00 2001
From: Kaladin13 <80884234+Kaladin13@users.noreply.github.com>
Date: Mon, 10 Nov 2025 15:14:41 +0300
Subject: [PATCH 23/28] Update payments/toncoin.mdx
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
payments/toncoin.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 2a223359d..cc1624a5b 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -152,7 +152,7 @@ To understand this approach in greater detail, see the following TypeScript impl
## Monitoring best practices
-Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When [getTransactions](/ecosystem/api/toncenter/v2/accounts/list-account-transactions) fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
+Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When [`getTransactions`](/ecosystem/api/toncenter/v2/accounts/list-account-transactions) fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
Store transaction state persistently. Record the last processed `lt` value (`lt` here is logical time) and transaction hash to resume monitoring after restarts without reprocessing transactions. This prevents duplicate deposit credits.
From c5f01d514d51738acbfbfd8ef2aa1b29b963d203 Mon Sep 17 00:00:00 2001
From: Your Name
Date: Wed, 12 Nov 2025 00:02:41 +0400
Subject: [PATCH 24/28] review
---
payments/toncoin.mdx | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index cc1624a5b..37de843d6 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -5,12 +5,19 @@ sidebarTitle: "Toncoin"
import { Aside } from "/snippets/aside.jsx";
-Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address, common to all users or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
+Processing Toncoin payments requires choosing between two architectural approaches:
+
+- invoice-based deposits to a single address, common to all users
+- unique deposit addresses per user.
Wallets in Ton are smart-contracts, not external accounts [like in Ethereum](/from-ethereum#account-model). Each wallet has its own address, code, and storage. Deposits are incoming messages to these wallet contracts.
+
+ FIXME Do not send funds to a wallet address that you cannot initialize.
+
+
## Deposit methods comparison
**Invoice-based flow**
From 62646bade11c1fa48c0f82320475a269ead3d0d1 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Wed, 12 Nov 2025 18:07:56 +0300
Subject: [PATCH 25/28] add comments about wuthdraaw
---
payments/toncoin.mdx | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 37de843d6..ec10664de 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -15,7 +15,7 @@ Processing Toncoin payments requires choosing between two architectural approach
- FIXME Do not send funds to a wallet address that you cannot initialize.
+ Do not send funds to a wallet address that you cannot initialize. Derive addresses deterministically based on contracts [initial state](/foundations/addresses/overview).
## Deposit methods comparison
@@ -99,10 +99,7 @@ Implementation requires a wallet generation strategy. A common approach uses a d
type="danger"
title="Funds at risk"
>
- Risk: funds sent to a [non-existent or wrong address](/foundations/addresses/overview) are irrecoverable.
- Scope: deposit address derivation and the first transfer to an un-deployed wallet.
- Mitigation: derive addresses deterministically; verify checksum/ownership; send a small test transfer on testnet; use non-bounceable for the first deposit; deploy immediately after receipt.
- Environment: validate the full flow on testnet before using mainnet.
+ Funds sent to a [non-existent or wrong address](/foundations/addresses/overview) are irrecoverable. Derive addresses deterministically and double check.
Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the un-deployed address, send the transaction in [non-bounceable mode](/foundations/messages/overview). The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
@@ -148,6 +145,10 @@ To understand this approach in greater detail, see the following TypeScript impl
## Withdrawal batching
+
+ When withdrawing, do not send funds to a wallet address that you cannot initialize later, based on contracts [initial state](/foundations/addresses/overview).
+
+
[Highload wallets](/standard/wallets/highload/overview) support parallel message processing by storing processed request identifiers instead of sequential `seqno`. This enables batching multiple withdrawals into one transaction, reducing fees and improving throughput.
## Common abuse patterns
From 1b9f53345b1b275ef021fb90363411c98b0501e9 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Wed, 12 Nov 2025 18:19:33 +0300
Subject: [PATCH 26/28] fix lint
---
payments/toncoin.mdx | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index ec10664de..10e063671 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -14,7 +14,9 @@ Processing Toncoin payments requires choosing between two architectural approach
Wallets in Ton are smart-contracts, not external accounts [like in Ethereum](/from-ethereum#account-model). Each wallet has its own address, code, and storage. Deposits are incoming messages to these wallet contracts.
-
+
Do not send funds to a wallet address that you cannot initialize. Derive addresses deterministically based on contracts [initial state](/foundations/addresses/overview).
@@ -145,7 +147,9 @@ To understand this approach in greater detail, see the following TypeScript impl
## Withdrawal batching
-
+
When withdrawing, do not send funds to a wallet address that you cannot initialize later, based on contracts [initial state](/foundations/addresses/overview).
From c6c99aef3895d8315e2b734bfe7d136334996169 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Wed, 12 Nov 2025 18:28:05 +0300
Subject: [PATCH 27/28] un part
---
payments/toncoin.mdx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 10e063671..8992951e0 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -104,10 +104,10 @@ Implementation requires a wallet generation strategy. A common approach uses a d
Funds sent to a [non-existent or wrong address](/foundations/addresses/overview) are irrecoverable. Derive addresses deterministically and double check.
-Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the un-deployed address, send the transaction in [non-bounceable mode](/foundations/messages/overview). The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
+Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the undeployed address, send the transaction in [non-bounceable mode](/foundations/messages/overview). The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
- Sending un-bounceable messages to nonexistent accounts without testing it first is particularly bad practice. Always test to ensure the address is correct and the deployment flow works as expected.
+ Sending unbounceable messages to nonexistent accounts without testing it first is particularly bad practice. Always test to ensure the address is correct and the deployment flow works as expected.
Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
From cfb5efe5a35962131406ead7b09adeab314b2a32 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Wed, 12 Nov 2025 18:29:59 +0300
Subject: [PATCH 28/28] fix again
---
payments/toncoin.mdx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 8992951e0..37af1e167 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -104,10 +104,10 @@ Implementation requires a wallet generation strategy. A common approach uses a d
Funds sent to a [non-existent or wrong address](/foundations/addresses/overview) are irrecoverable. Derive addresses deterministically and double check.
-Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the undeployed address, send the transaction in [non-bounceable mode](/foundations/messages/overview). The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
+Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the not deployed address, send the transaction in [non-bounceable mode](/foundations/messages/overview). The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
- Sending unbounceable messages to nonexistent accounts without testing it first is particularly bad practice. Always test to ensure the address is correct and the deployment flow works as expected.
+ Sending non-bounceable messages to nonexistent accounts without testing it first is particularly bad practice. Always test to ensure the address is correct and the deployment flow works as expected.
Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.