import { log } from "@ledgerhq/logs";
import { Observable, firstValueFrom, from } from "rxjs";
import semver from "semver";
import { createExchange, isExchangeTypeNg } from "@ledgerhq/hw-app-exchange";
import { withDevice } from "../../hw/deviceAccess";
import { getProviderConfig, getSwapProvider } from "../providers";
const withDevicePromise = (deviceId, fn) => firstValueFrom(withDevice(deviceId)(transport => from(fn(transport))));
const startExchange = (input) => {
    return new Observable(o => {
        let unsubscribed = false;
        const { device, exchangeType, appVersion, provider } = input;
        const startExchangeAsync = async () => {
            await withDevicePromise(device.deviceId, async (transport) => {
                log("exchange", `attempt to connect to ${device.deviceId}`);
                let version;
                if (unsubscribed)
                    return;
                if (provider) {
                    switch (exchangeType) {
                        case 0 /* ExchangeTypes.Swap */: {
                            const providerConfig = await getSwapProvider(provider);
                            if (providerConfig.useInExchangeApp === false) {
                                throw new Error(`Unsupported provider type ${providerConfig.type}`);
                            }
                            version = providerConfig.version;
                            break;
                        }
                        default: {
                            const providerConfig = await 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 = 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 (isExchangeTypeNg(exchangeType) && appVersion && semver.lt(appVersion, MIN_APP_EXCHANGE_NG)) {
        return false;
    }
    return true;
}
export default startExchange;
//# sourceMappingURL=startExchange.js.map