API
This page documents the public TON INU airdrops contracts so developers can build their own interfaces around the same on-chain flow used by the dApp.
Contract address
Mainnet TinuAirdrop root contract:
EQCObGYt1uR42x9SCGhBmcpEjeW2HnTMpcOdmV0ljFb5wNHO
Testnet TinuAirdrop root contract:
EQBreHwlCD1MaG_ZrP6UtrnX766YVO6KimHEld0o_58E5KjD
Contract model
The public airdrops flow uses:
- one root
TinuAirdropcontract - many
TinuAirdropPoolcontracts, one per airdrop pool
The root contract is used to create pools and discover them.
Each pool contract is used to read pool data and perform participant actions such as claiming.
Public flows
Create a pool
To create a pool, send an internal message to the root TinuAirdrop contract with:
- opcode
0xff000001 jettonDatacellpoolDatacelltimelineDatacell- optional additional info dictionary
The current TON INU dApp sends 15 TON with this message.
Create payload cell formats
jettonData is a cell with:
jettonAddress:addressjettonWalletAddress:address
In the current TON INU dApp, both fields are initially filled with the jetton minter address. The real pool jetton wallet address is set later when the pool is started.
poolData is a cell with:
totalJettonAmount:coinsmaxPerWallet:coinsisPrivate:int1
The current public TON INU flow uses only public pools, so isPrivate is stored as -1 in the 1-bit field.
timelineData is a cell with:
claimStart:uint64claimEnd:uint64
Both timestamps are Unix timestamps in seconds.
additionalInfoData is an optional dictionary cell used for public metadata such as website, social links, and description.
Start a pool
To start a pool, the creator sends a standard jetton transfer to the pool contract and includes a forward payload with:
- opcode
0xfff00001 - the pool jetton wallet address
- the airdrop jetton amount
The current TON INU dApp uses 0.1 TON as the outer message amount and 0.05 TON as the forwarded TON amount inside the jetton transfer.
Claim from a pool
To claim from a started pool, send an internal message directly to the pool contract with:
- opcode
0xfff00004
The current TON INU dApp sends 0.2 TON with this message.
This public page intentionally documents only the normal creator and participant flows. It does not document privileged or operational contract messages.
Root contract read methods
get_airdrop_data()
Returns:
numberOfPoolsnumberOfActivePools
get_pool_data(index)
Returns:
poolAddressownerAddresstimestamp
get_active_pool_data(index)
Returns:
poolAddresstimestamp
get_owned_pools_data(ownerAddress)
Returns a list of pool indexes owned by the provided wallet address.
get_pool_address(ownerAddress, jettonData, poolData, timelineData, additionalInfoData)
Returns the deterministic pool address for a given configuration.
This is useful before sending the create transaction because your UI can predict the pool address in advance.
Pool contract read methods
get_owner_address()
Returns the owner address for the pool.
get_jetton_data()
Returns:
jettonAddressjettonWalletAddress
get_pool_data()
Returns:
totalJettonAmountmaxPerWalletisPrivate
get_timeline_data()
Returns:
claimStartclaimEnd
get_pool_state()
Returns:
stateairdropJettonsjettonsLeftnumOfWallets
Pool states used by the contract are:
0= initial1= started2= finished3= canceled
get_wallet_data(address)
Returns:
addressmaxJettonsclaimedJettons
This is the main getter for checking whether a wallet has already claimed.
TypeScript example: read root data
import { Address, beginCell, Cell } from '@ton/core';
import { TonClient } from '@ton/ton';
const rootAddress = Address.parse('EQCObGYt1uR42x9SCGhBmcpEjeW2HnTMpcOdmV0ljFb5wNHO');
const client = new TonClient({ endpoint: 'https://toncenter.com/api/v2/jsonRPC' });
const data = await client.runMethod(rootAddress, 'get_airdrop_data', []);
const numberOfPools = data.stack.readBigNumber();
const numberOfActivePools = data.stack.readBigNumber();
const pool = await client.runMethod(rootAddress, 'get_pool_data', [
{ type: 'int', value: 0n },
]);
const poolAddress = pool.stack.readAddress();
const ownerAddress = pool.stack.readAddress();
const timestamp = pool.stack.readBigNumber();
TypeScript example: predict pool address
import { Address, beginCell } from '@ton/core';
import { TonClient } from '@ton/ton';
const rootAddress = Address.parse('EQCObGYt1uR42x9SCGhBmcpEjeW2HnTMpcOdmV0ljFb5wNHO');
const ownerAddress = Address.parse('OWNER_WALLET_ADDRESS');
const jettonAddress = Address.parse('JETTON_ADDRESS');
// jettonData: jettonAddress + jettonWalletAddress
const jettonData = beginCell()
.storeAddress(jettonAddress)
.storeAddress(jettonAddress)
.endCell();
// poolData: totalJettonAmount + maxPerWallet + isPrivate
const poolData = beginCell()
.storeCoins(1_000_000n)
.storeCoins(10_000n)
.storeInt(-1n, 1)
.endCell();
// timelineData: claimStart + claimEnd
const timelineData = beginCell()
.storeUint(1_700_000_000n, 64)
.storeUint(1_700_086_400n, 64)
.endCell();
// additionalInfoData: optional metadata dictionary
const additionalInfoData = beginCell().storeDictDirect(null).endCell();
const client = new TonClient({ endpoint: 'https://toncenter.com/api/v2/jsonRPC' });
const result = await client.runMethod(rootAddress, 'get_pool_address', [
{
type: 'slice',
cell: beginCell().storeAddress(ownerAddress).endCell(),
},
{ type: 'cell', cell: jettonData },
{ type: 'cell', cell: poolData },
{ type: 'cell', cell: timelineData },
{ type: 'cell', cell: additionalInfoData },
]);
const predictedPoolAddress = result.stack.readAddress();
TypeScript example: claim
import { Address, beginCell, toNano } from '@ton/core';
const poolAddress = Address.parse('AIRDROP_POOL_ADDRESS');
const body = beginCell()
.storeUint(0xfff00004, 32)
.storeUint(0, 64)
.storeUint(0, 1)
.endCell();
const message = {
address: poolAddress.toString(),
amount: toNano('0.2').toString(),
payload: body.toBoc().toString('base64'),
};