"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.addMultisignStellarMockAddresses = exports.addNotCreatedStellarMockAddresses = void 0;
const invariant_1 = __importDefault(require("invariant"));
const bignumber_js_1 = require("bignumber.js");
const errors_1 = require("@ledgerhq/errors");
const jsHelpers_1 = require("@ledgerhq/coin-framework/bridge/jsHelpers");
const errors_2 = require("@ledgerhq/coin-stellar/errors");
const account_1 = require("../../../account");
const currencies_1 = require("../../../currencies");
const mockHelpers_1 = require("../../../bridge/mockHelpers");
const validateAddress_1 = require("../../../bridge/validateAddress");
const receive = (0, mockHelpers_1.makeAccountBridgeReceive)();
const notCreatedStellarMockAddress = "GAW46JE3SHIAYLNNNQCAZFQ437WB5ZH7LDRDWR5LVDWHCTHCKYB6RCCH";
const multisignStellarMockAddress = "GCDDN6T2LJN3T7SPWJQV6BCCL5KNY5GBN7X4CMSZLDEXDHXAH32TOAHS";
const notCreatedAddresses = [];
const multiSignAddresses = [];
function addNotCreatedStellarMockAddresses(addr) {
    notCreatedAddresses.push(addr);
}
exports.addNotCreatedStellarMockAddresses = addNotCreatedStellarMockAddresses;
function addMultisignStellarMockAddresses(addr) {
    multiSignAddresses.push(addr);
}
exports.addMultisignStellarMockAddresses = addMultisignStellarMockAddresses;
addNotCreatedStellarMockAddresses(notCreatedStellarMockAddress);
addMultisignStellarMockAddresses(multisignStellarMockAddress);
const createTransaction = () => ({
    family: "stellar",
    amount: new bignumber_js_1.BigNumber(0),
    baseReserve: null,
    networkInfo: null,
    fees: null,
    recipient: "",
    memoValue: null,
    memoType: null,
    useAllAmount: false,
    mode: "send",
    assetReference: "",
    assetOwner: "",
});
const updateTransaction = (t, patch) => {
    return { ...t, ...patch };
};
const isMemoValid = (memoType, memoValue) => {
    switch (memoType) {
        case "MEMO_TEXT":
            if (memoValue.length > 28) {
                return false;
            }
            break;
        case "MEMO_ID":
            if (new bignumber_js_1.BigNumber(memoValue.toString()).isNaN()) {
                return false;
            }
            break;
        case "MEMO_HASH":
        case "MEMO_RETURN":
            if (!memoValue.length || memoValue.length !== 32) {
                return false;
            }
            break;
    }
    return true;
};
const getTransactionStatus = async (a, t) => {
    const errors = {};
    const warnings = {};
    const useAllAmount = !!t.useAllAmount;
    if (a.freshAddress === t.recipient) {
        errors.recipient = new errors_1.InvalidAddressBecauseDestinationIsAlsoSource();
    }
    else {
        if (!t.recipient) {
            errors.recipient = new errors_1.RecipientRequired("");
        }
        else if ((0, mockHelpers_1.isInvalidRecipient)(t.recipient)) {
            errors.recipient = new errors_1.InvalidAddress("");
        }
    }
    if (multiSignAddresses.includes(a.freshAddress)) {
        errors.recipient = new errors_2.StellarSourceHasMultiSign("", {
            currencyName: a.currency.name,
        });
    }
    if (!t.fees || !t.baseReserve) {
        errors.fees = new errors_1.FeeNotLoaded();
    }
    const estimatedFees = !t.fees ? new bignumber_js_1.BigNumber(0) : t.fees;
    const baseReserve = !t.baseReserve ? new bignumber_js_1.BigNumber(0) : t.baseReserve;
    let amount = !useAllAmount ? t.amount : a.balance.minus(baseReserve).minus(estimatedFees);
    let totalSpent = !useAllAmount ? amount.plus(estimatedFees) : a.balance.minus(baseReserve);
    if (totalSpent.gt(a.balance.minus(baseReserve))) {
        errors.amount = new errors_1.NotEnoughSpendableBalance("", {
            minimumAmount: (0, currencies_1.formatCurrencyUnit)(a.currency.units[0], baseReserve, {
                disableRounding: true,
                useGrouping: false,
                showCode: true,
            }),
        });
    }
    if (!errors.amount && amount.plus(estimatedFees).plus(baseReserve).gt(a.balance)) {
        errors.amount = new errors_1.NotEnoughBalance();
    }
    if (!errors.recipient && !errors.amount && (amount.lt(0) || totalSpent.gt(a.balance))) {
        errors.amount = new errors_1.NotEnoughBalance();
        totalSpent = new bignumber_js_1.BigNumber(0);
        amount = new bignumber_js_1.BigNumber(0);
    }
    if (!errors.amount && amount.eq(0)) {
        errors.amount = new errors_1.AmountRequired();
    }
    // if amount < 1.0 you can't
    if (!errors.amount && notCreatedAddresses.includes(t.recipient) && amount.lt(10000000)) {
        errors.amount = new errors_1.NotEnoughBalanceBecauseDestinationNotCreated("", {
            minimalAmount: "1 XLM",
        });
    }
    if (t.memoType && t.memoValue && !isMemoValid(t.memoType, t.memoValue)) {
        errors.transaction = new errors_2.StellarWrongMemoFormat();
    }
    return Promise.resolve({
        errors,
        warnings,
        estimatedFees,
        amount,
        totalSpent,
    });
};
const prepareTransaction = async (a, t) => {
    const networkInfo = t.networkInfo || {
        family: "stellar",
        fees: new bignumber_js_1.BigNumber("100"),
        baseReserve: new bignumber_js_1.BigNumber("100000"),
    };
    (0, invariant_1.default)(networkInfo.family === "stellar", "stellar networkInfo expected");
    const fees = t.fees || networkInfo.fees;
    const baseReserve = t.baseReserve || networkInfo.baseReserve;
    if (t.networkInfo !== networkInfo || t.fees !== fees || t.baseReserve !== baseReserve) {
        return { ...t, networkInfo, fees, baseReserve };
    }
    return t;
};
const estimateMaxSpendable = async ({ account, parentAccount, transaction }) => {
    const mainAccount = (0, account_1.getMainAccount)(account, parentAccount);
    const t = await prepareTransaction(mainAccount, {
        ...createTransaction(),
        recipient: notCreatedAddresses[0],
        // not used address
        ...transaction,
        useAllAmount: true,
    });
    const s = await getTransactionStatus(mainAccount, t);
    return s.amount;
};
const preload = async () => ({});
const hydrate = () => { };
const currencyBridge = {
    preload,
    hydrate,
    scanAccounts: mockHelpers_1.scanAccounts,
};
const accountBridge = {
    createTransaction,
    updateTransaction,
    prepareTransaction,
    getTransactionStatus,
    sync: mockHelpers_1.sync,
    receive,
    signOperation: mockHelpers_1.signOperation,
    signRawOperation: mockHelpers_1.signRawOperation,
    broadcast: mockHelpers_1.broadcast,
    estimateMaxSpendable,
    getSerializedAddressParameters: jsHelpers_1.getSerializedAddressParameters,
    validateAddress: validateAddress_1.validateAddress,
};
exports.default = {
    currencyBridge,
    accountBridge,
};
//# sourceMappingURL=mock.js.map