Payments Processing
This page explains how to process (send and accept) digital assets
on the TON blockchain.
It mostly describes how to work with TON coins
, but theoretical part is important even if you want to process only jettons
.
It's recommended to get acquainted with Asset Processing Overview before reading this tutorial.
Wallet smart contract
Wallet smart contracts on the TON Network allow external actors to interact with blockchain entities.
- Authenticates the owner: Rejects requests that attempt to process or pay fees on behalf of non-owners.
- Provides replay protection: Prevents the repeated execution of the same request, such as sending assets to another smart contract.
- Initiates arbitrary interactions with other smart contracts.
Standard solution for the first challenge is public-key cryptography: wallet
stores the public key and checks that an incoming message with a request is signed by the corresponding private key which is known only by the owner.
The solution to the third challenge is also common; generally, a request contains a fully formed inner message that the wallet
sends to the network. However, for replay protection, there are a few different approaches.
Seqno-based wallets
Seqno-based wallets use the simplest approach to sequencing messages. Each message has a special seqno
integer that must coincide with the counter stored in the wallet
smart contract. wallet
updates its counter on each request, thus ensuring that one request will not be processed twice. There are a few wallet
versions that differ in publicly available methods: the ability to limit requests by expiration time, and the ability to have multiple wallets with the same public key. However, an inherent requirement of that approach is to send requests one by one, since any gap in seqno
sequence will result in the inability to process all subsequent requests.
High-load wallets
This wallet
type follows an approach based on storing the identifier of the non-expired processed requests in smart-contract storage. In this approach, any request is checked for being a duplicate of an already processed request and, if a replay is detected, dropped. Due to expiration, the contract may not store all requests forever, but it will remove those that cannot be processed due to the expiration limit. Requests to this wallet
can be sent in parallel without interference, but this approach requires more sophisticated monitoring of request processing.
Wallet deployment
To deploy a wallet via TonLib, one needs to:
- Generate a private/public key pair via createNewKey or its wrapper functions (example in tonlib-go). Note that the private key is generated locally and does not leave the host machine.
- Form InitialAccountWallet structure corresponding to one of the enabled
wallets
. Currentlywallet.v3
,wallet.v4
,wallet.highload.v1
,wallet.highload.v2
are available. - Calculate the address of a new
wallet
smart contract via the getAccountAddress method. We recommend using a default revision0
and also deploying wallets in the basechainworkchain=0
for lower processing and storage fees. - Send some Toncoin to the calculated address. Note that you need to send them in
non-bounce
mode, as this address has no code yet and cannot process incoming messages.non-bounce
flag indicates that even if processing fails, money should not be returned with a bounce message. We do not recommend using thenon-bounce
flag for other transactions, especially when carrying large sums, since the bounce mechanism provides some degree of protection against mistakes. - Form the desired action, for instance
actionNoop
for deploy only. Then use createQuery and sendQuery to initiate interactions with the blockchain. - Check the contract in a few seconds with getAccountState method.
Read more in the Wallet Tutorial
Check the validity of wallet address
Most SDKs force you to verify address (most verify it during wallet creation or transaction preparation process), so, usually, it's not require any additional complex steps from you.
- JS (Tonweb)
- tonutils-go
- Ton4j
- ton-kotlin
const TonWeb = require("tonweb")
TonWeb.utils.Address.isValid('...')
package main
import (
"fmt"
"github.com/xssnick/tonutils-go/address"
)
if _, err := address.ParseAddr("EQCD39VS5j...HUn4bpAOg8xqB2N"); err != nil {
return errors.New("invalid address")
}