@artblocks/abx-sdk 0.1.0-alpha.4 → 0.1.0-alpha.41
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 +72 -0
- package/README.md +130 -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 +325 -0
- package/dist/anchors.d.ts.map +1 -0
- package/dist/anchors.js +740 -0
- package/dist/anchors.js.map +1 -0
- package/dist/chain-support.d.ts +28 -0
- package/dist/chain-support.d.ts.map +1 -0
- package/dist/chain-support.js +65 -0
- package/dist/chain-support.js.map +1 -0
- package/dist/chain-support.json +60 -0
- package/dist/chains.d.ts +24 -10
- package/dist/chains.d.ts.map +1 -1
- package/dist/chains.js +51 -17
- package/dist/chains.js.map +1 -1
- package/dist/chunks.d.ts +162 -31
- package/dist/chunks.d.ts.map +1 -1
- package/dist/chunks.js +179 -14
- 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/contract-generations.d.ts +58 -0
- package/dist/contract-generations.d.ts.map +1 -0
- package/dist/contract-generations.js +109 -0
- package/dist/contract-generations.js.map +1 -0
- package/dist/contract-generations.json +48 -0
- package/dist/create2.d.ts +84 -1
- package/dist/create2.d.ts.map +1 -1
- package/dist/create2.js +158 -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 +38 -5
- package/dist/deployments.d.ts.map +1 -1
- package/dist/deployments.js +157 -30
- package/dist/deployments.js.map +1 -1
- package/dist/deps.d.ts +123 -6
- package/dist/deps.d.ts.map +1 -1
- package/dist/deps.js +249 -7
- package/dist/deps.js.map +1 -1
- package/dist/env.d.ts +5 -4
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +20 -5
- package/dist/env.js.map +1 -1
- package/dist/errors.d.ts +109 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +148 -0
- package/dist/errors.js.map +1 -0
- package/dist/execute.d.ts +118 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +159 -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 +57 -0
- package/dist/generator-document.d.ts.map +1 -0
- package/dist/generator-document.js +123 -0
- package/dist/generator-document.js.map +1 -0
- package/dist/generator.d.ts +44 -2
- 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 +19 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -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 +69 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +92 -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 +276 -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 +850 -34
- package/dist/ops.js.map +1 -1
- package/dist/policy.d.ts +57 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +35 -0
- package/dist/policy.js.map +1 -0
- package/dist/probe.d.ts +58 -0
- package/dist/probe.d.ts.map +1 -1
- package/dist/probe.js +190 -9
- package/dist/probe.js.map +1 -1
- package/dist/reconstruct.d.ts +141 -3
- package/dist/reconstruct.d.ts.map +1 -1
- package/dist/reconstruct.js +479 -100
- package/dist/reconstruct.js.map +1 -1
- package/dist/resume.d.ts +147 -0
- package/dist/resume.d.ts.map +1 -0
- package/dist/resume.js +146 -0
- package/dist/resume.js.map +1 -0
- package/dist/script-chunks.d.ts +105 -0
- package/dist/script-chunks.d.ts.map +1 -0
- package/dist/script-chunks.js +158 -0
- package/dist/script-chunks.js.map +1 -0
- package/dist/service.d.ts +155 -9
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +103 -11
- 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 +139 -0
- package/dist/staging.d.ts.map +1 -0
- package/dist/staging.js +139 -0
- package/dist/staging.js.map +1 -0
- package/dist/token.d.ts +11 -1
- package/dist/token.d.ts.map +1 -1
- package/dist/token.js +32 -1
- package/dist/token.js.map +1 -1
- package/dist/tokendata.d.ts +63 -3
- package/dist/tokendata.d.ts.map +1 -1
- package/dist/tokendata.js +81 -19
- package/dist/tokendata.js.map +1 -1
- package/dist/tokens.d.ts +119 -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 +107 -5
- 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 +15 -6
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* On-chain program chunks — the writer-side twin of {@link AbxGenerator}'s `_escapedScript`.
|
|
3
|
+
*
|
|
4
|
+
* The generator (and the resolver) join `scriptChunk(i)` with a single `'\n'` between chunks. A
|
|
5
|
+
* fixed-size byte slice that ignores that join inserts a newline in the middle of a token — `mass`
|
|
6
|
+
* becomes `ma\nss`, which is invalid JavaScript — and `abx verify` still goes green because it
|
|
7
|
+
* never parses the reassembled program. Splitting AT an existing newline (and dropping it, because
|
|
8
|
+
* the join puts it back) makes `chunks.join('\n') === source`. A 22 kB+ span with no newline is
|
|
9
|
+
* refused: there is no honest split that matches the on-chain join.
|
|
10
|
+
*
|
|
11
|
+
* This module also carries the write-side counterpart to that split (`prepareSetScriptChunk` /
|
|
12
|
+
* `prepareRemoveLastScriptChunk`, wrapping `OnChainScript.sol`'s `setScriptChunk`/
|
|
13
|
+
* `removeLastScriptChunk` — contracts/src/extensions/onchain-script/OnChainScript.sol) and the
|
|
14
|
+
* SAFE-REPLACEMENT planning + verification pair (`planScriptReplace` / `verifyScriptReplace`) that
|
|
15
|
+
* `abx replace-script` is built on (packages/cli/src/ownerops.ts). Both take a small reader
|
|
16
|
+
* interface rather than a viem client — the same shape `resume.ts` uses — so the diff and the
|
|
17
|
+
* post-write verification are testable with a fake chain, no RPC, no signer.
|
|
18
|
+
*/
|
|
19
|
+
import { encodeFunctionData, hexToBytes } from 'viem';
|
|
20
|
+
import { seriesCodeAbi } from './abi/index.js';
|
|
21
|
+
const ZERO_VALUE = '0x0';
|
|
22
|
+
/** SSTORE2 data-contract code limit is 24576 bytes (EIP-170) minus STOP; stay conservative. */
|
|
23
|
+
export const DEFAULT_SCRIPT_CHUNK_SIZE = 22_000;
|
|
24
|
+
/** The byte the on-chain generator inserts between script chunks. Must stay in lockstep with
|
|
25
|
+
* `AbxGenerator._escapedScript` and the resolver's `.join('\n')`. */
|
|
26
|
+
export const SCRIPT_CHUNK_JOIN = '\n';
|
|
27
|
+
const NL = 0x0a;
|
|
28
|
+
/**
|
|
29
|
+
* Split a program so the generator's newline-join reconstitutes it byte-for-byte.
|
|
30
|
+
* Empty source → no chunks (nothing to store). A single chunk that already fits is stored as-is
|
|
31
|
+
* (the generator inserts no join when `n === 1`).
|
|
32
|
+
*/
|
|
33
|
+
export function splitScriptChunks(source, chunkSize = DEFAULT_SCRIPT_CHUNK_SIZE) {
|
|
34
|
+
if (chunkSize < 1)
|
|
35
|
+
throw new Error('chunkSize must be ≥ 1');
|
|
36
|
+
const bytes = new TextEncoder().encode(source);
|
|
37
|
+
if (bytes.length === 0)
|
|
38
|
+
return [];
|
|
39
|
+
if (bytes.length <= chunkSize)
|
|
40
|
+
return [bytes];
|
|
41
|
+
const chunks = [];
|
|
42
|
+
let i = 0;
|
|
43
|
+
while (i < bytes.length) {
|
|
44
|
+
const remaining = bytes.length - i;
|
|
45
|
+
if (remaining <= chunkSize) {
|
|
46
|
+
chunks.push(bytes.subarray(i));
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
// Last newline in the window. The generator will put it back between this chunk and the next,
|
|
50
|
+
// so the chunk itself excludes it.
|
|
51
|
+
let split = -1;
|
|
52
|
+
for (let j = i + chunkSize - 1; j >= i; j--) {
|
|
53
|
+
if (bytes[j] === NL) {
|
|
54
|
+
split = j;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (split < i) {
|
|
59
|
+
throw new Error(`script has a ${chunkSize}+ byte span with no newline — the on-chain generator joins ` +
|
|
60
|
+
`chunks with a newline, so a split here would insert a byte and can break the program ` +
|
|
61
|
+
`(a 22 kB minified line has been observed to turn \`mass\` into \`ma\\nss\`). ` +
|
|
62
|
+
`Insert a line break, or shrink the file.`);
|
|
63
|
+
}
|
|
64
|
+
chunks.push(bytes.subarray(i, split));
|
|
65
|
+
i = split + 1;
|
|
66
|
+
}
|
|
67
|
+
return chunks;
|
|
68
|
+
}
|
|
69
|
+
/** Inverse of {@link splitScriptChunks}: the join the generator performs on chain. */
|
|
70
|
+
export function joinScriptChunks(chunks) {
|
|
71
|
+
const dec = new TextDecoder();
|
|
72
|
+
return chunks.map((c) => dec.decode(c)).join(SCRIPT_CHUNK_JOIN);
|
|
73
|
+
}
|
|
74
|
+
// ── writes: OnChainScript.sol's setScriptChunk / removeLastScriptChunk ────────
|
|
75
|
+
// No `prepare*` wrapper existed for either before this — every caller (deploy-code's setup
|
|
76
|
+
// multicall, its --resume leg) hand-encoded `encodeFunctionData` inline. These mirror
|
|
77
|
+
// `prepareSetDependency`/`prepareRemoveLastDependency` (ops.ts) exactly: same `PreparedTx` shape,
|
|
78
|
+
// same "one index-addressed setter + one pop-the-tail remover" split.
|
|
79
|
+
/** Owner writes/replaces the on-chain program chunk at `index` (`index === count` appends) —
|
|
80
|
+
* `OnChainScript.setScriptChunk`. Content should come from {@link splitScriptChunks} so the
|
|
81
|
+
* generator's newline-join reassembles the exact source. Signer must be the owner. */
|
|
82
|
+
export function prepareSetScriptChunk(args) {
|
|
83
|
+
const index = BigInt(args.index);
|
|
84
|
+
const bytes = (args.chunk.length - 2) / 2;
|
|
85
|
+
// EVM code deposit is 200 gas/byte — the same physics-backed floor the code-setup multicall
|
|
86
|
+
// computes for its script-chunk legs (ops.ts). Restated per-chunk here so a caller that assembles
|
|
87
|
+
// its own multicall (`replace-script`) can sum an honest `gasFloor` instead of trusting
|
|
88
|
+
// `eth_estimateGas` against a target too fresh for the estimator to see (see PreparedTx.gasFloor's
|
|
89
|
+
// own doc for why a wrong estimate must be DETECTED, not silently replaced).
|
|
90
|
+
const gasFloor = bytes > 0 ? `0x${(bytes * 200).toString(16)}` : undefined;
|
|
91
|
+
return {
|
|
92
|
+
op: 'set-script-chunk',
|
|
93
|
+
to: args.contract,
|
|
94
|
+
data: encodeFunctionData({ abi: seriesCodeAbi, functionName: 'setScriptChunk', args: [index, args.chunk] }),
|
|
95
|
+
value: ZERO_VALUE,
|
|
96
|
+
chainId: args.chainId,
|
|
97
|
+
summary: `Set script chunk [${index}] (${bytes} byte${bytes === 1 ? '' : 's'})`,
|
|
98
|
+
fields: { contract: args.contract, index: index.toString(), bytes: String(bytes) },
|
|
99
|
+
...(gasFloor === undefined ? {} : { gasFloor }),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** Remove the LAST on-chain program chunk (the list stays dense; order is load-bearing) —
|
|
103
|
+
* `OnChainScript.removeLastScriptChunk`. There is no "remove N": shrinking by more than one chunk
|
|
104
|
+
* is this call, repeated. Signer must be the owner. */
|
|
105
|
+
export function prepareRemoveLastScriptChunk(args) {
|
|
106
|
+
return {
|
|
107
|
+
op: 'remove-last-script-chunk',
|
|
108
|
+
to: args.contract,
|
|
109
|
+
data: encodeFunctionData({ abi: seriesCodeAbi, functionName: 'removeLastScriptChunk', args: [] }),
|
|
110
|
+
value: ZERO_VALUE,
|
|
111
|
+
chainId: args.chainId,
|
|
112
|
+
summary: 'Remove the last script chunk (the list stays dense)',
|
|
113
|
+
fields: { contract: args.contract },
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Diff a replacement program's chunks against what a contract holds NOW, so `replace-script` sends
|
|
118
|
+
* only what actually changed. Mirrors `resume.ts`'s script-chunk leg (`planCoreLegs`) exactly —
|
|
119
|
+
* content, not count, decides "present" — the difference being that a resume leg is checked
|
|
120
|
+
* present/absent as a GROUP (the setup multicall is atomic, so partial-content-mismatch never
|
|
121
|
+
* legitimately happens), while a replacement is expected to change SOME indices and not others, so
|
|
122
|
+
* each index is diffed and reported independently.
|
|
123
|
+
*/
|
|
124
|
+
export async function planScriptReplace(read, next) {
|
|
125
|
+
const currentCount = await read.scriptChunkCount();
|
|
126
|
+
const toWrite = [];
|
|
127
|
+
for (let i = 0; i < next.length; i++) {
|
|
128
|
+
const stored = i < currentCount ? await read.scriptChunk(i) : null;
|
|
129
|
+
if (stored !== null && stored.toLowerCase() === next[i].toLowerCase())
|
|
130
|
+
continue;
|
|
131
|
+
toWrite.push({ index: i, hex: next[i] });
|
|
132
|
+
}
|
|
133
|
+
const toRemove = Math.max(0, currentCount - next.length);
|
|
134
|
+
return { toWrite, toRemove, currentCount, targetCount: next.length, noop: toWrite.length === 0 && toRemove === 0 };
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Read the completed script back from chain and confirm it reassembles EXACTLY to `expectedSource`
|
|
138
|
+
* — the safety property that justifies `replace-script` existing at all. A transaction not
|
|
139
|
+
* reverting is proof the EVM accepted each call; it is NOT proof the final program is what was
|
|
140
|
+
* intended (a stale RPC view, a concurrent write racing the same contract, or a bug in the ordering
|
|
141
|
+
* of writes-vs-removes could all leave a script that "sent fine" and reassembles to garbage). This
|
|
142
|
+
* is the check that turns "the multicall didn't revert" into "the program is provably correct" —
|
|
143
|
+
* run it BEFORE reporting success, never after.
|
|
144
|
+
*/
|
|
145
|
+
export async function verifyScriptReplace(read, expectedSource) {
|
|
146
|
+
const chunkCount = await read.scriptChunkCount();
|
|
147
|
+
const chunks = [];
|
|
148
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
149
|
+
const hex = await read.scriptChunk(i);
|
|
150
|
+
// `scriptChunkCount()` and `scriptChunk(i)` are two separate reads against (hopefully) the same
|
|
151
|
+
// block; a `null` here means they disagree, which is itself the failure this function exists to
|
|
152
|
+
// catch — report it as a verification miss rather than silently reassembling a gap.
|
|
153
|
+
chunks.push(hex === null ? new Uint8Array(0) : hexToBytes(hex));
|
|
154
|
+
}
|
|
155
|
+
const reassembled = joinScriptChunks(chunks);
|
|
156
|
+
return { ok: reassembled === expectedSource, reassembled, chunkCount };
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=script-chunks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-chunks.js","sourceRoot":"","sources":["../src/script-chunks.ts"],"names":[],"mappings":"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"}
|
package/dist/service.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The remote-service client — the SDK's one HTTP surface, speaking the provider-neutral
|
|
3
|
-
* control plane pinned by
|
|
3
|
+
* control plane pinned by site/content/docs/using-abx/remote-services.mdx. A client is bound to an
|
|
4
4
|
* endpoint + an injected bearer token, never to a brand: the reference CLI, the effects runner,
|
|
5
5
|
* and any hosted agent drive a self-hosted node and a managed provider through this same class.
|
|
6
6
|
*
|
|
@@ -10,15 +10,45 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { Hex } from 'viem';
|
|
12
12
|
import type { OpenSeaAttribute } from './traits.js';
|
|
13
|
+
import type { ContractGenerationSummary } from './contract-generations.js';
|
|
13
14
|
export declare const WELL_KNOWN_SERVICE_PATH = "/.well-known/abx-service";
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
15
|
+
/**
|
|
16
|
+
* Versioned interface ids a service declares in its descriptor. Versions ride these ids
|
|
17
|
+
* (they track the `/v1` path prefix); the descriptor has no separate format version.
|
|
18
|
+
*
|
|
19
|
+
* There are three optional interface families, and they are **all-or-nothing**: declaring one asserts every route it names
|
|
20
|
+
* answers per the spec. The artifact-registry routes ride {@link CONTROL_PLANE_INTERFACE} rather
|
|
21
|
+
* than an id of their own — once referenced output is locator-only, accepting a registration is a
|
|
22
|
+
* database insert, so a separate capability flag would describe a distinction that doesn't exist.
|
|
23
|
+
* A service that won't take a given caller's artifacts refuses on the credential (`403`), which is
|
|
24
|
+
* the honest axis: interfaces describe wire grammar, tokens describe permission.
|
|
25
|
+
*/
|
|
16
26
|
export declare const TOKEN_API_INTERFACE = "abx-token-api/v1";
|
|
17
27
|
export declare const CONTROL_PLANE_INTERFACE = "abx-control-plane/v1";
|
|
18
|
-
|
|
28
|
+
/** Provider-specific feedback discovery, submission, and account history at `/feedback`. Core ABX
|
|
29
|
+
* feedback is deliberately not this interface: it belongs to the ABX team, not a remote provider. */
|
|
30
|
+
export declare const SERVICE_FEEDBACK_INTERFACE = "abx-service-feedback/v1";
|
|
31
|
+
/**
|
|
32
|
+
* Why this locator can't be accepted for a referenced artifact, or `null` if it passes.
|
|
33
|
+
*
|
|
34
|
+
* A locator is a **reachability** claim, not a durability one: it must resolve for a third party
|
|
35
|
+
* with no producer credentials and no private-network assumption. The protocol deliberately has
|
|
36
|
+
* **no preference among schemes** — `https://` (S3/R2, a producer's own public base, a chosen
|
|
37
|
+
* IPFS/Arweave gateway), `ipfs://` and `ar://` are peers, because derived output is re-creatable and
|
|
38
|
+
* a producer with an opinion about which gateway serves its content is making an operational call the
|
|
39
|
+
* protocol has no standing to override.
|
|
40
|
+
*
|
|
41
|
+
* Reachability can't be *proved* without fetching, and fetching a third-party URL while handling an
|
|
42
|
+
* authed write is byte custody through the back door plus an SSRF surface. So this checks the two
|
|
43
|
+
* things that are decidable from the string alone and are always wrong:
|
|
44
|
+
* - a private / loopback host — resolvable only from the producer's own network;
|
|
45
|
+
* - a presigned, expiring URL — resolvable now, dead later, which is the worst failure shape
|
|
46
|
+
* (it passes every check at publish time and rots silently).
|
|
47
|
+
*/
|
|
48
|
+
export declare function locatorRejectionReason(locator: string): string | null;
|
|
19
49
|
/**
|
|
20
50
|
* The indexing lifecycle a registration moves through, closed and provider-neutral
|
|
21
|
-
* (
|
|
51
|
+
* (site/content/docs/using-abx/remote-services.mdx → The indexing lifecycle). One vocabulary for a
|
|
22
52
|
* managed provider and for your own node — the reference resolver stamps these too.
|
|
23
53
|
*
|
|
24
54
|
* queued registered + accepted; catch-up hasn't started
|
|
@@ -61,11 +91,30 @@ export interface IndexError {
|
|
|
61
91
|
export declare function classifyIndexError(err: unknown): IndexError;
|
|
62
92
|
/** Machine error codes every conforming service uses — clients key off these, never off prose. */
|
|
63
93
|
export type ServiceErrorCode = 'invalid_request' | 'unsupported_chain' | 'unauthorized' | 'forbidden' | 'not_registered' | 'disabled'
|
|
94
|
+
/** The report belongs at a different feedback target; the response carries its canonical URL. */
|
|
95
|
+
| 'feedback_target_moved'
|
|
64
96
|
/** 404 — this node serves no route at that path AT ALL (as opposed to a known route whose shape
|
|
65
97
|
* was wrong, which is a 400 `invalid_request` carrying the correct template). The pair exists so
|
|
66
98
|
* a client can tell "I built the wrong URL" from "this project isn't indexed here" from "this
|
|
67
99
|
* node is older than the route I want" — a bare 404 conflates all three and reads as an outage. */
|
|
68
100
|
| 'unknown_route'
|
|
101
|
+
/**
|
|
102
|
+
* **410** — this token id existed and is permanently gone (an ERC-721 burn). A statement about the
|
|
103
|
+
* TOKEN, which is why `not_registered` could not carry it: that one is a statement about the
|
|
104
|
+
* *contract* ("this node doesn't index it"), so it cannot truthfully describe a destroyed id.
|
|
105
|
+
*
|
|
106
|
+
* `410`, not `404`, and the rule generalizes: **a resolver answers what the contract's own URI
|
|
107
|
+
* getter answers.** A burned 721's `tokenURI` reverts `NonexistentToken`, so composing metadata
|
|
108
|
+
* for it would put a node in direct contradiction with the contract it speaks for — while `404`
|
|
109
|
+
* reads as "wrong URL / not indexed yet" and invites a retry that can never succeed. It is worse
|
|
110
|
+
* than cosmetic on the image route, which answers an unknown-but-in-cap id with a warming
|
|
111
|
+
* placeholder: for a destroyed id that says "still loading" forever.
|
|
112
|
+
*
|
|
113
|
+
* **ERC-1155 editions never answer this.** `uri(id)` has no existence gate there, a zero-supply id
|
|
114
|
+
* still resolves, and it can mint again — nothing is permanently gone, so `410` would be a lie.
|
|
115
|
+
* Serve the document with `supply: 0`.
|
|
116
|
+
*/
|
|
117
|
+
| 'burned'
|
|
69
118
|
/** 500 — an unexpected server-side failure. Never carries internal detail (it could embed the
|
|
70
119
|
* operator's own credentials); the node logs the cause. Retryable. */
|
|
71
120
|
| 'internal_error';
|
|
@@ -80,8 +129,10 @@ export interface ServiceDescriptor {
|
|
|
80
129
|
interfaces: string[];
|
|
81
130
|
/** EIP-155 chain ids served; the control plane rejects others with `unsupported_chain`. */
|
|
82
131
|
chains: number[];
|
|
83
|
-
/**
|
|
84
|
-
|
|
132
|
+
/** Contract generations this implementation understands, with operation-specific policy. */
|
|
133
|
+
contractGenerations?: ContractGenerationSummary[];
|
|
134
|
+
/** Present iff the control plane is enabled. `signupUrl` is provider-specific human
|
|
135
|
+
* onboarding/recovery and `docsUrl` is provider documentation; OAuth discovery is separate. */
|
|
85
136
|
auth?: {
|
|
86
137
|
scheme: 'bearer';
|
|
87
138
|
signupUrl?: string;
|
|
@@ -102,6 +153,69 @@ export interface ServiceDescriptor {
|
|
|
102
153
|
/** The public base this node believes it serves — a sanity echo for misconfig detection. */
|
|
103
154
|
baseUrl?: string;
|
|
104
155
|
}
|
|
156
|
+
export declare const FEEDBACK_KINDS: readonly ["bug", "friction", "gap", "confusion", "praise", "other"];
|
|
157
|
+
export type FeedbackKind = (typeof FEEDBACK_KINDS)[number];
|
|
158
|
+
export declare const FEEDBACK_SEVERITIES: readonly ["blocker", "major", "minor"];
|
|
159
|
+
export type FeedbackSeverity = (typeof FEEDBACK_SEVERITIES)[number];
|
|
160
|
+
export declare const ABX_FEEDBACK_AREAS: readonly ["protocol", "contracts", "cli", "sdk", "skills", "docs", "other"];
|
|
161
|
+
export type AbxFeedbackArea = (typeof ABX_FEEDBACK_AREAS)[number];
|
|
162
|
+
/** Optional evidence carried with a report. Providers may accept extra keys; credentials and
|
|
163
|
+
* private source never belong here. */
|
|
164
|
+
export interface FeedbackContext {
|
|
165
|
+
command?: string;
|
|
166
|
+
chainId?: number;
|
|
167
|
+
address?: string;
|
|
168
|
+
txHashes?: string[];
|
|
169
|
+
addresses?: string[];
|
|
170
|
+
cliVersion?: string;
|
|
171
|
+
sdkVersion?: string;
|
|
172
|
+
skill?: string;
|
|
173
|
+
sessionId?: string;
|
|
174
|
+
serviceUrl?: string;
|
|
175
|
+
[key: string]: unknown;
|
|
176
|
+
}
|
|
177
|
+
export interface FeedbackFields {
|
|
178
|
+
kind: FeedbackKind;
|
|
179
|
+
summary: string;
|
|
180
|
+
detail?: string;
|
|
181
|
+
severity?: FeedbackSeverity;
|
|
182
|
+
via?: 'agent' | 'human';
|
|
183
|
+
context?: FeedbackContext;
|
|
184
|
+
}
|
|
185
|
+
export interface AbxFeedbackReport extends FeedbackFields {
|
|
186
|
+
area: AbxFeedbackArea;
|
|
187
|
+
}
|
|
188
|
+
export interface ServiceFeedbackReport extends FeedbackFields {
|
|
189
|
+
/** Provider-defined component name; omit when uncertain. */
|
|
190
|
+
component?: string;
|
|
191
|
+
}
|
|
192
|
+
export type FeedbackReport = AbxFeedbackReport | ServiceFeedbackReport;
|
|
193
|
+
export interface FeedbackRecord extends FeedbackFields {
|
|
194
|
+
id: string;
|
|
195
|
+
target?: 'abx' | 'service';
|
|
196
|
+
tenantId?: string | null;
|
|
197
|
+
area?: string;
|
|
198
|
+
component?: string;
|
|
199
|
+
createdAt: string;
|
|
200
|
+
processedAt?: string | null;
|
|
201
|
+
}
|
|
202
|
+
export interface FeedbackListFilters {
|
|
203
|
+
area?: string;
|
|
204
|
+
component?: string;
|
|
205
|
+
kind?: FeedbackKind;
|
|
206
|
+
limit?: number;
|
|
207
|
+
}
|
|
208
|
+
/** The server is authoritative for its current schema; clients keep this extensible. */
|
|
209
|
+
export interface FeedbackInstructions {
|
|
210
|
+
target?: string;
|
|
211
|
+
what?: string;
|
|
212
|
+
authentication?: string;
|
|
213
|
+
yourReports?: string;
|
|
214
|
+
fields?: Record<string, unknown>;
|
|
215
|
+
guidance?: string[];
|
|
216
|
+
example?: unknown;
|
|
217
|
+
[key: string]: unknown;
|
|
218
|
+
}
|
|
105
219
|
/** `POST /v1/projects` — the off-chain bridge: everything the host can't derive from chain. */
|
|
106
220
|
export interface RegisterProjectBody {
|
|
107
221
|
chainId: number;
|
|
@@ -136,6 +250,10 @@ export interface RegisterProjectSummary {
|
|
|
136
250
|
eventCount: number;
|
|
137
251
|
tokenCount: number;
|
|
138
252
|
mintedCount: number;
|
|
253
|
+
/** Official generation, once the indexed factory and on-chain core version agree. */
|
|
254
|
+
contractGeneration?: ContractGenerationSummary;
|
|
255
|
+
/** Sum of every token's current supply — ERC-1155 editions only; absent for a 721 project. */
|
|
256
|
+
copies?: string;
|
|
139
257
|
status?: IndexStatus;
|
|
140
258
|
};
|
|
141
259
|
}
|
|
@@ -167,6 +285,10 @@ export interface RemoteProjectSummary {
|
|
|
167
285
|
eventCount?: number;
|
|
168
286
|
tokenCount?: number;
|
|
169
287
|
mintedCount?: number;
|
|
288
|
+
/** Official generation, once the indexed factory and on-chain core version agree. */
|
|
289
|
+
contractGeneration?: ContractGenerationSummary;
|
|
290
|
+
/** Sum of every token's current supply — ERC-1155 editions only; absent for a 721 project. */
|
|
291
|
+
copies?: string;
|
|
170
292
|
reconstructedAt?: string | null;
|
|
171
293
|
/** Where this project is in the indexing lifecycle — so a list renders "3 live, 1 backfilling,
|
|
172
294
|
* 1 failed" with no per-project round trip. */
|
|
@@ -190,6 +312,10 @@ export interface RemoteProjectStatus {
|
|
|
190
312
|
eventCount: number;
|
|
191
313
|
tokenCount: number;
|
|
192
314
|
mintedCount: number;
|
|
315
|
+
/** Official generation, once the indexed factory and on-chain core version agree. */
|
|
316
|
+
contractGeneration?: ContractGenerationSummary;
|
|
317
|
+
/** Sum of every token's current supply — ERC-1155 editions only; absent for a 721 project. */
|
|
318
|
+
copies?: string;
|
|
193
319
|
reconstructedAt: string | null;
|
|
194
320
|
/** Present on `stale`/`failed`. Credential-free by contract. */
|
|
195
321
|
error?: IndexError;
|
|
@@ -227,9 +353,19 @@ export interface PublishEffectArtifactBody {
|
|
|
227
353
|
output?: string;
|
|
228
354
|
effectKey?: string;
|
|
229
355
|
contentType?: string;
|
|
230
|
-
/**
|
|
356
|
+
/**
|
|
357
|
+
* REFERENCED outputs (`render/image`, a video, a model — anything the service doesn't stitch):
|
|
358
|
+
* an `https://` / `ipfs://` / `ar://` pointer, reachable without the producer's credentials. The
|
|
359
|
+
* service records it and 302-redirects; it never fetches or proxies the bytes. Required for this
|
|
360
|
+
* class — sending {@link bytes_base64} instead is a `400`.
|
|
361
|
+
*/
|
|
231
362
|
locator?: string;
|
|
232
|
-
/**
|
|
363
|
+
/**
|
|
364
|
+
* BOUND outputs only (`render/traits` — content that stitches into the metadata JSON): the raw
|
|
365
|
+
* output, ≤{@link BOUND_ARTIFACT_MAX_BYTES}, held by the service beside the artifact row. Sending
|
|
366
|
+
* a {@link locator} for a bound output is a `400` — the content is assembled into `tokenURI`, so a
|
|
367
|
+
* pointer there would be recorded and then never stitch.
|
|
368
|
+
*/
|
|
233
369
|
bytes_base64?: string;
|
|
234
370
|
}
|
|
235
371
|
/** `POST /v1/effect-status` — a producer reports one run's transient state. */
|
|
@@ -290,6 +426,16 @@ export declare class AbxServiceClient {
|
|
|
290
426
|
constructor(opts: ServiceClientOptions);
|
|
291
427
|
/** The public service descriptor — no auth, safe to fetch before trusting a provider. */
|
|
292
428
|
descriptor(): Promise<ServiceDescriptor>;
|
|
429
|
+
/** Public, machine-readable provider feedback instructions (`abx-service-feedback/v1`). */
|
|
430
|
+
feedbackInstructions(): Promise<FeedbackInstructions>;
|
|
431
|
+
/** File one report. Callers own the human-consent boundary before invoking this write. */
|
|
432
|
+
submitFeedback(report: FeedbackReport): Promise<{
|
|
433
|
+
ok: boolean;
|
|
434
|
+
id: string;
|
|
435
|
+
createdAt: string;
|
|
436
|
+
}>;
|
|
437
|
+
/** Reports visible to this credential at this target. */
|
|
438
|
+
listFeedback(filters?: FeedbackListFilters): Promise<FeedbackRecord[]>;
|
|
293
439
|
/**
|
|
294
440
|
* Register + index a project (the HTTP form of `abx add`; a re-POST is the nudge). Returns the
|
|
295
441
|
* completed summary (HTTP 200) or the accepted-and-still-working shape (HTTP 202) — narrow with
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,MAAM,CAAC;AAC9B,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/dist/service.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The remote-service client — the SDK's one HTTP surface, speaking the provider-neutral
|
|
3
|
-
* control plane pinned by
|
|
3
|
+
* control plane pinned by site/content/docs/using-abx/remote-services.mdx. A client is bound to an
|
|
4
4
|
* endpoint + an injected bearer token, never to a brand: the reference CLI, the effects runner,
|
|
5
5
|
* and any hosted agent drive a self-hosted node and a managed provider through this same class.
|
|
6
6
|
*
|
|
@@ -8,12 +8,75 @@
|
|
|
8
8
|
* credential resolution is the caller's concern (the CLI's named-remote convention lives in
|
|
9
9
|
* packages/cli/src/remote.ts).
|
|
10
10
|
*/
|
|
11
|
+
import { linearBackoffDelay, sleep } from './util.js';
|
|
11
12
|
export const WELL_KNOWN_SERVICE_PATH = '/.well-known/abx-service';
|
|
12
|
-
/**
|
|
13
|
-
*
|
|
13
|
+
/**
|
|
14
|
+
* Versioned interface ids a service declares in its descriptor. Versions ride these ids
|
|
15
|
+
* (they track the `/v1` path prefix); the descriptor has no separate format version.
|
|
16
|
+
*
|
|
17
|
+
* There are three optional interface families, and they are **all-or-nothing**: declaring one asserts every route it names
|
|
18
|
+
* answers per the spec. The artifact-registry routes ride {@link CONTROL_PLANE_INTERFACE} rather
|
|
19
|
+
* than an id of their own — once referenced output is locator-only, accepting a registration is a
|
|
20
|
+
* database insert, so a separate capability flag would describe a distinction that doesn't exist.
|
|
21
|
+
* A service that won't take a given caller's artifacts refuses on the credential (`403`), which is
|
|
22
|
+
* the honest axis: interfaces describe wire grammar, tokens describe permission.
|
|
23
|
+
*/
|
|
14
24
|
export const TOKEN_API_INTERFACE = 'abx-token-api/v1';
|
|
15
25
|
export const CONTROL_PLANE_INTERFACE = 'abx-control-plane/v1';
|
|
16
|
-
|
|
26
|
+
/** Provider-specific feedback discovery, submission, and account history at `/feedback`. Core ABX
|
|
27
|
+
* feedback is deliberately not this interface: it belongs to the ABX team, not a remote provider. */
|
|
28
|
+
export const SERVICE_FEEDBACK_INTERFACE = 'abx-service-feedback/v1';
|
|
29
|
+
/**
|
|
30
|
+
* Why this locator can't be accepted for a referenced artifact, or `null` if it passes.
|
|
31
|
+
*
|
|
32
|
+
* A locator is a **reachability** claim, not a durability one: it must resolve for a third party
|
|
33
|
+
* with no producer credentials and no private-network assumption. The protocol deliberately has
|
|
34
|
+
* **no preference among schemes** — `https://` (S3/R2, a producer's own public base, a chosen
|
|
35
|
+
* IPFS/Arweave gateway), `ipfs://` and `ar://` are peers, because derived output is re-creatable and
|
|
36
|
+
* a producer with an opinion about which gateway serves its content is making an operational call the
|
|
37
|
+
* protocol has no standing to override.
|
|
38
|
+
*
|
|
39
|
+
* Reachability can't be *proved* without fetching, and fetching a third-party URL while handling an
|
|
40
|
+
* authed write is byte custody through the back door plus an SSRF surface. So this checks the two
|
|
41
|
+
* things that are decidable from the string alone and are always wrong:
|
|
42
|
+
* - a private / loopback host — resolvable only from the producer's own network;
|
|
43
|
+
* - a presigned, expiring URL — resolvable now, dead later, which is the worst failure shape
|
|
44
|
+
* (it passes every check at publish time and rots silently).
|
|
45
|
+
*/
|
|
46
|
+
export function locatorRejectionReason(locator) {
|
|
47
|
+
const trimmed = locator.trim();
|
|
48
|
+
if (!/^(https?|ipfs|ar):/i.test(trimmed)) {
|
|
49
|
+
return `unsupported scheme — use https://, ipfs:// or ar://`;
|
|
50
|
+
}
|
|
51
|
+
if (/^https?:/i.test(trimmed)) {
|
|
52
|
+
let url;
|
|
53
|
+
try {
|
|
54
|
+
url = new URL(trimmed);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return 'not a parseable URL';
|
|
58
|
+
}
|
|
59
|
+
const host = url.hostname.toLowerCase().replace(/^\[|\]$/g, '');
|
|
60
|
+
const privateHost = host === 'localhost' ||
|
|
61
|
+
host.endsWith('.localhost') ||
|
|
62
|
+
host === '::1' ||
|
|
63
|
+
host === '0.0.0.0' ||
|
|
64
|
+
/^127\./.test(host) ||
|
|
65
|
+
/^10\./.test(host) ||
|
|
66
|
+
/^192\.168\./.test(host) ||
|
|
67
|
+
/^172\.(1[6-9]|2\d|3[01])\./.test(host) ||
|
|
68
|
+
/^169\.254\./.test(host) ||
|
|
69
|
+
/^f[cd][0-9a-f]{2}:/.test(host);
|
|
70
|
+
if (privateHost) {
|
|
71
|
+
return `'${url.hostname}' is a loopback/private host — a locator must resolve for anyone, not just from the producer's network`;
|
|
72
|
+
}
|
|
73
|
+
const q = url.searchParams;
|
|
74
|
+
if (q.has('X-Amz-Signature') || q.has('Signature') || q.has('X-Goog-Signature') || q.has('sig') || q.has('Expires') || q.has('X-Amz-Expires')) {
|
|
75
|
+
return 'looks like a presigned/expiring URL — it would resolve now and rot later; publish a durable public URL instead';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
17
80
|
/** Statuses a caller can stop waiting on — see {@link AbxServiceClient.awaitIndexed}. */
|
|
18
81
|
export const TERMINAL_INDEX_STATUSES = ['live', 'failed'];
|
|
19
82
|
/** The one message per class. Fixed strings — an upstream error is never interpolated, because a
|
|
@@ -38,6 +101,9 @@ export function classifyIndexError(err) {
|
|
|
38
101
|
}
|
|
39
102
|
return { class: cls, message: INDEX_ERROR_MESSAGES[cls] };
|
|
40
103
|
}
|
|
104
|
+
export const FEEDBACK_KINDS = ['bug', 'friction', 'gap', 'confusion', 'praise', 'other'];
|
|
105
|
+
export const FEEDBACK_SEVERITIES = ['blocker', 'major', 'minor'];
|
|
106
|
+
export const ABX_FEEDBACK_AREAS = ['protocol', 'contracts', 'cli', 'sdk', 'skills', 'docs', 'other'];
|
|
41
107
|
/** Narrow a register response to the deferred-catch-up branch. */
|
|
42
108
|
export function isAccepted(r) {
|
|
43
109
|
return r.accepted === true;
|
|
@@ -122,7 +188,36 @@ export class AbxServiceClient {
|
|
|
122
188
|
}
|
|
123
189
|
/** The public service descriptor — no auth, safe to fetch before trusting a provider. */
|
|
124
190
|
async descriptor() {
|
|
125
|
-
return (await this.request('GET', WELL_KNOWN_SERVICE_PATH, undefined, {
|
|
191
|
+
return (await this.request('GET', WELL_KNOWN_SERVICE_PATH, undefined, {
|
|
192
|
+
attempts: DESCRIPTOR_ATTEMPTS,
|
|
193
|
+
authenticated: false,
|
|
194
|
+
}));
|
|
195
|
+
}
|
|
196
|
+
/** Public, machine-readable provider feedback instructions (`abx-service-feedback/v1`). */
|
|
197
|
+
async feedbackInstructions() {
|
|
198
|
+
return (await this.request('GET', '/feedback', undefined, {
|
|
199
|
+
attempts: DESCRIPTOR_ATTEMPTS,
|
|
200
|
+
authenticated: false,
|
|
201
|
+
}));
|
|
202
|
+
}
|
|
203
|
+
/** File one report. Callers own the human-consent boundary before invoking this write. */
|
|
204
|
+
async submitFeedback(report) {
|
|
205
|
+
return (await this.request('POST', '/feedback', report));
|
|
206
|
+
}
|
|
207
|
+
/** Reports visible to this credential at this target. */
|
|
208
|
+
async listFeedback(filters = {}) {
|
|
209
|
+
const query = new URLSearchParams();
|
|
210
|
+
if (filters.area)
|
|
211
|
+
query.set('area', filters.area);
|
|
212
|
+
if (filters.component)
|
|
213
|
+
query.set('component', filters.component);
|
|
214
|
+
if (filters.kind)
|
|
215
|
+
query.set('kind', filters.kind);
|
|
216
|
+
if (filters.limit !== undefined)
|
|
217
|
+
query.set('limit', String(filters.limit));
|
|
218
|
+
const suffix = query.size ? `?${query}` : '';
|
|
219
|
+
const out = (await this.request('GET', `/feedback/mine${suffix}`));
|
|
220
|
+
return out.feedback ?? [];
|
|
126
221
|
}
|
|
127
222
|
/**
|
|
128
223
|
* Register + index a project (the HTTP form of `abx add`; a re-POST is the nudge). Returns the
|
|
@@ -213,7 +308,7 @@ export class AbxServiceClient {
|
|
|
213
308
|
const attempts = opts?.attempts ?? ATTEMPTS;
|
|
214
309
|
const url = this.baseUrl + path;
|
|
215
310
|
const headers = {};
|
|
216
|
-
if (this.token)
|
|
311
|
+
if (this.token && opts?.authenticated !== false)
|
|
217
312
|
headers['authorization'] = `Bearer ${this.token}`;
|
|
218
313
|
if (body !== undefined)
|
|
219
314
|
headers['content-type'] = 'application/json';
|
|
@@ -243,7 +338,7 @@ export class AbxServiceClient {
|
|
|
243
338
|
return { status: 202, body: resolved };
|
|
244
339
|
}
|
|
245
340
|
if (attempt < attempts)
|
|
246
|
-
await sleep(this.retryDelayMs
|
|
341
|
+
await sleep(linearBackoffDelay(attempt, this.retryDelayMs));
|
|
247
342
|
continue;
|
|
248
343
|
}
|
|
249
344
|
if (resp.ok) {
|
|
@@ -260,7 +355,7 @@ export class AbxServiceClient {
|
|
|
260
355
|
lastClass = said.class;
|
|
261
356
|
lastFailure = said.error ? `${resp.status} ${said.error}` : `${resp.status} ${resp.statusText}`;
|
|
262
357
|
if (attempt < attempts)
|
|
263
|
-
await sleep(this.retryDelayMs
|
|
358
|
+
await sleep(linearBackoffDelay(attempt, this.retryDelayMs));
|
|
264
359
|
continue;
|
|
265
360
|
}
|
|
266
361
|
// A genuine 4xx is an answer, not weather — surface the service's own words + code.
|
|
@@ -313,7 +408,4 @@ async function bodyMessage(resp) {
|
|
|
313
408
|
return {};
|
|
314
409
|
}
|
|
315
410
|
}
|
|
316
|
-
function sleep(ms) {
|
|
317
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
318
|
-
}
|
|
319
411
|
//# sourceMappingURL=service.js.map
|