@cyreneai/fee-claimer
v0.3.0
Published
Server-side SDK for Cyrene partner fee flows (DBC/DAMM v2).
Readme
@cyreneai/fee-claimer
TypeScript SDK for claiming partner fees from Cyrene AI-powered DBC (Dynamic Bonding Curve) and DAMM (Decentralized Automated Market Maker) pools on Solana.
Installation
npm install @cyreneai/fee-claimerQuick Start
import { CyrenePartnerFeesClient } from '@cyreneai/fee-claimer';
const client = new CyrenePartnerFeesClient({
baseUrl: 'https://cyreneai.com',
apiKey: process.env.CYRENE_API_KEY!,
cluster: 'MAINNET', // or 'DEVNET'
});
// Prepare partner launch transactions
const launch = await client.launchWithPartners({
tokenName: 'My Token',
tokenSymbol: 'MTK',
tokenImage: 'https://ipfs.erebrus.io/ipfs/...',
totalTokenSupply: 1_000_000_000,
migrationQuoteThreshold: 10,
platform: { address: 'PLATFORM_WALLET', bps: 5000 },
creator: { address: 'CREATOR_WALLET', bps: 2000 },
partner1: { address: 'PARTNER_1_WALLET', bps: 1000 },
partner2: { address: 'PARTNER_2_WALLET', bps: 1000 },
});
// Sign and submit launch.serializedConfigTransaction / serializedPoolTransaction
// with the partner wallet, then initialize the DBC pool:
// Initialize fee claimers for a DBC pool
await client.initializeDbcPool({
dbcPoolAddress: launch.dbcPoolAddress,
platform: { address: 'PLATFORM_WALLET', bps: 5000 },
creator: { address: 'CREATOR_WALLET', bps: 2000 },
partner1: { address: 'PARTNER_1_WALLET', bps: 1000 },
partner2: { address: 'PARTNER_2_WALLET', bps: 1000 },
});
// Or use the higher-level helper:
await client.launchAndInitializeDbc(
{
tokenName: 'My Token',
tokenSymbol: 'MTK',
tokenImage: 'https://ipfs.erebrus.io/ipfs/...',
totalTokenSupply: 1_000_000_000,
migrationQuoteThreshold: 10,
platform: { address: 'PLATFORM_WALLET', bps: 5000 },
creator: { address: 'CREATOR_WALLET', bps: 2000 },
partner1: { address: 'PARTNER_1_WALLET', bps: 1000 },
partner2: { address: 'PARTNER_2_WALLET', bps: 1000 },
},
async (launch) => {
// Your app/server signs and submits launch.serializedConfigTransaction,
// launch.serializedPoolTransaction, and optional launch.swapSerializedTransaction.
return {
configSignature: 'CONFIG_TX_SIGNATURE',
poolSignature: 'POOL_TX_SIGNATURE',
firstBuySignature: 'OPTIONAL_FIRST_BUY_SIGNATURE',
};
},
);
// Check individual claimable amounts
const amounts = await client.claimableAmounts({
dbcPoolAddress: 'DBC_POOL_ADDRESS',
partnerWalletAddress: 'PARTNER_1_WALLET',
});
console.log(`Claimable: ${amounts.dbc.walletBaseFee} base tokens`);
// Claim and distribute fees
await client.claimPartnerFees({ dbcPoolAddress: 'DBC_POOL_ADDRESS' });Configuration
interface ClientConfig {
baseUrl: string; // API base URL
apiKey: string; // Your Cyrene API key
cluster?: 'MAINNET' | 'DEVNET';
timeoutMs?: number; // Request timeout (default: 30000)
retries?: number; // Retry attempts (default: 2)
retryDelayMs?: number; // Retry delay (default: 500)
}API Reference
launchWithPartners
Prepare config, pool, and optional first-buy transactions for a partner launch flow.
const result = await client.launchWithPartners({
tokenName: 'My Token', // required
tokenSymbol: 'MTK', // required
tokenImage: 'https://ipfs.erebrus.io/ipfs/...', // required
tokenDescription: 'Optional token description', // optional
totalTokenSupply: 1_000_000_000, // required
migrationQuoteThreshold: 10, // required
quoteMint: 'SOL', // optional
cluster: 'MAINNET', // optional
isEarlySalesEnabled: false, // optional
enableFirstBuy: true, // optional
firstBuyAmountSol: 0.1, // optional, required when enableFirstBuy is true
minimumTokensOut: 0, // optional, required when enableFirstBuy is true
customVestingParams: { // optional
totalLockedVestingAmount: 100000000,
numberOfVestingPeriod: 6,
cliffUnlockAmount: 50000000,
totalVestingDuration: 15552000,
cliffDurationFromMigrationTime: 15552000,
},
lockedVestingParam: { // optional
totalLockedVestingAmount: 100000000,
numberOfVestingPeriod: 6,
cliffUnlockAmount: 50000000,
totalVestingDuration: 15552000,
cliffDurationFromMigrationTime: 15552000,
},
platform: { address: 'PLATFORM_WALLET', bps: 5000 }, // optional
creator: { address: 'CREATOR_WALLET', bps: 2000 }, // optional
partner1: { address: 'PARTNER_1', bps: 1000 }, // optional
partner2: { address: 'PARTNER_2', bps: 1000 }, // optional
baseMintPrivateKey: 'BASE58_OR_JSON_ARRAY', // optional
});
// Response
{
configAddress: string;
baseMint: string;
baseMintSource: 'provided' | 'vanity';
dbcPoolAddress: string;
initializePoolPayload: {
dbcPoolAddress: string;
cluster: 'MAINNET' | 'DEVNET';
platform: { address: string; bps: number } | null;
creator: { address: string; bps: number } | null;
partner1: { address: string; bps: number } | null;
partner2: { address: string; bps: number } | null;
};
serializedConfigTransaction: string;
serializedPoolTransaction: string;
swapSerializedTransaction: string | null;
}Notes:
- Required payload fields:
tokenName,tokenSymbol,tokenImage,totalTokenSupply,migrationQuoteThreshold. - The role split is validated as a 10000-scale input across
platform,creator,partner1, andpartner2. firstBuyAmountSolandminimumTokensOutare required only whenenableFirstBuyistrue.customVestingParamsandlockedVestingParamare alternative optional vesting inputs. If both are omitted, server defaults are used.baseMintPrivateKeyis optional. If omitted, the API uses the server-side fallback flow configured for base mint selection.
launchAndInitializeDbc
Run the full DBC launch flow:
- call
launchWithPartners - execute the returned transactions through your wallet/signer callback
- call
initializeDbcPoolautomatically
const result = await client.launchAndInitializeDbc(
{
tokenName: 'My Token',
tokenSymbol: 'MTK',
tokenImage: 'https://ipfs.erebrus.io/ipfs/...',
totalTokenSupply: 1_000_000_000,
migrationQuoteThreshold: 10,
platform: { address: 'PLATFORM_WALLET', bps: 5000 },
creator: { address: 'CREATOR_WALLET', bps: 2000 },
},
async (launch) => {
// Sign and submit the returned transactions in your own environment.
return {
configSignature: 'CONFIG_TX_SIGNATURE',
poolSignature: 'POOL_TX_SIGNATURE',
firstBuySignature: null,
};
},
);
// Response
{
launch: LaunchWithPartnersResponse;
execution: {
configSignature: string;
poolSignature: string;
firstBuySignature?: string | null;
};
initializePool: InitializePoolResponse;
}Notes:
- The SDK still does not sign transactions by itself.
- Your callback must actually submit and confirm the launch transactions before returning.
- Once the callback returns, the SDK calls
initializeDbcPoolautomatically usinglaunch.initializePoolPayload.
initializeDbcPool
Initialize DBC pool claimers and create Address Lookup Table.
const result = await client.initializeDbcPool({
dbcPoolAddress: 'DBC_POOL_ADDRESS',
platform: { address: 'PLATFORM_WALLET', bps: 5000 },
creator: { address: 'CREATOR_WALLET', bps: 2000 },
partner1: { address: 'WALLET_1', bps: 1000 },
partner2: { address: 'WALLET_2', bps: 1000 },
cluster: 'MAINNET', // optional
});
// Response
{
transaction: string;
transactionLink: string;
altAddress?: string;
dbcPoolAddress: string;
claimersCount: number;
totalBps: number;
normalizedInputTotalBps: number;
denormalizedVariableTotalBps: number;
normalizedRoles: Array<{ role: string; address: string; inputBps: number }>;
}initializeDammV2Pool
Initialize DAMM v2 pool claimers and create Address Lookup Table.
const result = await client.initializeDammV2Pool({
dammPoolAddress: 'DAMM_POOL_ADDRESS',
partners: [
{ address: 'WALLET_1', bps: 500 },
{ address: 'WALLET_2', bps: 250 },
],
cluster: 'MAINNET', // optional
});
// Response
{
transaction: string;
transactionLink: string;
dammPoolAddress: string;
claimersCount: number;
}claimableAmounts
Get individual claimable amounts for a wallet. Automatically handles graduation check.
const amounts = await client.claimableAmounts({
dbcPoolAddress: 'DBC_POOL_ADDRESS',
partnerWalletAddress: 'PARTNER_WALLET',
cluster: 'MAINNET', // optional
});
// Response
{
dbcPoolAddress: string;
partnerWalletAddress: string;
isGraduated: boolean;
dammPoolAddress?: string;
dbc: {
totalPartnerBaseFee: string;
totalPartnerQuoteFee: string;
walletBps: number;
walletBaseFee: string;
walletQuoteFee: string;
};
dammV2: {
totalPartnerFeeA: string;
totalPartnerFeeB: string;
walletBps: number;
walletFeeA: string;
walletFeeB: string;
};
}claimPartnerFees
Claim and distribute fees. Automatically uses correct ALT for DBC and DAMM.
const result = await client.claimPartnerFees({
dbcPoolAddress: 'DBC_POOL_ADDRESS',
partnerWalletAddress: 'SPECIFIC_WALLET', // optional
cluster: 'MAINNET', // optional
});
// Response
{
dbc: {
claimed: boolean;
baseAmount: string;
quoteAmount: string;
claimTx: string | null;
distributeTx: string | null;
};
dammV2?: {
initialized: boolean;
claimed: boolean;
baseAmount: string;
quoteAmount: string;
claimTx: string | null;
distributeTx: string | null;
};
isGraduated: boolean;
dammPoolAddress?: string;
}checkGraduation
Check if DBC pool has graduated to DAMM.
const result = await client.checkGraduation({
dbcPoolAddress: 'DBC_POOL_ADDRESS',
cluster: 'MAINNET', // optional
});
// Response
{
dbcPoolAddress: string;
graduated: boolean;
progress: number; // 0.0 to 1.0
dammPoolAddress?: string;
message: string;
}custodyPartners
Fetch on-chain claimer state for DBC or DAMM pools.
const result = await client.custodyPartners({
dbcPoolAddress: 'DBC_POOL_ADDRESS', // provide exactly one
// or dammPoolAddress: 'DAMM_POOL_ADDRESS',
cluster: 'MAINNET', // optional
});
// Response
{
pool: string;
claimerAddresses: string[];
claimerBps: number[];
poolState: 'Dbc' | 'DammV2' | 'NotInitialized';
claimers: Array<{ address: string; bps: number }>;
}Complete Workflow Example
import { CyrenePartnerFeesClient } from '@cyreneai/fee-claimer';
const client = new CyrenePartnerFeesClient({
baseUrl: 'https://cyreneai.com',
apiKey: process.env.CYRENE_API_KEY!,
cluster: 'MAINNET',
});
async function runWorkflow() {
const wallet = 'PARTNER_WALLET_ADDRESS';
// 1. Prepare launch transactions
const launch = await client.launchWithPartners({
tokenName: 'My Token',
tokenSymbol: 'MTK',
tokenImage: 'https://ipfs.erebrus.io/ipfs/...',
totalTokenSupply: 1_000_000_000,
migrationQuoteThreshold: 10,
platform: { address: 'PLATFORM_WALLET', bps: 5000 },
creator: { address: wallet, bps: 5000 },
});
// 2. Sign and submit the returned transactions with the partner wallet.
// After confirmation, initialize the DBC claimers.
await client.initializeDbcPool({
dbcPoolAddress: launch.dbcPoolAddress,
platform: { address: 'PLATFORM_WALLET', bps: 5000 },
creator: { address: wallet, bps: 5000 },
});
// 3. Check claimable amounts
const amounts = await client.claimableAmounts({
dbcPoolAddress: launch.dbcPoolAddress,
partnerWalletAddress: wallet,
});
// 4. Check graduation status
const grad = await client.checkGraduation({ dbcPoolAddress: launch.dbcPoolAddress });
// 5. Initialize DAMM if graduated
if (grad.graduated && grad.dammPoolAddress) {
await client.initializeDammV2Pool({
dammPoolAddress: grad.dammPoolAddress,
partners: [{ address: wallet, bps: 500 }],
});
}
// 6. Claim fees
await client.claimPartnerFees({ dbcPoolAddress: launch.dbcPoolAddress });
// 7. Verify custody state
const custody = await client.custodyPartners({ dbcPoolAddress: launch.dbcPoolAddress });
console.log('Pool state:', custody.poolState);
}
runWorkflow().catch(console.error);Error Handling
import { CyreneApiError } from '@cyreneai/fee-claimer';
try {
await client.claimPartnerFees({ dbcPoolAddress: 'INVALID' });
} catch (error) {
if (error instanceof CyreneApiError) {
console.error('Status:', error.status);
console.error('Message:', error.message);
if (error.status === 401) console.error('Invalid API key');
if (error.status === 404) console.error('Pool not found');
if (error.status === 400) console.error('Bad request');
}
}License
MIT
