@invisi-labs/protocol 1.1.5 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -245,6 +245,30 @@ var invisiProtocolAbi = [
245
245
  ],
246
246
  "stateMutability": "view"
247
247
  },
248
+ {
249
+ "type": "function",
250
+ "name": "broadcasterFeeBalance",
251
+ "inputs": [
252
+ {
253
+ "name": "token",
254
+ "type": "address",
255
+ "internalType": "address"
256
+ },
257
+ {
258
+ "name": "recipient",
259
+ "type": "address",
260
+ "internalType": "address"
261
+ }
262
+ ],
263
+ "outputs": [
264
+ {
265
+ "name": "",
266
+ "type": "uint256",
267
+ "internalType": "uint256"
268
+ }
269
+ ],
270
+ "stateMutability": "view"
271
+ },
248
272
  {
249
273
  "type": "function",
250
274
  "name": "cancelCredit",
@@ -300,6 +324,16 @@ var invisiProtocolAbi = [
300
324
  "name": "deadline",
301
325
  "type": "uint256",
302
326
  "internalType": "uint256"
327
+ },
328
+ {
329
+ "name": "feeRecipient",
330
+ "type": "address",
331
+ "internalType": "address"
332
+ },
333
+ {
334
+ "name": "feeAmount",
335
+ "type": "uint256",
336
+ "internalType": "uint256"
303
337
  }
304
338
  ]
305
339
  }
@@ -385,6 +419,16 @@ var invisiProtocolAbi = [
385
419
  "name": "deadline",
386
420
  "type": "uint256",
387
421
  "internalType": "uint256"
422
+ },
423
+ {
424
+ "name": "feeRecipient",
425
+ "type": "address",
426
+ "internalType": "address"
427
+ },
428
+ {
429
+ "name": "feeAmount",
430
+ "type": "uint256",
431
+ "internalType": "uint256"
388
432
  }
389
433
  ]
390
434
  },
@@ -911,6 +955,16 @@ var invisiProtocolAbi = [
911
955
  "name": "deadline",
912
956
  "type": "uint256",
913
957
  "internalType": "uint256"
958
+ },
959
+ {
960
+ "name": "feeRecipient",
961
+ "type": "address",
962
+ "internalType": "address"
963
+ },
964
+ {
965
+ "name": "feeAmount",
966
+ "type": "uint256",
967
+ "internalType": "uint256"
914
968
  }
915
969
  ]
916
970
  },
@@ -1081,6 +1135,16 @@ var invisiProtocolAbi = [
1081
1135
  "name": "deadline",
1082
1136
  "type": "uint256",
1083
1137
  "internalType": "uint256"
1138
+ },
1139
+ {
1140
+ "name": "feeRecipient",
1141
+ "type": "address",
1142
+ "internalType": "address"
1143
+ },
1144
+ {
1145
+ "name": "feeAmount",
1146
+ "type": "uint256",
1147
+ "internalType": "uint256"
1084
1148
  }
1085
1149
  ]
1086
1150
  },
@@ -1203,9 +1267,9 @@ var invisiProtocolAbi = [
1203
1267
  "internalType": "bytes"
1204
1268
  },
1205
1269
  {
1206
- "name": "requests",
1207
- "type": "tuple[]",
1208
- "internalType": "struct IInvisiProtocol.TransactRequest[]",
1270
+ "name": "r",
1271
+ "type": "tuple",
1272
+ "internalType": "struct IInvisiProtocol.TransactRequest",
1209
1273
  "components": [
1210
1274
  {
1211
1275
  "name": "params",
@@ -1258,6 +1322,16 @@ var invisiProtocolAbi = [
1258
1322
  "name": "deadline",
1259
1323
  "type": "uint256",
1260
1324
  "internalType": "uint256"
1325
+ },
1326
+ {
1327
+ "name": "feeRecipient",
1328
+ "type": "address",
1329
+ "internalType": "address"
1330
+ },
1331
+ {
1332
+ "name": "feeAmount",
1333
+ "type": "uint256",
1334
+ "internalType": "uint256"
1261
1335
  }
1262
1336
  ]
1263
1337
  },
@@ -1353,9 +1427,9 @@ var invisiProtocolAbi = [
1353
1427
  "internalType": "bytes"
1354
1428
  },
1355
1429
  {
1356
- "name": "r",
1357
- "type": "tuple",
1358
- "internalType": "struct IInvisiProtocol.TransactRequest",
1430
+ "name": "requests",
1431
+ "type": "tuple[]",
1432
+ "internalType": "struct IInvisiProtocol.TransactRequest[]",
1359
1433
  "components": [
1360
1434
  {
1361
1435
  "name": "params",
@@ -1408,6 +1482,16 @@ var invisiProtocolAbi = [
1408
1482
  "name": "deadline",
1409
1483
  "type": "uint256",
1410
1484
  "internalType": "uint256"
1485
+ },
1486
+ {
1487
+ "name": "feeRecipient",
1488
+ "type": "address",
1489
+ "internalType": "address"
1490
+ },
1491
+ {
1492
+ "name": "feeAmount",
1493
+ "type": "uint256",
1494
+ "internalType": "uint256"
1411
1495
  }
1412
1496
  ]
1413
1497
  },
@@ -1533,6 +1617,30 @@ var invisiProtocolAbi = [
1533
1617
  ],
1534
1618
  "stateMutability": "view"
1535
1619
  },
1620
+ {
1621
+ "type": "function",
1622
+ "name": "withdrawBroadcasterFees",
1623
+ "inputs": [
1624
+ {
1625
+ "name": "token",
1626
+ "type": "address",
1627
+ "internalType": "address"
1628
+ },
1629
+ {
1630
+ "name": "recipient",
1631
+ "type": "address",
1632
+ "internalType": "address"
1633
+ }
1634
+ ],
1635
+ "outputs": [
1636
+ {
1637
+ "name": "",
1638
+ "type": "uint256",
1639
+ "internalType": "uint256"
1640
+ }
1641
+ ],
1642
+ "stateMutability": "nonpayable"
1643
+ },
1536
1644
  {
1537
1645
  "type": "event",
1538
1646
  "name": "BatchOutputs",
@@ -1667,6 +1775,56 @@ var invisiProtocolAbi = [
1667
1775
  ],
1668
1776
  "anonymous": false
1669
1777
  },
1778
+ {
1779
+ "type": "event",
1780
+ "name": "BroadcasterFee",
1781
+ "inputs": [
1782
+ {
1783
+ "name": "token",
1784
+ "type": "address",
1785
+ "indexed": true,
1786
+ "internalType": "address"
1787
+ },
1788
+ {
1789
+ "name": "recipient",
1790
+ "type": "address",
1791
+ "indexed": true,
1792
+ "internalType": "address"
1793
+ },
1794
+ {
1795
+ "name": "amount",
1796
+ "type": "uint256",
1797
+ "indexed": false,
1798
+ "internalType": "uint256"
1799
+ }
1800
+ ],
1801
+ "anonymous": false
1802
+ },
1803
+ {
1804
+ "type": "event",
1805
+ "name": "BroadcasterFeeWithdrawn",
1806
+ "inputs": [
1807
+ {
1808
+ "name": "token",
1809
+ "type": "address",
1810
+ "indexed": true,
1811
+ "internalType": "address"
1812
+ },
1813
+ {
1814
+ "name": "recipient",
1815
+ "type": "address",
1816
+ "indexed": true,
1817
+ "internalType": "address"
1818
+ },
1819
+ {
1820
+ "name": "amount",
1821
+ "type": "uint256",
1822
+ "indexed": false,
1823
+ "internalType": "uint256"
1824
+ }
1825
+ ],
1826
+ "anonymous": false
1827
+ },
1670
1828
  {
1671
1829
  "type": "event",
1672
1830
  "name": "CircuitPauseUpdated",
@@ -2019,6 +2177,16 @@ var invisiProtocolAbi = [
2019
2177
  "name": "deadline",
2020
2178
  "type": "uint256",
2021
2179
  "internalType": "uint256"
2180
+ },
2181
+ {
2182
+ "name": "feeRecipient",
2183
+ "type": "address",
2184
+ "internalType": "address"
2185
+ },
2186
+ {
2187
+ "name": "feeAmount",
2188
+ "type": "uint256",
2189
+ "internalType": "uint256"
2022
2190
  }
2023
2191
  ]
2024
2192
  },
@@ -2474,6 +2642,28 @@ var invisiProtocolAbi = [
2474
2642
  ],
2475
2643
  "anonymous": false
2476
2644
  },
2645
+ {
2646
+ "type": "error",
2647
+ "name": "AddressEmptyCode",
2648
+ "inputs": [
2649
+ {
2650
+ "name": "target",
2651
+ "type": "address",
2652
+ "internalType": "address"
2653
+ }
2654
+ ]
2655
+ },
2656
+ {
2657
+ "type": "error",
2658
+ "name": "AddressInsufficientBalance",
2659
+ "inputs": [
2660
+ {
2661
+ "name": "account",
2662
+ "type": "address",
2663
+ "internalType": "address"
2664
+ }
2665
+ ]
2666
+ },
2477
2667
  {
2478
2668
  "type": "error",
2479
2669
  "name": "AddressScreeningFailed",
@@ -2532,6 +2722,11 @@ var invisiProtocolAbi = [
2532
2722
  "name": "ExpiryInPast",
2533
2723
  "inputs": []
2534
2724
  },
2725
+ {
2726
+ "type": "error",
2727
+ "name": "FailedInnerCall",
2728
+ "inputs": []
2729
+ },
2535
2730
  {
2536
2731
  "type": "error",
2537
2732
  "name": "InexactTokenReceipt",
@@ -2708,6 +2903,11 @@ var invisiProtocolAbi = [
2708
2903
  "name": "LengthMismatch",
2709
2904
  "inputs": []
2710
2905
  },
2906
+ {
2907
+ "type": "error",
2908
+ "name": "NoBroadcasterFees",
2909
+ "inputs": []
2910
+ },
2711
2911
  {
2712
2912
  "type": "error",
2713
2913
  "name": "NotEmergencyAdmin",
@@ -2766,6 +2966,17 @@ var invisiProtocolAbi = [
2766
2966
  "name": "ReentrancyGuardReentrantCall",
2767
2967
  "inputs": []
2768
2968
  },
2969
+ {
2970
+ "type": "error",
2971
+ "name": "SafeERC20FailedOperation",
2972
+ "inputs": [
2973
+ {
2974
+ "name": "token",
2975
+ "type": "address",
2976
+ "internalType": "address"
2977
+ }
2978
+ ]
2979
+ },
2769
2980
  {
2770
2981
  "type": "error",
2771
2982
  "name": "ShieldExpired",
@@ -3752,10 +3963,10 @@ function hexBytes(value, length) {
3752
3963
  throw new Error(`Expected ${length} hexadecimal bytes`);
3753
3964
  return (0, import_ethers.getBytes)(value);
3754
3965
  }
3755
- function normalizeKeys(walletIdentity, keys) {
3966
+ function normalizeKeys(ownerAddress, keys) {
3756
3967
  const decoded = (0, import_core.decodeAddress)(
3757
3968
  import_core.ReceivingAddress.from({
3758
- walletIdentity,
3969
+ ownerAddress,
3759
3970
  viewingPublicKey: hexBytes(keys.viewingPublicKey, 33),
3760
3971
  clueKey: hexBytes(keys.clueKey, 32)
3761
3972
  }).toString()
@@ -3770,14 +3981,14 @@ function normalize(context, registration, options) {
3770
3981
  uint64(context.chainId, "chainId");
3771
3982
  const registryAddress = (0, import_ethers.getAddress)(context.registryAddress);
3772
3983
  if (BigInt(registryAddress) === 0n) throw new Error("Registry address must be nonzero");
3773
- if (!/^0x(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$/.test(registration.walletIdentity))
3984
+ if (!/^0x(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$/.test(registration.ownerAddress))
3774
3985
  throw new Error("Wallet identity must be an EVM owner or padded bytes32");
3775
- const walletIdentity = (0, import_core.decodeAddress)(
3986
+ const ownerAddress = (0, import_core.decodeAddress)(
3776
3987
  import_core.ReceivingAddress.fromIdentity(
3777
- (0, import_ethers.toBeHex)(BigInt(registration.walletIdentity), 20)
3988
+ (0, import_ethers.toBeHex)(BigInt(registration.ownerAddress), 20)
3778
3989
  ).toString()
3779
- ).walletIdentity;
3780
- const keys = normalizeKeys(walletIdentity, registration.keys);
3990
+ ).ownerAddress;
3991
+ const keys = normalizeKeys(ownerAddress, registration.keys);
3781
3992
  const nonce = uint64(registration.nonce, "nonce"), deadline = uint64(registration.deadline, "deadline");
3782
3993
  if (nonce === MAX_NONCE) throw new Error("Registry nonce exhausted");
3783
3994
  if (options.update !== void 0 && typeof options.update !== "boolean")
@@ -3788,7 +3999,7 @@ function normalize(context, registration, options) {
3788
3999
  throw new Error("Registry nonce mismatch");
3789
4000
  if (context.now !== void 0 && deadline < uint64(context.now, "now"))
3790
4001
  throw new Error("Registration expired");
3791
- return { registryAddress, registration: { walletIdentity, keys, nonce, deadline } };
4002
+ return { registryAddress, registration: { ownerAddress, keys, nonce, deadline } };
3792
4003
  }
3793
4004
  function registrationTypedData(context, registration, options = {}) {
3794
4005
  const { registryAddress, registration: r } = normalize(context, registration, options);
@@ -3811,7 +4022,7 @@ function registrationTypedData(context, registration, options = {}) {
3811
4022
  ]
3812
4023
  },
3813
4024
  message: {
3814
- walletIdentity: (0, import_ethers.toBeHex)(BigInt(r.walletIdentity), 32),
4025
+ walletIdentity: (0, import_ethers.toBeHex)(BigInt(r.ownerAddress), 32),
3815
4026
  ...r.keys,
3816
4027
  nonce: r.nonce,
3817
4028
  deadline: r.deadline
@@ -3833,8 +4044,11 @@ function buildRegistrationCalldata(context, registration, signature, options = {
3833
4044
  options.update ? "updateKeys" : "registerKeys",
3834
4045
  [
3835
4046
  {
3836
- ...normalized.registration,
3837
- walletIdentity: (0, import_ethers.toBeHex)(BigInt(normalized.registration.walletIdentity), 32)
4047
+ // The registry wire schema retains its deployed EIP-712/ABI field name.
4048
+ walletIdentity: (0, import_ethers.toBeHex)(BigInt(normalized.registration.ownerAddress), 32),
4049
+ keys: normalized.registration.keys,
4050
+ nonce: normalized.registration.nonce,
4051
+ deadline: normalized.registration.deadline
3838
4052
  },
3839
4053
  signature
3840
4054
  ]
@@ -3844,10 +4058,10 @@ function buildRegistrationCalldata(context, registration, signature, options = {
3844
4058
  function createRegistryReceivingKeyLookup(client, registryAddress) {
3845
4059
  const address = (0, import_ethers.getAddress)(registryAddress);
3846
4060
  if (BigInt(address) === 0n) throw new Error("Registry address must be nonzero");
3847
- return async (walletIdentity) => {
4061
+ return async (ownerAddress) => {
3848
4062
  const identity = (0, import_core.decodeAddress)(
3849
- import_core.ReceivingAddress.fromIdentity(walletIdentity).toString()
3850
- ).walletIdentity;
4063
+ import_core.ReceivingAddress.fromIdentity(ownerAddress).toString()
4064
+ ).ownerAddress;
3851
4065
  const [keys, nonce] = await new import_ethers.Contract(
3852
4066
  address,
3853
4067
  invisiAddressRegistryAbi,
@@ -3895,7 +4109,7 @@ var RegistrationOperation = class _RegistrationOperation {
3895
4109
  const context = { ...registry.context, now: block.timestamp };
3896
4110
  const nonce = await runtime.reader.getRegistryNonce(
3897
4111
  context,
3898
- runtime.wallet.walletIdentity,
4112
+ runtime.wallet.ownerAddress,
3899
4113
  block
3900
4114
  );
3901
4115
  check(
@@ -3909,7 +4123,7 @@ var RegistrationOperation = class _RegistrationOperation {
3909
4123
  const address = import_core2.ReceivingAddress.parse(await registry.resolve(runtime.wallet.getAddress()));
3910
4124
  const keys = address.getReceivingKeys();
3911
4125
  const registration = {
3912
- walletIdentity: runtime.wallet.walletIdentity,
4126
+ ownerAddress: runtime.wallet.ownerAddress,
3913
4127
  keys: {
3914
4128
  viewingPublicKey: (0, import_ethers2.hexlify)(keys.viewingPublicKey),
3915
4129
  clueKey: (0, import_ethers2.hexlify)(keys.clueKey)
@@ -3961,7 +4175,7 @@ var RegistrationOperation = class _RegistrationOperation {
3961
4175
  "registry signature must be nonempty hexadecimal bytes"
3962
4176
  );
3963
4177
  const p = this.#plan;
3964
- const owner = p.registration.walletIdentity;
4178
+ const owner = p.registration.ownerAddress;
3965
4179
  let valid = false;
3966
4180
  try {
3967
4181
  const bytes = (0, import_ethers2.getBytes)(signature);
@@ -4035,7 +4249,7 @@ var RegistrationOperation = class _RegistrationOperation {
4035
4249
  check(
4036
4250
  await this.#runtime.reader.getRegistryNonce(
4037
4251
  p.context,
4038
- p.registration.walletIdentity,
4252
+ p.registration.ownerAddress,
4039
4253
  block
4040
4254
  ) === p.registration.nonce,
4041
4255
  "registry nonce changed; prepare again"
@@ -4086,7 +4300,7 @@ var RegistrationOperation = class _RegistrationOperation {
4086
4300
  const transaction = await reader.getTransaction(hash);
4087
4301
  const call = this.call();
4088
4302
  check(
4089
- transaction && transaction.transactionHash === hash && transaction.to.toLowerCase() === call.to.toLowerCase() && transaction.data.toLowerCase() === call.data.toLowerCase() && transaction.value === 0n && (this.#signature !== "0x" || BigInt(transaction.from) === BigInt(p.registration.walletIdentity)),
4303
+ transaction && transaction.transactionHash === hash && transaction.to.toLowerCase() === call.to.toLowerCase() && transaction.data.toLowerCase() === call.data.toLowerCase() && transaction.value === 0n && (this.#signature !== "0x" || BigInt(transaction.from) === BigInt(p.registration.ownerAddress)),
4090
4304
  "registry transaction differs from frozen request"
4091
4305
  );
4092
4306
  check(
@@ -4108,7 +4322,7 @@ var RegistrationOperation = class _RegistrationOperation {
4108
4322
  topics: log.topics
4109
4323
  })
4110
4324
  );
4111
- return event.eventName === "ReceivingKeysSet" && BigInt(event.args.walletIdentity) === BigInt(p.registration.walletIdentity) && event.args.viewingPublicKey.toLowerCase() === p.registration.keys.viewingPublicKey.toLowerCase() && event.args.clueKey.toLowerCase() === p.registration.keys.clueKey.toLowerCase() && event.args.nextNonce === p.registration.nonce + 1n;
4325
+ return event.eventName === "ReceivingKeysSet" && BigInt(event.args.walletIdentity) === BigInt(p.registration.ownerAddress) && event.args.viewingPublicKey.toLowerCase() === p.registration.keys.viewingPublicKey.toLowerCase() && event.args.clueKey.toLowerCase() === p.registration.keys.clueKey.toLowerCase() && event.args.nextNonce === p.registration.nonce + 1n;
4112
4326
  } catch {
4113
4327
  return false;
4114
4328
  }
@@ -4131,7 +4345,7 @@ var RegistrationOperation = class _RegistrationOperation {
4131
4345
  }
4132
4346
  }
4133
4347
  const head = await reader.getBlock(await reader.getLatestBlockNumber());
4134
- const nonce = await reader.getRegistryNonce(p.context, p.registration.walletIdentity, head);
4348
+ const nonce = await reader.getRegistryNonce(p.context, p.registration.ownerAddress, head);
4135
4349
  check(
4136
4350
  (await reader.getBlock(head.number)).hash === head.hash,
4137
4351
  "canonical registry block changed during reconciliation"
@@ -4210,9 +4424,8 @@ var AddressRegistry = class {
4210
4424
  }
4211
4425
  };
4212
4426
 
4213
- // src/credit-create.ts
4427
+ // src/fee.ts
4214
4428
  var import_ethers5 = require("ethers");
4215
- var import_core5 = require("@invisi-labs/core");
4216
4429
 
4217
4430
  // src/validation.ts
4218
4431
  var import_core4 = require("@invisi-labs/core");
@@ -4309,6 +4522,8 @@ function normalizeOpaqueDelivery(value, options = {}) {
4309
4522
  throw new Error("absent output requires an empty delivery");
4310
4523
  return { ciphertext: "0x", clue: "0x" };
4311
4524
  }
4525
+ if (options.allowEmpty && value.ciphertext === "0x" && value.clue === "0x")
4526
+ return { ciphertext: "0x", clue: "0x" };
4312
4527
  const ciphertext = envelope(value.ciphertext, 1, void 0, import_core4.MAX_CIPHERTEXT_BYTES);
4313
4528
  const clue = envelope(value.clue, 68);
4314
4529
  if (clue.slice(130, 132).toLowerCase() !== "18") throw new Error("clue precision must be 24");
@@ -4367,9 +4582,20 @@ var fundingFields = [
4367
4582
  { name: "deadline", type: "uint256" }
4368
4583
  ];
4369
4584
 
4585
+ // src/fee.ts
4586
+ function normalizeFee(p) {
4587
+ const feeRecipient = (0, import_ethers5.getAddress)(p.feeRecipient ?? ZERO_ADDRESS);
4588
+ const feeAmount = uint(p.feeAmount ?? 0n, 128, "feeAmount");
4589
+ if (BigInt(feeRecipient) === 0n !== (feeAmount === 0n))
4590
+ throw new Error("invalid fee context");
4591
+ return { feeRecipient, feeAmount };
4592
+ }
4593
+
4370
4594
  // src/credit-create.ts
4595
+ var import_ethers6 = require("ethers");
4596
+ var import_core5 = require("@invisi-labs/core");
4371
4597
  var creationTuple = [
4372
- "(address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32 creditCommitment,bytes32 changeCommitment,address owner,uint256 expiry,uint256 deadline)"
4598
+ "(address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32 creditCommitment,bytes32 changeCommitment,address owner,uint256 expiry,uint256 deadline,address feeRecipient,uint256 feeAmount)"
4373
4599
  ][0];
4374
4600
  var CREATE_CREDIT_FIELDS = [
4375
4601
  "token",
@@ -4379,25 +4605,31 @@ var CREATE_CREDIT_FIELDS = [
4379
4605
  "changeCommitment",
4380
4606
  "owner",
4381
4607
  "expiry",
4382
- "deadline"
4608
+ "deadline",
4609
+ "feeRecipient",
4610
+ "feeAmount"
4383
4611
  ];
4384
4612
  function validateCreateCreditRequest(c, p, cs, funding = {}) {
4385
4613
  known(p, CREATE_CREDIT_FIELDS);
4386
- if ((0, import_ethers5.getAddress)(p.token) !== (0, import_ethers5.getAddress)(c.tokenAddress))
4614
+ if ((0, import_ethers6.getAddress)(p.token) !== (0, import_ethers6.getAddress)(c.tokenAddress))
4387
4615
  throw new Error("request token mismatch");
4388
- const ctx = normalizeContext(c), ns = notes(p.nullifiers, "nullifiers"), sources = normalizeSources(p.sources, ns.length, 10), creditCommitment = word(field(p.creditCommitment)), changeCommitment = word(field(p.changeCommitment)), owner = (0, import_ethers5.getAddress)(p.owner), expiry = uint(p.expiry, 64, "expiry"), deadline = checkDeadline(c, p.deadline), f = normalizeFunding(funding);
4616
+ const ctx = normalizeContext(c), ns = notes(p.nullifiers, "nullifiers"), sources = normalizeSources(p.sources, ns.length, 10), creditCommitment = word(field(p.creditCommitment)), changeCommitment = word(field(p.changeCommitment)), owner = (0, import_ethers6.getAddress)(p.owner), expiry = uint(p.expiry, 64, "expiry"), deadline = checkDeadline(c, p.deadline), f = normalizeFunding(funding);
4389
4617
  if (BigInt(creditCommitment) === 0n || creditCommitment === changeCommitment)
4390
4618
  throw new Error("zero or duplicate commitment");
4391
4619
  if (BigInt(owner) === 0n || expiry === 0n || c.now !== void 0 && expiry <= c.now)
4392
4620
  throw new Error("owner must be nonzero and expiry future");
4393
4621
  if (dense(cs, "deliveries").length !== 3) throw new Error("deliveries count mismatch");
4394
4622
  const deliveries = cs.map(
4395
- (v, i) => normalizeOpaqueDelivery(v, { empty: i === 2 && BigInt(changeCommitment) === 0n })
4623
+ (v, i) => normalizeOpaqueDelivery(v, {
4624
+ empty: i === 2 && BigInt(changeCommitment) === 0n,
4625
+ allowEmpty: i === 2
4626
+ })
4396
4627
  );
4397
4628
  if (ns.length === 0 && f.amount === 0n)
4398
4629
  throw new Error("empty inputs require positive funding");
4399
4630
  return {
4400
4631
  ...ctx,
4632
+ ...normalizeFee(p),
4401
4633
  sources,
4402
4634
  nullifiers: ns,
4403
4635
  actualCount: ns.length,
@@ -4436,7 +4668,9 @@ function createCreditBaseInputs(c, p, cs, f = {}) {
4436
4668
  r.expiry,
4437
4669
  r.deadline,
4438
4670
  r.funding.amount,
4439
- BigInt(r.funding.payer)
4671
+ BigInt(r.funding.payer),
4672
+ BigInt(r.feeRecipient),
4673
+ r.feeAmount
4440
4674
  ].map(word);
4441
4675
  }
4442
4676
  function createCreditPublicInputs(c, p, deliveries, funding = {}) {
@@ -4458,18 +4692,18 @@ var hashContext = {
4458
4692
  };
4459
4693
  function createCreditRequestHash(p, cs, f = {}) {
4460
4694
  const r = validateCreateCreditRequest({ ...hashContext, tokenAddress: p.token }, p, cs, f);
4461
- return (0, import_ethers5.keccak256)(
4462
- import_ethers5.AbiCoder.defaultAbiCoder().encode(
4695
+ return (0, import_ethers6.keccak256)(
4696
+ import_ethers6.AbiCoder.defaultAbiCoder().encode(
4463
4697
  [
4464
4698
  { type: "bytes32" },
4465
4699
  creationTuple,
4466
4700
  { type: "bytes32" },
4467
4701
  { type: "address" },
4468
4702
  { type: "uint256" }
4469
- ].map((parameter) => import_ethers5.ParamType.from(parameter)),
4703
+ ].map((parameter) => import_ethers6.ParamType.from(parameter)),
4470
4704
  [
4471
- (0, import_ethers5.keccak256)(new TextEncoder().encode("InvisiCreateCredit")),
4472
- p,
4705
+ (0, import_ethers6.keccak256)(new TextEncoder().encode("InvisiCreateCredit")),
4706
+ { ...p, ...normalizeFee(p) },
4473
4707
  deliveriesHash(cs),
4474
4708
  r.funding.payer,
4475
4709
  r.funding.amount
@@ -4505,9 +4739,9 @@ function buildCreateCreditCalldata(p) {
4505
4739
  const r = validateCreateCreditRequest(p.context, p.params, p.deliveries, p.funding);
4506
4740
  validateFundingSubmission(r.funding, p.caller, p.context.now);
4507
4741
  return {
4508
- data: new import_ethers5.Interface(invisiProtocolAbi).encodeFunctionData("createCredit", [
4742
+ data: new import_ethers6.Interface(invisiProtocolAbi).encodeFunctionData("createCredit", [
4509
4743
  encodeCreditProof(p.proof),
4510
- p.params,
4744
+ { ...p.params, ...normalizeFee(p.params) },
4511
4745
  p.deliveries,
4512
4746
  r.funding
4513
4747
  ]),
@@ -4515,16 +4749,16 @@ function buildCreateCreditCalldata(p) {
4515
4749
  };
4516
4750
  }
4517
4751
  function encodeCreditProof(proof) {
4518
- if (!(0, import_ethers5.isHexString)(proof) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(proof) || (0, import_ethers5.dataLength)(proof) === 0)
4752
+ if (!(0, import_ethers6.isHexString)(proof) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(proof) || (0, import_ethers6.dataLength)(proof) === 0)
4519
4753
  throw new Error("empty or malformed Credit proof");
4520
- return import_ethers5.AbiCoder.defaultAbiCoder().encode(
4521
- ["uint8", "bytes"].map((parameter) => import_ethers5.ParamType.from(parameter)),
4754
+ return import_ethers6.AbiCoder.defaultAbiCoder().encode(
4755
+ ["uint8", "bytes"].map((parameter) => import_ethers6.ParamType.from(parameter)),
4522
4756
  [0, proof]
4523
4757
  );
4524
4758
  }
4525
4759
 
4526
4760
  // src/credit-lifecycle.ts
4527
- var import_ethers6 = require("ethers");
4761
+ var import_ethers7 = require("ethers");
4528
4762
  var import_core6 = require("@invisi-labs/core");
4529
4763
  var CREDIT_DRAW_CAPACITIES = [1, 12, 50, 120];
4530
4764
  function selectCreditDrawCircuit(count) {
@@ -4550,7 +4784,7 @@ function validateCreditDrawRequest(c, p, cs) {
4550
4784
  "totalAmount",
4551
4785
  "deadline"
4552
4786
  ]);
4553
- if ((0, import_ethers6.getAddress)(p.token) !== (0, import_ethers6.getAddress)(c.tokenAddress))
4787
+ if ((0, import_ethers7.getAddress)(p.token) !== (0, import_ethers7.getAddress)(c.tokenAddress))
4554
4788
  throw new Error("request token mismatch");
4555
4789
  const ctx = normalizeContext(c), ns = notes(p.nullifiers, "nullifiers"), profile = selectCreditDrawCircuit(ns.length), sources = normalizeSources(p.sources, ns.length, profile.maxSize);
4556
4790
  for (const [key, v] of Object.entries({
@@ -4568,7 +4802,7 @@ function validateCreditDrawRequest(c, p, cs) {
4568
4802
  if (BigInt(remainderCommitments[i]) === 0n && BigInt(recoveryAmounts[i]) !== 0n)
4569
4803
  throw new Error("full draw requires zero recovery amount");
4570
4804
  }
4571
- const spender = (0, import_ethers6.getAddress)(p.spender), totalAmount = uint(p.totalAmount, profile.totalBits, "totalAmount");
4805
+ const spender = (0, import_ethers7.getAddress)(p.spender), totalAmount = uint(p.totalAmount, profile.totalBits, "totalAmount");
4572
4806
  if (BigInt(spender) === 0n || totalAmount === 0n)
4573
4807
  throw new Error("spender and total amount must be positive");
4574
4808
  if (dense(cs, "deliveries").length !== 2 * ns.length)
@@ -4621,13 +4855,25 @@ function creditDrawBaseInputs(c, p, cs) {
4621
4855
  ].map(word);
4622
4856
  }
4623
4857
  function validateCancelCreditRequest(c, p) {
4624
- known(p, ["token", "source", "nullifier", "owner", "amount", "deadline"]);
4625
- if ((0, import_ethers6.getAddress)(p.token) !== (0, import_ethers6.getAddress)(c.tokenAddress))
4858
+ known(p, [
4859
+ "token",
4860
+ "source",
4861
+ "nullifier",
4862
+ "owner",
4863
+ "amount",
4864
+ "deadline",
4865
+ "feeRecipient",
4866
+ "feeAmount"
4867
+ ]);
4868
+ if ((0, import_ethers7.getAddress)(p.token) !== (0, import_ethers7.getAddress)(c.tokenAddress))
4626
4869
  throw new Error("request token mismatch");
4627
- const ctx = normalizeContext(c), source = normalizeSources([p.source], 1, 1)[0], nullifier = notes([p.nullifier], "nullifier")[0], owner = (0, import_ethers6.getAddress)(p.owner), amount = uint(p.amount, 126, "amount");
4870
+ const ctx = normalizeContext(c), source = normalizeSources([p.source], 1, 1)[0], nullifier = notes([p.nullifier], "nullifier")[0], owner = (0, import_ethers7.getAddress)(p.owner), amount = uint(p.amount, 126, "amount");
4628
4871
  if (BigInt(owner) === 0n || amount === 0n) throw new Error("owner and amount must be positive");
4872
+ const fee = normalizeFee(p);
4873
+ if (fee.feeAmount >= amount) throw new Error("fee must leave a positive owner refund");
4629
4874
  return {
4630
4875
  ...ctx,
4876
+ ...fee,
4631
4877
  source,
4632
4878
  nullifier,
4633
4879
  owner,
@@ -4646,7 +4892,9 @@ function cancelCreditBaseInputs(c, p) {
4646
4892
  BigInt(r.source.merkleRoot),
4647
4893
  BigInt(r.nullifier),
4648
4894
  r.amount,
4649
- r.deadline
4895
+ r.deadline,
4896
+ BigInt(r.feeRecipient),
4897
+ r.feeAmount
4650
4898
  ].map(word);
4651
4899
  }
4652
4900
  function validateTopUpCreditRequest(c, p, cs, funding = {}) {
@@ -4670,10 +4918,10 @@ function topUpCreditBaseInputs(c, p, cs, f = {}) {
4670
4918
  ];
4671
4919
  }
4672
4920
  var cancelTuple = [
4673
- "(address token,(uint256 treeId,bytes32 merkleRoot) source,bytes32 nullifier,address owner,uint256 amount,uint256 deadline)"
4921
+ "(address token,(uint256 treeId,bytes32 merkleRoot) source,bytes32 nullifier,address owner,uint256 amount,uint256 deadline,address feeRecipient,uint256 feeAmount)"
4674
4922
  ][0];
4675
4923
  var topTuple = [
4676
- "((address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32 creditCommitment,bytes32 changeCommitment,address owner,uint256 expiry,uint256 deadline) creation,(uint256 treeId,bytes32 merkleRoot) creditSource,bytes32 creditNullifier,uint256 previousExpiry)"
4924
+ "((address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32 creditCommitment,bytes32 changeCommitment,address owner,uint256 expiry,uint256 deadline,address feeRecipient,uint256 feeAmount) creation,(uint256 treeId,bytes32 merkleRoot) creditSource,bytes32 creditNullifier,uint256 previousExpiry)"
4677
4925
  ][0];
4678
4926
  var hashContext2 = {
4679
4927
  chainId: 0n,
@@ -4682,10 +4930,13 @@ var hashContext2 = {
4682
4930
  };
4683
4931
  function cancelCreditRequestHash(p) {
4684
4932
  validateCancelCreditRequest({ ...hashContext2, tokenAddress: p.token }, p);
4685
- return (0, import_ethers6.keccak256)(
4686
- import_ethers6.AbiCoder.defaultAbiCoder().encode(
4687
- [{ type: "bytes32" }, cancelTuple].map((parameter) => import_ethers6.ParamType.from(parameter)),
4688
- [(0, import_ethers6.keccak256)(new TextEncoder().encode("InvisiCancelCredit")), p]
4933
+ return (0, import_ethers7.keccak256)(
4934
+ import_ethers7.AbiCoder.defaultAbiCoder().encode(
4935
+ [{ type: "bytes32" }, cancelTuple].map((parameter) => import_ethers7.ParamType.from(parameter)),
4936
+ [
4937
+ (0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiCancelCredit")),
4938
+ { ...p, ...normalizeFee(p) }
4939
+ ]
4689
4940
  )
4690
4941
  );
4691
4942
  }
@@ -4696,18 +4947,18 @@ function topUpCreditRequestHash(p, cs, f = {}) {
4696
4947
  cs,
4697
4948
  f
4698
4949
  );
4699
- return (0, import_ethers6.keccak256)(
4700
- import_ethers6.AbiCoder.defaultAbiCoder().encode(
4950
+ return (0, import_ethers7.keccak256)(
4951
+ import_ethers7.AbiCoder.defaultAbiCoder().encode(
4701
4952
  [
4702
4953
  { type: "bytes32" },
4703
4954
  topTuple,
4704
4955
  { type: "bytes32" },
4705
4956
  { type: "address" },
4706
4957
  { type: "uint256" }
4707
- ].map((parameter) => import_ethers6.ParamType.from(parameter)),
4958
+ ].map((parameter) => import_ethers7.ParamType.from(parameter)),
4708
4959
  [
4709
- (0, import_ethers6.keccak256)(new TextEncoder().encode("InvisiTopUpCredit")),
4710
- p,
4960
+ (0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiTopUpCredit")),
4961
+ { ...p, creation: { ...p.creation, ...normalizeFee(p.creation) } },
4711
4962
  deliveriesHash(cs),
4712
4963
  r.creation.funding.payer,
4713
4964
  r.creation.funding.amount
@@ -4781,7 +5032,7 @@ function encodeTopUpCreditFundingTypedData(c, p, cs, f) {
4781
5032
  function buildCreditDrawCalldata(p) {
4782
5033
  validateCreditDrawRequest(p.context, p.params, p.deliveries);
4783
5034
  return {
4784
- data: new import_ethers6.Interface(invisiProtocolAbi).encodeFunctionData("creditDraw", [
5035
+ data: new import_ethers7.Interface(invisiProtocolAbi).encodeFunctionData("creditDraw", [
4785
5036
  encodeCreditProof(p.proof),
4786
5037
  p.params,
4787
5038
  p.deliveries
@@ -4793,9 +5044,9 @@ function buildCreditDrawCalldata(p) {
4793
5044
  function buildCancelCreditCalldata(p) {
4794
5045
  validateCancelCreditRequest(p.context, p.params);
4795
5046
  return {
4796
- data: new import_ethers6.Interface(invisiProtocolAbi).encodeFunctionData("cancelCredit", [
5047
+ data: new import_ethers7.Interface(invisiProtocolAbi).encodeFunctionData("cancelCredit", [
4797
5048
  encodeCreditProof(p.proof),
4798
- p.params
5049
+ { ...p.params, ...normalizeFee(p.params) }
4799
5050
  ])
4800
5051
  };
4801
5052
  }
@@ -4803,9 +5054,9 @@ function buildTopUpCreditCalldata(p) {
4803
5054
  const r = validateTopUpCreditRequest(p.context, p.params, p.deliveries, p.funding);
4804
5055
  validateFundingSubmission(r.creation.funding, p.caller, p.context.now);
4805
5056
  return {
4806
- data: new import_ethers6.Interface(invisiProtocolAbi).encodeFunctionData("topUpCredit", [
5057
+ data: new import_ethers7.Interface(invisiProtocolAbi).encodeFunctionData("topUpCredit", [
4807
5058
  encodeCreditProof(p.proof),
4808
- p.params,
5059
+ { ...p.params, creation: { ...p.params.creation, ...normalizeFee(p.params.creation) } },
4809
5060
  p.deliveries,
4810
5061
  r.creation.funding
4811
5062
  ]),
@@ -4814,7 +5065,7 @@ function buildTopUpCreditCalldata(p) {
4814
5065
  }
4815
5066
 
4816
5067
  // src/funds.ts
4817
- var import_ethers7 = require("ethers");
5068
+ var import_ethers8 = require("ethers");
4818
5069
  var import_core7 = require("@invisi-labs/core");
4819
5070
  var TRANSACT_CAPACITIES = [14, 56, 112, 168];
4820
5071
  function selectTransactCapacity(inputs, outputs) {
@@ -4824,7 +5075,7 @@ function selectTransactCapacity(inputs, outputs) {
4824
5075
  }
4825
5076
  function normalizeTransactRequest(c, p, cs, funding = {}) {
4826
5077
  const ctx = normalizeContext(c);
4827
- if ((0, import_ethers7.getAddress)(p.token) !== ctx.tokenAddress)
5078
+ if ((0, import_ethers8.getAddress)(p.token) !== ctx.tokenAddress)
4828
5079
  throw new Error("request token mismatch");
4829
5080
  known(p, [
4830
5081
  "token",
@@ -4833,12 +5084,21 @@ function normalizeTransactRequest(c, p, cs, funding = {}) {
4833
5084
  "outputCommitments",
4834
5085
  "withdrawalAddress",
4835
5086
  "withdrawalAmount",
4836
- "deadline"
5087
+ "deadline",
5088
+ "feeRecipient",
5089
+ "feeAmount"
4837
5090
  ]);
4838
5091
  const ns = notes(p.nullifiers, "nullifiers"), os = notes(p.outputCommitments, "outputCommitments"), capacity = selectTransactCapacity(ns.length, os.length);
4839
- const sources = normalizeSources(p.sources, ns.length, capacity), deliveries = dense(cs, "deliveries").map((v) => normalizeOpaqueDelivery(v));
5092
+ const sources = normalizeSources(p.sources, ns.length, capacity), deliveries = dense(cs, "deliveries").map(
5093
+ (v) => normalizeOpaqueDelivery(v, { allowEmpty: true })
5094
+ );
4840
5095
  if (deliveries.length !== os.length) throw new Error("deliveries count mismatch");
4841
- const withdrawalAmount = uint(p.withdrawalAmount, 128, "withdrawalAmount"), withdrawalAddress = (0, import_ethers7.getAddress)(p.withdrawalAddress), f = normalizeFunding(funding);
5096
+ const withdrawalAmount = uint(p.withdrawalAmount, 128, "withdrawalAmount"), withdrawalAddress = (0, import_ethers8.getAddress)(p.withdrawalAddress), f = normalizeFunding(funding);
5097
+ const feeAmount = uint(p.feeAmount ?? 0n, 128, "feeAmount");
5098
+ const feeRecipient = (0, import_ethers8.getAddress)(
5099
+ p.feeRecipient ?? "0x0000000000000000000000000000000000000000"
5100
+ );
5101
+ if (feeAmount === 0n !== (BigInt(feeRecipient) === 0n)) throw new Error("invalid fee");
4842
5102
  if (withdrawalAmount === 0n !== (BigInt(withdrawalAddress) === 0n) || os.length === 0 && withdrawalAmount === 0n)
4843
5103
  throw new Error("invalid withdrawal");
4844
5104
  if (ns.length === 0 && (f.amount === 0n || withdrawalAmount !== 0n))
@@ -4865,6 +5125,8 @@ function normalizeTransactRequest(c, p, cs, funding = {}) {
4865
5125
  deliveriesHash: deliveriesHash(deliveries),
4866
5126
  withdrawalAddress,
4867
5127
  withdrawalAmount,
5128
+ feeRecipient,
5129
+ feeAmount,
4868
5130
  deadline: checkDeadline(c, p.deadline),
4869
5131
  depositAmount: f.amount,
4870
5132
  depositPayer: f.payer,
@@ -4889,7 +5151,9 @@ function transactPublicInputs(c, p, cs, f = {}) {
4889
5151
  r.withdrawalAmount,
4890
5152
  r.deadline,
4891
5153
  r.depositAmount,
4892
- BigInt(r.depositPayer)
5154
+ BigInt(r.depositPayer),
5155
+ BigInt(r.feeRecipient),
5156
+ r.feeAmount
4893
5157
  ].map(word);
4894
5158
  }
4895
5159
  function encodeTransactTypedData(c, p, deliveries, f = {}) {
@@ -4902,10 +5166,10 @@ function encodeTransactTypedData(c, p, deliveries, f = {}) {
4902
5166
  });
4903
5167
  }
4904
5168
  var singleTuple = [
4905
- "(address token,bytes32 merkleRoot,bytes32[] nullifiers,bytes32[] outputCommitments,uint256 inputTreeId,address withdrawalAddress,uint256 withdrawalAmount,uint256 deadline)"
5169
+ "(address token,bytes32 merkleRoot,bytes32[] nullifiers,bytes32[] outputCommitments,uint256 inputTreeId,address withdrawalAddress,uint256 withdrawalAmount,uint256 deadline,address feeRecipient,uint256 feeAmount)"
4906
5170
  ][0];
4907
5171
  var crossTuple = [
4908
- "(address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32[] outputCommitments,address withdrawalAddress,uint256 withdrawalAmount,uint256 deadline)"
5172
+ "(address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32[] outputCommitments,address withdrawalAddress,uint256 withdrawalAmount,uint256 deadline,address feeRecipient,uint256 feeAmount)"
4909
5173
  ][0];
4910
5174
  function transactFundingRequestHash(proof, p, cs) {
4911
5175
  const single = {
@@ -4916,26 +5180,28 @@ function transactFundingRequestHash(proof, p, cs) {
4916
5180
  inputTreeId: p.sources[0]?.treeId ?? 0n,
4917
5181
  withdrawalAddress: p.withdrawalAddress,
4918
5182
  withdrawalAmount: p.withdrawalAmount,
4919
- deadline: p.deadline
5183
+ deadline: p.deadline,
5184
+ feeRecipient: p.feeRecipient ?? "0x0000000000000000000000000000000000000000",
5185
+ feeAmount: p.feeAmount ?? 0n
4920
5186
  };
4921
- return p.sources.length > 1 ? (0, import_ethers7.keccak256)(
4922
- import_ethers7.AbiCoder.defaultAbiCoder().encode(
5187
+ return p.sources.length > 1 ? (0, import_ethers8.keccak256)(
5188
+ import_ethers8.AbiCoder.defaultAbiCoder().encode(
4923
5189
  [{ type: "bytes32" }, { type: "bytes32" }, crossTuple, { type: "bytes32" }].map(
4924
- (parameter) => import_ethers7.ParamType.from(parameter)
5190
+ (parameter) => import_ethers8.ParamType.from(parameter)
4925
5191
  ),
4926
5192
  [
4927
- (0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiCrossTreeTransact")),
4928
- (0, import_ethers7.keccak256)(proof),
4929
- p,
5193
+ (0, import_ethers8.keccak256)(new TextEncoder().encode("InvisiCrossTreeTransact")),
5194
+ (0, import_ethers8.keccak256)(proof),
5195
+ { ...p, feeRecipient: single.feeRecipient, feeAmount: single.feeAmount },
4930
5196
  deliveriesHash(cs)
4931
5197
  ]
4932
5198
  )
4933
- ) : (0, import_ethers7.keccak256)(
4934
- import_ethers7.AbiCoder.defaultAbiCoder().encode(
5199
+ ) : (0, import_ethers8.keccak256)(
5200
+ import_ethers8.AbiCoder.defaultAbiCoder().encode(
4935
5201
  [{ type: "bytes32" }, singleTuple, { type: "bytes32" }].map(
4936
- (parameter) => import_ethers7.ParamType.from(parameter)
5202
+ (parameter) => import_ethers8.ParamType.from(parameter)
4937
5203
  ),
4938
- [(0, import_ethers7.keccak256)(proof), single, deliveriesHash(cs)]
5204
+ [(0, import_ethers8.keccak256)(proof), single, deliveriesHash(cs)]
4939
5205
  )
4940
5206
  );
4941
5207
  }
@@ -4967,7 +5233,9 @@ function buildTransactCalldata(p) {
4967
5233
  outputCommitments: r.outputCommitments,
4968
5234
  withdrawalAddress: r.withdrawalAddress,
4969
5235
  withdrawalAmount: r.withdrawalAmount,
4970
- deadline: r.deadline
5236
+ deadline: r.deadline,
5237
+ feeRecipient: r.feeRecipient,
5238
+ feeAmount: r.feeAmount
4971
5239
  },
4972
5240
  deliveries: p.deliveries,
4973
5241
  funding: r.funding
@@ -4975,13 +5243,13 @@ function buildTransactCalldata(p) {
4975
5243
  const abi = invisiProtocolAbi.filter(
4976
5244
  (item) => item.type === "function" && item.name === "transact" && item.inputs.length === 2 && item.inputs[1]?.type === "tuple"
4977
5245
  );
4978
- const data = new import_ethers7.Interface(abi).encodeFunctionData("transact", [p.proof, request]);
5246
+ const data = new import_ethers8.Interface(abi).encodeFunctionData("transact", [p.proof, request]);
4979
5247
  return { data, capacity: r.capacity, approveAmount: r.depositAmount };
4980
5248
  }
4981
5249
  function buildTransactAggregateCalldata(p) {
4982
5250
  if (![4, 8, 12].includes(dense(p.requests, "requests").length))
4983
5251
  throw new Error("aggregate requires 4, 8 or 12 requests");
4984
- for (const request of p.requests) {
5252
+ const requests = p.requests.map((request) => {
4985
5253
  const r = normalizeTransactRequest(
4986
5254
  { ...p.context, tokenAddress: request.params.token },
4987
5255
  request.params,
@@ -4990,21 +5258,25 @@ function buildTransactAggregateCalldata(p) {
4990
5258
  );
4991
5259
  if (r.capacity !== 14) throw new Error("aggregate supports only capacity 14");
4992
5260
  validateFundingSubmission(r.funding, p.caller, p.context.now);
4993
- }
5261
+ return {
5262
+ ...request,
5263
+ params: { ...request.params, feeRecipient: r.feeRecipient, feeAmount: r.feeAmount }
5264
+ };
5265
+ });
4994
5266
  return {
4995
- data: new import_ethers7.Interface(
5267
+ data: new import_ethers8.Interface(
4996
5268
  invisiProtocolAbi.filter(
4997
5269
  (item) => item.type === "function" && item.name === "transact" && item.inputs[1]?.type === "tuple[]"
4998
5270
  )
4999
- ).encodeFunctionData("transact", [p.proof, p.requests]),
5271
+ ).encodeFunctionData("transact", [p.proof, requests]),
5000
5272
  capacity: 14
5001
5273
  };
5002
5274
  }
5003
5275
  async function validateShieldRequest(p) {
5004
5276
  normalizeContext(p.context);
5005
- if ((0, import_ethers7.getAddress)(p.params.token) !== (0, import_ethers7.getAddress)(p.context.tokenAddress))
5277
+ if ((0, import_ethers8.getAddress)(p.params.token) !== (0, import_ethers8.getAddress)(p.context.tokenAddress))
5006
5278
  throw new Error("request token mismatch");
5007
- known(p.params, ["token", "outputCommitments", "deadline"]);
5279
+ known(p.params, ["token", "outputCommitments", "deadline", "feeRecipient", "feeAmount"]);
5008
5280
  checkDeadline(p.context, p.params.deadline);
5009
5281
  const outputs = dense(p.outputs, "outputs"), commitments = notes(p.params.outputCommitments, "outputCommitments"), cs = dense(p.deliveries, "deliveries"), f = normalizeFunding(p.funding);
5010
5282
  if (outputs.length < 1 || outputs.length > 10 || commitments.length !== outputs.length || cs.length !== outputs.length)
@@ -5015,7 +5287,7 @@ async function validateShieldRequest(p) {
5015
5287
  uint(o.amount, 128, "amount");
5016
5288
  if (o.amount === 0n) throw new Error("amount must be positive");
5017
5289
  field(o.identity);
5018
- normalizeOpaqueDelivery(cs[i]);
5290
+ normalizeOpaqueDelivery(cs[i], { allowEmpty: true });
5019
5291
  if (await (0, import_core7.computeNoteCommitment)(
5020
5292
  p.context.chainId,
5021
5293
  o.identity,
@@ -5025,27 +5297,28 @@ async function validateShieldRequest(p) {
5025
5297
  throw new Error("output commitment mismatch");
5026
5298
  total += o.amount;
5027
5299
  }
5028
- if (total !== f.amount) throw new Error("funding must equal output total");
5300
+ if (total + normalizeFee(p.params).feeAmount !== f.amount)
5301
+ throw new Error("funding must equal output total plus fee");
5029
5302
  return f;
5030
5303
  }
5031
5304
  function shieldFundingRequestHash(params, outputs, cs) {
5032
- const outputHash = (0, import_ethers7.keccak256)(
5033
- import_ethers7.AbiCoder.defaultAbiCoder().encode(
5034
- ["(bytes32 identity,uint256 amount)[]"].map((parameter) => import_ethers7.ParamType.from(parameter)),
5305
+ const outputHash = (0, import_ethers8.keccak256)(
5306
+ import_ethers8.AbiCoder.defaultAbiCoder().encode(
5307
+ ["(bytes32 identity,uint256 amount)[]"].map((parameter) => import_ethers8.ParamType.from(parameter)),
5035
5308
  [outputs]
5036
5309
  )
5037
5310
  );
5038
- return (0, import_ethers7.keccak256)(
5039
- import_ethers7.AbiCoder.defaultAbiCoder().encode(
5311
+ return (0, import_ethers8.keccak256)(
5312
+ import_ethers8.AbiCoder.defaultAbiCoder().encode(
5040
5313
  [
5041
5314
  "bytes32",
5042
- "(address token,bytes32[] outputCommitments,uint256 deadline)",
5315
+ "(address token,bytes32[] outputCommitments,uint256 deadline,address feeRecipient,uint256 feeAmount)",
5043
5316
  "bytes32",
5044
5317
  "bytes32"
5045
- ].map((parameter) => import_ethers7.ParamType.from(parameter)),
5318
+ ].map((parameter) => import_ethers8.ParamType.from(parameter)),
5046
5319
  [
5047
- (0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiShield")),
5048
- params,
5320
+ (0, import_ethers8.keccak256)(new TextEncoder().encode("InvisiShield")),
5321
+ { ...params, ...normalizeFee(params) },
5049
5322
  outputHash,
5050
5323
  deliveriesHash(cs)
5051
5324
  ]
@@ -5071,8 +5344,8 @@ async function buildShieldCalldata(p) {
5071
5344
  const f = await validateShieldRequest(p);
5072
5345
  validateFundingSubmission(f, p.caller, p.context.now);
5073
5346
  return {
5074
- data: new import_ethers7.Interface(invisiProtocolAbi).encodeFunctionData("shield", [
5075
- p.params,
5347
+ data: new import_ethers8.Interface(invisiProtocolAbi).encodeFunctionData("shield", [
5348
+ { ...p.params, ...normalizeFee(p.params) },
5076
5349
  p.outputs,
5077
5350
  p.deliveries,
5078
5351
  f
@@ -5082,7 +5355,7 @@ async function buildShieldCalldata(p) {
5082
5355
  }
5083
5356
  function transactUserPublicInputs(c, p, cs, f = {}) {
5084
5357
  const words = transactPublicInputs(c, p, cs, f), digest = BigInt(
5085
- ((typed) => import_ethers7.TypedDataEncoder.hash(
5358
+ ((typed) => import_ethers8.TypedDataEncoder.hash(
5086
5359
  typed.domain,
5087
5360
  Object.fromEntries(
5088
5361
  Object.entries(typed.types).map(([name, fields]) => [
@@ -5101,11 +5374,11 @@ function aggregateMemberRequestHash(c, r) {
5101
5374
  r.params.outputCommitments.length
5102
5375
  );
5103
5376
  if (capacity !== 14) throw new Error("aggregate supports only capacity 14");
5104
- return (0, import_ethers7.keccak256)(
5105
- import_ethers7.AbiCoder.defaultAbiCoder().encode(
5106
- ["bytes32", "uint256", "bytes32[]"].map((parameter) => import_ethers7.ParamType.from(parameter)),
5377
+ return (0, import_ethers8.keccak256)(
5378
+ import_ethers8.AbiCoder.defaultAbiCoder().encode(
5379
+ ["bytes32", "uint256", "bytes32[]"].map((parameter) => import_ethers8.ParamType.from(parameter)),
5107
5380
  [
5108
- (0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiAtomicBatchMemberV1")),
5381
+ (0, import_ethers8.keccak256)(new TextEncoder().encode("InvisiAtomicBatchMemberV1")),
5109
5382
  BigInt(capacity),
5110
5383
  transactPublicInputs(c, r.params, r.deliveries, r.funding)
5111
5384
  ]
@@ -5139,11 +5412,11 @@ function encodeAggregateFundingTypedData(c, r) {
5139
5412
  }
5140
5413
 
5141
5414
  // src/Protocol.ts
5142
- var import_ethers9 = require("ethers");
5415
+ var import_ethers10 = require("ethers");
5143
5416
  var import_rpc = require("@invisi-labs/rpc");
5144
5417
 
5145
5418
  // src/TokenProtocol.ts
5146
- var import_ethers8 = require("ethers");
5419
+ var import_ethers9 = require("ethers");
5147
5420
  var import_core8 = require("@invisi-labs/core");
5148
5421
  var TokenProtocol = class {
5149
5422
  context;
@@ -5168,7 +5441,7 @@ var TokenProtocol = class {
5168
5441
  throw new Error("deployment chain mismatch");
5169
5442
  }
5170
5443
  const code = await reader.getCode(this.context.protocolAddress);
5171
- if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || this.expectedRuntimeCodeHash && (0, import_ethers8.keccak256)(code) !== this.expectedRuntimeCodeHash) {
5444
+ if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || this.expectedRuntimeCodeHash && (0, import_ethers9.keccak256)(code) !== this.expectedRuntimeCodeHash) {
5172
5445
  throw new Error("deployment runtime code profile mismatch");
5173
5446
  }
5174
5447
  const tokenCode = await reader.getCode(this.context.tokenAddress);
@@ -5258,15 +5531,15 @@ var Protocol = class _Protocol {
5258
5531
  const reader = "getNetwork" in connection ? {
5259
5532
  getChainId: async () => (await connection.getNetwork()).chainId,
5260
5533
  getCode: async (address) => await connection.getCode(address),
5261
- getProtocolAddressRegistry: async (address) => (0, import_ethers9.getAddress)(
5262
- await new import_ethers9.Contract(
5534
+ getProtocolAddressRegistry: async (address) => (0, import_ethers10.getAddress)(
5535
+ await new import_ethers10.Contract(
5263
5536
  address,
5264
5537
  ["function addressRegistry() view returns (address)"],
5265
5538
  connection
5266
5539
  ).getFunction("addressRegistry")()
5267
5540
  ),
5268
5541
  getProtocolVersion: async (address) => BigInt(
5269
- await new import_ethers9.Contract(
5542
+ await new import_ethers10.Contract(
5270
5543
  address,
5271
5544
  ["function VERSION() view returns (uint256)"],
5272
5545
  connection
@@ -5276,7 +5549,7 @@ var Protocol = class _Protocol {
5276
5549
  if (await reader.getChainId() !== this.context.chainId)
5277
5550
  throw new Error("deployment chain mismatch");
5278
5551
  const code = await reader.getCode(this.context.protocolAddress);
5279
- if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || (0, import_ethers9.keccak256)(code) !== this.deployment.protocol.runtimeCodeHash)
5552
+ if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || (0, import_ethers10.keccak256)(code) !== this.deployment.protocol.runtimeCodeHash)
5280
5553
  throw new Error("protocol runtime code profile mismatch");
5281
5554
  if (reader.getProtocolVersion && await reader.getProtocolVersion(this.context.protocolAddress) !== 1n)
5282
5555
  throw new Error("unsupported onchain protocol version");
@@ -5284,12 +5557,12 @@ var Protocol = class _Protocol {
5284
5557
  if (registry) {
5285
5558
  if (!reader.getProtocolAddressRegistry)
5286
5559
  throw new Error("registry binding reader capability is missing");
5287
- if ((0, import_ethers9.getAddress)(
5560
+ if ((0, import_ethers10.getAddress)(
5288
5561
  await reader.getProtocolAddressRegistry(this.context.protocolAddress)
5289
- ) !== (0, import_ethers9.getAddress)(registry.address))
5562
+ ) !== (0, import_ethers10.getAddress)(registry.address))
5290
5563
  throw new Error("protocol registry binding mismatch");
5291
5564
  const registryCode = await reader.getCode(registry.address);
5292
- if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(registryCode) || (0, import_ethers9.keccak256)(registryCode) !== registry.runtimeCodeHash)
5565
+ if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(registryCode) || (0, import_ethers10.keccak256)(registryCode) !== registry.runtimeCodeHash)
5293
5566
  throw new Error("registry runtime code profile mismatch");
5294
5567
  }
5295
5568
  }
@@ -5303,7 +5576,7 @@ var Protocol = class _Protocol {
5303
5576
  /** Build an operation context for one asset within this same deployment. */
5304
5577
  forToken(tokenAddress) {
5305
5578
  return new TokenProtocol(
5306
- { ...this.context, tokenAddress: (0, import_ethers9.getAddress)(tokenAddress) },
5579
+ { ...this.context, tokenAddress: (0, import_ethers10.getAddress)(tokenAddress) },
5307
5580
  { expectedRuntimeCodeHash: this.deployment.protocol.runtimeCodeHash }
5308
5581
  );
5309
5582
  }
@@ -5314,7 +5587,7 @@ var import_core9 = require("@invisi-labs/core");
5314
5587
  async function verifyNoteCommitment(params) {
5315
5588
  const expected = await (0, import_core9.computeNoteCommitment)(
5316
5589
  params.chainId,
5317
- await (0, import_core9.computeNoteIdentity)(BigInt(params.walletIdentity), BigInt(params.nonce)),
5590
+ await (0, import_core9.computeNoteIdentity)(BigInt(params.ownerAddress), BigInt(params.nonce)),
5318
5591
  BigInt(params.tokenAddress),
5319
5592
  params.amount
5320
5593
  );
@@ -5346,12 +5619,12 @@ var import_prover = require("@invisi-labs/prover");
5346
5619
  // src/witness-layouts.json
5347
5620
  var witness_layouts_default = {
5348
5621
  transact_user_slots14: {
5349
- artifactSha256: "486a749ae3944ae83a7ff2d298e7469b18737d88553a7d99c4782f22f7332996",
5622
+ artifactSha256: "df9458f0be9c8905241ee74e5f11c0e1c348ef749fe1a9d599034a983f08dbd5",
5350
5623
  keys: {
5351
- evm: "7b3e65d5201246e733a1816489d80acb219a98e8606e1b81e6d48ff0c1fd537a",
5352
- "noir-recursive": "148957e28e6339a8ce1121851fb7a232e31f4c5b741e415733b8d627f4b62649"
5624
+ evm: "a9db580b09d05f09d4ea58b8d9755855525b8cc20beee4b1fbfe4cad10251e4e",
5625
+ "noir-recursive": "912191fc9484b2c0ab869d44900054b1a7c25c3256177abfc102884f3fa7d7ed"
5353
5626
  },
5354
- publicInputCount: 57,
5627
+ publicInputCount: 59,
5355
5628
  public: [
5356
5629
  {
5357
5630
  name: "chain_id",
@@ -5433,6 +5706,16 @@ var witness_layouts_default = {
5433
5706
  count: 1,
5434
5707
  array: false
5435
5708
  },
5709
+ {
5710
+ name: "fee_recipient",
5711
+ count: 1,
5712
+ array: false
5713
+ },
5714
+ {
5715
+ name: "fee_amount",
5716
+ count: 1,
5717
+ array: false
5718
+ },
5436
5719
  {
5437
5720
  name: "auth_digest_high",
5438
5721
  count: 1,
@@ -5445,11 +5728,11 @@ var witness_layouts_default = {
5445
5728
  }
5446
5729
  ],
5447
5730
  private: [
5448
- "wallet_identity",
5731
+ "input_owner_address",
5449
5732
  "public_key_x",
5450
5733
  "public_key_y",
5451
5734
  "signature",
5452
- "output_wallet_identities",
5735
+ "output_identities",
5453
5736
  "amounts",
5454
5737
  "nonces",
5455
5738
  "leaf_indices",
@@ -5458,11 +5741,11 @@ var witness_layouts_default = {
5458
5741
  ]
5459
5742
  },
5460
5743
  transact_user_slots56: {
5461
- artifactSha256: "169db2ff23c15adb14756edf9bb99bbd343df807b3e1c7f1f510070897e653cf",
5744
+ artifactSha256: "370299e1ee32a57b6a81ccdbf5e95efef144bee17d38d402bbbfbaa392d355d8",
5462
5745
  keys: {
5463
- evm: "cbf54de94bff266bf846f9722c0f3ffa1fb7a0f9f478466f193de0e9123ce7f5"
5746
+ evm: "2bb2fdf9ef33200038aa6e0a9f35e2a7252bf3946f5b5d68dd0ae85172adeddf"
5464
5747
  },
5465
- publicInputCount: 183,
5748
+ publicInputCount: 185,
5466
5749
  public: [
5467
5750
  {
5468
5751
  name: "chain_id",
@@ -5544,6 +5827,16 @@ var witness_layouts_default = {
5544
5827
  count: 1,
5545
5828
  array: false
5546
5829
  },
5830
+ {
5831
+ name: "fee_recipient",
5832
+ count: 1,
5833
+ array: false
5834
+ },
5835
+ {
5836
+ name: "fee_amount",
5837
+ count: 1,
5838
+ array: false
5839
+ },
5547
5840
  {
5548
5841
  name: "auth_digest_high",
5549
5842
  count: 1,
@@ -5556,11 +5849,11 @@ var witness_layouts_default = {
5556
5849
  }
5557
5850
  ],
5558
5851
  private: [
5559
- "wallet_identity",
5852
+ "input_owner_address",
5560
5853
  "public_key_x",
5561
5854
  "public_key_y",
5562
5855
  "signature",
5563
- "output_wallet_identities",
5856
+ "output_identities",
5564
5857
  "amounts",
5565
5858
  "nonces",
5566
5859
  "leaf_indices",
@@ -5569,11 +5862,11 @@ var witness_layouts_default = {
5569
5862
  ]
5570
5863
  },
5571
5864
  transact_user_slots112: {
5572
- artifactSha256: "221bbbd6ff0c7d7dec74677e52484f082b3e176bb0fa47f3236064e396d73739",
5865
+ artifactSha256: "259417390705f5ced1cbd671582a2fe40dbf7a259d8717f4e90989dc4368ad91",
5573
5866
  keys: {
5574
- evm: "67b2d361b023f193ecdb5a9aefbe2840349ee5ce848ab4101416734f3a7e91e9"
5867
+ evm: "523652b9391818c0af0af8668ba2cd786be25ef00e6bcafa662ed829a32746a7"
5575
5868
  },
5576
- publicInputCount: 351,
5869
+ publicInputCount: 353,
5577
5870
  public: [
5578
5871
  {
5579
5872
  name: "chain_id",
@@ -5655,6 +5948,16 @@ var witness_layouts_default = {
5655
5948
  count: 1,
5656
5949
  array: false
5657
5950
  },
5951
+ {
5952
+ name: "fee_recipient",
5953
+ count: 1,
5954
+ array: false
5955
+ },
5956
+ {
5957
+ name: "fee_amount",
5958
+ count: 1,
5959
+ array: false
5960
+ },
5658
5961
  {
5659
5962
  name: "auth_digest_high",
5660
5963
  count: 1,
@@ -5667,11 +5970,11 @@ var witness_layouts_default = {
5667
5970
  }
5668
5971
  ],
5669
5972
  private: [
5670
- "wallet_identity",
5973
+ "input_owner_address",
5671
5974
  "public_key_x",
5672
5975
  "public_key_y",
5673
5976
  "signature",
5674
- "output_wallet_identities",
5977
+ "output_identities",
5675
5978
  "amounts",
5676
5979
  "nonces",
5677
5980
  "leaf_indices",
@@ -5680,11 +5983,11 @@ var witness_layouts_default = {
5680
5983
  ]
5681
5984
  },
5682
5985
  transact_user_slots168: {
5683
- artifactSha256: "d479253eaaacc973806a84e142e2362d873bba0f150ce050d32b8d9b2947adc8",
5986
+ artifactSha256: "2a86703ca068c50f305d3b4b856ab3b2145d066da0bab894eac8e7c174c20292",
5684
5987
  keys: {
5685
- evm: "c50e72b0718c6393f82f5a67e248ba093d0db56ece42bbf092da93e9369c2624"
5988
+ evm: "c9d821fdd5b8cfcdc7fe93e673a8c99487879a4680c8f1b86c0b5c05a3cad515"
5686
5989
  },
5687
- publicInputCount: 519,
5990
+ publicInputCount: 521,
5688
5991
  public: [
5689
5992
  {
5690
5993
  name: "chain_id",
@@ -5766,6 +6069,16 @@ var witness_layouts_default = {
5766
6069
  count: 1,
5767
6070
  array: false
5768
6071
  },
6072
+ {
6073
+ name: "fee_recipient",
6074
+ count: 1,
6075
+ array: false
6076
+ },
6077
+ {
6078
+ name: "fee_amount",
6079
+ count: 1,
6080
+ array: false
6081
+ },
5769
6082
  {
5770
6083
  name: "auth_digest_high",
5771
6084
  count: 1,
@@ -5778,11 +6091,11 @@ var witness_layouts_default = {
5778
6091
  }
5779
6092
  ],
5780
6093
  private: [
5781
- "wallet_identity",
6094
+ "input_owner_address",
5782
6095
  "public_key_x",
5783
6096
  "public_key_y",
5784
6097
  "signature",
5785
- "output_wallet_identities",
6098
+ "output_identities",
5786
6099
  "amounts",
5787
6100
  "nonces",
5788
6101
  "leaf_indices",
@@ -5791,11 +6104,11 @@ var witness_layouts_default = {
5791
6104
  ]
5792
6105
  },
5793
6106
  transact_aggregate_14_4: {
5794
- artifactSha256: "4fe7c63fb80cba35af4c4525fbabcfb75033286e681afbdcb3fb043c03456246",
6107
+ artifactSha256: "4cd3f3d0dbcac9a48fec728450fd73a247321f655da02bd08db789e07b47527b",
5795
6108
  keys: {
5796
- evm: "664d4ff0de6b8c876ce990ea368d7a59cee411463c24dd5621d64c8949554674"
6109
+ evm: "6654b125cb96d5f4dd263c82cb34b0862bf63ff761fe5feab834f10283a0265d"
5797
6110
  },
5798
- publicInputCount: 229,
6111
+ publicInputCount: 237,
5799
6112
  public: [
5800
6113
  {
5801
6114
  name: "statements",
@@ -5815,11 +6128,11 @@ var witness_layouts_default = {
5815
6128
  ]
5816
6129
  },
5817
6130
  transact_aggregate_14_8: {
5818
- artifactSha256: "0a266ad4bb4c6dce42b1e851fcbb34b1becae1edd6bf6af82d7b9ed7184576df",
6131
+ artifactSha256: "b36ff5370043782364d41dbe00443970292b0240429f241c974ae6c9b10debfe",
5819
6132
  keys: {
5820
- evm: "042139122d0eee8beeaa9c18397276fa5a2872218495fa16ca438fbdd80fa3e1"
6133
+ evm: "2ad5b8b24109edf24197e97fbad35519d7d18558df19183ca3f91c4089ce4421"
5821
6134
  },
5822
- publicInputCount: 457,
6135
+ publicInputCount: 473,
5823
6136
  public: [
5824
6137
  {
5825
6138
  name: "statements",
@@ -5839,11 +6152,11 @@ var witness_layouts_default = {
5839
6152
  ]
5840
6153
  },
5841
6154
  transact_aggregate_14_12: {
5842
- artifactSha256: "738849e83eb4a78eb69cb6e20a86f6f27ba3784d04a83abd338f84de5c20d7d2",
6155
+ artifactSha256: "1191a92a333d826d4c4bd6a2e701a7751beb609904f8b928e3816f276d6fda67",
5843
6156
  keys: {
5844
- evm: "539928b264aea4d07a41e772d5d5a7b7666a6883decb985c27ca7422e7f8ea1f"
6157
+ evm: "a8b06d969e97f53624fae05d08aa548182ad09db24fe60159fae61d243c0cb9d"
5845
6158
  },
5846
- publicInputCount: 685,
6159
+ publicInputCount: 709,
5847
6160
  public: [
5848
6161
  {
5849
6162
  name: "statements",
@@ -5863,11 +6176,11 @@ var witness_layouts_default = {
5863
6176
  ]
5864
6177
  },
5865
6178
  create_credit: {
5866
- artifactSha256: "3ed6cfdee4f5fd840f023580f76c208768777fea79737f2511377e5c55be0230",
6179
+ artifactSha256: "16a41fd585d5f925e4e93fd6a308e1ca8c90ea287778871cb0d214f0d0e223ce",
5867
6180
  keys: {
5868
- evm: "56f663c6053be0d158a271022d200c732597efd3a2e0be48fe94549d0b1795e0"
6181
+ evm: "e8d3dc1f6922dbe1a0aa6016e65664be28d7005180ee943a4b237ac5518971bb"
5869
6182
  },
5870
- publicInputCount: 46,
6183
+ publicInputCount: 48,
5871
6184
  public: [
5872
6185
  {
5873
6186
  name: "chain_id",
@@ -5954,6 +6267,16 @@ var witness_layouts_default = {
5954
6267
  count: 1,
5955
6268
  array: false
5956
6269
  },
6270
+ {
6271
+ name: "fee_recipient",
6272
+ count: 1,
6273
+ array: false
6274
+ },
6275
+ {
6276
+ name: "fee_amount",
6277
+ count: 1,
6278
+ array: false
6279
+ },
5957
6280
  {
5958
6281
  name: "auth_digest_high",
5959
6282
  count: 1,
@@ -6512,11 +6835,11 @@ var witness_layouts_default = {
6512
6835
  ]
6513
6836
  },
6514
6837
  credit_cancel: {
6515
- artifactSha256: "b4459c2cf756d096e37291cf4d7cd129866b6d420b6d03c928f383b057112ccb",
6838
+ artifactSha256: "6485609280fe5a3d44ca9f1865b29b44253b3d2cd49770d000e7bb7a3db8e65d",
6516
6839
  keys: {
6517
- evm: "fc8ad196ef15f3328afcc8f01d867a3ebefd15451c2813948442fab1923b73b2"
6840
+ evm: "d74cf842d204cdf271c06a69482ddff11568e89630346b634d486205bec4bd9e"
6518
6841
  },
6519
- publicInputCount: 11,
6842
+ publicInputCount: 13,
6520
6843
  public: [
6521
6844
  {
6522
6845
  name: "chain_id",
@@ -6563,6 +6886,16 @@ var witness_layouts_default = {
6563
6886
  count: 1,
6564
6887
  array: false
6565
6888
  },
6889
+ {
6890
+ name: "fee_recipient",
6891
+ count: 1,
6892
+ array: false
6893
+ },
6894
+ {
6895
+ name: "fee_amount",
6896
+ count: 1,
6897
+ array: false
6898
+ },
6566
6899
  {
6567
6900
  name: "auth_digest_high",
6568
6901
  count: 1,
@@ -6596,11 +6929,11 @@ var witness_layouts_default = {
6596
6929
  ]
6597
6930
  },
6598
6931
  credit_top_up: {
6599
- artifactSha256: "2ffebd5753ec1b0c050204d4f97498765fe61ea01a793a9b2466c2f97536345c",
6932
+ artifactSha256: "3004eea1c26ec8e33f8fc9ee171a3b6af250682efb607f7003ae58f8327998ab",
6600
6933
  keys: {
6601
- evm: "40b02a9d2e7eb7b49daaac4b7760328537b7982fd5a225cc065bb74cd5ef44b3"
6934
+ evm: "b7f378a871a27649c3f7fd1af554c8f87d99bcf0780b21972e910212ed4e5a0d"
6602
6935
  },
6603
- publicInputCount: 50,
6936
+ publicInputCount: 52,
6604
6937
  public: [
6605
6938
  {
6606
6939
  name: "chain_id",
@@ -6687,6 +7020,16 @@ var witness_layouts_default = {
6687
7020
  count: 1,
6688
7021
  array: false
6689
7022
  },
7023
+ {
7024
+ name: "fee_recipient",
7025
+ count: 1,
7026
+ array: false
7027
+ },
7028
+ {
7029
+ name: "fee_amount",
7030
+ count: 1,
7031
+ array: false
7032
+ },
6690
7033
  {
6691
7034
  name: "credit_tree_id",
6692
7035
  count: 1,
@@ -6848,7 +7191,7 @@ var WitnessBuilder = class {
6848
7191
  words: words.slice(0, -2).map(BigInt)
6849
7192
  };
6850
7193
  check2(
6851
- signed.walletIdentity === identity && signed.digest === (0, import_core10.computeWalletAuthorizationDigest)(request),
7194
+ signed.ownerAddress === identity && signed.digest === (0, import_core10.computeWalletAuthorizationDigest)(request),
6852
7195
  "authorization statement mismatch"
6853
7196
  );
6854
7197
  const witness = signed.withWitness((value) => value);
@@ -6883,7 +7226,7 @@ var WitnessBuilder = class {
6883
7226
  this.context(note);
6884
7227
  return (0, import_core10.computeNoteCommitment)(
6885
7228
  note.chainId,
6886
- await (0, import_core10.computeNoteIdentity)(BigInt(note.walletIdentity), note.nonce),
7229
+ await (0, import_core10.computeNoteIdentity)(BigInt(note.ownerAddress), note.nonce),
6887
7230
  note.tokenAddress,
6888
7231
  note.amount
6889
7232
  );
@@ -6908,7 +7251,7 @@ var WitnessBuilder = class {
6908
7251
  check2(inputs.length === nullifiers.length, "input count mismatch");
6909
7252
  return Promise.all(
6910
7253
  inputs.map(async (input, i) => {
6911
- check2(input.note.walletIdentity === identity, "input wallet mismatch");
7254
+ check2(input.note.ownerAddress === identity, "input wallet mismatch");
6912
7255
  const leaf = await this.noteLeaf(input.note);
6913
7256
  check2(
6914
7257
  await (0, import_core10.computeNoteNullifier)(input.note.chainId, input.note.nonce, leaf) === nullifiers[i],
@@ -6924,8 +7267,8 @@ var WitnessBuilder = class {
6924
7267
  p.inputs.length === n.inputCount && p.outputs.length === n.outputCount,
6925
7268
  "note count mismatch"
6926
7269
  );
6927
- const identity = p.inputs[0]?.note.walletIdentity;
6928
- const unsignedSweep = !!identity && !p.authorization && n.outputCount === 0 && n.depositAmount === 0n && BigInt(p.params.withdrawalAddress) === BigInt(identity);
7270
+ const identity = p.inputs[0]?.note.ownerAddress;
7271
+ const unsignedSweep = !!identity && !p.authorization && n.outputCount === 0 && n.depositAmount === 0n && n.feeAmount === 0n && BigInt(p.params.withdrawalAddress) === BigInt(identity);
6929
7272
  const authority = identity && !unsignedSweep ? await this.authority("transact", n.capacity, words, p.authorization, identity) : zeroAuthority();
6930
7273
  const sources = await this.noteInputs(
6931
7274
  p.inputs,
@@ -6934,22 +7277,44 @@ var WitnessBuilder = class {
6934
7277
  identity ?? "0x" + "00".repeat(32),
6935
7278
  authority
6936
7279
  );
6937
- for (const [i, note] of p.outputs.entries())
6938
- check2(
6939
- await this.noteLeaf(note) === p.params.outputCommitments[i],
6940
- "output commitment mismatch"
6941
- );
6942
- const all = [...p.inputs.map((input) => input.note), ...p.outputs];
7280
+ const outputs = await Promise.all(
7281
+ p.outputs.map(async (output, i) => {
7282
+ const opening = "identity" in output ? output.note : output;
7283
+ const identity2 = "identity" in output ? field(output.identity) : BigInt(
7284
+ await (0, import_core10.computeNoteIdentity)(BigInt(output.ownerAddress), output.nonce)
7285
+ );
7286
+ const amount = uint(output.amount, 128, "output amount");
7287
+ check2(identity2 !== 0n && amount !== 0n, "zero output identity or amount");
7288
+ if (opening) {
7289
+ this.context(opening);
7290
+ check2(
7291
+ opening.amount === amount && BigInt(
7292
+ await (0, import_core10.computeNoteIdentity)(
7293
+ BigInt(opening.ownerAddress),
7294
+ opening.nonce
7295
+ )
7296
+ ) === identity2,
7297
+ "output opening mismatch"
7298
+ );
7299
+ }
7300
+ const commitment = await (0, import_core10.computeNoteCommitment)(
7301
+ c.chainId,
7302
+ word(identity2),
7303
+ BigInt(c.tokenAddress),
7304
+ amount
7305
+ );
7306
+ check2(commitment === p.params.outputCommitments[i], "output commitment mismatch");
7307
+ return { identity: identity2, amount };
7308
+ })
7309
+ );
7310
+ const all = [...p.inputs.map((input) => input.note), ...outputs];
6943
7311
  return provingRequest(
6944
7312
  `transact_user_slots${n.capacity}`,
6945
7313
  {
6946
- wallet_identity: identity ? BigInt(identity) : 0n,
7314
+ input_owner_address: identity ? BigInt(identity) : 0n,
6947
7315
  ...authority,
6948
- output_wallet_identities: pad2(
6949
- [
6950
- ...p.inputs.map(() => 0n),
6951
- ...p.outputs.map((note) => BigInt(note.walletIdentity))
6952
- ],
7316
+ output_identities: pad2(
7317
+ [...p.inputs.map(() => 0n), ...outputs.map((output) => output.identity)],
6953
7318
  n.capacity,
6954
7319
  () => 0n
6955
7320
  ),
@@ -6959,7 +7324,7 @@ var WitnessBuilder = class {
6959
7324
  () => 0n
6960
7325
  ),
6961
7326
  nonces: pad2(
6962
- all.map((note) => note.nonce),
7327
+ [...p.inputs.map((input) => input.note.nonce), ...outputs.map(() => 0n)],
6963
7328
  n.capacity,
6964
7329
  () => 0n
6965
7330
  ),
@@ -7003,7 +7368,7 @@ var WitnessBuilder = class {
7003
7368
  );
7004
7369
  if (p.change)
7005
7370
  check2(
7006
- p.change.walletIdentity === note.ownerWalletIdentity && await this.noteLeaf(p.change) === p.params.changeCommitment,
7371
+ p.change.ownerAddress === note.ownerWalletIdentity && await this.noteLeaf(p.change) === p.params.changeCommitment,
7007
7372
  "change commitment mismatch"
7008
7373
  );
7009
7374
  else check2(BigInt(p.params.changeCommitment) === 0n, "missing change note");
@@ -7222,14 +7587,14 @@ var WitnessBuilder = class {
7222
7587
  };
7223
7588
 
7224
7589
  // src/factory.ts
7225
- var import_ethers10 = require("ethers");
7590
+ var import_ethers11 = require("ethers");
7226
7591
  async function resolveInstanceAddress(client, factoryAddress, salt) {
7227
- const instance = await new import_ethers10.Contract(
7228
- (0, import_ethers10.getAddress)(factoryAddress),
7592
+ const instance = await new import_ethers11.Contract(
7593
+ (0, import_ethers11.getAddress)(factoryAddress),
7229
7594
  invisiFactoryAbi,
7230
7595
  client
7231
7596
  ).getFunction("getInstanceAddress")(salt);
7232
- return (0, import_ethers10.getAddress)(instance);
7597
+ return (0, import_ethers11.getAddress)(instance);
7233
7598
  }
7234
7599
  // Annotate the CommonJS export names for ESM import in node:
7235
7600
  0 && (module.exports = {