@0block.io/sdk 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/zeroblock.d.ts +31 -0
- package/dist/zeroblock.js +131 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./types.js";
|
|
|
3
3
|
export { createContext, type CreateContextParams, type TenantInit, type ZeroBlockContext, } from "./context.js";
|
|
4
4
|
export { buildSendTransactionRequest, createLandingClient, withLandingTip, type LandingClient, type LandingServiceConfig, type SendTransactionOptions, } from "./landing.js";
|
|
5
5
|
export { fetchRecentBlockhash, type FetchBlockhashOptions, type RecentBlockhash, } from "./blockhash.js";
|
|
6
|
+
export { zeroblockFetcher, fetchTokenBalanceViaZeroblock, fetchLookupTableViaZeroblock, type ZeroblockReadOptions, type ZeroblockTokenBalance, } from "./zeroblock.js";
|
|
6
7
|
export { toPk, deriveAta, deriveOrderMarker, deriveWrapperConfig, deriveRouterGlobalConfig, deriveRouterTenantConfig, derivePumpfunGlobal, derivePumpfunBondingCurve, derivePumpfunBondingCurveV2, derivePumpfunEventAuthority, derivePumpfunCreatorVault, derivePumpfunGlobalVolumeAccumulator, derivePumpfunUserVolumeAccumulator, derivePumpfunFeeConfig, } from "./pda.js";
|
|
7
8
|
export { type AccountFetcher, connectionFetcher, resolveTokenProgram, resolvePumpfunMarketContext, fetchPumpfunGlobalFeeRecipient, fetchPumpfunBondingCurveCreator, fetchPumpfunBuybackFeeRecipients, } from "./fetch.js";
|
|
8
9
|
export { buildPumpfunRemainingAccounts, type PumpfunRemainingAccountsParams, } from "./venues/pumpfun.js";
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ export * from "./types.js";
|
|
|
16
16
|
export { createContext, } from "./context.js";
|
|
17
17
|
export { buildSendTransactionRequest, createLandingClient, withLandingTip, } from "./landing.js";
|
|
18
18
|
export { fetchRecentBlockhash, } from "./blockhash.js";
|
|
19
|
+
export { zeroblockFetcher, fetchTokenBalanceViaZeroblock, fetchLookupTableViaZeroblock, } from "./zeroblock.js";
|
|
19
20
|
export { toPk, deriveAta, deriveOrderMarker, deriveWrapperConfig, deriveRouterGlobalConfig, deriveRouterTenantConfig, derivePumpfunGlobal, derivePumpfunBondingCurve, derivePumpfunBondingCurveV2, derivePumpfunEventAuthority, derivePumpfunCreatorVault, derivePumpfunGlobalVolumeAccumulator, derivePumpfunUserVolumeAccumulator, derivePumpfunFeeConfig, } from "./pda.js";
|
|
20
21
|
export { connectionFetcher, resolveTokenProgram, resolvePumpfunMarketContext, fetchPumpfunGlobalFeeRecipient, fetchPumpfunBondingCurveCreator, fetchPumpfunBuybackFeeRecipients, } from "./fetch.js";
|
|
21
22
|
export { buildPumpfunRemainingAccounts, } from "./venues/pumpfun.js";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AccountFetcher } from "./fetch.js";
|
|
2
|
+
import type { Address, LookupTableData } from "./types.js";
|
|
3
|
+
export interface ZeroblockReadOptions {
|
|
4
|
+
/** Injectable fetch (tests / non-standard runtimes). Defaults to global fetch. */
|
|
5
|
+
fetchImpl?: typeof fetch;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* An {@link AccountFetcher} backed by 0Block's read gateway instead of a
|
|
9
|
+
* web3.js Connection. Coalesces every getAccountInfo issued in the same
|
|
10
|
+
* microtask into ONE getMultipleAccounts round-trip (the market resolver reads
|
|
11
|
+
* ~4 accounts concurrently → a single request), and dedupes repeated addresses.
|
|
12
|
+
*/
|
|
13
|
+
export declare function zeroblockFetcher(apiBaseUrl: string, opts?: ZeroblockReadOptions): AccountFetcher;
|
|
14
|
+
export interface ZeroblockTokenBalance {
|
|
15
|
+
/** Raw base-unit balance (summed across the owner's token accounts), integer string. */
|
|
16
|
+
amountBaseUnits: string;
|
|
17
|
+
decimals: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The SPL token balance of `owner` for `mint`, via 0Block's
|
|
21
|
+
* getTokenAccountsByOwner proxy. Returns a ZERO balance (not an error) when the
|
|
22
|
+
* owner holds no token account for the mint — a legitimate "nothing to sell"
|
|
23
|
+
* state. Sums across multiple token accounts (rare multi-ATA case).
|
|
24
|
+
*/
|
|
25
|
+
export declare function fetchTokenBalanceViaZeroblock(apiBaseUrl: string, owner: Address, mint: Address, opts?: ZeroblockReadOptions): Promise<ZeroblockTokenBalance>;
|
|
26
|
+
/**
|
|
27
|
+
* Fetch and decode an Address Lookup Table via 0Block's accounts proxy —
|
|
28
|
+
* returns the table key + its stored addresses (base58), ready to pass as a
|
|
29
|
+
* {@link LookupTableData}. Returns null when the table account does not exist.
|
|
30
|
+
*/
|
|
31
|
+
export declare function fetchLookupTableViaZeroblock(apiBaseUrl: string, tableAddress: Address, opts?: ZeroblockReadOptions): Promise<LookupTableData | null>;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// 0Block READ GATEWAY client. Lets a browser build swap transactions with NO
|
|
2
|
+
// Solana RPC of its own: 0Block proxies the handful of read methods a swap
|
|
3
|
+
// needs (getMultipleAccounts, getTokenAccountsByOwner) to its OWN upstream RPC
|
|
4
|
+
// node and returns the standard JSON-RPC `result` verbatim. This module speaks
|
|
5
|
+
// that gateway and adapts it to the SDK's AccountFetcher seam, so the pump.fun
|
|
6
|
+
// market resolver, ALT decode, and balance reads all work unchanged — just
|
|
7
|
+
// sourced from 0Block instead of web3.js.
|
|
8
|
+
//
|
|
9
|
+
// Endpoints (all public, no API key — the data is public on-chain):
|
|
10
|
+
// POST {base}/api/v1/accounts { addresses:[<b58>...] } -> RPC getMultipleAccounts result
|
|
11
|
+
// GET {base}/api/v1/token-accounts?owner=<b58>&mint=<b58> -> RPC getTokenAccountsByOwner result
|
|
12
|
+
import * as web3 from "@solana/web3.js";
|
|
13
|
+
import { toPk } from "./pda.js";
|
|
14
|
+
/** Strip trailing slashes so `${base}/api/v1/...` is always well-formed. */
|
|
15
|
+
function normalizeBase(apiBaseUrl) {
|
|
16
|
+
return apiBaseUrl.replace(/\/+$/, "");
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Fetch raw account infos for `addresses` (order-preserving) via 0Block's
|
|
20
|
+
* getMultipleAccounts proxy. Missing accounts come back as null.
|
|
21
|
+
*/
|
|
22
|
+
async function fetchAccountsRaw(base, addresses, fetchImpl) {
|
|
23
|
+
const res = await fetchImpl(`${base}/api/v1/accounts`, {
|
|
24
|
+
method: "POST",
|
|
25
|
+
headers: { "Content-Type": "application/json" },
|
|
26
|
+
body: JSON.stringify({ addresses }),
|
|
27
|
+
});
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
throw new Error(`0Block accounts unavailable (HTTP ${res.status})`);
|
|
30
|
+
}
|
|
31
|
+
const body = (await res.json());
|
|
32
|
+
if (body.error) {
|
|
33
|
+
throw new Error(`0Block accounts error: ${body.error.message ?? "unknown"}`);
|
|
34
|
+
}
|
|
35
|
+
const value = body.value ?? [];
|
|
36
|
+
return addresses.map((_, i) => {
|
|
37
|
+
const acct = value[i];
|
|
38
|
+
if (!acct || acct.data === undefined)
|
|
39
|
+
return null;
|
|
40
|
+
const b64 = Array.isArray(acct.data) ? acct.data[0] : acct.data;
|
|
41
|
+
return {
|
|
42
|
+
data: new Uint8Array(Buffer.from(b64, "base64")),
|
|
43
|
+
owner: new web3.PublicKey(acct.owner ?? web3.PublicKey.default.toBase58()),
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* An {@link AccountFetcher} backed by 0Block's read gateway instead of a
|
|
49
|
+
* web3.js Connection. Coalesces every getAccountInfo issued in the same
|
|
50
|
+
* microtask into ONE getMultipleAccounts round-trip (the market resolver reads
|
|
51
|
+
* ~4 accounts concurrently → a single request), and dedupes repeated addresses.
|
|
52
|
+
*/
|
|
53
|
+
export function zeroblockFetcher(apiBaseUrl, opts) {
|
|
54
|
+
const base = normalizeBase(apiBaseUrl);
|
|
55
|
+
const fetchImpl = opts?.fetchImpl ?? fetch;
|
|
56
|
+
let queue = [];
|
|
57
|
+
let scheduled = false;
|
|
58
|
+
const flush = async () => {
|
|
59
|
+
const batch = queue;
|
|
60
|
+
queue = [];
|
|
61
|
+
scheduled = false;
|
|
62
|
+
const unique = [...new Set(batch.map((p) => p.address.toBase58()))];
|
|
63
|
+
try {
|
|
64
|
+
const infos = await fetchAccountsRaw(base, unique, fetchImpl);
|
|
65
|
+
const byAddr = new Map(unique.map((a, i) => [a, infos[i]]));
|
|
66
|
+
for (const p of batch)
|
|
67
|
+
p.resolve(byAddr.get(p.address.toBase58()) ?? null);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
for (const p of batch)
|
|
71
|
+
p.reject(err);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
return {
|
|
75
|
+
getAccountInfo(address) {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
queue.push({ address, resolve, reject });
|
|
78
|
+
if (!scheduled) {
|
|
79
|
+
scheduled = true;
|
|
80
|
+
queueMicrotask(() => void flush());
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The SPL token balance of `owner` for `mint`, via 0Block's
|
|
88
|
+
* getTokenAccountsByOwner proxy. Returns a ZERO balance (not an error) when the
|
|
89
|
+
* owner holds no token account for the mint — a legitimate "nothing to sell"
|
|
90
|
+
* state. Sums across multiple token accounts (rare multi-ATA case).
|
|
91
|
+
*/
|
|
92
|
+
export async function fetchTokenBalanceViaZeroblock(apiBaseUrl, owner, mint, opts) {
|
|
93
|
+
const base = normalizeBase(apiBaseUrl);
|
|
94
|
+
const fetchImpl = opts?.fetchImpl ?? fetch;
|
|
95
|
+
const ownerB58 = toPk(owner).toBase58();
|
|
96
|
+
const mintB58 = toPk(mint).toBase58();
|
|
97
|
+
const res = await fetchImpl(`${base}/api/v1/token-accounts?owner=${ownerB58}&mint=${mintB58}`);
|
|
98
|
+
if (!res.ok) {
|
|
99
|
+
throw new Error(`0Block token balance unavailable (HTTP ${res.status})`);
|
|
100
|
+
}
|
|
101
|
+
const body = (await res.json());
|
|
102
|
+
if (body.error) {
|
|
103
|
+
throw new Error(`0Block token balance error: ${body.error.message ?? "unknown"}`);
|
|
104
|
+
}
|
|
105
|
+
let total = 0n;
|
|
106
|
+
let decimals = 0;
|
|
107
|
+
for (const acct of body.value ?? []) {
|
|
108
|
+
const tokenAmount = acct.account?.data?.parsed?.info?.tokenAmount;
|
|
109
|
+
if (!tokenAmount || typeof tokenAmount.amount !== "string")
|
|
110
|
+
continue;
|
|
111
|
+
total += BigInt(tokenAmount.amount);
|
|
112
|
+
if (typeof tokenAmount.decimals === "number")
|
|
113
|
+
decimals = tokenAmount.decimals;
|
|
114
|
+
}
|
|
115
|
+
return { amountBaseUnits: total.toString(), decimals };
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Fetch and decode an Address Lookup Table via 0Block's accounts proxy —
|
|
119
|
+
* returns the table key + its stored addresses (base58), ready to pass as a
|
|
120
|
+
* {@link LookupTableData}. Returns null when the table account does not exist.
|
|
121
|
+
*/
|
|
122
|
+
export async function fetchLookupTableViaZeroblock(apiBaseUrl, tableAddress, opts) {
|
|
123
|
+
const base = normalizeBase(apiBaseUrl);
|
|
124
|
+
const fetchImpl = opts?.fetchImpl ?? fetch;
|
|
125
|
+
const keyB58 = toPk(tableAddress).toBase58();
|
|
126
|
+
const [info] = await fetchAccountsRaw(base, [keyB58], fetchImpl);
|
|
127
|
+
if (!info)
|
|
128
|
+
return null;
|
|
129
|
+
const state = web3.AddressLookupTableAccount.deserialize(info.data);
|
|
130
|
+
return { key: keyB58, addresses: state.addresses.map((a) => a.toBase58()) };
|
|
131
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0block.io/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Client-side transaction builder for the 0Block DEX router. Builds unsigned v0 swap transactions entirely offline \u2014 tenant-wrapped or direct \u2014 with shared address lookup tables, gateway tips, and on-chain fee-event decoding for accounting.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"solana",
|