@artblocks/abx-sdk 0.1.0-alpha.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/LICENSE +21 -0
- package/dist/abi/generated.d.ts +6185 -0
- package/dist/abi/generated.d.ts.map +1 -0
- package/dist/abi/generated.js +28 -0
- package/dist/abi/generated.js.map +1 -0
- package/dist/abi/index.d.ts +3227 -0
- package/dist/abi/index.d.ts.map +1 -0
- package/dist/abi/index.js +38 -0
- package/dist/abi/index.js.map +1 -0
- package/dist/chains.d.ts +27 -0
- package/dist/chains.d.ts.map +1 -0
- package/dist/chains.js +71 -0
- package/dist/chains.js.map +1 -0
- package/dist/chunks.d.ts +168 -0
- package/dist/chunks.d.ts.map +1 -0
- package/dist/chunks.js +232 -0
- package/dist/chunks.js.map +1 -0
- package/dist/clients.d.ts +42 -0
- package/dist/clients.d.ts.map +1 -0
- package/dist/clients.js +90 -0
- package/dist/clients.js.map +1 -0
- package/dist/create2.d.ts +42 -0
- package/dist/create2.d.ts.map +1 -0
- package/dist/create2.js +47 -0
- package/dist/create2.js.map +1 -0
- package/dist/deploy.d.ts +192 -0
- package/dist/deploy.d.ts.map +1 -0
- package/dist/deploy.js +231 -0
- package/dist/deploy.js.map +1 -0
- package/dist/deployments.d.ts +60 -0
- package/dist/deployments.d.ts.map +1 -0
- package/dist/deployments.js +81 -0
- package/dist/deployments.js.map +1 -0
- package/dist/deps.d.ts +109 -0
- package/dist/deps.d.ts.map +1 -0
- package/dist/deps.js +103 -0
- package/dist/deps.js.map +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +45 -0
- package/dist/env.js.map +1 -0
- package/dist/fastlz.d.ts +20 -0
- package/dist/fastlz.d.ts.map +1 -0
- package/dist/fastlz.js +123 -0
- package/dist/fastlz.js.map +1 -0
- package/dist/generator.d.ts +129 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +81 -0
- package/dist/generator.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/ops.d.ts +379 -0
- package/dist/ops.d.ts.map +1 -0
- package/dist/ops.js +811 -0
- package/dist/ops.js.map +1 -0
- package/dist/probe.d.ts +30 -0
- package/dist/probe.d.ts.map +1 -0
- package/dist/probe.js +74 -0
- package/dist/probe.js.map +1 -0
- package/dist/reconstruct.d.ts +97 -0
- package/dist/reconstruct.d.ts.map +1 -0
- package/dist/reconstruct.js +597 -0
- package/dist/reconstruct.js.map +1 -0
- package/dist/spine.d.ts +110 -0
- package/dist/spine.d.ts.map +1 -0
- package/dist/spine.js +0 -0
- package/dist/spine.js.map +1 -0
- package/dist/token.d.ts +33 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +66 -0
- package/dist/token.js.map +1 -0
- package/dist/tokendata.d.ts +50 -0
- package/dist/tokendata.d.ts.map +1 -0
- package/dist/tokendata.js +178 -0
- package/dist/tokendata.js.map +1 -0
- package/dist/traits.d.ts +38 -0
- package/dist/traits.d.ts.map +1 -0
- package/dist/traits.js +92 -0
- package/dist/traits.js.map +1 -0
- package/dist/types.d.ts +145 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/abi/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,uBAAuB,EACvB,4BAA4B,EAC5B,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,0BAA0B,EAC1B,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,kBAAkB,EAClB,sBAAsB,EACtB,2BAA2B,EAC3B,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AAiBxB;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAmBtB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// The ABI surface the SDK speaks. Generated artifacts come from the contracts
|
|
2
|
+
// package (Layer 1) via `pnpm sync-abis`; never hand-edit `generated.ts`.
|
|
3
|
+
export { oneOfOneImageFactoryAbi, oneOfOneImageFactoryBytecode, oneOfOneImageAbi, oneOfOneImageBytecode, seriesImageFactoryAbi, seriesImageFactoryBytecode, seriesImageAbi, seriesImageBytecode, seriesCodeFactoryAbi, seriesCodeFactoryBytecode, seriesCodeAbi, seriesCodeBytecode, abxSeedSourceAbi, abxSeedSourceBytecode, abxParamsLibAbi, abxParamsLibBytecode, abxCodeLibAbi, abxCodeLibBytecode, abxMetadataRendererAbi, abxMetadataRendererBytecode, abxChunkStoreAbi, abxChunkStoreBytecode, abxFixedPriceMinterAbi, abxFixedPriceMinterBytecode, } from './generated.js';
|
|
4
|
+
import { oneOfOneImageAbi, oneOfOneImageFactoryAbi, seriesImageAbi, seriesImageFactoryAbi, seriesCodeAbi, seriesCodeFactoryAbi, abxFixedPriceMinterAbi, } from './generated.js';
|
|
5
|
+
/** A stable signature key for an ABI event fragment (name + input types), for de-duping. */
|
|
6
|
+
function eventKey(f) {
|
|
7
|
+
return `${f.name ?? ''}(${(f.inputs ?? []).map((i) => i.type).join(',')})`;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The event-spine ABI: every event any ABX token type + its factory can emit — the set
|
|
11
|
+
* the reference indexer decodes. Both concrete tokens (1/1 and Series) declare the full
|
|
12
|
+
* spine they participate in (Register 1 standards + Register 2 native events); we union
|
|
13
|
+
* them plus the factories' `Deployed` and the fixed-price minter's sibling Minter-spine
|
|
14
|
+
* events (`SaleConfigured`/`Purchase`), de-duping shared fragments (e.g. `Transfer`) so a
|
|
15
|
+
* single ABI decodes any ABX contract's logs unambiguously.
|
|
16
|
+
*/
|
|
17
|
+
export const spineEventAbi = (() => {
|
|
18
|
+
const all = [
|
|
19
|
+
...oneOfOneImageAbi,
|
|
20
|
+
...seriesImageAbi,
|
|
21
|
+
...seriesCodeAbi,
|
|
22
|
+
...oneOfOneImageFactoryAbi,
|
|
23
|
+
...seriesImageFactoryAbi,
|
|
24
|
+
...seriesCodeFactoryAbi,
|
|
25
|
+
...abxFixedPriceMinterAbi,
|
|
26
|
+
].filter((f) => f.type === 'event');
|
|
27
|
+
const seen = new Set();
|
|
28
|
+
const out = [];
|
|
29
|
+
for (const f of all) {
|
|
30
|
+
const key = eventKey(f);
|
|
31
|
+
if (seen.has(key))
|
|
32
|
+
continue;
|
|
33
|
+
seen.add(key);
|
|
34
|
+
out.push(f);
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
})();
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/abi/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,0EAA0E;AAC1E,OAAO,EACL,uBAAuB,EACvB,4BAA4B,EAC5B,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,0BAA0B,EAC1B,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,kBAAkB,EAClB,sBAAsB,EACtB,2BAA2B,EAC3B,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AAExB,4FAA4F;AAC5F,SAAS,QAAQ,CAAC,CAAwE;IACxF,OAAO,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAC7E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE;IACjC,MAAM,GAAG,GAAG;QACV,GAAG,gBAAgB;QACnB,GAAG,cAAc;QACjB,GAAG,aAAa;QAChB,GAAG,uBAAuB;QAC1B,GAAG,qBAAqB;QACxB,GAAG,oBAAoB;QACvB,GAAG,sBAAsB;KAC1B,CAAC,MAAM,CAAC,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAU,CAAC,CAAC;QACjC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC,EAAE,CAAC"}
|
package/dist/chains.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Chain } from 'viem';
|
|
2
|
+
/**
|
|
3
|
+
* Chain targets. The SDK is neutral about *which* chain — it takes a target as
|
|
4
|
+
* input — but the toolkit's demo runs on a testnet, so that's the default here.
|
|
5
|
+
* The protocol is per-EVM-chain (one project = one contract, per chain).
|
|
6
|
+
*/
|
|
7
|
+
export declare const CHAINS: Record<string, Chain>;
|
|
8
|
+
export declare const DEFAULT_CHAIN_KEY = "base-sepolia";
|
|
9
|
+
export declare function resolveChain(key?: string): Chain;
|
|
10
|
+
/** The env var holding RPC endpoints for a chain: per-chain `ABX_RPC_URLS_<CHAIN>` (e.g.
|
|
11
|
+
* `ABX_RPC_URLS_SEPOLIA`) when set, else the bare `ABX_RPC_URLS` (the active `ABX_CHAIN`). */
|
|
12
|
+
export declare function rpcEnvVar(chainKey: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* The ordered, de-duplicated RPC endpoints for `chainKey`. **Network-scoped**: a
|
|
15
|
+
* per-chain `ABX_RPC_URLS_<CHAIN>` wins when set; otherwise the bare `ABX_RPC_URLS`
|
|
16
|
+
* (understood as "for the active `ABX_CHAIN`"). Both are comma/whitespace-separated
|
|
17
|
+
* lists in preference order — the client fails over across them and `abx doctor`
|
|
18
|
+
* probes + ranks each (e.g. widest `eth_getLogs` range). The bare and per-chain vars
|
|
19
|
+
* are never mixed, so a list for one network can't leak into another; a chainId guard
|
|
20
|
+
* (see `assertChainId`) then verifies the endpoints actually ARE `chainKey`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveRpcUrls(chainKey?: string): string[];
|
|
23
|
+
/** The primary RPC endpoint (the first of {@link resolveRpcUrls}). */
|
|
24
|
+
export declare function resolveRpcUrl(chainKey?: string): string;
|
|
25
|
+
/** A display-safe form of an RPC URL — host + a redacted key tail (URLs can embed keys). */
|
|
26
|
+
export declare function redactRpcUrl(url: string): string;
|
|
27
|
+
//# sourceMappingURL=chains.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../src/chains.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,MAAM,CAAC;AAGhC;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAGxC,CAAC;AAEF,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAShD,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAA0B,GAAG,KAAK,CAInE;AAED;+FAC+F;AAC/F,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAA0B,GAAG,MAAM,EAAE,CAY7E;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,QAAQ,GAAE,MAA0B,GAAG,MAAM,CAE1E;AAED,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAShD"}
|
package/dist/chains.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { sepolia, baseSepolia } from 'viem/chains';
|
|
2
|
+
import { loadDotEnv } from './env.js';
|
|
3
|
+
/**
|
|
4
|
+
* Chain targets. The SDK is neutral about *which* chain — it takes a target as
|
|
5
|
+
* input — but the toolkit's demo runs on a testnet, so that's the default here.
|
|
6
|
+
* The protocol is per-EVM-chain (one project = one contract, per chain).
|
|
7
|
+
*/
|
|
8
|
+
export const CHAINS = {
|
|
9
|
+
'base-sepolia': baseSepolia,
|
|
10
|
+
sepolia,
|
|
11
|
+
};
|
|
12
|
+
export const DEFAULT_CHAIN_KEY = 'base-sepolia';
|
|
13
|
+
// Public, keyless endpoints per chain — overridable. A self-hoster points these at
|
|
14
|
+
// their own node; nothing about resolution depends on a particular provider.
|
|
15
|
+
const DEFAULT_RPC_URLS = {
|
|
16
|
+
'base-sepolia': 'https://sepolia.base.org',
|
|
17
|
+
sepolia: 'https://ethereum-sepolia-rpc.publicnode.com',
|
|
18
|
+
};
|
|
19
|
+
export function resolveChain(key = DEFAULT_CHAIN_KEY) {
|
|
20
|
+
const chain = CHAINS[key];
|
|
21
|
+
if (!chain)
|
|
22
|
+
throw new Error(`Unknown chain "${key}". Known: ${Object.keys(CHAINS).join(', ')}`);
|
|
23
|
+
return chain;
|
|
24
|
+
}
|
|
25
|
+
/** The env var holding RPC endpoints for a chain: per-chain `ABX_RPC_URLS_<CHAIN>` (e.g.
|
|
26
|
+
* `ABX_RPC_URLS_SEPOLIA`) when set, else the bare `ABX_RPC_URLS` (the active `ABX_CHAIN`). */
|
|
27
|
+
export function rpcEnvVar(chainKey) {
|
|
28
|
+
// Env var names can't contain hyphens, so a key like `base-sepolia` becomes
|
|
29
|
+
// `ABX_RPC_URLS_BASE_SEPOLIA` (any non-alphanumeric collapses to `_`).
|
|
30
|
+
return `ABX_RPC_URLS_${chainKey.toUpperCase().replace(/[^A-Z0-9]+/g, '_')}`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The ordered, de-duplicated RPC endpoints for `chainKey`. **Network-scoped**: a
|
|
34
|
+
* per-chain `ABX_RPC_URLS_<CHAIN>` wins when set; otherwise the bare `ABX_RPC_URLS`
|
|
35
|
+
* (understood as "for the active `ABX_CHAIN`"). Both are comma/whitespace-separated
|
|
36
|
+
* lists in preference order — the client fails over across them and `abx doctor`
|
|
37
|
+
* probes + ranks each (e.g. widest `eth_getLogs` range). The bare and per-chain vars
|
|
38
|
+
* are never mixed, so a list for one network can't leak into another; a chainId guard
|
|
39
|
+
* (see `assertChainId`) then verifies the endpoints actually ARE `chainKey`.
|
|
40
|
+
*/
|
|
41
|
+
export function resolveRpcUrls(chainKey = DEFAULT_CHAIN_KEY) {
|
|
42
|
+
loadDotEnv();
|
|
43
|
+
// Per-chain override is authoritative when present; bare ABX_RPC_URLS is the
|
|
44
|
+
// single-/active-chain fallback. They are NOT concatenated — mixing networks is the bug.
|
|
45
|
+
const list = process.env[rpcEnvVar(chainKey)] ?? process.env.ABX_RPC_URLS ?? '';
|
|
46
|
+
const seen = new Set();
|
|
47
|
+
const urls = list
|
|
48
|
+
.split(/[\s,]+/)
|
|
49
|
+
.map((u) => u.trim())
|
|
50
|
+
.filter((u) => u && !seen.has(u) && seen.add(u));
|
|
51
|
+
if (urls.length === 0 && DEFAULT_RPC_URLS[chainKey])
|
|
52
|
+
urls.push(DEFAULT_RPC_URLS[chainKey]);
|
|
53
|
+
return urls;
|
|
54
|
+
}
|
|
55
|
+
/** The primary RPC endpoint (the first of {@link resolveRpcUrls}). */
|
|
56
|
+
export function resolveRpcUrl(chainKey = DEFAULT_CHAIN_KEY) {
|
|
57
|
+
return resolveRpcUrls(chainKey)[0] ?? '';
|
|
58
|
+
}
|
|
59
|
+
/** A display-safe form of an RPC URL — host + a redacted key tail (URLs can embed keys). */
|
|
60
|
+
export function redactRpcUrl(url) {
|
|
61
|
+
try {
|
|
62
|
+
const u = new URL(url);
|
|
63
|
+
const last = u.pathname.split('/').filter(Boolean).pop() ?? '';
|
|
64
|
+
const tail = last.length > 6 ? `…${last.slice(-4)}` : last;
|
|
65
|
+
return tail ? `${u.host}/…/${tail}` : u.host;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return url.length > 24 ? `${url.slice(0, 20)}…` : url;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=chains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chains.js","sourceRoot":"","sources":["../src/chains.ts"],"names":[],"mappings":"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"}
|
package/dist/chunks.d.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { type Address, type Hex, type PublicClient, type TransactionReceipt } from 'viem';
|
|
2
|
+
/**
|
|
3
|
+
* Multi-chunk on-chain content — the off-chain side of {@link AbxChunkStore}.
|
|
4
|
+
*
|
|
5
|
+
* Large content (a 30 kB image, a long description) is split into SSTORE2-sized chunks,
|
|
6
|
+
* optionally FastLZ-compressed **per chunk** off-chain (the chunk store decompresses on
|
|
7
|
+
* read, so it stays on-chain-renderable), written as immutable data contracts, and tied
|
|
8
|
+
* together by a manifest. The field then carries the `reader` representation with
|
|
9
|
+
* `value = abi.encode(chunkStore, manifest)`. gzip is *not* handled here — it's an
|
|
10
|
+
* off-chain decode signaled by the `-gzip` representation, applied to the assembled bytes.
|
|
11
|
+
*/
|
|
12
|
+
/** SSTORE2 data-contract code limit is 24576 bytes (EIP-170) minus the STOP byte; chunk
|
|
13
|
+
* conservatively so even an incompressible FastLZ chunk (slight expansion) still fits. */
|
|
14
|
+
export declare const DEFAULT_CHUNK_SIZE = 22000;
|
|
15
|
+
/** One planned chunk: the bytes to store + whether they're FastLZ-compressed. */
|
|
16
|
+
export interface PlannedChunk {
|
|
17
|
+
data: Uint8Array;
|
|
18
|
+
compressed: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* One staging transaction, described in lane-agnostic terms: the SDK builds the calldata,
|
|
22
|
+
* the caller decides how it's signed. The chunk-store writes are **ownerless**, so they can
|
|
23
|
+
* be signed by any funded signer — the env key (hot lane) *or* a connected browser wallet
|
|
24
|
+
* (wallet lane). Keeping the signer out of this module is what lets on-chain staging work
|
|
25
|
+
* under every signing lane instead of assuming a hot key.
|
|
26
|
+
*
|
|
27
|
+
* `summary` + `fields` are surfaced to a human on the wallet sign page; `to: null` means a
|
|
28
|
+
* contract creation (deploying the chunk store itself).
|
|
29
|
+
*/
|
|
30
|
+
export interface StagingTx {
|
|
31
|
+
to: Address | null;
|
|
32
|
+
data: Hex;
|
|
33
|
+
summary: string;
|
|
34
|
+
fields: Record<string, string>;
|
|
35
|
+
}
|
|
36
|
+
/** Sign + broadcast one {@link StagingTx} and return its mined receipt (for event parsing). */
|
|
37
|
+
export type SendStagingTx = (tx: StagingTx) => Promise<TransactionReceipt>;
|
|
38
|
+
/**
|
|
39
|
+
* Split content into chunks, FastLZ-compressing each when `fastlz` is set (per-chunk — the
|
|
40
|
+
* convention the store + reader expect). Pure: no chain, no I/O. A chunk is only stored
|
|
41
|
+
* compressed when that actually shrinks it (so the reader never wastes a decompress).
|
|
42
|
+
*/
|
|
43
|
+
export declare function planChunks(content: Uint8Array, opts?: {
|
|
44
|
+
fastlz?: boolean;
|
|
45
|
+
chunkSize?: number;
|
|
46
|
+
}): PlannedChunk[];
|
|
47
|
+
/**
|
|
48
|
+
* A per-transaction gas ceiling for packing chunk writes. Comfortably under mainnet's
|
|
49
|
+
* ~30M block limit so a batch always fits with room for the base + calldata cost; the
|
|
50
|
+
* planner splits content across multiple transactions to stay beneath it.
|
|
51
|
+
*/
|
|
52
|
+
export declare const DEFAULT_TX_GAS_BUDGET = 8000000;
|
|
53
|
+
/**
|
|
54
|
+
* Rough gas for writing one chunk as an SSTORE2 data contract: a fixed CREATE + base
|
|
55
|
+
* overhead plus the code-deposit cost (~200 gas/byte) and calldata. Deliberately an
|
|
56
|
+
* over-estimate so packed batches land safely inside {@link DEFAULT_TX_GAS_BUDGET};
|
|
57
|
+
* the wallet still does the real `eth_estimateGas` before sending.
|
|
58
|
+
*/
|
|
59
|
+
export declare function estimateChunkGas(chunk: PlannedChunk): number;
|
|
60
|
+
/** How content will be written on-chain — one atomic tx, or several batched ones. */
|
|
61
|
+
export type ContentTxPlan = {
|
|
62
|
+
mode: 'single';
|
|
63
|
+
chunks: PlannedChunk[];
|
|
64
|
+
txCount: 1;
|
|
65
|
+
} | {
|
|
66
|
+
mode: 'split';
|
|
67
|
+
batches: PlannedChunk[][];
|
|
68
|
+
txCount: number;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Decide the transaction shape for a piece of content. When the whole thing fits one
|
|
72
|
+
* tx's gas budget it's a single atomic {@link writeContent} (no address prediction, no
|
|
73
|
+
* follow-up). Otherwise it's split into gas-bounded batches of {@link writeChunk} calls
|
|
74
|
+
* (each batch one `multicall`), followed by a single {@link writeManifest} — so
|
|
75
|
+
* `txCount` is `batches.length + 1`. Pure: no chain, no I/O.
|
|
76
|
+
*/
|
|
77
|
+
export declare function planContentTxs(chunks: PlannedChunk[], opts?: {
|
|
78
|
+
gasBudget?: number;
|
|
79
|
+
}): ContentTxPlan;
|
|
80
|
+
/**
|
|
81
|
+
* Deploy `AbxChunkStore` — the shared, stateless multi-chunk store + reader. Deploy once
|
|
82
|
+
* per chain (like the renderer); every chunked field references it as its `reader`.
|
|
83
|
+
*/
|
|
84
|
+
export declare function deployChunkStore(send: SendStagingTx): Promise<{
|
|
85
|
+
chunkStore: Address;
|
|
86
|
+
txHash: Hex;
|
|
87
|
+
blockNumber: bigint;
|
|
88
|
+
}>;
|
|
89
|
+
/**
|
|
90
|
+
* Does `store` expose the current `writeContent(bytes[],bool[])` ABI? A chunk store deployed
|
|
91
|
+
* before `writeContent` existed (an older `AbxChunkStore`) still *has code*, so a bare
|
|
92
|
+
* `getCode` check passes — but the call reverts, silently breaking the `--onchain-image`
|
|
93
|
+
* path. We probe with an empty `writeContent([],[])`: the current store returns a manifest
|
|
94
|
+
* address, a stale/incompatible one reverts. This is a pure `eth_call` (no tx, no state
|
|
95
|
+
* change, no gas spent), so it's safe to run on every staging path as a guard.
|
|
96
|
+
*/
|
|
97
|
+
export declare function storeSupportsWriteContent(publicClient: PublicClient, store: Address): Promise<boolean>;
|
|
98
|
+
/** Write one chunk as an SSTORE2 data contract; returns its address (from `ChunkWritten`). */
|
|
99
|
+
export declare function writeChunk(send: SendStagingTx, args: {
|
|
100
|
+
store: Address;
|
|
101
|
+
data: Uint8Array;
|
|
102
|
+
}): Promise<{
|
|
103
|
+
pointer: Address;
|
|
104
|
+
txHash: Hex;
|
|
105
|
+
}>;
|
|
106
|
+
/**
|
|
107
|
+
* Write a whole piece of content — every chunk plus the manifest — in ONE transaction
|
|
108
|
+
* via `AbxChunkStore.writeContent`. The atomic, prediction-free path for content that
|
|
109
|
+
* fits a single tx's gas (see {@link planContentTxs}); returns the manifest address (the
|
|
110
|
+
* `reader` pointer) from the `ManifestWritten` event.
|
|
111
|
+
*/
|
|
112
|
+
export declare function writeContent(send: SendStagingTx, args: {
|
|
113
|
+
store: Address;
|
|
114
|
+
chunks: ReadonlyArray<PlannedChunk>;
|
|
115
|
+
}): Promise<{
|
|
116
|
+
manifest: Address;
|
|
117
|
+
txHash: Hex;
|
|
118
|
+
}>;
|
|
119
|
+
/**
|
|
120
|
+
* Write a batch of chunks in ONE transaction via the store's `multicall`, returning their
|
|
121
|
+
* pointer addresses **in order** (parsed from the `ChunkWritten` events). Used by the
|
|
122
|
+
* split path for content too large for a single tx: the caller writes one or more such
|
|
123
|
+
* batches, concatenates the returned pointers, then calls {@link writeManifest}. Pairs
|
|
124
|
+
* each pointer with its planned `compressed` flag for manifest assembly.
|
|
125
|
+
*/
|
|
126
|
+
export declare function writeChunkBatch(send: SendStagingTx, args: {
|
|
127
|
+
store: Address;
|
|
128
|
+
chunks: ReadonlyArray<PlannedChunk>;
|
|
129
|
+
}): Promise<{
|
|
130
|
+
written: Array<{
|
|
131
|
+
pointer: Address;
|
|
132
|
+
compressed: boolean;
|
|
133
|
+
}>;
|
|
134
|
+
txHash: Hex;
|
|
135
|
+
}>;
|
|
136
|
+
/**
|
|
137
|
+
* Stage a whole piece of content on the chunk store and return its manifest — the
|
|
138
|
+
* `pointer` half of a `reader` field's value. Plans the chunks, then executes the
|
|
139
|
+
* minimal transaction set ({@link planContentTxs}): one atomic {@link writeContent} when
|
|
140
|
+
* it fits, else gas-bounded {@link writeChunkBatch} multicalls plus a final
|
|
141
|
+
* {@link writeManifest}. Returns every tx hash so a UX can report the count honestly.
|
|
142
|
+
*
|
|
143
|
+
* This is the same path whether the manifest is later baked into a deploy's `InitParams`
|
|
144
|
+
* or set on a live token — staging always precedes the contract that references it.
|
|
145
|
+
*/
|
|
146
|
+
export declare function stageContent(send: SendStagingTx, args: {
|
|
147
|
+
store: Address;
|
|
148
|
+
content: Uint8Array;
|
|
149
|
+
fastlz?: boolean;
|
|
150
|
+
chunkSize?: number;
|
|
151
|
+
gasBudget?: number;
|
|
152
|
+
}): Promise<{
|
|
153
|
+
manifest: Address;
|
|
154
|
+
txHashes: Hex[];
|
|
155
|
+
chunkCount: number;
|
|
156
|
+
}>;
|
|
157
|
+
/** Write the manifest (ordered chunk list); returns its address (the `reader` pointer). */
|
|
158
|
+
export declare function writeManifest(send: SendStagingTx, args: {
|
|
159
|
+
store: Address;
|
|
160
|
+
chunks: ReadonlyArray<{
|
|
161
|
+
pointer: Address;
|
|
162
|
+
compressed: boolean;
|
|
163
|
+
}>;
|
|
164
|
+
}): Promise<{
|
|
165
|
+
manifest: Address;
|
|
166
|
+
txHash: Hex;
|
|
167
|
+
}>;
|
|
168
|
+
//# sourceMappingURL=chunks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunks.d.ts","sourceRoot":"","sources":["../src/chunks.ts"],"names":[],"mappings":"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"}
|
package/dist/chunks.js
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { encodeFunctionData, parseEventLogs, } from 'viem';
|
|
2
|
+
import { abxChunkStoreAbi, abxChunkStoreBytecode } from './abi/index.js';
|
|
3
|
+
import { flzCompress } from './fastlz.js';
|
|
4
|
+
import { ABX_SALT, CREATE2_PROXY, create2Calldata, predictCreate2Address } from './create2.js';
|
|
5
|
+
/**
|
|
6
|
+
* Multi-chunk on-chain content — the off-chain side of {@link AbxChunkStore}.
|
|
7
|
+
*
|
|
8
|
+
* Large content (a 30 kB image, a long description) is split into SSTORE2-sized chunks,
|
|
9
|
+
* optionally FastLZ-compressed **per chunk** off-chain (the chunk store decompresses on
|
|
10
|
+
* read, so it stays on-chain-renderable), written as immutable data contracts, and tied
|
|
11
|
+
* together by a manifest. The field then carries the `reader` representation with
|
|
12
|
+
* `value = abi.encode(chunkStore, manifest)`. gzip is *not* handled here — it's an
|
|
13
|
+
* off-chain decode signaled by the `-gzip` representation, applied to the assembled bytes.
|
|
14
|
+
*/
|
|
15
|
+
/** SSTORE2 data-contract code limit is 24576 bytes (EIP-170) minus the STOP byte; chunk
|
|
16
|
+
* conservatively so even an incompressible FastLZ chunk (slight expansion) still fits. */
|
|
17
|
+
export const DEFAULT_CHUNK_SIZE = 22_000;
|
|
18
|
+
/**
|
|
19
|
+
* Split content into chunks, FastLZ-compressing each when `fastlz` is set (per-chunk — the
|
|
20
|
+
* convention the store + reader expect). Pure: no chain, no I/O. A chunk is only stored
|
|
21
|
+
* compressed when that actually shrinks it (so the reader never wastes a decompress).
|
|
22
|
+
*/
|
|
23
|
+
export function planChunks(content, opts = {}) {
|
|
24
|
+
const size = opts.chunkSize ?? DEFAULT_CHUNK_SIZE;
|
|
25
|
+
const chunks = [];
|
|
26
|
+
for (let i = 0; i < content.length; i += size) {
|
|
27
|
+
const raw = content.subarray(i, i + size);
|
|
28
|
+
if (opts.fastlz) {
|
|
29
|
+
const packed = flzCompress(raw);
|
|
30
|
+
if (packed.length < raw.length) {
|
|
31
|
+
chunks.push({ data: packed, compressed: true });
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
chunks.push({ data: raw, compressed: false });
|
|
36
|
+
}
|
|
37
|
+
return chunks;
|
|
38
|
+
}
|
|
39
|
+
const toHex = (b) => `0x${Buffer.from(b).toString('hex')}`;
|
|
40
|
+
/**
|
|
41
|
+
* A per-transaction gas ceiling for packing chunk writes. Comfortably under mainnet's
|
|
42
|
+
* ~30M block limit so a batch always fits with room for the base + calldata cost; the
|
|
43
|
+
* planner splits content across multiple transactions to stay beneath it.
|
|
44
|
+
*/
|
|
45
|
+
export const DEFAULT_TX_GAS_BUDGET = 8_000_000;
|
|
46
|
+
/**
|
|
47
|
+
* Rough gas for writing one chunk as an SSTORE2 data contract: a fixed CREATE + base
|
|
48
|
+
* overhead plus the code-deposit cost (~200 gas/byte) and calldata. Deliberately an
|
|
49
|
+
* over-estimate so packed batches land safely inside {@link DEFAULT_TX_GAS_BUDGET};
|
|
50
|
+
* the wallet still does the real `eth_estimateGas` before sending.
|
|
51
|
+
*/
|
|
52
|
+
export function estimateChunkGas(chunk) {
|
|
53
|
+
return 40_000 + chunk.data.length * 240;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Decide the transaction shape for a piece of content. When the whole thing fits one
|
|
57
|
+
* tx's gas budget it's a single atomic {@link writeContent} (no address prediction, no
|
|
58
|
+
* follow-up). Otherwise it's split into gas-bounded batches of {@link writeChunk} calls
|
|
59
|
+
* (each batch one `multicall`), followed by a single {@link writeManifest} — so
|
|
60
|
+
* `txCount` is `batches.length + 1`. Pure: no chain, no I/O.
|
|
61
|
+
*/
|
|
62
|
+
export function planContentTxs(chunks, opts = {}) {
|
|
63
|
+
const budget = opts.gasBudget ?? DEFAULT_TX_GAS_BUDGET;
|
|
64
|
+
const total = chunks.reduce((g, c) => g + estimateChunkGas(c), 0);
|
|
65
|
+
// writeContent also pays for the manifest write; approximate it as one more chunk.
|
|
66
|
+
if (total + 60_000 <= budget)
|
|
67
|
+
return { mode: 'single', chunks, txCount: 1 };
|
|
68
|
+
const batches = [];
|
|
69
|
+
let cur = [];
|
|
70
|
+
let curGas = 0;
|
|
71
|
+
for (const c of chunks) {
|
|
72
|
+
const g = estimateChunkGas(c);
|
|
73
|
+
if (cur.length > 0 && curGas + g > budget) {
|
|
74
|
+
batches.push(cur);
|
|
75
|
+
cur = [];
|
|
76
|
+
curGas = 0;
|
|
77
|
+
}
|
|
78
|
+
cur.push(c);
|
|
79
|
+
curGas += g;
|
|
80
|
+
}
|
|
81
|
+
if (cur.length > 0)
|
|
82
|
+
batches.push(cur);
|
|
83
|
+
return { mode: 'split', batches, txCount: batches.length + 1 };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Deploy `AbxChunkStore` — the shared, stateless multi-chunk store + reader. Deploy once
|
|
87
|
+
* per chain (like the renderer); every chunked field references it as its `reader`.
|
|
88
|
+
*/
|
|
89
|
+
export async function deployChunkStore(send) {
|
|
90
|
+
// CREATE2 via the keyless proxy + canonical salt → the SAME address on every chain (matches the
|
|
91
|
+
// forge `DeployChunkStore` script and the manifest). The address is deterministic, so we compute
|
|
92
|
+
// it rather than read `receipt.contractAddress` (which is null — the tx targets the proxy, not a
|
|
93
|
+
// contract creation). Deploy only when the store isn't already there (the caller checks first).
|
|
94
|
+
const chunkStore = predictCreate2Address(ABX_SALT.chunkStore, abxChunkStoreBytecode);
|
|
95
|
+
const receipt = await send({
|
|
96
|
+
to: CREATE2_PROXY,
|
|
97
|
+
data: create2Calldata(ABX_SALT.chunkStore, abxChunkStoreBytecode),
|
|
98
|
+
summary: 'Deploy the shared on-chain chunk store (AbxChunkStore) — CREATE2, deterministic address',
|
|
99
|
+
fields: { contract: 'AbxChunkStore', address: chunkStore, note: 'one-time, ownerless, shared by every chunked field' },
|
|
100
|
+
});
|
|
101
|
+
return { chunkStore, txHash: receipt.transactionHash, blockNumber: receipt.blockNumber };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Does `store` expose the current `writeContent(bytes[],bool[])` ABI? A chunk store deployed
|
|
105
|
+
* before `writeContent` existed (an older `AbxChunkStore`) still *has code*, so a bare
|
|
106
|
+
* `getCode` check passes — but the call reverts, silently breaking the `--onchain-image`
|
|
107
|
+
* path. We probe with an empty `writeContent([],[])`: the current store returns a manifest
|
|
108
|
+
* address, a stale/incompatible one reverts. This is a pure `eth_call` (no tx, no state
|
|
109
|
+
* change, no gas spent), so it's safe to run on every staging path as a guard.
|
|
110
|
+
*/
|
|
111
|
+
export async function storeSupportsWriteContent(publicClient, store) {
|
|
112
|
+
try {
|
|
113
|
+
await publicClient.call({
|
|
114
|
+
to: store,
|
|
115
|
+
data: encodeFunctionData({ abi: abxChunkStoreAbi, functionName: 'writeContent', args: [[], []] }),
|
|
116
|
+
});
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** Write one chunk as an SSTORE2 data contract; returns its address (from `ChunkWritten`). */
|
|
124
|
+
export async function writeChunk(send, args) {
|
|
125
|
+
const receipt = await send({
|
|
126
|
+
to: args.store,
|
|
127
|
+
data: encodeFunctionData({ abi: abxChunkStoreAbi, functionName: 'writeChunk', args: [toHex(args.data)] }),
|
|
128
|
+
summary: 'Stage one on-chain content chunk',
|
|
129
|
+
fields: { store: args.store, bytes: String(args.data.length) },
|
|
130
|
+
});
|
|
131
|
+
const ev = parseEventLogs({ abi: abxChunkStoreAbi, eventName: 'ChunkWritten', logs: receipt.logs });
|
|
132
|
+
const pointer = ev[0]?.args.pointer;
|
|
133
|
+
if (!pointer)
|
|
134
|
+
throw new Error('writeChunk emitted no ChunkWritten event');
|
|
135
|
+
return { pointer, txHash: receipt.transactionHash };
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Write a whole piece of content — every chunk plus the manifest — in ONE transaction
|
|
139
|
+
* via `AbxChunkStore.writeContent`. The atomic, prediction-free path for content that
|
|
140
|
+
* fits a single tx's gas (see {@link planContentTxs}); returns the manifest address (the
|
|
141
|
+
* `reader` pointer) from the `ManifestWritten` event.
|
|
142
|
+
*/
|
|
143
|
+
export async function writeContent(send, args) {
|
|
144
|
+
const receipt = await send({
|
|
145
|
+
to: args.store,
|
|
146
|
+
data: encodeFunctionData({
|
|
147
|
+
abi: abxChunkStoreAbi,
|
|
148
|
+
functionName: 'writeContent',
|
|
149
|
+
args: [args.chunks.map((c) => toHex(c.data)), args.chunks.map((c) => c.compressed)],
|
|
150
|
+
}),
|
|
151
|
+
summary: `Stage on-chain content (${args.chunks.length} chunk${args.chunks.length === 1 ? '' : 's'}, atomic)`,
|
|
152
|
+
fields: { store: args.store, chunks: String(args.chunks.length) },
|
|
153
|
+
});
|
|
154
|
+
const ev = parseEventLogs({ abi: abxChunkStoreAbi, eventName: 'ManifestWritten', logs: receipt.logs });
|
|
155
|
+
const manifest = ev[0]?.args.manifest;
|
|
156
|
+
if (!manifest)
|
|
157
|
+
throw new Error('writeContent emitted no ManifestWritten event');
|
|
158
|
+
return { manifest, txHash: receipt.transactionHash };
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Write a batch of chunks in ONE transaction via the store's `multicall`, returning their
|
|
162
|
+
* pointer addresses **in order** (parsed from the `ChunkWritten` events). Used by the
|
|
163
|
+
* split path for content too large for a single tx: the caller writes one or more such
|
|
164
|
+
* batches, concatenates the returned pointers, then calls {@link writeManifest}. Pairs
|
|
165
|
+
* each pointer with its planned `compressed` flag for manifest assembly.
|
|
166
|
+
*/
|
|
167
|
+
export async function writeChunkBatch(send, args) {
|
|
168
|
+
const calls = args.chunks.map((c) => encodeFunctionData({ abi: abxChunkStoreAbi, functionName: 'writeChunk', args: [toHex(c.data)] }));
|
|
169
|
+
const receipt = await send({
|
|
170
|
+
to: args.store,
|
|
171
|
+
data: encodeFunctionData({ abi: abxChunkStoreAbi, functionName: 'multicall', args: [calls] }),
|
|
172
|
+
summary: `Stage ${args.chunks.length} on-chain content chunk${args.chunks.length === 1 ? '' : 's'} (batch)`,
|
|
173
|
+
fields: { store: args.store, chunks: String(args.chunks.length) },
|
|
174
|
+
});
|
|
175
|
+
const txHash = receipt.transactionHash;
|
|
176
|
+
const evs = parseEventLogs({ abi: abxChunkStoreAbi, eventName: 'ChunkWritten', logs: receipt.logs });
|
|
177
|
+
if (evs.length !== args.chunks.length) {
|
|
178
|
+
throw new Error(`writeChunkBatch: expected ${args.chunks.length} ChunkWritten events, got ${evs.length}`);
|
|
179
|
+
}
|
|
180
|
+
const written = evs.map((e, i) => ({
|
|
181
|
+
pointer: e.args.pointer,
|
|
182
|
+
compressed: args.chunks[i].compressed,
|
|
183
|
+
}));
|
|
184
|
+
return { written, txHash };
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Stage a whole piece of content on the chunk store and return its manifest — the
|
|
188
|
+
* `pointer` half of a `reader` field's value. Plans the chunks, then executes the
|
|
189
|
+
* minimal transaction set ({@link planContentTxs}): one atomic {@link writeContent} when
|
|
190
|
+
* it fits, else gas-bounded {@link writeChunkBatch} multicalls plus a final
|
|
191
|
+
* {@link writeManifest}. Returns every tx hash so a UX can report the count honestly.
|
|
192
|
+
*
|
|
193
|
+
* This is the same path whether the manifest is later baked into a deploy's `InitParams`
|
|
194
|
+
* or set on a live token — staging always precedes the contract that references it.
|
|
195
|
+
*/
|
|
196
|
+
export async function stageContent(send, args) {
|
|
197
|
+
const chunks = planChunks(args.content, { fastlz: args.fastlz, chunkSize: args.chunkSize });
|
|
198
|
+
const plan = planContentTxs(chunks, { gasBudget: args.gasBudget });
|
|
199
|
+
const txHashes = [];
|
|
200
|
+
if (plan.mode === 'single') {
|
|
201
|
+
const { manifest, txHash } = await writeContent(send, { store: args.store, chunks });
|
|
202
|
+
return { manifest, txHashes: [txHash], chunkCount: chunks.length };
|
|
203
|
+
}
|
|
204
|
+
const written = [];
|
|
205
|
+
for (const batch of plan.batches) {
|
|
206
|
+
const res = await writeChunkBatch(send, { store: args.store, chunks: batch });
|
|
207
|
+
written.push(...res.written);
|
|
208
|
+
txHashes.push(res.txHash);
|
|
209
|
+
}
|
|
210
|
+
const { manifest, txHash } = await writeManifest(send, { store: args.store, chunks: written });
|
|
211
|
+
txHashes.push(txHash);
|
|
212
|
+
return { manifest, txHashes, chunkCount: chunks.length };
|
|
213
|
+
}
|
|
214
|
+
/** Write the manifest (ordered chunk list); returns its address (the `reader` pointer). */
|
|
215
|
+
export async function writeManifest(send, args) {
|
|
216
|
+
const receipt = await send({
|
|
217
|
+
to: args.store,
|
|
218
|
+
data: encodeFunctionData({
|
|
219
|
+
abi: abxChunkStoreAbi,
|
|
220
|
+
functionName: 'writeManifest',
|
|
221
|
+
args: [args.chunks.map((c) => ({ pointer: c.pointer, compressed: c.compressed }))],
|
|
222
|
+
}),
|
|
223
|
+
summary: `Write the on-chain content manifest (${args.chunks.length} chunk${args.chunks.length === 1 ? '' : 's'})`,
|
|
224
|
+
fields: { store: args.store, chunks: String(args.chunks.length) },
|
|
225
|
+
});
|
|
226
|
+
const ev = parseEventLogs({ abi: abxChunkStoreAbi, eventName: 'ManifestWritten', logs: receipt.logs });
|
|
227
|
+
const manifest = ev[0]?.args.manifest;
|
|
228
|
+
if (!manifest)
|
|
229
|
+
throw new Error('writeManifest emitted no ManifestWritten event');
|
|
230
|
+
return { manifest, txHash: receipt.transactionHash };
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=chunks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunks.js","sourceRoot":"","sources":["../src/chunks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type PublicClient, type WalletClient, type Account } from 'viem';
|
|
2
|
+
export interface ClientOptions {
|
|
3
|
+
chainKey?: string;
|
|
4
|
+
rpcUrl?: string;
|
|
5
|
+
}
|
|
6
|
+
/** A read-only client — all the indexer and token API ever need. */
|
|
7
|
+
export declare function makePublicClient(opts?: ClientOptions): PublicClient;
|
|
8
|
+
/**
|
|
9
|
+
* Verify the configured RPC actually IS the chain we think it is, before any write.
|
|
10
|
+
* The env var names a network ("sepolia") but the URL behind it could point anywhere;
|
|
11
|
+
* this calls `eth_chainId` and hard-fails on a mismatch so an irreversible tx can't go
|
|
12
|
+
* to the wrong chain. Memoized per chainKey — one round-trip per process, so callers can
|
|
13
|
+
* invoke it liberally at write preflights. Reads never call it (they stay zero-overhead).
|
|
14
|
+
*
|
|
15
|
+
* `allowUnreachable` (used by `--dry-run` preflights): a *wrong-network* RPC still hard-fails
|
|
16
|
+
* with the clear mismatch message — a dry run makes RPC reads (predict address, resolve the
|
|
17
|
+
* factory/renderer) that otherwise fail deep inside viem as an opaque "returned no data" — but
|
|
18
|
+
* an *unreachable* RPC is tolerated (returns silently), so a genuinely offline `--dry-run` can
|
|
19
|
+
* still preview what it can. Only a reachable-but-wrong endpoint is a preview-blocking error.
|
|
20
|
+
*/
|
|
21
|
+
export declare function assertChainId(chainKey?: string, opts?: {
|
|
22
|
+
allowUnreachable?: boolean;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* A signing client, backed by a private key from the environment. The SDK never
|
|
26
|
+
* takes custody of keys beyond reading them from the operator's own env — there
|
|
27
|
+
* is no key storage, no prompt, no remote signer here.
|
|
28
|
+
*
|
|
29
|
+
* Key precedence: `ABX_DEPLOYER_PK` → `SEPOLIA_FUNDED_PK` → `SEPOLIA_WALLET_PK`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function makeWalletClient(opts?: ClientOptions): {
|
|
32
|
+
wallet: WalletClient;
|
|
33
|
+
account: Account;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* The env signing key (0x-normalized), same precedence as {@link makeWalletClient}
|
|
37
|
+
* (`ABX_DEPLOYER_PK` → `SEPOLIA_FUNDED_PK` → `SEPOLIA_WALLET_PK`), or `undefined` if none is set.
|
|
38
|
+
* For reusing the hot key as a *storage* signing identity (an Ethereum Turbo identity) without
|
|
39
|
+
* constructing a wallet client. Never throws.
|
|
40
|
+
*/
|
|
41
|
+
export declare function envSigningKey(): `0x${string}` | undefined;
|
|
42
|
+
//# sourceMappingURL=clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../src/clients.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,YAAY,EAEjB,KAAK,YAAY,EACjB,KAAK,OAAO,EACb,MAAM,MAAM,CAAC;AAKd,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAeD,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,aAAkB,GAAG,YAAY,CAEvE;AAID;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,QAAQ,GAAE,MAA0B,EACpC,IAAI,GAAE;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAM,GACtC,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,aAAkB,GAAG;IAC1D,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB,CAYA;AAOD;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,KAAK,MAAM,EAAE,GAAG,SAAS,CAIzD"}
|