kawasekit 0.3.0 → 0.4.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/dist/{chunk-EUW7AZ4P.js → chunk-FD6Q4NB2.js} +37 -20
- package/dist/chunk-FD6Q4NB2.js.map +1 -0
- package/dist/cli/index.cjs +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/index.cjs +34 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/signer/index.cjs +34 -17
- package/dist/signer/index.cjs.map +1 -1
- package/dist/signer/index.d.cts +40 -20
- package/dist/signer/index.d.ts +40 -20
- package/dist/signer/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-EUW7AZ4P.js.map +0 -1
package/dist/signer/index.d.cts
CHANGED
|
@@ -159,27 +159,28 @@ interface CreateLocalPolicyGatedSignerParams {
|
|
|
159
159
|
declare function createLocalPolicyGatedSigner(params: CreateLocalPolicyGatedSignerParams): PolicyGatedSigner<"advisory">;
|
|
160
160
|
|
|
161
161
|
/**
|
|
162
|
-
* The `mpc-2p` cross-process **wire** — the versioned `CoSignFrame` control
|
|
162
|
+
* The `mpc-2p` cross-process **wire** (v2) — the versioned `CoSignFrame` control
|
|
163
163
|
* envelope + the A3 canonical-request encoding, as TypeScript source-of-truth.
|
|
164
164
|
*
|
|
165
165
|
* This is the public, TS-interpreted half of the two-layer wire (RFC m6-3a §4.2):
|
|
166
166
|
* a small, versioned envelope carries the decoded {@link PaymentIntent} (never a
|
|
167
|
-
* digest — A4)
|
|
168
|
-
* by the WASM crypto agent). The
|
|
169
|
-
* `kawasekit-mpc-2p` Rust serde **byte-for-byte**
|
|
170
|
-
* `session_id`, `
|
|
171
|
-
*
|
|
172
|
-
*
|
|
167
|
+
* digest — A4) + a per-ceremony id + ssid + a freshness element, plus the opaque
|
|
168
|
+
* DKLs round payloads (hex, produced/consumed only by the WASM crypto agent). The
|
|
169
|
+
* shapes here mirror the deployed `kawasekit-mpc-2p` Rust serde **byte-for-byte**
|
|
170
|
+
* (snake_case `wire_version`, `session_id`, `ceremony_id`, `ssid`, `freshness_ts`,
|
|
171
|
+
* `freshness_nonce`, `auth_tag`; the string-encoded {@link WireIntent}), so a frame
|
|
172
|
+
* the SDK builds round-trips through the backend's `serde_json`.
|
|
173
173
|
*
|
|
174
|
-
* `
|
|
175
|
-
* reproduces the backend's `auth::
|
|
176
|
-
*
|
|
174
|
+
* `canonicalRequestBytes` is the A3 analog of the EIP-712 digest corpus: it
|
|
175
|
+
* reproduces the backend's `auth::canonical_request_bytes` exactly, so the injected
|
|
176
|
+
* authenticator's HMAC equals what the co-signer verifies (RFC §4.6:
|
|
177
|
+
* `HMAC_k(wireVersion ‖ ceremonyId ‖ ssid ‖ canonical(intent) ‖ freshness)`).
|
|
177
178
|
*
|
|
178
179
|
* @packageDocumentation
|
|
179
180
|
*/
|
|
180
181
|
|
|
181
182
|
/** The wire protocol version. A frame whose `wire_version` differs is rejected. */
|
|
182
|
-
declare const WIRE_VERSION:
|
|
183
|
+
declare const WIRE_VERSION: 2;
|
|
183
184
|
/**
|
|
184
185
|
* The string-encoded EIP-3009 intent as it crosses the wire — lowercase `0x`
|
|
185
186
|
* addresses, **decimal** integer strings, `0x` hex nonce. Decoupled from any
|
|
@@ -198,6 +199,20 @@ interface WireIntent {
|
|
|
198
199
|
}
|
|
199
200
|
/** Encode a decoded {@link PaymentIntent} for the wire. */
|
|
200
201
|
declare function toWireIntent(intent: PaymentIntent): WireIntent;
|
|
202
|
+
/**
|
|
203
|
+
* The A3 request envelope the adapter generates per `sign()` and authenticates: a
|
|
204
|
+
* per-ceremony id + ssid (bound into the A3 tag) + the intent + a freshness element
|
|
205
|
+
* (a timestamp + a per-request nonce distinct from the EIP-3009 nonce).
|
|
206
|
+
*/
|
|
207
|
+
interface CoSignRequestEnvelope {
|
|
208
|
+
readonly ceremonyId: string;
|
|
209
|
+
readonly ssid: string;
|
|
210
|
+
readonly intent: PaymentIntent;
|
|
211
|
+
/** Unix seconds; the backend checks it against a clock-skew window. */
|
|
212
|
+
readonly freshnessTs: number;
|
|
213
|
+
/** `0x` hex, distinct from the EIP-3009 nonce — the anti-replay key. */
|
|
214
|
+
readonly freshnessNonce: Hex;
|
|
215
|
+
}
|
|
201
216
|
/**
|
|
202
217
|
* A versioned control frame: the only cross-language content of the wire. The
|
|
203
218
|
* DKLs round bytes ride opaque inside `payload`; everything else is the small,
|
|
@@ -208,8 +223,12 @@ type CoSignFrame = {
|
|
|
208
223
|
} & ({
|
|
209
224
|
readonly kind: "request";
|
|
210
225
|
readonly session_id: string;
|
|
226
|
+
readonly ceremony_id: string;
|
|
227
|
+
readonly ssid: string;
|
|
211
228
|
readonly intent: WireIntent;
|
|
212
|
-
|
|
229
|
+
readonly freshness_ts: number;
|
|
230
|
+
readonly freshness_nonce: Hex;
|
|
231
|
+
/** A3 authenticator over {@link canonicalRequestBytes}, `0x`-hex. */
|
|
213
232
|
readonly auth_tag: Hex;
|
|
214
233
|
} | {
|
|
215
234
|
readonly kind: "round";
|
|
@@ -228,13 +247,14 @@ type CoSignFrame = {
|
|
|
228
247
|
readonly message: string;
|
|
229
248
|
});
|
|
230
249
|
/**
|
|
231
|
-
* The A3 canonical encoding of
|
|
232
|
-
* `auth::
|
|
233
|
-
* one `key=value\n` line per field
|
|
234
|
-
*
|
|
235
|
-
*
|
|
250
|
+
* The A3 canonical encoding of a request — a byte-exact mirror of the backend's
|
|
251
|
+
* `auth::canonical_request_bytes` (domain-tag `kawasekit-mpc-2p/cosign-request/v3`,
|
|
252
|
+
* one `key=value\n` line per field: `wireVersion ‖ ceremonyId ‖ ssid ‖
|
|
253
|
+
* canonical(intent) ‖ freshness`; lowercase `0x` addresses + freshness nonce,
|
|
254
|
+
* decimal integers, trailing newline). The injected authenticator HMACs these
|
|
255
|
+
* bytes; because the encoding is shared, the tag equals the co-signer's.
|
|
236
256
|
*/
|
|
237
|
-
declare function
|
|
257
|
+
declare function canonicalRequestBytes(env: CoSignRequestEnvelope): Uint8Array;
|
|
238
258
|
|
|
239
259
|
/**
|
|
240
260
|
* The `mpc-2p` PolicyGatedSigner adapter — `enforcement: "cryptographic"`.
|
|
@@ -302,7 +322,7 @@ interface CoSignTransport {
|
|
|
302
322
|
}
|
|
303
323
|
/** The A3 request authenticator — HMAC (or signature) over the canonical request bytes. */
|
|
304
324
|
interface CoSignRequestAuthenticator {
|
|
305
|
-
/** Authenticator tag over {@link
|
|
325
|
+
/** Authenticator tag over {@link canonicalRequestBytes}; the key stays inside. */
|
|
306
326
|
tag(canonicalRequest: Uint8Array): Hex | Promise<Hex>;
|
|
307
327
|
}
|
|
308
328
|
/** Parameters for {@link createMpc2pPolicyGatedSigner}. */
|
|
@@ -343,4 +363,4 @@ interface Mpc2pSignerParams {
|
|
|
343
363
|
*/
|
|
344
364
|
declare function createMpc2pPolicyGatedSigner(params: Mpc2pSignerParams): PolicyGatedSigner<"cryptographic">;
|
|
345
365
|
|
|
346
|
-
export { type CoSignConnection, type CoSignFrame, type CoSignRequestAuthenticator, type CoSignTransport, CoSignUnavailableError, type CreateLocalPolicyGatedSignerParams, type Mpc2pCoSignAgent, type Mpc2pSignerParams, type Mpc2pStepOutcome, NonBypassableEnforcement, PaymentIntent, PolicyGatedSigner, PolicyGatedSignerConfigError, WIRE_VERSION, type WireIntent, assertNonBypassable,
|
|
366
|
+
export { type CoSignConnection, type CoSignFrame, type CoSignRequestAuthenticator, type CoSignRequestEnvelope, type CoSignTransport, CoSignUnavailableError, type CreateLocalPolicyGatedSignerParams, type Mpc2pCoSignAgent, type Mpc2pSignerParams, type Mpc2pStepOutcome, NonBypassableEnforcement, PaymentIntent, PolicyGatedSigner, PolicyGatedSignerConfigError, WIRE_VERSION, type WireIntent, assertNonBypassable, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, requireNonBypassable, toWireIntent };
|
package/dist/signer/index.d.ts
CHANGED
|
@@ -159,27 +159,28 @@ interface CreateLocalPolicyGatedSignerParams {
|
|
|
159
159
|
declare function createLocalPolicyGatedSigner(params: CreateLocalPolicyGatedSignerParams): PolicyGatedSigner<"advisory">;
|
|
160
160
|
|
|
161
161
|
/**
|
|
162
|
-
* The `mpc-2p` cross-process **wire** — the versioned `CoSignFrame` control
|
|
162
|
+
* The `mpc-2p` cross-process **wire** (v2) — the versioned `CoSignFrame` control
|
|
163
163
|
* envelope + the A3 canonical-request encoding, as TypeScript source-of-truth.
|
|
164
164
|
*
|
|
165
165
|
* This is the public, TS-interpreted half of the two-layer wire (RFC m6-3a §4.2):
|
|
166
166
|
* a small, versioned envelope carries the decoded {@link PaymentIntent} (never a
|
|
167
|
-
* digest — A4)
|
|
168
|
-
* by the WASM crypto agent). The
|
|
169
|
-
* `kawasekit-mpc-2p` Rust serde **byte-for-byte**
|
|
170
|
-
* `session_id`, `
|
|
171
|
-
*
|
|
172
|
-
*
|
|
167
|
+
* digest — A4) + a per-ceremony id + ssid + a freshness element, plus the opaque
|
|
168
|
+
* DKLs round payloads (hex, produced/consumed only by the WASM crypto agent). The
|
|
169
|
+
* shapes here mirror the deployed `kawasekit-mpc-2p` Rust serde **byte-for-byte**
|
|
170
|
+
* (snake_case `wire_version`, `session_id`, `ceremony_id`, `ssid`, `freshness_ts`,
|
|
171
|
+
* `freshness_nonce`, `auth_tag`; the string-encoded {@link WireIntent}), so a frame
|
|
172
|
+
* the SDK builds round-trips through the backend's `serde_json`.
|
|
173
173
|
*
|
|
174
|
-
* `
|
|
175
|
-
* reproduces the backend's `auth::
|
|
176
|
-
*
|
|
174
|
+
* `canonicalRequestBytes` is the A3 analog of the EIP-712 digest corpus: it
|
|
175
|
+
* reproduces the backend's `auth::canonical_request_bytes` exactly, so the injected
|
|
176
|
+
* authenticator's HMAC equals what the co-signer verifies (RFC §4.6:
|
|
177
|
+
* `HMAC_k(wireVersion ‖ ceremonyId ‖ ssid ‖ canonical(intent) ‖ freshness)`).
|
|
177
178
|
*
|
|
178
179
|
* @packageDocumentation
|
|
179
180
|
*/
|
|
180
181
|
|
|
181
182
|
/** The wire protocol version. A frame whose `wire_version` differs is rejected. */
|
|
182
|
-
declare const WIRE_VERSION:
|
|
183
|
+
declare const WIRE_VERSION: 2;
|
|
183
184
|
/**
|
|
184
185
|
* The string-encoded EIP-3009 intent as it crosses the wire — lowercase `0x`
|
|
185
186
|
* addresses, **decimal** integer strings, `0x` hex nonce. Decoupled from any
|
|
@@ -198,6 +199,20 @@ interface WireIntent {
|
|
|
198
199
|
}
|
|
199
200
|
/** Encode a decoded {@link PaymentIntent} for the wire. */
|
|
200
201
|
declare function toWireIntent(intent: PaymentIntent): WireIntent;
|
|
202
|
+
/**
|
|
203
|
+
* The A3 request envelope the adapter generates per `sign()` and authenticates: a
|
|
204
|
+
* per-ceremony id + ssid (bound into the A3 tag) + the intent + a freshness element
|
|
205
|
+
* (a timestamp + a per-request nonce distinct from the EIP-3009 nonce).
|
|
206
|
+
*/
|
|
207
|
+
interface CoSignRequestEnvelope {
|
|
208
|
+
readonly ceremonyId: string;
|
|
209
|
+
readonly ssid: string;
|
|
210
|
+
readonly intent: PaymentIntent;
|
|
211
|
+
/** Unix seconds; the backend checks it against a clock-skew window. */
|
|
212
|
+
readonly freshnessTs: number;
|
|
213
|
+
/** `0x` hex, distinct from the EIP-3009 nonce — the anti-replay key. */
|
|
214
|
+
readonly freshnessNonce: Hex;
|
|
215
|
+
}
|
|
201
216
|
/**
|
|
202
217
|
* A versioned control frame: the only cross-language content of the wire. The
|
|
203
218
|
* DKLs round bytes ride opaque inside `payload`; everything else is the small,
|
|
@@ -208,8 +223,12 @@ type CoSignFrame = {
|
|
|
208
223
|
} & ({
|
|
209
224
|
readonly kind: "request";
|
|
210
225
|
readonly session_id: string;
|
|
226
|
+
readonly ceremony_id: string;
|
|
227
|
+
readonly ssid: string;
|
|
211
228
|
readonly intent: WireIntent;
|
|
212
|
-
|
|
229
|
+
readonly freshness_ts: number;
|
|
230
|
+
readonly freshness_nonce: Hex;
|
|
231
|
+
/** A3 authenticator over {@link canonicalRequestBytes}, `0x`-hex. */
|
|
213
232
|
readonly auth_tag: Hex;
|
|
214
233
|
} | {
|
|
215
234
|
readonly kind: "round";
|
|
@@ -228,13 +247,14 @@ type CoSignFrame = {
|
|
|
228
247
|
readonly message: string;
|
|
229
248
|
});
|
|
230
249
|
/**
|
|
231
|
-
* The A3 canonical encoding of
|
|
232
|
-
* `auth::
|
|
233
|
-
* one `key=value\n` line per field
|
|
234
|
-
*
|
|
235
|
-
*
|
|
250
|
+
* The A3 canonical encoding of a request — a byte-exact mirror of the backend's
|
|
251
|
+
* `auth::canonical_request_bytes` (domain-tag `kawasekit-mpc-2p/cosign-request/v3`,
|
|
252
|
+
* one `key=value\n` line per field: `wireVersion ‖ ceremonyId ‖ ssid ‖
|
|
253
|
+
* canonical(intent) ‖ freshness`; lowercase `0x` addresses + freshness nonce,
|
|
254
|
+
* decimal integers, trailing newline). The injected authenticator HMACs these
|
|
255
|
+
* bytes; because the encoding is shared, the tag equals the co-signer's.
|
|
236
256
|
*/
|
|
237
|
-
declare function
|
|
257
|
+
declare function canonicalRequestBytes(env: CoSignRequestEnvelope): Uint8Array;
|
|
238
258
|
|
|
239
259
|
/**
|
|
240
260
|
* The `mpc-2p` PolicyGatedSigner adapter — `enforcement: "cryptographic"`.
|
|
@@ -302,7 +322,7 @@ interface CoSignTransport {
|
|
|
302
322
|
}
|
|
303
323
|
/** The A3 request authenticator — HMAC (or signature) over the canonical request bytes. */
|
|
304
324
|
interface CoSignRequestAuthenticator {
|
|
305
|
-
/** Authenticator tag over {@link
|
|
325
|
+
/** Authenticator tag over {@link canonicalRequestBytes}; the key stays inside. */
|
|
306
326
|
tag(canonicalRequest: Uint8Array): Hex | Promise<Hex>;
|
|
307
327
|
}
|
|
308
328
|
/** Parameters for {@link createMpc2pPolicyGatedSigner}. */
|
|
@@ -343,4 +363,4 @@ interface Mpc2pSignerParams {
|
|
|
343
363
|
*/
|
|
344
364
|
declare function createMpc2pPolicyGatedSigner(params: Mpc2pSignerParams): PolicyGatedSigner<"cryptographic">;
|
|
345
365
|
|
|
346
|
-
export { type CoSignConnection, type CoSignFrame, type CoSignRequestAuthenticator, type CoSignTransport, CoSignUnavailableError, type CreateLocalPolicyGatedSignerParams, type Mpc2pCoSignAgent, type Mpc2pSignerParams, type Mpc2pStepOutcome, NonBypassableEnforcement, PaymentIntent, PolicyGatedSigner, PolicyGatedSignerConfigError, WIRE_VERSION, type WireIntent, assertNonBypassable,
|
|
366
|
+
export { type CoSignConnection, type CoSignFrame, type CoSignRequestAuthenticator, type CoSignRequestEnvelope, type CoSignTransport, CoSignUnavailableError, type CreateLocalPolicyGatedSignerParams, type Mpc2pCoSignAgent, type Mpc2pSignerParams, type Mpc2pStepOutcome, NonBypassableEnforcement, PaymentIntent, PolicyGatedSigner, PolicyGatedSignerConfigError, WIRE_VERSION, type WireIntent, assertNonBypassable, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, requireNonBypassable, toWireIntent };
|
package/dist/signer/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { WIRE_VERSION,
|
|
1
|
+
export { WIRE_VERSION, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, toWireIntent } from '../chunk-FD6Q4NB2.js';
|
|
2
2
|
export { CoSignUnavailableError, PolicyGatedSignerConfigError, assertNonBypassable, requireNonBypassable } from '../chunk-5TTOAVHE.js';
|
|
3
3
|
import '../chunk-WMVJNPX2.js';
|
|
4
4
|
import '../chunk-6CNAYQOL.js';
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/signer/local.ts","../src/signer/mpc-2p-wire.ts","../src/signer/mpc-2p.ts"],"names":["getAddress"],"mappings":"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","file":"chunk-EUW7AZ4P.js","sourcesContent":["/**\n * The `local` PolicyGatedSigner adapter — `enforcement: \"advisory\"`.\n *\n * Wraps a viem {@link Account} + a {@link SpendingPolicy} + a pinned EIP-712\n * domain. `sign(intent)` evaluates the policy SDK-side and, on pass, produces a\n * real EIP-3009 authorization via {@link signTransferWithAuthorization}. It is\n * **advisory** because the wrapped key can still sign anything elsewhere — the\n * gate is only reached if the caller chooses to call *this* `sign()`. Use it for\n * dev, the A1 cross-language fallback, and any flow that is explicitly not\n * bounded/regulated; the type-gate (`requireNonBypassable`) keeps it out of\n * flows that require non-bypassable enforcement.\n *\n * @packageDocumentation\n */\n\nimport type { Account } from \"viem\";\nimport { getAddress } from \"viem\";\nimport type { SpendingPolicy, SpendState } from \"../policy/spending-policy\";\nimport { evaluateSpendingPolicy } from \"../policy/spending-policy\";\nimport type { X402AssetParam } from \"../tokens/asset-domain\";\nimport { resolveAssetParam, resolvedAssetToEip3009Domain } from \"../tokens/asset-domain\";\nimport { signTransferWithAuthorization } from \"../tokens/eip3009\";\nimport { PolicyGatedSignerConfigError } from \"./errors\";\nimport type { PaymentIntent, PolicyGatedSigner, SignerDescription, SignResult } from \"./types\";\n\n/** Parameters for {@link createLocalPolicyGatedSigner}. */\nexport interface CreateLocalPolicyGatedSignerParams {\n\t/** EOA / LocalAccount that signs the EIP-3009 authorization. */\n\treadonly account: Account;\n\t/** The spending policy this signer enforces (SDK-side, advisory). */\n\treadonly policy: SpendingPolicy;\n\t/** Asset binding — pins the EIP-712 domain `name`/`version`/`verifyingContract`. */\n\treadonly asset: X402AssetParam;\n\t/**\n\t * Required literal acknowledgement that this signer is **advisory** (a\n\t * key-holder can bypass its policy). Omitting it is a compile error (TS) and\n\t * a construction-time throw (JS) — so constructing an advisory signer is a\n\t * conscious, greppable act. For bounded/regulated flows use a cryptographic\n\t * adapter instead.\n\t */\n\treadonly acknowledgeAdvisory: true;\n\t/**\n\t * Optional cumulative-spend view (read-only) the adapter evaluates\n\t * `cumulativeCap` against. `local` does not own an authoritative ledger; the\n\t * caller folds a successful spend back in (e.g. via `mergeSpendState`) before\n\t * the next call. Default: empty.\n\t */\n\treadonly spendState?: () => SpendState | Promise<SpendState>;\n}\n\n/**\n * Construct a `local` (advisory) PolicyGatedSigner.\n *\n * @example\n * ```ts\n * const signer = createLocalPolicyGatedSigner({\n * account,\n * policy: createSpendingPolicy({ session: { id, notAfter }, perToken: [{ token: JPYC, maxPerSign: 1_000n }], recipientAllowlist: \"any\" }),\n * asset: { kind: \"known\", id: \"jpyc-v2\" },\n * acknowledgeAdvisory: true,\n * });\n * const result = await signer.sign(intent);\n * ```\n */\nexport function createLocalPolicyGatedSigner(\n\tparams: CreateLocalPolicyGatedSignerParams,\n): PolicyGatedSigner<\"advisory\"> {\n\tif (params.acknowledgeAdvisory !== true) {\n\t\tthrow new PolicyGatedSignerConfigError(\n\t\t\t\"acknowledgeAdvisory\",\n\t\t\t\"a local signer is advisory (a key-holder can bypass its policy); pass `acknowledgeAdvisory: true` to construct one consciously, or use a cryptographic adapter for bounded/regulated flows\",\n\t\t);\n\t}\n\n\tconst { account, policy, spendState } = params;\n\tconst pinned = resolveAssetParam(params.asset);\n\tconst from = getAddress(account.address);\n\n\treturn {\n\t\tenforcement: \"advisory\",\n\t\tfrom,\n\t\tasync sign(intent: PaymentIntent): Promise<SignResult> {\n\t\t\tif (getAddress(intent.from) !== from) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\treason: \"from_mismatch\",\n\t\t\t\t\t\tdetail: `intent.from ${getAddress(intent.from)} does not equal signer.from ${from}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (getAddress(intent.token) !== pinned.verifyingContract) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\treason: \"token_not_allowed\",\n\t\t\t\t\t\tdetail: `intent.token ${getAddress(intent.token)} does not equal the signer's pinned verifyingContract ${pinned.verifyingContract}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst state: SpendState = (await spendState?.()) ?? { spentPerToken: [] };\n\t\t\tconst nowSeconds = BigInt(Math.floor(Date.now() / 1000));\n\t\t\tconst decision = evaluateSpendingPolicy(policy, intent, state, nowSeconds);\n\t\t\tif (!decision.ok) {\n\t\t\t\treturn { ok: false, rejection: decision.rejection };\n\t\t\t}\n\n\t\t\tconst signed = await signTransferWithAuthorization(\n\t\t\t\taccount,\n\t\t\t\tresolvedAssetToEip3009Domain(pinned, intent.chainId),\n\t\t\t\t{\n\t\t\t\t\tfrom,\n\t\t\t\t\tto: intent.to,\n\t\t\t\t\tvalue: intent.value,\n\t\t\t\t\tvalidAfter: intent.validAfter,\n\t\t\t\t\tvalidBefore: intent.validBefore,\n\t\t\t\t\tnonce: intent.nonce,\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { ok: true, signature: signed.signature, intent };\n\t\t},\n\t\tdescribe(): SignerDescription {\n\t\t\treturn {\n\t\t\t\tenforcement: \"advisory\",\n\t\t\t\tfrom,\n\t\t\t\tpolicyId: policy.session.id,\n\t\t\t\tnotAfter: policy.session.notAfter,\n\t\t\t\trevoked: policy.revoked,\n\t\t\t};\n\t\t},\n\t};\n}\n","/**\n * The `mpc-2p` cross-process **wire** — the versioned `CoSignFrame` control\n * envelope + the A3 canonical-request encoding, as TypeScript source-of-truth.\n *\n * This is the public, TS-interpreted half of the two-layer wire (RFC m6-3a §4.2):\n * a small, versioned envelope carries the decoded {@link PaymentIntent} (never a\n * digest — A4) plus the opaque DKLs round payloads (hex, produced/consumed only\n * by the WASM crypto agent). The shapes here mirror the deployed\n * `kawasekit-mpc-2p` Rust serde **byte-for-byte** (snake_case `wire_version`,\n * `session_id`, `auth_tag`; the string-encoded {@link WireIntent}), so a frame the\n * SDK builds round-trips through the backend's `serde_json`. The richer envelope\n * (ceremonyId / ssid / A3 freshness) is a later slice.\n *\n * `canonicalIntentBytes` is the A3 analog of the EIP-712 digest corpus: it\n * reproduces the backend's `auth::canonical_intent_bytes` exactly, so the\n * injected authenticator's HMAC equals what the co-signer verifies.\n *\n * @packageDocumentation\n */\n\nimport type { Hex } from \"viem\";\nimport type { PaymentIntent } from \"./types\";\n\n/** The wire protocol version. A frame whose `wire_version` differs is rejected. */\nexport const WIRE_VERSION = 1 as const;\n\n/**\n * The string-encoded EIP-3009 intent as it crosses the wire — lowercase `0x`\n * addresses, **decimal** integer strings, `0x` hex nonce. Decoupled from any\n * library's native serde so a stdlib client reproduces it trivially; matches the\n * Rust `WireIntent` field names + encoding exactly.\n */\nexport interface WireIntent {\n\treadonly token: string;\n\treadonly chain_id: number;\n\treadonly from: string;\n\treadonly to: string;\n\treadonly value: string;\n\treadonly valid_after: string;\n\treadonly valid_before: string;\n\treadonly nonce: string;\n}\n\n/** Encode a decoded {@link PaymentIntent} for the wire. */\nexport function toWireIntent(intent: PaymentIntent): WireIntent {\n\treturn {\n\t\ttoken: intent.token.toLowerCase(),\n\t\tchain_id: intent.chainId,\n\t\tfrom: intent.from.toLowerCase(),\n\t\tto: intent.to.toLowerCase(),\n\t\tvalue: intent.value.toString(),\n\t\tvalid_after: intent.validAfter.toString(),\n\t\tvalid_before: intent.validBefore.toString(),\n\t\tnonce: intent.nonce.toLowerCase(),\n\t};\n}\n\n/**\n * A versioned control frame: the only cross-language content of the wire. The\n * DKLs round bytes ride opaque inside `payload`; everything else is the small,\n * pinned envelope. Internally tagged by `kind` (matches the Rust serde).\n */\nexport type CoSignFrame = { readonly wire_version: typeof WIRE_VERSION } & (\n\t| {\n\t\t\treadonly kind: \"request\";\n\t\t\treadonly session_id: string;\n\t\t\treadonly intent: WireIntent;\n\t\t\t/** A3 authenticator over {@link canonicalIntentBytes}, `0x`-hex. */\n\t\t\treadonly auth_tag: Hex;\n\t }\n\t| { readonly kind: \"round\"; readonly payload: Hex }\n\t| { readonly kind: \"result\"; readonly r: Hex; readonly s: Hex; readonly v: number }\n\t| { readonly kind: \"rejection\"; readonly reason: string; readonly detail: string }\n\t| { readonly kind: \"error\"; readonly message: string }\n);\n\n/**\n * The A3 canonical encoding of an intent — a byte-exact mirror of the backend's\n * `auth::canonical_intent_bytes` (domain-tag `kawasekit-mpc-2p/cosign-request/v2`,\n * one `key=value\\n` line per field, lowercase `0x` addresses, decimal integers,\n * `0x` hex nonce, trailing newline). The injected authenticator HMACs these bytes;\n * because the encoding is shared, the tag equals the co-signer's.\n */\nexport function canonicalIntentBytes(intent: PaymentIntent): Uint8Array {\n\tconst lines = [\n\t\t\"kawasekit-mpc-2p/cosign-request/v2\",\n\t\t`token=${intent.token.toLowerCase()}`,\n\t\t`chainId=${intent.chainId}`,\n\t\t`from=${intent.from.toLowerCase()}`,\n\t\t`to=${intent.to.toLowerCase()}`,\n\t\t`value=${intent.value}`,\n\t\t`validAfter=${intent.validAfter}`,\n\t\t`validBefore=${intent.validBefore}`,\n\t\t`nonce=${intent.nonce.toLowerCase()}`,\n\t];\n\treturn new TextEncoder().encode(lines.map((l) => `${l}\\n`).join(\"\"));\n}\n","/**\n * The `mpc-2p` PolicyGatedSigner adapter — `enforcement: \"cryptographic\"`.\n *\n * A 2-of-2 MPC co-signer: the agent holds ONE DKLs share, the owner backend holds\n * the other + the authoritative policy gate. No valid signature exists without a\n * **policy-passing co-sign**, so — unlike `local` — a single key-holder cannot\n * bypass the policy. That is what earns the non-bypassable `\"cryptographic\"` label\n * and lets the M6-0 type-gate (`requireNonBypassable`) reject an advisory signer at\n * compile time in bounded flows.\n *\n * **Open-core / thin adapter.** This module is pure orchestration over injected\n * interfaces — it ships in the public SDK with **no crypto, no socket, no key**:\n *\n * - {@link Mpc2pCoSignAgent} — the WASM DKLs share (the private package's compiled\n * `crypto-core`); drives the agent's half of the ceremony round-by-round.\n * - {@link CoSignTransport} — the authenticated, encrypted (wss/mTLS) frame channel\n * to the owner backend (the private package's transport).\n * - {@link CoSignRequestAuthenticator} — the A3 HMAC (the pre-shared key never\n * enters this module).\n *\n * The adapter owns the protocol: it pins the EIP-712 domain, **re-derives the\n * digest from the intent (A4)** via the shared `transferWithAuthorizationTypes`\n * source-of-truth, computes the A3 canonical bytes, frames the versioned\n * {@link CoSignFrame} envelope, pumps the ceremony, and maps the terminal frame to\n * a {@link SignResult}. Crucially it has **no local-signing path**: any\n * transport/availability failure throws {@link CoSignUnavailableError}, never an\n * `{ ok: true }` and never a {@link PolicyRejection} (the no-silent-fallback\n * guarantee, RFC m6-3a constraint 3 / W8).\n *\n * @packageDocumentation\n */\n\nimport type { Address, Hex } from \"viem\";\nimport { getAddress, hashTypedData, serializeSignature } from \"viem\";\nimport type { X402AssetParam } from \"../tokens/asset-domain\";\nimport { resolveAssetParam, resolvedAssetToEip3009Domain } from \"../tokens/asset-domain\";\nimport { transferWithAuthorizationTypes } from \"../tokens/eip3009\";\nimport { CoSignUnavailableError, PolicyGatedSignerConfigError } from \"./errors\";\nimport type { CoSignFrame } from \"./mpc-2p-wire\";\nimport { canonicalIntentBytes, toWireIntent, WIRE_VERSION } from \"./mpc-2p-wire\";\nimport type {\n\tPaymentIntent,\n\tPolicyGatedSigner,\n\tPolicyRejection,\n\tSignerDescription,\n\tSignResult,\n} from \"./types\";\n\n/** The agent's half of the 2-of-2 ceremony (the injected WASM DKLs share). */\nexport interface Mpc2pCoSignAgent {\n\t/** The group 2-of-2 EOA this share controls — must equal the signer's `from`. */\n\tgroupEoa(): Address;\n\t/** Begin signing the 32-byte EIP-712 `digest`; returns the first outbound round (hex). */\n\tstart(digest: Hex): Hex;\n\t/** Feed one inbound round (hex); returns the next outbound round, or the final signature. */\n\tstep(incoming: Hex): Mpc2pStepOutcome;\n}\n\n/** The result of one {@link Mpc2pCoSignAgent.step}. */\nexport type Mpc2pStepOutcome =\n\t| { readonly outbound: Hex }\n\t| { readonly signature: { readonly r: Hex; readonly s: Hex; readonly v: number } };\n\n/** One authenticated, encrypted ceremony connection to the owner backend. */\nexport interface CoSignConnection {\n\t/** Send one control frame. */\n\tsend(frame: CoSignFrame): Promise<void>;\n\t/** Receive the next control frame (resolves per round). */\n\trecv(): Promise<CoSignFrame>;\n\t/** Release the connection (best-effort; errors here are ignored). */\n\tclose(): void | Promise<void>;\n}\n\n/** Opens a wss/mTLS {@link CoSignConnection} for a single co-sign ceremony. */\nexport interface CoSignTransport {\n\tconnect(): Promise<CoSignConnection>;\n}\n\n/** The A3 request authenticator — HMAC (or signature) over the canonical request bytes. */\nexport interface CoSignRequestAuthenticator {\n\t/** Authenticator tag over {@link canonicalIntentBytes}; the key stays inside. */\n\ttag(canonicalRequest: Uint8Array): Hex | Promise<Hex>;\n}\n\n/** Parameters for {@link createMpc2pPolicyGatedSigner}. */\nexport interface Mpc2pSignerParams {\n\t/** The group 2-of-2 EOA; every `intent.from` must equal this (asserted vs the agent). */\n\treadonly from: Address;\n\t/** Asset binding — pins the EIP-712 domain `name`/`version`/`verifyingContract` (A4). */\n\treadonly asset: X402AssetParam;\n\t/** The bound policy session, for `describe()` (the backend holds the authoritative policy). */\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\t/** The injected WASM DKLs share (private package). */\n\treadonly agent: Mpc2pCoSignAgent;\n\t/** The injected wss/mTLS frame channel (private package). */\n\treadonly transport: CoSignTransport;\n\t/** The injected A3 authenticator (the pre-shared key never enters the SDK). */\n\treadonly authenticator: CoSignRequestAuthenticator;\n}\n\n/**\n * The backend `rejection` reasons that are genuine **policy denials** (the owner\n * decided \"no\" — audit-meaningful → `{ ok: false, rejection }`). Any other reason\n * on a rejection frame is treated as \"the owner did not cleanly decide\" and throws\n * {@link CoSignUnavailableError} (no-silent-fallback; never a misclassified denial).\n */\nconst POLICY_REASONS: ReadonlySet<PolicyRejection[\"reason\"]> = new Set([\n\t\"revoked\",\n\t\"expired\",\n\t\"token_not_allowed\",\n\t\"recipient_not_allowed\",\n\t\"amount_exceeds_per_sign\",\n\t\"amount_exceeds_cumulative\",\n\t\"intent_digest_mismatch\",\n\t\"unauthenticated\",\n\t\"from_mismatch\",\n\t\"nonce_reuse_conflict\",\n]);\n\nfunction rejection(reason: PolicyRejection[\"reason\"], detail: string): SignResult {\n\treturn { ok: false, rejection: { reason, detail } };\n}\n\n/**\n * Construct an `mpc-2p` (cryptographic) PolicyGatedSigner over injected agent +\n * transport + authenticator.\n *\n * @example\n * ```ts\n * // The agent, transport and authenticator come from the private `kawasekit-mpc-2p`\n * // package (the WASM share, the wss/mTLS client, the HMAC key) — never bundled here.\n * const signer = createMpc2pPolicyGatedSigner({\n * from: groupEoa,\n * asset: { kind: \"known\", id: \"jpyc-v2\" },\n * session: { id: \"sess-1\", notAfter: 2_000_000_000n },\n * agent, transport, authenticator,\n * });\n * requireNonBypassable(signer); // ✓ \"cryptographic\" — passes the type-gate\n * const result = await signer.sign(intent);\n * ```\n */\nexport function createMpc2pPolicyGatedSigner(\n\tparams: Mpc2pSignerParams,\n): PolicyGatedSigner<\"cryptographic\"> {\n\tconst { agent, transport, authenticator, session } = params;\n\tconst pinned = resolveAssetParam(params.asset);\n\tconst from = getAddress(params.from);\n\n\t// The injected share MUST control the declared group EOA, or every signature\n\t// would recover to the wrong address.\n\tconst agentEoa = getAddress(agent.groupEoa());\n\tif (agentEoa !== from) {\n\t\tthrow new PolicyGatedSignerConfigError(\n\t\t\t\"from\",\n\t\t\t`the agent share controls ${agentEoa} but params.from is ${from}`,\n\t\t);\n\t}\n\n\treturn {\n\t\tenforcement: \"cryptographic\",\n\t\tfrom,\n\t\tasync sign(intent: PaymentIntent): Promise<SignResult> {\n\t\t\t// Adapter-local pre-checks (cheap; no wire needed). Same shape as `local`.\n\t\t\tif (getAddress(intent.from) !== from) {\n\t\t\t\treturn rejection(\n\t\t\t\t\t\"from_mismatch\",\n\t\t\t\t\t`intent.from ${getAddress(intent.from)} does not equal signer.from ${from}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (getAddress(intent.token) !== pinned.verifyingContract) {\n\t\t\t\treturn rejection(\n\t\t\t\t\t\"token_not_allowed\",\n\t\t\t\t\t`intent.token ${getAddress(intent.token)} does not equal the signer's pinned verifyingContract ${pinned.verifyingContract}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// A4: re-derive the EIP-712 digest from the intent + the pinned domain (the\n\t\t\t// SDK's exported types are the cross-language source of truth). The agent and\n\t\t\t// the backend each sign THIS digest; the SoT keeps them byte-identical.\n\t\t\tconst digest = hashTypedData({\n\t\t\t\tdomain: resolvedAssetToEip3009Domain(pinned, intent.chainId),\n\t\t\t\ttypes: transferWithAuthorizationTypes,\n\t\t\t\tprimaryType: \"TransferWithAuthorization\",\n\t\t\t\tmessage: {\n\t\t\t\t\tfrom,\n\t\t\t\t\tto: intent.to,\n\t\t\t\t\tvalue: intent.value,\n\t\t\t\t\tvalidAfter: intent.validAfter,\n\t\t\t\t\tvalidBefore: intent.validBefore,\n\t\t\t\t\tnonce: intent.nonce,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// A3: authenticate the request (the canonical bytes are the shared SoT; the\n\t\t\t// HMAC key lives inside the injected authenticator).\n\t\t\tconst authTag = await authenticator.tag(canonicalIntentBytes(intent));\n\n\t\t\tconst conn = await openConnection(transport);\n\t\t\ttry {\n\t\t\t\treturn await runCeremony(conn, agent, session.id, intent, digest, authTag);\n\t\t\t} finally {\n\t\t\t\ttry {\n\t\t\t\t\tawait conn.close();\n\t\t\t\t} catch {\n\t\t\t\t\t// best-effort cleanup; a close error must not mask the result/throw.\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tdescribe(): SignerDescription {\n\t\t\treturn {\n\t\t\t\tenforcement: \"cryptographic\",\n\t\t\t\tfrom,\n\t\t\t\tpolicyId: session.id,\n\t\t\t\tnotAfter: session.notAfter,\n\t\t\t\t// The backend owns authoritative revocation (a revoked session → a\n\t\t\t\t// rejection at sign time); this metadata field is best-effort.\n\t\t\t\trevoked: false,\n\t\t\t};\n\t\t},\n\t};\n}\n\nasync function openConnection(transport: CoSignTransport): Promise<CoSignConnection> {\n\ttry {\n\t\treturn await transport.connect();\n\t} catch (cause) {\n\t\tthrow new CoSignUnavailableError(\"co-signer connection failed\", { cause });\n\t}\n}\n\n/**\n * Drive the full ceremony over `conn`: send the authenticated request + the agent's\n * first round, then pump rounds until a terminal frame. Returns a {@link SignResult}\n * (success or a policy denial) or throws {@link CoSignUnavailableError}. There is no\n * path that returns `{ ok: true }` without a backend `result` frame.\n */\nasync function runCeremony(\n\tconn: CoSignConnection,\n\tagent: Mpc2pCoSignAgent,\n\tsessionId: string,\n\tintent: PaymentIntent,\n\tdigest: Hex,\n\tauthTag: Hex,\n): Promise<SignResult> {\n\tconst send = async (frame: CoSignFrame): Promise<void> => {\n\t\ttry {\n\t\t\tawait conn.send(frame);\n\t\t} catch (cause) {\n\t\t\tthrow new CoSignUnavailableError(\"co-sign connection dropped while sending\", { cause });\n\t\t}\n\t};\n\tconst recv = async (): Promise<CoSignFrame> => {\n\t\tlet frame: CoSignFrame;\n\t\ttry {\n\t\t\tframe = await conn.recv();\n\t\t} catch (cause) {\n\t\t\tthrow new CoSignUnavailableError(\"co-sign connection dropped mid-ceremony\", { cause });\n\t\t}\n\t\tif (frame.wire_version !== WIRE_VERSION) {\n\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t`co-signer spoke wire_version ${frame.wire_version}, expected ${WIRE_VERSION}`,\n\t\t\t);\n\t\t}\n\t\treturn frame;\n\t};\n\n\tawait send({\n\t\twire_version: WIRE_VERSION,\n\t\tkind: \"request\",\n\t\tsession_id: sessionId,\n\t\tintent: toWireIntent(intent),\n\t\tauth_tag: authTag,\n\t});\n\n\tlet first: Hex;\n\ttry {\n\t\tfirst = agent.start(digest);\n\t} catch (cause) {\n\t\tthrow new CoSignUnavailableError(\"the agent failed to start the ceremony\", { cause });\n\t}\n\tawait send({ wire_version: WIRE_VERSION, kind: \"round\", payload: first });\n\n\tlet agentSig: { r: Hex; s: Hex; v: number } | null = null;\n\tfor (;;) {\n\t\tconst frame = await recv();\n\t\tswitch (frame.kind) {\n\t\t\tcase \"round\": {\n\t\t\t\tlet step: Mpc2pStepOutcome;\n\t\t\t\ttry {\n\t\t\t\t\tstep = agent.step(frame.payload);\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tthrow new CoSignUnavailableError(\"the agent rejected a round frame\", { cause });\n\t\t\t\t}\n\t\t\t\tif (\"outbound\" in step) {\n\t\t\t\t\tawait send({ wire_version: WIRE_VERSION, kind: \"round\", payload: step.outbound });\n\t\t\t\t} else {\n\t\t\t\t\tagentSig = step.signature;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"result\": {\n\t\t\t\tif (agentSig === null) {\n\t\t\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t\t\t\"the backend returned a result before the agent derived a signature\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tframe.r.toLowerCase() !== agentSig.r.toLowerCase() ||\n\t\t\t\t\tframe.s.toLowerCase() !== agentSig.s.toLowerCase() ||\n\t\t\t\t\tframe.v !== agentSig.v\n\t\t\t\t) {\n\t\t\t\t\tthrow new CoSignUnavailableError(\"the backend and agent derived different signatures\");\n\t\t\t\t}\n\t\t\t\treturn { ok: true, signature: assembleSignature(agentSig), intent };\n\t\t\t}\n\t\t\tcase \"rejection\": {\n\t\t\t\t// A genuine policy denial → typed rejection. A non-policy \"rejection\"\n\t\t\t\t// (transient/internal) is \"the owner did not decide\" → no-fallback throw.\n\t\t\t\tif (POLICY_REASONS.has(frame.reason as PolicyRejection[\"reason\"])) {\n\t\t\t\t\t// reason membership verified against POLICY_REASONS above.\n\t\t\t\t\treturn rejection(frame.reason as PolicyRejection[\"reason\"], frame.detail);\n\t\t\t\t}\n\t\t\t\tthrow new CoSignUnavailableError(\n\t\t\t\t\t`co-signer returned a non-policy rejection (${frame.reason}): ${frame.detail}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tcase \"error\": {\n\t\t\t\tthrow new CoSignUnavailableError(`co-signer error: ${frame.message}`);\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\t// Unknown frame kind — never a silent success.\n\t\t\t\tthrow new CoSignUnavailableError(\"co-signer sent an unexpected frame\");\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Assemble a 65-byte EIP-3009 signature from the agent's `{ r, s, v }` (v = recovery_id + 27). */\nfunction assembleSignature(sig: { r: Hex; s: Hex; v: number }): Hex {\n\tconst yParity = sig.v - 27;\n\tif (yParity !== 0 && yParity !== 1) {\n\t\tthrow new CoSignUnavailableError(`malformed recovery id v=${sig.v} (expected 27 or 28)`);\n\t}\n\treturn serializeSignature({ r: sig.r, s: sig.s, yParity });\n}\n"]}
|