Observed since 20 Oct, 22:05 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
@0block.io/sdk
Client-side transaction builder for the 0Block DEX router. Builds unsigned v0 swap transactions entirely offline — tenant-wrapped or direct — with shared address lookup tables, gateway tips, and on-chain fee-event decoding for accounting.
The SDK for 0Block's two products — independent, composable:
| Product | What it does | Needs the other? |
|---|---|---|
| DEX Smart Router | Build swap transactions on-chain-routed across 60+ venues — through your tenant wrapper (your fee applies) or directly (0Block fee only) | No — submit through any RPC |
| Landing Service | Land any fully-signed Solana transaction: tip-gated submission forwarded to staked infrastructure and current/next leader TPUs | No — accepts any transaction |
Used together they form a complete trade pipeline: build with the router SDK, sign externally, land through the service.
Router highlights:
Keypair ever touches the SDK.npm install @0block.io/sdk
Requires Node ≥ 20 server-side; browser builds work with any modern bundler.
The mode is fixed at initialization:
import { createContext } from "@0block.io/sdk";
// Tenant mode — swaps route through your tenant wrapper program.
// Your tenant fee (set on-chain) and the 0Block fee apply.
const ctx = createContext({
tenant: {
wrapperProgramId: "<your tenant wrapper program id>",
tenantFeeVault: "<your tenant fee vault>",
},
});
// Direct mode — swaps invoke the 0Block router directly.
// Only the 0Block platform fee applies.
const ctx = createContext();
import { connectionFetcher, resolvePumpfunMarketContext } from "@0block.io/sdk";
const fetcher = connectionFetcher(connection);
const market = await resolvePumpfunMarketContext(fetcher, { mint });
// `market` is plain strings — push it to clients over your existing
// stream together with quotes and a FINALIZED blockhash.
import {
buildLookupTableAddresses,
buildInitLookupTableInstructions,
} from "@0block.io/sdk";
const addresses = buildLookupTableAddresses({ context: ctx, market });
const { tableAddress, transactions } = buildInitLookupTableInstructions({
authority: opsKey,
recentSlot,
addresses,
});
// Send each batch as one transaction, in order. Wait ~1 slot before first use.
import { applyPreset, buildPumpfunSwapTransaction } from "@0block.io/sdk";
const { minReturn, tip, computeBudget } = applyPreset(
{ slippagePct: 20, prioritySol: 0.001, bribeSol: 0.001 },
{ expectedOut: quote.expectedOut, tipAccount: streamed.tipAccount }
);
const built = buildPumpfunSwapTransaction({
context: ctx,
market,
user: wallet.address,
side: "buy",
amountIn: 10_000_000n, // 0.01 SOL
minReturn,
recentBlockhash: streamed.finalizedBlockhash,
lookupTables: streamed.lookupTables,
tip,
computeBudget,
});
// built.messageBytes → sign with the user's key (exactly one signature)
// built.orderId → correlate the fill via SwapResultEvent
// built.estimatedSize → wire size, pre-checked against the 1232-byte limit
Attach the signature and get wire bytes with serializeWithSignatures(built, [sig]),
then submit through the 0Block gateway.
import { decodeSwapResultEvents } from "@0block.io/sdk";
const events = decodeSwapResultEvents(tx.meta.logMessages);
// [{ orderId, status, commissions: { feeMint, totalFeeAmount,
// items: [{ kind: "platform" | "tenant", bps, amount, tenantProgram }] } }]
Land any transaction — router-built or otherwise. Three rules: include the tip (a plain transfer to an allowlisted account, kept as a static message key, never behind a lookup table), use a finalized blockhash, and confirm by polling (no websocket).
import { createLandingClient, withLandingTip } from "@0block.io/sdk";
// Any instructions at all — no router required:
const ixs = withLandingTip(myInstructions, payer, {
account: tipAccount, // allowlisted tip account
lamports: 1_000_000n, // ≥ the service minimum
});
// ...compile with a FINALIZED blockhash, sign...
const landing = createLandingClient({
url: "https://<landing-endpoint>",
apiKey: process.env.ZEROBLOCK_API_KEY,
});
const { signature, slot } = await landing.submitAndConfirm(wireBytes, readConnection, {
lastValidBlockHeight,
});
Router-built transactions already carry the tip when you pass tip to
buildPumpfunSwapTransaction — hand their signed wire bytes straight to
landing.sendTransaction.
| Runs | Function | Purpose |
|---|---|---|
| anywhere | createContext | Resolve tenant vs direct mode from init params |
| backend | resolvePumpfunMarketContext | Chain-derived accounts for a mint, as streamable strings |
| backend | buildLookupTableAddresses / buildInitLookupTableInstructions | Create the shared static-accounts table |
| client | applyPreset | Slippage % / priority SOL / bribe SOL → build params |
| client | buildPumpfunSwapTransaction | Complete unsigned v0 transaction (offline) |
| client | serializeWithSignatures | Attach external signatures → wire bytes |
| indexer | decodeSwapResultEvents | SwapResultEvent → normalized commission breakdown |
Lower-level building blocks (buildPumpfunSwapInstruction, PDA derivations,
wSOL wrap/unwrap helpers, tip and compute-budget builders, vendored IDLs) are
exported as well.
(payer, order_id): a duplicate order
id fails at account creation and the whole swap reverts. Mint orderId on
your backend (non-zero u128, one per business order — reuse it across
retries) and pass it to buildPumpfunSwapTransaction; the SDK refuses to
build tenant swaps without one. Direct mode has no marker; a random id is
generated when omitted.wrapper_config PDA signs the router CPI, and the router's
TenantConfig.tenant_authority must equal that PDA
(deriveWrapperConfig(wrapperProgramId)). Otherwise swaps fail
UnauthorizedTenant.TenantConfig account
in the tenant_cfg slot even on direct calls (ignored for fees). The router
operator provisions a standing "direct" config; override its key with
directTenantConfigKey if needed.confirmed hash may be unknown there.wrapSol / unwrapWsol if your users manage wSOL themselves.npm install
npm test # compiles, then runs the offline smoke test (no network, no keys)
The vendored IDLs under src/idl/ are generated from the on-chain programs'
Anchor builds. Regenerate them after any program change — account ordering and
discriminators must match on-chain reality.
UNLICENSED — all rights reserved. Contact 0block.io for usage terms.
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
@solana/web3.jsEnvironment{
"local_name": "@solana/web3.js",
"alias": false,
"peer_metadata": null
} | ^1.98.0 | runtime |
@coral-xyz/anchorEnvironment{
"local_name": "@coral-xyz/anchor",
"alias": false,
"peer_metadata": null
} | ^0.31.1 | runtime |
typescriptEnvironment{
"local_name": "typescript",
"alias": false,
"peer_metadata": null
} | ^5.5.4 | development |
Source distribution
{
"shasum": "078b8bf85979b64f1074513b589bc943ce5707c7",
"tarball": "https://registry.npmjs.org/@0block.io/sdk/-/sdk-0.3.0.tgz",
"fileCount": 40,
"integrity": "sha512-jiLl/tb51mV7hSUBAfZNxFTYSJwdpN2aixJhvu582GsqtLEqcR8DPeHe32FL+BHbgR9oAstMY86HXPV+wrEfOg==",
"signatures": [
{
"sig": "MEUCIQDHIHBQEgopz7DSsZJqEzwlOxJvOKTTmpC84V1meiJqVQIgGqm3u+Or19UH4Lz4WzW+yWajpB26E061MBmvErqVm3s=",
"keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
}
],
"unpackedSize": 263150
}Observed since 20 Oct, 22:05 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:39efabc60e679073b3431b21f30942d8323800cfd5145cfc06a34c0d314ca0c1