@ledgerhq/hw-app-btc 10.0.1 → 10.0.2-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/lib/Btc.d.ts.map +1 -1
  3. package/lib/Btc.js +72 -97
  4. package/lib/Btc.js.map +1 -1
  5. package/lib/BtcNew.js +217 -313
  6. package/lib/BtcNew.js.map +1 -1
  7. package/lib/BtcOld.js +46 -106
  8. package/lib/BtcOld.js.map +1 -1
  9. package/lib/bip32.js +12 -12
  10. package/lib/bip32.js.map +1 -1
  11. package/lib/buffertools.js +66 -69
  12. package/lib/buffertools.js.map +1 -1
  13. package/lib/compressPublicKey.js +3 -3
  14. package/lib/compressPublicKey.js.map +1 -1
  15. package/lib/constants.js +1 -1
  16. package/lib/createTransaction.d.ts +1 -1
  17. package/lib/createTransaction.d.ts.map +1 -1
  18. package/lib/createTransaction.js +285 -398
  19. package/lib/createTransaction.js.map +1 -1
  20. package/lib/debug.js +11 -13
  21. package/lib/debug.js.map +1 -1
  22. package/lib/finalizeInput.js +23 -62
  23. package/lib/finalizeInput.js.map +1 -1
  24. package/lib/getAppAndVersion.d.ts +1 -1
  25. package/lib/getAppAndVersion.d.ts.map +1 -1
  26. package/lib/getAppAndVersion.js +29 -72
  27. package/lib/getAppAndVersion.js.map +1 -1
  28. package/lib/getTrustedInput.js +108 -251
  29. package/lib/getTrustedInput.js.map +1 -1
  30. package/lib/getTrustedInputBIP143.js +9 -10
  31. package/lib/getTrustedInputBIP143.js.map +1 -1
  32. package/lib/getWalletPublicKey.d.ts +1 -1
  33. package/lib/getWalletPublicKey.d.ts.map +1 -1
  34. package/lib/getWalletPublicKey.js +27 -73
  35. package/lib/getWalletPublicKey.js.map +1 -1
  36. package/lib/hashPublicKey.js +4 -4
  37. package/lib/hashPublicKey.js.map +1 -1
  38. package/lib/index.js +3 -3
  39. package/lib/index.js.map +1 -1
  40. package/lib/newops/accounttype.d.ts +2 -2
  41. package/lib/newops/accounttype.d.ts.map +1 -1
  42. package/lib/newops/accounttype.js +85 -125
  43. package/lib/newops/accounttype.js.map +1 -1
  44. package/lib/newops/appClient.js +98 -205
  45. package/lib/newops/appClient.js.map +1 -1
  46. package/lib/newops/clientCommands.js +122 -213
  47. package/lib/newops/clientCommands.js.map +1 -1
  48. package/lib/newops/merkelizedPsbt.js +28 -75
  49. package/lib/newops/merkelizedPsbt.js.map +1 -1
  50. package/lib/newops/merkle.js +38 -67
  51. package/lib/newops/merkle.js.map +1 -1
  52. package/lib/newops/merkleMap.js +11 -12
  53. package/lib/newops/merkleMap.js.map +1 -1
  54. package/lib/newops/policy.d.ts +1 -1
  55. package/lib/newops/policy.d.ts.map +1 -1
  56. package/lib/newops/policy.js +17 -18
  57. package/lib/newops/policy.js.map +1 -1
  58. package/lib/newops/psbtExtractor.js +9 -9
  59. package/lib/newops/psbtExtractor.js.map +1 -1
  60. package/lib/newops/psbtFinalizer.js +22 -22
  61. package/lib/newops/psbtFinalizer.js.map +1 -1
  62. package/lib/newops/psbtv2.d.ts +1 -1
  63. package/lib/newops/psbtv2.d.ts.map +1 -1
  64. package/lib/newops/psbtv2.js +227 -286
  65. package/lib/newops/psbtv2.js.map +1 -1
  66. package/lib/serializeTransaction.js +13 -15
  67. package/lib/serializeTransaction.js.map +1 -1
  68. package/lib/shouldUseTrustedInputForSegwit.js +4 -5
  69. package/lib/shouldUseTrustedInputForSegwit.js.map +1 -1
  70. package/lib/signMessage.js +47 -99
  71. package/lib/signMessage.js.map +1 -1
  72. package/lib/signP2SHTransaction.d.ts +1 -1
  73. package/lib/signP2SHTransaction.d.ts.map +1 -1
  74. package/lib/signP2SHTransaction.js +91 -187
  75. package/lib/signP2SHTransaction.js.map +1 -1
  76. package/lib/signTransaction.js +8 -9
  77. package/lib/signTransaction.js.map +1 -1
  78. package/lib/splitTransaction.js +50 -54
  79. package/lib/splitTransaction.js.map +1 -1
  80. package/lib/startUntrustedHashTransactionInput.js +65 -167
  81. package/lib/startUntrustedHashTransactionInput.js.map +1 -1
  82. package/lib/types.js +1 -1
  83. package/lib/varint.js +10 -10
  84. package/lib/varint.js.map +1 -1
  85. package/lib-es/Btc.d.ts.map +1 -1
  86. package/lib-es/Btc.js +58 -84
  87. package/lib-es/Btc.js.map +1 -1
  88. package/lib-es/BtcNew.js +205 -302
  89. package/lib-es/BtcNew.js.map +1 -1
  90. package/lib-es/BtcOld.js +35 -96
  91. package/lib-es/BtcOld.js.map +1 -1
  92. package/lib-es/bip32.js +7 -7
  93. package/lib-es/bip32.js.map +1 -1
  94. package/lib-es/buffertools.js +62 -67
  95. package/lib-es/buffertools.js.map +1 -1
  96. package/lib-es/compressPublicKey.js +2 -2
  97. package/lib-es/compressPublicKey.js.map +1 -1
  98. package/lib-es/constants.js +12 -12
  99. package/lib-es/constants.js.map +1 -1
  100. package/lib-es/createTransaction.d.ts +1 -1
  101. package/lib-es/createTransaction.d.ts.map +1 -1
  102. package/lib-es/createTransaction.js +271 -384
  103. package/lib-es/createTransaction.js.map +1 -1
  104. package/lib-es/debug.js +10 -12
  105. package/lib-es/debug.js.map +1 -1
  106. package/lib-es/finalizeInput.js +20 -59
  107. package/lib-es/finalizeInput.js.map +1 -1
  108. package/lib-es/getAppAndVersion.d.ts +1 -1
  109. package/lib-es/getAppAndVersion.d.ts.map +1 -1
  110. package/lib-es/getAppAndVersion.js +27 -70
  111. package/lib-es/getAppAndVersion.js.map +1 -1
  112. package/lib-es/getTrustedInput.js +104 -247
  113. package/lib-es/getTrustedInput.js.map +1 -1
  114. package/lib-es/getTrustedInputBIP143.js +5 -6
  115. package/lib-es/getTrustedInputBIP143.js.map +1 -1
  116. package/lib-es/getWalletPublicKey.d.ts +1 -1
  117. package/lib-es/getWalletPublicKey.d.ts.map +1 -1
  118. package/lib-es/getWalletPublicKey.js +25 -71
  119. package/lib-es/getWalletPublicKey.js.map +1 -1
  120. package/lib-es/newops/accounttype.d.ts +2 -2
  121. package/lib-es/newops/accounttype.d.ts.map +1 -1
  122. package/lib-es/newops/accounttype.js +79 -123
  123. package/lib-es/newops/accounttype.js.map +1 -1
  124. package/lib-es/newops/appClient.js +92 -200
  125. package/lib-es/newops/appClient.js.map +1 -1
  126. package/lib-es/newops/clientCommands.js +117 -214
  127. package/lib-es/newops/clientCommands.js.map +1 -1
  128. package/lib-es/newops/merkelizedPsbt.js +25 -73
  129. package/lib-es/newops/merkelizedPsbt.js.map +1 -1
  130. package/lib-es/newops/merkle.js +36 -66
  131. package/lib-es/newops/merkle.js.map +1 -1
  132. package/lib-es/newops/merkleMap.js +8 -10
  133. package/lib-es/newops/merkleMap.js.map +1 -1
  134. package/lib-es/newops/policy.d.ts +1 -1
  135. package/lib-es/newops/policy.d.ts.map +1 -1
  136. package/lib-es/newops/policy.js +12 -14
  137. package/lib-es/newops/policy.js.map +1 -1
  138. package/lib-es/newops/psbtExtractor.js +7 -7
  139. package/lib-es/newops/psbtExtractor.js.map +1 -1
  140. package/lib-es/newops/psbtFinalizer.js +19 -19
  141. package/lib-es/newops/psbtFinalizer.js.map +1 -1
  142. package/lib-es/newops/psbtv2.d.ts +1 -1
  143. package/lib-es/newops/psbtv2.d.ts.map +1 -1
  144. package/lib-es/newops/psbtv2.js +225 -286
  145. package/lib-es/newops/psbtv2.js.map +1 -1
  146. package/lib-es/serializeTransaction.js +11 -13
  147. package/lib-es/serializeTransaction.js.map +1 -1
  148. package/lib-es/shouldUseTrustedInputForSegwit.js +1 -2
  149. package/lib-es/shouldUseTrustedInputForSegwit.js.map +1 -1
  150. package/lib-es/signMessage.js +44 -96
  151. package/lib-es/signMessage.js.map +1 -1
  152. package/lib-es/signP2SHTransaction.d.ts +1 -1
  153. package/lib-es/signP2SHTransaction.d.ts.map +1 -1
  154. package/lib-es/signP2SHTransaction.js +84 -180
  155. package/lib-es/signP2SHTransaction.js.map +1 -1
  156. package/lib-es/signTransaction.js +6 -7
  157. package/lib-es/signTransaction.js.map +1 -1
  158. package/lib-es/splitTransaction.js +46 -50
  159. package/lib-es/splitTransaction.js.map +1 -1
  160. package/lib-es/startUntrustedHashTransactionInput.js +62 -164
  161. package/lib-es/startUntrustedHashTransactionInput.js.map +1 -1
  162. package/lib-es/varint.js +9 -9
  163. package/lib-es/varint.js.map +1 -1
  164. package/package.json +5 -6
  165. package/src/Btc.ts +28 -5
package/lib/BtcNew.js CHANGED
@@ -8,44 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (_) try {
18
- 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;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
- exports.__esModule = true;
39
- var bitcoinjs_lib_1 = require("bitcoinjs-lib");
40
- var tiny_secp256k1_1 = require("tiny-secp256k1");
41
- var bip32_1 = require("./bip32");
42
- var buffertools_1 = require("./buffertools");
43
- var accounttype_1 = require("./newops/accounttype");
44
- var policy_1 = require("./newops/policy");
45
- var psbtExtractor_1 = require("./newops/psbtExtractor");
46
- var psbtFinalizer_1 = require("./newops/psbtFinalizer");
47
- var psbtv2_1 = require("./newops/psbtv2");
48
- var serializeTransaction_1 = require("./serializeTransaction");
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const bitcoinjs_lib_1 = require("bitcoinjs-lib");
13
+ const tiny_secp256k1_1 = require("tiny-secp256k1");
14
+ const bip32_1 = require("./bip32");
15
+ const buffertools_1 = require("./buffertools");
16
+ const accounttype_1 = require("./newops/accounttype");
17
+ const policy_1 = require("./newops/policy");
18
+ const psbtExtractor_1 = require("./newops/psbtExtractor");
19
+ const psbtFinalizer_1 = require("./newops/psbtFinalizer");
20
+ const psbtv2_1 = require("./newops/psbtv2");
21
+ const serializeTransaction_1 = require("./serializeTransaction");
49
22
  /**
50
23
  * This class implements the same interface as BtcOld (formerly
51
24
  * named Btc), but interacts with Bitcoin hardware app version 2+
@@ -59,8 +32,8 @@ var serializeTransaction_1 = require("./serializeTransaction");
59
32
  * be developed that exposes PSBT to the outer world, which would render
60
33
  * a much cleaner implementation.
61
34
  */
62
- var BtcNew = /** @class */ (function () {
63
- function BtcNew(client) {
35
+ class BtcNew {
36
+ constructor(client) {
64
37
  this.client = client;
65
38
  }
66
39
  /**
@@ -93,26 +66,17 @@ var BtcNew = /** @class */ (function () {
93
66
  *
94
67
  * We opted for adding a new function, which can greatly simplify client code.
95
68
  */
96
- BtcNew.prototype.getWalletXpub = function (_a) {
97
- var path = _a.path, xpubVersion = _a.xpubVersion;
98
- return __awaiter(this, void 0, void 0, function () {
99
- var pathElements, xpub, xpubComponents;
100
- return __generator(this, function (_b) {
101
- switch (_b.label) {
102
- case 0:
103
- pathElements = (0, bip32_1.pathStringToArray)(path);
104
- return [4 /*yield*/, this.client.getExtendedPubkey(false, pathElements)];
105
- case 1:
106
- xpub = _b.sent();
107
- xpubComponents = (0, bip32_1.getXpubComponents)(xpub);
108
- if (xpubComponents.version != xpubVersion) {
109
- throw new Error("Expected xpub version ".concat(xpubVersion, " doesn't match the xpub version from the device ").concat(xpubComponents.version));
110
- }
111
- return [2 /*return*/, xpub];
112
- }
113
- });
69
+ getWalletXpub({ path, xpubVersion, }) {
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ const pathElements = (0, bip32_1.pathStringToArray)(path);
72
+ const xpub = yield this.client.getExtendedPubkey(false, pathElements);
73
+ const xpubComponents = (0, bip32_1.getXpubComponents)(xpub);
74
+ if (xpubComponents.version != xpubVersion) {
75
+ throw new Error(`Expected xpub version ${xpubVersion} doesn't match the xpub version from the device ${xpubComponents.version}`);
76
+ }
77
+ return xpub;
114
78
  });
115
- };
79
+ }
116
80
  /**
117
81
  * This method returns a public key, a bitcoin address, and and a chaincode
118
82
  * for a specific derivation path.
@@ -120,35 +84,25 @@ var BtcNew = /** @class */ (function () {
120
84
  * Limitation: If the path is not a leaf node of a standard path, the address
121
85
  * will be the empty string "", see this.getWalletAddress() for details.
122
86
  */
123
- BtcNew.prototype.getWalletPublicKey = function (path, opts) {
87
+ getWalletPublicKey(path, opts) {
124
88
  var _a, _b;
125
- return __awaiter(this, void 0, void 0, function () {
126
- var pathElements, xpub, display, address, components, uncompressedPubkey;
127
- return __generator(this, function (_c) {
128
- switch (_c.label) {
129
- case 0:
130
- if (!isPathNormal(path)) {
131
- throw Error("non-standard path: ".concat(path));
132
- }
133
- pathElements = (0, bip32_1.pathStringToArray)(path);
134
- return [4 /*yield*/, this.client.getExtendedPubkey(false, pathElements)];
135
- case 1:
136
- xpub = _c.sent();
137
- display = (_a = opts === null || opts === void 0 ? void 0 : opts.verify) !== null && _a !== void 0 ? _a : false;
138
- return [4 /*yield*/, this.getWalletAddress(pathElements, descrTemplFrom((_b = opts === null || opts === void 0 ? void 0 : opts.format) !== null && _b !== void 0 ? _b : "legacy"), display)];
139
- case 2:
140
- address = _c.sent();
141
- components = (0, bip32_1.getXpubComponents)(xpub);
142
- uncompressedPubkey = Buffer.from((0, tiny_secp256k1_1.pointCompress)(components.pubkey, false));
143
- return [2 /*return*/, {
144
- publicKey: uncompressedPubkey.toString("hex"),
145
- bitcoinAddress: address,
146
- chainCode: components.chaincode.toString("hex")
147
- }];
148
- }
149
- });
89
+ return __awaiter(this, void 0, void 0, function* () {
90
+ if (!isPathNormal(path)) {
91
+ throw Error(`non-standard path: ${path}`);
92
+ }
93
+ const pathElements = (0, bip32_1.pathStringToArray)(path);
94
+ const xpub = yield this.client.getExtendedPubkey(false, pathElements);
95
+ const display = (_a = opts === null || opts === void 0 ? void 0 : opts.verify) !== null && _a !== void 0 ? _a : false;
96
+ const address = yield this.getWalletAddress(pathElements, descrTemplFrom((_b = opts === null || opts === void 0 ? void 0 : opts.format) !== null && _b !== void 0 ? _b : "legacy"), display);
97
+ const components = (0, bip32_1.getXpubComponents)(xpub);
98
+ const uncompressedPubkey = Buffer.from((0, tiny_secp256k1_1.pointCompress)(components.pubkey, false));
99
+ return {
100
+ publicKey: uncompressedPubkey.toString("hex"),
101
+ bitcoinAddress: address,
102
+ chainCode: components.chaincode.toString("hex"),
103
+ };
150
104
  });
151
- };
105
+ }
152
106
  /**
153
107
  * Get an address for the specified path.
154
108
  *
@@ -164,29 +118,19 @@ var BtcNew = /** @class */ (function () {
164
118
  * way to get the address from the device. In this case we have to create it
165
119
  * ourselves, but we don't at this time, and instead return an empty ("") address.
166
120
  */
167
- BtcNew.prototype.getWalletAddress = function (pathElements, descrTempl, display) {
168
- return __awaiter(this, void 0, void 0, function () {
169
- var accountPath, accountXpub, masterFingerprint, policy, changeAndIndex;
170
- return __generator(this, function (_a) {
171
- switch (_a.label) {
172
- case 0:
173
- accountPath = (0, bip32_1.hardenedPathOf)(pathElements);
174
- if (accountPath.length + 2 != pathElements.length) {
175
- return [2 /*return*/, ""];
176
- }
177
- return [4 /*yield*/, this.client.getExtendedPubkey(false, accountPath)];
178
- case 1:
179
- accountXpub = _a.sent();
180
- return [4 /*yield*/, this.client.getMasterFingerprint()];
181
- case 2:
182
- masterFingerprint = _a.sent();
183
- policy = new policy_1.WalletPolicy(descrTempl, (0, policy_1.createKey)(masterFingerprint, accountPath, accountXpub));
184
- changeAndIndex = pathElements.slice(-2, pathElements.length);
185
- return [2 /*return*/, this.client.getWalletAddress(policy, Buffer.alloc(32, 0), changeAndIndex[0], changeAndIndex[1], display)];
186
- }
187
- });
121
+ getWalletAddress(pathElements, descrTempl, display) {
122
+ return __awaiter(this, void 0, void 0, function* () {
123
+ const accountPath = (0, bip32_1.hardenedPathOf)(pathElements);
124
+ if (accountPath.length + 2 != pathElements.length) {
125
+ return "";
126
+ }
127
+ const accountXpub = yield this.client.getExtendedPubkey(false, accountPath);
128
+ const masterFingerprint = yield this.client.getMasterFingerprint();
129
+ const policy = new policy_1.WalletPolicy(descrTempl, (0, policy_1.createKey)(masterFingerprint, accountPath, accountXpub));
130
+ const changeAndIndex = pathElements.slice(-2, pathElements.length);
131
+ return this.client.getWalletAddress(policy, Buffer.alloc(32, 0), changeAndIndex[0], changeAndIndex[1], display);
188
132
  });
189
- };
133
+ }
190
134
  /**
191
135
  * Build and sign a transaction. See Btc.createPaymentTransaction for
192
136
  * details on how to use this method.
@@ -195,111 +139,97 @@ var BtcNew = /** @class */ (function () {
195
139
  * a psbt which is finally signed and finalized, and the extracted fully signed
196
140
  * transaction is returned.
197
141
  */
198
- BtcNew.prototype.createPaymentTransaction = function (arg) {
199
- return __awaiter(this, void 0, void 0, function () {
200
- var inputCount, psbt, masterFp, accountType, notifyCount, progress, accountXpub, accountPath, i, pathElems, outputsConcat, outputsBufferReader, outputCount, changeData, changeFound, i, amount, outputScript, isChange, changePath, pubkey, key, p, firstSigned, progressCallback, serializedTx;
201
- return __generator(this, function (_a) {
202
- switch (_a.label) {
203
- case 0:
204
- inputCount = arg.inputs.length;
205
- if (inputCount == 0) {
206
- throw Error("No inputs");
207
- }
208
- psbt = new psbtv2_1.PsbtV2();
209
- return [4 /*yield*/, this.client.getMasterFingerprint()];
210
- case 1:
211
- masterFp = _a.sent();
212
- accountType = accountTypeFromArg(arg, psbt, masterFp);
213
- if (arg.lockTime != undefined) {
214
- // The signer will assume locktime 0 if unset
215
- psbt.setGlobalFallbackLocktime(arg.lockTime);
216
- }
217
- psbt.setGlobalInputCount(inputCount);
218
- psbt.setGlobalPsbtVersion(2);
219
- psbt.setGlobalTxVersion(2);
220
- notifyCount = 0;
221
- progress = function () {
222
- if (!arg.onDeviceStreaming)
223
- return;
224
- arg.onDeviceStreaming({
225
- total: 2 * inputCount,
226
- index: notifyCount,
227
- progress: ++notifyCount / (2 * inputCount)
228
- });
229
- };
230
- accountXpub = "";
231
- accountPath = [];
232
- i = 0;
233
- _a.label = 2;
234
- case 2:
235
- if (!(i < inputCount)) return [3 /*break*/, 7];
236
- progress();
237
- pathElems = (0, bip32_1.pathStringToArray)(arg.associatedKeysets[i]);
238
- if (!(accountXpub == "")) return [3 /*break*/, 4];
239
- // We assume all inputs belong to the same account so we set
240
- // the account xpub and path based on the first input.
241
- accountPath = pathElems.slice(0, -2);
242
- return [4 /*yield*/, this.client.getExtendedPubkey(false, accountPath)];
243
- case 3:
244
- accountXpub = _a.sent();
245
- _a.label = 4;
246
- case 4: return [4 /*yield*/, this.setInput(psbt, i, arg.inputs[i], pathElems, accountType, masterFp, arg.sigHashType)];
247
- case 5:
248
- _a.sent();
249
- _a.label = 6;
250
- case 6:
251
- i++;
252
- return [3 /*break*/, 2];
253
- case 7:
254
- outputsConcat = Buffer.from(arg.outputScriptHex, "hex");
255
- outputsBufferReader = new buffertools_1.BufferReader(outputsConcat);
256
- outputCount = outputsBufferReader.readVarInt();
257
- psbt.setGlobalOutputCount(outputCount);
258
- return [4 /*yield*/, this.outputScriptAt(accountPath, accountType, arg.changePath)];
259
- case 8:
260
- changeData = _a.sent();
261
- changeFound = !changeData;
262
- for (i = 0; i < outputCount; i++) {
263
- amount = Number(outputsBufferReader.readUInt64());
264
- outputScript = outputsBufferReader.readVarSlice();
265
- psbt.setOutputAmount(i, amount);
266
- psbt.setOutputScript(i, outputScript);
267
- isChange = changeData && outputScript.equals(changeData === null || changeData === void 0 ? void 0 : changeData.cond.scriptPubKey);
268
- if (isChange) {
269
- changeFound = true;
270
- changePath = (0, bip32_1.pathStringToArray)(arg.changePath);
271
- pubkey = changeData.pubkey;
272
- accountType.setOwnOutput(i, changeData.cond, [pubkey], [changePath]);
273
- }
274
- }
275
- if (!changeFound) {
276
- throw new Error("Change script not found among outputs! " +
277
- (changeData === null || changeData === void 0 ? void 0 : changeData.cond.scriptPubKey.toString("hex")));
278
- }
279
- key = (0, policy_1.createKey)(masterFp, accountPath, accountXpub);
280
- p = new policy_1.WalletPolicy(accountType.getDescriptorTemplate(), key);
281
- // This is cheating, because it's not actually requested on the
282
- // device yet, but it will be, soonish.
283
- if (arg.onDeviceSignatureRequested)
284
- arg.onDeviceSignatureRequested();
285
- firstSigned = false;
286
- progressCallback = function () {
287
- if (!firstSigned) {
288
- firstSigned = true;
289
- arg.onDeviceSignatureGranted && arg.onDeviceSignatureGranted();
290
- }
291
- progress();
292
- };
293
- return [4 /*yield*/, this.signPsbt(psbt, p, progressCallback)];
294
- case 9:
295
- _a.sent();
296
- (0, psbtFinalizer_1.finalize)(psbt);
297
- serializedTx = (0, psbtExtractor_1.extract)(psbt);
298
- return [2 /*return*/, serializedTx.toString("hex")];
142
+ createPaymentTransaction(arg) {
143
+ return __awaiter(this, void 0, void 0, function* () {
144
+ const inputCount = arg.inputs.length;
145
+ if (inputCount == 0) {
146
+ throw Error("No inputs");
147
+ }
148
+ const psbt = new psbtv2_1.PsbtV2();
149
+ // The master fingerprint is needed when adding BIP32 derivation paths on
150
+ // the psbt.
151
+ const masterFp = yield this.client.getMasterFingerprint();
152
+ const accountType = accountTypeFromArg(arg, psbt, masterFp);
153
+ if (arg.lockTime != undefined) {
154
+ // The signer will assume locktime 0 if unset
155
+ psbt.setGlobalFallbackLocktime(arg.lockTime);
156
+ }
157
+ psbt.setGlobalInputCount(inputCount);
158
+ psbt.setGlobalPsbtVersion(2);
159
+ psbt.setGlobalTxVersion(2);
160
+ let notifyCount = 0;
161
+ const progress = () => {
162
+ if (!arg.onDeviceStreaming)
163
+ return;
164
+ arg.onDeviceStreaming({
165
+ total: 2 * inputCount,
166
+ index: notifyCount,
167
+ progress: ++notifyCount / (2 * inputCount),
168
+ });
169
+ };
170
+ let accountXpub = "";
171
+ let accountPath = [];
172
+ for (let i = 0; i < inputCount; i++) {
173
+ progress();
174
+ const pathElems = (0, bip32_1.pathStringToArray)(arg.associatedKeysets[i]);
175
+ if (accountXpub == "") {
176
+ // We assume all inputs belong to the same account so we set
177
+ // the account xpub and path based on the first input.
178
+ accountPath = pathElems.slice(0, -2);
179
+ accountXpub = yield this.client.getExtendedPubkey(false, accountPath);
299
180
  }
300
- });
181
+ yield this.setInput(psbt, i, arg.inputs[i], pathElems, accountType, masterFp, arg.sigHashType);
182
+ }
183
+ const outputsConcat = Buffer.from(arg.outputScriptHex, "hex");
184
+ const outputsBufferReader = new buffertools_1.BufferReader(outputsConcat);
185
+ const outputCount = outputsBufferReader.readVarInt();
186
+ psbt.setGlobalOutputCount(outputCount);
187
+ const changeData = yield this.outputScriptAt(accountPath, accountType, arg.changePath);
188
+ // If the caller supplied a changePath, we must make sure there actually is
189
+ // a change output. If no change output found, we'll throw an error.
190
+ let changeFound = !changeData;
191
+ for (let i = 0; i < outputCount; i++) {
192
+ const amount = Number(outputsBufferReader.readUInt64());
193
+ const outputScript = outputsBufferReader.readVarSlice();
194
+ psbt.setOutputAmount(i, amount);
195
+ psbt.setOutputScript(i, outputScript);
196
+ // We won't know if we're paying to ourselves, because there's no
197
+ // information in arg to support multiple "change paths". One exception is
198
+ // if there are multiple outputs to the change address.
199
+ const isChange = changeData && outputScript.equals(changeData === null || changeData === void 0 ? void 0 : changeData.cond.scriptPubKey);
200
+ if (isChange) {
201
+ changeFound = true;
202
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
203
+ const changePath = (0, bip32_1.pathStringToArray)(arg.changePath);
204
+ const pubkey = changeData.pubkey;
205
+ accountType.setOwnOutput(i, changeData.cond, [pubkey], [changePath]);
206
+ }
207
+ }
208
+ if (!changeFound) {
209
+ throw new Error("Change script not found among outputs! " +
210
+ (changeData === null || changeData === void 0 ? void 0 : changeData.cond.scriptPubKey.toString("hex")));
211
+ }
212
+ const key = (0, policy_1.createKey)(masterFp, accountPath, accountXpub);
213
+ const p = new policy_1.WalletPolicy(accountType.getDescriptorTemplate(), key);
214
+ // This is cheating, because it's not actually requested on the
215
+ // device yet, but it will be, soonish.
216
+ if (arg.onDeviceSignatureRequested)
217
+ arg.onDeviceSignatureRequested();
218
+ let firstSigned = false;
219
+ // This callback will be called once for each signature yielded.
220
+ const progressCallback = () => {
221
+ if (!firstSigned) {
222
+ firstSigned = true;
223
+ arg.onDeviceSignatureGranted && arg.onDeviceSignatureGranted();
224
+ }
225
+ progress();
226
+ };
227
+ yield this.signPsbt(psbt, p, progressCallback);
228
+ (0, psbtFinalizer_1.finalize)(psbt);
229
+ const serializedTx = (0, psbtExtractor_1.extract)(psbt);
230
+ return serializedTx.toString("hex");
301
231
  });
302
- };
232
+ }
303
233
  /**
304
234
  * Calculates an output script along with public key and possible redeemScript
305
235
  * from a path and accountType. The accountPath must be a prefix of path.
@@ -308,75 +238,60 @@ var BtcNew = /** @class */ (function () {
308
238
  * wrapped p2wpkh), and pubkey at provided path. The values of these three
309
239
  * properties depend on the accountType used.
310
240
  */
311
- BtcNew.prototype.outputScriptAt = function (accountPath, accountType, path) {
312
- return __awaiter(this, void 0, void 0, function () {
313
- var pathElems, i, xpub, pubkey, cond;
314
- return __generator(this, function (_a) {
315
- switch (_a.label) {
316
- case 0:
317
- if (!path)
318
- return [2 /*return*/, undefined];
319
- pathElems = (0, bip32_1.pathStringToArray)(path);
320
- // Make sure path is in our account, otherwise something fishy is probably
321
- // going on.
322
- for (i = 0; i < accountPath.length; i++) {
323
- if (accountPath[i] != pathElems[i]) {
324
- throw new Error("Path ".concat(path, " not in account ").concat((0, bip32_1.pathArrayToString)(accountPath)));
325
- }
326
- }
327
- return [4 /*yield*/, this.client.getExtendedPubkey(false, pathElems)];
328
- case 1:
329
- xpub = _a.sent();
330
- pubkey = (0, bip32_1.pubkeyFromXpub)(xpub);
331
- cond = accountType.spendingCondition([pubkey]);
332
- return [2 /*return*/, { cond: cond, pubkey: pubkey }];
241
+ outputScriptAt(accountPath, accountType, path) {
242
+ return __awaiter(this, void 0, void 0, function* () {
243
+ if (!path)
244
+ return undefined;
245
+ const pathElems = (0, bip32_1.pathStringToArray)(path);
246
+ // Make sure path is in our account, otherwise something fishy is probably
247
+ // going on.
248
+ for (let i = 0; i < accountPath.length; i++) {
249
+ if (accountPath[i] != pathElems[i]) {
250
+ throw new Error(`Path ${path} not in account ${(0, bip32_1.pathArrayToString)(accountPath)}`);
333
251
  }
334
- });
252
+ }
253
+ const xpub = yield this.client.getExtendedPubkey(false, pathElems);
254
+ const pubkey = (0, bip32_1.pubkeyFromXpub)(xpub);
255
+ const cond = accountType.spendingCondition([pubkey]);
256
+ return { cond, pubkey };
335
257
  });
336
- };
258
+ }
337
259
  /**
338
260
  * Adds relevant data about an input to the psbt. This includes sequence,
339
261
  * previous txid, output index, spent UTXO, redeem script for wrapped p2wpkh,
340
262
  * public key and its derivation path.
341
263
  */
342
- BtcNew.prototype.setInput = function (psbt, i, input, pathElements, accountType, masterFP, sigHashType) {
343
- return __awaiter(this, void 0, void 0, function () {
344
- var inputTx, spentOutputIndex, redeemScript, sequence, inputTxBuffer, inputTxid, xpubBase58, pubkey, spentTxOutput, spendCondition, spentOutput;
345
- return __generator(this, function (_a) {
346
- switch (_a.label) {
347
- case 0:
348
- inputTx = input[0];
349
- spentOutputIndex = input[1];
350
- redeemScript = input[2] ? Buffer.from(input[2], "hex") : undefined;
351
- sequence = input[3];
352
- if (sequence != undefined) {
353
- psbt.setInputSequence(i, sequence);
354
- }
355
- if (sigHashType != undefined) {
356
- psbt.setInputSighashType(i, sigHashType);
357
- }
358
- inputTxBuffer = (0, serializeTransaction_1.serializeTransaction)(inputTx, true);
359
- inputTxid = bitcoinjs_lib_1.crypto.hash256(inputTxBuffer);
360
- return [4 /*yield*/, this.client.getExtendedPubkey(false, pathElements)];
361
- case 1:
362
- xpubBase58 = _a.sent();
363
- pubkey = (0, bip32_1.pubkeyFromXpub)(xpubBase58);
364
- if (!inputTx.outputs)
365
- throw Error("Missing outputs array in transaction to sign");
366
- spentTxOutput = inputTx.outputs[spentOutputIndex];
367
- spendCondition = {
368
- scriptPubKey: spentTxOutput.script,
369
- redeemScript: redeemScript
370
- };
371
- spentOutput = { cond: spendCondition, amount: spentTxOutput.amount };
372
- accountType.setInput(i, inputTxBuffer, spentOutput, [pubkey], [pathElements]);
373
- psbt.setInputPreviousTxId(i, inputTxid);
374
- psbt.setInputOutputIndex(i, spentOutputIndex);
375
- return [2 /*return*/];
376
- }
377
- });
264
+ setInput(psbt, i, input, pathElements, accountType, masterFP, sigHashType) {
265
+ return __awaiter(this, void 0, void 0, function* () {
266
+ const inputTx = input[0];
267
+ const spentOutputIndex = input[1];
268
+ // redeemScript will be null for wrapped p2wpkh, we need to create it
269
+ // ourselves. But if set, it should be used.
270
+ const redeemScript = input[2] ? Buffer.from(input[2], "hex") : undefined;
271
+ const sequence = input[3];
272
+ if (sequence != undefined) {
273
+ psbt.setInputSequence(i, sequence);
274
+ }
275
+ if (sigHashType != undefined) {
276
+ psbt.setInputSighashType(i, sigHashType);
277
+ }
278
+ const inputTxBuffer = (0, serializeTransaction_1.serializeTransaction)(inputTx, true);
279
+ const inputTxid = bitcoinjs_lib_1.crypto.hash256(inputTxBuffer);
280
+ const xpubBase58 = yield this.client.getExtendedPubkey(false, pathElements);
281
+ const pubkey = (0, bip32_1.pubkeyFromXpub)(xpubBase58);
282
+ if (!inputTx.outputs)
283
+ throw Error("Missing outputs array in transaction to sign");
284
+ const spentTxOutput = inputTx.outputs[spentOutputIndex];
285
+ const spendCondition = {
286
+ scriptPubKey: spentTxOutput.script,
287
+ redeemScript: redeemScript,
288
+ };
289
+ const spentOutput = { cond: spendCondition, amount: spentTxOutput.amount };
290
+ accountType.setInput(i, inputTxBuffer, spentOutput, [pubkey], [pathElements]);
291
+ psbt.setInputPreviousTxId(i, inputTxid);
292
+ psbt.setInputOutputIndex(i, spentOutputIndex);
378
293
  });
379
- };
294
+ }
380
295
  /**
381
296
  * This implements the "Signer" role of the BIP370 transaction signing
382
297
  * process.
@@ -386,40 +301,31 @@ var BtcNew = /** @class */ (function () {
386
301
  * comment in-line. The signatures returned from the hardware device is added
387
302
  * to the appropriate input fields of the PSBT.
388
303
  */
389
- BtcNew.prototype.signPsbt = function (psbt, walletPolicy, progressCallback) {
390
- return __awaiter(this, void 0, void 0, function () {
391
- var sigs;
392
- return __generator(this, function (_a) {
393
- switch (_a.label) {
394
- case 0: return [4 /*yield*/, this.client.signPsbt(psbt, walletPolicy, Buffer.alloc(32, 0), progressCallback)];
395
- case 1:
396
- sigs = _a.sent();
397
- sigs.forEach(function (v, k) {
398
- // Note: Looking at BIP32 derivation does not work in the generic case,
399
- // since some inputs might not have a BIP32-derived pubkey.
400
- var pubkeys = psbt.getInputKeyDatas(k, psbtv2_1.psbtIn.BIP32_DERIVATION);
401
- var pubkey;
402
- if (pubkeys.length != 1) {
403
- // No legacy BIP32_DERIVATION, assume we're using taproot.
404
- pubkey = psbt.getInputKeyDatas(k, psbtv2_1.psbtIn.TAP_BIP32_DERIVATION);
405
- if (pubkey.length == 0) {
406
- throw Error("Missing pubkey derivation for input ".concat(k));
407
- }
408
- psbt.setInputTapKeySig(k, v);
409
- }
410
- else {
411
- pubkey = pubkeys[0];
412
- psbt.setInputPartialSig(k, pubkey, v);
413
- }
414
- });
415
- return [2 /*return*/];
304
+ signPsbt(psbt, walletPolicy, progressCallback) {
305
+ return __awaiter(this, void 0, void 0, function* () {
306
+ const sigs = yield this.client.signPsbt(psbt, walletPolicy, Buffer.alloc(32, 0), progressCallback);
307
+ sigs.forEach((v, k) => {
308
+ // Note: Looking at BIP32 derivation does not work in the generic case,
309
+ // since some inputs might not have a BIP32-derived pubkey.
310
+ const pubkeys = psbt.getInputKeyDatas(k, psbtv2_1.psbtIn.BIP32_DERIVATION);
311
+ let pubkey;
312
+ if (pubkeys.length != 1) {
313
+ // No legacy BIP32_DERIVATION, assume we're using taproot.
314
+ pubkey = psbt.getInputKeyDatas(k, psbtv2_1.psbtIn.TAP_BIP32_DERIVATION);
315
+ if (pubkey.length == 0) {
316
+ throw Error(`Missing pubkey derivation for input ${k}`);
317
+ }
318
+ psbt.setInputTapKeySig(k, v);
319
+ }
320
+ else {
321
+ pubkey = pubkeys[0];
322
+ psbt.setInputPartialSig(k, pubkey, v);
416
323
  }
417
324
  });
418
325
  });
419
- };
420
- return BtcNew;
421
- }());
422
- exports["default"] = BtcNew;
326
+ }
327
+ }
328
+ exports.default = BtcNew;
423
329
  function descrTemplFrom(addressFormat) {
424
330
  if (addressFormat == "legacy")
425
331
  return "pkh(@0)";
@@ -461,17 +367,15 @@ function accountTypeFromArg(arg, psbt, masterFp) {
461
367
  */
462
368
  function isPathNormal(path) {
463
369
  //path is not deepest hardened node of a standard path or deeper, use BtcOld
464
- var h = 0x80000000; //HARDENED from bip32
465
- var pathElems = (0, bip32_1.pathStringToArray)(path);
466
- var hard = function (n) { return n >= h; };
467
- var soft = function (n) { return n === undefined || n < h; };
468
- var change = function (n) {
469
- return n === undefined || n === 0 || n === 1;
470
- };
370
+ const h = 0x80000000; //HARDENED from bip32
371
+ const pathElems = (0, bip32_1.pathStringToArray)(path);
372
+ const hard = (n) => n >= h;
373
+ const soft = (n) => n === undefined || n < h;
374
+ const change = (n) => n === undefined || n === 0 || n === 1;
471
375
  if (pathElems.length >= 3 &&
472
376
  pathElems.length <= 5 &&
473
- [44 + h, 49 + h, 84 + h, 86 + h].some(function (v) { return v == pathElems[0]; }) &&
474
- [0 + h, 1 + h].some(function (v) { return v == pathElems[1]; }) &&
377
+ [44 + h, 49 + h, 84 + h, 86 + h].some((v) => v == pathElems[0]) &&
378
+ [0 + h, 1 + h].some((v) => v == pathElems[1]) &&
475
379
  hard(pathElems[2]) &&
476
380
  change(pathElems[3]) &&
477
381
  soft(pathElems[4])) {
@@ -480,7 +384,7 @@ function isPathNormal(path) {
480
384
  if (pathElems.length >= 4 &&
481
385
  pathElems.length <= 6 &&
482
386
  48 + h == pathElems[0] &&
483
- [0 + h, 1 + h].some(function (v) { return v == pathElems[1]; }) &&
387
+ [0 + h, 1 + h].some((v) => v == pathElems[1]) &&
484
388
  hard(pathElems[2]) &&
485
389
  hard(pathElems[3]) &&
486
390
  change(pathElems[4]) &&