@airgap/bitcoin 0.13.42 → 0.13.43-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 (28) hide show
  1. package/package.json +5 -5
  2. package/v1/data/BitcoinLegacyAddress.d.ts +9 -0
  3. package/v1/data/BitcoinLegacyAddress.js +25 -0
  4. package/v1/data/BitcoinLegacyAddress.js.map +1 -0
  5. package/v1/index.d.ts +7 -4
  6. package/v1/index.js +3 -1
  7. package/v1/index.js.map +1 -1
  8. package/v1/module/BitcoinModule.js +3 -1
  9. package/v1/module/BitcoinModule.js.map +1 -1
  10. package/v1/protocol/BitcoinLegacyProtocol.d.ts +56 -0
  11. package/v1/protocol/BitcoinLegacyProtocol.js +858 -0
  12. package/v1/protocol/BitcoinLegacyProtocol.js.map +1 -0
  13. package/v1/serializer/v3/schemas/converter/transaction-converter.d.ts +6 -0
  14. package/v1/serializer/v3/schemas/converter/transaction-converter.js +22 -1
  15. package/v1/serializer/v3/schemas/converter/transaction-converter.js.map +1 -1
  16. package/v1/serializer/v3/schemas/definitions/transaction-sign-request-bitcoin-legacy.d.ts +4 -0
  17. package/v1/serializer/v3/schemas/definitions/transaction-sign-request-bitcoin-legacy.js +3 -0
  18. package/v1/serializer/v3/schemas/definitions/transaction-sign-request-bitcoin-legacy.js.map +1 -0
  19. package/v1/serializer/v3/schemas/definitions/transaction-sign-response-bitcoin-legacy.d.ts +3 -0
  20. package/v1/serializer/v3/schemas/definitions/transaction-sign-response-bitcoin-legacy.js +3 -0
  21. package/v1/serializer/v3/schemas/definitions/transaction-sign-response-bitcoin-legacy.js.map +1 -0
  22. package/v1/serializer/v3/schemas/generated/transaction-sign-request-bitcoin-legacy.json +29 -0
  23. package/v1/serializer/v3/schemas/generated/transaction-sign-response-bitcoin-legacy.json +19 -0
  24. package/v1/serializer/v3/serializer-companion.d.ts +0 -1
  25. package/v1/serializer/v3/serializer-companion.js +50 -50
  26. package/v1/serializer/v3/serializer-companion.js.map +1 -1
  27. package/v1/types/bitcoinjs.d.ts +6 -0
  28. package/v1/types/transaction.d.ts +10 -0
@@ -0,0 +1,858 @@
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.createBitcoinLegacyProtocol = exports.BitcoinLegacyProtocolImpl = 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 crypto_1 = require("@airgap/crypto");
91
+ var module_kit_1 = require("@airgap/module-kit");
92
+ var bitcoin = __importStar(require("bitcoinjs-lib"));
93
+ var common_1 = require("../utils/common");
94
+ var key_1 = require("../utils/key");
95
+ var network_1 = require("../utils/network");
96
+ var bip32_1 = require("bip32");
97
+ var secp256k1_1 = __importDefault(require("@bitcoinerlab/secp256k1"));
98
+ var BitcoinProtocol_1 = require("./BitcoinProtocol");
99
+ var BitcoinLegacyAddress_1 = require("../data/BitcoinLegacyAddress");
100
+ // Implementation
101
+ var DUST_AMOUNT = 50;
102
+ var BitcoinLegacyProtocolImpl = /** @class */ (function () {
103
+ function BitcoinLegacyProtocolImpl(options, bitcoinJS) {
104
+ if (options === void 0) { options = {}; }
105
+ if (bitcoinJS === void 0) { bitcoinJS = bitcoin; }
106
+ this._isBitcoinProtocol = true;
107
+ this.bip32 = (0, bip32_1.BIP32Factory)(secp256k1_1.default);
108
+ this.options = (0, BitcoinProtocol_1.createBitcoinProtocolOptions)(options.network);
109
+ this.bitcoinJS = {
110
+ lib: bitcoinJS,
111
+ config: {
112
+ network: (0, network_1.getBitcoinJSNetwork)(this.options.network, bitcoinJS)
113
+ }
114
+ };
115
+ this.bitcoinJS.lib.initEccLib(secp256k1_1.default);
116
+ this.legacy = new BitcoinProtocol_1.BitcoinProtocolImpl(options);
117
+ this.metadata = this.legacy.metadata;
118
+ }
119
+ BitcoinLegacyProtocolImpl.prototype.getMetadata = function () {
120
+ return __awaiter(this, void 0, void 0, function () {
121
+ return __generator(this, function (_a) {
122
+ return [2 /*return*/, this.metadata];
123
+ });
124
+ });
125
+ };
126
+ BitcoinLegacyProtocolImpl.prototype.getAddressFromPublicKey = function (publicKey) {
127
+ return __awaiter(this, void 0, void 0, function () {
128
+ return __generator(this, function (_a) {
129
+ switch (publicKey.type) {
130
+ case 'pub':
131
+ return [2 /*return*/, this.getAddressFromNonExtendedPublicKey(publicKey)];
132
+ case 'xpub':
133
+ return [2 /*return*/, this.getAddressFromExtendedPublicKey(publicKey)];
134
+ default:
135
+ (0, coinlib_core_1.assertNever)(publicKey);
136
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Public key type is not supported.');
137
+ }
138
+ return [2 /*return*/];
139
+ });
140
+ });
141
+ };
142
+ BitcoinLegacyProtocolImpl.prototype.getAddressFromNonExtendedPublicKey = function (publicKey) {
143
+ return __awaiter(this, void 0, void 0, function () {
144
+ var hexPublicKey, payment;
145
+ return __generator(this, function (_a) {
146
+ hexPublicKey = (0, key_1.convertPublicKey)(publicKey, 'hex');
147
+ payment = this.bitcoinJS.lib.payments.p2pkh({ pubkey: Buffer.from(hexPublicKey.value, 'hex') });
148
+ return [2 /*return*/, BitcoinLegacyAddress_1.BitcoinLegacyAddress.fromPayment(payment).asString()];
149
+ });
150
+ });
151
+ };
152
+ BitcoinLegacyProtocolImpl.prototype.getAddressFromExtendedPublicKey = function (extendedPublicKey) {
153
+ return __awaiter(this, void 0, void 0, function () {
154
+ var encodedExtendedPublicKey, bip32;
155
+ return __generator(this, function (_a) {
156
+ encodedExtendedPublicKey = (0, key_1.convertExtendedPublicKey)(extendedPublicKey, { format: 'encoded', type: 'xpub' });
157
+ bip32 = this.bip32.fromBase58(encodedExtendedPublicKey.value, this.bitcoinJS.config.network);
158
+ return [2 /*return*/, BitcoinLegacyAddress_1.BitcoinLegacyAddress.fromBip32(bip32).asString()];
159
+ });
160
+ });
161
+ };
162
+ BitcoinLegacyProtocolImpl.prototype.deriveFromExtendedPublicKey = function (extendedPublicKey, visibilityIndex, addressIndex) {
163
+ return __awaiter(this, void 0, void 0, function () {
164
+ var encodedPublicKey, derivedBip32;
165
+ return __generator(this, function (_a) {
166
+ encodedPublicKey = (0, key_1.convertExtendedPublicKey)(extendedPublicKey, { format: 'encoded', type: 'xpub' });
167
+ derivedBip32 = this.bip32
168
+ .fromBase58(encodedPublicKey.value, this.bitcoinJS.config.network)
169
+ .derive(visibilityIndex)
170
+ .derive(addressIndex);
171
+ return [2 /*return*/, (0, module_kit_1.newPublicKey)(Buffer.from(derivedBip32.publicKey).toString('hex'), 'hex')];
172
+ });
173
+ });
174
+ };
175
+ BitcoinLegacyProtocolImpl.prototype.getDetailsFromTransaction = function (transaction, _publicKey) {
176
+ return __awaiter(this, void 0, void 0, function () {
177
+ return __generator(this, function (_a) {
178
+ return [2 /*return*/, this.getDetailsFromPSBT(transaction.psbt, _publicKey)];
179
+ });
180
+ });
181
+ };
182
+ BitcoinLegacyProtocolImpl.prototype.getDetailsFromPSBT = function (psbt, publickey) {
183
+ return __awaiter(this, void 0, void 0, function () {
184
+ var decodedPSBT, inTotal, i, input, prevIndex, prevTx, fee, _i, _a, o, alerts, clonedPSBT, amount, changeAddressDatas, changeAddressInfo;
185
+ var _this = this;
186
+ return __generator(this, function (_b) {
187
+ switch (_b.label) {
188
+ case 0:
189
+ decodedPSBT = this.bitcoinJS.lib.Psbt.fromHex(psbt);
190
+ inTotal = new bignumber_1.default(0);
191
+ for (i = 0; i < decodedPSBT.data.inputs.length; i++) {
192
+ input = decodedPSBT.data.inputs[i];
193
+ if (input.witnessUtxo) {
194
+ inTotal = inTotal.plus(input.witnessUtxo.value);
195
+ }
196
+ else if (input.nonWitnessUtxo) {
197
+ prevIndex = decodedPSBT.txInputs[i].index;
198
+ prevTx = this.bitcoinJS.lib.Transaction.fromBuffer(input.nonWitnessUtxo);
199
+ inTotal = inTotal.plus(prevTx.outs[prevIndex].value);
200
+ }
201
+ else {
202
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'PSBT input missing UTXO data.');
203
+ }
204
+ }
205
+ fee = inTotal;
206
+ for (_i = 0, _a = decodedPSBT.txOutputs; _i < _a.length; _i++) {
207
+ o = _a[_i];
208
+ fee = fee.minus(o.value);
209
+ }
210
+ alerts = [];
211
+ clonedPSBT = decodedPSBT.clone();
212
+ (0, common_1.eachRecursive)(clonedPSBT);
213
+ amount = (function () {
214
+ if (decodedPSBT.txOutputs.length === 1) {
215
+ return new bignumber_1.default(decodedPSBT.txOutputs[0].value);
216
+ }
217
+ {
218
+ var unknownKeyVals = decodedPSBT.data.globalMap.unknownKeyVals;
219
+ if (unknownKeyVals) {
220
+ var amountArray = unknownKeyVals.filter(function (kv) { return kv.key.equals(Buffer.from('amount')); });
221
+ if (amountArray.length > 0) {
222
+ return new bignumber_1.default(amountArray[0].value.toString());
223
+ }
224
+ }
225
+ }
226
+ var accumulated = new bignumber_1.default(0);
227
+ var useAccumulated = false;
228
+ decodedPSBT.data.outputs.forEach(function (outputKeyValues, index) {
229
+ if (outputKeyValues.unknownKeyVals) {
230
+ var derivationPaths = outputKeyValues.unknownKeyVals
231
+ .filter(function (kv) { return kv.key.equals(Buffer.from('dp')); })
232
+ .map(function (kv) { return kv.value.toString(); });
233
+ if (derivationPaths.length > 0) {
234
+ useAccumulated = true;
235
+ return;
236
+ }
237
+ }
238
+ var output = decodedPSBT.txOutputs[index];
239
+ accumulated = accumulated.plus(output.value);
240
+ });
241
+ if (useAccumulated) {
242
+ return accumulated;
243
+ }
244
+ return decodedPSBT.txOutputs
245
+ .map(function (obj) { return new bignumber_1.default(obj.value); })
246
+ .reduce(function (accumulator, currentValue) { return accumulator.plus(currentValue); });
247
+ })();
248
+ return [4 /*yield*/, Promise.all(decodedPSBT.data.outputs.map(function (obj, index) { return __awaiter(_this, void 0, void 0, function () {
249
+ var isChangeAddress, isOwned, addressIndex, address, amount, ourGeneratedAddress, getIndexes, ourPublickey, x, ourPublickey, x, ourPublickey;
250
+ return __generator(this, function (_a) {
251
+ switch (_a.label) {
252
+ case 0:
253
+ isChangeAddress = false;
254
+ isOwned = false;
255
+ addressIndex = 0;
256
+ address = decodedPSBT.txOutputs[index].address;
257
+ amount = decodedPSBT.txOutputs[index].value;
258
+ if (!obj.bip32Derivation) return [3 /*break*/, 11];
259
+ isChangeAddress = true;
260
+ getIndexes = obj.bip32Derivation[0].path.split('/');
261
+ if (!(publickey.type === 'xpub')) return [3 /*break*/, 3];
262
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(publickey, 1, +getIndexes[getIndexes.length - 1])];
263
+ case 1:
264
+ ourPublickey = _a.sent();
265
+ return [4 /*yield*/, this.getAddressFromPublicKey(ourPublickey)];
266
+ case 2:
267
+ ourGeneratedAddress = _a.sent();
268
+ return [3 /*break*/, 5];
269
+ case 3: return [4 /*yield*/, this.getAddressFromNonExtendedPublicKey(publickey)];
270
+ case 4:
271
+ ourGeneratedAddress = _a.sent();
272
+ _a.label = 5;
273
+ case 5:
274
+ if (ourGeneratedAddress === address) {
275
+ isOwned = true;
276
+ addressIndex = +getIndexes[getIndexes.length - 1];
277
+ }
278
+ x = 0;
279
+ _a.label = 6;
280
+ case 6:
281
+ if (!(x < 1000)) return [3 /*break*/, 10];
282
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(publickey, 1, x)];
283
+ case 7:
284
+ ourPublickey = _a.sent();
285
+ return [4 /*yield*/, this.getAddressFromPublicKey(ourPublickey)];
286
+ case 8:
287
+ ourGeneratedAddress = _a.sent();
288
+ if (ourGeneratedAddress === address) {
289
+ isOwned = true;
290
+ addressIndex = x;
291
+ return [3 /*break*/, 10];
292
+ }
293
+ _a.label = 9;
294
+ case 9:
295
+ x++;
296
+ return [3 /*break*/, 6];
297
+ case 10: return [3 /*break*/, 16];
298
+ case 11:
299
+ if (!obj.unknownKeyVals) return [3 /*break*/, 16];
300
+ x = 0;
301
+ _a.label = 12;
302
+ case 12:
303
+ if (!(x < 1000)) return [3 /*break*/, 16];
304
+ isChangeAddress = true;
305
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(publickey, 1, x)];
306
+ case 13:
307
+ ourPublickey = _a.sent();
308
+ return [4 /*yield*/, this.getAddressFromPublicKey(ourPublickey)];
309
+ case 14:
310
+ ourGeneratedAddress = _a.sent();
311
+ if (ourGeneratedAddress === address) {
312
+ isOwned = true;
313
+ addressIndex = x;
314
+ return [3 /*break*/, 16];
315
+ }
316
+ _a.label = 15;
317
+ case 15:
318
+ x++;
319
+ return [3 /*break*/, 12];
320
+ case 16:
321
+ if (isChangeAddress && isOwned) {
322
+ alerts.push({
323
+ type: 'success',
324
+ title: {
325
+ type: 'plain',
326
+ value: ''
327
+ },
328
+ description: {
329
+ type: 'plain',
330
+ value: 'Note: your change address has been verified'
331
+ },
332
+ icon: undefined,
333
+ actions: undefined
334
+ });
335
+ }
336
+ else if (isChangeAddress && !isOwned) {
337
+ alerts.push({
338
+ type: 'warning',
339
+ title: {
340
+ type: 'plain',
341
+ value: ''
342
+ },
343
+ description: {
344
+ type: 'plain',
345
+ value: 'Note: your change address has not been verified'
346
+ },
347
+ icon: undefined,
348
+ actions: undefined
349
+ });
350
+ }
351
+ return [2 /*return*/, [
352
+ address,
353
+ {
354
+ isChangeAddress: isChangeAddress,
355
+ isOwned: isOwned,
356
+ path: addressIndex === 0 ? '' : "m/44'/0'/0'/1/".concat(addressIndex),
357
+ amount: amount
358
+ }
359
+ ]];
360
+ }
361
+ });
362
+ }); }))];
363
+ case 1:
364
+ changeAddressDatas = _b.sent();
365
+ changeAddressInfo = {};
366
+ changeAddressDatas.forEach(function (changeAddressData) {
367
+ changeAddressInfo[changeAddressData[0]] = changeAddressData[1];
368
+ });
369
+ return [2 /*return*/, [
370
+ {
371
+ from: decodedPSBT.data.inputs.map(function (obj) {
372
+ var _a, _b;
373
+ return (_b = (_a = obj.bip32Derivation) === null || _a === void 0 ? void 0 : _a.map(function (el) {
374
+ return _this.bitcoinJS.lib.payments.p2pkh({
375
+ pubkey: el.pubkey,
376
+ network: _this.bitcoinJS.lib.networks.bitcoin
377
+ }).address;
378
+ }).join(' ')) !== null && _b !== void 0 ? _b : 'INVALID';
379
+ }),
380
+ to: decodedPSBT.txOutputs.map(function (obj) {
381
+ return obj.address || "Script: ".concat(obj.script.toString('hex')) || 'unknown';
382
+ }),
383
+ isInbound: false,
384
+ amount: (0, module_kit_1.newAmount)(amount, 'blockchain'),
385
+ fee: (0, module_kit_1.newAmount)(fee, 'blockchain'),
386
+ network: this.options.network,
387
+ changeAddressInfo: changeAddressInfo,
388
+ uiAlerts: alerts,
389
+ json: {
390
+ inputTx: (0, common_1.eachRecursive)(clonedPSBT.txInputs),
391
+ outputTx: (0, common_1.eachRecursive)(clonedPSBT.txOutputs),
392
+ inputData: clonedPSBT.data.inputs,
393
+ outputData: clonedPSBT.data.outputs,
394
+ PSBTVersion: clonedPSBT.version,
395
+ PSBTLocktime: clonedPSBT.locktime,
396
+ PSBTGlobalMap: clonedPSBT.data.globalMap,
397
+ rawPSBT: psbt
398
+ }
399
+ }
400
+ ]];
401
+ }
402
+ });
403
+ });
404
+ };
405
+ BitcoinLegacyProtocolImpl.prototype.verifyMessageWithPublicKey = function (message, signature, publicKey) {
406
+ return __awaiter(this, void 0, void 0, function () {
407
+ return __generator(this, function (_a) {
408
+ return [2 /*return*/, this.legacy.verifyMessageWithPublicKey(message, signature, publicKey)];
409
+ });
410
+ });
411
+ };
412
+ BitcoinLegacyProtocolImpl.prototype.encryptAsymmetricWithPublicKey = function (payload, publicKey) {
413
+ return __awaiter(this, void 0, void 0, function () {
414
+ return __generator(this, function (_a) {
415
+ return [2 /*return*/, this.legacy.encryptAsymmetricWithPublicKey(payload, publicKey)];
416
+ });
417
+ });
418
+ };
419
+ BitcoinLegacyProtocolImpl.prototype.getCryptoConfiguration = function () {
420
+ return __awaiter(this, void 0, void 0, function () {
421
+ return __generator(this, function (_a) {
422
+ return [2 /*return*/, this.legacy.getCryptoConfiguration()];
423
+ });
424
+ });
425
+ };
426
+ BitcoinLegacyProtocolImpl.prototype.getKeyPairFromDerivative = function (derivative) {
427
+ return __awaiter(this, void 0, void 0, function () {
428
+ var bip32, privateKeyUint8, privateKey, publicKeyUint8, publicKey;
429
+ return __generator(this, function (_a) {
430
+ bip32 = this.derivativeToBip32Node(derivative);
431
+ privateKeyUint8 = bip32.privateKey;
432
+ if (privateKeyUint8 === undefined) {
433
+ throw new Error('No private key!');
434
+ }
435
+ privateKey = Buffer.from(privateKeyUint8);
436
+ publicKeyUint8 = bip32.publicKey;
437
+ publicKey = Buffer.from(publicKeyUint8);
438
+ return [2 /*return*/, {
439
+ secretKey: (0, module_kit_1.newSecretKey)(privateKey.toString('hex'), 'hex'),
440
+ publicKey: (0, module_kit_1.newPublicKey)(publicKey.toString('hex'), 'hex')
441
+ }];
442
+ });
443
+ });
444
+ };
445
+ BitcoinLegacyProtocolImpl.prototype.getExtendedKeyPairFromDerivative = function (derivative) {
446
+ return __awaiter(this, void 0, void 0, function () {
447
+ var bip32;
448
+ return __generator(this, function (_a) {
449
+ bip32 = this.derivativeToBip32Node(derivative);
450
+ return [2 /*return*/, {
451
+ secretKey: (0, module_kit_1.newExtendedSecretKey)(bip32.toBase58(), 'encoded'),
452
+ publicKey: (0, key_1.convertExtendedPublicKey)((0, module_kit_1.newExtendedPublicKey)(bip32.neutered().toBase58(), 'encoded'), {
453
+ format: 'encoded',
454
+ type: 'xpub'
455
+ })
456
+ }];
457
+ });
458
+ });
459
+ };
460
+ BitcoinLegacyProtocolImpl.prototype.deriveFromExtendedSecretKey = function (extendedSecretKey, visibilityIndex, addressIndex) {
461
+ return __awaiter(this, void 0, void 0, function () {
462
+ var encodedSecretKey, derivedBip32, privateKeyUint8, privateKey;
463
+ return __generator(this, function (_a) {
464
+ encodedSecretKey = (0, key_1.convertExtendedSecretKey)(extendedSecretKey, { format: 'encoded', type: 'xprv' });
465
+ derivedBip32 = this.bip32
466
+ .fromBase58(encodedSecretKey.value, this.bitcoinJS.config.network)
467
+ .derive(visibilityIndex)
468
+ .derive(addressIndex);
469
+ privateKeyUint8 = derivedBip32.privateKey;
470
+ if (privateKeyUint8 === undefined) {
471
+ throw new Error('No private key!');
472
+ }
473
+ privateKey = Buffer.from(privateKeyUint8);
474
+ return [2 /*return*/, (0, module_kit_1.newSecretKey)(privateKey.toString('hex'), 'hex')];
475
+ });
476
+ });
477
+ };
478
+ BitcoinLegacyProtocolImpl.prototype.signTransactionWithSecretKey = function (transaction, secretKey) {
479
+ return __awaiter(this, void 0, void 0, function () {
480
+ return __generator(this, function (_a) {
481
+ switch (secretKey.type) {
482
+ case 'priv':
483
+ return [2 /*return*/, this.signTransactionWithNonExtendedSecretKey(transaction, secretKey)];
484
+ case 'xpriv':
485
+ return [2 /*return*/, this.signTransactionWithExtendedSecretKey(transaction, secretKey)];
486
+ default:
487
+ (0, coinlib_core_1.assertNever)(secretKey);
488
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Secret key type not supported.');
489
+ }
490
+ return [2 /*return*/];
491
+ });
492
+ });
493
+ };
494
+ BitcoinLegacyProtocolImpl.prototype.signTransactionWithNonExtendedSecretKey = function (transaction, secretKey) {
495
+ return __awaiter(this, void 0, void 0, function () {
496
+ return __generator(this, function (_a) {
497
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Sign with non extended secret key not supported');
498
+ });
499
+ });
500
+ };
501
+ BitcoinLegacyProtocolImpl.prototype.signTransactionWithExtendedSecretKey = function (transaction, extendedSecretKey) {
502
+ return __awaiter(this, void 0, void 0, function () {
503
+ var encodedExtendedSecretKey, bip32, decodedPSBT;
504
+ return __generator(this, function (_a) {
505
+ encodedExtendedSecretKey = (0, key_1.convertExtendedSecretKey)(extendedSecretKey, { format: 'encoded', type: 'xprv' });
506
+ bip32 = this.bip32.fromBase58(encodedExtendedSecretKey.value);
507
+ decodedPSBT = this.bitcoinJS.lib.Psbt.fromHex(transaction.psbt);
508
+ decodedPSBT.data.inputs.forEach(function (input, index) {
509
+ var _a;
510
+ (_a = input.bip32Derivation) === null || _a === void 0 ? void 0 : _a.forEach(function (deriv) {
511
+ try {
512
+ // This uses the same logic to find child key as the "findWalletByFingerprintDerivationPathAndProtocolIdentifier" method in the Vault
513
+ var cutoffFrom = deriv.path.lastIndexOf("'") || deriv.path.lastIndexOf('h');
514
+ var childPath = deriv.path.substr(cutoffFrom + 2);
515
+ var childNode_1 = bip32.derivePath(childPath);
516
+ // Wrap publicKey as Buffer to match Signer interface
517
+ decodedPSBT.signInput(index, {
518
+ publicKey: Buffer.from(childNode_1.publicKey),
519
+ sign: function (hash, lowR) { return Buffer.from(childNode_1.sign(hash, lowR)); }
520
+ });
521
+ }
522
+ catch (e) { }
523
+ });
524
+ });
525
+ return [2 /*return*/, (0, module_kit_1.newSignedTransaction)({ psbt: decodedPSBT.toHex() })];
526
+ });
527
+ });
528
+ };
529
+ BitcoinLegacyProtocolImpl.prototype.signMessageWithKeyPair = function (message, keyPair) {
530
+ return __awaiter(this, void 0, void 0, function () {
531
+ return __generator(this, function (_a) {
532
+ return [2 /*return*/, this.legacy.signMessageWithKeyPair(message, keyPair)];
533
+ });
534
+ });
535
+ };
536
+ BitcoinLegacyProtocolImpl.prototype.decryptAsymmetricWithKeyPair = function (payload, keyPair) {
537
+ return __awaiter(this, void 0, void 0, function () {
538
+ return __generator(this, function (_a) {
539
+ return [2 /*return*/, this.legacy.decryptAsymmetricWithKeyPair(payload, keyPair)];
540
+ });
541
+ });
542
+ };
543
+ BitcoinLegacyProtocolImpl.prototype.encryptAESWithSecretKey = function (payload, secretKey) {
544
+ return __awaiter(this, void 0, void 0, function () {
545
+ return __generator(this, function (_a) {
546
+ return [2 /*return*/, this.legacy.encryptAESWithSecretKey(payload, secretKey)];
547
+ });
548
+ });
549
+ };
550
+ BitcoinLegacyProtocolImpl.prototype.decryptAESWithSecretKey = function (payload, secretKey) {
551
+ return __awaiter(this, void 0, void 0, function () {
552
+ return __generator(this, function (_a) {
553
+ return [2 /*return*/, this.legacy.decryptAESWithSecretKey(payload, secretKey)];
554
+ });
555
+ });
556
+ };
557
+ // Online
558
+ BitcoinLegacyProtocolImpl.prototype.getNetwork = function () {
559
+ return __awaiter(this, void 0, void 0, function () {
560
+ return __generator(this, function (_a) {
561
+ return [2 /*return*/, this.options.network];
562
+ });
563
+ });
564
+ };
565
+ BitcoinLegacyProtocolImpl.prototype.getTransactionsForPublicKey = function (publicKey, limit, cursor) {
566
+ return __awaiter(this, void 0, void 0, function () {
567
+ return __generator(this, function (_a) {
568
+ return [2 /*return*/, this.legacy.getTransactionsForPublicKey(publicKey, limit, cursor)];
569
+ });
570
+ });
571
+ };
572
+ BitcoinLegacyProtocolImpl.prototype.getTransactionsForAddress = function (address, limit, cursor) {
573
+ return __awaiter(this, void 0, void 0, function () {
574
+ return __generator(this, function (_a) {
575
+ return [2 /*return*/, this.legacy.getTransactionsForAddress(address, limit, cursor)];
576
+ });
577
+ });
578
+ };
579
+ BitcoinLegacyProtocolImpl.prototype.getTransactionsForAddresses = function (addresses, limit, cursor) {
580
+ return __awaiter(this, void 0, void 0, function () {
581
+ return __generator(this, function (_a) {
582
+ return [2 /*return*/, this.legacy.getTransactionsForAddresses(addresses, limit, cursor)];
583
+ });
584
+ });
585
+ };
586
+ BitcoinLegacyProtocolImpl.prototype.getBalanceOfPublicKey = function (publicKey) {
587
+ return __awaiter(this, void 0, void 0, function () {
588
+ return __generator(this, function (_a) {
589
+ return [2 /*return*/, this.legacy.getBalanceOfPublicKey(publicKey)];
590
+ });
591
+ });
592
+ };
593
+ BitcoinLegacyProtocolImpl.prototype.getBalanceOfAddress = function (address) {
594
+ return __awaiter(this, void 0, void 0, function () {
595
+ return __generator(this, function (_a) {
596
+ return [2 /*return*/, this.legacy.getBalanceOfAddress(address)];
597
+ });
598
+ });
599
+ };
600
+ BitcoinLegacyProtocolImpl.prototype.getBalanceOfAddresses = function (addresses) {
601
+ return __awaiter(this, void 0, void 0, function () {
602
+ return __generator(this, function (_a) {
603
+ return [2 /*return*/, this.legacy.getBalanceOfAddresses(addresses)];
604
+ });
605
+ });
606
+ };
607
+ BitcoinLegacyProtocolImpl.prototype.getTransactionMaxAmountWithPublicKey = function (publicKey, to, configuration) {
608
+ return __awaiter(this, void 0, void 0, function () {
609
+ return __generator(this, function (_a) {
610
+ return [2 /*return*/, this.legacy.getTransactionMaxAmountWithPublicKey(publicKey, to, configuration)];
611
+ });
612
+ });
613
+ };
614
+ BitcoinLegacyProtocolImpl.prototype.getTransactionFeeWithPublicKey = function (_publicKey, _details, _configuration) {
615
+ return __awaiter(this, void 0, void 0, function () {
616
+ return __generator(this, function (_a) {
617
+ return [2 /*return*/, this.legacy.getTransactionFeeWithPublicKey(_publicKey, _details, _configuration)];
618
+ });
619
+ });
620
+ };
621
+ BitcoinLegacyProtocolImpl.prototype.prepareTransactionWithPublicKey = function (publicKey, details, configuration) {
622
+ return __awaiter(this, void 0, void 0, function () {
623
+ return __generator(this, function (_a) {
624
+ switch (publicKey.type) {
625
+ case 'pub':
626
+ return [2 /*return*/, this.prepareTransactionWithNonExtendedPublicKey(publicKey, details, configuration)];
627
+ case 'xpub':
628
+ return [2 /*return*/, this.prepareTransactionWithExtendedPublicKey(publicKey, details, configuration)];
629
+ default:
630
+ (0, coinlib_core_1.assertNever)(publicKey);
631
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Unuspported public key type.');
632
+ }
633
+ return [2 /*return*/];
634
+ });
635
+ });
636
+ };
637
+ BitcoinLegacyProtocolImpl.prototype.prepareTransactionWithNonExtendedPublicKey = function (publicKey, details, configuration) {
638
+ return __awaiter(this, void 0, void 0, function () {
639
+ return __generator(this, function (_a) {
640
+ throw new errors_1.UnsupportedError(coinlib_core_1.Domain.BITCOIN, 'Prepare transaction with non extended public key not supported');
641
+ });
642
+ });
643
+ };
644
+ BitcoinLegacyProtocolImpl.prototype.prepareTransactionWithExtendedPublicKey = function (extendedPublicKey, details, configuration) {
645
+ return __awaiter(this, void 0, void 0, function () {
646
+ 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, _a, _b, tx, indexes, childNode, data, prevTxHex;
647
+ var _this = this;
648
+ return __generator(this, function (_c) {
649
+ switch (_c.label) {
650
+ case 0:
651
+ if ((configuration === null || configuration === void 0 ? void 0 : configuration.masterFingerprint) === undefined) {
652
+ throw new errors_1.ConditionViolationError(coinlib_core_1.Domain.BITCOIN, 'Master fingerprint not set.');
653
+ }
654
+ if (!((configuration === null || configuration === void 0 ? void 0 : configuration.fee) !== undefined)) return [3 /*break*/, 1];
655
+ fee = configuration.fee;
656
+ return [3 /*break*/, 3];
657
+ case 1: return [4 /*yield*/, this.getTransactionFeeWithPublicKey(extendedPublicKey, details)];
658
+ case 2:
659
+ estimatedFee = _c.sent();
660
+ fee = estimatedFee.medium;
661
+ _c.label = 3;
662
+ case 3:
663
+ wrappedFee = new bignumber_1.default((0, module_kit_1.newAmount)(fee).blockchain(this.legacy.units).value);
664
+ transaction = (0, module_kit_1.newUnsignedTransaction)({
665
+ ins: [],
666
+ outs: []
667
+ });
668
+ return [4 /*yield*/, index_1.default.get("".concat(this.options.network.indexerApi, "/api/v2/utxo/").concat(extendedPublicKey.value, "?confirmed=true"), {
669
+ responseType: 'json'
670
+ })];
671
+ case 4:
672
+ utxos = (_c.sent()).data;
673
+ if (utxos.length <= 0) {
674
+ throw new errors_1.BalanceError(coinlib_core_1.Domain.BITCOIN, 'Not enough balance.');
675
+ }
676
+ totalRequiredBalance = details
677
+ .map(function (_a) {
678
+ var amount = _a.amount;
679
+ return new bignumber_1.default((0, module_kit_1.newAmount)(amount).blockchain(_this.legacy.units).value);
680
+ })
681
+ .reduce(function (accumulator, currentValue) { return accumulator.plus(currentValue); })
682
+ .plus(wrappedFee);
683
+ valueAccumulator = new bignumber_1.default(0);
684
+ getPathIndexes = function (path) {
685
+ var result = path
686
+ .split('/')
687
+ .slice(-2)
688
+ .map(function (item) { return parseInt(item); })
689
+ .filter(function (item) { return !isNaN(item); });
690
+ if (result.length !== 2) {
691
+ throw new Error('Unexpected path format');
692
+ }
693
+ return [result[0], result[1]];
694
+ };
695
+ _i = 0, utxos_1 = utxos;
696
+ _c.label = 5;
697
+ case 5:
698
+ if (!(_i < utxos_1.length)) return [3 /*break*/, 9];
699
+ utxo = utxos_1[_i];
700
+ valueAccumulator = valueAccumulator.plus(utxo.value);
701
+ indexes = getPathIndexes(utxo.path);
702
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(extendedPublicKey, indexes[0], indexes[1])];
703
+ case 6:
704
+ derivedPublicKey = _c.sent();
705
+ return [4 /*yield*/, this.getAddressFromPublicKey(derivedPublicKey)];
706
+ case 7:
707
+ derivedAddress = _c.sent();
708
+ if (derivedAddress === utxo.address) {
709
+ transaction.ins.push({
710
+ txId: utxo.txid,
711
+ value: new bignumber_1.default(utxo.value).toString(10),
712
+ vout: utxo.vout,
713
+ address: utxo.address,
714
+ derivationPath: utxo.path
715
+ });
716
+ }
717
+ else {
718
+ throw new Error('Invalid address returned from API');
719
+ }
720
+ if (valueAccumulator.isGreaterThanOrEqualTo(totalRequiredBalance)) {
721
+ return [3 /*break*/, 9];
722
+ }
723
+ _c.label = 8;
724
+ case 8:
725
+ _i++;
726
+ return [3 /*break*/, 5];
727
+ case 9:
728
+ if (valueAccumulator.isLessThan(totalRequiredBalance)) {
729
+ throw new Error('not enough balance 2');
730
+ }
731
+ for (i = 0; i < details.length; i++) {
732
+ value = (0, module_kit_1.newAmount)(details[i].amount).blockchain(this.legacy.units).value;
733
+ transaction.outs.push({
734
+ recipient: details[i].to,
735
+ isChange: false,
736
+ value: value
737
+ });
738
+ valueAccumulator = valueAccumulator.minus(value);
739
+ }
740
+ lastUsedInternalAddress = Math.max.apply(Math, __spreadArray([-1], utxos
741
+ .map(function (utxo) { return getPathIndexes(utxo.path); })
742
+ .filter(function (indexes) { return indexes[0] === 1; })
743
+ .map(function (indexes) { return indexes[1]; }), false));
744
+ changeValue = valueAccumulator.minus(wrappedFee);
745
+ if (!changeValue.isGreaterThan(new bignumber_1.default(DUST_AMOUNT))) return [3 /*break*/, 12];
746
+ changeAddressIndex = lastUsedInternalAddress + 1;
747
+ return [4 /*yield*/, this.deriveFromExtendedPublicKey(extendedPublicKey, 1, changeAddressIndex)];
748
+ case 10:
749
+ derivedPublicKey = _c.sent();
750
+ return [4 /*yield*/, this.getAddressFromPublicKey(derivedPublicKey)];
751
+ case 11:
752
+ derivedAddress = _c.sent();
753
+ transaction.outs.push({
754
+ recipient: derivedAddress,
755
+ isChange: true,
756
+ value: changeValue.toString(10),
757
+ derivationPath: "1/".concat(changeAddressIndex)
758
+ });
759
+ _c.label = 12;
760
+ case 12:
761
+ psbt = new this.bitcoinJS.lib.Psbt();
762
+ psbt.addUnknownKeyValToGlobal({
763
+ key: Buffer.from('amount'),
764
+ value: Buffer.from(details
765
+ .reduce(function (accumulator, next) {
766
+ return accumulator.plus((0, module_kit_1.newAmount)(next.amount).blockchain(_this.legacy.units).value);
767
+ }, new bignumber_1.default(0))
768
+ .toString())
769
+ });
770
+ xpubExtendedPublicKey = (0, key_1.convertExtendedPublicKey)(extendedPublicKey, { format: 'encoded', type: 'xpub' });
771
+ keyPair = this.bip32.fromBase58(xpubExtendedPublicKey.value);
772
+ replaceByFee = (configuration === null || configuration === void 0 ? void 0 : configuration.replaceByFee) ? true : false;
773
+ _a = 0, _b = transaction.ins;
774
+ _c.label = 13;
775
+ case 13:
776
+ if (!(_a < _b.length)) return [3 /*break*/, 16];
777
+ tx = _b[_a];
778
+ indexes = getPathIndexes(tx.derivationPath);
779
+ childNode = keyPair.derivePath(indexes.join('/'));
780
+ return [4 /*yield*/, index_1.default.get("".concat(this.options.network.indexerApi, "/api/v2/tx/").concat(tx.txId), {
781
+ responseType: 'json'
782
+ })];
783
+ case 14:
784
+ data = (_c.sent()).data;
785
+ prevTxHex = data.hex;
786
+ if (!prevTxHex) {
787
+ throw new Error("Missing prev tx hex for ".concat(tx.txId));
788
+ }
789
+ psbt.addInput({
790
+ hash: tx.txId,
791
+ index: tx.vout,
792
+ sequence: replaceByFee ? 0xfffffffd : undefined,
793
+ nonWitnessUtxo: Buffer.from(prevTxHex, 'hex'),
794
+ bip32Derivation: [
795
+ {
796
+ masterFingerprint: Buffer.from(configuration.masterFingerprint.value, 'hex'),
797
+ pubkey: Buffer.from(childNode.publicKey),
798
+ path: tx.derivationPath
799
+ }
800
+ ]
801
+ });
802
+ _c.label = 15;
803
+ case 15:
804
+ _a++;
805
+ return [3 /*break*/, 13];
806
+ case 16:
807
+ transaction.outs.forEach(function (out, index) {
808
+ psbt.addOutput({ address: out.recipient, value: parseInt(out.value, 10) });
809
+ if (out.derivationPath) {
810
+ psbt.addUnknownKeyValToOutput(index, {
811
+ key: Buffer.from('dp'),
812
+ value: Buffer.from(out.derivationPath, 'utf8')
813
+ });
814
+ }
815
+ });
816
+ return [2 /*return*/, (0, module_kit_1.newUnsignedTransaction)({ psbt: psbt.toHex() })];
817
+ }
818
+ });
819
+ });
820
+ };
821
+ BitcoinLegacyProtocolImpl.prototype.broadcastTransaction = function (transaction) {
822
+ return __awaiter(this, void 0, void 0, function () {
823
+ var hexTransaction, data;
824
+ return __generator(this, function (_a) {
825
+ switch (_a.label) {
826
+ case 0:
827
+ hexTransaction = this.bitcoinJS.lib.Psbt.fromHex(transaction.psbt).finalizeAllInputs().extractTransaction().toHex();
828
+ return [4 /*yield*/, index_1.default.post("".concat(this.options.network.indexerApi, "/api/v2/sendtx/"), hexTransaction)];
829
+ case 1:
830
+ data = (_a.sent()).data;
831
+ return [2 /*return*/, data.result];
832
+ }
833
+ });
834
+ });
835
+ };
836
+ BitcoinLegacyProtocolImpl.prototype.convertCryptoDerivative = function (derivative) {
837
+ var hexNode = (0, crypto_1.encodeDerivative)('hex', __assign(__assign({}, derivative), { secretKey: "00".concat(derivative.secretKey) }));
838
+ var extendedSecretKey = {
839
+ type: 'xpriv',
840
+ format: 'hex',
841
+ value: hexNode.secretKey
842
+ };
843
+ return (0, key_1.convertExtendedSecretKey)(extendedSecretKey, { format: 'encoded', type: 'xprv' });
844
+ };
845
+ BitcoinLegacyProtocolImpl.prototype.derivativeToBip32Node = function (derivative) {
846
+ var extendedSecretKey = this.convertCryptoDerivative(derivative);
847
+ return this.bip32.fromBase58(extendedSecretKey.value, this.bitcoinJS.config.network);
848
+ };
849
+ return BitcoinLegacyProtocolImpl;
850
+ }());
851
+ exports.BitcoinLegacyProtocolImpl = BitcoinLegacyProtocolImpl;
852
+ // Factory
853
+ function createBitcoinLegacyProtocol(options) {
854
+ if (options === void 0) { options = {}; }
855
+ return new BitcoinLegacyProtocolImpl(options);
856
+ }
857
+ exports.createBitcoinLegacyProtocol = createBitcoinLegacyProtocol;
858
+ //# sourceMappingURL=BitcoinLegacyProtocol.js.map