UNPKG

@ledgerhq/live-common

Version:
319 lines • 16.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.completeExchangeLogic = exports.startExchangeLogic = exports.bitcoinFamilyAccountGetXPubLogic = exports.bitcoinFamilyAccountGetPublicKeyLogic = exports.bitcoinFamilyAccountGetAddressLogic = exports.signMessageLogic = exports.broadcastTransactionLogic = exports.signRawTransactionLogic = exports.signTransactionLogic = exports.receiveOnAccountLogic = exports.translateContent = void 0; const types_live_1 = require("@ledgerhq/types-live"); const converters_1 = require("./converters"); const index_1 = require("../account/index"); const index_2 = require("../hw/signMessage/index"); const bridge_1 = require("../bridge"); const cryptoassets_1 = require("@ledgerhq/cryptoassets"); const index_3 = require("@ledgerhq/coin-bitcoin/wallet-btc/index"); function translateContent(content, locale = "en") { if (!content || typeof content === "string") return content; return content[locale] || content.en; } exports.translateContent = translateContent; function receiveOnAccountLogic(walletState, { manifest, accounts, tracking }, walletAccountId, uiNavigation, tokenCurrency) { tracking.receiveRequested(manifest); const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId); if (!accountId) { tracking.receiveFail(manifest); return Promise.reject(new Error(`accountId ${walletAccountId} unknown`)); } const account = accounts.find(account => account.id === accountId); if (!account) { tracking.receiveFail(manifest); return Promise.reject(new Error("Account required")); } const parentAccount = (0, index_1.getParentAccount)(account, accounts); const mainAccount = (0, index_1.getMainAccount)(account, parentAccount); const currency = tokenCurrency ? (0, cryptoassets_1.findTokenById)(tokenCurrency) : null; const receivingAccount = currency ? (0, index_1.makeEmptyTokenAccount)(mainAccount, currency) : account; const accountAddress = (0, converters_1.accountToWalletAPIAccount)(walletState, account, parentAccount).address; return uiNavigation(receivingAccount, parentAccount, accountAddress); } exports.receiveOnAccountLogic = receiveOnAccountLogic; function signTransactionLogic({ manifest, accounts, tracking }, walletAccountId, transaction, uiNavigation, tokenCurrency) { tracking.signTransactionRequested(manifest); if (!transaction) { tracking.signTransactionFail(manifest); return Promise.reject(new Error("Transaction required")); } const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId); if (!accountId) { tracking.signTransactionFail(manifest); return Promise.reject(new Error(`accountId ${walletAccountId} unknown`)); } const account = accounts.find(account => account.id === accountId); if (!account) { tracking.signTransactionFail(manifest); return Promise.reject(new Error("Account required")); } const parentAccount = (0, index_1.getParentAccount)(account, accounts); const accountFamily = (0, index_1.isTokenAccount)(account) ? parentAccount?.currency.family : account.currency.family; const mainAccount = (0, index_1.getMainAccount)(account, parentAccount); const currency = tokenCurrency ? (0, cryptoassets_1.findTokenById)(tokenCurrency) : null; const signerAccount = currency ? (0, index_1.makeEmptyTokenAccount)(mainAccount, currency) : account; const { canEditFees, liveTx, hasFeesProvided } = (0, converters_1.getWalletAPITransactionSignFlowInfos)({ walletApiTransaction: transaction, account: mainAccount, }); if (accountFamily !== liveTx.family) { return Promise.reject(new Error(`Account and transaction must be from the same family. Account family: ${accountFamily}, Transaction family: ${liveTx.family}`)); } return uiNavigation(signerAccount, parentAccount, { canEditFees, liveTx, hasFeesProvided, }); } exports.signTransactionLogic = signTransactionLogic; function signRawTransactionLogic({ manifest, accounts, tracking }, walletAccountId, transaction, uiNavigation) { tracking.signRawTransactionRequested(manifest); if (!transaction) { tracking.signRawTransactionFail(manifest); return Promise.reject(new Error("Transaction required")); } const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId); if (!accountId) { tracking.signRawTransactionFail(manifest); return Promise.reject(new Error(`accountId ${walletAccountId} unknown`)); } const account = accounts.find(account => account.id === accountId); if (!account) { tracking.signRawTransactionFail(manifest); return Promise.reject(new Error("Account required")); } const parentAccount = (0, index_1.getParentAccount)(account, accounts); return uiNavigation(account, parentAccount, transaction); } exports.signRawTransactionLogic = signRawTransactionLogic; function broadcastTransactionLogic({ manifest, accounts, tracking }, walletAccountId, signedOperation, uiNavigation, tokenCurrency) { if (!signedOperation) { tracking.broadcastFail(manifest); return Promise.reject(new Error("Transaction required")); } const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId); if (!accountId) { tracking.broadcastFail(manifest); return Promise.reject(new Error(`accountId ${walletAccountId} unknown`)); } const account = accounts.find(account => account.id === accountId); if (!account) { tracking.broadcastFail(manifest); return Promise.reject(new Error("Account required")); } const currency = tokenCurrency ? (0, cryptoassets_1.findTokenById)(tokenCurrency) : null; const parentAccount = (0, index_1.getParentAccount)(account, accounts); const mainAccount = (0, index_1.getMainAccount)(account, parentAccount); const signerAccount = currency ? (0, index_1.makeEmptyTokenAccount)(mainAccount, currency) : account; return uiNavigation(signerAccount, parentAccount, signedOperation); } exports.broadcastTransactionLogic = broadcastTransactionLogic; function signMessageLogic({ manifest, accounts, tracking }, walletAccountId, message, uiNavigation) { tracking.signMessageRequested(manifest); const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId); if (!accountId) { tracking.signMessageFail(manifest); return Promise.reject(new Error(`accountId ${walletAccountId} unknown`)); } const account = accounts.find(account => account.id === accountId); if (account === undefined) { tracking.signMessageFail(manifest); return Promise.reject(new Error("account not found")); } let formattedMessage; try { if ((0, index_1.isAccount)(account)) { formattedMessage = (0, index_2.prepareMessageToSign)(account, message); } else { throw new Error("account provided should be the main one"); } } catch (error) { tracking.signMessageFail(manifest); return Promise.reject(error); } return uiNavigation(account, formattedMessage); } exports.signMessageLogic = signMessageLogic; const bitcoinFamilyAccountGetAddressLogic = ({ manifest, accounts, tracking }, walletAccountId, derivationPath) => { tracking.bitcoinFamilyAccountAddressRequested(manifest); const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId); if (!accountId) { tracking.bitcoinFamilyAccountAddressFail(manifest); return Promise.reject(new Error(`accountId ${walletAccountId} unknown`)); } const account = accounts.find(account => account.id === accountId); if (account === undefined) { tracking.bitcoinFamilyAccountAddressFail(manifest); return Promise.reject(new Error("account not found")); } if (!(0, index_1.isAccount)(account) || account.currency.family !== "bitcoin") { tracking.bitcoinFamilyAccountAddressFail(manifest); return Promise.reject(new Error("account requested is not a bitcoin family account")); } if (derivationPath) { const path = derivationPath.split("/"); const accountNumber = Number(path[0]); const index = Number(path[1]); if (Number.isNaN(accountNumber) || Number.isNaN(index)) { tracking.bitcoinFamilyAccountAddressFail(manifest); return Promise.reject(new Error("Invalid derivationPath")); } const walletAccount = (0, index_3.getWalletAccount)(account); const address = walletAccount.xpub.crypto.getAddress(walletAccount.xpub.derivationMode, walletAccount.xpub.xpub, accountNumber, index); tracking.bitcoinFamilyAccountAddressSuccess(manifest); return Promise.resolve(address); } tracking.bitcoinFamilyAccountAddressSuccess(manifest); return Promise.resolve(account.freshAddress); }; exports.bitcoinFamilyAccountGetAddressLogic = bitcoinFamilyAccountGetAddressLogic; function getRelativePath(path) { const splitPath = path.split("'/"); return splitPath[splitPath.length - 1]; } const bitcoinFamilyAccountGetPublicKeyLogic = async ({ manifest, accounts, tracking }, walletAccountId, derivationPath) => { tracking.bitcoinFamilyAccountPublicKeyRequested(manifest); const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId); if (!accountId) { tracking.bitcoinFamilyAccountPublicKeyFail(manifest); return Promise.reject(new Error(`accountId ${walletAccountId} unknown`)); } const account = accounts.find(account => account.id === accountId); if (account === undefined) { tracking.bitcoinFamilyAccountPublicKeyFail(manifest); return Promise.reject(new Error("account not found")); } if (!(0, index_1.isAccount)(account) || account.currency.family !== "bitcoin") { tracking.bitcoinFamilyAccountPublicKeyFail(manifest); return Promise.reject(new Error("account requested is not a bitcoin family account")); } const path = derivationPath?.split("/") ?? getRelativePath(account.freshAddressPath).split("/"); const accountNumber = Number(path[0]); const index = Number(path[1]); if (Number.isNaN(accountNumber) || Number.isNaN(index)) { tracking.bitcoinFamilyAccountPublicKeyFail(manifest); return Promise.reject(new Error("Invalid derivationPath")); } const walletAccount = (0, index_3.getWalletAccount)(account); const publicKey = await walletAccount.xpub.crypto.getPubkeyAt(walletAccount.xpub.xpub, accountNumber, index); tracking.bitcoinFamilyAccountPublicKeySuccess(manifest); return publicKey.toString("hex"); }; exports.bitcoinFamilyAccountGetPublicKeyLogic = bitcoinFamilyAccountGetPublicKeyLogic; const bitcoinFamilyAccountGetXPubLogic = ({ manifest, accounts, tracking }, walletAccountId) => { tracking.bitcoinFamilyAccountXpubRequested(manifest); const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId); if (!accountId) { tracking.bitcoinFamilyAccountXpubFail(manifest); return Promise.reject(new Error(`accountId ${walletAccountId} unknown`)); } const account = accounts.find(account => account.id === accountId); if (account === undefined) { tracking.bitcoinFamilyAccountXpubFail(manifest); return Promise.reject(new Error("account not found")); } if (!(0, index_1.isAccount)(account) || account.currency.family !== "bitcoin") { tracking.bitcoinFamilyAccountXpubFail(manifest); return Promise.reject(new Error("account requested is not a bitcoin family account")); } if (!account.xpub) { tracking.bitcoinFamilyAccountXpubFail(manifest); return Promise.reject(new Error("account xpub not available")); } tracking.bitcoinFamilyAccountXpubSuccess(manifest); return Promise.resolve(account.xpub); }; exports.bitcoinFamilyAccountGetXPubLogic = bitcoinFamilyAccountGetXPubLogic; function startExchangeLogic({ manifest, tracking }, exchangeType, uiNavigation) { tracking.startExchangeRequested(manifest); return uiNavigation(exchangeType); } exports.startExchangeLogic = startExchangeLogic; function completeExchangeLogic({ manifest, accounts, tracking }, { provider, fromAccountId, toAccountId, transaction, binaryPayload, signature, feesStrategy, exchangeType, swapId, rate, tokenCurrency, }, uiNavigation) { tracking.completeExchangeRequested(manifest); const realFromAccountId = (0, converters_1.getAccountIdFromWalletAccountId)(fromAccountId); if (!realFromAccountId) { return Promise.reject(new Error(`accountId ${fromAccountId} unknown`)); } // Nb get a hold of the actual accounts, and parent accounts const fromAccount = accounts.find(a => a.id === realFromAccountId); let toAccount; if (toAccountId) { const realToAccountId = (0, converters_1.getAccountIdFromWalletAccountId)(toAccountId); if (!realToAccountId) { return Promise.reject(new Error(`accountId ${toAccountId} unknown`)); } toAccount = accounts.find(a => a.id === realToAccountId); } if (!fromAccount) { return Promise.reject(); } if (exchangeType === 0x00 && !toAccount) { // if we do a swap, a destination account must be provided return Promise.reject(); } const fromParentAccount = (0, index_1.getParentAccount)(fromAccount, accounts); const currency = tokenCurrency ? (0, cryptoassets_1.findTokenById)(tokenCurrency) : null; const newTokenAccount = currency ? (0, index_1.makeEmptyTokenAccount)(toAccount, currency) : undefined; const toParentAccount = toAccount ? (0, index_1.getParentAccount)(toAccount, accounts) : undefined; const exchange = { fromAccount, fromParentAccount: fromAccount !== fromParentAccount ? fromParentAccount : undefined, fromCurrency: (0, types_live_1.getCurrencyForAccount)(fromAccount), toAccount: newTokenAccount ? newTokenAccount : toAccount, toParentAccount: newTokenAccount ? toAccount : toParentAccount, toCurrency: toAccount ? getToCurrency(toAccount, newTokenAccount) : undefined, }; const accountBridge = (0, bridge_1.getAccountBridge)(fromAccount, fromParentAccount); const mainFromAccount = (0, index_1.getMainAccount)(fromAccount, fromParentAccount); const mainFromAccountFamily = mainFromAccount.currency.family; const { liveTx } = (0, converters_1.getWalletAPITransactionSignFlowInfos)({ walletApiTransaction: transaction, account: fromAccount, }); if (liveTx.family !== mainFromAccountFamily) { return Promise.reject(new Error(`Account and transaction must be from the same family. Account family: ${mainFromAccountFamily}, Transaction family: ${liveTx.family}`)); } /** * 'subAccountId' is used for ETH and it's ERC-20 tokens. * This field is ignored for BTC */ const subAccountId = exchange.fromParentAccount ? fromAccount.id : undefined; const bridgeTx = accountBridge.createTransaction(fromAccount); /** * We append the `recipient` to the tx created from `createTransaction` * to avoid having userGasLimit reset to null for ETH txs * cf. libs/ledger-live-common/src/families/ethereum/updateTransaction.ts */ const tx = accountBridge.updateTransaction({ ...bridgeTx, recipient: liveTx.recipient, }, { ...liveTx, feesStrategy: feesStrategy.toLowerCase(), subAccountId, }); return uiNavigation({ provider, exchange, transaction: tx, binaryPayload, signature, feesStrategy, exchangeType, swapId, rate, }); } exports.completeExchangeLogic = completeExchangeLogic; function getToCurrency(account, tokenAccount) { return tokenAccount ? (0, types_live_1.getCurrencyForAccount)(tokenAccount) : (0, types_live_1.getCurrencyForAccount)(account); } //# sourceMappingURL=logic.js.map