@integraledger/lcp-binding-canton-x402 0.16.1 → 0.18.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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @integraledger/lcp-binding-canton-x402
2
2
 
3
+ ## 0.18.0
4
+
5
+ ### Patch Changes
6
+
7
+ - @integraledger/lcp-binding-core@0.18.0
8
+ - @integraledger/lcp-kernel@0.18.0
9
+
10
+ ## 0.17.0
11
+
12
+ ### Patch Changes
13
+
14
+ - @integraledger/lcp-binding-core@0.17.0
15
+ - @integraledger/lcp-kernel@0.17.0
16
+
3
17
  ## 0.16.1
4
18
 
5
19
  ### Patch Changes
package/README.md CHANGED
@@ -93,7 +93,9 @@ carrier is used. No private key is needed; a party's cooperation is.
93
93
 
94
94
  **Not forward-indexable.** A participant's update stream is one participant's view, not a chain-global
95
95
  index, and the memo is a metadata value rather than an indexed key. `enumerate` scans one party's visible
96
- transfers and says so.
96
+ transfers and says so — and its `limit` is required, because the scan depth is a bound somebody has to
97
+ choose and this package does not even guess the endpoint PATH it reads from. Left optional it was
98
+ forwarded verbatim, so the deployment's own default governed and a settlement past it came back as `[]`.
97
99
 
98
100
  **Scoped to x402.** The manifest declares `protocol: "x402"` because the field, its 256-byte ceiling and
99
101
  its enforcement are all x402's. A Canton Coin payment settled outside x402 does not get this carrier — and
package/dist/adapter.d.ts CHANGED
@@ -66,8 +66,18 @@ export interface CantonX402Settlement {
66
66
  export interface CantonX402Reader {
67
67
  /** One settled transfer by ledger update id, or `null` if the participant has no such update. */
68
68
  transferView(updateId: string): Promise<CantonX402TransferView | null>;
69
- /** Update ids of transfers visible to `party`, most recent first. A participant view, not an index. */
70
- transfersFor(party: string, limit?: number): Promise<string[]>;
69
+ /**
70
+ * Update ids of transfers visible to `party`, most recent first. A participant view, not an index.
71
+ *
72
+ * ⛔ **`limit` IS REQUIRED, AND THAT IS THIS RAIL'S ANSWER TO THE SCAN QUESTION.** It used to be
73
+ * optional and forwarded verbatim, so an absent one handed the depth of the scan to whatever the
74
+ * deployment's endpoint defaults to — and a settlement past that default came back as an empty array,
75
+ * indistinguishable from "this party has none". This package will not invent the bound either: it does
76
+ * not even guess the PATH this call goes to ({@link CantonX402ReaderConfig.transfersPath}), so it has no
77
+ * standing to guess that endpoint's page size. The caller names the depth, and a full result is then
78
+ * exactly what the caller asked for rather than a truncation nobody chose.
79
+ */
80
+ transfersFor(party: string, limit: number): Promise<string[]>;
71
81
  }
72
82
  /** The Canton x402 rail's surface. `propose` returns an `extra` fragment for the SELLER to merge into its
73
83
  * `PaymentRequirements` — this rail's weld is committed by the seller and echoed by the payer, unlike the
@@ -86,8 +96,10 @@ export interface CantonX402Adapter {
86
96
  recover(ref: CantonX402SettlementRef, reader: CantonX402Reader): Promise<Outcome<`0x${string}`>>;
87
97
  /** Report the `settled` transition, with the asset the weld is attached to. */
88
98
  observe(ref: CantonX402SettlementRef, reader: CantonX402Reader): Promise<Outcome<CantonX402Settlement>>;
89
- /** Scan one party's visible transfers for `atrHash` — a participant view, never a global index. */
90
- enumerate(atrHash: string, party: string, reader: CantonX402Reader, limit?: number): Promise<CantonX402SettlementRef[]>;
99
+ /** Scan one party's visible transfers for `atrHash` — a participant view, never a global index.
100
+ * `limit` is the scan DEPTH and it is REQUIRED: see {@link CantonX402Reader.transfersFor} for why this
101
+ * package will not pick it, and why an absent one used to mean the endpoint picked instead. */
102
+ enumerate(atrHash: string, party: string, reader: CantonX402Reader, limit: number): Promise<CantonX402SettlementRef[]>;
91
103
  }
92
104
  /** Config for a live participant reader over a deployment's HTTP ledger surface. */
93
105
  export interface CantonX402ReaderConfig {
@@ -118,7 +130,29 @@ export interface CantonX402ReaderConfig {
118
130
  * it shipped as `/v1/updates/transfers`.
119
131
  */
120
132
  transfersPath: string;
133
+ /**
134
+ * Per-request deadline in ms; defaults to {@link CANTON_X402_DEFAULT_TIMEOUT_MS}.
135
+ *
136
+ * ⛔⛔ **`fetch` HAS NO TIMEOUT OF ITS OWN, AND NOTHING HERE SUPPLIED ONE.** A participant that accepted
137
+ * the connection and never answered hung `recover`, `observe` and `enumerate` FOREVER — no error, no
138
+ * refusal, no return. On a surface whose whole contract is to hand back an `Outcome` that is worse than
139
+ * a failure: a caller can retry a refusal and cannot retry a promise that never settles. It bites hardest
140
+ * on `enumerate`, which reads every listed update in a loop, so one unanswered transfer stalls the scan
141
+ * of a party's entire history. The endpoint is a counterparty's own service — this package does not even
142
+ * guess its PATH, so it certainly cannot assume its liveness.
143
+ */
144
+ timeoutMs?: number;
121
145
  }
146
+ /**
147
+ * The default per-request deadline on a participant HTTP call — the same 10s `evidence`'s hardened
148
+ * resolver uses, because it is the same kind of budget: one round trip to a counterparty's endpoint, not
149
+ * a long-poll and not a stream.
150
+ *
151
+ * Deliberately generous rather than tight. A participant under load legitimately takes seconds to answer,
152
+ * and a deadline below what the endpoint needs turns its slow honest answers into transport faults — a
153
+ * different wrong answer, not a fix.
154
+ */
155
+ export declare const CANTON_X402_DEFAULT_TIMEOUT_MS = 10000;
122
156
  /**
123
157
  * A live `CantonX402Reader` over a participant's HTTP ledger surface, PURE `fetch` — no Daml SDK.
124
158
  *
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAIhF;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,kGAAkG;IAClG,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvC,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAC;IACjB,+FAA+F;IAC/F,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,mFAAmF;AACnF,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iGAAiG;IACjG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IACvE,uGAAuG;IACvG,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAChE;AAED;;;6GAG6G;AAC7G,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,sGAAsG;IACtG,OAAO,CACL,GAAG,EAAE,uBAAuB,EAC5B,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC;IACnC,+EAA+E;IAC/E,OAAO,CACL,GAAG,EAAE,uBAAuB,EAC5B,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC1C,mGAAmG;IACnG,SAAS,CACP,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,EACxB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAAC;CACvC;AAED,oFAAoF;AACpF,MAAM,WAAW,sBAAsB;IACrC,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,sBAAsB,GAC1B,gBAAgB,CAsDlB;AAED;;;8GAG8G;AAC9G,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,eAAe,GACxB,iBAAiB,CA4FnB"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAIhF;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,kGAAkG;IAClG,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvC,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAC;IACjB,+FAA+F;IAC/F,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,mFAAmF;AACnF,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iGAAiG;IACjG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IACvE;;;;;;;;;;OAUG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC/D;AAED;;;6GAG6G;AAC7G,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,sGAAsG;IACtG,OAAO,CACL,GAAG,EAAE,uBAAuB,EAC5B,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC;IACnC,+EAA+E;IAC/E,OAAO,CACL,GAAG,EAAE,uBAAuB,EAC5B,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC1C;;oGAEgG;IAChG,SAAS,CACP,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAAC;CACvC;AAED,oFAAoF;AACpF,MAAM,WAAW,sBAAsB;IACrC,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B,QAAS,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,sBAAsB,GAC1B,gBAAgB,CAuElB;AAyBD;;;8GAG8G;AAC9G,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,eAAe,GACxB,iBAAiB,CAsHnB"}
package/dist/adapter.js CHANGED
@@ -1,5 +1,15 @@
1
1
  import { atrHashEquals, isAtrHash } from "@integraledger/lcp-kernel";
2
2
  import { readTransferMemoAtrHash, x402MemoRequirement } from "./memo.js";
3
+ /**
4
+ * The default per-request deadline on a participant HTTP call — the same 10s `evidence`'s hardened
5
+ * resolver uses, because it is the same kind of budget: one round trip to a counterparty's endpoint, not
6
+ * a long-poll and not a stream.
7
+ *
8
+ * Deliberately generous rather than tight. A participant under load legitimately takes seconds to answer,
9
+ * and a deadline below what the endpoint needs turns its slow honest answers into transport faults — a
10
+ * different wrong answer, not a fix.
11
+ */
12
+ export const CANTON_X402_DEFAULT_TIMEOUT_MS = 10_000;
3
13
  /**
4
14
  * A live `CantonX402Reader` over a participant's HTTP ledger surface, PURE `fetch` — no Daml SDK.
5
15
  *
@@ -24,6 +34,7 @@ export function makeCantonX402Reader(cfg) {
24
34
  throw new Error("makeCantonX402Reader: transferPath is empty — this package does not guess your participant's update endpoint");
25
35
  if (cfg.transfersPath.length === 0)
26
36
  throw new Error("makeCantonX402Reader: transfersPath is empty — this package does not guess your participant's update endpoint");
37
+ const timeoutMs = cfg.timeoutMs ?? CANTON_X402_DEFAULT_TIMEOUT_MS;
27
38
  async function ledgerCall(path, body) {
28
39
  const res = await fetch(`${cfg.jsonLedgerUrl}${path}`, {
29
40
  method: "POST",
@@ -32,6 +43,10 @@ export function makeCantonX402Reader(cfg) {
32
43
  authorization: `Bearer ${cfg.bearerJwt}`,
33
44
  },
34
45
  body: JSON.stringify(body),
46
+ // Without this the call never comes back on a participant that accepts and does not answer — see
47
+ // CantonX402ReaderConfig.timeoutMs. `AbortSignal.timeout` rejects with a `TimeoutError`, a throw out
48
+ // of the reader port and therefore a LOUD failure, as every other transport fault here is.
49
+ signal: AbortSignal.timeout(timeoutMs),
35
50
  });
36
51
  if (!res.ok) {
37
52
  const text = await res.text().catch(() => "");
@@ -50,13 +65,44 @@ export function makeCantonX402Reader(cfg) {
50
65
  return result ?? null;
51
66
  },
52
67
  async transfersFor(party, limit) {
53
- return ledgerCall(cfg.transfersPath, {
68
+ const result = await ledgerCall(cfg.transfersPath, {
54
69
  party,
55
- ...(limit !== undefined ? { limit } : {}),
70
+ limit,
56
71
  });
72
+ // ⛔⛔ **A `result: null` PASSED THE ENVELOPE CHECK AND CAME BACK AS AN ARRAY.** `ledgerCall` refuses
73
+ // an ABSENT `result` and `null` is present, so this returned `null` under a declared `string[]` and
74
+ // `enumerate`'s `for…of` threw `TypeError: updateIds is not iterable` — an exception out of a
75
+ // refuse-don't-throw surface, raised by the shape of a counterparty's response. The array is the
76
+ // check rather than not-null, and so is the ELEMENT type: a list carrying a `null` id would be
77
+ // POSTed straight back as `{ updateId: null }` and read as a transfer that is merely absent.
78
+ if (!Array.isArray(result) || result.some((id) => typeof id !== "string"))
79
+ throw new Error(`Daml ${cfg.transfersPath} returned a result that is not an array of update ids — this endpoint is not answering the transfer-listing shape this reader was pointed at`);
80
+ return result;
57
81
  },
58
82
  };
59
83
  }
84
+ /**
85
+ * The asset fields a transfer view must actually carry, named — empty when the view is complete.
86
+ *
87
+ * Non-empty STRINGS, not merely present values: `receiver: ""` names no party and `amount: ""` is no
88
+ * quantity, and a reader that fills its required fields with blanks has answered the type checker rather
89
+ * than the question. `instrumentId` is checked through both of its own halves for the same reason — a
90
+ * `{ admin: "", id: "" }` identifies no instrument.
91
+ */
92
+ function missingAssetFields(view) {
93
+ const text = (v) => typeof v === "string" && v.length > 0;
94
+ const out = [];
95
+ if (!text(view.receiver))
96
+ out.push("receiver");
97
+ if (!text(view.amount))
98
+ out.push("amount");
99
+ if (view.instrumentId === null ||
100
+ typeof view.instrumentId !== "object" ||
101
+ !text(view.instrumentId.admin) ||
102
+ !text(view.instrumentId.id))
103
+ out.push("instrumentId");
104
+ return out;
105
+ }
60
106
  /** Construct the Canton x402 adapter. **The manifest is injected, not baked in** — pass this package's own
61
107
  * `CANTON_X402_MANIFEST`; a manifest whose `rail` is not `"canton:x402"` throws, because an adapter over
62
108
  * another rail's manifest would publish that rail's claims as its own. Nothing has to be deployed first:
@@ -88,6 +134,26 @@ export function createCantonX402Adapter(manifest) {
88
134
  code: "canton/no-lcp-memo",
89
135
  detail: `the transfer at updateId ${ref.updateId} carries no well-formed atrHash under x402.memo`,
90
136
  };
137
+ // ⛔⛔ **THE MEMO WAS CHECKED AND THE ASSET WAS NOT, UNDER TYPES THAT SAID BOTH WERE THERE.**
138
+ // `CantonX402TransferView` declares `receiver`, `amount` and `instrumentId` as REQUIRED, but the view
139
+ // comes off a counterparty's HTTP endpoint through `JSON.parse` — a shape no type checks at runtime —
140
+ // so a reader that omitted them handed back `undefined` and this function copied it into a
141
+ // `CantonX402Settlement` whose own types promise strings. The result is a settled verdict carrying
142
+ // `receiver: undefined`, which a consumer then compares against the merchant it expected and finds
143
+ // unequal, or renders, or writes into a record.
144
+ //
145
+ // ⭐ And it is what makes `assetBinding: "carried"` in this manifest a TRUE claim rather than a hopeful
146
+ // one. That axis says a consumer can reach the asset the weld is attached to. Two lines above, an
147
+ // absent memo refuses loudly by name; the asset fields are the other half of the same promise and were
148
+ // not checked at all. One shape of missing evidence was a refusal and the other was a success.
149
+ const missing = missingAssetFields(view);
150
+ if (missing.length > 0)
151
+ return {
152
+ refused: true,
153
+ haltClass: "verification-failure",
154
+ code: "canton/incomplete-transfer-view",
155
+ detail: `the transfer at updateId ${ref.updateId} carries a well-formed atrHash but no ${missing.join(", ")} — this manifest declares assetBinding "carried", so a settlement whose asset cannot be read is not one this rail can report`,
156
+ };
91
157
  return {
92
158
  ok: true,
93
159
  value: {
@@ -118,6 +184,10 @@ export function createCantonX402Adapter(manifest) {
118
184
  // it would produce is indistinguishable from "this party has no settlements".
119
185
  if (!isAtrHash(atrHash))
120
186
  throw new Error(`enumerate: atrHash must be a 0x-prefixed 32-byte value, got "${atrHash}"`);
187
+ // The same reasoning as the atrHash above, applied to the bound: a scan of zero (or of half a
188
+ // transfer) returns [], which is the answer that cannot be told apart from "no settlements".
189
+ if (!Number.isInteger(limit) || limit < 1)
190
+ throw new Error(`enumerate: limit must be a positive integer — it is the scan DEPTH and this package will not choose it, got ${limit}`);
121
191
  const updateIds = await reader.transfersFor(party, limit);
122
192
  const out = [];
123
193
  for (const updateId of updateIds) {
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { type CantonX402Adapter, type CantonX402Reader, type CantonX402ReaderConfig, type CantonX402Settlement, type CantonX402SettlementRef, type CantonX402TransferView, createCantonX402Adapter, makeCantonX402Reader, } from "./adapter.js";
2
- export { CANTON_X402_MEMO_KEY, CANTON_X402_MEMO_MAX_BYTES, type CantonX402Network, type CantonX402NetworkConfig, getCantonX402Config, } from "./constants.js";
1
+ export { CANTON_X402_DEFAULT_TIMEOUT_MS, type CantonX402Adapter, type CantonX402Reader, type CantonX402ReaderConfig, type CantonX402Settlement, type CantonX402SettlementRef, type CantonX402TransferView, createCantonX402Adapter, makeCantonX402Reader, } from "./adapter.js";
2
+ export { CANTON_X402_COLLECTION_PATH, CANTON_X402_MEMO_KEY, CANTON_X402_MEMO_MAX_BYTES, type CantonX402Network, type CantonX402NetworkConfig, getCantonX402Config, } from "./constants.js";
3
3
  export { CANTON_X402_MANIFEST } from "./manifest.js";
4
4
  export { decodeTransferMemo, encodeTransferMemo, readTransferMemoAtrHash, x402MemoRequirement, } from "./memo.js";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,2BAA2B,EAC3B,oBAAoB,EACpB,0BAA0B,EAC1B,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- export { createCantonX402Adapter, makeCantonX402Reader, } from "./adapter.js";
2
- export { CANTON_X402_MEMO_KEY, CANTON_X402_MEMO_MAX_BYTES, getCantonX402Config, } from "./constants.js";
1
+ export { CANTON_X402_DEFAULT_TIMEOUT_MS, createCantonX402Adapter, makeCantonX402Reader, } from "./adapter.js";
2
+ export { CANTON_X402_COLLECTION_PATH, CANTON_X402_MEMO_KEY, CANTON_X402_MEMO_MAX_BYTES, getCantonX402Config, } from "./constants.js";
3
3
  export { CANTON_X402_MANIFEST } from "./manifest.js";
4
4
  export { decodeTransferMemo, encodeTransferMemo, readTransferMemoAtrHash, x402MemoRequirement, } from "./memo.js";
5
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAG1B,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAO9B,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,2BAA2B,EAC3B,oBAAoB,EACpB,0BAA0B,EAG1B,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,WAAW,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integraledger/lcp-binding-canton-x402",
3
- "version": "0.16.1",
3
+ "version": "0.18.0",
4
4
  "description": "Welds an ATR hash into a Canton Coin settlement over x402's exact scheme.",
5
5
  "keywords": [
6
6
  "lcp",
@@ -43,8 +43,8 @@
43
43
  },
44
44
  "homepage": "https://github.com/IntegraLedger/integra-protocol/tree/main/packages/binding-canton-x402#readme",
45
45
  "dependencies": {
46
- "@integraledger/lcp-binding-core": "0.16.1",
47
- "@integraledger/lcp-kernel": "0.16.1"
46
+ "@integraledger/lcp-binding-core": "0.18.0",
47
+ "@integraledger/lcp-kernel": "0.18.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/node": "24.13.3",
package/src/adapter.ts CHANGED
@@ -66,8 +66,18 @@ export interface CantonX402Settlement {
66
66
  export interface CantonX402Reader {
67
67
  /** One settled transfer by ledger update id, or `null` if the participant has no such update. */
68
68
  transferView(updateId: string): Promise<CantonX402TransferView | null>;
69
- /** Update ids of transfers visible to `party`, most recent first. A participant view, not an index. */
70
- transfersFor(party: string, limit?: number): Promise<string[]>;
69
+ /**
70
+ * Update ids of transfers visible to `party`, most recent first. A participant view, not an index.
71
+ *
72
+ * ⛔ **`limit` IS REQUIRED, AND THAT IS THIS RAIL'S ANSWER TO THE SCAN QUESTION.** It used to be
73
+ * optional and forwarded verbatim, so an absent one handed the depth of the scan to whatever the
74
+ * deployment's endpoint defaults to — and a settlement past that default came back as an empty array,
75
+ * indistinguishable from "this party has none". This package will not invent the bound either: it does
76
+ * not even guess the PATH this call goes to ({@link CantonX402ReaderConfig.transfersPath}), so it has no
77
+ * standing to guess that endpoint's page size. The caller names the depth, and a full result is then
78
+ * exactly what the caller asked for rather than a truncation nobody chose.
79
+ */
80
+ transfersFor(party: string, limit: number): Promise<string[]>;
71
81
  }
72
82
 
73
83
  /** The Canton x402 rail's surface. `propose` returns an `extra` fragment for the SELLER to merge into its
@@ -91,12 +101,14 @@ export interface CantonX402Adapter {
91
101
  ref: CantonX402SettlementRef,
92
102
  reader: CantonX402Reader,
93
103
  ): Promise<Outcome<CantonX402Settlement>>;
94
- /** Scan one party's visible transfers for `atrHash` — a participant view, never a global index. */
104
+ /** Scan one party's visible transfers for `atrHash` — a participant view, never a global index.
105
+ * `limit` is the scan DEPTH and it is REQUIRED: see {@link CantonX402Reader.transfersFor} for why this
106
+ * package will not pick it, and why an absent one used to mean the endpoint picked instead. */
95
107
  enumerate(
96
108
  atrHash: string,
97
109
  party: string,
98
110
  reader: CantonX402Reader,
99
- limit?: number,
111
+ limit: number,
100
112
  ): Promise<CantonX402SettlementRef[]>;
101
113
  }
102
114
 
@@ -129,8 +141,31 @@ export interface CantonX402ReaderConfig {
129
141
  * it shipped as `/v1/updates/transfers`.
130
142
  */
131
143
  transfersPath: string;
144
+ /**
145
+ * Per-request deadline in ms; defaults to {@link CANTON_X402_DEFAULT_TIMEOUT_MS}.
146
+ *
147
+ * ⛔⛔ **`fetch` HAS NO TIMEOUT OF ITS OWN, AND NOTHING HERE SUPPLIED ONE.** A participant that accepted
148
+ * the connection and never answered hung `recover`, `observe` and `enumerate` FOREVER — no error, no
149
+ * refusal, no return. On a surface whose whole contract is to hand back an `Outcome` that is worse than
150
+ * a failure: a caller can retry a refusal and cannot retry a promise that never settles. It bites hardest
151
+ * on `enumerate`, which reads every listed update in a loop, so one unanswered transfer stalls the scan
152
+ * of a party's entire history. The endpoint is a counterparty's own service — this package does not even
153
+ * guess its PATH, so it certainly cannot assume its liveness.
154
+ */
155
+ timeoutMs?: number;
132
156
  }
133
157
 
158
+ /**
159
+ * The default per-request deadline on a participant HTTP call — the same 10s `evidence`'s hardened
160
+ * resolver uses, because it is the same kind of budget: one round trip to a counterparty's endpoint, not
161
+ * a long-poll and not a stream.
162
+ *
163
+ * Deliberately generous rather than tight. A participant under load legitimately takes seconds to answer,
164
+ * and a deadline below what the endpoint needs turns its slow honest answers into transport faults — a
165
+ * different wrong answer, not a fix.
166
+ */
167
+ export const CANTON_X402_DEFAULT_TIMEOUT_MS = 10_000;
168
+
134
169
  /**
135
170
  * A live `CantonX402Reader` over a participant's HTTP ledger surface, PURE `fetch` — no Daml SDK.
136
171
  *
@@ -162,6 +197,8 @@ export function makeCantonX402Reader(
162
197
  "makeCantonX402Reader: transfersPath is empty — this package does not guess your participant's update endpoint",
163
198
  );
164
199
 
200
+ const timeoutMs = cfg.timeoutMs ?? CANTON_X402_DEFAULT_TIMEOUT_MS;
201
+
165
202
  async function ledgerCall<T>(path: string, body: unknown): Promise<T> {
166
203
  const res = await fetch(`${cfg.jsonLedgerUrl}${path}`, {
167
204
  method: "POST",
@@ -170,6 +207,10 @@ export function makeCantonX402Reader(
170
207
  authorization: `Bearer ${cfg.bearerJwt}`,
171
208
  },
172
209
  body: JSON.stringify(body),
210
+ // Without this the call never comes back on a participant that accepts and does not answer — see
211
+ // CantonX402ReaderConfig.timeoutMs. `AbortSignal.timeout` rejects with a `TimeoutError`, a throw out
212
+ // of the reader port and therefore a LOUD failure, as every other transport fault here is.
213
+ signal: AbortSignal.timeout(timeoutMs),
173
214
  });
174
215
  if (!res.ok) {
175
216
  const text = await res.text().catch(() => "");
@@ -193,15 +234,49 @@ export function makeCantonX402Reader(
193
234
  );
194
235
  return result ?? null;
195
236
  },
196
- async transfersFor(party: string, limit?: number): Promise<string[]> {
197
- return ledgerCall<string[]>(cfg.transfersPath, {
237
+ async transfersFor(party: string, limit: number): Promise<string[]> {
238
+ const result = await ledgerCall<unknown>(cfg.transfersPath, {
198
239
  party,
199
- ...(limit !== undefined ? { limit } : {}),
240
+ limit,
200
241
  });
242
+ // ⛔⛔ **A `result: null` PASSED THE ENVELOPE CHECK AND CAME BACK AS AN ARRAY.** `ledgerCall` refuses
243
+ // an ABSENT `result` and `null` is present, so this returned `null` under a declared `string[]` and
244
+ // `enumerate`'s `for…of` threw `TypeError: updateIds is not iterable` — an exception out of a
245
+ // refuse-don't-throw surface, raised by the shape of a counterparty's response. The array is the
246
+ // check rather than not-null, and so is the ELEMENT type: a list carrying a `null` id would be
247
+ // POSTed straight back as `{ updateId: null }` and read as a transfer that is merely absent.
248
+ if (!Array.isArray(result) || result.some((id) => typeof id !== "string"))
249
+ throw new Error(
250
+ `Daml ${cfg.transfersPath} returned a result that is not an array of update ids — this endpoint is not answering the transfer-listing shape this reader was pointed at`,
251
+ );
252
+ return result as string[];
201
253
  },
202
254
  };
203
255
  }
204
256
 
257
+ /**
258
+ * The asset fields a transfer view must actually carry, named — empty when the view is complete.
259
+ *
260
+ * Non-empty STRINGS, not merely present values: `receiver: ""` names no party and `amount: ""` is no
261
+ * quantity, and a reader that fills its required fields with blanks has answered the type checker rather
262
+ * than the question. `instrumentId` is checked through both of its own halves for the same reason — a
263
+ * `{ admin: "", id: "" }` identifies no instrument.
264
+ */
265
+ function missingAssetFields(view: CantonX402TransferView): string[] {
266
+ const text = (v: unknown): boolean => typeof v === "string" && v.length > 0;
267
+ const out: string[] = [];
268
+ if (!text(view.receiver)) out.push("receiver");
269
+ if (!text(view.amount)) out.push("amount");
270
+ if (
271
+ view.instrumentId === null ||
272
+ typeof view.instrumentId !== "object" ||
273
+ !text(view.instrumentId.admin) ||
274
+ !text(view.instrumentId.id)
275
+ )
276
+ out.push("instrumentId");
277
+ return out;
278
+ }
279
+
205
280
  /** Construct the Canton x402 adapter. **The manifest is injected, not baked in** — pass this package's own
206
281
  * `CANTON_X402_MANIFEST`; a manifest whose `rail` is not `"canton:x402"` throws, because an adapter over
207
282
  * another rail's manifest would publish that rail's claims as its own. Nothing has to be deployed first:
@@ -241,6 +316,26 @@ export function createCantonX402Adapter(
241
316
  code: "canton/no-lcp-memo",
242
317
  detail: `the transfer at updateId ${ref.updateId} carries no well-formed atrHash under x402.memo`,
243
318
  };
319
+ // ⛔⛔ **THE MEMO WAS CHECKED AND THE ASSET WAS NOT, UNDER TYPES THAT SAID BOTH WERE THERE.**
320
+ // `CantonX402TransferView` declares `receiver`, `amount` and `instrumentId` as REQUIRED, but the view
321
+ // comes off a counterparty's HTTP endpoint through `JSON.parse` — a shape no type checks at runtime —
322
+ // so a reader that omitted them handed back `undefined` and this function copied it into a
323
+ // `CantonX402Settlement` whose own types promise strings. The result is a settled verdict carrying
324
+ // `receiver: undefined`, which a consumer then compares against the merchant it expected and finds
325
+ // unequal, or renders, or writes into a record.
326
+ //
327
+ // ⭐ And it is what makes `assetBinding: "carried"` in this manifest a TRUE claim rather than a hopeful
328
+ // one. That axis says a consumer can reach the asset the weld is attached to. Two lines above, an
329
+ // absent memo refuses loudly by name; the asset fields are the other half of the same promise and were
330
+ // not checked at all. One shape of missing evidence was a refusal and the other was a success.
331
+ const missing = missingAssetFields(view);
332
+ if (missing.length > 0)
333
+ return {
334
+ refused: true,
335
+ haltClass: "verification-failure",
336
+ code: "canton/incomplete-transfer-view",
337
+ detail: `the transfer at updateId ${ref.updateId} carries a well-formed atrHash but no ${missing.join(", ")} — this manifest declares assetBinding "carried", so a settlement whose asset cannot be read is not one this rail can report`,
338
+ };
244
339
  return {
245
340
  ok: true,
246
341
  value: {
@@ -281,7 +376,7 @@ export function createCantonX402Adapter(
281
376
  atrHash: string,
282
377
  party: string,
283
378
  reader: CantonX402Reader,
284
- limit?: number,
379
+ limit: number,
285
380
  ): Promise<CantonX402SettlementRef[]> {
286
381
  // Fail-fast, like propose: a malformed atrHash can never match a decoded memo, and the silent []
287
382
  // it would produce is indistinguishable from "this party has no settlements".
@@ -289,6 +384,12 @@ export function createCantonX402Adapter(
289
384
  throw new Error(
290
385
  `enumerate: atrHash must be a 0x-prefixed 32-byte value, got "${atrHash}"`,
291
386
  );
387
+ // The same reasoning as the atrHash above, applied to the bound: a scan of zero (or of half a
388
+ // transfer) returns [], which is the answer that cannot be told apart from "no settlements".
389
+ if (!Number.isInteger(limit) || limit < 1)
390
+ throw new Error(
391
+ `enumerate: limit must be a positive integer — it is the scan DEPTH and this package will not choose it, got ${limit}`,
392
+ );
292
393
  const updateIds = await reader.transfersFor(party, limit);
293
394
  const out: CantonX402SettlementRef[] = [];
294
395
  for (const updateId of updateIds) {
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export {
2
+ CANTON_X402_DEFAULT_TIMEOUT_MS,
2
3
  type CantonX402Adapter,
3
4
  type CantonX402Reader,
4
5
  type CantonX402ReaderConfig,
@@ -9,6 +10,7 @@ export {
9
10
  makeCantonX402Reader,
10
11
  } from "./adapter.js";
11
12
  export {
13
+ CANTON_X402_COLLECTION_PATH,
12
14
  CANTON_X402_MEMO_KEY,
13
15
  CANTON_X402_MEMO_MAX_BYTES,
14
16
  type CantonX402Network,