UNPKG

@trezor/connect

Version:

High-level javascript interface for Trezor hardware wallet.

172 lines (171 loc) 5.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getLabel = exports.fixPath = exports.getIndexFromPath = exports.getPathFromIndex = exports.getSerializedPath = exports.validatePath = exports.getOutputScriptType = exports.getScriptType = exports.getAccountType = exports.isTaprootPath = exports.isBech32Path = exports.isSegwitPath = exports.getHDPath = exports.getSlip44ByPath = exports.fromHardened = exports.toHardened = exports.HD_HARDENED = void 0; const constants_1 = require("../constants"); exports.HD_HARDENED = 0x80000000; const toHardened = n => (n | exports.HD_HARDENED) >>> 0; exports.toHardened = toHardened; const fromHardened = n => (n & ~exports.HD_HARDENED) >>> 0; exports.fromHardened = fromHardened; const getSlip44ByPath = path => (0, exports.fromHardened)(path[1]); exports.getSlip44ByPath = getSlip44ByPath; const PATH_NOT_VALID = constants_1.ERRORS.TypedError('Method_InvalidParameter', 'Not a valid path'); const PATH_NEGATIVE_VALUES = constants_1.ERRORS.TypedError('Method_InvalidParameter', 'Path cannot contain negative values'); const getHDPath = path => { const parts = path.toLowerCase().split('/'); if (parts[0] !== 'm') throw PATH_NOT_VALID; return parts.filter(p => p !== 'm' && p !== '').map(p => { let hardened = false; if (p.endsWith("'")) { hardened = true; p = p.substring(0, p.length - 1); } let n = parseInt(p, 10); if (Number.isNaN(n)) { throw PATH_NOT_VALID; } else if (n < 0) { throw PATH_NEGATIVE_VALUES; } if (hardened) { n = (0, exports.toHardened)(n); } return n; }); }; exports.getHDPath = getHDPath; const isSegwitPath = path => Array.isArray(path) && path[0] === (0, exports.toHardened)(49); exports.isSegwitPath = isSegwitPath; const isBech32Path = path => Array.isArray(path) && path[0] === (0, exports.toHardened)(84); exports.isBech32Path = isBech32Path; const isTaprootPath = path => Array.isArray(path) && (path[0] === (0, exports.toHardened)(86) || path[0] === (0, exports.toHardened)(10025)); exports.isTaprootPath = isTaprootPath; const getAccountType = path => { if ((0, exports.isTaprootPath)(path)) return 'p2tr'; if ((0, exports.isBech32Path)(path)) return 'p2wpkh'; if ((0, exports.isSegwitPath)(path)) return 'p2sh'; return 'p2pkh'; }; exports.getAccountType = getAccountType; const getScriptType = path => { if (!Array.isArray(path) || path.length < 1) return undefined; const p1 = (0, exports.fromHardened)(path[0]); switch (p1) { case 44: return 'SPENDADDRESS'; case 48: { if (path.length < 4) return undefined; const p3 = (0, exports.fromHardened)(path[3]); switch (p3) { case 0: return 'SPENDMULTISIG'; case 1: return 'SPENDP2SHWITNESS'; case 2: return 'SPENDWITNESS'; default: return undefined; } } case 49: return 'SPENDP2SHWITNESS'; case 84: return 'SPENDWITNESS'; case 86: case 10025: return 'SPENDTAPROOT'; default: return undefined; } }; exports.getScriptType = getScriptType; const getOutputScriptType = path => { if (!Array.isArray(path) || path.length < 1) return undefined; const p = (0, exports.fromHardened)(path[0]); switch (p) { case 44: return 'PAYTOADDRESS'; case 48: { if (path.length < 4) return undefined; const p3 = (0, exports.fromHardened)(path[3]); switch (p3) { case 0: return 'PAYTOMULTISIG'; case 1: return 'PAYTOP2SHWITNESS'; case 2: return 'PAYTOWITNESS'; default: return undefined; } } case 49: return 'PAYTOP2SHWITNESS'; case 84: return 'PAYTOWITNESS'; case 86: case 10025: return 'PAYTOTAPROOT'; default: return undefined; } }; exports.getOutputScriptType = getOutputScriptType; const validatePath = (path, length = 0, base = false) => { let valid; if (typeof path === 'string') { valid = (0, exports.getHDPath)(path); } else if (Array.isArray(path)) { valid = path.map(p => { const n = parseInt(p, 10); if (Number.isNaN(n)) { throw PATH_NOT_VALID; } else if (n < 0) { throw PATH_NEGATIVE_VALUES; } return n; }); } if (!valid) throw PATH_NOT_VALID; if (length > 0 && valid.length < length) throw PATH_NOT_VALID; return base ? valid.splice(0, 3) : valid; }; exports.validatePath = validatePath; const getSerializedPath = path => `m/${path.map(i => { const s = (i & ~exports.HD_HARDENED).toString(); if (i & exports.HD_HARDENED) { return `${s}'`; } return s; }).join('/')}`; exports.getSerializedPath = getSerializedPath; const getPathFromIndex = (bip44purpose, bip44cointype, index) => [(0, exports.toHardened)(bip44purpose), (0, exports.toHardened)(bip44cointype), (0, exports.toHardened)(index)]; exports.getPathFromIndex = getPathFromIndex; const getIndexFromPath = path => { if (path.length < 3) { throw constants_1.ERRORS.TypedError('Method_InvalidParameter', `getIndexFromPath: invalid path length ${path.toString()}`); } return (0, exports.fromHardened)(path[2]); }; exports.getIndexFromPath = getIndexFromPath; const fixPath = utxo => { if (utxo.address_n && Array.isArray(utxo.address_n)) { utxo.address_n = utxo.address_n.map(i => i >>> 0); } if (utxo.address_n && typeof utxo.address_n === 'string') { utxo.address_n = (0, exports.getHDPath)(utxo.address_n); } return utxo; }; exports.fixPath = fixPath; const getLabel = (label, coinInfo) => { if (coinInfo) { return label.replace('#NETWORK', coinInfo.label); } return label.replace('#NETWORK', ''); }; exports.getLabel = getLabel; //# sourceMappingURL=pathUtils.js.map