"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.mergeSubAccounts = exports.buildSubAccounts = void 0;
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const index_1 = require("@ledgerhq/coin-framework/account/index");
const operation_1 = require("@ledgerhq/coin-framework/operation");
const jsHelpers_1 = require("../jsHelpers");
const utils_1 = require("./utils");
function buildTokenAccount({ parentAccountId, assetBalance, token, operations, }) {
    const id = (0, index_1.encodeTokenAccountId)(parentAccountId, token);
    const balance = new bignumber_js_1.default(assetBalance.value.toString() || "0");
    // TODO: recheck this logic
    const spendableBalance = new bignumber_js_1.default(assetBalance.value.toString()).minus(new bignumber_js_1.default(assetBalance.locked?.toString() || "0"));
    const tokenOperations = operations.map(op => (0, utils_1.cleanedOperation)({
        ...op,
        id: (0, operation_1.encodeOperationId)(id, op.hash, op.extra?.ledgerOpType),
        accountId: id,
        type: op.extra?.ledgerOpType,
        contract: token.contractAddress,
        value: op.extra?.assetAmount ? new bignumber_js_1.default(op.extra?.assetAmount) : op.value,
        senders: op.extra?.assetSenders ?? op.senders,
        recipients: op.extra?.assetRecipients ?? op.recipients,
    }));
    return {
        type: "TokenAccount",
        id,
        parentId: parentAccountId,
        token,
        operationsCount: operations.length,
        operations: tokenOperations,
        pendingOperations: [],
        balance,
        spendableBalance: spendableBalance,
        swapHistory: [],
        creationDate: operations.length > 0 ? operations[operations.length - 1].date : new Date(),
        balanceHistoryCache: index_1.emptyHistoryCache, // calculated in the jsHelpers
    };
}
async function buildSubAccounts({ accountId, allTokenAssetsBalances, syncConfig, operations, getTokenFromAsset, }) {
    const { blacklistedTokenIds = [] } = syncConfig;
    const tokenAccounts = [];
    if (allTokenAssetsBalances.length === 0 || !getTokenFromAsset) {
        return tokenAccounts;
    }
    for (const balance of allTokenAssetsBalances) {
        const token = await getTokenFromAsset(balance.asset);
        // NOTE: for future tokens, will need to check over currencyName/standard(erc20,trc10,trc20, etc)/id
        if (token && !blacklistedTokenIds.includes(token.id)) {
            tokenAccounts.push(buildTokenAccount({
                parentAccountId: accountId,
                assetBalance: balance,
                token,
                operations: operations.filter(op => op.extra.assetReference === balance.asset?.["assetReference"] &&
                    op.extra.assetOwner === balance.asset?.["assetOwner"]),
            }));
        }
    }
    return tokenAccounts;
}
exports.buildSubAccounts = buildSubAccounts;
function mergeSubAccounts(oldSubAccounts, newSubAccounts) {
    if (!oldSubAccounts.length) {
        return newSubAccounts;
    }
    const oldSubAccountsByTokenId = Object.fromEntries(oldSubAccounts.map(account => [account.token.id, account]));
    const newSubAccountsToAdd = [];
    for (const newSubAccount of newSubAccounts) {
        const existingSubAccount = oldSubAccountsByTokenId[newSubAccount.token.id];
        if (!existingSubAccount) {
            // New sub account does not exist yet. Just add it as is.
            newSubAccountsToAdd.push(newSubAccount);
            continue;
        }
        // New sub account is already known, probably outdated
        const operations = (0, jsHelpers_1.mergeOps)(existingSubAccount.operations, newSubAccount.operations);
        oldSubAccountsByTokenId[newSubAccount.token.id] = {
            ...existingSubAccount,
            balance: newSubAccount.balance,
            spendableBalance: newSubAccount.spendableBalance,
            operations,
            operationsCount: operations.length,
        };
    }
    const updatedOldSubAccounts = Object.values(oldSubAccountsByTokenId);
    return [...updatedOldSubAccounts, ...newSubAccountsToAdd];
}
exports.mergeSubAccounts = mergeSubAccounts;
//# sourceMappingURL=buildSubAccounts.js.map