@invisi-labs/sdk 1.1.6 → 1.1.7
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/{NoteOutput-DRkVnwlx.d.cts → broadcaster-preparation-DMxxZ_1Q.d.cts} +309 -120
- package/dist/{NoteOutput-DpDC6T2O.d.ts → broadcaster-preparation-DMxxZ_1Q.d.ts} +309 -120
- package/dist/broadcaster-preparation-RMWQFYNL.js +11 -0
- package/dist/broadcaster-preparation-UGOTO4SX.cjs +11 -0
- package/dist/broadcaster-preparation-UGOTO4SX.cjs.map +1 -0
- package/dist/chunk-7F7ZZW3L.cjs +374 -0
- package/dist/chunk-7F7ZZW3L.cjs.map +1 -0
- package/dist/{chunk-4SD3MW6N.js → chunk-EHP5TBC6.js} +1347 -2493
- package/dist/chunk-EHP5TBC6.js.map +1 -0
- package/dist/{broadcaster-preparation-QVL62KM6.js → chunk-GTPUYPQL.js} +6 -6
- package/dist/chunk-GTPUYPQL.js.map +1 -0
- package/dist/{chunk-FL4TIGWW.js → chunk-ITTGBIG2.js} +617 -521
- package/dist/chunk-ITTGBIG2.js.map +1 -0
- package/dist/chunk-J2JH6HIG.cjs +1877 -0
- package/dist/chunk-J2JH6HIG.cjs.map +1 -0
- package/dist/chunk-LOU7AP2B.cjs +128 -0
- package/dist/chunk-LOU7AP2B.cjs.map +1 -0
- package/dist/chunk-RHNIHI4P.cjs +3565 -0
- package/dist/chunk-RHNIHI4P.cjs.map +1 -0
- package/dist/{chunk-QC6TQR3R.js → chunk-XHKQ2BO2.js} +12 -12
- package/dist/chunk-XHKQ2BO2.js.map +1 -0
- package/dist/ethers.cjs +11 -385
- package/dist/ethers.cjs.map +1 -1
- package/dist/ethers.d.cts +3 -4
- package/dist/ethers.d.ts +3 -4
- package/dist/ethers.js +1 -1
- package/dist/index.cjs +451 -7845
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +72 -702
- package/dist/index.d.ts +72 -702
- package/dist/index.js +374 -862
- package/dist/index.js.map +1 -1
- package/dist/receipt-logs-CvC951p7.d.cts +318 -0
- package/dist/receipt-logs-m0-bhaxW.d.ts +318 -0
- package/dist/session-support.cjs +168 -0
- package/dist/session-support.cjs.map +1 -0
- package/dist/session-support.d.cts +252 -0
- package/dist/session-support.d.ts +252 -0
- package/dist/session-support.js +168 -0
- package/dist/session-support.js.map +1 -0
- package/package.json +10 -20
- package/dist/broadcaster-preparation-QVL62KM6.js.map +0 -1
- package/dist/chunk-4SD3MW6N.js.map +0 -1
- package/dist/chunk-FL4TIGWW.js.map +0 -1
- package/dist/chunk-QC6TQR3R.js.map +0 -1
- package/dist/indexeddb.cjs +0 -6878
- package/dist/indexeddb.cjs.map +0 -1
- package/dist/indexeddb.d.cts +0 -20
- package/dist/indexeddb.d.ts +0 -20
- package/dist/indexeddb.js +0 -71
- package/dist/indexeddb.js.map +0 -1
- package/dist/memory.cjs +0 -6886
- package/dist/memory.cjs.map +0 -1
- package/dist/memory.d.cts +0 -12
- package/dist/memory.d.ts +0 -12
- package/dist/memory.js +0 -11
- package/dist/sqlite.cjs +0 -6862
- package/dist/sqlite.cjs.map +0 -1
- package/dist/sqlite.d.cts +0 -28
- package/dist/sqlite.d.ts +0 -28
- package/dist/sqlite.js +0 -55
- package/dist/sqlite.js.map +0 -1
- package/dist/state-C4HZFotm.d.cts +0 -78
- package/dist/state-C4HZFotm.d.ts +0 -78
- package/dist/store-8aBhnbGr.d.ts +0 -42
- package/dist/store-YrbXb6CY.d.cts +0 -42
- /package/dist/{memory.js.map → broadcaster-preparation-RMWQFYNL.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,807 +1,184 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
AddressRegistry,
|
|
3
|
+
BroadcasterClient,
|
|
4
|
+
BroadcasterRpcError,
|
|
5
|
+
Invisi,
|
|
6
|
+
PreparedTransaction,
|
|
7
|
+
TransactionOutput,
|
|
8
|
+
broadcasterQuoteDomain,
|
|
9
|
+
broadcasterQuoteTypes,
|
|
10
|
+
broadcasterRequestHash,
|
|
11
|
+
broadcasterTransactInterface,
|
|
12
|
+
decodeBroadcasterIntent,
|
|
8
13
|
decryptCandidates,
|
|
9
14
|
defineGasBenchmarks,
|
|
10
|
-
|
|
11
|
-
estimateGasReference,
|
|
12
|
-
fundingSigningRequest,
|
|
13
|
-
operationPreview,
|
|
14
|
-
proveOperation,
|
|
15
|
+
extractDeliveryCandidates,
|
|
15
16
|
readProtocolLogs,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
walletSigningRequest
|
|
19
|
-
} from "./chunk-4SD3MW6N.js";
|
|
17
|
+
verifyBroadcasterQuote
|
|
18
|
+
} from "./chunk-EHP5TBC6.js";
|
|
20
19
|
import {
|
|
21
20
|
InvisiError,
|
|
22
21
|
NoteOutput,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
prepareWithErrors,
|
|
29
|
-
publicProof,
|
|
30
|
-
requiresAuthorization,
|
|
31
|
-
statement,
|
|
32
|
-
walletBalance
|
|
33
|
-
} from "./chunk-FL4TIGWW.js";
|
|
22
|
+
decodePaymentNote,
|
|
23
|
+
decodePaymentRequest,
|
|
24
|
+
encodePaymentNote,
|
|
25
|
+
encodePaymentRequest
|
|
26
|
+
} from "./chunk-ITTGBIG2.js";
|
|
34
27
|
import {
|
|
35
|
-
EthersChainReader
|
|
36
|
-
|
|
37
|
-
} from "./chunk-QC6TQR3R.js";
|
|
28
|
+
EthersChainReader
|
|
29
|
+
} from "./chunk-XHKQ2BO2.js";
|
|
38
30
|
|
|
39
|
-
// src/
|
|
40
|
-
import {
|
|
31
|
+
// src/index.ts
|
|
32
|
+
import {
|
|
33
|
+
Detector,
|
|
34
|
+
Disclosure,
|
|
35
|
+
MAX_MEMO_BYTES,
|
|
36
|
+
MissingCapabilityError,
|
|
37
|
+
NullifierCapability,
|
|
38
|
+
PublicWallet,
|
|
39
|
+
ViewingCapability,
|
|
40
|
+
Wallet as Wallet2,
|
|
41
|
+
WalletAuthorization,
|
|
42
|
+
computeCreditNullifier,
|
|
43
|
+
creditPeriods,
|
|
44
|
+
creditV1,
|
|
45
|
+
decodeDeliveryHeader,
|
|
46
|
+
decodeMemoText,
|
|
47
|
+
encodeMemo,
|
|
48
|
+
fundsV1
|
|
49
|
+
} from "@invisi-labs/core";
|
|
50
|
+
import { RegistrationOperation } from "@invisi-labs/protocol";
|
|
41
51
|
|
|
42
|
-
// src/
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
function check(ok, message) {
|
|
46
|
-
if (!ok) throw new Error(message);
|
|
52
|
+
// src/disclosure/DisclosureVerifier.ts
|
|
53
|
+
function check(value, message) {
|
|
54
|
+
if (!value) throw new Error(message);
|
|
47
55
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
async withBroadcaster(client, options) {
|
|
74
|
-
this.current();
|
|
75
|
-
check(
|
|
76
|
-
this.status === "prepared" && this.#runtime.reprepare,
|
|
77
|
-
"broadcaster must attach to an unsigned prepared transaction"
|
|
78
|
-
);
|
|
79
|
-
const { prepareBroadcasterPlan } = await import("./broadcaster-preparation-QVL62KM6.js");
|
|
80
|
-
const selected = await prepareBroadcasterPlan(
|
|
81
|
-
this.#saved.plan,
|
|
82
|
-
this.#runtime.reprepare,
|
|
83
|
-
client,
|
|
84
|
-
options
|
|
85
|
-
);
|
|
86
|
-
return new _PreparedTransaction(
|
|
87
|
-
this.#runtime,
|
|
88
|
-
{ plan: selected.plan, broadcasterQuote: selected.quote, generation: 0 },
|
|
89
|
-
"prepared",
|
|
90
|
-
{ generation: 0, busy: false }
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
get id() {
|
|
94
|
-
return this.#saved.plan.id;
|
|
95
|
-
}
|
|
96
|
-
get kind() {
|
|
97
|
-
return this.#saved.plan.kind;
|
|
98
|
-
}
|
|
99
|
-
estimateGas() {
|
|
100
|
-
return estimateGasReference(
|
|
101
|
-
this.#saved.plan,
|
|
102
|
-
this.#runtime.options.protocol,
|
|
103
|
-
this.#runtime.options.gasBenchmarks
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
preview() {
|
|
107
|
-
return operationPreview(this.#saved.plan, this.status);
|
|
108
|
-
}
|
|
109
|
-
/** Obtain a firm quote before signing. This intent contains no private inputs or witness. */
|
|
110
|
-
async exportBroadcasterIntent() {
|
|
111
|
-
this.current();
|
|
112
|
-
check(
|
|
113
|
-
["prepared", "authorized"].includes(this.status),
|
|
114
|
-
"quote intent requires a prepared transaction"
|
|
115
|
-
);
|
|
116
|
-
return exportBroadcasterIntent(this.#saved.plan);
|
|
117
|
-
}
|
|
118
|
-
current() {
|
|
119
|
-
check(
|
|
120
|
-
!this.#lifecycle.busy && this.#lifecycle.generation === this.#saved.generation,
|
|
121
|
-
"stale transaction handle or active worker"
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
async stage(stage, allowed, work, signal) {
|
|
125
|
-
signal?.throwIfAborted();
|
|
126
|
-
this.current();
|
|
127
|
-
check(allowed.includes(this.status), `invalid transaction stage for ${stage}`);
|
|
128
|
-
this.#lifecycle.busy = true;
|
|
129
|
-
const saved = structuredClone(this.#saved);
|
|
130
|
-
try {
|
|
131
|
-
const next = await work(saved);
|
|
132
|
-
signal?.throwIfAborted();
|
|
133
|
-
saved.generation++;
|
|
134
|
-
this.#lifecycle.generation = saved.generation;
|
|
135
|
-
return new _PreparedTransaction(
|
|
136
|
-
this.#runtime,
|
|
137
|
-
saved,
|
|
138
|
-
next.status,
|
|
139
|
-
this.#lifecycle,
|
|
140
|
-
next.authorization ?? this.#authorization
|
|
141
|
-
);
|
|
142
|
-
} finally {
|
|
143
|
-
this.#lifecycle.busy = false;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
/** Public EIP-712 request; signing transport and key custody belong to the caller. */
|
|
147
|
-
async exportWalletAuthorization(options = {}) {
|
|
148
|
-
options.signal?.throwIfAborted();
|
|
149
|
-
this.current();
|
|
150
|
-
check(
|
|
151
|
-
requiresAuthorization(this.#saved.plan),
|
|
152
|
-
"operation does not require wallet authorization"
|
|
153
|
-
);
|
|
154
|
-
check(
|
|
155
|
-
["prepared", "authorized"].includes(this.status),
|
|
156
|
-
"operation is not awaiting wallet authorization"
|
|
157
|
-
);
|
|
158
|
-
return walletSigningRequest(this.#saved.plan);
|
|
159
|
-
}
|
|
160
|
-
/** Attach an external EOA signature, retaining its witness only at the private proving boundary. */
|
|
161
|
-
async withWalletSignature(signature, options = {}) {
|
|
162
|
-
options.signal?.throwIfAborted();
|
|
163
|
-
this.current();
|
|
164
|
-
check(
|
|
165
|
-
requiresAuthorization(this.#saved.plan),
|
|
166
|
-
"operation does not require wallet authorization"
|
|
167
|
-
);
|
|
56
|
+
function reference(value) {
|
|
57
|
+
check(/^0x[0-9a-fA-F]{64}$/.test(value.transactionHash), "invalid disclosure transaction hash");
|
|
58
|
+
check(
|
|
59
|
+
typeof value.treeId === "bigint" && value.treeId > 0n && value.treeId < 1n << 64n,
|
|
60
|
+
"invalid disclosure tree ID"
|
|
61
|
+
);
|
|
62
|
+
check(
|
|
63
|
+
Number.isSafeInteger(value.leafIndex) && value.leafIndex >= 0 && value.leafIndex < 65536,
|
|
64
|
+
"invalid disclosure leaf index"
|
|
65
|
+
);
|
|
66
|
+
check(["funds", "owner", "spender"].includes(value.role), "invalid disclosure reference role");
|
|
67
|
+
return {
|
|
68
|
+
transactionHash: value.transactionHash.toLowerCase(),
|
|
69
|
+
treeId: value.treeId,
|
|
70
|
+
leafIndex: value.leafIndex,
|
|
71
|
+
role: value.role
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
var DisclosureVerifier = class {
|
|
75
|
+
#protocol;
|
|
76
|
+
#reader;
|
|
77
|
+
#confirmations;
|
|
78
|
+
constructor(options) {
|
|
79
|
+
const confirmations = options.confirmations ?? 1;
|
|
168
80
|
check(
|
|
169
|
-
|
|
170
|
-
"
|
|
171
|
-
);
|
|
172
|
-
const authorization = await acceptWalletSignature(this.#saved.plan, signature);
|
|
173
|
-
return this.stage(
|
|
174
|
-
"wallet authorization",
|
|
175
|
-
["prepared", "authorized"],
|
|
176
|
-
async () => ({ status: "authorized", authorization }),
|
|
177
|
-
options.signal
|
|
81
|
+
Number.isSafeInteger(confirmations) && confirmations >= 1,
|
|
82
|
+
"invalid disclosure confirmations"
|
|
178
83
|
);
|
|
84
|
+
this.#protocol = options.protocol;
|
|
85
|
+
this.#reader = "provider" in options ? new EthersChainReader(options.provider) : options.reader;
|
|
86
|
+
this.#confirmations = BigInt(confirmations);
|
|
87
|
+
Object.freeze(this);
|
|
179
88
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
this.current();
|
|
89
|
+
async barrier(block) {
|
|
90
|
+
await this.#protocol.validateDeployment(this.#reader);
|
|
91
|
+
const canonical = await this.#reader.getBlock(block.number);
|
|
184
92
|
check(
|
|
185
|
-
|
|
186
|
-
"
|
|
93
|
+
canonical.number === block.number && canonical.hash.toLowerCase() === block.hash.toLowerCase(),
|
|
94
|
+
"disclosure canonical block changed; reorg verification required"
|
|
187
95
|
);
|
|
188
|
-
const
|
|
189
|
-
options.signal?.throwIfAborted();
|
|
190
|
-
this.current();
|
|
191
|
-
return request;
|
|
192
|
-
}
|
|
193
|
-
/** Verify an external signature against this handle's own frozen operation. */
|
|
194
|
-
async withFundingSignature(signature, options = {}) {
|
|
195
|
-
options.signal?.throwIfAborted();
|
|
196
|
-
this.current();
|
|
96
|
+
const head = await this.#reader.getLatestBlockNumber();
|
|
197
97
|
check(
|
|
198
|
-
|
|
199
|
-
"
|
|
98
|
+
head >= block.number && head - block.number + 1n >= this.#confirmations,
|
|
99
|
+
"insufficient disclosure confirmations"
|
|
200
100
|
);
|
|
201
|
-
const verified = await acceptFundingSignature(this.#saved, signature, this.#runtime);
|
|
202
|
-
return this.stage(
|
|
203
|
-
"funding authorization",
|
|
204
|
-
this.kind === "shield" ? ["prepared"] : ["proved"],
|
|
205
|
-
async (saved) => {
|
|
206
|
-
saved.plan.funding.signature = verified;
|
|
207
|
-
if (saved.plan.statement?.target !== "noir-recursive") {
|
|
208
|
-
saved.call = await this.encode(saved);
|
|
209
|
-
}
|
|
210
|
-
return { status: "ready" };
|
|
211
|
-
},
|
|
212
|
-
options.signal
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
async prove(backendOrOptions = {}, suppliedOptions = {}) {
|
|
216
|
-
const options = { ..."prove" in backendOrOptions ? suppliedOptions : backendOrOptions };
|
|
217
101
|
check(
|
|
218
|
-
|
|
219
|
-
"
|
|
102
|
+
await this.#reader.getChainId() === this.#protocol.context.chainId,
|
|
103
|
+
"disclosure chain changed during verification"
|
|
220
104
|
);
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
throw new MissingCapabilityError("prover");
|
|
232
|
-
}
|
|
233
|
-
return this.stage(
|
|
234
|
-
"proof",
|
|
235
|
-
requiresAuthorization(plan) ? ["authorized"] : ["prepared"],
|
|
236
|
-
async (saved) => {
|
|
237
|
-
const p = saved.plan;
|
|
238
|
-
saved.proof = await proveOperation(
|
|
239
|
-
this.#runtime.options.protocol,
|
|
240
|
-
p,
|
|
241
|
-
this.#authorization,
|
|
242
|
-
prover,
|
|
243
|
-
options
|
|
244
|
-
);
|
|
245
|
-
if (p.fundingMode === "signature") {
|
|
246
|
-
return { status: "proved" };
|
|
247
|
-
}
|
|
248
|
-
if (p.statement?.target !== "noir-recursive") {
|
|
249
|
-
saved.call = await this.encode(saved);
|
|
250
|
-
}
|
|
251
|
-
return { status: "ready" };
|
|
252
|
-
},
|
|
253
|
-
options.signal
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
encode(saved) {
|
|
257
|
-
return encodeOperation(saved);
|
|
258
|
-
}
|
|
259
|
-
/** Shield caller funding needs no wallet signing or proof; this step only encodes its frozen request. */
|
|
260
|
-
async ready() {
|
|
105
|
+
return head - block.number + 1n;
|
|
106
|
+
}
|
|
107
|
+
/** Resolve the exact inserted output and its delivery from a successful canonical receipt. */
|
|
108
|
+
async readOutput(value) {
|
|
109
|
+
const selected = reference(value);
|
|
110
|
+
await this.#protocol.validateDeployment(this.#reader);
|
|
111
|
+
const received = await this.#reader.getReceipt(selected.transactionHash);
|
|
112
|
+
check(received, "disclosure transaction receipt is unavailable");
|
|
113
|
+
const receipt = structuredClone(received);
|
|
114
|
+
check(receipt.status === "success", "disclosure requires a successful transaction receipt");
|
|
261
115
|
check(
|
|
262
|
-
|
|
263
|
-
"
|
|
116
|
+
receipt.transactionHash.toLowerCase() === selected.transactionHash,
|
|
117
|
+
"disclosure receipt transaction mismatch"
|
|
264
118
|
);
|
|
265
|
-
return this.stage("encoding", ["prepared"], async (saved) => {
|
|
266
|
-
saved.call = await this.encode(saved);
|
|
267
|
-
return { status: "ready" };
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
async exportTransaction() {
|
|
271
|
-
this.current();
|
|
272
119
|
check(
|
|
273
|
-
|
|
274
|
-
"
|
|
120
|
+
typeof receipt.block.number === "bigint" && receipt.block.number >= 0n && /^0x[0-9a-fA-F]{64}$/.test(receipt.block.hash),
|
|
121
|
+
"invalid disclosure receipt block"
|
|
275
122
|
);
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
this.current();
|
|
281
|
-
check(this.#saved.proof, "transaction has no proof");
|
|
282
|
-
return publicProof(this.#saved.proof);
|
|
283
|
-
}
|
|
284
|
-
exportAggregateMember() {
|
|
285
|
-
this.current();
|
|
286
|
-
const saved = this.#saved, plan = saved.plan;
|
|
287
|
-
check(
|
|
288
|
-
this.status === "ready" && plan.params && saved.proof && plan.statement?.target === "noir-recursive" && plan.statement.circuitName === "transact_user_slots14",
|
|
289
|
-
"ready recursive slots14 transaction required"
|
|
123
|
+
const { context } = this.#protocol;
|
|
124
|
+
const logs = readProtocolLogs(receipt, context.protocolAddress);
|
|
125
|
+
const candidates = extractDeliveryCandidates(logs, context, receipt.block.number).filter(
|
|
126
|
+
(candidate2) => candidate2.treeId === selected.treeId && candidate2.leafIndex === selected.leafIndex && candidate2.role === selected.role && candidate2.tokenAddress.toLowerCase() === context.tokenAddress.toLowerCase()
|
|
290
127
|
);
|
|
291
|
-
sameStatement(saved.proof, statement(plan));
|
|
292
128
|
check(
|
|
293
|
-
|
|
294
|
-
"
|
|
129
|
+
candidates.length === 1,
|
|
130
|
+
"disclosure output has no unique canonical insertion and delivery"
|
|
295
131
|
);
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
311
|
-
return this.toJSON();
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
// src/explicit-preparation.ts
|
|
316
|
-
function explicitPreparation(options, data, tokenAddress) {
|
|
317
|
-
if (!options.chainReader) throw new Error("chain reader required");
|
|
318
|
-
const inputs = structuredClone(data.inputs ?? []);
|
|
319
|
-
const credits = structuredClone(data.creditInputs ?? []);
|
|
320
|
-
const inventory = { notes: {}, credits: {}, reservations: {} };
|
|
321
|
-
const context = options.protocol.context;
|
|
322
|
-
function position(input) {
|
|
323
|
-
if (typeof input.treeId !== "bigint" || input.treeId < 0n || input.treeId >= 1n << 256n || !Number.isInteger(input.leafIndex) || input.leafIndex < 0 || input.leafIndex >= 65536)
|
|
324
|
-
throw new Error("invalid explicit input position");
|
|
325
|
-
}
|
|
326
|
-
for (const input of inputs) {
|
|
327
|
-
position(input);
|
|
328
|
-
positiveAmount(input.note.amount);
|
|
329
|
-
if (inventory.notes[input.commitment]) throw new Error("duplicate explicit note input");
|
|
330
|
-
if (input.note.chainId !== context.chainId || input.note.protocolAddress !== BigInt(context.protocolAddress) || input.note.ownerAddress !== options.wallet.ownerAddress)
|
|
331
|
-
throw new Error("explicit note identity or deployment mismatch");
|
|
332
|
-
inventory.notes[input.commitment] = { ...input, spent: "unspent" };
|
|
333
|
-
}
|
|
334
|
-
for (const input of credits) {
|
|
335
|
-
position(input);
|
|
336
|
-
if (input.role !== "owner" && input.role !== "spender")
|
|
337
|
-
throw new Error("invalid explicit Credit role");
|
|
338
|
-
const key = input.commitment + ":" + input.role;
|
|
339
|
-
if (inventory.credits[key]) throw new Error("duplicate explicit Credit input");
|
|
340
|
-
inventory.credits[key] = { ...input, spent: "unspent" };
|
|
341
|
-
}
|
|
342
|
-
const scope = {
|
|
343
|
-
...context,
|
|
344
|
-
namespace: "explicit",
|
|
345
|
-
ownerAddress: options.wallet.ownerAddress
|
|
346
|
-
};
|
|
347
|
-
const {
|
|
348
|
-
store: _store,
|
|
349
|
-
coinSelector: _selector,
|
|
350
|
-
authorization: _authorization,
|
|
351
|
-
viewing: _viewing,
|
|
352
|
-
signer: _signer,
|
|
353
|
-
fundingSigner: _fundingSigner,
|
|
354
|
-
...capabilities
|
|
355
|
-
} = options;
|
|
356
|
-
if (inputs.some((input) => input.note.tokenAddress !== BigInt(getAddress(tokenAddress))))
|
|
357
|
-
throw new Error("explicit note token mismatch");
|
|
358
|
-
const runtime = {
|
|
359
|
-
options: { ...capabilities, protocol: options.protocol.forToken(tokenAddress) },
|
|
360
|
-
reader: options.chainReader,
|
|
361
|
-
scope
|
|
362
|
-
};
|
|
363
|
-
const reprepare = (intent) => import("./broadcaster-preparation-QVL62KM6.js").then(
|
|
364
|
-
({ prepareIntent }) => prepareIntent(
|
|
365
|
-
{
|
|
366
|
-
...runtime,
|
|
367
|
-
explicitInputs: true,
|
|
368
|
-
...data.changeAddress ? { changeAddress: data.changeAddress } : {},
|
|
369
|
-
readInventory: async () => structuredClone(inventory),
|
|
370
|
-
complete: async (plan) => plan
|
|
371
|
-
},
|
|
372
|
-
intent
|
|
373
|
-
)
|
|
374
|
-
);
|
|
375
|
-
return new TransactionPreparation({
|
|
376
|
-
...runtime,
|
|
377
|
-
explicitInputs: true,
|
|
378
|
-
...data.changeAddress ? { changeAddress: data.changeAddress } : {},
|
|
379
|
-
readInventory: async () => structuredClone(inventory),
|
|
380
|
-
complete: async (plan) => PreparedTransaction.prepare({ ...runtime, reprepare }, plan)
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// src/Invisi.ts
|
|
385
|
-
import { ProtocolRpcClient } from "@invisi-labs/rpc";
|
|
386
|
-
import { MissingCapabilityError as MissingCapabilityError2, PublicWallet } from "@invisi-labs/core";
|
|
387
|
-
|
|
388
|
-
// src/AddressRegistry.ts
|
|
389
|
-
import { AddressRegistry as Registry } from "@invisi-labs/protocol";
|
|
390
|
-
var AddressRegistry = class extends Registry {
|
|
391
|
-
prepareRegistration(options) {
|
|
392
|
-
return prepareWithErrors("prepareRegistration", async () => {
|
|
393
|
-
if ("provider" in options) {
|
|
394
|
-
const { provider, ...preparation } = options;
|
|
395
|
-
return super.prepareRegistration({
|
|
396
|
-
...preparation,
|
|
397
|
-
reader: new EthersChainReader(provider)
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
return super.prepareRegistration(options);
|
|
132
|
+
const candidate = candidates[0];
|
|
133
|
+
const confirmations = await this.barrier(receipt.block);
|
|
134
|
+
return Object.freeze({
|
|
135
|
+
reference: Object.freeze(selected),
|
|
136
|
+
block: Object.freeze({ ...receipt.block }),
|
|
137
|
+
confirmations,
|
|
138
|
+
output: Object.freeze({
|
|
139
|
+
chainId: context.chainId,
|
|
140
|
+
protocolAddress: BigInt(context.protocolAddress),
|
|
141
|
+
tokenAddress: BigInt(context.tokenAddress),
|
|
142
|
+
outputCommitment: candidate.commitment,
|
|
143
|
+
role: selected.role,
|
|
144
|
+
ciphertext: candidate.delivery.ciphertext
|
|
145
|
+
})
|
|
401
146
|
});
|
|
402
147
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
"SDK envelope versions are fixed; encode application payload bytes externally"
|
|
416
|
-
);
|
|
417
|
-
}
|
|
418
|
-
if ("signer" in options || "fundingSigner" in options) {
|
|
419
|
-
throw new Error(
|
|
420
|
-
"Invisi does not accept signer defaults; export a signing request and attach the external signature"
|
|
421
|
-
);
|
|
422
|
-
}
|
|
423
|
-
this.#options = {
|
|
424
|
-
...options,
|
|
425
|
-
...options.gasBenchmarks ? { gasBenchmarks: copyGasBenchmarks(options.gasBenchmarks) } : {}
|
|
426
|
-
};
|
|
427
|
-
Object.freeze(this);
|
|
428
|
-
}
|
|
429
|
-
async connect(options) {
|
|
430
|
-
return new WalletSession(await this.resolve(options));
|
|
431
|
-
}
|
|
432
|
-
async resolve(options) {
|
|
433
|
-
const allowed = [
|
|
434
|
-
"wallet",
|
|
435
|
-
"protocol",
|
|
436
|
-
"namespace",
|
|
437
|
-
"viewing",
|
|
438
|
-
"authorization",
|
|
439
|
-
"signer",
|
|
440
|
-
"fundingSigner"
|
|
441
|
-
];
|
|
442
|
-
for (const key of Object.keys(options)) {
|
|
443
|
-
if (!allowed.includes(key))
|
|
444
|
-
throw new Error(
|
|
445
|
-
`Unknown connection option: ${key}; configure infrastructure on Invisi`
|
|
446
|
-
);
|
|
447
|
-
}
|
|
448
|
-
const selected = { ...options };
|
|
449
|
-
const combined = { ...this.#options, ...selected };
|
|
450
|
-
const { provider, ...runtime } = combined;
|
|
451
|
-
const reader = combined.chainReader ?? (provider ? new EthersChainReader(provider) : void 0);
|
|
452
|
-
if (!reader) throw new MissingCapabilityError2("chain reader");
|
|
453
|
-
if (provider && (await provider.getNetwork()).chainId !== selected.protocol.context.chainId)
|
|
454
|
-
throw new Error("provider deployment chain mismatch");
|
|
455
|
-
await selected.protocol.validateDeployment(reader);
|
|
456
|
-
if (runtime.protocolRpc instanceof ProtocolRpcClient) {
|
|
457
|
-
runtime.protocolRpc = runtime.protocolRpc.withReader(reader);
|
|
458
|
-
}
|
|
459
|
-
const fundingVerifier = combined.fundingVerifier ?? (provider ? new EthersFundingVerifier(provider, selected.protocol.context.chainId) : void 0);
|
|
460
|
-
return configureRecipientInfrastructure({
|
|
461
|
-
...runtime,
|
|
462
|
-
...provider ? { provider } : {},
|
|
463
|
-
chainReader: reader,
|
|
464
|
-
...fundingVerifier ? { fundingVerifier } : {},
|
|
465
|
-
protocol: selected.protocol
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
/** Discover the selected chain's registry and prepare an independent signing request. */
|
|
469
|
-
async prepareRegistration(options) {
|
|
470
|
-
return prepareWithErrors("prepareRegistration", async () => {
|
|
471
|
-
for (const key of Object.keys(options)) {
|
|
472
|
-
if (!["wallet", "update", "deadline"].includes(key)) {
|
|
473
|
-
throw new Error(`Unknown registration option: ${key}`);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
this.assertPublicIdentity(options);
|
|
477
|
-
const selected = { ...options };
|
|
478
|
-
const { provider, protocolRpc } = this.#options;
|
|
479
|
-
if (!provider) throw new MissingCapabilityError2("ethers provider");
|
|
480
|
-
if (!(protocolRpc instanceof ProtocolRpcClient)) {
|
|
481
|
-
throw new MissingCapabilityError2("Protocol RPC deployment discovery");
|
|
482
|
-
}
|
|
483
|
-
const chainId = (await provider.getNetwork()).chainId;
|
|
484
|
-
const deployment = await protocolRpc.getDeployment(chainId);
|
|
485
|
-
if (!deployment.registry) {
|
|
486
|
-
throw new MissingCapabilityError2("receiving-key registry deployment");
|
|
487
|
-
}
|
|
488
|
-
const registry = new AddressRegistry(
|
|
489
|
-
{ chainId, registryAddress: deployment.registry.address },
|
|
490
|
-
{ expectedRuntimeCodeHash: deployment.registry.runtimeCodeHash }
|
|
491
|
-
);
|
|
492
|
-
return registry.prepareRegistration({ ...selected, provider });
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
assertPublicIdentity(options) {
|
|
496
|
-
const { wallet } = options;
|
|
497
|
-
if (!(wallet instanceof PublicWallet) || ["getViewer", "getDetector", "exportAuthorization"].some((key) => key in wallet)) {
|
|
498
|
-
throw new Error(
|
|
499
|
-
"Independent preparation requires a PublicWallet without private capabilities"
|
|
500
|
-
);
|
|
501
|
-
}
|
|
502
|
-
for (const key of ["authorization", "signer", "fundingSigner", "viewing"]) {
|
|
503
|
-
if (key in options)
|
|
504
|
-
throw new Error(`Independent preparation does not accept capability: ${key}`);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
resolveExplicit(options) {
|
|
508
|
-
this.assertPublicIdentity(options);
|
|
509
|
-
return this.resolve({ wallet: options.wallet, protocol: options.protocol });
|
|
510
|
-
}
|
|
511
|
-
async prepareTransfer(options) {
|
|
512
|
-
return prepareWithErrors("prepareTransfer", async () => {
|
|
513
|
-
const { wallet, protocol, ...input } = options;
|
|
514
|
-
const request = structuredClone(input);
|
|
515
|
-
const runtime = await this.resolveExplicit(options);
|
|
516
|
-
const preparation = explicitPreparation(runtime, request, request.tokenAddress);
|
|
517
|
-
return preparation.prepareTransfer(request);
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
async prepareShield(options) {
|
|
521
|
-
return prepareWithErrors("prepareShield", async () => {
|
|
522
|
-
const { wallet, protocol, ...input } = options;
|
|
523
|
-
const request = structuredClone(input);
|
|
524
|
-
const runtime = await this.resolveExplicit(options);
|
|
525
|
-
const preparation = explicitPreparation(runtime, {}, request.tokenAddress);
|
|
526
|
-
return preparation.prepareShield(request);
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
async prepareCreateCredit(options) {
|
|
530
|
-
return prepareWithErrors("prepareCreateCredit", async () => {
|
|
531
|
-
const { wallet, protocol, ...input } = options;
|
|
532
|
-
const request = structuredClone(input);
|
|
533
|
-
const runtime = await this.resolveExplicit(options);
|
|
534
|
-
const preparation = explicitPreparation(runtime, request, request.tokenAddress);
|
|
535
|
-
return preparation.prepareCreateCredit(request);
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
async prepareDrawCredit(options) {
|
|
539
|
-
return prepareWithErrors("prepareDrawCredit", async () => {
|
|
540
|
-
const { wallet, protocol, ...input } = options;
|
|
541
|
-
const request = structuredClone(input);
|
|
542
|
-
const runtime = await this.resolveExplicit(options);
|
|
543
|
-
const preparation = explicitPreparation(runtime, request, request.tokenAddress);
|
|
544
|
-
return preparation.prepareDrawCredit(request);
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
async prepareTopUpCredit(options) {
|
|
548
|
-
return prepareWithErrors("prepareTopUpCredit", async () => {
|
|
549
|
-
const { wallet, protocol, ...input } = options;
|
|
550
|
-
const request = structuredClone(input);
|
|
551
|
-
const runtime = await this.resolveExplicit(options);
|
|
552
|
-
const preparation = explicitPreparation(runtime, request, request.tokenAddress);
|
|
553
|
-
return preparation.prepareTopUpCredit(request);
|
|
554
|
-
});
|
|
555
|
-
}
|
|
556
|
-
async prepareCancelCredit(options) {
|
|
557
|
-
return prepareWithErrors("prepareCancelCredit", async () => {
|
|
558
|
-
const { wallet, protocol, ...input } = options;
|
|
559
|
-
const request = structuredClone(input);
|
|
560
|
-
const runtime = await this.resolveExplicit(options);
|
|
561
|
-
const preparation = explicitPreparation(runtime, request, request.tokenAddress);
|
|
562
|
-
return preparation.prepareCancelCredit(request);
|
|
148
|
+
async verify(disclosure, value) {
|
|
149
|
+
const evidence = await this.readOutput(value);
|
|
150
|
+
const result = await disclosure.verify(evidence.output);
|
|
151
|
+
const confirmations = await this.barrier(evidence.block);
|
|
152
|
+
return Object.freeze({
|
|
153
|
+
result: Object.freeze(result),
|
|
154
|
+
block: evidence.block,
|
|
155
|
+
confirmations,
|
|
156
|
+
output: Object.freeze({
|
|
157
|
+
...evidence.reference,
|
|
158
|
+
commitment: evidence.output.outputCommitment
|
|
159
|
+
})
|
|
563
160
|
});
|
|
564
161
|
}
|
|
565
162
|
toJSON() {
|
|
566
|
-
return {
|
|
163
|
+
return { disclosureVerifier: true, confirmations: this.#confirmations.toString() };
|
|
567
164
|
}
|
|
568
165
|
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
569
166
|
return this.toJSON();
|
|
570
167
|
}
|
|
571
168
|
};
|
|
572
169
|
|
|
573
|
-
// src/
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
decodeDeliveryHeader,
|
|
578
|
-
Wallet,
|
|
579
|
-
PublicWallet as PublicWallet2,
|
|
580
|
-
ViewingCapability,
|
|
581
|
-
Detector,
|
|
582
|
-
NullifierCapability,
|
|
583
|
-
WalletAuthorization,
|
|
584
|
-
MissingCapabilityError as MissingCapabilityError3,
|
|
585
|
-
Disclosure,
|
|
586
|
-
encodeMemo,
|
|
587
|
-
decodeMemoText,
|
|
588
|
-
MAX_MEMO_BYTES,
|
|
589
|
-
computeCreditNullifier,
|
|
590
|
-
creditPeriods
|
|
591
|
-
} from "@invisi-labs/core";
|
|
592
|
-
import { RegistrationOperation } from "@invisi-labs/protocol";
|
|
593
|
-
|
|
594
|
-
// src/Protocol.ts
|
|
595
|
-
import { Protocol as BaseProtocol } from "@invisi-labs/protocol";
|
|
596
|
-
import { getAddress as getAddress3 } from "ethers";
|
|
597
|
-
|
|
598
|
-
// src/broadcaster/index.ts
|
|
599
|
-
import { AbiCoder, getAddress as getAddress2, Interface, keccak256, verifyTypedData } from "ethers";
|
|
600
|
-
import { invisiProtocolAbi } from "@invisi-labs/protocol/contracts";
|
|
601
|
-
var broadcasterQuoteTypes = {
|
|
602
|
-
Quote: [
|
|
603
|
-
{ name: "token", type: "address" },
|
|
604
|
-
{ name: "feeRecipient", type: "address" },
|
|
605
|
-
{ name: "feeAmount", type: "uint256" },
|
|
606
|
-
{ name: "deadline", type: "uint256" },
|
|
607
|
-
{ name: "maxGas", type: "uint256" },
|
|
608
|
-
{ name: "requestHash", type: "bytes32" }
|
|
609
|
-
]
|
|
610
|
-
};
|
|
611
|
-
function broadcasterQuoteDomain(trust) {
|
|
612
|
-
return {
|
|
613
|
-
name: "InvisiBroadcaster",
|
|
614
|
-
version: "1",
|
|
615
|
-
chainId: trust.chainId,
|
|
616
|
-
verifyingContract: getAddress2(trust.protocol)
|
|
617
|
-
};
|
|
618
|
-
}
|
|
619
|
-
var supportedMethods = ["transact", "shield", "createCredit", "topUpCredit", "cancelCredit"];
|
|
620
|
-
var intentAbi = invisiProtocolAbi.filter(
|
|
621
|
-
(item) => item.type === "function" && supportedMethods.includes(item.name) && (item.name !== "transact" || item.inputs[1]?.type === "tuple")
|
|
622
|
-
);
|
|
623
|
-
var broadcasterTransactInterface = new Interface(intentAbi);
|
|
624
|
-
function decodeBroadcasterIntent(data) {
|
|
625
|
-
const parsed = broadcasterTransactInterface.parseTransaction({ data });
|
|
626
|
-
if (!parsed || !supportedMethods.includes(parsed.name))
|
|
627
|
-
throw new Error("unsupported broadcaster method");
|
|
628
|
-
const fragment = parsed.fragment;
|
|
629
|
-
const decoded = parsed.args;
|
|
630
|
-
if (broadcasterTransactInterface.encodeFunctionData(fragment, decoded).toLowerCase() !== data.toLowerCase())
|
|
631
|
-
throw new Error("noncanonical broadcaster calldata");
|
|
632
|
-
const method = parsed.name;
|
|
633
|
-
const raw = method === "transact" ? decoded[1] : void 0;
|
|
634
|
-
const params = raw?.params ?? (method === "shield" ? decoded[0] : method === "topUpCredit" ? decoded[1].creation : decoded[1]);
|
|
635
|
-
const funding = raw?.funding ?? (method === "shield" ? decoded[3] : ["createCredit", "topUpCredit"].includes(method) ? decoded[3] : void 0);
|
|
636
|
-
const deliveries = raw?.deliveries ?? (method === "shield" ? decoded[2] : ["createCredit", "topUpCredit"].includes(method) ? decoded[2] : []);
|
|
637
|
-
return {
|
|
638
|
-
fragment,
|
|
639
|
-
method,
|
|
640
|
-
args: decoded,
|
|
641
|
-
proof: method === "shield" ? "0x" : decoded[0],
|
|
642
|
-
request: { params, funding, deliveries }
|
|
643
|
-
};
|
|
644
|
-
}
|
|
645
|
-
function broadcasterRequestHash(data) {
|
|
646
|
-
const { fragment, method, args } = decodeBroadcasterIntent(data);
|
|
647
|
-
const copy = (value) => Array.isArray(value) ? value.map(copy) : value;
|
|
648
|
-
const canonical = copy(args);
|
|
649
|
-
if (method !== "shield") canonical[0] = "0x";
|
|
650
|
-
if (method === "transact") canonical[1][2][4] = "0x";
|
|
651
|
-
else if (method !== "cancelCredit") canonical[3][4] = "0x";
|
|
652
|
-
const calldata = broadcasterTransactInterface.encodeFunctionData(fragment, canonical);
|
|
653
|
-
return keccak256(
|
|
654
|
-
AbiCoder.defaultAbiCoder().encode(
|
|
655
|
-
["string", "string", "bytes"],
|
|
656
|
-
["InvisiBroadcasterIntentV1", method, calldata]
|
|
657
|
-
)
|
|
658
|
-
);
|
|
170
|
+
// src/protocol/connections.ts
|
|
171
|
+
var connections = /* @__PURE__ */ new WeakMap();
|
|
172
|
+
function rememberProtocolConnection(protocol, provider, protocolRpc) {
|
|
173
|
+
connections.set(protocol, { provider, protocolRpc });
|
|
659
174
|
}
|
|
660
|
-
function
|
|
661
|
-
|
|
662
|
-
const { request } = decodeBroadcasterIntent(data);
|
|
663
|
-
const p = request.params;
|
|
664
|
-
if (quote.requestHash !== broadcasterRequestHash(data) || getAddress2(quote.token) !== getAddress2(p.token) || getAddress2(quote.feeRecipient) !== getAddress2(p.feeRecipient) || BigInt(quote.feeAmount) !== p.feeAmount || BigInt(quote.deadline) > p.deadline || BigInt(quote.deadline) < now || BigInt(quote.maxGas) <= 0n || BigInt(quote.feeAmount) <= 0n || BigInt(quote.feeAmount) >= 1n << 128n)
|
|
665
|
-
throw new Error("quote does not match final intent or bounds");
|
|
666
|
-
if (getAddress2(
|
|
667
|
-
verifyTypedData(
|
|
668
|
-
broadcasterQuoteDomain(trust),
|
|
669
|
-
broadcasterQuoteTypes,
|
|
670
|
-
quote,
|
|
671
|
-
signed.signature
|
|
672
|
-
)
|
|
673
|
-
) !== getAddress2(trust.signer))
|
|
674
|
-
throw new Error("untrusted quote signature");
|
|
675
|
-
return quote;
|
|
175
|
+
function protocolConnection(protocol) {
|
|
176
|
+
return connections.get(protocol);
|
|
676
177
|
}
|
|
677
|
-
function checkedStatus(value, id) {
|
|
678
|
-
const status = value;
|
|
679
|
-
if (!status || status.id !== id || !["pending", "submitted", "confirmed", "reverted", "uncertain"].includes(status.state) || status.transactionHash !== void 0 && !/^0x[0-9a-fA-F]{64}$/.test(status.transactionHash))
|
|
680
|
-
throw new Error("invalid broadcaster status");
|
|
681
|
-
return status;
|
|
682
|
-
}
|
|
683
|
-
var BroadcasterClient = class {
|
|
684
|
-
configuration;
|
|
685
|
-
url;
|
|
686
|
-
transport;
|
|
687
|
-
requestId = 0;
|
|
688
|
-
constructor(configuration, transport) {
|
|
689
|
-
this.configuration = Object.freeze({
|
|
690
|
-
endpoint: configuration.endpoint,
|
|
691
|
-
quoteSigner: getAddress2(configuration.quoteSigner),
|
|
692
|
-
feeRecipient: getAddress2(configuration.feeRecipient)
|
|
693
|
-
});
|
|
694
|
-
if (BigInt(this.configuration.quoteSigner) === 0n || BigInt(this.configuration.feeRecipient) === 0n)
|
|
695
|
-
throw new Error("invalid broadcaster configuration");
|
|
696
|
-
this.url = configuration.endpoint;
|
|
697
|
-
const base = new URL(this.url);
|
|
698
|
-
if (base.protocol !== "https:" || base.username || base.password)
|
|
699
|
-
throw new Error("broadcaster requires HTTPS");
|
|
700
|
-
this.transport = transport ?? (async (request) => {
|
|
701
|
-
const response = await fetch(base, {
|
|
702
|
-
redirect: "error",
|
|
703
|
-
method: "POST",
|
|
704
|
-
body: JSON.stringify(request),
|
|
705
|
-
headers: { "content-type": "application/json" },
|
|
706
|
-
signal: AbortSignal.timeout(3e4)
|
|
707
|
-
});
|
|
708
|
-
if (!response.ok) throw new Error(`Broadcaster HTTP ${response.status}`);
|
|
709
|
-
if (!response.body) throw new Error("empty broadcaster response");
|
|
710
|
-
const reader = response.body.getReader();
|
|
711
|
-
const chunks = [];
|
|
712
|
-
let size = 0;
|
|
713
|
-
try {
|
|
714
|
-
while (true) {
|
|
715
|
-
const result = await reader.read();
|
|
716
|
-
if (result.done) break;
|
|
717
|
-
size += result.value.length;
|
|
718
|
-
if (size > 65536) throw new Error("broadcaster response too large");
|
|
719
|
-
chunks.push(result.value);
|
|
720
|
-
}
|
|
721
|
-
} finally {
|
|
722
|
-
await reader.cancel();
|
|
723
|
-
}
|
|
724
|
-
const bytes = new Uint8Array(size);
|
|
725
|
-
let offset = 0;
|
|
726
|
-
for (const chunk of chunks) {
|
|
727
|
-
bytes.set(chunk, offset);
|
|
728
|
-
offset += chunk.length;
|
|
729
|
-
}
|
|
730
|
-
return JSON.parse(new TextDecoder().decode(bytes));
|
|
731
|
-
});
|
|
732
|
-
}
|
|
733
|
-
async call(method, params) {
|
|
734
|
-
const id = ++this.requestId;
|
|
735
|
-
const response = await this.transport({
|
|
736
|
-
jsonrpc: "2.0",
|
|
737
|
-
id,
|
|
738
|
-
method,
|
|
739
|
-
params: [params]
|
|
740
|
-
});
|
|
741
|
-
if (!response || response.jsonrpc !== "2.0" || response.id !== id || Object.hasOwn(response, "result") === Object.hasOwn(response, "error"))
|
|
742
|
-
throw new Error("invalid broadcaster JSON-RPC response");
|
|
743
|
-
if (response.error) {
|
|
744
|
-
if (!Number.isInteger(response.error.code) || typeof response.error.message !== "string")
|
|
745
|
-
throw new Error("invalid broadcaster JSON-RPC error");
|
|
746
|
-
throw new BroadcasterRpcError(response.error.code, response.error.message);
|
|
747
|
-
}
|
|
748
|
-
return response.result;
|
|
749
|
-
}
|
|
750
|
-
async fee(token, data) {
|
|
751
|
-
const fee = await this.call("broadcaster_getFee", {
|
|
752
|
-
token: getAddress2(token),
|
|
753
|
-
...data ? { data } : {}
|
|
754
|
-
});
|
|
755
|
-
if (!fee || getAddress2(fee.feeRecipient) !== this.configuration.feeRecipient || !/^\d+$/.test(fee.feeAmount) || BigInt(fee.feeAmount) <= 0n || BigInt(fee.feeAmount) >= 1n << 128n || !/^\d+$/.test(fee.maxGas) || BigInt(fee.maxGas) <= 0n)
|
|
756
|
-
throw new Error("invalid broadcaster fee");
|
|
757
|
-
return fee;
|
|
758
|
-
}
|
|
759
|
-
async quote(data, context) {
|
|
760
|
-
const signed = await this.call("broadcaster_getQuote", {
|
|
761
|
-
data
|
|
762
|
-
});
|
|
763
|
-
verifyBroadcasterQuote(
|
|
764
|
-
signed,
|
|
765
|
-
{ ...context, signer: this.configuration.quoteSigner },
|
|
766
|
-
data
|
|
767
|
-
);
|
|
768
|
-
if (getAddress2(signed.quote.feeRecipient) !== this.configuration.feeRecipient)
|
|
769
|
-
throw new Error("unregistered fee recipient");
|
|
770
|
-
return { quote: signed.quote, signature: signed.signature, context: { ...context } };
|
|
771
|
-
}
|
|
772
|
-
async submit(data, signed, idempotencyKey) {
|
|
773
|
-
if (!signed.context) throw new Error("missing verified quote context");
|
|
774
|
-
verifyBroadcasterQuote(
|
|
775
|
-
signed,
|
|
776
|
-
{ ...signed.context, signer: this.configuration.quoteSigner },
|
|
777
|
-
data,
|
|
778
|
-
0n
|
|
779
|
-
);
|
|
780
|
-
if (getAddress2(signed.quote.feeRecipient) !== this.configuration.feeRecipient)
|
|
781
|
-
throw new Error("unregistered fee recipient");
|
|
782
|
-
return checkedStatus(
|
|
783
|
-
await this.call("broadcaster_submitTransaction", {
|
|
784
|
-
data,
|
|
785
|
-
quote: signed.quote,
|
|
786
|
-
signature: signed.signature,
|
|
787
|
-
idempotencyKey
|
|
788
|
-
}),
|
|
789
|
-
idempotencyKey
|
|
790
|
-
);
|
|
791
|
-
}
|
|
792
|
-
async status(id) {
|
|
793
|
-
return checkedStatus(await this.call("broadcaster_getTransactionStatus", { id }), id);
|
|
794
|
-
}
|
|
795
|
-
};
|
|
796
|
-
var BroadcasterRpcError = class extends Error {
|
|
797
|
-
constructor(code, message) {
|
|
798
|
-
super(message);
|
|
799
|
-
this.code = code;
|
|
800
|
-
this.name = "BroadcasterRpcError";
|
|
801
|
-
}
|
|
802
|
-
};
|
|
803
178
|
|
|
804
|
-
// src/Protocol.ts
|
|
179
|
+
// src/protocol/Protocol.ts
|
|
180
|
+
import { Protocol as BaseProtocol } from "@invisi-labs/protocol";
|
|
181
|
+
import { getAddress } from "ethers";
|
|
805
182
|
var sources = /* @__PURE__ */ new WeakMap();
|
|
806
183
|
var Protocol = class _Protocol extends BaseProtocol {
|
|
807
184
|
static async fromRpc(rpc, provider, options = {}) {
|
|
@@ -809,11 +186,17 @@ var Protocol = class _Protocol extends BaseProtocol {
|
|
|
809
186
|
const protocol = new _Protocol({ deployment: verified.deployment });
|
|
810
187
|
if (rpc.getBroadcasters)
|
|
811
188
|
sources.set(protocol, rpc);
|
|
189
|
+
if (rpc.withReader)
|
|
190
|
+
rememberProtocolConnection(
|
|
191
|
+
protocol,
|
|
192
|
+
provider,
|
|
193
|
+
rpc
|
|
194
|
+
);
|
|
812
195
|
return protocol;
|
|
813
196
|
}
|
|
814
197
|
/** Returns enabled services that answer a token fee probe; final quotes are checked by prepared. */
|
|
815
198
|
async getBroadcasters(options) {
|
|
816
|
-
const token =
|
|
199
|
+
const token = getAddress(options.tokenAddress);
|
|
817
200
|
if (!this.deployment.broadcasterRegistry)
|
|
818
201
|
throw new Error("broadcaster registry is not configured");
|
|
819
202
|
const rpc = sources.get(this);
|
|
@@ -854,22 +237,14 @@ var Protocol = class _Protocol extends BaseProtocol {
|
|
|
854
237
|
};
|
|
855
238
|
|
|
856
239
|
// src/index.ts
|
|
857
|
-
import {
|
|
858
|
-
|
|
859
|
-
// src/ProtocolRpcClient.ts
|
|
860
|
-
import { ProtocolRpcClient as RpcClient } from "@invisi-labs/rpc";
|
|
861
|
-
var ProtocolRpcClient2 = class extends RpcClient {
|
|
862
|
-
withProvider(provider) {
|
|
863
|
-
return this.withReader(new EthersChainReader(provider));
|
|
864
|
-
}
|
|
865
|
-
};
|
|
240
|
+
import { MAX_UPDATE_BLOCKS, ProtocolRpcError } from "@invisi-labs/rpc";
|
|
866
241
|
|
|
867
|
-
// src/BroadcasterRegistry.ts
|
|
868
|
-
import { getAddress as getAddress4, Interface as Interface2, keccak256 as keccak2562 } from "ethers";
|
|
242
|
+
// src/protocol/BroadcasterRegistry.ts
|
|
869
243
|
import { broadcasterRegistryAbi } from "@invisi-labs/protocol/contracts";
|
|
870
|
-
|
|
244
|
+
import { getAddress as getAddress2, Interface, keccak256 } from "ethers";
|
|
245
|
+
var abi = new Interface(broadcasterRegistryAbi);
|
|
871
246
|
function address(value) {
|
|
872
|
-
const normalized =
|
|
247
|
+
const normalized = getAddress2(value);
|
|
873
248
|
if (BigInt(normalized) === 0n) throw new Error("zero broadcaster address");
|
|
874
249
|
return normalized;
|
|
875
250
|
}
|
|
@@ -912,7 +287,7 @@ var BroadcasterRegistry = class {
|
|
|
912
287
|
if ((await provider.getNetwork()).chainId !== chainId) {
|
|
913
288
|
throw new Error("broadcaster registry chain mismatch");
|
|
914
289
|
}
|
|
915
|
-
if (
|
|
290
|
+
if (keccak256(await provider.getCode(this.address)).toLowerCase() !== runtimeCodeHash.toLowerCase()) {
|
|
916
291
|
throw new Error("broadcaster registry runtime code mismatch");
|
|
917
292
|
}
|
|
918
293
|
}
|
|
@@ -952,7 +327,7 @@ var BroadcasterRegistry = class {
|
|
|
952
327
|
toBlock: end
|
|
953
328
|
});
|
|
954
329
|
for (const log of logs) {
|
|
955
|
-
if (
|
|
330
|
+
if (getAddress2(log.address) !== this.address)
|
|
956
331
|
throw new Error("registry event address mismatch");
|
|
957
332
|
const event = abi.parseLog(log);
|
|
958
333
|
if (!event || event.name !== "BroadcasterSet")
|
|
@@ -970,87 +345,220 @@ var BroadcasterRegistry = class {
|
|
|
970
345
|
}
|
|
971
346
|
};
|
|
972
347
|
|
|
973
|
-
// src/
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
this
|
|
348
|
+
// src/protocol/ProtocolRpcClient.ts
|
|
349
|
+
import { ProtocolRpcClient as RpcClient } from "@invisi-labs/rpc";
|
|
350
|
+
var ProtocolRpcClient = class extends RpcClient {
|
|
351
|
+
withProvider(provider) {
|
|
352
|
+
return this.withReader(new EthersChainReader(provider));
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// src/payment-note/PaymentNote.ts
|
|
357
|
+
import { computeNoteIdentity, computeNoteCommitment, Wallet } from "@invisi-labs/core";
|
|
358
|
+
|
|
359
|
+
// src/payment-note/verification.ts
|
|
360
|
+
import {
|
|
361
|
+
poseidonHash,
|
|
362
|
+
TREE_DEPTH,
|
|
363
|
+
computeNoteNullifier
|
|
364
|
+
} from "@invisi-labs/core";
|
|
365
|
+
import { getAddress as getAddress3 } from "ethers";
|
|
366
|
+
function verificationOptions(protocol, options = {}) {
|
|
367
|
+
const connected = protocolConnection(protocol);
|
|
368
|
+
const resolved = { ...connected, ...options };
|
|
369
|
+
if (!("protocolRpc" in resolved) || !resolved.protocolRpc || !("chainReader" in resolved) && !("provider" in resolved))
|
|
370
|
+
throw new Error(
|
|
371
|
+
"Payment note verification requires Protocol.fromRpc or explicit chain and Protocol RPC connections"
|
|
372
|
+
);
|
|
373
|
+
return resolved;
|
|
374
|
+
}
|
|
375
|
+
function sameBlock(a, b) {
|
|
376
|
+
return a.number === b.number && a.hash === b.hash && a.parentHash === b.parentHash && a.timestamp === b.timestamp;
|
|
377
|
+
}
|
|
378
|
+
function asNote(data) {
|
|
379
|
+
return {
|
|
380
|
+
chainId: data.chainId,
|
|
381
|
+
protocolAddress: BigInt(data.protocolAddress),
|
|
382
|
+
tokenAddress: BigInt(data.tokenAddress),
|
|
383
|
+
amount: data.amount,
|
|
384
|
+
ownerAddress: data.ownerAddress,
|
|
385
|
+
nonce: data.nonce
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
async function verifyPaymentNote(data, protocol, options, wallet) {
|
|
389
|
+
if (data.chainId !== protocol.context.chainId || getAddress3(data.protocolAddress) !== getAddress3(protocol.context.protocolAddress))
|
|
390
|
+
throw new Error("Payment note protocol context mismatch");
|
|
391
|
+
const confirmations = options.confirmations ?? 1;
|
|
392
|
+
if (!Number.isSafeInteger(confirmations) || confirmations < 1)
|
|
393
|
+
throw new RangeError("confirmations must be positive");
|
|
394
|
+
const reader = options.chainReader ?? new EthersChainReader(options.provider);
|
|
395
|
+
await protocol.validateDeployment(reader);
|
|
396
|
+
if (wallet && getAddress3(wallet.ownerAddress) !== getAddress3(data.ownerAddress))
|
|
397
|
+
throw new Error("Payment note owner mismatch");
|
|
398
|
+
if (wallet) {
|
|
399
|
+
if (typeof wallet.exportAuthorization !== "function")
|
|
400
|
+
throw new Error("Wallet spending authorization capability required");
|
|
401
|
+
const authorization = wallet.exportAuthorization();
|
|
402
|
+
if (getAddress3(authorization.ownerAddress) !== getAddress3(data.ownerAddress))
|
|
403
|
+
throw new Error("Wallet authorization owner mismatch");
|
|
404
|
+
}
|
|
405
|
+
const latest = await reader.getLatestBlockNumber();
|
|
406
|
+
const number = latest - BigInt(confirmations - 1);
|
|
407
|
+
if (number < protocol.deployment.protocol.fromBlock)
|
|
408
|
+
throw new Error("Insufficient confirmed blocks");
|
|
409
|
+
const rpc = options.protocolRpc.withReader(reader);
|
|
410
|
+
const status = await rpc.getStatus(protocol.context);
|
|
411
|
+
if (!status.indexedHead) throw new Error("Protocol RPC has no indexed blocks");
|
|
412
|
+
const indexedNumber = status.indexedHead.number < number ? status.indexedHead.number : number;
|
|
413
|
+
if (indexedNumber < protocol.deployment.protocol.fromBlock)
|
|
414
|
+
throw new Error("Protocol RPC has not reached the deployment");
|
|
415
|
+
const checkedAt = await reader.getBlock(indexedNumber);
|
|
416
|
+
if (checkedAt.number !== indexedNumber)
|
|
417
|
+
throw new Error("Payment note confirmation block mismatch");
|
|
418
|
+
const result = await rpc.getNote(protocol.context, data.commitment, checkedAt);
|
|
419
|
+
if (!result) throw new Error("Payment note is not indexed at the requested confirmed block");
|
|
420
|
+
const { output, membership } = result;
|
|
421
|
+
if (output.commitment !== data.commitment || getAddress3(output.tokenAddress) !== getAddress3(data.tokenAddress) || membership.leaf !== data.commitment || membership.treeId !== output.treeId || membership.leafIndex !== output.leafIndex || membership.block.number > checkedAt.number || output.block.number > checkedAt.number || membership.path.length !== TREE_DEPTH || !Number.isSafeInteger(output.leafIndex) || output.leafIndex < 0 || output.leafIndex >= 2 ** TREE_DEPTH)
|
|
422
|
+
throw new Error("Payment note membership metadata mismatch");
|
|
423
|
+
let root = BigInt(data.commitment);
|
|
424
|
+
for (let level = 0; level < membership.path.length; level++) {
|
|
425
|
+
const sibling = membership.path[level];
|
|
426
|
+
root = BigInt(
|
|
427
|
+
await poseidonHash(output.leafIndex >> level & 1 ? [sibling, root] : [root, sibling])
|
|
428
|
+
);
|
|
978
429
|
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
430
|
+
if (root !== BigInt(membership.root) || !await reader.isKnownRoot(protocol.context, membership.treeId, membership.root, checkedAt))
|
|
431
|
+
throw new Error("Payment note membership root is not accepted on chain");
|
|
432
|
+
if (!sameBlock(output.block, await reader.getBlock(output.block.number)) || !sameBlock(membership.block, await reader.getBlock(membership.block.number)))
|
|
433
|
+
throw new Error("Payment note block is no longer canonical");
|
|
434
|
+
let spendabilityCheckedAt;
|
|
435
|
+
if (wallet) {
|
|
436
|
+
const current = await reader.getBlock(await reader.getLatestBlockNumber());
|
|
437
|
+
const nullifier = await computeNoteNullifier(data.chainId, data.nonce, data.commitment);
|
|
438
|
+
const spent = await reader.isSpent(protocol.context, [nullifier], current);
|
|
439
|
+
if (spent.length !== 1 || spent[0] !== false)
|
|
440
|
+
throw new Error("Payment note is already spent");
|
|
441
|
+
if (!await reader.isKnownRoot(
|
|
442
|
+
protocol.context,
|
|
443
|
+
membership.treeId,
|
|
444
|
+
membership.root,
|
|
445
|
+
current
|
|
446
|
+
))
|
|
447
|
+
throw new Error("Payment note membership root is no longer spendable");
|
|
448
|
+
if (!sameBlock(current, await reader.getBlock(current.number)))
|
|
449
|
+
throw new Error("Spendability block reorganized");
|
|
450
|
+
spendabilityCheckedAt = current;
|
|
451
|
+
}
|
|
452
|
+
if (!sameBlock(checkedAt, await reader.getBlock(checkedAt.number)))
|
|
453
|
+
throw new Error("Payment note verification block reorganized");
|
|
454
|
+
return {
|
|
455
|
+
input: {
|
|
456
|
+
note: asNote(data),
|
|
457
|
+
commitment: data.commitment,
|
|
458
|
+
treeId: output.treeId,
|
|
459
|
+
leafIndex: output.leafIndex
|
|
460
|
+
},
|
|
461
|
+
membership,
|
|
462
|
+
checkedAt,
|
|
463
|
+
...spendabilityCheckedAt ? { spendabilityCheckedAt } : {}
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// src/payment-note/PaymentNote.ts
|
|
468
|
+
var verification = /* @__PURE__ */ Symbol("PaymentNote verification");
|
|
469
|
+
var VerifiedPaymentNote = class {
|
|
470
|
+
#membership;
|
|
471
|
+
#checkedAt;
|
|
472
|
+
constructor(token, membership, checkedAt) {
|
|
473
|
+
if (token !== verification) throw new Error("Payment note verification required");
|
|
474
|
+
this.#membership = structuredClone(membership);
|
|
475
|
+
this.#checkedAt = structuredClone(checkedAt);
|
|
476
|
+
}
|
|
477
|
+
get membership() {
|
|
478
|
+
return structuredClone(this.#membership);
|
|
479
|
+
}
|
|
480
|
+
get checkedAt() {
|
|
481
|
+
return structuredClone(this.#checkedAt);
|
|
983
482
|
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
);
|
|
994
|
-
} finally {
|
|
995
|
-
copy.fill(0);
|
|
996
|
-
}
|
|
483
|
+
};
|
|
484
|
+
var SpendablePaymentNote = class extends VerifiedPaymentNote {
|
|
485
|
+
#input;
|
|
486
|
+
#spendabilityCheckedAt;
|
|
487
|
+
constructor(token, input, membership, checkedAt, spendabilityCheckedAt) {
|
|
488
|
+
super(token, membership, checkedAt);
|
|
489
|
+
this.#input = structuredClone(input);
|
|
490
|
+
this.#spendabilityCheckedAt = structuredClone(spendabilityCheckedAt);
|
|
491
|
+
Object.freeze(this);
|
|
997
492
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
throw new Error("invalid encrypted record revision");
|
|
1001
|
-
return new TextEncoder().encode(
|
|
1002
|
-
`Invisi.WalletRecord.v1\0${context.revision}\0${context.key}`
|
|
1003
|
-
);
|
|
493
|
+
get spendabilityCheckedAt() {
|
|
494
|
+
return structuredClone(this.#spendabilityCheckedAt);
|
|
1004
495
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
try {
|
|
1008
|
-
const encrypted = new Uint8Array(
|
|
1009
|
-
await crypto.subtle.encrypt(
|
|
1010
|
-
{ name: "AES-GCM", iv, additionalData: this.aad(context) },
|
|
1011
|
-
this.#key,
|
|
1012
|
-
plain
|
|
1013
|
-
)
|
|
1014
|
-
);
|
|
1015
|
-
const out = new Uint8Array(13 + encrypted.length);
|
|
1016
|
-
out[0] = 1;
|
|
1017
|
-
out.set(iv, 1);
|
|
1018
|
-
out.set(encrypted, 13);
|
|
1019
|
-
return out;
|
|
1020
|
-
} finally {
|
|
1021
|
-
plain.fill(0);
|
|
1022
|
-
}
|
|
496
|
+
toInput() {
|
|
497
|
+
return structuredClone(this.#input);
|
|
1023
498
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
return deserializeState(plain);
|
|
1045
|
-
} finally {
|
|
1046
|
-
plain.fill(0);
|
|
1047
|
-
}
|
|
499
|
+
};
|
|
500
|
+
var PaymentNote = class _PaymentNote {
|
|
501
|
+
chainId;
|
|
502
|
+
protocolAddress;
|
|
503
|
+
tokenAddress;
|
|
504
|
+
amount;
|
|
505
|
+
ownerAddress;
|
|
506
|
+
nonce;
|
|
507
|
+
commitment;
|
|
508
|
+
ipn;
|
|
509
|
+
constructor(data, ipn) {
|
|
510
|
+
this.chainId = data.chainId;
|
|
511
|
+
this.protocolAddress = data.protocolAddress;
|
|
512
|
+
this.tokenAddress = data.tokenAddress;
|
|
513
|
+
this.amount = data.amount;
|
|
514
|
+
this.ownerAddress = data.ownerAddress;
|
|
515
|
+
this.nonce = data.nonce;
|
|
516
|
+
this.commitment = data.commitment;
|
|
517
|
+
this.ipn = ipn;
|
|
518
|
+
Object.freeze(this);
|
|
1048
519
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
520
|
+
static async from(ipn) {
|
|
521
|
+
const data = decodePaymentNote(ipn);
|
|
522
|
+
const identity = await computeNoteIdentity(BigInt(data.ownerAddress), data.nonce);
|
|
523
|
+
const commitment = await computeNoteCommitment(
|
|
524
|
+
data.chainId,
|
|
525
|
+
identity,
|
|
526
|
+
BigInt(data.tokenAddress),
|
|
527
|
+
data.amount
|
|
528
|
+
);
|
|
529
|
+
if (commitment !== data.commitment) throw new Error("Payment note commitment mismatch");
|
|
530
|
+
return new _PaymentNote(data, encodePaymentNote(data));
|
|
531
|
+
}
|
|
532
|
+
async verify(protocol, options = {}) {
|
|
533
|
+
const result = await verifyPaymentNote(
|
|
534
|
+
this.data(),
|
|
535
|
+
protocol,
|
|
536
|
+
verificationOptions(protocol, options)
|
|
537
|
+
);
|
|
538
|
+
const verified = new VerifiedPaymentNote(verification, result.membership, result.checkedAt);
|
|
539
|
+
Object.freeze(verified);
|
|
540
|
+
return verified;
|
|
541
|
+
}
|
|
542
|
+
async verifySpendable(protocol, wallet, options = {}) {
|
|
543
|
+
if (!(wallet instanceof Wallet))
|
|
544
|
+
throw new Error("Wallet spending authorization capability required");
|
|
545
|
+
const result = await verifyPaymentNote(
|
|
546
|
+
this.data(),
|
|
547
|
+
protocol,
|
|
548
|
+
verificationOptions(protocol, options),
|
|
549
|
+
wallet
|
|
550
|
+
);
|
|
551
|
+
return new SpendablePaymentNote(
|
|
552
|
+
verification,
|
|
553
|
+
result.input,
|
|
554
|
+
result.membership,
|
|
555
|
+
result.checkedAt,
|
|
556
|
+
result.spendabilityCheckedAt
|
|
557
|
+
);
|
|
1051
558
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
559
|
+
data() {
|
|
560
|
+
const { chainId, protocolAddress, tokenAddress, amount, ownerAddress, nonce, commitment } = this;
|
|
561
|
+
return { chainId, protocolAddress, tokenAddress, amount, ownerAddress, nonce, commitment };
|
|
1054
562
|
}
|
|
1055
563
|
};
|
|
1056
564
|
export {
|
|
@@ -1061,25 +569,26 @@ export {
|
|
|
1061
569
|
Detector,
|
|
1062
570
|
Disclosure,
|
|
1063
571
|
DisclosureVerifier,
|
|
1064
|
-
EncryptedWalletCodec,
|
|
1065
572
|
Invisi,
|
|
1066
573
|
InvisiError,
|
|
1067
574
|
MAX_MEMO_BYTES,
|
|
1068
575
|
MAX_UPDATE_BLOCKS,
|
|
1069
|
-
|
|
576
|
+
MissingCapabilityError,
|
|
1070
577
|
NoteOutput,
|
|
1071
578
|
NullifierCapability,
|
|
1072
|
-
|
|
579
|
+
PaymentNote,
|
|
1073
580
|
PreparedTransaction,
|
|
1074
581
|
Protocol,
|
|
1075
|
-
|
|
582
|
+
ProtocolRpcClient,
|
|
1076
583
|
ProtocolRpcError,
|
|
1077
|
-
|
|
584
|
+
PublicWallet,
|
|
1078
585
|
RegistrationOperation,
|
|
586
|
+
SpendablePaymentNote,
|
|
587
|
+
TransactionOutput,
|
|
588
|
+
VerifiedPaymentNote,
|
|
1079
589
|
ViewingCapability,
|
|
1080
|
-
Wallet,
|
|
590
|
+
Wallet2 as Wallet,
|
|
1081
591
|
WalletAuthorization,
|
|
1082
|
-
WalletSession,
|
|
1083
592
|
broadcasterQuoteDomain,
|
|
1084
593
|
broadcasterQuoteTypes,
|
|
1085
594
|
broadcasterRequestHash,
|
|
@@ -1090,12 +599,15 @@ export {
|
|
|
1090
599
|
decodeBroadcasterIntent,
|
|
1091
600
|
decodeDeliveryHeader,
|
|
1092
601
|
decodeMemoText,
|
|
602
|
+
decodePaymentNote,
|
|
603
|
+
decodePaymentRequest,
|
|
1093
604
|
decryptCandidates,
|
|
1094
605
|
defineGasBenchmarks,
|
|
1095
606
|
encodeMemo,
|
|
607
|
+
encodePaymentNote,
|
|
608
|
+
encodePaymentRequest,
|
|
1096
609
|
fundsV1,
|
|
1097
610
|
readProtocolLogs,
|
|
1098
|
-
verifyBroadcasterQuote
|
|
1099
|
-
walletBalance
|
|
611
|
+
verifyBroadcasterQuote
|
|
1100
612
|
};
|
|
1101
613
|
//# sourceMappingURL=index.js.map
|