Quick Start
This guide will get you up and running with TokenOps SDK in under 5 minutes. We'll walk through setting up the SDK and demonstrate each major feature with working examples.
Setup
1. Install Dependencies
npm install tokenops-sdk viem
2. Environment Configuration
Create a .env file in your project root:
.env
TOKENOPS_API_KEY=your_api_key_here
RPC_URL=https://eth-sepolia.g.alchemy.com/v2/your_key
PRIVATE_KEY=your_development_private_key
3. Basic Setup
src/setup.ts
import {
ViemProviderAdapter,
TokenOpsApi
} from 'tokenops-sdk';
import {
createPublicClient,
createWalletClient,
http
} from 'viem';
import { sepolia } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
import 'dotenv/config';
// Setup blockchain clients
const publicClient = createPublicClient({
chain: sepolia,
transport: http(process.env.RPC_URL)
});
const walletClient = createWalletClient({
chain: sepolia,
transport: http(process.env.RPC_URL),
account: privateKeyToAccount(process.env.PRIVATE_KEY)
});
// Create provider adapter
export const provider = new ViemProviderAdapter(publicClient, walletClient);
// Initialize API client
export const api = new TokenOpsApi(process.env.TOKENOPS_API_KEY);
Feature Walkthroughs
Token Vesting
Create a simple vesting schedule for team tokens:
examples/vesting.ts
import { TokenVestingManagerFactory, TokenVestingManager } from 'tokenops-sdk';
import { provider } from './setup';
// Example function to create a vesting schedule
async function createVestingSchedule() {
// Factory address (testnet)
const factoryAddress = '0x...'; // Get from https://docs.tokenops.xyz/deployment-addresses
const tokenAddress = '0x...'; // Your ERC20 token
// 1. Deploy vesting manager
const factory = new TokenVestingManagerFactory(factoryAddress, provider);
const result = await factory.newTokenVestingManager(
tokenAddress,
BigInt(1), // Partial funding
{
account: provider.walletClient.account!.address,
value: BigInt(0)
}
);
console.log('Vesting manager deployed:', result.tokenVestingManager);
// 2. Create vesting schedule
const manager = new TokenVestingManager(
result.tokenVestingManager,
tokenAddress,
provider
);
const now = Math.floor(Date.now() / 1000);
const vestingParams = {
recipient: '0x742d35Cc6632C0532c718F4D8c2b1D1F8a1B9F36',
startTimestamp: BigInt(now + 60), // Start in 1 minute
endTimestamp: BigInt(now + 86400), // End in 24 hours
timelock: BigInt(0), // No additional timelock
initialUnlock: BigInt(0), // No immediate unlock
cliffReleaseTimestamp: BigInt(now + 3600), // 1 hour cliff
cliffAmount: BigInt('1000000000000000000'), // 1 token
releaseIntervalSecs: BigInt(3600), // Release hourly
linearVestAmount: BigInt('10000000000000000000'), // 10 tokens total
isRevocable: true
};
const vesting = await manager.createVesting(
vestingParams.recipient,
vestingParams.startTimestamp,
vestingParams.endTimestamp,
vestingParams.timelock,
vestingParams.initialUnlock,
vestingParams.cliffReleaseTimestamp,
vestingParams.cliffAmount,
vestingParams.releaseIntervalSecs,
vestingParams.linearVestAmount,
vestingParams.isRevocable,
{
account: provider.walletClient.account!.address,
amount: BigInt('11000000000000000000') // Total amount to fund
}
);
console.log('Vesting created:', vesting.vestingId);
return vesting.vestingId;
}
// Run example
createVestingSchedule().catch(console.error);
Staking Pool
Set up a staking pool with rewards:
examples/staking.ts
import { StakingFactory, Staking } from 'tokenops-sdk';
import { provider } from './setup';
// Example function to create a staking pool
async function createStakingPool() {
const factoryAddress = '0x...'; // Get from TokenOps docs
const stakingToken = '0x...'; // Token to stake
// 1. Deploy staking contract
const factory = new StakingFactory(factoryAddress, provider);
const now = Math.floor(Date.now() / 1000);
const stakingParams = {
merkleRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
whitelistStatus: 0, // No whitelist
poolMaxCap: BigInt('1000000000000000000000'), // 1000 tokens max
stakingToken: stakingToken,
timeUnit: BigInt(86400), // Daily rewards
rewardRatioNumerator: BigInt(1), // 1% daily
rewardRatioDenominator: BigInt(100),
tierUpperBound: BigInt('100000000000000000000'), // 100 tokens
tierLowerBound: BigInt('10000000000000000000'), // 10 tokens
startStakingDate: BigInt(now + 60), // Start in 1 minute
endStakingDate: BigInt(now + 2592000) // End in 30 days
};
const result = await factory.newStaking(
stakingParams.merkleRoot,
stakingParams.whitelistStatus,
stakingParams.poolMaxCap,
stakingParams.stakingToken,
stakingParams.timeUnit,
stakingParams.rewardRatioNumerator,
stakingParams.rewardRatioDenominator,
stakingParams.tierUpperBound,
stakingParams.tierLowerBound,
stakingParams.startStakingDate,
stakingParams.endStakingDate
);
console.log('Staking pool deployed:', result.stakingContract);
// 2. Stake tokens
const staking = new Staking(result.stakingContract, stakingToken, provider);
// Stake 50 tokens
const stakeAmount = BigInt('50000000000000000000');
await staking.stake(
stakeAmount,
[], // No merkle proof needed (no whitelist)
{ account: provider.walletClient.account!.address }
);
console.log('Staked:', stakeAmount.toString(), 'tokens');
return result.stakingContract;
}
// Run example
createStakingPool().catch(console.error);
Token Airdrop
Deploy a Merkle-based airdrop:
examples/airdrop.ts
import { MerkleDistributorFactory, MerkleDistributorERC20 } from 'tokenops-sdk';
import { provider } from './setup';
// Example function to create a merkle-based airdrop
async function createAirdrop() {
const factoryAddress = '0x...'; // Get from TokenOps docs
const tokenAddress = '0x...'; // Token to distribute
// 1. Deploy airdrop contract
const factory = new MerkleDistributorFactory(factoryAddress, provider);
const now = Math.floor(Date.now() / 1000);
const airdropParams = {
tokenAddress: tokenAddress,
merkleRoot: '0x1234...', // Generate from your recipient list
startTime: now + 60, // Start in 1 minute
endTime: now + 86400, // End in 24 hours
stakingAddress: '0x0000000000000000000000000000000000000000', // No staking
rewardOwner: provider.walletClient.account!.address,
bonusPercentage: 0 // No bonus
};
const result = await factory.newMerkleDistributor(
airdropParams.tokenAddress,
airdropParams.merkleRoot,
airdropParams.startTime,
airdropParams.endTime,
airdropParams.stakingAddress,
airdropParams.rewardOwner,
airdropParams.bonusPercentage,
{
account: provider.walletClient.account!.address,
value: BigInt(0)
}
);
console.log('Airdrop deployed:', result.merkleDistributor);
// 2. Claim from airdrop (example)
const distributor = new MerkleDistributorERC20(result.merkleDistributor, provider);
// Example claim (you'll need real proof data)
const claimParams = {
index: 0,
account: provider.walletClient.account!.address,
amount: BigInt('1000000000000000000'), // 1 token
merkleProof: ['0x...'] // Generate from merkle tree
};
// Note: This will fail without valid proof
// await distributor.claim(
// claimParams.index,
// claimParams.account,
// claimParams.amount,
// claimParams.merkleProof,
// { account: provider.walletClient.account!.address }
// );
return result.merkleDistributor;
}
// Run example
createAirdrop().catch(console.error);
Bulk Token Distribution
Send tokens to multiple recipients efficiently:
examples/disperse.ts
import { DisperseFactory, DisperseTokenFee } from 'tokenops-sdk';
import { provider } from './setup';
async function bulkDistribution() {
const factoryAddress = '0x...'; // Get from TokenOps docs
// 1. Deploy disperse contract
const factory = new DisperseFactory(factoryAddress, provider);
const result = await factory.newDisperseTokenFee({
account: provider.walletClient.account!.address
});
console.log('Disperse contract deployed:', result.disperse);
// 2. Distribute tokens
const disperse = new DisperseTokenFee(result.disperse, provider);
const tokenAddress = '0x...'; // Token to distribute
const recipients = [
'0x742d35Cc6632C0532c718F4D8c2b1D1f8a1B9F36',
'0x8ba1f109551bD432803012645Hac136c24F4a8E5',
'0x1234567890123456789012345678901234567890'
];
const amounts = [
BigInt('1000000000000000000'), // 1 token
BigInt('2000000000000000000'), // 2 tokens
BigInt('3000000000000000000') // 3 tokens
];
await disperse.disperseToken(
tokenAddress,
recipients,
amounts,
{ account: provider.walletClient.account!.address }
);
console.log('Bulk distribution complete!');
return result.disperse;
}
// Run example
bulkDistribution().catch(console.error);
Analytics API
Monitor your contracts and get insights:
examples/analytics.ts
import { TokenOpsApi } from 'tokenops-sdk';
async function getAnalytics() {
const api = new TokenOpsApi(process.env.TOKENOPS_API_KEY!);
// 1. Test API connection
const ping = await api.ping();
console.log('API Status:', ping);
// 2. Get vesting contract info
const chainId = 11155111; // Sepolia
const contractAddress = '0x...'; // Your vesting contract
const vestingInfo = await api.vesting(chainId, contractAddress);
console.log('Vesting Info:', vestingInfo);
// 3. Get vesting grants
const grants = await api.vestingGrants(
chainId,
contractAddress,
undefined, // tokenAddress (optional)
undefined, // recipientAddress (optional)
undefined, // eventType (optional)
1, // page
10 // size
);
console.log('Grants:', grants);
// 4. Get insights
const insights = await api.vestingInsights(
chainId,
contractAddress
);
console.log('Insights:', insights);
// 5. Subscribe to events (webhook)
await api.vestingSubscribe(
chainId,
contractAddress,
['VestingCreated', 'Claimed'],
'https://your-webhook-url.com/tokenops'
);
console.log('Webhook subscription created');
}
// Run example
getAnalytics().catch(console.error);
Complete Example Application
Here's a complete example that demonstrates multiple features:
examples/complete-example.ts
import { provider } from './setup';
import { TokenOpsApi } from 'tokenops-sdk';
import {
TokenVestingManagerFactory,
TokenVestingManager,
StakingFactory
} from 'tokenops-sdk';
const api = new TokenOpsApi(process.env.TOKENOPS_API_KEY!);
async function completeExample() {
console.log('Starting TokenOps SDK Complete Example');
try {
// 1. Test API connection
const ping = await api.ping();
console.log('✅ API Connected:', ping.message);
// 2. Deploy vesting manager
const vestingFactory = new TokenVestingManagerFactory(
'0x...', // Factory address
provider
);
const vestingResult = await vestingFactory.newTokenVestingManager(
'0x...', // Token address
BigInt(1),
{
account: provider.walletClient.account!.address,
value: BigInt(0)
}
);
console.log('✅ Vesting Manager Deployed:', vestingResult.tokenVestingManager);
// 3. Create vesting schedule
const manager = new TokenVestingManager(
vestingResult.tokenVestingManager,
'0x...', // Token address
provider
);
const now = Math.floor(Date.now() / 1000);
const vesting = await manager.createVesting(
'0x742d35Cc6632C0532c718F4D8c2b1D1f8a1B9F36', // Recipient
BigInt(now + 60), // Start
BigInt(now + 86400), // End
BigInt(0), // Timelock
BigInt(0), // Initial unlock
BigInt(now + 3600), // Cliff
BigInt('1000000000000000000'), // Cliff amount
BigInt(3600), // Release interval
BigInt('10000000000000000000'), // Linear amount
true, // Revocable
{
account: provider.walletClient.account!.address,
amount: BigInt('11000000000000000000')
}
);
console.log('✅ Vesting Schedule Created:', vesting.vestingId);
// 4. Monitor with API
setTimeout(async () => {
const vestingInfo = await api.vesting(
11155111, // Sepolia
vestingResult.tokenVestingManager
);
console.log('Vesting Info:', vestingInfo);
}, 5000);
console.log('🎉 Complete example finished successfully!');
} catch (error) {
console.error('❌ Error:', error);
}
}
// Run complete example
completeExample();
Common Issues
Transaction Failures
// Always check transaction receipts
const receipt = await provider.viemClient.getTransactionReceipt({ hash: txHash });
if (receipt.status === 'reverted') {
console.error('Transaction reverted');
}
API Rate Limits
// Handle rate limits gracefully
try {
const result = await api.vesting(chainId, contractAddress);
} catch (error) {
if (error.message.includes('rate limit')) {
// Wait and retry
await new Promise(resolve => setTimeout(resolve, 1000));
// Retry logic here
}
}
Getting Help
Telegram Community: Join Telegram
Ready to build more? Explore the Core Features to learn about advanced functionality!