How to use a single nominator pool
Before proceeding with this tutorial, we recommend familiarizing yourself with the single nominator pool specification.
Set up single nominator mode
Before starting, ensure you have topped up and activated the validator's wallet.
- Enable single nominator mode:
MyTonCtrl> enable_mode single-nominator
- Verify if single nominator mode is enabled:
MyTonCtrl> status_modes
Name Status Description
single-nominator enabled Orbs's single nominator pools.
- Create a pool:
MyTonCtrl> new_single_pool <pool-name> <owner_address>
If you have already created a pool, you can import it:
MyTonCtrl> import_pool <pool-name> <pool-addr>
- Display pool addresses using
pools_list
:
MyTonCtrl> pools_list
Name Status Balance Version Address
test-pool empty 0.0 spool_r2 kf_JcC5pn3etTAdwOnc16_tyMmKE8-ftNUnf0OnUjAIdDJpX
- Activate the pool:
MyTonCtrl> activate_single_pool <pool-name>
After successfully activating the pool:
MyTonCtrl> pools_list
Name Status Balance Version Address
test-pool active 0.99389 spool_r2 kf_JcC5pn3etTAdwOnc16_tyMmKE8-ftNUnf0OnUjAIdDJpX
You can manage this pool via MyTonCtrl like a standard nominator pool.
If the pool's balance is sufficient to participate in both rounds (balance > min_stake_amount * 2
), MyTonCtrl will automatically participate in both rounds using stake = balance / 2
, unless you manually set the stake using the set stake
command. This behavior differs from using a nominator pool but resembles staking with a validator wallet.
Start without MyTonCtrl
Prepare a launched validator
If you have MyTonCtrl installed and a validator running:
- Stop validation and withdraw all funds.
Prepare from scratch
If you have no prior validator setup, follow these steps:
- Run a validator and ensure it is synced.
- Stop validation and withdraw all funds.
Prepare single nominator
- Install Node.js v.16 or later and npm (detailed instructions).
- Install
ts-node
and thearg
module:
$ sudo apt install ts-node
$ sudo npm i arg -g
- Create symlinks for compilers:
$ sudo ln -s /usr/bin/ton/crypto/fift /usr/local/bin/fift
$ sudo ln -s /usr/bin/ton/crypto/func /usr/local/bin/func
- Run a test to verify the setup:
$ npm run test
- Replace MyTonCtrl nominator-pool scripts: Install pool scripts.
Create a single nominator pool
- Obtain a Toncenter API key from @tonapibot on Telegram.
- Set environment variables:
export OWNER_ADDRESS=<owner_address>
export VALIDATOR_ADDRESS=<validator_wallet_address>
export TON_ENDPOINT=https://toncenter.com/api/v2/jsonRPC
export TON_API_KEY=<toncenter_api_key>
- Create a deployer address:
$ npm run init-deploy-wallet
Insufficient Deployer [EQAo5U...yGgbvR] funds 0
- Top up the deployer address with 2.1 TON.
- Deploy the pool contract to get the pool address (
Ef-kC0..._WLqgs
):
$ npm run deploy
- Convert the address to
.addr
:
$ fift -s ./scripts/fift/str-to-addr.fif Ef-kC0..._WLqgs
(Saving address to file single-nominator.addr)
- Back up the deployer private key (
./build/deploy.config.json
) andsingle-nominator.addr
files. - Copy
single-nominator.addr
tomytoncore/pools/single-nominator-1.addr
. - Send a stake from the owner's address to the single nominator's address.
Withdrawals from the single nominator
Using wallets to withdraw
Fift:
- Create a
withdraw.boc
request with the desired amount:
$ fift -s ./scripts/fift/withdraw.fif <withdraw_amount>
- Create and sign the request from the owner's wallet:
$ fift -s wallet-v3.fif <my-wallet> <single_nominator_address> <sub_wallet_id> <seqno> <amount=1> -B withdraw.boc
- Broadcast the query:
$ lite-client -C global.config.json -c 'sendfile wallet-query.boc'
Tonkeeper:
- Create a
withdraw.boc
request with the desired amount:
$ fift -s ./scripts/fift/withdraw.fif <withdraw_amount>
- Send the request to the single nominator address:
$ tons wallet transfer <my-wallet> <single_nominator_address> <amount=1> --body withdraw.boc
- Link TypeScript:
npm link typescript
- Generate a deeplink:
npx ts-node scripts/ts/withdraw-deeplink.ts <single-nominator-addr> <withdraw-amount>
- Open the deeplink on the owner's phone.
Deposit to pool
You can deposit using MyTonCtrl with the following commands:
MyTonCtrl> mg <from-wallet-name> <pool-account-addr> <amount>
or
MyTonCtrl> deposit_to_pool <pool-addr> <amount>
Alternatively, follow these steps:
- Navigate to the pool’s page:
https://tonscan.org/nominator/{pool_address}
. - Ensure the pool information is displayed correctly. If the pool has an incorrect smart contract, no information will appear.
- Click the
ADD STAKE
button or scan the QR code using Tonkeeper or another TON wallet. - Enter the TON amount and send the transaction. The TON coins will then be added to staking.
If the wallet does not open automatically, manually send the transaction by copying the pool address and using any TON wallet. Note that 1 TON will be deducted as a commission for processing the deposit.
Withdraw funds
You can withdraw funds using the following command:
MyTonCtrl> withdraw_from_pool <pool-addr> <amount>
Alternatively, create and send the transaction manually:
- JS (@ton)
- Golang
import { Address, beginCell, internal, storeMessageRelaxed, toNano } from "@ton/core";
async function main() {
const single_nominator_address = Address.parse('single nominator address');
const WITHDRAW_OP = 0x1000;
const amount = 50000;
const messageBody = beginCell()
.storeUint(WITHDRAW_OP, 32) // op code for withdrawal
.storeUint(0, 64) // query_id
.storeCoins(amount) // amount to withdraw
.endCell();
const internalMessage = internal({
to: single_nominator_address,
value: toNano('1'),
bounce: true,
body: messageBody
});
}
func WithdrawSingleNominatorMessage(single_nominator_address string, query_id, amount uint64) (*tonconnect.Message, error) {
const WITHDRAW_OP = 0x1000;
payload, _ := cell.BeginCell().
MustStoreUInt(WITHDRAW_OP, 32). // op code for withdrawal
MustStoreUInt(query_id, 64). // query_id
MustStoreCoins(amount). // amount to withdraw
EndCell().MarshalJSON();
msg, err := tonconnect.NewMessage(
single_nominator_address,
tlb.MustFromTON("1").Nano().String(), // nanocoins to transfer/compute message
tonconnect.WithPayload(payload));
if err != nil {
return nil, err;
}
return msg, nil;
}
Election process
Set up a single nominator pool
Configure the single nominator pool contract using the following instructions.
Join the elections
Deposit the minimum stake amount into the single nominator pool.
MyTonCtrl will automatically join the elections. You can set the stake amount that MyTonCtrl sends to the elector contract approximately every 18 hours on Mainnet and 2 hours on Testnet.
MyTonCtrl> set stake 90000
Find the minimum stake amount using the status
command.
You can set stake
to null
, which will calculate based on the stakePercent
value (check with status_settings
).
Verify if the election has started:
MyTonCtrl> status
For Testnet:
MyTonCtrl> status fast
Example:
If the election has started and the single nominator pool is activated, the validator will automatically send an ElectorNewStake message to the elector contract at the beginning of the next round.
Check the validator wallet:
MyTonCtrl> wl
Name Status Balance Ver Wch Address
validator_wallet_001 active 995.828585374 v1 -1 kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct
Check the transaction history:
MyTonCtrl> vas kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct
Address Status Balance Version
kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct active 995.828585374 v1r3
Code hash
c3b9bb03936742cfbb9dcdd3a5e1f3204837f613ef141f273952aa41235d289e
Time Coins From/To
39 minutes ago >>> 1.3 kf_hz3BIXrn5npis1cPX5gE9msp1nMTYKZ3l4obzc8phrBfF
This ElectorNewStake transaction appears in the single nominator contract history on Tonviewer:
In this example, MyTonCtrl automatically staked 90000
Toncoins on the elector contract.
Check validator status
At the beginning of the next round, check the validator status with the status
command (status fast
on Testnet).
Confirm if your node has become a full validator by checking:
- Validator efficiency – The local validator's efficiency should be green and not
n/a
. - Validator index – The validator index should be greater than -1.
Check profit
At the end of the round, MyTonCtrl sends an ElectorRecoverStakeRequest message to the elector contract. It returns stake + profit
to your single nominator pool.
You can also check the pool's transaction history with the vas
command:
Stop participating
If you no longer wish to participate in validation:
- Disable validator mode:
MyTonCtrl> disable_mode validator
- Withdraw all funds from the single nominator contract to the owner wallet.
Transitioning a regular validator to nominator pool mode
- Disable the
validator
mode to stop participating in elections. - Wait for both stakes to return from the elector.
- Follow the steps to set up a single nominator pool.
Single nominator pool client
- Use the open-source client Single nominator client to deploy and interact with the contract.
- For support, contact the team on Telegram.
Run a single nominator pool with a vesting contract
Initially, the owner of the vesting contract manages it with their wallet contract. This scheme involves managing interactions between multiple contracts.
Contracts | Interface for managing |
---|---|
validator_wallet | MyTonCtrl |
vesting | vesting.ton.org |
owner_wallet | Apps like Tonkeeper or MyTonWallet |
single_nominator_pool | MyTonCtrl |
owner_wallet
– The TON wallet that owns thevesting
.
Ensure you have backed up the vesting owner_wallet
recovery phrase. If you lose access to the owner_wallet
, you will also lose access to managing the vesting
funds, and recovery will be impossible.
- Run a full node and wait for it to sync.
- Enable validator mode and retrieve the
wallet_v1
address created during installation usingMyTonCtrl wl
. - Send 200 TON (for monthly expenses) to the
validator_wallet
. - Create a
single_nominator_pool
:
MyTonCtrl> new_single_pool <pool-name> <vesting>
Example:
MyTonCtrl> new_single_pool my_s_pool EQD...lme-D
- Activate the
single_nominator_pool
:
MyTonCtrl> activate_single_pool <pool-name>
Example:
MyTonCtrl> activate_single_pool my_s_pool
- After the
single_nominator_pool
address appears on-chain, request whitelisting from the person who provided the vesting contract. - Once whitelisted, you can send locked tokens from the
vesting
contract to thesingle_nominator_pool
using vesting.ton.org:- a. Connect the
owner_wallet
on vesting.ton.org. - b. Test by sending 10 TON from
vesting
to thesingle_nominator_pool
. - c. Return the remaining funds (~8 TON) to
vesting
with a message [amount 0, commentw
] via the vesting.ton.org interface. - d. Confirm the remaining funds are received in
vesting
.
- a. Connect the
- Transfer the required TON amount from
vesting
tosingle_nominator_pool
for both cycles. - Wait for the validators’ voting.