kawasekit 0.3.0 → 0.5.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-G3UC6SME.js → chunk-P5563RGP.js} +3 -3
- package/dist/{chunk-G3UC6SME.js.map → chunk-P5563RGP.js.map} +1 -1
- package/dist/{chunk-EUW7AZ4P.js → chunk-S2ZSX2VS.js} +158 -36
- package/dist/chunk-S2ZSX2VS.js.map +1 -0
- package/dist/{chunk-5TTOAVHE.js → chunk-VJUXTVSW.js} +11 -3
- package/dist/chunk-VJUXTVSW.js.map +1 -0
- package/dist/cli/index.cjs +1 -1
- package/dist/cli/index.js +4 -4
- package/dist/index.cjs +163 -33
- 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 +3 -3
- package/dist/signer/index.cjs +164 -33
- package/dist/signer/index.cjs.map +1 -1
- package/dist/signer/index.d.cts +96 -20
- package/dist/signer/index.d.ts +96 -20
- package/dist/signer/index.js +2 -2
- package/dist/x402/index.cjs.map +1 -1
- package/dist/x402/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-5TTOAVHE.js.map +0 -1
- package/dist/chunk-EUW7AZ4P.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -8,7 +8,7 @@ export { C as ChainNotSupportedError, g as getChain, i as isSupportedChainId, s
|
|
|
8
8
|
export { C as ConfiguredKernelClient, I as IssueSessionKeyParams, K as KAWASEKIT_SESSION_ENVELOPE_VERSION, a as KawasekitSessionEnvelope, b as KawasekitSessionEnvelopeVersion, c as KawasekitSessionPolicySummary, R as RestoreSessionAccountParams, d as RevokeSessionKeyParams, e as RevokeSessionKeyResult, f as RotateSessionKeyParams, g as RotateSessionKeyResult, S as SessionEnvelopeChainMismatchError, h as SessionEnvelopeParseError, i as SessionEnvelopeSignerMismatchError, j as SessionEnvelopeVersionError, T as TransferJpycInputError, k as TransferJpycParams, l as TransferJpycResult, m as issueSessionKey, p as parseSessionEnvelope, r as restoreSessionAccount, n as revokeSessionKey, o as rotateSessionKey, s as serializeSessionEnvelope, t as transferJpyc } from './index-DFChv_fT.cjs';
|
|
9
9
|
export { CreateJpycDailyLimitPoliciesParams, ONE_DAY_SECONDS, createJpycDailyLimitPolicies } from './policy/index.cjs';
|
|
10
10
|
export { C as CreateSpendingPolicyParams, P as PolicyDecision, S as SpendState, a as SpendingPolicy, b as SpendingPolicyConfigError, T as TokenLimit, c as createSpendingPolicy, e as evaluateSpendingPolicy, m as mergeSpendState } from './spending-policy-CGIaBpg-.cjs';
|
|
11
|
-
export { CoSignConnection, CoSignFrame, CoSignRequestAuthenticator, CoSignTransport, CoSignUnavailableError, CreateLocalPolicyGatedSignerParams, Mpc2pCoSignAgent, Mpc2pSignerParams, Mpc2pStepOutcome, PolicyGatedSignerConfigError, WIRE_VERSION, WireIntent, assertNonBypassable,
|
|
11
|
+
export { CoSignConnection, CoSignFrame, CoSignRequestAuthenticator, CoSignRequestEnvelope, CoSignTransport, CoSignUnavailableError, CreateLocalPolicyGatedSignerParams, Mpc2pCoSignAgent, Mpc2pSignerParams, Mpc2pStepOutcome, PolicyGatedSignerConfigError, WIRE_VERSION, WireIntent, assertNonBypassable, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, requireNonBypassable, toWireIntent } from './signer/index.cjs';
|
|
12
12
|
export { E as EnforcementLevel, N as NonBypassableEnforcement, P as PaymentIntent, a as PolicyGatedSigner, b as PolicyRejection, S as SignResult, c as SignerDescription } from './types-BLJU67HZ.cjs';
|
|
13
13
|
export { C as CancelAuthorizationMessage, E as Eip3009Domain, K as KnownAssetDomain, a as KnownAssetId, R as ReceiveWithAuthorizationMessage, b as ResolvedAsset, S as SignedAuthorization, T as TransferWithAuthorizationMessage, X as X402AssetParam, c as X402TokenDomain, d as authorizationDeadlineFromNow, e as cancelAuthorizationTypes, f as deriveAuthorizationNonce, g as generateAuthorizationNonce, h as getKnownAssetDomain, l as listKnownAssetIds, r as receiveWithAuthorizationTypes, i as resolvedAssetToEip3009Domain, s as signCancelAuthorization, j as signReceiveWithAuthorization, k as signTransferWithAuthorization, t as transferWithAuthorizationTypes } from './asset-domain-4Ioxqn28.cjs';
|
|
14
14
|
export { B as BuildPaymentRequiredResponseParams, a as BuildPaymentRequirementsParams, C as CreateCoinbaseFacilitatorParams, b as CreateHttpFacilitatorParams, c as CreateSelfFacilitatorParams, d as CreateX402PaymentSignerParams, K as KawaseChain, S as SignX402PaymentParams, W as WrapFetchParams, X as X402Fetch, e as X402InvalidConfigError, f as X402InvalidPayloadError, g as X402PaymentSigner, h as X402PolicyRejectedError, i as X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS, j as X402_DEFAULT_MAX_TIMEOUT_SECONDS, k as X402_FACILITATOR_ERROR_CODES, l as X402_HEADER_IDEMPOTENCY_KEY, m as X402_HEADER_PAYMENT_REQUIRED, n as X402_HEADER_PAYMENT_RESPONSE, o as X402_HEADER_PAYMENT_SIGNATURE, p as buildPaymentRequiredResponse, q as buildPaymentRequirements, r as createCoinbaseFacilitator, s as createHttpFacilitator, t as createSelfFacilitator, u as createX402PaymentSigner, v as decodePaymentRequiredHeader, w as decodePaymentResponseHeader, x as decodePaymentSignatureHeader, y as deriveReceiptTimeoutMs, z as encodePaymentRequiredHeader, A as encodePaymentResponseHeader, D as encodePaymentSignatureHeader, E as wrapFetch, F as zerodevRpcUrl } from './index-CAmTA8xR.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { C as ChainNotSupportedError, g as getChain, i as isSupportedChainId, s
|
|
|
8
8
|
export { C as ConfiguredKernelClient, I as IssueSessionKeyParams, K as KAWASEKIT_SESSION_ENVELOPE_VERSION, a as KawasekitSessionEnvelope, b as KawasekitSessionEnvelopeVersion, c as KawasekitSessionPolicySummary, R as RestoreSessionAccountParams, d as RevokeSessionKeyParams, e as RevokeSessionKeyResult, f as RotateSessionKeyParams, g as RotateSessionKeyResult, S as SessionEnvelopeChainMismatchError, h as SessionEnvelopeParseError, i as SessionEnvelopeSignerMismatchError, j as SessionEnvelopeVersionError, T as TransferJpycInputError, k as TransferJpycParams, l as TransferJpycResult, m as issueSessionKey, p as parseSessionEnvelope, r as restoreSessionAccount, n as revokeSessionKey, o as rotateSessionKey, s as serializeSessionEnvelope, t as transferJpyc } from './index-CSpNGigO.js';
|
|
9
9
|
export { CreateJpycDailyLimitPoliciesParams, ONE_DAY_SECONDS, createJpycDailyLimitPolicies } from './policy/index.js';
|
|
10
10
|
export { C as CreateSpendingPolicyParams, P as PolicyDecision, S as SpendState, a as SpendingPolicy, b as SpendingPolicyConfigError, T as TokenLimit, c as createSpendingPolicy, e as evaluateSpendingPolicy, m as mergeSpendState } from './spending-policy-BD2Mpm-L.js';
|
|
11
|
-
export { CoSignConnection, CoSignFrame, CoSignRequestAuthenticator, CoSignTransport, CoSignUnavailableError, CreateLocalPolicyGatedSignerParams, Mpc2pCoSignAgent, Mpc2pSignerParams, Mpc2pStepOutcome, PolicyGatedSignerConfigError, WIRE_VERSION, WireIntent, assertNonBypassable,
|
|
11
|
+
export { CoSignConnection, CoSignFrame, CoSignRequestAuthenticator, CoSignRequestEnvelope, CoSignTransport, CoSignUnavailableError, CreateLocalPolicyGatedSignerParams, Mpc2pCoSignAgent, Mpc2pSignerParams, Mpc2pStepOutcome, PolicyGatedSignerConfigError, WIRE_VERSION, WireIntent, assertNonBypassable, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, requireNonBypassable, toWireIntent } from './signer/index.js';
|
|
12
12
|
export { E as EnforcementLevel, N as NonBypassableEnforcement, P as PaymentIntent, a as PolicyGatedSigner, b as PolicyRejection, S as SignResult, c as SignerDescription } from './types-BLJU67HZ.js';
|
|
13
13
|
export { C as CancelAuthorizationMessage, E as Eip3009Domain, K as KnownAssetDomain, a as KnownAssetId, R as ReceiveWithAuthorizationMessage, b as ResolvedAsset, S as SignedAuthorization, T as TransferWithAuthorizationMessage, X as X402AssetParam, c as X402TokenDomain, d as authorizationDeadlineFromNow, e as cancelAuthorizationTypes, f as deriveAuthorizationNonce, g as generateAuthorizationNonce, h as getKnownAssetDomain, l as listKnownAssetIds, r as receiveWithAuthorizationTypes, i as resolvedAssetToEip3009Domain, s as signCancelAuthorization, j as signReceiveWithAuthorization, k as signTransferWithAuthorization, t as transferWithAuthorizationTypes } from './asset-domain-4Ioxqn28.js';
|
|
14
14
|
export { B as BuildPaymentRequiredResponseParams, a as BuildPaymentRequirementsParams, C as CreateCoinbaseFacilitatorParams, b as CreateHttpFacilitatorParams, c as CreateSelfFacilitatorParams, d as CreateX402PaymentSignerParams, K as KawaseChain, S as SignX402PaymentParams, W as WrapFetchParams, X as X402Fetch, e as X402InvalidConfigError, f as X402InvalidPayloadError, g as X402PaymentSigner, h as X402PolicyRejectedError, i as X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS, j as X402_DEFAULT_MAX_TIMEOUT_SECONDS, k as X402_FACILITATOR_ERROR_CODES, l as X402_HEADER_IDEMPOTENCY_KEY, m as X402_HEADER_PAYMENT_REQUIRED, n as X402_HEADER_PAYMENT_RESPONSE, o as X402_HEADER_PAYMENT_SIGNATURE, p as buildPaymentRequiredResponse, q as buildPaymentRequirements, r as createCoinbaseFacilitator, s as createHttpFacilitator, t as createSelfFacilitator, u as createX402PaymentSigner, v as decodePaymentRequiredHeader, w as decodePaymentResponseHeader, x as decodePaymentSignatureHeader, y as deriveReceiptTimeoutMs, z as encodePaymentRequiredHeader, A as encodePaymentResponseHeader, D as encodePaymentSignatureHeader, E as wrapFetch, F as zerodevRpcUrl } from './index-C9tbaHPF.js';
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export { TransferJpycInputError, transferJpyc } from './chunk-RJLDKDWL.js';
|
|
2
|
-
export { X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS, X402_FACILITATOR_ERROR_CODES, createCoinbaseFacilitator, createHttpFacilitator, createSelfFacilitator, createX402PaymentSigner, deriveReceiptTimeoutMs, wrapFetch } from './chunk-
|
|
2
|
+
export { X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS, X402_FACILITATOR_ERROR_CODES, createCoinbaseFacilitator, createHttpFacilitator, createSelfFacilitator, createX402PaymentSigner, deriveReceiptTimeoutMs, wrapFetch } from './chunk-P5563RGP.js';
|
|
3
3
|
export { X402_DEFAULT_MAX_TIMEOUT_SECONDS, X402_HEADER_IDEMPOTENCY_KEY, X402_HEADER_PAYMENT_REQUIRED, X402_HEADER_PAYMENT_RESPONSE, X402_HEADER_PAYMENT_SIGNATURE, buildPaymentRequiredResponse, buildPaymentRequirements, createX402Handler, decodePaymentRequiredHeader, decodePaymentResponseHeader, decodePaymentSignatureHeader, encodePaymentRequiredHeader, encodePaymentResponseHeader, encodePaymentSignatureHeader } from './chunk-PVUKX6IF.js';
|
|
4
4
|
export { extractAcceptedNetworks, invokeHookSafely } from './chunk-LEHWRDVS.js';
|
|
5
5
|
export { createIdempotencyKeyBuilder, createInMemoryIdempotencyStore, deriveIdempotencyKey, normalizeIntentText } from './chunk-TTX3RBIZ.js';
|
|
6
6
|
export { IdempotencyConfigError, IdempotencyRecordParseError, IdempotencyRecordVersionError, KAWASEKIT_IDEMPOTENCY_RECORD_VERSION, X402_VERSION, chainIdToX402Network, isX402Network, parseIdempotencyRecord, serializeIdempotencyRecord, x402NetworkToChainId } from './chunk-QHUCU5YX.js';
|
|
7
7
|
export { KAWASEKIT_SESSION_ENVELOPE_VERSION, SessionEnvelopeChainMismatchError, SessionEnvelopeParseError, SessionEnvelopeSignerMismatchError, SessionEnvelopeVersionError, createAgentSmartAccount, issueSessionKey, parseSessionEnvelope, restoreSessionAccount, revokeSessionKey, rotateSessionKey, serializeSessionEnvelope } from './chunk-N3CVLISJ.js';
|
|
8
|
-
export { WIRE_VERSION,
|
|
9
|
-
export { CoSignUnavailableError, PolicyGatedSignerConfigError, assertNonBypassable, authorizationDeadlineFromNow, cancelAuthorizationTypes, deriveAuthorizationNonce, generateAuthorizationNonce, getKnownAssetDomain, listKnownAssetIds, receiveWithAuthorizationTypes, requireNonBypassable, resolvedAssetToEip3009Domain, signCancelAuthorization, signReceiveWithAuthorization, signTransferWithAuthorization, transferWithAuthorizationTypes } from './chunk-
|
|
8
|
+
export { WIRE_VERSION, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, toWireIntent } from './chunk-S2ZSX2VS.js';
|
|
9
|
+
export { CoSignUnavailableError, PolicyGatedSignerConfigError, assertNonBypassable, authorizationDeadlineFromNow, cancelAuthorizationTypes, deriveAuthorizationNonce, generateAuthorizationNonce, getKnownAssetDomain, listKnownAssetIds, receiveWithAuthorizationTypes, requireNonBypassable, resolvedAssetToEip3009Domain, signCancelAuthorization, signReceiveWithAuthorization, signTransferWithAuthorization, transferWithAuthorizationTypes } from './chunk-VJUXTVSW.js';
|
|
10
10
|
export { X402InvalidConfigError, X402InvalidPayloadError, X402PolicyRejectedError } from './chunk-WMVJNPX2.js';
|
|
11
11
|
export { ONE_DAY_SECONDS, createJpycDailyLimitPolicies } from './chunk-E47SIVFY.js';
|
|
12
12
|
export { SpendingPolicyConfigError, createSpendingPolicy, evaluateSpendingPolicy, mergeSpendState } from './chunk-6CNAYQOL.js';
|
package/dist/signer/index.cjs
CHANGED
|
@@ -17,9 +17,17 @@ var PolicyGatedSignerConfigError = class extends Error {
|
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
var CoSignUnavailableError = class extends Error {
|
|
20
|
+
/**
|
|
21
|
+
* `true` when the failure is the **transient transport class** (connect failed /
|
|
22
|
+
* connection dropped) — the only class the adapter's bounded retry replays
|
|
23
|
+
* (RFC m6-3a §4.7: never a delivered rejection, never a ban/identifiable-abort,
|
|
24
|
+
* never a protocol anomaly or timeout). Defaults to `false`.
|
|
25
|
+
*/
|
|
26
|
+
transient;
|
|
20
27
|
constructor(message, options) {
|
|
21
|
-
super(message, options);
|
|
28
|
+
super(message, options?.cause === void 0 ? void 0 : { cause: options.cause });
|
|
22
29
|
this.name = "CoSignUnavailableError";
|
|
30
|
+
this.transient = options?.transient ?? false;
|
|
23
31
|
}
|
|
24
32
|
};
|
|
25
33
|
|
|
@@ -362,7 +370,8 @@ function createLocalPolicyGatedSigner(params) {
|
|
|
362
370
|
}
|
|
363
371
|
|
|
364
372
|
// src/signer/mpc-2p-wire.ts
|
|
365
|
-
var WIRE_VERSION =
|
|
373
|
+
var WIRE_VERSION = 2;
|
|
374
|
+
var MAX_FRAME_BYTES = 8 * 1024 * 1024;
|
|
366
375
|
function toWireIntent(intent) {
|
|
367
376
|
return {
|
|
368
377
|
token: intent.token.toLowerCase(),
|
|
@@ -375,17 +384,23 @@ function toWireIntent(intent) {
|
|
|
375
384
|
nonce: intent.nonce.toLowerCase()
|
|
376
385
|
};
|
|
377
386
|
}
|
|
378
|
-
function
|
|
387
|
+
function canonicalRequestBytes(env) {
|
|
388
|
+
const i = env.intent;
|
|
379
389
|
const lines = [
|
|
380
|
-
"kawasekit-mpc-2p/cosign-request/
|
|
381
|
-
|
|
382
|
-
`
|
|
383
|
-
`
|
|
384
|
-
`
|
|
385
|
-
`
|
|
386
|
-
`
|
|
387
|
-
`
|
|
388
|
-
`
|
|
390
|
+
"kawasekit-mpc-2p/cosign-request/v3",
|
|
391
|
+
"wireVersion=2",
|
|
392
|
+
`ceremonyId=${env.ceremonyId}`,
|
|
393
|
+
`ssid=${env.ssid}`,
|
|
394
|
+
`token=${i.token.toLowerCase()}`,
|
|
395
|
+
`chainId=${i.chainId}`,
|
|
396
|
+
`from=${i.from.toLowerCase()}`,
|
|
397
|
+
`to=${i.to.toLowerCase()}`,
|
|
398
|
+
`value=${i.value}`,
|
|
399
|
+
`validAfter=${i.validAfter}`,
|
|
400
|
+
`validBefore=${i.validBefore}`,
|
|
401
|
+
`nonce=${i.nonce.toLowerCase()}`,
|
|
402
|
+
`freshnessTs=${env.freshnessTs}`,
|
|
403
|
+
`freshnessNonce=${env.freshnessNonce.toLowerCase()}`
|
|
389
404
|
];
|
|
390
405
|
return new TextEncoder().encode(lines.map((l) => `${l}
|
|
391
406
|
`).join(""));
|
|
@@ -411,6 +426,12 @@ function createMpc2pPolicyGatedSigner(params) {
|
|
|
411
426
|
const { agent, transport, authenticator, session } = params;
|
|
412
427
|
const pinned = resolveAssetParam(params.asset);
|
|
413
428
|
const from = viem.getAddress(params.from);
|
|
429
|
+
const wire = params.wire ?? {};
|
|
430
|
+
const maxAttempts = Math.max(1, wire.maxAttempts ?? 2);
|
|
431
|
+
const ceremonyTimeoutMs = wire.ceremonyTimeoutMs ?? 3e4;
|
|
432
|
+
const minWindowSecs = wire.minWindowSecs ?? 30;
|
|
433
|
+
const clockSkewBudgetSecs = wire.clockSkewBudgetSecs ?? 30;
|
|
434
|
+
const maxFrameBytes = wire.maxFrameBytes ?? MAX_FRAME_BYTES;
|
|
414
435
|
const agentEoa = viem.getAddress(agent.groupEoa());
|
|
415
436
|
if (agentEoa !== from) {
|
|
416
437
|
throw new PolicyGatedSignerConfigError(
|
|
@@ -447,16 +468,59 @@ function createMpc2pPolicyGatedSigner(params) {
|
|
|
447
468
|
nonce: intent.nonce
|
|
448
469
|
}
|
|
449
470
|
});
|
|
450
|
-
const
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
471
|
+
const validBeforeSecs = Number(intent.validBefore);
|
|
472
|
+
const nowSecs = Math.floor(Date.now() / 1e3);
|
|
473
|
+
if (validBeforeSecs - nowSecs < minWindowSecs + clockSkewBudgetSecs) {
|
|
474
|
+
throw new CoSignUnavailableError(
|
|
475
|
+
`intent.validBefore (${validBeforeSecs}) leaves under the minimum ceremony window (${minWindowSecs}s + ${clockSkewBudgetSecs}s clock-skew budget) \u2014 refusing a co-sign that risks being born expired (W11)`
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
const deadlineMs = Math.min(
|
|
479
|
+
Date.now() + ceremonyTimeoutMs,
|
|
480
|
+
(validBeforeSecs - clockSkewBudgetSecs) * 1e3
|
|
481
|
+
);
|
|
482
|
+
let lastTransient;
|
|
483
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
484
|
+
if (Date.now() >= deadlineMs) break;
|
|
485
|
+
const env = {
|
|
486
|
+
ceremonyId: globalThis.crypto.randomUUID(),
|
|
487
|
+
ssid: globalThis.crypto.randomUUID(),
|
|
488
|
+
intent,
|
|
489
|
+
freshnessTs: Math.floor(Date.now() / 1e3),
|
|
490
|
+
freshnessNonce: viem.toHex(globalThis.crypto.getRandomValues(new Uint8Array(16)))
|
|
491
|
+
};
|
|
492
|
+
const authTag = await authenticator.tag(canonicalRequestBytes(env));
|
|
455
493
|
try {
|
|
456
|
-
await
|
|
457
|
-
|
|
494
|
+
const conn = await openConnection(transport);
|
|
495
|
+
try {
|
|
496
|
+
return await runCeremony({
|
|
497
|
+
conn,
|
|
498
|
+
agent,
|
|
499
|
+
sessionId: session.id,
|
|
500
|
+
env,
|
|
501
|
+
digest,
|
|
502
|
+
authTag,
|
|
503
|
+
from,
|
|
504
|
+
deadlineMs,
|
|
505
|
+
maxFrameBytes
|
|
506
|
+
});
|
|
507
|
+
} finally {
|
|
508
|
+
try {
|
|
509
|
+
await conn.close();
|
|
510
|
+
} catch {
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
} catch (error) {
|
|
514
|
+
if (error instanceof CoSignUnavailableError && error.transient && attempt < maxAttempts) {
|
|
515
|
+
lastTransient = error;
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
throw error;
|
|
458
519
|
}
|
|
459
520
|
}
|
|
521
|
+
throw lastTransient ?? new CoSignUnavailableError(
|
|
522
|
+
"co-sign ceremony budget exhausted before validBefore (W11) \u2014 no attempt could start"
|
|
523
|
+
);
|
|
460
524
|
},
|
|
461
525
|
describe() {
|
|
462
526
|
return {
|
|
@@ -475,23 +539,32 @@ async function openConnection(transport) {
|
|
|
475
539
|
try {
|
|
476
540
|
return await transport.connect();
|
|
477
541
|
} catch (cause) {
|
|
478
|
-
throw new CoSignUnavailableError("co-signer connection failed", { cause });
|
|
542
|
+
throw new CoSignUnavailableError("co-signer connection failed", { cause, transient: true });
|
|
479
543
|
}
|
|
480
544
|
}
|
|
481
|
-
async function runCeremony(
|
|
545
|
+
async function runCeremony(ctx) {
|
|
546
|
+
const { conn, agent, env, digest, from } = ctx;
|
|
482
547
|
const send = async (frame) => {
|
|
483
548
|
try {
|
|
484
|
-
await conn.send(frame);
|
|
549
|
+
await withDeadline(conn.send(frame), ctx.deadlineMs);
|
|
485
550
|
} catch (cause) {
|
|
486
|
-
|
|
551
|
+
if (cause instanceof CoSignUnavailableError) throw cause;
|
|
552
|
+
throw new CoSignUnavailableError("co-sign connection dropped while sending", {
|
|
553
|
+
cause,
|
|
554
|
+
transient: true
|
|
555
|
+
});
|
|
487
556
|
}
|
|
488
557
|
};
|
|
489
558
|
const recv = async () => {
|
|
490
559
|
let frame;
|
|
491
560
|
try {
|
|
492
|
-
frame = await conn.recv();
|
|
561
|
+
frame = await withDeadline(conn.recv(), ctx.deadlineMs);
|
|
493
562
|
} catch (cause) {
|
|
494
|
-
|
|
563
|
+
if (cause instanceof CoSignUnavailableError) throw cause;
|
|
564
|
+
throw new CoSignUnavailableError("co-sign connection dropped mid-ceremony", {
|
|
565
|
+
cause,
|
|
566
|
+
transient: true
|
|
567
|
+
});
|
|
495
568
|
}
|
|
496
569
|
if (frame.wire_version !== WIRE_VERSION) {
|
|
497
570
|
throw new CoSignUnavailableError(
|
|
@@ -503,9 +576,13 @@ async function runCeremony(conn, agent, sessionId, intent, digest, authTag) {
|
|
|
503
576
|
await send({
|
|
504
577
|
wire_version: WIRE_VERSION,
|
|
505
578
|
kind: "request",
|
|
506
|
-
session_id: sessionId,
|
|
507
|
-
|
|
508
|
-
|
|
579
|
+
session_id: ctx.sessionId,
|
|
580
|
+
ceremony_id: env.ceremonyId,
|
|
581
|
+
ssid: env.ssid,
|
|
582
|
+
intent: toWireIntent(env.intent),
|
|
583
|
+
freshness_ts: env.freshnessTs,
|
|
584
|
+
freshness_nonce: env.freshnessNonce,
|
|
585
|
+
auth_tag: ctx.authTag
|
|
509
586
|
});
|
|
510
587
|
let first;
|
|
511
588
|
try {
|
|
@@ -519,6 +596,12 @@ async function runCeremony(conn, agent, sessionId, intent, digest, authTag) {
|
|
|
519
596
|
const frame = await recv();
|
|
520
597
|
switch (frame.kind) {
|
|
521
598
|
case "round": {
|
|
599
|
+
const payloadBytes = (frame.payload.length - 2) / 2;
|
|
600
|
+
if (payloadBytes > ctx.maxFrameBytes) {
|
|
601
|
+
throw new CoSignUnavailableError(
|
|
602
|
+
`co-signer sent a ${payloadBytes}-byte round frame (bound ${ctx.maxFrameBytes}) \u2014 refused pre-decode`
|
|
603
|
+
);
|
|
604
|
+
}
|
|
522
605
|
let step;
|
|
523
606
|
try {
|
|
524
607
|
step = agent.step(frame.payload);
|
|
@@ -533,15 +616,16 @@ async function runCeremony(conn, agent, sessionId, intent, digest, authTag) {
|
|
|
533
616
|
break;
|
|
534
617
|
}
|
|
535
618
|
case "result": {
|
|
619
|
+
const signature = assembleSignature({ r: frame.r, s: frame.s, v: frame.v });
|
|
536
620
|
if (agentSig === null) {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
);
|
|
621
|
+
await verifyRecovers(digest, signature, frame.s, from, "idempotent-replay");
|
|
622
|
+
return { ok: true, signature, intent: env.intent };
|
|
540
623
|
}
|
|
541
624
|
if (frame.r.toLowerCase() !== agentSig.r.toLowerCase() || frame.s.toLowerCase() !== agentSig.s.toLowerCase() || frame.v !== agentSig.v) {
|
|
542
625
|
throw new CoSignUnavailableError("the backend and agent derived different signatures");
|
|
543
626
|
}
|
|
544
|
-
|
|
627
|
+
await verifyRecovers(digest, signature, frame.s, from, "co-signed");
|
|
628
|
+
return { ok: true, signature, intent: env.intent };
|
|
545
629
|
}
|
|
546
630
|
case "rejection": {
|
|
547
631
|
if (POLICY_REASONS.has(frame.reason)) {
|
|
@@ -560,6 +644,52 @@ async function runCeremony(conn, agent, sessionId, intent, digest, authTag) {
|
|
|
560
644
|
}
|
|
561
645
|
}
|
|
562
646
|
}
|
|
647
|
+
function withDeadline(promise, deadlineMs) {
|
|
648
|
+
const remaining = deadlineMs - Date.now();
|
|
649
|
+
if (remaining <= 0) {
|
|
650
|
+
return Promise.reject(
|
|
651
|
+
new CoSignUnavailableError(
|
|
652
|
+
"co-sign ceremony timed out (the deadline fires before validBefore \u2014 W11)"
|
|
653
|
+
)
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
return new Promise((resolve, reject) => {
|
|
657
|
+
const timer = setTimeout(() => {
|
|
658
|
+
reject(
|
|
659
|
+
new CoSignUnavailableError(
|
|
660
|
+
"co-sign ceremony timed out (the deadline fires before validBefore \u2014 W11)"
|
|
661
|
+
)
|
|
662
|
+
);
|
|
663
|
+
}, remaining);
|
|
664
|
+
promise.then(
|
|
665
|
+
(value) => {
|
|
666
|
+
clearTimeout(timer);
|
|
667
|
+
resolve(value);
|
|
668
|
+
},
|
|
669
|
+
(cause) => {
|
|
670
|
+
clearTimeout(timer);
|
|
671
|
+
reject(cause);
|
|
672
|
+
}
|
|
673
|
+
);
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
var SECP256K1_HALF_N = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0n;
|
|
677
|
+
async function verifyRecovers(digest, signature, s, from, what) {
|
|
678
|
+
if (BigInt(s) > SECP256K1_HALF_N) {
|
|
679
|
+
throw new CoSignUnavailableError(`the ${what} signature is not low-S (EIP-2)`);
|
|
680
|
+
}
|
|
681
|
+
let recovered;
|
|
682
|
+
try {
|
|
683
|
+
recovered = await viem.recoverAddress({ hash: digest, signature });
|
|
684
|
+
} catch (cause) {
|
|
685
|
+
throw new CoSignUnavailableError(`the ${what} signature failed to recover`, { cause });
|
|
686
|
+
}
|
|
687
|
+
if (viem.getAddress(recovered) !== from) {
|
|
688
|
+
throw new CoSignUnavailableError(
|
|
689
|
+
`the ${what} signature recovers to ${viem.getAddress(recovered)}, not the group EOA ${from}`
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
563
693
|
function assembleSignature(sig) {
|
|
564
694
|
const yParity = sig.v - 27;
|
|
565
695
|
if (yParity !== 0 && yParity !== 1) {
|
|
@@ -569,10 +699,11 @@ function assembleSignature(sig) {
|
|
|
569
699
|
}
|
|
570
700
|
|
|
571
701
|
exports.CoSignUnavailableError = CoSignUnavailableError;
|
|
702
|
+
exports.MAX_FRAME_BYTES = MAX_FRAME_BYTES;
|
|
572
703
|
exports.PolicyGatedSignerConfigError = PolicyGatedSignerConfigError;
|
|
573
704
|
exports.WIRE_VERSION = WIRE_VERSION;
|
|
574
705
|
exports.assertNonBypassable = assertNonBypassable;
|
|
575
|
-
exports.
|
|
706
|
+
exports.canonicalRequestBytes = canonicalRequestBytes;
|
|
576
707
|
exports.createLocalPolicyGatedSigner = createLocalPolicyGatedSigner;
|
|
577
708
|
exports.createMpc2pPolicyGatedSigner = createMpc2pPolicyGatedSigner;
|
|
578
709
|
exports.requireNonBypassable = requireNonBypassable;
|