sendfun-sdk
Rust SDK for the send.fun programs on Solana.
launchpad: token creation, bonding curve trades, migration.dex: AMM trades after migration.nexus: staking and partner fees.transfer_hook: Token-2022 transfer-hook resolution.utils:MintInfo.
The SDK builds instructions, decodes accounts and events, and calculates quotes
(launchpad::quote, dex::quote). It has no RPC client and does not send
transactions.
Fetch accounts with your own client. Compatible: solana-rpc-client 3.x and
4.1+, blocking and nonblocking. Not compatible: 4.0.x.
Decode an account with the from_account function of its type. from_account
checks the owner, then the discriminator:
use BondingCurve;
let account = rpc.get_account?;
let curve = from_account?;
get_account fails when the account does not exist. For an account that can
be missing, use get_account_with_commitment. Its value is None for a
missing account. Decode with from_account_maybe. It returns Ok(None) for an
uncreated PDA that holds lamports.
Install
Optional features:
serde:SerializeandDeserializeon accounts, events and types.anchor:anchor-langinterop for on-chain callers.
Rules
- For a trade, read
platform_configfrom the bonding curve or the pool. - A partner other than
DEFAULT_PARTNERmust sign. constants::find_platform_address(slug)returns the key of a platform.- Each trade, migrate and create builder takes a
MintInfofor the base mint and aMintInfofor the quote mint. For the new base mint of a create, useMintInfo::launch. Load aMintInfoas below. Refresh it on a timer, like any account: load it and fill it again. For WSOL and USDC, you can also useconstants::WSOL_MINT_INFOandconstants::USDC_MINT_INFO. - The trade and migrate builders refuse a base mint that is not a Token-2022 mint.
- A build can fail with
HookError::NotLoaded. See its doc. - The SDK refuses a hook list that it cannot resolve before the instruction runs. A transaction can still fail at the hook. Simulate it.
- Do not edit the
generatedmodules. They come from the program IDLs.
Read the mints and the Clock in one call, then fill each hook:
use ;
use MintInfo;
use CLOCK_SYSVAR_ID as CLOCK;
// One call, so the fee is the fee at the mint read.
let accounts = rpc.get_multiple_accounts?;
let = accounts.as_slice else ;
let clock = AccountView ;
let mut base_mint_info = load?;
let mut quote_mint_info = load?;
for info in
A builder quotes the fee at the epoch of the read. Read the mint again when the
epoch changes. transfer_fee holds the whole FeeSchedule: fee_at(epoch)
gives the fee at another epoch, and newer_epoch the epoch the fee changes.
MintInfo::load_at reads a mint at an epoch, with no Clock. hook_program and validation_address() give a hooked
mint's hook program and the account that holds its list.
A router that cannot simulate checks each trade direction with
transfer_hook::route::trade. It takes both MintInfos, and reads every other
account a list reads from the router's own cache. transfer_hook::route::screen
checks a direction for any trader, before the router knows the trader.
transfer_hook::route::MarketLoad loads and screens a market at each update. It
names the accounts to fetch and the accounts to declare for the next update.
Documentation
License
MIT, see the LICENSE file.