"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.permissionGroupIdentifierToAgentGroup = exports.u8ToBigNumber = exports.u16ToBigNumber = exports.u32ToBigNumber = exports.bigNumberToU32 = exports.meshPermissionsToPermissions = exports.extrinsicPermissionsToTransactionPermissions = exports.permissionsToMeshPermissions = exports.transactionPermissionsToExtrinsicPermissions = exports.transactionPermissionsToTxGroups = exports.txGroupToTxTags = exports.textToString = exports.stringToText = exports.portfolioIdToMeshPortfolioId = exports.portfolioLikeToPortfolio = exports.portfolioIdToPortfolio = exports.portfolioLikeToPortfolioId = exports.portfolioToPortfolioId = exports.meshPortfolioIdToPortfolio = exports.permillToBigNumber = exports.percentageToPermill = exports.bigNumberToU128 = exports.bigNumberToU64 = exports.u128ToBigNumber = exports.u64ToBigNumber = exports.signerToString = exports.signerValueToSigner = exports.signerToSignerValue = exports.signatoryToSignerValue = exports.signerValueToSignatory = exports.accountIdToAccount = exports.stringToEcdsaSignature = exports.identityIdToString = exports.stringToIdentityId = exports.stringToBlockHash = exports.stringToHash = exports.hashToString = exports.accountIdToString = exports.stringToAccountId = exports.momentToDate = exports.dateToMoment = exports.stringToInvestorZKProofData = exports.tickerToString = exports.stringToTickerKey = exports.stringToTicker = exports.bytesToString = exports.stringToBytes = exports.boolToBoolean = exports.booleanToBool = exports.tickerToDid = void 0;
exports.transactionHexToTxTag = exports.addressToKey = exports.keyToAddress = exports.moduleAddressToString = exports.assetComplianceResultToCompliance = exports.extrinsicIdentifierToTxTag = exports.txTagToExtrinsicIdentifier = exports.txTagToProtocolOp = exports.complianceRequirementToRequirement = exports.complianceRequirementResultToRequirementCompliance = exports.requirementToComplianceRequirement = exports.trustedClaimIssuerToTrustedIssuer = exports.trustedIssuerToTrustedClaimIssuer = exports.meshClaimTypeToClaimType = exports.stringToTargetIdentity = exports.meshClaimToClaim = exports.middlewareEventToEventIdentifier = exports.scopeToMiddlewareScope = exports.middlewareScopeToScope = exports.claimToMeshClaim = exports.scopeIdToString = exports.stringToScopeId = exports.cddIdToString = exports.stringToCddId = exports.meshScopeToScope = exports.scopeToMeshScope = exports.canTransferResultToTransferStatus = exports.cddStatusToBoolean = exports.documentToAssetDocument = exports.assetDocumentToDocument = exports.documentHashToString = exports.stringToDocumentHash = exports.assetIdentifierToSecurityIdentifier = exports.securityIdentifierToAssetIdentifier = exports.isFigiValid = exports.isLeiValid = exports.isCusipValid = exports.isIsinValid = exports.posRatioToBigNumber = exports.assetTypeToKnownOrId = exports.internalAssetTypeToAssetType = exports.u8ToTransferStatus = exports.stringToMemo = exports.authorizationDataToAuthorization = exports.agentGroupToPermissionGroup = exports.balanceToBigNumber = exports.bigNumberToBalance = exports.authorizationTypeToMeshAuthorizationType = exports.authorizationToAuthorizationData = exports.agentGroupToPermissionGroupIdentifier = void 0;
exports.toExemptKey = exports.complianceConditionsToBtreeSet = exports.createStat2ndKey = exports.statisticsOpTypeToStatOpType = exports.meshStatToStatisticsOpType = exports.statUpdatesToBtreeStatUpdate = exports.statUpdate = exports.statisticsOpTypeToStatType = exports.corporateActionIdentifierToCaId = exports.distributionToDividendDistributionParams = exports.targetsToTargetIdentities = exports.targetIdentitiesToCorporateActionTargets = exports.scopeClaimProofToConfidentialIdentityClaimProof = exports.checkpointToRecordDateSpec = exports.stringToScalar = exports.corporateActionKindToCaKind = exports.stringToRistrettoPoint = exports.meshCorporateActionToCorporateActionParams = exports.stringToSignature = exports.storedScheduleToCheckpointScheduleParams = exports.scheduleSpecToMeshScheduleSpec = exports.meshCalendarPeriodToCalendarPeriod = exports.calendarPeriodToMeshCalendarPeriod = exports.fundraiserToOfferingDetails = exports.fundraiserTierToTier = exports.middlewarePortfolioToPortfolio = exports.permissionsLikeToPermissions = exports.offeringTierToPriceTier = exports.granularCanTransferResultToTransferBreakdown = exports.transferConditionToTransferRestriction = exports.scopeIdsToBtreeSetIdentityId = exports.transferRestrictionToPolymeshTransferCondition = exports.claimTypeToMeshClaimType = exports.portfolioMovementToMovePortfolioItem = exports.toIdentityWithClaimsArray = exports.endConditionToSettlementType = exports.meshAffirmationStatusToAffirmationStatus = exports.meshInstructionStatusToInstructionStatus = exports.venueTypeToMeshVenueType = exports.meshVenueTypeToVenueType = exports.secondaryAccountToMeshSecondaryKey = exports.transactionToTxTag = void 0;
const util_1 = require("@polkadot/util");
const util_crypto_1 = require("@polkadot/util-crypto");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const iso_7064_1 = require("iso-7064");
const lodash_1 = require("lodash");
const utils_1 = require("../generated/utils");
const internal_1 = require("../internal");
const types_1 = require("../middleware/types");
const types_2 = require("../types");
const internal_2 = require("../types/internal");
const utils_2 = require("../types/utils");
const constants_1 = require("./constants");
const internal_3 = require("./internal");
const typeguards_1 = require("./typeguards");
__exportStar(require("../generated/utils"), exports);
/**
 * Generate an Asset's DID from a ticker
 */
function tickerToDid(ticker) {
    return (0, util_crypto_1.blake2AsHex)((0, util_1.u8aConcat)((0, util_1.stringToU8a)('SECURITY_TOKEN:'), (0, util_1.u8aFixLength)((0, util_1.stringToU8a)(ticker), 96, true)));
}
exports.tickerToDid = tickerToDid;
/**
 * @hidden
 */
function booleanToBool(value, context) {
    return context.createType('bool', value);
}
exports.booleanToBool = booleanToBool;
/**
 * @hidden
 */
function boolToBoolean(value) {
    return value.isTrue;
}
exports.boolToBoolean = boolToBoolean;
/**
 * @hidden
 */
function stringToBytes(bytes, context) {
    return context.createType('Bytes', bytes);
}
exports.stringToBytes = stringToBytes;
/**
 * @hidden
 */
function bytesToString(bytes) {
    return (0, util_1.u8aToString)(bytes);
}
exports.bytesToString = bytesToString;
/**
 * @hidden
 */
function stringToTicker(ticker, context) {
    if (!ticker.length || ticker.length > constants_1.MAX_TICKER_LENGTH) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: `Ticker length must be between 1 and ${constants_1.MAX_TICKER_LENGTH} characters`,
        });
    }
    if (!(0, internal_3.isPrintableAscii)(ticker)) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: 'Only printable ASCII is allowed as ticker name',
        });
    }
    if (ticker !== ticker.toUpperCase()) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: 'Ticker cannot contain lower case letters',
        });
    }
    return context.createType('PolymeshPrimitivesTicker', (0, internal_3.padString)(ticker, constants_1.MAX_TICKER_LENGTH));
}
exports.stringToTicker = stringToTicker;
/**
 * @hidden
 */
function stringToTickerKey(ticker, context) {
    return { Ticker: stringToTicker(ticker, context) };
}
exports.stringToTickerKey = stringToTickerKey;
/**
 * @hidden
 */
function tickerToString(ticker) {
    return (0, internal_3.removePadding)((0, util_1.u8aToString)(ticker));
}
exports.tickerToString = tickerToString;
/* eslint-disable @typescript-eslint/naming-convention */
/**
 * @hidden
 */
function stringToInvestorZKProofData(proof, context) {
    return context.createType('InvestorZKProofData', proof);
}
exports.stringToInvestorZKProofData = stringToInvestorZKProofData;
/* eslint-enable @typescript-eslint/naming-convention */
/**
 * @hidden
 */
function dateToMoment(date, context) {
    return context.createType('u64', date.getTime());
}
exports.dateToMoment = dateToMoment;
/**
 * @hidden
 */
function momentToDate(moment) {
    return new Date(moment.toNumber());
}
exports.momentToDate = momentToDate;
/**
 * @hidden
 */
function stringToAccountId(accountId, context) {
    (0, internal_3.assertAddressValid)(accountId, context.ss58Format);
    return context.createType('AccountId', accountId);
}
exports.stringToAccountId = stringToAccountId;
/**
 * @hidden
 */
function accountIdToString(accountId) {
    return accountId.toString();
}
exports.accountIdToString = accountIdToString;
/**
 * @hidden
 */
function hashToString(hash) {
    return hash.toString();
}
exports.hashToString = hashToString;
/**
 * @hidden
 */
function stringToHash(hash, context) {
    return context.createType('Hash', hash);
}
exports.stringToHash = stringToHash;
/**
 * @hidden
 */
function stringToBlockHash(blockHash, context) {
    return context.createType('BlockHash', blockHash);
}
exports.stringToBlockHash = stringToBlockHash;
/**
 * @hidden
 */
function stringToIdentityId(identityId, context) {
    return context.createType('PolymeshPrimitivesIdentityId', identityId);
}
exports.stringToIdentityId = stringToIdentityId;
/**
 * @hidden
 */
function identityIdToString(identityId) {
    return identityId.toString();
}
exports.identityIdToString = identityIdToString;
/**
 * @hidden
 */
function stringToEcdsaSignature(signature, context) {
    return context.createType('EcdsaSignature', signature);
}
exports.stringToEcdsaSignature = stringToEcdsaSignature;
/**
 * @hidden
 */
function accountIdToAccount(accountId, context) {
    return new internal_1.Account({ address: accountId.toString() }, context);
}
exports.accountIdToAccount = accountIdToAccount;
/**
 * @hidden
 */
function signerValueToSignatory(signer, context) {
    return context.createType('Signatory', {
        [signer.type]: signer.value,
    });
}
exports.signerValueToSignatory = signerValueToSignatory;
/**
 * @hidden
 */
function createSignerValue(type, value) {
    return {
        type,
        value,
    };
}
/**
 * @hidden
 */
function signatoryToSignerValue(signatory) {
    if (signatory.isAccount) {
        return createSignerValue(types_2.SignerType.Account, accountIdToString(signatory.asAccount));
    }
    return createSignerValue(types_2.SignerType.Identity, identityIdToString(signatory.asIdentity));
}
exports.signatoryToSignerValue = signatoryToSignerValue;
/**
 * @hidden
 */
function signerToSignerValue(signer) {
    if (signer instanceof internal_1.Account) {
        return createSignerValue(types_2.SignerType.Account, signer.address);
    }
    return createSignerValue(types_2.SignerType.Identity, signer.did);
}
exports.signerToSignerValue = signerToSignerValue;
/**
 * @hidden
 */
function signerValueToSigner(signerValue, context) {
    const { type, value } = signerValue;
    if (type === types_2.SignerType.Account) {
        return new internal_1.Account({ address: value }, context);
    }
    return new internal_1.Identity({ did: value }, context);
}
exports.signerValueToSigner = signerValueToSigner;
/**
 * @hidden
 */
function signerToString(signer) {
    if (typeof signer === 'string') {
        return signer;
    }
    return signerToSignerValue(signer).value;
}
exports.signerToString = signerToString;
/**
 * @hidden
 */
function u64ToBigNumber(value) {
    return new bignumber_js_1.default(value.toString());
}
exports.u64ToBigNumber = u64ToBigNumber;
/**
 * @hidden
 */
function u128ToBigNumber(value) {
    return new bignumber_js_1.default(value.toString());
}
exports.u128ToBigNumber = u128ToBigNumber;
/**
 * @hidden
 */
function bigNumberToU64(value, context) {
    (0, internal_3.assertIsInteger)(value);
    (0, internal_3.assertIsPositive)(value);
    return context.createType('u64', value.toString());
}
exports.bigNumberToU64 = bigNumberToU64;
/**
 * @hidden
 */
function bigNumberToU128(value, context) {
    (0, internal_3.assertIsInteger)(value);
    (0, internal_3.assertIsPositive)(value);
    return context.createType('u128', value.toString());
}
exports.bigNumberToU128 = bigNumberToU128;
/**
 * @hidden
 */
function percentageToPermill(value, context) {
    (0, internal_3.assertIsPositive)(value);
    if (value.gt(100)) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: "Percentage shouldn't exceed 100",
        });
    }
    return context.createType('Permill', value.shiftedBy(4).toString()); // (value : 100) * 10^6
}
exports.percentageToPermill = percentageToPermill;
/**
 * @hidden
 *
 * @note returns a percentage value ([0, 100])
 */
function permillToBigNumber(value) {
    return new bignumber_js_1.default(value.toString()).shiftedBy(-4); // (value : 10^6) * 100
}
exports.permillToBigNumber = permillToBigNumber;
/**
 * @hidden
 */
function meshPortfolioIdToPortfolio(portfolioId, context) {
    const { did, kind } = portfolioId;
    const identityId = identityIdToString(did);
    if (kind.isDefault) {
        return new internal_1.DefaultPortfolio({ did: identityId }, context);
    }
    return new internal_1.NumberedPortfolio({ did: identityId, id: u64ToBigNumber(kind.asUser) }, context);
}
exports.meshPortfolioIdToPortfolio = meshPortfolioIdToPortfolio;
/**
 * @hidden
 */
function portfolioToPortfolioId(portfolio) {
    const { owner: { did }, } = portfolio;
    if (portfolio instanceof internal_1.DefaultPortfolio) {
        return { did };
    }
    else {
        const { id: number } = portfolio;
        return { did, number };
    }
}
exports.portfolioToPortfolioId = portfolioToPortfolioId;
/**
 * @hidden
 */
function portfolioLikeToPortfolioId(value) {
    let did;
    let number;
    if (typeof value === 'string') {
        did = value;
    }
    else if (value instanceof internal_1.Identity) {
        ({ did } = value);
    }
    else if (value instanceof internal_1.Portfolio) {
        ({ did, number } = portfolioToPortfolioId(value));
    }
    else {
        const { identity: valueIdentity } = value;
        ({ id: number } = value);
        did = (0, internal_3.asDid)(valueIdentity);
    }
    return { did, number };
}
exports.portfolioLikeToPortfolioId = portfolioLikeToPortfolioId;
/**
 * @hidden
 */
function portfolioIdToPortfolio(portfolioId, context) {
    const { did, number } = portfolioId;
    return number
        ? new internal_1.NumberedPortfolio({ did, id: number }, context)
        : new internal_1.DefaultPortfolio({ did }, context);
}
exports.portfolioIdToPortfolio = portfolioIdToPortfolio;
/**
 * @hidden
 */
function portfolioLikeToPortfolio(value, context) {
    return portfolioIdToPortfolio(portfolioLikeToPortfolioId(value), context);
}
exports.portfolioLikeToPortfolio = portfolioLikeToPortfolio;
/**
 * @hidden
 */
function portfolioIdToMeshPortfolioId(portfolioId, context) {
    const { did, number } = portfolioId;
    return context.createType('PortfolioId', {
        did: stringToIdentityId(did, context),
        kind: number ? { User: bigNumberToU64(number, context) } : 'Default',
    });
}
exports.portfolioIdToMeshPortfolioId = portfolioIdToMeshPortfolioId;
/**
 * @hidden
 */
function stringToText(text, context) {
    return context.createType('Text', text);
}
exports.stringToText = stringToText;
/**
 * @hidden
 */
function textToString(value) {
    return value.toString();
}
exports.textToString = textToString;
/**
 * Retrieve every Transaction Tag associated to a Transaction Group
 */
function txGroupToTxTags(group) {
    switch (group) {
        case types_2.TxGroup.PortfolioManagement: {
            return [
                types_2.TxTags.identity.AddInvestorUniquenessClaim,
                types_2.TxTags.portfolio.MovePortfolioFunds,
                types_2.TxTags.settlement.AddInstruction,
                types_2.TxTags.settlement.AddAndAffirmInstruction,
                types_2.TxTags.settlement.AffirmInstruction,
                types_2.TxTags.settlement.RejectInstruction,
                types_2.TxTags.settlement.CreateVenue,
            ];
        }
        case types_2.TxGroup.AssetManagement: {
            return [
                types_2.TxTags.asset.MakeDivisible,
                types_2.TxTags.asset.RenameAsset,
                types_2.TxTags.asset.SetFundingRound,
                types_2.TxTags.asset.AddDocuments,
                types_2.TxTags.asset.RemoveDocuments,
            ];
        }
        case types_2.TxGroup.AdvancedAssetManagement: {
            return [
                types_2.TxTags.asset.Freeze,
                types_2.TxTags.asset.Unfreeze,
                types_2.TxTags.identity.AddAuthorization,
                types_2.TxTags.identity.RemoveAuthorization,
            ];
        }
        case types_2.TxGroup.Distribution: {
            return [
                types_2.TxTags.identity.AddInvestorUniquenessClaim,
                types_2.TxTags.settlement.CreateVenue,
                types_2.TxTags.settlement.AddInstruction,
                types_2.TxTags.settlement.AddAndAffirmInstruction,
            ];
        }
        case types_2.TxGroup.Issuance: {
            return [types_2.TxTags.asset.Issue];
        }
        case types_2.TxGroup.TrustedClaimIssuersManagement: {
            return [
                types_2.TxTags.complianceManager.AddDefaultTrustedClaimIssuer,
                types_2.TxTags.complianceManager.RemoveDefaultTrustedClaimIssuer,
            ];
        }
        case types_2.TxGroup.ClaimsManagement: {
            return [types_2.TxTags.identity.AddClaim, types_2.TxTags.identity.RevokeClaim];
        }
        case types_2.TxGroup.ComplianceRequirementsManagement: {
            return [
                types_2.TxTags.complianceManager.AddComplianceRequirement,
                types_2.TxTags.complianceManager.RemoveComplianceRequirement,
                types_2.TxTags.complianceManager.PauseAssetCompliance,
                types_2.TxTags.complianceManager.ResumeAssetCompliance,
                types_2.TxTags.complianceManager.ResetAssetCompliance,
            ];
        }
        case types_2.TxGroup.CorporateActionsManagement: {
            return [
                types_2.TxTags.checkpoint.CreateSchedule,
                types_2.TxTags.checkpoint.RemoveSchedule,
                types_2.TxTags.checkpoint.CreateCheckpoint,
                types_2.TxTags.corporateAction.InitiateCorporateAction,
                types_2.TxTags.capitalDistribution.Distribute,
                types_2.TxTags.capitalDistribution.Claim,
                types_2.TxTags.identity.AddInvestorUniquenessClaim,
            ];
        }
        case types_2.TxGroup.StoManagement: {
            return [
                types_2.TxTags.sto.CreateFundraiser,
                types_2.TxTags.sto.FreezeFundraiser,
                types_2.TxTags.sto.Invest,
                types_2.TxTags.sto.ModifyFundraiserWindow,
                types_2.TxTags.sto.Stop,
                types_2.TxTags.sto.UnfreezeFundraiser,
                types_2.TxTags.identity.AddInvestorUniquenessClaim,
                types_2.TxTags.asset.Issue,
                types_2.TxTags.settlement.CreateVenue,
            ];
        }
    }
}
exports.txGroupToTxTags = txGroupToTxTags;
/**
 * @hidden
 *
 * @note tags that don't belong to any group will be ignored.
 *   The same goes for tags that belong to a group that wasn't completed
 */
function transactionPermissionsToTxGroups(permissions) {
    if (!permissions) {
        return [];
    }
    const { values: transactionValues, type, exceptions = [] } = permissions;
    let includedTags;
    let excludedTags;
    if (type === types_2.PermissionType.Include) {
        includedTags = transactionValues;
        excludedTags = exceptions;
    }
    else {
        includedTags = exceptions;
        excludedTags = transactionValues;
    }
    return (0, lodash_1.values)(types_2.TxGroup)
        .sort()
        .filter(group => {
        const tagsInGroup = txGroupToTxTags(group);
        return tagsInGroup.every(tag => {
            const isExcluded = !!excludedTags.find(excluded => (0, internal_3.isModuleOrTagMatch)(excluded, tag));
            if (isExcluded) {
                return false;
            }
            return !!includedTags.find(included => (0, internal_3.isModuleOrTagMatch)(included, tag));
        });
    });
}
exports.transactionPermissionsToTxGroups = transactionPermissionsToTxGroups;
/**
 * @hidden
 */
function splitTag(tag) {
    const [modName, txName] = tag.split('.');
    const palletName = (0, util_1.stringUpperFirst)(modName);
    const dispatchableName = (0, lodash_1.snakeCase)(txName);
    return { palletName, dispatchableName };
}
/**
 * @hidden
 */
function initExtrinsicDict(txValues, message) {
    const extrinsicDict = {};
    (0, lodash_1.uniq)(txValues)
        .sort()
        .forEach(tag => {
        if (tag.includes('.')) {
            const { palletName, dispatchableName } = splitTag(tag);
            let pallet = extrinsicDict[palletName];
            if (pallet === null) {
                throw new internal_1.PolymeshError({
                    code: types_2.ErrorCode.ValidationError,
                    message,
                    data: {
                        module: palletName,
                        transactions: [dispatchableName],
                    },
                });
            }
            else if (pallet === undefined) {
                pallet = extrinsicDict[palletName] = { tx: [] };
            }
            pallet.tx.push(dispatchableName);
        }
        else {
            extrinsicDict[(0, util_1.stringUpperFirst)(tag)] = null;
        }
    });
    return extrinsicDict;
}
/**
 * @hidden
 */
function buildPalletPermissions(transactions) {
    let extrinsic;
    const message = 'Attempting to add permissions for specific transactions as well as the entire module';
    const { values: txValues, exceptions = [], type } = transactions;
    const extrinsicDict = initExtrinsicDict(txValues, message);
    exceptions.forEach(exception => {
        const { palletName, dispatchableName } = splitTag(exception);
        const pallet = extrinsicDict[palletName];
        if (pallet === undefined) {
            throw new internal_1.PolymeshError({
                code: types_2.ErrorCode.ValidationError,
                message: 'Attempting to add a transaction permission exception without its corresponding module being included/excluded',
            });
        }
        else if (pallet === null) {
            extrinsicDict[palletName] = { tx: [dispatchableName], exception: true };
        }
        else if (pallet.exception) {
            pallet.tx.push(dispatchableName);
        }
        else {
            throw new internal_1.PolymeshError({
                code: types_2.ErrorCode.ValidationError,
                message: 'Cannot simultaneously include and exclude transactions belonging to the same module',
            });
        }
    });
    const pallets = (0, lodash_1.map)(extrinsicDict, (val, key) => {
        let dispatchables;
        if (val === null) {
            dispatchables = 'Whole';
        }
        else {
            const { tx, exception } = val;
            if (exception) {
                dispatchables = {
                    Except: tx,
                };
            }
            else {
                dispatchables = {
                    These: tx,
                };
            }
        }
        return {
            /* eslint-disable @typescript-eslint/naming-convention */
            pallet_name: key,
            dispatchable_names: dispatchables,
            /* eslint-enable @typescript-eslint/naming-convention */
        };
    });
    if (type === types_2.PermissionType.Include) {
        extrinsic = {
            These: pallets,
        };
    }
    else {
        extrinsic = {
            Except: pallets,
        };
    }
    return extrinsic;
}
/**
 * @hidden
 */
function transactionPermissionsToExtrinsicPermissions(transactionPermissions, context) {
    return context.createType('PolymeshPrimitivesSubsetSubsetRestrictionPalletPermissions', transactionPermissions ? buildPalletPermissions(transactionPermissions) : 'Whole');
}
exports.transactionPermissionsToExtrinsicPermissions = transactionPermissionsToExtrinsicPermissions;
/**
 * @hidden
 */
function permissionsToMeshPermissions(permissions, context) {
    const { assets, transactions, portfolios } = permissions;
    const extrinsic = transactionPermissionsToExtrinsicPermissions(transactions, context);
    let asset = 'Whole';
    if (assets) {
        const { values: assetValues, type } = assets;
        assetValues.sort(({ ticker: tickerA }, { ticker: tickerB }) => tickerA.localeCompare(tickerB));
        const tickers = assetValues.map(({ ticker }) => stringToTicker(ticker, context));
        if (type === types_2.PermissionType.Include) {
            asset = {
                These: tickers,
            };
        }
        else {
            asset = {
                Except: tickers,
            };
        }
    }
    let portfolio = 'Whole';
    if (portfolios) {
        const { values: portfolioValues, type } = portfolios;
        const portfolioIds = portfolioValues.map(pValue => portfolioIdToMeshPortfolioId(portfolioToPortfolioId(pValue), context));
        if (type === types_2.PermissionType.Include) {
            portfolio = {
                These: portfolioIds,
            };
        }
        else {
            portfolio = {
                Except: portfolioIds,
            };
        }
    }
    const value = {
        asset,
        extrinsic,
        portfolio,
    };
    return context.createType('Permissions', value);
}
exports.permissionsToMeshPermissions = permissionsToMeshPermissions;
/**
 * @hidden
 */
function extrinsicPermissionsToTransactionPermissions(permissions) {
    let extrinsicType;
    let pallets;
    if (permissions.isThese) {
        extrinsicType = types_2.PermissionType.Include;
        pallets = permissions.asThese;
    }
    else if (permissions.isExcept) {
        extrinsicType = types_2.PermissionType.Exclude;
        pallets = permissions.asExcept;
    }
    let txValues = [];
    let exceptions = [];
    const formatTxTag = (dispatchable, moduleName) => {
        return `${moduleName}.${(0, lodash_1.camelCase)(dispatchable)}`;
    };
    if (pallets) {
        pallets.forEach(({ palletName, dispatchableNames }) => {
            const moduleName = (0, util_1.stringLowerFirst)(bytesToString(palletName));
            if (dispatchableNames.isExcept) {
                const dispatchables = dispatchableNames.asExcept;
                exceptions = [
                    ...exceptions,
                    ...dispatchables.map(name => formatTxTag(bytesToString(name), moduleName)),
                ];
                txValues = [...txValues, moduleName];
            }
            else if (dispatchableNames.isThese) {
                const dispatchables = dispatchableNames.asThese;
                txValues = [
                    ...txValues,
                    ...dispatchables.map(name => formatTxTag(bytesToString(name), moduleName)),
                ];
            }
            else {
                txValues = [...txValues, moduleName];
            }
        });
        const result = {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            type: extrinsicType,
            values: txValues,
        };
        return exceptions.length ? Object.assign(Object.assign({}, result), { exceptions }) : result;
    }
    return null;
}
exports.extrinsicPermissionsToTransactionPermissions = extrinsicPermissionsToTransactionPermissions;
/**
 * @hidden
 */
function meshPermissionsToPermissions(permissions, context) {
    const { asset, extrinsic, portfolio } = permissions;
    let assets = null;
    let transactions = null;
    let portfolios = null;
    let assetsType;
    let assetsPermissions;
    if (asset.isThese) {
        assetsType = types_2.PermissionType.Include;
        assetsPermissions = asset.asThese;
    }
    else if (asset.isExcept) {
        assetsType = types_2.PermissionType.Exclude;
        assetsPermissions = asset.asExcept;
    }
    if (assetsPermissions) {
        assets = {
            values: assetsPermissions.map(ticker => new internal_1.Asset({ ticker: tickerToString(ticker) }, context)),
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            type: assetsType,
        };
    }
    transactions = extrinsicPermissionsToTransactionPermissions(extrinsic);
    let portfoliosType;
    let portfolioIds;
    if (portfolio.isThese) {
        portfoliosType = types_2.PermissionType.Include;
        portfolioIds = portfolio.asThese;
    }
    else if (portfolio.isExcept) {
        portfoliosType = types_2.PermissionType.Exclude;
        portfolioIds = portfolio.asExcept;
    }
    if (portfolioIds) {
        portfolios = {
            values: portfolioIds.map(portfolioId => meshPortfolioIdToPortfolio(portfolioId, context)),
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            type: portfoliosType,
        };
    }
    return {
        assets,
        transactions,
        transactionGroups: transactions ? transactionPermissionsToTxGroups(transactions) : [],
        portfolios,
    };
}
exports.meshPermissionsToPermissions = meshPermissionsToPermissions;
/**
 * @hidden
 */
function bigNumberToU32(value, context) {
    (0, internal_3.assertIsInteger)(value);
    (0, internal_3.assertIsPositive)(value);
    return context.createType('u32', value.toString());
}
exports.bigNumberToU32 = bigNumberToU32;
/**
 * @hidden
 */
function u32ToBigNumber(value) {
    return new bignumber_js_1.default(value.toString());
}
exports.u32ToBigNumber = u32ToBigNumber;
/**
 * @hidden
 */
function u16ToBigNumber(value) {
    return new bignumber_js_1.default(value.toString());
}
exports.u16ToBigNumber = u16ToBigNumber;
/**
 * @hidden
 */
function u8ToBigNumber(value) {
    return new bignumber_js_1.default(value.toString());
}
exports.u8ToBigNumber = u8ToBigNumber;
/**
 * @hidden
 */
function permissionGroupIdentifierToAgentGroup(permissionGroup, context) {
    return context.createType('AgentGroup', typeof permissionGroup !== 'object'
        ? permissionGroup
        : { Custom: bigNumberToU32(permissionGroup.custom, context) });
}
exports.permissionGroupIdentifierToAgentGroup = permissionGroupIdentifierToAgentGroup;
/**
 * @hidden
 */
function agentGroupToPermissionGroupIdentifier(agentGroup) {
    if (agentGroup.isFull) {
        return types_2.PermissionGroupType.Full;
    }
    else if (agentGroup.isExceptMeta) {
        return types_2.PermissionGroupType.ExceptMeta;
    }
    else if (agentGroup.isPolymeshV1CAA) {
        return types_2.PermissionGroupType.PolymeshV1Caa;
    }
    else if (agentGroup.isPolymeshV1PIA) {
        return types_2.PermissionGroupType.PolymeshV1Pia;
    }
    else {
        return { custom: u32ToBigNumber(agentGroup.asCustom) };
    }
}
exports.agentGroupToPermissionGroupIdentifier = agentGroupToPermissionGroupIdentifier;
/**
 * @hidden
 */
function authorizationToAuthorizationData(auth, context) {
    let value;
    const { type } = auth;
    if (type === types_2.AuthorizationType.RotatePrimaryKey) {
        value = null;
    }
    else if (type === types_2.AuthorizationType.JoinIdentity) {
        value = permissionsToMeshPermissions(auth.value, context);
    }
    else if (type === types_2.AuthorizationType.PortfolioCustody) {
        value = portfolioIdToMeshPortfolioId(portfolioToPortfolioId(auth.value), context);
    }
    else if (auth.type === types_2.AuthorizationType.TransferAssetOwnership ||
        auth.type === types_2.AuthorizationType.TransferTicker) {
        value = stringToTicker(auth.value, context);
    }
    else if (type === types_2.AuthorizationType.RotatePrimaryKeyToSecondary) {
        value = permissionsToMeshPermissions(auth.value, context);
    }
    else if (type === types_2.AuthorizationType.BecomeAgent) {
        const ticker = stringToTicker(auth.value.asset.ticker, context);
        if (auth.value instanceof internal_1.CustomPermissionGroup) {
            const { id } = auth.value;
            value = [ticker, permissionGroupIdentifierToAgentGroup({ custom: id }, context)];
        }
        else {
            const { type: groupType } = auth.value;
            value = [ticker, permissionGroupIdentifierToAgentGroup(groupType, context)];
        }
    }
    else {
        value = auth.value;
    }
    return context.createType('PolymeshPrimitivesAuthorizationAuthorizationData', {
        [type]: value,
    });
}
exports.authorizationToAuthorizationData = authorizationToAuthorizationData;
/**
 * @hidden
 */
function authorizationTypeToMeshAuthorizationType(authorizationType, context) {
    return context.createType('AuthorizationType', authorizationType);
}
exports.authorizationTypeToMeshAuthorizationType = authorizationTypeToMeshAuthorizationType;
/**
 * @hidden
 */
function bigNumberToBalance(value, context, divisible = true) {
    (0, internal_3.assertIsPositive)(value);
    if (value.isGreaterThan(constants_1.MAX_BALANCE)) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: 'The value exceeds the maximum possible balance',
            data: {
                currentValue: value,
                amountLimit: constants_1.MAX_BALANCE,
            },
        });
    }
    if (divisible) {
        if (value.decimalPlaces() > constants_1.MAX_DECIMALS) {
            throw new internal_1.PolymeshError({
                code: types_2.ErrorCode.ValidationError,
                message: 'The value has more decimal places than allowed',
                data: {
                    currentValue: value,
                    decimalsLimit: constants_1.MAX_DECIMALS,
                },
            });
        }
    }
    else {
        if (value.decimalPlaces()) {
            throw new internal_1.PolymeshError({
                code: types_2.ErrorCode.ValidationError,
                message: 'The value has decimals but the Asset is indivisible',
            });
        }
    }
    return context.createType('Balance', value.shiftedBy(6).toString());
}
exports.bigNumberToBalance = bigNumberToBalance;
/**
 * @hidden
 */
function balanceToBigNumber(balance) {
    return new bignumber_js_1.default(balance.toString()).shiftedBy(-6);
}
exports.balanceToBigNumber = balanceToBigNumber;
/**
 * @hidden
 */
function agentGroupToPermissionGroup(agentGroup, ticker, context) {
    const permissionGroupIdentifier = agentGroupToPermissionGroupIdentifier(agentGroup);
    switch (permissionGroupIdentifier) {
        case types_2.PermissionGroupType.ExceptMeta:
        case types_2.PermissionGroupType.Full:
        case types_2.PermissionGroupType.PolymeshV1Caa:
        case types_2.PermissionGroupType.PolymeshV1Pia: {
            return new internal_1.KnownPermissionGroup({ type: permissionGroupIdentifier, ticker }, context);
        }
        default: {
            const { custom: id } = permissionGroupIdentifier;
            return new internal_1.CustomPermissionGroup({ id, ticker }, context);
        }
    }
}
exports.agentGroupToPermissionGroup = agentGroupToPermissionGroup;
/**
 * @hidden
 */
function authorizationDataToAuthorization(auth, context) {
    if (auth.isAttestPrimaryKeyRotation) {
        return {
            type: types_2.AuthorizationType.AttestPrimaryKeyRotation,
            value: identityIdToString(auth.asAttestPrimaryKeyRotation),
        };
    }
    if (auth.isRotatePrimaryKey) {
        return {
            type: types_2.AuthorizationType.RotatePrimaryKey,
        };
    }
    if (auth.isTransferTicker) {
        return {
            type: types_2.AuthorizationType.TransferTicker,
            value: tickerToString(auth.asTransferTicker),
        };
    }
    if (auth.isAddMultiSigSigner) {
        return {
            type: types_2.AuthorizationType.AddMultiSigSigner,
            value: accountIdToString(auth.asAddMultiSigSigner),
        };
    }
    if (auth.isTransferAssetOwnership) {
        return {
            type: types_2.AuthorizationType.TransferAssetOwnership,
            value: tickerToString(auth.asTransferAssetOwnership),
        };
    }
    if (auth.isPortfolioCustody) {
        return {
            type: types_2.AuthorizationType.PortfolioCustody,
            value: meshPortfolioIdToPortfolio(auth.asPortfolioCustody, context),
        };
    }
    if (auth.isJoinIdentity) {
        return {
            type: types_2.AuthorizationType.JoinIdentity,
            value: meshPermissionsToPermissions(auth.asJoinIdentity, context),
        };
    }
    if (auth.isAddRelayerPayingKey) {
        const [userKey, payingKey, polyxLimit] = auth.asAddRelayerPayingKey;
        return {
            type: types_2.AuthorizationType.AddRelayerPayingKey,
            value: {
                beneficiary: new internal_1.Account({ address: accountIdToString(userKey) }, context),
                subsidizer: new internal_1.Account({ address: accountIdToString(payingKey) }, context),
                allowance: balanceToBigNumber(polyxLimit),
            },
        };
    }
    if (auth.isBecomeAgent) {
        const [ticker, agentGroup] = auth.asBecomeAgent;
        return {
            type: types_2.AuthorizationType.BecomeAgent,
            value: agentGroupToPermissionGroup(agentGroup, tickerToString(ticker), context),
        };
    }
    if (auth.isRotatePrimaryKeyToSecondary) {
        return {
            type: types_2.AuthorizationType.RotatePrimaryKeyToSecondary,
            value: meshPermissionsToPermissions(auth.asRotatePrimaryKeyToSecondary, context),
        };
    }
    throw new internal_1.PolymeshError({
        code: types_2.ErrorCode.UnexpectedError,
        message: 'Unsupported Authorization Type. Please contact the Polymath team',
        data: {
            auth: JSON.stringify(auth, null, 2),
        },
    });
}
exports.authorizationDataToAuthorization = authorizationDataToAuthorization;
/**
 * @hidden
 */
function stringToMemo(value, context) {
    if (value.length > constants_1.MAX_MEMO_LENGTH) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: 'Max memo length exceeded',
            data: {
                maxLength: constants_1.MAX_MEMO_LENGTH,
            },
        });
    }
    return context.createType('Memo', (0, internal_3.padString)(value, constants_1.MAX_MEMO_LENGTH));
}
exports.stringToMemo = stringToMemo;
/**
 * @hidden
 */
function u8ToTransferStatus(status) {
    const code = status.toNumber();
    switch (code) {
        case 81: {
            return types_2.TransferStatus.Success;
        }
        case 82: {
            return types_2.TransferStatus.InsufficientBalance;
        }
        case 83: {
            return types_2.TransferStatus.InsufficientAllowance;
        }
        case 84: {
            return types_2.TransferStatus.TransfersHalted;
        }
        case 85: {
            return types_2.TransferStatus.FundsLocked;
        }
        case 86: {
            return types_2.TransferStatus.InvalidSenderAddress;
        }
        case 87: {
            return types_2.TransferStatus.InvalidReceiverAddress;
        }
        case 88: {
            return types_2.TransferStatus.InvalidOperator;
        }
        case 160: {
            return types_2.TransferStatus.InvalidSenderIdentity;
        }
        case 161: {
            return types_2.TransferStatus.InvalidReceiverIdentity;
        }
        case 162: {
            return types_2.TransferStatus.ComplianceFailure;
        }
        case 163: {
            return types_2.TransferStatus.SmartExtensionFailure;
        }
        case 164: {
            return types_2.TransferStatus.InvalidGranularity;
        }
        case 165: {
            return types_2.TransferStatus.VolumeLimitReached;
        }
        case 166: {
            return types_2.TransferStatus.BlockedTransaction;
        }
        case 168: {
            return types_2.TransferStatus.FundsLimitReached;
        }
        case 169: {
            return types_2.TransferStatus.PortfolioFailure;
        }
        case 170: {
            return types_2.TransferStatus.CustodianError;
        }
        case 171: {
            return types_2.TransferStatus.ScopeClaimMissing;
        }
        case 172: {
            return types_2.TransferStatus.TransferRestrictionFailure;
        }
        case 80: {
            return types_2.TransferStatus.Failure;
        }
        default: {
            throw new internal_1.PolymeshError({
                code: types_2.ErrorCode.UnexpectedError,
                message: `Unsupported status code "${status.toString()}". Please report this issue to the Polymath team`,
            });
        }
    }
}
exports.u8ToTransferStatus = u8ToTransferStatus;
/**
 * @hidden
 */
function internalAssetTypeToAssetType(type, context) {
    return context.createType('AssetType', type);
}
exports.internalAssetTypeToAssetType = internalAssetTypeToAssetType;
/**
 * @hidden
 */
function assetTypeToKnownOrId(assetType) {
    if (assetType.isEquityCommon) {
        return types_2.KnownAssetType.EquityCommon;
    }
    if (assetType.isEquityPreferred) {
        return types_2.KnownAssetType.EquityPreferred;
    }
    if (assetType.isCommodity) {
        return types_2.KnownAssetType.Commodity;
    }
    if (assetType.isFixedIncome) {
        return types_2.KnownAssetType.FixedIncome;
    }
    if (assetType.isReit) {
        return types_2.KnownAssetType.Reit;
    }
    if (assetType.isFund) {
        return types_2.KnownAssetType.Fund;
    }
    if (assetType.isRevenueShareAgreement) {
        return types_2.KnownAssetType.RevenueShareAgreement;
    }
    if (assetType.isStructuredProduct) {
        return types_2.KnownAssetType.StructuredProduct;
    }
    if (assetType.isDerivative) {
        return types_2.KnownAssetType.Derivative;
    }
    if (assetType.isStableCoin) {
        return types_2.KnownAssetType.StableCoin;
    }
    return u32ToBigNumber(assetType.asCustom);
}
exports.assetTypeToKnownOrId = assetTypeToKnownOrId;
/**
 * @hidden
 */
function posRatioToBigNumber(postRatio) {
    const [numerator, denominator] = postRatio.map(u32ToBigNumber);
    return numerator.dividedBy(denominator);
}
exports.posRatioToBigNumber = posRatioToBigNumber;
/**
 * @hidden
 */
function isIsinValid(isin) {
    isin = isin.toUpperCase();
    if (!/^[0-9A-Z]{12}$/.test(isin)) {
        return false;
    }
    const v = [];
    (0, lodash_1.rangeRight)(11).forEach(i => {
        const c = parseInt(isin.charAt(i));
        if (isNaN(c)) {
            const letterCode = isin.charCodeAt(i) - 55;
            v.push(letterCode % 10);
            v.push(Math.floor(letterCode / 10));
        }
        else {
            v.push(Number(c));
        }
    });
    let sum = 0;
    (0, lodash_1.range)(v.length).forEach(i => {
        if (i % 2 === 0) {
            const d = v[i] * 2;
            sum += Math.floor(d / 10);
            sum += d % 10;
        }
        else {
            sum += v[i];
        }
    });
    return (10 - (sum % 10)) % 10 === Number(isin[isin.length - 1]);
}
exports.isIsinValid = isIsinValid;
/**
 * @hidden
 */
function validateCusipChecksum(cusip) {
    let sum = 0;
    // cSpell: disable-next-line
    const cusipChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ*@#'.split('');
    const cusipLength = cusip.length - 1;
    (0, lodash_1.range)(cusipLength).forEach(i => {
        const item = cusip[i];
        const code = item.charCodeAt(0);
        let num;
        if (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) {
            num = cusipChars.indexOf(item) + 10;
        }
        else {
            num = Number(item);
        }
        if (i % 2 !== 0) {
            num *= 2;
        }
        num = (num % 10) + Math.floor(num / 10);
        sum += num;
    });
    return (10 - (sum % 10)) % 10 === Number(cusip[cusip.length - 1]);
}
/**
 * @hidden
 *
 * @note CINS and CUSIP use the same validation
 */
function isCusipValid(cusip) {
    cusip = cusip.toUpperCase();
    if (!/^[0-9A-Z@#*]{9}$/.test(cusip)) {
        return false;
    }
    return validateCusipChecksum(cusip);
}
exports.isCusipValid = isCusipValid;
/**
 * @hidden
 */
function isLeiValid(lei) {
    lei = lei.toUpperCase();
    if (!/^[0-9A-Z]{18}\d{2}$/.test(lei)) {
        return false;
    }
    return (0, iso_7064_1.computeWithoutCheck)(lei) === 1;
}
exports.isLeiValid = isLeiValid;
/**
 * Check if given string is a valid FIGI identifier
 *
 * A FIGI consists of three parts:
 *   - a two-character prefix which is a combination of upper case consonants with the following exceptions: BS, BM, GG, GB, GH, KY, VG
 *   - a 'G' as the third character;
 *   - an eight-character combination of upper case consonants and the numerals 0 – 9
 *   - a single check digit
 * @hidden
 */
function isFigiValid(figi) {
    figi = figi.toUpperCase();
    if (['BS', 'BM', 'GG', 'GB', 'GH', 'KY', 'VG'].includes(figi.substring(0, 2)) ||
        !/^[B-DF-HJ-NP-TV-Z]{2}G[B-DF-HJ-NP-TV-Z0-9]{8}\d$/.test(figi)) {
        return false;
    }
    return validateCusipChecksum(figi);
}
exports.isFigiValid = isFigiValid;
/**
 * @hidden
 */
function securityIdentifierToAssetIdentifier(identifier, context) {
    const { type, value } = identifier;
    let error = false;
    switch (type) {
        case types_2.SecurityIdentifierType.Isin: {
            if (!isIsinValid(value)) {
                error = true;
            }
            break;
        }
        case types_2.SecurityIdentifierType.Lei: {
            if (!isLeiValid(value)) {
                error = true;
            }
            break;
        }
        case types_2.SecurityIdentifierType.Figi: {
            if (!isFigiValid(value)) {
                error = true;
            }
            break;
        }
        // CINS and CUSIP use the same validation
        default: {
            if (!isCusipValid(value)) {
                error = true;
            }
        }
    }
    if (error) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: `Invalid security identifier ${value} of type ${type}`,
        });
    }
    return context.createType('PolymeshPrimitivesAssetIdentifier', { [type]: value });
}
exports.securityIdentifierToAssetIdentifier = securityIdentifierToAssetIdentifier;
/**
 * @hidden
 */
function assetIdentifierToSecurityIdentifier(identifier) {
    if (identifier.isCusip) {
        return {
            type: types_2.SecurityIdentifierType.Cusip,
            value: (0, util_1.u8aToString)(identifier.asCusip),
        };
    }
    if (identifier.isIsin) {
        return {
            type: types_2.SecurityIdentifierType.Isin,
            value: (0, util_1.u8aToString)(identifier.asIsin),
        };
    }
    if (identifier.isCins) {
        return {
            type: types_2.SecurityIdentifierType.Cins,
            value: (0, util_1.u8aToString)(identifier.asCins),
        };
    }
    if (identifier.isFigi) {
        return {
            type: types_2.SecurityIdentifierType.Figi,
            value: (0, util_1.u8aToString)(identifier.asFigi),
        };
    }
    return {
        type: types_2.SecurityIdentifierType.Lei,
        value: (0, util_1.u8aToString)(identifier.asLei),
    };
}
exports.assetIdentifierToSecurityIdentifier = assetIdentifierToSecurityIdentifier;
/**
 * @hidden
 */
function stringToDocumentHash(docHash, context) {
    if (docHash === undefined) {
        return context.createType('PolymeshPrimitivesDocumentHash', 'None');
    }
    if (!(0, util_1.isHex)(docHash, -1, true)) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: 'Document hash must be a hexadecimal string prefixed by 0x',
        });
    }
    const { length } = docHash;
    // array of Hash types (H128, H160, etc) and their corresponding hex lengths
    const hashTypes = [32, 40, 48, 56, 64, 80, 96, 128].map(max => ({
        maxLength: max + 2,
        key: `H${max * 4}`,
    }));
    const type = hashTypes.find(({ maxLength: max }) => length <= max);
    if (!type) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: 'Document hash exceeds max length',
        });
    }
    const { maxLength, key } = type;
    return context.createType('DocumentHash', {
        [key]: (0, util_1.hexToU8a)(docHash.padEnd(maxLength, '0')),
    });
}
exports.stringToDocumentHash = stringToDocumentHash;
/**
 * @hidden
 */
function documentHashToString(docHash) {
    if (docHash.isNone) {
        return;
    }
    if (docHash.isH128) {
        return (0, util_1.u8aToHex)(docHash.asH128);
    }
    if (docHash.isH160) {
        return (0, util_1.u8aToHex)(docHash.asH160);
    }
    if (docHash.isH192) {
        return (0, util_1.u8aToHex)(docHash.asH192);
    }
    if (docHash.isH224) {
        return (0, util_1.u8aToHex)(docHash.asH224);
    }
    if (docHash.isH256) {
        return (0, util_1.u8aToHex)(docHash.asH256);
    }
    if (docHash.isH320) {
        return (0, util_1.u8aToHex)(docHash.asH320);
    }
    if (docHash.isH384) {
        return (0, util_1.u8aToHex)(docHash.asH384);
    }
    return (0, util_1.u8aToHex)(docHash.asH512);
}
exports.documentHashToString = documentHashToString;
/**
 * @hidden
 */
function assetDocumentToDocument({ uri, contentHash, name, filedAt, type }, context) {
    return context.createType('PolymeshPrimitivesDocument', {
        uri: stringToBytes(uri, context),
        name: stringToBytes(name, context),
        contentHash: stringToDocumentHash(contentHash, context),
        docType: (0, internal_3.optionize)(stringToBytes)(type, context),
        filingDate: (0, internal_3.optionize)(dateToMoment)(filedAt, context),
    });
}
exports.assetDocumentToDocument = assetDocumentToDocument;
/**
 * @hidden
 */
function documentToAssetDocument({ uri, contentHash: hash, name, docType, filingDate, }) {
    const filedAt = filingDate.unwrapOr(undefined);
    const type = docType.unwrapOr(undefined);
    const contentHash = documentHashToString(hash);
    let doc = {
        uri: bytesToString(uri),
        name: bytesToString(name),
    };
    if (contentHash) {
        doc = Object.assign(Object.assign({}, doc), { contentHash });
    }
    if (filedAt) {
        doc = Object.assign(Object.assign({}, doc), { filedAt: momentToDate(filedAt) });
    }
    if (type) {
        doc = Object.assign(Object.assign({}, doc), { type: bytesToString(type) });
    }
    return doc;
}
exports.documentToAssetDocument = documentToAssetDocument;
/**
 * @hidden
 */
function cddStatusToBoolean(cddStatus) {
    if (cddStatus.isOk) {
        return true;
    }
    return false;
}
exports.cddStatusToBoolean = cddStatusToBoolean;
/**
 * @hidden
 */
function canTransferResultToTransferStatus(canTransferResult) {
    if (canTransferResult.isErr) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.UnexpectedError,
            message: `Error while checking transfer validity: ${bytesToString(canTransferResult.asErr)}`,
        });
    }
    return u8ToTransferStatus(canTransferResult.asOk);
}
exports.canTransferResultToTransferStatus = canTransferResultToTransferStatus;
/**
 * @hidden
 */
function scopeToMeshScope(scope, context) {
    const { type, value } = scope;
    let scopeValue;
    switch (type) {
        case types_2.ScopeType.Ticker:
            scopeValue = stringToTicker(value, context);
            break;
        case types_2.ScopeType.Identity:
            scopeValue = stringToIdentityId(value, context);
            break;
        default:
            scopeValue = value;
            break;
    }
    return context.createType('Scope', {
        [type]: scopeValue,
    });
}
exports.scopeToMeshScope = scopeToMeshScope;
/**
 * @hidden
 */
function meshScopeToScope(scope) {
    if (scope.isTicker) {
        return {
            type: types_2.ScopeType.Ticker,
            value: tickerToString(scope.asTicker),
        };
    }
    if (scope.isIdentity) {
        return {
            type: types_2.ScopeType.Identity,
            value: identityIdToString(scope.asIdentity),
        };
    }
    return {
        type: types_2.ScopeType.Custom,
        value: (0, util_1.u8aToString)(scope.asCustom),
    };
}
exports.meshScopeToScope = meshScopeToScope;
/**
 * @hidden
 */
function stringToCddId(cddId, context) {
    return context.createType('CddId', cddId);
}
exports.stringToCddId = stringToCddId;
/**
 * @hidden
 */
function cddIdToString(cddId) {
    return cddId.toString();
}
exports.cddIdToString = cddIdToString;
/**
 * @hidden
 */
function stringToScopeId(scopeId, context) {
    return context.createType('ScopeId', scopeId);
}
exports.stringToScopeId = stringToScopeId;
/**
 * @hidden
 */
function scopeIdToString(scopeId) {
    return scopeId.toString();
}
exports.scopeIdToString = scopeIdToString;
/**
 * @hidden
 */
function claimToMeshClaim(claim, context) {
    let value;
    switch (claim.type) {
        case types_2.ClaimType.NoData: {
            value = null;
            break;
        }
        case types_2.ClaimType.NoType: {
            value = null;
            break;
        }
        case types_2.ClaimType.CustomerDueDiligence: {
            value = stringToCddId(claim.id, context);
            break;
        }
        case types_2.ClaimType.Jurisdiction: {
            const { code, scope } = claim;
            value = (0, utils_2.tuple)(code, scopeToMeshScope(scope, context));
            break;
        }
        case types_2.ClaimType.InvestorUniqueness: {
            const { scope, cddId, scopeId } = claim;
            value = (0, utils_2.tuple)(scopeToMeshScope(scope, context), stringToScopeId(scopeId, context), stringToCddId(cddId, context));
            break;
        }
        case types_2.ClaimType.InvestorUniquenessV2: {
            value = stringToCddId(claim.cddId, context);
            break;
        }
        default: {
            value = scopeToMeshScope(claim.scope, context);
        }
    }
    return context.createType('Claim', { [claim.type]: value });
}
exports.claimToMeshClaim = claimToMeshClaim;
/**
 * @hidden
 */
function middlewareScopeToScope(scope) {
    const { type, value } = scope;
    switch (type) {
        case types_1.ClaimScopeTypeEnum.Ticker:
            // eslint-disable-next-line no-control-regex
            return { type: types_2.ScopeType.Ticker, value: (0, internal_3.removePadding)(value) };
        case types_1.ClaimScopeTypeEnum.Identity:
        case types_1.ClaimScopeTypeEnum.Custom:
            return { type: types_2.ScopeType[scope.type], value };
    }
}
exports.middlewareScopeToScope = middlewareScopeToScope;
/**
 * @hidden
 */
function scopeToMiddlewareScope(scope) {
    const { type, value } = scope;
    switch (type) {
        case types_2.ScopeType.Ticker:
            return { type: types_1.ClaimScopeTypeEnum.Ticker, value: (0, lodash_1.padEnd)(value, 12, '\0') };
        case types_2.ScopeType.Identity:
        case types_2.ScopeType.Custom:
            return { type: types_1.ClaimScopeTypeEnum[scope.type], value };
    }
}
exports.scopeToMiddlewareScope = scopeToMiddlewareScope;
/**
 * @hidden
 */
function middlewareEventToEventIdentifier(event) {
    const { block_id: blockNumber, block, event_idx: eventIndex } = event;
    return {
        blockNumber: new bignumber_js_1.default(blockNumber),
        /* eslint-disable @typescript-eslint/no-non-null-assertion */
        blockDate: new Date(block.datetime),
        blockHash: block.hash,
        /* eslint-enable @typescript-eslint/no-non-null-assertion */
        eventIndex: new bignumber_js_1.default(eventIndex),
    };
}
exports.middlewareEventToEventIdentifier = middlewareEventToEventIdentifier;
/**
 * @hidden
 */
function meshClaimToClaim(claim) {
    if (claim.isJurisdiction) {
        const [code, scope] = claim.asJurisdiction;
        return {
            type: types_2.ClaimType.Jurisdiction,
            code: (0, utils_1.meshCountryCodeToCountryCode)(code),
            scope: meshScopeToScope(scope),
        };
    }
    if (claim.isNoData) {
        return {
            type: types_2.ClaimType.NoData,
        };
    }
    if (claim.isAccredited) {
        return {
            type: types_2.ClaimType.Accredited,
            scope: meshScopeToScope(claim.asAccredited),
        };
    }
    if (claim.isAffiliate) {
        return {
            type: types_2.ClaimType.Affiliate,
            scope: meshScopeToScope(claim.asAffiliate),
        };
    }
    if (claim.isBuyLockup) {
        return {
            type: types_2.ClaimType.BuyLockup,
            scope: meshScopeToScope(claim.asBuyLockup),
        };
    }
    if (claim.isSellLockup) {
        return {
            type: types_2.ClaimType.SellLockup,
            scope: meshScopeToScope(claim.asSellLockup),
        };
    }
    if (claim.isCustomerDueDiligence) {
        return {
            type: types_2.ClaimType.CustomerDueDiligence,
            id: cddIdToString(claim.asCustomerDueDiligence),
        };
    }
    if (claim.isKnowYourCustomer) {
        return {
            type: types_2.ClaimType.KnowYourCustomer,
            scope: meshScopeToScope(claim.asKnowYourCustomer),
        };
    }
    if (claim.isExempted) {
        return {
            type: types_2.ClaimType.Exempted,
            scope: meshScopeToScope(claim.asExempted),
        };
    }
    if (claim.isInvestorUniqueness) {
        const [scope, scopeId, cddId] = claim.asInvestorUniqueness;
        return {
            type: types_2.ClaimType.InvestorUniqueness,
            scope: meshScopeToScope(scope),
            scopeId: scopeIdToString(scopeId),
            cddId: cddIdToString(cddId),
        };
    }
    if (claim.isInvestorUniquenessV2) {
        return {
            type: types_2.ClaimType.InvestorUniquenessV2,
            cddId: cddIdToString(claim.asInvestorUniquenessV2),
        };
    }
    return {
        type: types_2.ClaimType.Blocked,
        scope: meshScopeToScope(claim.asBlocked),
    };
}
exports.meshClaimToClaim = meshClaimToClaim;
/**
 * @hidden
 */
function stringToTargetIdentity(did, context) {
    return context.createType('TargetIdentity', 
    // eslint-disable-next-line @typescript-eslint/naming-convention
    did ? { Specific: stringToIdentityId(did, context) } : 'ExternalAgent');
}
exports.stringToTargetIdentity = stringToTargetIdentity;
/**
 * @hidden
 */
function meshClaimTypeToClaimType(claimType) {
    if (claimType.isJurisdiction) {
        return types_2.ClaimType.Jurisdiction;
    }
    if (claimType.isAccredited) {
        return types_2.ClaimType.Accredited;
    }
    if (claimType.isAffiliate) {
        return types_2.ClaimType.Affiliate;
    }
    if (claimType.isBuyLockup) {
        return types_2.ClaimType.BuyLockup;
    }
    if (claimType.isSellLockup) {
        return types_2.ClaimType.SellLockup;
    }
    if (claimType.isCustomerDueDiligence) {
        return types_2.ClaimType.CustomerDueDiligence;
    }
    if (claimType.isKnowYourCustomer) {
        return types_2.ClaimType.KnowYourCustomer;
    }
    if (claimType.isExempted) {
        return types_2.ClaimType.Exempted;
    }
    if (claimType.isNoType) {
        return types_2.ClaimType.NoType;
    }
    return types_2.ClaimType.Blocked;
}
exports.meshClaimTypeToClaimType = meshClaimTypeToClaimType;
/**
 * @hidden
 */
function trustedIssuerToTrustedClaimIssuer(trustedIssuer, context) {
    const { issuer, trustedFor: claimTypes } = trustedIssuer;
    const identity = new internal_1.Identity({ did: identityIdToString(issuer) }, context);
    let trustedFor = null;
    if (claimTypes.isSpecific) {
        trustedFor = claimTypes.asSpecific.map(meshClaimTypeToClaimType);
    }
    return {
        identity,
        trustedFor,
    };
}
exports.trustedIssuerToTrustedClaimIssuer = trustedIssuerToTrustedClaimIssuer;
/**
 * @hidden
 */
function trustedClaimIssuerToTrustedIssuer(issuer, context) {
    const { trustedFor: claimTypes, identity } = issuer;
    const did = signerToString(identity);
    let trustedFor;
    if (!claimTypes) {
        trustedFor = 'Any';
    }
    else {
        trustedFor = { Specific: claimTypes };
    }
    return context.createType('PolymeshPrimitivesConditionTrustedIssuer', {
        issuer: stringToIdentityId(did, context),
        trustedFor,
    });
}
exports.trustedClaimIssuerToTrustedIssuer = trustedClaimIssuerToTrustedIssuer;
/**
 * @hidden
 */
function requirementToComplianceRequirement(requirement, context) {
    const senderConditions = [];
    const receiverConditions = [];
    requirement.conditions.forEach(condition => {
        let conditionContent;
        let { type } = condition;
        if ((0, typeguards_1.isSingleClaimCondition)(condition)) {
            const { claim } = condition;
            conditionContent = claimToMeshClaim(claim, context);
        }
        else if ((0, typeguards_1.isMultiClaimCondition)(condition)) {
            const { claims } = condition;
            conditionContent = claims.map(claim => claimToMeshClaim(claim, context));
        }
        else if ((0, typeguards_1.isIdentityCondition)(condition)) {
            const { identity } = condition;
            conditionContent = stringToTargetIdentity(signerToString(identity), context);
        }
        else {
            // IsExternalAgent does not exist as a condition type in Polymesh, it's SDK sugar
            type = types_2.ConditionType.IsIdentity;
            conditionContent = stringToTargetIdentity(null, context);
        }
        const { target, trustedClaimIssuers = [] } = condition;
        const meshCondition = context.createType('PolymeshPrimitivesCondition', {
            conditionType: {
                [type]: conditionContent,
            },
            issuers: trustedClaimIssuers.map(issuer => trustedClaimIssuerToTrustedIssuer(issuer, context)),
        });
        if ([types_2.ConditionTarget.Both, types_2.ConditionTarget.Receiver].includes(target)) {
            receiverConditions.push(meshCondition);
        }
        if ([types_2.ConditionTarget.Both, types_2.ConditionTarget.Sender].includes(target)) {
            senderConditions.push(meshCondition);
        }
    });
    return context.createType('PolymeshPrimitivesComplianceManagerComplianceRequirement', {
        senderConditions,
        receiverConditions,
        id: bigNumberToU32(requirement.id, context),
    });
}
exports.requirementToComplianceRequirement = requirementToComplianceRequirement;
/**
 * @hidden
 */
function meshConditionTypeToCondition(meshConditionType, context) {
    if (meshConditionType.isIsPresent) {
        return {
            type: types_2.ConditionType.IsPresent,
            claim: meshClaimToClaim(meshConditionType.asIsPresent),
        };
    }
    if (meshConditionType.isIsAbsent) {
        return {
            type: types_2.ConditionType.IsAbsent,
            claim: meshClaimToClaim(meshConditionType.asIsAbsent),
        };
    }
    if (meshConditionType.isIsAnyOf) {
        return {
            type: types_2.ConditionType.IsAnyOf,
            claims: meshConditionType.asIsAnyOf.map(claim => meshClaimToClaim(claim)),
        };
    }
    if (meshConditionType.isIsIdentity) {
        const target = meshConditionType.asIsIdentity;
        if (target.isExternalAgent) {
            return {
                type: types_2.ConditionType.IsExternalAgent,
            };
        }
        return {
            type: types_2.ConditionType.IsIdentity,
            identity: new internal_1.Identity({ did: identityIdToString(target.asSpecific) }, context),
        };
    }
    return {
        type: types_2.ConditionType.IsNoneOf,
        claims: meshConditionType.asIsNoneOf.map(claim => meshClaimToClaim(claim)),
    };
}
/**
 * @hidden
 * @note - the data for this method comes from an RPC call, which hasn't been updated to the camelCase types
 */
function complianceRequirementResultToRequirementCompliance(complianceRequirement, context) {
    const conditions = [];
    const conditionCompliancesAreEqual = ({ condition: aCondition, complies: aComplies }, { condition: bCondition, complies: bComplies }) => (0, internal_3.conditionsAreEqual)(aCondition, bCondition) && aComplies === bComplies;
    complianceRequirement.senderConditions.forEach(({ condition: { conditionType, issuers }, result }) => {
        const newCondition = {
            condition: Object.assign(Object.assign({}, meshConditionTypeToCondition(conditionType, context)), { target: types_2.ConditionTarget.Sender, trustedClaimIssuers: issuers.map(trustedIssuer => trustedIssuerToTrustedClaimIssuer(trustedIssuer, context)) }),
            complies: boolToBoolean(result),
        };
        const existingCondition = conditions.find(condition => conditionCompliancesAreEqual(condition, newCondition));
        if (!existingCondition) {
            conditions.push(newCondition);
        }
    });
    complianceRequirement.receiverConditions.forEach(({ condition: { conditionType, issuers }, result }) => {
        const newCondition = {
            condition: Object.assign(Object.assign({}, meshConditionTypeToCondition(conditionType, context)), { target: types_2.ConditionTarget.Receiver, trustedClaimIssuers: issuers.map(trustedIssuer => trustedIssuerToTrustedClaimIssuer(trustedIssuer, context)) }),
            complies: boolToBoolean(result),
        };
        const existingCondition = conditions.find(condition => conditionCompliancesAreEqual(condition, newCondition));
        if (existingCondition && existingCondition.condition.target === types_2.ConditionTarget.Sender) {
            existingCondition.condition.target = types_2.ConditionTarget.Both;
        }
        else {
            conditions.push(newCondition);
        }
    });
    return {
        id: u32ToBigNumber(complianceRequirement.id),
        conditions,
        complies: boolToBoolean(complianceRequirement.result),
    };
}
exports.complianceRequirementResultToRequirementCompliance = complianceRequirementResultToRequirementCompliance;
/**
 * @hidden
 */
function complianceRequirementToRequirement(complianceRequirement, context) {
    const conditions = [];
    complianceRequirement.senderConditions.forEach(({ conditionType, issuers }) => {
        const newCondition = Object.assign(Object.assign({}, meshConditionTypeToCondition(conditionType, context)), { target: types_2.ConditionTarget.Sender });
        if (issuers.length) {
            newCondition.trustedClaimIssuers = issuers.map(trustedIssuer => trustedIssuerToTrustedClaimIssuer(trustedIssuer, context));
        }
        const existingCondition = conditions.find(condition => (0, internal_3.conditionsAreEqual)(condition, newCondition));
        if (!existingCondition) {
            conditions.push(newCondition);
        }
    });
    complianceRequirement.receiverConditions.forEach(({ conditionType, issuers }) => {
        const newCondition = Object.assign(Object.assign({}, meshConditionTypeToCondition(conditionType, context)), { target: types_2.ConditionTarget.Receiver });
        if (issuers.length) {
            newCondition.trustedClaimIssuers = issuers.map(trustedIssuer => trustedIssuerToTrustedClaimIssuer(trustedIssuer, context));
        }
        const existingCondition = conditions.find(condition => (0, internal_3.conditionsAreEqual)(condition, newCondition));
        if (existingCondition && existingCondition.target === types_2.ConditionTarget.Sender) {
            existingCondition.target = types_2.ConditionTarget.Both;
        }
        else {
            conditions.push(newCondition);
        }
    });
    return {
        id: u32ToBigNumber(complianceRequirement.id),
        conditions,
    };
}
exports.complianceRequirementToRequirement = complianceRequirementToRequirement;
/**
 * @hidden
 */
function txTagToProtocolOp(tag, context) {
    const protocolOpTags = [
        types_2.TxTags.asset.RegisterTicker,
        types_2.TxTags.asset.Issue,
        types_2.TxTags.asset.AddDocuments,
        types_2.TxTags.asset.CreateAsset,
        types_2.TxTags.capitalDistribution.Distribute,
        types_2.TxTags.checkpoint.CreateSchedule,
        types_2.TxTags.complianceManager.AddComplianceRequirement,
        types_2.TxTags.identity.CddRegisterDid,
        types_2.TxTags.identity.AddClaim,
        types_2.TxTags.identity.AddSecondaryKeysWithAuthorization,
        types_2.TxTags.pips.Propose,
        types_2.TxTags.corporateBallot.AttachBallot,
        types_2.TxTags.capitalDistribution.Distribute,
    ];
    const [moduleName, extrinsicName] = tag.split('.');
    const value = `${(0, util_1.stringUpperFirst)(moduleName)}${(0, util_1.stringUpperFirst)(extrinsicName)}`;
    if (!(0, lodash_1.includes)(protocolOpTags, tag)) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: `${value} does not match any ProtocolOp`,
        });
    }
    return context.createType('ProtocolOp', value);
}
exports.txTagToProtocolOp = txTagToProtocolOp;
/**
 * @hidden
 */
function txTagToExtrinsicIdentifier(tag) {
    const [moduleName, extrinsicName] = tag.split('.');
    return {
        moduleId: moduleName.toLowerCase(),
        callId: (0, lodash_1.snakeCase)(extrinsicName),
    };
}
exports.txTagToExtrinsicIdentifier = txTagToExtrinsicIdentifier;
/**
 * @hidden
 */
function extrinsicIdentifierToTxTag(extrinsicIdentifier) {
    const { moduleId, callId } = extrinsicIdentifier;
    let moduleName;
    for (const txTagItem in types_2.TxTags) {
        if (txTagItem.toLowerCase() === moduleId) {
            moduleName = txTagItem;
        }
    }
    return `${moduleName}.${(0, lodash_1.camelCase)(callId)}`;
}
exports.extrinsicIdentifierToTxTag = extrinsicIdentifierToTxTag;
/**
 * @hidden
 */
function assetComplianceResultToCompliance(assetComplianceResult, context) {
    const { requirements: rawRequirements, result, paused } = assetComplianceResult;
    const requirements = rawRequirements.map(requirement => complianceRequirementResultToRequirementCompliance(requirement, context));
    return {
        requirements,
        complies: boolToBoolean(paused) || boolToBoolean(result),
    };
}
exports.assetComplianceResultToCompliance = assetComplianceResultToCompliance;
/**
 * @hidden
 */
function moduleAddressToString(moduleAddress, context) {
    return (0, util_crypto_1.encodeAddress)((0, util_1.stringToU8a)((0, internal_3.padString)(moduleAddress, constants_1.MAX_MODULE_LENGTH)), context.ss58Format.toNumber());
}
exports.moduleAddressToString = moduleAddressToString;
/**
 * @hidden
 */
function keyToAddress(key, context) {
    return (0, util_crypto_1.encodeAddress)(key, context.ss58Format.toNumber());
}
exports.keyToAddress = keyToAddress;
/**
 * @hidden
 */
function addressToKey(address, context) {
    return (0, util_1.u8aToHex)((0, util_crypto_1.decodeAddress)(address, constants_1.IGNORE_CHECKSUM, context.ss58Format.toNumber()));
}
exports.addressToKey = addressToKey;
/**
 * @hidden
 */
function transactionHexToTxTag(bytes, context) {
    const { section, method } = context.createType('Call', bytes);
    return extrinsicIdentifierToTxTag({
        moduleId: section.toLowerCase(),
        callId: method,
    });
}
exports.transactionHexToTxTag = transactionHexToTxTag;
/**
 * @hidden
 */
function transactionToTxTag(tx) {
    return `${tx.section}.${tx.method}`;
}
exports.transactionToTxTag = transactionToTxTag;
/**
 * @hidden
 */
function secondaryAccountToMeshSecondaryKey(secondaryKey, context) {
    const { account, permissions } = secondaryKey;
    return context.createType('SecondaryKey', {
        signer: signerValueToSignatory(signerToSignerValue(account), context),
        permissions: permissionsToMeshPermissions(permissions, context),
    });
}
exports.secondaryAccountToMeshSecondaryKey = secondaryAccountToMeshSecondaryKey;
/**
 * @hidden
 */
function meshVenueTypeToVenueType(type) {
    if (type.isOther) {
        return types_2.VenueType.Other;
    }
    if (type.isDistribution) {
        return types_2.VenueType.Distribution;
    }
    if (type.isSto) {
        return types_2.VenueType.Sto;
    }
    return types_2.VenueType.Exchange;
}
exports.meshVenueTypeToVenueType = meshVenueTypeToVenueType;
/**
 * @hidden
 */
function venueTypeToMeshVenueType(type, context) {
    return context.createType('VenueType', type);
}
exports.venueTypeToMeshVenueType = venueTypeToMeshVenueType;
/**
 * @hidden
 */
function meshInstructionStatusToInstructionStatus(status) {
    if (status.isPending) {
        return internal_2.InstructionStatus.Pending;
    }
    if (status.isFailed) {
        return internal_2.InstructionStatus.Failed;
    }
    return internal_2.InstructionStatus.Unknown;
}
exports.meshInstructionStatusToInstructionStatus = meshInstructionStatusToInstructionStatus;
/**
 * @hidden
 */
function meshAffirmationStatusToAffirmationStatus(status) {
    if (status.isUnknown) {
        return types_2.AffirmationStatus.Unknown;
    }
    if (status.isPending) {
        return types_2.AffirmationStatus.Pending;
    }
    return types_2.AffirmationStatus.Affirmed;
}
exports.meshAffirmationStatusToAffirmationStatus = meshAffirmationStatusToAffirmationStatus;
/**
 * @hidden
 */
function endConditionToSettlementType(endCondition, context) {
    let value;
    if (endCondition.type === types_2.InstructionType.SettleOnAffirmation) {
        value = types_2.InstructionType.SettleOnAffirmation;
    }
    else {
        value = {
            [types_2.InstructionType.SettleOnBlock]: bigNumberToU32(endCondition.value, context),
        };
    }
    return context.createType('SettlementType', value);
}
exports.endConditionToSettlementType = endConditionToSettlementType;
/**
 * @hidden
 */
function toIdentityWithClaimsArray(data, context) {
    return data.map(({ did, claims }) => ({
        identity: new internal_1.Identity({ did }, context),
        claims: claims.map(({ targetDID: targetDid, issuer, issuance_date: issuanceDate, expiry, type, jurisdiction, scope: claimScope, cdd_id: cddId, }) => ({
            target: new internal_1.Identity({ did: targetDid }, context),
            issuer: new internal_1.Identity({ did: issuer }, context),
            issuedAt: new Date(issuanceDate),
            expiry: expiry ? new Date(expiry) : null,
            claim: (0, internal_3.createClaim)(type, jurisdiction, claimScope, cddId, undefined),
        })),
    }));
}
exports.toIdentityWithClaimsArray = toIdentityWithClaimsArray;
/**
 * @hidden
 */
function portfolioMovementToMovePortfolioItem(portfolioItem, context) {
    const { asset, amount, memo } = portfolioItem;
    return context.createType('MovePortfolioItem', {
        ticker: stringToTicker((0, internal_3.asTicker)(asset), context),
        amount: bigNumberToBalance(amount, context),
        memo: (0, internal_3.optionize)(stringToMemo)(memo, context),
    });
}
exports.portfolioMovementToMovePortfolioItem = portfolioMovementToMovePortfolioItem;
/**
 * @hidden
 */
function claimTypeToMeshClaimType(claimType, context) {
    // NoData is the legacy name for NoType. Functionally they are the same, but createType only knows about one
    const data = claimType === types_2.ClaimType.NoData ? types_2.ClaimType.NoType : claimType;
    return context.createType('PolymeshPrimitivesIdentityClaimClaimType', data);
}
exports.claimTypeToMeshClaimType = claimTypeToMeshClaimType;
/**
 * @hidden
 */
function transferRestrictionToPolymeshTransferCondition(restriction, context) {
    const { type, value } = restriction;
    let restrictionType;
    let restrictionValue;
    if (type === types_2.TransferRestrictionType.Count) {
        restrictionType = 'MaxInvestorCount';
        restrictionValue = bigNumberToU64(value, context);
    }
    else {
        restrictionType = 'MaxInvestorOwnership';
        restrictionValue = percentageToPermill(value, context);
    }
    return context.createType('PolymeshPrimitivesTransferComplianceTransferCondition', {
        [restrictionType]: restrictionValue,
    });
}
exports.transferRestrictionToPolymeshTransferCondition = transferRestrictionToPolymeshTransferCondition;
/**
 * @hidden
 */
function scopeIdsToBtreeSetIdentityId(scopeIds, context) {
    // The chain expects inputs to be sorted. Copy to avoid mutating input
    const sortedScopes = [...scopeIds].sort();
    return context.createType('BTreeSetIdentityId', sortedScopes);
}
exports.scopeIdsToBtreeSetIdentityId = scopeIdsToBtreeSetIdentityId;
/**
 * @hidden
 */
function transferConditionToTransferRestriction(transferCondition) {
    if (transferCondition.isMaxInvestorCount) {
        return {
            type: types_2.TransferRestrictionType.Count,
            value: u64ToBigNumber(transferCondition.asMaxInvestorCount),
        };
    }
    else if (transferCondition.isMaxInvestorOwnership) {
        return {
            type: types_2.TransferRestrictionType.Percentage,
            value: permillToBigNumber(transferCondition.asMaxInvestorOwnership),
        };
    }
    else {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.FatalError,
            message: 'Unexpected transfer condition type',
        });
    }
}
exports.transferConditionToTransferRestriction = transferConditionToTransferRestriction;
/**
 * @hidden
 */
function granularCanTransferResultToTransferBreakdown(result, context) {
    const { invalid_granularity: invalidGranularity, self_transfer: selfTransfer, invalid_receiver_cdd: invalidReceiverCdd, invalid_sender_cdd: invalidSenderCdd, missing_scope_claim: missingScopeClaim, sender_insufficient_balance: insufficientBalance, asset_frozen: assetFrozen, portfolio_validity_result: { sender_portfolio_does_not_exist: senderPortfolioNotExists, receiver_portfolio_does_not_exist: receiverPortfolioNotExists, sender_insufficient_balance: senderInsufficientBalance, }, transfer_condition_result: transferConditionResult, compliance_result: complianceResult, result: finalResult, } = result;
    const general = [];
    if (boolToBoolean(invalidGranularity)) {
        general.push(types_2.TransferError.InvalidGranularity);
    }
    if (boolToBoolean(selfTransfer)) {
        general.push(types_2.TransferError.SelfTransfer);
    }
    if (boolToBoolean(invalidReceiverCdd)) {
        general.push(types_2.TransferError.InvalidReceiverCdd);
    }
    if (boolToBoolean(invalidSenderCdd)) {
        general.push(types_2.TransferError.InvalidSenderCdd);
    }
    if (boolToBoolean(missingScopeClaim)) {
        general.push(types_2.TransferError.ScopeClaimMissing);
    }
    if (boolToBoolean(insufficientBalance)) {
        general.push(types_2.TransferError.InsufficientBalance);
    }
    if (boolToBoolean(assetFrozen)) {
        general.push(types_2.TransferError.TransfersFrozen);
    }
    if (boolToBoolean(senderPortfolioNotExists)) {
        general.push(types_2.TransferError.InvalidSenderPortfolio);
    }
    if (boolToBoolean(receiverPortfolioNotExists)) {
        general.push(types_2.TransferError.InvalidReceiverPortfolio);
    }
    if (boolToBoolean(senderInsufficientBalance)) {
        general.push(types_2.TransferError.InsufficientPortfolioBalance);
    }
    const restrictions = transferConditionResult.map(({ condition, result: tmResult }) => {
        return {
            restriction: transferConditionToTransferRestriction(condition),
            result: boolToBoolean(tmResult),
        };
    });
    return {
        general,
        compliance: assetComplianceResultToCompliance(complianceResult, context),
        restrictions,
        result: boolToBoolean(finalResult),
    };
}
exports.granularCanTransferResultToTransferBreakdown = granularCanTransferResultToTransferBreakdown;
/**
 * @hidden
 */
function offeringTierToPriceTier(tier, context) {
    const { price, amount } = tier;
    return context.createType('PriceTier', {
        total: bigNumberToBalance(amount, context),
        price: bigNumberToBalance(price, context),
    });
}
exports.offeringTierToPriceTier = offeringTierToPriceTier;
/**
 * @hidden
 */
function permissionsLikeToPermissions(permissionsLike, context) {
    let assetPermissions = {
        values: [],
        type: types_2.PermissionType.Include,
    };
    let transactionPermissions = {
        values: [],
        type: types_2.PermissionType.Include,
    };
    let transactionGroupPermissions = [];
    let portfolioPermissions = {
        values: [],
        type: types_2.PermissionType.Include,
    };
    let transactions;
    let transactionGroups;
    if ('transactions' in permissionsLike) {
        ({ transactions } = permissionsLike);
    }
    if ('transactionGroups' in permissionsLike) {
        ({ transactionGroups } = permissionsLike);
    }
    const { assets, portfolios } = permissionsLike;
    if (assets === null) {
        assetPermissions = null;
    }
    else if (assets) {
        assetPermissions = Object.assign(Object.assign({}, assets), { values: assets.values.map(ticker => typeof ticker !== 'string' ? ticker : new internal_1.Asset({ ticker }, context)) });
    }
    if (transactions !== undefined) {
        transactionPermissions = transactions;
    }
    else if (transactionGroups !== undefined) {
        transactionGroupPermissions = (0, lodash_1.uniq)(transactionGroups);
        const groupTags = (0, lodash_1.flatten)(transactionGroups.map(txGroupToTxTags));
        transactionPermissions = Object.assign(Object.assign({}, transactionPermissions), { values: groupTags });
    }
    if (portfolios === null) {
        portfolioPermissions = null;
    }
    else if (portfolios) {
        portfolioPermissions = Object.assign(Object.assign({}, portfolios), { values: portfolios.values.map(portfolio => portfolioLikeToPortfolio(portfolio, context)) });
    }
    return {
        assets: assetPermissions,
        transactions: transactionPermissions && Object.assign(Object.assign({}, transactionPermissions), { values: [...transactionPermissions.values].sort() }),
        transactionGroups: transactionGroupPermissions,
        portfolios: portfolioPermissions,
    };
}
exports.permissionsLikeToPermissions = permissionsLikeToPermissions;
/**
 * @hidden
 */
function middlewarePortfolioToPortfolio(portfolio, context) {
    const { did, kind } = portfolio;
    if (kind.toLowerCase() === 'default' || kind === '0') {
        return new internal_1.DefaultPortfolio({ did }, context);
    }
    return new internal_1.NumberedPortfolio({ did, id: new bignumber_js_1.default(kind) }, context);
}
exports.middlewarePortfolioToPortfolio = middlewarePortfolioToPortfolio;
/**
 * @hidden
 */
function fundraiserTierToTier(fundraiserTier) {
    const { total, price, remaining } = fundraiserTier;
    return {
        amount: balanceToBigNumber(total),
        price: balanceToBigNumber(price),
        remaining: balanceToBigNumber(remaining),
    };
}
exports.fundraiserTierToTier = fundraiserTierToTier;
/**
 * @hidden
 */
function fundraiserToOfferingDetails(fundraiser, name, context) {
    const { creator, offeringPortfolio, raisingPortfolio, raisingAsset, tiers: rawTiers, venueId, start: rawStart, end: rawEnd, status: rawStatus, minimumInvestment: rawMinInvestment, } = fundraiser;
    const tiers = [];
    let totalRemaining = new bignumber_js_1.default(0);
    let totalAmount = new bignumber_js_1.default(0);
    let totalRemainingValue = new bignumber_js_1.default(0);
    rawTiers.forEach(rawTier => {
        const tier = fundraiserTierToTier(rawTier);
        tiers.push(tier);
        const { amount, remaining, price } = tier;
        totalAmount = totalAmount.plus(amount);
        totalRemaining = totalRemaining.plus(remaining);
        totalRemainingValue = totalRemainingValue.plus(price.multipliedBy(remaining));
    });
    const start = momentToDate(rawStart);
    const end = rawEnd.isSome ? momentToDate(rawEnd.unwrap()) : null;
    const now = new Date();
    const isStarted = now > start;
    const isExpired = end && now > end;
    const minInvestment = balanceToBigNumber(rawMinInvestment);
    let timing = types_2.OfferingTimingStatus.NotStarted;
    let balance = types_2.OfferingBalanceStatus.Available;
    let sale = types_2.OfferingSaleStatus.Live;
    if (isExpired) {
        timing = types_2.OfferingTimingStatus.Expired;
    }
    else if (isStarted) {
        timing = types_2.OfferingTimingStatus.Started;
    }
    if (totalRemainingValue.isZero()) {
        balance = types_2.OfferingBalanceStatus.SoldOut;
    }
    else if (totalRemainingValue.lt(minInvestment)) {
        balance = types_2.OfferingBalanceStatus.Residual;
    }
    if (rawStatus.isClosedEarly) {
        sale = types_2.OfferingSaleStatus.ClosedEarly;
    }
    else if (rawStatus.isClosed) {
        sale = types_2.OfferingSaleStatus.Closed;
    }
    else if (rawStatus.isFrozen) {
        sale = types_2.OfferingSaleStatus.Frozen;
    }
    return {
        creator: new internal_1.Identity({ did: identityIdToString(creator) }, context),
        name: bytesToString(name),
        offeringPortfolio: meshPortfolioIdToPortfolio(offeringPortfolio, context),
        raisingPortfolio: meshPortfolioIdToPortfolio(raisingPortfolio, context),
        raisingCurrency: tickerToString(raisingAsset),
        tiers,
        venue: new internal_1.Venue({ id: u64ToBigNumber(venueId) }, context),
        start,
        end,
        status: {
            timing,
            balance,
            sale,
        },
        minInvestment,
        totalAmount,
        totalRemaining,
    };
}
exports.fundraiserToOfferingDetails = fundraiserToOfferingDetails;
/**
 * @hidden
 */
function calendarPeriodToMeshCalendarPeriod(period, context) {
    const { unit, amount } = period;
    if (amount.isNegative()) {
        throw new internal_1.PolymeshError({
            code: types_2.ErrorCode.ValidationError,
            message: 'Calendar period cannot have a negative amount',
        });
    }
    return context.createType('CalendarPeriod', {
        unit: (0, util_1.stringUpperFirst)(unit),
        amount: bigNumberToU64(amount, context),
    });
}
exports.calendarPeriodToMeshCalendarPeriod = calendarPeriodToMeshCalendarPeriod;
/**
 * @hidden
 */
function meshCalendarPeriodToCalendarPeriod(period) {
    const { unit: rawUnit, amount } = period;
    let unit;
    if (rawUnit.isSecond) {
        unit = types_2.CalendarUnit.Second;
    }
    else if (rawUnit.isMinute) {
        unit = types_2.CalendarUnit.Minute;
    }
    else if (rawUnit.isHour) {
        unit = types_2.CalendarUnit.Hour;
    }
    else if (rawUnit.isDay) {
        unit = types_2.CalendarUnit.Day;
    }
    else if (rawUnit.isWeek) {
        unit = types_2.CalendarUnit.Week;
    }
    else if (rawUnit.isMonth) {
        unit = types_2.CalendarUnit.Month;
    }
    else {
        unit = types_2.CalendarUnit.Year;
    }
    return {
        unit,
        amount: u64ToBigNumber(amount),
    };
}
exports.meshCalendarPeriodToCalendarPeriod = meshCalendarPeriodToCalendarPeriod;
/**
 * @hidden
 */
function scheduleSpecToMeshScheduleSpec(details, context) {
    const { start, period, repetitions } = details;
    return context.createType('ScheduleSpec', {
        start: start && dateToMoment(start, context),
        period: calendarPeriodToMeshCalendarPeriod(period || { unit: types_2.CalendarUnit.Month, amount: new bignumber_js_1.default(0) }, context),
        remaining: bigNumberToU64(repetitions || new bignumber_js_1.default(0), context),
    });
}
exports.scheduleSpecToMeshScheduleSpec = scheduleSpecToMeshScheduleSpec;
/**
 * @hidden
 */
function storedScheduleToCheckpointScheduleParams(storedSchedule) {
    const { schedule: { start, period }, id, at, remaining, } = storedSchedule;
    return {
        id: u64ToBigNumber(id),
        period: meshCalendarPeriodToCalendarPeriod(period),
        start: momentToDate(start),
        remaining: u32ToBigNumber(remaining),
        nextCheckpointDate: momentToDate(at),
    };
}
exports.storedScheduleToCheckpointScheduleParams = storedScheduleToCheckpointScheduleParams;
/**
 * @hidden
 */
function stringToSignature(signature, context) {
    return context.createType('Signature', signature);
}
exports.stringToSignature = stringToSignature;
/**
 * @hidden
 */
function meshCorporateActionToCorporateActionParams(corporateAction, details, context) {
    const { kind: rawKind, declDate, targets: { identities, treatment }, defaultWithholdingTax, withholdingTax, } = corporateAction;
    let kind;
    if (rawKind.isIssuerNotice) {
        kind = types_2.CorporateActionKind.IssuerNotice;
    }
    else if (rawKind.isPredictableBenefit) {
        kind = types_2.CorporateActionKind.PredictableBenefit;
    }
    else if (rawKind.isUnpredictableBenefit) {
        kind = types_2.CorporateActionKind.UnpredictableBenefit;
    }
    else if (rawKind.isReorganization) {
        kind = types_2.CorporateActionKind.Reorganization;
    }
    else {
        kind = types_2.CorporateActionKind.Other;
    }
    const targets = {
        identities: identities.map(identityId => new internal_1.Identity({ did: identityIdToString(identityId) }, context)),
        treatment: treatment.isExclude ? types_2.TargetTreatment.Exclude : types_2.TargetTreatment.Include,
    };
    const taxWithholdings = withholdingTax.map(([identityId, tax]) => ({
        identity: new internal_1.Identity({ did: identityIdToString(identityId) }, context),
        percentage: permillToBigNumber(tax),
    }));
    return {
        kind,
        declarationDate: momentToDate(declDate),
        description: bytesToString(details),
        targets,
        defaultTaxWithholding: permillToBigNumber(defaultWithholdingTax),
        taxWithholdings,
    };
}
exports.meshCorporateActionToCorporateActionParams = meshCorporateActionToCorporateActionParams;
/**
 * @hidden
 */
function stringToRistrettoPoint(ristrettoPoint, context) {
    return context.createType('RistrettoPoint', ristrettoPoint);
}
exports.stringToRistrettoPoint = stringToRistrettoPoint;
/**
 * @hidden
 */
function corporateActionKindToCaKind(kind, context) {
    return context.createType('CAKind', kind);
}
exports.corporateActionKindToCaKind = corporateActionKindToCaKind;
/**
 * @hidden
 */
function stringToScalar(scalar, context) {
    return context.createType('Scalar', scalar);
}
exports.stringToScalar = stringToScalar;
/**
 * @hidden
 */
function checkpointToRecordDateSpec(checkpoint, context) {
    let value;
    if (checkpoint instanceof internal_1.Checkpoint) {
        /* eslint-disable @typescript-eslint/naming-convention */
        value = { Existing: bigNumberToU64(checkpoint.id, context) };
    }
    else if (checkpoint instanceof Date) {
        value = { Scheduled: dateToMoment(checkpoint, context) };
    }
    else {
        value = { ExistingSchedule: bigNumberToU64(checkpoint.id, context) };
        /* eslint-enable @typescript-eslint/naming-convention */
    }
    return context.createType('RecordDateSpec', value);
}
exports.checkpointToRecordDateSpec = checkpointToRecordDateSpec;
/**
 * @hidden
 */
function scopeClaimProofToConfidentialIdentityClaimProof(proof, scopeId, context) {
    const { proofScopeIdWellFormed, proofScopeIdCddIdMatch: { challengeResponses, subtractExpressionsRes, blindedScopeDidHash }, } = proof;
    const zkProofData = context.createType('ZkProofData', {
        /* eslint-disable @typescript-eslint/naming-convention */
        challenge_responses: challengeResponses.map(cr => stringToScalar(cr, context)),
        subtract_expressions_res: stringToRistrettoPoint(subtractExpressionsRes, context),
        blinded_scope_did_hash: stringToRistrettoPoint(blindedScopeDidHash, context),
        /* eslint-enable @typescript-eslint/naming-convention */
    });
    return context.createType('ConfidentialIdentityClaimProofsScopeClaimProof', {
        proofScopeIdWellformed: stringToSignature(proofScopeIdWellFormed, context),
        proofScopeIdCddIdMatch: zkProofData,
        scopeId: stringToRistrettoPoint(scopeId, context),
    });
}
exports.scopeClaimProofToConfidentialIdentityClaimProof = scopeClaimProofToConfidentialIdentityClaimProof;
/**
 * @hidden
 */
function targetIdentitiesToCorporateActionTargets(targetIdentities, context) {
    const { identities, treatment } = targetIdentities;
    return {
        identities: identities.map(identity => new internal_1.Identity({ did: identityIdToString(identity) }, context)),
        treatment: treatment.isInclude ? types_2.TargetTreatment.Include : types_2.TargetTreatment.Exclude,
    };
}
exports.targetIdentitiesToCorporateActionTargets = targetIdentitiesToCorporateActionTargets;
/**
 * @hidden
 */
function targetsToTargetIdentities(targets, context) {
    const { treatment, identities } = targets;
    return context.createType('TargetIdentities', {
        identities: identities.map(identity => stringToIdentityId(signerToString(identity), context)),
        treatment: context.createType('TargetTreatment', treatment),
    });
}
exports.targetsToTargetIdentities = targetsToTargetIdentities;
/**
 * @hidden
 */
function distributionToDividendDistributionParams(distribution, context) {
    const { from, currency, perShare, amount, expiresAt: expiryDate, paymentAt: paymentDate, } = distribution;
    return {
        origin: meshPortfolioIdToPortfolio(from, context),
        currency: tickerToString(currency),
        perShare: balanceToBigNumber(perShare),
        maxAmount: balanceToBigNumber(amount),
        expiryDate: expiryDate.isNone ? null : momentToDate(expiryDate.unwrap()),
        paymentDate: momentToDate(paymentDate),
    };
}
exports.distributionToDividendDistributionParams = distributionToDividendDistributionParams;
/**
 * @hidden
 */
function corporateActionIdentifierToCaId(corporateActionIdentifier, context) {
    const { ticker, localId } = corporateActionIdentifier;
    return context.createType('PalletCorporateActionsCaId', {
        ticker: stringToTicker(ticker, context),
        localId: bigNumberToU32(localId, context),
    });
}
exports.corporateActionIdentifierToCaId = corporateActionIdentifierToCaId;
/**
 * @hidden
 */
function statisticsOpTypeToStatType(op, context) {
    return context.createType('PolymeshPrimitivesStatisticsStatType', { op });
}
exports.statisticsOpTypeToStatType = statisticsOpTypeToStatType;
/**
 * @hidden
 */
function statUpdate(key2, value, context) {
    return context.createType('PolymeshPrimitivesStatisticsStatUpdate', { key2, value });
}
exports.statUpdate = statUpdate;
/**
 * @hidden
 */
function statUpdatesToBtreeStatUpdate(statUpdates, context) {
    const sorted = [...statUpdates];
    return context.createType('BTreeSetStatUpdate', sorted);
}
exports.statUpdatesToBtreeStatUpdate = statUpdatesToBtreeStatUpdate;
/**
 * @hidden
 */
function meshStatToStatisticsOpType(rawStat) {
    return rawStat.op.type;
}
exports.meshStatToStatisticsOpType = meshStatToStatisticsOpType;
/**
 * @hidden
 */
function statisticsOpTypeToStatOpType(type, context) {
    return context.createType('PolymeshPrimitivesStatisticsStatOpType', type);
}
exports.statisticsOpTypeToStatOpType = statisticsOpTypeToStatOpType;
/**
 * For now this is hard coded to return a NoClaimStat type. Once Claim scopes are added this should be extended
 * @hidden
 */
function createStat2ndKey(context) {
    return context.createType('PolymeshPrimitivesStatisticsStat2ndKey', 'NoClaimStat');
}
exports.createStat2ndKey = createStat2ndKey;
/**
 * @hidden
 */
function complianceConditionsToBtreeSet(conditions, context) {
    // The chain expects inputs to be sorted. Copy to avoid mutating input
    const sorted = [...conditions].sort();
    return context.createType('BTreeSetTransferCondition', sorted);
}
exports.complianceConditionsToBtreeSet = complianceConditionsToBtreeSet;
/**
 * @hidden
 */
function toExemptKey(tickerKey, op) {
    return { asset: tickerKey, op };
}
exports.toExemptKey = toExemptKey;
//# sourceMappingURL=conversion.js.map