@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.
@@ -321,8 +321,9 @@ function readProtocolLogs(receipt, protocolAddress) {
321
321
  }
322
322
 
323
323
  // src/session/discovery.ts
324
- var import_ethers3 = require("ethers");
325
324
  var import_core = require("@invisi-labs/core");
325
+ var import_ethers3 = require("ethers");
326
+ var import_core2 = require("@invisi-labs/core");
326
327
  var import_protocol = require("@invisi-labs/protocol");
327
328
  var EVENTS = /* @__PURE__ */ new Set([
328
329
  "CommitmentsInserted",
@@ -416,7 +417,7 @@ function extractDeliveryCandidates(logs, context, confirmedThrough) {
416
417
  check2(inserted, "delivery has no matching canonical insertion");
417
418
  if (commitment !== void 0)
418
419
  check2(hash(commitment) === inserted, "delivery commitment conflicts with insertion");
419
- const delivery = (0, import_protocol.normalizeDelivery)(wire, { credit: role !== "funds" });
420
+ const delivery = (0, import_protocol.normalizeOpaqueDelivery)(wire);
420
421
  check2(
421
422
  typeof token === "string" && (0, import_ethers3.isAddress)(token) && BigInt(token) !== 0n,
422
423
  "invalid event token"
@@ -447,7 +448,7 @@ function extractDeliveryCandidates(logs, context, confirmedThrough) {
447
448
  add(log, tree, index(leaves[0]), fields.creditCommitment, "owner", ds[0]);
448
449
  add(log, tree, index(leaves[0]), fields.creditCommitment, "spender", ds[1]);
449
450
  if (hasChange) add(log, tree, index(leaves[1]), change, "funds", ds[2]);
450
- else (0, import_protocol.normalizeDelivery)(ds[2], { empty: true });
451
+ else (0, import_protocol.normalizeOpaqueDelivery)(ds[2], { empty: true });
451
452
  };
452
453
  for (const log of relevant) {
453
454
  const a = object(log.args);
@@ -477,7 +478,7 @@ function extractDeliveryCandidates(logs, context, confirmedThrough) {
477
478
  const length = Number.parseInt(packed.slice(offset, offset + 4), 16);
478
479
  offset += 4;
479
480
  check2(
480
- length >= 160 && length <= 416 && offset + length * 2 + 136 <= packed.length,
481
+ length >= 1 && length <= import_core.MAX_CIPHERTEXT_BYTES && offset + length * 2 + 136 <= packed.length,
481
482
  "invalid packed delivery length"
482
483
  );
483
484
  const ciphertext = `0x${packed.slice(offset, offset + length * 2)}`;
@@ -499,8 +500,8 @@ function extractDeliveryCandidates(logs, context, confirmedThrough) {
499
500
  cs.forEach((c, i) => {
500
501
  if (BigInt(hash(c)) === 0n) {
501
502
  check2(integer(leaves[i]) === 0n, "absent remainder has nonzero position");
502
- (0, import_protocol.normalizeDelivery)(ds[2 * i], { empty: true });
503
- (0, import_protocol.normalizeDelivery)(ds[2 * i + 1], { empty: true });
503
+ (0, import_protocol.normalizeOpaqueDelivery)(ds[2 * i], { empty: true });
504
+ (0, import_protocol.normalizeOpaqueDelivery)(ds[2 * i + 1], { empty: true });
504
505
  } else {
505
506
  add(log, tree, index(leaves[i]), c, "owner", ds[2 * i]);
506
507
  add(log, tree, index(leaves[i]), c, "spender", ds[2 * i + 1]);
@@ -512,7 +513,7 @@ function extractDeliveryCandidates(logs, context, confirmedThrough) {
512
513
  }
513
514
  async function decryptCandidates(logs, options) {
514
515
  contextCheck(options.context);
515
- (0, import_core.decodeAddress)(import_core.ReceivingAddress.fromIdentity(options.viewing.walletIdentity).toString());
516
+ (0, import_core2.decodeAddress)(import_core2.ReceivingAddress.fromIdentity(options.viewing.walletIdentity).toString());
516
517
  check2(
517
518
  !logs.some(
518
519
  (log) => log.address.toLowerCase() === options.context.protocolAddress.toLowerCase() && log.removed
@@ -854,7 +855,7 @@ function walletBalances(state) {
854
855
  }
855
856
 
856
857
  // src/session/store.ts
857
- var import_core2 = require("@invisi-labs/core");
858
+ var import_core3 = require("@invisi-labs/core");
858
859
  var import_sha256 = require("@noble/hashes/sha256");
859
860
  var import_utils = require("@noble/hashes/utils");
860
861
  function scopeKey(scope) {
@@ -870,7 +871,7 @@ function scopeKey(scope) {
870
871
  return (0, import_utils.bytesToHex)(
871
872
  (0, import_sha256.sha256)(
872
873
  (0, import_utils.utf8ToBytes)(
873
- "Invisi.WalletScope.v2:" + JSON.stringify([
874
+ "Invisi.WalletScope.v1:" + JSON.stringify([
874
875
  scope.namespace,
875
876
  scope.chainId.toString(),
876
877
  scope.protocolAddress.toLowerCase(),
@@ -907,12 +908,12 @@ function validateState(state, scope, revision) {
907
908
  throw new Error("invalid spent state");
908
909
  }
909
910
  for (const record of Object.values(state.credits)) {
910
- const note = (0, import_core2.normalizeCreditDeliveryState)(record.state).note;
911
+ const note = (0, import_core3.normalizeCreditDeliveryState)(record.state).note;
911
912
  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))
912
913
  throw new Error("invalid stored Credit context or role");
913
914
  }
914
915
  for (const record of [...Object.values(state.notes), ...Object.values(state.credits)]) {
915
- if (!/^0x[0-9a-fA-F]{64}$/.test(record.commitment) || BigInt(record.commitment) <= 0n || BigInt(record.commitment) >= import_core2.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))
916
+ if (!/^0x[0-9a-fA-F]{64}$/.test(record.commitment) || BigInt(record.commitment) <= 0n || BigInt(record.commitment) >= import_core3.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))
916
917
  throw new Error("invalid stored receipt position");
917
918
  }
918
919
  for (const [id, operation] of Object.entries(state.reservations))
@@ -973,13 +974,11 @@ var TransactionalWalletStore = class {
973
974
  };
974
975
 
975
976
  // src/session/operation-protocol.ts
977
+ var import_core4 = require("@invisi-labs/core");
976
978
  var import_protocol2 = require("@invisi-labs/protocol");
977
979
  function requiresAuthorization(plan) {
978
- if (plan.kind === "sweep") {
979
- 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))
980
- throw new Error("invalid owner-only sweep plan");
981
- return false;
982
- }
980
+ 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);
981
+ if (ownerOnlyFullWithdrawal) return false;
983
982
  return !!plan.credit || plan.inputs.length > 0;
984
983
  }
985
984
  function inputFacts(plan) {
@@ -1110,6 +1109,7 @@ async function witnessFor(protocol, plan, authorization) {
1110
1109
  }
1111
1110
  if (credit.draw) {
1112
1111
  return builder.drawCredit({
1112
+ timestamp: plan.preparedAt.timestamp,
1113
1113
  params: credit.draw,
1114
1114
  deliveries: credit.deliveries,
1115
1115
  inputs: credit.inputs,
@@ -1240,7 +1240,12 @@ function operationExpired(plan, now) {
1240
1240
  const credit = plan.credit;
1241
1241
  if (credit?.topUp && now >= credit.topUp.previousExpiry) return true;
1242
1242
  if (credit?.creation && now >= credit.creation.expiry) return true;
1243
- if (credit?.draw && credit.draw.expiries.some((expiry) => now >= expiry)) return true;
1243
+ if (credit?.draw) {
1244
+ if (credit.draw.expiries.some((expiry) => now >= expiry)) return true;
1245
+ const prepared = (0, import_core4.creditPeriods)(plan.preparedAt.timestamp), current2 = (0, import_core4.creditPeriods)(now);
1246
+ if (prepared.currentDay !== current2.currentDay || prepared.currentMonth !== current2.currentMonth)
1247
+ return true;
1248
+ }
1244
1249
  return false;
1245
1250
  }
1246
1251
 
@@ -1248,352 +1253,987 @@ function operationExpired(plan, now) {
1248
1253
  var gas_benchmarks_default = [
1249
1254
  {
1250
1255
  formatVersion: 1,
1251
- id: "protocol-92ef274-osaka-real",
1256
+ id: "protocol-42f2546-621cbef5f84a-prague-credit-real",
1252
1257
  deployment: {
1253
1258
  chainId: "31337",
1254
- protocolAddress: "0x8870C63A18a9480C7de9B860b849fD293832856D",
1255
- runtimeCodeHash: "0x604572c0da90ea139b774cd0d2962a2972fac46e0556c7cec6f6f9aac5deef14",
1256
- tokenAddress: "0x4826533B4897376654Bb4d4AD88B7faFD0C98528"
1259
+ protocolAddress: "0xEeD9be753bccbCB21463C49f0c56cC0E48bEcf3c",
1260
+ runtimeCodeHash: "0x80228a2080d224b4481fc5df24fe8ce080d4536c663b13ec7829ecf0ef46abbd",
1261
+ tokenAddress: "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf"
1257
1262
  },
1258
1263
  source: {
1259
- protocolCommit: "92ef274c6b36d783507699a33ee20e52192c83c7",
1260
- measuredAt: "2026-10-27T08:42:15.991Z",
1264
+ protocolCommit: "42f2546b62312e4c11e21b8e6b2ff6f72187d6a6",
1265
+ measuredAt: "2026-10-29T10:56:24.758Z",
1261
1266
  chain: "Anvil 31337",
1262
- hardfork: "osaka",
1267
+ hardfork: "prague",
1263
1268
  token: "MockERC20",
1264
1269
  verifier: "real",
1270
+ fingerprints: {
1271
+ protocolSourceSha256: "621cbef5f84a133ca96674a2dba39b21b5f9fbc022977d4d2ab296d9d6e685e0",
1272
+ dirtyDiffSha256: "eb2c41cca3802a47196181648397ec6f47fb2ba0efa8aa3800508d8d255fae3f",
1273
+ compiledArtifactsSha256: "c0e658d74fe49caeebf5ef9deadc1751d9e48add690f7e9ab478de7a00dab7e4",
1274
+ creditManifestSha256: "da819378af60471905cc902a43e464b58159e0c75bd46fb804ea9d34d8aa7ef6",
1275
+ userManifestSha256: "067b6c50e4bc4d9c19dd29f25352db88d189a5f49aed0ed603daa70760e699df",
1276
+ sdkSourceSha256: "37e1f82a447db741f46e1490b866ddf85718eab42c33d369cf5f5d2ec3a25c78"
1277
+ },
1278
+ toolchain: {
1279
+ solidity: "0.8.38",
1280
+ barretenberg: "6.0.0",
1281
+ noir: "1.0.0-rc.6",
1282
+ evmVersion: "prague",
1283
+ optimizerRuns: 200,
1284
+ anvil: "anvil Version: 1.8.6"
1285
+ },
1286
+ blockGasLimit: "500000000",
1287
+ runtimeContracts: {
1288
+ transact_user_slots14_direct_Verifier: {
1289
+ address: "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1290
+ runtimeCodeHash: "0xedab185b2b9fc7d98660db2cdc99fe30b9d1341dfe568172a1626e322d208f7e"
1291
+ },
1292
+ "transact_user_slots14-adapter": {
1293
+ address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
1294
+ runtimeCodeHash: "0xe222cd9c142bc2b13e083e6fe66ea76c0e1e9a194715bfa57082b625c55d867f"
1295
+ },
1296
+ transact_user_slots56_direct_Verifier: {
1297
+ address: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
1298
+ runtimeCodeHash: "0x8913eb7060f38234aca199c4a1007892f68e703de48b588c436b24faaeb23a53"
1299
+ },
1300
+ "transact_user_slots56-adapter": {
1301
+ address: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
1302
+ runtimeCodeHash: "0x97c416d190da0b9b8111a5ee17367e8a702ba7884019bf724155ae629a783477"
1303
+ },
1304
+ transact_user_slots112_direct_Verifier: {
1305
+ address: "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9",
1306
+ runtimeCodeHash: "0x501a4791ff0c0a96465ab5e0d42d0ce763bbbb7fd8aebe21929de4d460e1b42c"
1307
+ },
1308
+ "transact_user_slots112-adapter": {
1309
+ address: "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
1310
+ runtimeCodeHash: "0xf22ed8ea34a4011650a41c1b9f664b5259ea5a8d66a82d706dab9611a38c109f"
1311
+ },
1312
+ transact_user_slots168_direct_Verifier: {
1313
+ address: "0x0165878A594ca255338adfa4d48449f69242Eb8F",
1314
+ runtimeCodeHash: "0xc22acdfa6f3e278ae46d194a1c50b905e4815fd7b61e39edb52334570670fdce"
1315
+ },
1316
+ "transact_user_slots168-adapter": {
1317
+ address: "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
1318
+ runtimeCodeHash: "0x05a318f54d93440a501b6fc6be88e4e76e89d72f1be8333553cb4a61f4f9a0d7"
1319
+ },
1320
+ transact_aggregate_14_4_Verifier: {
1321
+ address: "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6",
1322
+ runtimeCodeHash: "0x7a6f2bafe4c61a72a99a195e188f2f4a32900c0cc63cc132e33881d8199fd446"
1323
+ },
1324
+ "transact_aggregate_14_4-adapter": {
1325
+ address: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318",
1326
+ runtimeCodeHash: "0x15877da9940d5b8dd4868ffa92ded3b93d6092c3963ba9e18b50f1ea15d89898"
1327
+ },
1328
+ transact_aggregate_14_8_Verifier: {
1329
+ address: "0x610178dA211FEF7D417bC0e6FeD39F05609AD788",
1330
+ runtimeCodeHash: "0x5667d16b39973813a499375f6885a3082d7bfcd6e3c0f3548d7de3131cd285f3"
1331
+ },
1332
+ "transact_aggregate_14_8-adapter": {
1333
+ address: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
1334
+ runtimeCodeHash: "0x9d1a93c78edf7e81b4b6da10ab209b3fb009ed8355594f670559a67842d88cfc"
1335
+ },
1336
+ transact_aggregate_14_12_Verifier: {
1337
+ address: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
1338
+ runtimeCodeHash: "0xa4e67840a47182d4011d577981c2477bb4ab2bc36845bb136375f19f12c0800b"
1339
+ },
1340
+ "transact_aggregate_14_12-adapter": {
1341
+ address: "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
1342
+ runtimeCodeHash: "0x96a6e170aafc0af9d46232ba00206d950bba85e65962d43501bafb6d7f9fe61d"
1343
+ },
1344
+ create_credit_direct_Verifier: {
1345
+ address: "0x9A676e781A523b5d0C0e43731313A708CB607508",
1346
+ runtimeCodeHash: "0xbdc6450bf9ba01001082f345b8bd21006a4f75274f32d026cf6e14270e6d56e6"
1347
+ },
1348
+ "create_credit-adapter": {
1349
+ address: "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
1350
+ runtimeCodeHash: "0x3a95a22b32aef18ce053a7110056bbfbf13bb0b07932a49765ebb136528a4707"
1351
+ },
1352
+ credit_draw_slots1_direct_Verifier: {
1353
+ address: "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
1354
+ runtimeCodeHash: "0x47be80e72c3a22ea044638f6004de8c3a0264d5a0d17189c01153cdabfd7bab6"
1355
+ },
1356
+ "credit_draw_slots1-adapter": {
1357
+ address: "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
1358
+ runtimeCodeHash: "0x28f25aeb97659fb9253ae67f2ff284789710bc59e1ed077ffc7a07b800cbfcc1"
1359
+ },
1360
+ credit_draw_slots12_direct_Verifier: {
1361
+ address: "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
1362
+ runtimeCodeHash: "0x244d9ba22f5c736c2a5c42c466701e2a8ba7ae8108665133541026ea45d56e04"
1363
+ },
1364
+ "credit_draw_slots12-adapter": {
1365
+ address: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
1366
+ runtimeCodeHash: "0x60d48a35279d318a0621e5f59b293f44074463b8002ce180b7e6a31b995ac195"
1367
+ },
1368
+ credit_draw_slots50_direct_Verifier: {
1369
+ address: "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d",
1370
+ runtimeCodeHash: "0x2ad5eb64bcfae34ef04111dd8f9c1ffc5fc8aa6c1ad3a65d8da78233f3390660"
1371
+ },
1372
+ "credit_draw_slots50-adapter": {
1373
+ address: "0x59b670e9fA9D0A427751Af201D676719a970857b",
1374
+ runtimeCodeHash: "0x468966de20e5c71cf7b6f3cda7fa7a76b5d80dc5ddf82119f441ea6a7c6c1e70"
1375
+ },
1376
+ credit_draw_slots120_direct_Verifier: {
1377
+ address: "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1",
1378
+ runtimeCodeHash: "0x523b6d211618bbd33d708f8198b9f3daafc10e2fa7a6a857db5795ed748a24e4"
1379
+ },
1380
+ "credit_draw_slots120-adapter": {
1381
+ address: "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
1382
+ runtimeCodeHash: "0xa91d585ce6037e703efb914205bf193881fde4f470d2fc63b615699b56175239"
1383
+ },
1384
+ credit_cancel_direct_Verifier: {
1385
+ address: "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
1386
+ runtimeCodeHash: "0x182e86861a73f712071e40a6b8497b80c58c383eaa799182e7a50e39196399fd"
1387
+ },
1388
+ "credit_cancel-adapter": {
1389
+ address: "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
1390
+ runtimeCodeHash: "0xea1f0f22445eed5a92c8d6990219059b7e241ad66c55a6d9ddef22a94a0f015f"
1391
+ },
1392
+ credit_top_up_direct_Verifier: {
1393
+ address: "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
1394
+ runtimeCodeHash: "0xeeb42a2b6377ab305b713d1caf4ca96edb302c6d1e1007239e5c70091819c266"
1395
+ },
1396
+ "credit_top_up-adapter": {
1397
+ address: "0x09635F643e140090A9A8Dcd712eD6285858ceBef",
1398
+ runtimeCodeHash: "0xbcf35a1d0e6c16dd01b09f944889aa5917d358d986fe399a0343d06bbdedaa61"
1399
+ },
1400
+ PrivateTransferVerifierRegistry: {
1401
+ address: "0xc5a5C42992dECbae36851359345FE25997F5C42d",
1402
+ runtimeCodeHash: "0x678684af147cb42c872184b6e22c8439748139ae0c5885032941ab8832fcb142"
1403
+ },
1404
+ CrossTreeVerifierRegistry: {
1405
+ address: "0x67d269191c92Caf3cD7723F116c85e6E9bf55933",
1406
+ runtimeCodeHash: "0xa5ee16fc7ed9f982450e42a48365a93bfca784fa884adcb8695b557e921cb93b"
1407
+ },
1408
+ DualVerifierRouter: {
1409
+ address: "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E",
1410
+ runtimeCodeHash: "0xcc094ed6f1bcc9270c597f62b817e4fc0a54770f373320133c2836e5b07ef2cc"
1411
+ },
1412
+ AtomicBatchOutputLib: {
1413
+ address: "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690",
1414
+ runtimeCodeHash: "0x7c138c13e40b3ad0fee3b319d6c1580a21855cb5ecdda92571d530509d9b7316"
1415
+ },
1416
+ FundingLib: {
1417
+ address: "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
1418
+ runtimeCodeHash: "0x898d13d6ec4123df85f21ee0f98678dcd9f9b9a60134f88e35c1ef1aaa0a45f9"
1419
+ },
1420
+ PrivateTransferLib: {
1421
+ address: "0x9E545E3C0baAB3E08CdfD552C960A1050f373042",
1422
+ runtimeCodeHash: "0xfb18f2dd0a39af1b99ae35c25e2746cb5bc85c205e041db5f440671d84c82e5e"
1423
+ },
1424
+ CrossTreeTransferLib: {
1425
+ address: "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",
1426
+ runtimeCodeHash: "0x7b33a08f2feb9da462b951c95482cb2909796a85c0fde7cc9a6b65ff8b7ff253"
1427
+ },
1428
+ AggregateTransferLib: {
1429
+ address: "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8",
1430
+ runtimeCodeHash: "0xb3b4bd3a428f5c35712a57180f07b2249774d399ca87d4494929148ea26c5b99"
1431
+ },
1432
+ CreateCreditLib: {
1433
+ address: "0x851356ae760d987E095750cCeb3bC6014560891C",
1434
+ runtimeCodeHash: "0xe37a4b7c129c4fba5615d25ed8b7e898e64a306c68f7e599ade911db98fe881c"
1435
+ },
1436
+ CreditLifecycleLib: {
1437
+ address: "0xf5059a5D33d5853360D16C683c16e67980206f36",
1438
+ runtimeCodeHash: "0xf87a2227680efa7070071516587793e2e847c172b83261b8983c826f8a8c79bb"
1439
+ },
1440
+ ShieldLib: {
1441
+ address: "0x95401dc811bb5740090279Ba06cfA8fcF6113778",
1442
+ runtimeCodeHash: "0x371e57d8d324e44445a4ec30303b89a8bc98bbdbd03aeaa80faf0f821a65451d"
1443
+ },
1444
+ InvisiFactory: {
1445
+ address: "0x998abeb3E57409262aE5b751f60747921B33613E",
1446
+ runtimeCodeHash: "0xc56e5a0b71f4a1f63576a6663efb62b17c0d7520b6885a8d3483a356e12edf9b"
1447
+ },
1448
+ InvisiAddressRegistry: {
1449
+ address: "0x70e0bA845a1A0F2DA3359C97E0285013525FFC49",
1450
+ runtimeCodeHash: "0x007da3f4e888366ba0eed52cd511c4a369359291387ad19ca37e89eb395fce30"
1451
+ },
1452
+ InvisiProtocol: {
1453
+ address: "0xEeD9be753bccbCB21463C49f0c56cC0E48bEcf3c",
1454
+ runtimeCodeHash: "0x80228a2080d224b4481fc5df24fe8ce080d4536c663b13ec7829ecf0ef46abbd"
1455
+ },
1456
+ MockERC20: {
1457
+ address: "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf",
1458
+ runtimeCodeHash: "0xf7f676b5c54f6e94f82f0de65a0117468a0d915e8a79d150e74f76bd6d7f708b"
1459
+ }
1460
+ },
1265
1461
  assumptions: [
1266
- "normal CREATE/Factory deployment; no code or storage injection",
1267
- "Solidity 0.8.27 optimizer 200; real BB 5.2.1 verifiers",
1268
- "one source tree; two existing leaves; no rollover or screener",
1269
- "funding/approval setup excluded; complete transaction receipt gas included",
1270
- "exact allowance for caller funding; configured benchmark payout balances",
1271
- "observed local samples, not a confidence interval or gas limit"
1462
+ "normal CREATE/Factory deployment and fresh registry; EIP170/EIP3860 unchanged; no code/storage injection",
1463
+ "Solidity0.8.38 optimizer200 Prague; pinned BB6.0.0 real verifiers; every native proof independently verified",
1464
+ "one physical source tree and 123 existing leaves shared by every sample; top-up has two authenticated source groups; no rollover or screener",
1465
+ "funding/approvals/121 genuine Credit seeds/usage-seed draw/payout reset excluded from business gas",
1466
+ "each round restores identical token balances, exact caller allowance100, note cursor, nullifiers and baseline; spender payout starts zero",
1467
+ "complete receipt.gasUsed is measured, including verifier/calldata/logging/output insertion; memo0",
1468
+ "Prague local block gas limit500000000; measured transactions may be unmineable under lower network transaction/block limits",
1469
+ "observed three-sample ranges are neither a confidence interval nor a recommended transaction gas limit"
1272
1470
  ]
1273
1471
  },
1274
1472
  measurements: [
1275
1473
  {
1276
- id: "shield-1",
1474
+ id: "create-credit-caller-0x0",
1277
1475
  shape: {
1278
- kind: "shield",
1476
+ kind: "create-credit",
1279
1477
  target: "evm",
1280
- capacity: 0,
1478
+ capacity: 10,
1281
1479
  noteInputs: 0,
1282
- noteOutputs: 1,
1480
+ noteOutputs: 0,
1283
1481
  sourceTrees: 0,
1284
1482
  creditInputs: 0,
1285
- creditOutputs: 0,
1483
+ creditOutputs: 1,
1286
1484
  creditRemainders: 0,
1287
1485
  funding: "caller",
1288
1486
  permit: false,
1289
- deliveryBytes: 226
1487
+ deliveryBytes: 1132
1488
+ },
1489
+ circuit: {
1490
+ circuitName: "create_credit",
1491
+ target: "evm",
1492
+ artifactSha256: "3ed6cfdee4f5fd840f023580f76c208768777fea79737f2511377e5c55be0230",
1493
+ vkSha256: "56f663c6053be0d158a271022d200c732597efd3a2e0be48fe94549d0b1795e0"
1290
1494
  },
1291
- circuit: null,
1292
1495
  samples: [
1293
1496
  {
1294
- gasUsed: "649286",
1295
- transactionHash: "0xcc299d1780ada9a69b1d9f0f3d06a165db15fccbd2b7ff407834f02f5d563a18",
1296
- blockNumber: "50",
1297
- blockHash: "0xbcb868e781a20588d2fa099a4d7f87c1600044a2e5ec1e369e384d7a5f22f00a",
1298
- calldataBytes: 1156
1497
+ gasUsed: "1574696",
1498
+ transactionHash: "0x76112c532a1b5f24ad84fb83f91789ba4acd15ed9473ec9a0267cd5fe605448d",
1499
+ blockNumber: "172",
1500
+ blockHash: "0x0d91421e94947132a19f38ffdd76932c2d85add201de3d9189325ed3568125a7",
1501
+ calldataBytes: 11780
1299
1502
  },
1300
1503
  {
1301
- gasUsed: "649322",
1302
- transactionHash: "0x95139dff109725989f0769e3e6fb9bd3e7e1bf581fd475f14e822875eb90fda4",
1303
- blockNumber: "50",
1304
- blockHash: "0x7ace353fea4fc8c856c0fd45521d200b02619921977709ff4f910e0ff41c06fe",
1305
- calldataBytes: 1156
1504
+ gasUsed: "1574576",
1505
+ transactionHash: "0x545f72d9d207329bfc69ef0d1e96470c614924d5e463d974cc001712bf619fd8",
1506
+ blockNumber: "172",
1507
+ blockHash: "0x2053f97a2b2f3cf66e14da0ab9c1d7bd462d2d4f3ef2b13021aefcddedb71cf8",
1508
+ calldataBytes: 11780
1306
1509
  },
1307
1510
  {
1308
- gasUsed: "649322",
1309
- transactionHash: "0xef578bb38dc8ff8bfd47d2e76e3ab4273019ea9a385f5d2fd99add32ceaecb58",
1310
- blockNumber: "50",
1311
- blockHash: "0xded817f8ef89637e2443e3b626c0837f184ca134fe753be913d5570554c649a6",
1312
- calldataBytes: 1156
1511
+ gasUsed: "1574612",
1512
+ transactionHash: "0x880ec0c666068d0756fba39947dc5b211aeebb31f41bd1e1e54856b090f65d34",
1513
+ blockNumber: "172",
1514
+ blockHash: "0xbb86ed21379a917e9688a3c90364ae8fbe1ba633ac068360e0a82bf4d3113b6d",
1515
+ calldataBytes: 11780
1313
1516
  }
1314
1517
  ]
1315
1518
  },
1316
1519
  {
1317
- id: "shield-2",
1520
+ id: "create-credit-1x1",
1318
1521
  shape: {
1319
- kind: "shield",
1522
+ kind: "create-credit",
1320
1523
  target: "evm",
1321
- capacity: 0,
1322
- noteInputs: 0,
1323
- noteOutputs: 2,
1324
- sourceTrees: 0,
1524
+ capacity: 10,
1525
+ noteInputs: 1,
1526
+ noteOutputs: 1,
1527
+ sourceTrees: 1,
1325
1528
  creditInputs: 0,
1326
- creditOutputs: 0,
1529
+ creditOutputs: 1,
1327
1530
  creditRemainders: 0,
1328
- funding: "caller",
1531
+ funding: "none",
1329
1532
  permit: false,
1330
- deliveryBytes: 452
1533
+ deliveryBytes: 1360
1534
+ },
1535
+ circuit: {
1536
+ circuitName: "create_credit",
1537
+ target: "evm",
1538
+ artifactSha256: "3ed6cfdee4f5fd840f023580f76c208768777fea79737f2511377e5c55be0230",
1539
+ vkSha256: "56f663c6053be0d158a271022d200c732597efd3a2e0be48fe94549d0b1795e0"
1331
1540
  },
1332
- circuit: null,
1333
1541
  samples: [
1334
1542
  {
1335
- gasUsed: "757063",
1336
- transactionHash: "0x024e2dfbd6f50c368e2a4aa347e3029de668f4ebd36b80227aa003bb7ac21c74",
1337
- blockNumber: "50",
1338
- blockHash: "0x8ed63973c158d706ac54bb646626e4f0db5777b4bd56d179b94503af6c417c50",
1339
- calldataBytes: 1668
1543
+ gasUsed: "1671641",
1544
+ transactionHash: "0x24ca3f03681aeb188b48989d5eaf7dd264a8c32e828acd34ff1b44be74f17ea6",
1545
+ blockNumber: "172",
1546
+ blockHash: "0xcdac07aa5d3ec187874dc1fc9be65503235289c7036ebe455feaf5161db42bb5",
1547
+ calldataBytes: 12132
1340
1548
  },
1341
1549
  {
1342
- gasUsed: "757063",
1343
- transactionHash: "0x898d852ab28f68adac4d30b160a3dbfee33fa7ca875f70df9eb7763b6b1cd1f0",
1344
- blockNumber: "50",
1345
- blockHash: "0x9bb6810de38193933a9f26fa03d3d9bad1ca0151ff5e04544c56520e09da3043",
1346
- calldataBytes: 1668
1550
+ gasUsed: "1671509",
1551
+ transactionHash: "0x31a7f69ab02effa5fdd2e02bd02fb7e715a54786813261113fd7c07a0d3ef549",
1552
+ blockNumber: "172",
1553
+ blockHash: "0xc78ca874aa22cc6b8ea19e12a2806ba448a0f844345450d3fedc9841ea71c3a8",
1554
+ calldataBytes: 12132
1347
1555
  },
1348
1556
  {
1349
- gasUsed: "757039",
1350
- transactionHash: "0x8ff9720e3197aab2d741fbd8d0fa2969203ea8cd051d9649d1e5eb890bcc2be3",
1351
- blockNumber: "50",
1352
- blockHash: "0x8604c75eb6363aaae774276e638f5b749aae1f8f815eb99ab1183137eef5730e",
1353
- calldataBytes: 1668
1557
+ gasUsed: "1671485",
1558
+ transactionHash: "0xc5a30116885dcac8b3631c15847544cfeb91c46bde44c3765ac0ce42e3259157",
1559
+ blockNumber: "172",
1560
+ blockHash: "0x4a2c90ff972da4d37408567062779762efbb5790d4784d03842ee2c926c8c894",
1561
+ calldataBytes: 12132
1354
1562
  }
1355
1563
  ]
1356
1564
  },
1357
1565
  {
1358
- id: "shield-10",
1566
+ id: "draw-credit-1-partial",
1359
1567
  shape: {
1360
- kind: "shield",
1568
+ kind: "draw-credit",
1361
1569
  target: "evm",
1362
- capacity: 0,
1570
+ capacity: 1,
1363
1571
  noteInputs: 0,
1364
- noteOutputs: 10,
1365
- sourceTrees: 0,
1366
- creditInputs: 0,
1367
- creditOutputs: 0,
1368
- creditRemainders: 0,
1369
- funding: "caller",
1572
+ noteOutputs: 0,
1573
+ sourceTrees: 1,
1574
+ creditInputs: 1,
1575
+ creditOutputs: 1,
1576
+ creditRemainders: 1,
1577
+ funding: "none",
1370
1578
  permit: false,
1371
- deliveryBytes: 2260
1579
+ deliveryBytes: 1132
1580
+ },
1581
+ circuit: {
1582
+ circuitName: "credit_draw_slots1",
1583
+ target: "evm",
1584
+ artifactSha256: "4542b227e0552b45c302f1dace21cadeba4962c96244e021472f1f7531cff8d1",
1585
+ vkSha256: "43c051a2bedf9454c12e70b10156361e414944823ba23e80662c16c7ced0a2ce"
1372
1586
  },
1373
- circuit: null,
1374
1587
  samples: [
1375
1588
  {
1376
- gasUsed: "1692143",
1377
- transactionHash: "0x6c13db8bd8a8599daf5034e56712abefbf406982fafe7647b6d22291ba4199ed",
1378
- blockNumber: "50",
1379
- blockHash: "0x1ab2ae514f408a79e0c40ca10cee74b2e23d7c8a5f24641b8eea3e1cf58ce700",
1380
- calldataBytes: 5764
1589
+ gasUsed: "1588303",
1590
+ transactionHash: "0x85c5180692470aa952aa13eb29ca0404d4f5b5192cb31475f90d03d78864895e",
1591
+ blockNumber: "172",
1592
+ blockHash: "0xfe4876c0a2ebf05385a46562bca693b6df80da731fd9651117593916015dc38c",
1593
+ calldataBytes: 11588
1381
1594
  },
1382
1595
  {
1383
- gasUsed: "1692083",
1384
- transactionHash: "0x5e476c9d3838b782a51332af9bf5c372d29fc411c2168a7af619c52bd5309c7b",
1385
- blockNumber: "50",
1386
- blockHash: "0x9c62bc72fc90f990c6711b48865ff922a1856ae05c4fef61dad5f4da7d948401",
1387
- calldataBytes: 5764
1596
+ gasUsed: "1588303",
1597
+ transactionHash: "0x61684313840623187ca1205b4b07b43a08038448524ee1a028c7e14050032682",
1598
+ blockNumber: "172",
1599
+ blockHash: "0x9726d31c10e6516e38e3f63c84fc4b9a8a161486d35e0d8d07e6829261a88fe7",
1600
+ calldataBytes: 11588
1388
1601
  },
1389
1602
  {
1390
- gasUsed: "1692203",
1391
- transactionHash: "0x0092e2d9160fad95279cde586fc6c79c713244f55db8a2060a5abab9d98c176a",
1392
- blockNumber: "50",
1393
- blockHash: "0xac1bf780b4cc05b4dcc7ee5d741c049ba99ab4af9bdcd25104add730c2a14152",
1394
- calldataBytes: 5764
1603
+ gasUsed: "1588255",
1604
+ transactionHash: "0x0aa052fb8e356cc81dd73bcdae72f760937cd2e56bd4a3e8eb5878208b4f7596",
1605
+ blockNumber: "172",
1606
+ blockHash: "0x2c958cfba0627e18cd5cb47001b278628c305071929596e3335d770b92c1dc16",
1607
+ calldataBytes: 11588
1395
1608
  }
1396
1609
  ]
1397
1610
  },
1398
1611
  {
1399
- id: "transfer-1x2",
1612
+ id: "draw-credit-1-full",
1400
1613
  shape: {
1401
- kind: "transfer",
1614
+ kind: "draw-credit",
1402
1615
  target: "evm",
1403
- capacity: 14,
1404
- noteInputs: 1,
1405
- noteOutputs: 2,
1616
+ capacity: 1,
1617
+ noteInputs: 0,
1618
+ noteOutputs: 0,
1406
1619
  sourceTrees: 1,
1407
- creditInputs: 0,
1620
+ creditInputs: 1,
1408
1621
  creditOutputs: 0,
1409
1622
  creditRemainders: 0,
1410
1623
  funding: "none",
1411
1624
  permit: false,
1412
- deliveryBytes: 452
1625
+ deliveryBytes: 0
1413
1626
  },
1414
1627
  circuit: {
1415
- circuitName: "transact_user_slots14",
1628
+ circuitName: "credit_draw_slots1",
1416
1629
  target: "evm",
1417
- artifactSha256: "2a6a20839e90b88b1ecd629f59a01821bad3ee11dbe04db1fd9cdce7a3de0e84",
1418
- vkSha256: "ffe0e1a4e690792ecb4eb1fc1acc9ff60f13d3b5af03cfc6ae6d6bf26e99bdea"
1630
+ artifactSha256: "4542b227e0552b45c302f1dace21cadeba4962c96244e021472f1f7531cff8d1",
1631
+ vkSha256: "43c051a2bedf9454c12e70b10156361e414944823ba23e80662c16c7ced0a2ce"
1419
1632
  },
1420
1633
  samples: [
1421
1634
  {
1422
- gasUsed: "1617516",
1423
- transactionHash: "0xf49ea3d31cc1346472172e2dee84f9360f60a3fe948a3ef6e87f727af6d42f0d",
1424
- blockNumber: "49",
1425
- blockHash: "0xf59c57e63ec2f03abc36d28f273b0af5290184dc97197df740b23d79a851a887",
1426
- calldataBytes: 11012
1635
+ gasUsed: "1042812",
1636
+ transactionHash: "0xb5d55729d975abdc92ca44c0b72e44a0d5841da8b23dc11b5bd31f46d88a341a",
1637
+ blockNumber: "172",
1638
+ blockHash: "0x8a6ddbe2f1630e1956485cac7984fb9cdc4fbb26b10522e158b38e2970ee4f3b",
1639
+ calldataBytes: 10372
1427
1640
  },
1428
1641
  {
1429
- gasUsed: "1617516",
1430
- transactionHash: "0xf8d11286f1f2a4db006ff6b06900c47d0fbf685984499e1e5d4aea49478ba8e5",
1431
- blockNumber: "49",
1432
- blockHash: "0xeb5a800190be3534c9e2675c97ac56d0e0be8adef55f60bd32d375776a7d150c",
1433
- calldataBytes: 11012
1642
+ gasUsed: "1042824",
1643
+ transactionHash: "0xf64f3186fbf94fcbd9fb12426c714b4a8425599e1a7e5677866fae3d6873b7ae",
1644
+ blockNumber: "172",
1645
+ blockHash: "0xd630c44d8ce96234ec836dd2178caac2a6d0bc2df5cf37df1534eb8896be48d3",
1646
+ calldataBytes: 10372
1434
1647
  },
1435
1648
  {
1436
- gasUsed: "1617504",
1437
- transactionHash: "0x8939fcea97079a3c5118b9e94325455e2ad1cdb47310ae499a277272654b3eb6",
1438
- blockNumber: "49",
1439
- blockHash: "0xecffefb593e2fec5d5827cfd39d0cc4d0efb67dbff6f8dbbd0d2db2439a80cf9",
1440
- calldataBytes: 11012
1649
+ gasUsed: "1042884",
1650
+ transactionHash: "0xdf634e809b87603a62292ef046fa5e84715561fa76ef121c768303dd779568f1",
1651
+ blockNumber: "172",
1652
+ blockHash: "0x09cad4a799360bdf825c3ad70fe374b7fe2df802f8ee37ccb7f26ffc49aa2a3a",
1653
+ calldataBytes: 10372
1441
1654
  }
1442
1655
  ]
1443
1656
  },
1444
1657
  {
1445
- id: "transfer-1x14",
1658
+ id: "draw-credit-12-partial",
1446
1659
  shape: {
1447
- kind: "transfer",
1660
+ kind: "draw-credit",
1448
1661
  target: "evm",
1449
- capacity: 56,
1450
- noteInputs: 1,
1451
- noteOutputs: 14,
1662
+ capacity: 12,
1663
+ noteInputs: 0,
1664
+ noteOutputs: 0,
1452
1665
  sourceTrees: 1,
1453
- creditInputs: 0,
1454
- creditOutputs: 0,
1455
- creditRemainders: 0,
1666
+ creditInputs: 12,
1667
+ creditOutputs: 12,
1668
+ creditRemainders: 12,
1456
1669
  funding: "none",
1457
1670
  permit: false,
1458
- deliveryBytes: 3164
1671
+ deliveryBytes: 13584
1459
1672
  },
1460
1673
  circuit: {
1461
- circuitName: "transact_user_slots56",
1674
+ circuitName: "credit_draw_slots12",
1462
1675
  target: "evm",
1463
- artifactSha256: "ba83ec2f177d16fa88ea04bc54f2e99920f1ac195cdb05b88b9b3bbc245fd953",
1464
- vkSha256: "6ad5d3aff0c72a632fb19895658af093a6a92478a9994985e838a71e61237720"
1676
+ artifactSha256: "dd72b0867fc3be7cd90de263bd2d0892075cb18eb4f6dd671b13111710f10369",
1677
+ vkSha256: "5e31d771e6294993736078596d9c69f21fe7595eda50e3cce6d7406b65cf1443"
1465
1678
  },
1466
1679
  samples: [
1467
1680
  {
1468
- gasUsed: "2489010",
1469
- transactionHash: "0x053557acea930a869d6469c91e9bc015d0893607a6ab18d2af684986f7074676",
1470
- blockNumber: "49",
1471
- blockHash: "0x734873097eb5e4cb66bfc2cdb61fac6753b53a4b9450fb22895281100af3aaf3",
1472
- calldataBytes: 17156
1681
+ gasUsed: "3102895",
1682
+ transactionHash: "0x699ba81f296f4af397a8dfaf96adf14d00d0f7dd69c0b09608641fc9b99fc28f",
1683
+ blockNumber: "172",
1684
+ blockHash: "0x8d318f563f5563fa5c213617481089f75aab3a6e9d14818db107ac20a8c20ffb",
1685
+ calldataBytes: 30276
1473
1686
  },
1474
1687
  {
1475
- gasUsed: "2489106",
1476
- transactionHash: "0xb3990edb994011775e275bc1eb38c527b7206a2bfadf510e8aa53e260f3594b8",
1477
- blockNumber: "49",
1478
- blockHash: "0xf8cb019ebb0ecd0ec5d6634198292883c63fe93a7c65c34f9f3120c6cc54f1cf",
1479
- calldataBytes: 17156
1688
+ gasUsed: "3102871",
1689
+ transactionHash: "0xddfc1c6c505f6c54f4d9aabc96a02eb6b606182e8ad708a578eacd274d885dee",
1690
+ blockNumber: "172",
1691
+ blockHash: "0xcc7738fe329a608241615dc43b7d16e075eb62be202ea8aaf4ae27a5278bf438",
1692
+ calldataBytes: 30276
1480
1693
  },
1481
1694
  {
1482
- gasUsed: "2489094",
1483
- transactionHash: "0xc97079019567ff8a79d285421351ee4bc48d14092a0e12ff634151719e991088",
1484
- blockNumber: "49",
1485
- blockHash: "0x5a6947839165c8961eeeb9190331415c40366a78b4a6a5771e7b8954dbb8b3c7",
1486
- calldataBytes: 17156
1695
+ gasUsed: "3103171",
1696
+ transactionHash: "0x6efab6408d927e1877f1f6c33ecd285a128382f7d1dfe6e123927b035781c8aa",
1697
+ blockNumber: "172",
1698
+ blockHash: "0xcb4588df9ecdca0d353ccbd226e1d5d07f21e6dc93875e41cdd5f64568859f4d",
1699
+ calldataBytes: 30276
1487
1700
  }
1488
1701
  ]
1489
1702
  },
1490
1703
  {
1491
- id: "transfer-1x56",
1704
+ id: "draw-credit-12-full",
1492
1705
  shape: {
1493
- kind: "transfer",
1706
+ kind: "draw-credit",
1494
1707
  target: "evm",
1495
- capacity: 112,
1496
- noteInputs: 1,
1497
- noteOutputs: 56,
1708
+ capacity: 12,
1709
+ noteInputs: 0,
1710
+ noteOutputs: 0,
1498
1711
  sourceTrees: 1,
1499
- creditInputs: 0,
1712
+ creditInputs: 12,
1500
1713
  creditOutputs: 0,
1501
1714
  creditRemainders: 0,
1502
1715
  funding: "none",
1503
1716
  permit: false,
1504
- deliveryBytes: 12656
1717
+ deliveryBytes: 0
1505
1718
  },
1506
1719
  circuit: {
1507
- circuitName: "transact_user_slots112",
1720
+ circuitName: "credit_draw_slots12",
1508
1721
  target: "evm",
1509
- artifactSha256: "713b78469b6e97711122210f8497942120c1c9d66d3604bc184566c4eba59cc3",
1510
- vkSha256: "d6a46e297949c28b9a62fd9aef1f202870fdca97b8bfb15beefd27b9e9f3d86e"
1722
+ artifactSha256: "dd72b0867fc3be7cd90de263bd2d0892075cb18eb4f6dd671b13111710f10369",
1723
+ vkSha256: "5e31d771e6294993736078596d9c69f21fe7595eda50e3cce6d7406b65cf1443"
1511
1724
  },
1512
1725
  samples: [
1513
1726
  {
1514
- gasUsed: "5389227",
1515
- transactionHash: "0xb820d3c358724c1d64422017f232d074e4ff1ffaf1b1ce5ee719409427cf2208",
1516
- blockNumber: "49",
1517
- blockHash: "0x474bd1e52457801d1a596a9f23aeb6d365a17be028ee0c8cf8fd4758eaa1106b",
1518
- calldataBytes: 36356
1727
+ gasUsed: "1536675",
1728
+ transactionHash: "0xc0d3eef8e6b0e90984d776a5e41bcdce1e0ca0bc6dc3a71616e4768e80c01546",
1729
+ blockNumber: "172",
1730
+ blockHash: "0x22dfac3d8e9913a6a1f2ff84faaece4ed59bfe1cb74e06a60131ff28cc6c2f9d",
1731
+ calldataBytes: 15684
1519
1732
  },
1520
1733
  {
1521
- gasUsed: "5389095",
1522
- transactionHash: "0x16514d8cf1136d7a7f40591859e2ea2d256af66520498e1fc81eb28837db600d",
1523
- blockNumber: "49",
1524
- blockHash: "0x42314a0d6eb9e765869e1b66b279444c78f919d2c28aed544d9fa7ac3bd2acb4",
1525
- calldataBytes: 36356
1734
+ gasUsed: "1536675",
1735
+ transactionHash: "0x9879d86a1eaa550a6a6afaeeb0f5f07745d5dcd9caa07b660d7fb512911dc67e",
1736
+ blockNumber: "172",
1737
+ blockHash: "0xf88ba9f1b7a0c627338a61bbabe1c650bdfcd7fa1c56433d6853f492135b753d",
1738
+ calldataBytes: 15684
1739
+ },
1740
+ {
1741
+ gasUsed: "1536711",
1742
+ transactionHash: "0xbd8f75a021a8ce8dc1900bd2d84d723acc6a64018844050a5aa2f8712cf7fd6b",
1743
+ blockNumber: "172",
1744
+ blockHash: "0xa55b539c2ea4e10ce9a9ee8e6de9cf1daa97263b51f32cfef8342c100b663b0f",
1745
+ calldataBytes: 15684
1746
+ }
1747
+ ]
1748
+ },
1749
+ {
1750
+ id: "draw-credit-50-partial",
1751
+ shape: {
1752
+ kind: "draw-credit",
1753
+ target: "evm",
1754
+ capacity: 50,
1755
+ noteInputs: 0,
1756
+ noteOutputs: 0,
1757
+ sourceTrees: 1,
1758
+ creditInputs: 50,
1759
+ creditOutputs: 50,
1760
+ creditRemainders: 50,
1761
+ funding: "none",
1762
+ permit: false,
1763
+ deliveryBytes: 56600
1764
+ },
1765
+ circuit: {
1766
+ circuitName: "credit_draw_slots50",
1767
+ target: "evm",
1768
+ artifactSha256: "09c7469866748b4c0c4bbf2b040844771948a170999f6dc7a38fe5c0ecda4054",
1769
+ vkSha256: "7b613225b6f32a077011d4196c356e836d22dcd116efe687fde53144fbd8db9f"
1770
+ },
1771
+ samples: [
1772
+ {
1773
+ gasUsed: "8015473",
1774
+ transactionHash: "0x5dcc0fa08abaf5212424ac6f3e2f3bb8a0bd333f90ef6e421f8d3fe370ca1acf",
1775
+ blockNumber: "172",
1776
+ blockHash: "0x3197c523dece3492226c5021f974e7c02db2e686265943d03a5550c6cb96a12e",
1777
+ calldataBytes: 94276
1778
+ },
1779
+ {
1780
+ gasUsed: "8015449",
1781
+ transactionHash: "0x6a55f88551a45b3e118cde0607cfff1ef0b6ab15ad9472e838412d9ce714b42a",
1782
+ blockNumber: "172",
1783
+ blockHash: "0xea82c8962d45db8361bd67ed326806f21c511bd51550adc453d0c3e5cab3a7ae",
1784
+ calldataBytes: 94276
1785
+ },
1786
+ {
1787
+ gasUsed: "8015149",
1788
+ transactionHash: "0x2cc8d474a92abe91f8025109a70cf1f9f081dbec43aa4a475ab9f33222cfc76b",
1789
+ blockNumber: "172",
1790
+ blockHash: "0x4398f419da699ccca33867852d4975b5c461a40bb01cd5241a0e6dcacaeb78b3",
1791
+ calldataBytes: 94276
1792
+ }
1793
+ ]
1794
+ },
1795
+ {
1796
+ id: "draw-credit-50-full",
1797
+ shape: {
1798
+ kind: "draw-credit",
1799
+ target: "evm",
1800
+ capacity: 50,
1801
+ noteInputs: 0,
1802
+ noteOutputs: 0,
1803
+ sourceTrees: 1,
1804
+ creditInputs: 50,
1805
+ creditOutputs: 0,
1806
+ creditRemainders: 0,
1807
+ funding: "none",
1808
+ permit: false,
1809
+ deliveryBytes: 0
1810
+ },
1811
+ circuit: {
1812
+ circuitName: "credit_draw_slots50",
1813
+ target: "evm",
1814
+ artifactSha256: "09c7469866748b4c0c4bbf2b040844771948a170999f6dc7a38fe5c0ecda4054",
1815
+ vkSha256: "7b613225b6f32a077011d4196c356e836d22dcd116efe687fde53144fbd8db9f"
1816
+ },
1817
+ samples: [
1818
+ {
1819
+ gasUsed: "3216708",
1820
+ transactionHash: "0x16933368d26ea1d7fbe69027c700671df832ad308944eeff42e7c2da40297b06",
1821
+ blockNumber: "172",
1822
+ blockHash: "0x0739a6f4188b8bdeae7bd5460960086d04adfea993d07d65b2b3630ad01b8cab",
1823
+ calldataBytes: 33476
1824
+ },
1825
+ {
1826
+ gasUsed: "3216840",
1827
+ transactionHash: "0x45dc15a62b1661f54e167cf13b9693770370c926a8a7af959da7354e9bb4aa6e",
1828
+ blockNumber: "172",
1829
+ blockHash: "0xf2e294db9af3b11814fed1dec358b8370ea28a99189211f883c9b0012349d677",
1830
+ calldataBytes: 33476
1831
+ },
1832
+ {
1833
+ gasUsed: "3216744",
1834
+ transactionHash: "0x2c827753026ea421497534a01bcc2adaca866a7612f570dad3fcf18c660f8590",
1835
+ blockNumber: "172",
1836
+ blockHash: "0x3ccd465528ff22e6d1955670220df3565899a16dd683f71c83c9810f2df420b4",
1837
+ calldataBytes: 33476
1838
+ }
1839
+ ]
1840
+ },
1841
+ {
1842
+ id: "draw-credit-120-partial",
1843
+ shape: {
1844
+ kind: "draw-credit",
1845
+ target: "evm",
1846
+ capacity: 120,
1847
+ noteInputs: 0,
1848
+ noteOutputs: 0,
1849
+ sourceTrees: 1,
1850
+ creditInputs: 120,
1851
+ creditOutputs: 120,
1852
+ creditRemainders: 120,
1853
+ funding: "none",
1854
+ permit: false,
1855
+ deliveryBytes: 135840
1856
+ },
1857
+ circuit: {
1858
+ circuitName: "credit_draw_slots120",
1859
+ target: "evm",
1860
+ artifactSha256: "6ccd0366a669c50fd5da875c3eae194fe8aa4c36d35a5f9ebfd64636ea599b48",
1861
+ vkSha256: "d715848afc5c1ecdfcef5ed5026865abef5040a3bc232fd65330a5ffee8475fb"
1862
+ },
1863
+ samples: [
1864
+ {
1865
+ gasUsed: "17458512",
1866
+ transactionHash: "0x84dd6bda5f3172a53e899051fd226dc5869edb796bd513a33e7f224bed13f4ae",
1867
+ blockNumber: "172",
1868
+ blockHash: "0xfca82de1e112b92319185d8c3f0115e0aa339d0247ea65970eb0d37ba958b08e",
1869
+ calldataBytes: 211140
1870
+ },
1871
+ {
1872
+ gasUsed: "17458224",
1873
+ transactionHash: "0xae26838942cf8b5499d43cb5e74681ae87aec77890a8eabddd692ff83830e013",
1874
+ blockNumber: "172",
1875
+ blockHash: "0x3e513447e0cfdbb682a95b7a719b0d300ec46b0ee22b518eaae7fb082f6436e7",
1876
+ calldataBytes: 211140
1877
+ },
1878
+ {
1879
+ gasUsed: "17458524",
1880
+ transactionHash: "0xeaa07e77fe958f4317e71b07ddb876482ae9c5172fd6d6cefaacc551dbbda7d5",
1881
+ blockNumber: "172",
1882
+ blockHash: "0x12b34c1fd2e15480276052842157c2a6355acdd43d7bd01ae7511c3f39e0ecfc",
1883
+ calldataBytes: 211140
1884
+ }
1885
+ ]
1886
+ },
1887
+ {
1888
+ id: "draw-credit-120-full",
1889
+ shape: {
1890
+ kind: "draw-credit",
1891
+ target: "evm",
1892
+ capacity: 120,
1893
+ noteInputs: 0,
1894
+ noteOutputs: 0,
1895
+ sourceTrees: 1,
1896
+ creditInputs: 120,
1897
+ creditOutputs: 0,
1898
+ creditRemainders: 0,
1899
+ funding: "none",
1900
+ permit: false,
1901
+ deliveryBytes: 0
1902
+ },
1903
+ circuit: {
1904
+ circuitName: "credit_draw_slots120",
1905
+ target: "evm",
1906
+ artifactSha256: "6ccd0366a669c50fd5da875c3eae194fe8aa4c36d35a5f9ebfd64636ea599b48",
1907
+ vkSha256: "d715848afc5c1ecdfcef5ed5026865abef5040a3bc232fd65330a5ffee8475fb"
1908
+ },
1909
+ samples: [
1910
+ {
1911
+ gasUsed: "6289576",
1912
+ transactionHash: "0xbf11743f7edc5ed5ff334efc5e35634f45e48e4940d33ddd9c87d8fe444dafc5",
1913
+ blockNumber: "172",
1914
+ blockHash: "0x774de17971107b73cab2cd20f26b60665f55a37b0cc1147166babf16743e34d5",
1915
+ calldataBytes: 65220
1916
+ },
1917
+ {
1918
+ gasUsed: "6289768",
1919
+ transactionHash: "0x651bb13e0645ee8a08657db627f1072f5e964ddaff44f70f829440ed68488dea",
1920
+ blockNumber: "172",
1921
+ blockHash: "0xa9795828565fb0ce65bda295073106b8bbdc110bb8317d269839d3db3e312d5b",
1922
+ calldataBytes: 65220
1923
+ },
1924
+ {
1925
+ gasUsed: "6289720",
1926
+ transactionHash: "0x2a859d381cb4b50830971b1ffc9789b11569fc96147e130dae6fecd141f5ceb0",
1927
+ blockNumber: "172",
1928
+ blockHash: "0x7d990830157bfeff8e5cbe580e9effe97faa7676c9957ce32891b76c83961430",
1929
+ calldataBytes: 65220
1930
+ }
1931
+ ]
1932
+ },
1933
+ {
1934
+ id: "top-up-credit-1x1-unchanged-limits",
1935
+ shape: {
1936
+ kind: "top-up-credit",
1937
+ target: "evm",
1938
+ capacity: 10,
1939
+ noteInputs: 1,
1940
+ noteOutputs: 1,
1941
+ sourceTrees: 2,
1942
+ creditInputs: 1,
1943
+ creditOutputs: 1,
1944
+ creditRemainders: 0,
1945
+ funding: "none",
1946
+ permit: false,
1947
+ deliveryBytes: 1360
1948
+ },
1949
+ circuit: {
1950
+ circuitName: "credit_top_up",
1951
+ target: "evm",
1952
+ artifactSha256: "2ffebd5753ec1b0c050204d4f97498765fe61ea01a793a9b2466c2f97536345c",
1953
+ vkSha256: "40b02a9d2e7eb7b49daaac4b7760328537b7982fd5a225cc065bb74cd5ef44b3"
1954
+ },
1955
+ samples: [
1956
+ {
1957
+ gasUsed: "1711282",
1958
+ transactionHash: "0x74d45084bb07bacabbced09ee6ef69d8632a22a4493be783c326c47e929ba0ed",
1959
+ blockNumber: "172",
1960
+ blockHash: "0x3503643f7081b52ae20d4754a0e9b11f52034ae48059f5b5298546c2570fa091",
1961
+ calldataBytes: 12292
1962
+ },
1963
+ {
1964
+ gasUsed: "1711282",
1965
+ transactionHash: "0x4b5e2432d5571f6b56507b3ab995a8120560ba608959ff100f03b87873e72be6",
1966
+ blockNumber: "172",
1967
+ blockHash: "0xca15dc309371a5aa9c7bc5bf1d65c5b325c71528ce7856ba68a118114124fccc",
1968
+ calldataBytes: 12292
1969
+ },
1970
+ {
1971
+ gasUsed: "1711390",
1972
+ transactionHash: "0x304f3740b64c80dcc5c894fb30af59080d96a11e08371096ae695cbc46ef2c8b",
1973
+ blockNumber: "172",
1974
+ blockHash: "0x9671ed76d6b8e49a36ba229d3609289fcf70756f31277ac5fc0e3f08cd52304f",
1975
+ calldataBytes: 12292
1976
+ }
1977
+ ]
1978
+ },
1979
+ {
1980
+ id: "top-up-credit-1x1-changed-limits",
1981
+ shape: {
1982
+ kind: "top-up-credit",
1983
+ target: "evm",
1984
+ capacity: 10,
1985
+ noteInputs: 1,
1986
+ noteOutputs: 1,
1987
+ sourceTrees: 2,
1988
+ creditInputs: 1,
1989
+ creditOutputs: 1,
1990
+ creditRemainders: 0,
1991
+ funding: "none",
1992
+ permit: false,
1993
+ deliveryBytes: 1360
1994
+ },
1995
+ circuit: {
1996
+ circuitName: "credit_top_up",
1997
+ target: "evm",
1998
+ artifactSha256: "2ffebd5753ec1b0c050204d4f97498765fe61ea01a793a9b2466c2f97536345c",
1999
+ vkSha256: "40b02a9d2e7eb7b49daaac4b7760328537b7982fd5a225cc065bb74cd5ef44b3"
2000
+ },
2001
+ samples: [
2002
+ {
2003
+ gasUsed: "1711318",
2004
+ transactionHash: "0x65284df534b42631f8a592fb2a6efc16361a4cc122f1a8dd41418e7b950f48f1",
2005
+ blockNumber: "172",
2006
+ blockHash: "0xf198242a1edf5b133961568c9165648c829729e7bfbbf57a1e148551c971b87c",
2007
+ calldataBytes: 12292
2008
+ },
2009
+ {
2010
+ gasUsed: "1711438",
2011
+ transactionHash: "0xcee89a81e598974798365c4ebada806fb51196ee602334b0fffdbb25da0afe25",
2012
+ blockNumber: "172",
2013
+ blockHash: "0xb506a6fb54cc2f91b803211ed955aac0203fba93e2428f8f52ec0d413c90af09",
2014
+ calldataBytes: 12292
2015
+ },
2016
+ {
2017
+ gasUsed: "1711342",
2018
+ transactionHash: "0x957de5c79f365c9b0510b9e125a662317494aad50cb446edceef6f678d561cc7",
2019
+ blockNumber: "172",
2020
+ blockHash: "0xb1d5cffd6d6db58ade9d5e16d48b060b9ab2152415966dc809e7e70785472ab8",
2021
+ calldataBytes: 12292
2022
+ }
2023
+ ]
2024
+ },
2025
+ {
2026
+ id: "cancel-credit-1",
2027
+ shape: {
2028
+ kind: "cancel-credit",
2029
+ target: "evm",
2030
+ capacity: 1,
2031
+ noteInputs: 0,
2032
+ noteOutputs: 0,
2033
+ sourceTrees: 1,
2034
+ creditInputs: 1,
2035
+ creditOutputs: 0,
2036
+ creditRemainders: 0,
2037
+ funding: "none",
2038
+ permit: false,
2039
+ deliveryBytes: 0
2040
+ },
2041
+ circuit: {
2042
+ circuitName: "credit_cancel",
2043
+ target: "evm",
2044
+ artifactSha256: "b4459c2cf756d096e37291cf4d7cd129866b6d420b6d03c928f383b057112ccb",
2045
+ vkSha256: "fc8ad196ef15f3328afcc8f01d867a3ebefd15451c2813948442fab1923b73b2"
2046
+ },
2047
+ samples: [
2048
+ {
2049
+ gasUsed: "985543",
2050
+ transactionHash: "0x29ca63fbefcc5e92dbc86f67d6280993e567a5dd02ff3defd7f3251ce711865e",
2051
+ blockNumber: "172",
2052
+ blockHash: "0xecd7808fe9f7467af917069bd7a82ab0324e3cbab8dcad622b089d6e3eee9a58",
2053
+ calldataBytes: 9540
2054
+ },
2055
+ {
2056
+ gasUsed: "985795",
2057
+ transactionHash: "0xaf8bca0769330f89b647363f99b752dbbe6fdbb8b1aae912224f6a3a59f40faa",
2058
+ blockNumber: "172",
2059
+ blockHash: "0x58e1358e02f189d57628fa7c504b87fb000fe60eb9f0a0c3c0e58dae876e64da",
2060
+ calldataBytes: 9540
2061
+ },
2062
+ {
2063
+ gasUsed: "985711",
2064
+ transactionHash: "0x2c911fd5a422f6f72f2a00b16872b7e46e182d39b8f5bfa9e3b2bf99d3155da7",
2065
+ blockNumber: "172",
2066
+ blockHash: "0x9da571cbe63f52232261ee1527d5ed97a9e90e374b4fcda97d04feb25114d18e",
2067
+ calldataBytes: 9540
2068
+ }
2069
+ ]
2070
+ }
2071
+ ]
2072
+ },
2073
+ {
2074
+ formatVersion: 1,
2075
+ id: "protocol-92ef274-osaka-real",
2076
+ deployment: {
2077
+ chainId: "31337",
2078
+ protocolAddress: "0x8870C63A18a9480C7de9B860b849fD293832856D",
2079
+ runtimeCodeHash: "0x604572c0da90ea139b774cd0d2962a2972fac46e0556c7cec6f6f9aac5deef14",
2080
+ tokenAddress: "0x4826533B4897376654Bb4d4AD88B7faFD0C98528"
2081
+ },
2082
+ source: {
2083
+ protocolCommit: "92ef274c6b36d783507699a33ee20e52192c83c7",
2084
+ measuredAt: "2026-10-27T08:42:15.991Z",
2085
+ chain: "Anvil 31337",
2086
+ hardfork: "osaka",
2087
+ token: "MockERC20",
2088
+ verifier: "real",
2089
+ assumptions: [
2090
+ "normal CREATE/Factory deployment; no code or storage injection",
2091
+ "Solidity 0.8.27 optimizer 200; real BB 5.2.1 verifiers",
2092
+ "one source tree; two existing leaves; no rollover or screener",
2093
+ "funding/approval setup excluded; complete transaction receipt gas included",
2094
+ "exact allowance for caller funding; configured benchmark payout balances",
2095
+ "observed local samples, not a confidence interval or gas limit"
2096
+ ]
2097
+ },
2098
+ measurements: [
2099
+ {
2100
+ id: "shield-1",
2101
+ shape: {
2102
+ kind: "shield",
2103
+ target: "evm",
2104
+ capacity: 0,
2105
+ noteInputs: 0,
2106
+ noteOutputs: 1,
2107
+ sourceTrees: 0,
2108
+ creditInputs: 0,
2109
+ creditOutputs: 0,
2110
+ creditRemainders: 0,
2111
+ funding: "caller",
2112
+ permit: false,
2113
+ deliveryBytes: 226
2114
+ },
2115
+ circuit: null,
2116
+ samples: [
2117
+ {
2118
+ gasUsed: "649286",
2119
+ transactionHash: "0xcc299d1780ada9a69b1d9f0f3d06a165db15fccbd2b7ff407834f02f5d563a18",
2120
+ blockNumber: "50",
2121
+ blockHash: "0xbcb868e781a20588d2fa099a4d7f87c1600044a2e5ec1e369e384d7a5f22f00a",
2122
+ calldataBytes: 1156
2123
+ },
2124
+ {
2125
+ gasUsed: "649322",
2126
+ transactionHash: "0x95139dff109725989f0769e3e6fb9bd3e7e1bf581fd475f14e822875eb90fda4",
2127
+ blockNumber: "50",
2128
+ blockHash: "0x7ace353fea4fc8c856c0fd45521d200b02619921977709ff4f910e0ff41c06fe",
2129
+ calldataBytes: 1156
2130
+ },
2131
+ {
2132
+ gasUsed: "649322",
2133
+ transactionHash: "0xef578bb38dc8ff8bfd47d2e76e3ab4273019ea9a385f5d2fd99add32ceaecb58",
2134
+ blockNumber: "50",
2135
+ blockHash: "0xded817f8ef89637e2443e3b626c0837f184ca134fe753be913d5570554c649a6",
2136
+ calldataBytes: 1156
2137
+ }
2138
+ ]
2139
+ },
2140
+ {
2141
+ id: "shield-2",
2142
+ shape: {
2143
+ kind: "shield",
2144
+ target: "evm",
2145
+ capacity: 0,
2146
+ noteInputs: 0,
2147
+ noteOutputs: 2,
2148
+ sourceTrees: 0,
2149
+ creditInputs: 0,
2150
+ creditOutputs: 0,
2151
+ creditRemainders: 0,
2152
+ funding: "caller",
2153
+ permit: false,
2154
+ deliveryBytes: 452
2155
+ },
2156
+ circuit: null,
2157
+ samples: [
2158
+ {
2159
+ gasUsed: "757063",
2160
+ transactionHash: "0x024e2dfbd6f50c368e2a4aa347e3029de668f4ebd36b80227aa003bb7ac21c74",
2161
+ blockNumber: "50",
2162
+ blockHash: "0x8ed63973c158d706ac54bb646626e4f0db5777b4bd56d179b94503af6c417c50",
2163
+ calldataBytes: 1668
2164
+ },
2165
+ {
2166
+ gasUsed: "757063",
2167
+ transactionHash: "0x898d852ab28f68adac4d30b160a3dbfee33fa7ca875f70df9eb7763b6b1cd1f0",
2168
+ blockNumber: "50",
2169
+ blockHash: "0x9bb6810de38193933a9f26fa03d3d9bad1ca0151ff5e04544c56520e09da3043",
2170
+ calldataBytes: 1668
1526
2171
  },
1527
2172
  {
1528
- gasUsed: "5389203",
1529
- transactionHash: "0xee69d565a7eafb60ad7a47afe80a49d4fa40b50660669d9141e7dc6f4c3dbe0d",
1530
- blockNumber: "49",
1531
- blockHash: "0x0dcdada663ee04dd63e06fcdb79dacc5623201d29b687f63deede2b4762a994e",
1532
- calldataBytes: 36356
2173
+ gasUsed: "757039",
2174
+ transactionHash: "0x8ff9720e3197aab2d741fbd8d0fa2969203ea8cd051d9649d1e5eb890bcc2be3",
2175
+ blockNumber: "50",
2176
+ blockHash: "0x8604c75eb6363aaae774276e638f5b749aae1f8f815eb99ab1183137eef5730e",
2177
+ calldataBytes: 1668
1533
2178
  }
1534
2179
  ]
1535
2180
  },
1536
2181
  {
1537
- id: "transfer-1x112",
2182
+ id: "shield-10",
1538
2183
  shape: {
1539
- kind: "transfer",
2184
+ kind: "shield",
1540
2185
  target: "evm",
1541
- capacity: 168,
1542
- noteInputs: 1,
1543
- noteOutputs: 112,
1544
- sourceTrees: 1,
2186
+ capacity: 0,
2187
+ noteInputs: 0,
2188
+ noteOutputs: 10,
2189
+ sourceTrees: 0,
1545
2190
  creditInputs: 0,
1546
2191
  creditOutputs: 0,
1547
2192
  creditRemainders: 0,
1548
- funding: "none",
2193
+ funding: "caller",
1549
2194
  permit: false,
1550
- deliveryBytes: 25312
1551
- },
1552
- circuit: {
1553
- circuitName: "transact_user_slots168",
1554
- target: "evm",
1555
- artifactSha256: "f7b3b1384e961367702f544299ca3521d8205fac31b7691c45ff84325d5a31c3",
1556
- vkSha256: "e00181533d7e35d2307570528f9e7f8f88e2909b6ae338d93373b608dea96881"
2195
+ deliveryBytes: 2260
1557
2196
  },
2197
+ circuit: null,
1558
2198
  samples: [
1559
2199
  {
1560
- gasUsed: "9139842",
1561
- transactionHash: "0x09951c4e00b868b6660429d187a482004646e4c84ef341d3b98352c249db6a06",
1562
- blockNumber: "49",
1563
- blockHash: "0xba9da3c08189335acff1eb33554f5f12475e4a6510324cf6ec9eadf340ce15d2",
1564
- calldataBytes: 61444
2200
+ gasUsed: "1692143",
2201
+ transactionHash: "0x6c13db8bd8a8599daf5034e56712abefbf406982fafe7647b6d22291ba4199ed",
2202
+ blockNumber: "50",
2203
+ blockHash: "0x1ab2ae514f408a79e0c40ca10cee74b2e23d7c8a5f24641b8eea3e1cf58ce700",
2204
+ calldataBytes: 5764
1565
2205
  },
1566
2206
  {
1567
- gasUsed: "9139650",
1568
- transactionHash: "0xb06f69d1c6e5406758918d5d296ab889bab4c3814f616cc581ad312cc7ebb2f3",
1569
- blockNumber: "49",
1570
- blockHash: "0x5516a76b4b366f2e539a67bb848b7d232c3e6f328d34ca5bd3dba43a14c316bf",
1571
- calldataBytes: 61444
2207
+ gasUsed: "1692083",
2208
+ transactionHash: "0x5e476c9d3838b782a51332af9bf5c372d29fc411c2168a7af619c52bd5309c7b",
2209
+ blockNumber: "50",
2210
+ blockHash: "0x9c62bc72fc90f990c6711b48865ff922a1856ae05c4fef61dad5f4da7d948401",
2211
+ calldataBytes: 5764
1572
2212
  },
1573
2213
  {
1574
- gasUsed: "9139530",
1575
- transactionHash: "0x116c4875b7712b7cb51cdb0fcb6e66a95733dca272aa272bc0b1fd265edbe26c",
1576
- blockNumber: "49",
1577
- blockHash: "0xd36340fddd1eace21b73f785c6589bf73b07bef782f2e78a5e3d3d828b0b607c",
1578
- calldataBytes: 61444
2214
+ gasUsed: "1692203",
2215
+ transactionHash: "0x0092e2d9160fad95279cde586fc6c79c713244f55db8a2060a5abab9d98c176a",
2216
+ blockNumber: "50",
2217
+ blockHash: "0xac1bf780b4cc05b4dcc7ee5d741c049ba99ab4af9bdcd25104add730c2a14152",
2218
+ calldataBytes: 5764
1579
2219
  }
1580
2220
  ]
1581
2221
  },
1582
2222
  {
1583
- id: "withdraw-1x1",
2223
+ id: "transfer-1x2",
1584
2224
  shape: {
1585
- kind: "withdraw",
2225
+ kind: "transfer",
1586
2226
  target: "evm",
1587
2227
  capacity: 14,
1588
2228
  noteInputs: 1,
1589
- noteOutputs: 1,
2229
+ noteOutputs: 2,
1590
2230
  sourceTrees: 1,
1591
2231
  creditInputs: 0,
1592
2232
  creditOutputs: 0,
1593
2233
  creditRemainders: 0,
1594
2234
  funding: "none",
1595
2235
  permit: false,
1596
- deliveryBytes: 226
2236
+ deliveryBytes: 452
1597
2237
  },
1598
2238
  circuit: {
1599
2239
  circuitName: "transact_user_slots14",
@@ -1603,222 +2243,222 @@ var gas_benchmarks_default = [
1603
2243
  },
1604
2244
  samples: [
1605
2245
  {
1606
- gasUsed: "1597571",
1607
- transactionHash: "0x326892d32146e0bc36b396fd3973151a629312df68ed25a4ffbb6a3da23ba274",
2246
+ gasUsed: "1617516",
2247
+ transactionHash: "0xf49ea3d31cc1346472172e2dee84f9360f60a3fe948a3ef6e87f727af6d42f0d",
1608
2248
  blockNumber: "49",
1609
- blockHash: "0x3e0f326cba3dd019b86431b4c22145758a7f10c121a696a81a094746b04495b5",
1610
- calldataBytes: 10564
2249
+ blockHash: "0xf59c57e63ec2f03abc36d28f273b0af5290184dc97197df740b23d79a851a887",
2250
+ calldataBytes: 11012
1611
2251
  },
1612
2252
  {
1613
- gasUsed: "1597715",
1614
- transactionHash: "0x2e3a15157ac9c07e4717bbd4641481ce3bc0068d26157752815b6ec6b30acdd0",
2253
+ gasUsed: "1617516",
2254
+ transactionHash: "0xf8d11286f1f2a4db006ff6b06900c47d0fbf685984499e1e5d4aea49478ba8e5",
1615
2255
  blockNumber: "49",
1616
- blockHash: "0xab7fceac97d55e8702d1202b98d3a05c4b1e0f71e51b6d88d7e80e91cc338596",
1617
- calldataBytes: 10564
2256
+ blockHash: "0xeb5a800190be3534c9e2675c97ac56d0e0be8adef55f60bd32d375776a7d150c",
2257
+ calldataBytes: 11012
1618
2258
  },
1619
2259
  {
1620
- gasUsed: "1597595",
1621
- transactionHash: "0x5052e94a67520c43416cdcb60a1365a126560861173d0eef46bcbf0a566fe947",
2260
+ gasUsed: "1617504",
2261
+ transactionHash: "0x8939fcea97079a3c5118b9e94325455e2ad1cdb47310ae499a277272654b3eb6",
1622
2262
  blockNumber: "49",
1623
- blockHash: "0x9a64cf76b646b5a07b72fcc61266e87f17365fec891701c331982a93e5ba9b89",
1624
- calldataBytes: 10564
2263
+ blockHash: "0xecffefb593e2fec5d5827cfd39d0cc4d0efb67dbff6f8dbbd0d2db2439a80cf9",
2264
+ calldataBytes: 11012
1625
2265
  }
1626
2266
  ]
1627
2267
  },
1628
2268
  {
1629
- id: "sweep-1x0",
2269
+ id: "transfer-1x14",
1630
2270
  shape: {
1631
- kind: "sweep",
2271
+ kind: "transfer",
1632
2272
  target: "evm",
1633
- capacity: 14,
2273
+ capacity: 56,
1634
2274
  noteInputs: 1,
1635
- noteOutputs: 0,
2275
+ noteOutputs: 14,
1636
2276
  sourceTrees: 1,
1637
2277
  creditInputs: 0,
1638
2278
  creditOutputs: 0,
1639
2279
  creditRemainders: 0,
1640
2280
  funding: "none",
1641
2281
  permit: false,
1642
- deliveryBytes: 0
2282
+ deliveryBytes: 3164
1643
2283
  },
1644
2284
  circuit: {
1645
- circuitName: "transact_user_slots14",
2285
+ circuitName: "transact_user_slots56",
1646
2286
  target: "evm",
1647
- artifactSha256: "2a6a20839e90b88b1ecd629f59a01821bad3ee11dbe04db1fd9cdce7a3de0e84",
1648
- vkSha256: "ffe0e1a4e690792ecb4eb1fc1acc9ff60f13d3b5af03cfc6ae6d6bf26e99bdea"
2287
+ artifactSha256: "ba83ec2f177d16fa88ea04bc54f2e99920f1ac195cdb05b88b9b3bbc245fd953",
2288
+ vkSha256: "6ad5d3aff0c72a632fb19895658af093a6a92478a9994985e838a71e61237720"
1649
2289
  },
1650
2290
  samples: [
1651
2291
  {
1652
- gasUsed: "1069308",
1653
- transactionHash: "0xb1ab469d05ca5f49659f54a332cc172892dcce37e475342fbf52fa9cfb4d3927",
2292
+ gasUsed: "2489010",
2293
+ transactionHash: "0x053557acea930a869d6469c91e9bc015d0893607a6ab18d2af684986f7074676",
1654
2294
  blockNumber: "49",
1655
- blockHash: "0xe5b04579149987198801f1ca19ab771d5262de2aaf9861a6c962d50d1c6baef0",
1656
- calldataBytes: 10116
2295
+ blockHash: "0x734873097eb5e4cb66bfc2cdb61fac6753b53a4b9450fb22895281100af3aaf3",
2296
+ calldataBytes: 17156
1657
2297
  },
1658
2298
  {
1659
- gasUsed: "1069284",
1660
- transactionHash: "0xd6adee997f7e1e19e3918f913f6ee48d94df69c09ed74e333325023089e7f6df",
2299
+ gasUsed: "2489106",
2300
+ transactionHash: "0xb3990edb994011775e275bc1eb38c527b7206a2bfadf510e8aa53e260f3594b8",
1661
2301
  blockNumber: "49",
1662
- blockHash: "0xcb225566f8f1ea6ae8da30158b8f1aef03d50fa4ea352a00aa42b7f41a05d63c",
1663
- calldataBytes: 10116
2302
+ blockHash: "0xf8cb019ebb0ecd0ec5d6634198292883c63fe93a7c65c34f9f3120c6cc54f1cf",
2303
+ calldataBytes: 17156
1664
2304
  },
1665
2305
  {
1666
- gasUsed: "1069308",
1667
- transactionHash: "0xe06dd7f3a2718bc9a9412c2d6f505960ce225b2e5fe6c1c66bb5b0e8f427006f",
2306
+ gasUsed: "2489094",
2307
+ transactionHash: "0xc97079019567ff8a79d285421351ee4bc48d14092a0e12ff634151719e991088",
1668
2308
  blockNumber: "49",
1669
- blockHash: "0x37a08c5918892e1c19df017c746ab0ede03c1bb195c3be593d70c1f9de91897e",
1670
- calldataBytes: 10116
2309
+ blockHash: "0x5a6947839165c8961eeeb9190331415c40366a78b4a6a5771e7b8954dbb8b3c7",
2310
+ calldataBytes: 17156
1671
2311
  }
1672
2312
  ]
1673
2313
  },
1674
2314
  {
1675
- id: "create-credit-1x1",
2315
+ id: "transfer-1x56",
1676
2316
  shape: {
1677
- kind: "create-credit",
2317
+ kind: "transfer",
1678
2318
  target: "evm",
1679
- capacity: 10,
2319
+ capacity: 112,
1680
2320
  noteInputs: 1,
1681
- noteOutputs: 1,
2321
+ noteOutputs: 56,
1682
2322
  sourceTrees: 1,
1683
2323
  creditInputs: 0,
1684
- creditOutputs: 1,
2324
+ creditOutputs: 0,
1685
2325
  creditRemainders: 0,
1686
2326
  funding: "none",
1687
2327
  permit: false,
1688
- deliveryBytes: 1162
2328
+ deliveryBytes: 12656
1689
2329
  },
1690
2330
  circuit: {
1691
- circuitName: "create_credit",
2331
+ circuitName: "transact_user_slots112",
1692
2332
  target: "evm",
1693
- artifactSha256: "ab97cd5a036851a9748a5cfd8e6f9834e23090c8e95db4531aabfc37d3abb353",
1694
- vkSha256: "fac0e65b768a28750323cca851990598af936611125b6cfa3f5c16b04c7d084f"
2333
+ artifactSha256: "713b78469b6e97711122210f8497942120c1c9d66d3604bc184566c4eba59cc3",
2334
+ vkSha256: "d6a46e297949c28b9a62fd9aef1f202870fdca97b8bfb15beefd27b9e9f3d86e"
1695
2335
  },
1696
2336
  samples: [
1697
2337
  {
1698
- gasUsed: "1627325",
1699
- transactionHash: "0x7763d93a5b1e8797b5f4af2e1e5b1bb029a8b0f9f7b90bcc04f581947d826803",
2338
+ gasUsed: "5389227",
2339
+ transactionHash: "0xb820d3c358724c1d64422017f232d074e4ff1ffaf1b1ce5ee719409427cf2208",
1700
2340
  blockNumber: "49",
1701
- blockHash: "0x93e51ae5e99c68dc642693d478e444330d8e26255ff5bb9aafc4a3f4e70d3a45",
1702
- calldataBytes: 11940
2341
+ blockHash: "0x474bd1e52457801d1a596a9f23aeb6d365a17be028ee0c8cf8fd4758eaa1106b",
2342
+ calldataBytes: 36356
1703
2343
  },
1704
2344
  {
1705
- gasUsed: "1627385",
1706
- transactionHash: "0xe246d59cafa2a26dddf21c8385dd843be4d4596388ebe23e936df84e7f906635",
2345
+ gasUsed: "5389095",
2346
+ transactionHash: "0x16514d8cf1136d7a7f40591859e2ea2d256af66520498e1fc81eb28837db600d",
1707
2347
  blockNumber: "49",
1708
- blockHash: "0x3c24b2d6ed2a998562d34b49e0517515742a9b39d59aec38a9ac6b22be1b694b",
1709
- calldataBytes: 11940
2348
+ blockHash: "0x42314a0d6eb9e765869e1b66b279444c78f919d2c28aed544d9fa7ac3bd2acb4",
2349
+ calldataBytes: 36356
1710
2350
  },
1711
2351
  {
1712
- gasUsed: "1627157",
1713
- transactionHash: "0x2f7ed0b75435cc6a820d0cd90fd82d362f74787057413722b6eb3c6e37db87d3",
2352
+ gasUsed: "5389203",
2353
+ transactionHash: "0xee69d565a7eafb60ad7a47afe80a49d4fa40b50660669d9141e7dc6f4c3dbe0d",
1714
2354
  blockNumber: "49",
1715
- blockHash: "0x0a0301670b46017da772800c68bb941245ac1941c79fde9c85717632154e15ee",
1716
- calldataBytes: 11940
2355
+ blockHash: "0x0dcdada663ee04dd63e06fcdb79dacc5623201d29b687f63deede2b4762a994e",
2356
+ calldataBytes: 36356
1717
2357
  }
1718
2358
  ]
1719
2359
  },
1720
2360
  {
1721
- id: "draw-credit-1-partial",
2361
+ id: "transfer-1x112",
1722
2362
  shape: {
1723
- kind: "draw-credit",
2363
+ kind: "transfer",
1724
2364
  target: "evm",
1725
- capacity: 1,
1726
- noteInputs: 0,
1727
- noteOutputs: 0,
2365
+ capacity: 168,
2366
+ noteInputs: 1,
2367
+ noteOutputs: 112,
1728
2368
  sourceTrees: 1,
1729
- creditInputs: 1,
1730
- creditOutputs: 1,
1731
- creditRemainders: 1,
2369
+ creditInputs: 0,
2370
+ creditOutputs: 0,
2371
+ creditRemainders: 0,
1732
2372
  funding: "none",
1733
2373
  permit: false,
1734
- deliveryBytes: 936
2374
+ deliveryBytes: 25312
1735
2375
  },
1736
2376
  circuit: {
1737
- circuitName: "credit_draw_slots1",
2377
+ circuitName: "transact_user_slots168",
1738
2378
  target: "evm",
1739
- artifactSha256: "f5e458790948f37a61a833fad52cf2cc3b26a59515d271de32e0caaa4e229eb5",
1740
- vkSha256: "613699a440f50a0937e4c57e5152b5fdea42c31b10157d6b93226fef313df553"
2379
+ artifactSha256: "f7b3b1384e961367702f544299ca3521d8205fac31b7691c45ff84325d5a31c3",
2380
+ vkSha256: "e00181533d7e35d2307570528f9e7f8f88e2909b6ae338d93373b608dea96881"
1741
2381
  },
1742
2382
  samples: [
1743
2383
  {
1744
- gasUsed: "1581294",
1745
- transactionHash: "0xd438e22b0fa07a657279f182537e4996f1936f0881d5b7d637845f8ca2808aab",
2384
+ gasUsed: "9139842",
2385
+ transactionHash: "0x09951c4e00b868b6660429d187a482004646e4c84ef341d3b98352c249db6a06",
1746
2386
  blockNumber: "49",
1747
- blockHash: "0x9e384a3054530b1ff237a639bca1a559afb2b73b30e21c262aac85ebf480fc9b",
1748
- calldataBytes: 11396
2387
+ blockHash: "0xba9da3c08189335acff1eb33554f5f12475e4a6510324cf6ec9eadf340ce15d2",
2388
+ calldataBytes: 61444
1749
2389
  },
1750
2390
  {
1751
- gasUsed: "1581402",
1752
- transactionHash: "0xa70ac3e7284b6e98f8591a6ba88e4ddfb23ecbd05343641d0532f34920e10b56",
2391
+ gasUsed: "9139650",
2392
+ transactionHash: "0xb06f69d1c6e5406758918d5d296ab889bab4c3814f616cc581ad312cc7ebb2f3",
1753
2393
  blockNumber: "49",
1754
- blockHash: "0x37c5eb34ce96a841e96c36103a7ab65c1a3e08603dc9843efb0c0752c069f1d4",
1755
- calldataBytes: 11396
2394
+ blockHash: "0x5516a76b4b366f2e539a67bb848b7d232c3e6f328d34ca5bd3dba43a14c316bf",
2395
+ calldataBytes: 61444
1756
2396
  },
1757
2397
  {
1758
- gasUsed: "1581174",
1759
- transactionHash: "0xd062494979d0bc0e284ccb070f87b48f3e8e5befb6001f15a006dd2a4a72ca24",
2398
+ gasUsed: "9139530",
2399
+ transactionHash: "0x116c4875b7712b7cb51cdb0fcb6e66a95733dca272aa272bc0b1fd265edbe26c",
1760
2400
  blockNumber: "49",
1761
- blockHash: "0x12840d920f14163b2d29491f28cee616e1bb9fd9514a4debe10ae35256345fc1",
1762
- calldataBytes: 11396
2401
+ blockHash: "0xd36340fddd1eace21b73f785c6589bf73b07bef782f2e78a5e3d3d828b0b607c",
2402
+ calldataBytes: 61444
1763
2403
  }
1764
2404
  ]
1765
2405
  },
1766
2406
  {
1767
- id: "top-up-credit-1x1",
2407
+ id: "withdraw-1x1",
1768
2408
  shape: {
1769
- kind: "top-up-credit",
2409
+ kind: "withdraw",
1770
2410
  target: "evm",
1771
- capacity: 10,
2411
+ capacity: 14,
1772
2412
  noteInputs: 1,
1773
2413
  noteOutputs: 1,
1774
- sourceTrees: 2,
1775
- creditInputs: 1,
1776
- creditOutputs: 1,
2414
+ sourceTrees: 1,
2415
+ creditInputs: 0,
2416
+ creditOutputs: 0,
1777
2417
  creditRemainders: 0,
1778
2418
  funding: "none",
1779
2419
  permit: false,
1780
- deliveryBytes: 1162
2420
+ deliveryBytes: 226
1781
2421
  },
1782
2422
  circuit: {
1783
- circuitName: "credit_top_up",
2423
+ circuitName: "transact_user_slots14",
1784
2424
  target: "evm",
1785
- artifactSha256: "ee9dbcf8be6f6c09478190996e90b1d39d4a10a00245950f69fc1d2c329c6e9b",
1786
- vkSha256: "0c369fec0469b60baebb3be650bad42f3ccae6f0ff139cce6ad9a3f451ed7513"
2425
+ artifactSha256: "2a6a20839e90b88b1ecd629f59a01821bad3ee11dbe04db1fd9cdce7a3de0e84",
2426
+ vkSha256: "ffe0e1a4e690792ecb4eb1fc1acc9ff60f13d3b5af03cfc6ae6d6bf26e99bdea"
1787
2427
  },
1788
2428
  samples: [
1789
2429
  {
1790
- gasUsed: "1666948",
1791
- transactionHash: "0x1403da01167962a4349d2655ea217bfcfc1a2390138bea0279792c44b4381dd2",
2430
+ gasUsed: "1597571",
2431
+ transactionHash: "0x326892d32146e0bc36b396fd3973151a629312df68ed25a4ffbb6a3da23ba274",
1792
2432
  blockNumber: "49",
1793
- blockHash: "0xcb554ffcdb4afe5f6458e5d23ffbdd1fdbef9c23f982343065772c0b3e3dd633",
1794
- calldataBytes: 12100
2433
+ blockHash: "0x3e0f326cba3dd019b86431b4c22145758a7f10c121a696a81a094746b04495b5",
2434
+ calldataBytes: 10564
1795
2435
  },
1796
2436
  {
1797
- gasUsed: "1666900",
1798
- transactionHash: "0x3b5e54f29e3f888a443526cf23ab9255b3f0c7adf1d0d127c16b85f4c6a324d9",
2437
+ gasUsed: "1597715",
2438
+ transactionHash: "0x2e3a15157ac9c07e4717bbd4641481ce3bc0068d26157752815b6ec6b30acdd0",
1799
2439
  blockNumber: "49",
1800
- blockHash: "0xeb304df6bdd24b249cac3197b543b0eaa6381ed75ad812dff248f914864105ed",
1801
- calldataBytes: 12100
2440
+ blockHash: "0xab7fceac97d55e8702d1202b98d3a05c4b1e0f71e51b6d88d7e80e91cc338596",
2441
+ calldataBytes: 10564
1802
2442
  },
1803
2443
  {
1804
- gasUsed: "1666780",
1805
- transactionHash: "0x81c5ef25268a719275cb3b80618c2af291e1f7b3f91d7e82cc26bc894a8c332a",
2444
+ gasUsed: "1597595",
2445
+ transactionHash: "0x5052e94a67520c43416cdcb60a1365a126560861173d0eef46bcbf0a566fe947",
1806
2446
  blockNumber: "49",
1807
- blockHash: "0xfa42070d6349fc8d559b8bd4ad0ee6b79089107540c4472b9e492b8f5a6bd3e4",
1808
- calldataBytes: 12100
2447
+ blockHash: "0x9a64cf76b646b5a07b72fcc61266e87f17365fec891701c331982a93e5ba9b89",
2448
+ calldataBytes: 10564
1809
2449
  }
1810
2450
  ]
1811
2451
  },
1812
2452
  {
1813
- id: "cancel-credit-1",
2453
+ id: "sweep-1x0",
1814
2454
  shape: {
1815
- kind: "cancel-credit",
2455
+ kind: "sweep",
1816
2456
  target: "evm",
1817
- capacity: 1,
1818
- noteInputs: 0,
2457
+ capacity: 14,
2458
+ noteInputs: 1,
1819
2459
  noteOutputs: 0,
1820
2460
  sourceTrees: 1,
1821
- creditInputs: 1,
2461
+ creditInputs: 0,
1822
2462
  creditOutputs: 0,
1823
2463
  creditRemainders: 0,
1824
2464
  funding: "none",
@@ -1826,32 +2466,32 @@ var gas_benchmarks_default = [
1826
2466
  deliveryBytes: 0
1827
2467
  },
1828
2468
  circuit: {
1829
- circuitName: "credit_cancel",
2469
+ circuitName: "transact_user_slots14",
1830
2470
  target: "evm",
1831
- artifactSha256: "d332453a2b8c2c544747ac8d5f01912c9757f48d986226fd6a9b0e24d8321474",
1832
- vkSha256: "1f8a3c20cb081d6a90962556da3124919cc4e5675e59ad31562af39299da02fb"
2471
+ artifactSha256: "2a6a20839e90b88b1ecd629f59a01821bad3ee11dbe04db1fd9cdce7a3de0e84",
2472
+ vkSha256: "ffe0e1a4e690792ecb4eb1fc1acc9ff60f13d3b5af03cfc6ae6d6bf26e99bdea"
1833
2473
  },
1834
2474
  samples: [
1835
2475
  {
1836
- gasUsed: "998146",
1837
- transactionHash: "0x97bc72692d241e2c344b912804f9939061db5ef59cf4bb23922d93812e382160",
2476
+ gasUsed: "1069308",
2477
+ transactionHash: "0xb1ab469d05ca5f49659f54a332cc172892dcce37e475342fbf52fa9cfb4d3927",
1838
2478
  blockNumber: "49",
1839
- blockHash: "0x2e09df4df84a1c25961386febe8404531bb5da274836d50cc15a26c91b433a98",
1840
- calldataBytes: 9540
2479
+ blockHash: "0xe5b04579149987198801f1ca19ab771d5262de2aaf9861a6c962d50d1c6baef0",
2480
+ calldataBytes: 10116
1841
2481
  },
1842
2482
  {
1843
- gasUsed: "998134",
1844
- transactionHash: "0x26c5067b12c2bc4b694070784e6b19d4855efa6e77c2422f0c6b1567f061570a",
2483
+ gasUsed: "1069284",
2484
+ transactionHash: "0xd6adee997f7e1e19e3918f913f6ee48d94df69c09ed74e333325023089e7f6df",
1845
2485
  blockNumber: "49",
1846
- blockHash: "0xdd3f20520c09e001374cab58387e52c82446db053539e30dad28b0de679a333c",
1847
- calldataBytes: 9540
2486
+ blockHash: "0xcb225566f8f1ea6ae8da30158b8f1aef03d50fa4ea352a00aa42b7f41a05d63c",
2487
+ calldataBytes: 10116
1848
2488
  },
1849
2489
  {
1850
- gasUsed: "998230",
1851
- transactionHash: "0x5dc09445a405150da1445c22f50d6dd10d8d428a6a3f41ee90db7d3574657e31",
2490
+ gasUsed: "1069308",
2491
+ transactionHash: "0xe06dd7f3a2718bc9a9412c2d6f505960ce225b2e5fe6c1c66bb5b0e8f427006f",
1852
2492
  blockNumber: "49",
1853
- blockHash: "0x5c8f8223a50d2c8d48188a2db28ffa33c1b150a2fb465e99db4430949db3664b",
1854
- calldataBytes: 9540
2493
+ blockHash: "0x37a08c5918892e1c19df017c746ab0ede03c1bb195c3be593d70c1f9de91897e",
2494
+ calldataBytes: 10116
1855
2495
  }
1856
2496
  ]
1857
2497
  }
@@ -1882,6 +2522,29 @@ function copyGasBenchmarks(profiles) {
1882
2522
  for (const p of copy) {
1883
2523
  if (p.formatVersion !== 1 || !p.id || !decimal.test(p.deployment.chainId) || !address.test(p.deployment.protocolAddress) || !address.test(p.deployment.tokenAddress) || !p.deployment.runtimeCodeHash || !word2.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)
1884
2524
  throw new Error("invalid gas benchmark profile");
2525
+ if (p.source.fingerprints && ![
2526
+ "protocolSourceSha256",
2527
+ "dirtyDiffSha256",
2528
+ "compiledArtifactsSha256",
2529
+ "creditManifestSha256",
2530
+ "userManifestSha256",
2531
+ "sdkSourceSha256"
2532
+ ].every((key) => {
2533
+ const v = p.source.fingerprints[key];
2534
+ return typeof v === "string" && /^[a-f0-9]{64}$/i.test(v);
2535
+ }))
2536
+ throw new Error("invalid benchmark source fingerprint");
2537
+ if (p.source.blockGasLimit !== void 0 && (!decimal.test(p.source.blockGasLimit) || BigInt(p.source.blockGasLimit) <= 0n))
2538
+ throw new Error("invalid benchmark block gas limit");
2539
+ if (p.source.runtimeContracts && !Object.values(p.source.runtimeContracts).every(
2540
+ (v) => address.test(v.address) && word2.test(v.runtimeCodeHash)
2541
+ ))
2542
+ throw new Error("invalid benchmark runtime identity");
2543
+ if (p.source.toolchain && (!["solidity", "barretenberg", "noir", "evmVersion", "anvil"].every((key) => {
2544
+ const v = p.source.toolchain[key];
2545
+ return typeof v === "string" && v.length > 0;
2546
+ }) || !Number.isSafeInteger(p.source.toolchain.optimizerRuns) || p.source.toolchain.optimizerRuns < 0))
2547
+ throw new Error("invalid benchmark toolchain");
1885
2548
  for (const m of p.measurements) {
1886
2549
  if (!m.id || !m.samples.length || !["none", "caller", "signature"].includes(m.shape.funding) || typeof m.shape.permit !== "boolean")
1887
2550
  throw new Error("invalid gas benchmark measurement");
@@ -1961,11 +2624,20 @@ function estimateBenchmarkGas(plan, protocol, profiles) {
1961
2624
  );
1962
2625
  if (!request.deployment.runtimeCodeHash || !candidates.length)
1963
2626
  return { ...base, available: false, reason: "deployment-not-covered" };
1964
- for (const profile of candidates) {
1965
- const measurement = profile.measurements.find(
2627
+ const exact = candidates.flatMap(
2628
+ (profile) => profile.measurements.filter(
1966
2629
  (m) => shapeKeys.every((key) => m.shape[key] === request.shape[key]) && sameCircuit(m.circuit, request.circuit)
1967
- );
1968
- if (!measurement) continue;
2630
+ ).map((measurement) => ({ profile, measurement }))
2631
+ );
2632
+ const mean = (measurement) => {
2633
+ const count = BigInt(measurement.samples.length);
2634
+ return (measurement.samples.reduce((sum, s) => sum + BigInt(s.gasUsed), 0n) + count - 1n) / count;
2635
+ };
2636
+ exact.sort(
2637
+ (a, b) => mean(a.measurement) > mean(b.measurement) ? -1 : mean(a.measurement) < mean(b.measurement) ? 1 : a.measurement.id.localeCompare(b.measurement.id)
2638
+ );
2639
+ if (exact.length) {
2640
+ const { profile, measurement } = exact[0];
1969
2641
  const gas = measurement.samples.map((sample) => BigInt(sample.gasUsed));
1970
2642
  const count = BigInt(gas.length);
1971
2643
  return {
@@ -1995,14 +2667,20 @@ function estimateShapeGas(request, profiles = defaultProfiles) {
1995
2667
  const matching = measurements.filter(
1996
2668
  (measurement) => measurement.shape.kind === request.shape.kind && measurement.shape.target === request.shape.target && sameCircuit(measurement.circuit, request.circuit)
1997
2669
  );
1998
- const exact = matching.find(
2670
+ const exact = matching.filter(
1999
2671
  (measurement) => shapeKeys.every((key) => measurement.shape[key] === request.shape[key])
2000
2672
  );
2001
- if (exact) {
2002
- const gas = exact.samples.map((sample) => BigInt(sample.gasUsed));
2003
- const count = BigInt(gas.length);
2004
- return { gasUnits: (gas.reduce((sum, value) => sum + value, 0n) + count - 1n) / count };
2673
+ if (exact.length) {
2674
+ const means = exact.map((m) => {
2675
+ const count = BigInt(m.samples.length);
2676
+ return (m.samples.reduce((sum, s) => sum + BigInt(s.gasUsed), 0n) + count - 1n) / count;
2677
+ });
2678
+ return { gasUnits: means.reduce((max, v) => v > max ? v : max) };
2005
2679
  }
2680
+ if (["create-credit", "draw-credit", "top-up-credit", "cancel-credit"].includes(
2681
+ request.shape.kind
2682
+ ) && !matching.length)
2683
+ throw new Error("No current Credit gas reference for this artifact and verification key");
2006
2684
  const candidates = matching.length ? matching : measurements.filter(
2007
2685
  (measurement) => measurement.shape.kind === request.shape.kind && measurement.shape.target === request.shape.target
2008
2686
  );
@@ -2017,7 +2695,22 @@ function estimateShapeGas(request, profiles = defaultProfiles) {
2017
2695
  "deliveryBytes",
2018
2696
  ...!matching.length ? ["capacity"] : []
2019
2697
  ];
2020
- const estimates = candidates.map((measurement) => {
2698
+ const groups = /* @__PURE__ */ new Map();
2699
+ for (const candidate of candidates) {
2700
+ const key = JSON.stringify([
2701
+ shapeKeys.map((k) => candidate.shape[k]),
2702
+ candidate.circuit?.circuitName,
2703
+ candidate.circuit?.target,
2704
+ candidate.circuit?.artifactSha256.toLowerCase(),
2705
+ candidate.circuit?.vkSha256.toLowerCase()
2706
+ ]);
2707
+ const previous = groups.get(key);
2708
+ groups.set(
2709
+ key,
2710
+ previous ? { ...candidate, samples: [...previous.samples, ...candidate.samples] } : candidate
2711
+ );
2712
+ }
2713
+ const estimates = [...groups.values()].map((measurement) => {
2021
2714
  let numerator = 1n;
2022
2715
  let denominator = 1n;
2023
2716
  for (const key of dimensions) {
@@ -2048,7 +2741,8 @@ function estimateGasReference(plan, protocol, profiles) {
2048
2741
 
2049
2742
  // src/session/operation-execution.ts
2050
2743
  var import_ethers6 = require("ethers");
2051
- var import_core3 = require("@invisi-labs/core");
2744
+ var import_core5 = require("@invisi-labs/core");
2745
+ var import_protocol3 = require("@invisi-labs/protocol");
2052
2746
 
2053
2747
  // src/session/proof-integrity.ts
2054
2748
  var import_ethers5 = require("ethers");
@@ -2077,23 +2771,41 @@ async function authorizeOperation(plan, provider) {
2077
2771
  if (provider.walletIdentity !== plan.scope.walletIdentity)
2078
2772
  throw new Error("wallet authorization capability mismatch");
2079
2773
  const request = authorizationRequest(plan);
2080
- const digest = (0, import_core3.computeWalletAuthorizationDigest)(request);
2774
+ const digest = (0, import_core5.computeWalletAuthorizationDigest)(request);
2081
2775
  const signed = await provider.authorize(structuredClone(request));
2082
2776
  if (signed.walletIdentity !== plan.scope.walletIdentity || signed.digest !== digest)
2083
2777
  throw new Error("wallet authorization statement mismatch");
2084
2778
  return signed;
2085
2779
  }
2086
2780
  async function proveOperation(protocol, plan, authorization, prover, options) {
2781
+ if (Object.hasOwn(options, "target")) {
2782
+ throw new Error("prove accepts execution, not a backend target");
2783
+ }
2784
+ const { execution = "single", ...proverOptions } = options;
2785
+ if (execution !== "single" && execution !== "aggregate") {
2786
+ throw new Error("execution must be single or aggregate");
2787
+ }
2788
+ const frozen = statement(plan);
2789
+ if (execution === "aggregate" && (plan.kind !== "transfer" || plan.capacity !== 14)) {
2790
+ throw new Error("aggregate execution requires a 14-slot transfer");
2791
+ }
2792
+ if (plan.kind === "transfer") {
2793
+ plan.statement = import_protocol3.WitnessBuilder.statement(
2794
+ frozen.circuitName,
2795
+ frozen.expectedPublicInputs,
2796
+ execution === "aggregate" ? "noir-recursive" : "evm"
2797
+ );
2798
+ }
2087
2799
  const request = await witnessFor(protocol, plan, authorization);
2088
2800
  if (JSON.stringify({ ...request, witness: void 0 }) !== JSON.stringify(plan.statement))
2089
2801
  throw new Error("prepared proof statement changed");
2090
2802
  try {
2091
- const proof = publicProof(await prover.prove(request, options));
2803
+ const proof = publicProof(await prover.prove(request, proverOptions));
2092
2804
  sameStatement(proof, plan.statement);
2093
2805
  if (await prover.verify(
2094
2806
  structuredClone(proof),
2095
2807
  structuredClone(plan.statement),
2096
- options
2808
+ proverOptions
2097
2809
  ) !== true)
2098
2810
  throw new Error("proof verification failed");
2099
2811
  return proof;
@@ -2108,19 +2820,88 @@ async function signOperationFunding(saved, signer, verifier) {
2108
2820
  throw new Error("funding signer is not the payer");
2109
2821
  const typed = await fundingTypedData(saved);
2110
2822
  const signature = await signer.signTypedData(structuredClone(typed));
2823
+ return verifyFundingSignature(typed, payer, signature, verifier);
2824
+ }
2825
+ function walletSigningRequest(plan) {
2826
+ return (0, import_core5.createSigningRequest)((0, import_core5.walletAuthorizationTypedData)(authorizationRequest(plan)));
2827
+ }
2828
+ async function acceptWalletSignature(plan, signature) {
2829
+ const request = authorizationRequest(plan);
2830
+ const digest = (0, import_core5.computeWalletAuthorizationDigest)(request);
2831
+ try {
2832
+ const signed = import_ethers6.Signature.from(signature);
2833
+ const publicKey = (0, import_ethers6.getBytes)(import_ethers6.SigningKey.recoverPublicKey(digest, signed));
2834
+ const owner = await (0, import_core5.computeWalletIdentity)(publicKey);
2835
+ if (owner.toLowerCase() !== plan.scope.walletIdentity.toLowerCase()) {
2836
+ throw new Error("wallet signature identity mismatch");
2837
+ }
2838
+ return new import_core5.AuthorizedStatement(plan.scope.walletIdentity, digest, {
2839
+ public_key_x: Array.from(publicKey.slice(1, 33)),
2840
+ public_key_y: Array.from(publicKey.slice(33)),
2841
+ signature: Array.from((0, import_ethers6.getBytes)((0, import_ethers6.concat)([signed.r, signed.s])))
2842
+ });
2843
+ } catch {
2844
+ throw new Error("invalid wallet authorization signature");
2845
+ }
2846
+ }
2847
+ async function fundingSigningRequest(saved, runtime) {
2848
+ const plan = saved.plan;
2849
+ if (plan.fundingMode !== "signature") {
2850
+ throw new Error("operation does not require a funding signature");
2851
+ }
2852
+ if (plan.kind !== "shield" && !saved.proof) {
2853
+ throw new Error("proof must precede funding authorization");
2854
+ }
2855
+ await runtime.options.protocol.validateDeployment(runtime.reader);
2856
+ const block = await runtime.reader.getBlock(await runtime.reader.getLatestBlockNumber());
2857
+ if (block.timestamp > plan.deadline || block.timestamp > (plan.funding.deadline ?? 0n)) {
2858
+ throw new Error("funding authorization expired");
2859
+ }
2860
+ if (await runtime.reader.getFundingNonce(plan.context, plan.funding.payer, block) !== plan.funding.sigNonce) {
2861
+ throw new Error("funding nonce changed; prepare again");
2862
+ }
2863
+ const request = (0, import_core5.createSigningRequest)(await fundingTypedData(saved));
2864
+ if ((await runtime.reader.getBlock(block.number)).hash !== block.hash) {
2865
+ throw new Error("canonical funding block changed");
2866
+ }
2867
+ return request;
2868
+ }
2869
+ async function acceptFundingSignature(saved, signature, runtime) {
2870
+ if (!/^0x(?:[a-fA-F0-9]{2})+$/.test(signature)) {
2871
+ throw new Error("invalid EVM funding signature");
2872
+ }
2873
+ const request = await fundingSigningRequest(saved, runtime);
2874
+ return verifyFundingSignature(
2875
+ request,
2876
+ saved.plan.funding.payer,
2877
+ signature,
2878
+ runtime.options.fundingVerifier
2879
+ );
2880
+ }
2881
+ async function verifyFundingSignature(request, payer, signature, verifier) {
2882
+ if (!/^0x(?:[a-fA-F0-9]{2})+$/.test(signature)) {
2883
+ throw new Error("invalid EVM funding signature");
2884
+ }
2885
+ const types = Object.fromEntries(
2886
+ Object.entries(request.types).map(([name, fields]) => [name, [...fields]])
2887
+ );
2888
+ let validEOA = false;
2889
+ try {
2890
+ validEOA = (0, import_ethers6.verifyTypedData)(request.domain, types, request.message, signature).toLowerCase() === payer.toLowerCase();
2891
+ if (validEOA) {
2892
+ signature = import_ethers6.Signature.from(signature).serialized;
2893
+ }
2894
+ } catch {
2895
+ validEOA = false;
2896
+ }
2111
2897
  const valid = verifier ? await verifier.verifyTypedData({
2112
- ...structuredClone(typed),
2898
+ ...structuredClone(request),
2113
2899
  address: payer,
2114
2900
  signature
2115
- }) : (0, import_ethers6.verifyTypedData)(
2116
- typed.domain,
2117
- Object.fromEntries(
2118
- Object.entries(typed.types).map(([name, fields]) => [name, [...fields]])
2119
- ),
2120
- typed.message,
2121
- signature
2122
- ).toLowerCase() === payer.toLowerCase();
2123
- if (valid !== true) throw new Error("invalid EVM funding signature");
2901
+ }) : validEOA;
2902
+ if (valid !== true) {
2903
+ throw new Error("invalid EVM funding signature");
2904
+ }
2124
2905
  return signature;
2125
2906
  }
2126
2907
 
@@ -2161,16 +2942,16 @@ function operationPreview(plan, status) {
2161
2942
  }
2162
2943
 
2163
2944
  // src/session/Operation.ts
2164
- var import_core7 = require("@invisi-labs/core");
2165
- var import_protocol4 = require("@invisi-labs/protocol");
2945
+ var import_core9 = require("@invisi-labs/core");
2946
+ var import_protocol5 = require("@invisi-labs/protocol");
2166
2947
 
2167
2948
  // src/session/operation-confirmation.ts
2168
- var import_core6 = require("@invisi-labs/core");
2949
+ var import_core8 = require("@invisi-labs/core");
2169
2950
 
2170
2951
  // src/session/aggregate-receipt.ts
2171
2952
  var import_ethers7 = require("ethers");
2172
2953
  var import_contracts3 = require("@invisi-labs/protocol/contracts");
2173
- var import_protocol3 = require("@invisi-labs/protocol");
2954
+ var import_protocol4 = require("@invisi-labs/protocol");
2174
2955
  var aggregateAbi = import_contracts3.invisiProtocolAbi.filter(
2175
2956
  (item) => item.type === "function" && item.name === "transact" && item.inputs.length === 2 && item.inputs[1]?.type === "tuple[]"
2176
2957
  );
@@ -2198,7 +2979,7 @@ function matchesAggregateTransaction(saved, transaction) {
2198
2979
  });
2199
2980
  if (decoded.name !== "transact" || !Array.isArray(requests) || ![4, 8, 12].includes(requests.length))
2200
2981
  return false;
2201
- const canonical2 = (request) => (0, import_protocol3.buildTransactCalldata)({
2982
+ const canonical2 = (request) => (0, import_protocol4.buildTransactCalldata)({
2202
2983
  context: { ...plan.context, tokenAddress: request.params.token },
2203
2984
  proof: "0x00",
2204
2985
  params: request.params,
@@ -2206,7 +2987,7 @@ function matchesAggregateTransaction(saved, transaction) {
2206
2987
  funding: request.funding,
2207
2988
  caller: transaction.from
2208
2989
  }).data.toLowerCase();
2209
- const expected = (0, import_protocol3.buildTransactCalldata)({
2990
+ const expected = (0, import_protocol4.buildTransactCalldata)({
2210
2991
  context: plan.context,
2211
2992
  proof: "0x00",
2212
2993
  params: plan.params,
@@ -2221,10 +3002,10 @@ function matchesAggregateTransaction(saved, transaction) {
2221
3002
  }
2222
3003
 
2223
3004
  // src/session/credit-values.ts
2224
- var import_core4 = require("@invisi-labs/core");
3005
+ var import_core6 = require("@invisi-labs/core");
2225
3006
  async function creditLeaf(state) {
2226
3007
  const n = state.note;
2227
- return (0, import_core4.computeCreditCommitment)(
3008
+ return (0, import_core6.computeCreditCommitment)(
2228
3009
  n.chainId,
2229
3010
  n.spenderWalletIdentity,
2230
3011
  n.ownerWalletIdentity,
@@ -2234,22 +3015,23 @@ async function creditLeaf(state) {
2234
3015
  n.amount,
2235
3016
  n.nonce,
2236
3017
  n.expiry,
2237
- await (0, import_core4.computeCreditSharedKeyHash)(n.creditSharedKey)
3018
+ await (0, import_core6.computeCreditSharedKeyHash)(n.creditSharedKey),
3019
+ n
2238
3020
  );
2239
3021
  }
2240
3022
 
2241
3023
  // src/session/membership.ts
2242
- var import_core5 = require("@invisi-labs/core");
3024
+ var import_core7 = require("@invisi-labs/core");
2243
3025
  async function verifyMembership(reader, context, block, input, proof) {
2244
3026
  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))
2245
3027
  throw new Error("membership context/root mismatch");
2246
3028
  let root = BigInt(input.commitment);
2247
3029
  for (let i = 0; i < 16; i++) {
2248
3030
  const sibling = proof.path[i];
2249
- if (typeof sibling !== "bigint" || sibling < 0n || sibling >= import_core5.FIELD_MODULUS)
3031
+ if (typeof sibling !== "bigint" || sibling < 0n || sibling >= import_core7.FIELD_MODULUS)
2250
3032
  throw new Error("noncanonical membership path");
2251
3033
  root = BigInt(
2252
- await (0, import_core5.poseidonHash)(input.leafIndex >> i & 1 ? [sibling, root] : [root, sibling])
3034
+ await (0, import_core7.poseidonHash)(input.leafIndex >> i & 1 ? [sibling, root] : [root, sibling])
2253
3035
  );
2254
3036
  }
2255
3037
  if (root !== BigInt(proof.root))
@@ -2421,7 +3203,7 @@ async function confirmOperation(runtime, id, generation, hash2, signal) {
2421
3203
  if (credits.length) {
2422
3204
  const nullifiers = await Promise.all(
2423
3205
  credits.map(
2424
- async (record) => (0, import_core6.computeCreditNullifier)(
3206
+ async (record) => (0, import_core8.computeCreditNullifier)(
2425
3207
  plan.context.chainId,
2426
3208
  record.state.note.creditSharedKey,
2427
3209
  await creditLeaf(record.state)
@@ -2722,6 +3504,81 @@ var Operation = class _Operation {
2722
3504
  throw error;
2723
3505
  }
2724
3506
  }
3507
+ async signingCurrent() {
3508
+ await this.#runtime.store.transaction(this.#runtime.scope, (state) => {
3509
+ check6(!state.invalidated, "wallet state requires canonical resync");
3510
+ this.current(state.operations[this.id]);
3511
+ });
3512
+ }
3513
+ /** Public EIP-712 request; signing transport and key custody belong to the caller. */
3514
+ async exportWalletAuthorization(options = {}) {
3515
+ options.signal?.throwIfAborted();
3516
+ await this.signingCurrent();
3517
+ check6(
3518
+ requiresAuthorization(this.#saved.plan),
3519
+ "operation does not require wallet authorization"
3520
+ );
3521
+ check6(
3522
+ ["prepared", "authorized"].includes(this.status),
3523
+ "operation is not awaiting wallet authorization"
3524
+ );
3525
+ return walletSigningRequest(this.#saved.plan);
3526
+ }
3527
+ /** Attach an external EOA signature, retaining its witness only at the private proving boundary. */
3528
+ async withWalletSignature(signature, options = {}) {
3529
+ options.signal?.throwIfAborted();
3530
+ await this.signingCurrent();
3531
+ check6(
3532
+ requiresAuthorization(this.#saved.plan),
3533
+ "operation does not require wallet authorization"
3534
+ );
3535
+ check6(
3536
+ ["prepared", "authorized"].includes(this.status),
3537
+ "operation is not awaiting wallet authorization"
3538
+ );
3539
+ const authorization = await acceptWalletSignature(this.#saved.plan, signature);
3540
+ return this.stage(
3541
+ "wallet authorization",
3542
+ ["prepared", "authorized"],
3543
+ async () => ({ status: "authorized", authorization }),
3544
+ options.signal
3545
+ );
3546
+ }
3547
+ /** Export only after proving when the funding authorization binds an actual proof hash. */
3548
+ async exportFundingAuthorization(options = {}) {
3549
+ options.signal?.throwIfAborted();
3550
+ await this.signingCurrent();
3551
+ check6(
3552
+ this.status === (this.kind === "shield" ? "prepared" : "proved"),
3553
+ "operation is not awaiting funding authorization or proof"
3554
+ );
3555
+ const request = await fundingSigningRequest(this.#saved, this.#runtime);
3556
+ options.signal?.throwIfAborted();
3557
+ await this.signingCurrent();
3558
+ return request;
3559
+ }
3560
+ /** Verify an external signature against this handle's own frozen operation. */
3561
+ async withFundingSignature(signature, options = {}) {
3562
+ options.signal?.throwIfAborted();
3563
+ await this.signingCurrent();
3564
+ check6(
3565
+ this.status === (this.kind === "shield" ? "prepared" : "proved"),
3566
+ "operation is not awaiting funding authorization or proof"
3567
+ );
3568
+ const verified = await acceptFundingSignature(this.#saved, signature, this.#runtime);
3569
+ return this.stage(
3570
+ "funding authorization",
3571
+ this.kind === "shield" ? ["prepared"] : ["proved"],
3572
+ async (saved) => {
3573
+ saved.plan.funding.signature = verified;
3574
+ if (saved.plan.statement?.target !== "noir-recursive") {
3575
+ saved.call = await this.encode(saved);
3576
+ }
3577
+ return { status: "ready" };
3578
+ },
3579
+ options.signal
3580
+ );
3581
+ }
2725
3582
  async authorize(options = {}) {
2726
3583
  check6(
2727
3584
  requiresAuthorization(this.#saved.plan),
@@ -2742,7 +3599,8 @@ var Operation = class _Operation {
2742
3599
  options.signal
2743
3600
  );
2744
3601
  }
2745
- async prove(options = {}) {
3602
+ async prove(suppliedOptions = {}) {
3603
+ const options = { ...suppliedOptions };
2746
3604
  const plan = this.#saved.plan;
2747
3605
  check6(plan.kind !== "shield", "shield requires no proof");
2748
3606
  if (requiresAuthorization(plan)) {
@@ -2753,7 +3611,7 @@ var Operation = class _Operation {
2753
3611
  }
2754
3612
  const prover = this.#runtime.options.prover;
2755
3613
  if (!prover) {
2756
- throw new import_core7.MissingCapabilityError("prover");
3614
+ throw new import_core9.MissingCapabilityError("prover");
2757
3615
  }
2758
3616
  return this.stage(
2759
3617
  "proof",
@@ -2787,7 +3645,7 @@ var Operation = class _Operation {
2787
3645
  check6(p.kind === "shield" || this.#saved.proof, "proof must precede funding authorization");
2788
3646
  const signer = this.#runtime.options.fundingSigner;
2789
3647
  if (!signer) {
2790
- throw new import_core7.MissingCapabilityError("EVM funding signer");
3648
+ throw new import_core9.MissingCapabilityError("EVM funding signer");
2791
3649
  }
2792
3650
  check6(
2793
3651
  signer.address.toLowerCase() === p.funding.payer.toLowerCase(),
@@ -2889,7 +3747,7 @@ var Operation = class _Operation {
2889
3747
  request: {
2890
3748
  params: structuredClone(plan.params),
2891
3749
  deliveries: plan.outputs.map((output) => structuredClone(output.delivery)),
2892
- funding: (0, import_protocol4.normalizeFunding)(plan.funding)
3750
+ funding: (0, import_protocol5.normalizeFunding)(plan.funding)
2893
3751
  }
2894
3752
  };
2895
3753
  });
@@ -2976,18 +3834,181 @@ var Operation = class _Operation {
2976
3834
  }
2977
3835
  };
2978
3836
 
3837
+ // src/session/WalletSession.ts
3838
+ var import_core16 = require("@invisi-labs/core");
3839
+
3840
+ // src/session/history.ts
3841
+ function walletHistory(state, options = {}) {
3842
+ const token = options.tokenAddress?.toLowerCase();
3843
+ const outgoing = [];
3844
+ for (const record of Object.values(state.operations)) {
3845
+ const saved = record.payload;
3846
+ if (!saved?.plan || token && saved.plan.context.tokenAddress.toLowerCase() !== token) {
3847
+ continue;
3848
+ }
3849
+ const plan = saved.plan;
3850
+ outgoing.push({
3851
+ ...operationPreview(plan, record.status),
3852
+ preparedAt: { ...plan.preparedAt },
3853
+ ...record.transactionHash ? { transactionHash: record.transactionHash } : {},
3854
+ outputs: plan.outputs.map((output) => ({
3855
+ to: output.address,
3856
+ amount: output.note.amount,
3857
+ change: output.change,
3858
+ commitment: output.commitment,
3859
+ payload: Uint8Array.from(output.note.payload ?? [])
3860
+ }))
3861
+ });
3862
+ }
3863
+ outgoing.sort(
3864
+ (a, b) => a.preparedAt.number === b.preparedAt.number ? a.id.localeCompare(b.id) : a.preparedAt.number > b.preparedAt.number ? -1 : 1
3865
+ );
3866
+ const incoming = [];
3867
+ for (const record of Object.values(state.notes)) {
3868
+ const tokenAddress = `0x${record.note.tokenAddress.toString(16).padStart(40, "0")}`;
3869
+ if (token && tokenAddress !== token) continue;
3870
+ incoming.push({
3871
+ commitment: record.commitment,
3872
+ treeId: record.treeId,
3873
+ leafIndex: record.leafIndex,
3874
+ blockNumber: record.blockNumber,
3875
+ blockHash: record.blockHash,
3876
+ ...record.transactionHash ? { transactionHash: record.transactionHash } : {},
3877
+ tokenAddress,
3878
+ amount: record.note.amount,
3879
+ payload: Uint8Array.from(record.note.payload ?? []),
3880
+ spent: record.spent
3881
+ });
3882
+ }
3883
+ incoming.sort(
3884
+ (a, b) => a.blockNumber === b.blockNumber ? a.commitment.localeCompare(b.commitment) : a.blockNumber > b.blockNumber ? -1 : 1
3885
+ );
3886
+ return structuredClone({
3887
+ revision: state.revision,
3888
+ checkedThrough: state.discoveryThrough ?? null,
3889
+ invalidated: !!state.invalidated,
3890
+ outgoing,
3891
+ incoming
3892
+ });
3893
+ }
3894
+
3895
+ // src/errors.ts
3896
+ var import_core10 = require("@invisi-labs/core");
3897
+ var InvisiError = class extends Error {
3898
+ code;
3899
+ operation;
3900
+ address;
3901
+ outputIndex;
3902
+ field;
3903
+ capability;
3904
+ constructor(code, message, details = {}) {
3905
+ super(message, { cause: details.cause });
3906
+ this.name = "InvisiError";
3907
+ this.code = code;
3908
+ this.operation = details.operation;
3909
+ this.address = details.address;
3910
+ this.outputIndex = details.outputIndex;
3911
+ this.field = details.field;
3912
+ this.capability = details.capability;
3913
+ }
3914
+ };
3915
+ async function prepareWithErrors(operation, prepare) {
3916
+ try {
3917
+ return await prepare();
3918
+ } catch (cause) {
3919
+ if (cause instanceof InvisiError) {
3920
+ if (cause.operation) throw cause;
3921
+ throw new InvisiError(cause.code, cause.message, {
3922
+ operation,
3923
+ ...cause.address === void 0 ? {} : { address: cause.address },
3924
+ ...cause.outputIndex === void 0 ? {} : { outputIndex: cause.outputIndex },
3925
+ ...cause.field === void 0 ? {} : { field: cause.field },
3926
+ ...cause.capability === void 0 ? {} : { capability: cause.capability },
3927
+ cause: cause.cause
3928
+ });
3929
+ }
3930
+ throw new InvisiError(
3931
+ cause instanceof import_core10.MissingCapabilityError ? "MISSING_CAPABILITY" : "PREPARATION_FAILED",
3932
+ cause instanceof Error ? cause.message : "Transaction preparation failed",
3933
+ {
3934
+ operation,
3935
+ cause,
3936
+ ...cause instanceof import_core10.MissingCapabilityError ? { capability: cause.capability } : {}
3937
+ }
3938
+ );
3939
+ }
3940
+ }
3941
+
2979
3942
  // src/session/WalletSession.ts
2980
3943
  var import_ethers11 = require("ethers");
2981
- var import_core12 = require("@invisi-labs/core");
3944
+ var import_core17 = require("@invisi-labs/core");
2982
3945
 
2983
3946
  // src/session/transaction-preparation.ts
2984
3947
  var import_ethers10 = require("ethers");
2985
- var import_protocol7 = require("@invisi-labs/protocol");
3948
+ var import_protocol8 = require("@invisi-labs/protocol");
3949
+
3950
+ // src/resolve-recipient.ts
3951
+ var import_core11 = require("@invisi-labs/core");
3952
+ async function resolveRecipient(address2, lookup, details = {}) {
3953
+ const context = { ...details, address: address2 };
3954
+ let recipient;
3955
+ try {
3956
+ recipient = import_core11.ReceivingAddress.parse(address2);
3957
+ } catch (cause) {
3958
+ throw new InvisiError("INVALID_RECIPIENT", "Invalid recipient address", {
3959
+ ...context,
3960
+ cause
3961
+ });
3962
+ }
3963
+ if (recipient.kind === "long") return recipient;
3964
+ if (!lookup) {
3965
+ throw new InvisiError("MISSING_CAPABILITY", "Missing registry lookup capability", {
3966
+ ...context,
3967
+ capability: "registry lookup"
3968
+ });
3969
+ }
3970
+ let keys;
3971
+ try {
3972
+ keys = await lookup(recipient.walletIdentity);
3973
+ } catch (cause) {
3974
+ if (cause instanceof import_core11.MissingCapabilityError) {
3975
+ throw new InvisiError("MISSING_CAPABILITY", cause.message, {
3976
+ ...context,
3977
+ cause,
3978
+ capability: cause.capability
3979
+ });
3980
+ }
3981
+ throw new InvisiError("RECIPIENT_LOOKUP_FAILED", "Recipient registry lookup failed", {
3982
+ ...context,
3983
+ cause
3984
+ });
3985
+ }
3986
+ if (keys == null) {
3987
+ throw new InvisiError(
3988
+ "EVM_ADDRESS_NOT_REGISTERED",
3989
+ "EVM address has no registered receiving keys",
3990
+ context
3991
+ );
3992
+ }
3993
+ try {
3994
+ return import_core11.ReceivingAddress.from({
3995
+ walletIdentity: recipient.walletIdentity,
3996
+ viewingPublicKey: keys.viewingPublicKey,
3997
+ clueKey: keys.clueKey
3998
+ });
3999
+ } catch (cause) {
4000
+ throw new InvisiError(
4001
+ "RECIPIENT_LOOKUP_FAILED",
4002
+ "Registry returned invalid receiving keys",
4003
+ { ...context, cause }
4004
+ );
4005
+ }
4006
+ }
2986
4007
 
2987
4008
  // src/session/prepare-common.ts
2988
4009
  var import_ethers8 = require("ethers");
2989
- var import_core8 = require("@invisi-labs/core");
2990
- var import_protocol5 = require("@invisi-labs/protocol");
4010
+ var import_core12 = require("@invisi-labs/core");
4011
+ var import_protocol6 = require("@invisi-labs/protocol");
2991
4012
 
2992
4013
  // src/session/selection.ts
2993
4014
  function selectNotes(notes, target, reserved) {
@@ -3020,6 +4041,27 @@ function positiveAmount(value, bits = 128) {
3020
4041
  }
3021
4042
  return value;
3022
4043
  }
4044
+ function copyApplicationPayload(value) {
4045
+ if (value === void 0) return new Uint8Array();
4046
+ if (!(value instanceof Uint8Array)) throw new TypeError("payload must be Uint8Array");
4047
+ return Uint8Array.from(value);
4048
+ }
4049
+ function positiveOutputAmount(payment, outputIndex) {
4050
+ try {
4051
+ return positiveAmount(payment.amount);
4052
+ } catch (cause) {
4053
+ throw new InvisiError(
4054
+ "PREPARATION_FAILED",
4055
+ cause instanceof Error ? cause.message : "Invalid output amount",
4056
+ {
4057
+ address: payment.to,
4058
+ field: "amount",
4059
+ ...outputIndex === void 0 ? {} : { outputIndex },
4060
+ cause
4061
+ }
4062
+ );
4063
+ }
4064
+ }
3023
4065
  var Preparation = class {
3024
4066
  constructor(runtime) {
3025
4067
  this.runtime = runtime;
@@ -3042,7 +4084,15 @@ var Preparation = class {
3042
4084
  throw new Error("canonical wallet checkpoint changed; resync required");
3043
4085
  }
3044
4086
  }
3045
- return { context: { ...options.protocol.context, now: block.timestamp }, block, deadline };
4087
+ return {
4088
+ context: {
4089
+ ...options.protocol.context,
4090
+ now: block.timestamp,
4091
+ timestamp: block.timestamp
4092
+ },
4093
+ block,
4094
+ deadline
4095
+ };
3046
4096
  }
3047
4097
  async assertBlock(frame) {
3048
4098
  if ((await this.runtime.reader.getBlock(frame.block.number)).hash !== frame.block.hash) {
@@ -3065,7 +4115,7 @@ var Preparation = class {
3065
4115
  if (mode === "caller" && (source.sigNonce || source.deadline)) {
3066
4116
  throw new Error("caller funding uses zero nonce/deadline");
3067
4117
  }
3068
- const funding = (0, import_protocol5.normalizeFunding)({
4118
+ const funding = (0, import_protocol6.normalizeFunding)({
3069
4119
  payer,
3070
4120
  amount: source.amount,
3071
4121
  sigNonce: mode === "caller" ? 0n : source.sigNonce ?? await this.runtime.reader.getFundingNonce(
@@ -3081,52 +4131,70 @@ var Preparation = class {
3081
4131
  }
3082
4132
  return { funding, fundingMode: mode };
3083
4133
  }
3084
- async output(payment, context, change = false) {
3085
- positiveAmount(payment.amount);
3086
- const recipient = await import_core8.ReceivingAddress.parse(payment.to).resolve(
3087
- this.runtime.options.addressResolver
3088
- );
3089
- const memo = (0, import_core8.encodeMemo)(payment.memo);
3090
- const nonce = (0, import_core8.generateNonce)();
3091
- const identity = await (0, import_core8.computeNoteIdentity)(BigInt(recipient.walletIdentity), nonce);
3092
- const keys = recipient.getReceivingKeys();
3093
- const note = {
3094
- chainId: context.chainId,
3095
- protocolAddress: BigInt(context.protocolAddress),
3096
- tokenAddress: BigInt(context.tokenAddress),
3097
- walletIdentity: recipient.walletIdentity,
3098
- amount: payment.amount,
3099
- ...memo.length === 0 ? {} : { memo },
3100
- nonce
3101
- };
3102
- const commitment = await (0, import_core8.computeNoteCommitment)(
3103
- context.chainId,
3104
- identity,
3105
- note.tokenAddress,
3106
- note.amount
3107
- );
3108
- return {
3109
- note,
3110
- commitment,
3111
- identity,
3112
- address: payment.to,
3113
- change,
3114
- delivery: {
3115
- ciphertext: (0, import_ethers8.hexlify)(
3116
- await (0, import_core8.encryptPrivateTransferNote)(keys.viewingPublicKey, note, {
3117
- chainId: context.chainId,
3118
- protocolAddress: note.protocolAddress,
3119
- outputCommitment: commitment
3120
- })
3121
- ),
3122
- clue: (0, import_ethers8.hexlify)((0, import_core8.createClue)(keys.clueKey))
3123
- }
3124
- };
4134
+ async output(payment, context, change = false, outputIndex) {
4135
+ try {
4136
+ positiveOutputAmount(payment, outputIndex);
4137
+ const recipient = await resolveRecipient(
4138
+ payment.to,
4139
+ this.runtime.options.addressResolver,
4140
+ {
4141
+ field: change ? "changeAddress" : "to",
4142
+ ...outputIndex === void 0 ? {} : { outputIndex }
4143
+ }
4144
+ );
4145
+ const nonce = (0, import_core12.generateNonce)();
4146
+ const identity = await (0, import_core12.computeNoteIdentity)(BigInt(recipient.walletIdentity), nonce);
4147
+ const keys = recipient.getReceivingKeys();
4148
+ const note = {
4149
+ chainId: context.chainId,
4150
+ protocolAddress: BigInt(context.protocolAddress),
4151
+ tokenAddress: BigInt(context.tokenAddress),
4152
+ walletIdentity: recipient.walletIdentity,
4153
+ amount: payment.amount,
4154
+ payload: copyApplicationPayload(payment.payload),
4155
+ nonce
4156
+ };
4157
+ const commitment = await (0, import_core12.computeNoteCommitment)(
4158
+ context.chainId,
4159
+ identity,
4160
+ note.tokenAddress,
4161
+ note.amount
4162
+ );
4163
+ return {
4164
+ note,
4165
+ commitment,
4166
+ identity,
4167
+ address: payment.to,
4168
+ change,
4169
+ delivery: {
4170
+ ciphertext: (0, import_ethers8.hexlify)(
4171
+ await (0, import_core12.encryptPrivateTransferNote)(keys.viewingPublicKey, note, {
4172
+ chainId: context.chainId,
4173
+ protocolAddress: note.protocolAddress,
4174
+ outputCommitment: commitment
4175
+ })
4176
+ ),
4177
+ clue: (0, import_ethers8.hexlify)((0, import_core12.createClue)(keys.clueKey))
4178
+ }
4179
+ };
4180
+ } catch (cause) {
4181
+ if (cause instanceof InvisiError) throw cause;
4182
+ throw new InvisiError(
4183
+ "PREPARATION_FAILED",
4184
+ cause instanceof Error ? cause.message : "Output preparation failed",
4185
+ {
4186
+ address: payment.to,
4187
+ field: change ? "changeAddress" : "to",
4188
+ ...outputIndex === void 0 ? {} : { outputIndex },
4189
+ cause
4190
+ }
4191
+ );
4192
+ }
3125
4193
  }
3126
4194
  async membership(input, frame) {
3127
4195
  const { options, reader } = this.runtime;
3128
4196
  if (!options.protocolRpc)
3129
- throw new import_core8.MissingCapabilityError("Protocol RPC membership provider");
4197
+ throw new import_core12.MissingCapabilityError("Protocol RPC membership provider");
3130
4198
  const root = this.#roots.get(input.treeId);
3131
4199
  const proof = await options.protocolRpc.getMembership(
3132
4200
  frame.context,
@@ -3173,9 +4241,9 @@ var Preparation = class {
3173
4241
  for (const input of selected) {
3174
4242
  const note = input.note;
3175
4243
  const c = frame.context;
3176
- if (note.walletIdentity !== scope.walletIdentity || note.chainId !== c.chainId || note.protocolAddress !== BigInt(c.protocolAddress) || note.tokenAddress !== BigInt(c.tokenAddress) || await (0, import_core8.computeNoteCommitment)(
4244
+ if (note.walletIdentity !== scope.walletIdentity || note.chainId !== c.chainId || note.protocolAddress !== BigInt(c.protocolAddress) || note.tokenAddress !== BigInt(c.tokenAddress) || await (0, import_core12.computeNoteCommitment)(
3177
4245
  c.chainId,
3178
- await (0, import_core8.computeNoteIdentity)(BigInt(note.walletIdentity), note.nonce),
4246
+ await (0, import_core12.computeNoteIdentity)(BigInt(note.walletIdentity), note.nonce),
3179
4247
  note.tokenAddress,
3180
4248
  note.amount
3181
4249
  ) !== input.commitment) {
@@ -3227,8 +4295,8 @@ function storedCandidates(inputs) {
3227
4295
 
3228
4296
  // src/session/prepare-credit.ts
3229
4297
  var import_ethers9 = require("ethers");
3230
- var import_core9 = require("@invisi-labs/core");
3231
- var import_protocol6 = require("@invisi-labs/protocol");
4298
+ var import_core13 = require("@invisi-labs/core");
4299
+ var import_protocol7 = require("@invisi-labs/protocol");
3232
4300
  var EMPTY = { ciphertext: "0x", clue: "0x" };
3233
4301
  var CreditPreparation = class {
3234
4302
  constructor(runtime) {
@@ -3243,7 +4311,7 @@ var CreditPreparation = class {
3243
4311
  return value;
3244
4312
  }
3245
4313
  async seal(input, frame) {
3246
- const state = (0, import_core9.normalizeCreditDeliveryState)(input);
4314
+ const state = (0, import_core13.normalizeCreditDeliveryState)(input);
3247
4315
  const commitment = await creditLeaf(state);
3248
4316
  const context = {
3249
4317
  chainId: frame.context.chainId,
@@ -3255,9 +4323,9 @@ var CreditPreparation = class {
3255
4323
  const keys = role === "owner" ? state.ownerReceivingKeys : state.spenderReceivingKeys;
3256
4324
  return {
3257
4325
  ciphertext: (0, import_ethers9.hexlify)(
3258
- await (0, import_core9.encryptCreditNote)(keys.viewingPublicKey, state, { ...context, role })
4326
+ await (0, import_core13.encryptCreditNote)(keys.viewingPublicKey, state, { ...context, role })
3259
4327
  ),
3260
- clue: (0, import_ethers9.hexlify)((0, import_core9.createClue)(keys.clueKey))
4328
+ clue: (0, import_ethers9.hexlify)((0, import_core13.createClue)(keys.clueKey))
3261
4329
  };
3262
4330
  })
3263
4331
  );
@@ -3268,14 +4336,14 @@ var CreditPreparation = class {
3268
4336
  if (!stored || stored.spent !== "unspent" || stored.role !== role) {
3269
4337
  throw new Error(`confirmed unspent ${role} Credit is unavailable`);
3270
4338
  }
3271
- const state = (0, import_core9.normalizeCreditDeliveryState)(stored.state);
4339
+ const state = (0, import_core13.normalizeCreditDeliveryState)(stored.state);
3272
4340
  const n = state.note;
3273
4341
  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) {
3274
4342
  throw new Error("Credit role, commitment or deployment mismatch");
3275
4343
  }
3276
4344
  const proof = await this.#prepare.membership(stored, frame);
3277
4345
  const path = [...proof.path];
3278
- const nullifier = await (0, import_core9.computeCreditNullifier)(n.chainId, n.creditSharedKey, commitment);
4346
+ const nullifier = await (0, import_core13.computeCreditNullifier)(n.chainId, n.creditSharedKey, commitment);
3279
4347
  await this.#prepare.assertUnspent([nullifier], frame);
3280
4348
  return {
3281
4349
  input: {
@@ -3312,10 +4380,16 @@ var CreditPreparation = class {
3312
4380
  positiveAmount(options.amount, 126);
3313
4381
  const frame = await this.#prepare.frame(options.deadline);
3314
4382
  const expiry = this.expiry(options.expiry, frame);
3315
- const spender = await import_core9.ReceivingAddress.parse(options.spender).resolve(
3316
- this.runtime.options.addressResolver
4383
+ const spender = await resolveRecipient(
4384
+ options.spender,
4385
+ this.runtime.options.addressResolver,
4386
+ { field: "spender" }
4387
+ );
4388
+ const owner = await resolveRecipient(
4389
+ this.runtime.options.wallet.getReceivingAddress().toString(),
4390
+ this.runtime.options.addressResolver,
4391
+ { field: "wallet" }
3317
4392
  );
3318
- const owner = await this.runtime.options.wallet.getReceivingAddress().resolve(this.runtime.options.addressResolver);
3319
4393
  const ownerPayout = (0, import_ethers9.getAddress)(owner.walletIdentity);
3320
4394
  const spenderPayout = (0, import_ethers9.getAddress)(spender.walletIdentity);
3321
4395
  if (BigInt(ownerPayout) === 0n || BigInt(spenderPayout) === 0n) {
@@ -3331,11 +4405,16 @@ var CreditPreparation = class {
3331
4405
  spenderWalletIdentity: spender.walletIdentity,
3332
4406
  ownerPayout: BigInt(ownerPayout),
3333
4407
  spenderPayout: BigInt(spenderPayout),
4408
+ ...(0, import_core13.normalizeCreditPolicy)({
4409
+ singleLimit: options.singleLimit ?? 0n,
4410
+ dailyLimit: options.dailyLimit ?? 0n,
4411
+ monthlyLimit: options.monthlyLimit ?? 0n
4412
+ }),
3334
4413
  amount: options.amount,
3335
- ...options.memo === void 0 ? {} : { memo: options.memo },
4414
+ payload: copyApplicationPayload(options.payload),
3336
4415
  expiry,
3337
- nonce: (0, import_core9.generateNonce)(),
3338
- creditSharedKey: (0, import_core9.generateCreditSharedKey)()
4416
+ nonce: (0, import_core13.generateNonce)(),
4417
+ creditSharedKey: (0, import_core13.generateCreditSharedKey)()
3339
4418
  },
3340
4419
  ownerReceivingKeys: owner.getReceivingKeys(),
3341
4420
  spenderReceivingKeys: spender.getReceivingKeys()
@@ -3377,7 +4456,7 @@ var CreditPreparation = class {
3377
4456
  sources: selected.sources,
3378
4457
  nullifiers: selected.nullifiers,
3379
4458
  creditCommitment: output.commitment,
3380
- changeCommitment: plan.outputs[0]?.commitment ?? (0, import_protocol6.word)(0n),
4459
+ changeCommitment: plan.outputs[0]?.commitment ?? (0, import_protocol7.word)(0n),
3381
4460
  owner: (0, import_ethers9.getAddress)((0, import_ethers9.toBeHex)(output.state.note.ownerPayout, 20)),
3382
4461
  expiry: output.state.note.expiry,
3383
4462
  deadline: frame.deadline
@@ -3397,14 +4476,14 @@ var CreditPreparation = class {
3397
4476
  creditNullifier: previous.nullifier,
3398
4477
  previousExpiry: previous.input.state.note.expiry
3399
4478
  };
3400
- plan.statement = import_protocol6.WitnessBuilder.statement(
4479
+ plan.statement = import_protocol7.WitnessBuilder.statement(
3401
4480
  "credit_top_up",
3402
- (0, import_protocol6.topUpCreditPublicInputs)(frame.context, plan.credit.topUp, deliveries, plan.funding)
4481
+ (0, import_protocol7.topUpCreditPublicInputs)(frame.context, plan.credit.topUp, deliveries, plan.funding)
3403
4482
  );
3404
4483
  } else {
3405
- plan.statement = import_protocol6.WitnessBuilder.statement(
4484
+ plan.statement = import_protocol7.WitnessBuilder.statement(
3406
4485
  "create_credit",
3407
- (0, import_protocol6.createCreditPublicInputs)(frame.context, creation, deliveries, plan.funding)
4486
+ (0, import_protocol7.createCreditPublicInputs)(frame.context, creation, deliveries, plan.funding)
3408
4487
  );
3409
4488
  }
3410
4489
  await this.#prepare.assertBlock(frame);
@@ -3428,10 +4507,15 @@ var CreditPreparation = class {
3428
4507
  ...old,
3429
4508
  note: {
3430
4509
  ...old.note,
4510
+ singleLimit: options.singleLimit ?? old.note.singleLimit ?? 0n,
4511
+ dailyLimit: options.dailyLimit ?? old.note.dailyLimit ?? 0n,
4512
+ monthlyLimit: options.monthlyLimit ?? old.note.monthlyLimit ?? 0n,
3431
4513
  amount,
3432
4514
  expiry,
3433
- nonce: (0, import_core9.generateNonce)(),
3434
- ...options.memo === void 0 ? {} : { memo: options.memo }
4515
+ nonce: (0, import_core13.generateNonce)(),
4516
+ payload: copyApplicationPayload(
4517
+ options.payload === void 0 ? old.note.payload : options.payload
4518
+ )
3435
4519
  }
3436
4520
  },
3437
4521
  frame
@@ -3447,7 +4531,7 @@ var CreditPreparation = class {
3447
4531
  }
3448
4532
  async draw(options) {
3449
4533
  const frame = await this.#prepare.frame(options.deadline);
3450
- const profile = (0, import_protocol6.selectCreditDrawCircuit)(options.credits.length);
4534
+ const profile = (0, import_protocol7.selectCreditDrawCircuit)(options.credits.length);
3451
4535
  if (new Set(options.credits.map((value) => value.credit)).size !== options.credits.length) {
3452
4536
  throw new Error("duplicate Credit input");
3453
4537
  }
@@ -3479,10 +4563,11 @@ var CreditPreparation = class {
3479
4563
  }
3480
4564
  sources.set(member.source.treeId, member.source.merkleRoot);
3481
4565
  amounts.push(amount);
4566
+ const usage = (0, import_core13.applyCreditDrawUsage)(n, amount, frame.block.timestamp);
3482
4567
  const remaining = n.amount - amount;
3483
4568
  if (remaining === 0n) {
3484
- remainders.push((0, import_protocol6.word)(0n));
3485
- recoveryAmounts.push((0, import_protocol6.word)(0n));
4569
+ remainders.push((0, import_protocol7.word)(0n));
4570
+ recoveryAmounts.push((0, import_protocol7.word)(0n));
3486
4571
  deliveries.push({ ...EMPTY }, { ...EMPTY });
3487
4572
  continue;
3488
4573
  }
@@ -3498,9 +4583,12 @@ var CreditPreparation = class {
3498
4583
  ...state,
3499
4584
  note: {
3500
4585
  ...n,
4586
+ ...usage,
3501
4587
  amount: remaining,
3502
- ...options.credits[i].memo === void 0 ? {} : { memo: options.credits[i].memo },
3503
- nonce: await (0, import_core9.deriveRemainderNonce)(...args)
4588
+ payload: copyApplicationPayload(
4589
+ options.credits[i].payload === void 0 ? n.payload : options.credits[i].payload
4590
+ ),
4591
+ nonce: await (0, import_core13.deriveRemainderNonce)(...args)
3504
4592
  }
3505
4593
  },
3506
4594
  frame
@@ -3508,7 +4596,7 @@ var CreditPreparation = class {
3508
4596
  outputs.push(output);
3509
4597
  remainders.push(output.commitment);
3510
4598
  recoveryAmounts.push(
3511
- (0, import_protocol6.word)((remaining + await (0, import_core9.computeCreditRecoveryPad)(...args)) % import_core9.FIELD_MODULUS)
4599
+ (0, import_protocol7.word)((remaining + await (0, import_core13.computeCreditRecoveryPad)(...args)) % import_core13.FIELD_MODULUS)
3512
4600
  );
3513
4601
  deliveries.push(...output.deliveries);
3514
4602
  }
@@ -3532,9 +4620,9 @@ var CreditPreparation = class {
3532
4620
  draw: params,
3533
4621
  amounts
3534
4622
  };
3535
- plan.statement = import_protocol6.WitnessBuilder.statement(
4623
+ plan.statement = import_protocol7.WitnessBuilder.statement(
3536
4624
  profile.name,
3537
- (0, import_protocol6.creditDrawPublicInputs)(frame.context, params, deliveries)
4625
+ (0, import_protocol7.creditDrawPublicInputs)(frame.context, params, deliveries)
3538
4626
  );
3539
4627
  await this.#prepare.assertBlock(frame);
3540
4628
  return this.runtime.complete(plan);
@@ -3554,9 +4642,9 @@ var CreditPreparation = class {
3554
4642
  };
3555
4643
  plan.capacity = 1;
3556
4644
  plan.credit = { inputs: [previous.input], outputs: [], deliveries: [], cancel: params };
3557
- plan.statement = import_protocol6.WitnessBuilder.statement(
4645
+ plan.statement = import_protocol7.WitnessBuilder.statement(
3558
4646
  "credit_cancel",
3559
- (0, import_protocol6.cancelCreditPublicInputs)(frame.context, params)
4647
+ (0, import_protocol7.cancelCreditPublicInputs)(frame.context, params)
3560
4648
  );
3561
4649
  await this.#prepare.assertBlock(frame);
3562
4650
  return this.runtime.complete(plan);
@@ -3577,87 +4665,48 @@ var TransactionPreparation = class {
3577
4665
  return this.context.scope;
3578
4666
  }
3579
4667
  async prepareTransfer(options) {
4668
+ if (Object.hasOwn(options, "target") || Object.hasOwn(options, "execution")) {
4669
+ throw new Error(
4670
+ "prepareTransfer accepts no target or execution; choose execution in prove()"
4671
+ );
4672
+ }
3580
4673
  const copied = structuredClone(options);
3581
- const preparation = new Preparation(this.runtime(copied.tokenAddress));
4674
+ const runtime = this.runtime(copied.tokenAddress);
4675
+ if (copied.commitments !== void 0 && copied.commitments.length === 0)
4676
+ throw new Error("empty explicit input selection");
4677
+ const preparation = new Preparation({
4678
+ ...runtime,
4679
+ ...copied.commitments !== void 0 ? { inputSelection: copied.commitments } : {}
4680
+ });
3582
4681
  const frame = await preparation.frame(copied.deadline);
3583
- if (copied.outputs.length < 1 || copied.outputs.length > 168) {
3584
- throw new Error("transfer requires 1..168 outputs");
4682
+ if (copied.outputs.length > 168) throw new Error("transfer supports at most 168 outputs");
4683
+ let withdrawalAddress = import_protocol8.ZERO_ADDRESS;
4684
+ let withdrawalAmount = 0n;
4685
+ if (copied.withdrawal !== void 0) {
4686
+ withdrawalAddress = (0, import_ethers10.getAddress)(copied.withdrawal.to);
4687
+ positiveAmount(copied.withdrawal.amount);
4688
+ if (BigInt(withdrawalAddress) === 0n)
4689
+ throw new Error("withdrawal destination must be nonzero");
4690
+ withdrawalAmount = copied.withdrawal.amount;
3585
4691
  }
4692
+ if (copied.outputs.length === 0 && withdrawalAmount === 0n)
4693
+ throw new Error("transfer requires a private output or public withdrawal");
3586
4694
  const total = copied.outputs.reduce(
3587
- (sum, output) => sum + positiveAmount(output.amount),
3588
- 0n
4695
+ (sum, output, index2) => sum + positiveOutputAmount(output, index2),
4696
+ withdrawalAmount
3589
4697
  );
3590
4698
  const funding = await preparation.funding(copied.funding, frame);
3591
4699
  return this.funds(
3592
- "transfer",
3593
4700
  copied.outputs,
3594
4701
  total,
3595
- import_protocol7.ZERO_ADDRESS,
3596
- 0n,
4702
+ withdrawalAddress,
4703
+ withdrawalAmount,
3597
4704
  frame,
3598
4705
  funding,
3599
- copied.target,
3600
- preparation
3601
- );
3602
- }
3603
- async prepareWithdraw(options) {
3604
- const copied = structuredClone(options);
3605
- const preparation = new Preparation(this.runtime(copied.tokenAddress));
3606
- const frame = await preparation.frame(copied.deadline);
3607
- const to = (0, import_ethers10.getAddress)(copied.to);
3608
- positiveAmount(copied.amount);
3609
- if (BigInt(to) === 0n) {
3610
- throw new Error("withdrawal destination must be nonzero");
3611
- }
3612
- return this.funds(
3613
- "withdraw",
3614
- [],
3615
- copied.amount,
3616
- to,
3617
- copied.amount,
3618
- frame,
3619
- { funding: {}, fundingMode: "none" },
3620
- copied.target,
3621
- preparation
3622
- );
3623
- }
3624
- /** Full payout to the note owner; no arbitrary destination, change or spending signature. */
3625
- async prepareSweep(options) {
3626
- const copied = structuredClone(options);
3627
- const runtime = this.runtime(copied.tokenAddress);
3628
- const state = await runtime.readInventory();
3629
- const available = Object.values(state.notes).filter(
3630
- (record) => record.note.tokenAddress === BigInt(copied.tokenAddress) && record.spent === "unspent" && !state.reservations[record.commitment]
3631
- );
3632
- const selected = copied.commitments ?? available.map((record) => record.commitment);
3633
- if (selected.length === 0) throw new Error("empty sweep input selection");
3634
- if (new Set(selected).size !== selected.length) throw new Error("duplicate sweep inputs");
3635
- const byId = new Map(available.map((record) => [record.commitment, record]));
3636
- let amount = 0n;
3637
- for (const id of selected) {
3638
- const record = byId.get(id);
3639
- if (!record) throw new Error("sweep input unavailable");
3640
- amount += record.note.amount;
3641
- }
3642
- positiveAmount(amount);
3643
- const preparation = new Preparation({
3644
- ...runtime,
3645
- inputSelection: selected
3646
- });
3647
- const frame = await preparation.frame(copied.deadline);
3648
- return this.funds(
3649
- "sweep",
3650
- [],
3651
- amount,
3652
- this.scope.walletIdentity,
3653
- amount,
3654
- frame,
3655
- { funding: {}, fundingMode: "none" },
3656
- copied.target,
3657
4706
  preparation
3658
4707
  );
3659
4708
  }
3660
- async funds(kind, payments, total, withdrawalAddress, withdrawalAmount, frame, funding, target, preparation) {
4709
+ async funds(payments, total, withdrawalAddress, withdrawalAmount, frame, funding, preparation) {
3661
4710
  if (total >= 1n << 135n) {
3662
4711
  throw new Error("transaction sum exceeds uint135");
3663
4712
  }
@@ -3667,7 +4716,7 @@ var TransactionPreparation = class {
3667
4716
  frame
3668
4717
  );
3669
4718
  const outputs = await Promise.all(
3670
- payments.map((payment) => preparation.output(payment, context))
4719
+ payments.map((payment, index2) => preparation.output(payment, context, false, index2))
3671
4720
  );
3672
4721
  const change = selection.amount + (funding.funding.amount ?? 0n) - total;
3673
4722
  if (change > 0n) {
@@ -3692,17 +4741,17 @@ var TransactionPreparation = class {
3692
4741
  deadline
3693
4742
  };
3694
4743
  const deliveries = outputs.map((output) => output.delivery);
3695
- const normalized = (0, import_protocol7.normalizeTransactRequest)(context, params, deliveries, funding.funding);
3696
- const statement2 = import_protocol7.WitnessBuilder.statement(
4744
+ const normalized = (0, import_protocol8.normalizeTransactRequest)(context, params, deliveries, funding.funding);
4745
+ const statement2 = import_protocol8.WitnessBuilder.statement(
3697
4746
  `transact_user_slots${normalized.capacity}`,
3698
- (0, import_protocol7.transactUserPublicInputs)(context, params, deliveries, funding.funding),
3699
- target ?? "evm"
4747
+ (0, import_protocol8.transactUserPublicInputs)(context, params, deliveries, funding.funding),
4748
+ "evm"
3700
4749
  );
3701
4750
  await preparation.assertBlock(frame);
3702
4751
  return preparation.runtime.complete({
3703
4752
  version: 1,
3704
4753
  id: crypto.randomUUID(),
3705
- kind,
4754
+ kind: "transfer",
3706
4755
  context,
3707
4756
  scope: this.scope,
3708
4757
  preparedAt: block,
@@ -3724,7 +4773,9 @@ var TransactionPreparation = class {
3724
4773
  throw new Error("shield requires 1..10 outputs");
3725
4774
  }
3726
4775
  const outputs = await Promise.all(
3727
- copied.outputs.map((output) => preparation.output(output, frame.context))
4776
+ copied.outputs.map(
4777
+ (output, index2) => preparation.output(output, frame.context, false, index2)
4778
+ )
3728
4779
  );
3729
4780
  if (outputs.reduce((sum, output) => sum + output.note.amount, 0n) !== (funding.funding.amount ?? 0n)) {
3730
4781
  throw new Error("shield funding must equal output total");
@@ -3829,10 +4880,10 @@ async function refreshWallet(runtime, options) {
3829
4880
  }
3830
4881
 
3831
4882
  // src/session/WalletUpdater.ts
3832
- var import_core11 = require("@invisi-labs/core");
4883
+ var import_core15 = require("@invisi-labs/core");
3833
4884
 
3834
4885
  // src/session/inventory.ts
3835
- var import_core10 = require("@invisi-labs/core");
4886
+ var import_core14 = require("@invisi-labs/core");
3836
4887
  var CanonicalConflict = class extends Error {
3837
4888
  };
3838
4889
  var CreditMetadataMismatch = class extends Error {
@@ -3884,10 +4935,10 @@ var InventoryProcessor = class {
3884
4935
  }
3885
4936
  async creditNullifier(state) {
3886
4937
  const n = state.note;
3887
- return (0, import_core10.computeCreditNullifier)(
4938
+ return (0, import_core14.computeCreditNullifier)(
3888
4939
  n.chainId,
3889
4940
  n.creditSharedKey,
3890
- await (0, import_core10.computeCreditCommitment)(
4941
+ await (0, import_core14.computeCreditCommitment)(
3891
4942
  n.chainId,
3892
4943
  n.spenderWalletIdentity,
3893
4944
  n.ownerWalletIdentity,
@@ -3897,7 +4948,8 @@ var InventoryProcessor = class {
3897
4948
  n.amount,
3898
4949
  n.nonce,
3899
4950
  n.expiry,
3900
- await (0, import_core10.computeCreditSharedKeyHash)(n.creditSharedKey)
4951
+ await (0, import_core14.computeCreditSharedKeyHash)(n.creditSharedKey),
4952
+ n
3901
4953
  )
3902
4954
  );
3903
4955
  }
@@ -3944,6 +4996,9 @@ var InventoryProcessor = class {
3944
4996
  };
3945
4997
  for (const event of logs) {
3946
4998
  if (event.eventName === "CreditDraw") {
4999
+ const block = await this.#options.reader.getBlock(event.blockNumber);
5000
+ if (block.hash !== event.blockHash)
5001
+ throw new CanonicalConflict("draw block changed during Credit recovery");
3947
5002
  const args = event.args;
3948
5003
  const params = args.params;
3949
5004
  const indices = args.remainderLeafIndices;
@@ -3957,10 +5012,11 @@ var InventoryProcessor = class {
3957
5012
  previous.state.note.expiry === params.expiries[index2],
3958
5013
  "draw recovery expiry mismatch"
3959
5014
  );
3960
- const remainder = await (0, import_core10.recoverCreditRemainder)(
5015
+ const remainder = await (0, import_core14.recoverCreditRemainder)(
3961
5016
  context,
3962
5017
  previous.state.note,
3963
5018
  {
5019
+ timestamp: block.timestamp,
3964
5020
  creditNullifier: nullifier,
3965
5021
  remainderCommitment: params.remainderCommitments[index2],
3966
5022
  recoveryAmount: BigInt(params.recoveryAmounts[index2])
@@ -3972,7 +5028,7 @@ var InventoryProcessor = class {
3972
5028
  const child = foundByKey.get(
3973
5029
  params.remainderCommitments[index2] + ":" + previous.role
3974
5030
  );
3975
- const memo = child?.state.note.memo;
5031
+ const payload = child?.state.note.payload;
3976
5032
  const record = {
3977
5033
  commitment: params.remainderCommitments[index2],
3978
5034
  treeId: BigInt(args.outputTreeId),
@@ -3985,7 +5041,7 @@ var InventoryProcessor = class {
3985
5041
  ...clone(previous.state),
3986
5042
  note: {
3987
5043
  ...remainder,
3988
- ...memo === void 0 ? {} : { memo: (0, import_core10.encodeMemo)(memo) }
5044
+ ...payload === void 0 ? {} : { payload: clone(payload) }
3989
5045
  }
3990
5046
  },
3991
5047
  receivingKeySource: { kind: "draw", commitment: previous.commitment },
@@ -4064,7 +5120,7 @@ var WalletUpdater = class extends InventoryProcessor {
4064
5120
  }
4065
5121
  async run(batch, options) {
4066
5122
  const { reader, protocol, scope, store, viewing } = this.#options;
4067
- const nullifier = import_core11.NullifierCapability.fromIdentity(scope.walletIdentity);
5123
+ const nullifier = import_core15.NullifierCapability.fromIdentity(scope.walletIdentity);
4068
5124
  const { signal, reset } = options;
4069
5125
  signal?.throwIfAborted();
4070
5126
  const context = protocol.context;
@@ -4233,6 +5289,7 @@ var WalletUpdater = class extends InventoryProcessor {
4233
5289
  draft.notes = {};
4234
5290
  draft.credits = {};
4235
5291
  delete draft.observedThrough;
5292
+ delete draft.discoveryThrough;
4236
5293
  delete draft.invalidated;
4237
5294
  }
4238
5295
  mergeReceiptRecords(draft, { notes, credits, checkpoint: block });
@@ -4264,13 +5321,38 @@ var WalletUpdater = class extends InventoryProcessor {
4264
5321
  var WalletSession = class {
4265
5322
  #options;
4266
5323
  #updater;
5324
+ #listeners = /* @__PURE__ */ new Set();
4267
5325
  #sending = /* @__PURE__ */ new Set();
4268
5326
  #refreshQueue = Promise.resolve();
4269
5327
  scope;
4270
5328
  protocol;
4271
5329
  constructor(options) {
5330
+ if ("ciphertextCodecs" in options || "envelopeVersion" in options) {
5331
+ throw new Error(
5332
+ "SDK envelope versions are fixed; encode application payload bytes externally"
5333
+ );
5334
+ }
5335
+ const store = options.store;
4272
5336
  this.#options = {
4273
5337
  ...options,
5338
+ ...store ? {
5339
+ store: {
5340
+ persistent: store.persistent,
5341
+ readSnapshot: (scope) => store.readSnapshot(scope),
5342
+ transaction: async (scope, action) => {
5343
+ const result = await store.transaction(scope, action);
5344
+ if (scopeKey(scope) === scopeKey(this.scope)) {
5345
+ for (const listener of [...this.#listeners]) {
5346
+ try {
5347
+ listener();
5348
+ } catch {
5349
+ }
5350
+ }
5351
+ }
5352
+ return result;
5353
+ }
5354
+ }
5355
+ } : {},
4274
5356
  ...options.gasBenchmarks ? { gasBenchmarks: copyGasBenchmarks(options.gasBenchmarks) } : {}
4275
5357
  };
4276
5358
  this.protocol = options.protocol;
@@ -4285,7 +5367,7 @@ var WalletSession = class {
4285
5367
  /** Delegate sending to ethers; managed operations additionally retain the resulting hash. */
4286
5368
  async sendTransaction(input, options = {}) {
4287
5369
  const signer = this.#options.signer;
4288
- if (!signer) throw new import_core12.MissingCapabilityError("ethers signer");
5370
+ if (!signer) throw new import_core17.MissingCapabilityError("ethers signer");
4289
5371
  const operation = input instanceof Operation ? input : void 0;
4290
5372
  if (operation && this.#sending.has(operation.id))
4291
5373
  throw new Error("operation is already being sent by this session");
@@ -4293,12 +5375,12 @@ var WalletSession = class {
4293
5375
  const overrides = { ...options };
4294
5376
  const plain = operation ? void 0 : { ...input };
4295
5377
  try {
4296
- if (!signer.provider) throw new import_core12.MissingCapabilityError("connected ethers signer");
5378
+ if (!signer.provider) throw new import_core17.MissingCapabilityError("connected ethers signer");
4297
5379
  if ((await signer.provider.getNetwork()).chainId !== this.protocol.context.chainId) {
4298
5380
  throw new Error("signer-provider session chain mismatch");
4299
5381
  }
4300
5382
  if (operation) {
4301
- if (!this.#options.store) throw new import_core12.MissingCapabilityError("wallet store");
5383
+ if (!this.#options.store) throw new import_core17.MissingCapabilityError("wallet store");
4302
5384
  const state = await this.#options.store.readSnapshot(this.scope);
4303
5385
  if (!state.operations[operation.id])
4304
5386
  throw new Error("operation does not belong to this wallet session");
@@ -4329,25 +5411,30 @@ var WalletSession = class {
4329
5411
  runtime(tokenAddress) {
4330
5412
  const options = this.#options;
4331
5413
  if (!options.store) {
4332
- throw new import_core12.MissingCapabilityError("wallet store");
5414
+ throw new import_core17.MissingCapabilityError("wallet store");
4333
5415
  }
4334
5416
  if (!options.chainReader) {
4335
- throw new import_core12.MissingCapabilityError("chain reader");
5417
+ throw new import_core17.MissingCapabilityError("chain reader");
4336
5418
  }
4337
5419
  return {
4338
5420
  options: { ...options, protocol: options.protocol.forToken(tokenAddress) },
4339
5421
  scope: this.scope,
4340
5422
  store: options.store,
4341
5423
  reader: options.chainReader,
4342
- authorization: () => options.authorization ?? options.wallet.exportAuthorization()
5424
+ authorization: () => {
5425
+ if (options.authorization) return options.authorization;
5426
+ if (options.wallet instanceof import_core16.Wallet) return options.wallet.exportAuthorization();
5427
+ throw new import_core17.MissingCapabilityError("wallet authorization");
5428
+ }
4343
5429
  };
4344
5430
  }
4345
5431
  updater() {
4346
5432
  if (this.#updater) return this.#updater;
4347
5433
  const options = this.#options;
4348
5434
  if (!options.store || !options.chainReader || !options.protocolRpc)
4349
- throw new import_core12.MissingCapabilityError("wallet store, chain reader and Protocol RPC");
4350
- const viewing = options.viewing ?? options.wallet.getViewer();
5435
+ throw new import_core17.MissingCapabilityError("wallet store, chain reader and Protocol RPC");
5436
+ const viewing = options.viewing ?? (options.wallet instanceof import_core16.Wallet ? options.wallet.getViewer() : void 0);
5437
+ if (!viewing) throw new import_core17.MissingCapabilityError("viewing");
4351
5438
  const receivingAddress = options.wallet.getReceivingAddress();
4352
5439
  const receivingKeys = receivingAddress.kind === "long" ? receivingAddress.getReceivingKeys() : void 0;
4353
5440
  this.#updater = new WalletUpdater({
@@ -4361,10 +5448,27 @@ var WalletSession = class {
4361
5448
  });
4362
5449
  return this.#updater;
4363
5450
  }
5451
+ /** Local session commits only. Host applications own cross-tab/store subscriptions. */
5452
+ subscribe(listener) {
5453
+ this.#listeners.add(listener);
5454
+ return () => {
5455
+ this.#listeners.delete(listener);
5456
+ };
5457
+ }
5458
+ /** Detached history for wallet UI; construction records do not imply chain success. */
5459
+ async getHistory(options = {}) {
5460
+ const tokenAddress = options.tokenAddress ? (0, import_ethers11.getAddress)(options.tokenAddress) : void 0;
5461
+ const store = this.#options.store;
5462
+ if (!store) throw new import_core17.MissingCapabilityError("wallet store");
5463
+ return walletHistory(
5464
+ await store.readSnapshot(this.scope),
5465
+ tokenAddress ? { tokenAddress } : {}
5466
+ );
5467
+ }
4364
5468
  async balance(tokenAddress) {
4365
5469
  const store = this.#options.store;
4366
5470
  if (!store) {
4367
- throw new import_core12.MissingCapabilityError("wallet store");
5471
+ throw new import_core17.MissingCapabilityError("wallet store");
4368
5472
  }
4369
5473
  return walletBalance(await store.readSnapshot(this.scope), (0, import_ethers11.getAddress)(tokenAddress));
4370
5474
  }
@@ -4372,15 +5476,15 @@ var WalletSession = class {
4372
5476
  async refresh(options) {
4373
5477
  const provider = this.#options.protocolRpc;
4374
5478
  const reader = this.#options.chainReader;
4375
- if (!reader) throw new import_core12.MissingCapabilityError("chain reader");
4376
- if (!provider) throw new import_core12.MissingCapabilityError("Protocol RPC");
5479
+ if (!reader) throw new import_core17.MissingCapabilityError("chain reader");
5480
+ if (!provider) throw new import_core17.MissingCapabilityError("Protocol RPC");
4377
5481
  const updater = this.updater();
4378
5482
  const request = {
4379
5483
  ...options,
4380
5484
  ...options.detectionKey ? { detectionKey: options.detectionKey.slice() } : {}
4381
5485
  };
4382
- const task = this.#refreshQueue.then(
4383
- () => refreshWallet(
5486
+ const task = this.#refreshQueue.then(async () => {
5487
+ const result = await refreshWallet(
4384
5488
  {
4385
5489
  provider,
4386
5490
  reader,
@@ -4389,8 +5493,21 @@ var WalletSession = class {
4389
5493
  apply: (batch, settings) => updater.applyUpdates(batch, settings)
4390
5494
  },
4391
5495
  request
4392
- )
4393
- );
5496
+ );
5497
+ await this.#options.store.transaction(this.scope, (state) => {
5498
+ request.signal?.throwIfAborted();
5499
+ if (state.invalidated) throw new Error("wallet requires canonical resync");
5500
+ const previous = state.discoveryThrough;
5501
+ const start = previous ? previous.number + 1n : this.protocol.deployment.protocol.fromBlock;
5502
+ if (request.fromBlock <= start && (!previous || result.block.number >= previous.number)) {
5503
+ state.discoveryThrough = {
5504
+ number: result.block.number,
5505
+ hash: result.block.hash
5506
+ };
5507
+ }
5508
+ });
5509
+ return result;
5510
+ });
4394
5511
  this.#refreshQueue = task.catch(() => {
4395
5512
  });
4396
5513
  return task;
@@ -4401,38 +5518,43 @@ var WalletSession = class {
4401
5518
  options: runtime.options,
4402
5519
  scope: runtime.scope,
4403
5520
  reader: runtime.reader,
4404
- authorization: runtime.authorization,
4405
5521
  readInventory: () => runtime.store.readSnapshot(runtime.scope),
4406
5522
  complete: (plan) => Operation.prepare(runtime, plan)
4407
5523
  });
4408
5524
  }
4409
5525
  async prepareTransfer(options) {
4410
- return this.preparation(options.tokenAddress).prepareTransfer(options);
4411
- }
4412
- async prepareWithdraw(options) {
4413
- return this.preparation(options.tokenAddress).prepareWithdraw(options);
4414
- }
4415
- async prepareSweep(options) {
4416
- return this.preparation(options.tokenAddress).prepareSweep(options);
5526
+ return prepareWithErrors("prepareTransfer", async () => {
5527
+ return this.preparation(options.tokenAddress).prepareTransfer(options);
5528
+ });
4417
5529
  }
4418
5530
  async prepareShield(options) {
4419
- return this.preparation(options.tokenAddress).prepareShield(options);
5531
+ return prepareWithErrors("prepareShield", async () => {
5532
+ return this.preparation(options.tokenAddress).prepareShield(options);
5533
+ });
4420
5534
  }
4421
5535
  async prepareCreateCredit(options) {
4422
- return this.preparation(options.tokenAddress).prepareCreateCredit(options);
5536
+ return prepareWithErrors("prepareCreateCredit", async () => {
5537
+ return this.preparation(options.tokenAddress).prepareCreateCredit(options);
5538
+ });
4423
5539
  }
4424
5540
  async prepareDrawCredit(options) {
4425
- return this.preparation(options.tokenAddress).prepareDrawCredit(options);
5541
+ return prepareWithErrors("prepareDrawCredit", async () => {
5542
+ return this.preparation(options.tokenAddress).prepareDrawCredit(options);
5543
+ });
4426
5544
  }
4427
5545
  async prepareTopUpCredit(options) {
4428
- return this.preparation(options.tokenAddress).prepareTopUpCredit(options);
5546
+ return prepareWithErrors("prepareTopUpCredit", async () => {
5547
+ return this.preparation(options.tokenAddress).prepareTopUpCredit(options);
5548
+ });
4429
5549
  }
4430
5550
  async prepareCancelCredit(options) {
4431
- return this.preparation(options.tokenAddress).prepareCancelCredit(options);
5551
+ return prepareWithErrors("prepareCancelCredit", async () => {
5552
+ return this.preparation(options.tokenAddress).prepareCancelCredit(options);
5553
+ });
4432
5554
  }
4433
5555
  async resume(operationId) {
4434
5556
  const store = this.#options.store;
4435
- if (!store) throw new import_core12.MissingCapabilityError("wallet store");
5557
+ if (!store) throw new import_core17.MissingCapabilityError("wallet store");
4436
5558
  const state = await store.readSnapshot(this.scope);
4437
5559
  const saved = state.operations[operationId]?.payload;
4438
5560
  if (!saved?.plan) throw new Error("operation not found");