"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const logs_1 = require("@ledgerhq/logs");
const rxjs_1 = require("rxjs");
const semver_1 = __importDefault(require("semver"));
const hw_app_exchange_1 = require("@ledgerhq/hw-app-exchange");
const deviceAccess_1 = require("../../hw/deviceAccess");
const providers_1 = require("../providers");
const withDevicePromise = (deviceId, fn) => (0, rxjs_1.firstValueFrom)((0, deviceAccess_1.withDevice)(deviceId)(transport => (0, rxjs_1.from)(fn(transport))));
const startExchange = (input) => {
    return new rxjs_1.Observable(o => {
        let unsubscribed = false;
        const { device, exchangeType, appVersion, provider } = input;
        const startExchangeAsync = async () => {
            await withDevicePromise(device.deviceId, async (transport) => {
                (0, logs_1.log)("exchange", `attempt to connect to ${device.deviceId}`);
                let version;
                if (unsubscribed)
                    return;
                if (provider) {
                    switch (exchangeType) {
                        case 0 /* ExchangeTypes.Swap */: {
                            const providerConfig = await (0, providers_1.getSwapProvider)(provider);
                            if (providerConfig.useInExchangeApp === false) {
                                throw new Error(`Unsupported provider type ${providerConfig.type}`);
                            }
                            version = providerConfig.version;
                            break;
                        }
                        default: {
                            const providerConfig = await (0, providers_1.getProviderConfig)(exchangeType, provider);
                            version = providerConfig.version;
                        }
                    }
                }
                if (!checkNgPrerequisite(exchangeType, appVersion)) {
                    throw new Error("Incompatible AppExchange version with NG command");
                }
                /**
                 * Note: `transactionRate` is not needed at this stage. It is only used
                 * at the `completeExchange` step
                 */
                const exchange = (0, hw_app_exchange_1.createExchange)(transport, exchangeType, undefined, version);
                const nonce = await exchange.startNewTransaction();
                o.next({
                    type: "start-exchange-result",
                    startExchangeResult: { nonce, device },
                });
            });
        };
        startExchangeAsync().then(() => {
            o.complete();
            unsubscribed = true;
        }, error => {
            o.next({
                type: "start-exchange-error",
                startExchangeError: { error, device },
            });
            o.complete();
            unsubscribed = true;
        });
        return () => {
            unsubscribed = true;
        };
    });
};
// AppExchange Min version supporting NG types
const MIN_APP_EXCHANGE_NG = "3.3.0";
/**
 * If the App-Exchnage version is not high enough, "NG" type can't worked
 */
function checkNgPrerequisite(exchangeType, appVersion) {
    if ((0, hw_app_exchange_1.isExchangeTypeNg)(exchangeType) && appVersion && semver_1.default.lt(appVersion, MIN_APP_EXCHANGE_NG)) {
        return false;
    }
    return true;
}
exports.default = startExchange;
//# sourceMappingURL=startExchange.js.map