@shapeshiftoss/hdwallet-keepkey 1.62.39 → 1.62.42

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 (114) hide show
  1. package/LICENSE.md +6 -6
  2. package/dist/cjs/.tsbuildinfo +1 -0
  3. package/dist/{adapter.d.ts → cjs/adapter.d.ts} +6 -7
  4. package/dist/cjs/adapter.js +146 -0
  5. package/dist/{binance.d.ts → cjs/binance.d.ts} +3 -4
  6. package/dist/cjs/binance.js +144 -0
  7. package/dist/{bitcoin.d.ts → cjs/bitcoin.d.ts} +3 -4
  8. package/dist/cjs/bitcoin.js +549 -0
  9. package/dist/{bnbencoding.d.ts → cjs/bnbencoding.d.ts} +3 -2
  10. package/dist/{bnbencoding.js → cjs/bnbencoding.js} +22 -22
  11. package/dist/{cosmos.d.ts → cjs/cosmos.d.ts} +4 -5
  12. package/dist/cjs/cosmos.js +219 -0
  13. package/dist/{eos.d.ts → cjs/eos.d.ts} +3 -4
  14. package/dist/cjs/eos.js +244 -0
  15. package/dist/{ethereum.d.ts → cjs/ethereum.d.ts} +4 -5
  16. package/dist/cjs/ethereum.js +264 -0
  17. package/dist/cjs/index.d.ts +5 -0
  18. package/dist/{index.js → cjs/index.js} +0 -1
  19. package/dist/{keepkey.d.ts → cjs/keepkey.d.ts} +45 -20
  20. package/dist/cjs/keepkey.js +959 -0
  21. package/dist/{mayachain.d.ts → cjs/mayachain.d.ts} +4 -5
  22. package/dist/cjs/mayachain.js +169 -0
  23. package/dist/{osmosis.d.ts → cjs/osmosis.d.ts} +4 -5
  24. package/dist/cjs/osmosis.js +270 -0
  25. package/dist/cjs/package.json +1 -0
  26. package/dist/{ripple.d.ts → cjs/ripple.d.ts} +3 -4
  27. package/dist/cjs/ripple.js +104 -0
  28. package/dist/{thorchain.d.ts → cjs/thorchain.d.ts} +4 -5
  29. package/dist/cjs/thorchain.js +169 -0
  30. package/dist/{transport.d.ts → cjs/transport.d.ts} +2 -3
  31. package/dist/cjs/transport.js +333 -0
  32. package/dist/{typeRegistry.d.ts → cjs/typeRegistry.d.ts} +2 -3
  33. package/dist/{typeRegistry.js → cjs/typeRegistry.js} +26 -13
  34. package/dist/{utils.d.ts → cjs/utils.d.ts} +1 -2
  35. package/dist/{utils.js → cjs/utils.js} +7 -8
  36. package/dist/esm/.tsbuildinfo +1 -0
  37. package/dist/esm/adapter.d.ts +35 -0
  38. package/dist/esm/adapter.js +119 -0
  39. package/dist/esm/binance.d.ts +5 -0
  40. package/dist/esm/binance.js +112 -0
  41. package/dist/esm/bitcoin.d.ts +11 -0
  42. package/dist/esm/bitcoin.js +511 -0
  43. package/dist/esm/bnbencoding.d.ts +11 -0
  44. package/dist/esm/bnbencoding.js +103 -0
  45. package/dist/esm/cosmos.d.ts +6 -0
  46. package/dist/esm/cosmos.js +187 -0
  47. package/dist/esm/eos.d.ts +5 -0
  48. package/dist/esm/eos.js +212 -0
  49. package/dist/esm/ethereum.d.ts +17 -0
  50. package/dist/esm/ethereum.js +229 -0
  51. package/dist/esm/index.d.ts +5 -0
  52. package/dist/esm/index.js +5 -0
  53. package/dist/esm/keepkey.d.ts +177 -0
  54. package/dist/esm/keepkey.js +925 -0
  55. package/dist/esm/mayachain.d.ts +6 -0
  56. package/dist/esm/mayachain.js +137 -0
  57. package/dist/esm/osmosis.d.ts +6 -0
  58. package/dist/esm/osmosis.js +238 -0
  59. package/dist/esm/ripple.d.ts +5 -0
  60. package/dist/esm/ripple.js +72 -0
  61. package/dist/esm/thorchain.d.ts +6 -0
  62. package/dist/esm/thorchain.js +137 -0
  63. package/dist/esm/transport.d.ts +55 -0
  64. package/dist/esm/transport.js +306 -0
  65. package/dist/esm/typeRegistry.d.ts +4 -0
  66. package/dist/esm/typeRegistry.js +47 -0
  67. package/dist/esm/utils.d.ts +6 -0
  68. package/dist/esm/utils.js +56 -0
  69. package/package.json +33 -19
  70. package/dist/adapter.d.ts.map +0 -1
  71. package/dist/adapter.js +0 -175
  72. package/dist/adapter.js.map +0 -1
  73. package/dist/binance.d.ts.map +0 -1
  74. package/dist/binance.js +0 -146
  75. package/dist/binance.js.map +0 -1
  76. package/dist/bitcoin.d.ts.map +0 -1
  77. package/dist/bitcoin.js +0 -568
  78. package/dist/bitcoin.js.map +0 -1
  79. package/dist/bnbencoding.d.ts.map +0 -1
  80. package/dist/bnbencoding.js.map +0 -1
  81. package/dist/cosmos.d.ts.map +0 -1
  82. package/dist/cosmos.js +0 -230
  83. package/dist/cosmos.js.map +0 -1
  84. package/dist/eos.d.ts.map +0 -1
  85. package/dist/eos.js +0 -247
  86. package/dist/eos.js.map +0 -1
  87. package/dist/ethereum.d.ts.map +0 -1
  88. package/dist/ethereum.js +0 -281
  89. package/dist/ethereum.js.map +0 -1
  90. package/dist/index.d.ts +0 -6
  91. package/dist/index.d.ts.map +0 -1
  92. package/dist/index.js.map +0 -1
  93. package/dist/keepkey.d.ts.map +0 -1
  94. package/dist/keepkey.js +0 -1027
  95. package/dist/keepkey.js.map +0 -1
  96. package/dist/mayachain.d.ts.map +0 -1
  97. package/dist/mayachain.js +0 -180
  98. package/dist/mayachain.js.map +0 -1
  99. package/dist/osmosis.d.ts.map +0 -1
  100. package/dist/osmosis.js +0 -278
  101. package/dist/osmosis.js.map +0 -1
  102. package/dist/ripple.d.ts.map +0 -1
  103. package/dist/ripple.js +0 -111
  104. package/dist/ripple.js.map +0 -1
  105. package/dist/thorchain.d.ts.map +0 -1
  106. package/dist/thorchain.js +0 -180
  107. package/dist/thorchain.js.map +0 -1
  108. package/dist/transport.d.ts.map +0 -1
  109. package/dist/transport.js +0 -365
  110. package/dist/transport.js.map +0 -1
  111. package/dist/typeRegistry.d.ts.map +0 -1
  112. package/dist/typeRegistry.js.map +0 -1
  113. package/dist/utils.d.ts.map +0 -1
  114. package/dist/utils.js.map +0 -1
@@ -0,0 +1,549 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.btcGetAccountPaths = exports.btcVerifyMessage = exports.btcSignMessage = exports.btcSupportsNativeShapeShift = exports.btcSupportsSecureTransfer = exports.btcSignTx = exports.btcGetAddress = exports.btcSupportsScriptType = exports.btcSupportsCoin = void 0;
30
+ const Messages = __importStar(require("@keepkey/device-protocol/lib/messages_pb"));
31
+ const Types = __importStar(require("@keepkey/device-protocol/lib/types_pb"));
32
+ const bitcoinjs = __importStar(require("@shapeshiftoss/bitcoinjs-lib"));
33
+ const core = __importStar(require("@shapeshiftoss/hdwallet-core"));
34
+ const assert_1 = __importDefault(require("assert"));
35
+ const icepick_1 = require("icepick");
36
+ const utils_1 = require("./utils");
37
+ // FIXME: load this from the device's coin table, or from some static features
38
+ // table... instead of, you know, adding another God-forsaken coin table.
39
+ // :facepalm:
40
+ const supportedCoins = [
41
+ 'Bitcoin',
42
+ 'Testnet',
43
+ 'BitcoinCash',
44
+ 'BitcoinGold',
45
+ 'Litecoin',
46
+ 'Dash',
47
+ 'DigiByte',
48
+ 'Dogecoin',
49
+ ];
50
+ const segwitCoins = ['Bitcoin', 'Testnet', 'BitcoinGold', 'Litecoin'];
51
+ function legacyAccount(coin, slip44, accountIdx) {
52
+ return {
53
+ coin,
54
+ scriptType: core.BTCInputScriptType.SpendAddress,
55
+ addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + accountIdx],
56
+ };
57
+ }
58
+ function segwitAccount(coin, slip44, accountIdx) {
59
+ return {
60
+ coin,
61
+ scriptType: core.BTCInputScriptType.SpendP2SHWitness,
62
+ addressNList: [0x80000000 + 49, 0x80000000 + slip44, 0x80000000 + accountIdx],
63
+ };
64
+ }
65
+ function segwitNativeAccount(coin, slip44, accountIdx) {
66
+ return {
67
+ coin,
68
+ scriptType: core.BTCInputScriptType.SpendWitness,
69
+ addressNList: [0x80000000 + 84, 0x80000000 + slip44, 0x80000000 + accountIdx],
70
+ };
71
+ }
72
+ function packVarint(n) {
73
+ if (n < 253)
74
+ return n.toString(16).padStart(2, '0');
75
+ else if (n < 0xffff)
76
+ return 'FD' + n.toString(16).padStart(4, '0');
77
+ else if (n < 0xffffffff)
78
+ return 'FE' + n.toString(16).padStart(8, '0');
79
+ else
80
+ return 'FF' + n.toString(16).padStart(16, '0');
81
+ }
82
+ function prepareSignTx(coin, inputs, outputs) {
83
+ const unsignedTx = new Types.TransactionType();
84
+ unsignedTx.setInputsCnt(inputs.length);
85
+ unsignedTx.setOutputsCnt(outputs.length);
86
+ inputs.forEach((input, i) => {
87
+ const utxo = new Types.TxInputType();
88
+ utxo.setPrevHash(core.fromHexString(input.txid));
89
+ utxo.setPrevIndex(input.vout);
90
+ if (input.sequence !== undefined)
91
+ utxo.setSequence(input.sequence);
92
+ utxo.setScriptType((0, utils_1.translateInputScriptType)(input.scriptType));
93
+ utxo.setAddressNList(input.addressNList);
94
+ utxo.setAmount(Number(input.amount));
95
+ unsignedTx.addInputs(utxo, i);
96
+ });
97
+ outputs.forEach((o, k) => {
98
+ const output = o;
99
+ const newOutput = new Types.TxOutputType();
100
+ newOutput.setAmount(Number(output.amount));
101
+ // map to BCH address format
102
+ if (coin === 'BitcoinCash') {
103
+ if (output.address && !output.address.startsWith('bitcoincash:')) {
104
+ output.address = 'bitcoincash:' + output.address;
105
+ }
106
+ }
107
+ if (output.isChange || output.addressType === core.BTCOutputAddressType.Transfer) {
108
+ // BTCSignTxOutputTranfer || BTCSignTxOutputChange
109
+ newOutput.setScriptType((0, utils_1.translateOutputScriptType)(output.scriptType));
110
+ newOutput.setAddressNList(output.addressNList);
111
+ newOutput.setAddressType(output.isChange ? Types.OutputAddressType.CHANGE : Types.OutputAddressType.TRANSFER);
112
+ }
113
+ else if (output.opReturnData !== undefined && output.opReturnData !== null) {
114
+ // BTCSignTxOutputMemo
115
+ newOutput.setScriptType(Types.OutputScriptType.PAYTOOPRETURN);
116
+ newOutput.setAddressType(Types.OutputAddressType.SPEND);
117
+ newOutput.setOpReturnData(output.opReturnData);
118
+ }
119
+ else {
120
+ // BTCSignTxOutputSpend
121
+ newOutput.setScriptType(Types.OutputScriptType.PAYTOADDRESS);
122
+ (0, assert_1.default)(output.address !== undefined, 'Output must have a valid BTC address.');
123
+ newOutput.setAddress(output.address);
124
+ newOutput.setAddressType(Types.OutputAddressType.SPEND);
125
+ }
126
+ unsignedTx.addOutputs(newOutput, k);
127
+ });
128
+ const txmap = {}; // Create a map of transactions by txid needed for the KeepKey signing flow.
129
+ txmap['unsigned'] = unsignedTx;
130
+ const forceBip143Coins = ['BitcoinGold', 'BitcoinCash', 'BitcoinSV'];
131
+ if (forceBip143Coins.includes(coin))
132
+ return txmap;
133
+ inputs.forEach(inputTx => {
134
+ if (inputTx.txid in txmap)
135
+ return;
136
+ if (inputTx.scriptType === core.BTCInputScriptType.SpendP2SHWitness ||
137
+ inputTx.scriptType === core.BTCInputScriptType.SpendWitness ||
138
+ inputTx.scriptType === core.BTCInputScriptType.External)
139
+ return;
140
+ const prevTx = (() => {
141
+ if (inputTx.tx)
142
+ return inputTx.tx;
143
+ if (!inputTx.hex)
144
+ throw new Error('non-segwit inputs must have the associated prev tx');
145
+ const tx = bitcoinjs.Transaction.fromHex(inputTx.hex);
146
+ return {
147
+ version: tx.version,
148
+ locktime: tx.locktime,
149
+ vin: tx.ins.map(input => ({
150
+ txid: Buffer.from(input.hash).reverse().toString('hex'),
151
+ vout: input.index,
152
+ scriptSig: {
153
+ hex: Buffer.from(input.script).toString('hex'),
154
+ },
155
+ sequence: input.sequence,
156
+ })),
157
+ vout: tx.outs.map(output => ({
158
+ value: String(output.value),
159
+ scriptPubKey: {
160
+ hex: Buffer.from(output.script).toString('hex'),
161
+ },
162
+ })),
163
+ };
164
+ })();
165
+ const tx = new Types.TransactionType();
166
+ tx.setVersion(prevTx.version);
167
+ tx.setLockTime(prevTx.locktime);
168
+ tx.setInputsCnt(prevTx.vin.length);
169
+ tx.setOutputsCnt(prevTx.vout.length);
170
+ prevTx.vin.forEach((vin, i) => {
171
+ const txInput = new Types.TxInputType();
172
+ if ('coinbase' in vin) {
173
+ txInput.setPrevHash(core.fromHexString('\0'.repeat(64)));
174
+ txInput.setPrevIndex(0xffffffff);
175
+ txInput.setScriptSig(core.fromHexString(core.mustBeDefined(vin.coinbase)));
176
+ txInput.setSequence(vin.sequence);
177
+ }
178
+ else {
179
+ txInput.setPrevHash(core.fromHexString(vin.txid));
180
+ txInput.setPrevIndex(vin.vout);
181
+ txInput.setScriptSig(core.fromHexString(vin.scriptSig.hex));
182
+ txInput.setSequence(vin.sequence);
183
+ }
184
+ tx.addInputs(txInput, i);
185
+ });
186
+ prevTx.vout.forEach((vout, i) => {
187
+ const txOutput = new Types.TxOutputBinType();
188
+ txOutput.setAmount(Number(vout.value));
189
+ txOutput.setScriptPubkey(core.fromHexString(vout.scriptPubKey.hex));
190
+ tx.addBinOutputs(txOutput, i);
191
+ });
192
+ if (coin === 'Dash') {
193
+ const dip2_type = prevTx.type || 0;
194
+ // DIP2 Special Tx with payload
195
+ if (prevTx.version === 3 && dip2_type !== 0) {
196
+ if (!prevTx.extraPayload)
197
+ throw new Error('Payload missing in DIP2 transaction');
198
+ tx.setExtraData(core.fromHexString(packVarint(prevTx.extraPayload.length * 2) + prevTx.extraPayload));
199
+ }
200
+ // Trezor (and therefore KeepKey) firmware doesn't understand the
201
+ // split of version and type, so let's mimic the old serialization
202
+ // format
203
+ tx.setVersion(prevTx.version | (dip2_type << 16));
204
+ }
205
+ txmap[inputTx.txid] = tx;
206
+ });
207
+ return txmap;
208
+ }
209
+ async function ensureCoinSupport(wallet, coin) {
210
+ if (!supportedCoins.includes(coin))
211
+ throw new Error(`'${coin}' not yet supported in HDWalletKeepKey`);
212
+ if (!wallet.btcSupportsCoin(coin))
213
+ throw new Error(`'${coin} is not supported in this firmware version`);
214
+ }
215
+ function validateVoutOrdering(msg) {
216
+ // From THORChain specification:
217
+ /* ignoreTx checks if we can already ignore a tx according to preset rules
218
+
219
+ we expect array of "vout" for a BTC to have this format
220
+ OP_RETURN is mandatory only on inbound tx
221
+ vout:0 is our vault
222
+ vout:1 is any any change back to themselves
223
+ vout:2 is OP_RETURN (first 80 bytes)
224
+ vout:3 is OP_RETURN (next 80 bytes)
225
+
226
+ Rules to ignore a tx are:
227
+ - vout:0 doesn't have coins (value)
228
+ - vout:0 doesn't have address
229
+ - count vouts > 4
230
+ - count vouts with coins (value) > 2
231
+ */
232
+ // Check that vout:0 contains the vault address
233
+ if (msg.outputs[0].address != msg.vaultAddress) {
234
+ return false;
235
+ }
236
+ // Check that vout:1 is change address
237
+ if (msg.outputs[1].addressType != core.BTCOutputAddressType.Change) {
238
+ return false;
239
+ }
240
+ // Check and make sure vout:2 has OP_RETURN data
241
+ if (!(msg.outputs[2] && msg.outputs[2]?.opReturnData)) {
242
+ return false;
243
+ }
244
+ return true;
245
+ }
246
+ async function btcSupportsCoin(coin) {
247
+ // FIXME: inspect the CoinTable to determine which coins are actually supported by the device.
248
+ return supportedCoins.includes(coin);
249
+ }
250
+ exports.btcSupportsCoin = btcSupportsCoin;
251
+ async function btcSupportsScriptType(coin, scriptType) {
252
+ if (!supportedCoins.includes(coin))
253
+ return false;
254
+ if (!segwitCoins.includes(coin) && scriptType === core.BTCInputScriptType.SpendP2SHWitness)
255
+ return false;
256
+ if (!segwitCoins.includes(coin) && scriptType === core.BTCInputScriptType.SpendWitness)
257
+ return false;
258
+ return true;
259
+ }
260
+ exports.btcSupportsScriptType = btcSupportsScriptType;
261
+ async function btcGetAddress(wallet, transport, msg) {
262
+ await ensureCoinSupport(wallet, msg.coin);
263
+ const addr = new Messages.GetAddress();
264
+ addr.setAddressNList(msg.addressNList);
265
+ addr.setCoinName(msg.coin);
266
+ addr.setShowDisplay(msg.showDisplay || false);
267
+ addr.setScriptType((0, utils_1.translateInputScriptType)(msg.scriptType || core.BTCInputScriptType.SpendAddress));
268
+ const response = await transport.call(Messages.MessageType.MESSAGETYPE_GETADDRESS, addr, {
269
+ msgTimeout: core.LONG_TIMEOUT,
270
+ });
271
+ if (response.message_type === core.Events.CANCEL)
272
+ throw response;
273
+ const btcAddress = response.proto;
274
+ return core.mustBeDefined(btcAddress.getAddress());
275
+ }
276
+ exports.btcGetAddress = btcGetAddress;
277
+ async function btcSignTx(wallet, transport, msgIn) {
278
+ return transport.lockDuring(async () => {
279
+ // Make a copy of the input parameter so as to not mutate the caller's data.
280
+ // Unfreezing a recursively-frozen object is nontrivial, so we leverage an existing package
281
+ const msg = (0, icepick_1.thaw)(msgIn);
282
+ msg.outputs = (0, icepick_1.thaw)(msgIn.outputs);
283
+ await ensureCoinSupport(wallet, msg.coin);
284
+ if (msg.opReturnData) {
285
+ if (msg.opReturnData.length > 80) {
286
+ throw new Error('OP_RETURN output character count is too damn high.');
287
+ }
288
+ msg.outputs.push({
289
+ addressType: core.BTCOutputAddressType.Spend,
290
+ opReturnData: Buffer.from(msg.opReturnData).toString('base64'),
291
+ amount: '0',
292
+ isChange: false,
293
+ });
294
+ }
295
+ // If this is a THORChain transaction, validate the vout ordering
296
+ if (msg.vaultAddress && !validateVoutOrdering(msg)) {
297
+ throw new Error('Improper vout ordering for BTC Thorchain transaction');
298
+ }
299
+ const txmap = prepareSignTx(msg.coin, msg.inputs, msg.outputs);
300
+ // Prepare and send initial message
301
+ const tx = new Messages.SignTx();
302
+ tx.setInputsCount(msg.inputs.length);
303
+ tx.setOutputsCount(msg.outputs.length);
304
+ tx.setCoinName(msg.coin);
305
+ if (msg.version !== undefined)
306
+ tx.setVersion(msg.version);
307
+ tx.setLockTime(msg.locktime || 0);
308
+ let responseType;
309
+ let response;
310
+ const { message_enum, proto } = await transport.call(Messages.MessageType.MESSAGETYPE_SIGNTX, tx, {
311
+ msgTimeout: core.LONG_TIMEOUT,
312
+ omitLock: true,
313
+ }); // 5 Minute timeout
314
+ responseType = message_enum;
315
+ response = proto;
316
+ // Prepare structure for signatures
317
+ const signatures = new Array(msg.inputs.length).fill(null);
318
+ let serializedTx = '';
319
+ try {
320
+ // Begin callback loop
321
+ // eslint-disable-next-line no-constant-condition
322
+ while (true) {
323
+ if (responseType !== Messages.MessageType.MESSAGETYPE_TXREQUEST) {
324
+ throw new Error(`Unexpected message type: ${responseType}`);
325
+ }
326
+ const txRequest = response;
327
+ // If there's some part of signed transaction, add it
328
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
329
+ if (txRequest.hasSerialized() && txRequest.getSerialized().hasSerializedTx()) {
330
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
331
+ serializedTx += core.toHexString(txRequest.getSerialized().getSerializedTx_asU8());
332
+ }
333
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
334
+ if (txRequest.hasSerialized() && txRequest.getSerialized().hasSignatureIndex()) {
335
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
336
+ const sigIdx = txRequest.getSerialized().getSignatureIndex();
337
+ if (signatures[sigIdx] !== null) {
338
+ throw new Error(`Signature for index ${sigIdx} already filled`);
339
+ }
340
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
341
+ signatures[sigIdx] = core.toHexString(txRequest.getSerialized().getSignature_asU8());
342
+ }
343
+ if (txRequest.getRequestType() === Types.RequestType.TXFINISHED) {
344
+ // Device didn't ask for more information, finish workflow
345
+ break;
346
+ }
347
+ let currentTx;
348
+ let currentMsg;
349
+ let txAck;
350
+ // Device asked for one more information, let's process it.
351
+ if (!txRequest.hasDetails())
352
+ throw new Error('expected details');
353
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
354
+ const reqDetails = txRequest.getDetails();
355
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
356
+ if (!reqDetails.hasTxHash()) {
357
+ currentTx = txmap['unsigned'];
358
+ }
359
+ else {
360
+ currentTx = txmap[core.toHexString(reqDetails.getTxHash_asU8())];
361
+ }
362
+ if (txRequest.getRequestType() === Types.RequestType.TXMETA) {
363
+ currentMsg = new Types.TransactionType();
364
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
365
+ if (currentTx.hasVersion())
366
+ currentMsg.setVersion(currentTx.getVersion());
367
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
368
+ if (currentTx.hasLockTime())
369
+ currentMsg.setLockTime(currentTx.getLockTime());
370
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
371
+ if (currentTx.hasInputsCnt())
372
+ currentMsg.setInputsCnt(currentTx.getInputsCnt());
373
+ if (reqDetails.hasTxHash()) {
374
+ currentMsg.setOutputsCnt(currentTx.getBinOutputsList().length);
375
+ }
376
+ else {
377
+ currentMsg.setOutputsCnt(currentTx.getOutputsList().length);
378
+ }
379
+ if (currentTx.hasExtraData()) {
380
+ currentMsg.setExtraDataLen(currentTx.getExtraData_asU8().length);
381
+ }
382
+ else {
383
+ currentMsg.setExtraDataLen(0);
384
+ }
385
+ txAck = new Messages.TxAck();
386
+ txAck.setTx(currentMsg);
387
+ const message = await transport.call(Messages.MessageType.MESSAGETYPE_TXACK, txAck, {
388
+ msgTimeout: core.LONG_TIMEOUT,
389
+ omitLock: true,
390
+ }); // 5 Minute timeout
391
+ responseType = message.message_enum;
392
+ response = message.proto;
393
+ continue;
394
+ }
395
+ if (txRequest.getRequestType() === Types.RequestType.TXINPUT) {
396
+ if (!reqDetails.hasRequestIndex())
397
+ throw new Error('expected request index');
398
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
399
+ const reqIndex = reqDetails.getRequestIndex();
400
+ currentMsg = new Types.TransactionType();
401
+ currentMsg.setInputsList([currentTx.getInputsList()[reqIndex]]);
402
+ txAck = new Messages.TxAck();
403
+ txAck.setTx(currentMsg);
404
+ const message = await transport.call(Messages.MessageType.MESSAGETYPE_TXACK, txAck, {
405
+ msgTimeout: core.LONG_TIMEOUT,
406
+ omitLock: true,
407
+ }); // 5 Minute timeout
408
+ responseType = message.message_enum;
409
+ response = message.proto;
410
+ continue;
411
+ }
412
+ if (txRequest.getRequestType() === Types.RequestType.TXOUTPUT) {
413
+ if (!reqDetails.hasRequestIndex())
414
+ throw new Error('expected request index');
415
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
416
+ const reqIndex = reqDetails.getRequestIndex();
417
+ currentMsg = new Types.TransactionType();
418
+ if (reqDetails.hasTxHash()) {
419
+ currentMsg.setBinOutputsList([currentTx.getBinOutputsList()[reqIndex]]);
420
+ }
421
+ else {
422
+ currentMsg.setOutputsList([currentTx.getOutputsList()[reqIndex]]);
423
+ currentMsg.setOutputsCnt(1);
424
+ }
425
+ txAck = new Messages.TxAck();
426
+ txAck.setTx(currentMsg);
427
+ const message = await transport.call(Messages.MessageType.MESSAGETYPE_TXACK, txAck, {
428
+ msgTimeout: core.LONG_TIMEOUT,
429
+ omitLock: true,
430
+ }); // 5 Minute timeout
431
+ responseType = message.message_enum;
432
+ response = message.proto;
433
+ continue;
434
+ }
435
+ if (txRequest.getRequestType() === Types.RequestType.TXEXTRADATA) {
436
+ if (!reqDetails.hasExtraDataOffset() || !reqDetails.hasExtraDataLen())
437
+ throw new Error('missing extra data offset and length');
438
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
439
+ const offset = reqDetails.getExtraDataOffset();
440
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
441
+ const length = reqDetails.getExtraDataLen();
442
+ currentMsg = new Types.TransactionType();
443
+ currentMsg.setExtraData(currentTx.getExtraData_asU8().slice(offset, offset + length));
444
+ txAck = new Messages.TxAck();
445
+ txAck.setTx(currentMsg);
446
+ const message = await transport.call(Messages.MessageType.MESSAGETYPE_TXACK, txAck, {
447
+ msgTimeout: core.LONG_TIMEOUT,
448
+ omitLock: true,
449
+ }); // 5 Minute timeout
450
+ responseType = message.message_enum;
451
+ response = message.proto;
452
+ continue;
453
+ }
454
+ }
455
+ }
456
+ catch (error) {
457
+ console.error({ error });
458
+ throw new Error('Failed to sign BTC transaction');
459
+ }
460
+ if (signatures.includes(null)) {
461
+ throw new Error('Some signatures are missing!');
462
+ }
463
+ return {
464
+ signatures: signatures,
465
+ serializedTx,
466
+ };
467
+ });
468
+ }
469
+ exports.btcSignTx = btcSignTx;
470
+ async function btcSupportsSecureTransfer() {
471
+ return true;
472
+ }
473
+ exports.btcSupportsSecureTransfer = btcSupportsSecureTransfer;
474
+ function btcSupportsNativeShapeShift() {
475
+ return true;
476
+ }
477
+ exports.btcSupportsNativeShapeShift = btcSupportsNativeShapeShift;
478
+ async function btcSignMessage(wallet, transport, msg) {
479
+ await ensureCoinSupport(wallet, msg.coin);
480
+ const sign = new Messages.SignMessage();
481
+ sign.setAddressNList(msg.addressNList);
482
+ sign.setMessage((0, utils_1.toUTF8Array)(msg.message));
483
+ sign.setCoinName(msg.coin || 'Bitcoin');
484
+ sign.setScriptType((0, utils_1.translateInputScriptType)(msg.scriptType ?? core.BTCInputScriptType.SpendAddress));
485
+ const event = await transport.call(Messages.MessageType.MESSAGETYPE_SIGNMESSAGE, sign, {
486
+ msgTimeout: core.LONG_TIMEOUT,
487
+ });
488
+ const messageSignature = event.proto;
489
+ const address = messageSignature.getAddress();
490
+ if (!address)
491
+ throw new Error('btcSignMessage failed');
492
+ return {
493
+ address,
494
+ signature: core.toHexString(messageSignature.getSignature_asU8()),
495
+ };
496
+ }
497
+ exports.btcSignMessage = btcSignMessage;
498
+ async function btcVerifyMessage(wallet, transport, msg) {
499
+ await ensureCoinSupport(wallet, msg.coin);
500
+ const verify = new Messages.VerifyMessage();
501
+ verify.setAddress(msg.address);
502
+ verify.setSignature(core.arrayify('0x' + msg.signature));
503
+ verify.setMessage((0, utils_1.toUTF8Array)(msg.message));
504
+ verify.setCoinName(msg.coin);
505
+ let event;
506
+ try {
507
+ event = await transport.call(Messages.MessageType.MESSAGETYPE_VERIFYMESSAGE, verify);
508
+ }
509
+ catch (e) {
510
+ if (core.isIndexable(e) && e.message_enum === Messages.MessageType.MESSAGETYPE_FAILURE) {
511
+ return false;
512
+ }
513
+ throw e;
514
+ }
515
+ const success = event.proto;
516
+ return success.getMessage() === 'Message verified';
517
+ }
518
+ exports.btcVerifyMessage = btcVerifyMessage;
519
+ function btcGetAccountPaths(msg) {
520
+ const slip44 = core.slip44ByCoin(msg.coin);
521
+ if (slip44 === undefined)
522
+ return [];
523
+ const bip44 = legacyAccount(msg.coin, slip44, msg.accountIdx);
524
+ const bip49 = segwitAccount(msg.coin, slip44, msg.accountIdx);
525
+ const bip84 = segwitNativeAccount(msg.coin, slip44, msg.accountIdx);
526
+ // For BTC Forks
527
+ const btcLegacy = legacyAccount(msg.coin, core.slip44ByCoin('Bitcoin'), msg.accountIdx);
528
+ const btcSegwit = segwitAccount(msg.coin, core.slip44ByCoin('Bitcoin'), msg.accountIdx);
529
+ const btcSegwitNative = segwitNativeAccount(msg.coin, core.slip44ByCoin('Bitcoin'), msg.accountIdx);
530
+ // For BCH Forks
531
+ const bchLegacy = legacyAccount(msg.coin, core.slip44ByCoin('BitcoinCash'), msg.accountIdx);
532
+ let paths = {
533
+ Bitcoin: [bip44, bip49, bip84],
534
+ Litecoin: [bip44, bip49, bip84],
535
+ Dash: [bip44],
536
+ DigiByte: [bip44, bip49, bip84],
537
+ Dogecoin: [bip44],
538
+ Testnet: [bip44, bip49, bip84],
539
+ BitcoinCash: [bip44, btcLegacy],
540
+ BitcoinSV: [bip44, bchLegacy, btcLegacy],
541
+ BitcoinGold: [bip44, bip49, bip84, btcLegacy, btcSegwit, btcSegwitNative],
542
+ }[msg.coin] ?? [];
543
+ if (msg.scriptType !== undefined)
544
+ paths = paths.filter(path => {
545
+ return path.scriptType === msg.scriptType;
546
+ });
547
+ return paths;
548
+ }
549
+ exports.btcGetAccountPaths = btcGetAccountPaths;
@@ -1,4 +1,6 @@
1
- import * as core from "@shapeshiftoss/hdwallet-core";
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import type * as core from '@shapeshiftoss/hdwallet-core';
2
4
  export declare function decodeBnbTx(txBytes: Buffer, chainId: string): {
3
5
  signBytes: string;
4
6
  signBytesHash: string;
@@ -7,4 +9,3 @@ export declare function decodeBnbTx(txBytes: Buffer, chainId: string): {
7
9
  };
8
10
  export declare function validateBnbTx(txBytes: Buffer, chainId: string): boolean;
9
11
  export declare function encodeBnbTx(unsignedTx: core.BinanceTx, publicKey: Buffer, signature: Buffer): Buffer;
10
- //# sourceMappingURL=bnbencoding.d.ts.map
@@ -26,20 +26,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.decodeBnbTx = decodeBnbTx;
30
- exports.validateBnbTx = validateBnbTx;
31
- exports.encodeBnbTx = encodeBnbTx;
29
+ exports.encodeBnbTx = exports.validateBnbTx = exports.decodeBnbTx = void 0;
32
30
  const secp256k1_1 = __importDefault(require("@bitcoinerlab/secp256k1"));
33
31
  const bnbSdk = __importStar(require("bnb-javascript-sdk-nobroadcast"));
34
32
  const crypto_js_1 = __importDefault(require("crypto-js"));
35
33
  function decodeBnbTx(txBytes, chainId) {
36
34
  const txDecoded = bnbSdk.amino.decoder.unMarshalBinaryLengthPrefixed(txBytes, {
37
- aminoPrefix: "f0625dee",
35
+ aminoPrefix: 'f0625dee',
38
36
  msgs: [
39
37
  {
40
- aminoPrefix: "2a2c87fa",
41
- inputs: [{ address: Buffer.alloc(0), coins: [{ denom: "", amount: 0 }] }],
42
- outputs: [{ address: Buffer.alloc(0), coins: [{ denom: "", amount: 0 }] }],
38
+ aminoPrefix: '2a2c87fa',
39
+ inputs: [{ address: Buffer.alloc(0), coins: [{ denom: '', amount: 0 }] }],
40
+ outputs: [{ address: Buffer.alloc(0), coins: [{ denom: '', amount: 0 }] }],
43
41
  },
44
42
  ],
45
43
  signatures: [
@@ -50,16 +48,16 @@ function decodeBnbTx(txBytes, chainId) {
50
48
  sequence: 0,
51
49
  },
52
50
  ],
53
- memo: "",
51
+ memo: '',
54
52
  source: 0,
55
53
  data: Buffer.alloc(0),
56
54
  }).val;
57
55
  if (txDecoded.data !== null)
58
- throw new Error("bad data length");
56
+ throw new Error('bad data length');
59
57
  if (txDecoded.msgs.length !== 1)
60
- throw new Error("bad msgs length");
58
+ throw new Error('bad msgs length');
61
59
  if (txDecoded.signatures.length !== 1)
62
- throw new Error("bad signatures length");
60
+ throw new Error('bad signatures length');
63
61
  const signBytes = JSON.stringify({
64
62
  account_number: String(txDecoded.signatures[0].accountNumber),
65
63
  chain_id: chainId,
@@ -68,14 +66,14 @@ function decodeBnbTx(txBytes, chainId) {
68
66
  msgs: [
69
67
  {
70
68
  inputs: txDecoded.msgs[0].inputs.map((x) => ({
71
- address: bnbSdk.crypto.encodeAddress(x.address, "bnb"),
69
+ address: bnbSdk.crypto.encodeAddress(x.address, 'bnb'),
72
70
  coins: x.coins.map((y) => ({
73
71
  amount: Number(y.amount),
74
72
  denom: y.denom,
75
73
  })),
76
74
  })),
77
75
  outputs: txDecoded.msgs[0].outputs.map((x) => ({
78
- address: bnbSdk.crypto.encodeAddress(x.address, "bnb"),
76
+ address: bnbSdk.crypto.encodeAddress(x.address, 'bnb'),
79
77
  coins: x.coins.map((y) => ({
80
78
  amount: Number(y.amount),
81
79
  denom: y.denom,
@@ -89,17 +87,19 @@ function decodeBnbTx(txBytes, chainId) {
89
87
  const signBytesHash = crypto_js_1.default.SHA256(crypto_js_1.default.enc.Utf8.parse(signBytes)).toString();
90
88
  const pubKeyAmino = Buffer.from(txDecoded.signatures[0].pubKey);
91
89
  if (pubKeyAmino.readUInt32BE(0) !== 0xeb5ae987)
92
- throw new Error("bad pubkey aminoPrefix");
90
+ throw new Error('bad pubkey aminoPrefix');
93
91
  if (pubKeyAmino.readUInt8(4) !== 33)
94
- throw new Error("bad pubKey length");
92
+ throw new Error('bad pubKey length');
95
93
  const pubKey = pubKeyAmino.slice(5);
96
94
  const signature = txDecoded.signatures[0].signature;
97
95
  return { signBytes, signBytesHash, pubKey, signature };
98
96
  }
97
+ exports.decodeBnbTx = decodeBnbTx;
99
98
  function validateBnbTx(txBytes, chainId) {
100
99
  const { signBytesHash, pubKey, signature } = decodeBnbTx(txBytes, chainId);
101
- return secp256k1_1.default.verify(Buffer.from(signBytesHash, "hex"), pubKey, signature);
100
+ return secp256k1_1.default.verify(Buffer.from(signBytesHash, 'hex'), pubKey, signature);
102
101
  }
102
+ exports.validateBnbTx = validateBnbTx;
103
103
  function encodeBnbTx(unsignedTx, publicKey, signature) {
104
104
  const { account_number, chain_id, sequence, source } = unsignedTx;
105
105
  const msg = unsignedTx.msgs[0];
@@ -115,21 +115,21 @@ function encodeBnbTx(unsignedTx, publicKey, signature) {
115
115
  const baseMsg = {
116
116
  inputs: msg.inputs.map(msgNormalizer),
117
117
  outputs: msg.outputs.map(msgNormalizer),
118
- aminoPrefix: "2A2C87FA",
118
+ aminoPrefix: '2A2C87FA',
119
119
  };
120
120
  const tx = new bnbSdk.Transaction(Object.assign({}, unsignedTx, {
121
121
  chainId: chain_id,
122
122
  accountNumber: Number(account_number),
123
- source: Number(source !== null && source !== void 0 ? source : 0),
123
+ source: Number(source ?? 0),
124
124
  sequence: Number(sequence),
125
125
  // A bug in the binance SDK makes this field required, even though it shouldn't be.
126
126
  baseMsg: { getMsg: () => baseMsg, getBaseMsg: () => baseMsg, getSignMsg: () => baseMsg },
127
127
  }));
128
- const ecPubKey = bnbSdk.crypto.getPublicKey(Buffer.from(publicKey).toString("hex"));
128
+ const ecPubKey = bnbSdk.crypto.getPublicKey(Buffer.from(publicKey).toString('hex'));
129
129
  tx.addSignature(ecPubKey, signature);
130
- const serializedTx = Buffer.from(tx.serialize(), "hex");
130
+ const serializedTx = Buffer.from(tx.serialize(), 'hex');
131
131
  if (!validateBnbTx(serializedTx, chain_id))
132
- throw new Error("serialized tx did not validate");
132
+ throw new Error('serialized tx did not validate');
133
133
  return serializedTx;
134
134
  }
135
- //# sourceMappingURL=bnbencoding.js.map
135
+ exports.encodeBnbTx = encodeBnbTx;