API
This page documents the public TON INU presale launchpad contracts so developers can build their own interfaces around the same on-chain flow used by the dApp.
Contract address
Mainnet TinuPresaleLaunchpad root contract:
EQBlXgjjZvEjZr0acefeymEq2j53muFkENYjuVdCLHtaX-Kd
Testnet TinuPresaleLaunchpad root contract:
EQCuq9Z926XNC1CNjlCpiieh-UMLVtm-_zaoCbRsDlXPeOUI
Contract model
The public launchpad flow uses:
- one root
TinuPresaleLaunchpadcontract - many
TinuPresaleLaunchpoolcontracts, one per presale
The root contract is used to create launchpools and discover them.
Each launchpool contract is used to read sale data and perform participant actions such as buy, claim, and refund.
Public flows
Create a launchpool
To create a launchpool, send an internal message to the root TinuPresaleLaunchpad contract with:
- opcode
0xff000001 jettonDatacelllaunchpoolDatacelltimelineDatacell- 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 launchpool is started.
launchpoolData is a cell with:
- ref 1:
softCap:coins,hardCap:coins - ref 2:
minBuy:coins,maxBuy:coins - ref 3:
presaleRate:coins,listingRate:coins liquidityPercent:uint8
TON values are stored in nanotons. Rate values are stored using jetton base units, so they depend on the jetton decimals.
timelineData is a cell with:
presaleStart:uint64presaleEnd:uint64claimStart:uint64
All 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 launchpool
To start a launchpool, the creator sends a standard jetton transfer to the pool contract and includes a forward payload with:
- opcode
0xfff00001 - the launchpool jetton wallet address
- the presale jetton amount
- the listing 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.
Buy in a launchpool
To buy during an active presale, send an internal message directly to the launchpool contract with:
- opcode
0xfff00003 - contribution amount in nanotons
The current TON INU dApp sends amount + 0.1 TON with this message.
Claim jettons
To claim purchased jettons from a successful launchpool, send an internal message directly to the launchpool contract with:
- opcode
0xfff00004
The current TON INU dApp sends 0.2 TON with this message.
Claim refund
To claim a TON refund from a refundable launchpool, send an internal message directly to the launchpool contract with:
- opcode
0xfff00005
The current TON INU dApp sends 0.1 TON with this message.
This public page intentionally documents only the normal creator and investor flows. It does not document privileged or operational contract messages.
Root contract read methods
get_launchpad_data()
Returns:
numberOfLaunchpoolsnumberOfActiveLaunchpools
get_launchpool_data(index)
Returns:
launchpoolAddressownerAddresstimestamp
get_active_launchpool_data(index)
Returns:
launchpoolAddresstimestamp
get_owned_launchpools_data(ownerAddress)
Returns a list of launchpool indexes owned by the provided wallet address.
get_launchpool_address(ownerAddress, jettonData, launchpoolData, timelineData, additionalInfoData)
Returns the deterministic launchpool address for a given configuration.
This is useful before sending the create transaction because your UI can predict the launchpool address in advance.
Launchpool contract read methods
get_owner_address()
Returns the owner address for the launchpool.
get_jetton_data()
Returns:
jettonAddressjettonWalletAddresslaunchpadAddress
get_launchpool_data()
Returns:
softCaphardCapminBuymaxBuypresaleRatelistingRateliquidityPercent
get_timeline_data()
Returns:
presaleStartpresaleEndclaimStart
get_launchpool_state()
Returns:
statepresaleJettonsjettonsLeftlistingJettonsnumOfContributorstotalContributions
Launchpool states used by the contract are:
0= initial1= started2= finished3= canceled
get_contributor_data(address)
Returns:
addresscontributedAmountboughtJettonsclaimedJettonsrefunded
This is the main getter for checking a walletβs contribution, claim status, and refund status.
TypeScript example: read root data
import { Address } from '@ton/core';
import { TonClient } from '@ton/ton';
const rootAddress = Address.parse('EQBlXgjjZvEjZr0acefeymEq2j53muFkENYjuVdCLHtaX-Kd');
const client = new TonClient({ endpoint: 'https://toncenter.com/api/v2/jsonRPC' });
const data = await client.runMethod(rootAddress, 'get_launchpad_data', []);
const numberOfLaunchpools = data.stack.readBigNumber();
const numberOfActiveLaunchpools = data.stack.readBigNumber();
const pool = await client.runMethod(rootAddress, 'get_launchpool_data', [
{ type: 'int', value: 0n },
]);
const launchpoolAddress = pool.stack.readAddress();
const ownerAddress = pool.stack.readAddress();
const timestamp = pool.stack.readBigNumber();
TypeScript example: predict launchpool address
import { Address, beginCell } from '@ton/core';
import { TonClient } from '@ton/ton';
const rootAddress = Address.parse('EQBlXgjjZvEjZr0acefeymEq2j53muFkENYjuVdCLHtaX-Kd');
const ownerAddress = Address.parse('OWNER_WALLET_ADDRESS');
const jettonAddress = Address.parse('JETTON_ADDRESS');
// jettonData: jettonAddress + jettonWalletAddress
const jettonData = beginCell()
.storeAddress(jettonAddress)
.storeAddress(jettonAddress)
.endCell();
// launchpoolData: caps + buy limits + rates + liquidity percent
const launchpoolData = beginCell()
.storeRef(beginCell().storeCoins(100_000_000_000n).storeCoins(200_000_000_000n).endCell())
.storeRef(beginCell().storeCoins(1_000_000_000n).storeCoins(10_000_000_000n).endCell())
.storeRef(beginCell().storeCoins(1_000_000n).storeCoins(800_000n).endCell())
.storeUint(60, 8)
.endCell();
// timelineData: presaleStart + presaleEnd + claimStart
const timelineData = beginCell()
.storeUint(1_700_000_000n, 64)
.storeUint(1_700_086_400n, 64)
.storeUint(1_700_172_800n, 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_launchpool_address', [
{
type: 'slice',
cell: beginCell().storeAddress(ownerAddress).endCell(),
},
{ type: 'cell', cell: jettonData },
{ type: 'cell', cell: launchpoolData },
{ type: 'cell', cell: timelineData },
{ type: 'cell', cell: additionalInfoData },
]);
const predictedLaunchpoolAddress = result.stack.readAddress();
TypeScript example: buy
import { Address, beginCell, toNano } from '@ton/core';
const launchpoolAddress = Address.parse('LAUNCHPOOL_ADDRESS');
const amount = toNano('5');
const body = beginCell()
.storeUint(0xfff00003, 32)
.storeUint(0, 64)
.storeCoins(amount)
.storeUint(0, 1)
.endCell();
const message = {
address: launchpoolAddress.toString(),
amount: (toNano('0.1') + amount).toString(),
payload: body.toBoc().toString('base64'),
};
TypeScript example: claim refund
import { Address, beginCell, toNano } from '@ton/core';
const launchpoolAddress = Address.parse('LAUNCHPOOL_ADDRESS');
const body = beginCell()
.storeUint(0xfff00005, 32)
.storeUint(0, 64)
.storeUint(0, 1)
.endCell();
const message = {
address: launchpoolAddress.toString(),
amount: toNano('0.1').toString(),
payload: body.toBoc().toString('base64'),
};