Getting started
Install
| Package | What | Peer dependency |
|---|---|---|
@lodefoundation/sdk | The client and the chain-neutral types, every chain | — |
@lodefoundation/sdk-solana | The Solana adapter (installs @lodefoundation/carpenter-sdk) | @solana/kit ^8.3.0 |
@lodefoundation/sdk-evm | The EVM adapter | viem ^2.56.3 |
- Release
0.1.1- Rust
- Git dependencies at the release tag. Not on crates.io.
- Quoter wasm
- Shipped in @lodefoundation/sdk-solana. An install needs no Rust toolchain.
- Licence
- Apache-2.0
# both chains npm install @lodefoundation/sdk @lodefoundation/sdk-solana @lodefoundation/sdk-evm @solana/kit viem # Solana only: npm install @lodefoundation/sdk @lodefoundation/sdk-solana @solana/kit # EVM only: npm install @lodefoundation/sdk @lodefoundation/sdk-evm viem
# Cargo.toml
[dependencies]
floor-quote = { git = "https://github.com/gudtekdonkey/floor-sdk", tag = "0.1.1" }
floor-types = { git = "https://github.com/gudtekdonkey/floor-sdk", tag = "0.1.1" }# both chains npm install @lodefoundation/sdk @lodefoundation/sdk-solana @lodefoundation/sdk-evm @solana/kit viem # Solana only: npm install @lodefoundation/sdk @lodefoundation/sdk-solana @solana/kit # EVM only: npm install @lodefoundation/sdk @lodefoundation/sdk-evm viem
FloorClient
FloorClient takes one adapter per chain family and sends each call to the adapter for the launch’s chain.
- Solana
createSolanaAdapter:clusters,quoter,launchTable,traderLink(optional, a referral link).- EVM
createEvmAdapter:chains,rpcUrls.- Amounts
- Bigints in base units.
- Addresses
- Kept verbatim. A Solana address is case-sensitive.
TypeScript
import { FloorClient } from '@lodefoundation/sdk';
import { createSolanaAdapter } from '@lodefoundation/sdk-solana';
import { initQuote } from '@lodefoundation/sdk-solana/quote/wasm';
import { createEvmAdapter } from '@lodefoundation/sdk-evm';
import { createSolanaRpc } from '@solana/kit';
const rpc = createSolanaRpc(process.env.SOLANA_RPC_URL);
// floor_quote_bg.wasm, shipped in the package, served as a file
const quoter = await initQuote(wasmBytes);
const solana = createSolanaAdapter({
clusters: { mainnet: { rpc } },
quoter,
launchTable: async (ref) => lookupTableOf(ref), // a sale's lookup table
});
const evm = createEvmAdapter({
chains: [8453],
rpcUrls: { 8453: process.env.BASE_RPC_URL },
});
// one client: each call goes to the adapter for the launch's chain
const floor = new FloorClient([solana, evm]);Chains
| Chain | Reference | Adapter |
|---|---|---|
| Solana mainnet-beta | solanaRef('mainnet') | @lodefoundation/sdk-solana |
| Sepolia | solanaRef('devnet') | @lodefoundation/sdk-solana |
| Ethereum | evmRef(1) | @lodefoundation/sdk-evm |
| Base | evmRef(8453) | @lodefoundation/sdk-evm |
| BSC | evmRef(56) | @lodefoundation/sdk-evm |
| Robinhood Chain | evmRef(4663) | @lodefoundation/sdk-evm |
| Arc | evmRef(5042) | @lodefoundation/sdk-evm |
| Sepolia | evmRef(11155111) | @lodefoundation/sdk-evm |
The EVM chains share one set of LODE addresses; Sepolia is the test set. Rows that carry only Uniswap v4’s contracts are refused by name.
Trading
List launches
listLaunches(chain, { limit }) answers one registry page, newest first, and a cursor for the next.
- Unfiltered
- Anyone can create a launch with any name and symbol. Identify a launch by its address.
- Solana pages
- Paged by registry index; a page can hold fewer than
limitwhilecursoris not null. - Phase
pending,bonding,graduated
TypeScript
import { solanaRef } from '@lodefoundation/sdk';
// one registry page, newest first
const { launches, cursor } = await floor.listLaunches(
solanaRef('mainnet'), { limit: 20 },
);
// listings are unfiltered: match a launch by its address
const launch = launches.find((l) => l.ref.token === MINT);
if (!launch) throw new Error('not on this page: follow the cursor');Quote
quote(ref, side, amountIn) answers the output and the trader’s whole take, or throws.
| Field | What |
|---|---|
amountIn | bigint |
amountOut | bigint |
fees | Every part of the take |
feesExact | boolean |
refund | Optional |
graduates | A buy that sells the sale out graduates the launch inside it |
maxExtraNative | The most native currency such a buy can take on top of amountIn |
- Take on EVM
- LP fee, floor skim, creator fee, holder fee, LODE Platform fee.
- Take on Ethereum
- LP fee, floor skim, creator fee, holder fee, LODE Platform fee, Carpenter Platform fee.
- Sell-back
- Before graduation a sell-back pays the launch’s fixed sale price, less the LODE Platform fee, the same for any seller.
// lamports in, base units out const q = await floor.quote(launch.ref, 'buy', 1_000_000_000n); q.amountOut; // bigint q.fees; // the trader's whole take q.graduates; // a buy that sells the sale out q.maxExtraNative;
use floor_quote::state::{decode_cushion_top, decode_floor_pool, decode_pool, TickArraySet};
use floor_quote::{no_limit, quote_swap, PoolAccount, SwapQuoteParams};
let pool = decode_pool(&pool_bytes)?;
let floor_pool = decode_floor_pool(&floor_pool_bytes)?;
let set = TickArraySet::from_accounts(&pool_key, pool.tick_spacing, &tick_arrays, Some(&bitmap))?;
let q = quote_swap(&PoolAccount { key: pool_key, pool }, &set, Some(&floor_pool), &SwapQuoteParams {
zero_for_one: true, // a buy: the quote (token0) in
amount_specified: -1_000_000_000, // exact-in
sqrt_price_limit_x64: no_limit(true),
supply0, supply1,
cushion_top: decode_cushion_top(&floor_pool_bytes),
})?;
// q.amount_in, q.amount_out, q.fees// lamports in, base units out const q = await floor.quote(launch.ref, 'buy', 1_000_000_000n); q.amountOut; // bigint q.fees; // the trader's whole take q.graduates; // a buy that sells the sale out q.maxExtraNative;
Build a trade
buildTrade(params) never signs. It answers an UnsignedTx: everything one action needs, in order, for one wallet prompt.
| Family | Shape |
|---|---|
evm | { family, chainId, calls } |
solana | { family, cluster, transactions } |
TypeScript
const tx = await floor.buildTrade({
launch: launch.ref,
side: 'buy',
amountIn: 1_000_000_000n,
minAmountOut: (q.amountOut * 99n) / 100n,
trader,
});
tx.family; // 'evm' | 'solana'Send on EVM
| Wallet | Prompts |
|---|---|
| An atomic EIP-5792 batch on the chain | One: the approvals and the trade land together or not at all |
| No EIP-5792, or no atomic batch on the chain | One per call, in order; a reverted call stops the rest |
- Approvals
- Granted on chain, inside the same batch. No action asks for a Permit2 signature.
- Amount
exactfor a bonding buy,unlimitedfor a pool swap (approvalAmount).- Waits
batchTimeoutMs60 s,receiptTimeoutMs180 s,wait: falsereturns at the batch id.
TypeScript
import { sendEvmCalls } from '@lodefoundation/sdk-evm';
// { family: 'evm', chainId, calls }: the missing approvals, then the trade
const sent = await sendEvmCalls(walletClient, tx, {
onSubmitted: (id) => saveBatchId(id), // an EIP-5792 batch id
onSent: (hash) => saveHash(hash), // each transaction, one per call
});
// { path: 'eip5792', id, hashes } or { path: 'transactions', hashes }Send on Ethereum
| Action | Transactions | Prompts |
|---|---|---|
| Swap on a graduated pool | 1 | 1 |
| Sell-back during the sale | 1 | 1 |
| Sale buy | 1, or 2 while the launch is not prepared | 1 |
| First trade with a referral link | +1, the link first | 1 |
- Signing
- Every transaction of one action is signed together, then sent in order; the first failure stops the run.
- Blockhash
- Shared, valid for about 60–90 s.
opts.replanrebuilds what has not landed. - Sale trades
- Compiled through the launch’s own lookup table, which
launchTablesupplies.
TypeScript
import { sendSolanaTransactions } from '@lodefoundation/sdk-solana';
// { family: 'solana', cluster, transactions }: every transaction, in order
if (tx.family === 'solana') {
await sendSolanaTransactions(wallet, tx, rpc);
}Rust
Crates
| Crate | What |
|---|---|
floor-types | Account layouts, seeds, constants, discriminators and program ids, over carpenter-types |
floor-math | The skim ramp, fee booking, the bid band, the floor solve, the staircase, the sale, holder rewards, referrals |
floor-quote | FloorHookQuoter (the HookQuoter for floor_hook), quote_swap for LODE pools, the sale buy and sell-back |
floor-sale-amm | A jupiter-amm-interface Amm for LODE bonding sales (its own workspace, jupiter/) |
No crate depends on a Solana crate but floor-sale-amm. The Carpenter crates are pinned to the same release; both repositories must point at the same tag.
Rust
# Cargo.toml
[dependencies]
floor-quote = { git = "https://github.com/gudtekdonkey/floor-sdk", tag = "0.1.1" }
floor-types = { git = "https://github.com/gudtekdonkey/floor-sdk", tag = "0.1.1" }Jupiter adapter
| Case | Supported |
|---|---|
| Buys (wSOL in), exact-in | Yes |
| A buy that sells the sale out | No: SaleWouldGraduate |
| Sell-backs (wSOL out), exact-in | Yes, where the program carries sell_back_wsol |
| Sales quoted in another token | No: TokenQuoteNotRouted |
| Exact-out | No: ExactOutNotSupported |
Graduated pools are Carpenter pools: carpenter-amm, on the Carpenter SDK page.
Rust
# floor-sdk/jupiter: its own Cargo workspace cd jupiter && cargo test # label "LODE": buys (wSOL in) and sell-backs (wSOL out), exact-in # get_swap_and_account_metas returns Swap::Placeholder until Jupiter's # interface carries a LODE sale variant
Reference
Types
| Type | What |
|---|---|
ChainRef | A chain: solanaRef(cluster) or evmRef(chainId) |
LaunchRef | A launch: its chain and its token address |
Launch | Name, symbol, decimals, supply, the quote asset, the phase, the mode, the creator, floorPriceX18, raw |
Quote | amountIn, amountOut, fees, feesExact, refund, graduates, maxExtraNative |
UnsignedTx | Every call or transaction one action needs, in order |
- floorPriceX18
- The published floor in whole quote per whole token, × 1e18.
- raw
- The chain’s own decoded accounts.
Errors
| code | When |
|---|---|
no_cluster | No cluster is configured for the chain |
not_found | No launch, pool or position for the reference |
not_tradeable | The launch is not trading, or the take cannot be listed whole |
needs_trader | A sell-back before graduation needs opts.trader |
needs_launch_table | A sale trade needs the launch’s lookup table |
program_version | The cluster runs an earlier LODE program set |
| code | When |
|---|---|
wrong_chain | The wallet is on another chain. Nothing was sent. |
pending | Something was submitted and the wait ended. Do not send the action again. |
batch_failed | The wallet reports the EIP-5792 batch as failed |
reverted | A transaction reverted; the calls after it were not sent |
Program version
This release builds for the LODE program set whose hook callbacks take four accounts, whose sell-back is stateless and which has sell_back_wsol. The mainnet-beta and devnet programs it lists are that set.
- Check
createSolanaAdapterreads floor_hook’sApprovedHookrecord before building a trade.- Earlier set
SolanaAdapterError('program_version')
Carpenter SDK
LODE’s Solana pools are Carpenter pools. @lodefoundation/carpenter-sdk installs with @lodefoundation/sdk-solana; liquidity and pool creation are documented on the Carpenter SDK page.