"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const typhonjs_1 = require("@stricahq/typhonjs");
const buildSubAccounts_1 = require("@ledgerhq/coin-cardano/buildSubAccounts");
const errors_1 = require("@ledgerhq/errors");
const errors_2 = require("@ledgerhq/coin-cardano/errors");
const buildTransaction_1 = require("@ledgerhq/coin-cardano/buildTransaction");
const constants_1 = require("@ledgerhq/coin-cardano/constants");
const jsHelpers_1 = require("@ledgerhq/coin-framework/bridge/jsHelpers");
const mockHelpers_1 = require("../../../bridge/mockHelpers");
const validateAddress_1 = require("../../../bridge/validateAddress");
const receive = (0, mockHelpers_1.makeAccountBridgeReceive)();
const createTransaction = () => {
    return {
        family: "cardano",
        mode: "send",
        amount: new bignumber_js_1.default(100),
        recipient: "",
        poolId: "",
    };
};
const estimateMaxSpendable = ({ account }) => {
    return account.balance;
};
const isValidAddress = (address) => {
    return address.length > 0;
};
const getTransactionStatus = async (account, transaction) => {
    const errors = { fees: new Error(), recipient: new Error(), amount: new Error() };
    const warnings = {};
    const estimatedFees = transaction.fees || new bignumber_js_1.default(0);
    const tokenAccount = transaction.subAccountId && account.subAccounts
        ? account.subAccounts.find(a => {
            return a.id === transaction.subAccountId;
        })
        : undefined;
    const mockAccount = tokenAccount || account;
    let amount = transaction.useAllAmount
        ? await estimateMaxSpendable({ account: mockAccount })
        : transaction.amount;
    let totalSpent = transaction.amount.plus(estimatedFees);
    const useAllAmount = Boolean(transaction.useAllAmount);
    let tokensToSend = [];
    const isTokenTx = !!transaction.subAccountId;
    if (isTokenTx) {
        // Token transaction
        if (!tokenAccount || tokenAccount.type !== "TokenAccount") {
            throw new Error("TokenAccount not found");
        }
        const { assetId } = (0, buildSubAccounts_1.decodeTokenCurrencyId)(tokenAccount.token.id);
        const { policyId, assetName } = (0, buildSubAccounts_1.decodeTokenAssetId)(assetId);
        amount = transaction.useAllAmount ? tokenAccount.balance : transaction.amount;
        totalSpent = amount;
        tokensToSend = [
            {
                policyId,
                assetName,
                amount,
            },
        ];
    }
    else {
        amount = transaction.useAllAmount ? await estimateMaxSpendable({ account }) : amount;
        totalSpent = amount.plus(estimatedFees);
    }
    let minTransactionAmount = new bignumber_js_1.default(0);
    if (!transaction.fees) {
        errors.fees = new errors_1.FeeNotLoaded();
    }
    if (!transaction.recipient) {
        errors.recipient = new errors_1.RecipientRequired();
    }
    else if (!isValidAddress(transaction.recipient)) {
        errors.recipient = new errors_1.InvalidAddress("", {
            currencyName: account.currency.name,
        });
    }
    else {
        // minTransactionAmount can only be calculated with valid recipient
        const recipient = typhonjs_1.utils.getAddressFromString(transaction.recipient);
        minTransactionAmount = typhonjs_1.utils.calculateMinUtxoAmountBabbage({
            address: recipient,
            amount: new bignumber_js_1.default(constants_1.CARDANO_MAX_SUPPLY),
            tokens: tokensToSend,
        }, new bignumber_js_1.default(account.cardanoResources.protocolParams.utxoCostPerByte));
    }
    if (!amount.gt(0)) {
        errors.amount = useAllAmount ? new errors_2.CardanoNotEnoughFunds() : new errors_1.AmountRequired();
    }
    else if (!isTokenTx && amount.lt(minTransactionAmount)) {
        errors.amount = new errors_2.CardanoMinAmountError("", {
            amount: minTransactionAmount.div(1e6).toString(),
        });
    }
    else if (tokenAccount ? totalSpent.gt(tokenAccount.balance) : totalSpent.gt(account.balance)) {
        errors.amount = new errors_1.NotEnoughBalance();
    }
    else {
        try {
            await (0, buildTransaction_1.buildTransaction)(account, transaction);
        }
        catch (e) {
            if (e.message.toLowerCase() === "not enough ada" ||
                e.message.toLowerCase() === "not enough tokens") {
                errors.amount = new errors_2.CardanoNotEnoughFunds();
            }
        }
    }
    return Promise.resolve({
        errors,
        warnings,
        estimatedFees,
        amount,
        totalSpent,
    });
};
const prepareTransaction = async (account, transaction) => {
    transaction.fees = new bignumber_js_1.default(100);
    return transaction;
};
const accountBridge = {
    createTransaction,
    updateTransaction: jsHelpers_1.updateTransaction,
    getTransactionStatus,
    estimateMaxSpendable,
    prepareTransaction,
    sync: mockHelpers_1.sync,
    receive,
    signOperation: mockHelpers_1.signOperation,
    signRawOperation: mockHelpers_1.signRawOperation,
    broadcast: mockHelpers_1.broadcast,
    getSerializedAddressParameters: jsHelpers_1.getSerializedAddressParameters,
    validateAddress: validateAddress_1.validateAddress,
};
const currencyBridge = {
    preload: () => Promise.resolve({}),
    hydrate: () => { },
    scanAccounts: mockHelpers_1.scanAccounts,
};
exports.default = {
    accountBridge,
    currencyBridge,
};
//# sourceMappingURL=mock.js.map