"use strict";
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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("../../../../chai");
const api_1 = require("@polkadot/api");
const factory_1 = require("../../../../../src/factory");
const config_1 = require("../../../../config");
const src_1 = require("../../../../../src");
const storage_1 = require("../../../../../src/utils/storage");
const helpers_1 = require("../../../../utils/helpers");
describe("AssetRegistry", () => {
    let api;
    let interBtcAPI;
    let sudoAccount;
    let assetRegistryMetadataHash;
    let registeredKeysBefore = [];
    before(() => __awaiter(void 0, void 0, void 0, function* () {
        const keyring = new api_1.Keyring({ type: "sr25519" });
        api = yield factory_1.createSubstrateAPI(config_1.PARACHAIN_ENDPOINT);
        sudoAccount = keyring.addFromUri(config_1.SUDO_URI);
        interBtcAPI = new src_1.DefaultInterBtcApi(api, "regtest", sudoAccount, config_1.ESPLORA_BASE_PATH);
        assetRegistryMetadataHash = storage_1.getStorageKey("AssetRegistry", "Metadata");
        // check which keys exist before the tests
        const keys = yield interBtcAPI.api.rpc.state.getKeys(assetRegistryMetadataHash);
        registeredKeysBefore = keys.toArray();
    }));
    after(() => __awaiter(void 0, void 0, void 0, function* () {
        // clean up keys created in tests if necessary
        const registeredKeysAfter = (yield interBtcAPI.api.rpc.state.getKeys(assetRegistryMetadataHash)).toArray();
        const previousKeyHashes = registeredKeysBefore.map((key) => src_1.stripHexPrefix(key.toHex()));
        // need to use string comparison since the raw StorageKeys don't play nicely with .filter()
        const newKeys = registeredKeysAfter.filter((key) => {
            const newKeyHash = src_1.stripHexPrefix(key.toHex());
            return !previousKeyHashes.includes(newKeyHash);
        });
        if (newKeys.length > 0) {
            // clean up assets registered in test(s)
            const deleteKeysInstruction = interBtcAPI.api.tx.system.killStorage(newKeys);
            yield interBtcAPI.api.tx.sudo.sudo(deleteKeysInstruction).signAndSend(sudoAccount);
            // wait for finalized event
            yield helpers_1.waitForIncludedEvent(interBtcAPI, api.events.sudo.Sudid);
        }
        return api.disconnect();
    }));
    /**
     * This test checks that the returned metadata from the chain has all the fields we need to construct
     * a `Currency` object.
     * To see the fields required, take a look at {@link DefaultAssetRegistryAPI.metadataToCurrency}.
     *
     * Note: More detailed tests around the internal logic are in the unit tests.
     */
    it("should get expected shape of AssetRegistry metadata", () => __awaiter(void 0, void 0, void 0, function* () {
        var _a, _b;
        // check if any assets have been registered
        const existingKeys = (yield interBtcAPI.api.rpc.state.getKeys(assetRegistryMetadataHash)).toArray();
        if (existingKeys.length === 0) {
            // no existing foreign assets; register a new foreign asset for the test
            const nextAssetId = (yield interBtcAPI.api.query.assetRegistry.lastAssetId()).toNumber() + 1;
            const callToRegister = interBtcAPI.api.tx.assetRegistry.registerAsset({
                decimals: 6,
                name: "Test coin",
                symbol: "TSC",
            }, api.createType("u32", nextAssetId));
            // need sudo to add new foreign asset
            yield interBtcAPI.api.tx.sudo.sudo(callToRegister).signAndSend(sudoAccount);
            yield helpers_1.waitForIncludedEvent(interBtcAPI, api.events.sudo.Sudid);
        }
        // get the metadata for the asset we just registered
        const assetRegistryAPI = new src_1.DefaultAssetRegistryAPI(api);
        const foreignAssetEntries = yield assetRegistryAPI.getAssetRegistryEntries();
        const unwrappedMetadataTupleArray = src_1.DefaultAssetRegistryAPI.unwrapMetadataFromEntries(foreignAssetEntries);
        // now check that we have the fields we absolutely need on the returned metadata
        // check {@link DefaultAssetRegistryAPI.metadataToCurrency} to see which fields are needed.
        const requiredFieldClassnames = new Map([
            ["name", "Bytes"],
            ["symbol", "Bytes"],
            ["decimals", "u32"],
        ]);
        for (const [storageKey, metadata] of unwrappedMetadataTupleArray) {
            chai_1.assert.isDefined(metadata, "Expected metadata to be defined, but it is not.");
            chai_1.assert.isDefined(storageKey, "Expected storage key to be defined, but it is not.");
            const storageKeyValue = src_1.storageKeyToNthInner(storageKey);
            chai_1.assert.isDefined(storageKeyValue, "Expected storage key can be decoded but it cannot.");
            for (const [key, className] of requiredFieldClassnames) {
                chai_1.assert.isDefined(metadata[key], `Expected metadata to have field ${key.toString()}, but it does not.`);
                // check type
                chai_1.assert.equal((_a = metadata[key]) === null || _a === void 0 ? void 0 : _a.constructor.name, className, `Expected metadata to have field ${key.toString()} of type ${className}, 
                    but its type is ${(_b = metadata[key]) === null || _b === void 0 ? void 0 : _b.constructor.name}.`);
            }
        }
    })).timeout(3 * 60000);
});
//# sourceMappingURL=asset-registry.test.js.map