@airgap/bitcoin 0.13.45-beta.3 → 0.13.45-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/v0/index.js +10 -10
- package/v0/index.js.map +1 -1
- package/v0/protocol/BitcoinAddress.js +9 -8
- package/v0/protocol/BitcoinAddress.js.map +1 -1
- package/v0/protocol/BitcoinCryptoClient.js +85 -16
- package/v0/protocol/BitcoinCryptoClient.js.map +1 -1
- package/v0/protocol/BitcoinProtocol.js +987 -590
- package/v0/protocol/BitcoinProtocol.js.map +1 -1
- package/v0/protocol/BitcoinProtocolOptions.js +111 -45
- package/v0/protocol/BitcoinProtocolOptions.js.map +1 -1
- package/v0/protocol/BitcoinSegwitAddress.js +29 -12
- package/v0/protocol/BitcoinSegwitAddress.js.map +1 -1
- package/v0/protocol/BitcoinSegwitProtocol.js +483 -348
- package/v0/protocol/BitcoinSegwitProtocol.js.map +1 -1
- package/v0/protocol/BitcoinTestnetProtocol.js +36 -28
- package/v0/protocol/BitcoinTestnetProtocol.js.map +1 -1
- package/v0/serializer/validators/transaction-validator.js +30 -22
- package/v0/serializer/validators/transaction-validator.js.map +1 -1
- package/v0/serializer/validators/validators.js +23 -23
- package/v0/serializer/validators/validators.js.map +1 -1
- package/v1/block-explorer/BlockCypherBlockExplorer.js +61 -12
- package/v1/block-explorer/BlockCypherBlockExplorer.js.map +1 -1
- package/v1/data/BitcoinAddress.js +10 -9
- package/v1/data/BitcoinAddress.js.map +1 -1
- package/v1/data/BitcoinLegacyAddress.js +12 -11
- package/v1/data/BitcoinLegacyAddress.js.map +1 -1
- package/v1/data/BitcoinSegwitAddress.js +12 -11
- package/v1/data/BitcoinSegwitAddress.js.map +1 -1
- package/v1/data/BitcoinTaprootAddress.js +22 -31
- package/v1/data/BitcoinTaprootAddress.js.map +1 -1
- package/v1/index.js +11 -11
- package/v1/index.js.map +1 -1
- package/v1/module/BitcoinModule.d.ts +1 -1
- package/v1/module/BitcoinModule.js +102 -44
- package/v1/module/BitcoinModule.js.map +1 -1
- package/v1/module.js +3 -2
- package/v1/module.js.map +1 -1
- package/v1/protocol/BitcoinCryptoClient.js +90 -22
- package/v1/protocol/BitcoinCryptoClient.js.map +1 -1
- package/v1/protocol/BitcoinLegacyProtocol.js +796 -520
- package/v1/protocol/BitcoinLegacyProtocol.js.map +1 -1
- package/v1/protocol/BitcoinProtocol.js +1169 -735
- package/v1/protocol/BitcoinProtocol.js.map +1 -1
- package/v1/protocol/BitcoinSegwitProtocol.js +796 -542
- package/v1/protocol/BitcoinSegwitProtocol.js.map +1 -1
- package/v1/protocol/BitcoinTaprootProtocol.js +1000 -688
- package/v1/protocol/BitcoinTaprootProtocol.js.map +1 -1
- package/v1/protocol/BitcoinTestnetProtocol.js +33 -14
- package/v1/protocol/BitcoinTestnetProtocol.js.map +1 -1
- package/v1/serializer/v3/schemas/converter/transaction-converter.js +52 -29
- package/v1/serializer/v3/schemas/converter/transaction-converter.js.map +1 -1
- package/v1/serializer/v3/serializer-companion.js +165 -98
- package/v1/serializer/v3/serializer-companion.js.map +1 -1
- package/v1/serializer/v3/validators/transaction-validator.js +16 -13
- package/v1/serializer/v3/validators/transaction-validator.js.map +1 -1
- package/v1/serializer/v3/validators/validators.js +213 -122
- package/v1/serializer/v3/validators/validators.js.map +1 -1
- package/v1/types/crypto.d.ts +1 -1
- package/v1/types/key.d.ts +6 -6
- package/v1/types/protocol.d.ts +2 -2
- package/v1/types/transaction.d.ts +3 -3
- package/v1/utils/common.js +6 -4
- package/v1/utils/common.js.map +1 -1
- package/v1/utils/key.d.ts +6 -5
- package/v1/utils/key.js +39 -38
- package/v1/utils/key.js.map +1 -1
- package/v1/utils/network.js +4 -3
- package/v1/utils/network.js.map +1 -1
- package/v1/utils/protocol.js +19 -25
- package/v1/utils/protocol.js.map +1 -1
- package/v1/utils/signature.js +5 -4
- package/v1/utils/signature.js.map +1 -1
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
|
3
|
+
var extendStatics = function (d, b) {
|
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
+
return extendStatics(d, b);
|
|
8
|
+
};
|
|
9
|
+
return function (d, b) {
|
|
10
|
+
if (typeof b !== "function" && b !== null)
|
|
11
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
+
extendStatics(d, b);
|
|
13
|
+
function __() { this.constructor = d; }
|
|
14
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
+
};
|
|
16
|
+
})();
|
|
2
17
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
18
|
if (k2 === undefined) k2 = k;
|
|
4
19
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -15,40 +30,75 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
30
|
}) : function(o, v) {
|
|
16
31
|
o["default"] = v;
|
|
17
32
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
27
|
-
return function (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
41
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
42
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
43
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
44
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
45
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
46
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
50
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
51
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
52
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
53
|
+
function step(op) {
|
|
54
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
55
|
+
while (_) try {
|
|
56
|
+
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;
|
|
57
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
58
|
+
switch (op[0]) {
|
|
59
|
+
case 0: case 1: t = op; break;
|
|
60
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
61
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
62
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
63
|
+
default:
|
|
64
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
65
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
66
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
67
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
68
|
+
if (t[2]) _.ops.pop();
|
|
69
|
+
_.trys.pop(); continue;
|
|
70
|
+
}
|
|
71
|
+
op = body.call(thisArg, _);
|
|
72
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
73
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
77
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
78
|
+
if (ar || !(i in from)) {
|
|
79
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
80
|
+
ar[i] = from[i];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
84
|
+
};
|
|
35
85
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
86
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
87
|
};
|
|
38
88
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
89
|
exports.BitcoinSegwitProtocol = void 0;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
90
|
+
var index_1 = __importDefault(require("@airgap/coinlib-core/dependencies/src/axios-0.19.0/index"));
|
|
91
|
+
var bignumber_1 = __importDefault(require("@airgap/coinlib-core/dependencies/src/bignumber.js-9.0.0/bignumber"));
|
|
92
|
+
var index_2 = require("@airgap/coinlib-core/dependencies/src/bip39-2.5.0/index");
|
|
93
|
+
var bs58check = __importStar(require("@airgap/coinlib-core/dependencies/src/bs58check-2.1.2"));
|
|
94
|
+
var ProtocolSymbols_1 = require("@airgap/coinlib-core/utils/ProtocolSymbols");
|
|
95
|
+
var bitcoinJS = __importStar(require("bitcoinjs-lib"));
|
|
96
|
+
var BitcoinProtocol_1 = require("./BitcoinProtocol");
|
|
97
|
+
var BitcoinProtocolOptions_1 = require("./BitcoinProtocolOptions");
|
|
98
|
+
var BitcoinSegwitAddress_1 = require("./BitcoinSegwitAddress");
|
|
99
|
+
var bip32_1 = require("bip32");
|
|
100
|
+
var secp256k1_1 = __importDefault(require("@bitcoinerlab/secp256k1"));
|
|
101
|
+
var DUST_AMOUNT = 50;
|
|
52
102
|
// This function handles arrays and objects
|
|
53
103
|
function eachRecursive(obj) {
|
|
54
104
|
for (var k in obj) {
|
|
@@ -62,352 +112,437 @@ function eachRecursive(obj) {
|
|
|
62
112
|
return obj;
|
|
63
113
|
}
|
|
64
114
|
// https://github.com/satoshilabs/slips/blob/master/slip-0132.md
|
|
65
|
-
|
|
66
|
-
|
|
115
|
+
var ExtendedPublicKey = /** @class */ (function () {
|
|
116
|
+
function ExtendedPublicKey(extendedPublicKey) {
|
|
67
117
|
this.rawKey = bs58check.decode(extendedPublicKey).slice(4);
|
|
68
118
|
}
|
|
69
|
-
toXpub() {
|
|
119
|
+
ExtendedPublicKey.prototype.toXpub = function () {
|
|
70
120
|
return this.addPrefix('0488b21e');
|
|
71
|
-
}
|
|
72
|
-
toYPub() {
|
|
121
|
+
};
|
|
122
|
+
ExtendedPublicKey.prototype.toYPub = function () {
|
|
73
123
|
return this.addPrefix('049d7cb2');
|
|
74
|
-
}
|
|
75
|
-
toZPub() {
|
|
124
|
+
};
|
|
125
|
+
ExtendedPublicKey.prototype.toZPub = function () {
|
|
76
126
|
return this.addPrefix('04b24746');
|
|
77
|
-
}
|
|
78
|
-
addPrefix(prefix) {
|
|
79
|
-
|
|
127
|
+
};
|
|
128
|
+
ExtendedPublicKey.prototype.addPrefix = function (prefix) {
|
|
129
|
+
var data = Buffer.concat([Buffer.from(prefix, 'hex'), this.rawKey]);
|
|
80
130
|
return bs58check.encode(data);
|
|
131
|
+
};
|
|
132
|
+
return ExtendedPublicKey;
|
|
133
|
+
}());
|
|
134
|
+
var BitcoinSegwitProtocol = /** @class */ (function (_super) {
|
|
135
|
+
__extends(BitcoinSegwitProtocol, _super);
|
|
136
|
+
function BitcoinSegwitProtocol(options) {
|
|
137
|
+
if (options === void 0) { options = new BitcoinProtocolOptions_1.BitcoinProtocolOptions(); }
|
|
138
|
+
var _this = _super.call(this, options) || this;
|
|
139
|
+
_this.name = 'Bitcoin (Segwit)';
|
|
140
|
+
_this.identifier = ProtocolSymbols_1.MainProtocolSymbols.BTC_SEGWIT;
|
|
141
|
+
_this.standardDerivationPath = "m/84'/0'/0'";
|
|
142
|
+
_this.addressPlaceholder = 'bc1...';
|
|
143
|
+
_this.bip32 = (0, bip32_1.BIP32Factory)(secp256k1_1.default);
|
|
144
|
+
return _this;
|
|
81
145
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
BitcoinSegwitProtocol.prototype.getPublicKeyFromHexSecret = function (secret, derivationPath) {
|
|
147
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
148
|
+
var bitcoinNode, neutered, zpub;
|
|
149
|
+
return __generator(this, function (_a) {
|
|
150
|
+
bitcoinNode = this.bip32.fromSeed(Buffer.from(secret, 'hex'), this.options.network.extras.network);
|
|
151
|
+
neutered = bitcoinNode.derivePath(derivationPath).neutered();
|
|
152
|
+
zpub = new ExtendedPublicKey(neutered.toBase58()).toZPub();
|
|
153
|
+
return [2 /*return*/, zpub];
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
BitcoinSegwitProtocol.prototype.getPrivateKeyFromHexSecret = function (secret, derivationPath) {
|
|
158
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
159
|
+
var bitcoinNode, privateKey;
|
|
160
|
+
return __generator(this, function (_a) {
|
|
161
|
+
if (!derivationPath) {
|
|
162
|
+
return [2 /*return*/, this.bip32.fromSeed(Buffer.from(secret, 'hex'), this.options.network.extras.network)];
|
|
163
|
+
}
|
|
164
|
+
bitcoinNode = this.bip32.fromSeed(Buffer.from(secret, 'hex'), this.options.network.extras.network);
|
|
165
|
+
privateKey = bitcoinNode.derivePath(derivationPath).privateKey;
|
|
166
|
+
if (!privateKey) {
|
|
167
|
+
throw new Error('No privatekey!');
|
|
168
|
+
}
|
|
169
|
+
return [2 /*return*/, Buffer.from(privateKey).toString('hex')];
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
BitcoinSegwitProtocol.prototype.getExtendedPrivateKeyFromMnemonic = function (mnemonic, derivationPath, password) {
|
|
174
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
175
|
+
var secret;
|
|
176
|
+
return __generator(this, function (_a) {
|
|
177
|
+
secret = (0, index_2.mnemonicToSeed)(mnemonic, password);
|
|
178
|
+
return [2 /*return*/, this.getExtendedPrivateKeyFromHexSecret(secret, derivationPath)];
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
BitcoinSegwitProtocol.prototype.getExtendedPrivateKeyFromHexSecret = function (secret, derivationPath) {
|
|
183
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
184
|
+
var bitcoinNode;
|
|
185
|
+
return __generator(this, function (_a) {
|
|
186
|
+
bitcoinNode = this.bip32.fromSeed(Buffer.from(secret, 'hex'), this.options.network.extras.network);
|
|
187
|
+
return [2 /*return*/, bitcoinNode.derivePath(derivationPath).toBase58()];
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
BitcoinSegwitProtocol.prototype.getAddressFromPublicKey = function (publicKey, cursor) {
|
|
192
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
193
|
+
var address;
|
|
194
|
+
return __generator(this, function (_a) {
|
|
195
|
+
address = BitcoinSegwitAddress_1.BitcoinSegwitAddress.fromAddress(this.bip32.fromBase58(publicKey, this.options.network.extras.network).toBase58());
|
|
196
|
+
return [2 /*return*/, {
|
|
197
|
+
address: address.asString(),
|
|
198
|
+
cursor: { hasNext: false }
|
|
199
|
+
}];
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
BitcoinSegwitProtocol.prototype.getAddressesFromPublicKey = function (publicKey, cursor) {
|
|
204
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
205
|
+
return __generator(this, function (_a) {
|
|
206
|
+
switch (_a.label) {
|
|
207
|
+
case 0: return [4 /*yield*/, this.getAddressFromPublicKey(publicKey, cursor)];
|
|
208
|
+
case 1: return [2 /*return*/, [_a.sent()]];
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
BitcoinSegwitProtocol.prototype.getAddressFromExtendedPublicKey = function (extendedPublicKey, visibilityDerivationIndex, addressDerivationIndex) {
|
|
214
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
215
|
+
var xpub, keyPair, obj, addressRaw, address;
|
|
216
|
+
return __generator(this, function (_a) {
|
|
217
|
+
xpub = new ExtendedPublicKey(extendedPublicKey).toXpub();
|
|
218
|
+
keyPair = this.bip32
|
|
219
|
+
.fromBase58(xpub, this.options.network.extras.network)
|
|
220
|
+
.derive(visibilityDerivationIndex)
|
|
221
|
+
.derive(addressDerivationIndex);
|
|
222
|
+
obj = bitcoinJS.payments.p2wpkh({ pubkey: Buffer.from(keyPair.publicKey) });
|
|
223
|
+
addressRaw = obj.address;
|
|
224
|
+
if (!addressRaw) {
|
|
225
|
+
throw new Error('could not generate address');
|
|
226
|
+
}
|
|
227
|
+
address = BitcoinSegwitAddress_1.BitcoinSegwitAddress.fromAddress(addressRaw);
|
|
228
|
+
return [2 /*return*/, {
|
|
229
|
+
address: address.asString(),
|
|
230
|
+
cursor: { hasNext: false }
|
|
231
|
+
}];
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
BitcoinSegwitProtocol.prototype.getAddressesFromExtendedPublicKey = function (extendedPublicKey, visibilityDerivationIndex, addressCount, offset) {
|
|
147
236
|
// broadcaster knows this (both broadcaster and signer)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return Promise.all(generatorArray.map((x)
|
|
151
|
-
|
|
152
|
-
|
|
237
|
+
var node = this.bip32.fromBase58(new ExtendedPublicKey(extendedPublicKey).toXpub(), this.options.network.extras.network);
|
|
238
|
+
var generatorArray = Array.from(new Array(addressCount), function (x, i) { return i + offset; });
|
|
239
|
+
return Promise.all(generatorArray.map(function (x) {
|
|
240
|
+
var keyPair = node.derive(visibilityDerivationIndex).derive(x);
|
|
241
|
+
var addressRaw = bitcoinJS.payments.p2wpkh({ pubkey: Buffer.from(keyPair.publicKey) }).address;
|
|
153
242
|
if (!addressRaw) {
|
|
154
243
|
throw new Error('could not generate address');
|
|
155
244
|
}
|
|
156
|
-
|
|
245
|
+
var address = BitcoinSegwitAddress_1.BitcoinSegwitAddress.fromAddress(addressRaw);
|
|
157
246
|
return {
|
|
158
247
|
address: address.asString(),
|
|
159
248
|
cursor: { hasNext: false }
|
|
160
249
|
};
|
|
161
250
|
}));
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const warnings = [];
|
|
175
|
-
const clonedPSBT = decodedPSBT.clone();
|
|
176
|
-
eachRecursive(clonedPSBT); // All buffers to hex string
|
|
177
|
-
// Amount is tricky for BTC. Full amount of inputs is always transferred, but usually a (big) part of the amount is sent back to the sender via change address. So it's not easy to determine what the amount is that the user intended to send.
|
|
178
|
-
const amount = (() => {
|
|
179
|
-
// If tx has only one output, this is the amount
|
|
180
|
-
if (decodedPSBT.txOutputs.length === 1) {
|
|
181
|
-
return new bignumber_1.default(decodedPSBT.txOutputs[0].value);
|
|
182
|
-
}
|
|
183
|
-
// If we can match one output to an exact amount that we add to the PSBT, this is our amount.
|
|
184
|
-
{
|
|
185
|
-
const unknownKeyVals = decodedPSBT.data.globalMap.unknownKeyVals;
|
|
186
|
-
if (unknownKeyVals) {
|
|
187
|
-
const amountArray = unknownKeyVals.filter((kv) => kv.key.equals(Buffer.from('amount')));
|
|
188
|
-
if (amountArray.length > 0) {
|
|
189
|
-
return new bignumber_1.default(amountArray[0].value.toString()); // Buffer to number
|
|
190
|
-
}
|
|
251
|
+
};
|
|
252
|
+
BitcoinSegwitProtocol.prototype.getTransactionDetails = function (unsignedTx) {
|
|
253
|
+
var _a, _b;
|
|
254
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
255
|
+
var transaction, decodedPSBT, feeCalculator, _i, _c, txIn, _d, _e, txOut, warnings, clonedPSBT, amount;
|
|
256
|
+
return __generator(this, function (_f) {
|
|
257
|
+
transaction = unsignedTx.transaction;
|
|
258
|
+
decodedPSBT = bitcoinJS.Psbt.fromHex(transaction.psbt);
|
|
259
|
+
feeCalculator = new bignumber_1.default(0);
|
|
260
|
+
for (_i = 0, _c = decodedPSBT.data.inputs; _i < _c.length; _i++) {
|
|
261
|
+
txIn = _c[_i];
|
|
262
|
+
feeCalculator = feeCalculator.plus(new bignumber_1.default((_b = (_a = txIn.witnessUtxo) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 0));
|
|
191
263
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
let useAccumulated = false;
|
|
196
|
-
decodedPSBT.data.outputs.forEach((outputKeyValues, index) => {
|
|
197
|
-
if (outputKeyValues.unknownKeyVals) {
|
|
198
|
-
const derivationPaths = outputKeyValues.unknownKeyVals
|
|
199
|
-
.filter((kv) => kv.key.equals(Buffer.from('dp')))
|
|
200
|
-
.map((kv) => kv.value.toString());
|
|
201
|
-
if (derivationPaths.length > 0) {
|
|
202
|
-
// If one of the outputs has the derivation in the custom key/value map, we can use this to determine the amount.
|
|
203
|
-
useAccumulated = true;
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
264
|
+
for (_d = 0, _e = decodedPSBT.txOutputs; _d < _e.length; _d++) {
|
|
265
|
+
txOut = _e[_d];
|
|
266
|
+
feeCalculator = feeCalculator.minus(new bignumber_1.default(txOut.value));
|
|
206
267
|
}
|
|
207
|
-
|
|
208
|
-
|
|
268
|
+
warnings = [];
|
|
269
|
+
clonedPSBT = decodedPSBT.clone();
|
|
270
|
+
eachRecursive(clonedPSBT); // All buffers to hex string
|
|
271
|
+
amount = (function () {
|
|
272
|
+
// If tx has only one output, this is the amount
|
|
273
|
+
if (decodedPSBT.txOutputs.length === 1) {
|
|
274
|
+
return new bignumber_1.default(decodedPSBT.txOutputs[0].value);
|
|
275
|
+
}
|
|
276
|
+
// If we can match one output to an exact amount that we add to the PSBT, this is our amount.
|
|
277
|
+
{
|
|
278
|
+
var unknownKeyVals = decodedPSBT.data.globalMap.unknownKeyVals;
|
|
279
|
+
if (unknownKeyVals) {
|
|
280
|
+
var amountArray = unknownKeyVals.filter(function (kv) { return kv.key.equals(Buffer.from('amount')); });
|
|
281
|
+
if (amountArray.length > 0) {
|
|
282
|
+
return new bignumber_1.default(amountArray[0].value.toString()); // Buffer to number
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// If tx has an output and we added a derivation path in the PSBT (in the wallet, prepareTransaction), we know that it is a change address and we ignore it.
|
|
287
|
+
var accumulated = new bignumber_1.default(0);
|
|
288
|
+
var useAccumulated = false;
|
|
289
|
+
decodedPSBT.data.outputs.forEach(function (outputKeyValues, index) {
|
|
290
|
+
if (outputKeyValues.unknownKeyVals) {
|
|
291
|
+
var derivationPaths = outputKeyValues.unknownKeyVals
|
|
292
|
+
.filter(function (kv) { return kv.key.equals(Buffer.from('dp')); })
|
|
293
|
+
.map(function (kv) { return kv.value.toString(); });
|
|
294
|
+
if (derivationPaths.length > 0) {
|
|
295
|
+
// If one of the outputs has the derivation in the custom key/value map, we can use this to determine the amount.
|
|
296
|
+
useAccumulated = true;
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
var output = decodedPSBT.txOutputs[index];
|
|
301
|
+
accumulated = accumulated.plus(output.value);
|
|
302
|
+
});
|
|
303
|
+
if (useAccumulated) {
|
|
304
|
+
return accumulated;
|
|
305
|
+
}
|
|
306
|
+
// If we cannot match anything above, we need to assume that the whole amount is being sent and the user has to check the outputs.
|
|
307
|
+
return decodedPSBT.txOutputs
|
|
308
|
+
.map(function (obj) { return new bignumber_1.default(obj.value); })
|
|
309
|
+
.reduce(function (accumulator, currentValue) { return accumulator.plus(currentValue); });
|
|
310
|
+
})();
|
|
311
|
+
return [2 /*return*/, [
|
|
312
|
+
{
|
|
313
|
+
from: decodedPSBT.data.inputs.map(function (obj) {
|
|
314
|
+
var _a, _b;
|
|
315
|
+
return (_b = (_a = obj.bip32Derivation) === null || _a === void 0 ? void 0 : _a.map(function (el) {
|
|
316
|
+
return bitcoinJS.payments.p2wpkh({
|
|
317
|
+
pubkey: el.pubkey,
|
|
318
|
+
network: bitcoinJS.networks.bitcoin
|
|
319
|
+
}).address;
|
|
320
|
+
}).join(' ')) !== null && _b !== void 0 ? _b : 'INVALID';
|
|
321
|
+
}),
|
|
322
|
+
to: decodedPSBT.txOutputs.map(function (obj) {
|
|
323
|
+
return obj.address || "Script: ".concat(obj.script.toString('hex')) || 'unknown';
|
|
324
|
+
}),
|
|
325
|
+
amount: amount.toString(10),
|
|
326
|
+
fee: feeCalculator.toString(10),
|
|
327
|
+
protocolIdentifier: this.identifier,
|
|
328
|
+
network: this.options.network,
|
|
329
|
+
isInbound: false,
|
|
330
|
+
transactionDetails: {
|
|
331
|
+
// This is some unstructured data about the PSBT. This is shown in the UI as a JSON for advanced users.
|
|
332
|
+
inputTx: eachRecursive(clonedPSBT.txInputs),
|
|
333
|
+
outputTx: eachRecursive(clonedPSBT.txOutputs),
|
|
334
|
+
inputData: clonedPSBT.data.inputs,
|
|
335
|
+
outputData: clonedPSBT.data.outputs,
|
|
336
|
+
PSBTVersion: clonedPSBT.version,
|
|
337
|
+
PSBTLocktime: clonedPSBT.locktime,
|
|
338
|
+
PSBTGlobalMap: clonedPSBT.data.globalMap,
|
|
339
|
+
rawPSBT: unsignedTx.transaction
|
|
340
|
+
},
|
|
341
|
+
warnings: warnings
|
|
342
|
+
}
|
|
343
|
+
]];
|
|
209
344
|
});
|
|
210
|
-
if (useAccumulated) {
|
|
211
|
-
return accumulated;
|
|
212
|
-
}
|
|
213
|
-
// If we cannot match anything above, we need to assume that the whole amount is being sent and the user has to check the outputs.
|
|
214
|
-
return decodedPSBT.txOutputs
|
|
215
|
-
.map((obj) => new bignumber_1.default(obj.value))
|
|
216
|
-
.reduce((accumulator, currentValue) => accumulator.plus(currentValue));
|
|
217
|
-
})();
|
|
218
|
-
return [
|
|
219
|
-
{
|
|
220
|
-
from: decodedPSBT.data.inputs.map((obj) => obj.bip32Derivation
|
|
221
|
-
?.map((el) => bitcoinJS.payments.p2wpkh({
|
|
222
|
-
pubkey: el.pubkey,
|
|
223
|
-
network: bitcoinJS.networks.bitcoin
|
|
224
|
-
}).address)
|
|
225
|
-
.join(' ') ?? 'INVALID'),
|
|
226
|
-
to: decodedPSBT.txOutputs.map((obj) => {
|
|
227
|
-
return obj.address || `Script: ${obj.script.toString('hex')}` || 'unknown';
|
|
228
|
-
}),
|
|
229
|
-
amount: amount.toString(10),
|
|
230
|
-
fee: feeCalculator.toString(10),
|
|
231
|
-
protocolIdentifier: this.identifier,
|
|
232
|
-
network: this.options.network,
|
|
233
|
-
isInbound: false,
|
|
234
|
-
transactionDetails: {
|
|
235
|
-
// This is some unstructured data about the PSBT. This is shown in the UI as a JSON for advanced users.
|
|
236
|
-
inputTx: eachRecursive(clonedPSBT.txInputs),
|
|
237
|
-
outputTx: eachRecursive(clonedPSBT.txOutputs),
|
|
238
|
-
inputData: clonedPSBT.data.inputs,
|
|
239
|
-
outputData: clonedPSBT.data.outputs,
|
|
240
|
-
PSBTVersion: clonedPSBT.version,
|
|
241
|
-
PSBTLocktime: clonedPSBT.locktime,
|
|
242
|
-
PSBTGlobalMap: clonedPSBT.data.globalMap,
|
|
243
|
-
rawPSBT: unsignedTx.transaction
|
|
244
|
-
},
|
|
245
|
-
warnings
|
|
246
|
-
}
|
|
247
|
-
];
|
|
248
|
-
}
|
|
249
|
-
async getTransactionDetailsFromSigned(signedTx) {
|
|
250
|
-
return this.getTransactionDetails({ publicKey: '', transaction: { psbt: signedTx.transaction } });
|
|
251
|
-
}
|
|
252
|
-
async prepareTransactionFromExtendedPublicKey(extendedPublicKey, offset, recipients, values, fee, extras) {
|
|
253
|
-
if (!extras.masterFingerprint) {
|
|
254
|
-
throw new Error('MasterFingerprint not set!');
|
|
255
|
-
}
|
|
256
|
-
const wrappedValues = values.map((value) => new bignumber_1.default(value));
|
|
257
|
-
const wrappedFee = new bignumber_1.default(fee);
|
|
258
|
-
const transaction = {
|
|
259
|
-
ins: [],
|
|
260
|
-
outs: []
|
|
261
|
-
};
|
|
262
|
-
if (recipients.length !== wrappedValues.length) {
|
|
263
|
-
throw new Error('recipients do not match values');
|
|
264
|
-
}
|
|
265
|
-
const { data: utxos } = await index_1.default.get(`${this.options.network.extras.indexerApi}/api/v2/utxo/${extendedPublicKey}?confirmed=true`, {
|
|
266
|
-
responseType: 'json'
|
|
267
345
|
});
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
.plus(wrappedFee);
|
|
274
|
-
let valueAccumulator = new bignumber_1.default(0);
|
|
275
|
-
const getPathIndexes = (path) => {
|
|
276
|
-
const result = path
|
|
277
|
-
.split('/')
|
|
278
|
-
.slice(-2)
|
|
279
|
-
.map((item) => parseInt(item))
|
|
280
|
-
.filter((item) => !isNaN(item));
|
|
281
|
-
if (result.length !== 2) {
|
|
282
|
-
throw new Error('Unexpected path format');
|
|
283
|
-
}
|
|
284
|
-
return [result[0], result[1]];
|
|
285
|
-
};
|
|
286
|
-
for (const utxo of utxos) {
|
|
287
|
-
valueAccumulator = valueAccumulator.plus(utxo.value);
|
|
288
|
-
const indexes = getPathIndexes(utxo.path);
|
|
289
|
-
const derivedAddress = (await this.getAddressFromExtendedPublicKey(extendedPublicKey, indexes[0], indexes[1])).address;
|
|
290
|
-
if (derivedAddress === utxo.address) {
|
|
291
|
-
transaction.ins.push({
|
|
292
|
-
txId: utxo.txid,
|
|
293
|
-
value: new bignumber_1.default(utxo.value).toString(10),
|
|
294
|
-
vout: utxo.vout,
|
|
295
|
-
address: utxo.address,
|
|
296
|
-
derivationPath: utxo.path
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
throw new Error('Invalid address returned from API');
|
|
301
|
-
}
|
|
302
|
-
if (valueAccumulator.isGreaterThanOrEqualTo(totalRequiredBalance)) {
|
|
303
|
-
break;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
if (valueAccumulator.isLessThan(totalRequiredBalance)) {
|
|
307
|
-
throw new Error('not enough balance 2');
|
|
308
|
-
}
|
|
309
|
-
for (let i = 0; i < recipients.length; i++) {
|
|
310
|
-
transaction.outs.push({
|
|
311
|
-
recipient: recipients[i],
|
|
312
|
-
isChange: false,
|
|
313
|
-
value: wrappedValues[i].toString(10)
|
|
314
|
-
});
|
|
315
|
-
valueAccumulator = valueAccumulator.minus(wrappedValues[i]);
|
|
316
|
-
}
|
|
317
|
-
const lastUsedInternalAddress = Math.max(-1, ...utxos
|
|
318
|
-
.map((utxo) => getPathIndexes(utxo.path))
|
|
319
|
-
.filter((indexes) => indexes[0] === 1)
|
|
320
|
-
.map((indexes) => indexes[1]));
|
|
321
|
-
// If the change is considered dust, the transaction will fail.
|
|
322
|
-
// Dust is a variable value around 300-600 satoshis, depending on the configuration.
|
|
323
|
-
// We set a low fee here to not block any transactions, but it might still fail due to "dust".
|
|
324
|
-
const changeValue = valueAccumulator.minus(wrappedFee);
|
|
325
|
-
if (changeValue.isGreaterThan(new bignumber_1.default(DUST_AMOUNT))) {
|
|
326
|
-
const changeAddressIndex = lastUsedInternalAddress + 1;
|
|
327
|
-
const derivedAddress = (await this.getAddressFromExtendedPublicKey(extendedPublicKey, 1, changeAddressIndex)).address;
|
|
328
|
-
transaction.outs.push({
|
|
329
|
-
recipient: derivedAddress,
|
|
330
|
-
isChange: true,
|
|
331
|
-
value: changeValue.toString(10),
|
|
332
|
-
derivationPath: `1/${changeAddressIndex}`
|
|
346
|
+
};
|
|
347
|
+
BitcoinSegwitProtocol.prototype.getTransactionDetailsFromSigned = function (signedTx) {
|
|
348
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
349
|
+
return __generator(this, function (_a) {
|
|
350
|
+
return [2 /*return*/, this.getTransactionDetails({ publicKey: '', transaction: { psbt: signedTx.transaction } })];
|
|
333
351
|
});
|
|
334
|
-
}
|
|
335
|
-
const psbt = new bitcoinJS.Psbt();
|
|
336
|
-
// 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.
|
|
337
|
-
psbt.addUnknownKeyValToGlobal({
|
|
338
|
-
key: Buffer.from('amount'),
|
|
339
|
-
value: Buffer.from(wrappedValues.reduce((accumulator, currentValue) => accumulator.plus(currentValue)).toString())
|
|
340
352
|
});
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
353
|
+
};
|
|
354
|
+
BitcoinSegwitProtocol.prototype.prepareTransactionFromExtendedPublicKey = function (extendedPublicKey, offset, recipients, values, fee, extras) {
|
|
355
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
356
|
+
var wrappedValues, wrappedFee, transaction, utxos, totalRequiredBalance, valueAccumulator, getPathIndexes, _i, utxos_1, utxo, indexes, derivedAddress, i, lastUsedInternalAddress, changeValue, changeAddressIndex, derivedAddress, psbt, keyPair, replaceByFee, tx;
|
|
357
|
+
var _this = this;
|
|
358
|
+
return __generator(this, function (_a) {
|
|
359
|
+
switch (_a.label) {
|
|
360
|
+
case 0:
|
|
361
|
+
if (!extras.masterFingerprint) {
|
|
362
|
+
throw new Error('MasterFingerprint not set!');
|
|
363
|
+
}
|
|
364
|
+
wrappedValues = values.map(function (value) { return new bignumber_1.default(value); });
|
|
365
|
+
wrappedFee = new bignumber_1.default(fee);
|
|
366
|
+
transaction = {
|
|
367
|
+
ins: [],
|
|
368
|
+
outs: []
|
|
369
|
+
};
|
|
370
|
+
if (recipients.length !== wrappedValues.length) {
|
|
371
|
+
throw new Error('recipients do not match values');
|
|
372
|
+
}
|
|
373
|
+
return [4 /*yield*/, index_1.default.get("".concat(this.options.network.extras.indexerApi, "/api/v2/utxo/").concat(extendedPublicKey, "?confirmed=true"), {
|
|
374
|
+
responseType: 'json'
|
|
375
|
+
})];
|
|
376
|
+
case 1:
|
|
377
|
+
utxos = (_a.sent()).data;
|
|
378
|
+
if (utxos.length <= 0) {
|
|
379
|
+
throw new Error('not enough balance'); // no transactions found on those addresses, probably won't find anything in the next ones
|
|
380
|
+
}
|
|
381
|
+
totalRequiredBalance = wrappedValues
|
|
382
|
+
.reduce(function (accumulator, currentValue) { return accumulator.plus(currentValue); })
|
|
383
|
+
.plus(wrappedFee);
|
|
384
|
+
valueAccumulator = new bignumber_1.default(0);
|
|
385
|
+
getPathIndexes = function (path) {
|
|
386
|
+
var result = path
|
|
387
|
+
.split('/')
|
|
388
|
+
.slice(-2)
|
|
389
|
+
.map(function (item) { return parseInt(item); })
|
|
390
|
+
.filter(function (item) { return !isNaN(item); });
|
|
391
|
+
if (result.length !== 2) {
|
|
392
|
+
throw new Error('Unexpected path format');
|
|
393
|
+
}
|
|
394
|
+
return [result[0], result[1]];
|
|
395
|
+
};
|
|
396
|
+
_i = 0, utxos_1 = utxos;
|
|
397
|
+
_a.label = 2;
|
|
398
|
+
case 2:
|
|
399
|
+
if (!(_i < utxos_1.length)) return [3 /*break*/, 5];
|
|
400
|
+
utxo = utxos_1[_i];
|
|
401
|
+
valueAccumulator = valueAccumulator.plus(utxo.value);
|
|
402
|
+
indexes = getPathIndexes(utxo.path);
|
|
403
|
+
return [4 /*yield*/, this.getAddressFromExtendedPublicKey(extendedPublicKey, indexes[0], indexes[1])];
|
|
404
|
+
case 3:
|
|
405
|
+
derivedAddress = (_a.sent()).address;
|
|
406
|
+
if (derivedAddress === utxo.address) {
|
|
407
|
+
transaction.ins.push({
|
|
408
|
+
txId: utxo.txid,
|
|
409
|
+
value: new bignumber_1.default(utxo.value).toString(10),
|
|
410
|
+
vout: utxo.vout,
|
|
411
|
+
address: utxo.address,
|
|
412
|
+
derivationPath: utxo.path
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
throw new Error('Invalid address returned from API');
|
|
417
|
+
}
|
|
418
|
+
if (valueAccumulator.isGreaterThanOrEqualTo(totalRequiredBalance)) {
|
|
419
|
+
return [3 /*break*/, 5];
|
|
420
|
+
}
|
|
421
|
+
_a.label = 4;
|
|
422
|
+
case 4:
|
|
423
|
+
_i++;
|
|
424
|
+
return [3 /*break*/, 2];
|
|
425
|
+
case 5:
|
|
426
|
+
if (valueAccumulator.isLessThan(totalRequiredBalance)) {
|
|
427
|
+
throw new Error('not enough balance 2');
|
|
428
|
+
}
|
|
429
|
+
for (i = 0; i < recipients.length; i++) {
|
|
430
|
+
transaction.outs.push({
|
|
431
|
+
recipient: recipients[i],
|
|
432
|
+
isChange: false,
|
|
433
|
+
value: wrappedValues[i].toString(10)
|
|
434
|
+
});
|
|
435
|
+
valueAccumulator = valueAccumulator.minus(wrappedValues[i]);
|
|
436
|
+
}
|
|
437
|
+
lastUsedInternalAddress = Math.max.apply(Math, __spreadArray([-1], utxos
|
|
438
|
+
.map(function (utxo) { return getPathIndexes(utxo.path); })
|
|
439
|
+
.filter(function (indexes) { return indexes[0] === 1; })
|
|
440
|
+
.map(function (indexes) { return indexes[1]; }), false));
|
|
441
|
+
changeValue = valueAccumulator.minus(wrappedFee);
|
|
442
|
+
if (!changeValue.isGreaterThan(new bignumber_1.default(DUST_AMOUNT))) return [3 /*break*/, 7];
|
|
443
|
+
changeAddressIndex = lastUsedInternalAddress + 1;
|
|
444
|
+
return [4 /*yield*/, this.getAddressFromExtendedPublicKey(extendedPublicKey, 1, changeAddressIndex)];
|
|
445
|
+
case 6:
|
|
446
|
+
derivedAddress = (_a.sent()).address;
|
|
447
|
+
transaction.outs.push({
|
|
448
|
+
recipient: derivedAddress,
|
|
449
|
+
isChange: true,
|
|
450
|
+
value: changeValue.toString(10),
|
|
451
|
+
derivationPath: "1/".concat(changeAddressIndex)
|
|
452
|
+
});
|
|
453
|
+
_a.label = 7;
|
|
454
|
+
case 7:
|
|
455
|
+
psbt = new bitcoinJS.Psbt();
|
|
456
|
+
// 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.
|
|
457
|
+
psbt.addUnknownKeyValToGlobal({
|
|
458
|
+
key: Buffer.from('amount'),
|
|
459
|
+
value: Buffer.from(wrappedValues.reduce(function (accumulator, currentValue) { return accumulator.plus(currentValue); }).toString())
|
|
460
|
+
});
|
|
461
|
+
keyPair = this.bip32.fromBase58(new ExtendedPublicKey(extendedPublicKey).toXpub());
|
|
462
|
+
replaceByFee = extras.replaceByFee ? true : false;
|
|
463
|
+
transaction.ins.forEach(function (tx) {
|
|
464
|
+
var indexes = getPathIndexes(tx.derivationPath);
|
|
465
|
+
var childNode = keyPair.derivePath(indexes.join('/'));
|
|
466
|
+
var p2wpkh = bitcoinJS.payments.p2wpkh({ pubkey: Buffer.from(childNode.publicKey), network: _this.options.network.extras.network });
|
|
467
|
+
var p2shOutput = p2wpkh.output;
|
|
468
|
+
if (!p2shOutput) {
|
|
469
|
+
throw new Error('no p2shOutput');
|
|
470
|
+
}
|
|
471
|
+
psbt.addInput({
|
|
472
|
+
hash: tx.txId,
|
|
473
|
+
index: tx.vout,
|
|
474
|
+
sequence: replaceByFee ? 0xfffffffd : undefined,
|
|
475
|
+
witnessUtxo: {
|
|
476
|
+
script: p2shOutput,
|
|
477
|
+
value: parseInt(tx.value)
|
|
478
|
+
},
|
|
479
|
+
bip32Derivation: [
|
|
480
|
+
{
|
|
481
|
+
masterFingerprint: Buffer.from(extras.masterFingerprint, 'hex'),
|
|
482
|
+
pubkey: Buffer.from(childNode.publicKey),
|
|
483
|
+
path: tx.derivationPath
|
|
484
|
+
}
|
|
485
|
+
]
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
transaction.outs.forEach(function (out, index) {
|
|
489
|
+
psbt.addOutput({ address: out.recipient, value: parseInt(out.value) });
|
|
490
|
+
if (out.derivationPath) {
|
|
491
|
+
// We add the derivation path of our change address to the key value map of the PSBT. This will allow us to later "filter" out this address when displaying the transaction info.
|
|
492
|
+
psbt.addUnknownKeyValToOutput(index, {
|
|
493
|
+
key: Buffer.from('dp'),
|
|
494
|
+
value: Buffer.from(out.derivationPath, 'utf8')
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
tx = {
|
|
499
|
+
psbt: psbt.toHex()
|
|
500
|
+
};
|
|
501
|
+
return [2 /*return*/, tx];
|
|
502
|
+
}
|
|
366
503
|
});
|
|
367
504
|
});
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
505
|
+
};
|
|
506
|
+
BitcoinSegwitProtocol.prototype.signWithExtendedPrivateKey = function (extendedPrivateKey, transaction /* RawBitcoinSegwitTransaction */) {
|
|
507
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
508
|
+
var rawBitcoinSegwitTx, bip32PK, decodedPSBT;
|
|
509
|
+
return __generator(this, function (_a) {
|
|
510
|
+
rawBitcoinSegwitTx = transaction;
|
|
511
|
+
bip32PK = this.bip32.fromBase58(extendedPrivateKey);
|
|
512
|
+
decodedPSBT = bitcoinJS.Psbt.fromHex(rawBitcoinSegwitTx.psbt);
|
|
513
|
+
decodedPSBT.data.inputs.forEach(function (input, index) {
|
|
514
|
+
var _a;
|
|
515
|
+
(_a = input.bip32Derivation) === null || _a === void 0 ? void 0 : _a.forEach(function (deriv) {
|
|
516
|
+
try {
|
|
517
|
+
// This uses the same logic to find child key as the "findWalletByFingerprintDerivationPathAndProtocolIdentifier" method in the Vault
|
|
518
|
+
var cutoffFrom = deriv.path.lastIndexOf("'") || deriv.path.lastIndexOf('h');
|
|
519
|
+
var childPath = deriv.path.substr(cutoffFrom + 2);
|
|
520
|
+
var childNode_1 = bip32PK.derivePath(childPath);
|
|
521
|
+
decodedPSBT.signInput(index, {
|
|
522
|
+
publicKey: Buffer.from(childNode_1.publicKey),
|
|
523
|
+
sign: function (hash, lowR) { return Buffer.from(childNode_1.sign(hash, lowR)); }
|
|
524
|
+
});
|
|
525
|
+
console.log("Signed input ".concat(index, " with path ").concat(deriv.path));
|
|
526
|
+
}
|
|
527
|
+
catch (e) {
|
|
528
|
+
console.log("Error signing input ".concat(index), e);
|
|
529
|
+
}
|
|
530
|
+
});
|
|
375
531
|
});
|
|
376
|
-
|
|
532
|
+
return [2 /*return*/, decodedPSBT.toHex()];
|
|
533
|
+
});
|
|
377
534
|
});
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const bip32PK = this.bip32.fromBase58(extendedPrivateKey);
|
|
386
|
-
const decodedPSBT = bitcoinJS.Psbt.fromHex(rawBitcoinSegwitTx.psbt);
|
|
387
|
-
decodedPSBT.data.inputs.forEach((input, index) => {
|
|
388
|
-
input.bip32Derivation?.forEach((deriv) => {
|
|
389
|
-
try {
|
|
390
|
-
// This uses the same logic to find child key as the "findWalletByFingerprintDerivationPathAndProtocolIdentifier" method in the Vault
|
|
391
|
-
const cutoffFrom = deriv.path.lastIndexOf("'") || deriv.path.lastIndexOf('h');
|
|
392
|
-
const childPath = deriv.path.substr(cutoffFrom + 2);
|
|
393
|
-
const childNode = bip32PK.derivePath(childPath);
|
|
394
|
-
decodedPSBT.signInput(index, {
|
|
395
|
-
publicKey: Buffer.from(childNode.publicKey),
|
|
396
|
-
sign: (hash, lowR) => Buffer.from(childNode.sign(hash, lowR))
|
|
397
|
-
});
|
|
398
|
-
console.log(`Signed input ${index} with path ${deriv.path}`);
|
|
399
|
-
}
|
|
400
|
-
catch (e) {
|
|
401
|
-
console.log(`Error signing input ${index}`, e);
|
|
402
|
-
}
|
|
535
|
+
};
|
|
536
|
+
BitcoinSegwitProtocol.prototype.broadcastTransaction = function (rawTransaction) {
|
|
537
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
538
|
+
var hexTransaction;
|
|
539
|
+
return __generator(this, function (_a) {
|
|
540
|
+
hexTransaction = bitcoinJS.Psbt.fromHex(rawTransaction).finalizeAllInputs().extractTransaction().toHex();
|
|
541
|
+
return [2 /*return*/, _super.prototype.broadcastTransaction.call(this, hexTransaction)];
|
|
403
542
|
});
|
|
404
543
|
});
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
const hexTransaction = bitcoinJS.Psbt.fromHex(rawTransaction).finalizeAllInputs().extractTransaction().toHex();
|
|
409
|
-
return super.broadcastTransaction(hexTransaction);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
544
|
+
};
|
|
545
|
+
return BitcoinSegwitProtocol;
|
|
546
|
+
}(BitcoinProtocol_1.BitcoinProtocol));
|
|
412
547
|
exports.BitcoinSegwitProtocol = BitcoinSegwitProtocol;
|
|
413
548
|
//# sourceMappingURL=BitcoinSegwitProtocol.js.map
|