Files
zeekay 4c917f849b Move every caller and route to /v1
Commerce is called at /v1, the indexer at /v1/indexer, and the operator
serves /v1/clusters. The console's unused fleet helpers called a /api
base nothing serves; they are gone. The legacy Quart env files named an
app that no longer exists.

Claude-Session: https://claude.ai/code/session_011i2AG9nwpiKUCVxAdDzYuU
2026-09-29 18:34:58 -07:00

439 lines
15 KiB
TypeScript

"use client"
import Link from "next/link"
import { Badge } from "@/components/ui/badge"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { DocsLayout } from "@/components/docs-layout"
import { ArrowRight } from "@luxfi/ui/icons"
import { docsConfig } from "@/lib/docs-config"
export default function SDKsPage() {
return (
<DocsLayout>
<div className="space-y-10">
{/* Header */}
<div>
<h1 className="text-4xl font-bold mb-4">SDKs & Libraries</h1>
<p className="text-lg text-muted-foreground">
Official client libraries for every major language. Each SDK provides
type-safe access to all {docsConfig.brandName} APIs with built-in retry logic,
authentication, and error handling.
</p>
</div>
{/* TypeScript */}
<section className="space-y-4">
<Card>
<CardHeader>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<CardTitle className="text-xl">TypeScript / JavaScript</CardTitle>
</div>
<Badge variant="secondary">v2.0.0</Badge>
</div>
<p className="text-sm text-muted-foreground mt-1">
Works with Node.js 18+, Bun, Deno, and all modern browsers (via bundler).
Full TypeScript types included.
</p>
</CardHeader>
<CardContent className="space-y-4">
<div>
<h4 className="text-sm font-semibold mb-2">Install</h4>
<pre className="overflow-x-auto rounded-lg bg-zinc-950 p-4 text-sm text-zinc-100">
<code>{`npm install @bootnode/sdk
# or
yarn add @bootnode/sdk
# or
pnpm add @bootnode/sdk`}</code>
</pre>
</div>
<div>
<h4 className="text-sm font-semibold mb-2">Usage</h4>
<pre className="overflow-x-auto rounded-lg bg-zinc-950 p-4 text-sm text-zinc-100">
<code>{`import { Bootnode } from "@bootnode/sdk";
const client = new Bootnode({
apiKey: process.env.BOOTNODE_API_KEY!,
});
// JSON-RPC
const blockNumber = await client.rpc("ethereum", "mainnet", {
jsonrpc: "2.0",
id: 1,
method: "eth_blockNumber",
params: [],
});
console.log("Block:", parseInt(blockNumber.result, 16));
// Token API
const balances = await client.tokens.getBalances("ethereum", "0xd8dA...6045");
console.log("Tokens:", balances.tokens);
// NFT API
const nft = await client.nfts.getMetadata(
"ethereum",
"0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
"1234"
);
console.log("NFT:", nft.name);
// Wallets
const wallet = await client.wallets.create({
owner: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
chain: "base",
});
console.log("Smart wallet:", wallet.address);
// Webhooks
const webhook = await client.webhooks.create({
url: "https://myapp.com/webhooks",
chain: "ethereum",
eventType: "address_activity",
config: { addresses: ["0xd8dA...6045"] },
});
console.log("Webhook ID:", webhook.id);
// Gas prices
const gas = await client.gas.getPrices("ethereum");
console.log("Base fee:", gas.base_fee_gwei, "gwei");
// WebSocket subscriptions
const ws = client.ws("ethereum", "mainnet");
ws.subscribe("newHeads", (block) => {
console.log("New block:", parseInt(block.number, 16));
});
// Bundler
const userOpHash = await client.bundler.sendUserOperation("base", "mainnet", {
sender: wallet.address,
nonce: "0x0",
callData: "0x...",
// ... other UserOp fields
});
console.log("UserOp hash:", userOpHash);`}</code>
</pre>
</div>
</CardContent>
</Card>
</section>
{/* Python */}
<section className="space-y-4">
<Card>
<CardHeader>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<CardTitle className="text-xl">Python</CardTitle>
</div>
<Badge variant="secondary">v2.0.0</Badge>
</div>
<p className="text-sm text-muted-foreground mt-1">
Python 3.10+. Async-first with sync wrappers. Full type hints with Pydantic models.
</p>
</CardHeader>
<CardContent className="space-y-4">
<div>
<h4 className="text-sm font-semibold mb-2">Install</h4>
<pre className="overflow-x-auto rounded-lg bg-zinc-950 p-4 text-sm text-zinc-100">
<code>{`pip install bootnode
# or
uv add bootnode`}</code>
</pre>
</div>
<div>
<h4 className="text-sm font-semibold mb-2">Usage</h4>
<pre className="overflow-x-auto rounded-lg bg-zinc-950 p-4 text-sm text-zinc-100">
<code>{`import asyncio
from bootnode import Bootnode
client = Bootnode(api_key="${docsConfig.apiKeyPrefix}live_...")
async def main():
# JSON-RPC
result = await client.rpc("ethereum", "mainnet", {
"jsonrpc": "2.0",
"id": 1,
"method": "eth_blockNumber",
"params": [],
})
block = int(result["result"], 16)
print(f"Block: {block}")
# Token balances
balances = await client.tokens.get_balances(
"ethereum",
"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
)
for token in balances["tokens"]:
print(f" {token['symbol']}: {token['formatted_balance']}")
# NFT metadata
nft = await client.nfts.get_metadata(
"ethereum",
"0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
"1234"
)
print(f"NFT: {nft['name']}")
# Create smart wallet
wallet = await client.wallets.create(
owner="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
chain="base"
)
print(f"Wallet: {wallet['address']}")
# Gas prices
gas = await client.gas.get_prices("ethereum")
print(f"Base fee: {gas['base_fee_gwei']} gwei")
asyncio.run(main())
# Sync usage (for scripts):
from bootnode import BootnodeSync
sync_client = BootnodeSync(api_key="${docsConfig.apiKeyPrefix}live_...")
gas = sync_client.gas.get_prices("ethereum")
print(f"Base fee: {gas['base_fee_gwei']} gwei")`}</code>
</pre>
</div>
</CardContent>
</Card>
</section>
{/* Go */}
<section className="space-y-4">
<Card>
<CardHeader>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<CardTitle className="text-xl">Go</CardTitle>
</div>
<Badge variant="secondary">v1.0.0</Badge>
</div>
<p className="text-sm text-muted-foreground mt-1">
Go 1.21+. Context-aware, idiomatic Go with strong types.
</p>
</CardHeader>
<CardContent className="space-y-4">
<div>
<h4 className="text-sm font-semibold mb-2">Install</h4>
<pre className="overflow-x-auto rounded-lg bg-zinc-950 p-4 text-sm text-zinc-100">
<code>{`go get github.com/bootnode/bootnode-go`}</code>
</pre>
</div>
<div>
<h4 className="text-sm font-semibold mb-2">Usage</h4>
<pre className="overflow-x-auto rounded-lg bg-zinc-950 p-4 text-sm text-zinc-100">
<code>{`package main
import (
"context"
"fmt"
"log"
"os"
"strconv"
"github.com/bootnode/bootnode-go"
)
func main() {
client := bootnode.NewClient(os.Getenv("BOOTNODE_API_KEY"))
ctx := context.Background()
// JSON-RPC
result, err := client.RPC(ctx, "ethereum", "mainnet", map[string]any{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_blockNumber",
"params": []any{},
})
if err != nil {
log.Fatal(err)
}
blockHex := result["result"].(string)
block, _ := strconv.ParseInt(blockHex[2:], 16, 64)
fmt.Printf("Block: %d\\n", block)
// Token balances
balances, err := client.Tokens.GetBalances(ctx, "ethereum",
"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")
if err != nil {
log.Fatal(err)
}
for _, token := range balances.Tokens {
fmt.Printf(" %s: %s\\n", token.Symbol, token.FormattedBalance)
}
// Create smart wallet
wallet, err := client.Wallets.Create(ctx, bootnode.CreateWalletParams{
Owner: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
Chain: "base",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Wallet: %s\\n", wallet.Address)
// Gas prices
gas, err := client.Gas.GetPrices(ctx, "ethereum")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Base fee: %s gwei\\n", gas.BaseFeeGwei)
}`}</code>
</pre>
</div>
</CardContent>
</Card>
</section>
{/* Rust */}
<section className="space-y-4">
<Card>
<CardHeader>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<CardTitle className="text-xl">Rust</CardTitle>
</div>
<Badge variant="secondary">v0.9.0</Badge>
</div>
<p className="text-sm text-muted-foreground mt-1">
Rust 1.75+. Async with Tokio. Serde-based serialization. Zero-copy where possible.
</p>
</CardHeader>
<CardContent className="space-y-4">
<div>
<h4 className="text-sm font-semibold mb-2">Install</h4>
<pre className="overflow-x-auto rounded-lg bg-zinc-950 p-4 text-sm text-zinc-100">
<code>{`# Cargo.toml
[dependencies]
bootnode = "0.9"
tokio = { version = "1", features = ["full"] }
serde_json = "1"`}</code>
</pre>
</div>
<div>
<h4 className="text-sm font-semibold mb-2">Usage</h4>
<pre className="overflow-x-auto rounded-lg bg-zinc-950 p-4 text-sm text-zinc-100">
<code>{`use bootnode::Client;
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), bootnode::Error> {
let client = Client::new(
std::env::var("BOOTNODE_API_KEY")
.expect("BOOTNODE_API_KEY must be set")
);
// JSON-RPC
let result = client
.rpc("ethereum", "mainnet", json!({
"jsonrpc": "2.0",
"id": 1,
"method": "eth_blockNumber",
"params": []
}))
.await?;
let block_hex = result["result"].as_str().unwrap();
let block = u64::from_str_radix(&block_hex[2..], 16).unwrap();
println!("Block: {block}");
// Token balances
let balances = client
.tokens()
.get_balances("ethereum", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")
.await?;
for token in &balances.tokens {
println!(" {}: {}", token.symbol, token.formatted_balance);
}
// Create smart wallet
let wallet = client
.wallets()
.create("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "base")
.await?;
println!("Wallet: {}", wallet.address);
// Gas prices
let gas = client.gas().get_prices("ethereum").await?;
println!("Base fee: {} gwei", gas.base_fee_gwei);
Ok(())
}`}</code>
</pre>
</div>
</CardContent>
</Card>
</section>
{/* Feature Matrix */}
<section className="space-y-4">
<h2 className="text-2xl font-semibold">Feature Matrix</h2>
<div className="overflow-x-auto border rounded-lg">
<table className="w-full text-sm">
<thead>
<tr className="border-b bg-muted/50">
<th className="text-left p-3 font-medium">Feature</th>
<th className="text-left p-3 font-medium">TypeScript</th>
<th className="text-left p-3 font-medium">Python</th>
<th className="text-left p-3 font-medium">Go</th>
<th className="text-left p-3 font-medium">Rust</th>
</tr>
</thead>
<tbody>
{[
{ feature: "JSON-RPC", ts: true, py: true, go: true, rs: true },
{ feature: "Token API", ts: true, py: true, go: true, rs: true },
{ feature: "NFT API", ts: true, py: true, go: true, rs: true },
{ feature: "Wallets", ts: true, py: true, go: true, rs: true },
{ feature: "Webhooks", ts: true, py: true, go: true, rs: true },
{ feature: "Gas Manager", ts: true, py: true, go: true, rs: true },
{ feature: "Bundler", ts: true, py: true, go: true, rs: true },
{ feature: "WebSocket", ts: true, py: true, go: true, rs: true },
{ feature: "Auto-retry", ts: true, py: true, go: true, rs: true },
{ feature: "Streaming", ts: true, py: true, go: true, rs: true },
].map((row) => (
<tr key={row.feature} className="border-b last:border-0">
<td className="p-3 font-medium">{row.feature}</td>
<td className="p-3">{row.ts ? "Yes" : "Coming soon"}</td>
<td className="p-3">{row.py ? "Yes" : "Coming soon"}</td>
<td className="p-3">{row.go ? "Yes" : "Coming soon"}</td>
<td className="p-3">{row.rs ? "Yes" : "Coming soon"}</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
{/* Next Steps */}
<section className="space-y-4">
<h2 className="text-2xl font-semibold">Next Steps</h2>
<div className="grid gap-3 sm:grid-cols-2">
{[
{ title: "Quickstart", href: "/docs/quickstart", desc: "Get your first call running" },
{ title: "API Reference", href: "/docs/api", desc: "Full endpoint documentation" },
{ title: "Examples", href: "/docs/examples", desc: "Common use cases" },
{ title: "Changelog", href: "/docs/changelog", desc: "Latest SDK updates" },
].map((item) => (
<Link
key={item.title}
href={item.href}
className="flex items-center justify-between p-4 border rounded-lg hover:bg-muted transition-colors group"
>
<div>
<p className="font-medium">{item.title}</p>
<p className="text-sm text-muted-foreground">{item.desc}</p>
</div>
<ArrowRight className="h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors" />
</Link>
))}
</div>
</section>
</div>
</DocsLayout>
)
}