"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 state_1 = require("@ledgerhq/cryptoassets/state");
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;
async function receiveOnAccountLogic(walletState, { manifest, accounts, tracking }, walletAccountId, uiNavigation, tokenCurrency) {
    tracking.receiveRequested(manifest);
    const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId);
    if (!accountId) {
        tracking.receiveFail(manifest);
        throw new Error(`accountId ${walletAccountId} unknown`);
    }
    const account = accounts.find(account => account.id === accountId);
    if (!account) {
        tracking.receiveFail(manifest);
        throw new Error("Account required");
    }
    const parentAccount = (0, index_1.getParentAccount)(account, accounts);
    const mainAccount = (0, index_1.getMainAccount)(account, parentAccount);
    const currency = tokenCurrency ? await (0, state_1.getCryptoAssetsStore)().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;
async function signTransactionLogic({ manifest, accounts, tracking }, walletAccountId, transaction, uiNavigation, tokenCurrency, isEmbeddedSwap, partner) {
    tracking.signTransactionRequested(manifest, isEmbeddedSwap, partner);
    if (!transaction) {
        tracking.signTransactionFail(manifest, isEmbeddedSwap, partner);
        throw new Error("Transaction required");
    }
    const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId);
    if (!accountId) {
        tracking.signTransactionFail(manifest, isEmbeddedSwap, partner);
        throw new Error(`accountId ${walletAccountId} unknown`);
    }
    const account = accounts.find(account => account.id === accountId);
    if (!account) {
        tracking.signTransactionFail(manifest, isEmbeddedSwap, partner);
        throw 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 ? await (0, state_1.getCryptoAssetsStore)().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) {
        throw 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);
        throw new Error("Transaction required");
    }
    const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId);
    if (!accountId) {
        tracking.signRawTransactionFail(manifest);
        throw new Error(`accountId ${walletAccountId} unknown`);
    }
    const account = accounts.find(account => account.id === accountId);
    if (!account) {
        tracking.signRawTransactionFail(manifest);
        throw new Error("Account required");
    }
    const parentAccount = (0, index_1.getParentAccount)(account, accounts);
    return uiNavigation(account, parentAccount, transaction);
}
exports.signRawTransactionLogic = signRawTransactionLogic;
async function broadcastTransactionLogic({ manifest, accounts, tracking }, walletAccountId, signedOperation, uiNavigation, tokenCurrency) {
    if (!signedOperation) {
        tracking.broadcastFail(manifest);
        throw new Error("Transaction required");
    }
    const accountId = (0, converters_1.getAccountIdFromWalletAccountId)(walletAccountId);
    if (!accountId) {
        tracking.broadcastFail(manifest);
        throw new Error(`accountId ${walletAccountId} unknown`);
    }
    const account = accounts.find(account => account.id === accountId);
    if (!account) {
        tracking.broadcastFail(manifest);
        throw new Error("Account required");
    }
    const currency = tokenCurrency ? await (0, state_1.getCryptoAssetsStore)().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;
async 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) {
        throw 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) {
            throw new Error(`accountId ${toAccountId} unknown`);
        }
        toAccount = accounts.find(a => a.id === realToAccountId);
    }
    if (!fromAccount) {
        throw new Error("From account not found");
    }
    if (exchangeType === 0x00 && !toAccount) {
        // if we do a swap, a destination account must be provided
        throw new Error("To account required for swap");
    }
    const fromParentAccount = (0, index_1.getParentAccount)(fromAccount, accounts);
    const currency = tokenCurrency ? await (0, state_1.getCryptoAssetsStore)().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) {
        throw 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