@invisi-labs/sdk 1.1.6 → 1.2.0

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.
Files changed (132) hide show
  1. package/README.md +5 -0
  2. package/dist/broadcaster-3KTB4JO2.cjs +21 -0
  3. package/dist/broadcaster-3KTB4JO2.cjs.map +1 -0
  4. package/dist/broadcaster-7ZKKSTZQ.js +21 -0
  5. package/dist/broadcaster-preparation-PJ263WBL.cjs +15 -0
  6. package/dist/broadcaster-preparation-PJ263WBL.cjs.map +1 -0
  7. package/dist/broadcaster-preparation-ZQAPZAUG.js +15 -0
  8. package/dist/broadcaster-preparation-ZQAPZAUG.js.map +1 -0
  9. package/dist/chunk-2URICDPW.cjs +167 -0
  10. package/dist/chunk-2URICDPW.cjs.map +1 -0
  11. package/dist/chunk-3D24ABYR.js +86 -0
  12. package/dist/chunk-3D24ABYR.js.map +1 -0
  13. package/dist/chunk-3KTQQZOW.cjs +71 -0
  14. package/dist/chunk-3KTQQZOW.cjs.map +1 -0
  15. package/dist/chunk-4H4FARQK.js +1582 -0
  16. package/dist/chunk-4H4FARQK.js.map +1 -0
  17. package/dist/chunk-4SDP53YQ.cjs +765 -0
  18. package/dist/chunk-4SDP53YQ.cjs.map +1 -0
  19. package/dist/{chunk-QC6TQR3R.js → chunk-4VI6LYGH.js} +35 -12
  20. package/dist/chunk-4VI6LYGH.js.map +1 -0
  21. package/dist/chunk-BBSRP4MH.cjs +287 -0
  22. package/dist/chunk-BBSRP4MH.cjs.map +1 -0
  23. package/dist/chunk-DGMVGFKM.js +41 -0
  24. package/dist/chunk-DGMVGFKM.js.map +1 -0
  25. package/dist/chunk-GUD3LAUO.js +765 -0
  26. package/dist/chunk-GUD3LAUO.js.map +1 -0
  27. package/dist/chunk-HCB7RQ3S.cjs +79 -0
  28. package/dist/chunk-HCB7RQ3S.cjs.map +1 -0
  29. package/dist/{broadcaster-preparation-QVL62KM6.js → chunk-HKGJXQVN.js} +73 -34
  30. package/dist/chunk-HKGJXQVN.js.map +1 -0
  31. package/dist/chunk-HLH5JZD4.js +287 -0
  32. package/dist/chunk-HLH5JZD4.js.map +1 -0
  33. package/dist/chunk-J6TZZVAM.cjs +230 -0
  34. package/dist/chunk-J6TZZVAM.cjs.map +1 -0
  35. package/dist/chunk-LOR6PYH5.cjs +397 -0
  36. package/dist/chunk-LOR6PYH5.cjs.map +1 -0
  37. package/dist/chunk-MA2QZEF5.cjs +399 -0
  38. package/dist/chunk-MA2QZEF5.cjs.map +1 -0
  39. package/dist/chunk-MI4IP4ZD.cjs +86 -0
  40. package/dist/chunk-MI4IP4ZD.cjs.map +1 -0
  41. package/dist/chunk-NKYHYIRP.cjs +1582 -0
  42. package/dist/chunk-NKYHYIRP.cjs.map +1 -0
  43. package/dist/chunk-OCZLJKIA.cjs +41 -0
  44. package/dist/chunk-OCZLJKIA.cjs.map +1 -0
  45. package/dist/chunk-R5YAOJKB.js +71 -0
  46. package/dist/chunk-R5YAOJKB.js.map +1 -0
  47. package/dist/chunk-RY4M2CIQ.js +399 -0
  48. package/dist/chunk-RY4M2CIQ.js.map +1 -0
  49. package/dist/chunk-THMD5QO2.js +79 -0
  50. package/dist/chunk-THMD5QO2.js.map +1 -0
  51. package/dist/chunk-ZD2652WH.js +230 -0
  52. package/dist/chunk-ZD2652WH.js.map +1 -0
  53. package/dist/credit.cjs +1 -0
  54. package/dist/credit.cjs.map +1 -0
  55. package/dist/credit.d.cts +12 -0
  56. package/dist/credit.d.ts +12 -0
  57. package/dist/credit.js +1 -0
  58. package/dist/credit.js.map +1 -0
  59. package/dist/ethers.cjs +11 -385
  60. package/dist/ethers.cjs.map +1 -1
  61. package/dist/ethers.d.cts +16 -6
  62. package/dist/ethers.d.ts +16 -6
  63. package/dist/ethers.js +1 -1
  64. package/dist/index-CLhGwLxZ.d.cts +42 -0
  65. package/dist/index-Crp-ZFiM.d.ts +42 -0
  66. package/dist/index.cjs +479 -7847
  67. package/dist/index.cjs.map +1 -1
  68. package/dist/index.d.cts +87 -710
  69. package/dist/index.d.ts +87 -710
  70. package/dist/index.js +407 -869
  71. package/dist/index.js.map +1 -1
  72. package/dist/note.cjs +11 -0
  73. package/dist/note.cjs.map +1 -0
  74. package/dist/note.d.cts +29 -0
  75. package/dist/note.d.ts +29 -0
  76. package/dist/note.js +11 -0
  77. package/dist/note.js.map +1 -0
  78. package/dist/operation-bridge-CoECSxfi.d.cts +472 -0
  79. package/dist/operation-bridge-CoECSxfi.d.ts +472 -0
  80. package/dist/preparation-HUBTVCZE.js +404 -0
  81. package/dist/preparation-HUBTVCZE.js.map +1 -0
  82. package/dist/preparation-QD3ZSYV5.cjs +404 -0
  83. package/dist/preparation-QD3ZSYV5.cjs.map +1 -0
  84. package/dist/provenance-preparation-43DN2WK7.cjs +16 -0
  85. package/dist/provenance-preparation-43DN2WK7.cjs.map +1 -0
  86. package/dist/provenance-preparation-HEZE4L5H.js +16 -0
  87. package/dist/provenance-preparation-HEZE4L5H.js.map +1 -0
  88. package/dist/provenance.cjs +59 -0
  89. package/dist/provenance.cjs.map +1 -0
  90. package/dist/provenance.d.cts +34 -0
  91. package/dist/provenance.d.ts +34 -0
  92. package/dist/provenance.js +59 -0
  93. package/dist/provenance.js.map +1 -0
  94. package/dist/receipt-logs-8Msm_HZS.d.ts +322 -0
  95. package/dist/receipt-logs-DWG4In8N.d.cts +322 -0
  96. package/dist/session-support.cjs +189 -0
  97. package/dist/session-support.cjs.map +1 -0
  98. package/dist/session-support.d.cts +284 -0
  99. package/dist/session-support.d.ts +284 -0
  100. package/dist/session-support.js +189 -0
  101. package/dist/session-support.js.map +1 -0
  102. package/package.json +25 -19
  103. package/dist/NoteOutput-DRkVnwlx.d.cts +0 -398
  104. package/dist/NoteOutput-DpDC6T2O.d.ts +0 -398
  105. package/dist/broadcaster-preparation-QVL62KM6.js.map +0 -1
  106. package/dist/chunk-4SD3MW6N.js +0 -4711
  107. package/dist/chunk-4SD3MW6N.js.map +0 -1
  108. package/dist/chunk-FL4TIGWW.js +0 -1781
  109. package/dist/chunk-FL4TIGWW.js.map +0 -1
  110. package/dist/chunk-QC6TQR3R.js.map +0 -1
  111. package/dist/indexeddb.cjs +0 -6878
  112. package/dist/indexeddb.cjs.map +0 -1
  113. package/dist/indexeddb.d.cts +0 -20
  114. package/dist/indexeddb.d.ts +0 -20
  115. package/dist/indexeddb.js +0 -71
  116. package/dist/indexeddb.js.map +0 -1
  117. package/dist/memory.cjs +0 -6886
  118. package/dist/memory.cjs.map +0 -1
  119. package/dist/memory.d.cts +0 -12
  120. package/dist/memory.d.ts +0 -12
  121. package/dist/memory.js +0 -11
  122. package/dist/sqlite.cjs +0 -6862
  123. package/dist/sqlite.cjs.map +0 -1
  124. package/dist/sqlite.d.cts +0 -28
  125. package/dist/sqlite.d.ts +0 -28
  126. package/dist/sqlite.js +0 -55
  127. package/dist/sqlite.js.map +0 -1
  128. package/dist/state-C4HZFotm.d.cts +0 -78
  129. package/dist/state-C4HZFotm.d.ts +0 -78
  130. package/dist/store-8aBhnbGr.d.ts +0 -42
  131. package/dist/store-YrbXb6CY.d.cts +0 -42
  132. /package/dist/{memory.js.map → broadcaster-7ZKKSTZQ.js.map} +0 -0
@@ -0,0 +1,287 @@
1
+ import {
2
+ statement
3
+ } from "./chunk-THMD5QO2.js";
4
+ import {
5
+ Preparation,
6
+ positiveAmount,
7
+ positiveOutputAmount
8
+ } from "./chunk-RY4M2CIQ.js";
9
+ import {
10
+ resolvedOutputSnapshot
11
+ } from "./chunk-GUD3LAUO.js";
12
+
13
+ // src/broadcaster/intent.ts
14
+ import { normalizeFunding } from "@invisi-labs/protocol";
15
+ import { invisiProtocolAbi } from "@invisi-labs/protocol/contracts";
16
+ import { Interface } from "ethers";
17
+ function exportBroadcasterIntent(plan) {
18
+ if (plan.statement && plan.statement.target !== "evm")
19
+ throw new Error("unsupported broadcaster operation");
20
+ if (plan.statement) statement(plan);
21
+ const feeDefaults = (params) => ({
22
+ ...params,
23
+ feeRecipient: params.feeRecipient ?? "0x0000000000000000000000000000000000000000",
24
+ feeAmount: params.feeAmount ?? 0n
25
+ });
26
+ const funding = { ...normalizeFunding(plan.funding), signature: "0x" };
27
+ let method;
28
+ let args;
29
+ if (plan.params) {
30
+ method = "transact";
31
+ args = [
32
+ "0x",
33
+ {
34
+ params: feeDefaults(plan.params),
35
+ deliveries: plan.outputs.map((o) => o.delivery),
36
+ funding
37
+ }
38
+ ];
39
+ } else if (plan.shieldParams) {
40
+ method = "shield";
41
+ args = [
42
+ feeDefaults(plan.shieldParams),
43
+ plan.shieldOutputs,
44
+ plan.outputs.map((o) => o.delivery),
45
+ funding
46
+ ];
47
+ } else if (plan.credit?.creation) {
48
+ method = "createCredit";
49
+ args = ["0x", plan.credit.creation, plan.credit.deliveries];
50
+ } else if (plan.credit?.draw) {
51
+ method = "creditDraw";
52
+ args = ["0x", plan.credit.draw, plan.credit.deliveries];
53
+ } else if (plan.credit?.update) {
54
+ method = "updateCredit";
55
+ args = ["0x", plan.credit.update, plan.credit.deliveries];
56
+ } else if (plan.credit?.revocation) {
57
+ const p = plan.credit.revocation;
58
+ method = "revokeCredit";
59
+ args = [
60
+ p.token,
61
+ p.owner,
62
+ p.shard,
63
+ p.slot,
64
+ p.deadline,
65
+ p.feeRecipient ?? "0x0000000000000000000000000000000000000000",
66
+ p.feeAmount ?? 0n,
67
+ "0x"
68
+ ];
69
+ } else throw new Error("unsupported broadcaster operation");
70
+ const abi = invisiProtocolAbi.filter(
71
+ (item) => item.type === "function" && item.name === method && (method !== "transact" || item.inputs[1]?.type === "tuple")
72
+ );
73
+ return {
74
+ sendable: false,
75
+ data: new Interface(abi).encodeFunctionData(method, args)
76
+ };
77
+ }
78
+
79
+ // src/transactions/preparation/transaction-preparation.ts
80
+ import {
81
+ normalizeTransactRequest,
82
+ transactUserPublicInputs,
83
+ ZERO_ADDRESS
84
+ } from "@invisi-labs/protocol";
85
+ import { WitnessBuilder } from "@invisi-labs/prover";
86
+ import { getAddress } from "ethers";
87
+ var TransactionPreparation = class {
88
+ constructor(context) {
89
+ this.context = context;
90
+ const complete = context.complete;
91
+ this.context = {
92
+ ...context,
93
+ complete: (plan) => {
94
+ const intent = this.#intent ? structuredClone(this.#intent) : void 0;
95
+ if (intent && (intent.kind === "transfer" || intent.kind === "shield")) {
96
+ const businessOutputs = plan.outputs.filter((output) => !output.change);
97
+ intent.options.outputs = intent.options.outputs.map(
98
+ (payment, index) => resolvedOutputSnapshot(payment, businessOutputs[index])
99
+ );
100
+ }
101
+ return complete({ ...plan, ...intent ? { intent } : {} });
102
+ }
103
+ };
104
+ }
105
+ #intent;
106
+ runtime(tokenAddress) {
107
+ if (getAddress(tokenAddress) !== getAddress(this.context.options.protocol.context.tokenAddress))
108
+ throw new Error("preparation token mismatch");
109
+ return this.context;
110
+ }
111
+ get scope() {
112
+ return this.context.scope;
113
+ }
114
+ async prepareTransfer(options) {
115
+ this.#intent = { kind: "transfer", options: structuredClone(options) };
116
+ if (Object.hasOwn(options, "target") || Object.hasOwn(options, "execution")) {
117
+ throw new Error(
118
+ "prepareTransfer accepts no target or execution; choose execution in prove()"
119
+ );
120
+ }
121
+ const copied = structuredClone(options);
122
+ const runtime = this.runtime(copied.tokenAddress);
123
+ if (copied.commitments !== void 0 && copied.commitments.length === 0)
124
+ throw new Error("empty explicit input selection");
125
+ const preparation = new Preparation({
126
+ ...runtime,
127
+ ...copied.commitments !== void 0 ? { inputSelection: copied.commitments } : {}
128
+ });
129
+ const frame = await preparation.frame(copied.deadline);
130
+ if (copied.outputs.length > 190) throw new Error("transfer supports at most 190 outputs");
131
+ let withdrawalAddress = ZERO_ADDRESS;
132
+ let withdrawalAmount = 0n;
133
+ if (copied.withdrawal !== void 0) {
134
+ withdrawalAddress = getAddress(copied.withdrawal.to);
135
+ positiveAmount(copied.withdrawal.amount);
136
+ if (BigInt(withdrawalAddress) === 0n)
137
+ throw new Error("withdrawal destination must be nonzero");
138
+ withdrawalAmount = copied.withdrawal.amount;
139
+ }
140
+ if (copied.outputs.length === 0 && withdrawalAmount === 0n)
141
+ throw new Error("transfer requires a private output or public withdrawal");
142
+ const feeRecipient = copied.fee ? getAddress(copied.fee.recipient) : ZERO_ADDRESS;
143
+ const feeAmount = copied.fee?.amount ?? 0n;
144
+ if (copied.fee) {
145
+ positiveAmount(feeAmount);
146
+ if (BigInt(feeRecipient) === 0n) throw new Error("fee recipient must be nonzero");
147
+ }
148
+ const total = copied.outputs.reduce(
149
+ (sum, output, index) => sum + positiveOutputAmount(output, index),
150
+ withdrawalAmount + feeAmount
151
+ );
152
+ const funding = await preparation.funding(copied.funding, frame);
153
+ return this.funds(
154
+ copied.outputs,
155
+ total,
156
+ withdrawalAddress,
157
+ withdrawalAmount,
158
+ { recipient: feeRecipient, amount: feeAmount },
159
+ frame,
160
+ funding,
161
+ preparation
162
+ );
163
+ }
164
+ async funds(payments, total, withdrawalAddress, withdrawalAmount, fee, frame, funding, preparation) {
165
+ if (total >= 1n << 135n) {
166
+ throw new Error("transaction sum exceeds uint135");
167
+ }
168
+ const { context, block, deadline } = frame;
169
+ const selection = await preparation.selectFunds(
170
+ total - (funding.funding.amount ?? 0n),
171
+ frame
172
+ );
173
+ const outputs = await Promise.all(
174
+ payments.map((payment, index) => preparation.output(payment, context, false, index))
175
+ );
176
+ const change = selection.amount + (funding.funding.amount ?? 0n) - total;
177
+ if (change > 0n) {
178
+ outputs.push(await preparation.change(change, context));
179
+ }
180
+ const params = {
181
+ token: context.tokenAddress,
182
+ sources: selection.sources,
183
+ nullifiers: selection.nullifiers,
184
+ noteCommitments: outputs.map((output) => output.commitment),
185
+ withdrawalAddress,
186
+ withdrawalAmount,
187
+ deadline,
188
+ feeRecipient: fee.recipient,
189
+ feeAmount: fee.amount
190
+ };
191
+ const deliveries = outputs.map((output) => output.delivery);
192
+ const normalized = normalizeTransactRequest(context, params, deliveries, funding.funding);
193
+ const statement2 = WitnessBuilder.statement(
194
+ `transact_user_slots${normalized.capacity}`,
195
+ transactUserPublicInputs(context, params, deliveries, funding.funding),
196
+ "evm"
197
+ );
198
+ await preparation.assertBlock(frame);
199
+ return preparation.runtime.complete({
200
+ version: 1,
201
+ id: crypto.randomUUID(),
202
+ kind: "transfer",
203
+ context,
204
+ scope: this.scope,
205
+ preparedAt: block,
206
+ deadline,
207
+ outputs,
208
+ inputs: selection.inputs,
209
+ ...funding,
210
+ params,
211
+ capacity: normalized.capacity,
212
+ statement: statement2
213
+ });
214
+ }
215
+ async prepareShield(options) {
216
+ this.#intent = { kind: "shield", options: structuredClone(options) };
217
+ const copied = structuredClone(options);
218
+ const preparation = new Preparation(this.runtime(copied.tokenAddress));
219
+ const frame = await preparation.frame(copied.deadline);
220
+ const funding = await preparation.funding(copied.funding, frame);
221
+ if (copied.outputs.length < 1 || copied.outputs.length > 10) {
222
+ throw new Error("shield requires 1..10 outputs");
223
+ }
224
+ const outputs = await Promise.all(
225
+ copied.outputs.map(
226
+ (output, index) => preparation.output(output, frame.context, false, index)
227
+ )
228
+ );
229
+ if (outputs.reduce((sum, output) => sum + output.amount, 0n) !== (funding.funding.amount ?? 0n) - (copied.fee?.amount ?? 0n)) {
230
+ throw new Error("shield funding must equal output total");
231
+ }
232
+ await preparation.assertBlock(frame);
233
+ return preparation.runtime.complete({
234
+ version: 1,
235
+ id: crypto.randomUUID(),
236
+ kind: "shield",
237
+ context: frame.context,
238
+ scope: this.scope,
239
+ preparedAt: frame.block,
240
+ deadline: frame.deadline,
241
+ outputs,
242
+ inputs: [],
243
+ ...funding,
244
+ shieldParams: {
245
+ token: frame.context.tokenAddress,
246
+ feeRecipient: copied.fee?.recipient ?? ZERO_ADDRESS,
247
+ feeAmount: copied.fee?.amount ?? 0n,
248
+ noteCommitments: outputs.map((output) => output.commitment),
249
+ deadline: frame.deadline
250
+ },
251
+ shieldOutputs: outputs.map((output) => ({
252
+ identity: output.identity,
253
+ amount: output.amount
254
+ }))
255
+ });
256
+ }
257
+ async prepareCreateCredit(options) {
258
+ const copied = structuredClone(options);
259
+ this.#intent = { kind: "create-credit", options: structuredClone(copied) };
260
+ const { CreditPreparation } = await import("./preparation-HUBTVCZE.js");
261
+ return new CreditPreparation(this.runtime(copied.tokenAddress)).create(copied);
262
+ }
263
+ async prepareDrawCredit(options) {
264
+ const copied = structuredClone(options);
265
+ this.#intent = { kind: "draw-credit", options: structuredClone(copied) };
266
+ const { CreditPreparation } = await import("./preparation-HUBTVCZE.js");
267
+ return new CreditPreparation(this.runtime(copied.tokenAddress)).draw(copied);
268
+ }
269
+ async prepareUpdateCredit(options) {
270
+ const copied = structuredClone(options);
271
+ this.#intent = { kind: "update-credit", options: structuredClone(copied) };
272
+ const { CreditPreparation } = await import("./preparation-HUBTVCZE.js");
273
+ return new CreditPreparation(this.runtime(copied.tokenAddress)).update(copied);
274
+ }
275
+ async prepareRevokeCredit(options) {
276
+ const copied = structuredClone(options);
277
+ this.#intent = { kind: "revoke-credit", options: structuredClone(copied) };
278
+ const { CreditPreparation } = await import("./preparation-HUBTVCZE.js");
279
+ return new CreditPreparation(this.runtime(copied.tokenAddress)).revoke(copied);
280
+ }
281
+ };
282
+
283
+ export {
284
+ exportBroadcasterIntent,
285
+ TransactionPreparation
286
+ };
287
+ //# sourceMappingURL=chunk-HLH5JZD4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/broadcaster/intent.ts","../src/transactions/preparation/transaction-preparation.ts"],"sourcesContent":["import { normalizeFunding } from \"@invisi-labs/protocol\";\nimport type { Hex } from \"@invisi-labs/protocol/contracts\";\nimport { invisiProtocolAbi } from \"@invisi-labs/protocol/contracts\";\nimport { Interface } from \"ethers\";\nimport type { OperationPlan } from \"../transactions/operation-types\";\nimport { statement } from \"../transactions/signing/statement\";\n\n/** Quote-only export; callers still need the operation-specific proof or owner authorization. */\nexport function exportBroadcasterIntent(plan: OperationPlan) {\n if (plan.statement && plan.statement.target !== \"evm\")\n throw new Error(\"unsupported broadcaster operation\");\n if (plan.statement) statement(plan);\n const feeDefaults = <T extends { feeRecipient?: string; feeAmount?: bigint }>(params: T) => ({\n ...params,\n feeRecipient: params.feeRecipient ?? \"0x0000000000000000000000000000000000000000\",\n feeAmount: params.feeAmount ?? 0n,\n });\n const funding = { ...normalizeFunding(plan.funding), signature: \"0x\" };\n let method: string;\n let args: unknown[];\n if (plan.params) {\n method = \"transact\";\n args = [\n \"0x\",\n {\n params: feeDefaults(plan.params),\n deliveries: plan.outputs.map((o) => o.delivery),\n funding,\n },\n ];\n } else if (plan.shieldParams) {\n method = \"shield\";\n args = [\n feeDefaults(plan.shieldParams),\n plan.shieldOutputs,\n plan.outputs.map((o) => o.delivery),\n funding,\n ];\n } else if (plan.credit?.creation) {\n method = \"createCredit\";\n args = [\"0x\", plan.credit.creation, plan.credit.deliveries];\n } else if (plan.credit?.draw) {\n method = \"creditDraw\";\n args = [\"0x\", plan.credit.draw, plan.credit.deliveries];\n } else if (plan.credit?.update) {\n method = \"updateCredit\";\n args = [\"0x\", plan.credit.update, plan.credit.deliveries];\n } else if (plan.credit?.revocation) {\n const p = plan.credit.revocation;\n method = \"revokeCredit\";\n args = [\n p.token,\n p.owner,\n p.shard,\n p.slot,\n p.deadline,\n p.feeRecipient ?? \"0x0000000000000000000000000000000000000000\",\n p.feeAmount ?? 0n,\n \"0x\",\n ];\n } else throw new Error(\"unsupported broadcaster operation\");\n const abi = invisiProtocolAbi.filter(\n (item) =>\n item.type === \"function\" &&\n item.name === method &&\n (method !== \"transact\" || item.inputs[1]?.type === \"tuple\")\n );\n return {\n sendable: false as const,\n data: new Interface(abi).encodeFunctionData(method, args) as Hex,\n };\n}\n","import {\n normalizeTransactRequest,\n transactUserPublicInputs,\n ZERO_ADDRESS,\n} from \"@invisi-labs/protocol\";\nimport { WitnessBuilder } from \"@invisi-labs/prover\";\nimport type { Hex } from \"@invisi-labs/protocol/contracts\";\nimport { getAddress } from \"ethers\";\nimport { NoteOutput, resolvedOutputSnapshot } from \"../../notes/NoteOutput\";\nimport type {\n RevokeCreditPreparation,\n CreateCreditPreparation,\n DrawCreditPreparation,\n OperationPlan,\n PreparationRuntime,\n ShieldPreparation,\n UpdateCreditPreparation,\n TransferPreparation,\n} from \"../operation-types\";\nimport {\n positiveAmount,\n positiveOutputAmount,\n Preparation,\n type PreparationFrame,\n} from \"./prepare-common\";\n\n/** Shared preparation engine for managed sessions and explicitly supplied inputs. */\nexport class TransactionPreparation<Result> {\n #intent: import(\"../../broadcaster/broadcaster-preparation\").PreparationIntent | undefined;\n constructor(readonly context: PreparationRuntime<Result>) {\n const complete = context.complete;\n this.context = {\n ...context,\n complete: (plan) => {\n const intent = this.#intent ? structuredClone(this.#intent) : undefined;\n if (intent && (intent.kind === \"transfer\" || intent.kind === \"shield\")) {\n const businessOutputs = plan.outputs.filter((output) => !output.change);\n intent.options.outputs = intent.options.outputs.map((payment, index) =>\n resolvedOutputSnapshot(payment, businessOutputs[index]!)\n );\n }\n return complete({ ...plan, ...(intent ? { intent } : {}) });\n },\n };\n }\n private runtime(tokenAddress: Hex): PreparationRuntime<Result> {\n if (\n getAddress(tokenAddress) !==\n getAddress(this.context.options.protocol.context.tokenAddress)\n )\n throw new Error(\"preparation token mismatch\");\n return this.context;\n }\n private get scope() {\n return this.context.scope;\n }\n async prepareTransfer(options: TransferPreparation): Promise<Result> {\n this.#intent = { kind: \"transfer\", options: structuredClone(options) };\n if (Object.hasOwn(options, \"target\") || Object.hasOwn(options, \"execution\")) {\n throw new Error(\n \"prepareTransfer accepts no target or execution; choose execution in prove()\"\n );\n }\n const copied = structuredClone(options);\n const runtime = this.runtime(copied.tokenAddress);\n if (copied.commitments !== undefined && copied.commitments.length === 0)\n throw new Error(\"empty explicit input selection\");\n const preparation = new Preparation({\n ...runtime,\n ...(copied.commitments !== undefined ? { inputSelection: copied.commitments } : {}),\n });\n const frame = await preparation.frame(copied.deadline);\n if (copied.outputs.length > 190) throw new Error(\"transfer supports at most 190 outputs\");\n let withdrawalAddress: Hex = ZERO_ADDRESS;\n let withdrawalAmount = 0n;\n if (copied.withdrawal !== undefined) {\n withdrawalAddress = getAddress(copied.withdrawal.to) as Hex;\n positiveAmount(copied.withdrawal.amount);\n if (BigInt(withdrawalAddress) === 0n)\n throw new Error(\"withdrawal destination must be nonzero\");\n withdrawalAmount = copied.withdrawal.amount;\n }\n if (copied.outputs.length === 0 && withdrawalAmount === 0n)\n throw new Error(\"transfer requires a private output or public withdrawal\");\n const feeRecipient = copied.fee ? (getAddress(copied.fee.recipient) as Hex) : ZERO_ADDRESS;\n const feeAmount = copied.fee?.amount ?? 0n;\n if (copied.fee) {\n positiveAmount(feeAmount);\n if (BigInt(feeRecipient) === 0n) throw new Error(\"fee recipient must be nonzero\");\n }\n const total = copied.outputs.reduce(\n (sum, output, index) => sum + positiveOutputAmount(output, index),\n withdrawalAmount + feeAmount\n );\n const funding = await preparation.funding(copied.funding, frame);\n return this.funds(\n copied.outputs,\n total,\n withdrawalAddress,\n withdrawalAmount,\n { recipient: feeRecipient, amount: feeAmount },\n frame,\n funding,\n preparation\n );\n }\n\n private async funds(\n payments: readonly NoteOutput[],\n total: bigint,\n withdrawalAddress: `0x${string}`,\n withdrawalAmount: bigint,\n fee: { recipient: Hex; amount: bigint },\n frame: PreparationFrame,\n funding: Pick<OperationPlan, \"funding\" | \"fundingMode\">,\n preparation: Preparation<Result>\n ): Promise<Result> {\n if (total >= 1n << 135n) {\n throw new Error(\"transaction sum exceeds uint135\");\n }\n const { context, block, deadline } = frame;\n const selection = await preparation.selectFunds(\n total - (funding.funding.amount ?? 0n),\n frame\n );\n const outputs = await Promise.all(\n payments.map((payment, index) => preparation.output(payment, context, false, index))\n );\n const change = selection.amount + (funding.funding.amount ?? 0n) - total;\n if (change > 0n) {\n outputs.push(await preparation.change(change, context));\n }\n const params = {\n token: context.tokenAddress,\n sources: selection.sources,\n nullifiers: selection.nullifiers,\n noteCommitments: outputs.map((output) => output.commitment),\n withdrawalAddress,\n withdrawalAmount,\n deadline,\n feeRecipient: fee.recipient,\n feeAmount: fee.amount,\n };\n const deliveries = outputs.map((output) => output.delivery);\n const normalized = normalizeTransactRequest(context, params, deliveries, funding.funding);\n const statement = WitnessBuilder.statement(\n `transact_user_slots${normalized.capacity}`,\n transactUserPublicInputs(context, params, deliveries, funding.funding),\n \"evm\"\n );\n await preparation.assertBlock(frame);\n return preparation.runtime.complete({\n version: 1,\n id: crypto.randomUUID(),\n kind: \"transfer\",\n context,\n scope: this.scope,\n preparedAt: block,\n deadline,\n outputs,\n inputs: selection.inputs,\n ...funding,\n params,\n capacity: normalized.capacity,\n statement,\n });\n }\n\n async prepareShield(options: ShieldPreparation): Promise<Result> {\n this.#intent = { kind: \"shield\", options: structuredClone(options) };\n const copied = structuredClone(options);\n const preparation = new Preparation(this.runtime(copied.tokenAddress));\n const frame = await preparation.frame(copied.deadline);\n const funding = await preparation.funding(copied.funding, frame);\n if (copied.outputs.length < 1 || copied.outputs.length > 10) {\n throw new Error(\"shield requires 1..10 outputs\");\n }\n const outputs = await Promise.all(\n copied.outputs.map((output, index) =>\n preparation.output(output, frame.context, false, index)\n )\n );\n if (\n outputs.reduce((sum, output) => sum + output.amount, 0n) !==\n (funding.funding.amount ?? 0n) - (copied.fee?.amount ?? 0n)\n ) {\n throw new Error(\"shield funding must equal output total\");\n }\n await preparation.assertBlock(frame);\n return preparation.runtime.complete({\n version: 1,\n id: crypto.randomUUID(),\n kind: \"shield\",\n context: frame.context,\n scope: this.scope,\n preparedAt: frame.block,\n deadline: frame.deadline,\n outputs,\n inputs: [],\n ...funding,\n shieldParams: {\n token: frame.context.tokenAddress,\n feeRecipient: copied.fee?.recipient ?? ZERO_ADDRESS,\n feeAmount: copied.fee?.amount ?? 0n,\n noteCommitments: outputs.map((output) => output.commitment),\n deadline: frame.deadline,\n },\n shieldOutputs: outputs.map((output) => ({\n identity: output.identity,\n amount: output.amount,\n })),\n });\n }\n\n async prepareCreateCredit(options: CreateCreditPreparation): Promise<Result> {\n const copied = structuredClone(options);\n this.#intent = { kind: \"create-credit\", options: structuredClone(copied) };\n const { CreditPreparation } = await import(\"../../credit/preparation\");\n return new CreditPreparation(this.runtime(copied.tokenAddress)).create(copied);\n }\n\n async prepareDrawCredit(options: DrawCreditPreparation): Promise<Result> {\n const copied = structuredClone(options);\n this.#intent = { kind: \"draw-credit\", options: structuredClone(copied) };\n const { CreditPreparation } = await import(\"../../credit/preparation\");\n return new CreditPreparation(this.runtime(copied.tokenAddress)).draw(copied);\n }\n\n async prepareUpdateCredit(options: UpdateCreditPreparation): Promise<Result> {\n const copied = structuredClone(options);\n this.#intent = { kind: \"update-credit\", options: structuredClone(copied) };\n const { CreditPreparation } = await import(\"../../credit/preparation\");\n return new CreditPreparation(this.runtime(copied.tokenAddress)).update(copied);\n }\n\n async prepareRevokeCredit(options: RevokeCreditPreparation): Promise<Result> {\n const copied = structuredClone(options);\n this.#intent = { kind: \"revoke-credit\", options: structuredClone(copied) };\n const { CreditPreparation } = await import(\"../../credit/preparation\");\n return new CreditPreparation(this.runtime(copied.tokenAddress)).revoke(copied);\n }\n}\n"],"mappings":"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","names":["statement"]}
@@ -0,0 +1,230 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+ var _chunkMI4IP4ZDcjs = require('./chunk-MI4IP4ZD.cjs');
4
+
5
+
6
+ var _chunkHCB7RQ3Scjs = require('./chunk-HCB7RQ3S.cjs');
7
+
8
+
9
+ var _chunk3KTQQZOWcjs = require('./chunk-3KTQQZOW.cjs');
10
+
11
+ // src/broadcaster/provenance-preparation.ts
12
+ var _provenance = require('@invisi-labs/rpc/provenance');
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+ var _provenance3 = require('@invisi-labs/protocol/provenance');
22
+
23
+
24
+ var _provenancewitness = require('@invisi-labs/prover/provenance-witness');
25
+ function requireProvenanceCapability(plan, runtime) {
26
+ const cap = runtime.options.provenance;
27
+ if (!cap) throw Error("Provenance capability required for private inputs");
28
+ const trust = cap.client.trust;
29
+ if (BigInt(trust.chainId) !== plan.context.chainId || BigInt(trust.protocolAddress) !== BigInt(plan.context.protocolAddress) || cap.manifest.sha256 !== trust.manifestSha256)
30
+ throw Error("Provenance deployment or manifest mismatch");
31
+ }
32
+ async function prepareProvenance(plan, runtime) {
33
+ requireProvenanceCapability(plan, runtime);
34
+ if (!plan.inputs.length) throw Error("No private Note inputs require a Provenance proof");
35
+ const {
36
+ client: source,
37
+ manifest,
38
+ prover,
39
+ maxRootPages = 10,
40
+ maxLeaves = 1e5
41
+ } = runtime.options.provenance;
42
+ if (!Number.isSafeInteger(maxRootPages) || maxRootPages < 1 || maxRootPages > 100 || !Number.isSafeInteger(maxLeaves) || maxLeaves < 1)
43
+ throw Error("Invalid Provenance replay budget");
44
+ if (!plan.params || !plan.capacity || plan.params.nullifiers.length !== plan.inputs.length)
45
+ throw Error("Private transact statement required");
46
+ const trust = source.trust;
47
+ const openings = await Promise.all(
48
+ plan.inputs.map(async (input, i) => {
49
+ const opening = {
50
+ owner: input.note.ownerAddress,
51
+ nonce: input.note.nonce,
52
+ amount: input.note.amount
53
+ };
54
+ const computed = await _provenance3.noteOpening.call(void 0, { ...plan.context, ...opening });
55
+ if (computed.commitment !== BigInt(input.commitment) || computed.nullifier !== BigInt(plan.params.nullifiers[i]))
56
+ throw Error("Prepared Note opening or nullifier mismatch");
57
+ return opening;
58
+ })
59
+ );
60
+ const digest = _provenance3.operationDigest.call(void 0, {
61
+ ...plan.context,
62
+ mainCircuitCapacity: plan.capacity,
63
+ publicInputs: _chunkHCB7RQ3Scjs.statement.call(void 0, plan).expectedPublicInputs
64
+ });
65
+ const status = await source.getStatus();
66
+ const rootId = `${BigInt(trust.chainGeneration)}:${BigInt(String(status.checkpointSequence))}`;
67
+ const latest = await source.getRoot(rootId);
68
+ if (!latest.certificate || latest.allowedForNewProof !== true)
69
+ throw Error("No current recognized root");
70
+ const certificates = /* @__PURE__ */ new Map();
71
+ const matches = /* @__PURE__ */ new Map();
72
+ let remaining = maxLeaves;
73
+ const replay = async (certificate) => {
74
+ _provenance3.assertCertificateTrust.call(void 0, certificate, trust);
75
+ const block = await runtime.reader.getBlock(BigInt(certificate.confirmedBlockNumber));
76
+ if (!block || block.hash.toLowerCase() !== _provenance3.word.call(void 0, certificate.confirmedBlockHash).toLowerCase() || await runtime.reader.getChainId() !== plan.context.chainId)
77
+ throw Error("Provenance checkpoint canonical anchor mismatch");
78
+ const count = Number(BigInt(certificate.leafCount));
79
+ if (!Number.isSafeInteger(count) || count > remaining)
80
+ throw Error("Provenance replay leaf budget exceeded");
81
+ remaining -= count;
82
+ const tree = await source.syncRecognizedTree(
83
+ `${certificate.chainGeneration}:${certificate.rootSequence}`,
84
+ certificate,
85
+ { maxLeaves: Math.max(1, count) }
86
+ );
87
+ certificates.set(String(certificate.treeId), certificate);
88
+ for (let i = 0; i < plan.inputs.length; i++) {
89
+ if (matches.has(i)) continue;
90
+ const membership = await tree.membershipForCommitment(
91
+ trust,
92
+ plan.inputs[i].commitment
93
+ );
94
+ if (membership) matches.set(i, { certificate, membership });
95
+ }
96
+ };
97
+ await replay(latest.certificate);
98
+ if (matches.size !== plan.inputs.length) {
99
+ const newest = /* @__PURE__ */ new Map();
100
+ let cursor, complete = false;
101
+ for (let page = 0; page < maxRootPages; page++) {
102
+ const result = await source.getRoots(
103
+ cursor ? { cursor, limit: 200 } : { after: "0", limit: 200 }
104
+ );
105
+ for (const certificate of result.items) {
106
+ const previous = newest.get(String(certificate.treeId));
107
+ if (!previous || BigInt(previous.rootSequence) < BigInt(certificate.rootSequence))
108
+ newest.set(String(certificate.treeId), certificate);
109
+ }
110
+ if (!result.nextCursor) {
111
+ complete = true;
112
+ break;
113
+ }
114
+ const next = String(result.nextCursor);
115
+ if (next === cursor) throw Error("Provenance root cursor did not advance");
116
+ cursor = next;
117
+ }
118
+ if (!complete) throw Error("Provenance root replay page budget exceeded");
119
+ for (const certificate of newest.values()) {
120
+ if (certificates.has(String(certificate.treeId))) continue;
121
+ const current = await source.getRoot(
122
+ `${certificate.chainGeneration}:${certificate.rootSequence}`
123
+ );
124
+ if (current.allowedForNewProof !== true) continue;
125
+ await replay(certificate);
126
+ if (matches.size === plan.inputs.length) break;
127
+ }
128
+ }
129
+ if (matches.size !== plan.inputs.length) throw Error("Prepared Note is not recognized");
130
+ const used = [
131
+ ...new Map(
132
+ [...matches.values()].map((m) => [String(m.certificate.treeId), m.certificate])
133
+ ).values()
134
+ ].sort((a, b) => BigInt(a.treeId) < BigInt(b.treeId) ? -1 : 1);
135
+ const inputs = openings.map((opening, i) => {
136
+ const match = matches.get(i);
137
+ return {
138
+ ...opening,
139
+ sourceIndex: used.findIndex(
140
+ (c) => BigInt(c.treeId) === BigInt(match.certificate.treeId)
141
+ ),
142
+ leafIndex: match.membership.leafIndex,
143
+ path: match.membership.path
144
+ };
145
+ });
146
+ const capacity = _provenance3.CAPACITIES.find((k) => k >= inputs.length);
147
+ if (!capacity) throw Error("Provenance input capacity exceeded");
148
+ const sidecar = await _provenancewitness.exportSidecar.call(void 0,
149
+ {
150
+ ...trust,
151
+ capacity,
152
+ tokenAddress: plan.context.tokenAddress,
153
+ operationDigest: digest,
154
+ inputs,
155
+ sources: used.map((c) => ({ treeId: c.treeId, root: c.root, leafCount: c.leafCount }))
156
+ },
157
+ used,
158
+ trust,
159
+ manifest,
160
+ prover,
161
+ 0
162
+ );
163
+ return { operationDigest: digest, sidecars: [sidecar] };
164
+ }
165
+ async function provePreparedProvenance(saved, runtime, capability, reprove = false) {
166
+ if (!saved.call || !saved.proof || saved.plan.kind !== "transfer" || !saved.plan.inputs.length)
167
+ throw Error("Ready transaction with private Note inputs required");
168
+ const provider = runtime.options.prover;
169
+ const active = await _asyncNullishCoalesce(await _asyncNullishCoalesce(capability, async () => ( runtime.options.provenance)), async () => ( (_optionalChain([provider, 'optionalAccess', _ => _.getProvenanceCapability]) ? {
170
+ ...await provider.getProvenanceCapability(),
171
+ client: await _asyncNullishCoalesce(runtime.options.provenanceClient, async () => ( await officialProvenance.get(saved.plan.context)))
172
+ } : void 0)));
173
+ if (!active) throw Error("Local Provenance capability required");
174
+ if (saved.provenance && !reprove)
175
+ return _chunkMI4IP4ZDcjs.validateProvenanceProof.call(void 0, structuredClone(saved.provenance), active.client.trust);
176
+ const localRuntime = { ...runtime, options: { ...runtime.options, provenance: active } };
177
+ const evidence = await prepareProvenance(saved.plan, localRuntime);
178
+ const packet = {
179
+ format: "invisi-provenance-submission-v1",
180
+ data: saved.call.data,
181
+ context: {
182
+ chainId: saved.plan.context.chainId.toString(),
183
+ protocolAddress: saved.plan.context.protocolAddress,
184
+ tokenAddress: saved.plan.context.tokenAddress
185
+ },
186
+ mainCircuitCapacity: saved.plan.capacity,
187
+ publicInputs: [..._chunkHCB7RQ3Scjs.statement.call(void 0, saved.plan).expectedPublicInputs],
188
+ ...evidence
189
+ };
190
+ return _chunkMI4IP4ZDcjs.validateProvenanceProof.call(void 0, packet, active.client.trust);
191
+ }
192
+ function validateBroadcastEnvelope(saved, client) {
193
+ if (!saved.broadcasterQuote || !saved.broadcasterBinding || !saved.call)
194
+ throw Error("Prepared broadcaster quote and ready call required");
195
+ if (JSON.stringify(saved.broadcasterBinding.configuration) !== JSON.stringify(client.configuration) || saved.broadcasterBinding.intentHash !== _chunk3KTQQZOWcjs.broadcasterRequestHash.call(void 0, saved.call.data))
196
+ throw Error("Prepared broadcaster context changed");
197
+ const context = saved.plan.context;
198
+ if (BigInt(saved.call.to) !== BigInt(context.protocolAddress) || saved.call.value !== 0n || _optionalChain([saved, 'access', _2 => _2.broadcasterQuote, 'access', _3 => _3.context, 'optionalAccess', _4 => _4.chainId]) !== context.chainId || BigInt(saved.broadcasterQuote.context.protocol) !== BigInt(context.protocolAddress))
199
+ throw Error("Prepared broadcaster deployment changed");
200
+ }
201
+ async function validatePreparedBroadcast(saved, client, runtime) {
202
+ validateBroadcastEnvelope(saved, client);
203
+ if (saved.broadcasterQuote.provenanceRequired && saved.plan.inputs.length) {
204
+ const source = saved.provenance;
205
+ if (!source || source.sidecars.length !== 1)
206
+ throw Error("Prepared Provenance evidence required");
207
+ const digest = _provenance3.operationDigest.call(void 0, {
208
+ ...saved.plan.context,
209
+ mainCircuitCapacity: saved.plan.capacity,
210
+ publicInputs: _chunkHCB7RQ3Scjs.statement.call(void 0, saved.plan).expectedPublicInputs
211
+ });
212
+ if (source.operationDigest !== digest || source.data !== saved.call.data)
213
+ throw Error("Prepared Provenance statement changed");
214
+ const sidecar = source.sidecars[0];
215
+ const pi = sidecar.proofBundle.publicInputs;
216
+ if (sidecar.operationIndex !== "0" || _provenance3.word.call(void 0, BigInt(pi[7]) << 128n | BigInt(pi[8])) !== digest || BigInt(pi[2]) !== BigInt(saved.plan.context.tokenAddress) || BigInt(pi[6]) !== BigInt(saved.plan.inputs.length) || BigInt(pi[9]) !== await _provenance3.inputDigest.call(void 0, saved.plan.params.nullifiers))
217
+ throw Error("Prepared Provenance evidence binding mismatch");
218
+ if (runtime.options.provenance)
219
+ await _provenance3.validateProofBundle.call(void 0, sidecar.proofBundle, runtime.options.provenance.client.trust);
220
+ } else if (saved.provenance) throw Error("Unexpected Prepared Provenance evidence");
221
+ }
222
+ var officialProvenance = new (0, _provenance.OfficialProvenanceClients)();
223
+
224
+
225
+
226
+
227
+
228
+
229
+ exports.prepareProvenance = prepareProvenance; exports.provePreparedProvenance = provePreparedProvenance; exports.validateBroadcastEnvelope = validateBroadcastEnvelope; exports.validatePreparedBroadcast = validatePreparedBroadcast;
230
+ //# sourceMappingURL=chunk-J6TZZVAM.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/wx/Workspace/invisi-lab/invisi-sdk-ts/packages/sdk/dist/chunk-J6TZZVAM.cjs","../src/broadcaster/provenance-preparation.ts"],"names":[],"mappings":"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","file":"/Users/wx/Workspace/invisi-lab/invisi-sdk-ts/packages/sdk/dist/chunk-J6TZZVAM.cjs","sourcesContent":[null,"import { OfficialProvenanceClients } from \"@invisi-labs/rpc/provenance\";\nimport { validateProvenanceProof, type ProvenanceProof } from \"../provenance/proof-record\";\nimport {\n CAPACITIES,\n noteOpening,\n operationDigest,\n word,\n assertCertificateTrust,\n validateProofBundle,\n inputDigest,\n type ManifestIdentity,\n type ProofSidecar,\n type RootCertificate,\n} from \"@invisi-labs/protocol/provenance\";\nimport {\n exportSidecar,\n type OfflineProver,\n type WitnessInput,\n} from \"@invisi-labs/prover/provenance-witness\";\nimport { type ProvenanceClient } from \"@invisi-labs/rpc/provenance\";\nimport type {\n OperationPlan,\n TransactionRuntime,\n SavedOperation,\n} from \"../transactions/operation-types\";\nimport { statement } from \"../transactions/signing/statement\";\nimport { broadcasterRequestHash, type BroadcasterClient } from \"./index\";\n\nexport interface PreparedProvenanceCapability {\n client: ProvenanceClient;\n manifest: ManifestIdentity;\n prover: OfflineProver;\n maxRootPages?: number;\n maxLeaves?: number;\n}\nfunction requireProvenanceCapability(plan: OperationPlan, runtime: TransactionRuntime) {\n const cap = runtime.options.provenance;\n if (!cap) throw Error(\"Provenance capability required for private inputs\");\n const trust = cap.client.trust;\n if (\n BigInt(trust.chainId) !== plan.context.chainId ||\n BigInt(trust.protocolAddress) !== BigInt(plan.context.protocolAddress) ||\n cap.manifest.sha256 !== trust.manifestSha256\n )\n throw Error(\"Provenance deployment or manifest mismatch\");\n}\nexport async function prepareProvenance(\n plan: OperationPlan,\n runtime: TransactionRuntime\n): Promise<{ operationDigest: string; sidecars: ProofSidecar[] }> {\n requireProvenanceCapability(plan, runtime);\n if (!plan.inputs.length) throw Error(\"No private Note inputs require a Provenance proof\");\n const {\n client: source,\n manifest,\n prover,\n maxRootPages = 10,\n maxLeaves = 100000,\n } = runtime!.options.provenance!;\n if (\n !Number.isSafeInteger(maxRootPages) ||\n maxRootPages < 1 ||\n maxRootPages > 100 ||\n !Number.isSafeInteger(maxLeaves) ||\n maxLeaves < 1\n )\n throw Error(\"Invalid Provenance replay budget\");\n if (!plan.params || !plan.capacity || plan.params.nullifiers.length !== plan.inputs.length)\n throw Error(\"Private transact statement required\");\n const trust = source.trust;\n const openings = await Promise.all(\n plan.inputs.map(async (input, i) => {\n const opening = {\n owner: input.note.ownerAddress,\n nonce: input.note.nonce,\n amount: input.note.amount,\n };\n const computed = await noteOpening({ ...plan.context, ...opening });\n if (\n computed.commitment !== BigInt(input.commitment) ||\n computed.nullifier !== BigInt(plan.params!.nullifiers[i]!)\n )\n throw Error(\"Prepared Note opening or nullifier mismatch\");\n return opening;\n })\n );\n const digest = operationDigest({\n ...plan.context,\n mainCircuitCapacity: plan.capacity,\n publicInputs: statement(plan).expectedPublicInputs,\n });\n const status = await source.getStatus();\n const rootId = `${BigInt(trust.chainGeneration)}:${BigInt(String(status.checkpointSequence))}`;\n const latest = await source.getRoot(rootId);\n if (!latest.certificate || latest.allowedForNewProof !== true)\n throw Error(\"No current recognized root\");\n const certificates = new Map<string, RootCertificate>();\n const matches = new Map<\n number,\n { certificate: RootCertificate; membership: { leafIndex: number; path: bigint[] } }\n >();\n let remaining = maxLeaves;\n const replay = async (certificate: RootCertificate) => {\n assertCertificateTrust(certificate, trust);\n const block = await runtime!.reader.getBlock(BigInt(certificate.confirmedBlockNumber));\n if (\n !block ||\n block.hash.toLowerCase() !== word(certificate.confirmedBlockHash).toLowerCase() ||\n (await runtime!.reader.getChainId()) !== plan.context.chainId\n )\n throw Error(\"Provenance checkpoint canonical anchor mismatch\");\n const count = Number(BigInt(certificate.leafCount));\n if (!Number.isSafeInteger(count) || count > remaining)\n throw Error(\"Provenance replay leaf budget exceeded\");\n remaining -= count;\n const tree = await source.syncRecognizedTree(\n `${certificate.chainGeneration}:${certificate.rootSequence}`,\n certificate,\n { maxLeaves: Math.max(1, count) }\n );\n certificates.set(String(certificate.treeId), certificate);\n for (let i = 0; i < plan.inputs.length; i++) {\n if (matches.has(i)) continue;\n const membership = await tree.membershipForCommitment(\n trust,\n plan.inputs[i]!.commitment\n );\n if (membership) matches.set(i, { certificate, membership });\n }\n };\n await replay(latest.certificate as RootCertificate);\n if (matches.size !== plan.inputs.length) {\n const newest = new Map<string, RootCertificate>();\n let cursor: string | undefined,\n complete = false;\n for (let page = 0; page < maxRootPages; page++) {\n const result = await source.getRoots(\n cursor ? { cursor, limit: 200 } : { after: \"0\", limit: 200 }\n );\n for (const certificate of result.items as RootCertificate[]) {\n const previous = newest.get(String(certificate.treeId));\n if (!previous || BigInt(previous.rootSequence) < BigInt(certificate.rootSequence))\n newest.set(String(certificate.treeId), certificate);\n }\n if (!result.nextCursor) {\n complete = true;\n break;\n }\n const next = String(result.nextCursor);\n if (next === cursor) throw Error(\"Provenance root cursor did not advance\");\n cursor = next;\n }\n if (!complete) throw Error(\"Provenance root replay page budget exceeded\");\n for (const certificate of newest.values()) {\n if (certificates.has(String(certificate.treeId))) continue;\n const current = await source.getRoot(\n `${certificate.chainGeneration}:${certificate.rootSequence}`\n );\n if (current.allowedForNewProof !== true) continue;\n await replay(certificate);\n if (matches.size === plan.inputs.length) break;\n }\n }\n if (matches.size !== plan.inputs.length) throw Error(\"Prepared Note is not recognized\");\n const used = [\n ...new Map(\n [...matches.values()].map((m) => [String(m.certificate.treeId), m.certificate])\n ).values(),\n ].sort((a, b) => (BigInt(a.treeId) < BigInt(b.treeId) ? -1 : 1));\n const inputs: WitnessInput[] = openings.map((opening, i) => {\n const match = matches.get(i)!;\n return {\n ...opening,\n sourceIndex: used.findIndex(\n (c) => BigInt(c.treeId) === BigInt(match.certificate.treeId)\n ),\n leafIndex: match.membership.leafIndex,\n path: match.membership.path,\n };\n });\n const capacity = CAPACITIES.find((k) => k >= inputs.length);\n if (!capacity) throw Error(\"Provenance input capacity exceeded\");\n const sidecar = await exportSidecar(\n {\n ...trust,\n capacity,\n tokenAddress: plan.context.tokenAddress,\n operationDigest: digest,\n inputs,\n sources: used.map((c) => ({ treeId: c.treeId, root: c.root, leafCount: c.leafCount })),\n },\n used,\n trust,\n manifest,\n prover,\n 0\n );\n return { operationDigest: digest, sidecars: [sidecar] };\n}\nexport async function provePreparedProvenance(\n saved: SavedOperation,\n runtime: TransactionRuntime,\n capability?: PreparedProvenanceCapability,\n reprove = false\n): Promise<ProvenanceProof> {\n if (!saved.call || !saved.proof || saved.plan.kind !== \"transfer\" || !saved.plan.inputs.length)\n throw Error(\"Ready transaction with private Note inputs required\");\n const provider = runtime.options.prover as typeof runtime.options.prover &\n Partial<import(\"@invisi-labs/prover/provenance-witness\").ProvenanceProvider>;\n const active =\n capability ??\n runtime.options.provenance ??\n (provider?.getProvenanceCapability\n ? {\n ...(await provider.getProvenanceCapability()),\n client:\n runtime.options.provenanceClient ??\n (await officialProvenance.get(saved.plan.context)),\n }\n : undefined);\n if (!active) throw Error(\"Local Provenance capability required\");\n if (saved.provenance && !reprove)\n return validateProvenanceProof(structuredClone(saved.provenance), active.client.trust);\n const localRuntime = { ...runtime, options: { ...runtime.options, provenance: active } };\n const evidence = await prepareProvenance(saved.plan, localRuntime);\n const packet: ProvenanceProof = {\n format: \"invisi-provenance-submission-v1\",\n data: saved.call.data,\n context: {\n chainId: saved.plan.context.chainId.toString(),\n protocolAddress: saved.plan.context.protocolAddress,\n tokenAddress: saved.plan.context.tokenAddress,\n },\n mainCircuitCapacity: saved.plan.capacity!,\n publicInputs: [...statement(saved.plan).expectedPublicInputs],\n ...evidence,\n };\n return validateProvenanceProof(packet, active.client.trust);\n}\nexport function validateBroadcastEnvelope(saved: SavedOperation, client: BroadcasterClient) {\n if (!saved.broadcasterQuote || !saved.broadcasterBinding || !saved.call)\n throw Error(\"Prepared broadcaster quote and ready call required\");\n if (\n JSON.stringify(saved.broadcasterBinding.configuration) !==\n JSON.stringify(client.configuration) ||\n saved.broadcasterBinding.intentHash !== broadcasterRequestHash(saved.call.data)\n )\n throw Error(\"Prepared broadcaster context changed\");\n const context = saved.plan.context;\n if (\n BigInt(saved.call.to) !== BigInt(context.protocolAddress) ||\n saved.call.value !== 0n ||\n saved.broadcasterQuote.context?.chainId !== context.chainId ||\n BigInt(saved.broadcasterQuote.context.protocol) !== BigInt(context.protocolAddress)\n )\n throw Error(\"Prepared broadcaster deployment changed\");\n}\nexport async function validatePreparedBroadcast(\n saved: SavedOperation,\n client: BroadcasterClient,\n runtime: TransactionRuntime\n) {\n validateBroadcastEnvelope(saved, client);\n if (saved.broadcasterQuote!.provenanceRequired && saved.plan.inputs.length) {\n const source = saved.provenance;\n if (!source || source.sidecars.length !== 1)\n throw Error(\"Prepared Provenance evidence required\");\n const digest = operationDigest({\n ...saved.plan.context,\n mainCircuitCapacity: saved.plan.capacity!,\n publicInputs: statement(saved.plan).expectedPublicInputs,\n });\n if (source.operationDigest !== digest || source.data !== saved.call!.data)\n throw Error(\"Prepared Provenance statement changed\");\n const sidecar = source.sidecars[0]!;\n const pi = sidecar.proofBundle.publicInputs;\n if (\n sidecar.operationIndex !== \"0\" ||\n word((BigInt(pi[7]!) << 128n) | BigInt(pi[8]!)) !== digest ||\n BigInt(pi[2]!) !== BigInt(saved.plan.context.tokenAddress) ||\n BigInt(pi[6]!) !== BigInt(saved.plan.inputs.length) ||\n BigInt(pi[9]!) !== (await inputDigest(saved.plan.params!.nullifiers))\n )\n throw Error(\"Prepared Provenance evidence binding mismatch\");\n if (runtime.options.provenance)\n await validateProofBundle(sidecar.proofBundle, runtime.options.provenance.client.trust);\n } else if (saved.provenance) throw Error(\"Unexpected Prepared Provenance evidence\");\n}\n\nconst officialProvenance = new OfficialProvenanceClients();\n"]}