@artblocks/abx-sdk 0.1.0-alpha.2 → 0.1.0-alpha.21
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/CHANGELOG.md +2203 -0
- package/README.md +131 -0
- package/dist/abi/generated.d.ts +8502 -129
- package/dist/abi/generated.d.ts.map +1 -1
- package/dist/abi/generated.js +40 -22
- package/dist/abi/generated.js.map +1 -1
- package/dist/abi/index.d.ts +2645 -168
- package/dist/abi/index.d.ts.map +1 -1
- package/dist/abi/index.js +34 -7
- package/dist/abi/index.js.map +1 -1
- package/dist/anchors.d.ts +319 -0
- package/dist/anchors.d.ts.map +1 -0
- package/dist/anchors.js +703 -0
- package/dist/anchors.js.map +1 -0
- package/dist/chains.d.ts +15 -9
- package/dist/chains.d.ts.map +1 -1
- package/dist/chains.js +19 -15
- package/dist/chains.js.map +1 -1
- package/dist/chunks.d.ts +53 -23
- package/dist/chunks.d.ts.map +1 -1
- package/dist/chunks.js +68 -6
- package/dist/chunks.js.map +1 -1
- package/dist/clients.d.ts +23 -11
- package/dist/clients.d.ts.map +1 -1
- package/dist/clients.js +17 -18
- package/dist/clients.js.map +1 -1
- package/dist/create2.d.ts +85 -1
- package/dist/create2.d.ts.map +1 -1
- package/dist/create2.js +159 -2
- package/dist/create2.js.map +1 -1
- package/dist/creator-token.d.ts +132 -0
- package/dist/creator-token.d.ts.map +1 -0
- package/dist/creator-token.js +183 -0
- package/dist/creator-token.js.map +1 -0
- package/dist/deploy.d.ts +234 -14
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +289 -111
- package/dist/deploy.js.map +1 -1
- package/dist/deployments.d.ts +63 -0
- package/dist/deployments.d.ts.map +1 -1
- package/dist/deployments.js +202 -28
- package/dist/deployments.js.map +1 -1
- package/dist/deps.d.ts +122 -5
- package/dist/deps.d.ts.map +1 -1
- package/dist/deps.js +248 -6
- package/dist/deps.js.map +1 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +8 -0
- package/dist/env.js.map +1 -1
- package/dist/errors.d.ts +94 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +126 -0
- package/dist/errors.js.map +1 -0
- package/dist/execute.d.ts +115 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +142 -0
- package/dist/execute.js.map +1 -0
- package/dist/gateways.d.ts +79 -0
- package/dist/gateways.d.ts.map +1 -0
- package/dist/gateways.js +156 -0
- package/dist/gateways.js.map +1 -0
- package/dist/generator-document.d.ts +58 -0
- package/dist/generator-document.d.ts.map +1 -0
- package/dist/generator-document.js +124 -0
- package/dist/generator-document.js.map +1 -0
- package/dist/generator.d.ts +43 -1
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +29 -0
- package/dist/generator.js.map +1 -1
- package/dist/index.d.ts +18 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -3
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +48 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +295 -0
- package/dist/inspect.js.map +1 -0
- package/dist/migrate.d.ts +41 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +142 -0
- package/dist/migrate.js.map +1 -0
- package/dist/mime.d.ts +11 -0
- package/dist/mime.d.ts.map +1 -0
- package/dist/mime.js +40 -0
- package/dist/mime.js.map +1 -0
- package/dist/node.d.ts +10 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +24 -0
- package/dist/node.js.map +1 -0
- package/dist/onchain-uri.d.ts +110 -0
- package/dist/onchain-uri.d.ts.map +1 -0
- package/dist/onchain-uri.js +277 -0
- package/dist/onchain-uri.js.map +1 -0
- package/dist/ops.d.ts +507 -14
- package/dist/ops.d.ts.map +1 -1
- package/dist/ops.js +848 -32
- package/dist/ops.js.map +1 -1
- package/dist/policy.d.ts +58 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +36 -0
- package/dist/policy.js.map +1 -0
- package/dist/probe.d.ts +29 -0
- package/dist/probe.d.ts.map +1 -1
- package/dist/probe.js +104 -9
- package/dist/probe.js.map +1 -1
- package/dist/reconstruct.d.ts +94 -2
- package/dist/reconstruct.d.ts.map +1 -1
- package/dist/reconstruct.js +432 -97
- package/dist/reconstruct.js.map +1 -1
- package/dist/resume.d.ts +96 -0
- package/dist/resume.d.ts.map +1 -0
- package/dist/resume.js +95 -0
- package/dist/resume.js.map +1 -0
- package/dist/script-chunks.d.ts +24 -0
- package/dist/script-chunks.d.ts.map +1 -0
- package/dist/script-chunks.js +63 -0
- package/dist/script-chunks.js.map +1 -0
- package/dist/service.d.ts +206 -9
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +228 -18
- package/dist/service.js.map +1 -1
- package/dist/spine.d.ts +47 -4
- package/dist/spine.d.ts.map +1 -1
- package/dist/spine.js +0 -0
- package/dist/spine.js.map +1 -1
- package/dist/staging.d.ts +124 -0
- package/dist/staging.d.ts.map +1 -0
- package/dist/staging.js +134 -0
- package/dist/staging.js.map +1 -0
- package/dist/tokendata.d.ts +62 -2
- package/dist/tokendata.d.ts.map +1 -1
- package/dist/tokendata.js +79 -17
- package/dist/tokendata.js.map +1 -1
- package/dist/tokens.d.ts +120 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +317 -0
- package/dist/tokens.js.map +1 -0
- package/dist/types.d.ts +108 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/util.d.ts +74 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +106 -0
- package/dist/util.js.map +1 -0
- package/package.json +11 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staging.d.ts","sourceRoot":"","sources":["../src/staging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAE,GAAG,EAAE,YAAY,EAAC,MAAM,MAAM,CAAC;AACrD,OAAO,EAA6D,KAAK,eAAe,EAAE,KAAK,aAAa,EAAC,MAAM,aAAa,CAAC;AAGjI,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,cAAc,CAAC;AAEzC;;;;;;;;;;;;GAYG;AAEH;;;2CAG2C;AAC3C,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AASlD,eAAO,MAAM,wBAAwB,QAAY,CAAC;AAClD,eAAO,MAAM,0BAA0B,QAAa,CAAC;AAErD;sFACsF;AACtF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEjE;AAwCD;mGACmG;AACnG,eAAO,MAAM,wBAAwB,SAAU,CAAC;AAChD;0FAC0F;AAC1F,eAAO,MAAM,yBAAyB,SAAU,CAAC;AACjD,6FAA6F;AAC7F,eAAO,MAAM,uBAAuB,QAAY,CAAC;AACjD;;gBAEgB;AAChB,eAAO,MAAM,yBAAyB,QAAa,CAAC;AACpD;uEACuE;AACvE,eAAO,MAAM,2BAA2B,QAAa,CAAC;AAEtD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED,yGAAyG;AACzG,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE1D;;+CAE+C;AAC/C,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAI5E;AAED;4EAC4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,aAAa,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,GAAG,WAAW,CAOtF;AAED;;oFAEoF;AACpF,MAAM,MAAM,YAAY,GACpB;IAAC,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAC,GAC7C;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,WAAW,CAAA;CAAC,GAC1E;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,GAAG,EAAE,CAAA;CAAC,CAAC;AAExE,MAAM,WAAW,qBAAqB;IACpC;uDACmD;IACnD,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,yFAAyF;IACzF,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB;oCACgC;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,CAAC;CACrC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAC,CAAC,CAalH"}
|
package/dist/staging.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { ensureChunkStore, planChunks, planContentTxs, stageContent } from './chunks.js';
|
|
2
|
+
import { encodeReader } from './token.js';
|
|
3
|
+
import { METADATA_REPRESENTATION as R } from './spine.js';
|
|
4
|
+
// ── Two independent costs, and the one that binds is the READ ────────────────
|
|
5
|
+
//
|
|
6
|
+
// WRITE cost is ~200 gas/byte (SSTORE2 code deposit) + per-chunk tx overhead, paid once by the
|
|
7
|
+
// creator. Past these soft limits, off-chain (Arweave pay-once, or a hosted resolver + IPFS) is FAR
|
|
8
|
+
// cheaper — on-chain's remaining edge is self-resolution, not cost. Per-file limit ≈ one 22 KB
|
|
9
|
+
// storage chunk; project limit caps the whole collection's write gas. Neither says anything about
|
|
10
|
+
// whether the result can be READ.
|
|
11
|
+
export const ONCHAIN_IMAGE_SOFT_LIMIT = 24 * 1024; // per file
|
|
12
|
+
export const ONCHAIN_PROJECT_SOFT_LIMIT = 256 * 1024; // whole collection, WRITE cost only
|
|
13
|
+
/** Whether `bytesLen` is past the point where on-chain storage stops being the cost-sane choice to
|
|
14
|
+
* WRITE. Says nothing about readability — that's {@link classifyOnchainReadSize}. */
|
|
15
|
+
export function exceedsOnchainSoftLimit(bytesLen) {
|
|
16
|
+
return bytesLen > ONCHAIN_IMAGE_SOFT_LIMIT;
|
|
17
|
+
}
|
|
18
|
+
// READ cost is the constraint nobody sees coming, and it is the one that decides whether a
|
|
19
|
+
// marketplace, an indexer, or another contract can see the token at all. The renderer assembles the
|
|
20
|
+
// whole document on every `tokenURI` call, and that cost is **superlinear**: EVM memory expansion
|
|
21
|
+
// carries a quadratic term, and the chunk store's `read()` concatenates chunk by chunk. So there is
|
|
22
|
+
// no honest flat "gas per KB" — the rate itself climbs with size.
|
|
23
|
+
//
|
|
24
|
+
// Measured (`forge`, `OneOfOneImage` + `AbxMetadataRenderer`, callee execution gas for one
|
|
25
|
+
// `tokenURI` call — no caller-side returndata copy, which a node serving `eth_call` doesn't pay
|
|
26
|
+
// either; `reader` = the representation `--onchain-image` produces, 22,000-byte chunks):
|
|
27
|
+
//
|
|
28
|
+
// content tokenURI gas per KB content tokenURI gas per KB
|
|
29
|
+
// 3 KB 1,123,327 374,000 100 KB 40,254,159 403,000
|
|
30
|
+
// 10 KB 3,588,993 359,000 128 KB 53,559,735 418,000
|
|
31
|
+
// 23 KB 8,346,220 363,000 187 KB 86,021,071 460,000
|
|
32
|
+
// 40 KB 14,740,366 369,000 256 KB 131,269,134 513,000
|
|
33
|
+
// 50 KB 18,759,333 375,000
|
|
34
|
+
// 75 KB 29,137,215 388,000
|
|
35
|
+
// 90 KB 35,868,124 399,000
|
|
36
|
+
//
|
|
37
|
+
// So: **~360,000–405,000 gas per KB across the 10–100 KB range that matters, climbing past that**
|
|
38
|
+
// (~460,000/KB at 187 KB, ~510,000/KB at 256 KB). The 3 KB row is higher per KB because the JSON
|
|
39
|
+
// wrapper is a fixed cost the content hasn't yet dwarfed.
|
|
40
|
+
//
|
|
41
|
+
// `inline` and `reader` agree within ~1% up to 75 KB — the cost is the renderer's own string
|
|
42
|
+
// building, not the storage mechanism, which is why `--compress fastlz` makes a field cheaper to
|
|
43
|
+
// WRITE and not one gas cheaper to read. They diverge above that (reader 1.8% dearer at 90 KB, 2.4%
|
|
44
|
+
// at 128 KB, 5.5% at 187 KB, 9.6% at 256 KB) because the store's read loop is quadratic in chunk
|
|
45
|
+
// count.
|
|
46
|
+
//
|
|
47
|
+
// For orientation (these vary by provider and change over time): geth's `--rpc.gascap` defaults to
|
|
48
|
+
// 50,000,000, hosted providers commonly cap lower, and L1 block limits currently sit in the
|
|
49
|
+
// mid-30-millions. So ~40 KB is where a read stops being routine (~15M gas), ~90 KB is where no
|
|
50
|
+
// contract can read it inside a transaction, and the 50M default is not actually exhausted until
|
|
51
|
+
// **~120 KB**. The refusal below sits at 100 KB deliberately, short of that measured wall: it is a
|
|
52
|
+
// margin for a lower-capped hosted provider, not the wall itself. There is deliberately NO on-chain
|
|
53
|
+
// guard for any of this: reads happen off-chain, a too-large read is an RPC-capability problem
|
|
54
|
+
// rather than a reason to brick a contract, and the honest place to intervene is the toolkit, before
|
|
55
|
+
// the bytes are written.
|
|
56
|
+
/** Measured `tokenURI` gas per KB at the BOTTOM of the readable range (10 KB). The rate is not
|
|
57
|
+
* flat — see the note above, and use {@link tokenUriGasEstimate} for a figure at a given size. */
|
|
58
|
+
export const TOKEN_URI_GAS_PER_KB_LOW = 360_000;
|
|
59
|
+
/** Measured `tokenURI` gas per KB at the TOP of the readable range (100 KB). Past that the rate
|
|
60
|
+
* keeps climbing (~460,000/KB at 187 KB), so this is a range endpoint, not a ceiling. */
|
|
61
|
+
export const TOKEN_URI_GAS_PER_KB_HIGH = 405_000;
|
|
62
|
+
/** From here up, reading the token needs a deliberately high-gas RPC (~15M gas at 40 KB). */
|
|
63
|
+
export const ONCHAIN_READ_WARN_BYTES = 40 * 1024;
|
|
64
|
+
/** Past here (~40M gas at 100 KB and climbing superlinearly) the read is beyond many hosted
|
|
65
|
+
* providers' `eth_call` caps — a deliberate margin below the ~120 KB where geth's own 50M default
|
|
66
|
+
* runs out. */
|
|
67
|
+
export const ONCHAIN_READ_REFUSE_BYTES = 100 * 1024;
|
|
68
|
+
/** Where geth's default `--rpc.gascap` (50,000,000) is actually exhausted, measured. Documented so
|
|
69
|
+
* the refusal above can be described honestly as the margin it is. */
|
|
70
|
+
export const ONCHAIN_READ_GETH_CAP_BYTES = 120 * 1024;
|
|
71
|
+
/**
|
|
72
|
+
* Rough `tokenURI` gas for `bytesLen` of on-chain content — orientation, not a quote.
|
|
73
|
+
*
|
|
74
|
+
* Fitted to the measurements above as `350,000·KB + 650·KB²`: within ~3% of measured from 10 KB to
|
|
75
|
+
* 256 KB, and slightly high rather than low, which is the right direction for a number that gates a
|
|
76
|
+
* warning. A flat per-KB rate was wrong at both ends — it overstated a 10 KB read by ~30% and
|
|
77
|
+
* understated a 256 KB one by ~10%.
|
|
78
|
+
*/
|
|
79
|
+
export function tokenUriGasEstimate(bytesLen) {
|
|
80
|
+
const kb = bytesLen / 1024;
|
|
81
|
+
return Math.round(kb * 350_000 + kb * kb * 650);
|
|
82
|
+
}
|
|
83
|
+
/** Classify `bytesLen` of on-chain content by whether normal RPC tooling can READ the token that
|
|
84
|
+
* carries it — the pure predicate behind the CLI's warn/refuse gate (kept here so the SDK and the
|
|
85
|
+
* CLI can't disagree about the threshold). */
|
|
86
|
+
export function classifyOnchainReadSize(bytesLen) {
|
|
87
|
+
if (bytesLen > ONCHAIN_READ_REFUSE_BYTES)
|
|
88
|
+
return 'refuse';
|
|
89
|
+
if (bytesLen >= ONCHAIN_READ_WARN_BYTES)
|
|
90
|
+
return 'warn';
|
|
91
|
+
return 'ok';
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Pure staging plan for a piece of content — chunk count + transaction shape — with NO chain
|
|
95
|
+
* writes, no signer, no `ensureChunkStore`. Shared by {@link stageFieldContent} (which then
|
|
96
|
+
* actually stages) and a dry-run preview, so the count a human is told up front is the same one
|
|
97
|
+
* real staging produces. `content` must already be in its final pre-chunking form — gzipped when
|
|
98
|
+
* `compress === 'gzip'` (see the module doc for why that step isn't here). `chunkSize` defaults to
|
|
99
|
+
* {@link planChunks}'s default (currently 22 KB), so e.g. a 2.8 KB SVG is 1 chunk.
|
|
100
|
+
*/
|
|
101
|
+
export function planStagedContent(content, compress) {
|
|
102
|
+
const fastlz = compress === 'fastlz';
|
|
103
|
+
const planned = planChunks(content, { fastlz });
|
|
104
|
+
const plan = planContentTxs(planned);
|
|
105
|
+
const representation = compress === 'gzip' ? R.readerGzip : R.reader;
|
|
106
|
+
const stagedBytes = planned.reduce((n, c) => n + c.data.length, 0);
|
|
107
|
+
return { content, fastlz, chunks: planned.length, stagedBytes, plan, representation };
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Put `content` on-chain as SSTORE2 chunks behind the shared reader, and return the field's
|
|
111
|
+
* `(representation, value)`. `fastlz` compresses per chunk (reader decodes on read → stays
|
|
112
|
+
* on-chain renderable); `gzip` compresses the whole content (off-chain decode → the
|
|
113
|
+
* `reader-gzip` representation, not on-chain renderable).
|
|
114
|
+
*
|
|
115
|
+
* Staging is one atomic `writeContent` (content fits a single tx's gas) or gas-bounded chunk-write
|
|
116
|
+
* `multicall`s plus a final manifest write — {@link stageContent} picks. These store writes use
|
|
117
|
+
* `send` (typically the env key on the hot lane, or the connected wallet on the wallet lane) — the
|
|
118
|
+
* data contracts are ownerless, so any funded signer may write them; the caller signs the field-set
|
|
119
|
+
* that references the manifest separately.
|
|
120
|
+
*/
|
|
121
|
+
export async function stageFieldContent(args) {
|
|
122
|
+
const notify = args.onEvent ?? (() => { });
|
|
123
|
+
const p = planStagedContent(args.content, args.compress);
|
|
124
|
+
const resolvedStore = args.store ??
|
|
125
|
+
(await ensureChunkStore(args.publicClient, args.send, {
|
|
126
|
+
chainId: args.chainId,
|
|
127
|
+
onEvent: (e) => notify({ kind: 'chunk-store', event: e }),
|
|
128
|
+
}));
|
|
129
|
+
notify({ kind: 'planned', field: args.field, store: resolvedStore, contentPlan: p });
|
|
130
|
+
const { manifest, txHashes } = await stageContent(args.send, { store: resolvedStore, content: p.content, fastlz: p.fastlz, chainId: args.chainId });
|
|
131
|
+
notify({ kind: 'staged', field: args.field, manifest, txHashes });
|
|
132
|
+
return { value: encodeReader(resolvedStore, manifest), representation: p.representation };
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=staging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staging.js","sourceRoot":"","sources":["../src/staging.ts"],"names":[],"mappings":"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"}
|
package/dist/tokendata.d.ts
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
|
-
import { type Hex, type PublicClient } from 'viem';
|
|
2
|
-
import type { MetadataField, ProjectState, TokenState } from './types.js';
|
|
1
|
+
import { type Address, type Hex, type PublicClient } from 'viem';
|
|
2
|
+
import type { MetadataField, ParamSchema, ParamValue, ProjectState, TokenState } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* The canonical `tokenData` assembly — the off-chain serializer the spec names as
|
|
5
|
+
* authoritative (`specs/protocol/code-projects.md`). One flat object: the reserved
|
|
6
|
+
* coordinates + every param (contract ∪ token scope, token wins) + the augment hook's
|
|
7
|
+
* entries (augment wins per key), every value its canonical string (`chainId` alone is
|
|
8
|
+
* a number). The serialization is canonical because it is *hashed*: an effect's
|
|
9
|
+
* `inputsHash` commits to it, so this exact byte shape is what makes render outputs
|
|
10
|
+
* addressable and self-invalidating.
|
|
11
|
+
*
|
|
12
|
+
* Decode rules: a schema'd param decodes per its type (`Select` → the option string,
|
|
13
|
+
* `DecimalRange` ÷ 1e10, …); a schema-less literal stays the raw `bytes32` hex (a
|
|
14
|
+
* schema is what buys a human decode — `seed` is the canonical example); a data-backed
|
|
15
|
+
* value reads its blob (`String` → UTF-8, `Bytes`/schema-less → base64).
|
|
16
|
+
*/
|
|
17
|
+
/** The tokenData coordinates — never enumerable as params (the on-chain params store excludes
|
|
18
|
+
* `seed` from its key lists, and the generator/renderer skip the other three defensively).
|
|
19
|
+
* Exported because every off-chain surface that enumerates params must exclude exactly this
|
|
20
|
+
* set: two lists that have to agree are one list. */
|
|
21
|
+
export declare const RESERVED_TOKEN_DATA_KEYS: ReadonlySet<string>;
|
|
3
22
|
export interface TokenDataResult {
|
|
4
23
|
/** The flat object (values are canonical strings; `chainId` is a number). */
|
|
5
24
|
data: Record<string, string | number>;
|
|
@@ -47,4 +66,45 @@ export declare function contentDigestOf(state: ProjectState): Hex | null;
|
|
|
47
66
|
* resolver) agree on where a run's artifacts live, over any storage backend.
|
|
48
67
|
*/
|
|
49
68
|
export declare function renderArtifactKey(chainId: number, address: string, tokenId: string, hash: Hex, outputKey?: string, effectKey?: string): Hex;
|
|
69
|
+
/**
|
|
70
|
+
* The **bound** effect outputs — `specs/protocol/effects.md → Bound vs referenced`. An output is
|
|
71
|
+
* bound iff a binding stitches its *content* into the metadata JSON, which is what decides who holds
|
|
72
|
+
* its bytes:
|
|
73
|
+
*
|
|
74
|
+
* - **bound** (`render/traits` → `attributes`): the serving node holds the content, capped at
|
|
75
|
+
* {@link BOUND_ARTIFACT_MAX_BYTES} and servable only at the current settled `inputsHash`. A
|
|
76
|
+
* locator here cannot work — the content is assembled into `tokenURI`, so a locator would put a
|
|
77
|
+
* third-party fetch on the hottest read the resolver serves.
|
|
78
|
+
* - **referenced** (everything else — `render/image` projects a *URL*, a `video`/`model` only
|
|
79
|
+
* appears in the manifest): the PRODUCER holds the bytes and the node stores a locator. Holding
|
|
80
|
+
* these bytes buys a node no capability (it redirects either way) and costs it an object store.
|
|
81
|
+
*
|
|
82
|
+
* This is the wire rule for `POST /v1/effect-artifacts` in both directions: bytes for a referenced
|
|
83
|
+
* output and a locator for a bound one are each a `400`. Growing this set is an interface change —
|
|
84
|
+
* every serving node must be able to stitch a bound output's content.
|
|
85
|
+
*/
|
|
86
|
+
export declare const BOUND_EFFECT_OUTPUTS: ReadonlySet<string>;
|
|
87
|
+
/** The cap a serving node MUST accept per bound output and MUST refuse above (~100× a real traits
|
|
88
|
+
* payload — generous for JSON, far too small to become blob storage). */
|
|
89
|
+
export declare const BOUND_ARTIFACT_MAX_BYTES: number;
|
|
90
|
+
/** Is `{effectKey}/{outputKey}` a bound output — content the serving node must hold and stitch?
|
|
91
|
+
* Unknown effects answer `false`: an output a node can't stitch is referenced by definition, since
|
|
92
|
+
* bytes it can't stitch are bytes it could only redirect to. */
|
|
93
|
+
export declare function isBoundOutput(effectKey: string, outputKey: string): boolean;
|
|
94
|
+
/** One param's canonical decode, with the blob's SIZE alongside. */
|
|
95
|
+
export interface DecodedParam {
|
|
96
|
+
/** The canonical string — what tokenData carries for this key. */
|
|
97
|
+
value: string;
|
|
98
|
+
/** A data-backed param's full content length in bytes; `null` for a literal, and for a blob
|
|
99
|
+
* that didn't read (the value degraded to the hash). Callers that bound inline content —
|
|
100
|
+
* the off-chain resolver's params handling (spec v8 removed the `abx_params` projection from both lanes), mirroring the renderer's former inline ceiling (removed with the projection) —
|
|
101
|
+
* measure THIS, the same length the chain measures. */
|
|
102
|
+
contentBytes: number | null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The canonical per-param decode — the one implementation every off-chain surface shares
|
|
106
|
+
* (tokenData assembly here, `abx_params` in the resolver), so a value reads the same
|
|
107
|
+
* everywhere and stays byte-parallel with the on-chain generator and renderer.
|
|
108
|
+
*/
|
|
109
|
+
export declare function decodeParam(client: PublicClient | null, token: Address, tokenId: string, p: ParamValue, tokenScope: boolean, schema: ParamSchema | undefined): Promise<DecodedParam>;
|
|
50
110
|
//# sourceMappingURL=tokendata.d.ts.map
|
package/dist/tokendata.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokendata.d.ts","sourceRoot":"","sources":["../src/tokendata.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,GAAG,EACR,KAAK,YAAY,EAClB,MAAM,MAAM,CAAC;AAGd,OAAO,KAAK,EAAC,aAAa,
|
|
1
|
+
{"version":3,"file":"tokendata.d.ts","sourceRoot":"","sources":["../src/tokendata.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,OAAO,EACZ,KAAK,GAAG,EACR,KAAK,YAAY,EAClB,MAAM,MAAM,CAAC;AAGd,OAAO,KAAK,EAAC,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAC,MAAM,YAAY,CAAC;AAGjG;;;;;;;;;;;;;GAaG;AAEH;;;sDAGsD;AACtD,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,CAKvD,CAAC;AAMH,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACtC,+FAA+F;IAC/F,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6FAA6F;AAC7F,wBAAgB,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,GAAG,IAAI,CAEnE;AAED,+FAA+F;AAC/F,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAE1D;AAED,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAInF;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,YAAY,GAAG,IAAI,EAC3B,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,UAAU,EACjB,IAAI,GAAE;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAM,GAC7B,OAAO,CAAC,eAAe,CAAC,CAgD1B;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM,CAIpF;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,aAAa,EAAE,GAAG,GAAG,IAAI,EACzB,aAAa,EAAE,MAAM,EACrB,aAAa,SAAY,GACxB,GAAG,CAQL;AAED;wFACwF;AACxF,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,GAAG,GAAG,IAAI,CAI/D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,GAAG,EACT,SAAS,GAAE,MAAgB,EAC3B,SAAS,SAAW,GACnB,GAAG,CAIL;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAA8B,CAAC;AAEpF;0EAC0E;AAC1E,eAAO,MAAM,wBAAwB,QAAY,CAAC;AAElD;;iEAEiE;AACjE,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAE3E;AAID,oEAAoE;AACpE,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd;;;4DAGwD;IACxD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,GAAG,IAAI,EAC3B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,EACf,CAAC,EAAE,UAAU,EACb,UAAU,EAAE,OAAO,EACnB,MAAM,EAAE,WAAW,GAAG,SAAS,GAC9B,OAAO,CAAC,YAAY,CAAC,CAsCvB"}
|
package/dist/tokendata.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { concat, hexToBytes, keccak256, parseAbi, stringToBytes, } from 'viem';
|
|
1
|
+
import { bytesToHex, concat, hexToBytes, keccak256, parseAbi, stringToBytes, } from 'viem';
|
|
2
2
|
import { seriesCodeAbi } from './abi/index.js';
|
|
3
3
|
import { decodeScalarParam } from './spine.js';
|
|
4
|
+
import { bytesToBase64 } from './util.js';
|
|
4
5
|
/**
|
|
5
6
|
* The canonical `tokenData` assembly — the off-chain serializer the spec names as
|
|
6
7
|
* authoritative (`specs/protocol/code-projects.md`). One flat object: the reserved
|
|
@@ -15,7 +16,16 @@ import { decodeScalarParam } from './spine.js';
|
|
|
15
16
|
* schema is what buys a human decode — `seed` is the canonical example); a data-backed
|
|
16
17
|
* value reads its blob (`String` → UTF-8, `Bytes`/schema-less → base64).
|
|
17
18
|
*/
|
|
18
|
-
|
|
19
|
+
/** The tokenData coordinates — never enumerable as params (the on-chain params store excludes
|
|
20
|
+
* `seed` from its key lists, and the generator/renderer skip the other three defensively).
|
|
21
|
+
* Exported because every off-chain surface that enumerates params must exclude exactly this
|
|
22
|
+
* set: two lists that have to agree are one list. */
|
|
23
|
+
export const RESERVED_TOKEN_DATA_KEYS = new Set([
|
|
24
|
+
'chainId',
|
|
25
|
+
'contractAddress',
|
|
26
|
+
'tokenId',
|
|
27
|
+
'seed',
|
|
28
|
+
]);
|
|
19
29
|
const augmentHookAbi = parseAbi([
|
|
20
30
|
'function augmentTokenParams(address token, uint256 tokenId) view returns ((bytes32 key, string value)[])',
|
|
21
31
|
]);
|
|
@@ -60,9 +70,16 @@ export async function buildTokenData(client, state, token, opts = {}) {
|
|
|
60
70
|
for (const p of token.params ?? [])
|
|
61
71
|
merged.set(p.key, { p, tokenScope: true });
|
|
62
72
|
for (const [key, { p, tokenScope }] of merged) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
73
|
+
// Coordinates win. `seed` is the one reserved key allowed through — but only from TOKEN
|
|
74
|
+
// scope, matching the on-chain document exactly: `TokenDataLib.begin` reads
|
|
75
|
+
// `tokenParam(tokenId, "seed")` and never falls back to contract scope. Letting a
|
|
76
|
+
// contract-scope `seed` through here (the merged map holds both scopes) meant an unseeded
|
|
77
|
+
// token carried a seed off-chain that the on-chain generator did not have — the two lanes
|
|
78
|
+
// disagreeing about what a token's seed is, which is the one value they must agree on.
|
|
79
|
+
// Contract-scope `seed` remains settable on-chain by design; it simply is not a token's seed.
|
|
80
|
+
if (RESERVED_TOKEN_DATA_KEYS.has(key) && !(key === 'seed' && tokenScope))
|
|
81
|
+
continue;
|
|
82
|
+
data[key] = (await decodeParam(client, state.address, token.tokenId, p, tokenScope, schemas.get(key))).value;
|
|
66
83
|
}
|
|
67
84
|
// augment hook — last, wins per key (except the reserved coordinates). Skipped for the
|
|
68
85
|
// SETTLED form (opts.augment false): live data belongs in the live view, never in the
|
|
@@ -78,7 +95,7 @@ export async function buildTokenData(client, state, token, opts = {}) {
|
|
|
78
95
|
}));
|
|
79
96
|
for (const e of entries) {
|
|
80
97
|
const key = decodeBytes32Key(e.key);
|
|
81
|
-
if (
|
|
98
|
+
if (RESERVED_TOKEN_DATA_KEYS.has(key))
|
|
82
99
|
continue;
|
|
83
100
|
data[key] = e.value;
|
|
84
101
|
}
|
|
@@ -127,20 +144,63 @@ export function contentDigestOf(state) {
|
|
|
127
144
|
export function renderArtifactKey(chainId, address, tokenId, hash, outputKey = 'image', effectKey = 'render') {
|
|
128
145
|
return keccak256(stringToBytes(`${chainId}/${address.toLowerCase()}/${tokenId}/${effectKey}/${hash}/${outputKey}`));
|
|
129
146
|
}
|
|
130
|
-
|
|
131
|
-
|
|
147
|
+
/**
|
|
148
|
+
* The **bound** effect outputs — `specs/protocol/effects.md → Bound vs referenced`. An output is
|
|
149
|
+
* bound iff a binding stitches its *content* into the metadata JSON, which is what decides who holds
|
|
150
|
+
* its bytes:
|
|
151
|
+
*
|
|
152
|
+
* - **bound** (`render/traits` → `attributes`): the serving node holds the content, capped at
|
|
153
|
+
* {@link BOUND_ARTIFACT_MAX_BYTES} and servable only at the current settled `inputsHash`. A
|
|
154
|
+
* locator here cannot work — the content is assembled into `tokenURI`, so a locator would put a
|
|
155
|
+
* third-party fetch on the hottest read the resolver serves.
|
|
156
|
+
* - **referenced** (everything else — `render/image` projects a *URL*, a `video`/`model` only
|
|
157
|
+
* appears in the manifest): the PRODUCER holds the bytes and the node stores a locator. Holding
|
|
158
|
+
* these bytes buys a node no capability (it redirects either way) and costs it an object store.
|
|
159
|
+
*
|
|
160
|
+
* This is the wire rule for `POST /v1/effect-artifacts` in both directions: bytes for a referenced
|
|
161
|
+
* output and a locator for a bound one are each a `400`. Growing this set is an interface change —
|
|
162
|
+
* every serving node must be able to stitch a bound output's content.
|
|
163
|
+
*/
|
|
164
|
+
export const BOUND_EFFECT_OUTPUTS = new Set(['render/traits']);
|
|
165
|
+
/** The cap a serving node MUST accept per bound output and MUST refuse above (~100× a real traits
|
|
166
|
+
* payload — generous for JSON, far too small to become blob storage). */
|
|
167
|
+
export const BOUND_ARTIFACT_MAX_BYTES = 64 * 1024;
|
|
168
|
+
/** Is `{effectKey}/{outputKey}` a bound output — content the serving node must hold and stitch?
|
|
169
|
+
* Unknown effects answer `false`: an output a node can't stitch is referenced by definition, since
|
|
170
|
+
* bytes it can't stitch are bytes it could only redirect to. */
|
|
171
|
+
export function isBoundOutput(effectKey, outputKey) {
|
|
172
|
+
return BOUND_EFFECT_OUTPUTS.has(`${effectKey}/${outputKey}`);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The canonical per-param decode — the one implementation every off-chain surface shares
|
|
176
|
+
* (tokenData assembly here, `abx_params` in the resolver), so a value reads the same
|
|
177
|
+
* everywhere and stays byte-parallel with the on-chain generator and renderer.
|
|
178
|
+
*/
|
|
179
|
+
export async function decodeParam(client, token, tokenId, p, tokenScope, schema) {
|
|
180
|
+
const literal = (value) => ({ value, contentBytes: null });
|
|
132
181
|
if (!p.valueIsHash) {
|
|
182
|
+
// `seed`'s wire format is INVARIANT: always the raw 32-byte hex, schema or no schema. The
|
|
183
|
+
// on-chain side (`TokenDataLib.begin`) emits `toHexString(seed, 32)` unconditionally and never
|
|
184
|
+
// consults a schema, so consulting one here would fork the work. Concretely: a project that
|
|
185
|
+
// lets an authorized party choose the seed value declares a `seed` schema (typically
|
|
186
|
+
// `Uint256Range` — note this is "pick the value", not a re-roll: the caller supplies it), and this
|
|
187
|
+
// decode would then hand the work `"777"` where the on-chain generator hands it
|
|
188
|
+
// `"0x00…0309"` — the same token rendering differently depending on which surface served it.
|
|
189
|
+
// A `seed` schema governs WHO may write it and within what bounds; it does not change how it
|
|
190
|
+
// reads. Checked before the schema branch for exactly that reason.
|
|
191
|
+
if (p.key === 'seed')
|
|
192
|
+
return literal(p.value);
|
|
133
193
|
if (!schema)
|
|
134
|
-
return
|
|
194
|
+
return literal(decodeTagLoose(p.value));
|
|
135
195
|
if (schema.paramType === 'Select') {
|
|
136
196
|
const idx = Number(BigInt(p.value));
|
|
137
|
-
return schema.selectOptions[idx] ?? String(idx);
|
|
197
|
+
return literal(schema.selectOptions[idx] ?? String(idx));
|
|
138
198
|
}
|
|
139
|
-
return decodeScalarParam(schema.paramType, p.value);
|
|
199
|
+
return literal(decodeScalarParam(schema.paramType, p.value));
|
|
140
200
|
}
|
|
141
201
|
// data-backed: read the blob (token scope falls back to contract scope by construction)
|
|
142
202
|
if (!client)
|
|
143
|
-
return p.value; // best-effort floor: the hash itself
|
|
203
|
+
return literal(p.value); // best-effort floor: the hash itself
|
|
144
204
|
try {
|
|
145
205
|
const blob = (await client.readContract({
|
|
146
206
|
address: token,
|
|
@@ -149,14 +209,16 @@ async function decodeParam(client, token, tokenId, p, tokenScope, schema) {
|
|
|
149
209
|
args: tokenScope ? [BigInt(tokenId), keyToBytes32(p.key)] : [keyToBytes32(p.key)],
|
|
150
210
|
}));
|
|
151
211
|
const bytes = hexToBytes(blob);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
212
|
+
const value = schema?.paramType === 'String'
|
|
213
|
+
? new TextDecoder().decode(bytes)
|
|
214
|
+
: bytesToBase64(bytes); // Bytes + schema-less: base64 at read
|
|
215
|
+
return { value, contentBytes: bytes.length };
|
|
155
216
|
}
|
|
156
217
|
catch {
|
|
157
|
-
return p.value;
|
|
218
|
+
return literal(p.value);
|
|
158
219
|
}
|
|
159
220
|
}
|
|
221
|
+
// ── internals ──────────────────────────────────────────────────────────────────
|
|
160
222
|
/** A readable-ASCII `bytes32` literal as its string (e.g. a `display.animation` value). */
|
|
161
223
|
function decodeTagLoose(value) {
|
|
162
224
|
const bytes = hexToBytes(value);
|
|
@@ -173,6 +235,6 @@ function decodeBytes32Key(key) {
|
|
|
173
235
|
function keyToBytes32(key) {
|
|
174
236
|
const bytes = new Uint8Array(32);
|
|
175
237
|
bytes.set(stringToBytes(key).slice(0, 32));
|
|
176
|
-
return
|
|
238
|
+
return bytesToHex(bytes);
|
|
177
239
|
}
|
|
178
240
|
//# sourceMappingURL=tokendata.js.map
|
package/dist/tokendata.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokendata.js","sourceRoot":"","sources":["../src/tokendata.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,UAAU,EACV,SAAS,EACT,QAAQ,EACR,aAAa,GAId,MAAM,MAAM,CAAC;AACd,OAAO,EAAC,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAC,iBAAiB,EAAqB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"tokendata.js","sourceRoot":"","sources":["../src/tokendata.ts"],"names":[],"mappings":"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"}
|
package/dist/tokens.d.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { type Address, type Hex, type PublicClient } from 'viem';
|
|
2
|
+
export interface TokenRow {
|
|
3
|
+
tokenId: string;
|
|
4
|
+
/** `null` when `ownerOf` reverts — see {@link lifecycle}, which says WHY it reverted whenever the
|
|
5
|
+
* chain gives enough evidence to tell. Always `null` on an ERC-1155 edition: an id can have many
|
|
6
|
+
* concurrent holders, and *which* holders is not chain-enumerable outside the event log (that's
|
|
7
|
+
* the indexer's job, not a head read). */
|
|
8
|
+
owner: Address | null;
|
|
9
|
+
/**
|
|
10
|
+
* Does a token exist at this id right now — from head reads alone, no event log. The same words the
|
|
11
|
+
* fold uses ({@link TokenState.lifecycle}), plus `'unknown'` for the one case where a head read
|
|
12
|
+
* genuinely cannot say and the log can:
|
|
13
|
+
*
|
|
14
|
+
* - `'live'` — `ownerOf` answered (721), or `totalSupply(id) > 0` (edition).
|
|
15
|
+
* - `'burned'` — 721 only, terminal, and *decidable at head*: `nextTokenId` is a mint frontier that
|
|
16
|
+
* only ever rises, so an id BELOW it whose `ownerOf` reverts was minted and destroyed. A listing
|
|
17
|
+
* enumerates `0 … nextTokenId - 1`, so inside that range a revert IS a burn.
|
|
18
|
+
* - `'unminted'` — 721: at or past the frontier, never issued.
|
|
19
|
+
* - `'no-live-copies'` — editions: `totalSupply(id) == 0`. **The same word the fold uses for the
|
|
20
|
+
* same id**, deliberately: the fold could distinguish never-minted from fully-burned and does not,
|
|
21
|
+
* because the distinction has no consumer (the id can mint again either way). One field name, one
|
|
22
|
+
* value per id, whichever lane produced it.
|
|
23
|
+
* - `'unknown'` — a 1/1 exposes no `nextTokenId`, so a reverting `ownerOf` there is evidence of
|
|
24
|
+
* nothing: it is equally consistent with never-minted and with burned. The log settles it; a head
|
|
25
|
+
* read must not guess. This is the *only* remaining case, and it is why the word exists.
|
|
26
|
+
*
|
|
27
|
+
* The first draft had this lane answer `'unknown'` for an edition at zero while the fold answered
|
|
28
|
+
* `'burned'` for the same id — two values under one field name, which is the sibling-drift class
|
|
29
|
+
* this repo treats as a bug (see {@link TokenState.maxSupply}'s note). abx-services caught it in
|
|
30
|
+
* review, in a docstring that claimed the two lanes agreed. Splitting `'burned'` from
|
|
31
|
+
* `'no-live-copies'` is what makes the claim true instead of aspirational.
|
|
32
|
+
*/
|
|
33
|
+
lifecycle: 'live' | 'burned' | 'unminted' | 'no-live-copies' | 'unknown';
|
|
34
|
+
/**
|
|
35
|
+
* The mint-time seed as the raw `bytes32` — exactly what `tokenData` carries. A schema is what
|
|
36
|
+
* buys a human decode and `seed` deliberately has none, so raw hex IS its canonical form.
|
|
37
|
+
* `null` ⇒ no seed set for this token (no seed source, or not minted).
|
|
38
|
+
*/
|
|
39
|
+
seed: Hex | null;
|
|
40
|
+
/**
|
|
41
|
+
* Token-scope params, decoded to their canonical strings. Contract-scope params are listed once
|
|
42
|
+
* on {@link TokenListing.contractParams} rather than repeated per row; the work sees
|
|
43
|
+
* contract ∪ token with **token winning** (see `buildTokenData`, the canonical assembly).
|
|
44
|
+
*/
|
|
45
|
+
params: Record<string, string>;
|
|
46
|
+
/** ERC-1155 editions only — this id's live supply (`totalSupply(id)`), as a decimal string.
|
|
47
|
+
* Absent on a 721 token. */
|
|
48
|
+
supply?: string;
|
|
49
|
+
/** ERC-1155 editions only — this id's current supply cap (`maxSupply(id)`; `"0"` reads as
|
|
50
|
+
* open/uncapped exactly like the contract's own convention). Absent on a 721 token. */
|
|
51
|
+
maxSupply?: string;
|
|
52
|
+
}
|
|
53
|
+
/** What an edition id's cap actually means. `closed` is the state the on-chain getter cannot express
|
|
54
|
+
* (`maxSupply(id)` returns `0` for both "never capped" and "deliberately closed") — see
|
|
55
|
+
* {@link editionCapOf}. */
|
|
56
|
+
export type EditionCap = {
|
|
57
|
+
kind: 'open';
|
|
58
|
+
} | {
|
|
59
|
+
kind: 'capped';
|
|
60
|
+
cap: string;
|
|
61
|
+
} | {
|
|
62
|
+
kind: 'closed';
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Read an edition id's cap without re-deriving the rule at each call site — the derivation this
|
|
66
|
+
* protocol got wrong twice, in opposite directions: the on-chain getter overloads `0`, and the
|
|
67
|
+
* event fold used to miss the collection default entirely.
|
|
68
|
+
*
|
|
69
|
+
* Pass a folded {@link TokenState} (from `reconstructProject`) to get all three states. Pass a
|
|
70
|
+
* head-read {@link TokenRow}, which has no `maxSupplyOverridden` because a state read cannot know
|
|
71
|
+
* it, and a `'0'` cap reads `open` — the documented on-chain convention, and the reason
|
|
72
|
+
* `IAbxEditionSupply` tells an integrator rendering a buy button to consult the log.
|
|
73
|
+
*
|
|
74
|
+
* `null` ⇒ no cap information at all (a 721 token, or a row from a projection written before
|
|
75
|
+
* `DefaultMaxSupplySet` was folded).
|
|
76
|
+
*/
|
|
77
|
+
export declare function editionCapOf(token: {
|
|
78
|
+
maxSupply?: string;
|
|
79
|
+
maxSupplyOverridden?: boolean;
|
|
80
|
+
}): EditionCap | null;
|
|
81
|
+
export interface TokenListing {
|
|
82
|
+
chainId: number;
|
|
83
|
+
address: Address;
|
|
84
|
+
/** Ids `0 … nextTokenId - 1` have been minted at some point. `null` on a token type with no
|
|
85
|
+
* sequential mint frontier — a 1/1 (always just token 0), or an ERC-1155 edition (ids are
|
|
86
|
+
* caller-named, not a cursor; see each row's own `supply`/`maxSupply` instead). */
|
|
87
|
+
nextTokenId: number | null;
|
|
88
|
+
/** Live supply (mints − burns) — differs from `nextTokenId` only if tokens were burned. `null`
|
|
89
|
+
* on an edition: there's no unconditional whole-contract total, only a per-id one (each row's
|
|
90
|
+
* `supply`). */
|
|
91
|
+
totalSupply: number | null;
|
|
92
|
+
/** How many tokens have been destroyed: `nextTokenId − totalSupply`, both of which the contract
|
|
93
|
+
* keeps (the frontier counts mints and never falls; the total counts live tokens). `null` when
|
|
94
|
+
* either is absent — a 1/1, or an edition, where burns are per id (each row's `supply`). */
|
|
95
|
+
burnedCount: number | null;
|
|
96
|
+
maxInvocations: number | null;
|
|
97
|
+
/**
|
|
98
|
+
* Whether the contract exposes the params surface at all. `false` for the image token types
|
|
99
|
+
* (they have no Params extension), in which case every row's `seed` is `null` and `params` is
|
|
100
|
+
* empty — correct, not a failed read.
|
|
101
|
+
*/
|
|
102
|
+
hasParams: boolean;
|
|
103
|
+
/** Whether the contract exposes on-chain param *enumeration*. `false` on a project deployed
|
|
104
|
+
* before enumeration shipped: seeds still read (by name), but params can't be listed. */
|
|
105
|
+
hasParamEnumeration: boolean;
|
|
106
|
+
contractParams: Record<string, string>;
|
|
107
|
+
tokens: TokenRow[];
|
|
108
|
+
}
|
|
109
|
+
export interface ListTokensOptions {
|
|
110
|
+
/** Read only this many ids from `from` (default: all). */
|
|
111
|
+
limit?: number;
|
|
112
|
+
/** First token id to read (default 0). */
|
|
113
|
+
from?: number;
|
|
114
|
+
concurrency?: number;
|
|
115
|
+
/** Called after each token resolves — for a progress line on a large collection. */
|
|
116
|
+
onProgress?: (done: number, total: number) => void;
|
|
117
|
+
}
|
|
118
|
+
/** Every token's owner, seed, and params, straight from the contract. */
|
|
119
|
+
export declare function listTokens(client: PublicClient, address: Address, opts?: ListTokensOptions): Promise<TokenListing>;
|
|
120
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,YAAY,EAAC,MAAM,MAAM,CAAC;AA+B5E,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB;;;+CAG2C;IAC3C,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB;;;;;;;;;;;;;;;;;;;;;;;MAuBE;IACH,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,gBAAgB,GAAG,SAAS,CAAC;IACzE;;;;OAIG;IACH,IAAI,EAAE,GAAG,GAAG,IAAI,CAAC;IACjB;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;iCAC6B;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;4FACwF;IACxF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;4BAE4B;AAC5B,MAAM,MAAM,UAAU,GAAG;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GAAG;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,GAAG;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,CAAC;AAE3F;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAAC,GAAG,UAAU,GAAG,IAAI,CAI1G;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB;;wFAEoF;IACpF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;qBAEiB;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;iGAE6F;IAC7F,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;8FAC0F;IAC1F,mBAAmB,EAAE,OAAO,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,MAAM,EAAE,QAAQ,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpD;AAiCD,yEAAyE;AACzE,wBAAsB,UAAU,CAC9B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,OAAO,EAChB,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC,YAAY,CAAC,CAwGvB"}
|