@invisi-labs/sdk 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -21,32 +21,89 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
23
  AddressRegistry: () => AddressRegistry,
24
- Detector: () => import_core15.Detector,
25
- Disclosure: () => import_core15.Disclosure,
24
+ Detector: () => import_core20.Detector,
25
+ Disclosure: () => import_core20.Disclosure,
26
26
  DisclosureVerifier: () => DisclosureVerifier,
27
27
  EncryptedWalletCodec: () => EncryptedWalletCodec,
28
28
  Invisi: () => Invisi,
29
- MAX_MEMO_BYTES: () => import_core15.MAX_MEMO_BYTES,
30
- MissingCapabilityError: () => import_core15.MissingCapabilityError,
31
- NullifierCapability: () => import_core15.NullifierCapability,
29
+ InvisiError: () => InvisiError,
30
+ MAX_MEMO_BYTES: () => import_core20.MAX_MEMO_BYTES,
31
+ MissingCapabilityError: () => import_core20.MissingCapabilityError,
32
+ NullifierCapability: () => import_core20.NullifierCapability,
32
33
  Operation: () => Operation,
33
34
  PreparedTransaction: () => PreparedTransaction,
34
- Protocol: () => import_protocol10.Protocol,
35
+ Protocol: () => import_protocol11.Protocol,
35
36
  ProtocolRpcClient: () => ProtocolRpcClient2,
36
37
  ProtocolRpcError: () => import_rpc3.ProtocolRpcError,
37
- RegistrationOperation: () => import_protocol10.RegistrationOperation,
38
- ViewingCapability: () => import_core15.ViewingCapability,
39
- Wallet: () => import_core15.Wallet,
40
- WalletAuthorization: () => import_core15.WalletAuthorization,
38
+ PublicWallet: () => import_core20.PublicWallet,
39
+ RegistrationOperation: () => import_protocol11.RegistrationOperation,
40
+ ViewingCapability: () => import_core20.ViewingCapability,
41
+ Wallet: () => import_core20.Wallet,
42
+ WalletAuthorization: () => import_core20.WalletAuthorization,
41
43
  WalletSession: () => WalletSession,
42
- decodeMemoText: () => import_core15.decodeMemoText,
44
+ computeCreditNullifier: () => import_core20.computeCreditNullifier,
45
+ creditPeriods: () => import_core20.creditPeriods,
46
+ creditV1: () => import_core20.creditV1,
47
+ decodeDeliveryHeader: () => import_core20.decodeDeliveryHeader,
48
+ decodeMemoText: () => import_core20.decodeMemoText,
49
+ decryptCandidates: () => decryptCandidates,
43
50
  defineGasBenchmarks: () => defineGasBenchmarks,
44
- encodeMemo: () => import_core15.encodeMemo,
51
+ encodeMemo: () => import_core20.encodeMemo,
52
+ fundsV1: () => import_core20.fundsV1,
53
+ readProtocolLogs: () => readProtocolLogs,
45
54
  walletBalance: () => walletBalance
46
55
  });
47
56
  module.exports = __toCommonJS(src_exports);
48
57
 
58
+ // src/errors.ts
59
+ var import_core = require("@invisi-labs/core");
60
+ var InvisiError = class extends Error {
61
+ code;
62
+ operation;
63
+ address;
64
+ outputIndex;
65
+ field;
66
+ capability;
67
+ constructor(code, message, details = {}) {
68
+ super(message, { cause: details.cause });
69
+ this.name = "InvisiError";
70
+ this.code = code;
71
+ this.operation = details.operation;
72
+ this.address = details.address;
73
+ this.outputIndex = details.outputIndex;
74
+ this.field = details.field;
75
+ this.capability = details.capability;
76
+ }
77
+ };
78
+ async function prepareWithErrors(operation, prepare) {
79
+ try {
80
+ return await prepare();
81
+ } catch (cause) {
82
+ if (cause instanceof InvisiError) {
83
+ if (cause.operation) throw cause;
84
+ throw new InvisiError(cause.code, cause.message, {
85
+ operation,
86
+ ...cause.address === void 0 ? {} : { address: cause.address },
87
+ ...cause.outputIndex === void 0 ? {} : { outputIndex: cause.outputIndex },
88
+ ...cause.field === void 0 ? {} : { field: cause.field },
89
+ ...cause.capability === void 0 ? {} : { capability: cause.capability },
90
+ cause: cause.cause
91
+ });
92
+ }
93
+ throw new InvisiError(
94
+ cause instanceof import_core.MissingCapabilityError ? "MISSING_CAPABILITY" : "PREPARATION_FAILED",
95
+ cause instanceof Error ? cause.message : "Transaction preparation failed",
96
+ {
97
+ operation,
98
+ cause,
99
+ ...cause instanceof import_core.MissingCapabilityError ? { capability: cause.capability } : {}
100
+ }
101
+ );
102
+ }
103
+ }
104
+
49
105
  // src/session/operation-protocol.ts
106
+ var import_core2 = require("@invisi-labs/core");
50
107
  var import_protocol = require("@invisi-labs/protocol");
51
108
 
52
109
  // src/session/state.ts
@@ -105,11 +162,8 @@ function walletBalances(state) {
105
162
 
106
163
  // src/session/operation-protocol.ts
107
164
  function requiresAuthorization(plan) {
108
- if (plan.kind === "sweep") {
109
- if (plan.credit || !plan.inputs.length || plan.outputs.length || !plan.params || plan.params.outputCommitments.length || (plan.funding.amount ?? 0n) !== 0n || BigInt(plan.params.withdrawalAddress) !== BigInt(plan.scope.walletIdentity) || plan.params.withdrawalAmount !== plan.inputs.reduce((sum, input) => sum + input.note.amount, 0n) || plan.inputs.some((input) => input.note.walletIdentity !== plan.scope.walletIdentity))
110
- throw new Error("invalid owner-only sweep plan");
111
- return false;
112
- }
165
+ const ownerOnlyFullWithdrawal = !plan.credit && plan.inputs.length > 0 && plan.outputs.length === 0 && plan.params !== void 0 && plan.params.outputCommitments.length === 0 && (plan.funding.amount ?? 0n) === 0n && plan.fundingMode === "none" && BigInt(plan.params.withdrawalAddress) === BigInt(plan.scope.walletIdentity) && plan.params.withdrawalAmount === plan.inputs.reduce((sum, input) => sum + input.note.amount, 0n) && plan.inputs.every((input) => input.note.walletIdentity === plan.scope.walletIdentity);
166
+ if (ownerOnlyFullWithdrawal) return false;
113
167
  return !!plan.credit || plan.inputs.length > 0;
114
168
  }
115
169
  function inputFacts(plan) {
@@ -240,6 +294,7 @@ async function witnessFor(protocol, plan, authorization) {
240
294
  }
241
295
  if (credit.draw) {
242
296
  return builder.drawCredit({
297
+ timestamp: plan.preparedAt.timestamp,
243
298
  params: credit.draw,
244
299
  deliveries: credit.deliveries,
245
300
  inputs: credit.inputs,
@@ -370,7 +425,12 @@ function operationExpired(plan, now) {
370
425
  const credit = plan.credit;
371
426
  if (credit?.topUp && now >= credit.topUp.previousExpiry) return true;
372
427
  if (credit?.creation && now >= credit.creation.expiry) return true;
373
- if (credit?.draw && credit.draw.expiries.some((expiry) => now >= expiry)) return true;
428
+ if (credit?.draw) {
429
+ if (credit.draw.expiries.some((expiry) => now >= expiry)) return true;
430
+ const prepared = (0, import_core2.creditPeriods)(plan.preparedAt.timestamp), current2 = (0, import_core2.creditPeriods)(now);
431
+ if (prepared.currentDay !== current2.currentDay || prepared.currentMonth !== current2.currentMonth)
432
+ return true;
433
+ }
374
434
  return false;
375
435
  }
376
436
 
@@ -378,352 +438,987 @@ function operationExpired(plan, now) {
378
438
  var gas_benchmarks_default = [
379
439
  {
380
440
  formatVersion: 1,
381
- id: "protocol-92ef274-osaka-real",
441
+ id: "protocol-42f2546-621cbef5f84a-prague-credit-real",
382
442
  deployment: {
383
443
  chainId: "31337",
384
- protocolAddress: "0x8870C63A18a9480C7de9B860b849fD293832856D",
385
- runtimeCodeHash: "0x604572c0da90ea139b774cd0d2962a2972fac46e0556c7cec6f6f9aac5deef14",
386
- tokenAddress: "0x4826533B4897376654Bb4d4AD88B7faFD0C98528"
444
+ protocolAddress: "0xEeD9be753bccbCB21463C49f0c56cC0E48bEcf3c",
445
+ runtimeCodeHash: "0x80228a2080d224b4481fc5df24fe8ce080d4536c663b13ec7829ecf0ef46abbd",
446
+ tokenAddress: "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf"
387
447
  },
388
448
  source: {
389
- protocolCommit: "92ef274c6b36d783507699a33ee20e52192c83c7",
390
- measuredAt: "2026-10-27T08:42:15.991Z",
449
+ protocolCommit: "42f2546b62312e4c11e21b8e6b2ff6f72187d6a6",
450
+ measuredAt: "2026-10-29T10:56:24.758Z",
391
451
  chain: "Anvil 31337",
392
- hardfork: "osaka",
452
+ hardfork: "prague",
393
453
  token: "MockERC20",
394
454
  verifier: "real",
455
+ fingerprints: {
456
+ protocolSourceSha256: "621cbef5f84a133ca96674a2dba39b21b5f9fbc022977d4d2ab296d9d6e685e0",
457
+ dirtyDiffSha256: "eb2c41cca3802a47196181648397ec6f47fb2ba0efa8aa3800508d8d255fae3f",
458
+ compiledArtifactsSha256: "c0e658d74fe49caeebf5ef9deadc1751d9e48add690f7e9ab478de7a00dab7e4",
459
+ creditManifestSha256: "da819378af60471905cc902a43e464b58159e0c75bd46fb804ea9d34d8aa7ef6",
460
+ userManifestSha256: "067b6c50e4bc4d9c19dd29f25352db88d189a5f49aed0ed603daa70760e699df",
461
+ sdkSourceSha256: "37e1f82a447db741f46e1490b866ddf85718eab42c33d369cf5f5d2ec3a25c78"
462
+ },
463
+ toolchain: {
464
+ solidity: "0.8.38",
465
+ barretenberg: "6.0.0",
466
+ noir: "1.0.0-rc.6",
467
+ evmVersion: "prague",
468
+ optimizerRuns: 200,
469
+ anvil: "anvil Version: 1.8.6"
470
+ },
471
+ blockGasLimit: "500000000",
472
+ runtimeContracts: {
473
+ transact_user_slots14_direct_Verifier: {
474
+ address: "0x5FbDB2315678afecb367f032d93F642f64180aa3",
475
+ runtimeCodeHash: "0xedab185b2b9fc7d98660db2cdc99fe30b9d1341dfe568172a1626e322d208f7e"
476
+ },
477
+ "transact_user_slots14-adapter": {
478
+ address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
479
+ runtimeCodeHash: "0xe222cd9c142bc2b13e083e6fe66ea76c0e1e9a194715bfa57082b625c55d867f"
480
+ },
481
+ transact_user_slots56_direct_Verifier: {
482
+ address: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
483
+ runtimeCodeHash: "0x8913eb7060f38234aca199c4a1007892f68e703de48b588c436b24faaeb23a53"
484
+ },
485
+ "transact_user_slots56-adapter": {
486
+ address: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
487
+ runtimeCodeHash: "0x97c416d190da0b9b8111a5ee17367e8a702ba7884019bf724155ae629a783477"
488
+ },
489
+ transact_user_slots112_direct_Verifier: {
490
+ address: "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9",
491
+ runtimeCodeHash: "0x501a4791ff0c0a96465ab5e0d42d0ce763bbbb7fd8aebe21929de4d460e1b42c"
492
+ },
493
+ "transact_user_slots112-adapter": {
494
+ address: "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
495
+ runtimeCodeHash: "0xf22ed8ea34a4011650a41c1b9f664b5259ea5a8d66a82d706dab9611a38c109f"
496
+ },
497
+ transact_user_slots168_direct_Verifier: {
498
+ address: "0x0165878A594ca255338adfa4d48449f69242Eb8F",
499
+ runtimeCodeHash: "0xc22acdfa6f3e278ae46d194a1c50b905e4815fd7b61e39edb52334570670fdce"
500
+ },
501
+ "transact_user_slots168-adapter": {
502
+ address: "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
503
+ runtimeCodeHash: "0x05a318f54d93440a501b6fc6be88e4e76e89d72f1be8333553cb4a61f4f9a0d7"
504
+ },
505
+ transact_aggregate_14_4_Verifier: {
506
+ address: "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6",
507
+ runtimeCodeHash: "0x7a6f2bafe4c61a72a99a195e188f2f4a32900c0cc63cc132e33881d8199fd446"
508
+ },
509
+ "transact_aggregate_14_4-adapter": {
510
+ address: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318",
511
+ runtimeCodeHash: "0x15877da9940d5b8dd4868ffa92ded3b93d6092c3963ba9e18b50f1ea15d89898"
512
+ },
513
+ transact_aggregate_14_8_Verifier: {
514
+ address: "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
515
+ runtimeCodeHash: "0x5667d16b39973813a499375f6885a3082d7bfcd6e3c0f3548d7de3131cd285f3"
516
+ },
517
+ "transact_aggregate_14_8-adapter": {
518
+ address: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
519
+ runtimeCodeHash: "0x9d1a93c78edf7e81b4b6da10ab209b3fb009ed8355594f670559a67842d88cfc"
520
+ },
521
+ transact_aggregate_14_12_Verifier: {
522
+ address: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
523
+ runtimeCodeHash: "0xa4e67840a47182d4011d577981c2477bb4ab2bc36845bb136375f19f12c0800b"
524
+ },
525
+ "transact_aggregate_14_12-adapter": {
526
+ address: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
527
+ runtimeCodeHash: "0x96a6e170aafc0af9d46232ba00206d950bba85e65962d43501bafb6d7f9fe61d"
528
+ },
529
+ create_credit_direct_Verifier: {
530
+ address: "0x9A676e781A523b5d0C0e43731313A708CB607508",
531
+ runtimeCodeHash: "0xbdc6450bf9ba01001082f345b8bd21006a4f75274f32d026cf6e14270e6d56e6"
532
+ },
533
+ "create_credit-adapter": {
534
+ address: "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
535
+ runtimeCodeHash: "0x3a95a22b32aef18ce053a7110056bbfbf13bb0b07932a49765ebb136528a4707"
536
+ },
537
+ credit_draw_slots1_direct_Verifier: {
538
+ address: "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
539
+ runtimeCodeHash: "0x47be80e72c3a22ea044638f6004de8c3a0264d5a0d17189c01153cdabfd7bab6"
540
+ },
541
+ "credit_draw_slots1-adapter": {
542
+ address: "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
543
+ runtimeCodeHash: "0x28f25aeb97659fb9253ae67f2ff284789710bc59e1ed077ffc7a07b800cbfcc1"
544
+ },
545
+ credit_draw_slots12_direct_Verifier: {
546
+ address: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
547
+ runtimeCodeHash: "0x244d9ba22f5c736c2a5c42c466701e2a8ba7ae8108665133541026ea45d56e04"
548
+ },
549
+ "credit_draw_slots12-adapter": {
550
+ address: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
551
+ runtimeCodeHash: "0x60d48a35279d318a0621e5f59b293f44074463b8002ce180b7e6a31b995ac195"
552
+ },
553
+ credit_draw_slots50_direct_Verifier: {
554
+ address: "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d",
555
+ runtimeCodeHash: "0x2ad5eb64bcfae34ef04111dd8f9c1ffc5fc8aa6c1ad3a65d8da78233f3390660"
556
+ },
557
+ "credit_draw_slots50-adapter": {
558
+ address: "0x59b670e9fA9D0A427751Af201D676719a970857b",
559
+ runtimeCodeHash: "0x468966de20e5c71cf7b6f3cda7fa7a76b5d80dc5ddf82119f441ea6a7c6c1e70"
560
+ },
561
+ credit_draw_slots120_direct_Verifier: {
562
+ address: "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1",
563
+ runtimeCodeHash: "0x523b6d211618bbd33d708f8198b9f3daafc10e2fa7a6a857db5795ed748a24e4"
564
+ },
565
+ "credit_draw_slots120-adapter": {
566
+ address: "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
567
+ runtimeCodeHash: "0xa91d585ce6037e703efb914205bf193881fde4f470d2fc63b615699b56175239"
568
+ },
569
+ credit_cancel_direct_Verifier: {
570
+ address: "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
571
+ runtimeCodeHash: "0x182e86861a73f712071e40a6b8497b80c58c383eaa799182e7a50e39196399fd"
572
+ },
573
+ "credit_cancel-adapter": {
574
+ address: "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
575
+ runtimeCodeHash: "0xea1f0f22445eed5a92c8d6990219059b7e241ad66c55a6d9ddef22a94a0f015f"
576
+ },
577
+ credit_top_up_direct_Verifier: {
578
+ address: "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
579
+ runtimeCodeHash: "0xeeb42a2b6377ab305b713d1caf4ca96edb302c6d1e1007239e5c70091819c266"
580
+ },
581
+ "credit_top_up-adapter": {
582
+ address: "0x09635F643e140090A9A8Dcd712eD6285858ceBef",
583
+ runtimeCodeHash: "0xbcf35a1d0e6c16dd01b09f944889aa5917d358d986fe399a0343d06bbdedaa61"
584
+ },
585
+ PrivateTransferVerifierRegistry: {
586
+ address: "0xc5a5C42992dECbae36851359345FE25997F5C42d",
587
+ runtimeCodeHash: "0x678684af147cb42c872184b6e22c8439748139ae0c5885032941ab8832fcb142"
588
+ },
589
+ CrossTreeVerifierRegistry: {
590
+ address: "0x67d269191c92Caf3cD7723F116c85e6E9bf55933",
591
+ runtimeCodeHash: "0xa5ee16fc7ed9f982450e42a48365a93bfca784fa884adcb8695b557e921cb93b"
592
+ },
593
+ DualVerifierRouter: {
594
+ address: "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E",
595
+ runtimeCodeHash: "0xcc094ed6f1bcc9270c597f62b817e4fc0a54770f373320133c2836e5b07ef2cc"
596
+ },
597
+ AtomicBatchOutputLib: {
598
+ address: "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690",
599
+ runtimeCodeHash: "0x7c138c13e40b3ad0fee3b319d6c1580a21855cb5ecdda92571d530509d9b7316"
600
+ },
601
+ FundingLib: {
602
+ address: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
603
+ runtimeCodeHash: "0x898d13d6ec4123df85f21ee0f98678dcd9f9b9a60134f88e35c1ef1aaa0a45f9"
604
+ },
605
+ PrivateTransferLib: {
606
+ address: "0x9E545E3C0baAB3E08CdfD552C960A1050f373042",
607
+ runtimeCodeHash: "0xfb18f2dd0a39af1b99ae35c25e2746cb5bc85c205e041db5f440671d84c82e5e"
608
+ },
609
+ CrossTreeTransferLib: {
610
+ address: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
611
+ runtimeCodeHash: "0x7b33a08f2feb9da462b951c95482cb2909796a85c0fde7cc9a6b65ff8b7ff253"
612
+ },
613
+ AggregateTransferLib: {
614
+ address: "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8",
615
+ runtimeCodeHash: "0xb3b4bd3a428f5c35712a57180f07b2249774d399ca87d4494929148ea26c5b99"
616
+ },
617
+ CreateCreditLib: {
618
+ address: "0x851356ae760d987E095750cCeb3bC6014560891C",
619
+ runtimeCodeHash: "0xe37a4b7c129c4fba5615d25ed8b7e898e64a306c68f7e599ade911db98fe881c"
620
+ },
621
+ CreditLifecycleLib: {
622
+ address: "0xf5059a5D33d5853360D16C683c16e67980206f36",
623
+ runtimeCodeHash: "0xf87a2227680efa7070071516587793e2e847c172b83261b8983c826f8a8c79bb"
624
+ },
625
+ ShieldLib: {
626
+ address: "0x95401dc811bb5740090279Ba06cfA8fcF6113778",
627
+ runtimeCodeHash: "0x371e57d8d324e44445a4ec30303b89a8bc98bbdbd03aeaa80faf0f821a65451d"
628
+ },
629
+ InvisiFactory: {
630
+ address: "0x998abeb3E57409262aE5b751f60747921B33613E",
631
+ runtimeCodeHash: "0xc56e5a0b71f4a1f63576a6663efb62b17c0d7520b6885a8d3483a356e12edf9b"
632
+ },
633
+ InvisiAddressRegistry: {
634
+ address: "0x70e0bA845a1A0F2DA3359C97E0285013525FFC49",
635
+ runtimeCodeHash: "0x007da3f4e888366ba0eed52cd511c4a369359291387ad19ca37e89eb395fce30"
636
+ },
637
+ InvisiProtocol: {
638
+ address: "0xEeD9be753bccbCB21463C49f0c56cC0E48bEcf3c",
639
+ runtimeCodeHash: "0x80228a2080d224b4481fc5df24fe8ce080d4536c663b13ec7829ecf0ef46abbd"
640
+ },
641
+ MockERC20: {
642
+ address: "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf",
643
+ runtimeCodeHash: "0xf7f676b5c54f6e94f82f0de65a0117468a0d915e8a79d150e74f76bd6d7f708b"
644
+ }
645
+ },
395
646
  assumptions: [
396
- "normal CREATE/Factory deployment; no code or storage injection",
397
- "Solidity 0.8.27 optimizer 200; real BB 5.2.1 verifiers",
398
- "one source tree; two existing leaves; no rollover or screener",
399
- "funding/approval setup excluded; complete transaction receipt gas included",
400
- "exact allowance for caller funding; configured benchmark payout balances",
401
- "observed local samples, not a confidence interval or gas limit"
647
+ "normal CREATE/Factory deployment and fresh registry; EIP170/EIP3860 unchanged; no code/storage injection",
648
+ "Solidity0.8.38 optimizer200 Prague; pinned BB6.0.0 real verifiers; every native proof independently verified",
649
+ "one physical source tree and 123 existing leaves shared by every sample; top-up has two authenticated source groups; no rollover or screener",
650
+ "funding/approvals/121 genuine Credit seeds/usage-seed draw/payout reset excluded from business gas",
651
+ "each round restores identical token balances, exact caller allowance100, note cursor, nullifiers and baseline; spender payout starts zero",
652
+ "complete receipt.gasUsed is measured, including verifier/calldata/logging/output insertion; memo0",
653
+ "Prague local block gas limit500000000; measured transactions may be unmineable under lower network transaction/block limits",
654
+ "observed three-sample ranges are neither a confidence interval nor a recommended transaction gas limit"
402
655
  ]
403
656
  },
404
657
  measurements: [
405
658
  {
406
- id: "shield-1",
659
+ id: "create-credit-caller-0x0",
407
660
  shape: {
408
- kind: "shield",
661
+ kind: "create-credit",
409
662
  target: "evm",
410
- capacity: 0,
663
+ capacity: 10,
411
664
  noteInputs: 0,
412
- noteOutputs: 1,
665
+ noteOutputs: 0,
413
666
  sourceTrees: 0,
414
667
  creditInputs: 0,
415
- creditOutputs: 0,
668
+ creditOutputs: 1,
416
669
  creditRemainders: 0,
417
670
  funding: "caller",
418
671
  permit: false,
419
- deliveryBytes: 226
672
+ deliveryBytes: 1132
673
+ },
674
+ circuit: {
675
+ circuitName: "create_credit",
676
+ target: "evm",
677
+ artifactSha256: "3ed6cfdee4f5fd840f023580f76c208768777fea79737f2511377e5c55be0230",
678
+ vkSha256: "56f663c6053be0d158a271022d200c732597efd3a2e0be48fe94549d0b1795e0"
420
679
  },
421
- circuit: null,
422
680
  samples: [
423
681
  {
424
- gasUsed: "649286",
425
- transactionHash: "0xcc299d1780ada9a69b1d9f0f3d06a165db15fccbd2b7ff407834f02f5d563a18",
426
- blockNumber: "50",
427
- blockHash: "0xbcb868e781a20588d2fa099a4d7f87c1600044a2e5ec1e369e384d7a5f22f00a",
428
- calldataBytes: 1156
682
+ gasUsed: "1574696",
683
+ transactionHash: "0x76112c532a1b5f24ad84fb83f91789ba4acd15ed9473ec9a0267cd5fe605448d",
684
+ blockNumber: "172",
685
+ blockHash: "0x0d91421e94947132a19f38ffdd76932c2d85add201de3d9189325ed3568125a7",
686
+ calldataBytes: 11780
429
687
  },
430
688
  {
431
- gasUsed: "649322",
432
- transactionHash: "0x95139dff109725989f0769e3e6fb9bd3e7e1bf581fd475f14e822875eb90fda4",
433
- blockNumber: "50",
434
- blockHash: "0x7ace353fea4fc8c856c0fd45521d200b02619921977709ff4f910e0ff41c06fe",
435
- calldataBytes: 1156
689
+ gasUsed: "1574576",
690
+ transactionHash: "0x545f72d9d207329bfc69ef0d1e96470c614924d5e463d974cc001712bf619fd8",
691
+ blockNumber: "172",
692
+ blockHash: "0x2053f97a2b2f3cf66e14da0ab9c1d7bd462d2d4f3ef2b13021aefcddedb71cf8",
693
+ calldataBytes: 11780
436
694
  },
437
695
  {
438
- gasUsed: "649322",
439
- transactionHash: "0xef578bb38dc8ff8bfd47d2e76e3ab4273019ea9a385f5d2fd99add32ceaecb58",
440
- blockNumber: "50",
441
- blockHash: "0xded817f8ef89637e2443e3b626c0837f184ca134fe753be913d5570554c649a6",
442
- calldataBytes: 1156
696
+ gasUsed: "1574612",
697
+ transactionHash: "0x880ec0c666068d0756fba39947dc5b211aeebb31f41bd1e1e54856b090f65d34",
698
+ blockNumber: "172",
699
+ blockHash: "0xbb86ed21379a917e9688a3c90364ae8fbe1ba633ac068360e0a82bf4d3113b6d",
700
+ calldataBytes: 11780
443
701
  }
444
702
  ]
445
703
  },
446
704
  {
447
- id: "shield-2",
705
+ id: "create-credit-1x1",
448
706
  shape: {
449
- kind: "shield",
707
+ kind: "create-credit",
450
708
  target: "evm",
451
- capacity: 0,
452
- noteInputs: 0,
453
- noteOutputs: 2,
454
- sourceTrees: 0,
709
+ capacity: 10,
710
+ noteInputs: 1,
711
+ noteOutputs: 1,
712
+ sourceTrees: 1,
455
713
  creditInputs: 0,
456
- creditOutputs: 0,
714
+ creditOutputs: 1,
457
715
  creditRemainders: 0,
458
- funding: "caller",
716
+ funding: "none",
459
717
  permit: false,
460
- deliveryBytes: 452
718
+ deliveryBytes: 1360
719
+ },
720
+ circuit: {
721
+ circuitName: "create_credit",
722
+ target: "evm",
723
+ artifactSha256: "3ed6cfdee4f5fd840f023580f76c208768777fea79737f2511377e5c55be0230",
724
+ vkSha256: "56f663c6053be0d158a271022d200c732597efd3a2e0be48fe94549d0b1795e0"
461
725
  },
462
- circuit: null,
463
726
  samples: [
464
727
  {
465
- gasUsed: "757063",
466
- transactionHash: "0x024e2dfbd6f50c368e2a4aa347e3029de668f4ebd36b80227aa003bb7ac21c74",
467
- blockNumber: "50",
468
- blockHash: "0x8ed63973c158d706ac54bb646626e4f0db5777b4bd56d179b94503af6c417c50",
469
- calldataBytes: 1668
728
+ gasUsed: "1671641",
729
+ transactionHash: "0x24ca3f03681aeb188b48989d5eaf7dd264a8c32e828acd34ff1b44be74f17ea6",
730
+ blockNumber: "172",
731
+ blockHash: "0xcdac07aa5d3ec187874dc1fc9be65503235289c7036ebe455feaf5161db42bb5",
732
+ calldataBytes: 12132
470
733
  },
471
734
  {
472
- gasUsed: "757063",
473
- transactionHash: "0x898d852ab28f68adac4d30b160a3dbfee33fa7ca875f70df9eb7763b6b1cd1f0",
474
- blockNumber: "50",
475
- blockHash: "0x9bb6810de38193933a9f26fa03d3d9bad1ca0151ff5e04544c56520e09da3043",
476
- calldataBytes: 1668
735
+ gasUsed: "1671509",
736
+ transactionHash: "0x31a7f69ab02effa5fdd2e02bd02fb7e715a54786813261113fd7c07a0d3ef549",
737
+ blockNumber: "172",
738
+ blockHash: "0xc78ca874aa22cc6b8ea19e12a2806ba448a0f844345450d3fedc9841ea71c3a8",
739
+ calldataBytes: 12132
477
740
  },
478
741
  {
479
- gasUsed: "757039",
480
- transactionHash: "0x8ff9720e3197aab2d741fbd8d0fa2969203ea8cd051d9649d1e5eb890bcc2be3",
481
- blockNumber: "50",
482
- blockHash: "0x8604c75eb6363aaae774276e638f5b749aae1f8f815eb99ab1183137eef5730e",
483
- calldataBytes: 1668
742
+ gasUsed: "1671485",
743
+ transactionHash: "0xc5a30116885dcac8b3631c15847544cfeb91c46bde44c3765ac0ce42e3259157",
744
+ blockNumber: "172",
745
+ blockHash: "0x4a2c90ff972da4d37408567062779762efbb5790d4784d03842ee2c926c8c894",
746
+ calldataBytes: 12132
484
747
  }
485
748
  ]
486
749
  },
487
750
  {
488
- id: "shield-10",
751
+ id: "draw-credit-1-partial",
489
752
  shape: {
490
- kind: "shield",
753
+ kind: "draw-credit",
491
754
  target: "evm",
492
- capacity: 0,
755
+ capacity: 1,
493
756
  noteInputs: 0,
494
- noteOutputs: 10,
495
- sourceTrees: 0,
496
- creditInputs: 0,
497
- creditOutputs: 0,
498
- creditRemainders: 0,
499
- funding: "caller",
757
+ noteOutputs: 0,
758
+ sourceTrees: 1,
759
+ creditInputs: 1,
760
+ creditOutputs: 1,
761
+ creditRemainders: 1,
762
+ funding: "none",
500
763
  permit: false,
501
- deliveryBytes: 2260
764
+ deliveryBytes: 1132
765
+ },
766
+ circuit: {
767
+ circuitName: "credit_draw_slots1",
768
+ target: "evm",
769
+ artifactSha256: "4542b227e0552b45c302f1dace21cadeba4962c96244e021472f1f7531cff8d1",
770
+ vkSha256: "43c051a2bedf9454c12e70b10156361e414944823ba23e80662c16c7ced0a2ce"
502
771
  },
503
- circuit: null,
504
772
  samples: [
505
773
  {
506
- gasUsed: "1692143",
507
- transactionHash: "0x6c13db8bd8a8599daf5034e56712abefbf406982fafe7647b6d22291ba4199ed",
508
- blockNumber: "50",
509
- blockHash: "0x1ab2ae514f408a79e0c40ca10cee74b2e23d7c8a5f24641b8eea3e1cf58ce700",
510
- calldataBytes: 5764
774
+ gasUsed: "1588303",
775
+ transactionHash: "0x85c5180692470aa952aa13eb29ca0404d4f5b5192cb31475f90d03d78864895e",
776
+ blockNumber: "172",
777
+ blockHash: "0xfe4876c0a2ebf05385a46562bca693b6df80da731fd9651117593916015dc38c",
778
+ calldataBytes: 11588
511
779
  },
512
780
  {
513
- gasUsed: "1692083",
514
- transactionHash: "0x5e476c9d3838b782a51332af9bf5c372d29fc411c2168a7af619c52bd5309c7b",
515
- blockNumber: "50",
516
- blockHash: "0x9c62bc72fc90f990c6711b48865ff922a1856ae05c4fef61dad5f4da7d948401",
517
- calldataBytes: 5764
781
+ gasUsed: "1588303",
782
+ transactionHash: "0x61684313840623187ca1205b4b07b43a08038448524ee1a028c7e14050032682",
783
+ blockNumber: "172",
784
+ blockHash: "0x9726d31c10e6516e38e3f63c84fc4b9a8a161486d35e0d8d07e6829261a88fe7",
785
+ calldataBytes: 11588
518
786
  },
519
787
  {
520
- gasUsed: "1692203",
521
- transactionHash: "0x0092e2d9160fad95279cde586fc6c79c713244f55db8a2060a5abab9d98c176a",
522
- blockNumber: "50",
523
- blockHash: "0xac1bf780b4cc05b4dcc7ee5d741c049ba99ab4af9bdcd25104add730c2a14152",
524
- calldataBytes: 5764
788
+ gasUsed: "1588255",
789
+ transactionHash: "0x0aa052fb8e356cc81dd73bcdae72f760937cd2e56bd4a3e8eb5878208b4f7596",
790
+ blockNumber: "172",
791
+ blockHash: "0x2c958cfba0627e18cd5cb47001b278628c305071929596e3335d770b92c1dc16",
792
+ calldataBytes: 11588
525
793
  }
526
794
  ]
527
795
  },
528
796
  {
529
- id: "transfer-1x2",
797
+ id: "draw-credit-1-full",
530
798
  shape: {
531
- kind: "transfer",
799
+ kind: "draw-credit",
532
800
  target: "evm",
533
- capacity: 14,
534
- noteInputs: 1,
535
- noteOutputs: 2,
801
+ capacity: 1,
802
+ noteInputs: 0,
803
+ noteOutputs: 0,
536
804
  sourceTrees: 1,
537
- creditInputs: 0,
805
+ creditInputs: 1,
538
806
  creditOutputs: 0,
539
807
  creditRemainders: 0,
540
808
  funding: "none",
541
809
  permit: false,
542
- deliveryBytes: 452
810
+ deliveryBytes: 0
543
811
  },
544
812
  circuit: {
545
- circuitName: "transact_user_slots14",
813
+ circuitName: "credit_draw_slots1",
546
814
  target: "evm",
547
- artifactSha256: "2a6a20839e90b88b1ecd629f59a01821bad3ee11dbe04db1fd9cdce7a3de0e84",
548
- vkSha256: "ffe0e1a4e690792ecb4eb1fc1acc9ff60f13d3b5af03cfc6ae6d6bf26e99bdea"
815
+ artifactSha256: "4542b227e0552b45c302f1dace21cadeba4962c96244e021472f1f7531cff8d1",
816
+ vkSha256: "43c051a2bedf9454c12e70b10156361e414944823ba23e80662c16c7ced0a2ce"
549
817
  },
550
818
  samples: [
551
819
  {
552
- gasUsed: "1617516",
553
- transactionHash: "0xf49ea3d31cc1346472172e2dee84f9360f60a3fe948a3ef6e87f727af6d42f0d",
554
- blockNumber: "49",
555
- blockHash: "0xf59c57e63ec2f03abc36d28f273b0af5290184dc97197df740b23d79a851a887",
556
- calldataBytes: 11012
820
+ gasUsed: "1042812",
821
+ transactionHash: "0xb5d55729d975abdc92ca44c0b72e44a0d5841da8b23dc11b5bd31f46d88a341a",
822
+ blockNumber: "172",
823
+ blockHash: "0x8a6ddbe2f1630e1956485cac7984fb9cdc4fbb26b10522e158b38e2970ee4f3b",
824
+ calldataBytes: 10372
557
825
  },
558
826
  {
559
- gasUsed: "1617516",
560
- transactionHash: "0xf8d11286f1f2a4db006ff6b06900c47d0fbf685984499e1e5d4aea49478ba8e5",
561
- blockNumber: "49",
562
- blockHash: "0xeb5a800190be3534c9e2675c97ac56d0e0be8adef55f60bd32d375776a7d150c",
563
- calldataBytes: 11012
827
+ gasUsed: "1042824",
828
+ transactionHash: "0xf64f3186fbf94fcbd9fb12426c714b4a8425599e1a7e5677866fae3d6873b7ae",
829
+ blockNumber: "172",
830
+ blockHash: "0xd630c44d8ce96234ec836dd2178caac2a6d0bc2df5cf37df1534eb8896be48d3",
831
+ calldataBytes: 10372
564
832
  },
565
833
  {
566
- gasUsed: "1617504",
567
- transactionHash: "0x8939fcea97079a3c5118b9e94325455e2ad1cdb47310ae499a277272654b3eb6",
568
- blockNumber: "49",
569
- blockHash: "0xecffefb593e2fec5d5827cfd39d0cc4d0efb67dbff6f8dbbd0d2db2439a80cf9",
570
- calldataBytes: 11012
834
+ gasUsed: "1042884",
835
+ transactionHash: "0xdf634e809b87603a62292ef046fa5e84715561fa76ef121c768303dd779568f1",
836
+ blockNumber: "172",
837
+ blockHash: "0x09cad4a799360bdf825c3ad70fe374b7fe2df802f8ee37ccb7f26ffc49aa2a3a",
838
+ calldataBytes: 10372
571
839
  }
572
840
  ]
573
841
  },
574
842
  {
575
- id: "transfer-1x14",
843
+ id: "draw-credit-12-partial",
576
844
  shape: {
577
- kind: "transfer",
845
+ kind: "draw-credit",
578
846
  target: "evm",
579
- capacity: 56,
580
- noteInputs: 1,
581
- noteOutputs: 14,
847
+ capacity: 12,
848
+ noteInputs: 0,
849
+ noteOutputs: 0,
582
850
  sourceTrees: 1,
583
- creditInputs: 0,
584
- creditOutputs: 0,
585
- creditRemainders: 0,
851
+ creditInputs: 12,
852
+ creditOutputs: 12,
853
+ creditRemainders: 12,
586
854
  funding: "none",
587
855
  permit: false,
588
- deliveryBytes: 3164
856
+ deliveryBytes: 13584
589
857
  },
590
858
  circuit: {
591
- circuitName: "transact_user_slots56",
859
+ circuitName: "credit_draw_slots12",
592
860
  target: "evm",
593
- artifactSha256: "ba83ec2f177d16fa88ea04bc54f2e99920f1ac195cdb05b88b9b3bbc245fd953",
594
- vkSha256: "6ad5d3aff0c72a632fb19895658af093a6a92478a9994985e838a71e61237720"
861
+ artifactSha256: "dd72b0867fc3be7cd90de263bd2d0892075cb18eb4f6dd671b13111710f10369",
862
+ vkSha256: "5e31d771e6294993736078596d9c69f21fe7595eda50e3cce6d7406b65cf1443"
595
863
  },
596
864
  samples: [
597
865
  {
598
- gasUsed: "2489010",
599
- transactionHash: "0x053557acea930a869d6469c91e9bc015d0893607a6ab18d2af684986f7074676",
600
- blockNumber: "49",
601
- blockHash: "0x734873097eb5e4cb66bfc2cdb61fac6753b53a4b9450fb22895281100af3aaf3",
602
- calldataBytes: 17156
866
+ gasUsed: "3102895",
867
+ transactionHash: "0x699ba81f296f4af397a8dfaf96adf14d00d0f7dd69c0b09608641fc9b99fc28f",
868
+ blockNumber: "172",
869
+ blockHash: "0x8d318f563f5563fa5c213617481089f75aab3a6e9d14818db107ac20a8c20ffb",
870
+ calldataBytes: 30276
603
871
  },
604
872
  {
605
- gasUsed: "2489106",
606
- transactionHash: "0xb3990edb994011775e275bc1eb38c527b7206a2bfadf510e8aa53e260f3594b8",
607
- blockNumber: "49",
608
- blockHash: "0xf8cb019ebb0ecd0ec5d6634198292883c63fe93a7c65c34f9f3120c6cc54f1cf",
609
- calldataBytes: 17156
873
+ gasUsed: "3102871",
874
+ transactionHash: "0xddfc1c6c505f6c54f4d9aabc96a02eb6b606182e8ad708a578eacd274d885dee",
875
+ blockNumber: "172",
876
+ blockHash: "0xcc7738fe329a608241615dc43b7d16e075eb62be202ea8aaf4ae27a5278bf438",
877
+ calldataBytes: 30276
610
878
  },
611
879
  {
612
- gasUsed: "2489094",
613
- transactionHash: "0xc97079019567ff8a79d285421351ee4bc48d14092a0e12ff634151719e991088",
614
- blockNumber: "49",
615
- blockHash: "0x5a6947839165c8961eeeb9190331415c40366a78b4a6a5771e7b8954dbb8b3c7",
616
- calldataBytes: 17156
880
+ gasUsed: "3103171",
881
+ transactionHash: "0x6efab6408d927e1877f1f6c33ecd285a128382f7d1dfe6e123927b035781c8aa",
882
+ blockNumber: "172",
883
+ blockHash: "0xcb4588df9ecdca0d353ccbd226e1d5d07f21e6dc93875e41cdd5f64568859f4d",
884
+ calldataBytes: 30276
617
885
  }
618
886
  ]
619
887
  },
620
888
  {
621
- id: "transfer-1x56",
889
+ id: "draw-credit-12-full",
622
890
  shape: {
623
- kind: "transfer",
891
+ kind: "draw-credit",
624
892
  target: "evm",
625
- capacity: 112,
626
- noteInputs: 1,
627
- noteOutputs: 56,
893
+ capacity: 12,
894
+ noteInputs: 0,
895
+ noteOutputs: 0,
628
896
  sourceTrees: 1,
629
- creditInputs: 0,
897
+ creditInputs: 12,
630
898
  creditOutputs: 0,
631
899
  creditRemainders: 0,
632
900
  funding: "none",
633
901
  permit: false,
634
- deliveryBytes: 12656
902
+ deliveryBytes: 0
635
903
  },
636
904
  circuit: {
637
- circuitName: "transact_user_slots112",
905
+ circuitName: "credit_draw_slots12",
638
906
  target: "evm",
639
- artifactSha256: "713b78469b6e97711122210f8497942120c1c9d66d3604bc184566c4eba59cc3",
640
- vkSha256: "d6a46e297949c28b9a62fd9aef1f202870fdca97b8bfb15beefd27b9e9f3d86e"
907
+ artifactSha256: "dd72b0867fc3be7cd90de263bd2d0892075cb18eb4f6dd671b13111710f10369",
908
+ vkSha256: "5e31d771e6294993736078596d9c69f21fe7595eda50e3cce6d7406b65cf1443"
641
909
  },
642
910
  samples: [
643
911
  {
644
- gasUsed: "5389227",
645
- transactionHash: "0xb820d3c358724c1d64422017f232d074e4ff1ffaf1b1ce5ee719409427cf2208",
646
- blockNumber: "49",
647
- blockHash: "0x474bd1e52457801d1a596a9f23aeb6d365a17be028ee0c8cf8fd4758eaa1106b",
648
- calldataBytes: 36356
912
+ gasUsed: "1536675",
913
+ transactionHash: "0xc0d3eef8e6b0e90984d776a5e41bcdce1e0ca0bc6dc3a71616e4768e80c01546",
914
+ blockNumber: "172",
915
+ blockHash: "0x22dfac3d8e9913a6a1f2ff84faaece4ed59bfe1cb74e06a60131ff28cc6c2f9d",
916
+ calldataBytes: 15684
649
917
  },
650
918
  {
651
- gasUsed: "5389095",
652
- transactionHash: "0x16514d8cf1136d7a7f40591859e2ea2d256af66520498e1fc81eb28837db600d",
653
- blockNumber: "49",
654
- blockHash: "0x42314a0d6eb9e765869e1b66b279444c78f919d2c28aed544d9fa7ac3bd2acb4",
655
- calldataBytes: 36356
919
+ gasUsed: "1536675",
920
+ transactionHash: "0x9879d86a1eaa550a6a6afaeeb0f5f07745d5dcd9caa07b660d7fb512911dc67e",
921
+ blockNumber: "172",
922
+ blockHash: "0xf88ba9f1b7a0c627338a61bbabe1c650bdfcd7fa1c56433d6853f492135b753d",
923
+ calldataBytes: 15684
656
924
  },
657
925
  {
658
- gasUsed: "5389203",
659
- transactionHash: "0xee69d565a7eafb60ad7a47afe80a49d4fa40b50660669d9141e7dc6f4c3dbe0d",
660
- blockNumber: "49",
661
- blockHash: "0x0dcdada663ee04dd63e06fcdb79dacc5623201d29b687f63deede2b4762a994e",
662
- calldataBytes: 36356
926
+ gasUsed: "1536711",
927
+ transactionHash: "0xbd8f75a021a8ce8dc1900bd2d84d723acc6a64018844050a5aa2f8712cf7fd6b",
928
+ blockNumber: "172",
929
+ blockHash: "0xa55b539c2ea4e10ce9a9ee8e6de9cf1daa97263b51f32cfef8342c100b663b0f",
930
+ calldataBytes: 15684
663
931
  }
664
932
  ]
665
933
  },
666
934
  {
667
- id: "transfer-1x112",
935
+ id: "draw-credit-50-partial",
668
936
  shape: {
669
- kind: "transfer",
937
+ kind: "draw-credit",
670
938
  target: "evm",
671
- capacity: 168,
939
+ capacity: 50,
940
+ noteInputs: 0,
941
+ noteOutputs: 0,
942
+ sourceTrees: 1,
943
+ creditInputs: 50,
944
+ creditOutputs: 50,
945
+ creditRemainders: 50,
946
+ funding: "none",
947
+ permit: false,
948
+ deliveryBytes: 56600
949
+ },
950
+ circuit: {
951
+ circuitName: "credit_draw_slots50",
952
+ target: "evm",
953
+ artifactSha256: "09c7469866748b4c0c4bbf2b040844771948a170999f6dc7a38fe5c0ecda4054",
954
+ vkSha256: "7b613225b6f32a077011d4196c356e836d22dcd116efe687fde53144fbd8db9f"
955
+ },
956
+ samples: [
957
+ {
958
+ gasUsed: "8015473",
959
+ transactionHash: "0x5dcc0fa08abaf5212424ac6f3e2f3bb8a0bd333f90ef6e421f8d3fe370ca1acf",
960
+ blockNumber: "172",
961
+ blockHash: "0x3197c523dece3492226c5021f974e7c02db2e686265943d03a5550c6cb96a12e",
962
+ calldataBytes: 94276
963
+ },
964
+ {
965
+ gasUsed: "8015449",
966
+ transactionHash: "0x6a55f88551a45b3e118cde0607cfff1ef0b6ab15ad9472e838412d9ce714b42a",
967
+ blockNumber: "172",
968
+ blockHash: "0xea82c8962d45db8361bd67ed326806f21c511bd51550adc453d0c3e5cab3a7ae",
969
+ calldataBytes: 94276
970
+ },
971
+ {
972
+ gasUsed: "8015149",
973
+ transactionHash: "0x2cc8d474a92abe91f8025109a70cf1f9f081dbec43aa4a475ab9f33222cfc76b",
974
+ blockNumber: "172",
975
+ blockHash: "0x4398f419da699ccca33867852d4975b5c461a40bb01cd5241a0e6dcacaeb78b3",
976
+ calldataBytes: 94276
977
+ }
978
+ ]
979
+ },
980
+ {
981
+ id: "draw-credit-50-full",
982
+ shape: {
983
+ kind: "draw-credit",
984
+ target: "evm",
985
+ capacity: 50,
986
+ noteInputs: 0,
987
+ noteOutputs: 0,
988
+ sourceTrees: 1,
989
+ creditInputs: 50,
990
+ creditOutputs: 0,
991
+ creditRemainders: 0,
992
+ funding: "none",
993
+ permit: false,
994
+ deliveryBytes: 0
995
+ },
996
+ circuit: {
997
+ circuitName: "credit_draw_slots50",
998
+ target: "evm",
999
+ artifactSha256: "09c7469866748b4c0c4bbf2b040844771948a170999f6dc7a38fe5c0ecda4054",
1000
+ vkSha256: "7b613225b6f32a077011d4196c356e836d22dcd116efe687fde53144fbd8db9f"
1001
+ },
1002
+ samples: [
1003
+ {
1004
+ gasUsed: "3216708",
1005
+ transactionHash: "0x16933368d26ea1d7fbe69027c700671df832ad308944eeff42e7c2da40297b06",
1006
+ blockNumber: "172",
1007
+ blockHash: "0x0739a6f4188b8bdeae7bd5460960086d04adfea993d07d65b2b3630ad01b8cab",
1008
+ calldataBytes: 33476
1009
+ },
1010
+ {
1011
+ gasUsed: "3216840",
1012
+ transactionHash: "0x45dc15a62b1661f54e167cf13b9693770370c926a8a7af959da7354e9bb4aa6e",
1013
+ blockNumber: "172",
1014
+ blockHash: "0xf2e294db9af3b11814fed1dec358b8370ea28a99189211f883c9b0012349d677",
1015
+ calldataBytes: 33476
1016
+ },
1017
+ {
1018
+ gasUsed: "3216744",
1019
+ transactionHash: "0x2c827753026ea421497534a01bcc2adaca866a7612f570dad3fcf18c660f8590",
1020
+ blockNumber: "172",
1021
+ blockHash: "0x3ccd465528ff22e6d1955670220df3565899a16dd683f71c83c9810f2df420b4",
1022
+ calldataBytes: 33476
1023
+ }
1024
+ ]
1025
+ },
1026
+ {
1027
+ id: "draw-credit-120-partial",
1028
+ shape: {
1029
+ kind: "draw-credit",
1030
+ target: "evm",
1031
+ capacity: 120,
1032
+ noteInputs: 0,
1033
+ noteOutputs: 0,
1034
+ sourceTrees: 1,
1035
+ creditInputs: 120,
1036
+ creditOutputs: 120,
1037
+ creditRemainders: 120,
1038
+ funding: "none",
1039
+ permit: false,
1040
+ deliveryBytes: 135840
1041
+ },
1042
+ circuit: {
1043
+ circuitName: "credit_draw_slots120",
1044
+ target: "evm",
1045
+ artifactSha256: "6ccd0366a669c50fd5da875c3eae194fe8aa4c36d35a5f9ebfd64636ea599b48",
1046
+ vkSha256: "d715848afc5c1ecdfcef5ed5026865abef5040a3bc232fd65330a5ffee8475fb"
1047
+ },
1048
+ samples: [
1049
+ {
1050
+ gasUsed: "17458512",
1051
+ transactionHash: "0x84dd6bda5f3172a53e899051fd226dc5869edb796bd513a33e7f224bed13f4ae",
1052
+ blockNumber: "172",
1053
+ blockHash: "0xfca82de1e112b92319185d8c3f0115e0aa339d0247ea65970eb0d37ba958b08e",
1054
+ calldataBytes: 211140
1055
+ },
1056
+ {
1057
+ gasUsed: "17458224",
1058
+ transactionHash: "0xae26838942cf8b5499d43cb5e74681ae87aec77890a8eabddd692ff83830e013",
1059
+ blockNumber: "172",
1060
+ blockHash: "0x3e513447e0cfdbb682a95b7a719b0d300ec46b0ee22b518eaae7fb082f6436e7",
1061
+ calldataBytes: 211140
1062
+ },
1063
+ {
1064
+ gasUsed: "17458524",
1065
+ transactionHash: "0xeaa07e77fe958f4317e71b07ddb876482ae9c5172fd6d6cefaacc551dbbda7d5",
1066
+ blockNumber: "172",
1067
+ blockHash: "0x12b34c1fd2e15480276052842157c2a6355acdd43d7bd01ae7511c3f39e0ecfc",
1068
+ calldataBytes: 211140
1069
+ }
1070
+ ]
1071
+ },
1072
+ {
1073
+ id: "draw-credit-120-full",
1074
+ shape: {
1075
+ kind: "draw-credit",
1076
+ target: "evm",
1077
+ capacity: 120,
1078
+ noteInputs: 0,
1079
+ noteOutputs: 0,
1080
+ sourceTrees: 1,
1081
+ creditInputs: 120,
1082
+ creditOutputs: 0,
1083
+ creditRemainders: 0,
1084
+ funding: "none",
1085
+ permit: false,
1086
+ deliveryBytes: 0
1087
+ },
1088
+ circuit: {
1089
+ circuitName: "credit_draw_slots120",
1090
+ target: "evm",
1091
+ artifactSha256: "6ccd0366a669c50fd5da875c3eae194fe8aa4c36d35a5f9ebfd64636ea599b48",
1092
+ vkSha256: "d715848afc5c1ecdfcef5ed5026865abef5040a3bc232fd65330a5ffee8475fb"
1093
+ },
1094
+ samples: [
1095
+ {
1096
+ gasUsed: "6289576",
1097
+ transactionHash: "0xbf11743f7edc5ed5ff334efc5e35634f45e48e4940d33ddd9c87d8fe444dafc5",
1098
+ blockNumber: "172",
1099
+ blockHash: "0x774de17971107b73cab2cd20f26b60665f55a37b0cc1147166babf16743e34d5",
1100
+ calldataBytes: 65220
1101
+ },
1102
+ {
1103
+ gasUsed: "6289768",
1104
+ transactionHash: "0x651bb13e0645ee8a08657db627f1072f5e964ddaff44f70f829440ed68488dea",
1105
+ blockNumber: "172",
1106
+ blockHash: "0xa9795828565fb0ce65bda295073106b8bbdc110bb8317d269839d3db3e312d5b",
1107
+ calldataBytes: 65220
1108
+ },
1109
+ {
1110
+ gasUsed: "6289720",
1111
+ transactionHash: "0x2a859d381cb4b50830971b1ffc9789b11569fc96147e130dae6fecd141f5ceb0",
1112
+ blockNumber: "172",
1113
+ blockHash: "0x7d990830157bfeff8e5cbe580e9effe97faa7676c9957ce32891b76c83961430",
1114
+ calldataBytes: 65220
1115
+ }
1116
+ ]
1117
+ },
1118
+ {
1119
+ id: "top-up-credit-1x1-unchanged-limits",
1120
+ shape: {
1121
+ kind: "top-up-credit",
1122
+ target: "evm",
1123
+ capacity: 10,
672
1124
  noteInputs: 1,
673
- noteOutputs: 112,
1125
+ noteOutputs: 1,
1126
+ sourceTrees: 2,
1127
+ creditInputs: 1,
1128
+ creditOutputs: 1,
1129
+ creditRemainders: 0,
1130
+ funding: "none",
1131
+ permit: false,
1132
+ deliveryBytes: 1360
1133
+ },
1134
+ circuit: {
1135
+ circuitName: "credit_top_up",
1136
+ target: "evm",
1137
+ artifactSha256: "2ffebd5753ec1b0c050204d4f97498765fe61ea01a793a9b2466c2f97536345c",
1138
+ vkSha256: "40b02a9d2e7eb7b49daaac4b7760328537b7982fd5a225cc065bb74cd5ef44b3"
1139
+ },
1140
+ samples: [
1141
+ {
1142
+ gasUsed: "1711282",
1143
+ transactionHash: "0x74d45084bb07bacabbced09ee6ef69d8632a22a4493be783c326c47e929ba0ed",
1144
+ blockNumber: "172",
1145
+ blockHash: "0x3503643f7081b52ae20d4754a0e9b11f52034ae48059f5b5298546c2570fa091",
1146
+ calldataBytes: 12292
1147
+ },
1148
+ {
1149
+ gasUsed: "1711282",
1150
+ transactionHash: "0x4b5e2432d5571f6b56507b3ab995a8120560ba608959ff100f03b87873e72be6",
1151
+ blockNumber: "172",
1152
+ blockHash: "0xca15dc309371a5aa9c7bc5bf1d65c5b325c71528ce7856ba68a118114124fccc",
1153
+ calldataBytes: 12292
1154
+ },
1155
+ {
1156
+ gasUsed: "1711390",
1157
+ transactionHash: "0x304f3740b64c80dcc5c894fb30af59080d96a11e08371096ae695cbc46ef2c8b",
1158
+ blockNumber: "172",
1159
+ blockHash: "0x9671ed76d6b8e49a36ba229d3609289fcf70756f31277ac5fc0e3f08cd52304f",
1160
+ calldataBytes: 12292
1161
+ }
1162
+ ]
1163
+ },
1164
+ {
1165
+ id: "top-up-credit-1x1-changed-limits",
1166
+ shape: {
1167
+ kind: "top-up-credit",
1168
+ target: "evm",
1169
+ capacity: 10,
1170
+ noteInputs: 1,
1171
+ noteOutputs: 1,
1172
+ sourceTrees: 2,
1173
+ creditInputs: 1,
1174
+ creditOutputs: 1,
1175
+ creditRemainders: 0,
1176
+ funding: "none",
1177
+ permit: false,
1178
+ deliveryBytes: 1360
1179
+ },
1180
+ circuit: {
1181
+ circuitName: "credit_top_up",
1182
+ target: "evm",
1183
+ artifactSha256: "2ffebd5753ec1b0c050204d4f97498765fe61ea01a793a9b2466c2f97536345c",
1184
+ vkSha256: "40b02a9d2e7eb7b49daaac4b7760328537b7982fd5a225cc065bb74cd5ef44b3"
1185
+ },
1186
+ samples: [
1187
+ {
1188
+ gasUsed: "1711318",
1189
+ transactionHash: "0x65284df534b42631f8a592fb2a6efc16361a4cc122f1a8dd41418e7b950f48f1",
1190
+ blockNumber: "172",
1191
+ blockHash: "0xf198242a1edf5b133961568c9165648c829729e7bfbbf57a1e148551c971b87c",
1192
+ calldataBytes: 12292
1193
+ },
1194
+ {
1195
+ gasUsed: "1711438",
1196
+ transactionHash: "0xcee89a81e598974798365c4ebada806fb51196ee602334b0fffdbb25da0afe25",
1197
+ blockNumber: "172",
1198
+ blockHash: "0xb506a6fb54cc2f91b803211ed955aac0203fba93e2428f8f52ec0d413c90af09",
1199
+ calldataBytes: 12292
1200
+ },
1201
+ {
1202
+ gasUsed: "1711342",
1203
+ transactionHash: "0x957de5c79f365c9b0510b9e125a662317494aad50cb446edceef6f678d561cc7",
1204
+ blockNumber: "172",
1205
+ blockHash: "0xb1d5cffd6d6db58ade9d5e16d48b060b9ab2152415966dc809e7e70785472ab8",
1206
+ calldataBytes: 12292
1207
+ }
1208
+ ]
1209
+ },
1210
+ {
1211
+ id: "cancel-credit-1",
1212
+ shape: {
1213
+ kind: "cancel-credit",
1214
+ target: "evm",
1215
+ capacity: 1,
1216
+ noteInputs: 0,
1217
+ noteOutputs: 0,
674
1218
  sourceTrees: 1,
675
- creditInputs: 0,
1219
+ creditInputs: 1,
676
1220
  creditOutputs: 0,
677
1221
  creditRemainders: 0,
678
1222
  funding: "none",
679
1223
  permit: false,
680
- deliveryBytes: 25312
1224
+ deliveryBytes: 0
681
1225
  },
682
1226
  circuit: {
683
- circuitName: "transact_user_slots168",
1227
+ circuitName: "credit_cancel",
684
1228
  target: "evm",
685
- artifactSha256: "f7b3b1384e961367702f544299ca3521d8205fac31b7691c45ff84325d5a31c3",
686
- vkSha256: "e00181533d7e35d2307570528f9e7f8f88e2909b6ae338d93373b608dea96881"
1229
+ artifactSha256: "b4459c2cf756d096e37291cf4d7cd129866b6d420b6d03c928f383b057112ccb",
1230
+ vkSha256: "fc8ad196ef15f3328afcc8f01d867a3ebefd15451c2813948442fab1923b73b2"
687
1231
  },
688
1232
  samples: [
689
1233
  {
690
- gasUsed: "9139842",
691
- transactionHash: "0x09951c4e00b868b6660429d187a482004646e4c84ef341d3b98352c249db6a06",
692
- blockNumber: "49",
693
- blockHash: "0xba9da3c08189335acff1eb33554f5f12475e4a6510324cf6ec9eadf340ce15d2",
694
- calldataBytes: 61444
1234
+ gasUsed: "985543",
1235
+ transactionHash: "0x29ca63fbefcc5e92dbc86f67d6280993e567a5dd02ff3defd7f3251ce711865e",
1236
+ blockNumber: "172",
1237
+ blockHash: "0xecd7808fe9f7467af917069bd7a82ab0324e3cbab8dcad622b089d6e3eee9a58",
1238
+ calldataBytes: 9540
695
1239
  },
696
1240
  {
697
- gasUsed: "9139650",
698
- transactionHash: "0xb06f69d1c6e5406758918d5d296ab889bab4c3814f616cc581ad312cc7ebb2f3",
699
- blockNumber: "49",
700
- blockHash: "0x5516a76b4b366f2e539a67bb848b7d232c3e6f328d34ca5bd3dba43a14c316bf",
701
- calldataBytes: 61444
1241
+ gasUsed: "985795",
1242
+ transactionHash: "0xaf8bca0769330f89b647363f99b752dbbe6fdbb8b1aae912224f6a3a59f40faa",
1243
+ blockNumber: "172",
1244
+ blockHash: "0x58e1358e02f189d57628fa7c504b87fb000fe60eb9f0a0c3c0e58dae876e64da",
1245
+ calldataBytes: 9540
702
1246
  },
703
1247
  {
704
- gasUsed: "9139530",
705
- transactionHash: "0x116c4875b7712b7cb51cdb0fcb6e66a95733dca272aa272bc0b1fd265edbe26c",
706
- blockNumber: "49",
707
- blockHash: "0xd36340fddd1eace21b73f785c6589bf73b07bef782f2e78a5e3d3d828b0b607c",
708
- calldataBytes: 61444
1248
+ gasUsed: "985711",
1249
+ transactionHash: "0x2c911fd5a422f6f72f2a00b16872b7e46e182d39b8f5bfa9e3b2bf99d3155da7",
1250
+ blockNumber: "172",
1251
+ blockHash: "0x9da571cbe63f52232261ee1527d5ed97a9e90e374b4fcda97d04feb25114d18e",
1252
+ calldataBytes: 9540
1253
+ }
1254
+ ]
1255
+ }
1256
+ ]
1257
+ },
1258
+ {
1259
+ formatVersion: 1,
1260
+ id: "protocol-92ef274-osaka-real",
1261
+ deployment: {
1262
+ chainId: "31337",
1263
+ protocolAddress: "0x8870C63A18a9480C7de9B860b849fD293832856D",
1264
+ runtimeCodeHash: "0x604572c0da90ea139b774cd0d2962a2972fac46e0556c7cec6f6f9aac5deef14",
1265
+ tokenAddress: "0x4826533B4897376654Bb4d4AD88B7faFD0C98528"
1266
+ },
1267
+ source: {
1268
+ protocolCommit: "92ef274c6b36d783507699a33ee20e52192c83c7",
1269
+ measuredAt: "2026-10-27T08:42:15.991Z",
1270
+ chain: "Anvil 31337",
1271
+ hardfork: "osaka",
1272
+ token: "MockERC20",
1273
+ verifier: "real",
1274
+ assumptions: [
1275
+ "normal CREATE/Factory deployment; no code or storage injection",
1276
+ "Solidity 0.8.27 optimizer 200; real BB 5.2.1 verifiers",
1277
+ "one source tree; two existing leaves; no rollover or screener",
1278
+ "funding/approval setup excluded; complete transaction receipt gas included",
1279
+ "exact allowance for caller funding; configured benchmark payout balances",
1280
+ "observed local samples, not a confidence interval or gas limit"
1281
+ ]
1282
+ },
1283
+ measurements: [
1284
+ {
1285
+ id: "shield-1",
1286
+ shape: {
1287
+ kind: "shield",
1288
+ target: "evm",
1289
+ capacity: 0,
1290
+ noteInputs: 0,
1291
+ noteOutputs: 1,
1292
+ sourceTrees: 0,
1293
+ creditInputs: 0,
1294
+ creditOutputs: 0,
1295
+ creditRemainders: 0,
1296
+ funding: "caller",
1297
+ permit: false,
1298
+ deliveryBytes: 226
1299
+ },
1300
+ circuit: null,
1301
+ samples: [
1302
+ {
1303
+ gasUsed: "649286",
1304
+ transactionHash: "0xcc299d1780ada9a69b1d9f0f3d06a165db15fccbd2b7ff407834f02f5d563a18",
1305
+ blockNumber: "50",
1306
+ blockHash: "0xbcb868e781a20588d2fa099a4d7f87c1600044a2e5ec1e369e384d7a5f22f00a",
1307
+ calldataBytes: 1156
1308
+ },
1309
+ {
1310
+ gasUsed: "649322",
1311
+ transactionHash: "0x95139dff109725989f0769e3e6fb9bd3e7e1bf581fd475f14e822875eb90fda4",
1312
+ blockNumber: "50",
1313
+ blockHash: "0x7ace353fea4fc8c856c0fd45521d200b02619921977709ff4f910e0ff41c06fe",
1314
+ calldataBytes: 1156
1315
+ },
1316
+ {
1317
+ gasUsed: "649322",
1318
+ transactionHash: "0xef578bb38dc8ff8bfd47d2e76e3ab4273019ea9a385f5d2fd99add32ceaecb58",
1319
+ blockNumber: "50",
1320
+ blockHash: "0xded817f8ef89637e2443e3b626c0837f184ca134fe753be913d5570554c649a6",
1321
+ calldataBytes: 1156
709
1322
  }
710
1323
  ]
711
1324
  },
712
1325
  {
713
- id: "withdraw-1x1",
1326
+ id: "shield-2",
714
1327
  shape: {
715
- kind: "withdraw",
1328
+ kind: "shield",
1329
+ target: "evm",
1330
+ capacity: 0,
1331
+ noteInputs: 0,
1332
+ noteOutputs: 2,
1333
+ sourceTrees: 0,
1334
+ creditInputs: 0,
1335
+ creditOutputs: 0,
1336
+ creditRemainders: 0,
1337
+ funding: "caller",
1338
+ permit: false,
1339
+ deliveryBytes: 452
1340
+ },
1341
+ circuit: null,
1342
+ samples: [
1343
+ {
1344
+ gasUsed: "757063",
1345
+ transactionHash: "0x024e2dfbd6f50c368e2a4aa347e3029de668f4ebd36b80227aa003bb7ac21c74",
1346
+ blockNumber: "50",
1347
+ blockHash: "0x8ed63973c158d706ac54bb646626e4f0db5777b4bd56d179b94503af6c417c50",
1348
+ calldataBytes: 1668
1349
+ },
1350
+ {
1351
+ gasUsed: "757063",
1352
+ transactionHash: "0x898d852ab28f68adac4d30b160a3dbfee33fa7ca875f70df9eb7763b6b1cd1f0",
1353
+ blockNumber: "50",
1354
+ blockHash: "0x9bb6810de38193933a9f26fa03d3d9bad1ca0151ff5e04544c56520e09da3043",
1355
+ calldataBytes: 1668
1356
+ },
1357
+ {
1358
+ gasUsed: "757039",
1359
+ transactionHash: "0x8ff9720e3197aab2d741fbd8d0fa2969203ea8cd051d9649d1e5eb890bcc2be3",
1360
+ blockNumber: "50",
1361
+ blockHash: "0x8604c75eb6363aaae774276e638f5b749aae1f8f815eb99ab1183137eef5730e",
1362
+ calldataBytes: 1668
1363
+ }
1364
+ ]
1365
+ },
1366
+ {
1367
+ id: "shield-10",
1368
+ shape: {
1369
+ kind: "shield",
1370
+ target: "evm",
1371
+ capacity: 0,
1372
+ noteInputs: 0,
1373
+ noteOutputs: 10,
1374
+ sourceTrees: 0,
1375
+ creditInputs: 0,
1376
+ creditOutputs: 0,
1377
+ creditRemainders: 0,
1378
+ funding: "caller",
1379
+ permit: false,
1380
+ deliveryBytes: 2260
1381
+ },
1382
+ circuit: null,
1383
+ samples: [
1384
+ {
1385
+ gasUsed: "1692143",
1386
+ transactionHash: "0x6c13db8bd8a8599daf5034e56712abefbf406982fafe7647b6d22291ba4199ed",
1387
+ blockNumber: "50",
1388
+ blockHash: "0x1ab2ae514f408a79e0c40ca10cee74b2e23d7c8a5f24641b8eea3e1cf58ce700",
1389
+ calldataBytes: 5764
1390
+ },
1391
+ {
1392
+ gasUsed: "1692083",
1393
+ transactionHash: "0x5e476c9d3838b782a51332af9bf5c372d29fc411c2168a7af619c52bd5309c7b",
1394
+ blockNumber: "50",
1395
+ blockHash: "0x9c62bc72fc90f990c6711b48865ff922a1856ae05c4fef61dad5f4da7d948401",
1396
+ calldataBytes: 5764
1397
+ },
1398
+ {
1399
+ gasUsed: "1692203",
1400
+ transactionHash: "0x0092e2d9160fad95279cde586fc6c79c713244f55db8a2060a5abab9d98c176a",
1401
+ blockNumber: "50",
1402
+ blockHash: "0xac1bf780b4cc05b4dcc7ee5d741c049ba99ab4af9bdcd25104add730c2a14152",
1403
+ calldataBytes: 5764
1404
+ }
1405
+ ]
1406
+ },
1407
+ {
1408
+ id: "transfer-1x2",
1409
+ shape: {
1410
+ kind: "transfer",
716
1411
  target: "evm",
717
1412
  capacity: 14,
718
1413
  noteInputs: 1,
719
- noteOutputs: 1,
1414
+ noteOutputs: 2,
720
1415
  sourceTrees: 1,
721
1416
  creditInputs: 0,
722
1417
  creditOutputs: 0,
723
1418
  creditRemainders: 0,
724
1419
  funding: "none",
725
1420
  permit: false,
726
- deliveryBytes: 226
1421
+ deliveryBytes: 452
727
1422
  },
728
1423
  circuit: {
729
1424
  circuitName: "transact_user_slots14",
@@ -733,222 +1428,222 @@ var gas_benchmarks_default = [
733
1428
  },
734
1429
  samples: [
735
1430
  {
736
- gasUsed: "1597571",
737
- transactionHash: "0x326892d32146e0bc36b396fd3973151a629312df68ed25a4ffbb6a3da23ba274",
1431
+ gasUsed: "1617516",
1432
+ transactionHash: "0xf49ea3d31cc1346472172e2dee84f9360f60a3fe948a3ef6e87f727af6d42f0d",
738
1433
  blockNumber: "49",
739
- blockHash: "0x3e0f326cba3dd019b86431b4c22145758a7f10c121a696a81a094746b04495b5",
740
- calldataBytes: 10564
1434
+ blockHash: "0xf59c57e63ec2f03abc36d28f273b0af5290184dc97197df740b23d79a851a887",
1435
+ calldataBytes: 11012
741
1436
  },
742
1437
  {
743
- gasUsed: "1597715",
744
- transactionHash: "0x2e3a15157ac9c07e4717bbd4641481ce3bc0068d26157752815b6ec6b30acdd0",
1438
+ gasUsed: "1617516",
1439
+ transactionHash: "0xf8d11286f1f2a4db006ff6b06900c47d0fbf685984499e1e5d4aea49478ba8e5",
745
1440
  blockNumber: "49",
746
- blockHash: "0xab7fceac97d55e8702d1202b98d3a05c4b1e0f71e51b6d88d7e80e91cc338596",
747
- calldataBytes: 10564
1441
+ blockHash: "0xeb5a800190be3534c9e2675c97ac56d0e0be8adef55f60bd32d375776a7d150c",
1442
+ calldataBytes: 11012
748
1443
  },
749
1444
  {
750
- gasUsed: "1597595",
751
- transactionHash: "0x5052e94a67520c43416cdcb60a1365a126560861173d0eef46bcbf0a566fe947",
1445
+ gasUsed: "1617504",
1446
+ transactionHash: "0x8939fcea97079a3c5118b9e94325455e2ad1cdb47310ae499a277272654b3eb6",
752
1447
  blockNumber: "49",
753
- blockHash: "0x9a64cf76b646b5a07b72fcc61266e87f17365fec891701c331982a93e5ba9b89",
754
- calldataBytes: 10564
1448
+ blockHash: "0xecffefb593e2fec5d5827cfd39d0cc4d0efb67dbff6f8dbbd0d2db2439a80cf9",
1449
+ calldataBytes: 11012
755
1450
  }
756
1451
  ]
757
1452
  },
758
1453
  {
759
- id: "sweep-1x0",
1454
+ id: "transfer-1x14",
760
1455
  shape: {
761
- kind: "sweep",
1456
+ kind: "transfer",
762
1457
  target: "evm",
763
- capacity: 14,
1458
+ capacity: 56,
764
1459
  noteInputs: 1,
765
- noteOutputs: 0,
1460
+ noteOutputs: 14,
766
1461
  sourceTrees: 1,
767
1462
  creditInputs: 0,
768
1463
  creditOutputs: 0,
769
1464
  creditRemainders: 0,
770
1465
  funding: "none",
771
1466
  permit: false,
772
- deliveryBytes: 0
1467
+ deliveryBytes: 3164
773
1468
  },
774
1469
  circuit: {
775
- circuitName: "transact_user_slots14",
1470
+ circuitName: "transact_user_slots56",
776
1471
  target: "evm",
777
- artifactSha256: "2a6a20839e90b88b1ecd629f59a01821bad3ee11dbe04db1fd9cdce7a3de0e84",
778
- vkSha256: "ffe0e1a4e690792ecb4eb1fc1acc9ff60f13d3b5af03cfc6ae6d6bf26e99bdea"
1472
+ artifactSha256: "ba83ec2f177d16fa88ea04bc54f2e99920f1ac195cdb05b88b9b3bbc245fd953",
1473
+ vkSha256: "6ad5d3aff0c72a632fb19895658af093a6a92478a9994985e838a71e61237720"
779
1474
  },
780
1475
  samples: [
781
1476
  {
782
- gasUsed: "1069308",
783
- transactionHash: "0xb1ab469d05ca5f49659f54a332cc172892dcce37e475342fbf52fa9cfb4d3927",
1477
+ gasUsed: "2489010",
1478
+ transactionHash: "0x053557acea930a869d6469c91e9bc015d0893607a6ab18d2af684986f7074676",
784
1479
  blockNumber: "49",
785
- blockHash: "0xe5b04579149987198801f1ca19ab771d5262de2aaf9861a6c962d50d1c6baef0",
786
- calldataBytes: 10116
1480
+ blockHash: "0x734873097eb5e4cb66bfc2cdb61fac6753b53a4b9450fb22895281100af3aaf3",
1481
+ calldataBytes: 17156
787
1482
  },
788
1483
  {
789
- gasUsed: "1069284",
790
- transactionHash: "0xd6adee997f7e1e19e3918f913f6ee48d94df69c09ed74e333325023089e7f6df",
1484
+ gasUsed: "2489106",
1485
+ transactionHash: "0xb3990edb994011775e275bc1eb38c527b7206a2bfadf510e8aa53e260f3594b8",
791
1486
  blockNumber: "49",
792
- blockHash: "0xcb225566f8f1ea6ae8da30158b8f1aef03d50fa4ea352a00aa42b7f41a05d63c",
793
- calldataBytes: 10116
1487
+ blockHash: "0xf8cb019ebb0ecd0ec5d6634198292883c63fe93a7c65c34f9f3120c6cc54f1cf",
1488
+ calldataBytes: 17156
794
1489
  },
795
1490
  {
796
- gasUsed: "1069308",
797
- transactionHash: "0xe06dd7f3a2718bc9a9412c2d6f505960ce225b2e5fe6c1c66bb5b0e8f427006f",
1491
+ gasUsed: "2489094",
1492
+ transactionHash: "0xc97079019567ff8a79d285421351ee4bc48d14092a0e12ff634151719e991088",
798
1493
  blockNumber: "49",
799
- blockHash: "0x37a08c5918892e1c19df017c746ab0ede03c1bb195c3be593d70c1f9de91897e",
800
- calldataBytes: 10116
1494
+ blockHash: "0x5a6947839165c8961eeeb9190331415c40366a78b4a6a5771e7b8954dbb8b3c7",
1495
+ calldataBytes: 17156
801
1496
  }
802
1497
  ]
803
1498
  },
804
1499
  {
805
- id: "create-credit-1x1",
1500
+ id: "transfer-1x56",
806
1501
  shape: {
807
- kind: "create-credit",
1502
+ kind: "transfer",
808
1503
  target: "evm",
809
- capacity: 10,
1504
+ capacity: 112,
810
1505
  noteInputs: 1,
811
- noteOutputs: 1,
1506
+ noteOutputs: 56,
812
1507
  sourceTrees: 1,
813
1508
  creditInputs: 0,
814
- creditOutputs: 1,
1509
+ creditOutputs: 0,
815
1510
  creditRemainders: 0,
816
1511
  funding: "none",
817
1512
  permit: false,
818
- deliveryBytes: 1162
1513
+ deliveryBytes: 12656
819
1514
  },
820
1515
  circuit: {
821
- circuitName: "create_credit",
1516
+ circuitName: "transact_user_slots112",
822
1517
  target: "evm",
823
- artifactSha256: "ab97cd5a036851a9748a5cfd8e6f9834e23090c8e95db4531aabfc37d3abb353",
824
- vkSha256: "fac0e65b768a28750323cca851990598af936611125b6cfa3f5c16b04c7d084f"
1518
+ artifactSha256: "713b78469b6e97711122210f8497942120c1c9d66d3604bc184566c4eba59cc3",
1519
+ vkSha256: "d6a46e297949c28b9a62fd9aef1f202870fdca97b8bfb15beefd27b9e9f3d86e"
825
1520
  },
826
1521
  samples: [
827
1522
  {
828
- gasUsed: "1627325",
829
- transactionHash: "0x7763d93a5b1e8797b5f4af2e1e5b1bb029a8b0f9f7b90bcc04f581947d826803",
1523
+ gasUsed: "5389227",
1524
+ transactionHash: "0xb820d3c358724c1d64422017f232d074e4ff1ffaf1b1ce5ee719409427cf2208",
830
1525
  blockNumber: "49",
831
- blockHash: "0x93e51ae5e99c68dc642693d478e444330d8e26255ff5bb9aafc4a3f4e70d3a45",
832
- calldataBytes: 11940
1526
+ blockHash: "0x474bd1e52457801d1a596a9f23aeb6d365a17be028ee0c8cf8fd4758eaa1106b",
1527
+ calldataBytes: 36356
833
1528
  },
834
1529
  {
835
- gasUsed: "1627385",
836
- transactionHash: "0xe246d59cafa2a26dddf21c8385dd843be4d4596388ebe23e936df84e7f906635",
1530
+ gasUsed: "5389095",
1531
+ transactionHash: "0x16514d8cf1136d7a7f40591859e2ea2d256af66520498e1fc81eb28837db600d",
837
1532
  blockNumber: "49",
838
- blockHash: "0x3c24b2d6ed2a998562d34b49e0517515742a9b39d59aec38a9ac6b22be1b694b",
839
- calldataBytes: 11940
1533
+ blockHash: "0x42314a0d6eb9e765869e1b66b279444c78f919d2c28aed544d9fa7ac3bd2acb4",
1534
+ calldataBytes: 36356
840
1535
  },
841
1536
  {
842
- gasUsed: "1627157",
843
- transactionHash: "0x2f7ed0b75435cc6a820d0cd90fd82d362f74787057413722b6eb3c6e37db87d3",
1537
+ gasUsed: "5389203",
1538
+ transactionHash: "0xee69d565a7eafb60ad7a47afe80a49d4fa40b50660669d9141e7dc6f4c3dbe0d",
844
1539
  blockNumber: "49",
845
- blockHash: "0x0a0301670b46017da772800c68bb941245ac1941c79fde9c85717632154e15ee",
846
- calldataBytes: 11940
1540
+ blockHash: "0x0dcdada663ee04dd63e06fcdb79dacc5623201d29b687f63deede2b4762a994e",
1541
+ calldataBytes: 36356
847
1542
  }
848
1543
  ]
849
1544
  },
850
1545
  {
851
- id: "draw-credit-1-partial",
1546
+ id: "transfer-1x112",
852
1547
  shape: {
853
- kind: "draw-credit",
1548
+ kind: "transfer",
854
1549
  target: "evm",
855
- capacity: 1,
856
- noteInputs: 0,
857
- noteOutputs: 0,
1550
+ capacity: 168,
1551
+ noteInputs: 1,
1552
+ noteOutputs: 112,
858
1553
  sourceTrees: 1,
859
- creditInputs: 1,
860
- creditOutputs: 1,
861
- creditRemainders: 1,
1554
+ creditInputs: 0,
1555
+ creditOutputs: 0,
1556
+ creditRemainders: 0,
862
1557
  funding: "none",
863
1558
  permit: false,
864
- deliveryBytes: 936
1559
+ deliveryBytes: 25312
865
1560
  },
866
1561
  circuit: {
867
- circuitName: "credit_draw_slots1",
1562
+ circuitName: "transact_user_slots168",
868
1563
  target: "evm",
869
- artifactSha256: "f5e458790948f37a61a833fad52cf2cc3b26a59515d271de32e0caaa4e229eb5",
870
- vkSha256: "613699a440f50a0937e4c57e5152b5fdea42c31b10157d6b93226fef313df553"
1564
+ artifactSha256: "f7b3b1384e961367702f544299ca3521d8205fac31b7691c45ff84325d5a31c3",
1565
+ vkSha256: "e00181533d7e35d2307570528f9e7f8f88e2909b6ae338d93373b608dea96881"
871
1566
  },
872
1567
  samples: [
873
1568
  {
874
- gasUsed: "1581294",
875
- transactionHash: "0xd438e22b0fa07a657279f182537e4996f1936f0881d5b7d637845f8ca2808aab",
1569
+ gasUsed: "9139842",
1570
+ transactionHash: "0x09951c4e00b868b6660429d187a482004646e4c84ef341d3b98352c249db6a06",
876
1571
  blockNumber: "49",
877
- blockHash: "0x9e384a3054530b1ff237a639bca1a559afb2b73b30e21c262aac85ebf480fc9b",
878
- calldataBytes: 11396
1572
+ blockHash: "0xba9da3c08189335acff1eb33554f5f12475e4a6510324cf6ec9eadf340ce15d2",
1573
+ calldataBytes: 61444
879
1574
  },
880
1575
  {
881
- gasUsed: "1581402",
882
- transactionHash: "0xa70ac3e7284b6e98f8591a6ba88e4ddfb23ecbd05343641d0532f34920e10b56",
1576
+ gasUsed: "9139650",
1577
+ transactionHash: "0xb06f69d1c6e5406758918d5d296ab889bab4c3814f616cc581ad312cc7ebb2f3",
883
1578
  blockNumber: "49",
884
- blockHash: "0x37c5eb34ce96a841e96c36103a7ab65c1a3e08603dc9843efb0c0752c069f1d4",
885
- calldataBytes: 11396
1579
+ blockHash: "0x5516a76b4b366f2e539a67bb848b7d232c3e6f328d34ca5bd3dba43a14c316bf",
1580
+ calldataBytes: 61444
886
1581
  },
887
1582
  {
888
- gasUsed: "1581174",
889
- transactionHash: "0xd062494979d0bc0e284ccb070f87b48f3e8e5befb6001f15a006dd2a4a72ca24",
1583
+ gasUsed: "9139530",
1584
+ transactionHash: "0x116c4875b7712b7cb51cdb0fcb6e66a95733dca272aa272bc0b1fd265edbe26c",
890
1585
  blockNumber: "49",
891
- blockHash: "0x12840d920f14163b2d29491f28cee616e1bb9fd9514a4debe10ae35256345fc1",
892
- calldataBytes: 11396
1586
+ blockHash: "0xd36340fddd1eace21b73f785c6589bf73b07bef782f2e78a5e3d3d828b0b607c",
1587
+ calldataBytes: 61444
893
1588
  }
894
1589
  ]
895
1590
  },
896
1591
  {
897
- id: "top-up-credit-1x1",
1592
+ id: "withdraw-1x1",
898
1593
  shape: {
899
- kind: "top-up-credit",
1594
+ kind: "withdraw",
900
1595
  target: "evm",
901
- capacity: 10,
1596
+ capacity: 14,
902
1597
  noteInputs: 1,
903
1598
  noteOutputs: 1,
904
- sourceTrees: 2,
905
- creditInputs: 1,
906
- creditOutputs: 1,
1599
+ sourceTrees: 1,
1600
+ creditInputs: 0,
1601
+ creditOutputs: 0,
907
1602
  creditRemainders: 0,
908
1603
  funding: "none",
909
1604
  permit: false,
910
- deliveryBytes: 1162
1605
+ deliveryBytes: 226
911
1606
  },
912
1607
  circuit: {
913
- circuitName: "credit_top_up",
1608
+ circuitName: "transact_user_slots14",
914
1609
  target: "evm",
915
- artifactSha256: "ee9dbcf8be6f6c09478190996e90b1d39d4a10a00245950f69fc1d2c329c6e9b",
916
- vkSha256: "0c369fec0469b60baebb3be650bad42f3ccae6f0ff139cce6ad9a3f451ed7513"
1610
+ artifactSha256: "2a6a20839e90b88b1ecd629f59a01821bad3ee11dbe04db1fd9cdce7a3de0e84",
1611
+ vkSha256: "ffe0e1a4e690792ecb4eb1fc1acc9ff60f13d3b5af03cfc6ae6d6bf26e99bdea"
917
1612
  },
918
1613
  samples: [
919
1614
  {
920
- gasUsed: "1666948",
921
- transactionHash: "0x1403da01167962a4349d2655ea217bfcfc1a2390138bea0279792c44b4381dd2",
1615
+ gasUsed: "1597571",
1616
+ transactionHash: "0x326892d32146e0bc36b396fd3973151a629312df68ed25a4ffbb6a3da23ba274",
922
1617
  blockNumber: "49",
923
- blockHash: "0xcb554ffcdb4afe5f6458e5d23ffbdd1fdbef9c23f982343065772c0b3e3dd633",
924
- calldataBytes: 12100
1618
+ blockHash: "0x3e0f326cba3dd019b86431b4c22145758a7f10c121a696a81a094746b04495b5",
1619
+ calldataBytes: 10564
925
1620
  },
926
1621
  {
927
- gasUsed: "1666900",
928
- transactionHash: "0x3b5e54f29e3f888a443526cf23ab9255b3f0c7adf1d0d127c16b85f4c6a324d9",
1622
+ gasUsed: "1597715",
1623
+ transactionHash: "0x2e3a15157ac9c07e4717bbd4641481ce3bc0068d26157752815b6ec6b30acdd0",
929
1624
  blockNumber: "49",
930
- blockHash: "0xeb304df6bdd24b249cac3197b543b0eaa6381ed75ad812dff248f914864105ed",
931
- calldataBytes: 12100
1625
+ blockHash: "0xab7fceac97d55e8702d1202b98d3a05c4b1e0f71e51b6d88d7e80e91cc338596",
1626
+ calldataBytes: 10564
932
1627
  },
933
1628
  {
934
- gasUsed: "1666780",
935
- transactionHash: "0x81c5ef25268a719275cb3b80618c2af291e1f7b3f91d7e82cc26bc894a8c332a",
1629
+ gasUsed: "1597595",
1630
+ transactionHash: "0x5052e94a67520c43416cdcb60a1365a126560861173d0eef46bcbf0a566fe947",
936
1631
  blockNumber: "49",
937
- blockHash: "0xfa42070d6349fc8d559b8bd4ad0ee6b79089107540c4472b9e492b8f5a6bd3e4",
938
- calldataBytes: 12100
1632
+ blockHash: "0x9a64cf76b646b5a07b72fcc61266e87f17365fec891701c331982a93e5ba9b89",
1633
+ calldataBytes: 10564
939
1634
  }
940
1635
  ]
941
1636
  },
942
1637
  {
943
- id: "cancel-credit-1",
1638
+ id: "sweep-1x0",
944
1639
  shape: {
945
- kind: "cancel-credit",
1640
+ kind: "sweep",
946
1641
  target: "evm",
947
- capacity: 1,
948
- noteInputs: 0,
1642
+ capacity: 14,
1643
+ noteInputs: 1,
949
1644
  noteOutputs: 0,
950
1645
  sourceTrees: 1,
951
- creditInputs: 1,
1646
+ creditInputs: 0,
952
1647
  creditOutputs: 0,
953
1648
  creditRemainders: 0,
954
1649
  funding: "none",
@@ -956,32 +1651,32 @@ var gas_benchmarks_default = [
956
1651
  deliveryBytes: 0
957
1652
  },
958
1653
  circuit: {
959
- circuitName: "credit_cancel",
1654
+ circuitName: "transact_user_slots14",
960
1655
  target: "evm",
961
- artifactSha256: "d332453a2b8c2c544747ac8d5f01912c9757f48d986226fd6a9b0e24d8321474",
962
- vkSha256: "1f8a3c20cb081d6a90962556da3124919cc4e5675e59ad31562af39299da02fb"
1656
+ artifactSha256: "2a6a20839e90b88b1ecd629f59a01821bad3ee11dbe04db1fd9cdce7a3de0e84",
1657
+ vkSha256: "ffe0e1a4e690792ecb4eb1fc1acc9ff60f13d3b5af03cfc6ae6d6bf26e99bdea"
963
1658
  },
964
1659
  samples: [
965
1660
  {
966
- gasUsed: "998146",
967
- transactionHash: "0x97bc72692d241e2c344b912804f9939061db5ef59cf4bb23922d93812e382160",
1661
+ gasUsed: "1069308",
1662
+ transactionHash: "0xb1ab469d05ca5f49659f54a332cc172892dcce37e475342fbf52fa9cfb4d3927",
968
1663
  blockNumber: "49",
969
- blockHash: "0x2e09df4df84a1c25961386febe8404531bb5da274836d50cc15a26c91b433a98",
970
- calldataBytes: 9540
1664
+ blockHash: "0xe5b04579149987198801f1ca19ab771d5262de2aaf9861a6c962d50d1c6baef0",
1665
+ calldataBytes: 10116
971
1666
  },
972
1667
  {
973
- gasUsed: "998134",
974
- transactionHash: "0x26c5067b12c2bc4b694070784e6b19d4855efa6e77c2422f0c6b1567f061570a",
1668
+ gasUsed: "1069284",
1669
+ transactionHash: "0xd6adee997f7e1e19e3918f913f6ee48d94df69c09ed74e333325023089e7f6df",
975
1670
  blockNumber: "49",
976
- blockHash: "0xdd3f20520c09e001374cab58387e52c82446db053539e30dad28b0de679a333c",
977
- calldataBytes: 9540
1671
+ blockHash: "0xcb225566f8f1ea6ae8da30158b8f1aef03d50fa4ea352a00aa42b7f41a05d63c",
1672
+ calldataBytes: 10116
978
1673
  },
979
1674
  {
980
- gasUsed: "998230",
981
- transactionHash: "0x5dc09445a405150da1445c22f50d6dd10d8d428a6a3f41ee90db7d3574657e31",
1675
+ gasUsed: "1069308",
1676
+ transactionHash: "0xe06dd7f3a2718bc9a9412c2d6f505960ce225b2e5fe6c1c66bb5b0e8f427006f",
982
1677
  blockNumber: "49",
983
- blockHash: "0x5c8f8223a50d2c8d48188a2db28ffa33c1b150a2fb465e99db4430949db3664b",
984
- calldataBytes: 9540
1678
+ blockHash: "0x37a08c5918892e1c19df017c746ab0ede03c1bb195c3be593d70c1f9de91897e",
1679
+ calldataBytes: 10116
985
1680
  }
986
1681
  ]
987
1682
  }
@@ -1012,6 +1707,29 @@ function copyGasBenchmarks(profiles) {
1012
1707
  for (const p of copy) {
1013
1708
  if (p.formatVersion !== 1 || !p.id || !decimal.test(p.deployment.chainId) || !address.test(p.deployment.protocolAddress) || !address.test(p.deployment.tokenAddress) || !p.deployment.runtimeCodeHash || !word.test(p.deployment.runtimeCodeHash) || p.source.verifier !== "real" || !/^[0-9a-f]{40}$/i.test(p.source.protocolCommit) || !p.source.measuredAt || !Array.isArray(p.source.assumptions) || !p.source.assumptions.every((assumption) => typeof assumption === "string") || !p.measurements.length)
1014
1709
  throw new Error("invalid gas benchmark profile");
1710
+ if (p.source.fingerprints && ![
1711
+ "protocolSourceSha256",
1712
+ "dirtyDiffSha256",
1713
+ "compiledArtifactsSha256",
1714
+ "creditManifestSha256",
1715
+ "userManifestSha256",
1716
+ "sdkSourceSha256"
1717
+ ].every((key) => {
1718
+ const v = p.source.fingerprints[key];
1719
+ return typeof v === "string" && /^[a-f0-9]{64}$/i.test(v);
1720
+ }))
1721
+ throw new Error("invalid benchmark source fingerprint");
1722
+ if (p.source.blockGasLimit !== void 0 && (!decimal.test(p.source.blockGasLimit) || BigInt(p.source.blockGasLimit) <= 0n))
1723
+ throw new Error("invalid benchmark block gas limit");
1724
+ if (p.source.runtimeContracts && !Object.values(p.source.runtimeContracts).every(
1725
+ (v) => address.test(v.address) && word.test(v.runtimeCodeHash)
1726
+ ))
1727
+ throw new Error("invalid benchmark runtime identity");
1728
+ if (p.source.toolchain && (!["solidity", "barretenberg", "noir", "evmVersion", "anvil"].every((key) => {
1729
+ const v = p.source.toolchain[key];
1730
+ return typeof v === "string" && v.length > 0;
1731
+ }) || !Number.isSafeInteger(p.source.toolchain.optimizerRuns) || p.source.toolchain.optimizerRuns < 0))
1732
+ throw new Error("invalid benchmark toolchain");
1015
1733
  for (const m of p.measurements) {
1016
1734
  if (!m.id || !m.samples.length || !["none", "caller", "signature"].includes(m.shape.funding) || typeof m.shape.permit !== "boolean")
1017
1735
  throw new Error("invalid gas benchmark measurement");
@@ -1091,11 +1809,20 @@ function estimateBenchmarkGas(plan, protocol, profiles) {
1091
1809
  );
1092
1810
  if (!request.deployment.runtimeCodeHash || !candidates.length)
1093
1811
  return { ...base, available: false, reason: "deployment-not-covered" };
1094
- for (const profile of candidates) {
1095
- const measurement = profile.measurements.find(
1812
+ const exact = candidates.flatMap(
1813
+ (profile) => profile.measurements.filter(
1096
1814
  (m) => shapeKeys.every((key) => m.shape[key] === request.shape[key]) && sameCircuit(m.circuit, request.circuit)
1097
- );
1098
- if (!measurement) continue;
1815
+ ).map((measurement) => ({ profile, measurement }))
1816
+ );
1817
+ const mean = (measurement) => {
1818
+ const count = BigInt(measurement.samples.length);
1819
+ return (measurement.samples.reduce((sum, s) => sum + BigInt(s.gasUsed), 0n) + count - 1n) / count;
1820
+ };
1821
+ exact.sort(
1822
+ (a, b) => mean(a.measurement) > mean(b.measurement) ? -1 : mean(a.measurement) < mean(b.measurement) ? 1 : a.measurement.id.localeCompare(b.measurement.id)
1823
+ );
1824
+ if (exact.length) {
1825
+ const { profile, measurement } = exact[0];
1099
1826
  const gas = measurement.samples.map((sample) => BigInt(sample.gasUsed));
1100
1827
  const count = BigInt(gas.length);
1101
1828
  return {
@@ -1125,14 +1852,20 @@ function estimateShapeGas(request, profiles = defaultProfiles) {
1125
1852
  const matching = measurements.filter(
1126
1853
  (measurement) => measurement.shape.kind === request.shape.kind && measurement.shape.target === request.shape.target && sameCircuit(measurement.circuit, request.circuit)
1127
1854
  );
1128
- const exact = matching.find(
1855
+ const exact = matching.filter(
1129
1856
  (measurement) => shapeKeys.every((key) => measurement.shape[key] === request.shape[key])
1130
1857
  );
1131
- if (exact) {
1132
- const gas = exact.samples.map((sample) => BigInt(sample.gasUsed));
1133
- const count = BigInt(gas.length);
1134
- return { gasUnits: (gas.reduce((sum, value) => sum + value, 0n) + count - 1n) / count };
1858
+ if (exact.length) {
1859
+ const means = exact.map((m) => {
1860
+ const count = BigInt(m.samples.length);
1861
+ return (m.samples.reduce((sum, s) => sum + BigInt(s.gasUsed), 0n) + count - 1n) / count;
1862
+ });
1863
+ return { gasUnits: means.reduce((max, v) => v > max ? v : max) };
1135
1864
  }
1865
+ if (["create-credit", "draw-credit", "top-up-credit", "cancel-credit"].includes(
1866
+ request.shape.kind
1867
+ ) && !matching.length)
1868
+ throw new Error("No current Credit gas reference for this artifact and verification key");
1136
1869
  const candidates = matching.length ? matching : measurements.filter(
1137
1870
  (measurement) => measurement.shape.kind === request.shape.kind && measurement.shape.target === request.shape.target
1138
1871
  );
@@ -1147,7 +1880,22 @@ function estimateShapeGas(request, profiles = defaultProfiles) {
1147
1880
  "deliveryBytes",
1148
1881
  ...!matching.length ? ["capacity"] : []
1149
1882
  ];
1150
- const estimates = candidates.map((measurement) => {
1883
+ const groups = /* @__PURE__ */ new Map();
1884
+ for (const candidate of candidates) {
1885
+ const key = JSON.stringify([
1886
+ shapeKeys.map((k) => candidate.shape[k]),
1887
+ candidate.circuit?.circuitName,
1888
+ candidate.circuit?.target,
1889
+ candidate.circuit?.artifactSha256.toLowerCase(),
1890
+ candidate.circuit?.vkSha256.toLowerCase()
1891
+ ]);
1892
+ const previous = groups.get(key);
1893
+ groups.set(
1894
+ key,
1895
+ previous ? { ...candidate, samples: [...previous.samples, ...candidate.samples] } : candidate
1896
+ );
1897
+ }
1898
+ const estimates = [...groups.values()].map((measurement) => {
1151
1899
  let numerator = 1n;
1152
1900
  let denominator = 1n;
1153
1901
  for (const key of dimensions) {
@@ -1181,7 +1929,8 @@ var import_ethers6 = require("ethers");
1181
1929
 
1182
1930
  // src/session/operation-execution.ts
1183
1931
  var import_ethers2 = require("ethers");
1184
- var import_core = require("@invisi-labs/core");
1932
+ var import_core3 = require("@invisi-labs/core");
1933
+ var import_protocol2 = require("@invisi-labs/protocol");
1185
1934
 
1186
1935
  // src/session/proof-integrity.ts
1187
1936
  var import_ethers = require("ethers");
@@ -1210,23 +1959,41 @@ async function authorizeOperation(plan, provider) {
1210
1959
  if (provider.walletIdentity !== plan.scope.walletIdentity)
1211
1960
  throw new Error("wallet authorization capability mismatch");
1212
1961
  const request = authorizationRequest(plan);
1213
- const digest = (0, import_core.computeWalletAuthorizationDigest)(request);
1962
+ const digest = (0, import_core3.computeWalletAuthorizationDigest)(request);
1214
1963
  const signed = await provider.authorize(structuredClone(request));
1215
1964
  if (signed.walletIdentity !== plan.scope.walletIdentity || signed.digest !== digest)
1216
1965
  throw new Error("wallet authorization statement mismatch");
1217
1966
  return signed;
1218
1967
  }
1219
1968
  async function proveOperation(protocol, plan, authorization, prover, options) {
1969
+ if (Object.hasOwn(options, "target")) {
1970
+ throw new Error("prove accepts execution, not a backend target");
1971
+ }
1972
+ const { execution = "single", ...proverOptions } = options;
1973
+ if (execution !== "single" && execution !== "aggregate") {
1974
+ throw new Error("execution must be single or aggregate");
1975
+ }
1976
+ const frozen = statement(plan);
1977
+ if (execution === "aggregate" && (plan.kind !== "transfer" || plan.capacity !== 14)) {
1978
+ throw new Error("aggregate execution requires a 14-slot transfer");
1979
+ }
1980
+ if (plan.kind === "transfer") {
1981
+ plan.statement = import_protocol2.WitnessBuilder.statement(
1982
+ frozen.circuitName,
1983
+ frozen.expectedPublicInputs,
1984
+ execution === "aggregate" ? "noir-recursive" : "evm"
1985
+ );
1986
+ }
1220
1987
  const request = await witnessFor(protocol, plan, authorization);
1221
1988
  if (JSON.stringify({ ...request, witness: void 0 }) !== JSON.stringify(plan.statement))
1222
1989
  throw new Error("prepared proof statement changed");
1223
1990
  try {
1224
- const proof = publicProof(await prover.prove(request, options));
1991
+ const proof = publicProof(await prover.prove(request, proverOptions));
1225
1992
  sameStatement(proof, plan.statement);
1226
1993
  if (await prover.verify(
1227
1994
  structuredClone(proof),
1228
1995
  structuredClone(plan.statement),
1229
- options
1996
+ proverOptions
1230
1997
  ) !== true)
1231
1998
  throw new Error("proof verification failed");
1232
1999
  return proof;
@@ -1241,25 +2008,94 @@ async function signOperationFunding(saved, signer, verifier) {
1241
2008
  throw new Error("funding signer is not the payer");
1242
2009
  const typed = await fundingTypedData(saved);
1243
2010
  const signature = await signer.signTypedData(structuredClone(typed));
2011
+ return verifyFundingSignature(typed, payer, signature, verifier);
2012
+ }
2013
+ function walletSigningRequest(plan) {
2014
+ return (0, import_core3.createSigningRequest)((0, import_core3.walletAuthorizationTypedData)(authorizationRequest(plan)));
2015
+ }
2016
+ async function acceptWalletSignature(plan, signature) {
2017
+ const request = authorizationRequest(plan);
2018
+ const digest = (0, import_core3.computeWalletAuthorizationDigest)(request);
2019
+ try {
2020
+ const signed = import_ethers2.Signature.from(signature);
2021
+ const publicKey = (0, import_ethers2.getBytes)(import_ethers2.SigningKey.recoverPublicKey(digest, signed));
2022
+ const owner = await (0, import_core3.computeWalletIdentity)(publicKey);
2023
+ if (owner.toLowerCase() !== plan.scope.walletIdentity.toLowerCase()) {
2024
+ throw new Error("wallet signature identity mismatch");
2025
+ }
2026
+ return new import_core3.AuthorizedStatement(plan.scope.walletIdentity, digest, {
2027
+ public_key_x: Array.from(publicKey.slice(1, 33)),
2028
+ public_key_y: Array.from(publicKey.slice(33)),
2029
+ signature: Array.from((0, import_ethers2.getBytes)((0, import_ethers2.concat)([signed.r, signed.s])))
2030
+ });
2031
+ } catch {
2032
+ throw new Error("invalid wallet authorization signature");
2033
+ }
2034
+ }
2035
+ async function fundingSigningRequest(saved, runtime) {
2036
+ const plan = saved.plan;
2037
+ if (plan.fundingMode !== "signature") {
2038
+ throw new Error("operation does not require a funding signature");
2039
+ }
2040
+ if (plan.kind !== "shield" && !saved.proof) {
2041
+ throw new Error("proof must precede funding authorization");
2042
+ }
2043
+ await runtime.options.protocol.validateDeployment(runtime.reader);
2044
+ const block = await runtime.reader.getBlock(await runtime.reader.getLatestBlockNumber());
2045
+ if (block.timestamp > plan.deadline || block.timestamp > (plan.funding.deadline ?? 0n)) {
2046
+ throw new Error("funding authorization expired");
2047
+ }
2048
+ if (await runtime.reader.getFundingNonce(plan.context, plan.funding.payer, block) !== plan.funding.sigNonce) {
2049
+ throw new Error("funding nonce changed; prepare again");
2050
+ }
2051
+ const request = (0, import_core3.createSigningRequest)(await fundingTypedData(saved));
2052
+ if ((await runtime.reader.getBlock(block.number)).hash !== block.hash) {
2053
+ throw new Error("canonical funding block changed");
2054
+ }
2055
+ return request;
2056
+ }
2057
+ async function acceptFundingSignature(saved, signature, runtime) {
2058
+ if (!/^0x(?:[a-fA-F0-9]{2})+$/.test(signature)) {
2059
+ throw new Error("invalid EVM funding signature");
2060
+ }
2061
+ const request = await fundingSigningRequest(saved, runtime);
2062
+ return verifyFundingSignature(
2063
+ request,
2064
+ saved.plan.funding.payer,
2065
+ signature,
2066
+ runtime.options.fundingVerifier
2067
+ );
2068
+ }
2069
+ async function verifyFundingSignature(request, payer, signature, verifier) {
2070
+ if (!/^0x(?:[a-fA-F0-9]{2})+$/.test(signature)) {
2071
+ throw new Error("invalid EVM funding signature");
2072
+ }
2073
+ const types = Object.fromEntries(
2074
+ Object.entries(request.types).map(([name, fields]) => [name, [...fields]])
2075
+ );
2076
+ let validEOA = false;
2077
+ try {
2078
+ validEOA = (0, import_ethers2.verifyTypedData)(request.domain, types, request.message, signature).toLowerCase() === payer.toLowerCase();
2079
+ if (validEOA) {
2080
+ signature = import_ethers2.Signature.from(signature).serialized;
2081
+ }
2082
+ } catch {
2083
+ validEOA = false;
2084
+ }
1244
2085
  const valid = verifier ? await verifier.verifyTypedData({
1245
- ...structuredClone(typed),
2086
+ ...structuredClone(request),
1246
2087
  address: payer,
1247
2088
  signature
1248
- }) : (0, import_ethers2.verifyTypedData)(
1249
- typed.domain,
1250
- Object.fromEntries(
1251
- Object.entries(typed.types).map(([name, fields]) => [name, [...fields]])
1252
- ),
1253
- typed.message,
1254
- signature
1255
- ).toLowerCase() === payer.toLowerCase();
1256
- if (valid !== true) throw new Error("invalid EVM funding signature");
2089
+ }) : validEOA;
2090
+ if (valid !== true) {
2091
+ throw new Error("invalid EVM funding signature");
2092
+ }
1257
2093
  return signature;
1258
2094
  }
1259
2095
 
1260
2096
  // src/PreparedTransaction.ts
1261
- var import_core2 = require("@invisi-labs/core");
1262
- var import_protocol2 = require("@invisi-labs/protocol");
2097
+ var import_core4 = require("@invisi-labs/core");
2098
+ var import_protocol3 = require("@invisi-labs/protocol");
1263
2099
 
1264
2100
  // src/session/operation-preview.ts
1265
2101
  function operationPreview(plan, status) {
@@ -1367,30 +2203,77 @@ var PreparedTransaction = class _PreparedTransaction {
1367
2203
  this.#lifecycle.busy = false;
1368
2204
  }
1369
2205
  }
1370
- async authorize(providerOrOptions = {}, suppliedOptions = {}) {
1371
- const options = "authorize" in providerOrOptions ? suppliedOptions : providerOrOptions;
1372
- const provider = "authorize" in providerOrOptions ? providerOrOptions : this.#runtime.authorization();
2206
+ /** Public EIP-712 request; signing transport and key custody belong to the caller. */
2207
+ async exportWalletAuthorization(options = {}) {
2208
+ options.signal?.throwIfAborted();
2209
+ this.current();
1373
2210
  check2(
1374
2211
  requiresAuthorization(this.#saved.plan),
1375
2212
  "operation does not require wallet authorization"
1376
2213
  );
1377
- const selectedProvider = provider;
1378
2214
  check2(
1379
- provider.walletIdentity === this.#runtime.scope.walletIdentity,
1380
- "wallet authorization capability mismatch"
2215
+ ["prepared", "authorized"].includes(this.status),
2216
+ "operation is not awaiting wallet authorization"
2217
+ );
2218
+ return walletSigningRequest(this.#saved.plan);
2219
+ }
2220
+ /** Attach an external EOA signature, retaining its witness only at the private proving boundary. */
2221
+ async withWalletSignature(signature, options = {}) {
2222
+ options.signal?.throwIfAborted();
2223
+ this.current();
2224
+ check2(
2225
+ requiresAuthorization(this.#saved.plan),
2226
+ "operation does not require wallet authorization"
2227
+ );
2228
+ check2(
2229
+ ["prepared", "authorized"].includes(this.status),
2230
+ "operation is not awaiting wallet authorization"
1381
2231
  );
2232
+ const authorization = await acceptWalletSignature(this.#saved.plan, signature);
1382
2233
  return this.stage(
1383
2234
  "wallet authorization",
1384
2235
  ["prepared", "authorized"],
2236
+ async () => ({ status: "authorized", authorization }),
2237
+ options.signal
2238
+ );
2239
+ }
2240
+ /** Export only after proving when the funding authorization binds an actual proof hash. */
2241
+ async exportFundingAuthorization(options = {}) {
2242
+ options.signal?.throwIfAborted();
2243
+ this.current();
2244
+ check2(
2245
+ this.status === (this.kind === "shield" ? "prepared" : "proved"),
2246
+ "operation is not awaiting funding authorization or proof"
2247
+ );
2248
+ const request = await fundingSigningRequest(this.#saved, this.#runtime);
2249
+ options.signal?.throwIfAborted();
2250
+ this.current();
2251
+ return request;
2252
+ }
2253
+ /** Verify an external signature against this handle's own frozen operation. */
2254
+ async withFundingSignature(signature, options = {}) {
2255
+ options.signal?.throwIfAborted();
2256
+ this.current();
2257
+ check2(
2258
+ this.status === (this.kind === "shield" ? "prepared" : "proved"),
2259
+ "operation is not awaiting funding authorization or proof"
2260
+ );
2261
+ const verified = await acceptFundingSignature(this.#saved, signature, this.#runtime);
2262
+ return this.stage(
2263
+ "funding authorization",
2264
+ this.kind === "shield" ? ["prepared"] : ["proved"],
1385
2265
  async (saved) => {
1386
- const authorization = await authorizeOperation(saved.plan, selectedProvider);
1387
- return { status: "authorized", authorization };
2266
+ saved.plan.funding.signature = verified;
2267
+ if (saved.plan.statement?.target !== "noir-recursive") {
2268
+ saved.call = await this.encode(saved);
2269
+ }
2270
+ return { status: "ready" };
1388
2271
  },
1389
2272
  options.signal
1390
2273
  );
1391
2274
  }
1392
2275
  async prove(backendOrOptions = {}, suppliedOptions = {}) {
1393
- const options = "prove" in backendOrOptions ? suppliedOptions : backendOrOptions;
2276
+ const options = { ..."prove" in backendOrOptions ? suppliedOptions : backendOrOptions };
1394
2277
  const plan = this.#saved.plan;
1395
2278
  check2(plan.kind !== "shield", "shield requires no proof");
1396
2279
  if (requiresAuthorization(plan)) {
@@ -1401,7 +2284,7 @@ var PreparedTransaction = class _PreparedTransaction {
1401
2284
  }
1402
2285
  const prover = "prove" in backendOrOptions ? backendOrOptions : this.#runtime.options.prover;
1403
2286
  if (!prover) {
1404
- throw new import_core2.MissingCapabilityError("prover");
2287
+ throw new import_core4.MissingCapabilityError("prover");
1405
2288
  }
1406
2289
  return this.stage(
1407
2290
  "proof",
@@ -1429,37 +2312,6 @@ var PreparedTransaction = class _PreparedTransaction {
1429
2312
  encode(saved) {
1430
2313
  return encodeOperation(saved);
1431
2314
  }
1432
- async authorizeFunding(signerOrOptions = {}, suppliedOptions = {}) {
1433
- const options = "signTypedData" in signerOrOptions ? suppliedOptions : signerOrOptions;
1434
- const suppliedSigner = "signTypedData" in signerOrOptions ? signerOrOptions : void 0;
1435
- const p = this.#saved.plan;
1436
- check2(p.fundingMode === "signature", "operation does not require a funding signature");
1437
- check2(p.kind === "shield" || this.#saved.proof, "proof must precede funding authorization");
1438
- const signer = suppliedSigner ?? this.#runtime.options.fundingSigner;
1439
- if (!signer) {
1440
- throw new import_core2.MissingCapabilityError("EVM funding signer");
1441
- }
1442
- check2(
1443
- signer.address.toLowerCase() === p.funding.payer.toLowerCase(),
1444
- "funding signer is not the payer"
1445
- );
1446
- return this.stage(
1447
- "funding authorization",
1448
- p.kind === "shield" ? ["prepared"] : ["proved"],
1449
- async (saved) => {
1450
- saved.plan.funding.signature = await signOperationFunding(
1451
- saved,
1452
- signer,
1453
- this.#runtime.options.fundingVerifier
1454
- );
1455
- if (saved.plan.statement?.target !== "noir-recursive") {
1456
- saved.call = await this.encode(saved);
1457
- }
1458
- return { status: "ready" };
1459
- },
1460
- options.signal
1461
- );
1462
- }
1463
2315
  /** Shield caller funding needs no wallet signing or proof; this step only encodes its frozen request. */
1464
2316
  async ready() {
1465
2317
  check2(
@@ -1504,7 +2356,7 @@ var PreparedTransaction = class _PreparedTransaction {
1504
2356
  request: {
1505
2357
  params: structuredClone(plan.params),
1506
2358
  deliveries: plan.outputs.map((output) => structuredClone(output.delivery)),
1507
- funding: (0, import_protocol2.normalizeFunding)(plan.funding)
2359
+ funding: (0, import_protocol3.normalizeFunding)(plan.funding)
1508
2360
  }
1509
2361
  };
1510
2362
  }
@@ -1516,23 +2368,81 @@ var PreparedTransaction = class _PreparedTransaction {
1516
2368
  }
1517
2369
  };
1518
2370
 
2371
+ // src/resolve-recipient.ts
2372
+ var import_core5 = require("@invisi-labs/core");
2373
+ async function resolveRecipient(address2, lookup, details = {}) {
2374
+ const context = { ...details, address: address2 };
2375
+ let recipient;
2376
+ try {
2377
+ recipient = import_core5.ReceivingAddress.parse(address2);
2378
+ } catch (cause) {
2379
+ throw new InvisiError("INVALID_RECIPIENT", "Invalid recipient address", {
2380
+ ...context,
2381
+ cause
2382
+ });
2383
+ }
2384
+ if (recipient.kind === "long") return recipient;
2385
+ if (!lookup) {
2386
+ throw new InvisiError("MISSING_CAPABILITY", "Missing registry lookup capability", {
2387
+ ...context,
2388
+ capability: "registry lookup"
2389
+ });
2390
+ }
2391
+ let keys;
2392
+ try {
2393
+ keys = await lookup(recipient.walletIdentity);
2394
+ } catch (cause) {
2395
+ if (cause instanceof import_core5.MissingCapabilityError) {
2396
+ throw new InvisiError("MISSING_CAPABILITY", cause.message, {
2397
+ ...context,
2398
+ cause,
2399
+ capability: cause.capability
2400
+ });
2401
+ }
2402
+ throw new InvisiError("RECIPIENT_LOOKUP_FAILED", "Recipient registry lookup failed", {
2403
+ ...context,
2404
+ cause
2405
+ });
2406
+ }
2407
+ if (keys == null) {
2408
+ throw new InvisiError(
2409
+ "EVM_ADDRESS_NOT_REGISTERED",
2410
+ "EVM address has no registered receiving keys",
2411
+ context
2412
+ );
2413
+ }
2414
+ try {
2415
+ return import_core5.ReceivingAddress.from({
2416
+ walletIdentity: recipient.walletIdentity,
2417
+ viewingPublicKey: keys.viewingPublicKey,
2418
+ clueKey: keys.clueKey
2419
+ });
2420
+ } catch (cause) {
2421
+ throw new InvisiError(
2422
+ "RECIPIENT_LOOKUP_FAILED",
2423
+ "Registry returned invalid receiving keys",
2424
+ { ...context, cause }
2425
+ );
2426
+ }
2427
+ }
2428
+
1519
2429
  // src/session/prepare-common.ts
1520
2430
  var import_ethers3 = require("ethers");
1521
- var import_core4 = require("@invisi-labs/core");
1522
- var import_protocol3 = require("@invisi-labs/protocol");
2431
+ var import_core7 = require("@invisi-labs/core");
2432
+ var import_protocol4 = require("@invisi-labs/protocol");
1523
2433
 
1524
2434
  // src/session/membership.ts
1525
- var import_core3 = require("@invisi-labs/core");
2435
+ var import_core6 = require("@invisi-labs/core");
1526
2436
  async function verifyMembership(reader, context, block, input, proof) {
1527
2437
  if (proof.block.hash !== block.hash || proof.block.number !== block.number || proof.leaf !== input.commitment || proof.treeId !== input.treeId || proof.leafIndex !== input.leafIndex || proof.path.length !== 16 || !Number.isInteger(input.leafIndex) || input.leafIndex < 0 || input.leafIndex >= 65536 || !await reader.isKnownRoot(context, input.treeId, proof.root, block))
1528
2438
  throw new Error("membership context/root mismatch");
1529
2439
  let root = BigInt(input.commitment);
1530
2440
  for (let i = 0; i < 16; i++) {
1531
2441
  const sibling = proof.path[i];
1532
- if (typeof sibling !== "bigint" || sibling < 0n || sibling >= import_core3.FIELD_MODULUS)
2442
+ if (typeof sibling !== "bigint" || sibling < 0n || sibling >= import_core6.FIELD_MODULUS)
1533
2443
  throw new Error("noncanonical membership path");
1534
2444
  root = BigInt(
1535
- await (0, import_core3.poseidonHash)(input.leafIndex >> i & 1 ? [sibling, root] : [root, sibling])
2445
+ await (0, import_core6.poseidonHash)(input.leafIndex >> i & 1 ? [sibling, root] : [root, sibling])
1536
2446
  );
1537
2447
  }
1538
2448
  if (root !== BigInt(proof.root))
@@ -1568,7 +2478,28 @@ function positiveAmount(value, bits = 128) {
1568
2478
  if (typeof value !== "bigint" || value <= 0n || value >= 1n << BigInt(bits)) {
1569
2479
  throw new Error(`amount must be a positive uint${bits}`);
1570
2480
  }
1571
- return value;
2481
+ return value;
2482
+ }
2483
+ function copyApplicationPayload(value) {
2484
+ if (value === void 0) return new Uint8Array();
2485
+ if (!(value instanceof Uint8Array)) throw new TypeError("payload must be Uint8Array");
2486
+ return Uint8Array.from(value);
2487
+ }
2488
+ function positiveOutputAmount(payment, outputIndex) {
2489
+ try {
2490
+ return positiveAmount(payment.amount);
2491
+ } catch (cause) {
2492
+ throw new InvisiError(
2493
+ "PREPARATION_FAILED",
2494
+ cause instanceof Error ? cause.message : "Invalid output amount",
2495
+ {
2496
+ address: payment.to,
2497
+ field: "amount",
2498
+ ...outputIndex === void 0 ? {} : { outputIndex },
2499
+ cause
2500
+ }
2501
+ );
2502
+ }
1572
2503
  }
1573
2504
  var Preparation = class {
1574
2505
  constructor(runtime) {
@@ -1592,7 +2523,15 @@ var Preparation = class {
1592
2523
  throw new Error("canonical wallet checkpoint changed; resync required");
1593
2524
  }
1594
2525
  }
1595
- return { context: { ...options.protocol.context, now: block.timestamp }, block, deadline };
2526
+ return {
2527
+ context: {
2528
+ ...options.protocol.context,
2529
+ now: block.timestamp,
2530
+ timestamp: block.timestamp
2531
+ },
2532
+ block,
2533
+ deadline
2534
+ };
1596
2535
  }
1597
2536
  async assertBlock(frame) {
1598
2537
  if ((await this.runtime.reader.getBlock(frame.block.number)).hash !== frame.block.hash) {
@@ -1615,7 +2554,7 @@ var Preparation = class {
1615
2554
  if (mode === "caller" && (source.sigNonce || source.deadline)) {
1616
2555
  throw new Error("caller funding uses zero nonce/deadline");
1617
2556
  }
1618
- const funding = (0, import_protocol3.normalizeFunding)({
2557
+ const funding = (0, import_protocol4.normalizeFunding)({
1619
2558
  payer,
1620
2559
  amount: source.amount,
1621
2560
  sigNonce: mode === "caller" ? 0n : source.sigNonce ?? await this.runtime.reader.getFundingNonce(
@@ -1631,52 +2570,70 @@ var Preparation = class {
1631
2570
  }
1632
2571
  return { funding, fundingMode: mode };
1633
2572
  }
1634
- async output(payment, context, change = false) {
1635
- positiveAmount(payment.amount);
1636
- const recipient = await import_core4.ReceivingAddress.parse(payment.to).resolve(
1637
- this.runtime.options.addressResolver
1638
- );
1639
- const memo = (0, import_core4.encodeMemo)(payment.memo);
1640
- const nonce = (0, import_core4.generateNonce)();
1641
- const identity = await (0, import_core4.computeNoteIdentity)(BigInt(recipient.walletIdentity), nonce);
1642
- const keys = recipient.getReceivingKeys();
1643
- const note = {
1644
- chainId: context.chainId,
1645
- protocolAddress: BigInt(context.protocolAddress),
1646
- tokenAddress: BigInt(context.tokenAddress),
1647
- walletIdentity: recipient.walletIdentity,
1648
- amount: payment.amount,
1649
- ...memo.length === 0 ? {} : { memo },
1650
- nonce
1651
- };
1652
- const commitment = await (0, import_core4.computeNoteCommitment)(
1653
- context.chainId,
1654
- identity,
1655
- note.tokenAddress,
1656
- note.amount
1657
- );
1658
- return {
1659
- note,
1660
- commitment,
1661
- identity,
1662
- address: payment.to,
1663
- change,
1664
- delivery: {
1665
- ciphertext: (0, import_ethers3.hexlify)(
1666
- await (0, import_core4.encryptPrivateTransferNote)(keys.viewingPublicKey, note, {
1667
- chainId: context.chainId,
1668
- protocolAddress: note.protocolAddress,
1669
- outputCommitment: commitment
1670
- })
1671
- ),
1672
- clue: (0, import_ethers3.hexlify)((0, import_core4.createClue)(keys.clueKey))
1673
- }
1674
- };
2573
+ async output(payment, context, change = false, outputIndex) {
2574
+ try {
2575
+ positiveOutputAmount(payment, outputIndex);
2576
+ const recipient = await resolveRecipient(
2577
+ payment.to,
2578
+ this.runtime.options.addressResolver,
2579
+ {
2580
+ field: change ? "changeAddress" : "to",
2581
+ ...outputIndex === void 0 ? {} : { outputIndex }
2582
+ }
2583
+ );
2584
+ const nonce = (0, import_core7.generateNonce)();
2585
+ const identity = await (0, import_core7.computeNoteIdentity)(BigInt(recipient.walletIdentity), nonce);
2586
+ const keys = recipient.getReceivingKeys();
2587
+ const note = {
2588
+ chainId: context.chainId,
2589
+ protocolAddress: BigInt(context.protocolAddress),
2590
+ tokenAddress: BigInt(context.tokenAddress),
2591
+ walletIdentity: recipient.walletIdentity,
2592
+ amount: payment.amount,
2593
+ payload: copyApplicationPayload(payment.payload),
2594
+ nonce
2595
+ };
2596
+ const commitment = await (0, import_core7.computeNoteCommitment)(
2597
+ context.chainId,
2598
+ identity,
2599
+ note.tokenAddress,
2600
+ note.amount
2601
+ );
2602
+ return {
2603
+ note,
2604
+ commitment,
2605
+ identity,
2606
+ address: payment.to,
2607
+ change,
2608
+ delivery: {
2609
+ ciphertext: (0, import_ethers3.hexlify)(
2610
+ await (0, import_core7.encryptPrivateTransferNote)(keys.viewingPublicKey, note, {
2611
+ chainId: context.chainId,
2612
+ protocolAddress: note.protocolAddress,
2613
+ outputCommitment: commitment
2614
+ })
2615
+ ),
2616
+ clue: (0, import_ethers3.hexlify)((0, import_core7.createClue)(keys.clueKey))
2617
+ }
2618
+ };
2619
+ } catch (cause) {
2620
+ if (cause instanceof InvisiError) throw cause;
2621
+ throw new InvisiError(
2622
+ "PREPARATION_FAILED",
2623
+ cause instanceof Error ? cause.message : "Output preparation failed",
2624
+ {
2625
+ address: payment.to,
2626
+ field: change ? "changeAddress" : "to",
2627
+ ...outputIndex === void 0 ? {} : { outputIndex },
2628
+ cause
2629
+ }
2630
+ );
2631
+ }
1675
2632
  }
1676
2633
  async membership(input, frame) {
1677
2634
  const { options, reader } = this.runtime;
1678
2635
  if (!options.protocolRpc)
1679
- throw new import_core4.MissingCapabilityError("Protocol RPC membership provider");
2636
+ throw new import_core7.MissingCapabilityError("Protocol RPC membership provider");
1680
2637
  const root = this.#roots.get(input.treeId);
1681
2638
  const proof = await options.protocolRpc.getMembership(
1682
2639
  frame.context,
@@ -1723,9 +2680,9 @@ var Preparation = class {
1723
2680
  for (const input of selected) {
1724
2681
  const note = input.note;
1725
2682
  const c = frame.context;
1726
- if (note.walletIdentity !== scope.walletIdentity || note.chainId !== c.chainId || note.protocolAddress !== BigInt(c.protocolAddress) || note.tokenAddress !== BigInt(c.tokenAddress) || await (0, import_core4.computeNoteCommitment)(
2683
+ if (note.walletIdentity !== scope.walletIdentity || note.chainId !== c.chainId || note.protocolAddress !== BigInt(c.protocolAddress) || note.tokenAddress !== BigInt(c.tokenAddress) || await (0, import_core7.computeNoteCommitment)(
1727
2684
  c.chainId,
1728
- await (0, import_core4.computeNoteIdentity)(BigInt(note.walletIdentity), note.nonce),
2685
+ await (0, import_core7.computeNoteIdentity)(BigInt(note.walletIdentity), note.nonce),
1729
2686
  note.tokenAddress,
1730
2687
  note.amount
1731
2688
  ) !== input.commitment) {
@@ -1777,18 +2734,18 @@ function storedCandidates(inputs) {
1777
2734
 
1778
2735
  // src/session/transaction-preparation.ts
1779
2736
  var import_ethers5 = require("ethers");
1780
- var import_protocol5 = require("@invisi-labs/protocol");
2737
+ var import_protocol6 = require("@invisi-labs/protocol");
1781
2738
 
1782
2739
  // src/session/prepare-credit.ts
1783
2740
  var import_ethers4 = require("ethers");
1784
- var import_core6 = require("@invisi-labs/core");
1785
- var import_protocol4 = require("@invisi-labs/protocol");
2741
+ var import_core9 = require("@invisi-labs/core");
2742
+ var import_protocol5 = require("@invisi-labs/protocol");
1786
2743
 
1787
2744
  // src/session/credit-values.ts
1788
- var import_core5 = require("@invisi-labs/core");
2745
+ var import_core8 = require("@invisi-labs/core");
1789
2746
  async function creditLeaf(state) {
1790
2747
  const n = state.note;
1791
- return (0, import_core5.computeCreditCommitment)(
2748
+ return (0, import_core8.computeCreditCommitment)(
1792
2749
  n.chainId,
1793
2750
  n.spenderWalletIdentity,
1794
2751
  n.ownerWalletIdentity,
@@ -1798,7 +2755,8 @@ async function creditLeaf(state) {
1798
2755
  n.amount,
1799
2756
  n.nonce,
1800
2757
  n.expiry,
1801
- await (0, import_core5.computeCreditSharedKeyHash)(n.creditSharedKey)
2758
+ await (0, import_core8.computeCreditSharedKeyHash)(n.creditSharedKey),
2759
+ n
1802
2760
  );
1803
2761
  }
1804
2762
 
@@ -1817,7 +2775,7 @@ var CreditPreparation = class {
1817
2775
  return value;
1818
2776
  }
1819
2777
  async seal(input, frame) {
1820
- const state = (0, import_core6.normalizeCreditDeliveryState)(input);
2778
+ const state = (0, import_core9.normalizeCreditDeliveryState)(input);
1821
2779
  const commitment = await creditLeaf(state);
1822
2780
  const context = {
1823
2781
  chainId: frame.context.chainId,
@@ -1829,9 +2787,9 @@ var CreditPreparation = class {
1829
2787
  const keys = role === "owner" ? state.ownerReceivingKeys : state.spenderReceivingKeys;
1830
2788
  return {
1831
2789
  ciphertext: (0, import_ethers4.hexlify)(
1832
- await (0, import_core6.encryptCreditNote)(keys.viewingPublicKey, state, { ...context, role })
2790
+ await (0, import_core9.encryptCreditNote)(keys.viewingPublicKey, state, { ...context, role })
1833
2791
  ),
1834
- clue: (0, import_ethers4.hexlify)((0, import_core6.createClue)(keys.clueKey))
2792
+ clue: (0, import_ethers4.hexlify)((0, import_core9.createClue)(keys.clueKey))
1835
2793
  };
1836
2794
  })
1837
2795
  );
@@ -1842,14 +2800,14 @@ var CreditPreparation = class {
1842
2800
  if (!stored || stored.spent !== "unspent" || stored.role !== role) {
1843
2801
  throw new Error(`confirmed unspent ${role} Credit is unavailable`);
1844
2802
  }
1845
- const state = (0, import_core6.normalizeCreditDeliveryState)(stored.state);
2803
+ const state = (0, import_core9.normalizeCreditDeliveryState)(stored.state);
1846
2804
  const n = state.note;
1847
2805
  if ((role === "owner" ? n.ownerWalletIdentity : n.spenderWalletIdentity) !== this.runtime.scope.walletIdentity || n.chainId !== frame.context.chainId || n.protocolAddress !== BigInt(frame.context.protocolAddress) || n.tokenAddress !== BigInt(frame.context.tokenAddress) || await creditLeaf(state) !== commitment) {
1848
2806
  throw new Error("Credit role, commitment or deployment mismatch");
1849
2807
  }
1850
2808
  const proof = await this.#prepare.membership(stored, frame);
1851
2809
  const path = [...proof.path];
1852
- const nullifier = await (0, import_core6.computeCreditNullifier)(n.chainId, n.creditSharedKey, commitment);
2810
+ const nullifier = await (0, import_core9.computeCreditNullifier)(n.chainId, n.creditSharedKey, commitment);
1853
2811
  await this.#prepare.assertUnspent([nullifier], frame);
1854
2812
  return {
1855
2813
  input: {
@@ -1886,10 +2844,16 @@ var CreditPreparation = class {
1886
2844
  positiveAmount(options.amount, 126);
1887
2845
  const frame = await this.#prepare.frame(options.deadline);
1888
2846
  const expiry = this.expiry(options.expiry, frame);
1889
- const spender = await import_core6.ReceivingAddress.parse(options.spender).resolve(
1890
- this.runtime.options.addressResolver
2847
+ const spender = await resolveRecipient(
2848
+ options.spender,
2849
+ this.runtime.options.addressResolver,
2850
+ { field: "spender" }
2851
+ );
2852
+ const owner = await resolveRecipient(
2853
+ this.runtime.options.wallet.getReceivingAddress().toString(),
2854
+ this.runtime.options.addressResolver,
2855
+ { field: "wallet" }
1891
2856
  );
1892
- const owner = await this.runtime.options.wallet.getReceivingAddress().resolve(this.runtime.options.addressResolver);
1893
2857
  const ownerPayout = (0, import_ethers4.getAddress)(owner.walletIdentity);
1894
2858
  const spenderPayout = (0, import_ethers4.getAddress)(spender.walletIdentity);
1895
2859
  if (BigInt(ownerPayout) === 0n || BigInt(spenderPayout) === 0n) {
@@ -1905,11 +2869,16 @@ var CreditPreparation = class {
1905
2869
  spenderWalletIdentity: spender.walletIdentity,
1906
2870
  ownerPayout: BigInt(ownerPayout),
1907
2871
  spenderPayout: BigInt(spenderPayout),
2872
+ ...(0, import_core9.normalizeCreditPolicy)({
2873
+ singleLimit: options.singleLimit ?? 0n,
2874
+ dailyLimit: options.dailyLimit ?? 0n,
2875
+ monthlyLimit: options.monthlyLimit ?? 0n
2876
+ }),
1908
2877
  amount: options.amount,
1909
- ...options.memo === void 0 ? {} : { memo: options.memo },
2878
+ payload: copyApplicationPayload(options.payload),
1910
2879
  expiry,
1911
- nonce: (0, import_core6.generateNonce)(),
1912
- creditSharedKey: (0, import_core6.generateCreditSharedKey)()
2880
+ nonce: (0, import_core9.generateNonce)(),
2881
+ creditSharedKey: (0, import_core9.generateCreditSharedKey)()
1913
2882
  },
1914
2883
  ownerReceivingKeys: owner.getReceivingKeys(),
1915
2884
  spenderReceivingKeys: spender.getReceivingKeys()
@@ -1951,7 +2920,7 @@ var CreditPreparation = class {
1951
2920
  sources: selected.sources,
1952
2921
  nullifiers: selected.nullifiers,
1953
2922
  creditCommitment: output.commitment,
1954
- changeCommitment: plan.outputs[0]?.commitment ?? (0, import_protocol4.word)(0n),
2923
+ changeCommitment: plan.outputs[0]?.commitment ?? (0, import_protocol5.word)(0n),
1955
2924
  owner: (0, import_ethers4.getAddress)((0, import_ethers4.toBeHex)(output.state.note.ownerPayout, 20)),
1956
2925
  expiry: output.state.note.expiry,
1957
2926
  deadline: frame.deadline
@@ -1971,14 +2940,14 @@ var CreditPreparation = class {
1971
2940
  creditNullifier: previous.nullifier,
1972
2941
  previousExpiry: previous.input.state.note.expiry
1973
2942
  };
1974
- plan.statement = import_protocol4.WitnessBuilder.statement(
2943
+ plan.statement = import_protocol5.WitnessBuilder.statement(
1975
2944
  "credit_top_up",
1976
- (0, import_protocol4.topUpCreditPublicInputs)(frame.context, plan.credit.topUp, deliveries, plan.funding)
2945
+ (0, import_protocol5.topUpCreditPublicInputs)(frame.context, plan.credit.topUp, deliveries, plan.funding)
1977
2946
  );
1978
2947
  } else {
1979
- plan.statement = import_protocol4.WitnessBuilder.statement(
2948
+ plan.statement = import_protocol5.WitnessBuilder.statement(
1980
2949
  "create_credit",
1981
- (0, import_protocol4.createCreditPublicInputs)(frame.context, creation, deliveries, plan.funding)
2950
+ (0, import_protocol5.createCreditPublicInputs)(frame.context, creation, deliveries, plan.funding)
1982
2951
  );
1983
2952
  }
1984
2953
  await this.#prepare.assertBlock(frame);
@@ -2002,10 +2971,15 @@ var CreditPreparation = class {
2002
2971
  ...old,
2003
2972
  note: {
2004
2973
  ...old.note,
2974
+ singleLimit: options.singleLimit ?? old.note.singleLimit ?? 0n,
2975
+ dailyLimit: options.dailyLimit ?? old.note.dailyLimit ?? 0n,
2976
+ monthlyLimit: options.monthlyLimit ?? old.note.monthlyLimit ?? 0n,
2005
2977
  amount,
2006
2978
  expiry,
2007
- nonce: (0, import_core6.generateNonce)(),
2008
- ...options.memo === void 0 ? {} : { memo: options.memo }
2979
+ nonce: (0, import_core9.generateNonce)(),
2980
+ payload: copyApplicationPayload(
2981
+ options.payload === void 0 ? old.note.payload : options.payload
2982
+ )
2009
2983
  }
2010
2984
  },
2011
2985
  frame
@@ -2021,7 +2995,7 @@ var CreditPreparation = class {
2021
2995
  }
2022
2996
  async draw(options) {
2023
2997
  const frame = await this.#prepare.frame(options.deadline);
2024
- const profile = (0, import_protocol4.selectCreditDrawCircuit)(options.credits.length);
2998
+ const profile = (0, import_protocol5.selectCreditDrawCircuit)(options.credits.length);
2025
2999
  if (new Set(options.credits.map((value) => value.credit)).size !== options.credits.length) {
2026
3000
  throw new Error("duplicate Credit input");
2027
3001
  }
@@ -2053,10 +3027,11 @@ var CreditPreparation = class {
2053
3027
  }
2054
3028
  sources.set(member.source.treeId, member.source.merkleRoot);
2055
3029
  amounts.push(amount);
3030
+ const usage = (0, import_core9.applyCreditDrawUsage)(n, amount, frame.block.timestamp);
2056
3031
  const remaining = n.amount - amount;
2057
3032
  if (remaining === 0n) {
2058
- remainders.push((0, import_protocol4.word)(0n));
2059
- recoveryAmounts.push((0, import_protocol4.word)(0n));
3033
+ remainders.push((0, import_protocol5.word)(0n));
3034
+ recoveryAmounts.push((0, import_protocol5.word)(0n));
2060
3035
  deliveries.push({ ...EMPTY }, { ...EMPTY });
2061
3036
  continue;
2062
3037
  }
@@ -2072,9 +3047,12 @@ var CreditPreparation = class {
2072
3047
  ...state,
2073
3048
  note: {
2074
3049
  ...n,
3050
+ ...usage,
2075
3051
  amount: remaining,
2076
- ...options.credits[i].memo === void 0 ? {} : { memo: options.credits[i].memo },
2077
- nonce: await (0, import_core6.deriveRemainderNonce)(...args)
3052
+ payload: copyApplicationPayload(
3053
+ options.credits[i].payload === void 0 ? n.payload : options.credits[i].payload
3054
+ ),
3055
+ nonce: await (0, import_core9.deriveRemainderNonce)(...args)
2078
3056
  }
2079
3057
  },
2080
3058
  frame
@@ -2082,7 +3060,7 @@ var CreditPreparation = class {
2082
3060
  outputs.push(output);
2083
3061
  remainders.push(output.commitment);
2084
3062
  recoveryAmounts.push(
2085
- (0, import_protocol4.word)((remaining + await (0, import_core6.computeCreditRecoveryPad)(...args)) % import_core6.FIELD_MODULUS)
3063
+ (0, import_protocol5.word)((remaining + await (0, import_core9.computeCreditRecoveryPad)(...args)) % import_core9.FIELD_MODULUS)
2086
3064
  );
2087
3065
  deliveries.push(...output.deliveries);
2088
3066
  }
@@ -2106,9 +3084,9 @@ var CreditPreparation = class {
2106
3084
  draw: params,
2107
3085
  amounts
2108
3086
  };
2109
- plan.statement = import_protocol4.WitnessBuilder.statement(
3087
+ plan.statement = import_protocol5.WitnessBuilder.statement(
2110
3088
  profile.name,
2111
- (0, import_protocol4.creditDrawPublicInputs)(frame.context, params, deliveries)
3089
+ (0, import_protocol5.creditDrawPublicInputs)(frame.context, params, deliveries)
2112
3090
  );
2113
3091
  await this.#prepare.assertBlock(frame);
2114
3092
  return this.runtime.complete(plan);
@@ -2128,9 +3106,9 @@ var CreditPreparation = class {
2128
3106
  };
2129
3107
  plan.capacity = 1;
2130
3108
  plan.credit = { inputs: [previous.input], outputs: [], deliveries: [], cancel: params };
2131
- plan.statement = import_protocol4.WitnessBuilder.statement(
3109
+ plan.statement = import_protocol5.WitnessBuilder.statement(
2132
3110
  "credit_cancel",
2133
- (0, import_protocol4.cancelCreditPublicInputs)(frame.context, params)
3111
+ (0, import_protocol5.cancelCreditPublicInputs)(frame.context, params)
2134
3112
  );
2135
3113
  await this.#prepare.assertBlock(frame);
2136
3114
  return this.runtime.complete(plan);
@@ -2151,87 +3129,48 @@ var TransactionPreparation = class {
2151
3129
  return this.context.scope;
2152
3130
  }
2153
3131
  async prepareTransfer(options) {
3132
+ if (Object.hasOwn(options, "target") || Object.hasOwn(options, "execution")) {
3133
+ throw new Error(
3134
+ "prepareTransfer accepts no target or execution; choose execution in prove()"
3135
+ );
3136
+ }
2154
3137
  const copied = structuredClone(options);
2155
- const preparation = new Preparation(this.runtime(copied.tokenAddress));
3138
+ const runtime = this.runtime(copied.tokenAddress);
3139
+ if (copied.commitments !== void 0 && copied.commitments.length === 0)
3140
+ throw new Error("empty explicit input selection");
3141
+ const preparation = new Preparation({
3142
+ ...runtime,
3143
+ ...copied.commitments !== void 0 ? { inputSelection: copied.commitments } : {}
3144
+ });
2156
3145
  const frame = await preparation.frame(copied.deadline);
2157
- if (copied.outputs.length < 1 || copied.outputs.length > 168) {
2158
- throw new Error("transfer requires 1..168 outputs");
3146
+ if (copied.outputs.length > 168) throw new Error("transfer supports at most 168 outputs");
3147
+ let withdrawalAddress = import_protocol6.ZERO_ADDRESS;
3148
+ let withdrawalAmount = 0n;
3149
+ if (copied.withdrawal !== void 0) {
3150
+ withdrawalAddress = (0, import_ethers5.getAddress)(copied.withdrawal.to);
3151
+ positiveAmount(copied.withdrawal.amount);
3152
+ if (BigInt(withdrawalAddress) === 0n)
3153
+ throw new Error("withdrawal destination must be nonzero");
3154
+ withdrawalAmount = copied.withdrawal.amount;
2159
3155
  }
3156
+ if (copied.outputs.length === 0 && withdrawalAmount === 0n)
3157
+ throw new Error("transfer requires a private output or public withdrawal");
2160
3158
  const total = copied.outputs.reduce(
2161
- (sum, output) => sum + positiveAmount(output.amount),
2162
- 0n
3159
+ (sum, output, index2) => sum + positiveOutputAmount(output, index2),
3160
+ withdrawalAmount
2163
3161
  );
2164
3162
  const funding = await preparation.funding(copied.funding, frame);
2165
3163
  return this.funds(
2166
- "transfer",
2167
3164
  copied.outputs,
2168
3165
  total,
2169
- import_protocol5.ZERO_ADDRESS,
2170
- 0n,
3166
+ withdrawalAddress,
3167
+ withdrawalAmount,
2171
3168
  frame,
2172
3169
  funding,
2173
- copied.target,
2174
- preparation
2175
- );
2176
- }
2177
- async prepareWithdraw(options) {
2178
- const copied = structuredClone(options);
2179
- const preparation = new Preparation(this.runtime(copied.tokenAddress));
2180
- const frame = await preparation.frame(copied.deadline);
2181
- const to = (0, import_ethers5.getAddress)(copied.to);
2182
- positiveAmount(copied.amount);
2183
- if (BigInt(to) === 0n) {
2184
- throw new Error("withdrawal destination must be nonzero");
2185
- }
2186
- return this.funds(
2187
- "withdraw",
2188
- [],
2189
- copied.amount,
2190
- to,
2191
- copied.amount,
2192
- frame,
2193
- { funding: {}, fundingMode: "none" },
2194
- copied.target,
2195
3170
  preparation
2196
3171
  );
2197
3172
  }
2198
- /** Full payout to the note owner; no arbitrary destination, change or spending signature. */
2199
- async prepareSweep(options) {
2200
- const copied = structuredClone(options);
2201
- const runtime = this.runtime(copied.tokenAddress);
2202
- const state = await runtime.readInventory();
2203
- const available = Object.values(state.notes).filter(
2204
- (record) => record.note.tokenAddress === BigInt(copied.tokenAddress) && record.spent === "unspent" && !state.reservations[record.commitment]
2205
- );
2206
- const selected = copied.commitments ?? available.map((record) => record.commitment);
2207
- if (selected.length === 0) throw new Error("empty sweep input selection");
2208
- if (new Set(selected).size !== selected.length) throw new Error("duplicate sweep inputs");
2209
- const byId = new Map(available.map((record) => [record.commitment, record]));
2210
- let amount = 0n;
2211
- for (const id of selected) {
2212
- const record = byId.get(id);
2213
- if (!record) throw new Error("sweep input unavailable");
2214
- amount += record.note.amount;
2215
- }
2216
- positiveAmount(amount);
2217
- const preparation = new Preparation({
2218
- ...runtime,
2219
- inputSelection: selected
2220
- });
2221
- const frame = await preparation.frame(copied.deadline);
2222
- return this.funds(
2223
- "sweep",
2224
- [],
2225
- amount,
2226
- this.scope.walletIdentity,
2227
- amount,
2228
- frame,
2229
- { funding: {}, fundingMode: "none" },
2230
- copied.target,
2231
- preparation
2232
- );
2233
- }
2234
- async funds(kind, payments, total, withdrawalAddress, withdrawalAmount, frame, funding, target, preparation) {
3173
+ async funds(payments, total, withdrawalAddress, withdrawalAmount, frame, funding, preparation) {
2235
3174
  if (total >= 1n << 135n) {
2236
3175
  throw new Error("transaction sum exceeds uint135");
2237
3176
  }
@@ -2241,7 +3180,7 @@ var TransactionPreparation = class {
2241
3180
  frame
2242
3181
  );
2243
3182
  const outputs = await Promise.all(
2244
- payments.map((payment) => preparation.output(payment, context))
3183
+ payments.map((payment, index2) => preparation.output(payment, context, false, index2))
2245
3184
  );
2246
3185
  const change = selection.amount + (funding.funding.amount ?? 0n) - total;
2247
3186
  if (change > 0n) {
@@ -2266,17 +3205,17 @@ var TransactionPreparation = class {
2266
3205
  deadline
2267
3206
  };
2268
3207
  const deliveries = outputs.map((output) => output.delivery);
2269
- const normalized = (0, import_protocol5.normalizeTransactRequest)(context, params, deliveries, funding.funding);
2270
- const statement2 = import_protocol5.WitnessBuilder.statement(
3208
+ const normalized = (0, import_protocol6.normalizeTransactRequest)(context, params, deliveries, funding.funding);
3209
+ const statement2 = import_protocol6.WitnessBuilder.statement(
2271
3210
  `transact_user_slots${normalized.capacity}`,
2272
- (0, import_protocol5.transactUserPublicInputs)(context, params, deliveries, funding.funding),
2273
- target ?? "evm"
3211
+ (0, import_protocol6.transactUserPublicInputs)(context, params, deliveries, funding.funding),
3212
+ "evm"
2274
3213
  );
2275
3214
  await preparation.assertBlock(frame);
2276
3215
  return preparation.runtime.complete({
2277
3216
  version: 1,
2278
3217
  id: crypto.randomUUID(),
2279
- kind,
3218
+ kind: "transfer",
2280
3219
  context,
2281
3220
  scope: this.scope,
2282
3221
  preparedAt: block,
@@ -2298,7 +3237,9 @@ var TransactionPreparation = class {
2298
3237
  throw new Error("shield requires 1..10 outputs");
2299
3238
  }
2300
3239
  const outputs = await Promise.all(
2301
- copied.outputs.map((output) => preparation.output(output, frame.context))
3240
+ copied.outputs.map(
3241
+ (output, index2) => preparation.output(output, frame.context, false, index2)
3242
+ )
2302
3243
  );
2303
3244
  if (outputs.reduce((sum, output) => sum + output.note.amount, 0n) !== (funding.funding.amount ?? 0n)) {
2304
3245
  throw new Error("shield funding must equal output total");
@@ -2380,14 +3321,21 @@ function explicitPreparation(options, data, tokenAddress) {
2380
3321
  namespace: "explicit",
2381
3322
  walletIdentity: options.wallet.walletIdentity
2382
3323
  };
2383
- const { store: _store, coinSelector: _selector, ...capabilities } = options;
3324
+ const {
3325
+ store: _store,
3326
+ coinSelector: _selector,
3327
+ authorization: _authorization,
3328
+ viewing: _viewing,
3329
+ signer: _signer,
3330
+ fundingSigner: _fundingSigner,
3331
+ ...capabilities
3332
+ } = options;
2384
3333
  if (inputs.some((input) => input.note.tokenAddress !== BigInt((0, import_ethers6.getAddress)(tokenAddress))))
2385
3334
  throw new Error("explicit note token mismatch");
2386
3335
  const runtime = {
2387
3336
  options: { ...capabilities, protocol: options.protocol.forToken(tokenAddress) },
2388
3337
  reader: options.chainReader,
2389
- scope,
2390
- authorization: () => options.authorization ?? options.wallet.exportAuthorization()
3338
+ scope
2391
3339
  };
2392
3340
  return new TransactionPreparation({
2393
3341
  ...runtime,
@@ -2685,34 +3633,6 @@ var EthersAddressResolver = class {
2685
3633
  }).getReceivingKeys();
2686
3634
  };
2687
3635
  };
2688
- var EthersFundingSigner = class _EthersFundingSigner {
2689
- constructor(signer, chainId, address2) {
2690
- this.signer = signer;
2691
- this.chainId = chainId;
2692
- this.address = getAddress5(address2);
2693
- }
2694
- address;
2695
- static async create(signer, chainId) {
2696
- return new _EthersFundingSigner(signer, chainId, getAddress5(await signer.getAddress()));
2697
- }
2698
- async signTypedData(data) {
2699
- const copied = structuredClone(data);
2700
- check3(
2701
- BigInt(copied.domain.chainId) === this.chainId,
2702
- "funding typed-data chain mismatch"
2703
- );
2704
- check3(
2705
- getAddress5(await this.signer.getAddress()) === this.address,
2706
- "funding signer address mismatch"
2707
- );
2708
- if (this.signer.provider) await chain(this.signer.provider, this.chainId);
2709
- return await this.signer.signTypedData(
2710
- copied.domain,
2711
- fundingTypes(copied),
2712
- copied.message
2713
- );
2714
- }
2715
- };
2716
3636
  var EthersFundingVerifier = class {
2717
3637
  constructor(client, chainId) {
2718
3638
  this.client = client;
@@ -2755,7 +3675,24 @@ var EthersFundingVerifier = class {
2755
3675
  };
2756
3676
 
2757
3677
  // src/Invisi.ts
2758
- var import_core14 = require("@invisi-labs/core");
3678
+ var import_core19 = require("@invisi-labs/core");
3679
+
3680
+ // src/AddressRegistry.ts
3681
+ var import_protocol7 = require("@invisi-labs/protocol");
3682
+ var AddressRegistry = class extends import_protocol7.AddressRegistry {
3683
+ prepareRegistration(options) {
3684
+ return prepareWithErrors("prepareRegistration", async () => {
3685
+ if ("provider" in options) {
3686
+ const { provider, ...preparation } = options;
3687
+ return super.prepareRegistration({
3688
+ ...preparation,
3689
+ reader: new EthersChainReader(provider)
3690
+ });
3691
+ }
3692
+ return super.prepareRegistration(options);
3693
+ });
3694
+ }
3695
+ };
2759
3696
 
2760
3697
  // src/session/codec.ts
2761
3698
  function encode(value) {
@@ -2801,8 +3738,8 @@ function deserializeState(data) {
2801
3738
 
2802
3739
  // src/session/protocol-events.ts
2803
3740
  var import_contracts2 = require("@invisi-labs/protocol/contracts");
2804
- var import_ethers8 = require("ethers");
2805
- var protocolInterface = new import_ethers8.Interface(import_contracts2.invisiProtocolAbi);
3741
+ var import_ethers9 = require("ethers");
3742
+ var protocolInterface = new import_ethers9.Interface(import_contracts2.invisiProtocolAbi);
2806
3743
  function decodeProtocolEvent(log) {
2807
3744
  const decoded = protocolInterface.parseLog(log);
2808
3745
  if (!decoded) throw new Error("Unknown protocol receipt event");
@@ -2865,9 +3802,10 @@ function readProtocolLogs(receipt, protocolAddress) {
2865
3802
  }
2866
3803
 
2867
3804
  // src/session/discovery.ts
2868
- var import_ethers9 = require("ethers");
2869
- var import_core7 = require("@invisi-labs/core");
2870
- var import_protocol6 = require("@invisi-labs/protocol");
3805
+ var import_core10 = require("@invisi-labs/core");
3806
+ var import_ethers10 = require("ethers");
3807
+ var import_core11 = require("@invisi-labs/core");
3808
+ var import_protocol8 = require("@invisi-labs/protocol");
2871
3809
  var EVENTS = /* @__PURE__ */ new Set([
2872
3810
  "CommitmentsInserted",
2873
3811
  "BatchOutputs",
@@ -2915,7 +3853,7 @@ function hash(value) {
2915
3853
  function contextCheck(context) {
2916
3854
  check4(context.chainId >= 0n && context.chainId < 1n << 64n, "invalid discovery chain");
2917
3855
  check4(
2918
- (0, import_ethers9.isAddress)(context.protocolAddress) && BigInt(context.protocolAddress) !== 0n,
3856
+ (0, import_ethers10.isAddress)(context.protocolAddress) && BigInt(context.protocolAddress) !== 0n,
2919
3857
  "invalid discovery instance/token"
2920
3858
  );
2921
3859
  }
@@ -2960,9 +3898,9 @@ function extractDeliveryCandidates(logs, context, confirmedThrough) {
2960
3898
  check4(inserted, "delivery has no matching canonical insertion");
2961
3899
  if (commitment !== void 0)
2962
3900
  check4(hash(commitment) === inserted, "delivery commitment conflicts with insertion");
2963
- const delivery = (0, import_protocol6.normalizeDelivery)(wire, { credit: role !== "funds" });
3901
+ const delivery = (0, import_protocol8.normalizeOpaqueDelivery)(wire);
2964
3902
  check4(
2965
- typeof token === "string" && (0, import_ethers9.isAddress)(token) && BigInt(token) !== 0n,
3903
+ typeof token === "string" && (0, import_ethers10.isAddress)(token) && BigInt(token) !== 0n,
2966
3904
  "invalid event token"
2967
3905
  );
2968
3906
  const value = {
@@ -2991,7 +3929,7 @@ function extractDeliveryCandidates(logs, context, confirmedThrough) {
2991
3929
  add(log, tree, index(leaves[0]), fields.creditCommitment, "owner", ds[0]);
2992
3930
  add(log, tree, index(leaves[0]), fields.creditCommitment, "spender", ds[1]);
2993
3931
  if (hasChange) add(log, tree, index(leaves[1]), change, "funds", ds[2]);
2994
- else (0, import_protocol6.normalizeDelivery)(ds[2], { empty: true });
3932
+ else (0, import_protocol8.normalizeOpaqueDelivery)(ds[2], { empty: true });
2995
3933
  };
2996
3934
  for (const log of relevant) {
2997
3935
  const a = object(log.args);
@@ -3021,7 +3959,7 @@ function extractDeliveryCandidates(logs, context, confirmedThrough) {
3021
3959
  const length = Number.parseInt(packed.slice(offset, offset + 4), 16);
3022
3960
  offset += 4;
3023
3961
  check4(
3024
- length >= 160 && length <= 416 && offset + length * 2 + 136 <= packed.length,
3962
+ length >= 1 && length <= import_core10.MAX_CIPHERTEXT_BYTES && offset + length * 2 + 136 <= packed.length,
3025
3963
  "invalid packed delivery length"
3026
3964
  );
3027
3965
  const ciphertext = `0x${packed.slice(offset, offset + length * 2)}`;
@@ -3043,8 +3981,8 @@ function extractDeliveryCandidates(logs, context, confirmedThrough) {
3043
3981
  cs.forEach((c, i) => {
3044
3982
  if (BigInt(hash(c)) === 0n) {
3045
3983
  check4(integer(leaves[i]) === 0n, "absent remainder has nonzero position");
3046
- (0, import_protocol6.normalizeDelivery)(ds[2 * i], { empty: true });
3047
- (0, import_protocol6.normalizeDelivery)(ds[2 * i + 1], { empty: true });
3984
+ (0, import_protocol8.normalizeOpaqueDelivery)(ds[2 * i], { empty: true });
3985
+ (0, import_protocol8.normalizeOpaqueDelivery)(ds[2 * i + 1], { empty: true });
3048
3986
  } else {
3049
3987
  add(log, tree, index(leaves[i]), c, "owner", ds[2 * i]);
3050
3988
  add(log, tree, index(leaves[i]), c, "spender", ds[2 * i + 1]);
@@ -3056,7 +3994,7 @@ function extractDeliveryCandidates(logs, context, confirmedThrough) {
3056
3994
  }
3057
3995
  async function decryptCandidates(logs, options) {
3058
3996
  contextCheck(options.context);
3059
- (0, import_core7.decodeAddress)(import_core7.ReceivingAddress.fromIdentity(options.viewing.walletIdentity).toString());
3997
+ (0, import_core11.decodeAddress)(import_core11.ReceivingAddress.fromIdentity(options.viewing.walletIdentity).toString());
3060
3998
  check4(
3061
3999
  !logs.some(
3062
4000
  (log) => log.address.toLowerCase() === options.context.protocolAddress.toLowerCase() && log.removed
@@ -3344,7 +4282,7 @@ function mergeReceiptRecords(state, batch) {
3344
4282
  }
3345
4283
 
3346
4284
  // src/session/store.ts
3347
- var import_core8 = require("@invisi-labs/core");
4285
+ var import_core12 = require("@invisi-labs/core");
3348
4286
  var import_sha2562 = require("@noble/hashes/sha256");
3349
4287
  var import_utils2 = require("@noble/hashes/utils");
3350
4288
  function scopeKey(scope) {
@@ -3360,7 +4298,7 @@ function scopeKey(scope) {
3360
4298
  return (0, import_utils2.bytesToHex)(
3361
4299
  (0, import_sha2562.sha256)(
3362
4300
  (0, import_utils2.utf8ToBytes)(
3363
- "Invisi.WalletScope.v2:" + JSON.stringify([
4301
+ "Invisi.WalletScope.v1:" + JSON.stringify([
3364
4302
  scope.namespace,
3365
4303
  scope.chainId.toString(),
3366
4304
  scope.protocolAddress.toLowerCase(),
@@ -3397,12 +4335,12 @@ function validateState(state, scope, revision) {
3397
4335
  throw new Error("invalid spent state");
3398
4336
  }
3399
4337
  for (const record of Object.values(state.credits)) {
3400
- const note = (0, import_core8.normalizeCreditDeliveryState)(record.state).note;
4338
+ const note = (0, import_core12.normalizeCreditDeliveryState)(record.state).note;
3401
4339
  if (note.chainId !== scope.chainId || note.protocolAddress !== BigInt(scope.protocolAddress) || !["owner", "spender"].includes(record.role) || (record.role === "owner" ? note.ownerWalletIdentity : note.spenderWalletIdentity).toLowerCase() !== scope.walletIdentity.toLowerCase() || !["unspent", "unknown", "spent"].includes(record.spent))
3402
4340
  throw new Error("invalid stored Credit context or role");
3403
4341
  }
3404
4342
  for (const record of [...Object.values(state.notes), ...Object.values(state.credits)]) {
3405
- if (!/^0x[0-9a-fA-F]{64}$/.test(record.commitment) || BigInt(record.commitment) <= 0n || BigInt(record.commitment) >= import_core8.FIELD_MODULUS || typeof record.treeId !== "bigint" || record.treeId < 1n || record.treeId >= 1n << 64n || !Number.isInteger(record.leafIndex) || record.leafIndex < 0 || record.leafIndex >= 65536 || typeof record.blockNumber !== "bigint" || record.blockNumber < 0n || !/^0x[0-9a-fA-F]{64}$/.test(record.blockHash))
4343
+ if (!/^0x[0-9a-fA-F]{64}$/.test(record.commitment) || BigInt(record.commitment) <= 0n || BigInt(record.commitment) >= import_core12.FIELD_MODULUS || typeof record.treeId !== "bigint" || record.treeId < 1n || record.treeId >= 1n << 64n || !Number.isInteger(record.leafIndex) || record.leafIndex < 0 || record.leafIndex >= 65536 || typeof record.blockNumber !== "bigint" || record.blockNumber < 0n || !/^0x[0-9a-fA-F]{64}$/.test(record.blockHash))
3406
4344
  throw new Error("invalid stored receipt position");
3407
4345
  }
3408
4346
  for (const [id, operation] of Object.entries(state.reservations))
@@ -3463,16 +4401,16 @@ var TransactionalWalletStore = class {
3463
4401
  };
3464
4402
 
3465
4403
  // src/session/Operation.ts
3466
- var import_core10 = require("@invisi-labs/core");
3467
- var import_protocol8 = require("@invisi-labs/protocol");
4404
+ var import_core14 = require("@invisi-labs/core");
4405
+ var import_protocol10 = require("@invisi-labs/protocol");
3468
4406
 
3469
4407
  // src/session/operation-confirmation.ts
3470
- var import_core9 = require("@invisi-labs/core");
4408
+ var import_core13 = require("@invisi-labs/core");
3471
4409
 
3472
4410
  // src/session/aggregate-receipt.ts
3473
- var import_ethers11 = require("ethers");
4411
+ var import_ethers12 = require("ethers");
3474
4412
  var import_contracts3 = require("@invisi-labs/protocol/contracts");
3475
- var import_protocol7 = require("@invisi-labs/protocol");
4413
+ var import_protocol9 = require("@invisi-labs/protocol");
3476
4414
  var aggregateAbi = import_contracts3.invisiProtocolAbi.filter(
3477
4415
  (item) => item.type === "function" && item.name === "transact" && item.inputs.length === 2 && item.inputs[1]?.type === "tuple[]"
3478
4416
  );
@@ -3481,7 +4419,7 @@ function matchesAggregateTransaction(saved, transaction) {
3481
4419
  if (plan.statement?.target !== "noir-recursive" || !plan.params || !saved.externalized || transaction.to.toLowerCase() !== plan.context.protocolAddress.toLowerCase() || transaction.value !== 0n)
3482
4420
  return false;
3483
4421
  try {
3484
- const decoded = new import_ethers11.Interface(aggregateAbi).parseTransaction({ data: transaction.data }), requests = decoded.args[1].map((request) => {
4422
+ const decoded = new import_ethers12.Interface(aggregateAbi).parseTransaction({ data: transaction.data }), requests = decoded.args[1].map((request) => {
3485
4423
  const member = request.toObject(true);
3486
4424
  member.params.sources = request.params.sources.map(
3487
4425
  (source) => source.toObject(true)
@@ -3500,7 +4438,7 @@ function matchesAggregateTransaction(saved, transaction) {
3500
4438
  });
3501
4439
  if (decoded.name !== "transact" || !Array.isArray(requests) || ![4, 8, 12].includes(requests.length))
3502
4440
  return false;
3503
- const canonical2 = (request) => (0, import_protocol7.buildTransactCalldata)({
4441
+ const canonical2 = (request) => (0, import_protocol9.buildTransactCalldata)({
3504
4442
  context: { ...plan.context, tokenAddress: request.params.token },
3505
4443
  proof: "0x00",
3506
4444
  params: request.params,
@@ -3508,7 +4446,7 @@ function matchesAggregateTransaction(saved, transaction) {
3508
4446
  funding: request.funding,
3509
4447
  caller: transaction.from
3510
4448
  }).data.toLowerCase();
3511
- const expected = (0, import_protocol7.buildTransactCalldata)({
4449
+ const expected = (0, import_protocol9.buildTransactCalldata)({
3512
4450
  context: plan.context,
3513
4451
  proof: "0x00",
3514
4452
  params: plan.params,
@@ -3687,7 +4625,7 @@ async function confirmOperation(runtime, id, generation, hash2, signal) {
3687
4625
  if (credits.length) {
3688
4626
  const nullifiers = await Promise.all(
3689
4627
  credits.map(
3690
- async (record) => (0, import_core9.computeCreditNullifier)(
4628
+ async (record) => (0, import_core13.computeCreditNullifier)(
3691
4629
  plan.context.chainId,
3692
4630
  record.state.note.creditSharedKey,
3693
4631
  await creditLeaf(record.state)
@@ -3988,6 +4926,81 @@ var Operation = class _Operation {
3988
4926
  throw error;
3989
4927
  }
3990
4928
  }
4929
+ async signingCurrent() {
4930
+ await this.#runtime.store.transaction(this.#runtime.scope, (state) => {
4931
+ check7(!state.invalidated, "wallet state requires canonical resync");
4932
+ this.current(state.operations[this.id]);
4933
+ });
4934
+ }
4935
+ /** Public EIP-712 request; signing transport and key custody belong to the caller. */
4936
+ async exportWalletAuthorization(options = {}) {
4937
+ options.signal?.throwIfAborted();
4938
+ await this.signingCurrent();
4939
+ check7(
4940
+ requiresAuthorization(this.#saved.plan),
4941
+ "operation does not require wallet authorization"
4942
+ );
4943
+ check7(
4944
+ ["prepared", "authorized"].includes(this.status),
4945
+ "operation is not awaiting wallet authorization"
4946
+ );
4947
+ return walletSigningRequest(this.#saved.plan);
4948
+ }
4949
+ /** Attach an external EOA signature, retaining its witness only at the private proving boundary. */
4950
+ async withWalletSignature(signature, options = {}) {
4951
+ options.signal?.throwIfAborted();
4952
+ await this.signingCurrent();
4953
+ check7(
4954
+ requiresAuthorization(this.#saved.plan),
4955
+ "operation does not require wallet authorization"
4956
+ );
4957
+ check7(
4958
+ ["prepared", "authorized"].includes(this.status),
4959
+ "operation is not awaiting wallet authorization"
4960
+ );
4961
+ const authorization = await acceptWalletSignature(this.#saved.plan, signature);
4962
+ return this.stage(
4963
+ "wallet authorization",
4964
+ ["prepared", "authorized"],
4965
+ async () => ({ status: "authorized", authorization }),
4966
+ options.signal
4967
+ );
4968
+ }
4969
+ /** Export only after proving when the funding authorization binds an actual proof hash. */
4970
+ async exportFundingAuthorization(options = {}) {
4971
+ options.signal?.throwIfAborted();
4972
+ await this.signingCurrent();
4973
+ check7(
4974
+ this.status === (this.kind === "shield" ? "prepared" : "proved"),
4975
+ "operation is not awaiting funding authorization or proof"
4976
+ );
4977
+ const request = await fundingSigningRequest(this.#saved, this.#runtime);
4978
+ options.signal?.throwIfAborted();
4979
+ await this.signingCurrent();
4980
+ return request;
4981
+ }
4982
+ /** Verify an external signature against this handle's own frozen operation. */
4983
+ async withFundingSignature(signature, options = {}) {
4984
+ options.signal?.throwIfAborted();
4985
+ await this.signingCurrent();
4986
+ check7(
4987
+ this.status === (this.kind === "shield" ? "prepared" : "proved"),
4988
+ "operation is not awaiting funding authorization or proof"
4989
+ );
4990
+ const verified = await acceptFundingSignature(this.#saved, signature, this.#runtime);
4991
+ return this.stage(
4992
+ "funding authorization",
4993
+ this.kind === "shield" ? ["prepared"] : ["proved"],
4994
+ async (saved) => {
4995
+ saved.plan.funding.signature = verified;
4996
+ if (saved.plan.statement?.target !== "noir-recursive") {
4997
+ saved.call = await this.encode(saved);
4998
+ }
4999
+ return { status: "ready" };
5000
+ },
5001
+ options.signal
5002
+ );
5003
+ }
3991
5004
  async authorize(options = {}) {
3992
5005
  check7(
3993
5006
  requiresAuthorization(this.#saved.plan),
@@ -4008,7 +5021,8 @@ var Operation = class _Operation {
4008
5021
  options.signal
4009
5022
  );
4010
5023
  }
4011
- async prove(options = {}) {
5024
+ async prove(suppliedOptions = {}) {
5025
+ const options = { ...suppliedOptions };
4012
5026
  const plan = this.#saved.plan;
4013
5027
  check7(plan.kind !== "shield", "shield requires no proof");
4014
5028
  if (requiresAuthorization(plan)) {
@@ -4019,7 +5033,7 @@ var Operation = class _Operation {
4019
5033
  }
4020
5034
  const prover = this.#runtime.options.prover;
4021
5035
  if (!prover) {
4022
- throw new import_core10.MissingCapabilityError("prover");
5036
+ throw new import_core14.MissingCapabilityError("prover");
4023
5037
  }
4024
5038
  return this.stage(
4025
5039
  "proof",
@@ -4053,7 +5067,7 @@ var Operation = class _Operation {
4053
5067
  check7(p.kind === "shield" || this.#saved.proof, "proof must precede funding authorization");
4054
5068
  const signer = this.#runtime.options.fundingSigner;
4055
5069
  if (!signer) {
4056
- throw new import_core10.MissingCapabilityError("EVM funding signer");
5070
+ throw new import_core14.MissingCapabilityError("EVM funding signer");
4057
5071
  }
4058
5072
  check7(
4059
5073
  signer.address.toLowerCase() === p.funding.payer.toLowerCase(),
@@ -4155,7 +5169,7 @@ var Operation = class _Operation {
4155
5169
  request: {
4156
5170
  params: structuredClone(plan.params),
4157
5171
  deliveries: plan.outputs.map((output) => structuredClone(output.delivery)),
4158
- funding: (0, import_protocol8.normalizeFunding)(plan.funding)
5172
+ funding: (0, import_protocol10.normalizeFunding)(plan.funding)
4159
5173
  }
4160
5174
  };
4161
5175
  });
@@ -4243,8 +5257,66 @@ var Operation = class _Operation {
4243
5257
  };
4244
5258
 
4245
5259
  // src/session/WalletSession.ts
4246
- var import_ethers12 = require("ethers");
4247
- var import_core13 = require("@invisi-labs/core");
5260
+ var import_core17 = require("@invisi-labs/core");
5261
+
5262
+ // src/session/history.ts
5263
+ function walletHistory(state, options = {}) {
5264
+ const token = options.tokenAddress?.toLowerCase();
5265
+ const outgoing = [];
5266
+ for (const record of Object.values(state.operations)) {
5267
+ const saved = record.payload;
5268
+ if (!saved?.plan || token && saved.plan.context.tokenAddress.toLowerCase() !== token) {
5269
+ continue;
5270
+ }
5271
+ const plan = saved.plan;
5272
+ outgoing.push({
5273
+ ...operationPreview(plan, record.status),
5274
+ preparedAt: { ...plan.preparedAt },
5275
+ ...record.transactionHash ? { transactionHash: record.transactionHash } : {},
5276
+ outputs: plan.outputs.map((output) => ({
5277
+ to: output.address,
5278
+ amount: output.note.amount,
5279
+ change: output.change,
5280
+ commitment: output.commitment,
5281
+ payload: Uint8Array.from(output.note.payload ?? [])
5282
+ }))
5283
+ });
5284
+ }
5285
+ outgoing.sort(
5286
+ (a, b) => a.preparedAt.number === b.preparedAt.number ? a.id.localeCompare(b.id) : a.preparedAt.number > b.preparedAt.number ? -1 : 1
5287
+ );
5288
+ const incoming = [];
5289
+ for (const record of Object.values(state.notes)) {
5290
+ const tokenAddress = `0x${record.note.tokenAddress.toString(16).padStart(40, "0")}`;
5291
+ if (token && tokenAddress !== token) continue;
5292
+ incoming.push({
5293
+ commitment: record.commitment,
5294
+ treeId: record.treeId,
5295
+ leafIndex: record.leafIndex,
5296
+ blockNumber: record.blockNumber,
5297
+ blockHash: record.blockHash,
5298
+ ...record.transactionHash ? { transactionHash: record.transactionHash } : {},
5299
+ tokenAddress,
5300
+ amount: record.note.amount,
5301
+ payload: Uint8Array.from(record.note.payload ?? []),
5302
+ spent: record.spent
5303
+ });
5304
+ }
5305
+ incoming.sort(
5306
+ (a, b) => a.blockNumber === b.blockNumber ? a.commitment.localeCompare(b.commitment) : a.blockNumber > b.blockNumber ? -1 : 1
5307
+ );
5308
+ return structuredClone({
5309
+ revision: state.revision,
5310
+ checkedThrough: state.discoveryThrough ?? null,
5311
+ invalidated: !!state.invalidated,
5312
+ outgoing,
5313
+ incoming
5314
+ });
5315
+ }
5316
+
5317
+ // src/session/WalletSession.ts
5318
+ var import_ethers13 = require("ethers");
5319
+ var import_core18 = require("@invisi-labs/core");
4248
5320
 
4249
5321
  // src/session/refresh.ts
4250
5322
  async function refreshWallet(runtime, options) {
@@ -4301,10 +5373,10 @@ async function refreshWallet(runtime, options) {
4301
5373
  }
4302
5374
 
4303
5375
  // src/session/WalletUpdater.ts
4304
- var import_core12 = require("@invisi-labs/core");
5376
+ var import_core16 = require("@invisi-labs/core");
4305
5377
 
4306
5378
  // src/session/inventory.ts
4307
- var import_core11 = require("@invisi-labs/core");
5379
+ var import_core15 = require("@invisi-labs/core");
4308
5380
  var CanonicalConflict = class extends Error {
4309
5381
  };
4310
5382
  var CreditMetadataMismatch = class extends Error {
@@ -4356,10 +5428,10 @@ var InventoryProcessor = class {
4356
5428
  }
4357
5429
  async creditNullifier(state) {
4358
5430
  const n = state.note;
4359
- return (0, import_core11.computeCreditNullifier)(
5431
+ return (0, import_core15.computeCreditNullifier)(
4360
5432
  n.chainId,
4361
5433
  n.creditSharedKey,
4362
- await (0, import_core11.computeCreditCommitment)(
5434
+ await (0, import_core15.computeCreditCommitment)(
4363
5435
  n.chainId,
4364
5436
  n.spenderWalletIdentity,
4365
5437
  n.ownerWalletIdentity,
@@ -4369,7 +5441,8 @@ var InventoryProcessor = class {
4369
5441
  n.amount,
4370
5442
  n.nonce,
4371
5443
  n.expiry,
4372
- await (0, import_core11.computeCreditSharedKeyHash)(n.creditSharedKey)
5444
+ await (0, import_core15.computeCreditSharedKeyHash)(n.creditSharedKey),
5445
+ n
4373
5446
  )
4374
5447
  );
4375
5448
  }
@@ -4416,6 +5489,9 @@ var InventoryProcessor = class {
4416
5489
  };
4417
5490
  for (const event of logs) {
4418
5491
  if (event.eventName === "CreditDraw") {
5492
+ const block = await this.#options.reader.getBlock(event.blockNumber);
5493
+ if (block.hash !== event.blockHash)
5494
+ throw new CanonicalConflict("draw block changed during Credit recovery");
4419
5495
  const args = event.args;
4420
5496
  const params = args.params;
4421
5497
  const indices = args.remainderLeafIndices;
@@ -4429,10 +5505,11 @@ var InventoryProcessor = class {
4429
5505
  previous.state.note.expiry === params.expiries[index2],
4430
5506
  "draw recovery expiry mismatch"
4431
5507
  );
4432
- const remainder = await (0, import_core11.recoverCreditRemainder)(
5508
+ const remainder = await (0, import_core15.recoverCreditRemainder)(
4433
5509
  context,
4434
5510
  previous.state.note,
4435
5511
  {
5512
+ timestamp: block.timestamp,
4436
5513
  creditNullifier: nullifier,
4437
5514
  remainderCommitment: params.remainderCommitments[index2],
4438
5515
  recoveryAmount: BigInt(params.recoveryAmounts[index2])
@@ -4444,7 +5521,7 @@ var InventoryProcessor = class {
4444
5521
  const child = foundByKey.get(
4445
5522
  params.remainderCommitments[index2] + ":" + previous.role
4446
5523
  );
4447
- const memo = child?.state.note.memo;
5524
+ const payload = child?.state.note.payload;
4448
5525
  const record = {
4449
5526
  commitment: params.remainderCommitments[index2],
4450
5527
  treeId: BigInt(args.outputTreeId),
@@ -4457,7 +5534,7 @@ var InventoryProcessor = class {
4457
5534
  ...clone(previous.state),
4458
5535
  note: {
4459
5536
  ...remainder,
4460
- ...memo === void 0 ? {} : { memo: (0, import_core11.encodeMemo)(memo) }
5537
+ ...payload === void 0 ? {} : { payload: clone(payload) }
4461
5538
  }
4462
5539
  },
4463
5540
  receivingKeySource: { kind: "draw", commitment: previous.commitment },
@@ -4536,7 +5613,7 @@ var WalletUpdater = class extends InventoryProcessor {
4536
5613
  }
4537
5614
  async run(batch, options) {
4538
5615
  const { reader, protocol, scope, store, viewing } = this.#options;
4539
- const nullifier = import_core12.NullifierCapability.fromIdentity(scope.walletIdentity);
5616
+ const nullifier = import_core16.NullifierCapability.fromIdentity(scope.walletIdentity);
4540
5617
  const { signal, reset } = options;
4541
5618
  signal?.throwIfAborted();
4542
5619
  const context = protocol.context;
@@ -4705,6 +5782,7 @@ var WalletUpdater = class extends InventoryProcessor {
4705
5782
  draft.notes = {};
4706
5783
  draft.credits = {};
4707
5784
  delete draft.observedThrough;
5785
+ delete draft.discoveryThrough;
4708
5786
  delete draft.invalidated;
4709
5787
  }
4710
5788
  mergeReceiptRecords(draft, { notes, credits, checkpoint: block });
@@ -4736,13 +5814,38 @@ var WalletUpdater = class extends InventoryProcessor {
4736
5814
  var WalletSession = class {
4737
5815
  #options;
4738
5816
  #updater;
5817
+ #listeners = /* @__PURE__ */ new Set();
4739
5818
  #sending = /* @__PURE__ */ new Set();
4740
5819
  #refreshQueue = Promise.resolve();
4741
5820
  scope;
4742
5821
  protocol;
4743
5822
  constructor(options) {
5823
+ if ("ciphertextCodecs" in options || "envelopeVersion" in options) {
5824
+ throw new Error(
5825
+ "SDK envelope versions are fixed; encode application payload bytes externally"
5826
+ );
5827
+ }
5828
+ const store = options.store;
4744
5829
  this.#options = {
4745
5830
  ...options,
5831
+ ...store ? {
5832
+ store: {
5833
+ persistent: store.persistent,
5834
+ readSnapshot: (scope) => store.readSnapshot(scope),
5835
+ transaction: async (scope, action) => {
5836
+ const result = await store.transaction(scope, action);
5837
+ if (scopeKey(scope) === scopeKey(this.scope)) {
5838
+ for (const listener of [...this.#listeners]) {
5839
+ try {
5840
+ listener();
5841
+ } catch {
5842
+ }
5843
+ }
5844
+ }
5845
+ return result;
5846
+ }
5847
+ }
5848
+ } : {},
4746
5849
  ...options.gasBenchmarks ? { gasBenchmarks: copyGasBenchmarks(options.gasBenchmarks) } : {}
4747
5850
  };
4748
5851
  this.protocol = options.protocol;
@@ -4757,7 +5860,7 @@ var WalletSession = class {
4757
5860
  /** Delegate sending to ethers; managed operations additionally retain the resulting hash. */
4758
5861
  async sendTransaction(input, options = {}) {
4759
5862
  const signer = this.#options.signer;
4760
- if (!signer) throw new import_core13.MissingCapabilityError("ethers signer");
5863
+ if (!signer) throw new import_core18.MissingCapabilityError("ethers signer");
4761
5864
  const operation = input instanceof Operation ? input : void 0;
4762
5865
  if (operation && this.#sending.has(operation.id))
4763
5866
  throw new Error("operation is already being sent by this session");
@@ -4765,12 +5868,12 @@ var WalletSession = class {
4765
5868
  const overrides = { ...options };
4766
5869
  const plain = operation ? void 0 : { ...input };
4767
5870
  try {
4768
- if (!signer.provider) throw new import_core13.MissingCapabilityError("connected ethers signer");
5871
+ if (!signer.provider) throw new import_core18.MissingCapabilityError("connected ethers signer");
4769
5872
  if ((await signer.provider.getNetwork()).chainId !== this.protocol.context.chainId) {
4770
5873
  throw new Error("signer-provider session chain mismatch");
4771
5874
  }
4772
5875
  if (operation) {
4773
- if (!this.#options.store) throw new import_core13.MissingCapabilityError("wallet store");
5876
+ if (!this.#options.store) throw new import_core18.MissingCapabilityError("wallet store");
4774
5877
  const state = await this.#options.store.readSnapshot(this.scope);
4775
5878
  if (!state.operations[operation.id])
4776
5879
  throw new Error("operation does not belong to this wallet session");
@@ -4801,25 +5904,30 @@ var WalletSession = class {
4801
5904
  runtime(tokenAddress) {
4802
5905
  const options = this.#options;
4803
5906
  if (!options.store) {
4804
- throw new import_core13.MissingCapabilityError("wallet store");
5907
+ throw new import_core18.MissingCapabilityError("wallet store");
4805
5908
  }
4806
5909
  if (!options.chainReader) {
4807
- throw new import_core13.MissingCapabilityError("chain reader");
5910
+ throw new import_core18.MissingCapabilityError("chain reader");
4808
5911
  }
4809
5912
  return {
4810
5913
  options: { ...options, protocol: options.protocol.forToken(tokenAddress) },
4811
5914
  scope: this.scope,
4812
5915
  store: options.store,
4813
5916
  reader: options.chainReader,
4814
- authorization: () => options.authorization ?? options.wallet.exportAuthorization()
5917
+ authorization: () => {
5918
+ if (options.authorization) return options.authorization;
5919
+ if (options.wallet instanceof import_core17.Wallet) return options.wallet.exportAuthorization();
5920
+ throw new import_core18.MissingCapabilityError("wallet authorization");
5921
+ }
4815
5922
  };
4816
5923
  }
4817
5924
  updater() {
4818
5925
  if (this.#updater) return this.#updater;
4819
5926
  const options = this.#options;
4820
5927
  if (!options.store || !options.chainReader || !options.protocolRpc)
4821
- throw new import_core13.MissingCapabilityError("wallet store, chain reader and Protocol RPC");
4822
- const viewing = options.viewing ?? options.wallet.getViewer();
5928
+ throw new import_core18.MissingCapabilityError("wallet store, chain reader and Protocol RPC");
5929
+ const viewing = options.viewing ?? (options.wallet instanceof import_core17.Wallet ? options.wallet.getViewer() : void 0);
5930
+ if (!viewing) throw new import_core18.MissingCapabilityError("viewing");
4823
5931
  const receivingAddress = options.wallet.getReceivingAddress();
4824
5932
  const receivingKeys = receivingAddress.kind === "long" ? receivingAddress.getReceivingKeys() : void 0;
4825
5933
  this.#updater = new WalletUpdater({
@@ -4833,26 +5941,43 @@ var WalletSession = class {
4833
5941
  });
4834
5942
  return this.#updater;
4835
5943
  }
5944
+ /** Local session commits only. Host applications own cross-tab/store subscriptions. */
5945
+ subscribe(listener) {
5946
+ this.#listeners.add(listener);
5947
+ return () => {
5948
+ this.#listeners.delete(listener);
5949
+ };
5950
+ }
5951
+ /** Detached history for wallet UI; construction records do not imply chain success. */
5952
+ async getHistory(options = {}) {
5953
+ const tokenAddress = options.tokenAddress ? (0, import_ethers13.getAddress)(options.tokenAddress) : void 0;
5954
+ const store = this.#options.store;
5955
+ if (!store) throw new import_core18.MissingCapabilityError("wallet store");
5956
+ return walletHistory(
5957
+ await store.readSnapshot(this.scope),
5958
+ tokenAddress ? { tokenAddress } : {}
5959
+ );
5960
+ }
4836
5961
  async balance(tokenAddress) {
4837
5962
  const store = this.#options.store;
4838
5963
  if (!store) {
4839
- throw new import_core13.MissingCapabilityError("wallet store");
5964
+ throw new import_core18.MissingCapabilityError("wallet store");
4840
5965
  }
4841
- return walletBalance(await store.readSnapshot(this.scope), (0, import_ethers12.getAddress)(tokenAddress));
5966
+ return walletBalance(await store.readSnapshot(this.scope), (0, import_ethers13.getAddress)(tokenAddress));
4842
5967
  }
4843
5968
  /** Pull explicitly selected indexed pages; no chain scanning or public tree reconstruction. */
4844
5969
  async refresh(options) {
4845
5970
  const provider = this.#options.protocolRpc;
4846
5971
  const reader = this.#options.chainReader;
4847
- if (!reader) throw new import_core13.MissingCapabilityError("chain reader");
4848
- if (!provider) throw new import_core13.MissingCapabilityError("Protocol RPC");
5972
+ if (!reader) throw new import_core18.MissingCapabilityError("chain reader");
5973
+ if (!provider) throw new import_core18.MissingCapabilityError("Protocol RPC");
4849
5974
  const updater = this.updater();
4850
5975
  const request = {
4851
5976
  ...options,
4852
5977
  ...options.detectionKey ? { detectionKey: options.detectionKey.slice() } : {}
4853
5978
  };
4854
- const task = this.#refreshQueue.then(
4855
- () => refreshWallet(
5979
+ const task = this.#refreshQueue.then(async () => {
5980
+ const result = await refreshWallet(
4856
5981
  {
4857
5982
  provider,
4858
5983
  reader,
@@ -4861,8 +5986,21 @@ var WalletSession = class {
4861
5986
  apply: (batch, settings) => updater.applyUpdates(batch, settings)
4862
5987
  },
4863
5988
  request
4864
- )
4865
- );
5989
+ );
5990
+ await this.#options.store.transaction(this.scope, (state) => {
5991
+ request.signal?.throwIfAborted();
5992
+ if (state.invalidated) throw new Error("wallet requires canonical resync");
5993
+ const previous = state.discoveryThrough;
5994
+ const start = previous ? previous.number + 1n : this.protocol.deployment.protocol.fromBlock;
5995
+ if (request.fromBlock <= start && (!previous || result.block.number >= previous.number)) {
5996
+ state.discoveryThrough = {
5997
+ number: result.block.number,
5998
+ hash: result.block.hash
5999
+ };
6000
+ }
6001
+ });
6002
+ return result;
6003
+ });
4866
6004
  this.#refreshQueue = task.catch(() => {
4867
6005
  });
4868
6006
  return task;
@@ -4873,38 +6011,43 @@ var WalletSession = class {
4873
6011
  options: runtime.options,
4874
6012
  scope: runtime.scope,
4875
6013
  reader: runtime.reader,
4876
- authorization: runtime.authorization,
4877
6014
  readInventory: () => runtime.store.readSnapshot(runtime.scope),
4878
6015
  complete: (plan) => Operation.prepare(runtime, plan)
4879
6016
  });
4880
6017
  }
4881
6018
  async prepareTransfer(options) {
4882
- return this.preparation(options.tokenAddress).prepareTransfer(options);
4883
- }
4884
- async prepareWithdraw(options) {
4885
- return this.preparation(options.tokenAddress).prepareWithdraw(options);
4886
- }
4887
- async prepareSweep(options) {
4888
- return this.preparation(options.tokenAddress).prepareSweep(options);
6019
+ return prepareWithErrors("prepareTransfer", async () => {
6020
+ return this.preparation(options.tokenAddress).prepareTransfer(options);
6021
+ });
4889
6022
  }
4890
6023
  async prepareShield(options) {
4891
- return this.preparation(options.tokenAddress).prepareShield(options);
6024
+ return prepareWithErrors("prepareShield", async () => {
6025
+ return this.preparation(options.tokenAddress).prepareShield(options);
6026
+ });
4892
6027
  }
4893
6028
  async prepareCreateCredit(options) {
4894
- return this.preparation(options.tokenAddress).prepareCreateCredit(options);
6029
+ return prepareWithErrors("prepareCreateCredit", async () => {
6030
+ return this.preparation(options.tokenAddress).prepareCreateCredit(options);
6031
+ });
4895
6032
  }
4896
6033
  async prepareDrawCredit(options) {
4897
- return this.preparation(options.tokenAddress).prepareDrawCredit(options);
6034
+ return prepareWithErrors("prepareDrawCredit", async () => {
6035
+ return this.preparation(options.tokenAddress).prepareDrawCredit(options);
6036
+ });
4898
6037
  }
4899
6038
  async prepareTopUpCredit(options) {
4900
- return this.preparation(options.tokenAddress).prepareTopUpCredit(options);
6039
+ return prepareWithErrors("prepareTopUpCredit", async () => {
6040
+ return this.preparation(options.tokenAddress).prepareTopUpCredit(options);
6041
+ });
4901
6042
  }
4902
6043
  async prepareCancelCredit(options) {
4903
- return this.preparation(options.tokenAddress).prepareCancelCredit(options);
6044
+ return prepareWithErrors("prepareCancelCredit", async () => {
6045
+ return this.preparation(options.tokenAddress).prepareCancelCredit(options);
6046
+ });
4904
6047
  }
4905
6048
  async resume(operationId) {
4906
6049
  const store = this.#options.store;
4907
- if (!store) throw new import_core13.MissingCapabilityError("wallet store");
6050
+ if (!store) throw new import_core18.MissingCapabilityError("wallet store");
4908
6051
  const state = await store.readSnapshot(this.scope);
4909
6052
  const saved = state.operations[operationId]?.payload;
4910
6053
  if (!saved?.plan) throw new Error("operation not found");
@@ -4922,6 +6065,16 @@ var WalletSession = class {
4922
6065
  var Invisi = class {
4923
6066
  #options;
4924
6067
  constructor(options = {}) {
6068
+ if ("ciphertextCodecs" in options || "envelopeVersion" in options) {
6069
+ throw new Error(
6070
+ "SDK envelope versions are fixed; encode application payload bytes externally"
6071
+ );
6072
+ }
6073
+ if ("signer" in options || "fundingSigner" in options) {
6074
+ throw new Error(
6075
+ "Invisi does not accept signer defaults; export a signing request and attach the external signature"
6076
+ );
6077
+ }
4925
6078
  this.#options = {
4926
6079
  ...options,
4927
6080
  ...options.gasBenchmarks ? { gasBenchmarks: copyGasBenchmarks(options.gasBenchmarks) } : {}
@@ -4932,7 +6085,15 @@ var Invisi = class {
4932
6085
  return new WalletSession(await this.resolve(options));
4933
6086
  }
4934
6087
  async resolve(options) {
4935
- const allowed = ["wallet", "protocol", "namespace", "viewing", "authorization"];
6088
+ const allowed = [
6089
+ "wallet",
6090
+ "protocol",
6091
+ "namespace",
6092
+ "viewing",
6093
+ "authorization",
6094
+ "signer",
6095
+ "fundingSigner"
6096
+ ];
4936
6097
  for (const key of Object.keys(options)) {
4937
6098
  if (!allowed.includes(key))
4938
6099
  throw new Error(
@@ -4941,97 +6102,150 @@ var Invisi = class {
4941
6102
  }
4942
6103
  const selected = { ...options };
4943
6104
  const combined = { ...this.#options, ...selected };
4944
- const { provider, signer, ...runtime } = combined;
6105
+ const { provider, addressLookup = "protocol-rpc", ...runtime } = combined;
6106
+ if (addressLookup !== void 0 && addressLookup !== "chain" && addressLookup !== "protocol-rpc") {
6107
+ throw new Error("Invalid recipient address lookup source");
6108
+ }
4945
6109
  const reader = combined.chainReader ?? (provider ? new EthersChainReader(provider) : void 0);
4946
- if (!reader) throw new import_core14.MissingCapabilityError("chain reader");
6110
+ if (!reader) throw new import_core19.MissingCapabilityError("chain reader");
4947
6111
  if (provider && (await provider.getNetwork()).chainId !== selected.protocol.context.chainId)
4948
6112
  throw new Error("provider deployment chain mismatch");
4949
6113
  await selected.protocol.validateDeployment(reader);
4950
6114
  if (runtime.protocolRpc instanceof import_rpc.ProtocolRpcClient) {
4951
6115
  runtime.protocolRpc = runtime.protocolRpc.withReader(reader);
4952
6116
  }
4953
- if (signer) {
4954
- if (!provider) throw new import_core14.MissingCapabilityError("provider for signer");
4955
- if (!signer.provider) throw new Error("signer must be connected to a provider");
4956
- if ((await signer.provider.getNetwork()).chainId !== selected.protocol.context.chainId)
4957
- throw new Error("signer-provider deployment chain mismatch");
4958
- }
4959
6117
  const registry = selected.protocol.deployment.registry;
4960
- const fundingSigner = combined.fundingSigner ?? (signer ? await EthersFundingSigner.create(signer, selected.protocol.context.chainId) : void 0);
4961
6118
  const fundingVerifier = combined.fundingVerifier ?? (provider ? new EthersFundingVerifier(provider, selected.protocol.context.chainId) : void 0);
4962
- const addressResolver = combined.addressResolver ?? (provider && registry ? new EthersAddressResolver(
4963
- provider,
4964
- {
4965
- chainId: selected.protocol.context.chainId,
4966
- registryAddress: registry.address
4967
- },
4968
- registry.runtimeCodeHash
4969
- ).lookup : void 0);
6119
+ let addressResolver = combined.addressResolver;
6120
+ if (!addressResolver && registry) {
6121
+ if (addressLookup === "protocol-rpc") {
6122
+ const rpc = runtime.protocolRpc;
6123
+ addressResolver = async (identity) => {
6124
+ if (!(rpc instanceof import_rpc.ProtocolRpcClient)) {
6125
+ throw new import_core19.MissingCapabilityError("Protocol RPC recipient discovery");
6126
+ }
6127
+ const discovered = await rpc.getDeployment(selected.protocol.context.chainId);
6128
+ const expected = selected.protocol.deployment;
6129
+ if (discovered.protocol.address !== expected.protocol.address || discovered.protocol.runtimeCodeHash !== expected.protocol.runtimeCodeHash || discovered.protocol.fromBlock !== expected.protocol.fromBlock || discovered.registry?.address !== registry.address || discovered.registry.runtimeCodeHash !== registry.runtimeCodeHash || discovered.registry.fromBlock !== registry.fromBlock)
6130
+ throw new Error("Recipient registry deployment pins mismatch");
6131
+ const registration = await rpc.getReceivingAddress(identity);
6132
+ return registration ? import_core19.ReceivingAddress.parse(registration.receivingAddress).getReceivingKeys() : null;
6133
+ };
6134
+ } else if (provider) {
6135
+ addressResolver = new EthersAddressResolver(
6136
+ provider,
6137
+ {
6138
+ chainId: selected.protocol.context.chainId,
6139
+ registryAddress: registry.address
6140
+ },
6141
+ registry.runtimeCodeHash
6142
+ ).lookup;
6143
+ }
6144
+ }
4970
6145
  return {
4971
6146
  ...runtime,
4972
6147
  chainReader: reader,
4973
- ...signer ? { signer } : {},
4974
- ...fundingSigner ? { fundingSigner } : {},
4975
6148
  ...fundingVerifier ? { fundingVerifier } : {},
4976
6149
  ...addressResolver ? { addressResolver } : {},
4977
6150
  protocol: selected.protocol
4978
6151
  };
4979
6152
  }
6153
+ /** Discover the selected chain's registry and prepare an independent signing request. */
6154
+ async prepareRegistration(options) {
6155
+ return prepareWithErrors("prepareRegistration", async () => {
6156
+ for (const key of Object.keys(options)) {
6157
+ if (!["wallet", "update", "deadline"].includes(key)) {
6158
+ throw new Error(`Unknown registration option: ${key}`);
6159
+ }
6160
+ }
6161
+ this.assertPublicIdentity(options);
6162
+ const selected = { ...options };
6163
+ const { provider, protocolRpc } = this.#options;
6164
+ if (!provider) throw new import_core19.MissingCapabilityError("ethers provider");
6165
+ if (!(protocolRpc instanceof import_rpc.ProtocolRpcClient)) {
6166
+ throw new import_core19.MissingCapabilityError("Protocol RPC deployment discovery");
6167
+ }
6168
+ const chainId = (await provider.getNetwork()).chainId;
6169
+ const deployment = await protocolRpc.getDeployment(chainId);
6170
+ if (!deployment.registry) {
6171
+ throw new import_core19.MissingCapabilityError("receiving-key registry deployment");
6172
+ }
6173
+ const registry = new AddressRegistry(
6174
+ { chainId, registryAddress: deployment.registry.address },
6175
+ { expectedRuntimeCodeHash: deployment.registry.runtimeCodeHash }
6176
+ );
6177
+ return registry.prepareRegistration({ ...selected, provider });
6178
+ });
6179
+ }
6180
+ assertPublicIdentity(options) {
6181
+ const { wallet } = options;
6182
+ if (!(wallet instanceof import_core19.PublicWallet) || ["getViewer", "getDetector", "exportAuthorization"].some((key) => key in wallet)) {
6183
+ throw new Error(
6184
+ "Independent preparation requires a PublicWallet without private capabilities"
6185
+ );
6186
+ }
6187
+ for (const key of ["authorization", "signer", "fundingSigner", "viewing"]) {
6188
+ if (key in options)
6189
+ throw new Error(`Independent preparation does not accept capability: ${key}`);
6190
+ }
6191
+ }
6192
+ resolveExplicit(options) {
6193
+ this.assertPublicIdentity(options);
6194
+ return this.resolve({ wallet: options.wallet, protocol: options.protocol });
6195
+ }
4980
6196
  async prepareTransfer(options) {
4981
- const { wallet, protocol, ...input } = options;
4982
- const request = structuredClone(input);
4983
- const runtime = await this.resolve({ wallet, protocol });
4984
- const preparation = explicitPreparation(runtime, request, request.tokenAddress);
4985
- return preparation.prepareTransfer(request);
4986
- }
4987
- async prepareWithdraw(options) {
4988
- const { wallet, protocol, ...input } = options;
4989
- const request = structuredClone(input);
4990
- const runtime = await this.resolve({ wallet, protocol });
4991
- const preparation = explicitPreparation(runtime, request, request.tokenAddress);
4992
- return preparation.prepareWithdraw(request);
4993
- }
4994
- async prepareSweep(options) {
4995
- const { wallet, protocol, ...input } = options;
4996
- const request = structuredClone(input);
4997
- const runtime = await this.resolve({ wallet, protocol });
4998
- const preparation = explicitPreparation(runtime, request, request.tokenAddress);
4999
- return preparation.prepareSweep(request);
6197
+ return prepareWithErrors("prepareTransfer", async () => {
6198
+ const { wallet, protocol, ...input } = options;
6199
+ const request = structuredClone(input);
6200
+ const runtime = await this.resolveExplicit(options);
6201
+ const preparation = explicitPreparation(runtime, request, request.tokenAddress);
6202
+ return preparation.prepareTransfer(request);
6203
+ });
5000
6204
  }
5001
6205
  async prepareShield(options) {
5002
- const { wallet, protocol, ...input } = options;
5003
- const request = structuredClone(input);
5004
- const runtime = await this.resolve({ wallet, protocol });
5005
- const preparation = explicitPreparation(runtime, {}, request.tokenAddress);
5006
- return preparation.prepareShield(request);
6206
+ return prepareWithErrors("prepareShield", async () => {
6207
+ const { wallet, protocol, ...input } = options;
6208
+ const request = structuredClone(input);
6209
+ const runtime = await this.resolveExplicit(options);
6210
+ const preparation = explicitPreparation(runtime, {}, request.tokenAddress);
6211
+ return preparation.prepareShield(request);
6212
+ });
5007
6213
  }
5008
6214
  async prepareCreateCredit(options) {
5009
- const { wallet, protocol, ...input } = options;
5010
- const request = structuredClone(input);
5011
- const runtime = await this.resolve({ wallet, protocol });
5012
- const preparation = explicitPreparation(runtime, request, request.tokenAddress);
5013
- return preparation.prepareCreateCredit(request);
6215
+ return prepareWithErrors("prepareCreateCredit", async () => {
6216
+ const { wallet, protocol, ...input } = options;
6217
+ const request = structuredClone(input);
6218
+ const runtime = await this.resolveExplicit(options);
6219
+ const preparation = explicitPreparation(runtime, request, request.tokenAddress);
6220
+ return preparation.prepareCreateCredit(request);
6221
+ });
5014
6222
  }
5015
6223
  async prepareDrawCredit(options) {
5016
- const { wallet, protocol, ...input } = options;
5017
- const request = structuredClone(input);
5018
- const runtime = await this.resolve({ wallet, protocol });
5019
- const preparation = explicitPreparation(runtime, request, request.tokenAddress);
5020
- return preparation.prepareDrawCredit(request);
6224
+ return prepareWithErrors("prepareDrawCredit", async () => {
6225
+ const { wallet, protocol, ...input } = options;
6226
+ const request = structuredClone(input);
6227
+ const runtime = await this.resolveExplicit(options);
6228
+ const preparation = explicitPreparation(runtime, request, request.tokenAddress);
6229
+ return preparation.prepareDrawCredit(request);
6230
+ });
5021
6231
  }
5022
6232
  async prepareTopUpCredit(options) {
5023
- const { wallet, protocol, ...input } = options;
5024
- const request = structuredClone(input);
5025
- const runtime = await this.resolve({ wallet, protocol });
5026
- const preparation = explicitPreparation(runtime, request, request.tokenAddress);
5027
- return preparation.prepareTopUpCredit(request);
6233
+ return prepareWithErrors("prepareTopUpCredit", async () => {
6234
+ const { wallet, protocol, ...input } = options;
6235
+ const request = structuredClone(input);
6236
+ const runtime = await this.resolveExplicit(options);
6237
+ const preparation = explicitPreparation(runtime, request, request.tokenAddress);
6238
+ return preparation.prepareTopUpCredit(request);
6239
+ });
5028
6240
  }
5029
6241
  async prepareCancelCredit(options) {
5030
- const { wallet, protocol, ...input } = options;
5031
- const request = structuredClone(input);
5032
- const runtime = await this.resolve({ wallet, protocol });
5033
- const preparation = explicitPreparation(runtime, request, request.tokenAddress);
5034
- return preparation.prepareCancelCredit(request);
6242
+ return prepareWithErrors("prepareCancelCredit", async () => {
6243
+ const { wallet, protocol, ...input } = options;
6244
+ const request = structuredClone(input);
6245
+ const runtime = await this.resolveExplicit(options);
6246
+ const preparation = explicitPreparation(runtime, request, request.tokenAddress);
6247
+ return preparation.prepareCancelCredit(request);
6248
+ });
5035
6249
  }
5036
6250
  toJSON() {
5037
6251
  return { invisi: true };
@@ -5042,8 +6256,8 @@ var Invisi = class {
5042
6256
  };
5043
6257
 
5044
6258
  // src/index.ts
5045
- var import_core15 = require("@invisi-labs/core");
5046
- var import_protocol10 = require("@invisi-labs/protocol");
6259
+ var import_core20 = require("@invisi-labs/core");
6260
+ var import_protocol11 = require("@invisi-labs/protocol");
5047
6261
  var import_rpc3 = require("@invisi-labs/rpc");
5048
6262
 
5049
6263
  // src/ProtocolRpcClient.ts
@@ -5054,21 +6268,6 @@ var ProtocolRpcClient2 = class extends import_rpc2.ProtocolRpcClient {
5054
6268
  }
5055
6269
  };
5056
6270
 
5057
- // src/AddressRegistry.ts
5058
- var import_protocol9 = require("@invisi-labs/protocol");
5059
- var AddressRegistry = class extends import_protocol9.AddressRegistry {
5060
- prepareRegistration(options) {
5061
- if ("provider" in options) {
5062
- const { provider, ...preparation } = options;
5063
- return super.prepareRegistration({
5064
- ...preparation,
5065
- reader: new EthersChainReader(provider)
5066
- });
5067
- }
5068
- return super.prepareRegistration(options);
5069
- }
5070
- };
5071
-
5072
6271
  // src/integrations/encrypted-codec.ts
5073
6272
  var EncryptedWalletCodec = class _EncryptedWalletCodec {
5074
6273
  #key;
@@ -5160,6 +6359,7 @@ var EncryptedWalletCodec = class _EncryptedWalletCodec {
5160
6359
  DisclosureVerifier,
5161
6360
  EncryptedWalletCodec,
5162
6361
  Invisi,
6362
+ InvisiError,
5163
6363
  MAX_MEMO_BYTES,
5164
6364
  MissingCapabilityError,
5165
6365
  NullifierCapability,
@@ -5168,14 +6368,22 @@ var EncryptedWalletCodec = class _EncryptedWalletCodec {
5168
6368
  Protocol,
5169
6369
  ProtocolRpcClient,
5170
6370
  ProtocolRpcError,
6371
+ PublicWallet,
5171
6372
  RegistrationOperation,
5172
6373
  ViewingCapability,
5173
6374
  Wallet,
5174
6375
  WalletAuthorization,
5175
6376
  WalletSession,
6377
+ computeCreditNullifier,
6378
+ creditPeriods,
6379
+ creditV1,
6380
+ decodeDeliveryHeader,
5176
6381
  decodeMemoText,
6382
+ decryptCandidates,
5177
6383
  defineGasBenchmarks,
5178
6384
  encodeMemo,
6385
+ fundsV1,
6386
+ readProtocolLogs,
5179
6387
  walletBalance
5180
6388
  });
5181
6389
  //# sourceMappingURL=index.cjs.map