@taquito/sapling 17.3.2 → 17.4.0-beta-RC.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 (53) hide show
  1. package/dist/lib/constants.js +0 -1
  2. package/dist/lib/errors.js +0 -1
  3. package/dist/lib/sapling-forger/sapling-forger.js +8 -9
  4. package/dist/lib/sapling-keys/helpers.js +6 -7
  5. package/dist/lib/sapling-keys/in-memory-proving-key.js +15 -18
  6. package/dist/lib/sapling-keys/in-memory-spending-key.js +22 -25
  7. package/dist/lib/sapling-keys/in-memory-viewing-key.js +18 -21
  8. package/dist/lib/sapling-module-wrapper.js +1 -2
  9. package/dist/lib/sapling-state/sapling-state.js +6 -7
  10. package/dist/lib/sapling-state/utils.js +0 -1
  11. package/dist/lib/sapling-tx-builder/sapling-transactions-builder.js +78 -80
  12. package/dist/lib/sapling-tx-viewer/helpers.js +2 -3
  13. package/dist/lib/sapling-tx-viewer/sapling-transaction-viewer.js +36 -39
  14. package/dist/lib/taquito-sapling.js +55 -58
  15. package/dist/lib/types.js +0 -1
  16. package/dist/lib/version.js +2 -3
  17. package/dist/taquito-sapling.es6.js +1383 -1380
  18. package/dist/taquito-sapling.es6.js.map +1 -1
  19. package/dist/taquito-sapling.umd.js +1387 -1393
  20. package/dist/taquito-sapling.umd.js.map +1 -1
  21. package/dist/types/constants.d.ts +5 -5
  22. package/dist/types/errors.d.ts +52 -52
  23. package/dist/types/sapling-forger/sapling-forger.d.ts +30 -30
  24. package/dist/types/sapling-keys/helpers.d.ts +2 -2
  25. package/dist/types/sapling-keys/in-memory-proving-key.d.ts +35 -35
  26. package/dist/types/sapling-keys/in-memory-spending-key.d.ts +53 -53
  27. package/dist/types/sapling-keys/in-memory-viewing-key.d.ts +48 -48
  28. package/dist/types/sapling-module-wrapper.d.ts +19 -19
  29. package/dist/types/sapling-state/sapling-state.d.ts +56 -56
  30. package/dist/types/sapling-state/utils.d.ts +22 -22
  31. package/dist/types/sapling-tx-builder/sapling-transactions-builder.d.ts +32 -32
  32. package/dist/types/sapling-tx-viewer/helpers.d.ts +11 -11
  33. package/dist/types/sapling-tx-viewer/sapling-transaction-viewer.d.ts +50 -50
  34. package/dist/types/taquito-sapling.d.ts +81 -81
  35. package/dist/types/types.d.ts +147 -147
  36. package/dist/types/version.d.ts +4 -4
  37. package/package.json +33 -35
  38. package/dist/lib/constants.js.map +0 -1
  39. package/dist/lib/errors.js.map +0 -1
  40. package/dist/lib/sapling-forger/sapling-forger.js.map +0 -1
  41. package/dist/lib/sapling-keys/helpers.js.map +0 -1
  42. package/dist/lib/sapling-keys/in-memory-proving-key.js.map +0 -1
  43. package/dist/lib/sapling-keys/in-memory-spending-key.js.map +0 -1
  44. package/dist/lib/sapling-keys/in-memory-viewing-key.js.map +0 -1
  45. package/dist/lib/sapling-module-wrapper.js.map +0 -1
  46. package/dist/lib/sapling-state/sapling-state.js.map +0 -1
  47. package/dist/lib/sapling-state/utils.js.map +0 -1
  48. package/dist/lib/sapling-tx-builder/sapling-transactions-builder.js.map +0 -1
  49. package/dist/lib/sapling-tx-viewer/helpers.js.map +0 -1
  50. package/dist/lib/sapling-tx-viewer/sapling-transaction-viewer.js.map +0 -1
  51. package/dist/lib/taquito-sapling.js.map +0 -1
  52. package/dist/lib/types.js.map +0 -1
  53. package/dist/lib/version.js.map +0 -1
@@ -25,6 +25,8 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25
25
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26
26
  PERFORMANCE OF THIS SOFTWARE.
27
27
  ***************************************************************************** */
28
+ /* global Reflect, Promise, SuppressedError, Symbol */
29
+
28
30
 
29
31
  function __rest(s, e) {
30
32
  var t = {};
@@ -66,1407 +68,1408 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
66
68
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
67
69
  };
68
70
 
69
- /**
70
- * @category Error
71
- * @description Error indicates the spending key is invalid
72
- */
73
- class InvalidSpendingKey extends ParameterValidationError {
74
- constructor(sk, errorDetail) {
75
- super();
76
- this.sk = sk;
77
- this.errorDetail = errorDetail;
78
- this.name = 'InvalidSpendingKey';
79
- this.message = `Invalid spending key "${sk}" ${errorDetail}.`;
80
- }
81
- }
82
- /**
83
- * @category Error
84
- * @description Error indicates an invalid Merkle tree being passed
85
- */
86
- class InvalidMerkleTreeError extends ParameterValidationError {
87
- constructor(root) {
88
- super();
89
- this.root = root;
90
- this.name = 'InvalidMerkleTreeError';
91
- this.message = `Invalid merkle tree has root "${JSON.stringify(root)}" different from expected root.`;
92
- }
93
- }
94
- /**
95
- * @category Error
96
- * @description Error indicates a failure when trying to construct the Merkle tree
97
- */
98
- class TreeConstructionFailure extends TaquitoError {
99
- constructor(message) {
100
- super();
101
- this.message = message;
102
- this.name = 'TreeConstructionFailure';
103
- }
104
- }
105
- /**
106
- * @category Error
107
- * @description Error indicates the memo is invalid
108
- */
109
- class InvalidMemo extends ParameterValidationError {
110
- constructor(memo, errorDetails) {
111
- super();
112
- this.memo = memo;
113
- this.errorDetails = errorDetails;
114
- this.name = 'InvalidMemo';
115
- this.message = `Invalid memo "${memo}" with length ${memo.length} ${errorDetails}`;
116
- }
117
- }
118
- /**
119
- * @category Error
120
- * @description Error indicates not enough balance to prepare the sapling transaction
121
- */
122
- class InsufficientBalance extends TaquitoError {
123
- constructor(realBalance, amountToSpend) {
124
- super();
125
- this.realBalance = realBalance;
126
- this.amountToSpend = amountToSpend;
127
- this.name = 'InsufficientBalance';
128
- this.message = `Unable to spend "${amountToSpend}" mutez while the balance is only ${realBalance} mutez.`;
129
- }
130
- }
131
- /**
132
- * @category Error
133
- * @description Error indicates SaplingTransactionViewer failure
134
- */
135
- class SaplingTransactionViewerError extends TaquitoError {
136
- constructor(message) {
137
- super();
138
- this.message = message;
139
- this.name = 'SaplingTransactionViewerError';
140
- }
71
+ /**
72
+ * @category Error
73
+ * @description Error indicates the spending key is invalid
74
+ */
75
+ class InvalidSpendingKey extends ParameterValidationError {
76
+ constructor(sk, errorDetail) {
77
+ super();
78
+ this.sk = sk;
79
+ this.errorDetail = errorDetail;
80
+ this.name = 'InvalidSpendingKey';
81
+ this.message = `Invalid spending key "${sk}" ${errorDetail}.`;
82
+ }
83
+ }
84
+ /**
85
+ * @category Error
86
+ * @description Error indicates an invalid Merkle tree being passed
87
+ */
88
+ class InvalidMerkleTreeError extends ParameterValidationError {
89
+ constructor(root) {
90
+ super();
91
+ this.root = root;
92
+ this.name = 'InvalidMerkleTreeError';
93
+ this.message = `Invalid merkle tree has root "${JSON.stringify(root)}" different from expected root.`;
94
+ }
95
+ }
96
+ /**
97
+ * @category Error
98
+ * @description Error indicates a failure when trying to construct the Merkle tree
99
+ */
100
+ class TreeConstructionFailure extends TaquitoError {
101
+ constructor(message) {
102
+ super();
103
+ this.message = message;
104
+ this.name = 'TreeConstructionFailure';
105
+ }
106
+ }
107
+ /**
108
+ * @category Error
109
+ * @description Error indicates the memo is invalid
110
+ */
111
+ class InvalidMemo extends ParameterValidationError {
112
+ constructor(memo, errorDetails) {
113
+ super();
114
+ this.memo = memo;
115
+ this.errorDetails = errorDetails;
116
+ this.name = 'InvalidMemo';
117
+ this.message = `Invalid memo "${memo}" with length ${memo.length} ${errorDetails}`;
118
+ }
119
+ }
120
+ /**
121
+ * @category Error
122
+ * @description Error indicates not enough balance to prepare the sapling transaction
123
+ */
124
+ class InsufficientBalance extends TaquitoError {
125
+ constructor(realBalance, amountToSpend) {
126
+ super();
127
+ this.realBalance = realBalance;
128
+ this.amountToSpend = amountToSpend;
129
+ this.name = 'InsufficientBalance';
130
+ this.message = `Unable to spend "${amountToSpend}" mutez while the balance is only ${realBalance} mutez.`;
131
+ }
132
+ }
133
+ /**
134
+ * @category Error
135
+ * @description Error indicates SaplingTransactionViewer failure
136
+ */
137
+ class SaplingTransactionViewerError extends TaquitoError {
138
+ constructor(message) {
139
+ super();
140
+ this.message = message;
141
+ this.name = 'SaplingTransactionViewerError';
142
+ }
141
143
  }
142
144
 
143
- function memoHexToUtf8(memo) {
144
- const memoNoPadding = removeZeroPaddedBytesRight(memo);
145
- return memoNoPadding === '' ? memoNoPadding : bytes2Char(memoNoPadding);
146
- }
147
- function removeZeroPaddedBytesRight(memo) {
148
- const matchZeroRight = memo.match(/^(.*?)(00)+$/);
149
- return matchZeroRight ? matchZeroRight[1] : memo;
150
- }
151
- function readableFormat(saplingTransactionProperties) {
152
- return {
153
- value: convertValueToBigNumber(saplingTransactionProperties.value),
154
- memo: memoHexToUtf8(Buffer.from(saplingTransactionProperties.memo).toString('hex')),
155
- paymentAddress: b58cencode(saplingTransactionProperties.paymentAddress, prefix[Prefix.ZET1]),
156
- };
157
- }
158
- function convertValueToBigNumber(value) {
159
- return new BigNumber(Buffer.from(value).toString('hex'), 16);
160
- }
161
- function bufToUint8Array(buffer) {
162
- return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Uint8Array.BYTES_PER_ELEMENT);
145
+ function memoHexToUtf8(memo) {
146
+ const memoNoPadding = removeZeroPaddedBytesRight(memo);
147
+ return memoNoPadding === '' ? memoNoPadding : bytes2Char(memoNoPadding);
148
+ }
149
+ function removeZeroPaddedBytesRight(memo) {
150
+ const matchZeroRight = memo.match(/^(.*?)(00)+$/);
151
+ return matchZeroRight ? matchZeroRight[1] : memo;
152
+ }
153
+ function readableFormat(saplingTransactionProperties) {
154
+ return {
155
+ value: convertValueToBigNumber(saplingTransactionProperties.value),
156
+ memo: memoHexToUtf8(Buffer.from(saplingTransactionProperties.memo).toString('hex')),
157
+ paymentAddress: b58cencode(saplingTransactionProperties.paymentAddress, prefix[Prefix.ZET1]),
158
+ };
159
+ }
160
+ function convertValueToBigNumber(value) {
161
+ return new BigNumber(Buffer.from(value).toString('hex'), 16);
162
+ }
163
+ function bufToUint8Array(buffer) {
164
+ return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Uint8Array.BYTES_PER_ELEMENT);
163
165
  }
164
166
 
165
- class SaplingForger {
166
- /**
167
- * @description Forge sapling transactions
168
- * @param spendDescriptions the list of spend descriptions
169
- * @param outputDescriptions the list of output descriptions
170
- * @param signature signature hash
171
- * @param balance balance of the Sapling contract (input/output difference)
172
- * @param root root of the merkle tree
173
- * @returns Forged sapling transaction of type Buffer
174
- */
175
- forgeSaplingTransaction(tx) {
176
- const spendBuf = this.forgeSpendDescriptions(tx.inputs);
177
- const spend = Buffer.concat([toHexBuf(spendBuf.length, 32), spendBuf]);
178
- const outputBuf = this.forgeOutputDescriptions(tx.outputs);
179
- const output = Buffer.concat([toHexBuf(outputBuf.length, 32), outputBuf]);
180
- const root = Buffer.from(tx.root, 'hex');
181
- return Buffer.concat([
182
- spend,
183
- output,
184
- tx.signature,
185
- toHexBuf(tx.balance, 64),
186
- root,
187
- toHexBuf(tx.boundData.length, 32),
188
- tx.boundData,
189
- ]);
190
- }
191
- /**
192
- * @description Forge list of spend descriptions
193
- * @param spendDescriptions list of spend descriptions
194
- * @returns concatenated forged bytes of type Buffer
195
- */
196
- forgeSpendDescriptions(spendDescriptions) {
197
- const descriptions = [];
198
- for (const i of spendDescriptions) {
199
- const buff = this.forgeSpendDescription(i);
200
- descriptions.push(buff);
201
- }
202
- return Buffer.concat(descriptions);
203
- }
204
- forgeSpendDescription(desc) {
205
- return Buffer.concat([
206
- desc.commitmentValue,
207
- desc.nullifier,
208
- desc.publicKeyReRandomization,
209
- desc.proof,
210
- desc.signature,
211
- ]);
212
- }
213
- /**
214
- * @description Forge list of output descriptions
215
- * @param outputDescriptions list of output descriptions
216
- * @returns concatenated forged bytes of type Buffer
217
- */
218
- forgeOutputDescriptions(outputDescriptions) {
219
- const descriptions = [];
220
- for (const i of outputDescriptions) {
221
- const buff = this.forgeOutputDescription(i);
222
- descriptions.push(buff);
223
- }
224
- return Buffer.concat(descriptions);
225
- }
226
- forgeOutputDescription(desc) {
227
- const ct = desc.ciphertext;
228
- return Buffer.concat([
229
- desc.commitment,
230
- desc.proof,
231
- ct.commitmentValue,
232
- ct.ephemeralPublicKey,
233
- toHexBuf(ct.payloadEnc.length, 32),
234
- ct.payloadEnc,
235
- ct.nonceEnc,
236
- ct.payloadOut,
237
- ct.nonceOut,
238
- ]);
239
- }
240
- forgeUnsignedTxInput(unsignedSpendDescription) {
241
- return Buffer.concat([
242
- unsignedSpendDescription.commitmentValue,
243
- unsignedSpendDescription.nullifier,
244
- unsignedSpendDescription.publicKeyReRandomization,
245
- unsignedSpendDescription.proof,
246
- ]);
247
- }
248
- forgeTransactionPlaintext(txPlainText) {
249
- const encodedMemo = Buffer.from(char2Bytes(txPlainText.memo).padEnd(txPlainText.memoSize, '0'), 'hex');
250
- return Buffer.concat([
251
- txPlainText.diversifier,
252
- toHexBuf(new BigNumber(txPlainText.amount), 64),
253
- txPlainText.randomCommitmentTrapdoor,
254
- toHexBuf(txPlainText.memoSize, 32),
255
- encodedMemo,
256
- ]);
257
- }
167
+ class SaplingForger {
168
+ /**
169
+ * @description Forge sapling transactions
170
+ * @param spendDescriptions the list of spend descriptions
171
+ * @param outputDescriptions the list of output descriptions
172
+ * @param signature signature hash
173
+ * @param balance balance of the Sapling contract (input/output difference)
174
+ * @param root root of the merkle tree
175
+ * @returns Forged sapling transaction of type Buffer
176
+ */
177
+ forgeSaplingTransaction(tx) {
178
+ const spendBuf = this.forgeSpendDescriptions(tx.inputs);
179
+ const spend = Buffer.concat([toHexBuf(spendBuf.length, 32), spendBuf]);
180
+ const outputBuf = this.forgeOutputDescriptions(tx.outputs);
181
+ const output = Buffer.concat([toHexBuf(outputBuf.length, 32), outputBuf]);
182
+ const root = Buffer.from(tx.root, 'hex');
183
+ return Buffer.concat([
184
+ spend,
185
+ output,
186
+ tx.signature,
187
+ toHexBuf(tx.balance, 64),
188
+ root,
189
+ toHexBuf(tx.boundData.length, 32),
190
+ tx.boundData,
191
+ ]);
192
+ }
193
+ /**
194
+ * @description Forge list of spend descriptions
195
+ * @param spendDescriptions list of spend descriptions
196
+ * @returns concatenated forged bytes of type Buffer
197
+ */
198
+ forgeSpendDescriptions(spendDescriptions) {
199
+ const descriptions = [];
200
+ for (const i of spendDescriptions) {
201
+ const buff = this.forgeSpendDescription(i);
202
+ descriptions.push(buff);
203
+ }
204
+ return Buffer.concat(descriptions);
205
+ }
206
+ forgeSpendDescription(desc) {
207
+ return Buffer.concat([
208
+ desc.commitmentValue,
209
+ desc.nullifier,
210
+ desc.publicKeyReRandomization,
211
+ desc.proof,
212
+ desc.signature,
213
+ ]);
214
+ }
215
+ /**
216
+ * @description Forge list of output descriptions
217
+ * @param outputDescriptions list of output descriptions
218
+ * @returns concatenated forged bytes of type Buffer
219
+ */
220
+ forgeOutputDescriptions(outputDescriptions) {
221
+ const descriptions = [];
222
+ for (const i of outputDescriptions) {
223
+ const buff = this.forgeOutputDescription(i);
224
+ descriptions.push(buff);
225
+ }
226
+ return Buffer.concat(descriptions);
227
+ }
228
+ forgeOutputDescription(desc) {
229
+ const ct = desc.ciphertext;
230
+ return Buffer.concat([
231
+ desc.commitment,
232
+ desc.proof,
233
+ ct.commitmentValue,
234
+ ct.ephemeralPublicKey,
235
+ toHexBuf(ct.payloadEnc.length, 32),
236
+ ct.payloadEnc,
237
+ ct.nonceEnc,
238
+ ct.payloadOut,
239
+ ct.nonceOut,
240
+ ]);
241
+ }
242
+ forgeUnsignedTxInput(unsignedSpendDescription) {
243
+ return Buffer.concat([
244
+ unsignedSpendDescription.commitmentValue,
245
+ unsignedSpendDescription.nullifier,
246
+ unsignedSpendDescription.publicKeyReRandomization,
247
+ unsignedSpendDescription.proof,
248
+ ]);
249
+ }
250
+ forgeTransactionPlaintext(txPlainText) {
251
+ const encodedMemo = Buffer.from(char2Bytes(txPlainText.memo).padEnd(txPlainText.memoSize, '0'), 'hex');
252
+ return Buffer.concat([
253
+ txPlainText.diversifier,
254
+ toHexBuf(new BigNumber(txPlainText.amount), 64),
255
+ txPlainText.randomCommitmentTrapdoor,
256
+ toHexBuf(txPlainText.memoSize, 32),
257
+ encodedMemo,
258
+ ]);
259
+ }
258
260
  }
259
261
 
260
- const KDF_KEY = 'KDFSaplingForTezosV1';
261
- const OCK_KEY = 'OCK_keystringderivation_TEZOS';
262
- const DEFAULT_MEMO = '';
262
+ const KDF_KEY = 'KDFSaplingForTezosV1';
263
+ const OCK_KEY = 'OCK_keystringderivation_TEZOS';
264
+ const DEFAULT_MEMO = '';
263
265
  const DEFAULT_BOUND_DATA = Buffer.from('', 'hex');
264
266
 
265
- var _viewingKeyProvider, _readProvider$2, _saplingContractId;
266
- /**
267
- * @description Allows to retrieve and decrypt sapling transactions using on a viewing key
268
- *
269
- * @param inMemoryViewingKey Holds the sapling viewing key
270
- * @param saplingContractId Address of the sapling contract or sapling id if the smart contract contains multiple sapling states
271
- * @param readProvider Allows to read data from the blockchain
272
- */
273
- class SaplingTransactionViewer {
274
- constructor(inMemoryViewingKey, saplingContractId, readProvider) {
275
- _viewingKeyProvider.set(this, void 0);
276
- _readProvider$2.set(this, void 0);
277
- _saplingContractId.set(this, void 0);
278
- __classPrivateFieldSet(this, _viewingKeyProvider, inMemoryViewingKey);
279
- __classPrivateFieldSet(this, _saplingContractId, saplingContractId);
280
- __classPrivateFieldSet(this, _readProvider$2, readProvider);
281
- }
282
- /**
283
- * @description Retrieve the unspent balance associated with the configured viewing key and sapling state
284
- *
285
- * @returns the balance in mutez represented as a BigNumber
286
- *
287
- */
288
- getBalance() {
289
- return __awaiter(this, void 0, void 0, function* () {
290
- let balance = new BigNumber(0);
291
- const { commitments_and_ciphertexts, nullifiers } = yield this.getSaplingDiff();
292
- for (let i = 0; i < commitments_and_ciphertexts.length; i++) {
293
- const decrypted = yield this.decryptCiphertextAsReceiver(commitments_and_ciphertexts[i]);
294
- if (decrypted) {
295
- const valueBigNumber = convertValueToBigNumber(decrypted.value);
296
- const isSpent = yield this.isSpent(decrypted.paymentAddress, valueBigNumber.toString(), decrypted.randomCommitmentTrapdoor, i, nullifiers);
297
- if (!isSpent) {
298
- balance = balance.plus(valueBigNumber);
299
- }
300
- }
301
- }
302
- return balance;
303
- });
304
- }
305
- /**
306
- * @description Retrieve all the incoming and outgoing transactions associated with the configured viewing key.
307
- * The response properties are in Uint8Array format; use the getIncomingAndOutgoingTransactions method for readable properties
308
- *
309
- */
310
- getIncomingAndOutgoingTransactionsRaw() {
311
- return __awaiter(this, void 0, void 0, function* () {
312
- const incoming = [];
313
- const outgoing = [];
314
- const { commitments_and_ciphertexts, nullifiers } = yield this.getSaplingDiff();
315
- for (let i = 0; i < commitments_and_ciphertexts.length; i++) {
316
- const decryptedAsReceiver = yield this.decryptCiphertextAsReceiver(commitments_and_ciphertexts[i]);
317
- const decryptedAsSender = yield this.decryptCiphertextAsSender(commitments_and_ciphertexts[i]);
318
- if (decryptedAsReceiver) {
319
- const balance = convertValueToBigNumber(decryptedAsReceiver.value);
320
- const isSpent = yield this.isSpent(decryptedAsReceiver.paymentAddress, balance.toString(), decryptedAsReceiver.randomCommitmentTrapdoor, i, nullifiers);
321
- incoming.push(Object.assign(Object.assign({}, decryptedAsReceiver), { isSpent, position: i }));
322
- }
323
- if (decryptedAsSender) {
324
- outgoing.push(decryptedAsSender);
325
- }
326
- }
327
- return {
328
- incoming,
329
- outgoing,
330
- };
331
- });
332
- }
333
- /**
334
- * @description Retrieve all the incoming and outgoing decoded transactions associated with the configured viewing key
335
- *
336
- */
337
- getIncomingAndOutgoingTransactions() {
338
- return __awaiter(this, void 0, void 0, function* () {
339
- const tx = yield this.getIncomingAndOutgoingTransactionsRaw();
340
- const incoming = tx.incoming.map((_a) => {
341
- var { isSpent } = _a, rest = __rest(_a, ["isSpent"]);
342
- return Object.assign(Object.assign({}, readableFormat(rest)), { isSpent });
343
- });
344
- const outgoing = tx.outgoing.map((outgoingTx) => {
345
- return readableFormat(outgoingTx);
346
- });
347
- return { incoming, outgoing };
348
- });
349
- }
350
- getSaplingDiff() {
351
- return __awaiter(this, void 0, void 0, function* () {
352
- let saplingDiffResponse;
353
- if (__classPrivateFieldGet(this, _saplingContractId).saplingId) {
354
- saplingDiffResponse = yield __classPrivateFieldGet(this, _readProvider$2).getSaplingDiffById({ id: __classPrivateFieldGet(this, _saplingContractId).saplingId }, 'head');
355
- }
356
- else if (__classPrivateFieldGet(this, _saplingContractId).contractAddress) {
357
- saplingDiffResponse = yield __classPrivateFieldGet(this, _readProvider$2).getSaplingDiffByContract(__classPrivateFieldGet(this, _saplingContractId).contractAddress, 'head');
358
- }
359
- else {
360
- throw new SaplingTransactionViewerError('A contract address or a sapling id was expected in the SaplingTransactionViewer constructor.');
361
- }
362
- return saplingDiffResponse;
363
- });
364
- }
365
- decryptCiphertextAsReceiver(commitmentsAndCiphertexts) {
366
- return __awaiter(this, void 0, void 0, function* () {
367
- const commitment = commitmentsAndCiphertexts[0];
368
- const { epk, payload_enc, nonce_enc } = commitmentsAndCiphertexts[1];
369
- const incomingViewingKey = yield __classPrivateFieldGet(this, _viewingKeyProvider).getIncomingViewingKey();
370
- const keyAgreement = yield sapling.keyAgreement(epk, incomingViewingKey);
371
- const keyAgreementHash = blake.blake2b(keyAgreement, Buffer.from(KDF_KEY), 32);
372
- const decrypted = yield this.decryptCiphertext(keyAgreementHash, hex2buf(nonce_enc), hex2buf(payload_enc));
373
- if (decrypted) {
374
- const { diversifier, value, randomCommitmentTrapdoor: rcm, memo, } = this.extractTransactionProperties(decrypted);
375
- const paymentAddress = bufToUint8Array(yield sapling.getRawPaymentAddressFromIncomingViewingKey(incomingViewingKey, diversifier));
376
- try {
377
- const valid = yield sapling.verifyCommitment(commitment, paymentAddress, convertValueToBigNumber(value).toString(), rcm);
378
- if (valid) {
379
- return { value, memo, paymentAddress, randomCommitmentTrapdoor: rcm };
380
- }
381
- }
382
- catch (ex) {
383
- if (!/invalid value/.test(ex)) {
384
- throw ex;
385
- }
386
- }
387
- }
388
- });
389
- }
390
- decryptCiphertextAsSender(commitmentsAndCiphertexts) {
391
- return __awaiter(this, void 0, void 0, function* () {
392
- const commitment = commitmentsAndCiphertexts[0];
393
- const { epk, payload_enc, nonce_enc, payload_out, nonce_out, cv } = commitmentsAndCiphertexts[1];
394
- const outgoingViewingKey = yield __classPrivateFieldGet(this, _viewingKeyProvider).getOutgoingViewingKey();
395
- const concat = cv.concat(commitment, epk, outgoingViewingKey.toString('hex'));
396
- const outgoingCipherKey = blake.blake2b(Buffer.from(concat, 'hex'), Buffer.from(OCK_KEY), 32);
397
- const decryptedOut = yield this.decryptCiphertext(outgoingCipherKey, hex2buf(nonce_out), hex2buf(payload_out));
398
- if (decryptedOut) {
399
- const { recipientDiversifiedTransmissionKey: pkd, ephemeralPrivateKey: esk } = this.extractPkdAndEsk(decryptedOut);
400
- const keyAgreement = yield sapling.keyAgreement(pkd, esk);
401
- const keyAgreementHash = blake.blake2b(keyAgreement, Buffer.from(KDF_KEY), 32);
402
- const decryptedEnc = yield this.decryptCiphertext(keyAgreementHash, hex2buf(nonce_enc), hex2buf(payload_enc));
403
- if (decryptedEnc) {
404
- const { diversifier, value, randomCommitmentTrapdoor: rcm, memo, } = this.extractTransactionProperties(decryptedEnc);
405
- const paymentAddress = mergebuf(diversifier, pkd);
406
- try {
407
- const isValid = yield sapling.verifyCommitment(commitment, paymentAddress, convertValueToBigNumber(value).toString(), rcm);
408
- if (isValid) {
409
- return { value, memo, paymentAddress, randomCommitmentTrapdoor: rcm };
410
- }
411
- }
412
- catch (ex) {
413
- if (!/invalid value/.test(ex)) {
414
- throw ex;
415
- }
416
- }
417
- }
418
- }
419
- });
420
- }
421
- decryptCiphertext(keyAgreementHash, nonce, payload) {
422
- return __awaiter(this, void 0, void 0, function* () {
423
- return openSecretBox(keyAgreementHash, nonce, payload);
424
- });
425
- }
426
- extractTransactionProperties(decrypted) {
427
- return {
428
- diversifier: decrypted.slice(0, 11),
429
- value: decrypted.slice(11, 19),
430
- randomCommitmentTrapdoor: decrypted.slice(19, 51),
431
- memoSize: decrypted.slice(51, 55),
432
- memo: decrypted.slice(55),
433
- };
434
- }
435
- extractPkdAndEsk(decrypted) {
436
- return {
437
- recipientDiversifiedTransmissionKey: decrypted.slice(0, 32),
438
- ephemeralPrivateKey: decrypted.slice(32),
439
- };
440
- }
441
- isSpent(address, value, randomCommitmentTrapdoor, position, nullifiers) {
442
- return __awaiter(this, void 0, void 0, function* () {
443
- const computedNullifier = yield sapling.computeNullifier(__classPrivateFieldGet(this, _viewingKeyProvider).getFullViewingKey(), address, value, randomCommitmentTrapdoor, position);
444
- return nullifiers.includes(computedNullifier.toString('hex'));
445
- });
446
- }
447
- }
448
- _viewingKeyProvider = new WeakMap(), _readProvider$2 = new WeakMap(), _saplingContractId = new WeakMap();
267
+ var _SaplingTransactionViewer_viewingKeyProvider, _SaplingTransactionViewer_readProvider, _SaplingTransactionViewer_saplingContractId;
268
+ /**
269
+ * @description Allows to retrieve and decrypt sapling transactions using on a viewing key
270
+ *
271
+ * @param inMemoryViewingKey Holds the sapling viewing key
272
+ * @param saplingContractId Address of the sapling contract or sapling id if the smart contract contains multiple sapling states
273
+ * @param readProvider Allows to read data from the blockchain
274
+ */
275
+ class SaplingTransactionViewer {
276
+ constructor(inMemoryViewingKey, saplingContractId, readProvider) {
277
+ _SaplingTransactionViewer_viewingKeyProvider.set(this, void 0);
278
+ _SaplingTransactionViewer_readProvider.set(this, void 0);
279
+ _SaplingTransactionViewer_saplingContractId.set(this, void 0);
280
+ __classPrivateFieldSet(this, _SaplingTransactionViewer_viewingKeyProvider, inMemoryViewingKey, "f");
281
+ __classPrivateFieldSet(this, _SaplingTransactionViewer_saplingContractId, saplingContractId, "f");
282
+ __classPrivateFieldSet(this, _SaplingTransactionViewer_readProvider, readProvider, "f");
283
+ }
284
+ /**
285
+ * @description Retrieve the unspent balance associated with the configured viewing key and sapling state
286
+ *
287
+ * @returns the balance in mutez represented as a BigNumber
288
+ *
289
+ */
290
+ getBalance() {
291
+ return __awaiter(this, void 0, void 0, function* () {
292
+ let balance = new BigNumber(0);
293
+ const { commitments_and_ciphertexts, nullifiers } = yield this.getSaplingDiff();
294
+ for (let i = 0; i < commitments_and_ciphertexts.length; i++) {
295
+ const decrypted = yield this.decryptCiphertextAsReceiver(commitments_and_ciphertexts[i]);
296
+ if (decrypted) {
297
+ const valueBigNumber = convertValueToBigNumber(decrypted.value);
298
+ const isSpent = yield this.isSpent(decrypted.paymentAddress, valueBigNumber.toString(), decrypted.randomCommitmentTrapdoor, i, nullifiers);
299
+ if (!isSpent) {
300
+ balance = balance.plus(valueBigNumber);
301
+ }
302
+ }
303
+ }
304
+ return balance;
305
+ });
306
+ }
307
+ /**
308
+ * @description Retrieve all the incoming and outgoing transactions associated with the configured viewing key.
309
+ * The response properties are in Uint8Array format; use the getIncomingAndOutgoingTransactions method for readable properties
310
+ *
311
+ */
312
+ getIncomingAndOutgoingTransactionsRaw() {
313
+ return __awaiter(this, void 0, void 0, function* () {
314
+ const incoming = [];
315
+ const outgoing = [];
316
+ const { commitments_and_ciphertexts, nullifiers } = yield this.getSaplingDiff();
317
+ for (let i = 0; i < commitments_and_ciphertexts.length; i++) {
318
+ const decryptedAsReceiver = yield this.decryptCiphertextAsReceiver(commitments_and_ciphertexts[i]);
319
+ const decryptedAsSender = yield this.decryptCiphertextAsSender(commitments_and_ciphertexts[i]);
320
+ if (decryptedAsReceiver) {
321
+ const balance = convertValueToBigNumber(decryptedAsReceiver.value);
322
+ const isSpent = yield this.isSpent(decryptedAsReceiver.paymentAddress, balance.toString(), decryptedAsReceiver.randomCommitmentTrapdoor, i, nullifiers);
323
+ incoming.push(Object.assign(Object.assign({}, decryptedAsReceiver), { isSpent, position: i }));
324
+ }
325
+ if (decryptedAsSender) {
326
+ outgoing.push(decryptedAsSender);
327
+ }
328
+ }
329
+ return {
330
+ incoming,
331
+ outgoing,
332
+ };
333
+ });
334
+ }
335
+ /**
336
+ * @description Retrieve all the incoming and outgoing decoded transactions associated with the configured viewing key
337
+ *
338
+ */
339
+ getIncomingAndOutgoingTransactions() {
340
+ return __awaiter(this, void 0, void 0, function* () {
341
+ const tx = yield this.getIncomingAndOutgoingTransactionsRaw();
342
+ const incoming = tx.incoming.map((_a) => {
343
+ var { isSpent } = _a, rest = __rest(_a, ["isSpent"]);
344
+ return Object.assign(Object.assign({}, readableFormat(rest)), { isSpent });
345
+ });
346
+ const outgoing = tx.outgoing.map((outgoingTx) => {
347
+ return readableFormat(outgoingTx);
348
+ });
349
+ return { incoming, outgoing };
350
+ });
351
+ }
352
+ getSaplingDiff() {
353
+ return __awaiter(this, void 0, void 0, function* () {
354
+ let saplingDiffResponse;
355
+ if (__classPrivateFieldGet(this, _SaplingTransactionViewer_saplingContractId, "f").saplingId) {
356
+ saplingDiffResponse = yield __classPrivateFieldGet(this, _SaplingTransactionViewer_readProvider, "f").getSaplingDiffById({ id: __classPrivateFieldGet(this, _SaplingTransactionViewer_saplingContractId, "f").saplingId }, 'head');
357
+ }
358
+ else if (__classPrivateFieldGet(this, _SaplingTransactionViewer_saplingContractId, "f").contractAddress) {
359
+ saplingDiffResponse = yield __classPrivateFieldGet(this, _SaplingTransactionViewer_readProvider, "f").getSaplingDiffByContract(__classPrivateFieldGet(this, _SaplingTransactionViewer_saplingContractId, "f").contractAddress, 'head');
360
+ }
361
+ else {
362
+ throw new SaplingTransactionViewerError('A contract address or a sapling id was expected in the SaplingTransactionViewer constructor.');
363
+ }
364
+ return saplingDiffResponse;
365
+ });
366
+ }
367
+ decryptCiphertextAsReceiver(commitmentsAndCiphertexts) {
368
+ return __awaiter(this, void 0, void 0, function* () {
369
+ const commitment = commitmentsAndCiphertexts[0];
370
+ const { epk, payload_enc, nonce_enc } = commitmentsAndCiphertexts[1];
371
+ const incomingViewingKey = yield __classPrivateFieldGet(this, _SaplingTransactionViewer_viewingKeyProvider, "f").getIncomingViewingKey();
372
+ const keyAgreement = yield sapling.keyAgreement(epk, incomingViewingKey);
373
+ const keyAgreementHash = blake.blake2b(keyAgreement, Buffer.from(KDF_KEY), 32);
374
+ const decrypted = yield this.decryptCiphertext(keyAgreementHash, hex2buf(nonce_enc), hex2buf(payload_enc));
375
+ if (decrypted) {
376
+ const { diversifier, value, randomCommitmentTrapdoor: rcm, memo, } = this.extractTransactionProperties(decrypted);
377
+ const paymentAddress = bufToUint8Array(yield sapling.getRawPaymentAddressFromIncomingViewingKey(incomingViewingKey, diversifier));
378
+ try {
379
+ const valid = yield sapling.verifyCommitment(commitment, paymentAddress, convertValueToBigNumber(value).toString(), rcm);
380
+ if (valid) {
381
+ return { value, memo, paymentAddress, randomCommitmentTrapdoor: rcm };
382
+ }
383
+ }
384
+ catch (ex) {
385
+ if (!/invalid value/.test(ex)) {
386
+ throw ex;
387
+ }
388
+ }
389
+ }
390
+ });
391
+ }
392
+ decryptCiphertextAsSender(commitmentsAndCiphertexts) {
393
+ return __awaiter(this, void 0, void 0, function* () {
394
+ const commitment = commitmentsAndCiphertexts[0];
395
+ const { epk, payload_enc, nonce_enc, payload_out, nonce_out, cv } = commitmentsAndCiphertexts[1];
396
+ const outgoingViewingKey = yield __classPrivateFieldGet(this, _SaplingTransactionViewer_viewingKeyProvider, "f").getOutgoingViewingKey();
397
+ const concat = cv.concat(commitment, epk, outgoingViewingKey.toString('hex'));
398
+ const outgoingCipherKey = blake.blake2b(Buffer.from(concat, 'hex'), Buffer.from(OCK_KEY), 32);
399
+ const decryptedOut = yield this.decryptCiphertext(outgoingCipherKey, hex2buf(nonce_out), hex2buf(payload_out));
400
+ if (decryptedOut) {
401
+ const { recipientDiversifiedTransmissionKey: pkd, ephemeralPrivateKey: esk } = this.extractPkdAndEsk(decryptedOut);
402
+ const keyAgreement = yield sapling.keyAgreement(pkd, esk);
403
+ const keyAgreementHash = blake.blake2b(keyAgreement, Buffer.from(KDF_KEY), 32);
404
+ const decryptedEnc = yield this.decryptCiphertext(keyAgreementHash, hex2buf(nonce_enc), hex2buf(payload_enc));
405
+ if (decryptedEnc) {
406
+ const { diversifier, value, randomCommitmentTrapdoor: rcm, memo, } = this.extractTransactionProperties(decryptedEnc);
407
+ const paymentAddress = mergebuf(diversifier, pkd);
408
+ try {
409
+ const isValid = yield sapling.verifyCommitment(commitment, paymentAddress, convertValueToBigNumber(value).toString(), rcm);
410
+ if (isValid) {
411
+ return { value, memo, paymentAddress, randomCommitmentTrapdoor: rcm };
412
+ }
413
+ }
414
+ catch (ex) {
415
+ if (!/invalid value/.test(ex)) {
416
+ throw ex;
417
+ }
418
+ }
419
+ }
420
+ }
421
+ });
422
+ }
423
+ decryptCiphertext(keyAgreementHash, nonce, payload) {
424
+ return __awaiter(this, void 0, void 0, function* () {
425
+ return openSecretBox(keyAgreementHash, nonce, payload);
426
+ });
427
+ }
428
+ extractTransactionProperties(decrypted) {
429
+ return {
430
+ diversifier: decrypted.slice(0, 11),
431
+ value: decrypted.slice(11, 19),
432
+ randomCommitmentTrapdoor: decrypted.slice(19, 51),
433
+ memoSize: decrypted.slice(51, 55),
434
+ memo: decrypted.slice(55),
435
+ };
436
+ }
437
+ extractPkdAndEsk(decrypted) {
438
+ return {
439
+ recipientDiversifiedTransmissionKey: decrypted.slice(0, 32),
440
+ ephemeralPrivateKey: decrypted.slice(32),
441
+ };
442
+ }
443
+ isSpent(address, value, randomCommitmentTrapdoor, position, nullifiers) {
444
+ return __awaiter(this, void 0, void 0, function* () {
445
+ const computedNullifier = yield sapling.computeNullifier(__classPrivateFieldGet(this, _SaplingTransactionViewer_viewingKeyProvider, "f").getFullViewingKey(), address, value, randomCommitmentTrapdoor, position);
446
+ return nullifiers.includes(computedNullifier.toString('hex'));
447
+ });
448
+ }
449
+ }
450
+ _SaplingTransactionViewer_viewingKeyProvider = new WeakMap(), _SaplingTransactionViewer_readProvider = new WeakMap(), _SaplingTransactionViewer_saplingContractId = new WeakMap();
449
451
 
450
- /**
451
- *
452
- * @param leaves nodes in the tree that we would like to make pairs from
453
- * @returns a paired/chunked array: [a, b, c, d] => [[a, b], [c, d]]
454
- */
455
- function pairNodes(leaves) {
456
- const pairs = new Array(Math.ceil(leaves.length / 2));
457
- for (let i = 0; i < leaves.length / 2; i++) {
458
- pairs[i] = leaves.slice(i * 2, i * 2 + 2);
459
- }
460
- return pairs;
461
- }
462
- /**
463
- * @description helper function to assist in Lazy initializing an object
464
- */
465
- class Lazy {
466
- constructor(init) {
467
- this.init = init;
468
- this.isInitialized = false;
469
- this.value = undefined;
470
- }
471
- // initializes the lazily initiated object
472
- get() {
473
- return __awaiter(this, void 0, void 0, function* () {
474
- if (!this.isInitialized) {
475
- this.value = yield this.init();
476
- this.isInitialized = true;
477
- }
478
- return this.value;
479
- });
480
- }
481
- }
482
- /**
483
- *
484
- * @param hex hexadecimal string we would like to swap
485
- * @returns a hexadecimal string with swapped endians
486
- */
487
- const changeEndianness = (hex) => {
488
- if (hex.length % 2 != 0) {
489
- hex = '0' + hex;
490
- }
491
- const bytes = hex.match(/.{2}/g) || [];
492
- return bytes.reverse().join('');
452
+ /**
453
+ *
454
+ * @param leaves nodes in the tree that we would like to make pairs from
455
+ * @returns a paired/chunked array: [a, b, c, d] => [[a, b], [c, d]]
456
+ */
457
+ function pairNodes(leaves) {
458
+ const pairs = new Array(Math.ceil(leaves.length / 2));
459
+ for (let i = 0; i < leaves.length / 2; i++) {
460
+ pairs[i] = leaves.slice(i * 2, i * 2 + 2);
461
+ }
462
+ return pairs;
463
+ }
464
+ /**
465
+ * @description helper function to assist in Lazy initializing an object
466
+ */
467
+ class Lazy {
468
+ constructor(init) {
469
+ this.init = init;
470
+ this.isInitialized = false;
471
+ this.value = undefined;
472
+ }
473
+ // initializes the lazily initiated object
474
+ get() {
475
+ return __awaiter(this, void 0, void 0, function* () {
476
+ if (!this.isInitialized) {
477
+ this.value = yield this.init();
478
+ this.isInitialized = true;
479
+ }
480
+ return this.value;
481
+ });
482
+ }
483
+ }
484
+ /**
485
+ *
486
+ * @param hex hexadecimal string we would like to swap
487
+ * @returns a hexadecimal string with swapped endians
488
+ */
489
+ const changeEndianness = (hex) => {
490
+ if (hex.length % 2 != 0) {
491
+ hex = '0' + hex;
492
+ }
493
+ const bytes = hex.match(/.{2}/g) || [];
494
+ return bytes.reverse().join('');
493
495
  };
494
496
 
495
- /**
496
- * Some code in this file was originally written or inspired by Airgap-it
497
- * https://github.com/airgap-it/airgap-coin-lib/blob/master/LICENSE.md
498
- *
499
- */
500
- /**
501
- * @description The SaplingState class's main purpose is to provide a Merkle path for the forger and the transaction builder, so that it may verify that the Sapling transaction is valid
502
- *
503
- */
504
- class SaplingState {
505
- constructor(height) {
506
- this.height = height;
507
- this.uncommittedMerkleHash = '0100000000000000000000000000000000000000000000000000000000000000';
508
- this.uncommittedMerkleHashes = new Lazy(() => this.createUncommittedMerkleHashes());
509
- }
510
- getStateTree(stateDiff, constructTree = true) {
511
- return __awaiter(this, void 0, void 0, function* () {
512
- if (this.stateTree !== undefined && this.stateTree.root === stateDiff.root) {
513
- return this.stateTree;
514
- }
515
- const commitments = stateDiff.commitments_and_ciphertexts.map(([commitment, _]) => commitment);
516
- let merkleTree;
517
- if (constructTree) {
518
- merkleTree = yield this.constructMerkleTree(commitments, 0);
519
- yield this.validateMerkleTree(merkleTree, stateDiff.root);
520
- }
521
- this.stateTree = {
522
- height: this.height,
523
- size: commitments.length,
524
- root: stateDiff.root,
525
- tree: merkleTree,
526
- };
527
- return this.stateTree;
528
- });
529
- }
530
- /**
531
- *
532
- * @param stateTree stateTree parameter that holds information details on our Merkle tree
533
- * @param position position of the hash in the Merkle tree
534
- * @returns a promise of a string that serves as the Merkle path that can be passed on to the Sapling forger or the transaction builder
535
- */
536
- getWitness(stateTree, position) {
537
- return __awaiter(this, void 0, void 0, function* () {
538
- const heightBuffer = hex2Bytes(changeEndianness(num2PaddedHex(stateTree.height)));
539
- const posBuffer = hex2Bytes(changeEndianness(num2PaddedHex(position, 64)));
540
- const neighbouringHashes = yield this.getNeighbouringHashes([], stateTree.height, position, stateTree.tree);
541
- const witness = neighbouringHashes
542
- .map((hash) => Buffer.concat([hex2Bytes(changeEndianness(num2PaddedHex(hash.length))), hash]))
543
- .reverse()
544
- .reduce((acc, next) => Buffer.concat([acc, next]));
545
- return Buffer.concat([heightBuffer, witness, posBuffer]).toString('hex');
546
- });
547
- }
548
- /**
549
- *
550
- * @param leaves array of leaves or nodes that we want to construct the Merkle tree from
551
- * @param height height of the desired Merkle tree
552
- * @returns a promise of MerkleTree type object
553
- */
554
- constructMerkleTree(leaves, height) {
555
- return __awaiter(this, void 0, void 0, function* () {
556
- if (height === this.height && leaves.length === 1) {
557
- return leaves[0];
558
- }
559
- if (height === this.height || leaves.length > Math.pow(2, this.height - 1 - height)) {
560
- throw new TreeConstructionFailure('Children length exceeds maximum number of nodes in a merkle tree');
561
- }
562
- const pairedLeaves = pairNodes(leaves);
563
- const updatedLeaves = yield Promise.all(pairedLeaves.map((chunk) => __awaiter(this, void 0, void 0, function* () {
564
- const left = yield this.getMerkleHash(chunk[0], height);
565
- const right = yield this.getMerkleHash(chunk[1], height);
566
- const parentHash = yield merkleHash(height, left, right);
567
- return [parentHash.toString('hex'), chunk[0], chunk[1]];
568
- })));
569
- return this.constructMerkleTree(updatedLeaves, height + 1);
570
- });
571
- }
572
- getMerkleHash(tree, height) {
573
- return __awaiter(this, void 0, void 0, function* () {
574
- if (tree === undefined) {
575
- return (yield this.uncommittedMerkleHashes.get())[height];
576
- }
577
- else if (typeof tree === 'string') {
578
- return Buffer.from(tree, 'hex');
579
- }
580
- else {
581
- return Buffer.from(tree[0], 'hex');
582
- }
583
- });
584
- }
585
- /**
586
- *
587
- * @returns hashes of empty or null values to fill in the Merkle tree
588
- */
589
- createUncommittedMerkleHashes() {
590
- return __awaiter(this, void 0, void 0, function* () {
591
- const res = new Array(this.height);
592
- res[0] = Buffer.from(this.uncommittedMerkleHash, 'hex');
593
- for (let i = 0; i < this.height; i++) {
594
- const hash = res[i];
595
- res[i + 1] = yield merkleHash(i, hash, hash);
596
- }
597
- return res;
598
- });
599
- }
600
- /**
601
- *
602
- * @param tree Merkle tree to validate
603
- * @param expectedRoot the expected merkle root to validate against
604
- * @throws {@link InvalidMerkleTreeError}
605
- */
606
- validateMerkleTree(tree, expectedRoot) {
607
- return __awaiter(this, void 0, void 0, function* () {
608
- const root = yield this.getMerkleHash(tree, this.height - 1);
609
- if (root.toString('hex') !== expectedRoot) {
610
- throw new InvalidMerkleTreeError(root.toString('hex'));
611
- }
612
- });
613
- }
614
- /**
615
- *
616
- * @param acc accumulator variable for the recursive function
617
- * @param height height of the tree
618
- * @param position position of the hash we would like find the neighbours of
619
- * @param tree the Merkle tree that we want to traverse
620
- * @returns the accumulated Buffer array of neighbouring hashes
621
- */
622
- getNeighbouringHashes(acc, height, position, tree) {
623
- return __awaiter(this, void 0, void 0, function* () {
624
- if (typeof tree === 'undefined') {
625
- throw new Error();
626
- }
627
- else if (typeof tree === 'string') {
628
- return acc;
629
- }
630
- else {
631
- let nextPos, nextTree, otherTree;
632
- const fullTree = new BigNumber(2).pow(height - 1);
633
- if (position.lt(fullTree)) {
634
- nextPos = position;
635
- nextTree = tree[1];
636
- otherTree = tree[2];
637
- }
638
- else {
639
- nextPos = position.minus(fullTree);
640
- nextTree = tree[2];
641
- otherTree = tree[1];
642
- }
643
- return this.getNeighbouringHashes([yield this.getMerkleHash(otherTree, height - 1), ...acc], height - 1, nextPos, nextTree);
644
- }
645
- });
646
- }
497
+ /**
498
+ * Some code in this file was originally written or inspired by Airgap-it
499
+ * https://github.com/airgap-it/airgap-coin-lib/blob/master/LICENSE.md
500
+ *
501
+ */
502
+ /**
503
+ * @description The SaplingState class's main purpose is to provide a Merkle path for the forger and the transaction builder, so that it may verify that the Sapling transaction is valid
504
+ *
505
+ */
506
+ class SaplingState {
507
+ constructor(height) {
508
+ this.height = height;
509
+ this.uncommittedMerkleHash = '0100000000000000000000000000000000000000000000000000000000000000';
510
+ this.uncommittedMerkleHashes = new Lazy(() => this.createUncommittedMerkleHashes());
511
+ }
512
+ getStateTree(stateDiff, constructTree = true) {
513
+ return __awaiter(this, void 0, void 0, function* () {
514
+ if (this.stateTree !== undefined && this.stateTree.root === stateDiff.root) {
515
+ return this.stateTree;
516
+ }
517
+ const commitments = stateDiff.commitments_and_ciphertexts.map(([commitment, _]) => commitment);
518
+ let merkleTree;
519
+ if (constructTree) {
520
+ merkleTree = yield this.constructMerkleTree(commitments, 0);
521
+ yield this.validateMerkleTree(merkleTree, stateDiff.root);
522
+ }
523
+ this.stateTree = {
524
+ height: this.height,
525
+ size: commitments.length,
526
+ root: stateDiff.root,
527
+ tree: merkleTree,
528
+ };
529
+ return this.stateTree;
530
+ });
531
+ }
532
+ /**
533
+ *
534
+ * @param stateTree stateTree parameter that holds information details on our Merkle tree
535
+ * @param position position of the hash in the Merkle tree
536
+ * @returns a promise of a string that serves as the Merkle path that can be passed on to the Sapling forger or the transaction builder
537
+ */
538
+ getWitness(stateTree, position) {
539
+ return __awaiter(this, void 0, void 0, function* () {
540
+ const heightBuffer = hex2Bytes(changeEndianness(num2PaddedHex(stateTree.height)));
541
+ const posBuffer = hex2Bytes(changeEndianness(num2PaddedHex(position, 64)));
542
+ const neighbouringHashes = yield this.getNeighbouringHashes([], stateTree.height, position, stateTree.tree);
543
+ const witness = neighbouringHashes
544
+ .map((hash) => Buffer.concat([hex2Bytes(changeEndianness(num2PaddedHex(hash.length))), hash]))
545
+ .reverse()
546
+ .reduce((acc, next) => Buffer.concat([acc, next]));
547
+ return Buffer.concat([heightBuffer, witness, posBuffer]).toString('hex');
548
+ });
549
+ }
550
+ /**
551
+ *
552
+ * @param leaves array of leaves or nodes that we want to construct the Merkle tree from
553
+ * @param height height of the desired Merkle tree
554
+ * @returns a promise of MerkleTree type object
555
+ */
556
+ constructMerkleTree(leaves, height) {
557
+ return __awaiter(this, void 0, void 0, function* () {
558
+ if (height === this.height && leaves.length === 1) {
559
+ return leaves[0];
560
+ }
561
+ if (height === this.height || leaves.length > Math.pow(2, this.height - 1 - height)) {
562
+ throw new TreeConstructionFailure('Children length exceeds maximum number of nodes in a merkle tree');
563
+ }
564
+ const pairedLeaves = pairNodes(leaves);
565
+ const updatedLeaves = yield Promise.all(pairedLeaves.map((chunk) => __awaiter(this, void 0, void 0, function* () {
566
+ const left = yield this.getMerkleHash(chunk[0], height);
567
+ const right = yield this.getMerkleHash(chunk[1], height);
568
+ const parentHash = yield merkleHash(height, left, right);
569
+ return [parentHash.toString('hex'), chunk[0], chunk[1]];
570
+ })));
571
+ return this.constructMerkleTree(updatedLeaves, height + 1);
572
+ });
573
+ }
574
+ getMerkleHash(tree, height) {
575
+ return __awaiter(this, void 0, void 0, function* () {
576
+ if (tree === undefined) {
577
+ return (yield this.uncommittedMerkleHashes.get())[height];
578
+ }
579
+ else if (typeof tree === 'string') {
580
+ return Buffer.from(tree, 'hex');
581
+ }
582
+ else {
583
+ return Buffer.from(tree[0], 'hex');
584
+ }
585
+ });
586
+ }
587
+ /**
588
+ *
589
+ * @returns hashes of empty or null values to fill in the Merkle tree
590
+ */
591
+ createUncommittedMerkleHashes() {
592
+ return __awaiter(this, void 0, void 0, function* () {
593
+ const res = new Array(this.height);
594
+ res[0] = Buffer.from(this.uncommittedMerkleHash, 'hex');
595
+ for (let i = 0; i < this.height; i++) {
596
+ const hash = res[i];
597
+ res[i + 1] = yield merkleHash(i, hash, hash);
598
+ }
599
+ return res;
600
+ });
601
+ }
602
+ /**
603
+ *
604
+ * @param tree Merkle tree to validate
605
+ * @param expectedRoot the expected merkle root to validate against
606
+ * @throws {@link InvalidMerkleTreeError}
607
+ */
608
+ validateMerkleTree(tree, expectedRoot) {
609
+ return __awaiter(this, void 0, void 0, function* () {
610
+ const root = yield this.getMerkleHash(tree, this.height - 1);
611
+ if (root.toString('hex') !== expectedRoot) {
612
+ throw new InvalidMerkleTreeError(root.toString('hex'));
613
+ }
614
+ });
615
+ }
616
+ /**
617
+ *
618
+ * @param acc accumulator variable for the recursive function
619
+ * @param height height of the tree
620
+ * @param position position of the hash we would like find the neighbours of
621
+ * @param tree the Merkle tree that we want to traverse
622
+ * @returns the accumulated Buffer array of neighbouring hashes
623
+ */
624
+ getNeighbouringHashes(acc, height, position, tree) {
625
+ return __awaiter(this, void 0, void 0, function* () {
626
+ if (typeof tree === 'undefined') {
627
+ throw new Error();
628
+ }
629
+ else if (typeof tree === 'string') {
630
+ return acc;
631
+ }
632
+ else {
633
+ let nextPos, nextTree, otherTree;
634
+ const fullTree = new BigNumber(2).pow(height - 1);
635
+ if (position.lt(fullTree)) {
636
+ nextPos = position;
637
+ nextTree = tree[1];
638
+ otherTree = tree[2];
639
+ }
640
+ else {
641
+ nextPos = position.minus(fullTree);
642
+ nextTree = tree[2];
643
+ otherTree = tree[1];
644
+ }
645
+ return this.getNeighbouringHashes([yield this.getMerkleHash(otherTree, height - 1), ...acc], height - 1, nextPos, nextTree);
646
+ }
647
+ });
648
+ }
647
649
  }
648
650
 
649
- // eslint-disable-next-line @typescript-eslint/no-var-requires
650
- const saplingOutputParams = require('../saplingOutputParams');
651
- // eslint-disable-next-line @typescript-eslint/no-var-requires
652
- const saplingSpendParams = require('../saplingSpendParams');
653
- class SaplingWrapper {
654
- withProvingContext(action) {
655
- return __awaiter(this, void 0, void 0, function* () {
656
- yield this.initSaplingParameters();
657
- return sapling.withProvingContext(action);
658
- });
659
- }
660
- getRandomBytes(length) {
661
- return randomBytes(length);
662
- }
663
- randR() {
664
- return __awaiter(this, void 0, void 0, function* () {
665
- return sapling.randR();
666
- });
667
- }
668
- getOutgoingViewingKey(vk) {
669
- return __awaiter(this, void 0, void 0, function* () {
670
- return sapling.getOutgoingViewingKey(vk);
671
- });
672
- }
673
- preparePartialOutputDescription(parametersOutputProof) {
674
- return __awaiter(this, void 0, void 0, function* () {
675
- const partialOutputDesc = yield sapling.preparePartialOutputDescription(parametersOutputProof.saplingContext, parametersOutputProof.address, parametersOutputProof.randomCommitmentTrapdoor, parametersOutputProof.ephemeralPrivateKey, parametersOutputProof.amount);
676
- return {
677
- commitmentValue: partialOutputDesc.cv,
678
- commitment: partialOutputDesc.cm,
679
- proof: partialOutputDesc.proof,
680
- };
681
- });
682
- }
683
- getDiversifiedFromRawPaymentAddress(decodedDestination) {
684
- return __awaiter(this, void 0, void 0, function* () {
685
- return sapling.getDiversifiedFromRawPaymentAddress(decodedDestination);
686
- });
687
- }
688
- deriveEphemeralPublicKey(diversifier, esk) {
689
- return __awaiter(this, void 0, void 0, function* () {
690
- return sapling.deriveEphemeralPublicKey(diversifier, esk);
691
- });
692
- }
693
- getPkdFromRawPaymentAddress(destination) {
694
- return __awaiter(this, void 0, void 0, function* () {
695
- return sapling.getPkdFromRawPaymentAddress(destination);
696
- });
697
- }
698
- keyAgreement(p, sk) {
699
- return __awaiter(this, void 0, void 0, function* () {
700
- return sapling.keyAgreement(p, sk);
701
- });
702
- }
703
- createBindingSignature(saplingContext, balance, transactionSigHash) {
704
- return __awaiter(this, void 0, void 0, function* () {
705
- return sapling.createBindingSignature(saplingContext, balance, transactionSigHash);
706
- });
707
- }
708
- initSaplingParameters() {
709
- return __awaiter(this, void 0, void 0, function* () {
710
- const spendParams = Buffer.from(saplingSpendParams.saplingSpendParams, 'base64');
711
- const outputParams = Buffer.from(saplingOutputParams.saplingOutputParams, 'base64');
712
- return sapling.initParameters(spendParams, outputParams);
713
- });
714
- }
651
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
652
+ const saplingOutputParams = require('../saplingOutputParams');
653
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
654
+ const saplingSpendParams = require('../saplingSpendParams');
655
+ class SaplingWrapper {
656
+ withProvingContext(action) {
657
+ return __awaiter(this, void 0, void 0, function* () {
658
+ yield this.initSaplingParameters();
659
+ return sapling.withProvingContext(action);
660
+ });
661
+ }
662
+ getRandomBytes(length) {
663
+ return randomBytes(length);
664
+ }
665
+ randR() {
666
+ return __awaiter(this, void 0, void 0, function* () {
667
+ return sapling.randR();
668
+ });
669
+ }
670
+ getOutgoingViewingKey(vk) {
671
+ return __awaiter(this, void 0, void 0, function* () {
672
+ return sapling.getOutgoingViewingKey(vk);
673
+ });
674
+ }
675
+ preparePartialOutputDescription(parametersOutputProof) {
676
+ return __awaiter(this, void 0, void 0, function* () {
677
+ const partialOutputDesc = yield sapling.preparePartialOutputDescription(parametersOutputProof.saplingContext, parametersOutputProof.address, parametersOutputProof.randomCommitmentTrapdoor, parametersOutputProof.ephemeralPrivateKey, parametersOutputProof.amount);
678
+ return {
679
+ commitmentValue: partialOutputDesc.cv,
680
+ commitment: partialOutputDesc.cm,
681
+ proof: partialOutputDesc.proof,
682
+ };
683
+ });
684
+ }
685
+ getDiversifiedFromRawPaymentAddress(decodedDestination) {
686
+ return __awaiter(this, void 0, void 0, function* () {
687
+ return sapling.getDiversifiedFromRawPaymentAddress(decodedDestination);
688
+ });
689
+ }
690
+ deriveEphemeralPublicKey(diversifier, esk) {
691
+ return __awaiter(this, void 0, void 0, function* () {
692
+ return sapling.deriveEphemeralPublicKey(diversifier, esk);
693
+ });
694
+ }
695
+ getPkdFromRawPaymentAddress(destination) {
696
+ return __awaiter(this, void 0, void 0, function* () {
697
+ return sapling.getPkdFromRawPaymentAddress(destination);
698
+ });
699
+ }
700
+ keyAgreement(p, sk) {
701
+ return __awaiter(this, void 0, void 0, function* () {
702
+ return sapling.keyAgreement(p, sk);
703
+ });
704
+ }
705
+ createBindingSignature(saplingContext, balance, transactionSigHash) {
706
+ return __awaiter(this, void 0, void 0, function* () {
707
+ return sapling.createBindingSignature(saplingContext, balance, transactionSigHash);
708
+ });
709
+ }
710
+ initSaplingParameters() {
711
+ return __awaiter(this, void 0, void 0, function* () {
712
+ const spendParams = Buffer.from(saplingSpendParams.saplingSpendParams, 'base64');
713
+ const outputParams = Buffer.from(saplingOutputParams.saplingOutputParams, 'base64');
714
+ return sapling.initParameters(spendParams, outputParams);
715
+ });
716
+ }
715
717
  }
716
718
 
717
- var _inMemorySpendingKey$1, _inMemoryProvingKey, _saplingForger$1, _contractAddress$1, _saplingId$1, _memoSize$1, _readProvider$1, _saplingWrapper, _chainId, _saplingState;
718
- class SaplingTransactionBuilder {
719
- constructor(keys, saplingForger, saplingContractDetails, readProvider, saplingWrapper = new SaplingWrapper()) {
720
- _inMemorySpendingKey$1.set(this, void 0);
721
- _inMemoryProvingKey.set(this, void 0);
722
- _saplingForger$1.set(this, void 0);
723
- _contractAddress$1.set(this, void 0);
724
- _saplingId$1.set(this, void 0);
725
- _memoSize$1.set(this, void 0);
726
- _readProvider$1.set(this, void 0);
727
- _saplingWrapper.set(this, void 0);
728
- _chainId.set(this, void 0);
729
- _saplingState.set(this, void 0);
730
- __classPrivateFieldSet(this, _saplingForger$1, saplingForger);
731
- __classPrivateFieldSet(this, _contractAddress$1, saplingContractDetails.contractAddress);
732
- __classPrivateFieldSet(this, _memoSize$1, saplingContractDetails.memoSize);
733
- __classPrivateFieldSet(this, _inMemorySpendingKey$1, keys.saplingSigner);
734
- __classPrivateFieldSet(this, _inMemoryProvingKey, keys.saplingProver);
735
- __classPrivateFieldSet(this, _saplingState, new SaplingState(32));
736
- __classPrivateFieldSet(this, _saplingId$1, saplingContractDetails.saplingId);
737
- __classPrivateFieldSet(this, _saplingWrapper, saplingWrapper);
738
- __classPrivateFieldSet(this, _readProvider$1, readProvider);
739
- }
740
- createShieldedTx(saplingTransactionParams, txTotalAmount, boundData) {
741
- return __awaiter(this, void 0, void 0, function* () {
742
- const rcm = yield __classPrivateFieldGet(this, _saplingWrapper).randR();
743
- const balance = this.calculateTransactionBalance('0', txTotalAmount.toString());
744
- const { signature, inputs, outputs } = yield __classPrivateFieldGet(this, _saplingWrapper).withProvingContext((saplingContext) => __awaiter(this, void 0, void 0, function* () {
745
- const outputs = [];
746
- const inputs = [];
747
- for (const i in saplingTransactionParams) {
748
- outputs.push(yield this.prepareSaplingOutputDescription({
749
- saplingContext,
750
- address: b58cdecode(saplingTransactionParams[i].to, prefix[Prefix.ZET1]),
751
- amount: saplingTransactionParams[i].amount,
752
- memo: saplingTransactionParams[i].memo,
753
- randomCommitmentTrapdoor: rcm,
754
- }));
755
- }
756
- const signature = yield this.createBindingSignature({
757
- saplingContext,
758
- inputs,
759
- outputs,
760
- balance,
761
- boundData,
762
- });
763
- return { signature, inputs, outputs };
764
- }));
765
- return {
766
- inputs,
767
- outputs,
768
- signature,
769
- balance,
770
- };
771
- });
772
- }
773
- createSaplingTx(saplingTransactionParams, txTotalAmount, boundData, chosenInputs) {
774
- return __awaiter(this, void 0, void 0, function* () {
775
- const randomCommitmentTrapdoor = yield __classPrivateFieldGet(this, _saplingWrapper).randR();
776
- const saplingViewer = yield __classPrivateFieldGet(this, _inMemorySpendingKey$1).getSaplingViewingKeyProvider();
777
- const outgoingViewingKey = yield saplingViewer.getOutgoingViewingKey();
778
- const { signature, balance, inputs, outputs } = yield __classPrivateFieldGet(this, _saplingWrapper).withProvingContext((saplingContext) => __awaiter(this, void 0, void 0, function* () {
779
- const outputs = [];
780
- const inputs = [];
781
- inputs.push(...(yield this.prepareSaplingSpendDescription(saplingContext, chosenInputs.inputsToSpend)));
782
- let sumAmountOutput = new BigNumber(0);
783
- for (const i in saplingTransactionParams) {
784
- sumAmountOutput = sumAmountOutput.plus(new BigNumber(saplingTransactionParams[i].amount));
785
- outputs.push(yield this.prepareSaplingOutputDescription({
786
- saplingContext,
787
- address: b58cdecode(saplingTransactionParams[i].to, prefix[Prefix.ZET1]),
788
- amount: saplingTransactionParams[i].amount,
789
- memo: saplingTransactionParams[i].memo,
790
- randomCommitmentTrapdoor,
791
- outgoingViewingKey,
792
- }));
793
- }
794
- if (chosenInputs.sumSelectedInputs.isGreaterThan(sumAmountOutput)) {
795
- const payBackAddress = (yield saplingViewer.getAddress()).address;
796
- const { payBackOutput, payBackAmount } = yield this.createPaybackOutput({
797
- saplingContext,
798
- address: b58cdecode(payBackAddress, prefix[Prefix.ZET1]),
799
- amount: txTotalAmount.toString(),
800
- memo: DEFAULT_MEMO,
801
- randomCommitmentTrapdoor: randomCommitmentTrapdoor,
802
- outgoingViewingKey: outgoingViewingKey,
803
- }, chosenInputs.sumSelectedInputs);
804
- sumAmountOutput = sumAmountOutput.plus(new BigNumber(payBackAmount));
805
- outputs.push(payBackOutput);
806
- }
807
- const balance = this.calculateTransactionBalance(chosenInputs.sumSelectedInputs.toString(), sumAmountOutput.toString());
808
- const signature = yield this.createBindingSignature({
809
- saplingContext,
810
- inputs,
811
- outputs,
812
- balance,
813
- boundData,
814
- });
815
- return { signature, balance, inputs, outputs };
816
- }));
817
- return {
818
- inputs,
819
- outputs,
820
- signature,
821
- balance,
822
- };
823
- });
824
- }
825
- // sum of values of inputs minus sums of values of output equals balance
826
- calculateTransactionBalance(inputTotal, outputTotal) {
827
- return new BigNumber(inputTotal).minus(new BigNumber(outputTotal));
828
- }
829
- prepareSaplingOutputDescription(parametersOutputDescription) {
830
- return __awaiter(this, void 0, void 0, function* () {
831
- const ephemeralPrivateKey = yield __classPrivateFieldGet(this, _saplingWrapper).randR();
832
- const { commitmentValue, commitment, proof } = yield __classPrivateFieldGet(this, _saplingWrapper).preparePartialOutputDescription({
833
- saplingContext: parametersOutputDescription.saplingContext,
834
- address: parametersOutputDescription.address,
835
- randomCommitmentTrapdoor: parametersOutputDescription.randomCommitmentTrapdoor,
836
- ephemeralPrivateKey,
837
- amount: parametersOutputDescription.amount,
838
- });
839
- const diversifier = yield __classPrivateFieldGet(this, _saplingWrapper).getDiversifiedFromRawPaymentAddress(parametersOutputDescription.address);
840
- const ephemeralPublicKey = yield __classPrivateFieldGet(this, _saplingWrapper).deriveEphemeralPublicKey(diversifier, ephemeralPrivateKey);
841
- const outgoingCipherKey = parametersOutputDescription.outgoingViewingKey
842
- ? blake.blake2b(Buffer.concat([
843
- commitmentValue,
844
- commitment,
845
- ephemeralPublicKey,
846
- parametersOutputDescription.outgoingViewingKey,
847
- ]), Buffer.from(OCK_KEY), 32)
848
- : __classPrivateFieldGet(this, _saplingWrapper).getRandomBytes(32);
849
- const ciphertext = yield this.encryptCiphertext({
850
- address: parametersOutputDescription.address,
851
- ephemeralPrivateKey,
852
- diversifier,
853
- outgoingCipherKey,
854
- amount: parametersOutputDescription.amount,
855
- randomCommitmentTrapdoor: parametersOutputDescription.randomCommitmentTrapdoor,
856
- memo: parametersOutputDescription.memo,
857
- });
858
- return {
859
- commitment,
860
- proof,
861
- ciphertext: Object.assign(Object.assign({}, ciphertext), { commitmentValue,
862
- ephemeralPublicKey }),
863
- };
864
- });
865
- }
866
- prepareSaplingSpendDescription(saplingContext, inputsToSpend) {
867
- return __awaiter(this, void 0, void 0, function* () {
868
- const publicKeyReRandomization = yield __classPrivateFieldGet(this, _saplingWrapper).randR();
869
- let stateDiff;
870
- if (__classPrivateFieldGet(this, _saplingId$1)) {
871
- stateDiff = yield __classPrivateFieldGet(this, _readProvider$1).getSaplingDiffById({ id: __classPrivateFieldGet(this, _saplingId$1) }, 'head');
872
- }
873
- else {
874
- stateDiff = yield __classPrivateFieldGet(this, _readProvider$1).getSaplingDiffByContract(__classPrivateFieldGet(this, _contractAddress$1), 'head');
875
- }
876
- const stateTree = yield __classPrivateFieldGet(this, _saplingState).getStateTree(stateDiff, true);
877
- const saplingSpendDescriptions = [];
878
- for (let i = 0; i < inputsToSpend.length; i++) {
879
- const amount = convertValueToBigNumber(inputsToSpend[i].value).toString();
880
- const witness = yield __classPrivateFieldGet(this, _saplingState).getWitness(stateTree, new BigNumber(inputsToSpend[i].position));
881
- const unsignedSpendDescription = __classPrivateFieldGet(this, _inMemoryProvingKey) ? yield __classPrivateFieldGet(this, _inMemoryProvingKey).prepareSpendDescription({
882
- saplingContext,
883
- address: inputsToSpend[i].paymentAddress,
884
- randomCommitmentTrapdoor: inputsToSpend[i].randomCommitmentTrapdoor,
885
- publicKeyReRandomization,
886
- amount,
887
- root: stateDiff.root,
888
- witness,
889
- })
890
- : yield __classPrivateFieldGet(this, _inMemorySpendingKey$1).prepareSpendDescription({
891
- saplingContext,
892
- address: inputsToSpend[i].paymentAddress,
893
- randomCommitmentTrapdoor: inputsToSpend[i].randomCommitmentTrapdoor,
894
- publicKeyReRandomization,
895
- amount,
896
- root: stateDiff.root,
897
- witness,
898
- });
899
- const unsignedSpendDescriptionBytes = __classPrivateFieldGet(this, _saplingForger$1).forgeUnsignedTxInput(unsignedSpendDescription);
900
- const hash = blake.blake2b(unsignedSpendDescriptionBytes, yield this.getAntiReplay(), 32);
901
- const spendDescription = yield __classPrivateFieldGet(this, _inMemorySpendingKey$1).signSpendDescription({
902
- publicKeyReRandomization,
903
- unsignedSpendDescription,
904
- hash,
905
- });
906
- if (spendDescription.signature === undefined) {
907
- throw new Error('Spend signing failed');
908
- }
909
- saplingSpendDescriptions.push(spendDescription);
910
- }
911
- return saplingSpendDescriptions;
912
- });
913
- }
914
- encryptCiphertext(parametersCiphertext) {
915
- return __awaiter(this, void 0, void 0, function* () {
916
- const recipientDiversifiedTransmissionKey = yield __classPrivateFieldGet(this, _saplingWrapper).getPkdFromRawPaymentAddress(parametersCiphertext.address);
917
- const keyAgreement = yield __classPrivateFieldGet(this, _saplingWrapper).keyAgreement(recipientDiversifiedTransmissionKey, parametersCiphertext.ephemeralPrivateKey);
918
- const keyAgreementHash = blake.blake2b(keyAgreement, Buffer.from(KDF_KEY), 32);
919
- const nonceEnc = Buffer.from(__classPrivateFieldGet(this, _saplingWrapper).getRandomBytes(24));
920
- const transactionPlaintext = __classPrivateFieldGet(this, _saplingForger$1).forgeTransactionPlaintext({
921
- diversifier: parametersCiphertext.diversifier,
922
- amount: parametersCiphertext.amount,
923
- randomCommitmentTrapdoor: parametersCiphertext.randomCommitmentTrapdoor,
924
- memoSize: __classPrivateFieldGet(this, _memoSize$1) * 2,
925
- memo: parametersCiphertext.memo,
926
- });
927
- const nonceOut = Buffer.from(__classPrivateFieldGet(this, _saplingWrapper).getRandomBytes(24));
928
- const payloadEnc = Buffer.from(secretBox(keyAgreementHash, nonceEnc, transactionPlaintext));
929
- const payloadOut = Buffer.from(secretBox(parametersCiphertext.outgoingCipherKey, nonceOut, Buffer.concat([
930
- recipientDiversifiedTransmissionKey,
931
- parametersCiphertext.ephemeralPrivateKey,
932
- ])));
933
- return { payloadEnc, nonceEnc, payloadOut, nonceOut };
934
- });
935
- }
936
- createPaybackOutput(params, sumSelectedInputs) {
937
- return __awaiter(this, void 0, void 0, function* () {
938
- const payBackAmount = sumSelectedInputs.minus(params.amount).toString();
939
- const payBackOutput = yield this.prepareSaplingOutputDescription({
940
- saplingContext: params.saplingContext,
941
- address: params.address,
942
- amount: payBackAmount,
943
- memo: params.memo,
944
- randomCommitmentTrapdoor: params.randomCommitmentTrapdoor,
945
- outgoingViewingKey: params.outgoingViewingKey,
946
- });
947
- return { payBackOutput, payBackAmount };
948
- });
949
- }
950
- createBindingSignature(parametersBindingSig) {
951
- return __awaiter(this, void 0, void 0, function* () {
952
- const outputs = __classPrivateFieldGet(this, _saplingForger$1).forgeOutputDescriptions(parametersBindingSig.outputs);
953
- const inputs = __classPrivateFieldGet(this, _saplingForger$1).forgeSpendDescriptions(parametersBindingSig.inputs);
954
- const transactionSigHash = blake.blake2b(Buffer.concat([inputs, outputs, parametersBindingSig.boundData]), yield this.getAntiReplay(), 32);
955
- return __classPrivateFieldGet(this, _saplingWrapper).createBindingSignature(parametersBindingSig.saplingContext, parametersBindingSig.balance.toFixed(), transactionSigHash);
956
- });
957
- }
958
- getAntiReplay() {
959
- return __awaiter(this, void 0, void 0, function* () {
960
- let chainId = __classPrivateFieldGet(this, _chainId);
961
- if (!chainId) {
962
- chainId = yield __classPrivateFieldGet(this, _readProvider$1).getChainId();
963
- __classPrivateFieldSet(this, _chainId, chainId);
964
- }
965
- return Buffer.from(`${__classPrivateFieldGet(this, _contractAddress$1)}${chainId}`);
966
- });
967
- }
968
- }
969
- _inMemorySpendingKey$1 = new WeakMap(), _inMemoryProvingKey = new WeakMap(), _saplingForger$1 = new WeakMap(), _contractAddress$1 = new WeakMap(), _saplingId$1 = new WeakMap(), _memoSize$1 = new WeakMap(), _readProvider$1 = new WeakMap(), _saplingWrapper = new WeakMap(), _chainId = new WeakMap(), _saplingState = new WeakMap();
719
+ var _SaplingTransactionBuilder_inMemorySpendingKey, _SaplingTransactionBuilder_inMemoryProvingKey, _SaplingTransactionBuilder_saplingForger, _SaplingTransactionBuilder_contractAddress, _SaplingTransactionBuilder_saplingId, _SaplingTransactionBuilder_memoSize, _SaplingTransactionBuilder_readProvider, _SaplingTransactionBuilder_saplingWrapper, _SaplingTransactionBuilder_chainId, _SaplingTransactionBuilder_saplingState;
720
+ class SaplingTransactionBuilder {
721
+ constructor(keys, saplingForger, saplingContractDetails, readProvider, saplingWrapper = new SaplingWrapper()) {
722
+ _SaplingTransactionBuilder_inMemorySpendingKey.set(this, void 0);
723
+ _SaplingTransactionBuilder_inMemoryProvingKey.set(this, void 0);
724
+ _SaplingTransactionBuilder_saplingForger.set(this, void 0);
725
+ _SaplingTransactionBuilder_contractAddress.set(this, void 0);
726
+ _SaplingTransactionBuilder_saplingId.set(this, void 0);
727
+ _SaplingTransactionBuilder_memoSize.set(this, void 0);
728
+ _SaplingTransactionBuilder_readProvider.set(this, void 0);
729
+ _SaplingTransactionBuilder_saplingWrapper.set(this, void 0);
730
+ _SaplingTransactionBuilder_chainId.set(this, void 0);
731
+ _SaplingTransactionBuilder_saplingState.set(this, void 0);
732
+ __classPrivateFieldSet(this, _SaplingTransactionBuilder_saplingForger, saplingForger, "f");
733
+ __classPrivateFieldSet(this, _SaplingTransactionBuilder_contractAddress, saplingContractDetails.contractAddress, "f");
734
+ __classPrivateFieldSet(this, _SaplingTransactionBuilder_memoSize, saplingContractDetails.memoSize, "f");
735
+ __classPrivateFieldSet(this, _SaplingTransactionBuilder_inMemorySpendingKey, keys.saplingSigner, "f");
736
+ __classPrivateFieldSet(this, _SaplingTransactionBuilder_inMemoryProvingKey, keys.saplingProver, "f");
737
+ __classPrivateFieldSet(this, _SaplingTransactionBuilder_saplingState, new SaplingState(32), "f");
738
+ __classPrivateFieldSet(this, _SaplingTransactionBuilder_saplingId, saplingContractDetails.saplingId, "f");
739
+ __classPrivateFieldSet(this, _SaplingTransactionBuilder_saplingWrapper, saplingWrapper, "f");
740
+ __classPrivateFieldSet(this, _SaplingTransactionBuilder_readProvider, readProvider, "f");
741
+ }
742
+ createShieldedTx(saplingTransactionParams, txTotalAmount, boundData) {
743
+ return __awaiter(this, void 0, void 0, function* () {
744
+ const rcm = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").randR();
745
+ const balance = this.calculateTransactionBalance('0', txTotalAmount.toString());
746
+ const { signature, inputs, outputs } = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").withProvingContext((saplingContext) => __awaiter(this, void 0, void 0, function* () {
747
+ const outputs = [];
748
+ const inputs = [];
749
+ for (const i in saplingTransactionParams) {
750
+ outputs.push(yield this.prepareSaplingOutputDescription({
751
+ saplingContext,
752
+ address: b58cdecode(saplingTransactionParams[i].to, prefix[Prefix.ZET1]),
753
+ amount: saplingTransactionParams[i].amount,
754
+ memo: saplingTransactionParams[i].memo,
755
+ randomCommitmentTrapdoor: rcm,
756
+ }));
757
+ }
758
+ const signature = yield this.createBindingSignature({
759
+ saplingContext,
760
+ inputs,
761
+ outputs,
762
+ balance,
763
+ boundData,
764
+ });
765
+ return { signature, inputs, outputs };
766
+ }));
767
+ return {
768
+ inputs,
769
+ outputs,
770
+ signature,
771
+ balance,
772
+ };
773
+ });
774
+ }
775
+ createSaplingTx(saplingTransactionParams, txTotalAmount, boundData, chosenInputs) {
776
+ return __awaiter(this, void 0, void 0, function* () {
777
+ const randomCommitmentTrapdoor = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").randR();
778
+ const saplingViewer = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_inMemorySpendingKey, "f").getSaplingViewingKeyProvider();
779
+ const outgoingViewingKey = yield saplingViewer.getOutgoingViewingKey();
780
+ const { signature, balance, inputs, outputs } = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").withProvingContext((saplingContext) => __awaiter(this, void 0, void 0, function* () {
781
+ const outputs = [];
782
+ const inputs = [];
783
+ inputs.push(...(yield this.prepareSaplingSpendDescription(saplingContext, chosenInputs.inputsToSpend)));
784
+ let sumAmountOutput = new BigNumber(0);
785
+ for (const i in saplingTransactionParams) {
786
+ sumAmountOutput = sumAmountOutput.plus(new BigNumber(saplingTransactionParams[i].amount));
787
+ outputs.push(yield this.prepareSaplingOutputDescription({
788
+ saplingContext,
789
+ address: b58cdecode(saplingTransactionParams[i].to, prefix[Prefix.ZET1]),
790
+ amount: saplingTransactionParams[i].amount,
791
+ memo: saplingTransactionParams[i].memo,
792
+ randomCommitmentTrapdoor,
793
+ outgoingViewingKey,
794
+ }));
795
+ }
796
+ if (chosenInputs.sumSelectedInputs.isGreaterThan(sumAmountOutput)) {
797
+ const payBackAddress = (yield saplingViewer.getAddress()).address;
798
+ const { payBackOutput, payBackAmount } = yield this.createPaybackOutput({
799
+ saplingContext,
800
+ address: b58cdecode(payBackAddress, prefix[Prefix.ZET1]),
801
+ amount: txTotalAmount.toString(),
802
+ memo: DEFAULT_MEMO,
803
+ randomCommitmentTrapdoor: randomCommitmentTrapdoor,
804
+ outgoingViewingKey: outgoingViewingKey,
805
+ }, chosenInputs.sumSelectedInputs);
806
+ sumAmountOutput = sumAmountOutput.plus(new BigNumber(payBackAmount));
807
+ outputs.push(payBackOutput);
808
+ }
809
+ const balance = this.calculateTransactionBalance(chosenInputs.sumSelectedInputs.toString(), sumAmountOutput.toString());
810
+ const signature = yield this.createBindingSignature({
811
+ saplingContext,
812
+ inputs,
813
+ outputs,
814
+ balance,
815
+ boundData,
816
+ });
817
+ return { signature, balance, inputs, outputs };
818
+ }));
819
+ return {
820
+ inputs,
821
+ outputs,
822
+ signature,
823
+ balance,
824
+ };
825
+ });
826
+ }
827
+ // sum of values of inputs minus sums of values of output equals balance
828
+ calculateTransactionBalance(inputTotal, outputTotal) {
829
+ return new BigNumber(inputTotal).minus(new BigNumber(outputTotal));
830
+ }
831
+ prepareSaplingOutputDescription(parametersOutputDescription) {
832
+ return __awaiter(this, void 0, void 0, function* () {
833
+ const ephemeralPrivateKey = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").randR();
834
+ const { commitmentValue, commitment, proof } = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").preparePartialOutputDescription({
835
+ saplingContext: parametersOutputDescription.saplingContext,
836
+ address: parametersOutputDescription.address,
837
+ randomCommitmentTrapdoor: parametersOutputDescription.randomCommitmentTrapdoor,
838
+ ephemeralPrivateKey,
839
+ amount: parametersOutputDescription.amount,
840
+ });
841
+ const diversifier = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").getDiversifiedFromRawPaymentAddress(parametersOutputDescription.address);
842
+ const ephemeralPublicKey = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").deriveEphemeralPublicKey(diversifier, ephemeralPrivateKey);
843
+ const outgoingCipherKey = parametersOutputDescription.outgoingViewingKey
844
+ ? blake.blake2b(Buffer.concat([
845
+ commitmentValue,
846
+ commitment,
847
+ ephemeralPublicKey,
848
+ parametersOutputDescription.outgoingViewingKey,
849
+ ]), Buffer.from(OCK_KEY), 32)
850
+ : __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").getRandomBytes(32);
851
+ const ciphertext = yield this.encryptCiphertext({
852
+ address: parametersOutputDescription.address,
853
+ ephemeralPrivateKey,
854
+ diversifier,
855
+ outgoingCipherKey,
856
+ amount: parametersOutputDescription.amount,
857
+ randomCommitmentTrapdoor: parametersOutputDescription.randomCommitmentTrapdoor,
858
+ memo: parametersOutputDescription.memo,
859
+ });
860
+ return {
861
+ commitment,
862
+ proof,
863
+ ciphertext: Object.assign(Object.assign({}, ciphertext), { commitmentValue,
864
+ ephemeralPublicKey }),
865
+ };
866
+ });
867
+ }
868
+ prepareSaplingSpendDescription(saplingContext, inputsToSpend) {
869
+ return __awaiter(this, void 0, void 0, function* () {
870
+ const publicKeyReRandomization = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").randR();
871
+ let stateDiff;
872
+ if (__classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingId, "f")) {
873
+ stateDiff = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_readProvider, "f").getSaplingDiffById({ id: __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingId, "f") }, 'head');
874
+ }
875
+ else {
876
+ stateDiff = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_readProvider, "f").getSaplingDiffByContract(__classPrivateFieldGet(this, _SaplingTransactionBuilder_contractAddress, "f"), 'head');
877
+ }
878
+ const stateTree = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingState, "f").getStateTree(stateDiff, true);
879
+ const saplingSpendDescriptions = [];
880
+ for (let i = 0; i < inputsToSpend.length; i++) {
881
+ const amount = convertValueToBigNumber(inputsToSpend[i].value).toString();
882
+ const witness = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingState, "f").getWitness(stateTree, new BigNumber(inputsToSpend[i].position));
883
+ const unsignedSpendDescription = __classPrivateFieldGet(this, _SaplingTransactionBuilder_inMemoryProvingKey, "f")
884
+ ? yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_inMemoryProvingKey, "f").prepareSpendDescription({
885
+ saplingContext,
886
+ address: inputsToSpend[i].paymentAddress,
887
+ randomCommitmentTrapdoor: inputsToSpend[i].randomCommitmentTrapdoor,
888
+ publicKeyReRandomization,
889
+ amount,
890
+ root: stateDiff.root,
891
+ witness,
892
+ })
893
+ : yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_inMemorySpendingKey, "f").prepareSpendDescription({
894
+ saplingContext,
895
+ address: inputsToSpend[i].paymentAddress,
896
+ randomCommitmentTrapdoor: inputsToSpend[i].randomCommitmentTrapdoor,
897
+ publicKeyReRandomization,
898
+ amount,
899
+ root: stateDiff.root,
900
+ witness,
901
+ });
902
+ const unsignedSpendDescriptionBytes = __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingForger, "f").forgeUnsignedTxInput(unsignedSpendDescription);
903
+ const hash = blake.blake2b(unsignedSpendDescriptionBytes, yield this.getAntiReplay(), 32);
904
+ const spendDescription = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_inMemorySpendingKey, "f").signSpendDescription({
905
+ publicKeyReRandomization,
906
+ unsignedSpendDescription,
907
+ hash,
908
+ });
909
+ if (spendDescription.signature === undefined) {
910
+ throw new Error('Spend signing failed');
911
+ }
912
+ saplingSpendDescriptions.push(spendDescription);
913
+ }
914
+ return saplingSpendDescriptions;
915
+ });
916
+ }
917
+ encryptCiphertext(parametersCiphertext) {
918
+ return __awaiter(this, void 0, void 0, function* () {
919
+ const recipientDiversifiedTransmissionKey = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").getPkdFromRawPaymentAddress(parametersCiphertext.address);
920
+ const keyAgreement = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").keyAgreement(recipientDiversifiedTransmissionKey, parametersCiphertext.ephemeralPrivateKey);
921
+ const keyAgreementHash = blake.blake2b(keyAgreement, Buffer.from(KDF_KEY), 32);
922
+ const nonceEnc = Buffer.from(__classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").getRandomBytes(24));
923
+ const transactionPlaintext = __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingForger, "f").forgeTransactionPlaintext({
924
+ diversifier: parametersCiphertext.diversifier,
925
+ amount: parametersCiphertext.amount,
926
+ randomCommitmentTrapdoor: parametersCiphertext.randomCommitmentTrapdoor,
927
+ memoSize: __classPrivateFieldGet(this, _SaplingTransactionBuilder_memoSize, "f") * 2,
928
+ memo: parametersCiphertext.memo,
929
+ });
930
+ const nonceOut = Buffer.from(__classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").getRandomBytes(24));
931
+ const payloadEnc = Buffer.from(secretBox(keyAgreementHash, nonceEnc, transactionPlaintext));
932
+ const payloadOut = Buffer.from(secretBox(parametersCiphertext.outgoingCipherKey, nonceOut, Buffer.concat([
933
+ recipientDiversifiedTransmissionKey,
934
+ parametersCiphertext.ephemeralPrivateKey,
935
+ ])));
936
+ return { payloadEnc, nonceEnc, payloadOut, nonceOut };
937
+ });
938
+ }
939
+ createPaybackOutput(params, sumSelectedInputs) {
940
+ return __awaiter(this, void 0, void 0, function* () {
941
+ const payBackAmount = sumSelectedInputs.minus(params.amount).toString();
942
+ const payBackOutput = yield this.prepareSaplingOutputDescription({
943
+ saplingContext: params.saplingContext,
944
+ address: params.address,
945
+ amount: payBackAmount,
946
+ memo: params.memo,
947
+ randomCommitmentTrapdoor: params.randomCommitmentTrapdoor,
948
+ outgoingViewingKey: params.outgoingViewingKey,
949
+ });
950
+ return { payBackOutput, payBackAmount };
951
+ });
952
+ }
953
+ createBindingSignature(parametersBindingSig) {
954
+ return __awaiter(this, void 0, void 0, function* () {
955
+ const outputs = __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingForger, "f").forgeOutputDescriptions(parametersBindingSig.outputs);
956
+ const inputs = __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingForger, "f").forgeSpendDescriptions(parametersBindingSig.inputs);
957
+ const transactionSigHash = blake.blake2b(Buffer.concat([inputs, outputs, parametersBindingSig.boundData]), yield this.getAntiReplay(), 32);
958
+ return __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").createBindingSignature(parametersBindingSig.saplingContext, parametersBindingSig.balance.toFixed(), transactionSigHash);
959
+ });
960
+ }
961
+ getAntiReplay() {
962
+ return __awaiter(this, void 0, void 0, function* () {
963
+ let chainId = __classPrivateFieldGet(this, _SaplingTransactionBuilder_chainId, "f");
964
+ if (!chainId) {
965
+ chainId = yield __classPrivateFieldGet(this, _SaplingTransactionBuilder_readProvider, "f").getChainId();
966
+ __classPrivateFieldSet(this, _SaplingTransactionBuilder_chainId, chainId, "f");
967
+ }
968
+ return Buffer.from(`${__classPrivateFieldGet(this, _SaplingTransactionBuilder_contractAddress, "f")}${chainId}`);
969
+ });
970
+ }
971
+ }
972
+ _SaplingTransactionBuilder_inMemorySpendingKey = new WeakMap(), _SaplingTransactionBuilder_inMemoryProvingKey = new WeakMap(), _SaplingTransactionBuilder_saplingForger = new WeakMap(), _SaplingTransactionBuilder_contractAddress = new WeakMap(), _SaplingTransactionBuilder_saplingId = new WeakMap(), _SaplingTransactionBuilder_memoSize = new WeakMap(), _SaplingTransactionBuilder_readProvider = new WeakMap(), _SaplingTransactionBuilder_saplingWrapper = new WeakMap(), _SaplingTransactionBuilder_chainId = new WeakMap(), _SaplingTransactionBuilder_saplingState = new WeakMap();
970
973
 
971
- function decryptKey(spendingKey, password) {
972
- const keyArr = b58cdecode(spendingKey, prefix[Prefix.SASK]);
973
- // exit first if no password and key is encrypted
974
- if (!password && spendingKey.slice(0, 4) !== 'sask') {
975
- throw new InvalidSpendingKey(spendingKey, 'no password provided to decrypt');
976
- }
977
- if (password && spendingKey.slice(0, 4) !== 'sask') {
978
- const salt = toBuffer(keyArr.slice(0, 8));
979
- const encryptedSk = toBuffer(keyArr.slice(8));
980
- const encryptionKey = pbkdf2.pbkdf2Sync(password, salt, 32768, 32, 'sha512');
981
- const decrypted = openSecretBox(new Uint8Array(encryptionKey), new Uint8Array(24), new Uint8Array(encryptedSk));
982
- if (!decrypted) {
983
- throw new InvalidSpendingKey(spendingKey, 'incorrect password or unable to decrypt');
984
- }
985
- return toBuffer(decrypted);
986
- }
987
- else {
988
- return toBuffer(keyArr);
989
- }
974
+ function decryptKey(spendingKey, password) {
975
+ const keyArr = b58cdecode(spendingKey, prefix[Prefix.SASK]);
976
+ // exit first if no password and key is encrypted
977
+ if (!password && spendingKey.slice(0, 4) !== 'sask') {
978
+ throw new InvalidSpendingKey(spendingKey, 'no password provided to decrypt');
979
+ }
980
+ if (password && spendingKey.slice(0, 4) !== 'sask') {
981
+ const salt = toBuffer(keyArr.slice(0, 8));
982
+ const encryptedSk = toBuffer(keyArr.slice(8));
983
+ const encryptionKey = pbkdf2.pbkdf2Sync(password, salt, 32768, 32, 'sha512');
984
+ const decrypted = openSecretBox(new Uint8Array(encryptionKey), new Uint8Array(24), new Uint8Array(encryptedSk));
985
+ if (!decrypted) {
986
+ throw new InvalidSpendingKey(spendingKey, 'incorrect password or unable to decrypt');
987
+ }
988
+ return toBuffer(decrypted);
989
+ }
990
+ else {
991
+ return toBuffer(keyArr);
992
+ }
990
993
  }
991
994
 
992
- var _spendingKeyBuf, _saplingViewingKey;
993
- /**
994
- * @description holds the spending key, create proof and signature for spend descriptions
995
- * can instantiate from mnemonic word list or decrypt a encrypted spending key
996
- * with access to instantiate a InMemoryViewingKey
997
- */
998
- class InMemorySpendingKey {
999
- /**
1000
- *
1001
- * @param spendingKey unencrypted sask... or encrypted MMXj...
1002
- * @param password required for MMXj encrypted keys
1003
- */
1004
- constructor(spendingKey, password) {
1005
- _spendingKeyBuf.set(this, void 0);
1006
- _saplingViewingKey.set(this, void 0);
1007
- __classPrivateFieldSet(this, _spendingKeyBuf, decryptKey(spendingKey, password));
1008
- }
1009
- /**
1010
- *
1011
- * @param mnemonic string of words
1012
- * @param derivationPath tezos current standard 'm/'
1013
- * @returns InMemorySpendingKey class instantiated
1014
- */
1015
- static fromMnemonic(mnemonic, derivationPath = 'm/') {
1016
- return __awaiter(this, void 0, void 0, function* () {
1017
- // no password passed here. password provided only changes from sask -> MMXj
1018
- const fullSeed = yield bip39.mnemonicToSeed(mnemonic);
1019
- const first32 = fullSeed.slice(0, 32);
1020
- const second32 = fullSeed.slice(32);
1021
- // reduce seed bytes must be 32 bytes reflecting both halves
1022
- const seed = Buffer.from(first32.map((byte, index) => byte ^ second32[index]));
1023
- const spendingKeyArr = new Uint8Array(yield sapling.getExtendedSpendingKey(seed, derivationPath));
1024
- const spendingKey = b58cencode(spendingKeyArr, prefix[Prefix.SASK]);
1025
- return new InMemorySpendingKey(spendingKey);
1026
- });
1027
- }
1028
- /**
1029
- *
1030
- * @returns InMemoryViewingKey instantiated class
1031
- */
1032
- getSaplingViewingKeyProvider() {
1033
- return __awaiter(this, void 0, void 0, function* () {
1034
- let viewingKey;
1035
- if (!__classPrivateFieldGet(this, _saplingViewingKey)) {
1036
- viewingKey = yield sapling.getExtendedFullViewingKeyFromSpendingKey(__classPrivateFieldGet(this, _spendingKeyBuf));
1037
- __classPrivateFieldSet(this, _saplingViewingKey, new InMemoryViewingKey(viewingKey.toString('hex')));
1038
- }
1039
- return __classPrivateFieldGet(this, _saplingViewingKey);
1040
- });
1041
- }
1042
- /**
1043
- * @description Prepare an unsigned sapling spend description using the spending key
1044
- * @param parametersSpendProof.saplingContext The sapling proving context
1045
- * @param parametersSpendProof.address The address of the input
1046
- * @param parametersSpendProof.randomCommitmentTrapdoor The randomness of the commitment
1047
- * @param parametersSpendProof.publicKeyReRandomization The re-randomization of the public key
1048
- * @param parametersSpendProof.amount The value of the input
1049
- * @param parametersSpendProof.root The root of the merkle tree
1050
- * @param parametersSpendProof.witness The path of the commitment in the tree
1051
- * @param derivationPath tezos current standard 'm/'
1052
- * @returns The unsigned spend description
1053
- */
1054
- prepareSpendDescription(parametersSpendProof) {
1055
- return __awaiter(this, void 0, void 0, function* () {
1056
- const spendDescription = yield sapling.prepareSpendDescriptionWithSpendingKey(parametersSpendProof.saplingContext, __classPrivateFieldGet(this, _spendingKeyBuf), parametersSpendProof.address, parametersSpendProof.randomCommitmentTrapdoor, parametersSpendProof.publicKeyReRandomization, parametersSpendProof.amount, parametersSpendProof.root, parametersSpendProof.witness);
1057
- return {
1058
- commitmentValue: spendDescription.cv,
1059
- nullifier: spendDescription.nf,
1060
- publicKeyReRandomization: spendDescription.rk,
1061
- rtAnchor: spendDescription.rt,
1062
- proof: spendDescription.proof,
1063
- };
1064
- });
1065
- }
1066
- /**
1067
- * @description Sign a sapling spend description
1068
- * @param parametersSpendSig.publicKeyReRandomization The re-randomization of the public key
1069
- * @param parametersSpendSig.unsignedSpendDescription The unsigned Spend description
1070
- * @param parametersSpendSig.hash The data to be signed
1071
- * @returns The signed spend description
1072
- */
1073
- signSpendDescription(parametersSpendSig) {
1074
- return __awaiter(this, void 0, void 0, function* () {
1075
- const signedSpendDescription = yield sapling.signSpendDescription({
1076
- cv: parametersSpendSig.unsignedSpendDescription.commitmentValue,
1077
- rt: parametersSpendSig.unsignedSpendDescription.rtAnchor,
1078
- nf: parametersSpendSig.unsignedSpendDescription.nullifier,
1079
- rk: parametersSpendSig.unsignedSpendDescription.publicKeyReRandomization,
1080
- proof: parametersSpendSig.unsignedSpendDescription.proof,
1081
- }, __classPrivateFieldGet(this, _spendingKeyBuf), parametersSpendSig.publicKeyReRandomization, parametersSpendSig.hash);
1082
- return {
1083
- commitmentValue: signedSpendDescription.cv,
1084
- nullifier: signedSpendDescription.nf,
1085
- publicKeyReRandomization: signedSpendDescription.rk,
1086
- proof: signedSpendDescription.proof,
1087
- signature: signedSpendDescription.spendAuthSig,
1088
- };
1089
- });
1090
- }
1091
- /**
1092
- * @description Return a proof authorizing key from the configured spending key
1093
- */
1094
- getProvingKey() {
1095
- return __awaiter(this, void 0, void 0, function* () {
1096
- const provingKey = yield sapling.getProofAuthorizingKey(__classPrivateFieldGet(this, _spendingKeyBuf));
1097
- return provingKey.toString('hex');
1098
- });
1099
- }
1100
- }
1101
- _spendingKeyBuf = new WeakMap(), _saplingViewingKey = new WeakMap();
995
+ var _InMemorySpendingKey_spendingKeyBuf, _InMemorySpendingKey_saplingViewingKey;
996
+ /**
997
+ * @description holds the spending key, create proof and signature for spend descriptions
998
+ * can instantiate from mnemonic word list or decrypt a encrypted spending key
999
+ * with access to instantiate a InMemoryViewingKey
1000
+ */
1001
+ class InMemorySpendingKey {
1002
+ /**
1003
+ *
1004
+ * @param spendingKey unencrypted sask... or encrypted MMXj...
1005
+ * @param password required for MMXj encrypted keys
1006
+ */
1007
+ constructor(spendingKey, password) {
1008
+ _InMemorySpendingKey_spendingKeyBuf.set(this, void 0);
1009
+ _InMemorySpendingKey_saplingViewingKey.set(this, void 0);
1010
+ __classPrivateFieldSet(this, _InMemorySpendingKey_spendingKeyBuf, decryptKey(spendingKey, password), "f");
1011
+ }
1012
+ /**
1013
+ *
1014
+ * @param mnemonic string of words
1015
+ * @param derivationPath tezos current standard 'm/'
1016
+ * @returns InMemorySpendingKey class instantiated
1017
+ */
1018
+ static fromMnemonic(mnemonic, derivationPath = 'm/') {
1019
+ return __awaiter(this, void 0, void 0, function* () {
1020
+ // no password passed here. password provided only changes from sask -> MMXj
1021
+ const fullSeed = yield bip39.mnemonicToSeed(mnemonic);
1022
+ const first32 = fullSeed.slice(0, 32);
1023
+ const second32 = fullSeed.slice(32);
1024
+ // reduce seed bytes must be 32 bytes reflecting both halves
1025
+ const seed = Buffer.from(first32.map((byte, index) => byte ^ second32[index]));
1026
+ const spendingKeyArr = new Uint8Array(yield sapling.getExtendedSpendingKey(seed, derivationPath));
1027
+ const spendingKey = b58cencode(spendingKeyArr, prefix[Prefix.SASK]);
1028
+ return new InMemorySpendingKey(spendingKey);
1029
+ });
1030
+ }
1031
+ /**
1032
+ *
1033
+ * @returns InMemoryViewingKey instantiated class
1034
+ */
1035
+ getSaplingViewingKeyProvider() {
1036
+ return __awaiter(this, void 0, void 0, function* () {
1037
+ let viewingKey;
1038
+ if (!__classPrivateFieldGet(this, _InMemorySpendingKey_saplingViewingKey, "f")) {
1039
+ viewingKey = yield sapling.getExtendedFullViewingKeyFromSpendingKey(__classPrivateFieldGet(this, _InMemorySpendingKey_spendingKeyBuf, "f"));
1040
+ __classPrivateFieldSet(this, _InMemorySpendingKey_saplingViewingKey, new InMemoryViewingKey(viewingKey.toString('hex')), "f");
1041
+ }
1042
+ return __classPrivateFieldGet(this, _InMemorySpendingKey_saplingViewingKey, "f");
1043
+ });
1044
+ }
1045
+ /**
1046
+ * @description Prepare an unsigned sapling spend description using the spending key
1047
+ * @param parametersSpendProof.saplingContext The sapling proving context
1048
+ * @param parametersSpendProof.address The address of the input
1049
+ * @param parametersSpendProof.randomCommitmentTrapdoor The randomness of the commitment
1050
+ * @param parametersSpendProof.publicKeyReRandomization The re-randomization of the public key
1051
+ * @param parametersSpendProof.amount The value of the input
1052
+ * @param parametersSpendProof.root The root of the merkle tree
1053
+ * @param parametersSpendProof.witness The path of the commitment in the tree
1054
+ * @param derivationPath tezos current standard 'm/'
1055
+ * @returns The unsigned spend description
1056
+ */
1057
+ prepareSpendDescription(parametersSpendProof) {
1058
+ return __awaiter(this, void 0, void 0, function* () {
1059
+ const spendDescription = yield sapling.prepareSpendDescriptionWithSpendingKey(parametersSpendProof.saplingContext, __classPrivateFieldGet(this, _InMemorySpendingKey_spendingKeyBuf, "f"), parametersSpendProof.address, parametersSpendProof.randomCommitmentTrapdoor, parametersSpendProof.publicKeyReRandomization, parametersSpendProof.amount, parametersSpendProof.root, parametersSpendProof.witness);
1060
+ return {
1061
+ commitmentValue: spendDescription.cv,
1062
+ nullifier: spendDescription.nf,
1063
+ publicKeyReRandomization: spendDescription.rk,
1064
+ rtAnchor: spendDescription.rt,
1065
+ proof: spendDescription.proof,
1066
+ };
1067
+ });
1068
+ }
1069
+ /**
1070
+ * @description Sign a sapling spend description
1071
+ * @param parametersSpendSig.publicKeyReRandomization The re-randomization of the public key
1072
+ * @param parametersSpendSig.unsignedSpendDescription The unsigned Spend description
1073
+ * @param parametersSpendSig.hash The data to be signed
1074
+ * @returns The signed spend description
1075
+ */
1076
+ signSpendDescription(parametersSpendSig) {
1077
+ return __awaiter(this, void 0, void 0, function* () {
1078
+ const signedSpendDescription = yield sapling.signSpendDescription({
1079
+ cv: parametersSpendSig.unsignedSpendDescription.commitmentValue,
1080
+ rt: parametersSpendSig.unsignedSpendDescription.rtAnchor,
1081
+ nf: parametersSpendSig.unsignedSpendDescription.nullifier,
1082
+ rk: parametersSpendSig.unsignedSpendDescription.publicKeyReRandomization,
1083
+ proof: parametersSpendSig.unsignedSpendDescription.proof,
1084
+ }, __classPrivateFieldGet(this, _InMemorySpendingKey_spendingKeyBuf, "f"), parametersSpendSig.publicKeyReRandomization, parametersSpendSig.hash);
1085
+ return {
1086
+ commitmentValue: signedSpendDescription.cv,
1087
+ nullifier: signedSpendDescription.nf,
1088
+ publicKeyReRandomization: signedSpendDescription.rk,
1089
+ proof: signedSpendDescription.proof,
1090
+ signature: signedSpendDescription.spendAuthSig,
1091
+ };
1092
+ });
1093
+ }
1094
+ /**
1095
+ * @description Return a proof authorizing key from the configured spending key
1096
+ */
1097
+ getProvingKey() {
1098
+ return __awaiter(this, void 0, void 0, function* () {
1099
+ const provingKey = yield sapling.getProofAuthorizingKey(__classPrivateFieldGet(this, _InMemorySpendingKey_spendingKeyBuf, "f"));
1100
+ return provingKey.toString('hex');
1101
+ });
1102
+ }
1103
+ }
1104
+ _InMemorySpendingKey_spendingKeyBuf = new WeakMap(), _InMemorySpendingKey_saplingViewingKey = new WeakMap();
1102
1105
 
1103
- var _fullViewingKey;
1104
- /**
1105
- * @description Holds the viewing key
1106
- */
1107
- class InMemoryViewingKey {
1108
- constructor(fullViewingKey) {
1109
- _fullViewingKey.set(this, void 0);
1110
- __classPrivateFieldSet(this, _fullViewingKey, Buffer.from(fullViewingKey, 'hex'));
1111
- }
1112
- /**
1113
- * @description Allows to instantiate the InMemoryViewingKey from an encrypted/unencrypted spending key
1114
- *
1115
- * @param spendingKey Base58Check-encoded spending key
1116
- * @param password Optional password to decrypt the spending key
1117
- * @example
1118
- * ```
1119
- * await InMemoryViewingKey.fromSpendingKey('sask27SLmU9herddHz4qFJBLMjWYMbJF8RtS579w9ej9mfCYK7VUdyCJPHK8AzW9zMsopGZEkYeNjAY7Zz1bkM7CGu8eKLzrjBLTMC5wWJDhxiK91ahA29rhDRsHdJDV2u2jFwb2MNUix8JW7sAkAqYVaJpCehTBPgRQ1KqKwqqUaNmuD8kazd4Q8MCWmgbWs21Yuomdqyi9FLigjRp7oY4m5adaVU19Nj1AHvsMY2tePeU2L')
1120
- * ```
1121
- *
1122
- */
1123
- static fromSpendingKey(spendingKey, password) {
1124
- return __awaiter(this, void 0, void 0, function* () {
1125
- const inMemorySpendingkey = new InMemorySpendingKey(spendingKey, password);
1126
- return inMemorySpendingkey.getSaplingViewingKeyProvider();
1127
- });
1128
- }
1129
- /**
1130
- * @description Retrieve the full viewing key
1131
- * @returns Buffer representing the full viewing key
1132
- *
1133
- */
1134
- getFullViewingKey() {
1135
- return __classPrivateFieldGet(this, _fullViewingKey);
1136
- }
1137
- /**
1138
- * @description Retrieve the outgoing viewing key
1139
- * @returns Buffer representing the outgoing viewing key
1140
- *
1141
- */
1142
- getOutgoingViewingKey() {
1143
- return __awaiter(this, void 0, void 0, function* () {
1144
- return sapling.getOutgoingViewingKey(__classPrivateFieldGet(this, _fullViewingKey));
1145
- });
1146
- }
1147
- /**
1148
- * @description Retrieve the incoming viewing key
1149
- * @returns Buffer representing the incoming viewing key
1150
- *
1151
- */
1152
- getIncomingViewingKey() {
1153
- return __awaiter(this, void 0, void 0, function* () {
1154
- return sapling.getIncomingViewingKey(__classPrivateFieldGet(this, _fullViewingKey));
1155
- });
1156
- }
1157
- /**
1158
- * @description Retrieve a payment address
1159
- * @param addressIndex used to determine which diversifier should be used to derive the address, default is 0
1160
- * @returns Base58Check-encoded address and its index
1161
- *
1162
- */
1163
- getAddress(addressIndex) {
1164
- return __awaiter(this, void 0, void 0, function* () {
1165
- const { index, raw } = yield sapling.getPaymentAddressFromViewingKey(__classPrivateFieldGet(this, _fullViewingKey), addressIndex);
1166
- return {
1167
- address: b58cencode(raw, prefix[Prefix.ZET1]),
1168
- addressIndex: index.readInt32LE(),
1169
- };
1170
- });
1171
- }
1172
- }
1173
- _fullViewingKey = new WeakMap();
1106
+ var _InMemoryViewingKey_fullViewingKey;
1107
+ /**
1108
+ * @description Holds the viewing key
1109
+ */
1110
+ class InMemoryViewingKey {
1111
+ constructor(fullViewingKey) {
1112
+ _InMemoryViewingKey_fullViewingKey.set(this, void 0);
1113
+ __classPrivateFieldSet(this, _InMemoryViewingKey_fullViewingKey, Buffer.from(fullViewingKey, 'hex'), "f");
1114
+ }
1115
+ /**
1116
+ * @description Allows to instantiate the InMemoryViewingKey from an encrypted/unencrypted spending key
1117
+ *
1118
+ * @param spendingKey Base58Check-encoded spending key
1119
+ * @param password Optional password to decrypt the spending key
1120
+ * @example
1121
+ * ```
1122
+ * await InMemoryViewingKey.fromSpendingKey('sask27SLmU9herddHz4qFJBLMjWYMbJF8RtS579w9ej9mfCYK7VUdyCJPHK8AzW9zMsopGZEkYeNjAY7Zz1bkM7CGu8eKLzrjBLTMC5wWJDhxiK91ahA29rhDRsHdJDV2u2jFwb2MNUix8JW7sAkAqYVaJpCehTBPgRQ1KqKwqqUaNmuD8kazd4Q8MCWmgbWs21Yuomdqyi9FLigjRp7oY4m5adaVU19Nj1AHvsMY2tePeU2L')
1123
+ * ```
1124
+ *
1125
+ */
1126
+ static fromSpendingKey(spendingKey, password) {
1127
+ return __awaiter(this, void 0, void 0, function* () {
1128
+ const inMemorySpendingkey = new InMemorySpendingKey(spendingKey, password);
1129
+ return inMemorySpendingkey.getSaplingViewingKeyProvider();
1130
+ });
1131
+ }
1132
+ /**
1133
+ * @description Retrieve the full viewing key
1134
+ * @returns Buffer representing the full viewing key
1135
+ *
1136
+ */
1137
+ getFullViewingKey() {
1138
+ return __classPrivateFieldGet(this, _InMemoryViewingKey_fullViewingKey, "f");
1139
+ }
1140
+ /**
1141
+ * @description Retrieve the outgoing viewing key
1142
+ * @returns Buffer representing the outgoing viewing key
1143
+ *
1144
+ */
1145
+ getOutgoingViewingKey() {
1146
+ return __awaiter(this, void 0, void 0, function* () {
1147
+ return sapling.getOutgoingViewingKey(__classPrivateFieldGet(this, _InMemoryViewingKey_fullViewingKey, "f"));
1148
+ });
1149
+ }
1150
+ /**
1151
+ * @description Retrieve the incoming viewing key
1152
+ * @returns Buffer representing the incoming viewing key
1153
+ *
1154
+ */
1155
+ getIncomingViewingKey() {
1156
+ return __awaiter(this, void 0, void 0, function* () {
1157
+ return sapling.getIncomingViewingKey(__classPrivateFieldGet(this, _InMemoryViewingKey_fullViewingKey, "f"));
1158
+ });
1159
+ }
1160
+ /**
1161
+ * @description Retrieve a payment address
1162
+ * @param addressIndex used to determine which diversifier should be used to derive the address, default is 0
1163
+ * @returns Base58Check-encoded address and its index
1164
+ *
1165
+ */
1166
+ getAddress(addressIndex) {
1167
+ return __awaiter(this, void 0, void 0, function* () {
1168
+ const { index, raw } = yield sapling.getPaymentAddressFromViewingKey(__classPrivateFieldGet(this, _InMemoryViewingKey_fullViewingKey, "f"), addressIndex);
1169
+ return {
1170
+ address: b58cencode(raw, prefix[Prefix.ZET1]),
1171
+ addressIndex: index.readInt32LE(),
1172
+ };
1173
+ });
1174
+ }
1175
+ }
1176
+ _InMemoryViewingKey_fullViewingKey = new WeakMap();
1174
1177
 
1175
- var _provingKey;
1176
- /**
1177
- * @description holds the proving key, create proof for spend descriptions
1178
- * The class can be instantiated from a proving key or a spending key
1179
- */
1180
- class InMemoryProvingKey {
1181
- constructor(provingKey) {
1182
- _provingKey.set(this, void 0);
1183
- __classPrivateFieldSet(this, _provingKey, Buffer.from(provingKey, 'hex'));
1184
- }
1185
- /**
1186
- * @description Allows to instantiate the InMemoryProvingKey from an encrypted/unencrypted spending key
1187
- *
1188
- * @param spendingKey Base58Check-encoded spending key
1189
- * @param password Optional password to decrypt the spending key
1190
- * @example
1191
- * ```
1192
- * await InMemoryProvingKey.fromSpendingKey('sask27SLmU9herddHz4qFJBLMjWYMbJF8RtS579w9ej9mfCYK7VUdyCJPHK8AzW9zMsopGZEkYeNjAY7Zz1bkM7CGu8eKLzrjBLTMC5wWJDhxiK91ahA29rhDRsHdJDV2u2jFwb2MNUix8JW7sAkAqYVaJpCehTBPgRQ1KqKwqqUaNmuD8kazd4Q8MCWmgbWs21Yuomdqyi9FLigjRp7oY4m5adaVU19Nj1AHvsMY2tePeU2L')
1193
- * ```
1194
- *
1195
- */
1196
- static fromSpendingKey(spendingKey, password) {
1197
- return __awaiter(this, void 0, void 0, function* () {
1198
- const decodedSpendingKey = decryptKey(spendingKey, password);
1199
- const provingKey = yield sapling.getProofAuthorizingKey(decodedSpendingKey);
1200
- return new InMemoryProvingKey(provingKey.toString('hex'));
1201
- });
1202
- }
1203
- /**
1204
- * @description Prepare an unsigned sapling spend description using the proving key
1205
- *
1206
- * @param parametersSpendProof.saplingContext The sapling proving context
1207
- * @param parametersSpendProof.address The address of the input
1208
- * @param parametersSpendProof.randomCommitmentTrapdoor The randomness of the commitment
1209
- * @param parametersSpendProof.publicKeyReRandomization The re-randomization of the public key
1210
- * @param parametersSpendProof.amount The value of the input
1211
- * @param parametersSpendProof.root The root of the merkle tree
1212
- * @param parametersSpendProof.witness The path of the commitment in the tree
1213
- * @param derivationPath tezos current standard 'm/'
1214
- * @returns The unsinged spend description
1215
- */
1216
- prepareSpendDescription(parametersSpendProof) {
1217
- return __awaiter(this, void 0, void 0, function* () {
1218
- const spendDescription = yield sapling.prepareSpendDescriptionWithAuthorizingKey(parametersSpendProof.saplingContext, __classPrivateFieldGet(this, _provingKey), parametersSpendProof.address, parametersSpendProof.randomCommitmentTrapdoor, parametersSpendProof.publicKeyReRandomization, parametersSpendProof.amount, parametersSpendProof.root, parametersSpendProof.witness);
1219
- return {
1220
- commitmentValue: spendDescription.cv,
1221
- nullifier: spendDescription.nf,
1222
- publicKeyReRandomization: spendDescription.rk,
1223
- rtAnchor: spendDescription.rt,
1224
- proof: spendDescription.proof,
1225
- };
1226
- });
1227
- }
1228
- }
1229
- _provingKey = new WeakMap();
1178
+ var _InMemoryProvingKey_provingKey;
1179
+ /**
1180
+ * @description holds the proving key, create proof for spend descriptions
1181
+ * The class can be instantiated from a proving key or a spending key
1182
+ */
1183
+ class InMemoryProvingKey {
1184
+ constructor(provingKey) {
1185
+ _InMemoryProvingKey_provingKey.set(this, void 0);
1186
+ __classPrivateFieldSet(this, _InMemoryProvingKey_provingKey, Buffer.from(provingKey, 'hex'), "f");
1187
+ }
1188
+ /**
1189
+ * @description Allows to instantiate the InMemoryProvingKey from an encrypted/unencrypted spending key
1190
+ *
1191
+ * @param spendingKey Base58Check-encoded spending key
1192
+ * @param password Optional password to decrypt the spending key
1193
+ * @example
1194
+ * ```
1195
+ * await InMemoryProvingKey.fromSpendingKey('sask27SLmU9herddHz4qFJBLMjWYMbJF8RtS579w9ej9mfCYK7VUdyCJPHK8AzW9zMsopGZEkYeNjAY7Zz1bkM7CGu8eKLzrjBLTMC5wWJDhxiK91ahA29rhDRsHdJDV2u2jFwb2MNUix8JW7sAkAqYVaJpCehTBPgRQ1KqKwqqUaNmuD8kazd4Q8MCWmgbWs21Yuomdqyi9FLigjRp7oY4m5adaVU19Nj1AHvsMY2tePeU2L')
1196
+ * ```
1197
+ *
1198
+ */
1199
+ static fromSpendingKey(spendingKey, password) {
1200
+ return __awaiter(this, void 0, void 0, function* () {
1201
+ const decodedSpendingKey = decryptKey(spendingKey, password);
1202
+ const provingKey = yield sapling.getProofAuthorizingKey(decodedSpendingKey);
1203
+ return new InMemoryProvingKey(provingKey.toString('hex'));
1204
+ });
1205
+ }
1206
+ /**
1207
+ * @description Prepare an unsigned sapling spend description using the proving key
1208
+ *
1209
+ * @param parametersSpendProof.saplingContext The sapling proving context
1210
+ * @param parametersSpendProof.address The address of the input
1211
+ * @param parametersSpendProof.randomCommitmentTrapdoor The randomness of the commitment
1212
+ * @param parametersSpendProof.publicKeyReRandomization The re-randomization of the public key
1213
+ * @param parametersSpendProof.amount The value of the input
1214
+ * @param parametersSpendProof.root The root of the merkle tree
1215
+ * @param parametersSpendProof.witness The path of the commitment in the tree
1216
+ * @param derivationPath tezos current standard 'm/'
1217
+ * @returns The unsinged spend description
1218
+ */
1219
+ prepareSpendDescription(parametersSpendProof) {
1220
+ return __awaiter(this, void 0, void 0, function* () {
1221
+ const spendDescription = yield sapling.prepareSpendDescriptionWithAuthorizingKey(parametersSpendProof.saplingContext, __classPrivateFieldGet(this, _InMemoryProvingKey_provingKey, "f"), parametersSpendProof.address, parametersSpendProof.randomCommitmentTrapdoor, parametersSpendProof.publicKeyReRandomization, parametersSpendProof.amount, parametersSpendProof.root, parametersSpendProof.witness);
1222
+ return {
1223
+ commitmentValue: spendDescription.cv,
1224
+ nullifier: spendDescription.nf,
1225
+ publicKeyReRandomization: spendDescription.rk,
1226
+ rtAnchor: spendDescription.rt,
1227
+ proof: spendDescription.proof,
1228
+ };
1229
+ });
1230
+ }
1231
+ }
1232
+ _InMemoryProvingKey_provingKey = new WeakMap();
1230
1233
 
1231
- /**
1232
- * @packageDocumentation
1233
- * @module @taquito/sapling
1234
- */
1235
- var _inMemorySpendingKey, _saplingId, _contractAddress, _memoSize, _readProvider, _packer, _saplingForger, _saplingTxBuilder, _saplingTransactionViewer;
1236
- /**
1237
- * @description Class that surfaces all of the sapling capability allowing to read from a sapling state and prepare transactions
1238
- *
1239
- * @param keys.saplingSigner Holds the sapling spending key
1240
- * @param keys.saplingProver (Optional) Allows to generate the proofs with the proving key rather than the spending key
1241
- * @param saplingContractDetails Contains the address of the sapling contract, the memo size, and an optional sapling id that must be defined if the sapling contract contains more than one sapling state
1242
- * @param readProvider Allows to read data from the blockchain
1243
- * @param packer (Optional) Allows packing data. Use the `MichelCodecPacker` by default.
1244
- * @param saplingForger (Optional) Allows serializing the sapling transactions. Use the `SaplingForger` by default.
1245
- * @param saplingTxBuilder (Optional) Allows to prepare the sapling transactions. Use the `SaplingTransactionBuilder` by default.
1246
- * @example
1247
- * ```
1248
- * const inMemorySpendingKey = await InMemorySpendingKey.fromMnemonic('YOUR_MNEMONIC');
1249
- * const readProvider = new RpcReadAdapter(new RpcClient('https://YOUR_PREFERRED_RPC_URL'))
1250
- *
1251
- * const saplingToolkit = new SaplingToolkit(
1252
- * { saplingSigner: inMemorySpendingKey },
1253
- * { contractAddress: SAPLING_CONTRACT_ADDRESS, memoSize: 8 },
1254
- * readProvider
1255
- * )
1256
- * ```
1257
- */
1258
- class SaplingToolkit {
1259
- constructor(keys, saplingContractDetails, readProvider, packer = new MichelCodecPacker(), saplingForger = new SaplingForger(), saplingTxBuilder = new SaplingTransactionBuilder(keys, saplingForger, saplingContractDetails, readProvider)) {
1260
- _inMemorySpendingKey.set(this, void 0);
1261
- _saplingId.set(this, void 0);
1262
- _contractAddress.set(this, void 0);
1263
- _memoSize.set(this, void 0);
1264
- _readProvider.set(this, void 0);
1265
- _packer.set(this, void 0);
1266
- _saplingForger.set(this, void 0);
1267
- _saplingTxBuilder.set(this, void 0);
1268
- _saplingTransactionViewer.set(this, void 0);
1269
- __classPrivateFieldSet(this, _inMemorySpendingKey, keys.saplingSigner);
1270
- __classPrivateFieldSet(this, _saplingId, saplingContractDetails.saplingId);
1271
- __classPrivateFieldSet(this, _contractAddress, saplingContractDetails.contractAddress);
1272
- __classPrivateFieldSet(this, _memoSize, saplingContractDetails.memoSize);
1273
- __classPrivateFieldSet(this, _readProvider, readProvider);
1274
- __classPrivateFieldSet(this, _packer, packer);
1275
- __classPrivateFieldSet(this, _saplingForger, saplingForger);
1276
- __classPrivateFieldSet(this, _saplingTxBuilder, saplingTxBuilder);
1277
- }
1278
- /**
1279
- * @description Get an instance of `SaplingTransactionViewer` which allows to retrieve and decrypt sapling transactions and calculate the unspent balance.
1280
- */
1281
- getSaplingTransactionViewer() {
1282
- return __awaiter(this, void 0, void 0, function* () {
1283
- let saplingTransactionViewer;
1284
- if (!__classPrivateFieldGet(this, _saplingTransactionViewer)) {
1285
- const saplingViewingKey = yield __classPrivateFieldGet(this, _inMemorySpendingKey).getSaplingViewingKeyProvider();
1286
- saplingTransactionViewer = new SaplingTransactionViewer(saplingViewingKey, this.getSaplingContractId(), __classPrivateFieldGet(this, _readProvider));
1287
- __classPrivateFieldSet(this, _saplingTransactionViewer, saplingTransactionViewer);
1288
- }
1289
- return __classPrivateFieldGet(this, _saplingTransactionViewer);
1290
- });
1291
- }
1292
- /**
1293
- * @description Prepare a shielded transaction
1294
- * @param shieldedTxParams `to` is the payment address that will receive the shielded tokens (zet).
1295
- * `amount` is the amount of shielded tokens in tez by default.
1296
- * `mutez` needs to be set to true if the amount of shielded tokens is in mutez.
1297
- * `memo` is an empty string by default.
1298
- * @returns a string representing the sapling transaction
1299
- */
1300
- prepareShieldedTransaction(shieldedTxParams) {
1301
- return __awaiter(this, void 0, void 0, function* () {
1302
- const { formatedParams, totalAmount } = this.formatTransactionParams(shieldedTxParams, this.validateDestinationSaplingAddress);
1303
- const root = yield this.getRoot();
1304
- const { inputs, outputs, signature, balance } = yield __classPrivateFieldGet(this, _saplingTxBuilder).createShieldedTx(formatedParams, totalAmount, DEFAULT_BOUND_DATA);
1305
- const forgedSaplingTx = __classPrivateFieldGet(this, _saplingForger).forgeSaplingTransaction({
1306
- inputs,
1307
- outputs,
1308
- balance,
1309
- root,
1310
- boundData: DEFAULT_BOUND_DATA,
1311
- signature,
1312
- });
1313
- return forgedSaplingTx.toString('hex');
1314
- });
1315
- }
1316
- /**
1317
- * @description Prepare an unshielded transaction
1318
- * @param unshieldedTxParams `to` is the Tezos address that will receive the unshielded tokens (tz1, tz2 or tz3).
1319
- * `amount` is the amount of unshielded tokens in tez by default.
1320
- * `mutez` needs to be set to true if the amount of unshielded tokens is in mutez.
1321
- * @returns a string representing the sapling transaction.
1322
- */
1323
- prepareUnshieldedTransaction(unshieldedTxParams) {
1324
- return __awaiter(this, void 0, void 0, function* () {
1325
- const { formatedParams, totalAmount } = this.formatTransactionParams([unshieldedTxParams], this.validateDestinationImplicitAddress);
1326
- const boundData = yield this.createBoundData(formatedParams[0].to);
1327
- const root = yield this.getRoot();
1328
- const chosenInputs = yield this.selectInputsToSpend(new BigNumber(formatedParams[0].amount));
1329
- const { inputs, outputs, signature, balance } = yield __classPrivateFieldGet(this, _saplingTxBuilder).createSaplingTx([], totalAmount, boundData, chosenInputs);
1330
- const forgedSaplingTx = __classPrivateFieldGet(this, _saplingForger).forgeSaplingTransaction({
1331
- inputs,
1332
- outputs,
1333
- balance,
1334
- root,
1335
- boundData,
1336
- signature,
1337
- });
1338
- return forgedSaplingTx.toString('hex');
1339
- });
1340
- }
1341
- /**
1342
- * @description Prepare a sapling transaction (zet to zet)
1343
- * @param saplingTxParams `to` is the payment address that will receive the shielded tokens (zet).
1344
- * `amount` is the amount of unshielded tokens in tez by default.
1345
- * `mutez` needs to be set to true if the amount of unshielded tokens is in mutez.
1346
- * `memo` is an empty string by default.
1347
- * @returns a string representing the sapling transaction.
1348
- */
1349
- prepareSaplingTransaction(saplingTxParams) {
1350
- return __awaiter(this, void 0, void 0, function* () {
1351
- const { formatedParams, totalAmount } = this.formatTransactionParams(saplingTxParams, this.validateDestinationSaplingAddress);
1352
- const root = yield this.getRoot();
1353
- const chosenInputs = yield this.selectInputsToSpend(totalAmount);
1354
- const { inputs, outputs, signature, balance } = yield __classPrivateFieldGet(this, _saplingTxBuilder).createSaplingTx(formatedParams, totalAmount, DEFAULT_BOUND_DATA, chosenInputs);
1355
- const forgedSaplingTx = __classPrivateFieldGet(this, _saplingForger).forgeSaplingTransaction({
1356
- inputs,
1357
- outputs,
1358
- balance,
1359
- root,
1360
- boundData: DEFAULT_BOUND_DATA,
1361
- signature,
1362
- });
1363
- return forgedSaplingTx.toString('hex');
1364
- });
1365
- }
1366
- formatTransactionParams(txParams, validateDestination) {
1367
- const formatedParams = [];
1368
- let totalAmount = new BigNumber(0);
1369
- txParams.forEach((param) => {
1370
- var _a;
1371
- validateDestination(param.to);
1372
- const amountMutez = param.mutez
1373
- ? param.amount.toString()
1374
- : format('tz', 'mutez', param.amount).toString();
1375
- totalAmount = totalAmount.plus(new BigNumber(amountMutez));
1376
- const memo = (_a = param.memo) !== null && _a !== void 0 ? _a : DEFAULT_MEMO;
1377
- if (memo.length > __classPrivateFieldGet(this, _memoSize)) {
1378
- throw new InvalidMemo(memo, `expecting length to be less than ${__classPrivateFieldGet(this, _memoSize)}`);
1379
- }
1380
- formatedParams.push({ to: param.to, amount: amountMutez, memo });
1381
- });
1382
- return { formatedParams, totalAmount };
1383
- }
1384
- getRoot() {
1385
- return __awaiter(this, void 0, void 0, function* () {
1386
- if (__classPrivateFieldGet(this, _saplingId)) {
1387
- const { root } = yield __classPrivateFieldGet(this, _readProvider).getSaplingDiffById({ id: __classPrivateFieldGet(this, _saplingId) }, 'head');
1388
- return root;
1389
- }
1390
- else {
1391
- const { root } = yield __classPrivateFieldGet(this, _readProvider).getSaplingDiffByContract(__classPrivateFieldGet(this, _contractAddress), 'head');
1392
- return root;
1393
- }
1394
- });
1395
- }
1396
- createBoundData(destination) {
1397
- return __awaiter(this, void 0, void 0, function* () {
1398
- const pref = destination.substring(0, 3);
1399
- let pad;
1400
- switch (pref) {
1401
- case 'tz1': {
1402
- pad = Buffer.from('00', 'hex');
1403
- break;
1404
- }
1405
- case 'tz2': {
1406
- pad = Buffer.from('01', 'hex');
1407
- break;
1408
- }
1409
- case 'tz3': {
1410
- pad = Buffer.from('02', 'hex');
1411
- break;
1412
- }
1413
- default: {
1414
- throw new InvalidAddressError(destination, invalidDetail(ValidationResult.NO_PREFIX_MATCHED) +
1415
- ` expecting one of the following prefix '${Prefix.TZ1}', '${Prefix.TZ2}' or '${Prefix.TZ3}'.`);
1416
- }
1417
- }
1418
- const decodedDestination = b58cdecode(destination, prefix[pref]);
1419
- const padDestination = Buffer.concat([pad, Buffer.from(decodedDestination)]);
1420
- const packedDestination = yield __classPrivateFieldGet(this, _packer).packData({
1421
- data: { bytes: padDestination.toString('hex') },
1422
- type: { prim: 'bytes' },
1423
- });
1424
- return Buffer.from(packedDestination.packed, 'hex');
1425
- });
1426
- }
1427
- validateDestinationImplicitAddress(to) {
1428
- const toValidation = validateKeyHash(to);
1429
- if (toValidation !== ValidationResult.VALID) {
1430
- throw new InvalidKeyHashError(to, invalidDetail(toValidation));
1431
- }
1432
- }
1433
- validateDestinationSaplingAddress(to) {
1434
- if (!to.startsWith(Prefix.ZET1)) {
1435
- throw new InvalidAddressError(to, invalidDetail(ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix ${Prefix.ZET1}.`);
1436
- }
1437
- }
1438
- getSaplingContractId() {
1439
- let saplingContractId;
1440
- if (__classPrivateFieldGet(this, _saplingId)) {
1441
- saplingContractId = { saplingId: __classPrivateFieldGet(this, _saplingId) };
1442
- }
1443
- else {
1444
- saplingContractId = { contractAddress: __classPrivateFieldGet(this, _contractAddress) };
1445
- }
1446
- return saplingContractId;
1447
- }
1448
- selectInputsToSpend(amountMutez) {
1449
- return __awaiter(this, void 0, void 0, function* () {
1450
- const saplingTxViewer = yield this.getSaplingTransactionViewer();
1451
- const { incoming } = yield saplingTxViewer.getIncomingAndOutgoingTransactionsRaw();
1452
- const inputsToSpend = [];
1453
- let sumSelectedInputs = new BigNumber(0);
1454
- incoming.forEach((input) => {
1455
- if (!input.isSpent && sumSelectedInputs.isLessThan(amountMutez)) {
1456
- const txAmount = convertValueToBigNumber(input.value);
1457
- sumSelectedInputs = sumSelectedInputs.plus(txAmount);
1458
- const rest = __rest(input, ["isSpent"]);
1459
- inputsToSpend.push(rest);
1460
- }
1461
- });
1462
- if (sumSelectedInputs.isLessThan(new BigNumber(amountMutez))) {
1463
- throw new InsufficientBalance(sumSelectedInputs.toString(), amountMutez.toString());
1464
- }
1465
- return { inputsToSpend, sumSelectedInputs };
1466
- });
1467
- }
1468
- }
1469
- _inMemorySpendingKey = new WeakMap(), _saplingId = new WeakMap(), _contractAddress = new WeakMap(), _memoSize = new WeakMap(), _readProvider = new WeakMap(), _packer = new WeakMap(), _saplingForger = new WeakMap(), _saplingTxBuilder = new WeakMap(), _saplingTransactionViewer = new WeakMap();
1234
+ /**
1235
+ * @packageDocumentation
1236
+ * @module @taquito/sapling
1237
+ */
1238
+ var _SaplingToolkit_inMemorySpendingKey, _SaplingToolkit_saplingId, _SaplingToolkit_contractAddress, _SaplingToolkit_memoSize, _SaplingToolkit_readProvider, _SaplingToolkit_packer, _SaplingToolkit_saplingForger, _SaplingToolkit_saplingTxBuilder, _SaplingToolkit_saplingTransactionViewer;
1239
+ /**
1240
+ * @description Class that surfaces all of the sapling capability allowing to read from a sapling state and prepare transactions
1241
+ *
1242
+ * @param keys.saplingSigner Holds the sapling spending key
1243
+ * @param keys.saplingProver (Optional) Allows to generate the proofs with the proving key rather than the spending key
1244
+ * @param saplingContractDetails Contains the address of the sapling contract, the memo size, and an optional sapling id that must be defined if the sapling contract contains more than one sapling state
1245
+ * @param readProvider Allows to read data from the blockchain
1246
+ * @param packer (Optional) Allows packing data. Use the `MichelCodecPacker` by default.
1247
+ * @param saplingForger (Optional) Allows serializing the sapling transactions. Use the `SaplingForger` by default.
1248
+ * @param saplingTxBuilder (Optional) Allows to prepare the sapling transactions. Use the `SaplingTransactionBuilder` by default.
1249
+ * @example
1250
+ * ```
1251
+ * const inMemorySpendingKey = await InMemorySpendingKey.fromMnemonic('YOUR_MNEMONIC');
1252
+ * const readProvider = new RpcReadAdapter(new RpcClient('https://YOUR_PREFERRED_RPC_URL'))
1253
+ *
1254
+ * const saplingToolkit = new SaplingToolkit(
1255
+ * { saplingSigner: inMemorySpendingKey },
1256
+ * { contractAddress: SAPLING_CONTRACT_ADDRESS, memoSize: 8 },
1257
+ * readProvider
1258
+ * )
1259
+ * ```
1260
+ */
1261
+ class SaplingToolkit {
1262
+ constructor(keys, saplingContractDetails, readProvider, packer = new MichelCodecPacker(), saplingForger = new SaplingForger(), saplingTxBuilder = new SaplingTransactionBuilder(keys, saplingForger, saplingContractDetails, readProvider)) {
1263
+ _SaplingToolkit_inMemorySpendingKey.set(this, void 0);
1264
+ _SaplingToolkit_saplingId.set(this, void 0);
1265
+ _SaplingToolkit_contractAddress.set(this, void 0);
1266
+ _SaplingToolkit_memoSize.set(this, void 0);
1267
+ _SaplingToolkit_readProvider.set(this, void 0);
1268
+ _SaplingToolkit_packer.set(this, void 0);
1269
+ _SaplingToolkit_saplingForger.set(this, void 0);
1270
+ _SaplingToolkit_saplingTxBuilder.set(this, void 0);
1271
+ _SaplingToolkit_saplingTransactionViewer.set(this, void 0);
1272
+ __classPrivateFieldSet(this, _SaplingToolkit_inMemorySpendingKey, keys.saplingSigner, "f");
1273
+ __classPrivateFieldSet(this, _SaplingToolkit_saplingId, saplingContractDetails.saplingId, "f");
1274
+ __classPrivateFieldSet(this, _SaplingToolkit_contractAddress, saplingContractDetails.contractAddress, "f");
1275
+ __classPrivateFieldSet(this, _SaplingToolkit_memoSize, saplingContractDetails.memoSize, "f");
1276
+ __classPrivateFieldSet(this, _SaplingToolkit_readProvider, readProvider, "f");
1277
+ __classPrivateFieldSet(this, _SaplingToolkit_packer, packer, "f");
1278
+ __classPrivateFieldSet(this, _SaplingToolkit_saplingForger, saplingForger, "f");
1279
+ __classPrivateFieldSet(this, _SaplingToolkit_saplingTxBuilder, saplingTxBuilder, "f");
1280
+ }
1281
+ /**
1282
+ * @description Get an instance of `SaplingTransactionViewer` which allows to retrieve and decrypt sapling transactions and calculate the unspent balance.
1283
+ */
1284
+ getSaplingTransactionViewer() {
1285
+ return __awaiter(this, void 0, void 0, function* () {
1286
+ let saplingTransactionViewer;
1287
+ if (!__classPrivateFieldGet(this, _SaplingToolkit_saplingTransactionViewer, "f")) {
1288
+ const saplingViewingKey = yield __classPrivateFieldGet(this, _SaplingToolkit_inMemorySpendingKey, "f").getSaplingViewingKeyProvider();
1289
+ saplingTransactionViewer = new SaplingTransactionViewer(saplingViewingKey, this.getSaplingContractId(), __classPrivateFieldGet(this, _SaplingToolkit_readProvider, "f"));
1290
+ __classPrivateFieldSet(this, _SaplingToolkit_saplingTransactionViewer, saplingTransactionViewer, "f");
1291
+ }
1292
+ return __classPrivateFieldGet(this, _SaplingToolkit_saplingTransactionViewer, "f");
1293
+ });
1294
+ }
1295
+ /**
1296
+ * @description Prepare a shielded transaction
1297
+ * @param shieldedTxParams `to` is the payment address that will receive the shielded tokens (zet).
1298
+ * `amount` is the amount of shielded tokens in tez by default.
1299
+ * `mutez` needs to be set to true if the amount of shielded tokens is in mutez.
1300
+ * `memo` is an empty string by default.
1301
+ * @returns a string representing the sapling transaction
1302
+ */
1303
+ prepareShieldedTransaction(shieldedTxParams) {
1304
+ return __awaiter(this, void 0, void 0, function* () {
1305
+ const { formatedParams, totalAmount } = this.formatTransactionParams(shieldedTxParams, this.validateDestinationSaplingAddress);
1306
+ const root = yield this.getRoot();
1307
+ const { inputs, outputs, signature, balance } = yield __classPrivateFieldGet(this, _SaplingToolkit_saplingTxBuilder, "f").createShieldedTx(formatedParams, totalAmount, DEFAULT_BOUND_DATA);
1308
+ const forgedSaplingTx = __classPrivateFieldGet(this, _SaplingToolkit_saplingForger, "f").forgeSaplingTransaction({
1309
+ inputs,
1310
+ outputs,
1311
+ balance,
1312
+ root,
1313
+ boundData: DEFAULT_BOUND_DATA,
1314
+ signature,
1315
+ });
1316
+ return forgedSaplingTx.toString('hex');
1317
+ });
1318
+ }
1319
+ /**
1320
+ * @description Prepare an unshielded transaction
1321
+ * @param unshieldedTxParams `to` is the Tezos address that will receive the unshielded tokens (tz1, tz2 or tz3).
1322
+ * `amount` is the amount of unshielded tokens in tez by default.
1323
+ * `mutez` needs to be set to true if the amount of unshielded tokens is in mutez.
1324
+ * @returns a string representing the sapling transaction.
1325
+ */
1326
+ prepareUnshieldedTransaction(unshieldedTxParams) {
1327
+ return __awaiter(this, void 0, void 0, function* () {
1328
+ const { formatedParams, totalAmount } = this.formatTransactionParams([unshieldedTxParams], this.validateDestinationImplicitAddress);
1329
+ const boundData = yield this.createBoundData(formatedParams[0].to);
1330
+ const root = yield this.getRoot();
1331
+ const chosenInputs = yield this.selectInputsToSpend(new BigNumber(formatedParams[0].amount));
1332
+ const { inputs, outputs, signature, balance } = yield __classPrivateFieldGet(this, _SaplingToolkit_saplingTxBuilder, "f").createSaplingTx([], totalAmount, boundData, chosenInputs);
1333
+ const forgedSaplingTx = __classPrivateFieldGet(this, _SaplingToolkit_saplingForger, "f").forgeSaplingTransaction({
1334
+ inputs,
1335
+ outputs,
1336
+ balance,
1337
+ root,
1338
+ boundData,
1339
+ signature,
1340
+ });
1341
+ return forgedSaplingTx.toString('hex');
1342
+ });
1343
+ }
1344
+ /**
1345
+ * @description Prepare a sapling transaction (zet to zet)
1346
+ * @param saplingTxParams `to` is the payment address that will receive the shielded tokens (zet).
1347
+ * `amount` is the amount of unshielded tokens in tez by default.
1348
+ * `mutez` needs to be set to true if the amount of unshielded tokens is in mutez.
1349
+ * `memo` is an empty string by default.
1350
+ * @returns a string representing the sapling transaction.
1351
+ */
1352
+ prepareSaplingTransaction(saplingTxParams) {
1353
+ return __awaiter(this, void 0, void 0, function* () {
1354
+ const { formatedParams, totalAmount } = this.formatTransactionParams(saplingTxParams, this.validateDestinationSaplingAddress);
1355
+ const root = yield this.getRoot();
1356
+ const chosenInputs = yield this.selectInputsToSpend(totalAmount);
1357
+ const { inputs, outputs, signature, balance } = yield __classPrivateFieldGet(this, _SaplingToolkit_saplingTxBuilder, "f").createSaplingTx(formatedParams, totalAmount, DEFAULT_BOUND_DATA, chosenInputs);
1358
+ const forgedSaplingTx = __classPrivateFieldGet(this, _SaplingToolkit_saplingForger, "f").forgeSaplingTransaction({
1359
+ inputs,
1360
+ outputs,
1361
+ balance,
1362
+ root,
1363
+ boundData: DEFAULT_BOUND_DATA,
1364
+ signature,
1365
+ });
1366
+ return forgedSaplingTx.toString('hex');
1367
+ });
1368
+ }
1369
+ formatTransactionParams(txParams, validateDestination) {
1370
+ const formatedParams = [];
1371
+ let totalAmount = new BigNumber(0);
1372
+ txParams.forEach((param) => {
1373
+ var _a;
1374
+ validateDestination(param.to);
1375
+ const amountMutez = param.mutez
1376
+ ? param.amount.toString()
1377
+ : format('tz', 'mutez', param.amount).toString();
1378
+ totalAmount = totalAmount.plus(new BigNumber(amountMutez));
1379
+ const memo = (_a = param.memo) !== null && _a !== void 0 ? _a : DEFAULT_MEMO;
1380
+ if (memo.length > __classPrivateFieldGet(this, _SaplingToolkit_memoSize, "f")) {
1381
+ throw new InvalidMemo(memo, `expecting length to be less than ${__classPrivateFieldGet(this, _SaplingToolkit_memoSize, "f")}`);
1382
+ }
1383
+ formatedParams.push({ to: param.to, amount: amountMutez, memo });
1384
+ });
1385
+ return { formatedParams, totalAmount };
1386
+ }
1387
+ getRoot() {
1388
+ return __awaiter(this, void 0, void 0, function* () {
1389
+ if (__classPrivateFieldGet(this, _SaplingToolkit_saplingId, "f")) {
1390
+ const { root } = yield __classPrivateFieldGet(this, _SaplingToolkit_readProvider, "f").getSaplingDiffById({ id: __classPrivateFieldGet(this, _SaplingToolkit_saplingId, "f") }, 'head');
1391
+ return root;
1392
+ }
1393
+ else {
1394
+ const { root } = yield __classPrivateFieldGet(this, _SaplingToolkit_readProvider, "f").getSaplingDiffByContract(__classPrivateFieldGet(this, _SaplingToolkit_contractAddress, "f"), 'head');
1395
+ return root;
1396
+ }
1397
+ });
1398
+ }
1399
+ createBoundData(destination) {
1400
+ return __awaiter(this, void 0, void 0, function* () {
1401
+ const pref = destination.substring(0, 3);
1402
+ let pad;
1403
+ switch (pref) {
1404
+ case 'tz1': {
1405
+ pad = Buffer.from('00', 'hex');
1406
+ break;
1407
+ }
1408
+ case 'tz2': {
1409
+ pad = Buffer.from('01', 'hex');
1410
+ break;
1411
+ }
1412
+ case 'tz3': {
1413
+ pad = Buffer.from('02', 'hex');
1414
+ break;
1415
+ }
1416
+ default: {
1417
+ throw new InvalidAddressError(destination, invalidDetail(ValidationResult.NO_PREFIX_MATCHED) +
1418
+ ` expecting one of the following prefix '${Prefix.TZ1}', '${Prefix.TZ2}' or '${Prefix.TZ3}'.`);
1419
+ }
1420
+ }
1421
+ const decodedDestination = b58cdecode(destination, prefix[pref]);
1422
+ const padDestination = Buffer.concat([pad, Buffer.from(decodedDestination)]);
1423
+ const packedDestination = yield __classPrivateFieldGet(this, _SaplingToolkit_packer, "f").packData({
1424
+ data: { bytes: padDestination.toString('hex') },
1425
+ type: { prim: 'bytes' },
1426
+ });
1427
+ return Buffer.from(packedDestination.packed, 'hex');
1428
+ });
1429
+ }
1430
+ validateDestinationImplicitAddress(to) {
1431
+ const toValidation = validateKeyHash(to);
1432
+ if (toValidation !== ValidationResult.VALID) {
1433
+ throw new InvalidKeyHashError(to, invalidDetail(toValidation));
1434
+ }
1435
+ }
1436
+ validateDestinationSaplingAddress(to) {
1437
+ if (!to.startsWith(Prefix.ZET1)) {
1438
+ throw new InvalidAddressError(to, invalidDetail(ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix ${Prefix.ZET1}.`);
1439
+ }
1440
+ }
1441
+ getSaplingContractId() {
1442
+ let saplingContractId;
1443
+ if (__classPrivateFieldGet(this, _SaplingToolkit_saplingId, "f")) {
1444
+ saplingContractId = { saplingId: __classPrivateFieldGet(this, _SaplingToolkit_saplingId, "f") };
1445
+ }
1446
+ else {
1447
+ saplingContractId = { contractAddress: __classPrivateFieldGet(this, _SaplingToolkit_contractAddress, "f") };
1448
+ }
1449
+ return saplingContractId;
1450
+ }
1451
+ selectInputsToSpend(amountMutez) {
1452
+ return __awaiter(this, void 0, void 0, function* () {
1453
+ const saplingTxViewer = yield this.getSaplingTransactionViewer();
1454
+ const { incoming } = yield saplingTxViewer.getIncomingAndOutgoingTransactionsRaw();
1455
+ const inputsToSpend = [];
1456
+ let sumSelectedInputs = new BigNumber(0);
1457
+ incoming.forEach((input) => {
1458
+ if (!input.isSpent && sumSelectedInputs.isLessThan(amountMutez)) {
1459
+ const txAmount = convertValueToBigNumber(input.value);
1460
+ sumSelectedInputs = sumSelectedInputs.plus(txAmount);
1461
+ const rest = __rest(input, ["isSpent"]);
1462
+ inputsToSpend.push(rest);
1463
+ }
1464
+ });
1465
+ if (sumSelectedInputs.isLessThan(new BigNumber(amountMutez))) {
1466
+ throw new InsufficientBalance(sumSelectedInputs.toString(), amountMutez.toString());
1467
+ }
1468
+ return { inputsToSpend, sumSelectedInputs };
1469
+ });
1470
+ }
1471
+ }
1472
+ _SaplingToolkit_inMemorySpendingKey = new WeakMap(), _SaplingToolkit_saplingId = new WeakMap(), _SaplingToolkit_contractAddress = new WeakMap(), _SaplingToolkit_memoSize = new WeakMap(), _SaplingToolkit_readProvider = new WeakMap(), _SaplingToolkit_packer = new WeakMap(), _SaplingToolkit_saplingForger = new WeakMap(), _SaplingToolkit_saplingTxBuilder = new WeakMap(), _SaplingToolkit_saplingTransactionViewer = new WeakMap();
1470
1473
 
1471
1474
  export { InMemoryProvingKey, InMemorySpendingKey, InMemoryViewingKey, SaplingToolkit, SaplingTransactionViewer };
1472
1475
  //# sourceMappingURL=taquito-sapling.es6.js.map