API
This page documents the public TON INU locker contract so developers can build their own interfaces around the same on-chain flow used by the dApp.
Contract address
Mainnet TinuLocker contract:
EQD32LX69WZ375NJ0y8b5WdyK03XVjeOaDWuWAVTuio1YxRI
How lock creation works
A new lock is created when a jetton wallet sends a standard jetton transfer to the locker contract and includes a forward payload with:
- opcode
0xff000001(lock) unlockAtTimestampas a 64-bit Unix timestamp in seconds
The locker then receives the jetton transfer_notification and stores the lock under the sender jetton wallet address.
If you are building a custom UI, the user does not send the lock message directly to TinuLocker. The user sends a jetton transfer from their jetton wallet to the locker contract.
Read methods
get_jetton_wallets()
Returns a list of jetton wallet addresses that currently have at least one stored lock record.
get_address_data(jettonWalletAddress)
Returns:
jettonWalletAddressnumOfLocks
If the address is unknown, the contract returns the requested address and 0.
get_lock_data(jettonWalletAddress, index)
Returns one lock record:
lockTimestampamountunlockAtTimestampowner
If the lock does not exist, the contract returns zero values and null owner.
get_address_full_data(jettonWalletAddress)
Returns:
jettonWalletAddressnumOfLocks- full lock tuple list for that jetton wallet address
This is the most convenient getter when you want to render a full lock list in one call.
Safe write flow
Create lock via jetton transfer
Your UI should send a standard jetton transfer body to the user's jetton wallet with:
destination = TinuLocker addressforwardTonAmount = 0.05 TONforwardPayload = lock opcode + unlock timestamp- outer TON value large enough to cover gas and the locker
lockPrice
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.
This public page intentionally documents only the normal lock creation flow. It does not document privileged or operational contract messages.
TypeScript example
import { Address, beginCell } from '@ton/core';
import { TonClient } from '@ton/ton';
const lockerAddress = Address.parse('EQD32LX69WZ375NJ0y8b5WdyK03XVjeOaDWuWAVTuio1YxRI');
const jettonWalletAddress = Address.parse('JETTON_WALLET_ADDRESS');
const client = new TonClient({ endpoint: 'https://toncenter.com/api/v2/jsonRPC' });
const addressData = await client.runMethod(lockerAddress, 'get_address_data', [
{
type: 'slice',
cell: beginCell().storeAddress(jettonWalletAddress).endCell(),
},
]);
const storedWallet = addressData.stack.readAddress();
const numOfLocks = addressData.stack.readBigNumber();
const firstLock = await client.runMethod(lockerAddress, 'get_lock_data', [
{
type: 'slice',
cell: beginCell().storeAddress(jettonWalletAddress).endCell(),
},
{ type: 'int', value: 0n },
]);
const lockTimestamp = firstLock.stack.readBigNumber();
const amount = firstLock.stack.readBigNumber();
const unlockAtTimestamp = firstLock.stack.readBigNumber();
const owner = firstLock.stack.readAddressOpt();
Jetton transfer payload example for creating a lock
import { Address, beginCell, toNano } from '@ton/core';
const lockerAddress = Address.parse('EQD32LX69WZ375NJ0y8b5WdyK03XVjeOaDWuWAVTuio1YxRI');
const userAddress = Address.parse('USER_WALLET_ADDRESS');
const jettonAmount = 1_000_000n;
const unlockAtTimestamp = BigInt(Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60);
const forwardPayload = beginCell()
.storeUint(0xff000001, 32)
.storeUint(unlockAtTimestamp, 64)
.endCell();
const jettonTransferBody = beginCell()
.storeUint(0xf8a7ea5, 32)
.storeUint(0, 64)
.storeCoins(jettonAmount)
.storeAddress(lockerAddress)
.storeAddress(userAddress)
.storeBit(0)
.storeCoins(toNano('0.05'))
.storeBit(1)
.storeRef(forwardPayload)
.endCell();
Send that body to the user's jetton wallet contract, not directly to the locker.