@airgap/bitcoin 0.13.41 → 0.13.42-beta.1

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 (39) hide show
  1. package/package.json +8 -6
  2. package/v0/protocol/BitcoinSegwitProtocol.d.ts +1 -0
  3. package/v0/protocol/BitcoinSegwitProtocol.js +22 -15
  4. package/v0/protocol/BitcoinSegwitProtocol.js.map +1 -1
  5. package/v1/data/BitcoinSegwitAddress.d.ts +2 -1
  6. package/v1/data/BitcoinSegwitAddress.js.map +1 -1
  7. package/v1/data/BitcoinTaprootAddress.d.ts +9 -0
  8. package/v1/data/BitcoinTaprootAddress.js +57 -0
  9. package/v1/data/BitcoinTaprootAddress.js.map +1 -0
  10. package/v1/index.d.ts +4 -3
  11. package/v1/index.js +4 -1
  12. package/v1/index.js.map +1 -1
  13. package/v1/module/BitcoinModule.d.ts +1 -1
  14. package/v1/module/BitcoinModule.js +4 -0
  15. package/v1/module/BitcoinModule.js.map +1 -1
  16. package/v1/protocol/BitcoinSegwitProtocol.d.ts +3 -2
  17. package/v1/protocol/BitcoinSegwitProtocol.js +31 -19
  18. package/v1/protocol/BitcoinSegwitProtocol.js.map +1 -1
  19. package/v1/protocol/BitcoinTaprootProtocol.d.ts +60 -0
  20. package/v1/protocol/BitcoinTaprootProtocol.js +1091 -0
  21. package/v1/protocol/BitcoinTaprootProtocol.js.map +1 -0
  22. package/v1/serializer/v3/schemas/converter/transaction-converter.d.ts +7 -1
  23. package/v1/serializer/v3/schemas/converter/transaction-converter.js +22 -1
  24. package/v1/serializer/v3/schemas/converter/transaction-converter.js.map +1 -1
  25. package/v1/serializer/v3/schemas/definitions/transaction-sign-request-bitcoin-taproot.d.ts +4 -0
  26. package/v1/serializer/v3/schemas/definitions/transaction-sign-request-bitcoin-taproot.js +3 -0
  27. package/v1/serializer/v3/schemas/definitions/transaction-sign-request-bitcoin-taproot.js.map +1 -0
  28. package/v1/serializer/v3/schemas/definitions/transaction-sign-response-bitcoin-taproot.d.ts +3 -0
  29. package/v1/serializer/v3/schemas/definitions/transaction-sign-response-bitcoin-taproot.js +3 -0
  30. package/v1/serializer/v3/schemas/definitions/transaction-sign-response-bitcoin-taproot.js.map +1 -0
  31. package/v1/serializer/v3/schemas/generated/transaction-sign-request-bitcoin-taproot.json +29 -0
  32. package/v1/serializer/v3/schemas/generated/transaction-sign-response-bitcoin-taproot.json +19 -0
  33. package/v1/serializer/v3/serializer-companion.js +26 -4
  34. package/v1/serializer/v3/serializer-companion.js.map +1 -1
  35. package/v1/types/bitcoinjs.d.ts +6 -0
  36. package/v1/types/transaction.d.ts +10 -0
  37. package/v1/utils/protocol.d.ts +3 -0
  38. package/v1/utils/protocol.js +6 -1
  39. package/v1/utils/protocol.js.map +1 -1
@@ -0,0 +1,1091 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
+ return new (P || (P = Promise))(function (resolve, reject) {
39
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
43
+ });
44
+ };
45
+ var __generator = (this && this.__generator) || function (thisArg, body) {
46
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
47
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
48
+ function verb(n) { return function (v) { return step([n, v]); }; }
49
+ function step(op) {
50
+ if (f) throw new TypeError("Generator is already executing.");
51
+ while (_) try {
52
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
53
+ if (y = 0, t) op = [op[0] & 2, t.value];
54
+ switch (op[0]) {
55
+ case 0: case 1: t = op; break;
56
+ case 4: _.label++; return { value: op[1], done: false };
57
+ case 5: _.label++; y = op[1]; op = [0]; continue;
58
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
59
+ default:
60
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
61
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
62
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
63
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
64
+ if (t[2]) _.ops.pop();
65
+ _.trys.pop(); continue;
66
+ }
67
+ op = body.call(thisArg, _);
68
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
69
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
70
+ }
71
+ };
72
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
73
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
74
+ if (ar || !(i in from)) {
75
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
76
+ ar[i] = from[i];
77
+ }
78
+ }
79
+ return to.concat(ar || Array.prototype.slice.call(from));
80
+ };
81
+ var __importDefault = (this && this.__importDefault) || function (mod) {
82
+ return (mod && mod.__esModule) ? mod : { "default": mod };
83
+ };
84
+ Object.defineProperty(exports, "__esModule", { value: true });
85
+ exports.createBitcoinTaprootProtocol = exports.BitcoinTaprootProtocolImpl = void 0;
86
+ var coinlib_core_1 = require("@airgap/coinlib-core");
87
+ var index_1 = __importDefault(require("@airgap/coinlib-core/dependencies/src/axios-0.19.0/index"));
88
+ var bignumber_1 = __importDefault(require("@airgap/coinlib-core/dependencies/src/bignumber.js-9.0.0/bignumber"));
89
+ var errors_1 = require("@airgap/coinlib-core/errors");
90
+ var module_kit_1 = require("@airgap/module-kit");
91
+ var bitcoin = __importStar(require("bitcoinjs-lib"));
92
+ var BitcoinTaprootAddress_1 = require("../data/BitcoinTaprootAddress");
93
+ var common_1 = require("../utils/common");
94
+ var key_1 = require("../utils/key");
95
+ var network_1 = require("../utils/network");
96
+ var BitcoinProtocol_1 = require("./BitcoinProtocol");
97
+ var bip32_1 = require("bip32");
98
+ var BitcoinSegwitProtocol_1 = require("./BitcoinSegwitProtocol");
99
+ var crypto_1 = require("@airgap/crypto");
100
+ var secp256k1_1 = __importDefault(require("@bitcoinerlab/secp256k1"));
101
+ // Implementation
102
+ var DUST_AMOUNT = 50;
103
+ var BitcoinTaprootProtocolImpl = /** @class */ (function () {
104
+ function BitcoinTaprootProtocolImpl(options, bitcoinJS) {
105
+ if (options === void 0) { options = {}; }
106
+ if (bitcoinJS === void 0) { bitcoinJS = bitcoin; }
107
+ var _a, _b, _c;
108
+ this._isBitcoinProtocol = true;
109
+ this._isBitcoinTaprootProtocol = true;
110
+ this.bip32 = (0, bip32_1.BIP32Factory)(secp256k1_1.default);
111
+ this.options = (0, BitcoinProtocol_1.createBitcoinProtocolOptions)(options.network);
112
+ this.bitcoinJS = {
113
+ lib: bitcoinJS,
114
+ config: {
115
+ network: (0, network_1.getBitcoinJSNetwork)(this.options.network, bitcoinJS)
116
+ }
117
+ };
118
+ this.bitcoinJS.lib.initEccLib(secp256k1_1.default);
119
+ this.segwit = new BitcoinSegwitProtocol_1.BitcoinSegwitProtocolImpl(options);
120
+ this.metadata = __assign(__assign({}, this.segwit.legacy.metadata), { identifier: coinlib_core_1.MainProtocolSymbols.BTC_TAPROOT, name: 'Bitcoin (Taproot)', account: __assign(__assign({}, ((_a = this.segwit.legacy.metadata.account) !== null && _a !== void 0 ? _a : {})), { standardDerivationPath: "m/86'/0'/0'", address: __assign(__assign({}, ((_c = (_b = this.segwit.legacy.metadata.account) === null || _b === void 0 ? void 0 : _b.address) !== null && _c !== void 0 ? _c : {})), { regex: '^(bc1[pq][a-z0-9]{39,59}|bc1q[a-z0-9]{39,59}|[13][a-km-zA-HJ-NP-Z1-9]{25,34})$' }) }) });
121
+ }
122
+ BitcoinTaprootProtocolImpl.prototype.prepareTransactionWithPublicKey = function (publicKey, details, configuration) {
123
+ return __awaiter(this, void 0, void 0, function () {
124
+ return __generator(this, function (_a) {
125
+ switch (publicKey.type) {
126
+ case 'pub':
127
+ return [2 /*return*/, this.prepareTransactionWithNonExtendedPublicKey(publicKey, details, configuration)];
128
+ case 'xpub':
129
+ return [2 /*return*/, this.prepareTransactionWithExtendedPublicKey(publicKey, details, configuration)];
130
+ default:
131
+ (0, coinlib_core_1.assertNever)(publicKey);
132
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Unsupported public key type.');
133
+ }
134
+ return [2 /*return*/];
135
+ });
136
+ });
137
+ };
138
+ BitcoinTaprootProtocolImpl.prototype.prepareTransactionWithNonExtendedPublicKey = function (publicKey, details, configuration) {
139
+ return __awaiter(this, void 0, void 0, function () {
140
+ return __generator(this, function (_a) {
141
+ throw new Error('Method not implemented.');
142
+ });
143
+ });
144
+ };
145
+ BitcoinTaprootProtocolImpl.prototype.getCryptoConfiguration = function () {
146
+ return __awaiter(this, void 0, void 0, function () {
147
+ return __generator(this, function (_a) {
148
+ return [2 /*return*/, this.segwit.getCryptoConfiguration()];
149
+ });
150
+ });
151
+ };
152
+ BitcoinTaprootProtocolImpl.prototype.getKeyPairFromDerivative = function (derivative) {
153
+ return __awaiter(this, void 0, void 0, function () {
154
+ return __generator(this, function (_a) {
155
+ return [2 /*return*/, this.segwit.getKeyPairFromDerivative(derivative)];
156
+ });
157
+ });
158
+ };
159
+ BitcoinTaprootProtocolImpl.prototype.signTransactionWithSecretKey = function (transaction, secretKey) {
160
+ return __awaiter(this, void 0, void 0, function () {
161
+ return __generator(this, function (_a) {
162
+ switch (secretKey.type) {
163
+ case 'priv':
164
+ return [2 /*return*/, this.signTransactionWithNonExtendedSecretKey(transaction, secretKey)];
165
+ case 'xpriv':
166
+ return [2 /*return*/, this.signTransactionWithExtendedSecretKey(transaction, secretKey)];
167
+ default:
168
+ (0, coinlib_core_1.assertNever)(secretKey);
169
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Secret key type not supported.');
170
+ }
171
+ return [2 /*return*/];
172
+ });
173
+ });
174
+ };
175
+ BitcoinTaprootProtocolImpl.prototype.signTransactionWithExtendedSecretKey = function (transaction, secretKey) {
176
+ return __awaiter(this, void 0, void 0, function () {
177
+ var encodedExtendedSecretKey, bip32, decodedPSBT;
178
+ var _this = this;
179
+ return __generator(this, function (_a) {
180
+ encodedExtendedSecretKey = (0, key_1.convertExtendedSecretKey)(secretKey, { format: 'encoded', type: 'xprv' });
181
+ bip32 = this.bip32.fromBase58(encodedExtendedSecretKey.value);
182
+ decodedPSBT = this.bitcoinJS.lib.Psbt.fromHex(transaction.psbt);
183
+ decodedPSBT.data.inputs.forEach(function (input, index) {
184
+ var _a;
185
+ (_a = input.tapBip32Derivation) === null || _a === void 0 ? void 0 : _a.forEach(function (deriv) {
186
+ try {
187
+ var cutoffFrom = deriv.path.lastIndexOf("'") || deriv.path.lastIndexOf('h');
188
+ var childPath = deriv.path.substr(cutoffFrom + 2);
189
+ var childNode = bip32.derivePath(childPath);
190
+ var tweakedChildNode_1 = childNode.tweak(_this.bitcoinJS.lib.crypto.taggedHash('TapTweak', Buffer.from(childNode.publicKey.subarray(1, 33))));
191
+ decodedPSBT.signInput(index, {
192
+ publicKey: Buffer.from(tweakedChildNode_1.publicKey),
193
+ sign: function (hash, lowR) { return Buffer.from(tweakedChildNode_1.sign(hash, lowR)); },
194
+ signSchnorr: function (hash) { return Buffer.from(tweakedChildNode_1.signSchnorr(hash)); }
195
+ });
196
+ console.log("Signed input ".concat(index, " with path ").concat(deriv.path));
197
+ }
198
+ catch (e) {
199
+ throw new Error("Error signing index #".concat(index));
200
+ }
201
+ });
202
+ });
203
+ return [2 /*return*/, (0, module_kit_1.newSignedTransaction)({ psbt: decodedPSBT.toHex() })];
204
+ });
205
+ });
206
+ };
207
+ BitcoinTaprootProtocolImpl.prototype.signTransactionWithNonExtendedSecretKey = function (transaction, secretKey) {
208
+ return __awaiter(this, void 0, void 0, function () {
209
+ return __generator(this, function (_a) {
210
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Sign with non extended secret key not supported (Taproot).');
211
+ });
212
+ });
213
+ };
214
+ BitcoinTaprootProtocolImpl.prototype.getMetadata = function () {
215
+ return __awaiter(this, void 0, void 0, function () {
216
+ return __generator(this, function (_a) {
217
+ return [2 /*return*/, this.metadata];
218
+ });
219
+ });
220
+ };
221
+ BitcoinTaprootProtocolImpl.prototype.getAddressFromPublicKey = function (publicKey) {
222
+ switch (publicKey.type) {
223
+ case 'pub':
224
+ return this.getAddressFromNonExtendedPublicKey(publicKey);
225
+ case 'xpub':
226
+ return this.getAddressFromExtendedPublicKey(publicKey);
227
+ default:
228
+ (0, coinlib_core_1.assertNever)(publicKey);
229
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Public key type is not supported.');
230
+ }
231
+ };
232
+ BitcoinTaprootProtocolImpl.prototype.getAddressFromExtendedPublicKey = function (extendedPublicKey) {
233
+ return __awaiter(this, void 0, void 0, function () {
234
+ var encodedExtendedPublicKey, payment;
235
+ return __generator(this, function (_a) {
236
+ encodedExtendedPublicKey = (0, key_1.convertExtendedPublicKey)(extendedPublicKey, { format: 'encoded', type: 'xpub' });
237
+ payment = this.bitcoinJS.lib.payments.p2tr({
238
+ internalPubkey: Buffer.from(encodedExtendedPublicKey.value, 'hex').subarray(1, 33),
239
+ network: this.bitcoinJS.config.network
240
+ });
241
+ return [2 /*return*/, BitcoinTaprootAddress_1.BitcoinTaprootAddress.fromPayment(payment).asString()];
242
+ });
243
+ });
244
+ };
245
+ BitcoinTaprootProtocolImpl.prototype.getDetailsFromTransaction = function (transaction, _publicKey) {
246
+ return __awaiter(this, void 0, void 0, function () {
247
+ return __generator(this, function (_a) {
248
+ return [2 /*return*/, this.getDetailsFromPSBT(transaction.psbt, _publicKey)];
249
+ });
250
+ });
251
+ };
252
+ BitcoinTaprootProtocolImpl.prototype.getDetailsFromPSBT = function (psbt, publicKey) {
253
+ var _a, _b;
254
+ return __awaiter(this, void 0, void 0, function () {
255
+ var decodedPSBT, fee, _i, _c, txIn, _d, _e, txOut, alerts, clonedPSBT, amount, changeAddressDatas, changeAddressInfo;
256
+ var _this = this;
257
+ return __generator(this, function (_f) {
258
+ switch (_f.label) {
259
+ case 0:
260
+ decodedPSBT = this.bitcoinJS.lib.Psbt.fromHex(psbt);
261
+ fee = new bignumber_1.default(0);
262
+ for (_i = 0, _c = decodedPSBT.data.inputs; _i < _c.length; _i++) {
263
+ txIn = _c[_i];
264
+ fee = fee.plus(new bignumber_1.default((_b = (_a = txIn.witnessUtxo) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 0));
265
+ }
266
+ for (_d = 0, _e = decodedPSBT.txOutputs; _d < _e.length; _d++) {
267
+ txOut = _e[_d];
268
+ fee = fee.minus(new bignumber_1.default(txOut.value));
269
+ }
270
+ alerts = [];
271
+ clonedPSBT = decodedPSBT.clone();
272
+ (0, common_1.eachRecursive)(clonedPSBT); // Convert all buffers to hex strings
273
+ amount = (function () {
274
+ if (decodedPSBT.txOutputs.length === 1) {
275
+ return new bignumber_1.default(decodedPSBT.txOutputs[0].value);
276
+ }
277
+ var unknownKeyVals = decodedPSBT.data.globalMap.unknownKeyVals;
278
+ if (unknownKeyVals) {
279
+ var amountArray = unknownKeyVals.filter(function (kv) { return kv.key.equals(Buffer.from('amount')); });
280
+ if (amountArray.length > 0) {
281
+ return new bignumber_1.default(amountArray[0].value.toString());
282
+ }
283
+ }
284
+ var accumulated = new bignumber_1.default(0);
285
+ var useAccumulated = false;
286
+ decodedPSBT.data.outputs.forEach(function (outputKeyValues, index) {
287
+ if (outputKeyValues.unknownKeyVals) {
288
+ var derivationPaths = outputKeyValues.unknownKeyVals
289
+ .filter(function (kv) { return kv.key.equals(Buffer.from('dp')); })
290
+ .map(function (kv) { return kv.value.toString(); });
291
+ if (derivationPaths.length > 0) {
292
+ useAccumulated = true;
293
+ return;
294
+ }
295
+ }
296
+ var output = decodedPSBT.txOutputs[index];
297
+ accumulated = accumulated.plus(output.value);
298
+ });
299
+ if (useAccumulated) {
300
+ return accumulated;
301
+ }
302
+ return decodedPSBT.txOutputs
303
+ .map(function (obj) { return new bignumber_1.default(obj.value); })
304
+ .reduce(function (accumulator, currentValue) { return accumulator.plus(currentValue); });
305
+ })();
306
+ return [4 /*yield*/, Promise.all(decodedPSBT.data.outputs.map(function (obj, index) { return __awaiter(_this, void 0, void 0, function () {
307
+ var isChangeAddress, isOwned, addressIndex, address, amount, ourGeneratedAddress, getIndexes, ourPublickey, x, ourPublickey, getIndexes, ourPublickey, x, ourPublickey, x, ourPublickey;
308
+ return __generator(this, function (_a) {
309
+ switch (_a.label) {
310
+ case 0:
311
+ isChangeAddress = false;
312
+ isOwned = false;
313
+ addressIndex = 0;
314
+ address = decodedPSBT.txOutputs[index].address;
315
+ amount = decodedPSBT.txOutputs[index].value;
316
+ if (!obj.bip32Derivation) return [3 /*break*/, 11];
317
+ console.log('BIP32 Derivation:', obj.bip32Derivation);
318
+ isChangeAddress = true;
319
+ getIndexes = obj.bip32Derivation[0].path.split('/');
320
+ if (!(publicKey.type === 'xpub')) return [3 /*break*/, 3];
321
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(publicKey, 1, +getIndexes[getIndexes.length - 1])];
322
+ case 1:
323
+ ourPublickey = _a.sent();
324
+ return [4 /*yield*/, this.getAddressFromPublicKey(ourPublickey)];
325
+ case 2:
326
+ ourGeneratedAddress = _a.sent();
327
+ return [3 /*break*/, 5];
328
+ case 3: return [4 /*yield*/, this.getAddressFromNonExtendedPublicKey(publicKey)];
329
+ case 4:
330
+ ourGeneratedAddress = _a.sent();
331
+ _a.label = 5;
332
+ case 5:
333
+ if (ourGeneratedAddress === address) {
334
+ isOwned = true;
335
+ addressIndex = +getIndexes[getIndexes.length - 1];
336
+ }
337
+ x = 0;
338
+ _a.label = 6;
339
+ case 6:
340
+ if (!(x < 1000)) return [3 /*break*/, 10];
341
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(publicKey, 1, x)];
342
+ case 7:
343
+ ourPublickey = _a.sent();
344
+ return [4 /*yield*/, this.getAddressFromPublicKey(ourPublickey)];
345
+ case 8:
346
+ ourGeneratedAddress = _a.sent();
347
+ if (ourGeneratedAddress === address) {
348
+ isOwned = true;
349
+ addressIndex = x;
350
+ return [3 /*break*/, 10];
351
+ }
352
+ _a.label = 9;
353
+ case 9:
354
+ x++;
355
+ return [3 /*break*/, 6];
356
+ case 10: return [3 /*break*/, 27];
357
+ case 11:
358
+ if (!obj.tapBip32Derivation) return [3 /*break*/, 22];
359
+ console.log('BIP32 tapBip32Derivation:', obj.tapBip32Derivation);
360
+ isChangeAddress = true;
361
+ getIndexes = obj.tapBip32Derivation[0].path.split('/');
362
+ if (!(publicKey.type === 'xpub')) return [3 /*break*/, 14];
363
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(publicKey, 1, +getIndexes[getIndexes.length - 1])];
364
+ case 12:
365
+ ourPublickey = _a.sent();
366
+ return [4 /*yield*/, this.getAddressFromPublicKey(ourPublickey)];
367
+ case 13:
368
+ ourGeneratedAddress = _a.sent();
369
+ return [3 /*break*/, 16];
370
+ case 14: return [4 /*yield*/, this.getAddressFromNonExtendedPublicKey(publicKey)];
371
+ case 15:
372
+ ourGeneratedAddress = _a.sent();
373
+ _a.label = 16;
374
+ case 16:
375
+ if (ourGeneratedAddress === address) {
376
+ isOwned = true;
377
+ addressIndex = +getIndexes[getIndexes.length - 1];
378
+ }
379
+ x = 0;
380
+ _a.label = 17;
381
+ case 17:
382
+ if (!(x < 1000)) return [3 /*break*/, 21];
383
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(publicKey, 1, x)];
384
+ case 18:
385
+ ourPublickey = _a.sent();
386
+ return [4 /*yield*/, this.getAddressFromPublicKey(ourPublickey)];
387
+ case 19:
388
+ ourGeneratedAddress = _a.sent();
389
+ if (ourGeneratedAddress === address) {
390
+ isOwned = true;
391
+ addressIndex = x;
392
+ return [3 /*break*/, 21];
393
+ }
394
+ _a.label = 20;
395
+ case 20:
396
+ x++;
397
+ return [3 /*break*/, 17];
398
+ case 21: return [3 /*break*/, 27];
399
+ case 22:
400
+ if (!obj.unknownKeyVals) return [3 /*break*/, 27];
401
+ console.log('obj.unknownKeyVals:', obj.unknownKeyVals);
402
+ x = 0;
403
+ _a.label = 23;
404
+ case 23:
405
+ if (!(x < 1000)) return [3 /*break*/, 27];
406
+ isChangeAddress = true;
407
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(publicKey, 1, x)];
408
+ case 24:
409
+ ourPublickey = _a.sent();
410
+ return [4 /*yield*/, this.getAddressFromPublicKey(ourPublickey)];
411
+ case 25:
412
+ ourGeneratedAddress = _a.sent();
413
+ console.log(ourGeneratedAddress === address, x);
414
+ if (ourGeneratedAddress === address) {
415
+ isOwned = true;
416
+ addressIndex = x;
417
+ return [3 /*break*/, 27];
418
+ }
419
+ _a.label = 26;
420
+ case 26:
421
+ x++;
422
+ return [3 /*break*/, 23];
423
+ case 27:
424
+ if (isChangeAddress && isOwned) {
425
+ alerts.push({
426
+ type: 'success',
427
+ title: { type: 'plain', value: '' },
428
+ description: { type: 'plain', value: 'Note: your change address has been verified' },
429
+ icon: undefined,
430
+ actions: undefined
431
+ });
432
+ }
433
+ else if (isChangeAddress && !isOwned) {
434
+ alerts.push({
435
+ type: 'warning',
436
+ title: { type: 'plain', value: '' },
437
+ description: { type: 'plain', value: 'Note: your change address has not been verified' },
438
+ icon: undefined,
439
+ actions: undefined
440
+ });
441
+ }
442
+ return [2 /*return*/, [
443
+ address,
444
+ {
445
+ isChangeAddress: isChangeAddress,
446
+ isOwned: isOwned,
447
+ path: addressIndex === 0 ? '' : "m/86'/0'/0'/1/".concat(addressIndex),
448
+ amount: amount
449
+ }
450
+ ]];
451
+ }
452
+ });
453
+ }); }))];
454
+ case 1:
455
+ changeAddressDatas = _f.sent();
456
+ changeAddressInfo = {};
457
+ changeAddressDatas.forEach(function (changeAddressData) {
458
+ changeAddressInfo[changeAddressData[0]] = changeAddressData[1];
459
+ });
460
+ return [2 /*return*/, [
461
+ {
462
+ from: decodedPSBT.data.inputs.map(function (obj) {
463
+ var _a, _b;
464
+ return (_b = (_a = obj.tapBip32Derivation) === null || _a === void 0 ? void 0 : _a.map(function (el) {
465
+ return _this.bitcoinJS.lib.payments.p2tr({
466
+ internalPubkey: el.pubkey,
467
+ network: _this.bitcoinJS.lib.networks.bitcoin
468
+ }).address;
469
+ }).join(' ')) !== null && _b !== void 0 ? _b : 'INVALID';
470
+ }),
471
+ to: decodedPSBT.txOutputs.map(function (obj) {
472
+ return obj.address || "Script: ".concat(obj.script.toString('hex')) || 'unknown';
473
+ }),
474
+ isInbound: false,
475
+ amount: (0, module_kit_1.newAmount)(amount, 'blockchain'),
476
+ fee: (0, module_kit_1.newAmount)(fee, 'blockchain'),
477
+ network: this.options.network,
478
+ changeAddressInfo: changeAddressInfo,
479
+ uiAlerts: alerts,
480
+ json: {
481
+ inputTx: (0, common_1.eachRecursive)(clonedPSBT.txInputs),
482
+ outputTx: (0, common_1.eachRecursive)(clonedPSBT.txOutputs),
483
+ inputData: clonedPSBT.data.inputs,
484
+ outputData: clonedPSBT.data.outputs,
485
+ PSBTVersion: clonedPSBT.version,
486
+ PSBTLocktime: clonedPSBT.locktime,
487
+ PSBTGlobalMap: clonedPSBT.data.globalMap,
488
+ rawPSBT: psbt
489
+ }
490
+ }
491
+ ]];
492
+ }
493
+ });
494
+ });
495
+ };
496
+ BitcoinTaprootProtocolImpl.prototype.getNetwork = function () {
497
+ return __awaiter(this, void 0, void 0, function () {
498
+ return __generator(this, function (_a) {
499
+ return [2 /*return*/, this.options.network];
500
+ });
501
+ });
502
+ };
503
+ BitcoinTaprootProtocolImpl.prototype.getTransactionsForPublicKey = function (publicKey, limit, cursor) {
504
+ return __awaiter(this, void 0, void 0, function () {
505
+ return __generator(this, function (_a) {
506
+ switch (publicKey.type) {
507
+ case 'pub':
508
+ return [2 /*return*/, this.getTransactionsForNonExtendedPublicKey(publicKey, limit, cursor)];
509
+ case 'xpub':
510
+ return [2 /*return*/, this.getTransactionsForExtendedPublicKey(publicKey, limit, cursor)];
511
+ default:
512
+ (0, coinlib_core_1.assertNever)(publicKey);
513
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Public key type not supported');
514
+ }
515
+ return [2 /*return*/];
516
+ });
517
+ });
518
+ };
519
+ BitcoinTaprootProtocolImpl.prototype.getTransactionsForNonExtendedPublicKey = function (publicKey, limit, cursor) {
520
+ return __awaiter(this, void 0, void 0, function () {
521
+ var address;
522
+ return __generator(this, function (_a) {
523
+ switch (_a.label) {
524
+ case 0: return [4 /*yield*/, this.getAddressFromPublicKey(publicKey)];
525
+ case 1:
526
+ address = _a.sent();
527
+ return [2 /*return*/, this.getTransactionsForAddresses([address], limit, cursor)];
528
+ }
529
+ });
530
+ });
531
+ };
532
+ BitcoinTaprootProtocolImpl.prototype.getTransactionsForExtendedPublicKey = function (extendedPublicKey, limit, cursor) {
533
+ var _a;
534
+ return __awaiter(this, void 0, void 0, function () {
535
+ var encodedExtendedPublicKey, page, url, data, ourAddresses, airGapTransactions, _i, _b, transaction, tempAirGapTransactionFrom, tempAirGapTransactionTo, tempAirGapTransactionIsInbound, amountNotAdded, amount, _c, _d, vin, _e, _f, vout, airGapTransaction, hasNext;
536
+ return __generator(this, function (_g) {
537
+ switch (_g.label) {
538
+ case 0:
539
+ encodedExtendedPublicKey = (0, key_1.convertExtendedPublicKey)(extendedPublicKey, { format: 'encoded', type: 'xpub' });
540
+ page = (_a = cursor === null || cursor === void 0 ? void 0 : cursor.page) !== null && _a !== void 0 ? _a : 1;
541
+ url = "".concat(this.options.network.indexerApi, "/api/v2/xpub/tr(").concat(encodedExtendedPublicKey.value, ")?details=txs&tokens=used&pageSize=").concat(limit, "&page=").concat(page);
542
+ return [4 /*yield*/, index_1.default.get(url, {
543
+ responseType: 'json'
544
+ })];
545
+ case 1:
546
+ data = (_g.sent()).data;
547
+ ourAddresses = (data.tokens || []).filter(function (token) { return token.type === 'XPUBAddress'; }).map(function (token) { return token.name; });
548
+ airGapTransactions = [];
549
+ if (data.page === page) {
550
+ for (_i = 0, _b = data.transactions || []; _i < _b.length; _i++) {
551
+ transaction = _b[_i];
552
+ tempAirGapTransactionFrom = [];
553
+ tempAirGapTransactionTo = [];
554
+ tempAirGapTransactionIsInbound = true;
555
+ amountNotAdded = true;
556
+ amount = new bignumber_1.default(0);
557
+ for (_c = 0, _d = transaction.vin; _c < _d.length; _c++) {
558
+ vin = _d[_c];
559
+ if ((0, common_1.containsSome)(vin.addresses, ourAddresses)) {
560
+ tempAirGapTransactionIsInbound = false;
561
+ }
562
+ tempAirGapTransactionFrom.push.apply(tempAirGapTransactionFrom, vin.addresses);
563
+ }
564
+ for (_e = 0, _f = transaction.vout; _e < _f.length; _e++) {
565
+ vout = _f[_e];
566
+ if (vout.addresses) {
567
+ tempAirGapTransactionTo.push.apply(tempAirGapTransactionTo, vout.addresses);
568
+ }
569
+ if ((0, common_1.containsSome)(vout.addresses, ourAddresses) && transaction.vout.length > 2) {
570
+ amount = amount.plus(vout.value);
571
+ amountNotAdded = false;
572
+ }
573
+ }
574
+ // deduct fee from amount
575
+ //amount = amount.minus(transaction.fees)
576
+ if (amountNotAdded) {
577
+ amount = amount.plus(transaction.vout[0].value);
578
+ }
579
+ airGapTransaction = {
580
+ from: tempAirGapTransactionFrom,
581
+ to: tempAirGapTransactionTo,
582
+ isInbound: tempAirGapTransactionIsInbound,
583
+ amount: (0, module_kit_1.newAmount)(amount, 'blockchain'),
584
+ fee: (0, module_kit_1.newAmount)(transaction.fees, 'blockchain'),
585
+ status: {
586
+ type: 'applied',
587
+ hash: transaction.txid,
588
+ block: transaction.blockHeight.toString()
589
+ },
590
+ network: this.options.network,
591
+ timestamp: transaction.blockTime
592
+ };
593
+ airGapTransactions.push(airGapTransaction);
594
+ }
595
+ }
596
+ hasNext = page < data.totalPages;
597
+ return [2 /*return*/, {
598
+ transactions: airGapTransactions,
599
+ cursor: {
600
+ hasNext: hasNext,
601
+ page: hasNext ? page + 1 : undefined
602
+ }
603
+ }];
604
+ }
605
+ });
606
+ });
607
+ };
608
+ BitcoinTaprootProtocolImpl.prototype.getTransactionsForAddress = function (address, limit, cursor) {
609
+ return __awaiter(this, void 0, void 0, function () {
610
+ return __generator(this, function (_a) {
611
+ return [2 /*return*/, this.getTransactionsForAddresses([address], limit, cursor)];
612
+ });
613
+ });
614
+ };
615
+ BitcoinTaprootProtocolImpl.prototype.getTransactionsForAddresses = function (addresses, limit, cursor) {
616
+ var _a;
617
+ return __awaiter(this, void 0, void 0, function () {
618
+ var airGapTransactions, page, url, data, _i, _b, transaction, tempAirGapTransactionFrom, tempAirGapTransactionTo, tempAirGapTransactionIsInbound, amount, _c, _d, vin, _e, _f, vout, airGapTransaction, hasNext;
619
+ return __generator(this, function (_g) {
620
+ switch (_g.label) {
621
+ case 0:
622
+ airGapTransactions = [];
623
+ page = (_a = cursor === null || cursor === void 0 ? void 0 : cursor.page) !== null && _a !== void 0 ? _a : 1;
624
+ url = "".concat(this.options.network.indexerApi, "/api/v2/address/").concat(addresses[0], "?page=").concat(page, "&pageSize=").concat(limit, "&details=txs");
625
+ return [4 /*yield*/, index_1.default.get(url, {
626
+ responseType: 'json'
627
+ })];
628
+ case 1:
629
+ data = (_g.sent()).data;
630
+ if (data.page == page) {
631
+ for (_i = 0, _b = data.transactions || []; _i < _b.length; _i++) {
632
+ transaction = _b[_i];
633
+ tempAirGapTransactionFrom = [];
634
+ tempAirGapTransactionTo = [];
635
+ tempAirGapTransactionIsInbound = true;
636
+ amount = new bignumber_1.default(0);
637
+ for (_c = 0, _d = transaction.vin; _c < _d.length; _c++) {
638
+ vin = _d[_c];
639
+ if (vin.addresses && (0, common_1.containsSome)(vin.addresses, addresses)) {
640
+ tempAirGapTransactionIsInbound = false;
641
+ }
642
+ tempAirGapTransactionFrom.push.apply(tempAirGapTransactionFrom, vin.addresses);
643
+ amount = vin.value ? amount.plus(vin.value) : amount;
644
+ }
645
+ for (_e = 0, _f = transaction.vout; _e < _f.length; _e++) {
646
+ vout = _f[_e];
647
+ if (vout.addresses) {
648
+ tempAirGapTransactionTo.push.apply(tempAirGapTransactionTo, vout.addresses);
649
+ // If receiving address is our address, and transaction is outbound => our change
650
+ if ((0, common_1.containsSome)(vout.addresses, addresses) && !tempAirGapTransactionIsInbound) {
651
+ // remove only if related to this address
652
+ amount = amount.minus(new bignumber_1.default(vout.value));
653
+ }
654
+ // If receiving address is not ours, and transaction isbound => senders change
655
+ if (!(0, common_1.containsSome)(vout.addresses, addresses) && tempAirGapTransactionIsInbound) {
656
+ amount = amount.minus(new bignumber_1.default(vout.value));
657
+ }
658
+ }
659
+ }
660
+ // deduct fee from amount
661
+ amount = amount.minus(new bignumber_1.default(transaction.fees));
662
+ airGapTransaction = {
663
+ from: tempAirGapTransactionFrom,
664
+ to: tempAirGapTransactionTo,
665
+ isInbound: tempAirGapTransactionIsInbound,
666
+ amount: (0, module_kit_1.newAmount)(amount, 'blockchain'),
667
+ fee: (0, module_kit_1.newAmount)(transaction.fees, 'blockchain'),
668
+ status: {
669
+ type: 'applied',
670
+ hash: transaction.txid,
671
+ block: transaction.blockHeight.toString()
672
+ },
673
+ network: this.options.network,
674
+ timestamp: transaction.blockTime
675
+ };
676
+ airGapTransactions.push(airGapTransaction);
677
+ }
678
+ }
679
+ hasNext = page < data.totalPages;
680
+ return [2 /*return*/, {
681
+ transactions: airGapTransactions,
682
+ cursor: {
683
+ hasNext: hasNext,
684
+ page: hasNext ? page + 1 : undefined
685
+ }
686
+ }];
687
+ }
688
+ });
689
+ });
690
+ };
691
+ BitcoinTaprootProtocolImpl.prototype.getBalanceOfPublicKey = function (publicKey) {
692
+ return __awaiter(this, void 0, void 0, function () {
693
+ return __generator(this, function (_a) {
694
+ switch (publicKey.type) {
695
+ case 'pub':
696
+ return [2 /*return*/, this.getBalanceOfNonExtendedPublicKey(publicKey)];
697
+ case 'xpub':
698
+ return [2 /*return*/, this.getBalanceOfExtendedPublicKey(publicKey)];
699
+ default:
700
+ (0, coinlib_core_1.assertNever)(publicKey);
701
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Unsupported public key type.');
702
+ }
703
+ return [2 /*return*/];
704
+ });
705
+ });
706
+ };
707
+ BitcoinTaprootProtocolImpl.prototype.getBalanceOfNonExtendedPublicKey = function (publicKey) {
708
+ return __awaiter(this, void 0, void 0, function () {
709
+ var address;
710
+ return __generator(this, function (_a) {
711
+ switch (_a.label) {
712
+ case 0: return [4 /*yield*/, this.getAddressFromPublicKey(publicKey)];
713
+ case 1:
714
+ address = _a.sent();
715
+ return [2 /*return*/, this.getBalanceOfAddresses([address])];
716
+ }
717
+ });
718
+ });
719
+ };
720
+ BitcoinTaprootProtocolImpl.prototype.getBalanceOfExtendedPublicKey = function (extendedPublicKey) {
721
+ return __awaiter(this, void 0, void 0, function () {
722
+ var encodedExtendedPublicKey, data;
723
+ return __generator(this, function (_a) {
724
+ switch (_a.label) {
725
+ case 0:
726
+ encodedExtendedPublicKey = (0, key_1.convertExtendedPublicKey)(extendedPublicKey, { format: 'encoded', type: 'xpub' });
727
+ return [4 /*yield*/, index_1.default.get("".concat(this.options.network.indexerApi, "/api/v2/xpub/tr(").concat(encodedExtendedPublicKey.value, ")?pageSize=1"), {
728
+ responseType: 'json'
729
+ })];
730
+ case 1:
731
+ data = (_a.sent()).data;
732
+ return [2 /*return*/, {
733
+ total: (0, module_kit_1.newAmount)(data.balance, 'blockchain')
734
+ }];
735
+ }
736
+ });
737
+ });
738
+ };
739
+ BitcoinTaprootProtocolImpl.prototype.getTransactionMaxAmountWithPublicKey = function (publicKey, to, configuration) {
740
+ return __awaiter(this, void 0, void 0, function () {
741
+ return __generator(this, function (_a) {
742
+ return [2 /*return*/, this.segwit.getTransactionMaxAmountWithPublicKey(publicKey, to, configuration)];
743
+ });
744
+ });
745
+ };
746
+ BitcoinTaprootProtocolImpl.prototype.getTransactionFeeWithPublicKey = function (publicKey, details, configuration) {
747
+ return __awaiter(this, void 0, void 0, function () {
748
+ return __generator(this, function (_a) {
749
+ return [2 /*return*/, this.segwit.getTransactionFeeWithPublicKey(publicKey, details, configuration)];
750
+ });
751
+ });
752
+ };
753
+ BitcoinTaprootProtocolImpl.prototype.broadcastTransaction = function (transaction) {
754
+ return __awaiter(this, void 0, void 0, function () {
755
+ var psbt, hexTransaction, data;
756
+ return __generator(this, function (_a) {
757
+ switch (_a.label) {
758
+ case 0:
759
+ psbt = this.bitcoinJS.lib.Psbt.fromHex(transaction.psbt);
760
+ // Verify and finalize each Taproot input
761
+ psbt.data.inputs.forEach(function (input, index) {
762
+ if (input.tapInternalKey) {
763
+ try {
764
+ var finalized = psbt.finalizeTaprootInput(index);
765
+ if (!finalized) {
766
+ throw new Error("Failed to finalize Taproot input #".concat(index));
767
+ }
768
+ }
769
+ catch (error) {
770
+ throw new Error("Error finalizing Taproot input #".concat(index, ": ").concat(error));
771
+ }
772
+ }
773
+ });
774
+ hexTransaction = psbt.extractTransaction().toHex();
775
+ return [4 /*yield*/, index_1.default.post("".concat(this.options.network.indexerApi, "/api/v2/sendtx/"), hexTransaction)];
776
+ case 1:
777
+ data = (_a.sent()).data;
778
+ return [2 /*return*/, data.result
779
+ // return ''
780
+ ];
781
+ }
782
+ });
783
+ });
784
+ };
785
+ BitcoinTaprootProtocolImpl.prototype.getExtendedKeyPairFromDerivative = function (derivative) {
786
+ return __awaiter(this, void 0, void 0, function () {
787
+ var bip32;
788
+ return __generator(this, function (_a) {
789
+ bip32 = this.derivativeToBip32Node(derivative);
790
+ return [2 /*return*/, {
791
+ secretKey: (0, module_kit_1.newExtendedSecretKey)(bip32.toBase58(), 'encoded'),
792
+ publicKey: (0, key_1.convertExtendedPublicKey)((0, module_kit_1.newExtendedPublicKey)(bip32.neutered().toBase58(), 'encoded'), {
793
+ format: 'encoded',
794
+ type: 'xpub'
795
+ })
796
+ }];
797
+ });
798
+ });
799
+ };
800
+ BitcoinTaprootProtocolImpl.prototype.derivativeToBip32Node = function (derivative) {
801
+ var extendedSecretKey = this.convertCryptoDerivative(derivative);
802
+ return this.bip32.fromBase58(extendedSecretKey.value, this.bitcoinJS.config.network);
803
+ };
804
+ BitcoinTaprootProtocolImpl.prototype.convertCryptoDerivative = function (derivative) {
805
+ var hexNode = (0, crypto_1.encodeDerivative)('hex', __assign(__assign({}, derivative), { secretKey: "00".concat(derivative.secretKey) }));
806
+ var extendedSecretKey = {
807
+ type: 'xpriv',
808
+ format: 'hex',
809
+ value: hexNode.secretKey
810
+ };
811
+ return (0, key_1.convertExtendedSecretKey)(extendedSecretKey, { format: 'encoded', type: 'xprv' });
812
+ };
813
+ BitcoinTaprootProtocolImpl.prototype.deriveFromExtendedSecretKey = function (extendedSecretKey, visibilityIndex, addressIndex) {
814
+ return __awaiter(this, void 0, void 0, function () {
815
+ return __generator(this, function (_a) {
816
+ return [2 /*return*/, this.segwit.deriveFromExtendedSecretKey(extendedSecretKey, visibilityIndex, addressIndex)];
817
+ });
818
+ });
819
+ };
820
+ BitcoinTaprootProtocolImpl.prototype.deriveFromExtendedPublicKey = function (extendedPublicKey, visibilityIndex, addressIndex) {
821
+ return __awaiter(this, void 0, void 0, function () {
822
+ var encodedPublicKey, derivedBip32;
823
+ return __generator(this, function (_a) {
824
+ encodedPublicKey = (0, key_1.convertExtendedPublicKey)(extendedPublicKey, { format: 'encoded', type: 'xpub' });
825
+ derivedBip32 = this.bip32
826
+ .fromBase58(encodedPublicKey.value, this.bitcoinJS.config.network)
827
+ .derive(visibilityIndex)
828
+ .derive(addressIndex);
829
+ return [2 /*return*/, (0, module_kit_1.newPublicKey)(Buffer.from(derivedBip32.publicKey).toString('hex'), 'hex')];
830
+ });
831
+ });
832
+ };
833
+ BitcoinTaprootProtocolImpl.prototype.signMessageWithKeyPair = function (message, keyPair) {
834
+ return __awaiter(this, void 0, void 0, function () {
835
+ return __generator(this, function (_a) {
836
+ return [2 /*return*/, this.segwit.signMessageWithKeyPair(message, keyPair)];
837
+ });
838
+ });
839
+ };
840
+ BitcoinTaprootProtocolImpl.prototype.verifyMessageWithPublicKey = function (message, signature, publicKey) {
841
+ return __awaiter(this, void 0, void 0, function () {
842
+ return __generator(this, function (_a) {
843
+ return [2 /*return*/, this.segwit.verifyMessageWithPublicKey(message, signature, publicKey)];
844
+ });
845
+ });
846
+ };
847
+ BitcoinTaprootProtocolImpl.prototype.decryptAsymmetricWithKeyPair = function (payload, keyPair) {
848
+ return __awaiter(this, void 0, void 0, function () {
849
+ return __generator(this, function (_a) {
850
+ return [2 /*return*/, this.segwit.decryptAsymmetricWithKeyPair(payload, keyPair)];
851
+ });
852
+ });
853
+ };
854
+ BitcoinTaprootProtocolImpl.prototype.encryptAsymmetricWithPublicKey = function (payload, publicKey) {
855
+ return __awaiter(this, void 0, void 0, function () {
856
+ return __generator(this, function (_a) {
857
+ return [2 /*return*/, this.segwit.encryptAsymmetricWithPublicKey(payload, publicKey)];
858
+ });
859
+ });
860
+ };
861
+ BitcoinTaprootProtocolImpl.prototype.encryptAESWithSecretKey = function (payload, secretKey) {
862
+ return __awaiter(this, void 0, void 0, function () {
863
+ return __generator(this, function (_a) {
864
+ return [2 /*return*/, this.segwit.encryptAESWithSecretKey(payload, secretKey)];
865
+ });
866
+ });
867
+ };
868
+ BitcoinTaprootProtocolImpl.prototype.decryptAESWithSecretKey = function (payload, secretKey) {
869
+ return this.segwit.decryptAESWithSecretKey(payload, secretKey);
870
+ };
871
+ BitcoinTaprootProtocolImpl.prototype.getBalanceOfAddress = function (address, configuration) {
872
+ return __awaiter(this, void 0, void 0, function () {
873
+ return __generator(this, function (_a) {
874
+ return [2 /*return*/, this.segwit.getBalanceOfAddress(address)];
875
+ });
876
+ });
877
+ };
878
+ BitcoinTaprootProtocolImpl.prototype.getBalanceOfAddresses = function (addresses, configuration) {
879
+ return __awaiter(this, void 0, void 0, function () {
880
+ return __generator(this, function (_a) {
881
+ return [2 /*return*/, this.segwit.getBalanceOfAddresses(addresses)];
882
+ });
883
+ });
884
+ };
885
+ // Common methods similar to Segwit implementation
886
+ // ... [Include all the common methods from Segwit implementation but modify for Taproot]
887
+ BitcoinTaprootProtocolImpl.prototype.getAddressFromNonExtendedPublicKey = function (publicKey) {
888
+ return __awaiter(this, void 0, void 0, function () {
889
+ var hexPublicKey, payment;
890
+ return __generator(this, function (_a) {
891
+ hexPublicKey = (0, key_1.convertPublicKey)(publicKey, 'hex');
892
+ payment = this.bitcoinJS.lib.payments.p2tr({
893
+ internalPubkey: Buffer.from(hexPublicKey.value, 'hex').subarray(1, 33),
894
+ network: this.bitcoinJS.config.network
895
+ });
896
+ return [2 /*return*/, BitcoinTaprootAddress_1.BitcoinTaprootAddress.fromPayment(payment).asString()];
897
+ });
898
+ });
899
+ };
900
+ BitcoinTaprootProtocolImpl.prototype.prepareTransactionWithExtendedPublicKey = function (extendedPublicKey, details, configuration) {
901
+ return __awaiter(this, void 0, void 0, function () {
902
+ var fee, estimatedFee, wrappedFee, transaction, utxos, totalRequiredBalance, valueAccumulator, getPathIndexes, _i, utxos_1, utxo, indexes, derivedPublicKey, derivedAddress, i, value, lastUsedInternalAddress, changeValue, changeAddressIndex, derivedPublicKey, derivedAddress, psbt, xpubExtendedPublicKey, keyPair, replaceByFee;
903
+ var _this = this;
904
+ return __generator(this, function (_a) {
905
+ switch (_a.label) {
906
+ case 0:
907
+ if ((configuration === null || configuration === void 0 ? void 0 : configuration.masterFingerprint) === undefined) {
908
+ throw new errors_1.ConditionViolationError(coinlib_core_1.Domain.BITCOIN, 'Master fingerprint not set.');
909
+ }
910
+ if (!((configuration === null || configuration === void 0 ? void 0 : configuration.fee) !== undefined)) return [3 /*break*/, 1];
911
+ fee = configuration.fee;
912
+ return [3 /*break*/, 3];
913
+ case 1: return [4 /*yield*/, this.getTransactionFeeWithPublicKey(extendedPublicKey, details)];
914
+ case 2:
915
+ estimatedFee = _a.sent();
916
+ fee = estimatedFee.medium;
917
+ _a.label = 3;
918
+ case 3:
919
+ wrappedFee = new bignumber_1.default((0, module_kit_1.newAmount)(fee).blockchain(this.segwit.legacy.units).value);
920
+ transaction = (0, module_kit_1.newUnsignedTransaction)({
921
+ ins: [],
922
+ outs: []
923
+ });
924
+ return [4 /*yield*/, index_1.default.get("".concat(this.options.network.indexerApi, "/api/v2/utxo/tr(").concat(extendedPublicKey.value, ")?confirmed=true"), {
925
+ responseType: 'json'
926
+ })];
927
+ case 4:
928
+ utxos = (_a.sent()).data;
929
+ if (utxos.length <= 0) {
930
+ throw new errors_1.BalanceError(coinlib_core_1.Domain.BITCOIN, 'Not enough balance.'); // no transactions found on those addresses, probably won't find anything in the next ones
931
+ }
932
+ totalRequiredBalance = details
933
+ .map(function (_a) {
934
+ var amount = _a.amount;
935
+ return new bignumber_1.default((0, module_kit_1.newAmount)(amount).blockchain(_this.segwit.legacy.units).value);
936
+ })
937
+ .reduce(function (accumulator, currentValue) { return accumulator.plus(currentValue); })
938
+ .plus(wrappedFee);
939
+ valueAccumulator = new bignumber_1.default(0);
940
+ getPathIndexes = function (path) {
941
+ var result = path
942
+ .split('/')
943
+ .slice(-2)
944
+ .map(function (item) { return parseInt(item); })
945
+ .filter(function (item) { return !isNaN(item); });
946
+ if (result.length !== 2) {
947
+ throw new Error('Unexpected path format');
948
+ }
949
+ return [result[0], result[1]];
950
+ };
951
+ _i = 0, utxos_1 = utxos;
952
+ _a.label = 5;
953
+ case 5:
954
+ if (!(_i < utxos_1.length)) return [3 /*break*/, 9];
955
+ utxo = utxos_1[_i];
956
+ valueAccumulator = valueAccumulator.plus(utxo.value);
957
+ indexes = getPathIndexes(utxo.path);
958
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(extendedPublicKey, indexes[0], indexes[1])];
959
+ case 6:
960
+ derivedPublicKey = _a.sent();
961
+ return [4 /*yield*/, this.getAddressFromPublicKey(derivedPublicKey)];
962
+ case 7:
963
+ derivedAddress = _a.sent();
964
+ if (derivedAddress === utxo.address) {
965
+ transaction.ins.push({
966
+ txId: utxo.txid,
967
+ value: new bignumber_1.default(utxo.value).toString(10),
968
+ vout: utxo.vout,
969
+ address: utxo.address,
970
+ derivationPath: utxo.path
971
+ });
972
+ }
973
+ else {
974
+ throw new Error('Invalid address returned from API');
975
+ }
976
+ if (valueAccumulator.isGreaterThanOrEqualTo(totalRequiredBalance)) {
977
+ return [3 /*break*/, 9];
978
+ }
979
+ _a.label = 8;
980
+ case 8:
981
+ _i++;
982
+ return [3 /*break*/, 5];
983
+ case 9:
984
+ if (valueAccumulator.isLessThan(totalRequiredBalance)) {
985
+ throw new Error('not enough balance 2');
986
+ }
987
+ for (i = 0; i < details.length; i++) {
988
+ value = (0, module_kit_1.newAmount)(details[i].amount).blockchain(this.segwit.legacy.units).value;
989
+ transaction.outs.push({
990
+ recipient: details[i].to,
991
+ isChange: false,
992
+ value: value
993
+ });
994
+ valueAccumulator = valueAccumulator.minus(value);
995
+ }
996
+ lastUsedInternalAddress = Math.max.apply(Math, __spreadArray([-1], utxos
997
+ .map(function (utxo) { return getPathIndexes(utxo.path); })
998
+ .filter(function (indexes) { return indexes[0] === 1; })
999
+ .map(function (indexes) { return indexes[1]; }), false));
1000
+ changeValue = valueAccumulator.minus(wrappedFee);
1001
+ if (!changeValue.isGreaterThan(new bignumber_1.default(DUST_AMOUNT))) return [3 /*break*/, 12];
1002
+ changeAddressIndex = lastUsedInternalAddress + 1;
1003
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(extendedPublicKey, 1, changeAddressIndex)];
1004
+ case 10:
1005
+ derivedPublicKey = _a.sent();
1006
+ return [4 /*yield*/, this.getAddressFromPublicKey(derivedPublicKey)];
1007
+ case 11:
1008
+ derivedAddress = _a.sent();
1009
+ console.log("outs", {
1010
+ recipient: derivedAddress,
1011
+ isChange: true,
1012
+ value: changeValue.toString(10),
1013
+ derivationPath: "1/".concat(changeAddressIndex)
1014
+ });
1015
+ transaction.outs.push({
1016
+ recipient: derivedAddress,
1017
+ isChange: true,
1018
+ value: changeValue.toString(10),
1019
+ derivationPath: "1/".concat(changeAddressIndex)
1020
+ });
1021
+ _a.label = 12;
1022
+ case 12:
1023
+ psbt = new this.bitcoinJS.lib.Psbt();
1024
+ // We add the total amount of the transaction to the global map. This can be used to show the info in the "from-to" component after the transaction was signed.
1025
+ psbt.addUnknownKeyValToGlobal({
1026
+ key: Buffer.from('amount'),
1027
+ value: Buffer.from(details
1028
+ .reduce(function (accumulator, next) {
1029
+ return accumulator.plus((0, module_kit_1.newAmount)(next.amount).blockchain(_this.segwit.legacy.units).value);
1030
+ }, new bignumber_1.default(0))
1031
+ .toString())
1032
+ });
1033
+ xpubExtendedPublicKey = (0, key_1.convertExtendedPublicKey)(extendedPublicKey, { format: 'encoded', type: 'xpub' });
1034
+ keyPair = this.bip32.fromBase58(xpubExtendedPublicKey.value);
1035
+ replaceByFee = (configuration === null || configuration === void 0 ? void 0 : configuration.replaceByFee) ? true : false;
1036
+ console.log('transaction.ins', transaction.ins);
1037
+ transaction.ins.forEach(function (tx) {
1038
+ var indexes = getPathIndexes(tx.derivationPath);
1039
+ var childNode = keyPair.derivePath(indexes.join('/'));
1040
+ var xOnlyPubkey = childNode.publicKey.length === 33 ? childNode.publicKey.slice(1, 33) : childNode.publicKey;
1041
+ var payment = _this.bitcoinJS.lib.payments.p2tr({
1042
+ internalPubkey: Buffer.from(xOnlyPubkey),
1043
+ network: _this.bitcoinJS.config.network
1044
+ });
1045
+ var inputCommon = {
1046
+ hash: tx.txId,
1047
+ index: tx.vout,
1048
+ sequence: replaceByFee ? 0xfffffffd : undefined,
1049
+ witnessUtxo: {
1050
+ script: payment.output,
1051
+ value: parseInt(tx.value, 10)
1052
+ }
1053
+ };
1054
+ var p2shOutput = payment.output;
1055
+ if (!p2shOutput) {
1056
+ throw new Error('no p2shOutput');
1057
+ }
1058
+ var fingerprintBuffer = Buffer.from(configuration.masterFingerprint.value, 'hex');
1059
+ psbt.addInput(__assign(__assign({}, inputCommon), { tapInternalKey: Buffer.from(xOnlyPubkey), tapBip32Derivation: [
1060
+ {
1061
+ leafHashes: [],
1062
+ path: tx.derivationPath,
1063
+ pubkey: Buffer.from(xOnlyPubkey),
1064
+ masterFingerprint: fingerprintBuffer
1065
+ }
1066
+ ] }));
1067
+ });
1068
+ transaction.outs.forEach(function (out, index) {
1069
+ psbt.addOutput({ address: out.recipient, value: parseInt(out.value, 10) });
1070
+ if (out.derivationPath) {
1071
+ psbt.addUnknownKeyValToOutput(index, {
1072
+ key: Buffer.from('dp'),
1073
+ value: Buffer.from(out.derivationPath, 'utf8')
1074
+ });
1075
+ }
1076
+ });
1077
+ return [2 /*return*/, (0, module_kit_1.newUnsignedTransaction)({ psbt: psbt.toHex() })];
1078
+ }
1079
+ });
1080
+ });
1081
+ };
1082
+ return BitcoinTaprootProtocolImpl;
1083
+ }());
1084
+ exports.BitcoinTaprootProtocolImpl = BitcoinTaprootProtocolImpl;
1085
+ // Factory
1086
+ function createBitcoinTaprootProtocol(options) {
1087
+ if (options === void 0) { options = {}; }
1088
+ return new BitcoinTaprootProtocolImpl(options);
1089
+ }
1090
+ exports.createBitcoinTaprootProtocol = createBitcoinTaprootProtocol;
1091
+ //# sourceMappingURL=BitcoinTaprootProtocol.js.map