@exodus/hw-ledger 3.9.2 → 4.0.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.
- package/CHANGELOG.md +14 -0
- package/lib/atoms/index.d.ts +3 -3
- package/lib/atoms/index.js +7 -10
- package/lib/index.d.ts +5 -5
- package/lib/index.js +9 -14
- package/lib/module/assets/applications.js +1 -3
- package/lib/module/assets/basemainnet.d.ts +1 -1
- package/lib/module/assets/basemainnet.js +5 -10
- package/lib/module/assets/bitcoin.d.ts +1 -1
- package/lib/module/assets/bitcoin.js +31 -36
- package/lib/module/assets/ethereum.d.ts +1 -1
- package/lib/module/assets/ethereum.js +31 -64
- package/lib/module/assets/index.d.ts +1 -1
- package/lib/module/assets/index.js +22 -28
- package/lib/module/assets/matic.d.ts +1 -1
- package/lib/module/assets/matic.js +5 -10
- package/lib/module/assets/ripple.d.ts +1 -1
- package/lib/module/assets/ripple.js +13 -17
- package/lib/module/assets/solana.d.ts +1 -1
- package/lib/module/assets/solana.js +16 -19
- package/lib/module/assets/tronmainnet.d.ts +1 -1
- package/lib/module/assets/tronmainnet.js +14 -50
- package/lib/module/assets/utils/bip322.js +7 -43
- package/lib/module/assets/utils/derivation-paths.js +17 -28
- package/lib/module/assets/utils/index.js +3 -19
- package/lib/module/assets/utils/psbt.js +34 -46
- package/lib/module/assets/utils/xpub.js +3 -6
- package/lib/module/constants.js +1 -4
- package/lib/module/device.d.ts +1 -1
- package/lib/module/device.js +21 -28
- package/lib/module/discovery.js +14 -18
- package/lib/module/errors.js +5 -12
- package/lib/module/index.js +2 -23
- package/lib/module/management/application.d.ts +2 -2
- package/lib/module/management/application.js +1 -4
- package/lib/module/types.d.ts +3 -2
- package/lib/module/types.js +1 -2
- package/lib/plugin/index.js +4 -6
- package/lib/redux/id.js +1 -3
- package/lib/redux/index.js +7 -12
- package/lib/redux/initial-state.js +1 -3
- package/lib/redux/selectors/bluetoothScanning.js +3 -5
- package/lib/redux/selectors/bluetoothStatus.js +3 -5
- package/lib/redux/selectors/index.js +4 -9
- package/package.json +13 -5
|
@@ -1,28 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const minimalistic_assert_1 = __importDefault(require("minimalistic-assert"));
|
|
8
|
-
const hw_common_1 = require("@exodus/hw-common");
|
|
9
|
-
const ripple_binary_codec_1 = __importDefault(require("@exodus/ripple-binary-codec"));
|
|
10
|
-
const applications_js_1 = __importDefault(require("./applications.js"));
|
|
1
|
+
import AppXrpImport from '@ledgerhq/hw-app-xrp';
|
|
2
|
+
import assert from 'minimalistic-assert';
|
|
3
|
+
import { XPubUnsupportedError, SignMessageUnsupportedError } from '@exodus/hw-common';
|
|
4
|
+
import binaryCodec from '@exodus/ripple-binary-codec';
|
|
5
|
+
import applications from './applications.js';
|
|
6
|
+
const AppXrp = (AppXrpImport.default ?? AppXrpImport);
|
|
11
7
|
async function createHandler(transport) {
|
|
12
|
-
const app = new
|
|
8
|
+
const app = new AppXrp(transport);
|
|
13
9
|
const getAddress = async (params) => {
|
|
14
10
|
const { address } = await app.getAddress(params.derivationPath.replace('m/', ''));
|
|
15
11
|
return address;
|
|
16
12
|
};
|
|
17
13
|
const getXPub = async () => {
|
|
18
|
-
throw new
|
|
14
|
+
throw new XPubUnsupportedError();
|
|
19
15
|
};
|
|
20
16
|
const getPublicKey = async (params) => {
|
|
21
17
|
const { publicKey } = await app.getAddress(params.derivationPath.replace('m/', ''));
|
|
22
18
|
return Buffer.from(publicKey, 'hex');
|
|
23
19
|
};
|
|
24
20
|
const signTransaction = async (params) => {
|
|
25
|
-
(
|
|
21
|
+
assert(Array.isArray(params.derivationPaths) && params.derivationPaths.length === 1, 'derivationsPath array must be one element long');
|
|
26
22
|
const { txData } = params.signableTransaction;
|
|
27
23
|
const derivationPath = params.derivationPaths[0].replace('m/', '');
|
|
28
24
|
const { address, publicKey } = await app.getAddress(derivationPath);
|
|
@@ -31,7 +27,7 @@ async function createHandler(transport) {
|
|
|
31
27
|
Account: address,
|
|
32
28
|
SigningPubKey: publicKey.toUpperCase(),
|
|
33
29
|
};
|
|
34
|
-
const encoded =
|
|
30
|
+
const encoded = binaryCodec.encode(txForSigning);
|
|
35
31
|
const signature = await app.signTransaction(derivationPath, encoded);
|
|
36
32
|
return [
|
|
37
33
|
{
|
|
@@ -41,7 +37,7 @@ async function createHandler(transport) {
|
|
|
41
37
|
];
|
|
42
38
|
};
|
|
43
39
|
const signMessage = async () => {
|
|
44
|
-
throw new
|
|
40
|
+
throw new SignMessageUnsupportedError();
|
|
45
41
|
};
|
|
46
42
|
return {
|
|
47
43
|
getAddress,
|
|
@@ -52,7 +48,7 @@ async function createHandler(transport) {
|
|
|
52
48
|
};
|
|
53
49
|
}
|
|
54
50
|
const metadata = {
|
|
55
|
-
applications: [
|
|
51
|
+
applications: [applications.XRP],
|
|
56
52
|
handler: createHandler,
|
|
57
53
|
};
|
|
58
|
-
|
|
54
|
+
export default metadata;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type Transport from '@ledgerhq/hw-transport';
|
|
2
1
|
import type { HardwareWalletAssetHandler } from '@exodus/hw-common';
|
|
2
|
+
import type { Transport } from '../types.js';
|
|
3
3
|
declare function createHandler(transport: Transport): Promise<HardwareWalletAssetHandler>;
|
|
4
4
|
declare const metadata: {
|
|
5
5
|
applications: {
|
|
@@ -1,29 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
const hw_common_1 = require("@exodus/hw-common");
|
|
10
|
-
const errors_js_1 = require("../errors.js");
|
|
11
|
-
const applications_js_1 = __importDefault(require("./applications.js"));
|
|
1
|
+
import AppSolanaImport from '@ledgerhq/hw-app-solana';
|
|
2
|
+
import assert from 'minimalistic-assert';
|
|
3
|
+
import { toBase58 } from '@exodus/bytes/base58.js';
|
|
4
|
+
import { XPubUnsupportedError } from '@exodus/hw-common';
|
|
5
|
+
import { RequiresBlindSigningError } from '../errors.js';
|
|
6
|
+
import applications from './applications.js';
|
|
7
|
+
const AppSolana = (AppSolanaImport.default ??
|
|
8
|
+
AppSolanaImport);
|
|
12
9
|
async function createHandler(transport) {
|
|
13
|
-
const app = new
|
|
10
|
+
const app = new AppSolana(transport);
|
|
14
11
|
const getAddress = async (params) => {
|
|
15
12
|
const { address } = await app.getAddress(params.derivationPath.replace('m/', ''));
|
|
16
|
-
return
|
|
13
|
+
return toBase58(address);
|
|
17
14
|
};
|
|
18
15
|
const getXPub = async (params) => {
|
|
19
|
-
throw new
|
|
16
|
+
throw new XPubUnsupportedError();
|
|
20
17
|
};
|
|
21
18
|
const getPublicKey = async (params) => {
|
|
22
19
|
const { address } = await app.getAddress(params.derivationPath.replace('m/', ''));
|
|
23
20
|
return address;
|
|
24
21
|
};
|
|
25
22
|
const signTransaction = async (params) => {
|
|
26
|
-
(
|
|
23
|
+
assert(Array.isArray(params.derivationPaths) && params.derivationPaths.length === 1, 'derivationsPath array must be one element long');
|
|
27
24
|
let serializedTransaction;
|
|
28
25
|
if (Buffer.isBuffer(params.signableTransaction)) {
|
|
29
26
|
serializedTransaction = params.signableTransaction;
|
|
@@ -41,7 +38,7 @@ async function createHandler(transport) {
|
|
|
41
38
|
.signTransaction(params.derivationPaths[0].replace('m/', ''), serializedTransaction)
|
|
42
39
|
.catch((err) => {
|
|
43
40
|
if (err.message.includes('Try enabling blind signature in the app')) {
|
|
44
|
-
throw new
|
|
41
|
+
throw new RequiresBlindSigningError();
|
|
45
42
|
}
|
|
46
43
|
else {
|
|
47
44
|
throw err;
|
|
@@ -56,7 +53,7 @@ async function createHandler(transport) {
|
|
|
56
53
|
];
|
|
57
54
|
};
|
|
58
55
|
const signMessage = async (params) => {
|
|
59
|
-
(
|
|
56
|
+
assert(Buffer.isBuffer(params.message.rawMessage), 'rawMessage must be a buffer');
|
|
60
57
|
const { signature } = await app.signOffchainMessage(params.derivationPath.replace('m/', ''), params.message.rawMessage);
|
|
61
58
|
return signature;
|
|
62
59
|
};
|
|
@@ -69,7 +66,7 @@ async function createHandler(transport) {
|
|
|
69
66
|
};
|
|
70
67
|
}
|
|
71
68
|
const metadata = {
|
|
72
|
-
applications: [
|
|
69
|
+
applications: [applications.Solana],
|
|
73
70
|
handler: createHandler,
|
|
74
71
|
};
|
|
75
|
-
|
|
72
|
+
export default metadata;
|
|
@@ -1,54 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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 () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
const hw_app_trx_1 = __importDefault(require("@ledgerhq/hw-app-trx"));
|
|
40
|
-
const minimalistic_assert_1 = __importDefault(require("minimalistic-assert"));
|
|
41
|
-
const hw_common_1 = require("@exodus/hw-common");
|
|
42
|
-
const secp256k1 = __importStar(require("@exodus/crypto/secp256k1"));
|
|
43
|
-
const applications_js_1 = __importDefault(require("./applications.js"));
|
|
1
|
+
import AppTronImport from '@ledgerhq/hw-app-trx';
|
|
2
|
+
import assert from 'minimalistic-assert';
|
|
3
|
+
import { XPubUnsupportedError } from '@exodus/hw-common';
|
|
4
|
+
import * as secp256k1 from '@exodus/crypto/secp256k1';
|
|
5
|
+
import applications from './applications.js';
|
|
6
|
+
const AppTron = (AppTronImport.default ??
|
|
7
|
+
AppTronImport);
|
|
44
8
|
async function createHandler(transport) {
|
|
45
|
-
const app = new
|
|
9
|
+
const app = new AppTron(transport);
|
|
46
10
|
const getAddress = async (params) => {
|
|
47
11
|
const { address } = await app.getAddress(params.derivationPath.replace('m/', ''));
|
|
48
12
|
return address;
|
|
49
13
|
};
|
|
50
14
|
const getXPub = async (params) => {
|
|
51
|
-
throw new
|
|
15
|
+
throw new XPubUnsupportedError();
|
|
52
16
|
};
|
|
53
17
|
const getPublicKey = async (params) => {
|
|
54
18
|
const { publicKey } = await app.getAddress(params.derivationPath.replace('m/', ''));
|
|
@@ -59,7 +23,7 @@ async function createHandler(transport) {
|
|
|
59
23
|
});
|
|
60
24
|
};
|
|
61
25
|
const signTransaction = async (params) => {
|
|
62
|
-
(
|
|
26
|
+
assert(Array.isArray(params.derivationPaths) && params.derivationPaths.length === 1, 'derivationsPath array must be one element long');
|
|
63
27
|
if (!Buffer.isBuffer(params.signableTransaction)) {
|
|
64
28
|
throw new TypeError(`signableTransaction must be Buffer or serializable to a Buffer.`);
|
|
65
29
|
}
|
|
@@ -72,7 +36,7 @@ async function createHandler(transport) {
|
|
|
72
36
|
};
|
|
73
37
|
const signMessage = async (params) => {
|
|
74
38
|
if (params.message.rawMessage) {
|
|
75
|
-
(
|
|
39
|
+
assert(Buffer.isBuffer(params.message.rawMessage), 'rawMessage must be a buffer');
|
|
76
40
|
const signature = await app.signPersonalMessage(params.derivationPath.replace('m/', ''), params.message.rawMessage.toString('hex'));
|
|
77
41
|
return Buffer.from(signature, 'hex');
|
|
78
42
|
}
|
|
@@ -80,7 +44,7 @@ async function createHandler(transport) {
|
|
|
80
44
|
throw new Error('TIP712 messages are not yet supported');
|
|
81
45
|
}
|
|
82
46
|
else {
|
|
83
|
-
(
|
|
47
|
+
assert(false, 'rawMessage or TIP712Message must be specified');
|
|
84
48
|
}
|
|
85
49
|
};
|
|
86
50
|
return {
|
|
@@ -92,7 +56,7 @@ async function createHandler(transport) {
|
|
|
92
56
|
};
|
|
93
57
|
}
|
|
94
58
|
const metadata = {
|
|
95
|
-
applications: [
|
|
59
|
+
applications: [applications.Tron],
|
|
96
60
|
handler: createHandler,
|
|
97
61
|
};
|
|
98
|
-
|
|
62
|
+
export default metadata;
|
|
@@ -1,49 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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 () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.buildBip322PSBT = buildBip322PSBT;
|
|
37
|
-
const bitcoin = __importStar(require("@exodus/bitcoinjs"));
|
|
38
|
-
const bip322_js_1 = require("@exodus/bip322-js");
|
|
39
|
-
function buildBip322PSBT(message, address) {
|
|
40
|
-
const scriptPubKey = bip322_js_1.Address.convertAdressToScriptPubkey(address);
|
|
41
|
-
const toSpendTx = bip322_js_1.BIP322.buildToSpendTx(message, scriptPubKey);
|
|
1
|
+
import * as bitcoin from '@exodus/bitcoinjs';
|
|
2
|
+
import { BIP322, Address } from '@exodus/bip322-js';
|
|
3
|
+
export function buildBip322PSBT(message, address) {
|
|
4
|
+
const scriptPubKey = Address.convertAdressToScriptPubkey(address);
|
|
5
|
+
const toSpendTx = BIP322.buildToSpendTx(message, scriptPubKey);
|
|
42
6
|
const toSpendTxId = toSpendTx.getId();
|
|
43
|
-
if (
|
|
7
|
+
if (Address.isP2SH(address)) {
|
|
44
8
|
throw new Error('Unable to sign BIP-322 message for unimplemented address type.');
|
|
45
9
|
}
|
|
46
|
-
else if (
|
|
10
|
+
else if (Address.isP2WPKH(address) || Address.isP2TR(address)) {
|
|
47
11
|
return buildToSignNativeSegwitOrTaproot(toSpendTxId, scriptPubKey);
|
|
48
12
|
}
|
|
49
13
|
throw new Error('Unable to sign BIP-322 message for unsupported address type.');
|
|
@@ -1,45 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.splitDerivationPath = splitDerivationPath;
|
|
7
|
-
exports.assertBip44Path = assertBip44Path;
|
|
8
|
-
exports.splitBip44DerivationPath = splitBip44DerivationPath;
|
|
9
|
-
exports.assertBip44PathNumber = assertBip44PathNumber;
|
|
10
|
-
exports.buildBip44PathFromNumber = buildBip44PathFromNumber;
|
|
11
|
-
exports.splitBip44PathToNumber = splitBip44PathToNumber;
|
|
12
|
-
const minimalistic_assert_1 = __importDefault(require("minimalistic-assert"));
|
|
13
|
-
function splitDerivationPath(derivationPath) {
|
|
14
|
-
(0, minimalistic_assert_1.default)(typeof derivationPath === 'string', 'derivationPath must be string');
|
|
1
|
+
import assert from 'minimalistic-assert';
|
|
2
|
+
export function splitDerivationPath(derivationPath) {
|
|
3
|
+
assert(typeof derivationPath === 'string', 'derivationPath must be string');
|
|
15
4
|
const parts = derivationPath.split('/');
|
|
16
|
-
(
|
|
17
|
-
(
|
|
5
|
+
assert(parts.length > 1, 'invalid derivationPath: must have length > 1');
|
|
6
|
+
assert(parts[0] === 'm', 'invalid derivationPath: must start with m');
|
|
18
7
|
return parts.slice(1);
|
|
19
8
|
}
|
|
20
|
-
function assertBip44Path(parts) {
|
|
21
|
-
(
|
|
22
|
-
(
|
|
9
|
+
export function assertBip44Path(parts) {
|
|
10
|
+
assert(parts.length === 5, 'invalid bip44 derivation path: length must be 5');
|
|
11
|
+
assert(parts.every((part) => typeof part === 'string'), 'Invalid parts');
|
|
23
12
|
}
|
|
24
|
-
function splitBip44DerivationPath(derivationPath) {
|
|
13
|
+
export function splitBip44DerivationPath(derivationPath) {
|
|
25
14
|
const parts = splitDerivationPath(derivationPath);
|
|
26
15
|
assertBip44Path(parts);
|
|
27
16
|
const [purpose, coin, account, change, address] = parts;
|
|
28
|
-
(
|
|
29
|
-
(
|
|
30
|
-
(
|
|
17
|
+
assert(purpose.endsWith("'"), 'invalid derivationPath: purpose must be hardened');
|
|
18
|
+
assert(coin.endsWith("'"), 'invalid derivationPath: coin must be hardened');
|
|
19
|
+
assert(account.endsWith("'"), 'invalid derivationPath: account must be hardened');
|
|
31
20
|
return [purpose, coin, account, change, address];
|
|
32
21
|
}
|
|
33
|
-
function assertBip44PathNumber(parts) {
|
|
34
|
-
(
|
|
35
|
-
(
|
|
22
|
+
export function assertBip44PathNumber(parts) {
|
|
23
|
+
assert(parts.length === 5, 'invalid bip44 derivation path: length must be 5');
|
|
24
|
+
assert(parts.every((part) => typeof part === 'number'), 'Invalid parts');
|
|
36
25
|
}
|
|
37
|
-
function buildBip44PathFromNumber(parts) {
|
|
26
|
+
export function buildBip44PathFromNumber(parts) {
|
|
38
27
|
const [purpose, coin, account, chainIndex, addressIndex] = parts;
|
|
39
28
|
const HARDENED_OFFSET = 0x80_00_00_00;
|
|
40
29
|
return `m/${purpose - HARDENED_OFFSET}'/${coin - HARDENED_OFFSET}'/${account - HARDENED_OFFSET}'/${chainIndex}/${addressIndex}`;
|
|
41
30
|
}
|
|
42
|
-
function splitBip44PathToNumber(derivationPath) {
|
|
31
|
+
export function splitBip44PathToNumber(derivationPath) {
|
|
43
32
|
const [purpose, coin, account, change, address] = splitBip44DerivationPath(derivationPath);
|
|
44
33
|
const HARDENED_OFFSET = 0x80_00_00_00;
|
|
45
34
|
return [
|
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./derivation-paths.js"), exports);
|
|
18
|
-
__exportStar(require("./xpub.js"), exports);
|
|
19
|
-
__exportStar(require("./psbt.js"), exports);
|
|
1
|
+
export * from './derivation-paths.js';
|
|
2
|
+
export * from './xpub.js';
|
|
3
|
+
export * from './psbt.js';
|
|
@@ -1,18 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
exports.getMultisigWalletPolicy = exports.getWalletPolicy = void 0;
|
|
7
|
-
exports.assertPsbtOnlyHasAllowedDerivationPaths = assertPsbtOnlyHasAllowedDerivationPaths;
|
|
8
|
-
exports.tagPsbtWithDerivationPaths = tagPsbtWithDerivationPaths;
|
|
9
|
-
exports.derivationPathsToWalletPolicy = derivationPathsToWalletPolicy;
|
|
10
|
-
exports.addDummyInputs = addDummyInputs;
|
|
11
|
-
const minimalistic_assert_1 = __importDefault(require("minimalistic-assert"));
|
|
12
|
-
const ledger_bitcoin_1 = require("@exodus/ledger-bitcoin");
|
|
13
|
-
const bitcoinjs_1 = require("@exodus/bitcoinjs");
|
|
14
|
-
const derivation_paths_js_1 = require("./derivation-paths.js");
|
|
15
|
-
function assertPsbtOnlyHasAllowedDerivationPaths(psbt, masterFingerprint, derivationPaths) {
|
|
1
|
+
import assert from 'minimalistic-assert';
|
|
2
|
+
import { DefaultWalletPolicy, WalletPolicy } from '@exodus/ledger-bitcoin';
|
|
3
|
+
import { payments, address as baddress, Transaction } from '@exodus/bitcoinjs';
|
|
4
|
+
import { buildBip44PathFromNumber, assertBip44PathNumber, splitBip44PathToNumber, splitBip44DerivationPath, } from './derivation-paths.js';
|
|
5
|
+
export function assertPsbtOnlyHasAllowedDerivationPaths(psbt, masterFingerprint, derivationPaths) {
|
|
16
6
|
for (let i = 0; i < psbt.getGlobalInputCount(); i++) {
|
|
17
7
|
const BIP32_DERIVATION = 6;
|
|
18
8
|
const TAP_BIP32_DERIVATION = 22;
|
|
@@ -36,12 +26,12 @@ function assertAllowedDerivation(bip32Derivation, masterFingerprint, derivationP
|
|
|
36
26
|
const masterFingerprintToCheck = bip32Derivation.masterFingerprint.toString('hex');
|
|
37
27
|
const isOurMasterFingerprint = masterFingerprintToCheck === masterFingerprint;
|
|
38
28
|
if (isOurMasterFingerprint) {
|
|
39
|
-
|
|
40
|
-
const derivationPath =
|
|
41
|
-
(
|
|
29
|
+
assertBip44PathNumber(bip32Derivation.path);
|
|
30
|
+
const derivationPath = buildBip44PathFromNumber(bip32Derivation.path);
|
|
31
|
+
assert(derivationPaths.includes(derivationPath), `found unsupported derivation path: ${derivationPath}`);
|
|
42
32
|
}
|
|
43
33
|
}
|
|
44
|
-
function tagPsbtWithDerivationPaths(psbt, masterFingerprint, derivationPathToPublicKeyMap, addressToDerivationPathMap) {
|
|
34
|
+
export function tagPsbtWithDerivationPaths(psbt, masterFingerprint, derivationPathToPublicKeyMap, addressToDerivationPathMap) {
|
|
45
35
|
const masterFingerprintBuffer = Buffer.from(masterFingerprint, 'hex');
|
|
46
36
|
const scriptPubKeyToDerivationPathMap = computeScriptPubKeyToDerivationPathMap(derivationPathToPublicKeyMap);
|
|
47
37
|
const derivationPathsToSignFor = [];
|
|
@@ -54,7 +44,7 @@ function tagPsbtWithDerivationPaths(psbt, masterFingerprint, derivationPathToPub
|
|
|
54
44
|
}
|
|
55
45
|
else if (nonWitnessUtxo) {
|
|
56
46
|
const prevOutputIndex = psbt.getInputOutputIndex(inputIndex);
|
|
57
|
-
const decodedTransaction =
|
|
47
|
+
const decodedTransaction = Transaction.fromBuffer(nonWitnessUtxo);
|
|
58
48
|
scriptPubKey = decodedTransaction.outs[prevOutputIndex].script;
|
|
59
49
|
}
|
|
60
50
|
else {
|
|
@@ -63,15 +53,15 @@ function tagPsbtWithDerivationPaths(psbt, masterFingerprint, derivationPathToPub
|
|
|
63
53
|
let derivationPath = scriptPubKeyToDerivationPathMap[scriptPubKey.toString('hex')];
|
|
64
54
|
if (addressToDerivationPathMap && !derivationPath) {
|
|
65
55
|
try {
|
|
66
|
-
const address =
|
|
56
|
+
const address = baddress.fromOutputScript(scriptPubKey);
|
|
67
57
|
derivationPath = addressToDerivationPathMap[address];
|
|
68
58
|
}
|
|
69
59
|
catch { }
|
|
70
60
|
}
|
|
71
61
|
if (derivationPath) {
|
|
72
62
|
const publicKey = derivationPathToPublicKeyMap[derivationPath];
|
|
73
|
-
(
|
|
74
|
-
const derivationPathNumerical =
|
|
63
|
+
assert(Buffer.isBuffer(publicKey), `no public key found for derivation path`);
|
|
64
|
+
const derivationPathNumerical = splitBip44PathToNumber(derivationPath);
|
|
75
65
|
if (isTaproot(scriptPubKey)) {
|
|
76
66
|
psbt.setInputTapBip32Derivation(inputIndex, publicKey.slice(1), [], masterFingerprintBuffer, derivationPathNumerical);
|
|
77
67
|
}
|
|
@@ -86,15 +76,15 @@ function tagPsbtWithDerivationPaths(psbt, masterFingerprint, derivationPathToPub
|
|
|
86
76
|
let derivationPath = scriptPubKeyToDerivationPathMap[scriptPubKey.toString('hex')];
|
|
87
77
|
if (addressToDerivationPathMap && !derivationPath) {
|
|
88
78
|
try {
|
|
89
|
-
const address =
|
|
79
|
+
const address = baddress.fromOutputScript(scriptPubKey);
|
|
90
80
|
derivationPath = addressToDerivationPathMap[address];
|
|
91
81
|
}
|
|
92
82
|
catch { }
|
|
93
83
|
}
|
|
94
84
|
if (derivationPath) {
|
|
95
85
|
const publicKey = derivationPathToPublicKeyMap[derivationPath];
|
|
96
|
-
(
|
|
97
|
-
const derivationPathNumerical =
|
|
86
|
+
assert(Buffer.isBuffer(publicKey), `no public key found for derivation path`);
|
|
87
|
+
const derivationPathNumerical = splitBip44PathToNumber(derivationPath);
|
|
98
88
|
if (isTaproot(scriptPubKey)) {
|
|
99
89
|
psbt.setOutputTapBip32Derivation(outputIndex, publicKey.slice(1), [], masterFingerprintBuffer, derivationPathNumerical);
|
|
100
90
|
}
|
|
@@ -108,37 +98,37 @@ function tagPsbtWithDerivationPaths(psbt, masterFingerprint, derivationPathToPub
|
|
|
108
98
|
function computeScriptPubKeyToDerivationPathMap(derivationPathToPublicKeyMap) {
|
|
109
99
|
return Object.entries(derivationPathToPublicKeyMap).reduce((acc, [derivationPath, publicKey]) => {
|
|
110
100
|
if (derivationPath.startsWith('m/44')) {
|
|
111
|
-
const p2pkh =
|
|
101
|
+
const p2pkh = payments.p2pkh({
|
|
112
102
|
pubkey: publicKey,
|
|
113
103
|
}).output;
|
|
114
|
-
(
|
|
104
|
+
assert(p2pkh, 'failed to compute p2pkh scriptPubKey');
|
|
115
105
|
Object.assign(acc, {
|
|
116
106
|
[p2pkh.toString('hex')]: derivationPath,
|
|
117
107
|
});
|
|
118
108
|
}
|
|
119
109
|
else if (derivationPath.startsWith('m/49')) {
|
|
120
|
-
const nestedSegwit =
|
|
121
|
-
redeem:
|
|
110
|
+
const nestedSegwit = payments.p2sh({
|
|
111
|
+
redeem: payments.p2wpkh({ pubkey: publicKey }),
|
|
122
112
|
}).output;
|
|
123
|
-
(
|
|
113
|
+
assert(nestedSegwit, 'failed to compute p2sh scriptPubKey');
|
|
124
114
|
Object.assign(acc, {
|
|
125
115
|
[nestedSegwit.toString('hex')]: derivationPath,
|
|
126
116
|
});
|
|
127
117
|
}
|
|
128
118
|
else if (derivationPath.startsWith('m/84')) {
|
|
129
|
-
const p2wpkh =
|
|
119
|
+
const p2wpkh = payments.p2wpkh({
|
|
130
120
|
pubkey: publicKey,
|
|
131
121
|
}).output;
|
|
132
|
-
(
|
|
122
|
+
assert(p2wpkh, 'failed to compute p2wpkh scriptPubKey');
|
|
133
123
|
Object.assign(acc, {
|
|
134
124
|
[p2wpkh.toString('hex')]: derivationPath,
|
|
135
125
|
});
|
|
136
126
|
}
|
|
137
127
|
else if (derivationPath.startsWith('m/86')) {
|
|
138
|
-
const p2tr =
|
|
128
|
+
const p2tr = payments.p2tr({
|
|
139
129
|
internalPubkey: publicKey.slice(1),
|
|
140
130
|
}).output;
|
|
141
|
-
(
|
|
131
|
+
assert(p2tr, 'failed to compute p2tr scriptPubKey');
|
|
142
132
|
Object.assign(acc, {
|
|
143
133
|
[p2tr.toString('hex')]: derivationPath,
|
|
144
134
|
});
|
|
@@ -149,17 +139,16 @@ function computeScriptPubKeyToDerivationPathMap(derivationPathToPublicKeyMap) {
|
|
|
149
139
|
function isTaproot(scriptPubKey) {
|
|
150
140
|
return scriptPubKey.length === 34 && scriptPubKey.at(0) === 0x51 && scriptPubKey.at(1) === 0x20;
|
|
151
141
|
}
|
|
152
|
-
const getWalletPolicy = (fpr, xpub, purpose, coin, account) => {
|
|
142
|
+
export const getWalletPolicy = (fpr, xpub, purpose, coin, account) => {
|
|
153
143
|
const desc = {
|
|
154
144
|
"44'": 'pkh(@0/**)',
|
|
155
145
|
"49'": 'sh(wpkh(@0/**))',
|
|
156
146
|
"84'": 'wpkh(@0/**)',
|
|
157
147
|
"86'": 'tr(@0/**)',
|
|
158
148
|
}[purpose];
|
|
159
|
-
return new
|
|
149
|
+
return new DefaultWalletPolicy(desc, `[${fpr}/${purpose}/${coin}/${account}]${xpub}`);
|
|
160
150
|
};
|
|
161
|
-
|
|
162
|
-
const getMultisigWalletPolicy = (fpr, xpub, purpose, coin, account, multisigData) => {
|
|
151
|
+
export const getMultisigWalletPolicy = (fpr, xpub, purpose, coin, account, multisigData) => {
|
|
163
152
|
let template = `tr(@0/**,sortedmulti_a(${multisigData.threshold}`;
|
|
164
153
|
const keys = [multisigData.internalXpub];
|
|
165
154
|
multisigData.xpubs.forEach((xpub2, i) => {
|
|
@@ -172,11 +161,10 @@ const getMultisigWalletPolicy = (fpr, xpub, purpose, coin, account, multisigData
|
|
|
172
161
|
template += `,@${i + 1}/**`;
|
|
173
162
|
});
|
|
174
163
|
template += '))';
|
|
175
|
-
return new
|
|
164
|
+
return new WalletPolicy('Multisig', template, keys);
|
|
176
165
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const splittedDerivationPaths = derivationPaths.map(derivation_paths_js_1.splitBip44DerivationPath);
|
|
166
|
+
export async function derivationPathsToWalletPolicy(fpr, app, derivationPaths, multisigData) {
|
|
167
|
+
const splittedDerivationPaths = derivationPaths.map(splitBip44DerivationPath);
|
|
180
168
|
const dedupedPaths = Object.values(splittedDerivationPaths.reduce((prev, splittedDerivationPath) => {
|
|
181
169
|
const [purpose, coin, account] = splittedDerivationPath;
|
|
182
170
|
prev[[purpose, coin, account].toString()] = [purpose, coin, account];
|
|
@@ -187,10 +175,10 @@ async function derivationPathsToWalletPolicy(fpr, app, derivationPaths, multisig
|
|
|
187
175
|
const [purpose, coin, account] = dedupedPath;
|
|
188
176
|
const xpub = await app.getExtendedPubkey(`m/${purpose}/${coin}/${account}`);
|
|
189
177
|
if (multisigData) {
|
|
190
|
-
walletPolicies.push(
|
|
178
|
+
walletPolicies.push(getMultisigWalletPolicy(fpr, xpub, purpose, coin, account, multisigData));
|
|
191
179
|
}
|
|
192
180
|
else {
|
|
193
|
-
walletPolicies.push(
|
|
181
|
+
walletPolicies.push(getWalletPolicy(fpr, xpub, purpose, coin, account));
|
|
194
182
|
}
|
|
195
183
|
}
|
|
196
184
|
return walletPolicies;
|
|
@@ -206,7 +194,7 @@ function canModifyInputs(psbt) {
|
|
|
206
194
|
}
|
|
207
195
|
return true;
|
|
208
196
|
}
|
|
209
|
-
function addDummyInputs(psbt) {
|
|
197
|
+
export function addDummyInputs(psbt) {
|
|
210
198
|
const canAddDummy = canModifyInputs(psbt);
|
|
211
199
|
if (!canAddDummy) {
|
|
212
200
|
return;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.buildFauxXPUB = buildFauxXPUB;
|
|
4
|
-
const base58check_js_1 = require("@exodus/bytes/base58check.js");
|
|
5
|
-
function buildFauxXPUB(publicKey, chainCode) {
|
|
1
|
+
import { toBase58checkSync } from '@exodus/bytes/base58check.js';
|
|
2
|
+
export function buildFauxXPUB(publicKey, chainCode) {
|
|
6
3
|
const LEN = 78;
|
|
7
4
|
const XPUB_PREFIX = 0x04_88_b2_1e;
|
|
8
5
|
const buffer = Buffer.alloc(LEN);
|
|
@@ -15,5 +12,5 @@ function buildFauxXPUB(publicKey, chainCode) {
|
|
|
15
12
|
buffer.writeUInt32BE(index, 9);
|
|
16
13
|
chainCode.copy(buffer, 13);
|
|
17
14
|
publicKey.copy(buffer, 45);
|
|
18
|
-
return
|
|
15
|
+
return toBase58checkSync(buffer);
|
|
19
16
|
}
|
package/lib/module/constants.js
CHANGED
package/lib/module/device.d.ts
CHANGED
|
@@ -19,6 +19,6 @@ export declare class LedgerDevice implements HardwareWalletDevice {
|
|
|
19
19
|
getAddress: (params: GetAddressParams) => Promise<string>;
|
|
20
20
|
getXPub: (params: GetXPubParams) => Promise<string>;
|
|
21
21
|
getPublicKey: (params: GetPublicKeyParams) => Promise<Readonly<Uint8Array<ArrayBufferLike>>>;
|
|
22
|
-
signTransaction: (params: SignTransactionParams) => Promise<import("@exodus/hw-common"
|
|
22
|
+
signTransaction: (params: SignTransactionParams) => Promise<import("@exodus/hw-common").Signatures>;
|
|
23
23
|
signMessage: (params: SignMessageParams) => Promise<Readonly<Uint8Array<ArrayBufferLike>>>;
|
|
24
24
|
}
|