"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
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 currencies_1 = require("../currencies");
const signMessage = __importStar(require("../hw/signMessage/index"));
const cryptoCurrencies_1 = require("../mock/fixtures/cryptoCurrencies");
const converters = __importStar(require("./converters"));
const logic_1 = require("./logic");
const serializers = __importStar(require("./serializers"));
const store_1 = require("@ledgerhq/live-wallet/store");
describe("receiveOnAccountLogic", () => {
    const walletState = store_1.initialState;
    // Given
    const mockPlatformReceiveRequested = jest.fn();
    const mockPlatformReceiveFail = jest.fn();
    const context = createContextContainingAccountId({
        platformReceiveRequested: mockPlatformReceiveRequested,
        platformReceiveFail: mockPlatformReceiveFail,
    }, "11", "12");
    const uiNavigation = jest.fn();
    beforeEach(() => {
        mockPlatformReceiveRequested.mockClear();
        mockPlatformReceiveFail.mockClear();
        uiNavigation.mockClear();
    });
    describe("when nominal case", () => {
        // Given
        const accountId = "js:2:ethereum:0x012:";
        const expectedResult = "Function called";
        beforeEach(() => uiNavigation.mockResolvedValueOnce(expectedResult));
        it("calls uiNavigation callback with an accountAddress", async () => {
            // Given
            const convertedAccount = {
                ...createPlatformAccount(),
                address: "Converted address",
            };
            jest.spyOn(converters, "accountToPlatformAccount").mockReturnValueOnce(convertedAccount);
            // When
            const result = await (0, logic_1.receiveOnAccountLogic)(walletState, context, accountId, uiNavigation);
            // Then
            expect(uiNavigation).toBeCalledTimes(1);
            expect(uiNavigation.mock.calls[0][2]).toEqual("Converted address");
            expect(result).toEqual(expectedResult);
        });
        it("calls the tracking for success", async () => {
            // When
            await (0, logic_1.receiveOnAccountLogic)(walletState, context, accountId, uiNavigation);
            // Then
            expect(mockPlatformReceiveRequested).toBeCalledTimes(1);
            expect(mockPlatformReceiveFail).toBeCalledTimes(0);
        });
    });
    describe("when account cannot be found", () => {
        // Given
        const nonFoundAccountId = "js:2:ethereum:0x010:";
        it("returns an error", async () => {
            // When
            await expect(async () => {
                await (0, logic_1.receiveOnAccountLogic)(walletState, context, nonFoundAccountId, uiNavigation);
            }).rejects.toThrowError("Account required");
            // Then
            expect(uiNavigation).toBeCalledTimes(0);
        });
        it("calls the tracking for error", async () => {
            // When
            await expect(async () => {
                await (0, logic_1.receiveOnAccountLogic)(walletState, context, nonFoundAccountId, uiNavigation);
            }).rejects.toThrow();
            // Then
            expect(mockPlatformReceiveRequested).toBeCalledTimes(1);
            expect(mockPlatformReceiveFail).toBeCalledTimes(1);
        });
    });
});
describe("completeExchangeLogic", () => {
    // Given
    const mockPlatformCompleteExchangeRequested = jest.fn();
    const context = createContextContainingAccountId({
        platformCompleteExchangeRequested: mockPlatformCompleteExchangeRequested,
    }, "11", "12");
    const uiNavigation = jest.fn();
    beforeAll(() => {
        (0, currencies_1.setSupportedCurrencies)(["bitcoin", "ethereum"]);
    });
    afterAll(() => {
        (0, currencies_1.setSupportedCurrencies)([]);
    });
    beforeEach(() => {
        mockPlatformCompleteExchangeRequested.mockClear();
        uiNavigation.mockClear();
    });
    describe("when nominal case", () => {
        // Given
        const expectedResult = "Function called";
        beforeEach(() => uiNavigation.mockResolvedValueOnce(expectedResult));
        it("calls uiNavigation callback (token)", async () => {
            // Given
            const fromAccount = (0, cryptoCurrencies_1.createFixtureTokenAccount)("16");
            const fromParentAccount = (0, cryptoCurrencies_1.createFixtureAccount)("16");
            context.accounts = [...context.accounts, fromAccount, fromParentAccount];
            const rawPlatformTransaction = createRawEtherumTransaction();
            const completeExchangeRequest = {
                provider: "provider",
                fromAccountId: "js:2:ethereum:0x16:+ethereum%2Ferc20%2Fusd_tether__erc20_",
                toAccountId: "js:2:ethereum:0x042:",
                transaction: rawPlatformTransaction,
                binaryPayload: "binaryPayload",
                signature: "signature",
                feesStrategy: "medium",
                exchangeType: 8,
            };
            const expectedTransaction = {
                family: "evm",
                amount: new bignumber_js_1.default("1000000000"),
                subAccountId: "js:2:ethereum:0x16:+ethereum%2Ferc20%2Fusd_tether__erc20_",
                recipient: "0x0123456",
                nonce: 8,
                data: Buffer.from("Some data...", "hex"),
                type: 0,
                gasPrice: new bignumber_js_1.default("700000"),
                maxFeePerGas: undefined,
                maxPriorityFeePerGas: undefined,
                gasLimit: new bignumber_js_1.default("1200000"),
                customGasLimit: new bignumber_js_1.default("1200000"),
                feesStrategy: "medium",
                mode: "send",
                useAllAmount: false,
                chainId: 1,
            };
            // When
            const result = await (0, logic_1.completeExchangeLogic)(context, completeExchangeRequest, uiNavigation);
            // Then
            expect(uiNavigation).toBeCalledTimes(1);
            expect(uiNavigation.mock.calls[0][0]).toEqual({
                provider: "provider",
                exchange: {
                    fromAccount,
                    fromParentAccount,
                    fromCurrency: fromAccount.token,
                    toAccount: undefined,
                    toParentAccount: undefined,
                    toCurrency: undefined,
                },
                transaction: expectedTransaction,
                binaryPayload: "binaryPayload",
                signature: "signature",
                feesStrategy: "medium",
                exchangeType: 8,
            });
            expect(result).toEqual(expectedResult);
        });
        it("calls uiNavigation callback (coin)", async () => {
            // Given
            const fromAccount = (0, cryptoCurrencies_1.createFixtureAccount)("17");
            context.accounts = [...context.accounts, fromAccount];
            const rawPlatformTransaction = createRawEtherumTransaction();
            const completeExchangeRequest = {
                provider: "provider",
                fromAccountId: "js:2:ethereum:0x017:",
                toAccountId: "js:2:ethereum:0x042:",
                transaction: rawPlatformTransaction,
                binaryPayload: "binaryPayload",
                signature: "signature",
                feesStrategy: "medium",
                exchangeType: 8,
            };
            const expectedTransaction = {
                family: "evm",
                amount: new bignumber_js_1.default("1000000000"),
                recipient: "0x0123456",
                nonce: 8,
                data: Buffer.from("Some data...", "hex"),
                gasPrice: new bignumber_js_1.default("700000"),
                gasLimit: new bignumber_js_1.default("1200000"),
                customGasLimit: new bignumber_js_1.default("1200000"),
                feesStrategy: "medium",
                mode: "send",
                useAllAmount: false,
                chainId: 1,
                subAccountId: undefined,
                type: 0,
                maxFeePerGas: undefined,
                maxPriorityFeePerGas: undefined,
            };
            // When
            const result = await (0, logic_1.completeExchangeLogic)(context, completeExchangeRequest, uiNavigation);
            // Then
            expect(uiNavigation).toBeCalledTimes(1);
            expect(uiNavigation.mock.calls[0][0]).toEqual({
                provider: "provider",
                exchange: {
                    fromAccount,
                    fromParentAccount: undefined,
                    fromCurrency: fromAccount.currency,
                    toAccount: undefined,
                    toParentAccount: undefined,
                    toCurrency: undefined,
                },
                transaction: expectedTransaction,
                binaryPayload: "binaryPayload",
                signature: "signature",
                feesStrategy: "medium",
                exchangeType: 8,
            });
            expect(result).toEqual(expectedResult);
        });
        it.each(["slow", "medium", "fast", "custom"])("calls uiNavigation with a transaction that has the %s feeStrategy", async (expectedFeeStrategy) => {
            // Given
            const fromAccount = (0, cryptoCurrencies_1.createFixtureAccount)("17");
            context.accounts = [...context.accounts, fromAccount];
            const rawPlatformTransaction = createRawEtherumTransaction();
            const completeExchangeRequest = {
                provider: "provider",
                fromAccountId: "js:2:ethereum:0x017:",
                toAccountId: "js:2:ethereum:0x042:",
                transaction: rawPlatformTransaction,
                binaryPayload: "binaryPayload",
                signature: "signature",
                feesStrategy: expectedFeeStrategy,
                exchangeType: 8,
            };
            // When
            await (0, logic_1.completeExchangeLogic)(context, completeExchangeRequest, uiNavigation);
            // Then
            expect(uiNavigation).toBeCalledTimes(1);
            expect(uiNavigation.mock.calls[0][0]["transaction"].feesStrategy).toEqual(expectedFeeStrategy);
        });
        it("calls the tracking for success", async () => {
            // Given
            const completeExchangeRequest = {
                provider: "provider",
                fromAccountId: "js:2:ethereum:0x012:",
                toAccountId: "js:2:ethereum:0x042:",
                transaction: createRawEtherumTransaction(),
                binaryPayload: "binaryPayload",
                signature: "signature",
                feesStrategy: "feeStrategy",
                exchangeType: 8,
            };
            // When
            await (0, logic_1.completeExchangeLogic)(context, completeExchangeRequest, uiNavigation);
            // Then
            expect(mockPlatformCompleteExchangeRequested).toBeCalledTimes(1);
        });
    });
    describe("when Account is from a different family than the transaction", () => {
        // Given
        const expectedResult = "Function called";
        beforeEach(() => uiNavigation.mockResolvedValueOnce(expectedResult));
        it("returns an error", async () => {
            // Given
            const fromAccount = (0, cryptoCurrencies_1.createFixtureAccount)("17");
            context.accounts = [...context.accounts, fromAccount];
            const rawPlatformTransaction = createRawBitcoinTransaction();
            const completeExchangeRequest = {
                provider: "provider",
                fromAccountId: "js:2:ethereum:0x017:",
                toAccountId: "js:2:ethereum:0x042:",
                transaction: rawPlatformTransaction,
                binaryPayload: "binaryPayload",
                signature: "signature",
                feesStrategy: "feeStrategy",
                exchangeType: 8,
            };
            // When
            await expect(async () => {
                await (0, logic_1.completeExchangeLogic)(context, completeExchangeRequest, uiNavigation);
            }).rejects.toThrowError("Account and transaction must be from the same family");
            // Then
            expect(uiNavigation).toBeCalledTimes(0);
        });
    });
});
describe("broadcastTransactionLogic", () => {
    // Given
    const mockplatformBroadcastFail = jest.fn();
    const context = createContextContainingAccountId({
        platformBroadcastFail: mockplatformBroadcastFail,
    }, "11", "12");
    const uiNavigation = jest.fn();
    beforeEach(() => {
        mockplatformBroadcastFail.mockClear();
        uiNavigation.mockClear();
    });
    describe("when nominal case", () => {
        // Given
        const accountId = "js:2:ethereum:0x012:";
        const rawSignedTransaction = createSignedOperationRaw();
        it("calls uiNavigation callback with a signedOperation", async () => {
            // Given
            const expectedResult = "Function called";
            const signedOperation = createSignedOperation();
            jest
                .spyOn(serializers, "deserializePlatformSignedTransaction")
                .mockReturnValueOnce(signedOperation);
            uiNavigation.mockResolvedValueOnce(expectedResult);
            // When
            const result = await (0, logic_1.broadcastTransactionLogic)(context, accountId, rawSignedTransaction, uiNavigation);
            // Then
            expect(uiNavigation).toBeCalledTimes(1);
            expect(uiNavigation.mock.calls[0][2]).toEqual(signedOperation);
            expect(result).toEqual(expectedResult);
        });
        it("calls the tracking for success", async () => {
            // When
            await (0, logic_1.broadcastTransactionLogic)(context, accountId, rawSignedTransaction, uiNavigation);
            // Then
            expect(mockplatformBroadcastFail).toBeCalledTimes(0);
        });
    });
    describe("when account cannot be found", () => {
        // Given
        const nonFoundAccountId = "js:2:ethereum:0x010:";
        const rawSignedTransaction = createSignedOperationRaw();
        it("returns an error", async () => {
            // Given
            const expectedResult = "Function called";
            const signedOperation = createSignedOperation();
            jest
                .spyOn(serializers, "deserializePlatformSignedTransaction")
                .mockReturnValueOnce(signedOperation);
            uiNavigation.mockResolvedValueOnce(expectedResult);
            // When
            await expect(async () => {
                await (0, logic_1.broadcastTransactionLogic)(context, nonFoundAccountId, rawSignedTransaction, uiNavigation);
            }).rejects.toThrowError("Account required");
            // Then
            expect(uiNavigation).toBeCalledTimes(0);
        });
        it("calls the tracking for error", async () => {
            // When
            await expect(async () => {
                await (0, logic_1.broadcastTransactionLogic)(context, nonFoundAccountId, rawSignedTransaction, uiNavigation);
            }).rejects.toThrow();
            // Then
            expect(mockplatformBroadcastFail).toBeCalledTimes(1);
        });
    });
});
describe("signMessageLogic", () => {
    // Given
    const mockPlatformSignMessageRequested = jest.fn();
    const mockPlatformSignMessageFail = jest.fn();
    const context = createContextContainingAccountId({
        platformSignMessageRequested: mockPlatformSignMessageRequested,
        platformSignMessageFail: mockPlatformSignMessageFail,
    }, "11", "12");
    const uiNavigation = jest.fn();
    beforeEach(() => {
        mockPlatformSignMessageRequested.mockClear();
        mockPlatformSignMessageFail.mockClear();
        uiNavigation.mockClear();
    });
    describe("when nominal case", () => {
        // Given
        const accountId = "js:2:ethereum:0x012:";
        const messageToSign = "Message to sign";
        const spyPrepareMessageToSign = jest.spyOn(signMessage, "prepareMessageToSign");
        beforeEach(() => spyPrepareMessageToSign.mockClear());
        it("calls uiNavigation callback with a signedOperation", async () => {
            // Given
            const expectedResult = "Function called";
            const formattedMessage = createMessageData();
            spyPrepareMessageToSign.mockReturnValueOnce(formattedMessage);
            uiNavigation.mockResolvedValueOnce(expectedResult);
            // When
            const result = await (0, logic_1.signMessageLogic)(context, accountId, messageToSign, uiNavigation);
            // Then
            expect(uiNavigation).toBeCalledTimes(1);
            expect(uiNavigation.mock.calls[0][1]).toEqual(formattedMessage);
            expect(result).toEqual(expectedResult);
        });
        it("calls the tracking for success", async () => {
            // When
            await (0, logic_1.signMessageLogic)(context, accountId, messageToSign, uiNavigation);
            // Then
            expect(mockPlatformSignMessageRequested).toBeCalledTimes(1);
            expect(mockPlatformSignMessageFail).toBeCalledTimes(0);
        });
    });
    describe("when account cannot be found", () => {
        // Given
        const nonFoundAccountId = "js:2:ethereum:0x010:";
        const messageToSign = "Message to sign";
        it("returns an error", async () => {
            // When
            await expect(async () => {
                await (0, logic_1.signMessageLogic)(context, nonFoundAccountId, messageToSign, uiNavigation);
            }).rejects.toThrowError(`account with id "${nonFoundAccountId}" not found`);
            // Then
            expect(uiNavigation).toBeCalledTimes(0);
        });
        it("calls the tracking for error", async () => {
            // When
            await expect(async () => {
                await (0, logic_1.signMessageLogic)(context, nonFoundAccountId, messageToSign, uiNavigation);
            }).rejects.toThrow();
            // Then
            expect(mockPlatformSignMessageRequested).toBeCalledTimes(1);
            expect(mockPlatformSignMessageFail).toBeCalledTimes(1);
        });
    });
    describe("when account found is not of type 'Account'", () => {
        // Given
        const tokenAccountId = "15";
        const messageToSign = "Message to sign";
        context.accounts = [createTokenAccount(tokenAccountId), ...context.accounts];
        it("returns an error", async () => {
            // When
            await expect(async () => {
                await (0, logic_1.signMessageLogic)(context, tokenAccountId, messageToSign, uiNavigation);
            }).rejects.toThrowError("account provided should be the main one");
            // Then
            expect(uiNavigation).toBeCalledTimes(0);
        });
        it("calls the tracking for error", async () => {
            // When
            await expect(async () => {
                await (0, logic_1.signMessageLogic)(context, tokenAccountId, messageToSign, uiNavigation);
            }).rejects.toThrow();
            // Then
            expect(mockPlatformSignMessageRequested).toBeCalledTimes(1);
            expect(mockPlatformSignMessageFail).toBeCalledTimes(1);
        });
    });
    describe("when inner call prepareMessageToSign raise an error", () => {
        // Given
        const accountId = "js:2:ethereum:0x012:";
        const messageToSign = "Message to sign";
        const spyPrepareMessageToSign = jest.spyOn(signMessage, "prepareMessageToSign");
        beforeEach(() => spyPrepareMessageToSign.mockClear());
        it("returns an error", async () => {
            // Given
            spyPrepareMessageToSign.mockImplementationOnce(() => {
                throw new Error("Some error");
            });
            // When
            await expect(async () => {
                await (0, logic_1.signMessageLogic)(context, accountId, messageToSign, uiNavigation);
            }).rejects.toThrowError("Some error");
            // Then
            expect(uiNavigation).toBeCalledTimes(0);
        });
        it("calls the tracking for error", async () => {
            // Given
            spyPrepareMessageToSign.mockImplementationOnce(() => {
                throw new Error("Some error");
            });
            // When
            await expect(async () => {
                await (0, logic_1.signMessageLogic)(context, accountId, messageToSign, uiNavigation);
            }).rejects.toThrow();
            // Then
            expect(mockPlatformSignMessageRequested).toBeCalledTimes(1);
            expect(mockPlatformSignMessageFail).toBeCalledTimes(1);
        });
    });
});
function createAppManifest(id = "1") {
    return {
        id,
        private: false,
        name: "New App Manifest",
        url: "https://www.ledger.com",
        homepageUrl: "https://www.ledger.com",
        supportUrl: "https://www.ledger.com",
        icon: null,
        platforms: ["ios", "android", "desktop"],
        apiVersion: "1.0.0",
        manifestVersion: "1.0.0",
        branch: "debug",
        params: undefined,
        categories: [],
        currencies: "*",
        content: {
            shortDescription: {
                en: "short description",
            },
            description: {
                en: "description",
            },
        },
        permissions: [],
        domains: [],
        visibility: "complete",
    };
}
function createContextContainingAccountId(tracking, ...accountIds) {
    return {
        manifest: createAppManifest(),
        accounts: [...accountIds.map(val => (0, cryptoCurrencies_1.createFixtureAccount)(val)), (0, cryptoCurrencies_1.createFixtureAccount)()],
        tracking: tracking,
    };
}
function createSignedOperation() {
    const operation = {
        id: "42",
        hash: "hashed",
        type: "IN",
        value: new bignumber_js_1.default(0),
        fee: new bignumber_js_1.default(0),
        senders: [],
        recipients: [],
        blockHeight: null,
        blockHash: null,
        accountId: "14",
        date: new Date(),
        extra: {},
    };
    return {
        operation,
        signature: "Signature",
    };
}
function createSignedOperationRaw() {
    const rawOperation = {
        id: "12",
        hash: "123456",
        type: "CREATE",
        value: "0",
        fee: "0",
        senders: [],
        recipients: [],
        blockHeight: null,
        blockHash: null,
        accountId: "12",
        date: "01/01/1970",
        extra: {},
    };
    return {
        operation: rawOperation,
        signature: "Signature",
    };
}
function createPlatformAccount() {
    return {
        id: "12",
        name: "",
        address: "",
        currency: "",
        balance: new bignumber_js_1.default(0),
        spendableBalance: new bignumber_js_1.default(0),
        blockHeight: 0,
        lastSyncDate: new Date(),
    };
}
function createMessageData() {
    return {
        account: (0, cryptoCurrencies_1.createFixtureAccount)("17"),
        message: "default message",
    };
}
function createTokenAccount(id = "32") {
    return {
        type: "TokenAccount",
        id,
        parentId: "whatever",
        token: createTokenCurrency(),
        balance: new bignumber_js_1.default(0),
        spendableBalance: new bignumber_js_1.default(0),
        creationDate: new Date(),
        operationsCount: 0,
        operations: [],
        pendingOperations: [],
        balanceHistoryCache: {
            WEEK: { latestDate: null, balances: [] },
            HOUR: { latestDate: null, balances: [] },
            DAY: { latestDate: null, balances: [] },
        },
        swapHistory: [],
    };
}
function createTokenCurrency() {
    return {
        type: "TokenCurrency",
        id: "3",
        contractAddress: "",
        parentCurrency: (0, cryptoCurrencies_1.createFixtureCryptoCurrency)("eth"),
        tokenType: "",
        //-- CurrencyCommon
        name: "",
        ticker: "",
        units: [],
    };
}
function createRawEtherumTransaction() {
    return {
        family: "ethereum",
        amount: "1000000000",
        recipient: "0x0123456",
        nonce: 8,
        data: "Some data...",
        gasPrice: "700000",
        gasLimit: "1200000",
    };
}
function createRawBitcoinTransaction() {
    return {
        family: "bitcoin",
        amount: "1000000000",
        recipient: "0x0123456",
        feePerByte: "900000",
    };
}
//# sourceMappingURL=logic.test.js.map