@capxul/mcp 4.20.0-beta.33 → 4.20.0-beta.35

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.
@@ -1,5 +1,5 @@
1
1
  import { r as __commonJSMin } from "./lib-DnmstTkB.mjs";
2
- import { a as anumber, h as u32$1, l as createHasher, m as toBytes$2, n as abytes, o as aoutput, p as swap32IfBE, r as aexists, s as clean, t as Hash$1 } from "./utils-CenTnkL6.mjs";
2
+ import { c as clean, f as swap32IfBE, i as aexists, m as u32$1, n as Hash$1, o as anumber, p as toBytes$2, r as abytes, s as aoutput, t as sha256$2, u as createHasher } from "./sha2-D5rBHwg7.mjs";
3
3
  import { Cause, Clock, Context, Data, Deferred, Effect, Exit, Fiber, Layer, Option, Predicate, Queue, Ref, Result, Schema, SchemaAST, SchemaGetter, SchemaIssue, SchemaParser } from "effect";
4
4
  //#region ../../packages/protocol/src/errors/failure-modes.ts
5
5
  /**
@@ -2179,6 +2179,15 @@ const CAPXUL_ERROR_CODES = [
2179
2179
  "WORK_DIED",
2180
2180
  "ACTOR_STOPPED"
2181
2181
  ];
2182
+ /** The existing Organization authority refusal vocabulary. */
2183
+ const ROLE_PERMISSION_DENIED_REASONS = [
2184
+ "over_cap",
2185
+ "daily_cap",
2186
+ "not_member",
2187
+ "disallowed_recipient",
2188
+ "condition_violation",
2189
+ "budget_exhausted"
2190
+ ];
2182
2191
  const EXPECTED_OUTCOME_CODES = /* @__PURE__ */ new Set([
2183
2192
  "INVALID_INPUT",
2184
2193
  "NOT_AUTHENTICATED",
@@ -7278,7 +7287,7 @@ function publicKeyToAddress(publicKey) {
7278
7287
  //#region ../../node_modules/.pnpm/viem@2.55.18_patch_hash=6dka2762lzcggf7at6h6xt4khq_@typescript+typescript6@6.0.2_zod@4.6.5/node_modules/viem/_esm/utils/signature/recoverPublicKey.js
7279
7288
  async function recoverPublicKey({ hash, signature }) {
7280
7289
  const hashHex = isHex$1(hash) ? hash : toHex(hash);
7281
- const { secp256k1 } = await import("./secp256k1-BSimfttS.mjs");
7290
+ const { secp256k1 } = await import("./secp256k1-CLeVBma1.mjs");
7282
7291
  return `0x${(() => {
7283
7292
  if (typeof signature === "object" && "r" in signature && "s" in signature) {
7284
7293
  const { r, s, v, yParity } = signature;
@@ -7372,6 +7381,28 @@ function getSizeOfLength(length) {
7372
7381
  throw new BaseError("Length is too large.");
7373
7382
  }
7374
7383
  //#endregion
7384
+ //#region ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/sha256.js
7385
+ /**
7386
+ * SHA2-256 a.k.a. sha256. In JS, it is the fastest hash, even faster than Blake3.
7387
+ *
7388
+ * To break sha256 using birthday attack, attackers need to try 2^128 hashes.
7389
+ * BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.
7390
+ *
7391
+ * Check out [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
7392
+ * @module
7393
+ * @deprecated
7394
+ */
7395
+ /** @deprecated Use import from `noble/hashes/sha2` module */
7396
+ const sha256$1 = sha256$2;
7397
+ //#endregion
7398
+ //#region ../../node_modules/.pnpm/viem@2.55.18_patch_hash=6dka2762lzcggf7at6h6xt4khq_@typescript+typescript6@6.0.2_zod@4.6.5/node_modules/viem/_esm/utils/hash/sha256.js
7399
+ function sha256(value, to_) {
7400
+ const to = to_ || "hex";
7401
+ const bytes = sha256$1(isHex$1(value, { strict: false }) ? toBytes$1(value) : value);
7402
+ if (to === "bytes") return bytes;
7403
+ return toHex(bytes);
7404
+ }
7405
+ //#endregion
7375
7406
  //#region ../../node_modules/.pnpm/viem@2.55.18_patch_hash=6dka2762lzcggf7at6h6xt4khq_@typescript+typescript6@6.0.2_zod@4.6.5/node_modules/viem/_esm/utils/abi/decodeFunctionData.js
7376
7407
  function decodeFunctionData(parameters) {
7377
7408
  const { abi, data } = parameters;
@@ -7747,7 +7778,7 @@ function isQuantityHex(value) {
7747
7778
  function isBytes32(value) {
7748
7779
  return typeof value === "string" && BYTES32_HEX.test(value);
7749
7780
  }
7750
- function refused(field, shape, value) {
7781
+ function refused$1(field, shape, value) {
7751
7782
  throw Errors.invalidInput(field, invalidValueReason(`must be ${shape}`, value));
7752
7783
  }
7753
7784
  /** Rebuilding the `0x` prefix keeps the result a `Hex`; lowercasing never changes the bytes. */
@@ -7756,19 +7787,19 @@ function lowered(value) {
7756
7787
  }
7757
7788
  /** Hex data exactly as given: case kept, for text another party compares or hashes as is. */
7758
7789
  function toExactHex(value, field = "value") {
7759
- return isHex(value) ? value : refused(field, "0x-prefixed hex", value);
7790
+ return isHex(value) ? value : refused$1(field, "0x-prefixed hex", value);
7760
7791
  }
7761
7792
  /** Hex data, lowercased. */
7762
7793
  function toLowerHex(value, field = "value") {
7763
- return isHex(value) ? lowered(value) : refused(field, "0x-prefixed hex", value);
7794
+ return isHex(value) ? lowered(value) : refused$1(field, "0x-prefixed hex", value);
7764
7795
  }
7765
7796
  /** A bytes32 value, lowercased. */
7766
7797
  function toLowerBytes32(value, field = "value") {
7767
- return isBytes32(value) ? lowered(value) : refused(field, "a 0x-prefixed bytes32 value", value);
7798
+ return isBytes32(value) ? lowered(value) : refused$1(field, "a 0x-prefixed bytes32 value", value);
7768
7799
  }
7769
7800
  /** An address, lowercased: the form stored rows and digests compare. */
7770
7801
  function toLowerAddress(value, field = "address") {
7771
- return isAddress(value) ? lowered(value) : refused(field, "an EVM address", value);
7802
+ return isAddress(value) ? lowered(value) : refused$1(field, "an EVM address", value);
7772
7803
  }
7773
7804
  //#endregion
7774
7805
  //#region ../../packages/protocol/src/evm/schema.ts
@@ -8321,16 +8352,19 @@ const PaymentCommandSchema = Schema.Union([
8321
8352
  PaymentBirthCommandSchema,
8322
8353
  Schema.Struct({
8323
8354
  kind: Schema.Literal("claim_commitment"),
8355
+ requestKey: Schema.optional(nonEmpty("requestKey")),
8324
8356
  actor: AccountActorRefSchema,
8325
8357
  paymentId: PaymentIdSchema
8326
8358
  }),
8327
8359
  Schema.Struct({
8328
8360
  kind: Schema.Literal("cancel_commitment"),
8361
+ requestKey: Schema.optional(nonEmpty("requestKey")),
8329
8362
  actor: ActorRefSchema,
8330
8363
  paymentId: PaymentIdSchema
8331
8364
  }),
8332
8365
  Schema.Struct({
8333
8366
  kind: Schema.Literal("redirect_commitment"),
8367
+ requestKey: Schema.optional(nonEmpty("requestKey")),
8334
8368
  actor: ActorRefSchema,
8335
8369
  paymentId: PaymentIdSchema,
8336
8370
  recipient: ActorOrDestinationRefSchema
@@ -8355,8 +8389,10 @@ const PreparedMoneyItemSchema = Schema.Union([
8355
8389
  tokenAddress: AddressSchema$1,
8356
8390
  rawAmount: WeiAmountSchema$1,
8357
8391
  kind: Uint16Schema,
8358
- documentHash: NonzeroDocumentHashSchema
8359
- }),
8392
+ documentHash: NonzeroDocumentHashSchema,
8393
+ jobNonce: Schema.optional(Bytes32Schema),
8394
+ executor: Schema.optional(AddressSchema$1)
8395
+ }).pipe(Schema.refine((item) => item.jobNonce === void 0 === (item.executor === void 0), { message: "Prepared V3 identity requires both jobNonce and executor" })),
8360
8396
  Schema.Struct({
8361
8397
  operation: Schema.Literal("create_commitment"),
8362
8398
  paymentId: PaymentIdSchema,
@@ -8458,6 +8494,12 @@ const PersonalUnsignedUserOperationSchema = Schema.Struct({
8458
8494
  entryPoint: Schema.optional(Schema.Never),
8459
8495
  safe4337ModuleAddress: Schema.optional(Schema.Never)
8460
8496
  });
8497
+ const SubmittedPaymentExecutionSchema = Schema.Struct({
8498
+ executionId: MoneyExecutionIdSchema,
8499
+ commandId: PaymentCommandIdSchema,
8500
+ userOpHash: Bytes32Schema,
8501
+ payment: Payment
8502
+ });
8461
8503
  const PreparedPaymentExecutionSchema = Schema.Struct({
8462
8504
  actorAccountId: AccountIdSchema$1,
8463
8505
  item: PreparedMoneyItemSchema,
@@ -8475,7 +8517,8 @@ const PreparedPaymentExecutionSchema = Schema.Struct({
8475
8517
  chainId: BaseSepoliaChainIdSchema,
8476
8518
  signerAddress: AddressSchema$1,
8477
8519
  userOpSenderSafe: SafeAddressSchema,
8478
- digest: Bytes32Schema
8520
+ digest: Bytes32Schema,
8521
+ settled: Schema.optional(SubmittedPaymentExecutionSchema)
8479
8522
  });
8480
8523
  const SubmitPaymentExecutionInputSchema = Schema.Struct({
8481
8524
  executionId: MoneyExecutionIdSchema,
@@ -8489,12 +8532,6 @@ const AbandonPaymentExecutionInputSchema = Schema.Struct({
8489
8532
  "prepared_mismatch"
8490
8533
  ])
8491
8534
  });
8492
- const SubmittedPaymentExecutionSchema = Schema.Struct({
8493
- executionId: MoneyExecutionIdSchema,
8494
- commandId: PaymentCommandIdSchema,
8495
- userOpHash: Bytes32Schema,
8496
- payment: Payment
8497
- });
8498
8535
  const SubmittedPaymentCommandExecutionSchema = Schema.Struct({
8499
8536
  executionId: MoneyExecutionIdSchema,
8500
8537
  commandId: PaymentCommandIdSchema,
@@ -8509,14 +8546,17 @@ const PaymentLifecycleExecutionIntentSchema = Schema.Union([
8509
8546
  }),
8510
8547
  Schema.Struct({
8511
8548
  kind: Schema.Literal("claim"),
8512
- paymentId: PaymentIdSchema
8549
+ paymentId: PaymentIdSchema,
8550
+ requestKey: Schema.optional(nonEmpty("requestKey"))
8513
8551
  }),
8514
8552
  Schema.Struct({
8515
8553
  kind: Schema.Literal("cancel"),
8516
- paymentId: PaymentIdSchema
8554
+ paymentId: PaymentIdSchema,
8555
+ requestKey: Schema.optional(nonEmpty("requestKey"))
8517
8556
  }),
8518
8557
  Schema.Struct({
8519
8558
  kind: Schema.Literal("redirect"),
8559
+ requestKey: Schema.optional(nonEmpty("requestKey")),
8520
8560
  paymentId: PaymentIdSchema,
8521
8561
  recipient: RedirectPaymentRef
8522
8562
  })
@@ -8575,10 +8615,12 @@ const RequestPaymentConfirmationFields = {
8575
8615
  const RequestPaymentTermsSchema = Schema.Struct(RequestPaymentConfirmationFields);
8576
8616
  const RequestPaymentConfirmationSchema = Schema.Union([Schema.Struct({
8577
8617
  ...RequestPaymentConfirmationFields,
8618
+ requestKey: Schema.optional(nonEmpty("requestKey")),
8578
8619
  payer: Schema.Struct({ kind: Schema.Literal("account") }),
8579
8620
  permissionId: Schema.optional(Schema.Never)
8580
8621
  }), Schema.Struct({
8581
8622
  ...RequestPaymentConfirmationFields,
8623
+ requestKey: Schema.optional(nonEmpty("requestKey")),
8582
8624
  payer: OrganizationActorRefSchema,
8583
8625
  permissionId: PermissionIdSchema
8584
8626
  })]);
@@ -8638,13 +8680,14 @@ const PreparedPaymentCommandExecutionSchema = Schema.Struct({
8638
8680
  commitmentId: Uint256StringSchema,
8639
8681
  documentHash: NonzeroDocumentHashSchema
8640
8682
  })),
8641
- documentBundles: Schema.optional(Schema.Array(PaymentDocumentBundleV3Schema))
8683
+ documentBundles: Schema.optional(Schema.Array(PaymentDocumentBundleV3Schema)),
8684
+ settled: Schema.optional(SubmittedPaymentCommandExecutionSchema)
8642
8685
  }).check(Schema.makeFilter((execution) => {
8643
8686
  if (!("kind" in execution.request) || execution.request.kind !== "payment_request") return true;
8644
8687
  const source = execution.sourceCommand;
8645
8688
  const prepared = execution.preparedCommand;
8646
8689
  if (source?.kind !== "birth" || prepared === void 0 || source.lineage?.kind !== "payment_request") return false;
8647
- if (source.lineage.requestId !== execution.request.confirmation.requestId || source.requestKey !== execution.request.requestKey || source.requestKey !== execution.request.confirmation.requestId || execution.userOperation === void 0) return false;
8690
+ if (source.lineage.requestId !== execution.request.confirmation.requestId || source.requestKey !== execution.request.requestKey || source.requestKey !== (execution.request.confirmation.requestKey ?? execution.request.confirmation.requestId) || execution.userOperation === void 0) return false;
8648
8691
  if ([
8649
8692
  source.items.length,
8650
8693
  execution.request.items.length,
@@ -8657,7 +8700,7 @@ const PreparedPaymentCommandExecutionSchema = Schema.Struct({
8657
8700
  prepared.instructionDocuments?.length
8658
8701
  ].some((length) => length !== 1)) return false;
8659
8702
  const item = prepared.items[0];
8660
- return "recipientSafe" in item && item.operation === source.items[0].operation && item.operation === execution.request.items[0].operation && item.paymentId === execution.paymentIds[0] && item.paymentId === execution.sourcePaymentIds?.[0] && item.recipientSafe === execution.sourceRecipientSafes?.[0];
8703
+ return "recipientSafe" in item && item.operation === source.items[0].operation && item.operation === execution.request.items[0].operation && [item.paymentId, execution.sourcePaymentIds?.[0]].every((id) => id === execution.paymentIds[0]) && item.recipientSafe === execution.sourceRecipientSafes?.[0];
8661
8704
  }));
8662
8705
  //#endregion
8663
8706
  //#region ../../packages/protocol/src/accounts/approval-schema.ts
@@ -8725,6 +8768,7 @@ const ApprovalSummarySchema = Schema.Struct({
8725
8768
  /** The exact operation the signature covers: the digest is the one thing the key signs. */
8726
8769
  const ApprovalOperationSchema = Schema.Struct({
8727
8770
  executionId: MoneyExecutionIdSchema,
8771
+ commandId: Schema.optional(nonEmpty("commandId")),
8728
8772
  digest: Bytes32Schema,
8729
8773
  userOperation: PersonalUnsignedUserOperationSchema,
8730
8774
  paymentIds: Schema.Array(PaymentIdSchema)
@@ -8917,6 +8961,21 @@ const approvals = {
8917
8961
  ...APPROVAL
8918
8962
  ]
8919
8963
  }),
8964
+ /** Read the signed operation's progress. Consumption alone does not prove completion. */
8965
+ observe: Operation.query("accounts.approvals.observe", {
8966
+ input: Schema.Struct({ approvalId: ApprovalIdSchema }),
8967
+ output: Schema.Struct({
8968
+ approval: ApprovalSchema,
8969
+ completed: Schema.Boolean
8970
+ }),
8971
+ errors: [
8972
+ ...CALL$10,
8973
+ ...DEFECTS,
8974
+ ...APPROVAL,
8975
+ "SUPERSEDED",
8976
+ "TRANSACTION_FAILED"
8977
+ ]
8978
+ }),
8920
8979
  /** The person opened the approval page: stamp the first review of a pending approval. */
8921
8980
  review: Operation.mutation("accounts.approvals.review", {
8922
8981
  input: Schema.Struct({ approvalId: ApprovalIdSchema }),
@@ -10042,6 +10101,12 @@ function toOrgId(raw) {
10042
10101
  //#endregion
10043
10102
  //#region ../../packages/protocol/src/errors/schema.ts
10044
10103
  const FailureModeSchema$1 = Schema.Literals(FAILURE_MODES$1);
10104
+ Schema.Struct({
10105
+ reason: Schema.Literals(ROLE_PERMISSION_DENIED_REASONS),
10106
+ operation: Schema.optionalKey(Schema.String),
10107
+ remaining: Schema.optionalKey(AssetAmountSchema),
10108
+ required: Schema.optionalKey(AssetAmountSchema)
10109
+ });
10045
10110
  const ChainUpstreamSchema$1 = Schema.Literals(CHAIN_UPSTREAMS);
10046
10111
  const ChainCauseSchema = Schema.Struct({
10047
10112
  mode: FailureModeSchema$1,
@@ -12663,6 +12728,7 @@ const inboxes = {
12663
12728
  input: Schema.Struct({
12664
12729
  actor,
12665
12730
  paymentRequestId: Schema.String,
12731
+ requestKey: Schema.optionalKey(nonEmpty("requestKey")),
12666
12732
  timing: Schema.optionalKey(PaymentTiming),
12667
12733
  permissionId: Schema.optionalKey(Schema.String)
12668
12734
  }),
@@ -13039,7 +13105,8 @@ const PEOPLE_OPERATIONS = {
13039
13105
  expire: "accounts.approvals.expire",
13040
13106
  recordApproval: "accounts.approvals.recordApproval",
13041
13107
  recordExpiry: "accounts.approvals.recordExpiry",
13042
- sendApproved: "accounts.approvals.sendApproved"
13108
+ sendApproved: "accounts.approvals.sendApproved",
13109
+ rescheduleApproved: "accounts.approvals.rescheduleApproved"
13043
13110
  },
13044
13111
  balances: { readBinding: "accounts.balances.readBinding" },
13045
13112
  claims: {
@@ -16831,7 +16898,7 @@ function mapAccountLifecycle(input) {
16831
16898
  }
16832
16899
  //#endregion
16833
16900
  //#region ../../packages/sdk/package.json
16834
- var version$1 = "4.20.0-beta.33";
16901
+ var version$1 = "4.20.0-beta.35";
16835
16902
  //#endregion
16836
16903
  //#region ../../packages/sdk/src/observability/telemetry/exception-projection.ts
16837
16904
  /** Fixed fallback for failures that have no safe message. */
@@ -17394,6 +17461,126 @@ function mapOk(result, f) {
17394
17461
  }
17395
17462
  }
17396
17463
  //#endregion
17464
+ //#region ../../packages/protocol/src/evm/test-assets.ts
17465
+ const SYNTHETIC_TEST_ASSET_SOURCE = "synthetic-test-liquidity";
17466
+ /**
17467
+ * Owned test assets, with metadata read from each creation receipt and contract.
17468
+ * Settlement admission lives in assets.ts. The fixed test exchange uses the
17469
+ * original five assets; bank EURC has its own deployment.
17470
+ *
17471
+ * `symbol` is the display string the owned contract returns. A
17472
+ * provider-supported USDC would be a different contract at a different
17473
+ * address returning the same symbol, which is why the resolvers below key on
17474
+ * `assetId`, or on chain plus address, and never on a symbol.
17475
+ */
17476
+ const SYNTHETIC_TEST_ASSET_FIXTURES = {
17477
+ usdc: {
17478
+ assetId: assetIdFor(84532, "0x06ba8b863ca77490b0e7008427562bdbfcff730e"),
17479
+ chainId: toChainId(84532),
17480
+ tokenAddress: "0x06ba8b863ca77490b0e7008427562bdbfcff730e",
17481
+ symbol: "USDC",
17482
+ decimals: 6,
17483
+ peg: toCurrencyCode("USD"),
17484
+ deploymentStartBlock: 46690061,
17485
+ deploymentTransaction: "0x2661b7af5f62b9e31c707a59746cda65b90ba4448852317ac1968162fb94ff52",
17486
+ source: SYNTHETIC_TEST_ASSET_SOURCE
17487
+ },
17488
+ usdt: {
17489
+ assetId: assetIdFor(84532, "0xcb5f361ae070e75d573941b8cd54995fa3876d75"),
17490
+ chainId: toChainId(84532),
17491
+ tokenAddress: "0xcb5f361ae070e75d573941b8cd54995fa3876d75",
17492
+ symbol: "USDT",
17493
+ decimals: 6,
17494
+ peg: toCurrencyCode("USD"),
17495
+ deploymentStartBlock: 46690061,
17496
+ deploymentTransaction: "0x98e5303f97974a31eddb61ad030072d900ce7283ce8080bfe0b9e5ea6f297749",
17497
+ source: SYNTHETIC_TEST_ASSET_SOURCE
17498
+ },
17499
+ weth: {
17500
+ assetId: assetIdFor(84532, "0x85b7bd39ce3df9a85135e1e307225dd435f67e47"),
17501
+ chainId: toChainId(84532),
17502
+ tokenAddress: "0x85b7bd39ce3df9a85135e1e307225dd435f67e47",
17503
+ symbol: "WETH",
17504
+ decimals: 18,
17505
+ peg: null,
17506
+ deploymentStartBlock: 46690061,
17507
+ deploymentTransaction: "0x48dfacc01c15adc34f6c629aec5c9ff7bb84176d448017da0d0d4fdaf8b5a68a",
17508
+ source: SYNTHETIC_TEST_ASSET_SOURCE
17509
+ },
17510
+ wbtc: {
17511
+ assetId: assetIdFor(84532, "0xcf433a81f507dcc88c2c404650ffafb40750b451"),
17512
+ chainId: toChainId(84532),
17513
+ tokenAddress: "0xcf433a81f507dcc88c2c404650ffafb40750b451",
17514
+ symbol: "WBTC",
17515
+ decimals: 8,
17516
+ peg: null,
17517
+ deploymentStartBlock: 46690061,
17518
+ deploymentTransaction: "0xa975fcda0a67509742243bbfc386032d2e0d6ca78404c255fae2e4ffae1c7f4d",
17519
+ source: SYNTHETIC_TEST_ASSET_SOURCE
17520
+ },
17521
+ cngn: {
17522
+ assetId: assetIdFor(84532, "0xda515a7267e190710f0003f951c62bcfd70d6b2a"),
17523
+ chainId: toChainId(84532),
17524
+ tokenAddress: "0xda515a7267e190710f0003f951c62bcfd70d6b2a",
17525
+ symbol: "cNGN",
17526
+ decimals: 6,
17527
+ peg: toCurrencyCode("NGN"),
17528
+ deploymentStartBlock: 46690061,
17529
+ deploymentTransaction: "0x6f6b0302448c7cd7db5c118a8250e548c6e72821df373e5a27550e5cdfa635a1",
17530
+ source: SYNTHETIC_TEST_ASSET_SOURCE
17531
+ },
17532
+ eurc: {
17533
+ assetId: assetIdFor(84532, "0x15055b4ed1d248c169b92705757cd9c3d985ad5f"),
17534
+ chainId: toChainId(84532),
17535
+ tokenAddress: "0x15055b4ed1d248c169b92705757cd9c3d985ad5f",
17536
+ symbol: "EURC",
17537
+ decimals: 6,
17538
+ peg: toCurrencyCode("EUR"),
17539
+ deploymentStartBlock: 47893251,
17540
+ deploymentTransaction: "0x4e0ab412d980a672336487afd10da007d51f34f17876b19b13732c8125be90ca",
17541
+ source: SYNTHETIC_TEST_ASSET_SOURCE
17542
+ }
17543
+ };
17544
+ /** EURC is minted for bank deposits and has no admission to the fixed test exchange. */
17545
+ const SYNTHETIC_TEST_ASSETS = [...[
17546
+ SYNTHETIC_TEST_ASSET_FIXTURES.usdc,
17547
+ SYNTHETIC_TEST_ASSET_FIXTURES.usdt,
17548
+ SYNTHETIC_TEST_ASSET_FIXTURES.weth,
17549
+ SYNTHETIC_TEST_ASSET_FIXTURES.wbtc,
17550
+ SYNTHETIC_TEST_ASSET_FIXTURES.cngn
17551
+ ], SYNTHETIC_TEST_ASSET_FIXTURES.eurc];
17552
+ toChainId(84532);
17553
+ /**
17554
+ * The settlement tier: the owned test assets admitted to the exact-transfer
17555
+ * path and to the treasury reads. USDC, USDT, WETH and EURC are admitted assets.
17556
+ * There is no default token.
17557
+ */
17558
+ const SETTLEMENT_ASSETS_BASE_SEPOLIA = Object.freeze({
17559
+ CAPXUL_TEST_USDC: SYNTHETIC_TEST_ASSET_FIXTURES.usdc,
17560
+ CAPXUL_TEST_USDT: SYNTHETIC_TEST_ASSET_FIXTURES.usdt,
17561
+ CAPXUL_TEST_WETH: SYNTHETIC_TEST_ASSET_FIXTURES.weth,
17562
+ CAPXUL_TEST_EURC: SYNTHETIC_TEST_ASSET_FIXTURES.eurc
17563
+ });
17564
+ const CONFIGURED_MONEY_ASSETS = Object.freeze(Object.values(SETTLEMENT_ASSETS_BASE_SEPOLIA));
17565
+ Object.freeze({ BASE_SEPOLIA: Object.freeze({
17566
+ CAPXUL_TEST_USDC: SETTLEMENT_ASSETS_BASE_SEPOLIA.CAPXUL_TEST_USDC.assetId,
17567
+ CAPXUL_TEST_USDT: SETTLEMENT_ASSETS_BASE_SEPOLIA.CAPXUL_TEST_USDT.assetId,
17568
+ CAPXUL_TEST_WETH: SETTLEMENT_ASSETS_BASE_SEPOLIA.CAPXUL_TEST_WETH.assetId,
17569
+ CAPXUL_TEST_EURC: SETTLEMENT_ASSETS_BASE_SEPOLIA.CAPXUL_TEST_EURC.assetId
17570
+ }) });
17571
+ /**
17572
+ * Every known asset in ONE identity space. The tiers above declare admission;
17573
+ * this is the only list an identity resolves against, so an asset is never
17574
+ * two different things depending on which list a caller happened to read.
17575
+ */
17576
+ const MONEY_ASSET_REGISTRY = [...SYNTHETIC_TEST_ASSETS];
17577
+ CONFIGURED_MONEY_ASSETS.map((asset) => asset.tokenAddress.toLowerCase());
17578
+ /** The registry row for `assetId` across every tier, or `null`. */
17579
+ function configuredMoneyAssetById(assetId) {
17580
+ const canonical = toAssetId(assetId);
17581
+ return MONEY_ASSET_REGISTRY.find((asset) => asset.assetId === canonical) ?? null;
17582
+ }
17583
+ //#endregion
17397
17584
  //#region ../../packages/sdk/src/platform/transport/call-operation.ts
17398
17585
  function callOperation(port, row, args, options) {
17399
17586
  const op = row;
@@ -18735,6 +18922,23 @@ async function verifyPaymentDocumentSignatureV3(input) {
18735
18922
  })).toLowerCase() === envelope.signature.signer;
18736
18923
  }
18737
18924
  //#endregion
18925
+ //#region ../../packages/protocol/src/documents/identities.ts
18926
+ /** A caller handed this module a value its own types rule out: a defect, named. */
18927
+ function defect$1(step, message) {
18928
+ return new CapxulError("UNKNOWN", message, { details: { step } });
18929
+ }
18930
+ function hashDocumentOriginIdV3(input) {
18931
+ if (!Number.isSafeInteger(input.chainId) || input.chainId <= 0 || !Number.isSafeInteger(input.itemIndex) || input.itemIndex < 0 || input.actorKind !== "account" && input.actorKind !== "organization" || input.actorId.length === 0 || input.requestKey.length === 0) throw defect$1("hashDocumentOriginIdV3", "Invalid document origin input");
18932
+ return keccak256$1(encodeAbiParameters$1(parseAbiParameters("string namespace, uint256 chainId, string actorKind, string actorId, string requestKey, uint256 itemIndex"), [
18933
+ "capxul.document-origin.v3",
18934
+ BigInt(input.chainId),
18935
+ input.actorKind,
18936
+ input.actorId,
18937
+ input.requestKey,
18938
+ BigInt(input.itemIndex)
18939
+ ]));
18940
+ }
18941
+ //#endregion
18738
18942
  //#region ../../packages/sdk/src/documents/birth-context.ts
18739
18943
  function sourcePurpose(source) {
18740
18944
  if ("purposeKind" in source) return source.purposeKind;
@@ -18749,13 +18953,20 @@ function isBirthItem(item) {
18749
18953
  function requestRetryInstruction(input) {
18750
18954
  const request = input.evidence.request;
18751
18955
  const original = input.evidence.sourceCommand;
18752
- if (!("kind" in request) || request.kind !== "retry" || original?.kind !== "birth" || original.lineage?.kind !== "payment_request" && original.lineage?.kind !== "invoice_checkout" || original.lineage.requestId !== original.requestKey || !input.evidence.sourcePaymentIds?.includes(request.paymentId)) return void 0;
18956
+ if (!("kind" in request) || request.kind !== "retry" || original?.kind !== "birth" || original.lineage?.kind !== "payment_request" && original.lineage?.kind !== "invoice_checkout" || !input.evidence.sourcePaymentIds?.includes(request.paymentId)) return void 0;
18753
18957
  const document = original.items[input.index]?.document;
18754
18958
  if (document?.kind !== "envelope") return void 0;
18755
18959
  const bytes = decodeCanonicalBase64V3(document.bytesBase64);
18756
18960
  const envelope = decodeSupportedPaymentDocumentEnvelope(bytes);
18757
18961
  if (envelope.primaryType !== "Memo" && envelope.primaryType !== "Invoice") return void 0;
18758
18962
  if (envelope.version === 5) return void 0;
18963
+ if (original.lineage.requestId !== original.requestKey && (original.lineage.kind !== "payment_request" || envelope.primaryType !== "Invoice" || envelope.message.originId !== hashDocumentOriginIdV3({
18964
+ chainId: input.evidence.chainId,
18965
+ actorKind: original.actor.kind,
18966
+ actorId: original.actor.kind === "account" ? original.actor.accountId : original.actor.orgId,
18967
+ requestKey: original.lineage.requestId,
18968
+ itemIndex: input.index
18969
+ }))) return void 0;
18759
18970
  return {
18760
18971
  documentHash: hashSupportedPaymentDocument(envelope),
18761
18972
  contentHash: hashPaymentDocumentContentV3(bytes),
@@ -18784,11 +18995,7 @@ function requestBirthContext(evidence) {
18784
18995
  ].some((items) => items?.length !== 1)) return null;
18785
18996
  const item = command.items[0];
18786
18997
  const instruction = command.instructionDocuments?.[0];
18787
- if (!isBirthItem(item) || instruction === void 0 || source.lineage?.kind !== "payment_request" || [
18788
- source.lineage.requestId,
18789
- source.requestKey,
18790
- request.requestKey
18791
- ].some((key) => key !== request.confirmation.requestId) || documentJson(request.actor) !== documentJson(source.actor) || documentJson(request.items) !== documentJson(source.items) || evidence.sourcePaymentIds?.[0] !== evidence.paymentIds[0] || evidence.sourceRecipientSafes?.[0]?.toLowerCase() !== request.confirmation.issuerSafe.toLowerCase() || documentJson(evidence.documentBundles) !== documentJson(command.documentBundles) || !confirmedRequestFactsMatch(request.confirmation, source, item, instruction)) return null;
18998
+ if (!isBirthItem(item) || instruction === void 0 || source.lineage?.kind !== "payment_request" || source.lineage.requestId !== request.confirmation.requestId || [source.requestKey, request.requestKey].some((key) => key !== (request.confirmation.requestKey ?? request.confirmation.requestId)) || documentJson(request.actor) !== documentJson(source.actor) || documentJson(request.items) !== documentJson(source.items) || evidence.sourcePaymentIds?.[0] !== evidence.paymentIds[0] || evidence.sourceRecipientSafes?.[0]?.toLowerCase() !== request.confirmation.issuerSafe.toLowerCase() || documentJson(evidence.documentBundles) !== documentJson(command.documentBundles) || !confirmedRequestFactsMatch(request.confirmation, source, item, instruction)) return null;
18792
18999
  return {
18793
19000
  source: source.items,
18794
19001
  actorKind: source.actor.kind,
@@ -18814,126 +19021,6 @@ function retryBirthContext(evidence) {
18814
19021
  };
18815
19022
  }
18816
19023
  //#endregion
18817
- //#region ../../packages/protocol/src/evm/test-assets.ts
18818
- const SYNTHETIC_TEST_ASSET_SOURCE = "synthetic-test-liquidity";
18819
- /**
18820
- * Owned test assets, with metadata read from each creation receipt and contract.
18821
- * Settlement admission lives in assets.ts. The fixed test exchange uses the
18822
- * original five assets; bank EURC has its own deployment.
18823
- *
18824
- * `symbol` is the display string the owned contract returns. A
18825
- * provider-supported USDC would be a different contract at a different
18826
- * address returning the same symbol, which is why the resolvers below key on
18827
- * `assetId`, or on chain plus address, and never on a symbol.
18828
- */
18829
- const SYNTHETIC_TEST_ASSET_FIXTURES = {
18830
- usdc: {
18831
- assetId: assetIdFor(84532, "0x06ba8b863ca77490b0e7008427562bdbfcff730e"),
18832
- chainId: toChainId(84532),
18833
- tokenAddress: "0x06ba8b863ca77490b0e7008427562bdbfcff730e",
18834
- symbol: "USDC",
18835
- decimals: 6,
18836
- peg: toCurrencyCode("USD"),
18837
- deploymentStartBlock: 46690061,
18838
- deploymentTransaction: "0x2661b7af5f62b9e31c707a59746cda65b90ba4448852317ac1968162fb94ff52",
18839
- source: SYNTHETIC_TEST_ASSET_SOURCE
18840
- },
18841
- usdt: {
18842
- assetId: assetIdFor(84532, "0xcb5f361ae070e75d573941b8cd54995fa3876d75"),
18843
- chainId: toChainId(84532),
18844
- tokenAddress: "0xcb5f361ae070e75d573941b8cd54995fa3876d75",
18845
- symbol: "USDT",
18846
- decimals: 6,
18847
- peg: toCurrencyCode("USD"),
18848
- deploymentStartBlock: 46690061,
18849
- deploymentTransaction: "0x98e5303f97974a31eddb61ad030072d900ce7283ce8080bfe0b9e5ea6f297749",
18850
- source: SYNTHETIC_TEST_ASSET_SOURCE
18851
- },
18852
- weth: {
18853
- assetId: assetIdFor(84532, "0x85b7bd39ce3df9a85135e1e307225dd435f67e47"),
18854
- chainId: toChainId(84532),
18855
- tokenAddress: "0x85b7bd39ce3df9a85135e1e307225dd435f67e47",
18856
- symbol: "WETH",
18857
- decimals: 18,
18858
- peg: null,
18859
- deploymentStartBlock: 46690061,
18860
- deploymentTransaction: "0x48dfacc01c15adc34f6c629aec5c9ff7bb84176d448017da0d0d4fdaf8b5a68a",
18861
- source: SYNTHETIC_TEST_ASSET_SOURCE
18862
- },
18863
- wbtc: {
18864
- assetId: assetIdFor(84532, "0xcf433a81f507dcc88c2c404650ffafb40750b451"),
18865
- chainId: toChainId(84532),
18866
- tokenAddress: "0xcf433a81f507dcc88c2c404650ffafb40750b451",
18867
- symbol: "WBTC",
18868
- decimals: 8,
18869
- peg: null,
18870
- deploymentStartBlock: 46690061,
18871
- deploymentTransaction: "0xa975fcda0a67509742243bbfc386032d2e0d6ca78404c255fae2e4ffae1c7f4d",
18872
- source: SYNTHETIC_TEST_ASSET_SOURCE
18873
- },
18874
- cngn: {
18875
- assetId: assetIdFor(84532, "0xda515a7267e190710f0003f951c62bcfd70d6b2a"),
18876
- chainId: toChainId(84532),
18877
- tokenAddress: "0xda515a7267e190710f0003f951c62bcfd70d6b2a",
18878
- symbol: "cNGN",
18879
- decimals: 6,
18880
- peg: toCurrencyCode("NGN"),
18881
- deploymentStartBlock: 46690061,
18882
- deploymentTransaction: "0x6f6b0302448c7cd7db5c118a8250e548c6e72821df373e5a27550e5cdfa635a1",
18883
- source: SYNTHETIC_TEST_ASSET_SOURCE
18884
- },
18885
- eurc: {
18886
- assetId: assetIdFor(84532, "0x15055b4ed1d248c169b92705757cd9c3d985ad5f"),
18887
- chainId: toChainId(84532),
18888
- tokenAddress: "0x15055b4ed1d248c169b92705757cd9c3d985ad5f",
18889
- symbol: "EURC",
18890
- decimals: 6,
18891
- peg: toCurrencyCode("EUR"),
18892
- deploymentStartBlock: 47893251,
18893
- deploymentTransaction: "0x4e0ab412d980a672336487afd10da007d51f34f17876b19b13732c8125be90ca",
18894
- source: SYNTHETIC_TEST_ASSET_SOURCE
18895
- }
18896
- };
18897
- /** EURC is minted for bank deposits and has no admission to the fixed test exchange. */
18898
- const SYNTHETIC_TEST_ASSETS = [...[
18899
- SYNTHETIC_TEST_ASSET_FIXTURES.usdc,
18900
- SYNTHETIC_TEST_ASSET_FIXTURES.usdt,
18901
- SYNTHETIC_TEST_ASSET_FIXTURES.weth,
18902
- SYNTHETIC_TEST_ASSET_FIXTURES.wbtc,
18903
- SYNTHETIC_TEST_ASSET_FIXTURES.cngn
18904
- ], SYNTHETIC_TEST_ASSET_FIXTURES.eurc];
18905
- toChainId(84532);
18906
- /**
18907
- * The settlement tier: the owned test assets admitted to the exact-transfer
18908
- * path and to the treasury reads. USDC, USDT, WETH and EURC are admitted assets.
18909
- * There is no default token.
18910
- */
18911
- const SETTLEMENT_ASSETS_BASE_SEPOLIA = Object.freeze({
18912
- CAPXUL_TEST_USDC: SYNTHETIC_TEST_ASSET_FIXTURES.usdc,
18913
- CAPXUL_TEST_USDT: SYNTHETIC_TEST_ASSET_FIXTURES.usdt,
18914
- CAPXUL_TEST_WETH: SYNTHETIC_TEST_ASSET_FIXTURES.weth,
18915
- CAPXUL_TEST_EURC: SYNTHETIC_TEST_ASSET_FIXTURES.eurc
18916
- });
18917
- const CONFIGURED_MONEY_ASSETS = Object.freeze(Object.values(SETTLEMENT_ASSETS_BASE_SEPOLIA));
18918
- Object.freeze({ BASE_SEPOLIA: Object.freeze({
18919
- CAPXUL_TEST_USDC: SETTLEMENT_ASSETS_BASE_SEPOLIA.CAPXUL_TEST_USDC.assetId,
18920
- CAPXUL_TEST_USDT: SETTLEMENT_ASSETS_BASE_SEPOLIA.CAPXUL_TEST_USDT.assetId,
18921
- CAPXUL_TEST_WETH: SETTLEMENT_ASSETS_BASE_SEPOLIA.CAPXUL_TEST_WETH.assetId,
18922
- CAPXUL_TEST_EURC: SETTLEMENT_ASSETS_BASE_SEPOLIA.CAPXUL_TEST_EURC.assetId
18923
- }) });
18924
- /**
18925
- * Every known asset in ONE identity space. The tiers above declare admission;
18926
- * this is the only list an identity resolves against, so an asset is never
18927
- * two different things depending on which list a caller happened to read.
18928
- */
18929
- const MONEY_ASSET_REGISTRY = [...SYNTHETIC_TEST_ASSETS];
18930
- CONFIGURED_MONEY_ASSETS.map((asset) => asset.tokenAddress.toLowerCase());
18931
- /** The registry row for `assetId` across every tier, or `null`. */
18932
- function configuredMoneyAssetById(assetId) {
18933
- const canonical = toAssetId(assetId);
18934
- return MONEY_ASSET_REGISTRY.find((asset) => asset.assetId === canonical) ?? null;
18935
- }
18936
- //#endregion
18937
19024
  //#region ../../packages/protocol/src/documents/receipts.ts
18938
19025
  async function parseSupportingReceiptV3(input) {
18939
19026
  const supporting = SchemaParser.decodeUnknownSync(SupportingReceiptInputSchema, { onExcessProperty: "error" })(input);
@@ -18964,23 +19051,6 @@ async function parseSupportingReceiptV3(input) {
18964
19051
  };
18965
19052
  }
18966
19053
  //#endregion
18967
- //#region ../../packages/protocol/src/documents/identities.ts
18968
- /** A caller handed this module a value its own types rule out: a defect, named. */
18969
- function defect$1(step, message) {
18970
- return new CapxulError("UNKNOWN", message, { details: { step } });
18971
- }
18972
- function hashDocumentOriginIdV3(input) {
18973
- if (!Number.isSafeInteger(input.chainId) || input.chainId <= 0 || !Number.isSafeInteger(input.itemIndex) || input.itemIndex < 0 || input.actorKind !== "account" && input.actorKind !== "organization" || input.actorId.length === 0 || input.requestKey.length === 0) throw defect$1("hashDocumentOriginIdV3", "Invalid document origin input");
18974
- return keccak256$1(encodeAbiParameters$1(parseAbiParameters("string namespace, uint256 chainId, string actorKind, string actorId, string requestKey, uint256 itemIndex"), [
18975
- "capxul.document-origin.v3",
18976
- BigInt(input.chainId),
18977
- input.actorKind,
18978
- input.actorId,
18979
- input.requestKey,
18980
- BigInt(input.itemIndex)
18981
- ]));
18982
- }
18983
- //#endregion
18984
19054
  //#region ../../packages/protocol/src/documents/context.ts
18985
19055
  function sameAmount(left, right) {
18986
19056
  return left.asset === right.asset && left.minorUnits === right.minorUnits && left.decimals === right.decimals;
@@ -19261,6 +19331,25 @@ function verifiesInvoiceCheckoutBirthEvidence(evidence, invoice, chainId, source
19261
19331
  return "kind" in evidence.request && evidence.request.kind === "invoice_checkout" && evidence.request.linkToken === invoice.linkToken && evidence.preparedCommand?.items.length === 1 && item?.operation === "send" && evidence.preparedCommand.senderSafe.toLowerCase() === sourceWallet.toLowerCase() && evidence.preparedCommand.contractAddress.toLowerCase() === invoice.contractAddress.toLowerCase() && item.settlementId === invoice.settlementId && item.documentHash === invoice.documentHash && item.recipientSafe.toLowerCase() === invoice.recipientSafe.toLowerCase() && item.tokenAddress.toLowerCase() === invoice.tokenAddress.toLowerCase() && item.rawAmount === invoice.rawAmount && item.kind === (invoice.documentKind === "memo" ? 0 : 1) && invoice.chainId === chainId;
19262
19332
  }
19263
19333
  //#endregion
19334
+ //#region ../../packages/protocol/src/payments/execution-identity.ts
19335
+ /** A command and its exact signed operation have one durable execution identity. */
19336
+ function moneyExecutionId(commandId, digest) {
19337
+ return `money_execution_${keccak256$1(encodeAbiParameters$1([
19338
+ { type: "string" },
19339
+ { type: "string" },
19340
+ { type: "bytes32" }
19341
+ ], [
19342
+ "capxul.money-execution.v1",
19343
+ commandId,
19344
+ toLowerBytes32(digest)
19345
+ ])).slice(2)}`;
19346
+ }
19347
+ /** Existing stored executions keep their digest-derived identity. */
19348
+ function matchesMoneyExecutionId(executionId, digest, commandId) {
19349
+ const exactDigest = toLowerBytes32(digest);
19350
+ return executionId === `money_execution_${exactDigest.slice(2)}` || commandId !== void 0 && executionId === moneyExecutionId(commandId, exactDigest);
19351
+ }
19352
+ //#endregion
19264
19353
  //#region ../../packages/protocol/src/evm/payments-abi.ts
19265
19354
  /** The exact compiled CapxulPaymentsV2 ABI. */
19266
19355
  const CAPXUL_PAYMENTS_V2_ABI = [
@@ -19815,17 +19904,280 @@ const CAPXUL_PAYMENTS_V2_ABI = [
19815
19904
  },
19816
19905
  {
19817
19906
  type: "error",
19818
- name: "AlreadyCancelled",
19819
- inputs: []
19907
+ name: "AlreadyCancelled",
19908
+ inputs: []
19909
+ },
19910
+ {
19911
+ type: "error",
19912
+ name: "AlreadyClaimed",
19913
+ inputs: []
19914
+ },
19915
+ {
19916
+ type: "error",
19917
+ name: "DocumentHashMismatch",
19918
+ inputs: [{
19919
+ name: "expected",
19920
+ type: "bytes32",
19921
+ internalType: "bytes32"
19922
+ }, {
19923
+ name: "supplied",
19924
+ type: "bytes32",
19925
+ internalType: "bytes32"
19926
+ }]
19927
+ },
19928
+ {
19929
+ type: "error",
19930
+ name: "InvalidTimeParams",
19931
+ inputs: []
19932
+ },
19933
+ {
19934
+ type: "error",
19935
+ name: "NotCreator",
19936
+ inputs: []
19937
+ },
19938
+ {
19939
+ type: "error",
19940
+ name: "NotRecipient",
19941
+ inputs: []
19942
+ },
19943
+ {
19944
+ type: "error",
19945
+ name: "NothingToClaim",
19946
+ inputs: []
19947
+ },
19948
+ {
19949
+ type: "error",
19950
+ name: "SettlementIdConsumed",
19951
+ inputs: [{
19952
+ name: "settlementId",
19953
+ type: "bytes32",
19954
+ internalType: "bytes32"
19955
+ }]
19956
+ },
19957
+ {
19958
+ type: "error",
19959
+ name: "TokenCallReturnedFalse",
19960
+ inputs: [{
19961
+ name: "token",
19962
+ type: "address",
19963
+ internalType: "address"
19964
+ }]
19965
+ },
19966
+ {
19967
+ type: "error",
19968
+ name: "TokenHasNoCode",
19969
+ inputs: [{
19970
+ name: "token",
19971
+ type: "address",
19972
+ internalType: "address"
19973
+ }]
19974
+ },
19975
+ {
19976
+ type: "error",
19977
+ name: "ZeroAddress",
19978
+ inputs: []
19979
+ },
19980
+ {
19981
+ type: "error",
19982
+ name: "ZeroAmount",
19983
+ inputs: []
19984
+ },
19985
+ {
19986
+ type: "error",
19987
+ name: "ZeroDocumentHash",
19988
+ inputs: []
19989
+ },
19990
+ {
19991
+ type: "error",
19992
+ name: "ZeroSettlementId",
19993
+ inputs: []
19994
+ }
19995
+ ];
19996
+ /** Immutable CapxulPaymentsV2 deployment on Base Sepolia. */
19997
+ const CAPXUL_PAYMENTS_V2_ADDRESS = "0x7a5c25aB7ce91d7a475B71cd1ec33E230291f8a4";
19998
+ //#endregion
19999
+ //#region ../../packages/protocol/src/evm/payments-v3.ts
20000
+ const PAYMENT_ITEM_COMPONENTS = [
20001
+ {
20002
+ name: "settlementId",
20003
+ type: "bytes32",
20004
+ internalType: "bytes32"
20005
+ },
20006
+ {
20007
+ name: "recipient",
20008
+ type: "address",
20009
+ internalType: "address"
20010
+ },
20011
+ {
20012
+ name: "token",
20013
+ type: "address",
20014
+ internalType: "address"
20015
+ },
20016
+ {
20017
+ name: "amount",
20018
+ type: "uint256",
20019
+ internalType: "uint256"
20020
+ },
20021
+ {
20022
+ name: "kind",
20023
+ type: "uint16",
20024
+ internalType: "uint16"
20025
+ },
20026
+ {
20027
+ name: "documentHash",
20028
+ type: "bytes32",
20029
+ internalType: "bytes32"
20030
+ },
20031
+ {
20032
+ name: "jobNonce",
20033
+ type: "bytes32",
20034
+ internalType: "bytes32"
20035
+ },
20036
+ {
20037
+ name: "executor",
20038
+ type: "address",
20039
+ internalType: "address"
20040
+ }
20041
+ ];
20042
+ const PAYMENT_ITEM_INPUT = {
20043
+ name: "item",
20044
+ type: "tuple",
20045
+ internalType: "struct CapxulPaymentsV3.PaymentItem",
20046
+ components: PAYMENT_ITEM_COMPONENTS
20047
+ };
20048
+ /** The exact compiled CapxulPaymentsV3 ABI. */
20049
+ const CAPXUL_PAYMENTS_V3_ABI = [
20050
+ {
20051
+ type: "function",
20052
+ name: "paymentId",
20053
+ inputs: [PAYMENT_ITEM_INPUT],
20054
+ outputs: [{
20055
+ name: "",
20056
+ type: "bytes32",
20057
+ internalType: "bytes32"
20058
+ }],
20059
+ stateMutability: "view"
20060
+ },
20061
+ {
20062
+ type: "function",
20063
+ name: "send",
20064
+ inputs: [PAYMENT_ITEM_INPUT],
20065
+ outputs: [],
20066
+ stateMutability: "nonpayable"
20067
+ },
20068
+ {
20069
+ type: "function",
20070
+ name: "sendBatch",
20071
+ inputs: [{
20072
+ name: "items",
20073
+ type: "tuple[]",
20074
+ internalType: "struct CapxulPaymentsV3.PaymentItem[]",
20075
+ components: PAYMENT_ITEM_COMPONENTS
20076
+ }],
20077
+ outputs: [],
20078
+ stateMutability: "nonpayable"
20079
+ },
20080
+ {
20081
+ type: "function",
20082
+ name: "settled",
20083
+ inputs: [{
20084
+ name: "",
20085
+ type: "bytes32",
20086
+ internalType: "bytes32"
20087
+ }],
20088
+ outputs: [{
20089
+ name: "",
20090
+ type: "bool",
20091
+ internalType: "bool"
20092
+ }],
20093
+ stateMutability: "view"
20094
+ },
20095
+ {
20096
+ type: "event",
20097
+ name: "PaymentSent",
20098
+ inputs: [
20099
+ {
20100
+ name: "settlementId",
20101
+ type: "bytes32",
20102
+ indexed: true,
20103
+ internalType: "bytes32"
20104
+ },
20105
+ {
20106
+ name: "sender",
20107
+ type: "address",
20108
+ indexed: true,
20109
+ internalType: "address"
20110
+ },
20111
+ {
20112
+ name: "recipient",
20113
+ type: "address",
20114
+ indexed: true,
20115
+ internalType: "address"
20116
+ },
20117
+ {
20118
+ name: "token",
20119
+ type: "address",
20120
+ indexed: false,
20121
+ internalType: "address"
20122
+ },
20123
+ {
20124
+ name: "amount",
20125
+ type: "uint256",
20126
+ indexed: false,
20127
+ internalType: "uint256"
20128
+ },
20129
+ {
20130
+ name: "kind",
20131
+ type: "uint16",
20132
+ indexed: false,
20133
+ internalType: "uint16"
20134
+ },
20135
+ {
20136
+ name: "documentHash",
20137
+ type: "bytes32",
20138
+ indexed: false,
20139
+ internalType: "bytes32"
20140
+ }
20141
+ ],
20142
+ anonymous: false
20143
+ },
20144
+ {
20145
+ type: "error",
20146
+ name: "InexactTransfer",
20147
+ inputs: [
20148
+ {
20149
+ name: "token",
20150
+ type: "address",
20151
+ internalType: "address"
20152
+ },
20153
+ {
20154
+ name: "expected",
20155
+ type: "uint256",
20156
+ internalType: "uint256"
20157
+ },
20158
+ {
20159
+ name: "received",
20160
+ type: "uint256",
20161
+ internalType: "uint256"
20162
+ }
20163
+ ]
19820
20164
  },
19821
20165
  {
19822
20166
  type: "error",
19823
- name: "AlreadyClaimed",
19824
- inputs: []
20167
+ name: "InvalidExecutor",
20168
+ inputs: [{
20169
+ name: "expected",
20170
+ type: "address",
20171
+ internalType: "address"
20172
+ }, {
20173
+ name: "supplied",
20174
+ type: "address",
20175
+ internalType: "address"
20176
+ }]
19825
20177
  },
19826
20178
  {
19827
20179
  type: "error",
19828
- name: "DocumentHashMismatch",
20180
+ name: "PaymentIdMismatch",
19829
20181
  inputs: [{
19830
20182
  name: "expected",
19831
20183
  type: "bytes32",
@@ -19838,22 +20190,7 @@ const CAPXUL_PAYMENTS_V2_ABI = [
19838
20190
  },
19839
20191
  {
19840
20192
  type: "error",
19841
- name: "InvalidTimeParams",
19842
- inputs: []
19843
- },
19844
- {
19845
- type: "error",
19846
- name: "NotCreator",
19847
- inputs: []
19848
- },
19849
- {
19850
- type: "error",
19851
- name: "NotRecipient",
19852
- inputs: []
19853
- },
19854
- {
19855
- type: "error",
19856
- name: "NothingToClaim",
20193
+ name: "ReentrantCall",
19857
20194
  inputs: []
19858
20195
  },
19859
20196
  {
@@ -19898,14 +20235,73 @@ const CAPXUL_PAYMENTS_V2_ABI = [
19898
20235
  name: "ZeroDocumentHash",
19899
20236
  inputs: []
19900
20237
  },
20238
+ {
20239
+ type: "error",
20240
+ name: "ZeroJobNonce",
20241
+ inputs: []
20242
+ },
19901
20243
  {
19902
20244
  type: "error",
19903
20245
  name: "ZeroSettlementId",
19904
20246
  inputs: []
19905
20247
  }
19906
20248
  ];
19907
- /** Immutable CapxulPaymentsV2 deployment on Base Sepolia. */
19908
- const CAPXUL_PAYMENTS_V2_ADDRESS = "0x7a5c25aB7ce91d7a475B71cd1ec33E230291f8a4";
20249
+ /** The fixed CREATE2 deployment on every admitted chain. */
20250
+ const CAPXUL_PAYMENTS_V3_ADDRESS = "0x46b28f455c8de7c1505e3185A3f8f87B07eaE1aE";
20251
+ //#endregion
20252
+ //#region ../../packages/protocol/src/evm/payments/encoding.ts
20253
+ const CAPXUL_PAYMENT_V3_TYPEHASH = keccak256$1(toBytes$1("CapxulPayment(uint256 chainId,address router,bytes32 jobNonce,address executor,address recipient,address token,uint256 amount,uint16 kind,bytes32 documentHash)"));
20254
+ function paymentJobNonce(commandId, itemIndex) {
20255
+ if (!Number.isSafeInteger(itemIndex) || itemIndex < 0) throw Errors.invalidInput("itemIndex", "must be a non-negative safe integer");
20256
+ return sha256(toBytes$1(`{"commandId":${JSON.stringify(commandId)},"index":${itemIndex},"version":1}`));
20257
+ }
20258
+ function capxulPaymentsV3PaymentId(chainId, router, item) {
20259
+ return keccak256$1(encodeAbiParameters$1(parseAbiParameters("bytes32,uint256,address,bytes32,address,address,address,uint256,uint16,bytes32"), [
20260
+ CAPXUL_PAYMENT_V3_TYPEHASH,
20261
+ BigInt(chainId),
20262
+ router,
20263
+ item.jobNonce,
20264
+ item.executor,
20265
+ item.recipient,
20266
+ item.token,
20267
+ item.amount,
20268
+ item.kind,
20269
+ item.documentHash
20270
+ ]));
20271
+ }
20272
+ function encodeCapxulPaymentsV3Send(item) {
20273
+ return encodeFunctionData({
20274
+ abi: CAPXUL_PAYMENTS_V3_ABI,
20275
+ functionName: "send",
20276
+ args: [item]
20277
+ });
20278
+ }
20279
+ function encodeCapxulPaymentsV3SendBatch(items) {
20280
+ return encodeFunctionData({
20281
+ abi: CAPXUL_PAYMENTS_V3_ABI,
20282
+ functionName: "sendBatch",
20283
+ args: [items]
20284
+ });
20285
+ }
20286
+ function v3Item(command, item, itemIndex) {
20287
+ const { commandId, chainId, senderSafe } = command;
20288
+ if (commandId === void 0 || chainId === void 0 || senderSafe === void 0) throw Errors.invalidInput("command", "CapxulPaymentsV3 requires its command identity");
20289
+ const terms = {
20290
+ recipient: item.recipientSafe,
20291
+ token: item.tokenAddress,
20292
+ amount: BigInt(item.rawAmount),
20293
+ kind: item.kind,
20294
+ documentHash: item.documentHash,
20295
+ jobNonce: item.jobNonce ?? paymentJobNonce(commandId, itemIndex),
20296
+ executor: item.executor ?? senderSafe
20297
+ };
20298
+ const settlementId = capxulPaymentsV3PaymentId(chainId, command.contractAddress, terms);
20299
+ if (settlementId.toLowerCase() !== item.settlementId.toLowerCase()) throw Errors.invalidInput("settlementId", "does not match CapxulPaymentsV3 terms");
20300
+ return {
20301
+ settlementId,
20302
+ ...terms
20303
+ };
20304
+ }
19909
20305
  //#endregion
19910
20306
  //#region ../../packages/protocol/src/evm/zodiac-abi.ts
19911
20307
  const MODULE_PROXY_FACTORY_ABI = [{
@@ -20270,7 +20666,8 @@ function requiredByPaymentToken(items) {
20270
20666
  }
20271
20667
  return totals;
20272
20668
  }
20273
- function birthCall(contract, item) {
20669
+ function birthCall(command, item, itemIndex) {
20670
+ const contract = command.contractAddress;
20274
20671
  const common = {
20275
20672
  settlementId: item.settlementId,
20276
20673
  recipient: item.recipientSafe,
@@ -20281,7 +20678,7 @@ function birthCall(contract, item) {
20281
20678
  return {
20282
20679
  to: contract,
20283
20680
  value: 0n,
20284
- data: item.operation === "send" ? encodeCapxulPaymentsV2Send({
20681
+ data: item.operation === "send" ? contract.toLowerCase() === "0x46b28f455c8de7c1505e3185A3f8f87B07eaE1aE".toLowerCase() ? encodeCapxulPaymentsV3Send(v3Item(command, item, itemIndex)) : encodeCapxulPaymentsV2Send({
20285
20682
  ...common,
20286
20683
  amount: BigInt(item.rawAmount)
20287
20684
  }) : encodeCapxulPaymentsV2CreateCommitment({
@@ -20293,7 +20690,8 @@ function birthCall(contract, item) {
20293
20690
  })
20294
20691
  };
20295
20692
  }
20296
- function birthCalls(contract, items) {
20693
+ function birthCalls(command, items) {
20694
+ const contract = command.contractAddress;
20297
20695
  const approvals = [...requiredByPaymentToken(items).values()].map(({ token, total }) => ({
20298
20696
  to: token,
20299
20697
  value: 0n,
@@ -20307,7 +20705,7 @@ function birthCalls(contract, items) {
20307
20705
  if (items.length > 1 && sends.length === items.length) return [...approvals, {
20308
20706
  to: contract,
20309
20707
  value: 0n,
20310
- data: encodeCapxulPaymentsV2SendBatch(sends.map((item) => ({
20708
+ data: contract.toLowerCase() === "0x46b28f455c8de7c1505e3185A3f8f87B07eaE1aE".toLowerCase() ? encodeCapxulPaymentsV3SendBatch(sends.map((item, index) => v3Item(command, item, index))) : encodeCapxulPaymentsV2SendBatch(sends.map((item) => ({
20311
20709
  settlementId: item.settlementId,
20312
20710
  recipient: item.recipientSafe,
20313
20711
  token: item.tokenAddress,
@@ -20316,7 +20714,7 @@ function birthCalls(contract, items) {
20316
20714
  documentHash: item.documentHash
20317
20715
  })))
20318
20716
  }];
20319
- return [...approvals, ...items.map((item) => birthCall(contract, item))];
20717
+ return [...approvals, ...items.map((item, index) => birthCall(command, item, index))];
20320
20718
  }
20321
20719
  function lifecycleData(item) {
20322
20720
  switch (item.operation) {
@@ -20331,7 +20729,7 @@ function encodePreparedPaymentCallData(command) {
20331
20729
  if (command.items.length === 0) throw Errors.invalidInput("items", "must not be empty");
20332
20730
  const births = command.items.filter(isBirth);
20333
20731
  if (births.length === command.items.length) {
20334
- const calls = birthCalls(command.contractAddress, births);
20732
+ const calls = birthCalls(command, births);
20335
20733
  return command.executionRoute.kind === "direct" ? safe4337MultiSendUserOpCallData({ calls }) : buildOrgRoleSpendPersonalCallData(buildOrgRoleMultiCall({
20336
20734
  rolesModuleAddress: command.executionRoute.rolesModule,
20337
20735
  roleKey: command.executionRoute.roleKey,
@@ -20394,15 +20792,16 @@ function verifiesMoneyOperation(evidence, expectedSafe, chainId, permissionId) {
20394
20792
  try {
20395
20793
  const command = evidence.preparedCommand;
20396
20794
  const operation = evidence.userOperation;
20397
- if (command === void 0 || operation === void 0 || false) return false;
20398
- if (command.commandId !== evidence.commandId || command.chainId !== chainId || evidence.chainId !== chainId || command.contractAddress.toLowerCase() !== "0x7a5c25aB7ce91d7a475B71cd1ec33E230291f8a4".toLowerCase() || command.items.length !== evidence.paymentIds.length || command.items.some((item, index) => item.paymentId !== evidence.paymentIds[index]) || evidence.userOpSenderSafe.toLowerCase() !== expectedSafe.toLowerCase() || command.executionRoute.userOpSenderSafe.toLowerCase() !== expectedSafe.toLowerCase() || operation.sender.toLowerCase() !== expectedSafe.toLowerCase()) return false;
20795
+ if (command === void 0 || operation === void 0) return false;
20796
+ const knownRouter = command.contractAddress.toLowerCase() === "0x7a5c25aB7ce91d7a475B71cd1ec33E230291f8a4".toLowerCase() || command.contractAddress.toLowerCase() === "0x46b28f455c8de7c1505e3185A3f8f87B07eaE1aE".toLowerCase();
20797
+ if (command.commandId !== evidence.commandId || command.chainId !== chainId || evidence.chainId !== chainId || !knownRouter || command.items.length !== evidence.paymentIds.length || command.items.some((item, index) => item.paymentId !== evidence.paymentIds[index]) || evidence.userOpSenderSafe.toLowerCase() !== expectedSafe.toLowerCase() || command.executionRoute.userOpSenderSafe.toLowerCase() !== expectedSafe.toLowerCase() || operation.sender.toLowerCase() !== expectedSafe.toLowerCase()) return false;
20399
20798
  const route = command.executionRoute;
20400
20799
  if (route.kind === "direct") {
20401
20800
  if (permissionId !== void 0 || command.senderSafe.toLowerCase() !== expectedSafe.toLowerCase()) return false;
20402
20801
  } else if ((permissionId === void 0 ? !isOwnerLifecycle(command) : route.roleKey.toLowerCase() !== roleKeyForPermission(permissionId).toLowerCase()) || command.senderSafe.toLowerCase() !== route.organizationSafe.toLowerCase()) return false;
20403
20802
  if (operation.callData.toLowerCase() !== encodePreparedPaymentCallData(command).toLowerCase()) return false;
20404
20803
  const digest = moneySafeOpDigest(operation, chainId);
20405
- return evidence.digest.toLowerCase() === digest.toLowerCase() && evidence.executionId === `money_execution_${digest.slice(2).toLowerCase()}`;
20804
+ return evidence.digest.toLowerCase() === digest.toLowerCase() && matchesMoneyExecutionId(evidence.executionId, digest, evidence.commandId);
20406
20805
  } catch {
20407
20806
  return false;
20408
20807
  }
@@ -20538,6 +20937,29 @@ function reportMoneyTelemetryFailure(kind, name, cause) {
20538
20937
  }));
20539
20938
  }
20540
20939
  //#endregion
20940
+ //#region ../../packages/protocol/src/payments/request-finality.ts
20941
+ /** Add a proved request outcome without changing the original failure. */
20942
+ function withPaymentRequestFinality(error, paymentRequestFinality) {
20943
+ const marked = new CapxulError(error.code, error.message, {
20944
+ cause: error.cause,
20945
+ details: {
20946
+ ...error.details,
20947
+ paymentRequestFinality
20948
+ },
20949
+ ...error.correlationId === void 0 ? {} : { correlationId: error.correlationId },
20950
+ ...error.layer === void 0 ? {} : { layer: error.layer },
20951
+ ...error.mode === void 0 ? {} : { mode: error.mode },
20952
+ ...error.chain === void 0 ? {} : { chain: error.chain }
20953
+ });
20954
+ marked.name = error.name;
20955
+ if (error.stack !== void 0) marked.stack = error.stack;
20956
+ return marked;
20957
+ }
20958
+ /** Only an authoritative failed-key response or confirmed durable closure resolves a key. */
20959
+ function isFinalPaymentRequestError(error) {
20960
+ return error.details?.paymentRequestFinality === "closed" || error.code === "INVALID_INPUT" && error.details?.field === "requestKey" && error.details.paymentRequestFinality === "failed";
20961
+ }
20962
+ //#endregion
20541
20963
  //#region ../../packages/sdk/src/payments/prepared-execution.ts
20542
20964
  async function abandonPrepared(deps, executionId, reason, result, onPreparedClosed) {
20543
20965
  const abandoned = await runIfActive(void 0, executions.abandon.name, () => callOperation(deps.convexCall, executions.abandon, {
@@ -20545,8 +20967,12 @@ async function abandonPrepared(deps, executionId, reason, result, onPreparedClos
20545
20967
  reason
20546
20968
  }).pipe(Effect.mapError((publicError) => ({ publicError }))), deps.runPromise);
20547
20969
  if (!abandoned.ok) return abandoned;
20548
- if (abandoned.value) onPreparedClosed?.();
20549
- return result;
20970
+ if (!abandoned.value) return result;
20971
+ onPreparedClosed?.();
20972
+ return result.ok ? result : {
20973
+ ok: false,
20974
+ error: withPaymentRequestFinality(result.error, "closed")
20975
+ };
20550
20976
  }
20551
20977
  async function notifyVerifiedPaymentPrepared(onPrepared, paymentId) {
20552
20978
  if (onPrepared === void 0) return {
@@ -20590,14 +21016,31 @@ async function abandonPreparedCommand(deps, executionId, closePayment, reason, r
20590
21016
  reason
20591
21017
  })).pipe(Effect.mapError((publicError) => ({ publicError })))), controls), deps.runPromise);
20592
21018
  if (!abandoned.ok) return abandoned;
20593
- if (abandoned.value) onPreparedClosed?.();
20594
- return result;
21019
+ if (!abandoned.value) return result;
21020
+ onPreparedClosed?.();
21021
+ return result.ok ? result : {
21022
+ ok: false,
21023
+ error: withPaymentRequestFinality(result.error, "closed")
21024
+ };
20595
21025
  }
20596
21026
  //#endregion
20597
21027
  //#region ../../packages/sdk/src/payments/command-execution.ts
20598
21028
  function isAborted$3(signal) {
20599
21029
  return signal?.aborted === true;
20600
21030
  }
21031
+ function settledPaymentsMatch(evidence) {
21032
+ try {
21033
+ return evidence.settled?.payments.every((payment, index) => {
21034
+ const item = evidence.preparedCommand?.items[index];
21035
+ const instructions = payment.documents.filter((document) => document.role === "instruction");
21036
+ const amount = toExactAssetAmount(payment.amount, CONFIGURED_MONEY_ASSETS);
21037
+ const asset = CONFIGURED_MONEY_ASSETS.find((row) => row.assetId === amount.asset);
21038
+ return item?.operation === "send" && payment.status === "settled" && payment.direction === "out" && payment.receipt?.chainId === evidence.chainId && item.tokenAddress.toLowerCase() === asset?.tokenAddress.toLowerCase() && item.rawAmount === amount.minorUnits && instructions.length === 1 && canonicalJson(instructions[0]) === canonicalJson(evidence.preparedCommand?.instructionDocuments?.[index]);
21039
+ }) === true;
21040
+ } catch {
21041
+ return false;
21042
+ }
21043
+ }
20601
21044
  async function executePrepared(deps, prepare, isExpectedRequest, closePaymentOnExit, onPreparedClosed, signal, controls, onPrepared, readAcceptedReplay, checkout, sourceWallet) {
20602
21045
  if (isAborted$3(signal)) return {
20603
21046
  ok: false,
@@ -20630,7 +21073,7 @@ async function executePrepared(deps, prepare, isExpectedRequest, closePaymentOnE
20630
21073
  const prepared = await prepare(signerAddress);
20631
21074
  if (!current()) return cancelled;
20632
21075
  if (!prepared.ok) return prepared;
20633
- const accepted = readAcceptedReplay?.();
21076
+ const accepted = readAcceptedReplay?.() ?? prepared.value.settled;
20634
21077
  const closePrepared = closePaymentOnExit && accepted === void 0;
20635
21078
  const executionId = Schema.decodeUnknownResult(MoneyExecutionIdSchema)(readField(prepared.value, "executionId"));
20636
21079
  if (executionId._tag === "Failure") return {
@@ -20656,12 +21099,12 @@ async function executePrepared(deps, prepare, isExpectedRequest, closePaymentOnE
20656
21099
  if (!verified) return abandon("prepared_mismatch", Errors.invalidInput("execution", "prepared Money operation mismatch"));
20657
21100
  if (accepted !== void 0) {
20658
21101
  const decodedSubmission = Schema.decodeResult(SubmittedPaymentCommandExecutionSchema, { onExcessProperty: "error" })(accepted);
20659
- if (decodedSubmission._tag === "Failure" || !acceptedSubmissionMatches(evidence, decodedSubmission.success)) return {
21102
+ if (decodedSubmission._tag === "Failure" || !acceptedSubmissionMatches(evidence, decodedSubmission.success) || evidence.settled !== void 0 && !settledPaymentsMatch(evidence)) return {
20660
21103
  ok: false,
20661
- error: Errors.invalidInput("execution", "accepted Payroll replay evidence mismatch")
21104
+ error: Errors.invalidInput("execution", "accepted Money replay evidence mismatch")
20662
21105
  };
20663
21106
  if (!current() || isAborted$3(signal)) return cancelled;
20664
- return {
21107
+ if (evidence.settled === void 0) return {
20665
21108
  ok: true,
20666
21109
  value: decodedSubmission.success
20667
21110
  };
@@ -20678,6 +21121,10 @@ async function executePrepared(deps, prepare, isExpectedRequest, closePaymentOnE
20678
21121
  }
20679
21122
  if (!current()) return cancelled;
20680
21123
  if (isAborted$3(signal)) return abandon("cancelled", Errors.cancelled({ operation: "payments" }));
21124
+ if (evidence.settled !== void 0) return {
21125
+ ok: true,
21126
+ value: evidence.settled
21127
+ };
20681
21128
  await emitPreparedInitiation(deps, evidence);
20682
21129
  if (!current()) return cancelled;
20683
21130
  if (isAborted$3(signal)) return abandon("cancelled", Errors.cancelled({ operation: "payments" }));
@@ -20728,10 +21175,10 @@ function itemMatches(prepared, amount) {
20728
21175
  return item.paymentId === prepared.paymentId && Object.entries(PAYMENT_PURPOSE_KIND_CODES).some(([name, code]) => name === prepared.purposeKind && code === item.kind) && expectedPurpose === prepared.purposeKind && documentKind === "invoice" === (purpose === "invoice") && purpose !== "payroll" && item.tokenAddress.toLowerCase() === asset?.tokenAddress.toLowerCase() && (item.operation === "send" ? item.rawAmount : item.totalAmount) === amount.minorUnits && plannedCommitmentMatches(prepared) && recipientMatches(prepared, item.recipientSafe.toLowerCase());
20729
21176
  }
20730
21177
  /** The callData a personal Payment birth item must carry: approve, then send or commit. */
20731
- function expectedPersonalCallData(prepared) {
21178
+ function expectedPersonalCallData(prepared, expectedSafe, chainId) {
20732
21179
  const item = prepared.item;
20733
21180
  if (item.operation !== "send" && item.operation !== "create_commitment") throw new Error("Expected personal Payment birth item");
20734
- const contract = CAPXUL_PAYMENTS_V2_ADDRESS;
21181
+ const contract = toAddress(CAPXUL_PAYMENTS_V2_ADDRESS);
20735
21182
  const { settlementId, recipientSafe, tokenAddress, documentHash } = item;
20736
21183
  const amount = BigInt(item.operation === "send" ? item.rawAmount : item.totalAmount);
20737
21184
  const paymentData = item.operation === "send" ? encodeCapxulPaymentsV2Send({
@@ -20752,26 +21199,61 @@ function expectedPersonalCallData(prepared) {
20752
21199
  kind: item.kind,
20753
21200
  documentHash
20754
21201
  });
20755
- return safe4337MultiSendUserOpCallData({ calls: [{
21202
+ const calls = (router, encodedPaymentData) => safe4337MultiSendUserOpCallData({ calls: [{
20756
21203
  to: tokenAddress,
20757
21204
  value: 0n,
20758
21205
  data: encodeFunctionData({
20759
21206
  abi: ERC20_APPROVE_ABI,
20760
21207
  functionName: "approve",
20761
- args: [contract, amount]
21208
+ args: [router, amount]
20762
21209
  })
20763
21210
  }, {
20764
- to: contract,
21211
+ to: router,
20765
21212
  value: 0n,
20766
- data: paymentData
21213
+ data: encodedPaymentData
20767
21214
  }] });
21215
+ const v2 = calls(contract, paymentData);
21216
+ if (item.operation !== "send") return [v2];
21217
+ const terms = {
21218
+ recipient: item.recipientSafe,
21219
+ token: item.tokenAddress,
21220
+ amount,
21221
+ kind: item.kind,
21222
+ documentHash,
21223
+ jobNonce: paymentJobNonce(prepared.commandId, 0),
21224
+ executor: toAddress(expectedSafe)
21225
+ };
21226
+ const v3Contract = toAddress(CAPXUL_PAYMENTS_V3_ADDRESS);
21227
+ const v3SettlementId = capxulPaymentsV3PaymentId(chainId, v3Contract, terms);
21228
+ if (v3SettlementId.toLowerCase() !== settlementId.toLowerCase()) return [v2];
21229
+ return [calls(v3Contract, encodeCapxulPaymentsV3Send({
21230
+ settlementId: v3SettlementId,
21231
+ ...terms
21232
+ }))];
20768
21233
  }
20769
21234
  function verifiesPersonalOperation(prepared, expectedSafe, chainId) {
20770
21235
  try {
20771
21236
  const operation = prepared.userOperation;
20772
- if (operation.sender.toLowerCase() !== expectedSafe.toLowerCase() || operation.callData.toLowerCase() !== expectedPersonalCallData(prepared).toLowerCase()) return false;
21237
+ if (operation.sender.toLowerCase() !== expectedSafe.toLowerCase() || !expectedPersonalCallData(prepared, expectedSafe, chainId).some((callData) => operation.callData.toLowerCase() === callData.toLowerCase())) return false;
20773
21238
  const digest = moneySafeOpDigest(operation, chainId);
20774
- return prepared.digest.toLowerCase() === digest.toLowerCase() && prepared.executionId === `money_execution_${digest.slice(2).toLowerCase()}`;
21239
+ return prepared.digest.toLowerCase() === digest.toLowerCase() && matchesMoneyExecutionId(prepared.executionId, digest, prepared.commandId);
21240
+ } catch {
21241
+ return false;
21242
+ }
21243
+ }
21244
+ /** A settled reply retains the verified operation, quantity, instruction and receipt. */
21245
+ function verifiesSettledPersonalReplay(evidence) {
21246
+ const settled = evidence.settled;
21247
+ if (settled === void 0) return true;
21248
+ try {
21249
+ const instructions = settled.payment.documents.filter((document) => document.role === "instruction");
21250
+ return acceptedSubmissionMatches({
21251
+ ...evidence,
21252
+ paymentIds: [evidence.paymentId]
21253
+ }, {
21254
+ ...settled,
21255
+ payments: [settled.payment]
21256
+ }) && settled.payment.status === "settled" && settled.payment.direction === "out" && settled.payment.receipt?.chainId === evidence.chainId && itemMatches(evidence, toExactAssetAmount(settled.payment.amount, CONFIGURED_MONEY_ASSETS)) && instructions.length === 1 && canonicalJson(instructions[0]) === canonicalJson(evidence.instructionDocument);
20775
21257
  } catch {
20776
21258
  return false;
20777
21259
  }
@@ -20885,6 +21367,7 @@ async function preparedMismatch(chainId, evidence, payment, expected) {
20885
21367
  if (evidence.userOpSenderSafe.toLowerCase() !== expected.expectedSafe.toLowerCase()) return mismatch$1("userOpSenderSafe", "prepared Payment execution uses another Account Safe");
20886
21368
  if (!await verifiesPersonalDocument(evidence)) return mismatch$1("document", "prepared Payment document does not match the request");
20887
21369
  if (!verifiesPersonalOperation(evidence, expected.expectedSafe, chainId)) return mismatch$1("execution", "prepared Payment operation does not match the request");
21370
+ if (!verifiesSettledPersonalReplay(evidence)) return mismatch$1("execution", "settled Payment replay evidence mismatch");
20888
21371
  }
20889
21372
  /**
20890
21373
  * Prepare one personal Payment for this signer and check what the backend
@@ -20935,19 +21418,27 @@ async function emitPreparedPaymentInitiated(deps, evidence) {
20935
21418
  async function executePersonalPayment(deps, payment, signal, requestKey, onPreparedClosed, onPrepared) {
20936
21419
  if (isAborted$2(signal)) return cancelled$1(CAPXUL_OPERATIONS.payments.pay);
20937
21420
  if (deps.signer === void 0) return mismatch$1("signer", "payments.pay requires a configured CapxulSigner");
20938
- if (deps.actor.authSession() === null) return {
21421
+ const session = deps.actor.authSession();
21422
+ if (session === null) return {
20939
21423
  ok: false,
20940
21424
  error: Errors.notAuthenticated()
20941
21425
  };
21426
+ const lifetime = deps.actor.authLifetime();
21427
+ const current = () => deps.actor.matchesAuthLifetime(lifetime, session.authUserId);
20942
21428
  const signerAddress = await signerCall(deps.signer.source, "getAddress", () => deps.signer.getAddress());
20943
21429
  if (!signerAddress.ok) return signerAddress;
20944
21430
  const prepared = await prepareVerifiedPersonalPayment(deps, payment, signerAddress.value, requestKey ?? `pay_${crypto.randomUUID()}`, signal, onPreparedClosed);
20945
21431
  if (!prepared.ok) return prepared;
20946
21432
  const evidence = prepared.value;
21433
+ if (evidence.settled !== void 0 && !current()) return cancelled$1(CAPXUL_OPERATIONS.payments.pay);
20947
21434
  const digest = evidence.digest;
20948
21435
  if (isAborted$2(signal)) return abandonPrepared(deps, evidence.executionId, "cancelled", cancelled$1(CAPXUL_OPERATIONS.payments.pay), onPreparedClosed);
20949
21436
  const delivered = await notifyVerifiedPaymentPrepared(onPrepared, evidence.paymentId);
20950
21437
  if (!delivered.ok) return delivered;
21438
+ if (evidence.settled !== void 0) return current() ? {
21439
+ ok: true,
21440
+ value: evidence.settled
21441
+ } : cancelled$1(CAPXUL_OPERATIONS.payments.pay);
20951
21442
  if (isAborted$2(signal)) return abandonPrepared(deps, evidence.executionId, "cancelled", cancelled$1(CAPXUL_OPERATIONS.payments.pay), onPreparedClosed);
20952
21443
  await emitPreparedPaymentInitiated(deps, evidence);
20953
21444
  if (isAborted$2(signal)) return abandonPrepared(deps, evidence.executionId, "cancelled", cancelled$1(CAPXUL_OPERATIONS.payments.pay), onPreparedClosed);
@@ -21450,6 +21941,41 @@ function resolvedTargetFromResolution(resolution) {
21450
21941
  };
21451
21942
  }
21452
21943
  //#endregion
21944
+ //#region ../../packages/sdk/src/requests/request-keys.ts
21945
+ /** Keep an Invoice attempt through uncertainty; renew an old failed default only before preparation. */
21946
+ async function withInvoiceRequestKey(actorId, intent, provided, run) {
21947
+ let key;
21948
+ let prepared = false;
21949
+ try {
21950
+ key = await paymentRequestKeyLifecycle(`invoice-request:${actorId}`, intent, provided);
21951
+ let result = await run(key.key, () => {
21952
+ prepared = true;
21953
+ });
21954
+ const renew = provided === void 0 && !prepared && !result.ok && isFinalPaymentRequestError(result.error) && result.error.details?.paymentRequestFinality === "failed";
21955
+ let finished = true;
21956
+ try {
21957
+ await key.finish(!result.ok && isFinalPaymentRequestError(result.error));
21958
+ } catch {
21959
+ finished = false;
21960
+ }
21961
+ if (renew && finished) {
21962
+ key = await paymentRequestKeyLifecycle(`invoice-request:${actorId}`, intent);
21963
+ result = await run(key.key, () => {
21964
+ prepared = true;
21965
+ });
21966
+ await key.finish(!result.ok && isFinalPaymentRequestError(result.error)).catch(() => void 0);
21967
+ }
21968
+ return result;
21969
+ } catch (cause) {
21970
+ return {
21971
+ ok: false,
21972
+ error: asCapxulError(cause)
21973
+ };
21974
+ } finally {
21975
+ await key?.finish(false).catch(() => void 0);
21976
+ }
21977
+ }
21978
+ //#endregion
21453
21979
  //#region ../../packages/sdk/src/requests/checkout-payments.ts
21454
21980
  const missing$1 = async () => ({
21455
21981
  ok: false,
@@ -21639,72 +22165,96 @@ function makeCheckoutMethods(deps) {
21639
22165
  }
21640
22166
  //#endregion
21641
22167
  //#region ../../packages/sdk/src/requests/inbox-payments.ts
21642
- function mapApprovedInboxPayment(command, input) {
22168
+ const refused = () => ({
22169
+ ok: false,
22170
+ error: Errors.providerError("convex", inboxes.approve.name, "approved Payment read does not match its command")
22171
+ });
22172
+ /** Read the approved command's actual Payment under the payer's existing scope. */
22173
+ async function readApprovedInboxPayment(calls, command, controls, current) {
21643
22174
  const item = command.items[0];
21644
- if (item === void 0 || item.operation !== "send" && item.operation !== "create_commitment") return {
22175
+ const cancelled = {
21645
22176
  ok: false,
21646
- error: Errors.providerError("convex", inboxes.approve.name, "reply has no payment birth item")
22177
+ error: Errors.cancelled({ operation: inboxes.approve.name })
21647
22178
  };
21648
- try {
21649
- const asset = CONFIGURED_MONEY_ASSETS.find((candidate) => candidate.tokenAddress.toLowerCase() === item.tokenAddress.toLowerCase());
21650
- if (asset === void 0) return {
21651
- ok: false,
21652
- error: Errors.providerError("convex", inboxes.approve.name, "prepared payment asset is not configured")
21653
- };
21654
- const amount = {
21655
- asset: asset.assetId,
21656
- value: formatUnits(BigInt(item.operation === "send" ? item.rawAmount : item.totalAmount), asset.decimals)
21657
- };
21658
- const zero = {
21659
- ...amount,
21660
- value: "0"
21661
- };
21662
- const timing = input.timing ?? { kind: "instant" };
21663
- return {
21664
- ok: true,
21665
- value: {
21666
- id: item.paymentId,
21667
- status: timing.kind === "instant" ? "pending" : timing.kind === "scheduled" ? "scheduled" : "streaming",
21668
- amount,
21669
- paymentType: "invoice",
21670
- direction: "out",
21671
- counterpartyLabel: item.recipientSafe,
21672
- receipt: null,
21673
- recipient: {
21674
- kind: "external_address",
21675
- label: item.recipientSafe
21676
- },
21677
- documents: [],
21678
- timing,
21679
- released: zero,
21680
- availableToClaim: zero,
21681
- createdAt: 0,
21682
- updatedAt: 0
21683
- }
21684
- };
21685
- } catch (cause) {
21686
- return {
21687
- ok: false,
21688
- error: Errors.unknown(cause)
21689
- };
21690
- }
22179
+ if (command.items.length !== 1 || item === void 0 || item.operation !== "send" && item.operation !== "create_commitment") return refused();
22180
+ if (!current()) return cancelled;
22181
+ const check = (payment) => {
22182
+ if (!current()) return cancelled;
22183
+ if (payment === null || payment.id !== item.paymentId || payment.direction !== "out") return refused();
22184
+ try {
22185
+ const amount = toExactAssetAmount(payment.amount, CONFIGURED_MONEY_ASSETS);
22186
+ const asset = CONFIGURED_MONEY_ASSETS.find((row) => row.assetId === amount.asset);
22187
+ const instruction = payment.documents.find((document) => document.role === "instruction");
22188
+ const expected = command.instructionDocuments?.[0];
22189
+ if (asset?.tokenAddress.toLowerCase() !== item.tokenAddress.toLowerCase() || amount.minorUnits !== (item.operation === "send" ? item.rawAmount : item.totalAmount) || instruction?.documentHash !== item.documentHash || expected !== void 0 && (instruction.contentHash !== expected.contentHash || instruction.format !== expected.format) || payment.status === "settled" && payment.receipt?.chainId !== command.chainId) return refused();
22190
+ return {
22191
+ ok: true,
22192
+ value: normalizePaymentTiming(payment)
22193
+ };
22194
+ } catch (cause) {
22195
+ return {
22196
+ ok: false,
22197
+ error: Errors.unknown(cause)
22198
+ };
22199
+ }
22200
+ };
22201
+ const actor = calls.actor;
22202
+ const result = actor.kind === "account" ? await calls.bookChecked(records.get, { paymentId: item.paymentId }, controls, check) : await calls.bookChecked(records.getForOrganization, {
22203
+ orgId: actor.orgId,
22204
+ paymentId: item.paymentId
22205
+ }, controls, (response) => response.orgId === actor.orgId ? check(response.payment) : refused());
22206
+ return current() ? result : cancelled;
21691
22207
  }
21692
22208
  //#endregion
21693
22209
  //#region ../../packages/sdk/src/requests/inboxes.ts
21694
22210
  function makeInboxMethods(calls) {
21695
- const { actor, convexCall, deps, observeContactScope, book, bookChecked } = calls;
22211
+ const { actor, convexCall, deps, observeContactScope, book } = calls;
21696
22212
  return {
21697
22213
  paymentTerms: (requestId, options) => book(inboxes.paymentTerms, {
21698
22214
  actor,
21699
22215
  paymentRequestId: requestId
21700
22216
  }, options, (terms) => terms),
21701
22217
  list: (options) => book(inboxes.listCurrent, { actor }, options, (items) => mapPage(items, mapInboxItem)),
21702
- approve: (input, options) => bookChecked(inboxes.approve, {
21703
- actor,
21704
- paymentRequestId: input.requestId,
21705
- ...input.timing === void 0 ? {} : { timing: input.timing },
21706
- ...input.permissionId === void 0 ? {} : { permissionId: input.permissionId }
21707
- }, options, (prepared) => mapApprovedInboxPayment(prepared, input)),
22218
+ approve: async (providedInput, options) => {
22219
+ const input = structuredClone(providedInput);
22220
+ const identity = deps.identityActor;
22221
+ const lifetime = identity?.authLifetime();
22222
+ const current = () => identity === void 0 || lifetime !== void 0 && identity.matchesAuthLifetime(lifetime, lifetime.authUserId);
22223
+ const cancelled = {
22224
+ ok: false,
22225
+ error: Errors.cancelled({ operation: inboxes.approve.name })
22226
+ };
22227
+ const controls = deps.invocationControls?.(options) ?? options;
22228
+ const approve = async (requestKey) => {
22229
+ if (!current()) return cancelled;
22230
+ const prepared = await book(inboxes.approve, {
22231
+ actor,
22232
+ paymentRequestId: input.requestId,
22233
+ ...requestKey === void 0 ? {} : { requestKey },
22234
+ ...input.timing === void 0 ? {} : { timing: input.timing },
22235
+ ...input.permissionId === void 0 ? {} : { permissionId: input.permissionId }
22236
+ }, controls, (value) => value);
22237
+ if (!current()) return cancelled;
22238
+ if (!prepared.ok) return prepared;
22239
+ return readApprovedInboxPayment(calls, prepared.value, controls, current);
22240
+ };
22241
+ const terms = await book(inboxes.paymentTerms, {
22242
+ actor,
22243
+ paymentRequestId: input.requestId
22244
+ }, controls, (value) => value);
22245
+ if (!current()) return cancelled;
22246
+ if (!terms.ok) return terms;
22247
+ if (terms.value.instruction.kind !== "invoice") return approve(input.requestKey);
22248
+ return withInvoiceRequestKey(lifetime?.authUserId ?? "signed-out", {
22249
+ ...terms.value,
22250
+ payer: actor.kind === "account" ? { kind: "account" } : {
22251
+ kind: "organization",
22252
+ orgId: actor.orgId
22253
+ },
22254
+ permissionId: input.permissionId,
22255
+ release: input.timing ?? { kind: "instant" }
22256
+ }, input.requestKey, (key) => approve(key));
22257
+ },
21708
22258
  fulfill: (input, options) => {
21709
22259
  const onPrepared = options?.onPrepared;
21710
22260
  const decoded = Schema.decodeResult(RequestPaymentConfirmationSchema, { onExcessProperty: "error" })(input);
@@ -21727,20 +22277,26 @@ function makeInboxMethods(calls) {
21727
22277
  const controls = deps.invocationControls?.(options) ?? options;
21728
22278
  return runCapxulEffect(Effect.gen(function* () {
21729
22279
  const parent = yield* Effect.currentSpan.pipe(Effect.orDie);
21730
- return yield* awaitCapxulResult(() => executeRequestPayment({
22280
+ const run = (named, prepared) => executeRequestPayment({
21731
22281
  actor: identityActor,
21732
22282
  chainId,
21733
22283
  signer,
21734
22284
  convexCall,
21735
22285
  runPromise: deps.runPromise,
21736
22286
  ...deps.telemetry === void 0 ? {} : { telemetry: deps.telemetry }
21737
- }, confirmation, carryInvocationParentSpan(controls, parent), onPrepared === void 0 ? void 0 : async (paymentIds) => {
21738
- await onPrepared({ paymentIds });
22287
+ }, named, carryInvocationParentSpan(controls, parent), async (paymentIds) => {
22288
+ prepared();
22289
+ await onPrepared?.({ paymentIds });
21739
22290
  return {
21740
22291
  ok: true,
21741
22292
  value: void 0
21742
22293
  };
21743
- }));
22294
+ });
22295
+ const { requestKey, ...intent } = confirmation;
22296
+ return yield* awaitCapxulResult(() => confirmation.instruction.kind !== "invoice" ? run(confirmation, () => void 0) : withInvoiceRequestKey(identityActor.authSession()?.authUserId ?? "signed-out", intent, requestKey, (key, prepared) => run({
22297
+ ...confirmation,
22298
+ requestKey: key
22299
+ }, prepared)));
21744
22300
  }).pipe(Effect.tap(() => observeContactScope)), controls, CAPXUL_OPERATIONS.inbox.fulfill, deps.runPromise);
21745
22301
  },
21746
22302
  decline: (requestId, options) => book(inboxes.decline, {
@@ -22666,7 +23222,7 @@ function makePersonalPay(deps) {
22666
23222
  };
22667
23223
  }
22668
23224
  release(false);
22669
- await finishQuietly(requestKey, submitted.ok || flight.requestState.resolved);
23225
+ await finishQuietly(requestKey, submitted.ok || flight.requestState.resolved || isFinalPaymentRequestError(submitted.error));
22670
23226
  return mapOk(submitted, (value) => normalizePaymentTiming(value.payment));
22671
23227
  };
22672
23228
  }
@@ -22743,6 +23299,7 @@ function makePaymentsMethods(deps) {
22743
23299
  createCommitment: (input, options) => pay(input, options),
22744
23300
  claim: (paymentId, options) => runLifecycle({
22745
23301
  kind: "claim",
23302
+ requestKey: options?.requestKey ?? `pay_${crypto.randomUUID()}`,
22746
23303
  paymentId
22747
23304
  }, deps.invocationControls?.(options) ?? options, CAPXUL_OPERATIONS.payments.claim),
22748
23305
  list: (options) => {
@@ -22755,6 +23312,7 @@ function makePaymentsMethods(deps) {
22755
23312
  },
22756
23313
  cancel: (paymentId, options) => runLifecycle({
22757
23314
  kind: "cancel",
23315
+ requestKey: options?.requestKey ?? `pay_${crypto.randomUUID()}`,
22758
23316
  paymentId
22759
23317
  }, deps.invocationControls?.(options) ?? options, CAPXUL_OPERATIONS.payments.cancel),
22760
23318
  redirect: async (input, options) => {
@@ -22763,6 +23321,7 @@ function makePaymentsMethods(deps) {
22763
23321
  if (!recipient.ok) return runCapxulEffect(Effect.fail(recipient.error), observationOnlyControls(controls), CAPXUL_OPERATIONS.payments.redirect, deps.runPromise);
22764
23322
  return runLifecycle({
22765
23323
  kind: "redirect",
23324
+ requestKey: options?.requestKey ?? `pay_${crypto.randomUUID()}`,
22766
23325
  paymentId: input.paymentId,
22767
23326
  recipient: recipient.value
22768
23327
  }, controls, CAPXUL_OPERATIONS.payments.redirect);
@@ -23016,7 +23575,7 @@ async function executeOrganizationBatch(scope, input, signal, operation, control
23016
23575
  }
23017
23576
  release(false);
23018
23577
  try {
23019
- await requestKey.finish(result.ok || flight.requestState.resolved);
23578
+ await requestKey.finish(result.ok || flight.requestState.resolved || isFinalPaymentRequestError(result.error));
23020
23579
  } catch {}
23021
23580
  const normalized = mapOk(result, (value) => value.payments.map((payment) => normalizePaymentTiming(payment)));
23022
23581
  if (!normalized.ok) return normalized;
@@ -23117,7 +23676,8 @@ function makeOrganizationPaymentsMethods(deps, orgId) {
23117
23676
  },
23118
23677
  cancel: (paymentId, options) => ownerLifecycle({
23119
23678
  kind: "cancel",
23120
- paymentId
23679
+ paymentId,
23680
+ requestKey: options?.requestKey ?? `pay_${crypto.randomUUID()}`
23121
23681
  }, deps.invocationControls?.(options) ?? options, CAPXUL_OPERATIONS.organizationPayments.cancel),
23122
23682
  redirect: (input, options) => {
23123
23683
  const controls = deps.invocationControls?.(options) ?? options;
@@ -23125,7 +23685,8 @@ function makeOrganizationPaymentsMethods(deps, orgId) {
23125
23685
  return recipient.ok ? ownerLifecycle({
23126
23686
  kind: "redirect",
23127
23687
  paymentId: input.paymentId,
23128
- recipient: recipient.value
23688
+ recipient: recipient.value,
23689
+ requestKey: options?.requestKey ?? `pay_${crypto.randomUUID()}`
23129
23690
  }, controls, CAPXUL_OPERATIONS.organizationPayments.redirect) : runCapxulEffect(Effect.fail(recipient.error), observationOnlyControls(controls), CAPXUL_OPERATIONS.organizationPayments.redirect, deps.runPromise);
23130
23691
  },
23131
23692
  payBatch: (input, options) => {
@@ -23745,6 +24306,46 @@ function makeAccountMethods(deps) {
23745
24306
  };
23746
24307
  }
23747
24308
  //#endregion
24309
+ //#region ../../packages/sdk/src/accounts/approval-rules.ts
24310
+ const IN_FLIGHT = /* @__PURE__ */ new Set([
24311
+ "pending",
24312
+ "settling",
24313
+ "in_transit"
24314
+ ]);
24315
+ /** A Payment the chain has not decided yet. */
24316
+ function inFlight(payment) {
24317
+ return IN_FLIGHT.has(payment.status);
24318
+ }
24319
+ /**
24320
+ * The operation the approval describes is the one its digest signs: the
24321
+ * SafeOp digest of its UserOperation on this client's chain, and the
24322
+ * execution that digest names. Anything else is refused before the key signs.
24323
+ */
24324
+ function describedOperation(approval, chainId) {
24325
+ const { operation, summary } = approval;
24326
+ if (chainId !== void 0 && summary.network.chainId !== chainId) return Errors.invalidInput("approval", "the approval is for another chain");
24327
+ try {
24328
+ const digest = moneySafeOpDigest(operation.userOperation, summary.network.chainId);
24329
+ if (digest.toLowerCase() === operation.digest.toLowerCase() && matchesMoneyExecutionId(operation.executionId, digest, operation.commandId)) return void 0;
24330
+ } catch {}
24331
+ return Errors.invalidInput("approval", "the operation does not match the digest it asks to sign");
24332
+ }
24333
+ /** Wait, unless the caller gives up first. False when aborted. */
24334
+ function sleep(ms, signal) {
24335
+ if (signal?.aborted === true) return Promise.resolve(false);
24336
+ return new Promise((resolve) => {
24337
+ const timer = setTimeout(() => {
24338
+ signal?.removeEventListener("abort", onAbort);
24339
+ resolve(true);
24340
+ }, ms);
24341
+ const onAbort = () => {
24342
+ clearTimeout(timer);
24343
+ resolve(false);
24344
+ };
24345
+ signal?.addEventListener("abort", onAbort, { once: true });
24346
+ });
24347
+ }
24348
+ //#endregion
23748
24349
  //#region ../../packages/sdk/src/accounts/organization-approvals.ts
23749
24350
  /** The Organization Payment prepared for `signerAddress` and checked, before any approval. */
23750
24351
  async function prepareVerifiedOrganizationPayment(deps, input, signerAddress, signal) {
@@ -23837,58 +24438,6 @@ async function checkedBankApproval(deps, input, opened) {
23837
24438
  });
23838
24439
  }
23839
24440
  //#endregion
23840
- //#region ../../packages/sdk/src/accounts/approval-rules.ts
23841
- const IN_FLIGHT = /* @__PURE__ */ new Set([
23842
- "pending",
23843
- "settling",
23844
- "in_transit"
23845
- ]);
23846
- /** A Payment the chain has not decided yet. */
23847
- function inFlight(payment) {
23848
- return IN_FLIGHT.has(payment.status);
23849
- }
23850
- /**
23851
- * The approved operation is not sent yet: the approval is approved, or it was
23852
- * consumed but a Payment is still `pending` (a recorded send moves it to
23853
- * `settling`), so the send did not land.
23854
- */
23855
- function unsent(approval, payments) {
23856
- return approval.state === "approved" || approval.state === "consumed" && payments.some((payment) => payment.status === "pending");
23857
- }
23858
- /** The send was refused because another send of the same operation holds its claim. */
23859
- function anotherSendInFlight(error) {
23860
- return error.code === "SUPERSEDED" && error.details?.reason === "unobservable-claim";
23861
- }
23862
- /**
23863
- * The operation the approval describes is the one its digest signs: the
23864
- * SafeOp digest of its UserOperation on this client's chain, and the
23865
- * execution that digest names. Anything else is refused before the key signs.
23866
- */
23867
- function describedOperation(approval, chainId) {
23868
- const { operation, summary } = approval;
23869
- if (chainId !== void 0 && summary.network.chainId !== chainId) return Errors.invalidInput("approval", "the approval is for another chain");
23870
- try {
23871
- const digest = moneySafeOpDigest(operation.userOperation, summary.network.chainId);
23872
- if (digest.toLowerCase() === operation.digest.toLowerCase() && operation.executionId === `money_execution_${digest.slice(2).toLowerCase()}`) return void 0;
23873
- } catch {}
23874
- return Errors.invalidInput("approval", "the operation does not match the digest it asks to sign");
23875
- }
23876
- /** Wait, unless the caller gives up first. False when aborted. */
23877
- function sleep(ms, signal) {
23878
- if (signal?.aborted === true) return Promise.resolve(false);
23879
- return new Promise((resolve) => {
23880
- const timer = setTimeout(() => {
23881
- signal?.removeEventListener("abort", onAbort);
23882
- resolve(true);
23883
- }, ms);
23884
- const onAbort = () => {
23885
- clearTimeout(timer);
23886
- resolve(false);
23887
- };
23888
- signal?.addEventListener("abort", onAbort, { once: true });
23889
- });
23890
- }
23891
- //#endregion
23892
24441
  //#region ../../packages/protocol/src/payroll/model.ts
23893
24442
  function toPayrollRunId(raw) {
23894
24443
  return toNonEmptyStringBrand(raw, "payrollRunId", (value) => isNonEmptyString(value));
@@ -24350,7 +24899,8 @@ function lifecycleIntent(input) {
24350
24899
  ok: true,
24351
24900
  value: {
24352
24901
  kind: "cancel",
24353
- paymentId: input.cancel
24902
+ paymentId: input.cancel,
24903
+ requestKey: input.requestKey ?? `pay_${crypto.randomUUID()}`
24354
24904
  }
24355
24905
  };
24356
24906
  const recipient = normalizeTargetForBackend(input.to, "to");
@@ -24359,7 +24909,8 @@ function lifecycleIntent(input) {
24359
24909
  value: {
24360
24910
  kind: "redirect",
24361
24911
  paymentId: input.redirect,
24362
- recipient: recipient.value
24912
+ recipient: recipient.value,
24913
+ requestKey: input.requestKey ?? `pay_${crypto.randomUUID()}`
24363
24914
  }
24364
24915
  } : recipient;
24365
24916
  }
@@ -24391,10 +24942,19 @@ async function prepareVerifiedRequestPayment(deps, input, signerAddress, signal)
24391
24942
  error: Errors.invalidInput("confirmation", "invalid request confirmation")
24392
24943
  };
24393
24944
  const confirmation = decoded.success;
24394
- return checked(deps, signerAddress, await runIfActive(signal, commands$1.prepareRequest.name, () => callOperation(deps.convexCall, commands$1.prepareRequest, {
24395
- confirmation,
24396
- signerAddress
24397
- }).pipe(Effect.mapError((publicError) => ({ publicError }))), deps.runPromise), requestPaymentCheck(confirmation), false);
24945
+ const run = async (named, prepared) => {
24946
+ const result = await runIfActive(signal, commands$1.prepareRequest.name, () => callOperation(deps.convexCall, commands$1.prepareRequest, {
24947
+ confirmation: named,
24948
+ signerAddress
24949
+ }).pipe(Effect.mapError((publicError) => ({ publicError }))), deps.runPromise);
24950
+ if (result.ok) prepared();
24951
+ return checked(deps, signerAddress, result, requestPaymentCheck(named), false);
24952
+ };
24953
+ const { requestKey, ...intent } = confirmation;
24954
+ return confirmation.instruction.kind !== "invoice" ? run(confirmation, () => void 0) : withInvoiceRequestKey(deps.actor?.authSession()?.authUserId ?? "signed-out", intent, requestKey, (key, prepared) => run({
24955
+ ...confirmation,
24956
+ requestKey: key
24957
+ }, prepared));
24398
24958
  }
24399
24959
  /** One payroll run: the run the backend writes and the batch that pays it, checked together. */
24400
24960
  async function prepareVerifiedPayrollRun(deps, input, signerAddress, signal) {
@@ -24489,7 +25049,7 @@ function makeApprovalsMethods(deps) {
24489
25049
  const signal = options?.signal;
24490
25050
  if (isCommandApproval(input)) return openApproval(signal, (signerAddress) => prepareVerifiedCommand(deps, input, signerAddress, signal));
24491
25051
  if (isPermissionChange(input)) return openApproval(signal, async (signerAddress) => {
24492
- const { prepareVerifiedPermissionChange } = await import("./permission-approvals-DMdZgL2O.mjs");
25052
+ const { prepareVerifiedPermissionChange } = await import("./permission-approvals-5ayOO0fo.mjs");
24493
25053
  return prepareVerifiedPermissionChange(deps, input, signerAddress, signal);
24494
25054
  });
24495
25055
  if ("organizationId" in input) return checkedBankApproval(deps, input, await openApproval(signal, (signerAddress) => prepareVerifiedOrganizationPayment(deps, input, signerAddress, signal)));
@@ -24586,43 +25146,33 @@ function makeApprovalsMethods(deps) {
24586
25146
  };
24587
25147
  /**
24588
25148
  * One read of the approval: its outcome when it has ended, or null to read
24589
- * again. The Payments are read before anything is sent, so a send is never
24590
- * made for Payments this caller cannot follow.
25149
+ * again. This path only reads. The backend owns submission and recovery.
24591
25150
  */
24592
25151
  const step = async (approvalId, signal, organizationId) => {
24593
- const read = await call(approvals.get.name, approvals.get, { approvalId }, signal);
25152
+ const read = await call(approvals.observe.name, approvals.observe, { approvalId }, signal);
24594
25153
  if (!read.ok) return read;
24595
- const approval = read.value;
25154
+ const { approval, completed } = read.value;
24596
25155
  if (approval.state === "pending") return {
24597
25156
  ok: true,
24598
25157
  value: null
24599
25158
  };
24600
- if (endsOnceSent(approval)) {
24601
- if (approval.state !== "approved" && approval.state !== "consumed") return {
24602
- ok: true,
24603
- value: {
24604
- approval,
24605
- payments: []
24606
- }
24607
- };
24608
- const sent = await submit(approvalId);
24609
- return sent.ok || !anotherSendInFlight(sent.error) ? sent : {
24610
- ok: true,
24611
- value: null
24612
- };
24613
- }
25159
+ const closed = approval.state === "rejected" || approval.state === "expired";
25160
+ if (!closed && !completed) return {
25161
+ ok: true,
25162
+ value: null
25163
+ };
25164
+ if (!movesMoney(approval)) return {
25165
+ ok: true,
25166
+ value: {
25167
+ approval,
25168
+ payments: []
25169
+ }
25170
+ };
24614
25171
  const payments = await readApprovalPayments(deps, approval.operation.paymentIds, organizationId ?? (approval.actor.kind === "organization" ? approval.actor.orgId : void 0), signal);
24615
25172
  if (!payments.ok) return payments;
24616
- if (unsent(approval, payments.value)) {
24617
- const sent = await submit(approvalId);
24618
- return sent.ok || anotherSendInFlight(sent.error) ? {
24619
- ok: true,
24620
- value: null
24621
- } : sent;
24622
- }
24623
25173
  return {
24624
25174
  ok: true,
24625
- value: approval.state !== "consumed" || !payments.value.some(inFlight) ? {
25175
+ value: closed || endsOnceSent(approval) || !payments.value.some(inFlight) ? {
24626
25176
  approval,
24627
25177
  payments: payments.value
24628
25178
  } : null
@@ -25251,7 +25801,7 @@ function decodeStatus(body) {
25251
25801
  */
25252
25802
  const HEADS = {
25253
25803
  transfer: "select \"id\", \"chain_id\", \"tx_hash\", \"transaction_log_ordinal\", \"log_index\", \"block_number\", \"block_hash\", \"timestamp\", \"asset_id\", \"token\", \"from\", \"to\", \"amount\" from \"transfer\" where (\"transfer\".\"from\" = $1 or \"transfer\".\"to\" = $2) order by \"transfer\".\"block_number\" desc, \"transfer\".\"id\" desc",
25254
- payment: "select \"id\", \"chain_id\", \"tx_hash\", \"transaction_log_ordinal\", \"log_index\", \"block_number\", \"block_hash\", \"timestamp\", \"contract\", \"settlement_id\", \"sender\", \"recipient\", \"asset_id\", \"token\", \"amount\", \"kind\", \"document_hash\" from \"payment\" where (\"payment\".\"sender\" = $1 or \"payment\".\"recipient\" = $2) order by \"payment\".\"block_number\" desc, \"payment\".\"id\" desc",
25804
+ payment: "select \"id\", \"chain_id\", \"tx_hash\", \"transaction_log_ordinal\", \"log_index\", \"block_number\", \"block_hash\", \"timestamp\", \"contract\", \"settlement_id\", \"sender\", \"recipient\", \"asset_id\", \"token\", \"amount\", \"kind\", \"document_hash\", \"job_nonce\", \"executor\" from \"payment\" where (\"payment\".\"sender\" = $1 or \"payment\".\"recipient\" = $2) order by \"payment\".\"block_number\" desc, \"payment\".\"id\" desc",
25255
25805
  balance: "select \"chain_id\", \"asset_id\", \"to\", \"amount\" from \"balance\" where \"balance\".\"to\" = $1"
25256
25806
  };
25257
25807
  /** How many times the statement binds the Safe address. */
@@ -25294,7 +25844,7 @@ function ponderQuery(table, input) {
25294
25844
  input.limit
25295
25845
  ];
25296
25846
  return {
25297
- sql: `${HEADS.payment.slice(0, HEADS.payment.indexOf("where "))}where (("payment"."sender" = $1 or "payment"."recipient" = $2) and "payment"."settlement_id" in (${input.settlements.map((_, i) => `$${i + 3}`).join(", ")})) limit $${params.length}`,
25847
+ sql: `${HEADS.payment.slice(0, HEADS.payment.indexOf("where ")).replace(" from \"payment\"", ", \"contract\" as \"router\" from \"payment\"")}where (("payment"."sender" = $1 or "payment"."recipient" = $2) and "payment"."settlement_id" in (${input.settlements.map((_, i) => `$${i + 3}`).join(", ")})) limit $${params.length}`,
25298
25848
  params,
25299
25849
  typings: params.map(() => "none")
25300
25850
  };
@@ -38257,7 +38807,7 @@ function verifyPermissionExecution(raw, command, orgId, expectedSafe, signerAddr
38257
38807
  const callData = direct.length === 1 ? safe4337ExecuteUserOpCallData(direct[0]) : safe4337MultiSendUserOpCallData({ calls: direct });
38258
38808
  if (operation.callData.toLowerCase() !== callData.toLowerCase()) return mismatch("UserOperation call data mismatch");
38259
38809
  const digest = moneySafeOpDigest(operation, chainId);
38260
- if (evidence.digest.toLowerCase() !== digest.toLowerCase() || evidence.executionId !== `money_execution_${digest.slice(2).toLowerCase()}`) return mismatch("Prepared digest or execution identity mismatch");
38810
+ if (evidence.digest.toLowerCase() !== digest.toLowerCase() || !matchesMoneyExecutionId(evidence.executionId, digest, evidence.commandId)) return mismatch("Prepared digest or execution identity mismatch");
38261
38811
  return {
38262
38812
  ok: true,
38263
38813
  value: {
@@ -40114,4 +40664,4 @@ var ConvexOrganizationSetupAdapter = class {
40114
40664
  }
40115
40665
  };
40116
40666
  //#endregion
40117
- export { isSignerNotReadySignal as $, ChainIdSchema$1 as $t, bindProductTelemetryInvocation as A, detectAuthCacheAdapter as An, publicKeyToAddress as At, BASE_SEPOLIA_CHAIN_ID as B, redactUrlSecrets as Bn, toBytes$1 as Bt, PonderIndexerAdapter as C, copyInvocationObservation as Cn, toOrgId as Ct, TelemetryPortTag as D, toPublishableKey as Dn, isBytes32 as Dt, AccountReadPortTag as E, toAllowedOrigin as En, images as Et, makeCheckoutMethods as F, AuthCachePortTag as Fn, concatHex as Ft, failureEvidenceProps as G, CapxulError as Gn, hexToBigInt as Gt, asCapxulError as H, isRecord as Hn, numberToHex as Ht, makeTargetsMethods as I, deserializeCapxulError as In, isAddress$1 as It, withCapturedAttemptContext as J, isFailureMode as Jn, BaseError as Jt, observeFailedResult as K, isCapxulError as Kn, hexToNumber as Kt, makeVerificationMethods as L, serializeCapxulError as Ln, InvalidAddressError as Lt, makeAccountMethods as M, toEpochMs as Mn, createCursor as Mt, makePaymentsMethods as N, toAuthUserId as Nn, slice as Nt, ConvexCallPortTag as O, AuthClientError as On, hashTypedData as Ot, makeDestinationsMethods as P, toEmail as Pn, concat$1 as Pt, isEcdsaSignatureHex as Q, EpochMsSchema$1 as Qt, abandonPrepared as R, decodeChainCause as Rn, keccak256$1 as Rt, makeHoldingsMethods as S, attachInvocationObservation as Sn, ORGANIZATION_SETUP_STATUSES as St, ConvexAccountLayer as T, sanitizeObservationContext as Tn, AppIdSchema$1 as Tt, toPublicError$1 as U, readField as Un, stringToHex as Ut, callOperation as V, isCredentialField as Vn, bytesToHex as Vt, failureDetail as W, Errors as Wn, toHex as Wt, UNOBSERVABLE_SIGNER_STATUS as X, isHex$1 as Xt, version$1 as Y, size as Yt, causeChain as Z, DurationMsSchema$1 as Zt, makeActivityMethods as _, SystemClockLayer as _n, OPERATIONS as _t, prepareConfiguration as a, askIdentity as an, toCountryCode as at, ConvexSmartAccountLayer as b, BetterAuthBrowserLayer as bn, setups as bt, OrgPortTag as c, runPortEffect as cn, toHandle as ct, verifiedPreparation as d, toCapxulResult as dn, CLI_CAPABILITIES as dt, isEvmAddress as en, openfortSignerNotReadyCode as et, buildCommand as f, formatTraceparent as fn, CLI_COMMAND_NAMES as ft, makeMeMethods as g, oauthBearerAuthClient as gn, normalizeCapxulOperation as gt, bootIdentityFlow as h, carryInvocationParentSpan as hn, isCapxulOperation as ht, authorInvitation as i, makeAuthMethods as in, makeClientRequestMethods as it, makeApprovalsMethods as j, globalLocalStorage as jn, formatGwei as jt, convexCallErrorFromCapxul as k, AuthClientPortTag as kn, toRlp as kt, preparePermission as l, sessionFromActor as ln, validateHandle as lt, executeIdentityProductObservation as m, ActorFailure as mn, CAPXUL_OPERATIONS as mt, makeOrgMethods as n, absurd as nn, signerFailure as nt, verifiedConfiguration as o, publicIdentityFailure as on, toKycTier as ot, validateReplacementInput as p, CAPXUL_ERROR_CODES as pn, CLI_INVOCATION_KINDS as pt, observeSdkClient as q, FAILURE_MODES$1 as qn, trim as qt, makeBankingMethods as r, getFunctionName as rn, makeCurrentUserMethods as rt, ConvexOrganizationAdapter as s, runIdentityFacade as sn, toTesterKind as st, ConvexOrganizationSetupAdapter as t, toAddress as tn, recoverRawDigestSigner as tt, preparedIdentity as u, runCapxulEffect as un, redactTelemetryProps as ut, makePaymentDocumentsMethods as v, ClockPortTag as vn, details as vt, makeAccountsMethods as w, readInvocationObservation as wn, diagnostics as wt, SmartAccountPortTag as x, observationRequestHeaders as xn, ORGANIZATION_SETUP_REASONS as xt, makeSmartAccountMethods as y, BetterAuthNodeLayer as yn, onboardings as yt, normalizeSafeSaltEmail as z, redactSecrets as zn, hexToBytes as zt };
40667
+ export { isSignerNotReadySignal as $, ChainIdSchema$1 as $t, bindProductTelemetryInvocation as A, detectAuthCacheAdapter as An, toRlp as At, BASE_SEPOLIA_CHAIN_ID as B, redactUrlSecrets as Bn, hexToBytes as Bt, PonderIndexerAdapter as C, copyInvocationObservation as Cn, toOrgId as Ct, TelemetryPortTag as D, toPublishableKey as Dn, isBytes32 as Dt, AccountReadPortTag as E, toAllowedOrigin as En, images as Et, makeCheckoutMethods as F, AuthCachePortTag as Fn, concat$1 as Ft, failureEvidenceProps as G, CapxulError as Gn, hexToBigInt as Gt, asCapxulError as H, isRecord as Hn, numberToHex as Ht, makeTargetsMethods as I, deserializeCapxulError as In, concatHex as It, withCapturedAttemptContext as J, isFailureMode as Jn, BaseError as Jt, observeFailedResult as K, isCapxulError as Kn, hexToNumber as Kt, makeVerificationMethods as L, serializeCapxulError as Ln, isAddress$1 as Lt, makeAccountMethods as M, toEpochMs as Mn, formatGwei as Mt, makePaymentsMethods as N, toAuthUserId as Nn, createCursor as Nt, ConvexCallPortTag as O, AuthClientError as On, hashTypedData as Ot, makeDestinationsMethods as P, toEmail as Pn, slice as Pt, isEcdsaSignatureHex as Q, EpochMsSchema$1 as Qt, abandonPrepared as R, decodeChainCause as Rn, InvalidAddressError as Rt, makeHoldingsMethods as S, attachInvocationObservation as Sn, ORGANIZATION_SETUP_STATUSES as St, ConvexAccountLayer as T, sanitizeObservationContext as Tn, AppIdSchema$1 as Tt, toPublicError$1 as U, readField as Un, stringToHex as Ut, callOperation as V, isCredentialField as Vn, bytesToHex as Vt, failureDetail as W, Errors as Wn, toHex as Wt, UNOBSERVABLE_SIGNER_STATUS as X, isHex$1 as Xt, version$1 as Y, size as Yt, causeChain as Z, DurationMsSchema$1 as Zt, makeActivityMethods as _, SystemClockLayer as _n, OPERATIONS as _t, prepareConfiguration as a, askIdentity as an, toCountryCode as at, ConvexSmartAccountLayer as b, BetterAuthBrowserLayer as bn, setups as bt, OrgPortTag as c, runPortEffect as cn, toHandle as ct, verifiedPreparation as d, toCapxulResult as dn, CLI_CAPABILITIES as dt, isEvmAddress as en, openfortSignerNotReadyCode as et, buildCommand as f, formatTraceparent as fn, CLI_COMMAND_NAMES as ft, makeMeMethods as g, oauthBearerAuthClient as gn, normalizeCapxulOperation as gt, bootIdentityFlow as h, carryInvocationParentSpan as hn, isCapxulOperation as ht, authorInvitation as i, makeAuthMethods as in, makeClientRequestMethods as it, makeApprovalsMethods as j, globalLocalStorage as jn, publicKeyToAddress as jt, convexCallErrorFromCapxul as k, AuthClientPortTag as kn, sha256 as kt, preparePermission as l, sessionFromActor as ln, validateHandle as lt, executeIdentityProductObservation as m, ActorFailure as mn, CAPXUL_OPERATIONS as mt, makeOrgMethods as n, absurd as nn, signerFailure as nt, verifiedConfiguration as o, publicIdentityFailure as on, toKycTier as ot, validateReplacementInput as p, CAPXUL_ERROR_CODES as pn, CLI_INVOCATION_KINDS as pt, observeSdkClient as q, FAILURE_MODES$1 as qn, trim as qt, makeBankingMethods as r, getFunctionName as rn, makeCurrentUserMethods as rt, ConvexOrganizationAdapter as s, runIdentityFacade as sn, toTesterKind as st, ConvexOrganizationSetupAdapter as t, toAddress as tn, recoverRawDigestSigner as tt, preparedIdentity as u, runCapxulEffect as un, redactTelemetryProps as ut, makePaymentDocumentsMethods as v, ClockPortTag as vn, details as vt, makeAccountsMethods as w, readInvocationObservation as wn, diagnostics as wt, SmartAccountPortTag as x, observationRequestHeaders as xn, ORGANIZATION_SETUP_REASONS as xt, makeSmartAccountMethods as y, BetterAuthNodeLayer as yn, onboardings as yt, normalizeSafeSaltEmail as z, redactSecrets as zn, keccak256$1 as zt };