@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.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  invisiAddressRegistryAbi,
3
3
  invisiFactoryAbi,
4
4
  invisiProtocolAbi
5
- } from "./chunk-47SC3EAI.js";
5
+ } from "./chunk-BYJ4LXCJ.js";
6
6
 
7
7
  // src/AddressRegistry.ts
8
8
  import { getAddress as getAddress2, keccak256 } from "ethers";
@@ -38,10 +38,10 @@ function hexBytes(value, length) {
38
38
  throw new Error(`Expected ${length} hexadecimal bytes`);
39
39
  return getBytes(value);
40
40
  }
41
- function normalizeKeys(walletIdentity, keys) {
41
+ function normalizeKeys(ownerAddress, keys) {
42
42
  const decoded = decodeAddress(
43
43
  ReceivingAddress.from({
44
- walletIdentity,
44
+ ownerAddress,
45
45
  viewingPublicKey: hexBytes(keys.viewingPublicKey, 33),
46
46
  clueKey: hexBytes(keys.clueKey, 32)
47
47
  }).toString()
@@ -56,14 +56,14 @@ function normalize(context, registration, options) {
56
56
  uint64(context.chainId, "chainId");
57
57
  const registryAddress = getAddress(context.registryAddress);
58
58
  if (BigInt(registryAddress) === 0n) throw new Error("Registry address must be nonzero");
59
- if (!/^0x(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$/.test(registration.walletIdentity))
59
+ if (!/^0x(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$/.test(registration.ownerAddress))
60
60
  throw new Error("Wallet identity must be an EVM owner or padded bytes32");
61
- const walletIdentity = decodeAddress(
61
+ const ownerAddress = decodeAddress(
62
62
  ReceivingAddress.fromIdentity(
63
- toBeHex(BigInt(registration.walletIdentity), 20)
63
+ toBeHex(BigInt(registration.ownerAddress), 20)
64
64
  ).toString()
65
- ).walletIdentity;
66
- const keys = normalizeKeys(walletIdentity, registration.keys);
65
+ ).ownerAddress;
66
+ const keys = normalizeKeys(ownerAddress, registration.keys);
67
67
  const nonce = uint64(registration.nonce, "nonce"), deadline = uint64(registration.deadline, "deadline");
68
68
  if (nonce === MAX_NONCE) throw new Error("Registry nonce exhausted");
69
69
  if (options.update !== void 0 && typeof options.update !== "boolean")
@@ -74,7 +74,7 @@ function normalize(context, registration, options) {
74
74
  throw new Error("Registry nonce mismatch");
75
75
  if (context.now !== void 0 && deadline < uint64(context.now, "now"))
76
76
  throw new Error("Registration expired");
77
- return { registryAddress, registration: { walletIdentity, keys, nonce, deadline } };
77
+ return { registryAddress, registration: { ownerAddress, keys, nonce, deadline } };
78
78
  }
79
79
  function registrationTypedData(context, registration, options = {}) {
80
80
  const { registryAddress, registration: r } = normalize(context, registration, options);
@@ -97,7 +97,7 @@ function registrationTypedData(context, registration, options = {}) {
97
97
  ]
98
98
  },
99
99
  message: {
100
- walletIdentity: toBeHex(BigInt(r.walletIdentity), 32),
100
+ walletIdentity: toBeHex(BigInt(r.ownerAddress), 32),
101
101
  ...r.keys,
102
102
  nonce: r.nonce,
103
103
  deadline: r.deadline
@@ -119,8 +119,11 @@ function buildRegistrationCalldata(context, registration, signature, options = {
119
119
  options.update ? "updateKeys" : "registerKeys",
120
120
  [
121
121
  {
122
- ...normalized.registration,
123
- walletIdentity: toBeHex(BigInt(normalized.registration.walletIdentity), 32)
122
+ // The registry wire schema retains its deployed EIP-712/ABI field name.
123
+ walletIdentity: toBeHex(BigInt(normalized.registration.ownerAddress), 32),
124
+ keys: normalized.registration.keys,
125
+ nonce: normalized.registration.nonce,
126
+ deadline: normalized.registration.deadline
124
127
  },
125
128
  signature
126
129
  ]
@@ -130,10 +133,10 @@ function buildRegistrationCalldata(context, registration, signature, options = {
130
133
  function createRegistryReceivingKeyLookup(client, registryAddress) {
131
134
  const address = getAddress(registryAddress);
132
135
  if (BigInt(address) === 0n) throw new Error("Registry address must be nonzero");
133
- return async (walletIdentity) => {
136
+ return async (ownerAddress) => {
134
137
  const identity = decodeAddress(
135
- ReceivingAddress.fromIdentity(walletIdentity).toString()
136
- ).walletIdentity;
138
+ ReceivingAddress.fromIdentity(ownerAddress).toString()
139
+ ).ownerAddress;
137
140
  const [keys, nonce] = await new Contract(
138
141
  address,
139
142
  invisiAddressRegistryAbi,
@@ -181,7 +184,7 @@ var RegistrationOperation = class _RegistrationOperation {
181
184
  const context = { ...registry.context, now: block.timestamp };
182
185
  const nonce = await runtime.reader.getRegistryNonce(
183
186
  context,
184
- runtime.wallet.walletIdentity,
187
+ runtime.wallet.ownerAddress,
185
188
  block
186
189
  );
187
190
  check(
@@ -195,7 +198,7 @@ var RegistrationOperation = class _RegistrationOperation {
195
198
  const address = ReceivingAddress2.parse(await registry.resolve(runtime.wallet.getAddress()));
196
199
  const keys = address.getReceivingKeys();
197
200
  const registration = {
198
- walletIdentity: runtime.wallet.walletIdentity,
201
+ ownerAddress: runtime.wallet.ownerAddress,
199
202
  keys: {
200
203
  viewingPublicKey: hexlify2(keys.viewingPublicKey),
201
204
  clueKey: hexlify2(keys.clueKey)
@@ -247,7 +250,7 @@ var RegistrationOperation = class _RegistrationOperation {
247
250
  "registry signature must be nonempty hexadecimal bytes"
248
251
  );
249
252
  const p = this.#plan;
250
- const owner = p.registration.walletIdentity;
253
+ const owner = p.registration.ownerAddress;
251
254
  let valid = false;
252
255
  try {
253
256
  const bytes = getBytes2(signature);
@@ -321,7 +324,7 @@ var RegistrationOperation = class _RegistrationOperation {
321
324
  check(
322
325
  await this.#runtime.reader.getRegistryNonce(
323
326
  p.context,
324
- p.registration.walletIdentity,
327
+ p.registration.ownerAddress,
325
328
  block
326
329
  ) === p.registration.nonce,
327
330
  "registry nonce changed; prepare again"
@@ -372,7 +375,7 @@ var RegistrationOperation = class _RegistrationOperation {
372
375
  const transaction = await reader.getTransaction(hash);
373
376
  const call = this.call();
374
377
  check(
375
- 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)),
378
+ 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)),
376
379
  "registry transaction differs from frozen request"
377
380
  );
378
381
  check(
@@ -394,7 +397,7 @@ var RegistrationOperation = class _RegistrationOperation {
394
397
  topics: log.topics
395
398
  })
396
399
  );
397
- 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;
400
+ 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;
398
401
  } catch {
399
402
  return false;
400
403
  }
@@ -417,7 +420,7 @@ var RegistrationOperation = class _RegistrationOperation {
417
420
  }
418
421
  }
419
422
  const head = await reader.getBlock(await reader.getLatestBlockNumber());
420
- const nonce = await reader.getRegistryNonce(p.context, p.registration.walletIdentity, head);
423
+ const nonce = await reader.getRegistryNonce(p.context, p.registration.ownerAddress, head);
421
424
  check(
422
425
  (await reader.getBlock(head.number)).hash === head.hash,
423
426
  "canonical registry block changed during reconciliation"
@@ -496,17 +499,8 @@ var AddressRegistry = class {
496
499
  }
497
500
  };
498
501
 
499
- // src/credit-create.ts
500
- import {
501
- AbiCoder as AbiCoder2,
502
- dataLength as dataLength2,
503
- getAddress as getAddress4,
504
- Interface as Interface3,
505
- isHexString as isHexString3,
506
- keccak256 as keccak2563,
507
- ParamType as ParamType2
508
- } from "ethers";
509
- import { computeWalletAuthorizationDigest, walletAuthorizationTypedData } from "@invisi-labs/core";
502
+ // src/fee.ts
503
+ import { getAddress as getAddress4 } from "ethers";
510
504
 
511
505
  // src/validation.ts
512
506
  import { MAX_CIPHERTEXT_BYTES } from "@invisi-labs/core";
@@ -611,6 +605,8 @@ function normalizeOpaqueDelivery(value, options = {}) {
611
605
  throw new Error("absent output requires an empty delivery");
612
606
  return { ciphertext: "0x", clue: "0x" };
613
607
  }
608
+ if (options.allowEmpty && value.ciphertext === "0x" && value.clue === "0x")
609
+ return { ciphertext: "0x", clue: "0x" };
614
610
  const ciphertext = envelope(value.ciphertext, 1, void 0, MAX_CIPHERTEXT_BYTES);
615
611
  const clue = envelope(value.clue, 68);
616
612
  if (clue.slice(130, 132).toLowerCase() !== "18") throw new Error("clue precision must be 24");
@@ -669,9 +665,28 @@ var fundingFields = [
669
665
  { name: "deadline", type: "uint256" }
670
666
  ];
671
667
 
668
+ // src/fee.ts
669
+ function normalizeFee(p) {
670
+ const feeRecipient = getAddress4(p.feeRecipient ?? ZERO_ADDRESS);
671
+ const feeAmount = uint(p.feeAmount ?? 0n, 128, "feeAmount");
672
+ if (BigInt(feeRecipient) === 0n !== (feeAmount === 0n))
673
+ throw new Error("invalid fee context");
674
+ return { feeRecipient, feeAmount };
675
+ }
676
+
672
677
  // src/credit-create.ts
678
+ import {
679
+ AbiCoder as AbiCoder2,
680
+ dataLength as dataLength2,
681
+ getAddress as getAddress5,
682
+ Interface as Interface3,
683
+ isHexString as isHexString3,
684
+ keccak256 as keccak2563,
685
+ ParamType as ParamType2
686
+ } from "ethers";
687
+ import { computeWalletAuthorizationDigest, walletAuthorizationTypedData } from "@invisi-labs/core";
673
688
  var creationTuple = [
674
- "(address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32 creditCommitment,bytes32 changeCommitment,address owner,uint256 expiry,uint256 deadline)"
689
+ "(address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32 creditCommitment,bytes32 changeCommitment,address owner,uint256 expiry,uint256 deadline,address feeRecipient,uint256 feeAmount)"
675
690
  ][0];
676
691
  var CREATE_CREDIT_FIELDS = [
677
692
  "token",
@@ -681,25 +696,31 @@ var CREATE_CREDIT_FIELDS = [
681
696
  "changeCommitment",
682
697
  "owner",
683
698
  "expiry",
684
- "deadline"
699
+ "deadline",
700
+ "feeRecipient",
701
+ "feeAmount"
685
702
  ];
686
703
  function validateCreateCreditRequest(c, p, cs, funding = {}) {
687
704
  known(p, CREATE_CREDIT_FIELDS);
688
- if (getAddress4(p.token) !== getAddress4(c.tokenAddress))
705
+ if (getAddress5(p.token) !== getAddress5(c.tokenAddress))
689
706
  throw new Error("request token mismatch");
690
- 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 = getAddress4(p.owner), expiry = uint(p.expiry, 64, "expiry"), deadline = checkDeadline(c, p.deadline), f = normalizeFunding(funding);
707
+ 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 = getAddress5(p.owner), expiry = uint(p.expiry, 64, "expiry"), deadline = checkDeadline(c, p.deadline), f = normalizeFunding(funding);
691
708
  if (BigInt(creditCommitment) === 0n || creditCommitment === changeCommitment)
692
709
  throw new Error("zero or duplicate commitment");
693
710
  if (BigInt(owner) === 0n || expiry === 0n || c.now !== void 0 && expiry <= c.now)
694
711
  throw new Error("owner must be nonzero and expiry future");
695
712
  if (dense(cs, "deliveries").length !== 3) throw new Error("deliveries count mismatch");
696
713
  const deliveries = cs.map(
697
- (v, i) => normalizeOpaqueDelivery(v, { empty: i === 2 && BigInt(changeCommitment) === 0n })
714
+ (v, i) => normalizeOpaqueDelivery(v, {
715
+ empty: i === 2 && BigInt(changeCommitment) === 0n,
716
+ allowEmpty: i === 2
717
+ })
698
718
  );
699
719
  if (ns.length === 0 && f.amount === 0n)
700
720
  throw new Error("empty inputs require positive funding");
701
721
  return {
702
722
  ...ctx,
723
+ ...normalizeFee(p),
703
724
  sources,
704
725
  nullifiers: ns,
705
726
  actualCount: ns.length,
@@ -738,7 +759,9 @@ function createCreditBaseInputs(c, p, cs, f = {}) {
738
759
  r.expiry,
739
760
  r.deadline,
740
761
  r.funding.amount,
741
- BigInt(r.funding.payer)
762
+ BigInt(r.funding.payer),
763
+ BigInt(r.feeRecipient),
764
+ r.feeAmount
742
765
  ].map(word);
743
766
  }
744
767
  function createCreditPublicInputs(c, p, deliveries, funding = {}) {
@@ -771,7 +794,7 @@ function createCreditRequestHash(p, cs, f = {}) {
771
794
  ].map((parameter) => ParamType2.from(parameter)),
772
795
  [
773
796
  keccak2563(new TextEncoder().encode("InvisiCreateCredit")),
774
- p,
797
+ { ...p, ...normalizeFee(p) },
775
798
  deliveriesHash(cs),
776
799
  r.funding.payer,
777
800
  r.funding.amount
@@ -809,7 +832,7 @@ function buildCreateCreditCalldata(p) {
809
832
  return {
810
833
  data: new Interface3(invisiProtocolAbi).encodeFunctionData("createCredit", [
811
834
  encodeCreditProof(p.proof),
812
- p.params,
835
+ { ...p.params, ...normalizeFee(p.params) },
813
836
  p.deliveries,
814
837
  r.funding
815
838
  ]),
@@ -826,7 +849,7 @@ function encodeCreditProof(proof) {
826
849
  }
827
850
 
828
851
  // src/credit-lifecycle.ts
829
- import { AbiCoder as AbiCoder3, getAddress as getAddress5, Interface as Interface4, keccak256 as keccak2564, ParamType as ParamType3 } from "ethers";
852
+ import { AbiCoder as AbiCoder3, getAddress as getAddress6, Interface as Interface4, keccak256 as keccak2564, ParamType as ParamType3 } from "ethers";
830
853
  import {
831
854
  creditPeriods,
832
855
  computeWalletAuthorizationDigest as computeWalletAuthorizationDigest2,
@@ -856,7 +879,7 @@ function validateCreditDrawRequest(c, p, cs) {
856
879
  "totalAmount",
857
880
  "deadline"
858
881
  ]);
859
- if (getAddress5(p.token) !== getAddress5(c.tokenAddress))
882
+ if (getAddress6(p.token) !== getAddress6(c.tokenAddress))
860
883
  throw new Error("request token mismatch");
861
884
  const ctx = normalizeContext(c), ns = notes(p.nullifiers, "nullifiers"), profile = selectCreditDrawCircuit(ns.length), sources = normalizeSources(p.sources, ns.length, profile.maxSize);
862
885
  for (const [key, v] of Object.entries({
@@ -874,7 +897,7 @@ function validateCreditDrawRequest(c, p, cs) {
874
897
  if (BigInt(remainderCommitments[i]) === 0n && BigInt(recoveryAmounts[i]) !== 0n)
875
898
  throw new Error("full draw requires zero recovery amount");
876
899
  }
877
- const spender = getAddress5(p.spender), totalAmount = uint(p.totalAmount, profile.totalBits, "totalAmount");
900
+ const spender = getAddress6(p.spender), totalAmount = uint(p.totalAmount, profile.totalBits, "totalAmount");
878
901
  if (BigInt(spender) === 0n || totalAmount === 0n)
879
902
  throw new Error("spender and total amount must be positive");
880
903
  if (dense(cs, "deliveries").length !== 2 * ns.length)
@@ -927,13 +950,25 @@ function creditDrawBaseInputs(c, p, cs) {
927
950
  ].map(word);
928
951
  }
929
952
  function validateCancelCreditRequest(c, p) {
930
- known(p, ["token", "source", "nullifier", "owner", "amount", "deadline"]);
931
- if (getAddress5(p.token) !== getAddress5(c.tokenAddress))
953
+ known(p, [
954
+ "token",
955
+ "source",
956
+ "nullifier",
957
+ "owner",
958
+ "amount",
959
+ "deadline",
960
+ "feeRecipient",
961
+ "feeAmount"
962
+ ]);
963
+ if (getAddress6(p.token) !== getAddress6(c.tokenAddress))
932
964
  throw new Error("request token mismatch");
933
- const ctx = normalizeContext(c), source = normalizeSources([p.source], 1, 1)[0], nullifier = notes([p.nullifier], "nullifier")[0], owner = getAddress5(p.owner), amount = uint(p.amount, 126, "amount");
965
+ const ctx = normalizeContext(c), source = normalizeSources([p.source], 1, 1)[0], nullifier = notes([p.nullifier], "nullifier")[0], owner = getAddress6(p.owner), amount = uint(p.amount, 126, "amount");
934
966
  if (BigInt(owner) === 0n || amount === 0n) throw new Error("owner and amount must be positive");
967
+ const fee = normalizeFee(p);
968
+ if (fee.feeAmount >= amount) throw new Error("fee must leave a positive owner refund");
935
969
  return {
936
970
  ...ctx,
971
+ ...fee,
937
972
  source,
938
973
  nullifier,
939
974
  owner,
@@ -952,7 +987,9 @@ function cancelCreditBaseInputs(c, p) {
952
987
  BigInt(r.source.merkleRoot),
953
988
  BigInt(r.nullifier),
954
989
  r.amount,
955
- r.deadline
990
+ r.deadline,
991
+ BigInt(r.feeRecipient),
992
+ r.feeAmount
956
993
  ].map(word);
957
994
  }
958
995
  function validateTopUpCreditRequest(c, p, cs, funding = {}) {
@@ -976,10 +1013,10 @@ function topUpCreditBaseInputs(c, p, cs, f = {}) {
976
1013
  ];
977
1014
  }
978
1015
  var cancelTuple = [
979
- "(address token,(uint256 treeId,bytes32 merkleRoot) source,bytes32 nullifier,address owner,uint256 amount,uint256 deadline)"
1016
+ "(address token,(uint256 treeId,bytes32 merkleRoot) source,bytes32 nullifier,address owner,uint256 amount,uint256 deadline,address feeRecipient,uint256 feeAmount)"
980
1017
  ][0];
981
1018
  var topTuple = [
982
- "((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)"
1019
+ "((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)"
983
1020
  ][0];
984
1021
  var hashContext2 = {
985
1022
  chainId: 0n,
@@ -991,7 +1028,10 @@ function cancelCreditRequestHash(p) {
991
1028
  return keccak2564(
992
1029
  AbiCoder3.defaultAbiCoder().encode(
993
1030
  [{ type: "bytes32" }, cancelTuple].map((parameter) => ParamType3.from(parameter)),
994
- [keccak2564(new TextEncoder().encode("InvisiCancelCredit")), p]
1031
+ [
1032
+ keccak2564(new TextEncoder().encode("InvisiCancelCredit")),
1033
+ { ...p, ...normalizeFee(p) }
1034
+ ]
995
1035
  )
996
1036
  );
997
1037
  }
@@ -1013,7 +1053,7 @@ function topUpCreditRequestHash(p, cs, f = {}) {
1013
1053
  ].map((parameter) => ParamType3.from(parameter)),
1014
1054
  [
1015
1055
  keccak2564(new TextEncoder().encode("InvisiTopUpCredit")),
1016
- p,
1056
+ { ...p, creation: { ...p.creation, ...normalizeFee(p.creation) } },
1017
1057
  deliveriesHash(cs),
1018
1058
  r.creation.funding.payer,
1019
1059
  r.creation.funding.amount
@@ -1101,7 +1141,7 @@ function buildCancelCreditCalldata(p) {
1101
1141
  return {
1102
1142
  data: new Interface4(invisiProtocolAbi).encodeFunctionData("cancelCredit", [
1103
1143
  encodeCreditProof(p.proof),
1104
- p.params
1144
+ { ...p.params, ...normalizeFee(p.params) }
1105
1145
  ])
1106
1146
  };
1107
1147
  }
@@ -1111,7 +1151,7 @@ function buildTopUpCreditCalldata(p) {
1111
1151
  return {
1112
1152
  data: new Interface4(invisiProtocolAbi).encodeFunctionData("topUpCredit", [
1113
1153
  encodeCreditProof(p.proof),
1114
- p.params,
1154
+ { ...p.params, creation: { ...p.params.creation, ...normalizeFee(p.params.creation) } },
1115
1155
  p.deliveries,
1116
1156
  r.creation.funding
1117
1157
  ]),
@@ -1120,7 +1160,7 @@ function buildTopUpCreditCalldata(p) {
1120
1160
  }
1121
1161
 
1122
1162
  // src/funds.ts
1123
- import { AbiCoder as AbiCoder4, getAddress as getAddress6, Interface as Interface5, keccak256 as keccak2565, ParamType as ParamType4, TypedDataEncoder as TypedDataEncoder2 } from "ethers";
1163
+ import { AbiCoder as AbiCoder4, getAddress as getAddress7, Interface as Interface5, keccak256 as keccak2565, ParamType as ParamType4, TypedDataEncoder as TypedDataEncoder2 } from "ethers";
1124
1164
  import { computeNoteCommitment, walletAuthorizationTypedData as walletAuthorizationTypedData3 } from "@invisi-labs/core";
1125
1165
  var TRANSACT_CAPACITIES = [14, 56, 112, 168];
1126
1166
  function selectTransactCapacity(inputs, outputs) {
@@ -1130,7 +1170,7 @@ function selectTransactCapacity(inputs, outputs) {
1130
1170
  }
1131
1171
  function normalizeTransactRequest(c, p, cs, funding = {}) {
1132
1172
  const ctx = normalizeContext(c);
1133
- if (getAddress6(p.token) !== ctx.tokenAddress)
1173
+ if (getAddress7(p.token) !== ctx.tokenAddress)
1134
1174
  throw new Error("request token mismatch");
1135
1175
  known(p, [
1136
1176
  "token",
@@ -1139,12 +1179,21 @@ function normalizeTransactRequest(c, p, cs, funding = {}) {
1139
1179
  "outputCommitments",
1140
1180
  "withdrawalAddress",
1141
1181
  "withdrawalAmount",
1142
- "deadline"
1182
+ "deadline",
1183
+ "feeRecipient",
1184
+ "feeAmount"
1143
1185
  ]);
1144
1186
  const ns = notes(p.nullifiers, "nullifiers"), os = notes(p.outputCommitments, "outputCommitments"), capacity = selectTransactCapacity(ns.length, os.length);
1145
- const sources = normalizeSources(p.sources, ns.length, capacity), deliveries = dense(cs, "deliveries").map((v) => normalizeOpaqueDelivery(v));
1187
+ const sources = normalizeSources(p.sources, ns.length, capacity), deliveries = dense(cs, "deliveries").map(
1188
+ (v) => normalizeOpaqueDelivery(v, { allowEmpty: true })
1189
+ );
1146
1190
  if (deliveries.length !== os.length) throw new Error("deliveries count mismatch");
1147
- const withdrawalAmount = uint(p.withdrawalAmount, 128, "withdrawalAmount"), withdrawalAddress = getAddress6(p.withdrawalAddress), f = normalizeFunding(funding);
1191
+ const withdrawalAmount = uint(p.withdrawalAmount, 128, "withdrawalAmount"), withdrawalAddress = getAddress7(p.withdrawalAddress), f = normalizeFunding(funding);
1192
+ const feeAmount = uint(p.feeAmount ?? 0n, 128, "feeAmount");
1193
+ const feeRecipient = getAddress7(
1194
+ p.feeRecipient ?? "0x0000000000000000000000000000000000000000"
1195
+ );
1196
+ if (feeAmount === 0n !== (BigInt(feeRecipient) === 0n)) throw new Error("invalid fee");
1148
1197
  if (withdrawalAmount === 0n !== (BigInt(withdrawalAddress) === 0n) || os.length === 0 && withdrawalAmount === 0n)
1149
1198
  throw new Error("invalid withdrawal");
1150
1199
  if (ns.length === 0 && (f.amount === 0n || withdrawalAmount !== 0n))
@@ -1171,6 +1220,8 @@ function normalizeTransactRequest(c, p, cs, funding = {}) {
1171
1220
  deliveriesHash: deliveriesHash(deliveries),
1172
1221
  withdrawalAddress,
1173
1222
  withdrawalAmount,
1223
+ feeRecipient,
1224
+ feeAmount,
1174
1225
  deadline: checkDeadline(c, p.deadline),
1175
1226
  depositAmount: f.amount,
1176
1227
  depositPayer: f.payer,
@@ -1195,7 +1246,9 @@ function transactPublicInputs(c, p, cs, f = {}) {
1195
1246
  r.withdrawalAmount,
1196
1247
  r.deadline,
1197
1248
  r.depositAmount,
1198
- BigInt(r.depositPayer)
1249
+ BigInt(r.depositPayer),
1250
+ BigInt(r.feeRecipient),
1251
+ r.feeAmount
1199
1252
  ].map(word);
1200
1253
  }
1201
1254
  function encodeTransactTypedData(c, p, deliveries, f = {}) {
@@ -1208,10 +1261,10 @@ function encodeTransactTypedData(c, p, deliveries, f = {}) {
1208
1261
  });
1209
1262
  }
1210
1263
  var singleTuple = [
1211
- "(address token,bytes32 merkleRoot,bytes32[] nullifiers,bytes32[] outputCommitments,uint256 inputTreeId,address withdrawalAddress,uint256 withdrawalAmount,uint256 deadline)"
1264
+ "(address token,bytes32 merkleRoot,bytes32[] nullifiers,bytes32[] outputCommitments,uint256 inputTreeId,address withdrawalAddress,uint256 withdrawalAmount,uint256 deadline,address feeRecipient,uint256 feeAmount)"
1212
1265
  ][0];
1213
1266
  var crossTuple = [
1214
- "(address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32[] outputCommitments,address withdrawalAddress,uint256 withdrawalAmount,uint256 deadline)"
1267
+ "(address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32[] outputCommitments,address withdrawalAddress,uint256 withdrawalAmount,uint256 deadline,address feeRecipient,uint256 feeAmount)"
1215
1268
  ][0];
1216
1269
  function transactFundingRequestHash(proof, p, cs) {
1217
1270
  const single = {
@@ -1222,7 +1275,9 @@ function transactFundingRequestHash(proof, p, cs) {
1222
1275
  inputTreeId: p.sources[0]?.treeId ?? 0n,
1223
1276
  withdrawalAddress: p.withdrawalAddress,
1224
1277
  withdrawalAmount: p.withdrawalAmount,
1225
- deadline: p.deadline
1278
+ deadline: p.deadline,
1279
+ feeRecipient: p.feeRecipient ?? "0x0000000000000000000000000000000000000000",
1280
+ feeAmount: p.feeAmount ?? 0n
1226
1281
  };
1227
1282
  return p.sources.length > 1 ? keccak2565(
1228
1283
  AbiCoder4.defaultAbiCoder().encode(
@@ -1232,7 +1287,7 @@ function transactFundingRequestHash(proof, p, cs) {
1232
1287
  [
1233
1288
  keccak2565(new TextEncoder().encode("InvisiCrossTreeTransact")),
1234
1289
  keccak2565(proof),
1235
- p,
1290
+ { ...p, feeRecipient: single.feeRecipient, feeAmount: single.feeAmount },
1236
1291
  deliveriesHash(cs)
1237
1292
  ]
1238
1293
  )
@@ -1273,7 +1328,9 @@ function buildTransactCalldata(p) {
1273
1328
  outputCommitments: r.outputCommitments,
1274
1329
  withdrawalAddress: r.withdrawalAddress,
1275
1330
  withdrawalAmount: r.withdrawalAmount,
1276
- deadline: r.deadline
1331
+ deadline: r.deadline,
1332
+ feeRecipient: r.feeRecipient,
1333
+ feeAmount: r.feeAmount
1277
1334
  },
1278
1335
  deliveries: p.deliveries,
1279
1336
  funding: r.funding
@@ -1287,7 +1344,7 @@ function buildTransactCalldata(p) {
1287
1344
  function buildTransactAggregateCalldata(p) {
1288
1345
  if (![4, 8, 12].includes(dense(p.requests, "requests").length))
1289
1346
  throw new Error("aggregate requires 4, 8 or 12 requests");
1290
- for (const request of p.requests) {
1347
+ const requests = p.requests.map((request) => {
1291
1348
  const r = normalizeTransactRequest(
1292
1349
  { ...p.context, tokenAddress: request.params.token },
1293
1350
  request.params,
@@ -1296,21 +1353,25 @@ function buildTransactAggregateCalldata(p) {
1296
1353
  );
1297
1354
  if (r.capacity !== 14) throw new Error("aggregate supports only capacity 14");
1298
1355
  validateFundingSubmission(r.funding, p.caller, p.context.now);
1299
- }
1356
+ return {
1357
+ ...request,
1358
+ params: { ...request.params, feeRecipient: r.feeRecipient, feeAmount: r.feeAmount }
1359
+ };
1360
+ });
1300
1361
  return {
1301
1362
  data: new Interface5(
1302
1363
  invisiProtocolAbi.filter(
1303
1364
  (item) => item.type === "function" && item.name === "transact" && item.inputs[1]?.type === "tuple[]"
1304
1365
  )
1305
- ).encodeFunctionData("transact", [p.proof, p.requests]),
1366
+ ).encodeFunctionData("transact", [p.proof, requests]),
1306
1367
  capacity: 14
1307
1368
  };
1308
1369
  }
1309
1370
  async function validateShieldRequest(p) {
1310
1371
  normalizeContext(p.context);
1311
- if (getAddress6(p.params.token) !== getAddress6(p.context.tokenAddress))
1372
+ if (getAddress7(p.params.token) !== getAddress7(p.context.tokenAddress))
1312
1373
  throw new Error("request token mismatch");
1313
- known(p.params, ["token", "outputCommitments", "deadline"]);
1374
+ known(p.params, ["token", "outputCommitments", "deadline", "feeRecipient", "feeAmount"]);
1314
1375
  checkDeadline(p.context, p.params.deadline);
1315
1376
  const outputs = dense(p.outputs, "outputs"), commitments = notes(p.params.outputCommitments, "outputCommitments"), cs = dense(p.deliveries, "deliveries"), f = normalizeFunding(p.funding);
1316
1377
  if (outputs.length < 1 || outputs.length > 10 || commitments.length !== outputs.length || cs.length !== outputs.length)
@@ -1321,7 +1382,7 @@ async function validateShieldRequest(p) {
1321
1382
  uint(o.amount, 128, "amount");
1322
1383
  if (o.amount === 0n) throw new Error("amount must be positive");
1323
1384
  field(o.identity);
1324
- normalizeOpaqueDelivery(cs[i]);
1385
+ normalizeOpaqueDelivery(cs[i], { allowEmpty: true });
1325
1386
  if (await computeNoteCommitment(
1326
1387
  p.context.chainId,
1327
1388
  o.identity,
@@ -1331,7 +1392,8 @@ async function validateShieldRequest(p) {
1331
1392
  throw new Error("output commitment mismatch");
1332
1393
  total += o.amount;
1333
1394
  }
1334
- if (total !== f.amount) throw new Error("funding must equal output total");
1395
+ if (total + normalizeFee(p.params).feeAmount !== f.amount)
1396
+ throw new Error("funding must equal output total plus fee");
1335
1397
  return f;
1336
1398
  }
1337
1399
  function shieldFundingRequestHash(params, outputs, cs) {
@@ -1345,13 +1407,13 @@ function shieldFundingRequestHash(params, outputs, cs) {
1345
1407
  AbiCoder4.defaultAbiCoder().encode(
1346
1408
  [
1347
1409
  "bytes32",
1348
- "(address token,bytes32[] outputCommitments,uint256 deadline)",
1410
+ "(address token,bytes32[] outputCommitments,uint256 deadline,address feeRecipient,uint256 feeAmount)",
1349
1411
  "bytes32",
1350
1412
  "bytes32"
1351
1413
  ].map((parameter) => ParamType4.from(parameter)),
1352
1414
  [
1353
1415
  keccak2565(new TextEncoder().encode("InvisiShield")),
1354
- params,
1416
+ { ...params, ...normalizeFee(params) },
1355
1417
  outputHash,
1356
1418
  deliveriesHash(cs)
1357
1419
  ]
@@ -1378,7 +1440,7 @@ async function buildShieldCalldata(p) {
1378
1440
  validateFundingSubmission(f, p.caller, p.context.now);
1379
1441
  return {
1380
1442
  data: new Interface5(invisiProtocolAbi).encodeFunctionData("shield", [
1381
- p.params,
1443
+ { ...p.params, ...normalizeFee(p.params) },
1382
1444
  p.outputs,
1383
1445
  p.deliveries,
1384
1446
  f
@@ -1445,7 +1507,7 @@ function encodeAggregateFundingTypedData(c, r) {
1445
1507
  }
1446
1508
 
1447
1509
  // src/Protocol.ts
1448
- import { Contract as Contract2, getAddress as getAddress7, keccak256 as keccak2567 } from "ethers";
1510
+ import { Contract as Contract2, getAddress as getAddress8, keccak256 as keccak2567 } from "ethers";
1449
1511
  import {
1450
1512
  defineDeployment
1451
1513
  } from "@invisi-labs/rpc";
@@ -1566,7 +1628,7 @@ var Protocol = class _Protocol {
1566
1628
  const reader = "getNetwork" in connection ? {
1567
1629
  getChainId: async () => (await connection.getNetwork()).chainId,
1568
1630
  getCode: async (address) => await connection.getCode(address),
1569
- getProtocolAddressRegistry: async (address) => getAddress7(
1631
+ getProtocolAddressRegistry: async (address) => getAddress8(
1570
1632
  await new Contract2(
1571
1633
  address,
1572
1634
  ["function addressRegistry() view returns (address)"],
@@ -1592,9 +1654,9 @@ var Protocol = class _Protocol {
1592
1654
  if (registry) {
1593
1655
  if (!reader.getProtocolAddressRegistry)
1594
1656
  throw new Error("registry binding reader capability is missing");
1595
- if (getAddress7(
1657
+ if (getAddress8(
1596
1658
  await reader.getProtocolAddressRegistry(this.context.protocolAddress)
1597
- ) !== getAddress7(registry.address))
1659
+ ) !== getAddress8(registry.address))
1598
1660
  throw new Error("protocol registry binding mismatch");
1599
1661
  const registryCode = await reader.getCode(registry.address);
1600
1662
  if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(registryCode) || keccak2567(registryCode) !== registry.runtimeCodeHash)
@@ -1611,7 +1673,7 @@ var Protocol = class _Protocol {
1611
1673
  /** Build an operation context for one asset within this same deployment. */
1612
1674
  forToken(tokenAddress) {
1613
1675
  return new TokenProtocol(
1614
- { ...this.context, tokenAddress: getAddress7(tokenAddress) },
1676
+ { ...this.context, tokenAddress: getAddress8(tokenAddress) },
1615
1677
  { expectedRuntimeCodeHash: this.deployment.protocol.runtimeCodeHash }
1616
1678
  );
1617
1679
  }
@@ -1628,7 +1690,7 @@ import {
1628
1690
  async function verifyNoteCommitment(params) {
1629
1691
  const expected = await computeNoteCommitment2(
1630
1692
  params.chainId,
1631
- await computeNoteIdentity(BigInt(params.walletIdentity), BigInt(params.nonce)),
1693
+ await computeNoteIdentity(BigInt(params.ownerAddress), BigInt(params.nonce)),
1632
1694
  BigInt(params.tokenAddress),
1633
1695
  params.amount
1634
1696
  );
@@ -1675,12 +1737,12 @@ import {
1675
1737
  // src/witness-layouts.json
1676
1738
  var witness_layouts_default = {
1677
1739
  transact_user_slots14: {
1678
- artifactSha256: "486a749ae3944ae83a7ff2d298e7469b18737d88553a7d99c4782f22f7332996",
1740
+ artifactSha256: "df9458f0be9c8905241ee74e5f11c0e1c348ef749fe1a9d599034a983f08dbd5",
1679
1741
  keys: {
1680
- evm: "7b3e65d5201246e733a1816489d80acb219a98e8606e1b81e6d48ff0c1fd537a",
1681
- "noir-recursive": "148957e28e6339a8ce1121851fb7a232e31f4c5b741e415733b8d627f4b62649"
1742
+ evm: "a9db580b09d05f09d4ea58b8d9755855525b8cc20beee4b1fbfe4cad10251e4e",
1743
+ "noir-recursive": "912191fc9484b2c0ab869d44900054b1a7c25c3256177abfc102884f3fa7d7ed"
1682
1744
  },
1683
- publicInputCount: 57,
1745
+ publicInputCount: 59,
1684
1746
  public: [
1685
1747
  {
1686
1748
  name: "chain_id",
@@ -1762,6 +1824,16 @@ var witness_layouts_default = {
1762
1824
  count: 1,
1763
1825
  array: false
1764
1826
  },
1827
+ {
1828
+ name: "fee_recipient",
1829
+ count: 1,
1830
+ array: false
1831
+ },
1832
+ {
1833
+ name: "fee_amount",
1834
+ count: 1,
1835
+ array: false
1836
+ },
1765
1837
  {
1766
1838
  name: "auth_digest_high",
1767
1839
  count: 1,
@@ -1774,11 +1846,11 @@ var witness_layouts_default = {
1774
1846
  }
1775
1847
  ],
1776
1848
  private: [
1777
- "wallet_identity",
1849
+ "input_owner_address",
1778
1850
  "public_key_x",
1779
1851
  "public_key_y",
1780
1852
  "signature",
1781
- "output_wallet_identities",
1853
+ "output_identities",
1782
1854
  "amounts",
1783
1855
  "nonces",
1784
1856
  "leaf_indices",
@@ -1787,11 +1859,11 @@ var witness_layouts_default = {
1787
1859
  ]
1788
1860
  },
1789
1861
  transact_user_slots56: {
1790
- artifactSha256: "169db2ff23c15adb14756edf9bb99bbd343df807b3e1c7f1f510070897e653cf",
1862
+ artifactSha256: "370299e1ee32a57b6a81ccdbf5e95efef144bee17d38d402bbbfbaa392d355d8",
1791
1863
  keys: {
1792
- evm: "cbf54de94bff266bf846f9722c0f3ffa1fb7a0f9f478466f193de0e9123ce7f5"
1864
+ evm: "2bb2fdf9ef33200038aa6e0a9f35e2a7252bf3946f5b5d68dd0ae85172adeddf"
1793
1865
  },
1794
- publicInputCount: 183,
1866
+ publicInputCount: 185,
1795
1867
  public: [
1796
1868
  {
1797
1869
  name: "chain_id",
@@ -1873,6 +1945,16 @@ var witness_layouts_default = {
1873
1945
  count: 1,
1874
1946
  array: false
1875
1947
  },
1948
+ {
1949
+ name: "fee_recipient",
1950
+ count: 1,
1951
+ array: false
1952
+ },
1953
+ {
1954
+ name: "fee_amount",
1955
+ count: 1,
1956
+ array: false
1957
+ },
1876
1958
  {
1877
1959
  name: "auth_digest_high",
1878
1960
  count: 1,
@@ -1885,11 +1967,11 @@ var witness_layouts_default = {
1885
1967
  }
1886
1968
  ],
1887
1969
  private: [
1888
- "wallet_identity",
1970
+ "input_owner_address",
1889
1971
  "public_key_x",
1890
1972
  "public_key_y",
1891
1973
  "signature",
1892
- "output_wallet_identities",
1974
+ "output_identities",
1893
1975
  "amounts",
1894
1976
  "nonces",
1895
1977
  "leaf_indices",
@@ -1898,11 +1980,11 @@ var witness_layouts_default = {
1898
1980
  ]
1899
1981
  },
1900
1982
  transact_user_slots112: {
1901
- artifactSha256: "221bbbd6ff0c7d7dec74677e52484f082b3e176bb0fa47f3236064e396d73739",
1983
+ artifactSha256: "259417390705f5ced1cbd671582a2fe40dbf7a259d8717f4e90989dc4368ad91",
1902
1984
  keys: {
1903
- evm: "67b2d361b023f193ecdb5a9aefbe2840349ee5ce848ab4101416734f3a7e91e9"
1985
+ evm: "523652b9391818c0af0af8668ba2cd786be25ef00e6bcafa662ed829a32746a7"
1904
1986
  },
1905
- publicInputCount: 351,
1987
+ publicInputCount: 353,
1906
1988
  public: [
1907
1989
  {
1908
1990
  name: "chain_id",
@@ -1984,6 +2066,16 @@ var witness_layouts_default = {
1984
2066
  count: 1,
1985
2067
  array: false
1986
2068
  },
2069
+ {
2070
+ name: "fee_recipient",
2071
+ count: 1,
2072
+ array: false
2073
+ },
2074
+ {
2075
+ name: "fee_amount",
2076
+ count: 1,
2077
+ array: false
2078
+ },
1987
2079
  {
1988
2080
  name: "auth_digest_high",
1989
2081
  count: 1,
@@ -1996,11 +2088,11 @@ var witness_layouts_default = {
1996
2088
  }
1997
2089
  ],
1998
2090
  private: [
1999
- "wallet_identity",
2091
+ "input_owner_address",
2000
2092
  "public_key_x",
2001
2093
  "public_key_y",
2002
2094
  "signature",
2003
- "output_wallet_identities",
2095
+ "output_identities",
2004
2096
  "amounts",
2005
2097
  "nonces",
2006
2098
  "leaf_indices",
@@ -2009,11 +2101,11 @@ var witness_layouts_default = {
2009
2101
  ]
2010
2102
  },
2011
2103
  transact_user_slots168: {
2012
- artifactSha256: "d479253eaaacc973806a84e142e2362d873bba0f150ce050d32b8d9b2947adc8",
2104
+ artifactSha256: "2a86703ca068c50f305d3b4b856ab3b2145d066da0bab894eac8e7c174c20292",
2013
2105
  keys: {
2014
- evm: "c50e72b0718c6393f82f5a67e248ba093d0db56ece42bbf092da93e9369c2624"
2106
+ evm: "c9d821fdd5b8cfcdc7fe93e673a8c99487879a4680c8f1b86c0b5c05a3cad515"
2015
2107
  },
2016
- publicInputCount: 519,
2108
+ publicInputCount: 521,
2017
2109
  public: [
2018
2110
  {
2019
2111
  name: "chain_id",
@@ -2095,6 +2187,16 @@ var witness_layouts_default = {
2095
2187
  count: 1,
2096
2188
  array: false
2097
2189
  },
2190
+ {
2191
+ name: "fee_recipient",
2192
+ count: 1,
2193
+ array: false
2194
+ },
2195
+ {
2196
+ name: "fee_amount",
2197
+ count: 1,
2198
+ array: false
2199
+ },
2098
2200
  {
2099
2201
  name: "auth_digest_high",
2100
2202
  count: 1,
@@ -2107,11 +2209,11 @@ var witness_layouts_default = {
2107
2209
  }
2108
2210
  ],
2109
2211
  private: [
2110
- "wallet_identity",
2212
+ "input_owner_address",
2111
2213
  "public_key_x",
2112
2214
  "public_key_y",
2113
2215
  "signature",
2114
- "output_wallet_identities",
2216
+ "output_identities",
2115
2217
  "amounts",
2116
2218
  "nonces",
2117
2219
  "leaf_indices",
@@ -2120,11 +2222,11 @@ var witness_layouts_default = {
2120
2222
  ]
2121
2223
  },
2122
2224
  transact_aggregate_14_4: {
2123
- artifactSha256: "4fe7c63fb80cba35af4c4525fbabcfb75033286e681afbdcb3fb043c03456246",
2225
+ artifactSha256: "4cd3f3d0dbcac9a48fec728450fd73a247321f655da02bd08db789e07b47527b",
2124
2226
  keys: {
2125
- evm: "664d4ff0de6b8c876ce990ea368d7a59cee411463c24dd5621d64c8949554674"
2227
+ evm: "6654b125cb96d5f4dd263c82cb34b0862bf63ff761fe5feab834f10283a0265d"
2126
2228
  },
2127
- publicInputCount: 229,
2229
+ publicInputCount: 237,
2128
2230
  public: [
2129
2231
  {
2130
2232
  name: "statements",
@@ -2144,11 +2246,11 @@ var witness_layouts_default = {
2144
2246
  ]
2145
2247
  },
2146
2248
  transact_aggregate_14_8: {
2147
- artifactSha256: "0a266ad4bb4c6dce42b1e851fcbb34b1becae1edd6bf6af82d7b9ed7184576df",
2249
+ artifactSha256: "b36ff5370043782364d41dbe00443970292b0240429f241c974ae6c9b10debfe",
2148
2250
  keys: {
2149
- evm: "042139122d0eee8beeaa9c18397276fa5a2872218495fa16ca438fbdd80fa3e1"
2251
+ evm: "2ad5b8b24109edf24197e97fbad35519d7d18558df19183ca3f91c4089ce4421"
2150
2252
  },
2151
- publicInputCount: 457,
2253
+ publicInputCount: 473,
2152
2254
  public: [
2153
2255
  {
2154
2256
  name: "statements",
@@ -2168,11 +2270,11 @@ var witness_layouts_default = {
2168
2270
  ]
2169
2271
  },
2170
2272
  transact_aggregate_14_12: {
2171
- artifactSha256: "738849e83eb4a78eb69cb6e20a86f6f27ba3784d04a83abd338f84de5c20d7d2",
2273
+ artifactSha256: "1191a92a333d826d4c4bd6a2e701a7751beb609904f8b928e3816f276d6fda67",
2172
2274
  keys: {
2173
- evm: "539928b264aea4d07a41e772d5d5a7b7666a6883decb985c27ca7422e7f8ea1f"
2275
+ evm: "a8b06d969e97f53624fae05d08aa548182ad09db24fe60159fae61d243c0cb9d"
2174
2276
  },
2175
- publicInputCount: 685,
2277
+ publicInputCount: 709,
2176
2278
  public: [
2177
2279
  {
2178
2280
  name: "statements",
@@ -2192,11 +2294,11 @@ var witness_layouts_default = {
2192
2294
  ]
2193
2295
  },
2194
2296
  create_credit: {
2195
- artifactSha256: "3ed6cfdee4f5fd840f023580f76c208768777fea79737f2511377e5c55be0230",
2297
+ artifactSha256: "16a41fd585d5f925e4e93fd6a308e1ca8c90ea287778871cb0d214f0d0e223ce",
2196
2298
  keys: {
2197
- evm: "56f663c6053be0d158a271022d200c732597efd3a2e0be48fe94549d0b1795e0"
2299
+ evm: "e8d3dc1f6922dbe1a0aa6016e65664be28d7005180ee943a4b237ac5518971bb"
2198
2300
  },
2199
- publicInputCount: 46,
2301
+ publicInputCount: 48,
2200
2302
  public: [
2201
2303
  {
2202
2304
  name: "chain_id",
@@ -2283,6 +2385,16 @@ var witness_layouts_default = {
2283
2385
  count: 1,
2284
2386
  array: false
2285
2387
  },
2388
+ {
2389
+ name: "fee_recipient",
2390
+ count: 1,
2391
+ array: false
2392
+ },
2393
+ {
2394
+ name: "fee_amount",
2395
+ count: 1,
2396
+ array: false
2397
+ },
2286
2398
  {
2287
2399
  name: "auth_digest_high",
2288
2400
  count: 1,
@@ -2841,11 +2953,11 @@ var witness_layouts_default = {
2841
2953
  ]
2842
2954
  },
2843
2955
  credit_cancel: {
2844
- artifactSha256: "b4459c2cf756d096e37291cf4d7cd129866b6d420b6d03c928f383b057112ccb",
2956
+ artifactSha256: "6485609280fe5a3d44ca9f1865b29b44253b3d2cd49770d000e7bb7a3db8e65d",
2845
2957
  keys: {
2846
- evm: "fc8ad196ef15f3328afcc8f01d867a3ebefd15451c2813948442fab1923b73b2"
2958
+ evm: "d74cf842d204cdf271c06a69482ddff11568e89630346b634d486205bec4bd9e"
2847
2959
  },
2848
- publicInputCount: 11,
2960
+ publicInputCount: 13,
2849
2961
  public: [
2850
2962
  {
2851
2963
  name: "chain_id",
@@ -2892,6 +3004,16 @@ var witness_layouts_default = {
2892
3004
  count: 1,
2893
3005
  array: false
2894
3006
  },
3007
+ {
3008
+ name: "fee_recipient",
3009
+ count: 1,
3010
+ array: false
3011
+ },
3012
+ {
3013
+ name: "fee_amount",
3014
+ count: 1,
3015
+ array: false
3016
+ },
2895
3017
  {
2896
3018
  name: "auth_digest_high",
2897
3019
  count: 1,
@@ -2925,11 +3047,11 @@ var witness_layouts_default = {
2925
3047
  ]
2926
3048
  },
2927
3049
  credit_top_up: {
2928
- artifactSha256: "2ffebd5753ec1b0c050204d4f97498765fe61ea01a793a9b2466c2f97536345c",
3050
+ artifactSha256: "3004eea1c26ec8e33f8fc9ee171a3b6af250682efb607f7003ae58f8327998ab",
2929
3051
  keys: {
2930
- evm: "40b02a9d2e7eb7b49daaac4b7760328537b7982fd5a225cc065bb74cd5ef44b3"
3052
+ evm: "b7f378a871a27649c3f7fd1af554c8f87d99bcf0780b21972e910212ed4e5a0d"
2931
3053
  },
2932
- publicInputCount: 50,
3054
+ publicInputCount: 52,
2933
3055
  public: [
2934
3056
  {
2935
3057
  name: "chain_id",
@@ -3016,6 +3138,16 @@ var witness_layouts_default = {
3016
3138
  count: 1,
3017
3139
  array: false
3018
3140
  },
3141
+ {
3142
+ name: "fee_recipient",
3143
+ count: 1,
3144
+ array: false
3145
+ },
3146
+ {
3147
+ name: "fee_amount",
3148
+ count: 1,
3149
+ array: false
3150
+ },
3019
3151
  {
3020
3152
  name: "credit_tree_id",
3021
3153
  count: 1,
@@ -3177,7 +3309,7 @@ var WitnessBuilder = class {
3177
3309
  words: words.slice(0, -2).map(BigInt)
3178
3310
  };
3179
3311
  check2(
3180
- signed.walletIdentity === identity && signed.digest === computeWalletAuthorizationDigest3(request),
3312
+ signed.ownerAddress === identity && signed.digest === computeWalletAuthorizationDigest3(request),
3181
3313
  "authorization statement mismatch"
3182
3314
  );
3183
3315
  const witness = signed.withWitness((value) => value);
@@ -3212,7 +3344,7 @@ var WitnessBuilder = class {
3212
3344
  this.context(note);
3213
3345
  return computeNoteCommitment3(
3214
3346
  note.chainId,
3215
- await computeNoteIdentity2(BigInt(note.walletIdentity), note.nonce),
3347
+ await computeNoteIdentity2(BigInt(note.ownerAddress), note.nonce),
3216
3348
  note.tokenAddress,
3217
3349
  note.amount
3218
3350
  );
@@ -3237,7 +3369,7 @@ var WitnessBuilder = class {
3237
3369
  check2(inputs.length === nullifiers.length, "input count mismatch");
3238
3370
  return Promise.all(
3239
3371
  inputs.map(async (input, i) => {
3240
- check2(input.note.walletIdentity === identity, "input wallet mismatch");
3372
+ check2(input.note.ownerAddress === identity, "input wallet mismatch");
3241
3373
  const leaf = await this.noteLeaf(input.note);
3242
3374
  check2(
3243
3375
  await computeNoteNullifier(input.note.chainId, input.note.nonce, leaf) === nullifiers[i],
@@ -3253,8 +3385,8 @@ var WitnessBuilder = class {
3253
3385
  p.inputs.length === n.inputCount && p.outputs.length === n.outputCount,
3254
3386
  "note count mismatch"
3255
3387
  );
3256
- const identity = p.inputs[0]?.note.walletIdentity;
3257
- const unsignedSweep = !!identity && !p.authorization && n.outputCount === 0 && n.depositAmount === 0n && BigInt(p.params.withdrawalAddress) === BigInt(identity);
3388
+ const identity = p.inputs[0]?.note.ownerAddress;
3389
+ const unsignedSweep = !!identity && !p.authorization && n.outputCount === 0 && n.depositAmount === 0n && n.feeAmount === 0n && BigInt(p.params.withdrawalAddress) === BigInt(identity);
3258
3390
  const authority = identity && !unsignedSweep ? await this.authority("transact", n.capacity, words, p.authorization, identity) : zeroAuthority();
3259
3391
  const sources = await this.noteInputs(
3260
3392
  p.inputs,
@@ -3263,22 +3395,44 @@ var WitnessBuilder = class {
3263
3395
  identity ?? "0x" + "00".repeat(32),
3264
3396
  authority
3265
3397
  );
3266
- for (const [i, note] of p.outputs.entries())
3267
- check2(
3268
- await this.noteLeaf(note) === p.params.outputCommitments[i],
3269
- "output commitment mismatch"
3270
- );
3271
- const all = [...p.inputs.map((input) => input.note), ...p.outputs];
3398
+ const outputs = await Promise.all(
3399
+ p.outputs.map(async (output, i) => {
3400
+ const opening = "identity" in output ? output.note : output;
3401
+ const identity2 = "identity" in output ? field(output.identity) : BigInt(
3402
+ await computeNoteIdentity2(BigInt(output.ownerAddress), output.nonce)
3403
+ );
3404
+ const amount = uint(output.amount, 128, "output amount");
3405
+ check2(identity2 !== 0n && amount !== 0n, "zero output identity or amount");
3406
+ if (opening) {
3407
+ this.context(opening);
3408
+ check2(
3409
+ opening.amount === amount && BigInt(
3410
+ await computeNoteIdentity2(
3411
+ BigInt(opening.ownerAddress),
3412
+ opening.nonce
3413
+ )
3414
+ ) === identity2,
3415
+ "output opening mismatch"
3416
+ );
3417
+ }
3418
+ const commitment = await computeNoteCommitment3(
3419
+ c.chainId,
3420
+ word(identity2),
3421
+ BigInt(c.tokenAddress),
3422
+ amount
3423
+ );
3424
+ check2(commitment === p.params.outputCommitments[i], "output commitment mismatch");
3425
+ return { identity: identity2, amount };
3426
+ })
3427
+ );
3428
+ const all = [...p.inputs.map((input) => input.note), ...outputs];
3272
3429
  return provingRequest(
3273
3430
  `transact_user_slots${n.capacity}`,
3274
3431
  {
3275
- wallet_identity: identity ? BigInt(identity) : 0n,
3432
+ input_owner_address: identity ? BigInt(identity) : 0n,
3276
3433
  ...authority,
3277
- output_wallet_identities: pad2(
3278
- [
3279
- ...p.inputs.map(() => 0n),
3280
- ...p.outputs.map((note) => BigInt(note.walletIdentity))
3281
- ],
3434
+ output_identities: pad2(
3435
+ [...p.inputs.map(() => 0n), ...outputs.map((output) => output.identity)],
3282
3436
  n.capacity,
3283
3437
  () => 0n
3284
3438
  ),
@@ -3288,7 +3442,7 @@ var WitnessBuilder = class {
3288
3442
  () => 0n
3289
3443
  ),
3290
3444
  nonces: pad2(
3291
- all.map((note) => note.nonce),
3445
+ [...p.inputs.map((input) => input.note.nonce), ...outputs.map(() => 0n)],
3292
3446
  n.capacity,
3293
3447
  () => 0n
3294
3448
  ),
@@ -3332,7 +3486,7 @@ var WitnessBuilder = class {
3332
3486
  );
3333
3487
  if (p.change)
3334
3488
  check2(
3335
- p.change.walletIdentity === note.ownerWalletIdentity && await this.noteLeaf(p.change) === p.params.changeCommitment,
3489
+ p.change.ownerAddress === note.ownerWalletIdentity && await this.noteLeaf(p.change) === p.params.changeCommitment,
3336
3490
  "change commitment mismatch"
3337
3491
  );
3338
3492
  else check2(BigInt(p.params.changeCommitment) === 0n, "missing change note");
@@ -3551,14 +3705,14 @@ var WitnessBuilder = class {
3551
3705
  };
3552
3706
 
3553
3707
  // src/factory.ts
3554
- import { Contract as Contract3, getAddress as getAddress8 } from "ethers";
3708
+ import { Contract as Contract3, getAddress as getAddress9 } from "ethers";
3555
3709
  async function resolveInstanceAddress(client, factoryAddress, salt) {
3556
3710
  const instance = await new Contract3(
3557
- getAddress8(factoryAddress),
3711
+ getAddress9(factoryAddress),
3558
3712
  invisiFactoryAbi,
3559
3713
  client
3560
3714
  ).getFunction("getInstanceAddress")(salt);
3561
- return getAddress8(instance);
3715
+ return getAddress9(instance);
3562
3716
  }
3563
3717
  export {
3564
3718
  AddressRegistry,