@integraledger/lcp-binding-canton-x402 0.15.1 → 0.16.1
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 +36 -1
- package/README.md +5 -0
- package/dist/adapter.d.ts +31 -3
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +14 -3
- package/dist/adapter.js.map +1 -1
- package/dist/constants.d.ts +13 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +13 -0
- package/dist/constants.js.map +1 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +2 -2
- package/dist/manifest.js.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +43 -5
- package/src/constants.ts +14 -0
- package/src/manifest.ts +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# @integraledger/lcp-binding-canton-x402
|
|
2
2
|
|
|
3
|
+
## 0.16.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @integraledger/lcp-binding-core@0.16.1
|
|
8
|
+
- @integraledger/lcp-kernel@0.16.1
|
|
9
|
+
|
|
10
|
+
## 0.16.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- e4dde9b: The participant endpoint paths are configuration, not constants this package invents.
|
|
15
|
+
|
|
16
|
+
`makeCantonX402Reader` POSTed to `/v1/updates/transfer` and `/v1/updates/transfers`. Neither names an
|
|
17
|
+
endpoint of any published Daml JSON API version — v1 defines `/v1/create`, `/v1/exercise`, `/v1/query` and
|
|
18
|
+
`/v1/fetch` and no `updates` family, and the update endpoints that do exist live under `/v2/`. Nothing here
|
|
19
|
+
could have caught it: the only assertion over those paths was a stubbed `fetch` compared against the URL
|
|
20
|
+
the code itself builds, so the test and the code restated one guess to each other.
|
|
21
|
+
|
|
22
|
+
The fix is not a better guess. A Canton Coin `TransferFactory_Transfer` is a token-standard object, and
|
|
23
|
+
how a deployment exposes one over HTTP — stock JSON Ledger API version, scan proxy, or a facilitator's own
|
|
24
|
+
service in front of the participant — is a property of that deployment. `CantonX402ReaderConfig` therefore
|
|
25
|
+
requires `transferPath` and `transfersPath`, refuses an empty one at construction rather than POSTing to
|
|
26
|
+
the base URL, and the live harness reads them from `CANTON_X402_TRANSFER_PATH` /
|
|
27
|
+
`CANTON_X402_TRANSFERS_PATH` (mapped in `live-proofs.yml`, so `check:live-rails --check-env` names them
|
|
28
|
+
when a run cannot proceed).
|
|
29
|
+
|
|
30
|
+
**This changes published behaviour**: `makeCantonX402Reader` now needs two more fields and throws without
|
|
31
|
+
them.
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- @integraledger/lcp-binding-core@0.16.0
|
|
36
|
+
- @integraledger/lcp-kernel@0.16.0
|
|
37
|
+
|
|
3
38
|
## 0.15.1
|
|
4
39
|
|
|
5
40
|
### Patch Changes
|
|
@@ -95,7 +130,7 @@ and a large number of documentation claims were corrected against the host speci
|
|
|
95
130
|
First release. Welds an ATR hash into a Canton Coin settlement over x402's `exact` scheme for Canton:
|
|
96
131
|
the seller advertises `PaymentRequirements.extra.memo`, the payer echoes it into the transfer metadata
|
|
97
132
|
under `x402.memo`, and the facilitator rejects `invalid_exact_canton_memo_mismatch` on a mismatch
|
|
98
|
-
(scheme safety check 12). A §8.3.1 Native Field binding, conforms to LCP
|
|
133
|
+
(scheme safety check 12). A §8.3.1 Native Field binding, conforms to the published LCP specification.
|
|
99
134
|
|
|
100
135
|
Split out of `@integraledger/lcp-binding-canton` rather than replacing it: x402's exact-Canton scheme
|
|
101
136
|
settles Canton Coin only, so the `LcpAnchor` overlay remains the carrier for every other Canton
|
package/README.md
CHANGED
|
@@ -49,6 +49,11 @@ const extra = adapter.propose(atrHash); // { memo: "0x…" }
|
|
|
49
49
|
const reader = makeCantonX402Reader({
|
|
50
50
|
jsonLedgerUrl: "https://participant.example",
|
|
51
51
|
bearerJwt: process.env["CANTON_READER_JWT"] ?? "",
|
|
52
|
+
// Your deployment's own paths. This package does not guess them: how a Canton Coin
|
|
53
|
+
// `TransferFactory_Transfer` is exposed over HTTP is a property of the participant, the scan proxy or
|
|
54
|
+
// the facilitator in front of it, not of Canton. An empty string is refused at construction.
|
|
55
|
+
transferPath: process.env["CANTON_X402_TRANSFER_PATH"] ?? "",
|
|
56
|
+
transfersPath: process.env["CANTON_X402_TRANSFERS_PATH"] ?? "",
|
|
52
57
|
});
|
|
53
58
|
const settled = await adapter.observe({ updateId }, reader);
|
|
54
59
|
// { ok: true, value: { state: "settled", atrHash, receiver, amount, instrumentId } }
|
package/dist/adapter.d.ts
CHANGED
|
@@ -89,20 +89,48 @@ export interface CantonX402Adapter {
|
|
|
89
89
|
/** Scan one party's visible transfers for `atrHash` — a participant view, never a global index. */
|
|
90
90
|
enumerate(atrHash: string, party: string, reader: CantonX402Reader, limit?: number): Promise<CantonX402SettlementRef[]>;
|
|
91
91
|
}
|
|
92
|
-
/** Config for a live
|
|
92
|
+
/** Config for a live participant reader over a deployment's HTTP ledger surface. */
|
|
93
93
|
export interface CantonX402ReaderConfig {
|
|
94
|
-
/**
|
|
94
|
+
/** Ledger API base URL — e.g. `https://participant.example`. */
|
|
95
95
|
jsonLedgerUrl: string;
|
|
96
96
|
/** Bearer JWT authenticating the reading party on the participant. */
|
|
97
97
|
bearerJwt: string;
|
|
98
|
+
/**
|
|
99
|
+
* The path, relative to `jsonLedgerUrl`, that answers ONE update id with its transfer view. POSTed a
|
|
100
|
+
* `{ updateId }` body; answers a Daml `{ result, errors }` envelope.
|
|
101
|
+
*
|
|
102
|
+
* ⛔ **REQUIRED, and deliberately not defaulted.** This package shipped `/v1/updates/transfer` as a
|
|
103
|
+
* constant, and that is not an endpoint of any published Daml JSON API version: v1 defines
|
|
104
|
+
* `/v1/create`, `/v1/exercise`, `/v1/query` and `/v1/fetch` and no `updates` family at all, and the
|
|
105
|
+
* update endpoints that do exist live under `/v2/`. Nothing in this repository could have caught it —
|
|
106
|
+
* the only assertion over it is a stubbed `fetch` compared against the URL the code itself builds, so
|
|
107
|
+
* the test and the code restate one guess.
|
|
108
|
+
*
|
|
109
|
+
* The honest shape is configuration rather than a better guess. A Canton Coin
|
|
110
|
+
* `TransferFactory_Transfer` is a token-standard object, and how a given deployment exposes one over
|
|
111
|
+
* HTTP — stock JSON Ledger API version, scan proxy, or a facilitator's own service — is a property of
|
|
112
|
+
* that deployment. This package will not invent it: supply the path your participant answers on.
|
|
113
|
+
*/
|
|
114
|
+
transferPath: string;
|
|
115
|
+
/**
|
|
116
|
+
* The path, relative to `jsonLedgerUrl`, that answers one party's visible transfer update ids. POSTed a
|
|
117
|
+
* `{ party, limit? }` body. REQUIRED for the same reason as {@link CantonX402ReaderConfig.transferPath};
|
|
118
|
+
* it shipped as `/v1/updates/transfers`.
|
|
119
|
+
*/
|
|
120
|
+
transfersPath: string;
|
|
98
121
|
}
|
|
99
122
|
/**
|
|
100
|
-
* A live `CantonX402Reader` over
|
|
123
|
+
* A live `CantonX402Reader` over a participant's HTTP ledger surface, PURE `fetch` — no Daml SDK.
|
|
101
124
|
*
|
|
102
125
|
* Fails LOUD on a non-2xx response or a Daml `errors[]` envelope; an absent update surfaces as `null`,
|
|
103
126
|
* because a reference the participant cannot see is a value the caller must classify, not a transport
|
|
104
127
|
* failure. No package id is required — the memo rides the CIP-56 token-standard transfer, so unlike the
|
|
105
128
|
* overlay this replaced there is no deployment-specific DAR to deploy or configure.
|
|
129
|
+
*
|
|
130
|
+
* ⛔ **The two endpoint paths are yours to supply, and are refused when empty.** See
|
|
131
|
+
* {@link CantonX402ReaderConfig.transferPath}: the constants this once shipped named no endpoint of any
|
|
132
|
+
* published Daml JSON API version, and the only thing asserting them was a stubbed `fetch` compared with
|
|
133
|
+
* the URL this function builds — a test and a code path restating one guess to each other.
|
|
106
134
|
*/
|
|
107
135
|
export declare function makeCantonX402Reader(cfg: CantonX402ReaderConfig): CantonX402Reader;
|
|
108
136
|
/** Construct the Canton x402 adapter. **The manifest is injected, not baked in** — pass this package's own
|
package/dist/adapter.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/adapter.js
CHANGED
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
import { atrHashEquals, isAtrHash } from "@integraledger/lcp-kernel";
|
|
2
2
|
import { readTransferMemoAtrHash, x402MemoRequirement } from "./memo.js";
|
|
3
3
|
/**
|
|
4
|
-
* A live `CantonX402Reader` over
|
|
4
|
+
* A live `CantonX402Reader` over a participant's HTTP ledger surface, PURE `fetch` — no Daml SDK.
|
|
5
5
|
*
|
|
6
6
|
* Fails LOUD on a non-2xx response or a Daml `errors[]` envelope; an absent update surfaces as `null`,
|
|
7
7
|
* because a reference the participant cannot see is a value the caller must classify, not a transport
|
|
8
8
|
* failure. No package id is required — the memo rides the CIP-56 token-standard transfer, so unlike the
|
|
9
9
|
* overlay this replaced there is no deployment-specific DAR to deploy or configure.
|
|
10
|
+
*
|
|
11
|
+
* ⛔ **The two endpoint paths are yours to supply, and are refused when empty.** See
|
|
12
|
+
* {@link CantonX402ReaderConfig.transferPath}: the constants this once shipped named no endpoint of any
|
|
13
|
+
* published Daml JSON API version, and the only thing asserting them was a stubbed `fetch` compared with
|
|
14
|
+
* the URL this function builds — a test and a code path restating one guess to each other.
|
|
10
15
|
*/
|
|
11
16
|
export function makeCantonX402Reader(cfg) {
|
|
12
17
|
if (cfg.jsonLedgerUrl.length === 0)
|
|
13
18
|
throw new Error("makeCantonX402Reader: jsonLedgerUrl is empty");
|
|
14
19
|
if (cfg.bearerJwt.length === 0)
|
|
15
20
|
throw new Error("makeCantonX402Reader: bearerJwt is empty");
|
|
21
|
+
// Fail at CONSTRUCTION, not at the first read: an empty path would POST to the base URL, and a
|
|
22
|
+
// participant answering something at `/` would be read as a transfer view.
|
|
23
|
+
if (cfg.transferPath.length === 0)
|
|
24
|
+
throw new Error("makeCantonX402Reader: transferPath is empty — this package does not guess your participant's update endpoint");
|
|
25
|
+
if (cfg.transfersPath.length === 0)
|
|
26
|
+
throw new Error("makeCantonX402Reader: transfersPath is empty — this package does not guess your participant's update endpoint");
|
|
16
27
|
async function ledgerCall(path, body) {
|
|
17
28
|
const res = await fetch(`${cfg.jsonLedgerUrl}${path}`, {
|
|
18
29
|
method: "POST",
|
|
@@ -35,11 +46,11 @@ export function makeCantonX402Reader(cfg) {
|
|
|
35
46
|
}
|
|
36
47
|
return {
|
|
37
48
|
async transferView(updateId) {
|
|
38
|
-
const result = await ledgerCall(
|
|
49
|
+
const result = await ledgerCall(cfg.transferPath, { updateId });
|
|
39
50
|
return result ?? null;
|
|
40
51
|
},
|
|
41
52
|
async transfersFor(party, limit) {
|
|
42
|
-
return ledgerCall(
|
|
53
|
+
return ledgerCall(cfg.transfersPath, {
|
|
43
54
|
party,
|
|
44
55
|
...(limit !== undefined ? { limit } : {}),
|
|
45
56
|
});
|
package/dist/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -34,4 +34,17 @@ export interface CantonX402NetworkConfig {
|
|
|
34
34
|
* payments settled through x402's Canton-Coin scheme, and `@integraledger/lcp-binding-canton`'s overlay
|
|
35
35
|
* covers everything else. */
|
|
36
36
|
export declare function getCantonX402Config(network: CantonX402Network): CantonX402NetworkConfig;
|
|
37
|
+
/**
|
|
38
|
+
* ⛔⛔ THE COLLECTION PATH THIS RAIL'S `weldGrades` IS KEYED BY — exported so a consumer looks the grade up
|
|
39
|
+
* with the SAME token this manifest declares it under.
|
|
40
|
+
*
|
|
41
|
+
* `binding-evm-x402` shipped `0.15.1` with `weldGrades` keyed `ERC3009` — the escrow sibling's COLLECTOR
|
|
42
|
+
* name — while the value a consumer computes from an x402 offer is `eip3009`. The map and the lookup key
|
|
43
|
+
* disagreed inside one published package, so `weldGrades[assetTransferMethod]` answered `undefined`: the
|
|
44
|
+
* grade absent rather than wrong, which reads as a rail declaring no weld grade at all. Nothing caught it —
|
|
45
|
+
* the profile schema constrains weldGrades VALUES (`signature` | `tx`) and says nothing about keys.
|
|
46
|
+
*
|
|
47
|
+
* ⇒ The key is a constant, not a literal, on every rail. `check:weld-grade-keys` holds it.
|
|
48
|
+
*/
|
|
49
|
+
export declare const CANTON_X402_COLLECTION_PATH = "x402-memo";
|
|
37
50
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAEhD,2FAA2F;AAC3F,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,sEAAsE;AACtE,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjE;uEACuE;AACvE,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,oGAAoG;IACpG,YAAY,EAAE,MAAM,CAAC;IACrB,kGAAkG;IAClG,KAAK,EAAE,MAAM,CAAC;CACf;AAoBD;;8BAE8B;AAC9B,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,iBAAiB,GACzB,uBAAuB,CAIzB"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAEhD,2FAA2F;AAC3F,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,sEAAsE;AACtE,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjE;uEACuE;AACvE,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,oGAAoG;IACpG,YAAY,EAAE,MAAM,CAAC;IACrB,kGAAkG;IAClG,KAAK,EAAE,MAAM,CAAC;CACf;AAoBD;;8BAE8B;AAC9B,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,iBAAiB,GACzB,uBAAuB,CAIzB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,cAAc,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -44,4 +44,17 @@ export function getCantonX402Config(network) {
|
|
|
44
44
|
return DEVNET;
|
|
45
45
|
return MAINNET;
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* ⛔⛔ THE COLLECTION PATH THIS RAIL'S `weldGrades` IS KEYED BY — exported so a consumer looks the grade up
|
|
49
|
+
* with the SAME token this manifest declares it under.
|
|
50
|
+
*
|
|
51
|
+
* `binding-evm-x402` shipped `0.15.1` with `weldGrades` keyed `ERC3009` — the escrow sibling's COLLECTOR
|
|
52
|
+
* name — while the value a consumer computes from an x402 offer is `eip3009`. The map and the lookup key
|
|
53
|
+
* disagreed inside one published package, so `weldGrades[assetTransferMethod]` answered `undefined`: the
|
|
54
|
+
* grade absent rather than wrong, which reads as a rail declaring no weld grade at all. Nothing caught it —
|
|
55
|
+
* the profile schema constrains weldGrades VALUES (`signature` | `tx`) and says nothing about keys.
|
|
56
|
+
*
|
|
57
|
+
* ⇒ The key is a constant, not a literal, on every rail. `check:weld-grade-keys` holds it.
|
|
58
|
+
*/
|
|
59
|
+
export const CANTON_X402_COLLECTION_PATH = "x402-memo";
|
|
47
60
|
//# sourceMappingURL=constants.js.map
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,WAAW,CAAC;AAEhD,2FAA2F;AAC3F,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAe9C,MAAM,OAAO,GAA4B;IACvC,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,uBAAuB;IACrC,KAAK,EAAE,gBAAgB;CACxB,CAAC;AAEF,MAAM,MAAM,GAA4B;IACtC,OAAO,EAAE,QAAQ;IACjB,YAAY,EAAE,qCAAqC;IACnD,KAAK,EAAE,eAAe;CACvB,CAAC;AAEF,MAAM,OAAO,GAA4B;IACvC,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,0BAA0B;IACxC,KAAK,EAAE,gBAAgB;CACxB,CAAC;AAEF;;8BAE8B;AAC9B,MAAM,UAAU,mBAAmB,CACjC,OAA0B;IAE1B,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAC1C,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IACxC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,WAAW,CAAC;AAEhD,2FAA2F;AAC3F,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAe9C,MAAM,OAAO,GAA4B;IACvC,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,uBAAuB;IACrC,KAAK,EAAE,gBAAgB;CACxB,CAAC;AAEF,MAAM,MAAM,GAA4B;IACtC,OAAO,EAAE,QAAQ;IACjB,YAAY,EAAE,qCAAqC;IACnD,KAAK,EAAE,eAAe;CACvB,CAAC;AAEF,MAAM,OAAO,GAA4B;IACvC,OAAO,EAAE,SAAS;IAClB,YAAY,EAAE,0BAA0B;IACxC,KAAK,EAAE,gBAAgB;CACxB,CAAC;AAEF;;8BAE8B;AAC9B,MAAM,UAAU,mBAAmB,CACjC,OAA0B;IAE1B,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAC1C,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IACxC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,WAAW,CAAC"}
|
package/dist/manifest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAMvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,eAAO,MAAM,oBAAoB,EAAE,eAmBlC,CAAC"}
|
package/dist/manifest.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CANTON_X402_MEMO_KEY } from "./constants.js";
|
|
1
|
+
import { CANTON_X402_COLLECTION_PATH, CANTON_X402_MEMO_KEY, } from "./constants.js";
|
|
2
2
|
/**
|
|
3
3
|
* The Canton transfer-memo binding manifest.
|
|
4
4
|
*
|
|
@@ -75,7 +75,7 @@ export const CANTON_X402_MANIFEST = {
|
|
|
75
75
|
reversible: false,
|
|
76
76
|
note: "a Canton transfer consumes the input holdings it names and Canton has no reversal, so an executed transfer's memo is permanent; recourse is the record's elected forum (PAY-3/RCS-5), never dispute resolution",
|
|
77
77
|
},
|
|
78
|
-
weldGrades: {
|
|
78
|
+
weldGrades: { [CANTON_X402_COLLECTION_PATH]: "tx" },
|
|
79
79
|
lifecycleStates: ["proposed", "settled"],
|
|
80
80
|
};
|
|
81
81
|
//# sourceMappingURL=manifest.js.map
|
package/dist/manifest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AACA,OAAO,EACL,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAoB;IACnD,IAAI,EAAE,aAAa;IACnB,OAAO,EAAE,cAAc;IACvB,QAAQ,EAAE,MAAM;IAChB,WAAW,EAAE,oBAAoB;IACjC,QAAQ,EAAE;QACR,OAAO,EAAE,IAAI;QACb,oBAAoB,EAAE,KAAK;QAC3B,gBAAgB,EAAE,KAAK;KACxB;IACD,YAAY,EAAE,SAAS;IACvB,WAAW,EAAE,YAAY;IACzB,QAAQ,EAAE,qCAAqC,oBAAoB,EAAE;IACrE,QAAQ,EAAE;QACR,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE,gNAAgN;KACvN;IACD,UAAU,EAAE,EAAE,CAAC,2BAA2B,CAAC,EAAE,IAAI,EAAE;IACnD,eAAe,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;CACzC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@integraledger/lcp-binding-canton-x402",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.1",
|
|
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.
|
|
47
|
-
"@integraledger/lcp-kernel": "0.
|
|
46
|
+
"@integraledger/lcp-binding-core": "0.16.1",
|
|
47
|
+
"@integraledger/lcp-kernel": "0.16.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "24.13.3",
|
package/src/adapter.ts
CHANGED
|
@@ -100,21 +100,49 @@ export interface CantonX402Adapter {
|
|
|
100
100
|
): Promise<CantonX402SettlementRef[]>;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
/** Config for a live
|
|
103
|
+
/** Config for a live participant reader over a deployment's HTTP ledger surface. */
|
|
104
104
|
export interface CantonX402ReaderConfig {
|
|
105
|
-
/**
|
|
105
|
+
/** Ledger API base URL — e.g. `https://participant.example`. */
|
|
106
106
|
jsonLedgerUrl: string;
|
|
107
107
|
/** Bearer JWT authenticating the reading party on the participant. */
|
|
108
108
|
bearerJwt: string;
|
|
109
|
+
/**
|
|
110
|
+
* The path, relative to `jsonLedgerUrl`, that answers ONE update id with its transfer view. POSTed a
|
|
111
|
+
* `{ updateId }` body; answers a Daml `{ result, errors }` envelope.
|
|
112
|
+
*
|
|
113
|
+
* ⛔ **REQUIRED, and deliberately not defaulted.** This package shipped `/v1/updates/transfer` as a
|
|
114
|
+
* constant, and that is not an endpoint of any published Daml JSON API version: v1 defines
|
|
115
|
+
* `/v1/create`, `/v1/exercise`, `/v1/query` and `/v1/fetch` and no `updates` family at all, and the
|
|
116
|
+
* update endpoints that do exist live under `/v2/`. Nothing in this repository could have caught it —
|
|
117
|
+
* the only assertion over it is a stubbed `fetch` compared against the URL the code itself builds, so
|
|
118
|
+
* the test and the code restate one guess.
|
|
119
|
+
*
|
|
120
|
+
* The honest shape is configuration rather than a better guess. A Canton Coin
|
|
121
|
+
* `TransferFactory_Transfer` is a token-standard object, and how a given deployment exposes one over
|
|
122
|
+
* HTTP — stock JSON Ledger API version, scan proxy, or a facilitator's own service — is a property of
|
|
123
|
+
* that deployment. This package will not invent it: supply the path your participant answers on.
|
|
124
|
+
*/
|
|
125
|
+
transferPath: string;
|
|
126
|
+
/**
|
|
127
|
+
* The path, relative to `jsonLedgerUrl`, that answers one party's visible transfer update ids. POSTed a
|
|
128
|
+
* `{ party, limit? }` body. REQUIRED for the same reason as {@link CantonX402ReaderConfig.transferPath};
|
|
129
|
+
* it shipped as `/v1/updates/transfers`.
|
|
130
|
+
*/
|
|
131
|
+
transfersPath: string;
|
|
109
132
|
}
|
|
110
133
|
|
|
111
134
|
/**
|
|
112
|
-
* A live `CantonX402Reader` over
|
|
135
|
+
* A live `CantonX402Reader` over a participant's HTTP ledger surface, PURE `fetch` — no Daml SDK.
|
|
113
136
|
*
|
|
114
137
|
* Fails LOUD on a non-2xx response or a Daml `errors[]` envelope; an absent update surfaces as `null`,
|
|
115
138
|
* because a reference the participant cannot see is a value the caller must classify, not a transport
|
|
116
139
|
* failure. No package id is required — the memo rides the CIP-56 token-standard transfer, so unlike the
|
|
117
140
|
* overlay this replaced there is no deployment-specific DAR to deploy or configure.
|
|
141
|
+
*
|
|
142
|
+
* ⛔ **The two endpoint paths are yours to supply, and are refused when empty.** See
|
|
143
|
+
* {@link CantonX402ReaderConfig.transferPath}: the constants this once shipped named no endpoint of any
|
|
144
|
+
* published Daml JSON API version, and the only thing asserting them was a stubbed `fetch` compared with
|
|
145
|
+
* the URL this function builds — a test and a code path restating one guess to each other.
|
|
118
146
|
*/
|
|
119
147
|
export function makeCantonX402Reader(
|
|
120
148
|
cfg: CantonX402ReaderConfig,
|
|
@@ -123,6 +151,16 @@ export function makeCantonX402Reader(
|
|
|
123
151
|
throw new Error("makeCantonX402Reader: jsonLedgerUrl is empty");
|
|
124
152
|
if (cfg.bearerJwt.length === 0)
|
|
125
153
|
throw new Error("makeCantonX402Reader: bearerJwt is empty");
|
|
154
|
+
// Fail at CONSTRUCTION, not at the first read: an empty path would POST to the base URL, and a
|
|
155
|
+
// participant answering something at `/` would be read as a transfer view.
|
|
156
|
+
if (cfg.transferPath.length === 0)
|
|
157
|
+
throw new Error(
|
|
158
|
+
"makeCantonX402Reader: transferPath is empty — this package does not guess your participant's update endpoint",
|
|
159
|
+
);
|
|
160
|
+
if (cfg.transfersPath.length === 0)
|
|
161
|
+
throw new Error(
|
|
162
|
+
"makeCantonX402Reader: transfersPath is empty — this package does not guess your participant's update endpoint",
|
|
163
|
+
);
|
|
126
164
|
|
|
127
165
|
async function ledgerCall<T>(path: string, body: unknown): Promise<T> {
|
|
128
166
|
const res = await fetch(`${cfg.jsonLedgerUrl}${path}`, {
|
|
@@ -150,13 +188,13 @@ export function makeCantonX402Reader(
|
|
|
150
188
|
updateId: string,
|
|
151
189
|
): Promise<CantonX402TransferView | null> {
|
|
152
190
|
const result = await ledgerCall<CantonX402TransferView | null>(
|
|
153
|
-
|
|
191
|
+
cfg.transferPath,
|
|
154
192
|
{ updateId },
|
|
155
193
|
);
|
|
156
194
|
return result ?? null;
|
|
157
195
|
},
|
|
158
196
|
async transfersFor(party: string, limit?: number): Promise<string[]> {
|
|
159
|
-
return ledgerCall<string[]>(
|
|
197
|
+
return ledgerCall<string[]>(cfg.transfersPath, {
|
|
160
198
|
party,
|
|
161
199
|
...(limit !== undefined ? { limit } : {}),
|
|
162
200
|
});
|
package/src/constants.ts
CHANGED
|
@@ -63,3 +63,17 @@ export function getCantonX402Config(
|
|
|
63
63
|
if (network === "devnet") return DEVNET;
|
|
64
64
|
return MAINNET;
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* ⛔⛔ THE COLLECTION PATH THIS RAIL'S `weldGrades` IS KEYED BY — exported so a consumer looks the grade up
|
|
69
|
+
* with the SAME token this manifest declares it under.
|
|
70
|
+
*
|
|
71
|
+
* `binding-evm-x402` shipped `0.15.1` with `weldGrades` keyed `ERC3009` — the escrow sibling's COLLECTOR
|
|
72
|
+
* name — while the value a consumer computes from an x402 offer is `eip3009`. The map and the lookup key
|
|
73
|
+
* disagreed inside one published package, so `weldGrades[assetTransferMethod]` answered `undefined`: the
|
|
74
|
+
* grade absent rather than wrong, which reads as a rail declaring no weld grade at all. Nothing caught it —
|
|
75
|
+
* the profile schema constrains weldGrades VALUES (`signature` | `tx`) and says nothing about keys.
|
|
76
|
+
*
|
|
77
|
+
* ⇒ The key is a constant, not a literal, on every rail. `check:weld-grade-keys` holds it.
|
|
78
|
+
*/
|
|
79
|
+
export const CANTON_X402_COLLECTION_PATH = "x402-memo";
|
package/src/manifest.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { BindingManifest } from "@integraledger/lcp-binding-core";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
CANTON_X402_COLLECTION_PATH,
|
|
4
|
+
CANTON_X402_MEMO_KEY,
|
|
5
|
+
} from "./constants.js";
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* The Canton transfer-memo binding manifest.
|
|
@@ -77,6 +80,6 @@ export const CANTON_X402_MANIFEST: BindingManifest = {
|
|
|
77
80
|
reversible: false,
|
|
78
81
|
note: "a Canton transfer consumes the input holdings it names and Canton has no reversal, so an executed transfer's memo is permanent; recourse is the record's elected forum (PAY-3/RCS-5), never dispute resolution",
|
|
79
82
|
},
|
|
80
|
-
weldGrades: {
|
|
83
|
+
weldGrades: { [CANTON_X402_COLLECTION_PATH]: "tx" },
|
|
81
84
|
lifecycleStates: ["proposed", "settled"],
|
|
82
85
|
};
|