"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Api = void 0;
const react_1 = __importStar(require("react"));
const react_router_dom_1 = require("react-router-dom");
const react_error_boundary_1 = require("react-error-boundary");
const ui_keyring_1 = __importDefault(require("@polkadot/ui-keyring"));
const extension_dapp_1 = require("@polkadot/extension-dapp");
const polymesh_sdk_1 = require("@polymathnetwork/polymesh-sdk");
const polymesh_ui_1 = require("@polymathnetwork/polymesh-ui");
const lodash_orderby_1 = __importDefault(require("lodash.orderby"));
const getChainProperties_1 = require("../utils/getChainProperties");
const keyLabelStorage_1 = require("../utils/keyLabelStorage");
const constants_1 = require("../data/constants");
const definition_1 = require("./definition");
const requiredReduxActions = [
    'setSdk',
    'setSelectedAccount',
    'setDid',
    'setHasUid',
    'setIsITN',
    'setPolyWallet',
    'setChainProperties',
];
const delay = (ms) => __awaiter(void 0, void 0, void 0, function* () { return new Promise((resolve) => setTimeout(resolve, ms)); });
let network;
let polyWallet;
exports.Api = ({ children, redux, appName, apiConfig }) => {
    const [isReady, setIsReady] = react_1.useState(false);
    const handleError = react_error_boundary_1.useErrorHandler();
    const history = react_router_dom_1.useHistory();
    const { appStateActions, store } = redux;
    const { dispatch } = store;
    const { polyWssNodeUrl, graphqlEndpoint, graphqlApiKey, masqueradeEnv, isProdEnv, rpcUrl, } = apiConfig;
    react_1.useEffect(() => {
        const { search } = window.location;
        const params = new URLSearchParams(search);
        const masqueradeQuery = params.get('masq');
        const masquerade = masqueradeQuery || masqueradeEnv;
        function connect(address, keyring, signer) {
            return __awaiter(this, void 0, void 0, function* () {
                dispatch(appStateActions.setSelectedAccount(address));
                const sdk = yield polymesh_sdk_1.Polymesh.connect({
                    nodeUrl: polyWssNodeUrl,
                    signer,
                    keyring,
                    middleware: {
                        link: graphqlEndpoint,
                        key: graphqlApiKey,
                    },
                });
                dispatch(appStateActions.setSdk(sdk));
                setIsReady(true);
                try {
                    const identity = yield sdk.getCurrentIdentity();
                    if (identity) {
                        const hasUid = yield polyWallet.uid.isSet();
                        dispatch(appStateActions.setHasUid(hasUid));
                        if (network !== constants_1.NetworkName.itn && !hasUid) {
                            history.push(definition_1.AppStaticRoute.uIdMissing, {
                                polyWallet,
                                did: identity.did,
                                network,
                            });
                        }
                        const didIsValid = yield sdk.isIdentityValid({
                            identity: identity.did,
                        });
                        const cddAttestations = yield sdk.claims.getCddClaims({
                            target: identity,
                        });
                        const cddAttestation = lodash_orderby_1.default(cddAttestations, ['expiry'], ['desc'])[0];
                        dispatch(appStateActions.setDid({
                            identity,
                            didIsValid,
                            issuer: cddAttestation === null || cddAttestation === void 0 ? void 0 : cddAttestation.issuer,
                            expiry: (cddAttestation === null || cddAttestation === void 0 ? void 0 : cddAttestation.expiry) || undefined,
                        }));
                    }
                    else {
                        dispatch(appStateActions.setDid({
                            didIsValid: false,
                        }));
                    }
                }
                catch (error) {
                    dispatch(appStateActions.setDid({
                        didIsValid: false,
                    }));
                }
            });
        }
        function init() {
            return __awaiter(this, void 0, void 0, function* () {
                try {
                    yield delay(500);
                    const extensions = yield extension_dapp_1.web3Enable(appName);
                    if (!masquerade && (!extensions || extensions.length === 0)) {
                        history.push(definition_1.AppStaticRoute.extension);
                    }
                    polyWallet = extensions.filter((ext) => ext.name === 'polywallet')[0];
                    if (polyWallet) {
                        dispatch(appStateActions.setPolyWallet(polyWallet));
                        const networkMeta = yield polyWallet.network.get();
                        const cleanEndpoint = networkMeta.wssUrl.replace(/\/$/, '');
                        const cleanUrl = polyWssNodeUrl.replace(/\/$/, '');
                        if (cleanUrl !== cleanEndpoint) {
                            history.push(definition_1.AppStaticRoute.wrongNetwork);
                        }
                        network = networkMeta.name;
                        dispatch(appStateActions.setIsITN(network === constants_1.NetworkName.itn));
                        if (window.location.hostname !== 'localhost') {
                            polyWallet.network.subscribe(() => {
                                window.location.reload();
                            });
                            polyWallet.accounts.subscribe(() => {
                                window.location.reload();
                            });
                        }
                    }
                    else if (!masquerade) {
                        history.push(definition_1.AppStaticRoute.extension);
                    }
                    const chainProperties = yield getChainProperties_1.getChainProperties(rpcUrl);
                    dispatch(appStateActions.setChainProperties(chainProperties));
                    const { ss58Format } = chainProperties;
                    const keyring = new polymesh_sdk_1.Keyring({ type: 'ed25519', ss58Format });
                    let address;
                    let signer;
                    if (masquerade && !isProdEnv) {
                        try {
                            ui_keyring_1.default.loadAll({
                                type: 'ed25519',
                                isDevelopment: true,
                            });
                        }
                        catch (error) {
                            // This try-catch is needed to enable use of browser navigation buttons.
                            // You can't initialize `keyring` more than once, and using an `if` statement
                            // broke things because it couldn't find the test account `alice`.
                        }
                        const allTestingPairs = ui_keyring_1.default.getPairs();
                        const testingAccountPair = allTestingPairs.filter(({ meta: { name, isTesting } }) => name === masquerade && isTesting === true)[0];
                        keyring.addPair(testingAccountPair);
                        if (testingAccountPair) {
                            address = testingAccountPair.address;
                            connect(address, keyring, signer);
                        }
                        else {
                            throw new Error(`Couldn't find test account ${masquerade}`);
                        }
                    }
                    else {
                        const accounts = (yield extension_dapp_1.web3Accounts({ ss58Format })).filter((account) => account.meta.source === 'polywallet');
                        if (accounts[0]) {
                            const account = accounts === null || accounts === void 0 ? void 0 : accounts[0];
                            if (!account)
                                throw new Error('Account not found');
                            address = account.address;
                            if (account.meta.name)
                                keyLabelStorage_1.keyLabel.save(address, account.meta.name);
                            keyring.addFromAddress(address);
                            const injector = yield extension_dapp_1.web3FromAddress(address);
                            signer = injector.signer;
                            connect(address, keyring, signer);
                        }
                    }
                }
                catch (error) {
                    // Display error via ErrorBoundary fallback component.
                    handleError(error);
                }
            });
        }
        const providedReduxActions = Object.keys(appStateActions);
        const missingReduxActions = requiredReduxActions.filter((a) => !providedReduxActions.includes(a));
        if (missingReduxActions.length) {
            throw new Error(`Missing Redux actions for API to init: ${missingReduxActions.join(', ')}`);
        }
        else {
            init();
        }
    }, []); // eslint-disable-line
    if (isReady)
        return children;
    else
        return react_1.default.createElement(polymesh_ui_1.LoadingScreen, null);
};
//# sourceMappingURL=Api.js.map