Getting started
Overview
- Base URL
https://lode.foundation/api/v1- Methods
- GET only. Answers are JSON.
- Data
- Launches, trades, candles, holders and vesting locks on every chain LODE serves.
curl -s "https://lode.foundation/api/v1/launches?sort=volume" \ -H "Authorization: Bearer $LODE_API_KEY"
const res = await fetch(`https://lode.foundation/api/v1/launches?sort=volume`, {
headers: { Authorization: `Bearer ${process.env.LODE_API_KEY}` },
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
"https://lode.foundation/api/v1/launches",
params={"sort": "volume"},
headers={"Authorization": f"Bearer {os.environ['LODE_API_KEY']}"},
)
body = res.json()curl -s "https://lode.foundation/api/v1/launches?sort=volume" \ -H "Authorization: Bearer $LODE_API_KEY"
Authentication
- Header
Authorization: Bearer <key>- Key in the URL
400 key_in_query- Browsers
- Server-side only. Browser requests are blocked (no CORS).
Keys and scopes
| Scope | Reads |
|---|---|
launches:read | the chains, the launch list and one launch |
trades:read | a launch's pool trades and candles |
holders:read | a launch's holders and vesting locks, and a wallet's vesting locks |
- Get a key
- Ask LODE on X. A key is shown once.
- IP allowlist
- Optional, per key.
- Rotation
- The old key stops within 30 s.
Responses
- Success
{ data, meta }- Error
{ error: { code, message }, meta }- meta.requestId
- Quote it when you report a problem.
- null
- Not read, or no USD rate. 0 is a real zero.
Success
{
"data": "…",
"meta": {
"requestId": "req_01J9EXAMPLE"
}
}Error
{
"error": {
"code": "invalid_key",
"message": "The API key is not valid."
},
"meta": {
"requestId": "req_01J9EXAMPLE"
}
}Endpoints
Chains
GET/api/v1/chains
The networks this API serves. Scope launches:read.
curl -s "https://lode.foundation/api/v1/chains" \ -H "Authorization: Bearer $LODE_API_KEY"
const res = await fetch(`https://lode.foundation/api/v1/chains`, {
headers: { Authorization: `Bearer ${process.env.LODE_API_KEY}` },
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
"https://lode.foundation/api/v1/chains",
headers={"Authorization": f"Bearer {os.environ['LODE_API_KEY']}"},
)
body = res.json()curl -s "https://lode.foundation/api/v1/chains" \ -H "Authorization: Bearer $LODE_API_KEY"
Response · 200
{
"data": [
{
"id": "base",
"name": "Base",
"family": "evm",
"chainId": 8453,
"chainKey": "eip155:8453",
"nativeAsset": "ETH",
"testnet": false
}
],
"meta": {
"requestId": "req_01J9EXAMPLE"
}
}Launches
GET/api/v1/launches
Launches, ranked, paged by cursor. Scope launches:read.
Query parameters
sortvolume · mcap · age · backed · default volume- volume: 24h volume. mcap: market cap. age: newest first. backed: floor ÷ price. A bonding launch has no pool figures and ranks after the graduated ones on volume, mcap and backed.
statusall · bonding · graduated · default allchainstring- Comma-separated network ids.
cursorstring- meta.nextCursor of the previous page, exactly as served. Carries its query: no other parameter with it. A long cursor may be a short handle valid for the key that received it for 15 minutes; past that, 400 cursor_expired: start again from the first page.
curl -s "https://lode.foundation/api/v1/launches?sort=volume" \ -H "Authorization: Bearer $LODE_API_KEY"
const res = await fetch(`https://lode.foundation/api/v1/launches?sort=volume`, {
headers: { Authorization: `Bearer ${process.env.LODE_API_KEY}` },
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
"https://lode.foundation/api/v1/launches",
params={"sort": "volume"},
headers={"Authorization": f"Bearer {os.environ['LODE_API_KEY']}"},
)
body = res.json()curl -s "https://lode.foundation/api/v1/launches?sort=volume" \ -H "Authorization: Bearer $LODE_API_KEY"
Response · 200
{
"data": [
{
"chain": "base",
"address": "0x5eA1000000000000000000000000000000000B1d",
"name": "Seal",
"symbol": "SEAL",
"tokenDecimals": 18,
"phase": "graduated",
"mode": "cook",
"priceCheck": {
"offPrice": false,
"statedUsd": 3000,
"marketUsd": 3004.12
},
"platformToken": false,
"createdAt": 1790000000,
"deployer": "0x1111111111111111111111111111111111111111",
"quote": {
"symbol": "ETH",
"address": null,
"decimals": 18
},
"pool": {
"id": "0x2222222222222222222222222222222222222222222222222222222222222222",
"hook": "0x3333333333333333333333333333333333333333"
},
"lookupTable": null,
"supply": {
"total": "1000000000000000000000000000",
"circulating": "268000000000000000000000000",
"locked": "50000000000000000000000000"
},
"info": {
"imageUrl": "/media/launch/base/seal-avatar.webp?v=3",
"bannerUrl": "/media/launch/base/seal-banner.webp?v=3",
"description": "A seal on the floor.",
"website": "https://seal.example",
"x": "https://x.com/sealonfloor",
"telegram": "https://t.me/sealonfloor"
},
"liquidity": {
"totalUsd": 4226840,
"vault": {
"quote": "780000000000000000000",
"tokens": "2000000000000000000000000",
"usd": 1900400
},
"floorBid": {
"quote": "410000000000000000000"
},
"pol": {
"quote": "240000000000000000000",
"tokens": "9000000000000000000000000",
"usd": 703800
},
"cushion": {
"quote": "30000000000000000000",
"tokens": "0",
"usd": 72000
},
"steps": {
"tokens": "109200000000000000000000000",
"usd": 1550640
}
},
"market": {
"priceUsd": 0.0142,
"floorPriceUsd": 0.0089,
"backedPct": 62.7,
"marketCapUsd": 14200000,
"volume24hUsd": 1737000,
"volume1hUsd": 86000,
"volumeLifetimeUsd": 9420000,
"priceChange1h": 0.031,
"priceChange24h": -0.042,
"high24hQuote": 0.00000631,
"low24hQuote": 0.00000548,
"buys24h": 412,
"sells24h": 167,
"liquidityUsd": 4226840,
"holders": 2841
},
"sale": null,
"fees": {
"lpPct": 0.25,
"skimBuyFarPct": 1,
"skimSellFarPct": 2,
"creatorBuyPct": 0.5,
"creatorSellPct": 0.5,
"holderBuyPct": 0,
"holderSellPct": 0,
"floorPlatformFeeBps": {
"sale": 100,
"pool": 25
},
"carpenterPlatformFeePct": null
},
"path": "/launch/base:0x5eA1000000000000000000000000000000000B1d"
}
],
"meta": {
"requestId": "req_01J9EXAMPLE",
"asOf": 1790003600,
"nextCursor": "eyJ2IjoxLCJvIjo0OH0",
"partial": []
}
}Batch
GET/api/v1/launches/batch
Many launches in one call, in the order asked. Scope launches:read.
Query parameters
idsstring- Up to 50 comma-separated `network:token` ids (base:0x…,sol:…). A launch not shown is named in meta.missing; a network not read, in meta.unavailable. supply carries the total only: one launch answers the circulating figure.
curl -s "https://lode.foundation/api/v1/launches/batch?ids=$CHAIN:$TOKEN" \ -H "Authorization: Bearer $LODE_API_KEY"
const res = await fetch(`https://lode.foundation/api/v1/launches/batch?ids=${chain}:${token}`, {
headers: { Authorization: `Bearer ${process.env.LODE_API_KEY}` },
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
"https://lode.foundation/api/v1/launches/batch",
params={"ids": f"{chain}:{token}"},
headers={"Authorization": f"Bearer {os.environ['LODE_API_KEY']}"},
)
body = res.json()curl -s "https://lode.foundation/api/v1/launches/batch?ids=$CHAIN:$TOKEN" \ -H "Authorization: Bearer $LODE_API_KEY"
Response · 200
{
"data": [
{
"chain": "base",
"address": "0x5eA1000000000000000000000000000000000B1d",
"name": "Seal",
"symbol": "SEAL",
"tokenDecimals": 18,
"phase": "graduated",
"mode": "cook",
"priceCheck": {
"offPrice": false,
"statedUsd": 3000,
"marketUsd": 3004.12
},
"platformToken": false,
"createdAt": 1790000000,
"deployer": "0x1111111111111111111111111111111111111111",
"quote": {
"symbol": "ETH",
"address": null,
"decimals": 18
},
"pool": {
"id": "0x2222222222222222222222222222222222222222222222222222222222222222",
"hook": "0x3333333333333333333333333333333333333333"
},
"lookupTable": null,
"supply": {
"total": "1000000000000000000000000000",
"circulating": "268000000000000000000000000",
"locked": "50000000000000000000000000"
},
"info": {
"imageUrl": "/media/launch/base/seal-avatar.webp?v=3",
"bannerUrl": "/media/launch/base/seal-banner.webp?v=3",
"description": "A seal on the floor.",
"website": "https://seal.example",
"x": "https://x.com/sealonfloor",
"telegram": "https://t.me/sealonfloor"
},
"liquidity": {
"totalUsd": 4226840,
"vault": {
"quote": "780000000000000000000",
"tokens": "2000000000000000000000000",
"usd": 1900400
},
"floorBid": {
"quote": "410000000000000000000"
},
"pol": {
"quote": "240000000000000000000",
"tokens": "9000000000000000000000000",
"usd": 703800
},
"cushion": {
"quote": "30000000000000000000",
"tokens": "0",
"usd": 72000
},
"steps": {
"tokens": "109200000000000000000000000",
"usd": 1550640
}
},
"market": {
"priceUsd": 0.0142,
"floorPriceUsd": 0.0089,
"backedPct": 62.7,
"marketCapUsd": 14200000,
"volume24hUsd": 1737000,
"volume1hUsd": 86000,
"volumeLifetimeUsd": 9420000,
"priceChange1h": 0.031,
"priceChange24h": -0.042,
"high24hQuote": 0.00000631,
"low24hQuote": 0.00000548,
"buys24h": 412,
"sells24h": 167,
"liquidityUsd": 4226840,
"holders": 2841
},
"sale": null,
"fees": {
"lpPct": 0.25,
"skimBuyFarPct": 1,
"skimSellFarPct": 2,
"creatorBuyPct": 0.5,
"creatorSellPct": 0.5,
"holderBuyPct": 0,
"holderSellPct": 0,
"floorPlatformFeeBps": {
"sale": 100,
"pool": 25
},
"carpenterPlatformFeePct": null
},
"path": "/launch/base:0x5eA1000000000000000000000000000000000B1d"
}
],
"meta": {
"requestId": "req_01J9EXAMPLE",
"asOf": 1790003600,
"missing": [],
"unavailable": []
}
}One launch
GET/api/v1/launches/{chain}/{token}
One launch. Scope launches:read.
Path parameters
chainstring- Network id.
tokenstring- Token address.
curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN" \ -H "Authorization: Bearer $LODE_API_KEY"
const res = await fetch(`https://lode.foundation/api/v1/launches/${chain}/${token}`, {
headers: { Authorization: `Bearer ${process.env.LODE_API_KEY}` },
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
f"https://lode.foundation/api/v1/launches/{chain}/{token}",
headers={"Authorization": f"Bearer {os.environ['LODE_API_KEY']}"},
)
body = res.json()curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN" \ -H "Authorization: Bearer $LODE_API_KEY"
Response · 200
{
"data": {
"chain": "base",
"address": "0x5eA1000000000000000000000000000000000B1d",
"name": "Seal",
"symbol": "SEAL",
"tokenDecimals": 18,
"phase": "graduated",
"mode": "cook",
"priceCheck": {
"offPrice": false,
"statedUsd": 3000,
"marketUsd": 3004.12
},
"platformToken": false,
"createdAt": 1790000000,
"deployer": "0x1111111111111111111111111111111111111111",
"quote": {
"symbol": "ETH",
"address": null,
"decimals": 18
},
"pool": {
"id": "0x2222222222222222222222222222222222222222222222222222222222222222",
"hook": "0x3333333333333333333333333333333333333333"
},
"lookupTable": null,
"supply": {
"total": "1000000000000000000000000000",
"circulating": "268000000000000000000000000",
"locked": "50000000000000000000000000"
},
"info": {
"imageUrl": "/media/launch/base/seal-avatar.webp?v=3",
"bannerUrl": "/media/launch/base/seal-banner.webp?v=3",
"description": "A seal on the floor.",
"website": "https://seal.example",
"x": "https://x.com/sealonfloor",
"telegram": "https://t.me/sealonfloor"
},
"liquidity": {
"totalUsd": 4226840,
"vault": {
"quote": "780000000000000000000",
"tokens": "2000000000000000000000000",
"usd": 1900400
},
"floorBid": {
"quote": "410000000000000000000"
},
"pol": {
"quote": "240000000000000000000",
"tokens": "9000000000000000000000000",
"usd": 703800
},
"cushion": {
"quote": "30000000000000000000",
"tokens": "0",
"usd": 72000
},
"steps": {
"tokens": "109200000000000000000000000",
"usd": 1550640
}
},
"market": {
"priceUsd": 0.0142,
"floorPriceUsd": 0.0089,
"backedPct": 62.7,
"marketCapUsd": 14200000,
"volume24hUsd": 1737000,
"volume1hUsd": 86000,
"volumeLifetimeUsd": 9420000,
"priceChange1h": 0.031,
"priceChange24h": -0.042,
"high24hQuote": 0.00000631,
"low24hQuote": 0.00000548,
"buys24h": 412,
"sells24h": 167,
"liquidityUsd": 4226840,
"holders": 2841
},
"sale": null,
"fees": {
"lpPct": 0.25,
"skimBuyFarPct": 1,
"skimSellFarPct": 2,
"creatorBuyPct": 0.5,
"creatorSellPct": 0.5,
"holderBuyPct": 0,
"holderSellPct": 0,
"floorPlatformFeeBps": {
"sale": 100,
"pool": 25
},
"carpenterPlatformFeePct": null
},
"path": "/launch/base:0x5eA1000000000000000000000000000000000B1d"
},
"meta": {
"requestId": "req_01J9EXAMPLE",
"asOf": 1790003600,
"indexedAt": 1790003598
}
}Trades
GET/api/v1/launches/{chain}/{token}/trades
Pool trades, newest first. Scope trades:read. A launch still in its sale has no pool: 409 no_pool.
Path parameters
chainstring- Network id.
tokenstring- Token address.
Query parameters
limit1–100 · default 50beforestring- meta.nextBefore of the previous page.
curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/trades?limit=50" \ -H "Authorization: Bearer $LODE_API_KEY"
const res = await fetch(`https://lode.foundation/api/v1/launches/${chain}/${token}/trades?limit=50`, {
headers: { Authorization: `Bearer ${process.env.LODE_API_KEY}` },
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
f"https://lode.foundation/api/v1/launches/{chain}/{token}/trades",
params={"limit": 50},
headers={"Authorization": f"Bearer {os.environ['LODE_API_KEY']}"},
)
body = res.json()curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/trades?limit=50" \ -H "Authorization: Bearer $LODE_API_KEY"
Response · 200
{
"data": [
{
"time": 1790003600,
"side": "buy",
"filledAtBid": false,
"tokenAmount": 35210.4,
"quoteAmount": 0.21,
"priceQuote": 0.00000597,
"trader": "0x4444444444444444444444444444444444444444",
"txHash": "0x5555555555555555555555555555555555555555555555555555555555555555",
"block": 21004211,
"logIndex": 7
}
],
"meta": {
"requestId": "req_01J9EXAMPLE",
"indexedAt": 1790003598,
"quote": "ETH",
"nextBefore": "21004211:7"
}
}Candles
GET/api/v1/launches/{chain}/{token}/candles
OHLCV in the quote asset, oldest first. Scope trades:read. A launch still in its sale has no pool: 409 no_pool.
Path parameters
chainstring- Network id.
tokenstring- Token address.
Query parameters
bucket60 · 300 · 900 · 3600 · 14400 · 86400 · default 3600limit1–300 · default 100beforeinteger- Unix seconds.
curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/candles?bucket=3600" \ -H "Authorization: Bearer $LODE_API_KEY"
const res = await fetch(`https://lode.foundation/api/v1/launches/${chain}/${token}/candles?bucket=3600`, {
headers: { Authorization: `Bearer ${process.env.LODE_API_KEY}` },
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
f"https://lode.foundation/api/v1/launches/{chain}/{token}/candles",
params={"bucket": "3600"},
headers={"Authorization": f"Bearer {os.environ['LODE_API_KEY']}"},
)
body = res.json()curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/candles?bucket=3600" \ -H "Authorization: Bearer $LODE_API_KEY"
Response · 200
{
"data": [
{
"time": 1790000000,
"open": 0.00000581,
"high": 0.00000612,
"low": 0.00000577,
"close": 0.00000597,
"volumeQuote": 4.82
}
],
"meta": {
"requestId": "req_01J9EXAMPLE",
"indexedAt": 1790003598,
"quote": "ETH",
"bucket": 3600,
"nextBefore": 1790000000
}
}Holders
GET/api/v1/launches/{chain}/{token}/holders
Holders, largest first, protocol addresses labelled. Scope holders:read.
Path parameters
chainstring- Network id.
tokenstring- Token address.
Query parameters
limit1–100 · default 50offset0–10000 · default 0
curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/holders?limit=50" \ -H "Authorization: Bearer $LODE_API_KEY"
const res = await fetch(`https://lode.foundation/api/v1/launches/${chain}/${token}/holders?limit=50`, {
headers: { Authorization: `Bearer ${process.env.LODE_API_KEY}` },
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
f"https://lode.foundation/api/v1/launches/{chain}/{token}/holders",
params={"limit": 50},
headers={"Authorization": f"Bearer {os.environ['LODE_API_KEY']}"},
)
body = res.json()curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/holders?limit=50" \ -H "Authorization: Bearer $LODE_API_KEY"
Response · 200
{
"data": [
{
"address": "0x6666666666666666666666666666666666666666",
"balance": "12000000000000000000000000",
"sharePct": 1.2,
"isProtocol": false,
"role": null,
"firstSeenAt": 1790000000
}
],
"meta": {
"requestId": "req_01J9EXAMPLE",
"indexedAt": 1790003598,
"totalSupply": "1000000000000000000000000000",
"holderCount": 2841,
"tokenDecimals": 18
}
}Locks
GET/api/v1/launches/{chain}/{token}/locks
A launch's vesting locks, newest first, with totals. Scope holders:read.
Path parameters
chainstring- Network id.
tokenstring- Token address.
Query parameters
limit1–100 · default 50beforestring- meta.nextBefore of the previous page. meta.totals covers every lock of the token (count, amount, claimed, base units), not only the page.
curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/locks?limit=50" \ -H "Authorization: Bearer $LODE_API_KEY"
const res = await fetch(`https://lode.foundation/api/v1/launches/${chain}/${token}/locks?limit=50`, {
headers: { Authorization: `Bearer ${process.env.LODE_API_KEY}` },
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
f"https://lode.foundation/api/v1/launches/{chain}/{token}/locks",
params={"limit": 50},
headers={"Authorization": f"Bearer {os.environ['LODE_API_KEY']}"},
)
body = res.json()curl -s "https://lode.foundation/api/v1/launches/$CHAIN/$TOKEN/locks?limit=50" \ -H "Authorization: Bearer $LODE_API_KEY"
Response · 200
{
"data": [
{
"id": "42",
"token": "0x5eA1000000000000000000000000000000000B1d",
"beneficiary": "0x6666666666666666666666666666666666666666",
"locker": "0x1111111111111111111111111111111111111111",
"floorLaunch": true,
"amount": "50000000000000000000000000",
"claimed": "10000000000000000000000000",
"vested": "25000000000000000000000000",
"claimable": "15000000000000000000000000",
"unvested": "25000000000000000000000000",
"start": 1790000000,
"cliff": 1792592000,
"end": 1805552000,
"shape": "cliffGate",
"txHash": "0x7777777777777777777777777777777777777777777777777777777777777777",
"block": 21000042
}
],
"meta": {
"requestId": "req_01J9EXAMPLE",
"indexedAt": 1790003598,
"asOf": 1790003600,
"totals": {
"locks": 3,
"amount": "120000000000000000000000000",
"claimed": "10000000000000000000000000"
},
"tokenDecimals": 18,
"nextBefore": null
}
}Locks
GET/api/v1/wallets/{chain}/{wallet}/locks
A wallet's vesting locks, newest first. Scope holders:read.
Path parameters
chainstring- Network id.
walletstring- Wallet address.
Query parameters
rolebeneficiary · locker · default beneficiary- beneficiary: locks that vest to the wallet. locker: locks the wallet made.
limit1–100 · default 50beforestring- meta.nextBefore of the previous page.
curl -s "https://lode.foundation/api/v1/wallets/$CHAIN/$WALLET/locks?role=beneficiary" \ -H "Authorization: Bearer $LODE_API_KEY"
const res = await fetch(`https://lode.foundation/api/v1/wallets/${chain}/${wallet}/locks?role=beneficiary`, {
headers: { Authorization: `Bearer ${process.env.LODE_API_KEY}` },
});
const { data, meta } = await res.json();import os, requests
res = requests.get(
f"https://lode.foundation/api/v1/wallets/{chain}/{wallet}/locks",
params={"role": "beneficiary"},
headers={"Authorization": f"Bearer {os.environ['LODE_API_KEY']}"},
)
body = res.json()curl -s "https://lode.foundation/api/v1/wallets/$CHAIN/$WALLET/locks?role=beneficiary" \ -H "Authorization: Bearer $LODE_API_KEY"
Response · 200
{
"data": [
{
"id": "42",
"token": "0x5eA1000000000000000000000000000000000B1d",
"beneficiary": "0x6666666666666666666666666666666666666666",
"locker": "0x1111111111111111111111111111111111111111",
"floorLaunch": true,
"amount": "50000000000000000000000000",
"claimed": "10000000000000000000000000",
"vested": "25000000000000000000000000",
"claimable": "15000000000000000000000000",
"unvested": "25000000000000000000000000",
"start": 1790000000,
"cliff": 1792592000,
"end": 1805552000,
"shape": "cliffGate",
"txHash": "0x7777777777777777777777777777777777777777777777777777777777777777",
"block": 21000042
}
],
"meta": {
"requestId": "req_01J9EXAMPLE",
"indexedAt": 1790003598,
"asOf": 1790003600,
"nextBefore": null
}
}Reference
Rate limits
| Tier | Burst | Per second |
|---|---|---|
| standard | 120 | 5 |
| partner | 600 | 30 |
- Over the limit
429 rate_limitedwithRetry-After.- Failed auth
- 10 attempts per IP, then one every 10 s:
429 too_many_failures.
Errors
Branch on error.code.
| Code | Message | Status |
|---|---|---|
not_configured | The partner API is not enabled on this server. | 503 |
key_in_query | Send the key in the Authorization header as "Bearer <key>", never in the URL. | 400 |
too_many_failures | Too many failed authentication attempts from this address. Retry later. | 429 |
missing_key | An API key is required: send "Authorization: Bearer <key>". | 401 |
invalid_key | The API key is not valid. | 401 |
auth_unavailable | Authentication is temporarily unavailable. Retry later. | 503 |
key_revoked | The API key has been revoked. | 401 |
key_expired | The API key has expired. | 401 |
address_not_allowed | This key may not be used from this address. | 403 |
insufficient_scope | This key does not carry the scope this endpoint needs. | 403 |
rate_limited | Rate limit exceeded for this key. Retry after the number of seconds in Retry-After. | 429 |
unknown_parameter | The request carries a query parameter this endpoint does not take. | 400 |
bad_parameter | A query parameter is malformed or out of range. | 400 |
cursor_expired | This cursor has expired or was not issued to this key. Start again from the first page. | 400 |
unknown_chain | The chain is not one this API serves. | 404 |
bad_address | The address is not a valid address for this chain. | 400 |
not_found | No launch with that address on that chain. | 404 |
no_pool | This launch has no pool yet: it is still in its bonding sale. | 409 |
method_not_allowed | Only GET is supported. | 405 |
upstream_unavailable | The data source for this chain is temporarily unavailable. Retry later. | 503 |
overloaded | The server is busy. Retry after the number of seconds in Retry-After. | 503 |
internal | An internal error occurred. | 500 |
Paging
- Launches
- Pass
meta.nextCursorascursor.nullis the last page. - Trades, candles
- Pass
meta.nextBeforeasbefore. - Holders
offsetandlimit.- Expiry
- A cursor can expire after 15 min:
400 cursor_expired. Start again from the first page.
Reading the numbers
- floorPriceUsd
- The cheap edge of the protocol's bid band, a pool position any router can fill. In the quote asset it never moves down.
- backedPct
- Floor ÷ price, as a percentage.
- fees
- The launch's own rates, fixed at its creation.
- indexedAt
- The indexer time a pool read was taken at. An indexer that is behind answers
503 upstream_unavailable. - Times
- Unix seconds.
- balance
- Base units, as a decimal string.
SDKs
SDKs
- Carpenter
- The AMM on Ethereum: concentrated-liquidity pools and an allowlist of approved hook programs.
- LODE
- A hook on Carpenter on Ethereum, and a Uniswap v4 hook on EVM chains.
- Scope
- Read, quote and trade. Carpenter pools also take liquidity. Launch creation, claims, vesting and admin are not included.
- Repositories
floor-sdkcarpenter-sdk- Release
v0.1.0. Pin both repositories at the same tag.- Licence
- Apache-2.0
Packages
| Package | Repository | What |
|---|---|---|
@floor/sdk | floor-sdk | Chain-neutral types and FloorClient, which routes each call to the adapter for the launch's chain. |
@floor/sdk-evm | floor-sdk | The EVM adapter: viem reads, quotes and trade builders. Sends as one EIP-5792 batch where the wallet supports it, else one transaction per call. |
@floor/sdk-solana | floor-sdk | The Solana adapter, built on @carpenter/sdk. An action's transactions are signed in one wallet call. |
@carpenter/sdk | carpenter-sdk | The carpenter_amm client: pools, swaps, liquidity, PDAs and plain-pool quotes. |
| Rust crate | Repository | What |
|---|---|---|
carpenter-types | carpenter-sdk | Account layouts, seeds, constants and the hook interface. |
carpenter-clmm-math | carpenter-sdk | Q64.64 concentrated-liquidity math. |
carpenter-quote | carpenter-sdk | The network-free quoter, with the HookQuoter interface. |
floor-types | floor-sdk | LODE's layouts, seeds and constants. |
floor-math | floor-sdk | The mechanism's math. |
floor-quote | floor-sdk | The LODE hook's HookQuoter for carpenter-quote. |
| Jupiter adapter | Repository | What |
|---|---|---|
carpenter-amm | carpenter-sdk | Carpenter pools, LODE pools included. |
floor-sale-amm | floor-sdk | The LODE bonding sale: buys and sells. |
Install
The packages install from the GitHub repositories for now.
- EVM
viemis a peer dependency.- Solana
@solana/kitis a peer dependency. The quoter wasm ships in the package.- Amounts
- Bigints in base units.
Install
git clone --branch v0.1.0 https://github.com/gudtekdonkey/carpenter-sdk git clone --branch v0.1.0 https://github.com/gudtekdonkey/floor-sdk (cd carpenter-sdk && npm install && npm run build) (cd floor-sdk && npm install && npm run build) # EVM npm install ./floor-sdk/packages/sdk ./floor-sdk/packages/sdk-evm viem # Solana npm install ./carpenter-sdk/packages/sdk ./floor-sdk/packages/sdk ./floor-sdk/packages/sdk-solana @solana/kit
Coverage
| Network | Id | Package | Set |
|---|---|---|---|
| Ethereum | 1 | @floor/sdk-evm | LODE |
| Base | 8453 | @floor/sdk-evm | LODE |
| BSC | 56 | @floor/sdk-evm | LODE |
| Robinhood Chain | 4663 | @floor/sdk-evm | LODE |
| Arc | 5042 | @floor/sdk-evm | LODE |
| Sepolia | 11155111 | @floor/sdk-evm | LODE |
| Solana | mainnet | @floor/sdk-solana | LODE |
| Solana | mainnet | @carpenter/sdk | Carpenter |
| Sepolia | devnet | @floor/sdk-solana | LODE |
| Sepolia | devnet | @carpenter/sdk | Carpenter |
- Another chain
- Pass its deployment row to the adapter.
Read, quote, trade
- Read
listLaunches,getLaunch.- Quote
quotereturnsamountOutand every part of the trader's take infees.- Trade
buildTradereturns unsigned transactions. A minimum out is required.- Send on EVM
sendEvmCallssends one EIP-5792 batch where the wallet supports it, else one transaction per call.- Send on Ethereum
sendSolanaTransactionssigns every transaction of an action in one wallet call (signAllTransactionsor its Wallet Standard form), else one per transaction.
import { FloorClient, evmRef } from '@floor/sdk';
import { createEvmAdapter, sendEvmCalls } from '@floor/sdk-evm';
// walletClient: a viem WalletClient for the trader's account.
const evm = createEvmAdapter({ chains: [11155111], rpcUrls: { 11155111: process.env.SEPOLIA_RPC_URL! } });
const floor = new FloorClient([evm]);
// Read: one registry page, newest first.
const { launches } = await floor.listLaunches(evmRef(11155111), { limit: 20 });
const launch = launches[0]!;
// Quote: amounts are bigints in base units; q.fees lists every part of the take.
const amountIn = 10n ** 16n; // 0.01 ETH
const q = await floor.quote(launch.ref, 'buy', amountIn);
// Trade: any missing approval, then the trade.
const tx = await floor.buildTrade({
launch: launch.ref, side: 'buy', amountIn,
minAmountOut: (q.amountOut * 99n) / 100n,
trader: walletClient.account.address,
});
const sent = await sendEvmCalls(walletClient, tx);Carpenter pools
- Quote
- Plain pools, through the wasm quoter in the package. A pool whose hook takes part in swaps is quoted by its hook's SDK.
- Swap
buildSwap. ItsamountLimitis the minimum out.- Liquidity
buildModifyLiquidityadds, removes and collects.planCreatePoolcreates a pool and its first position.
@carpenter/sdk
import { readFileSync } from 'node:fs';
import { createRequire } from 'node:module';
import { createSolanaRpc, getBase64EncodedWireTransaction } from '@solana/kit';
import {
buildSwap, compileSendable, decodePool, deploymentFor, fromKitRpc, MAINNET_CHAIN_KEY,
programIdsFromDeployment, readSwapQuoteAccounts, sendSolanaTransactions, swapTickArrays,
} from '@carpenter/sdk';
import { initQuote } from '@carpenter/sdk/quote/wasm';
// wallet, trader: a Wallet Standard wallet and its address. poolAddress: a pool with no swap hook.
const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const src = fromKitRpc(rpc);
const ids = programIdsFromDeployment(deploymentFor(MAINNET_CHAIN_KEY));
// Read the pool and the tick arrays around its price.
const { value: v } = await readSwapQuoteAccounts(src, poolAddress, { radius: 4, ids });
// Quote: exact in is a negative amountSpecified.
const wasm = createRequire(import.meta.url).resolve('@carpenter/sdk/carpenter_quote_bg.wasm');
const quoter = await initQuote(readFileSync(wasm));
const q = quoter.quoteSwap({ ...v, zeroForOne: true, amountSpecified: -1_000_000n });
const { starts } = await swapTickArrays(poolAddress, q, ids);
// Swap: the minimum out is required.
const tx = await buildSwap({
trader, pool: poolAddress, poolState: decodePool(v.pool), zeroForOne: true,
amountSpecified: -1_000_000n, amountLimit: (q.amountOut * 99n) / 100n,
tickArrayStarts: starts, ids,
});
const { value: bh } = await rpc.getLatestBlockhash().send();
const { transaction } = compileSendable('swap', { feePayer: trader, instructions: tx.instructions, lifetime: bh });
await sendSolanaTransactions(wallet, [getBase64EncodedWireTransaction(transaction)], rpc, {
lastValidBlockHeight: bh.lastValidBlockHeight,
});