UNPKG

rerumcupiditate

Version:

ledger and trezor hd sign and export coin address.

161 lines (150 loc) 6.07 kB
import buildOutputScript from 'build-output-script'; import { Unit } from 'bitcore-lib'; import { BtcSeriesEntity, BtcSeriesData, Utxo, OutPut, TX_SPLIT_API } from '../model/btc'; import { zip } from 'lodash'; import { LedgerTransport } from './transport' import { EthEntity, EthData } from '../model/eth'; import { toHex, numberToHex } from 'web3-utils'; import { convert } from 'ethereumjs-units'; import { CoinType } from '../model/utils'; import { convertCoinAddress } from '../common/convert'; import { writeInfoLog } from '../common/logger'; const axios = require('axios'); class LedgerLogic { private transport?: LedgerTransport; private coin_type: string; /** * 交易签名逻辑处理类 * @param coinType */ constructor(coinType: string) { this.coin_type = coinType; writeInfoLog(`初始化交易签名逻辑处理类.`); } /** * 组装ledger签名实体对象 * @param data */ public async getLedgerEntity(data: any): Promise<any> { writeInfoLog(`构造ledger签名实体对象.`); switch (this.coin_type) { case CoinType.ETH: return await this.getEthLedgerEntity(data); case CoinType.BTC: default: return await this.getBtcSeriesLedgerEntity(data); } } /** * 构造ledger签名实体对象:BTC系列:btc、bch、ltc * @param data */ private async getBtcSeriesLedgerEntity(data: BtcSeriesData): Promise<BtcSeriesEntity> { writeInfoLog(`构造ledger btc系列 签名实体对象`); let entity: BtcSeriesEntity = { isMutiSign: data.input.paths.length > 1, inputs: await this.getBtcSeriesLedgerInputs(data), outputScript: await this.getBtcSeriesLedgerOutputScript(data.outputs), segwit: false, paths: Array(data.utxos.length).fill(data.input.paths[data.input.signIndex].path) } return entity; } /** * 构造ledger签名实体对象:ETH * @param data */ private async getEthLedgerEntity(data: EthData): Promise<EthEntity> { try { writeInfoLog(`构造ledger eth 签名实体对象`); let entity: EthEntity = { nonce: numberToHex(data.nonce), gasPrice: numberToHex(data.gasPrice), gasLimit: numberToHex(data.gasLimit), to: toHex(data.toAddress), value: numberToHex(convert(data.txnCoinNum, 'eth', 'wei')), data: data.data ? data.data : '', chainId: numberToHex(data.chainId) } return entity; } catch (error) { throw new Error(`构造ledger eth 签名实体对象失败,错误信息:${error.message}`); } } /** * btc系列签名 报文解析组装签名所需inputs、格式化地址支持bch、ltc,多签需要赎回脚本 * @param data */ private async getBtcSeriesLedgerInputs(data: BtcSeriesData): Promise<any> { //格式化地址 data.input.address = convertCoinAddress(data.input.address, this.coin_type); let inputs: any = await this.getBtcSeriesTxInputsByUtxo(data.utxos); //多签:需要赎回脚本 if (data.input.paths.length > 1) { inputs.forEach(element => { element.push(data.input.redeemScript); }); } return inputs; } /** * btc系列签名 utxo hax 报文解析组装签名所需inputs * @param listUtxo */ private async getBtcSeriesTxInputsByUtxo(listUtxo: Array<Utxo>): Promise<any> { try { writeInfoLog(`ledger btc系列 utxo txid报文解析.`); this.transport = new LedgerTransport(this.coin_type); const transport: any = await this.transport.getTransport(); let splitTxs: Array<any> = new Array<any>(); let indexs: Array<number> = new Array<number>(); let txApiUrl: string; for (let element of listUtxo) { switch (this.coin_type) { case CoinType.BCH: txApiUrl = `${TX_SPLIT_API.BCH}/${element.txid}/hex`; break; case CoinType.LTC: txApiUrl = `${TX_SPLIT_API.LTC}/${element.txid}`; break; case CoinType.BTC: default: txApiUrl = `${TX_SPLIT_API.BTC}/${element.txid}/hex`; break; } let res: any = await axios.get(txApiUrl); for (let i = 0; i < res.data.length; i++) { let swegit: boolean = res.data[i].hex.substring(8, 8 + 2) == "00" ? true : false; let splitTx: any = await transport.splitTransaction(res.data[i].hex, swegit, undefined); splitTxs.push(splitTx); indexs.push(listUtxo[i].index); } } return zip(splitTxs, indexs); } catch (error) { throw new Error(`获取utxo txid报文解析失败,错误信息:${error.message}`) } } /** * btc系列签名锁定脚本 * @param listOutput */ private async getBtcSeriesLedgerOutputScript(listOutput: Array<OutPut>): Promise<string> { try { let tmp: Array<any> = new Array<any>(); listOutput.forEach(element => { tmp.push({ address: convertCoinAddress(element.address, this.coin_type), value: Unit.fromBTC(element.coinNum).toSatoshis() }); }); writeInfoLog(`ledger btc系列 签名锁定脚本.`); return buildOutputScript(tmp); } catch (error) { throw new Error(`构造ledger btc系列 签名锁定脚本失败,错误信息:${error.message}`); } } } export { LedgerLogic }