From a1369fc1ce779bb08effa34dd3532bfebb29ed1b Mon Sep 17 00:00:00 2001 From: Prashant Bajpai <34747455+prashantasdeveloper@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:00:30 +0530 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Add=20dual=20version=20s?= =?UTF-8?q?upport=20for=206.x-7.x=20chain?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/client/Assets.ts | 198 ++++++++--- src/api/client/Claims.ts | 6 +- src/api/entities/Asset/Base/BaseAsset.ts | 132 ++++--- .../Asset/Base/Compliance/Requirements.ts | 36 +- .../Base/Compliance/TrustedClaimIssuers.ts | 20 +- .../entities/Asset/Base/Documents/index.ts | 11 +- src/api/entities/Asset/Base/Metadata/index.ts | 45 +-- .../entities/Asset/Base/Permissions/index.ts | 42 +-- .../entities/Asset/Base/Settlements/index.ts | 23 +- .../Asset/Fungible/AssetHolders/index.ts | 8 +- .../Asset/Fungible/Checkpoints/Schedules.ts | 20 +- .../Asset/Fungible/Checkpoints/index.ts | 21 +- .../CorporateActions/Distributions.ts | 17 +- .../Asset/Fungible/CorporateActions/index.ts | 23 +- .../entities/Asset/Fungible/Issuance/index.ts | 4 +- .../Asset/Fungible/Offerings/index.ts | 27 +- .../TransferRestrictionBase.ts | 47 +-- src/api/entities/Asset/Fungible/index.ts | 40 ++- .../Asset/NonFungible/AssetHolders/index.ts | 10 +- src/api/entities/Asset/NonFungible/Nft.ts | 43 ++- .../Asset/NonFungible/NftCollection.ts | 86 +++-- src/api/entities/Asset/types.ts | 12 +- src/api/entities/Checkpoint.ts | 72 ++-- src/api/entities/CheckpointSchedule/index.ts | 37 +- src/api/entities/CorporateAction.ts | 6 +- src/api/entities/CorporateActionBase/index.ts | 50 ++- src/api/entities/CustomPermissionGroup.ts | 32 +- src/api/entities/DefaultTrustedClaimIssuer.ts | 20 +- .../entities/DividendDistribution/index.ts | 16 +- src/api/entities/Identity/AssetPermissions.ts | 37 +- src/api/entities/Identity/index.ts | 92 +++-- src/api/entities/Instruction/index.ts | 34 +- src/api/entities/KnownPermissionGroup.ts | 11 +- src/api/entities/MetadataEntry/index.ts | 39 ++- src/api/entities/Offering/index.ts | 54 +-- src/api/entities/PermissionGroup.ts | 10 +- src/api/entities/Portfolio/index.ts | 52 +-- src/api/entities/TickerReservation/index.ts | 44 ++- src/api/entities/types.ts | 4 + src/api/procedures/__tests__/moveFunds.ts | 4 +- src/api/procedures/addAssetMediators.ts | 14 +- src/api/procedures/addAssetRequirement.ts | 16 +- src/api/procedures/addAssetStat.ts | 26 +- src/api/procedures/addInstruction.ts | 28 +- src/api/procedures/addTransferRestriction.ts | 25 +- src/api/procedures/claimDividends.ts | 9 +- src/api/procedures/clearMetadata.ts | 26 +- src/api/procedures/closeOffering.ts | 21 +- .../configureDividendDistribution.ts | 28 +- src/api/procedures/controllerTransfer.ts | 16 +- src/api/procedures/createAsset.ts | 74 ++-- src/api/procedures/createCheckpoint.ts | 20 +- .../procedures/createCheckpointSchedule.ts | 22 +- src/api/procedures/createGroup.ts | 39 +-- src/api/procedures/createNftCollection.ts | 93 +++-- src/api/procedures/investInOffering.ts | 19 +- src/api/procedures/inviteExternalAgent.ts | 44 +-- src/api/procedures/issueNft.ts | 46 +-- src/api/procedures/issueTokens.ts | 47 +-- src/api/procedures/launchOffering.ts | 27 +- src/api/procedures/linkCaDocs.ts | 15 +- src/api/procedures/modifyAsset.ts | 24 +- .../modifyAssetTrustedClaimIssuers.ts | 22 +- src/api/procedures/modifyCaCheckpoint.ts | 20 +- src/api/procedures/modifyCaDefaultConfig.ts | 20 +- .../procedures/modifyComplianceRequirement.ts | 20 +- .../procedures/modifyCorporateActionsAgent.ts | 15 +- src/api/procedures/modifyOfferingTimes.ts | 18 +- src/api/procedures/moveFunds.ts | 57 +-- src/api/procedures/nftControllerTransfer.ts | 43 ++- src/api/procedures/payDividends.ts | 4 +- .../reclaimDividendDistributionFunds.ts | 21 +- src/api/procedures/redeemNft.ts | 17 +- src/api/procedures/redeemTokens.ts | 41 +-- src/api/procedures/registerMetadata.ts | 28 +- src/api/procedures/removeAssetMediators.ts | 14 +- src/api/procedures/removeAssetRequirement.ts | 18 +- src/api/procedures/removeAssetStat.ts | 25 +- .../procedures/removeCheckpointSchedule.ts | 29 +- src/api/procedures/removeCorporateAction.ts | 18 +- src/api/procedures/removeExternalAgent.ts | 49 +-- src/api/procedures/removeLocalMetadata.ts | 42 +-- src/api/procedures/reserveTicker.ts | 11 +- src/api/procedures/setAssetDocuments.ts | 30 +- src/api/procedures/setAssetRequirements.ts | 20 +- src/api/procedures/setGroupPermissions.ts | 11 +- src/api/procedures/setMetadata.ts | 24 +- src/api/procedures/setPermissionGroup.ts | 9 +- src/api/procedures/setTransferRestrictions.ts | 40 +-- src/api/procedures/setVenueFiltering.ts | 25 +- src/api/procedures/toggleFreezeOffering.ts | 18 +- src/api/procedures/toggleFreezeTransfers.ts | 19 +- src/api/procedures/togglePauseRequirements.ts | 18 +- src/api/procedures/toggleTickerPreApproval.ts | 26 +- src/api/procedures/transferAssetOwnership.ts | 12 +- src/api/procedures/types.ts | 4 +- src/api/procedures/utils.ts | 8 +- src/api/procedures/waivePermissions.ts | 6 +- src/base/Context.ts | 44 ++- src/middleware/typesV1.ts | 4 + src/polkadot/polymesh/types.ts | 6 +- src/types/internal.ts | 28 +- src/utils/conversion.ts | 325 ++++++++++++------ src/utils/internal.ts | 208 ++++++++--- 104 files changed, 2026 insertions(+), 1555 deletions(-) diff --git a/src/api/client/Assets.ts b/src/api/client/Assets.ts index 91c63f8c30..7a6bccb85b 100644 --- a/src/api/client/Assets.ts +++ b/src/api/client/Assets.ts @@ -1,4 +1,5 @@ import { PolymeshPrimitivesTicker } from '@polkadot/types/lookup'; +import { U8aFixed } from '@polkadot/types-codec'; import { Context, @@ -26,6 +27,7 @@ import { UnsubCallback, } from '~/types'; import { + assetIdToString, bytesToString, meshMetadataSpecToMetadataSpec, stringToIdentityId, @@ -36,6 +38,7 @@ import { asAsset, assembleAssetQuery, createProcedureMethod, + getAssetIdForTicker, getDid, isPrintableAscii, requestPaginated, @@ -142,28 +145,41 @@ export class Assets { }): Promise { const { context: { - polymeshApi: { query }, + polymeshApi: { + query: { asset }, + }, + isV6, }, context, } = this; const did = await getDid(args?.owner, context); + const rawDid = stringToIdentityId(did, context); - const entries = await query.asset.assetOwnershipRelations.entries( - stringToIdentityId(did, context) - ); + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const entries = await (asset as any).assetOwnershipRelations.entries(rawDid); - return entries.reduce((result, [key, relation]) => { - if (relation.isTickerOwned) { - const ticker = tickerToString(key.args[1]); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return (entries as any[]).reduce((result, [key, relation]) => { + if (relation.isTickerOwned) { + const ticker = tickerToString(key.args[1]); - if (isPrintableAscii(ticker)) { - return [...result, new TickerReservation({ ticker }, context)]; + if (isPrintableAscii(ticker)) { + return [...result, new TickerReservation({ ticker }, context)]; + } } - } - return result; - }, []); + return result; + }, []); + } + + const entries = await asset.tickersOwnedByUser.entries(rawDid); + + return entries.map(([key]) => { + const ticker = tickerToString(key.args[1]); + return new TickerReservation({ ticker }, context); + }); } /** @@ -200,45 +216,109 @@ export class Assets { public async getAssets(args?: { owner: string | Identity }): Promise { const { context: { - polymeshApi: { query }, + polymeshApi: { + query: { asset }, + }, + isV6, }, context, } = this; const did = await getDid(args?.owner, context); + const rawDid = stringToIdentityId(did, context); + + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const entries = await (asset as any).assetOwnershipRelations.entries(rawDid); + + const ownedTickers: string[] = []; + const rawTickers: PolymeshPrimitivesTicker[] = []; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (entries as any[]).forEach(([key, relation]) => { + if (relation.isAssetOwned) { + const rawTicker = key.args[1]; + const ticker = tickerToString(rawTicker); + if (isPrintableAscii(ticker)) { + ownedTickers.push(ticker); + rawTickers.push(rawTicker); + } + } + }); - const entries = await query.asset.assetOwnershipRelations.entries( - stringToIdentityId(did, context) - ); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const ownedDetails = await (asset as any).tokens.multi(rawTickers); - const ownedTickers: string[] = []; - const rawTickers: PolymeshPrimitivesTicker[] = []; + return assembleAssetQuery(ownedDetails, ownedTickers, context); + } - entries.forEach(([key, relation]) => { - if (relation.isAssetOwned) { - const rawTicker = key.args[1]; - const ticker = tickerToString(rawTicker); - if (isPrintableAscii(ticker)) { - ownedTickers.push(ticker); - rawTickers.push(rawTicker); - } + const entries = await asset.securityTokensOwnedByuser.entries(rawDid); + + const ownedAssets: string[] = []; + const rawAssetIds: U8aFixed[] = []; + + entries.forEach(([key]) => { + const rawAssetId = key.args[1]; + const ticker = assetIdToString(rawAssetId); + if (isPrintableAscii(ticker)) { + ownedAssets.push(ticker); + rawAssetIds.push(rawAssetId); } }); + const ownedDetails = await asset.securityTokens.multi(rawAssetIds); - const ownedDetails = await query.asset.tokens.multi(rawTickers); - - return assembleAssetQuery(ownedDetails, ownedTickers, context); + return assembleAssetQuery(ownedDetails, ownedAssets, context); } /** * Retrieve a FungibleAsset * * @param args.ticker - Asset ticker + * @param args.assetId - Unique Id of the Asset (for spec version 6.x, this is same as ticker) */ - public async getFungibleAsset(args: { ticker: string }): Promise { - const { ticker } = args; + public async getFungibleAsset(args: { assetId: string }): Promise; + public async getFungibleAsset(args: { ticker: string }): Promise; + // eslint-disable-next-line require-jsdoc + public async getFungibleAsset(args: { + ticker?: string; + assetId?: string; + }): Promise { + const { ticker, assetId } = args; + + const { + context, + context: { isV6 }, + } = this; + + let asset: FungibleAsset; + if (isV6) { + const id = (assetId || ticker)!; + asset = new FungibleAsset({ assetId: id }, context); + const exists = await asset.exists(); + + if (!exists) { + throw new PolymeshError({ + code: ErrorCode.DataUnavailable, + message: `There is no Asset with ticker "${id}"`, + }); + } + + return asset; + } + + if (ticker) { + const id = await getAssetIdForTicker(ticker, context); + if (!id.length) { + throw new PolymeshError({ + code: ErrorCode.DataUnavailable, + message: `There is no Asset with ticker "${ticker}"`, + }); + } + asset = new FungibleAsset({ assetId: id }, context); + } else { + asset = new FungibleAsset({ assetId: assetId! }, context); + } - const asset = new FungibleAsset({ ticker }, this.context); const exists = await asset.exists(); if (!exists) { @@ -256,11 +336,51 @@ export class Assets { * * @param args.ticker - NftCollection ticker */ - public async getNftCollection(args: { ticker: string }): Promise { - const { ticker } = args; + public async getNftCollection(args: { ticker: string }): Promise; + public async getNftCollection(args: { assetId: string }): Promise; + + // eslint-disable-next-line require-jsdoc + public async getNftCollection(args: { + ticker?: string; + assetId?: string; + }): Promise { + const { ticker, assetId } = args; + + const { + context, + context: { isV6 }, + } = this; + + let collection: NftCollection; + if (isV6) { + const id = (assetId || ticker)!; + collection = new NftCollection({ assetId: id }, context); + const exists = await collection.exists(); + + if (!exists) { + throw new PolymeshError({ + code: ErrorCode.DataUnavailable, + message: `There is no NftCollection with ticker "${id}"`, + }); + } + + return collection; + } + + if (ticker) { + const id = await getAssetIdForTicker(ticker, context); + if (!id.length) { + throw new PolymeshError({ + code: ErrorCode.DataUnavailable, + message: `There is no NftCollection with ticker "${ticker}"`, + }); + } + collection = new NftCollection({ assetId: id }, context); + } else { + collection = new NftCollection({ assetId: assetId! }, context); + } - const nftCollection = new NftCollection({ ticker }, this.context); - const exists = await nftCollection.exists(); + const exists = await collection.exists(); if (!exists) { throw new PolymeshError({ @@ -269,7 +389,7 @@ export class Assets { }); } - return nftCollection; + return collection; } /** @@ -282,7 +402,7 @@ export class Assets { context: { polymeshApi: { query: { - asset: { assetNames, tokens }, + asset: { assetNames, securityTokens }, }, }, }, @@ -307,7 +427,7 @@ export class Assets { } ); - const details = await tokens.multi(rawTickers); + const details = await securityTokens.multi(rawTickers); const data = assembleAssetQuery(details, tickers, context); diff --git a/src/api/client/Claims.ts b/src/api/client/Claims.ts index 2912cea32e..5aadc2bcfe 100644 --- a/src/api/client/Claims.ts +++ b/src/api/client/Claims.ts @@ -215,7 +215,7 @@ export class Claims { let targetIssuers; const filters = { - scope: scope ? await scopeToMiddlewareScope(scope, context) : undefined, + scope: scope ? scopeToMiddlewareScope(scope) : undefined, trustedClaimIssuers: trustedClaimIssuers?.map(trustedClaimIssuer => signerToString(trustedClaimIssuer) ), @@ -360,7 +360,7 @@ export class Claims { issuedAt: momentToDate(issuanceDate), lastUpdatedAt: momentToDate(lastUpdateDate), expiry, - claim: meshClaimToClaim(claim) as CddClaim, + claim: meshClaimToClaim(claim, context) as CddClaim, }); } }); @@ -437,7 +437,7 @@ export class Claims { if (isMiddlewareAvailable) { const filters = { dids: [did], - scope: scope ? await scopeToMiddlewareScope(scope, context) : undefined, + scope: scope ? scopeToMiddlewareScope(scope) : undefined, includeExpired, }; diff --git a/src/api/entities/Asset/Base/BaseAsset.ts b/src/api/entities/Asset/Base/BaseAsset.ts index 175d2e719e..8867ef4736 100644 --- a/src/api/entities/Asset/Base/BaseAsset.ts +++ b/src/api/entities/Asset/Base/BaseAsset.ts @@ -44,6 +44,7 @@ import { import { tickerToDid } from '~/utils'; import { assetIdentifierToSecurityIdentifier, + assetToMeshAssetId, assetTypeToKnownOrId, balanceToBigNumber, bigNumberToU32, @@ -51,7 +52,6 @@ import { bytesToString, identitiesSetToIdentities, identityIdToString, - stringToTicker, u64ToBigNumber, } from '~/utils/conversion'; import { createProcedureMethod } from '~/utils/internal'; @@ -70,12 +70,19 @@ export class BaseAsset extends Entity { /** * Identity ID of the Asset (used for Claims) */ - public did: string; + + public did?: string; /** * ticker of the Asset */ - public ticker: string; + // TODO @prashantasdeveloper add comment + public ticker?: string; + + /** + * Unique ID of the Asset + */ + public id: string; /** * Transfer ownership of the Asset to another Identity. This generates an authorization request that must be accepted @@ -97,9 +104,9 @@ export class BaseAsset extends Entity { * Check if a value is of type {@link UniqueIdentifiers} */ public static override isUniqueIdentifiers(identifier: unknown): identifier is UniqueIdentifiers { - const { ticker } = identifier as UniqueIdentifiers; + const { assetId } = identifier as UniqueIdentifiers; - return typeof ticker === 'string'; + return typeof assetId === 'string'; } /** @@ -117,10 +124,15 @@ export class BaseAsset extends Entity { constructor(identifiers: UniqueIdentifiers, context: Context) { super(identifiers, context); - const { ticker } = identifiers; - - this.ticker = ticker; - this.did = tickerToDid(ticker); + const { assetId } = identifiers; + const { isV6 } = context; + if (isV6) { + this.ticker = assetId; + this.id = assetId; + this.did = tickerToDid(assetId); + } else { + this.id = assetId; + } this.compliance = new Compliance(this, context); this.documents = new Documents(this, context); @@ -129,7 +141,7 @@ export class BaseAsset extends Entity { this.freeze = createProcedureMethod( { - getProcedureAndArgs: () => [toggleFreezeTransfers, { ticker, freeze: true }], + getProcedureAndArgs: () => [toggleFreezeTransfers, { asset: this, freeze: true }], voidArgs: true, }, context @@ -137,14 +149,14 @@ export class BaseAsset extends Entity { this.unfreeze = createProcedureMethod( { - getProcedureAndArgs: () => [toggleFreezeTransfers, { ticker, freeze: false }], + getProcedureAndArgs: () => [toggleFreezeTransfers, { asset: this, freeze: false }], voidArgs: true, }, context ); this.transferOwnership = createProcedureMethod( - { getProcedureAndArgs: args => [transferAssetOwnership, { ticker, ...args }] }, + { getProcedureAndArgs: args => [transferAssetOwnership, { asset: this, ...args }] }, context ); @@ -163,12 +175,12 @@ export class BaseAsset extends Entity { ); this.setVenueFiltering = createProcedureMethod( - { getProcedureAndArgs: args => [setVenueFiltering, { ticker, ...args }] }, + { getProcedureAndArgs: args => [setVenueFiltering, { asset: this, ...args }] }, context ); this.modify = createProcedureMethod( - { getProcedureAndArgs: args => [modifyAsset, { ticker, ...args }] }, + { getProcedureAndArgs: args => [modifyAsset, { asset: this, ...args }] }, context ); } @@ -210,22 +222,28 @@ export class BaseAsset extends Entity { polymeshApi: { query: { asset }, }, + isV6, }, - ticker, context, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); + + let identifiersStorage = asset.assetIdentifiers; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + identifiersStorage = (asset as any).identifiers; + } if (callback) { context.assertSupportsSubscription(); - return asset.identifiers(rawTicker, identifiers => { + return identifiersStorage(rawAssetId, identifiers => { // eslint-disable-next-line @typescript-eslint/no-floating-promises -- callback errors should be handled by the caller callback(identifiers.map(assetIdentifierToSecurityIdentifier)); }); } - const assetIdentifiers = await asset.identifiers(rawTicker); + const assetIdentifiers = await identifiersStorage(rawAssetId); return assetIdentifiers.map(assetIdentifierToSecurityIdentifier); } @@ -241,7 +259,6 @@ export class BaseAsset extends Entity { // eslint-disable-next-line require-jsdoc public async isFrozen(callback?: SubCallback): Promise { const { - ticker, context: { polymeshApi: { query: { asset }, @@ -250,17 +267,17 @@ export class BaseAsset extends Entity { context, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); if (callback) { context.assertSupportsSubscription(); - return asset.frozen(rawTicker, frozen => { + return asset.frozen(rawAssetId, frozen => { // eslint-disable-next-line @typescript-eslint/no-floating-promises -- callback errors should be handled by the caller callback(boolToBoolean(frozen)); }); } - const result = await asset.frozen(rawTicker); + const result = await asset.frozen(rawAssetId); return boolToBoolean(result); } @@ -282,8 +299,8 @@ export class BaseAsset extends Entity { polymeshApi: { query: { asset, externalAgents }, }, + isV6, }, - ticker, context, } = this; @@ -335,17 +352,23 @@ export class BaseAsset extends Entity { }; }; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); - const groupOfAgentPromise = externalAgents.groupOfAgent.entries(rawTicker); - const namePromise = asset.assetNames(rawTicker); + const groupOfAgentPromise = externalAgents.groupOfAgent.entries(rawAssetId); + const namePromise = asset.assetNames(rawAssetId); + + let tokensStorage = asset.securityTokens; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + tokensStorage = (asset as any).tokens; + } if (callback) { context.assertSupportsSubscription(); const groupEntries = await groupOfAgentPromise; const assetName = await namePromise; - return asset.tokens(rawTicker, async securityToken => { + return tokensStorage(rawAssetId, async securityToken => { const result = await assembleResult(securityToken, groupEntries, assetName); // eslint-disable-next-line @typescript-eslint/no-floating-promises -- callback errors should be handled by the caller @@ -354,7 +377,7 @@ export class BaseAsset extends Entity { } const [token, groups, name] = await Promise.all([ - asset.tokens(rawTicker), + tokensStorage(rawAssetId), groupOfAgentPromise, namePromise, ]); @@ -367,15 +390,16 @@ export class BaseAsset extends Entity { public async getRequiredMediators(): Promise { const { context, - ticker, context: { - polymeshApi: { query }, + polymeshApi: { + query: { asset }, + }, }, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); - const rawMediators = await query.asset.mandatoryMediators(rawTicker); + const rawMediators = await asset.mandatoryMediators(rawAssetId); return identitiesSetToIdentities(rawMediators, context); } @@ -385,24 +409,24 @@ export class BaseAsset extends Entity { */ public async getVenueFilteringDetails(): Promise { const { - ticker, context, context: { polymeshApi: { query }, }, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); + const [rawIsEnabled, venueEntries] = await Promise.all([ - query.settlement.venueFiltering(rawTicker), - query.settlement.venueAllowList.entries(rawTicker), + query.settlement.venueFiltering(rawAssetId), + query.settlement.venueAllowList.entries(rawAssetId), ]); const allowedVenues = venueEntries.map(([key]) => { const rawId = key.args[1]; - const id = u64ToBigNumber(rawId); + const venueId = u64ToBigNumber(rawId); - return new Venue({ id }, context); + return new Venue({ id: venueId }, context); }); const isEnabled = boolToBoolean(rawIsEnabled); @@ -431,23 +455,22 @@ export class BaseAsset extends Entity { query: { asset }, }, }, - ticker, context, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); const assembleResult = (roundName: Bytes): string | null => bytesToString(roundName) || null; if (callback) { context.assertSupportsSubscription(); - return asset.fundingRound(rawTicker, round => { + return asset.fundingRound(rawAssetId, round => { // eslint-disable-next-line @typescript-eslint/no-floating-promises -- callback errors should be handled by the caller callback(assembleResult(round)); }); } - const fundingRound = await asset.fundingRound(rawTicker); + const fundingRound = await asset.fundingRound(rawAssetId); return assembleResult(fundingRound); } @@ -456,26 +479,37 @@ export class BaseAsset extends Entity { */ public async exists(): Promise { const { - ticker, context, context: { - polymeshApi: { query }, + polymeshApi: { + query: { asset, nft }, + }, + isV6, }, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); + let tokensStorage = asset.securityTokens; + let collectionsStorage = nft.collectionAsset; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + tokensStorage = (asset as any).tokens; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + collectionsStorage = (nft as any).collectionTicker; + } const [tokenSize, nftId] = await Promise.all([ - query.asset.tokens.size(rawTicker), - query.nft.collectionTicker(rawTicker), + tokensStorage.size(rawAssetId), + collectionsStorage(rawAssetId), ]); return !tokenSize.isZero() && nftId.isZero(); } + // TODO @prashantasdeveloper add comments /** - * Return the NftCollection's ticker + * Return the BaseAsset's ID */ public toHuman(): string { - return this.ticker; + return this.id; } } diff --git a/src/api/entities/Asset/Base/Compliance/Requirements.ts b/src/api/entities/Asset/Base/Compliance/Requirements.ts index 51f84704f9..a2772ea1db 100644 --- a/src/api/entities/Asset/Base/Compliance/Requirements.ts +++ b/src/api/entities/Asset/Base/Compliance/Requirements.ts @@ -26,9 +26,9 @@ import { UnsubCallback, } from '~/types'; import { + assetToMeshAssetId, boolToBoolean, complianceRequirementToRequirement, - stringToTicker, trustedIssuerToTrustedClaimIssuer, } from '~/utils/conversion'; import { createProcedureMethod, requestMulti } from '~/utils/internal'; @@ -43,43 +43,41 @@ export class Requirements extends Namespace { constructor(parent: BaseAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.add = createProcedureMethod( - { getProcedureAndArgs: args => [addAssetRequirement, { ticker, ...args }] }, + { getProcedureAndArgs: args => [addAssetRequirement, { asset: parent, ...args }] }, context ); this.remove = createProcedureMethod( - { getProcedureAndArgs: args => [removeAssetRequirement, { ticker, ...args }] }, + { getProcedureAndArgs: args => [removeAssetRequirement, { asset: parent, ...args }] }, context ); this.set = createProcedureMethod( - { getProcedureAndArgs: args => [setAssetRequirements, { ticker, ...args }] }, + { getProcedureAndArgs: args => [setAssetRequirements, { asset: parent, ...args }] }, context ); this.reset = createProcedureMethod( { - getProcedureAndArgs: () => [setAssetRequirements, { ticker, requirements: [] }], + getProcedureAndArgs: () => [setAssetRequirements, { asset: parent, requirements: [] }], voidArgs: true, }, context ); this.pause = createProcedureMethod( { - getProcedureAndArgs: () => [togglePauseRequirements, { ticker, pause: true }], + getProcedureAndArgs: () => [togglePauseRequirements, { asset: parent, pause: true }], voidArgs: true, }, context ); this.unpause = createProcedureMethod( { - getProcedureAndArgs: () => [togglePauseRequirements, { ticker, pause: false }], + getProcedureAndArgs: () => [togglePauseRequirements, { asset: parent, pause: false }], voidArgs: true, }, context ); this.modify = createProcedureMethod( - { getProcedureAndArgs: args => [modifyComplianceRequirement, { ticker, ...args }] }, + { getProcedureAndArgs: args => [modifyComplianceRequirement, { asset: parent, ...args }] }, context ); } @@ -115,7 +113,7 @@ export class Requirements extends Namespace { callback?: SubCallback ): Promise { const { - parent: { ticker }, + parent, context: { polymeshApi: { query: { complianceManager }, @@ -124,7 +122,7 @@ export class Requirements extends Namespace { context, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); const assembleResult = ([assetCompliance, claimIssuers]: [ PolymeshPrimitivesComplianceManagerAssetCompliance, @@ -149,8 +147,8 @@ export class Requirements extends Namespace { >( context, [ - [complianceManager.assetCompliances, rawTicker], - [complianceManager.trustedClaimIssuer, rawTicker], + [complianceManager.assetCompliances, rawAssetId], + [complianceManager.trustedClaimIssuer, rawAssetId], ], res => { // eslint-disable-next-line @typescript-eslint/no-floating-promises -- callback errors should be handled by the caller @@ -162,8 +160,8 @@ export class Requirements extends Namespace { const result = await requestMulti< [typeof complianceManager.assetCompliances, typeof complianceManager.trustedClaimIssuer] >(context, [ - [complianceManager.assetCompliances, rawTicker], - [complianceManager.trustedClaimIssuer, rawTicker], + [complianceManager.assetCompliances, rawAssetId], + [complianceManager.trustedClaimIssuer, rawAssetId], ]); return assembleResult(result); @@ -189,7 +187,7 @@ export class Requirements extends Namespace { */ public async arePaused(): Promise { const { - parent: { ticker }, + parent, context: { polymeshApi: { query: { complianceManager }, @@ -198,9 +196,9 @@ export class Requirements extends Namespace { context, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); - const { paused } = await complianceManager.assetCompliances(rawTicker); + const { paused } = await complianceManager.assetCompliances(rawAssetId); return boolToBoolean(paused); } diff --git a/src/api/entities/Asset/Base/Compliance/TrustedClaimIssuers.ts b/src/api/entities/Asset/Base/Compliance/TrustedClaimIssuers.ts index 9047addbcb..20a7d6ca76 100644 --- a/src/api/entities/Asset/Base/Compliance/TrustedClaimIssuers.ts +++ b/src/api/entities/Asset/Base/Compliance/TrustedClaimIssuers.ts @@ -17,7 +17,7 @@ import { UnsubCallback, } from '~/types'; import { TrustedClaimIssuerOperation } from '~/types/internal'; -import { stringToTicker, trustedIssuerToTrustedClaimIssuer } from '~/utils/conversion'; +import { assetToMeshAssetId, trustedIssuerToTrustedClaimIssuer } from '~/utils/conversion'; import { createProcedureMethod } from '~/utils/internal'; /** @@ -30,8 +30,6 @@ export class TrustedClaimIssuers extends Namespace { constructor(parent: BaseAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.set = createProcedureMethod< ModifyAssetTrustedClaimIssuersAddSetParams, ModifyAssetTrustedClaimIssuersParams, @@ -40,7 +38,7 @@ export class TrustedClaimIssuers extends Namespace { { getProcedureAndArgs: args => [ modifyAssetTrustedClaimIssuers, - { ticker, ...args, operation: TrustedClaimIssuerOperation.Set }, + { asset: parent, ...args, operation: TrustedClaimIssuerOperation.Set }, ], }, context @@ -53,7 +51,7 @@ export class TrustedClaimIssuers extends Namespace { { getProcedureAndArgs: args => [ modifyAssetTrustedClaimIssuers, - { ticker, ...args, operation: TrustedClaimIssuerOperation.Add }, + { asset: parent, ...args, operation: TrustedClaimIssuerOperation.Add }, ], }, context @@ -66,7 +64,7 @@ export class TrustedClaimIssuers extends Namespace { { getProcedureAndArgs: args => [ modifyAssetTrustedClaimIssuers, - { ticker, ...args, operation: TrustedClaimIssuerOperation.Remove }, + { asset: parent, ...args, operation: TrustedClaimIssuerOperation.Remove }, ], }, context @@ -109,10 +107,10 @@ export class TrustedClaimIssuers extends Namespace { }, }, context, - parent: { ticker }, + parent, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); const assembleResult = ( issuers: PolymeshPrimitivesConditionTrustedIssuer[] @@ -123,7 +121,7 @@ export class TrustedClaimIssuers extends Namespace { trustedFor, } = trustedIssuerToTrustedClaimIssuer(issuer, context); return { - identity: new DefaultTrustedClaimIssuer({ did, ticker }, context), + identity: new DefaultTrustedClaimIssuer({ did, assetId: parent.id }, context), trustedFor, }; }); @@ -131,13 +129,13 @@ export class TrustedClaimIssuers extends Namespace { if (callback) { context.assertSupportsSubscription(); - return complianceManager.trustedClaimIssuer(rawTicker, issuers => { + return complianceManager.trustedClaimIssuer(rawAssetId, issuers => { // eslint-disable-next-line @typescript-eslint/no-floating-promises -- callback errors should be handled by the caller callback(assembleResult(issuers)); }); } - const claimIssuers = await complianceManager.trustedClaimIssuer(rawTicker); + const claimIssuers = await complianceManager.trustedClaimIssuer(rawAssetId); return assembleResult(claimIssuers); } diff --git a/src/api/entities/Asset/Base/Documents/index.ts b/src/api/entities/Asset/Base/Documents/index.ts index cf6d5e1629..229100bb82 100644 --- a/src/api/entities/Asset/Base/Documents/index.ts +++ b/src/api/entities/Asset/Base/Documents/index.ts @@ -7,7 +7,7 @@ import { ResultSet, SetAssetDocumentsParams, } from '~/types'; -import { documentToAssetDocument, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, documentToAssetDocument } from '~/utils/conversion'; import { createProcedureMethod, requestPaginated } from '~/utils/internal'; /** @@ -20,10 +20,8 @@ export class Documents extends Namespace { constructor(parent: BaseAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.set = createProcedureMethod( - { getProcedureAndArgs: args => [setAssetDocuments, { ticker, ...args }] }, + { getProcedureAndArgs: args => [setAssetDocuments, { asset: parent, ...args }] }, context ); } @@ -44,11 +42,12 @@ export class Documents extends Namespace { polymeshApi: { query }, }, context, - parent: { ticker }, + parent, } = this; + const rawAssetId = assetToMeshAssetId(parent, context); const { entries, lastKey: next } = await requestPaginated(query.asset.assetDocuments, { - arg: stringToTicker(ticker, context), + arg: rawAssetId, paginationOpts, }); diff --git a/src/api/entities/Asset/Base/Metadata/index.ts b/src/api/entities/Asset/Base/Metadata/index.ts index 20f328a15a..f22062a23c 100644 --- a/src/api/entities/Asset/Base/Metadata/index.ts +++ b/src/api/entities/Asset/Base/Metadata/index.ts @@ -21,12 +21,12 @@ import { RegisterMetadataParams, } from '~/types'; import { + assetToMeshAssetId, bigNumberToU64, bytesToString, meshMetadataKeyToMetadataKey, meshMetadataSpecToMetadataSpec, meshMetadataValueToMetadataValue, - stringToTicker, u64ToBigNumber, } from '~/utils/conversion'; import { createProcedureMethod } from '~/utils/internal'; @@ -41,10 +41,8 @@ export class Metadata extends Namespace { constructor(parent: BaseAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.register = createProcedureMethod( - { getProcedureAndArgs: args => [registerMetadata, { ticker, ...args }] }, + { getProcedureAndArgs: args => [registerMetadata, { asset: parent, ...args }] }, context ); } @@ -72,18 +70,18 @@ export class Metadata extends Namespace { }, }, context, - parent: { ticker }, + parent, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); const [rawGlobalKeys, rawLocalKeys] = await Promise.all([ assetMetadataGlobalKeyToName.entries(), - assetMetadataLocalKeyToName.entries(rawTicker), + assetMetadataLocalKeyToName.entries(rawAssetId), ]); const assembleResult = (rawId: u64, type: MetadataType): MetadataEntry => - new MetadataEntry({ ticker, type, id: u64ToBigNumber(rawId) }, context); + new MetadataEntry({ assetId: parent.id, type, id: u64ToBigNumber(rawId) }, context); return [ ...rawGlobalKeys.map( @@ -118,7 +116,7 @@ export class Metadata extends Namespace { }, }, context, - parent: { ticker }, + parent, } = this; const { id, type } = args; @@ -130,8 +128,8 @@ export class Metadata extends Namespace { if (type === MetadataType.Global) { rawName = await assetMetadataGlobalKeyToName(rawId); } else { - const rawTicker = stringToTicker(ticker, context); - rawName = await assetMetadataLocalKeyToName(rawTicker, rawId); + const rawAssetId = assetToMeshAssetId(parent, context); + rawName = await assetMetadataLocalKeyToName(rawAssetId, rawId); } if (rawName.isEmpty) { @@ -141,7 +139,7 @@ export class Metadata extends Namespace { }); } - return new MetadataEntry({ ticker, type, id }, context); + return new MetadataEntry({ assetId: parent.id, type, id }, context); } /** @@ -151,7 +149,8 @@ export class Metadata extends Namespace { */ public async getNextLocalId(): Promise { const { - parent: { ticker }, + parent: asset, + context, context: { polymeshApi: { query: { @@ -161,7 +160,9 @@ export class Metadata extends Namespace { }, } = this; - const rawId = await currentAssetMetadataLocalKey(ticker); + const rawAssetId = assetToMeshAssetId(asset, context); + + const rawId = await currentAssetMetadataLocalKey(rawAssetId); if (rawId.isSome) { return u64ToBigNumber(rawId.unwrap()).plus(1); @@ -190,12 +191,12 @@ export class Metadata extends Namespace { }, }, context, - parent: { ticker }, + parent, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); - const [rawValueEntries] = await Promise.all([assetMetadataValues.entries(rawTicker)]); + const [rawValueEntries] = await Promise.all([assetMetadataValues.entries(rawAssetId)]); const namePromises: Promise>[] = []; const specPromises: Promise>[] = []; @@ -209,11 +210,11 @@ export class Metadata extends Namespace { args: [, rawMetadataKey], }, ]) => { - valueDetailsPromises.push(assetMetadataValueDetails(rawTicker, rawMetadataKey)); + valueDetailsPromises.push(assetMetadataValueDetails(rawAssetId, rawMetadataKey)); if (rawMetadataKey.isLocal) { - namePromises.push(assetMetadataLocalKeyToName(rawTicker, rawMetadataKey.asLocal)); - specPromises.push(assetMetadataLocalSpecs(rawTicker, rawMetadataKey.asLocal)); + namePromises.push(assetMetadataLocalKeyToName(rawAssetId, rawMetadataKey.asLocal)); + specPromises.push(assetMetadataLocalSpecs(rawAssetId, rawMetadataKey.asLocal)); } else { namePromises.push(assetMetadataGlobalKeyToName(rawMetadataKey.asGlobal)); specPromises.push(assetMetadataGlobalSpecs(rawMetadataKey.asGlobal)); @@ -236,8 +237,8 @@ export class Metadata extends Namespace { return { metadataEntry: new MetadataEntry( { - ...meshMetadataKeyToMetadataKey(rawMetadataKey, ticker), - ticker, + ...meshMetadataKeyToMetadataKey(rawMetadataKey, parent, context), + assetId: parent.id, }, context ), diff --git a/src/api/entities/Asset/Base/Permissions/index.ts b/src/api/entities/Asset/Base/Permissions/index.ts index 6fc2e25b0e..d6006e2c20 100644 --- a/src/api/entities/Asset/Base/Permissions/index.ts +++ b/src/api/entities/Asset/Base/Permissions/index.ts @@ -25,8 +25,8 @@ import { } from '~/types'; import { agentGroupToPermissionGroup, + assetToMeshAssetId, identityIdToString, - stringToTicker, u32ToBigNumber, } from '~/utils/conversion'; import { createProcedureMethod } from '~/utils/internal'; @@ -41,20 +41,18 @@ export class Permissions extends Namespace { constructor(parent: BaseAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.createGroup = createProcedureMethod( - { getProcedureAndArgs: args => [createGroup, { ticker, ...args }] }, + { getProcedureAndArgs: args => [createGroup, { asset: parent, ...args }] }, context ); this.inviteAgent = createProcedureMethod( - { getProcedureAndArgs: args => [inviteExternalAgent, { ticker, ...args }] }, + { getProcedureAndArgs: args => [inviteExternalAgent, { asset: parent, ...args }] }, context ); this.removeAgent = createProcedureMethod( - { getProcedureAndArgs: args => [removeExternalAgent, { ticker, ...args }] }, + { getProcedureAndArgs: args => [removeExternalAgent, { asset: parent, ...args }] }, context ); } @@ -91,16 +89,13 @@ export class Permissions extends Namespace { public async getGroup( args: { id: BigNumber } | { type: PermissionGroupType } ): Promise { - const { - parent: { ticker }, - context, - } = this; + const { parent, context } = this; if ('type' in args) { - return new KnownPermissionGroup({ ticker, type: args.type }, context); + return new KnownPermissionGroup({ assetId: parent.id, type: args.type }, context); } - const customGroup = new CustomPermissionGroup({ ticker, id: args.id }, context); + const customGroup = new CustomPermissionGroup({ assetId: parent.id, id: args.id }, context); const exists = await customGroup.exists(); @@ -125,20 +120,23 @@ export class Permissions extends Namespace { }, }, context, - parent: { ticker }, + parent, } = this; const known = Object.values(PermissionGroupType).map( - type => new KnownPermissionGroup({ type, ticker }, context) + type => new KnownPermissionGroup({ type, assetId: parent.id }, context) ); - const rawCustomPermissionGroups = await externalAgents.groupPermissions.entries( - stringToTicker(ticker, context) - ); + const rawAssetId = assetToMeshAssetId(parent, context); + + const rawCustomPermissionGroups = await externalAgents.groupPermissions.entries(rawAssetId); const custom: CustomPermissionGroup[] = rawCustomPermissionGroups.map( ([storageKey]) => - new CustomPermissionGroup({ ticker, id: u32ToBigNumber(storageKey.args[1]) }, context) + new CustomPermissionGroup( + { assetId: parent.id, id: u32ToBigNumber(storageKey.args[1]) }, + context + ) ); return { @@ -158,17 +156,19 @@ export class Permissions extends Namespace { query: { externalAgents }, }, }, - parent: { ticker }, + parent, context, } = this; - const groups = await externalAgents.groupOfAgent.entries(stringToTicker(ticker, context)); + const rawAssetId = assetToMeshAssetId(parent, context); + + const groups = await externalAgents.groupOfAgent.entries(rawAssetId); return groups.map(([storageKey, agentGroup]) => { const rawAgentGroup = agentGroup.unwrap(); return { agent: new Identity({ did: identityIdToString(storageKey.args[1]) }, context), - group: agentGroupToPermissionGroup(rawAgentGroup, ticker, context), + group: agentGroupToPermissionGroup(rawAgentGroup, parent.id, context), }; }); } diff --git a/src/api/entities/Asset/Base/Settlements/index.ts b/src/api/entities/Asset/Base/Settlements/index.ts index bbee4a773c..ef5d4faee8 100644 --- a/src/api/entities/Asset/Base/Settlements/index.ts +++ b/src/api/entities/Asset/Base/Settlements/index.ts @@ -14,13 +14,13 @@ import { } from '~/types'; import { isFungibleAsset } from '~/utils'; import { + assetToMeshAssetId, bigNumberToBalance, granularCanTransferResultToTransferBreakdown, nftToMeshNft, portfolioIdToMeshPortfolioId, portfolioIdToPortfolio, portfolioLikeToPortfolioId, - stringToTicker, } from '~/utils/conversion'; import { createProcedureMethod } from '~/utils/internal'; @@ -46,10 +46,7 @@ class BaseSettlements extends Namespace { this.preApprove = createProcedureMethod( { - getProcedureAndArgs: () => [ - toggleTickerPreApproval, - { ticker: parent.ticker, preApprove: true }, - ], + getProcedureAndArgs: () => [toggleTickerPreApproval, { asset: parent, preApprove: true }], voidArgs: true, }, context @@ -57,10 +54,7 @@ class BaseSettlements extends Namespace { this.removePreApproval = createProcedureMethod( { - getProcedureAndArgs: () => [ - toggleTickerPreApproval, - { ticker: parent.ticker, preApprove: false }, - ], + getProcedureAndArgs: () => [toggleTickerPreApproval, { asset: parent, preApprove: false }], voidArgs: true, }, context @@ -97,12 +91,11 @@ class BaseSettlements extends Namespace { } ): Promise { const { - parent: { ticker }, + parent, context: { polymeshApi: { call }, }, context, - parent, } = this; const { assetApi, nftApi } = call; @@ -134,6 +127,8 @@ class BaseSettlements extends Namespace { let granularResult: CanTransferGranularReturn; let nftResult; + const rawAssetId = assetToMeshAssetId(parent, context); + if ('amount' in args) { amount = args.amount; ({ isDivisible } = await parent.details()); @@ -142,18 +137,18 @@ class BaseSettlements extends Namespace { rawFromPortfolio, toCustodian.did, rawToPortfolio, - stringToTicker(ticker, context), + rawAssetId, bigNumberToBalance(amount, context, isDivisible) ); } else { - const rawNfts = nftToMeshNft(ticker, args.nfts, context); + const rawNfts = nftToMeshNft(parent, args.nfts, context); [granularResult, nftResult] = await Promise.all([ assetApi.canTransferGranular( fromCustodian.did, rawFromPortfolio, toCustodian.did, rawToPortfolio, - stringToTicker(ticker, context), + rawAssetId, bigNumberToBalance(amount, context, isDivisible) ), nftApi.validateNftTransfer(rawFromPortfolio, rawToPortfolio, rawNfts), diff --git a/src/api/entities/Asset/Fungible/AssetHolders/index.ts b/src/api/entities/Asset/Fungible/AssetHolders/index.ts index 153c26afef..d82de5baef 100644 --- a/src/api/entities/Asset/Fungible/AssetHolders/index.ts +++ b/src/api/entities/Asset/Fungible/AssetHolders/index.ts @@ -2,7 +2,7 @@ import BigNumber from 'bignumber.js'; import { FungibleAsset, Identity, Namespace } from '~/internal'; import { IdentityBalance, PaginationOptions, ResultSet } from '~/types'; -import { balanceToBigNumber, identityIdToString, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, balanceToBigNumber, identityIdToString } from '~/utils/conversion'; import { requestPaginated } from '~/utils/internal'; /** @@ -20,12 +20,12 @@ export class AssetHolders extends Namespace { polymeshApi: { query }, }, context, - parent: { ticker }, + parent, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); const { entries, lastKey: next } = await requestPaginated(query.asset.balanceOf, { - arg: rawTicker, + arg: rawAssetId, paginationOpts, }); diff --git a/src/api/entities/Asset/Fungible/Checkpoints/Schedules.ts b/src/api/entities/Asset/Fungible/Checkpoints/Schedules.ts index d78d4a3c06..8a79e8c8b4 100644 --- a/src/api/entities/Asset/Fungible/Checkpoints/Schedules.ts +++ b/src/api/entities/Asset/Fungible/Checkpoints/Schedules.ts @@ -16,7 +16,7 @@ import { RemoveCheckpointScheduleParams, ScheduleWithDetails, } from '~/types'; -import { momentToDate, stringToTicker, u64ToBigNumber } from '~/utils/conversion'; +import { assetToMeshAssetId, momentToDate, u64ToBigNumber } from '~/utils/conversion'; import { createProcedureMethod } from '~/utils/internal'; /** @@ -29,14 +29,12 @@ export class Schedules extends Namespace { constructor(parent: FungibleAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.create = createProcedureMethod( - { getProcedureAndArgs: args => [createCheckpointSchedule, { ticker, ...args }] }, + { getProcedureAndArgs: args => [createCheckpointSchedule, { asset: parent, ...args }] }, context ); this.remove = createProcedureMethod( - { getProcedureAndArgs: args => [removeCheckpointSchedule, { ticker, ...args }] }, + { getProcedureAndArgs: args => [removeCheckpointSchedule, { asset: parent, ...args }] }, context ); } @@ -82,7 +80,7 @@ export class Schedules extends Namespace { */ public async get(): Promise { const { - parent: { ticker }, + parent, context: { polymeshApi: { query: { checkpoint }, @@ -91,20 +89,20 @@ export class Schedules extends Namespace { context, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); - const rawSchedulesEntries = await checkpoint.scheduledCheckpoints.entries(rawTicker); + const rawSchedulesEntries = await checkpoint.scheduledCheckpoints.entries(rawAssetId); return rawSchedulesEntries.map(([key, rawScheduleOpt]) => { const rawSchedule = rawScheduleOpt.unwrap(); const rawId = key.args[1]; - const id = u64ToBigNumber(rawId); + const checkpointId = u64ToBigNumber(rawId); const points = [...rawSchedule.pending].map(rawPoint => momentToDate(rawPoint)); const schedule = new CheckpointSchedule( { - ticker, - id, + id: checkpointId, pendingPoints: points, + assetId: parent.id, }, context ); diff --git a/src/api/entities/Asset/Fungible/Checkpoints/index.ts b/src/api/entities/Asset/Fungible/Checkpoints/index.ts index 08963d498d..97346b551b 100644 --- a/src/api/entities/Asset/Fungible/Checkpoints/index.ts +++ b/src/api/entities/Asset/Fungible/Checkpoints/index.ts @@ -19,9 +19,9 @@ import { } from '~/types'; import { tuple } from '~/types/utils'; import { + assetToMeshAssetId, balanceToBigNumber, momentToDate, - stringToTicker, u64ToBigNumber, } from '~/utils/conversion'; import { createProcedureMethod, requestPaginated } from '~/utils/internal'; @@ -40,10 +40,8 @@ export class Checkpoints extends Namespace { constructor(parent: FungibleAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.create = createProcedureMethod( - { getProcedureAndArgs: () => [createCheckpoint, { ticker }], voidArgs: true }, + { getProcedureAndArgs: () => [createCheckpoint, { asset: parent }], voidArgs: true }, context ); @@ -62,11 +60,11 @@ export class Checkpoints extends Namespace { */ public async getOne(args: { id: BigNumber }): Promise { const { - parent: { ticker }, + parent: { id: assetId }, context, } = this; - const checkpoint = new Checkpoint({ id: args.id, ticker }, context); + const checkpoint = new Checkpoint({ id: args.id, assetId }, context); const exists = await checkpoint.exists(); @@ -87,7 +85,8 @@ export class Checkpoints extends Namespace { */ public async get(paginationOpts?: PaginationOptions): Promise> { const { - parent: { ticker }, + parent, + parent: { id: assetId }, context, context: { polymeshApi: { @@ -96,10 +95,10 @@ export class Checkpoints extends Namespace { }, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); const { entries, lastKey: next } = await requestPaginated(checkpointQuery.totalSupply, { - arg: rawTicker, + arg: rawAssetId, paginationOpts, }); @@ -113,9 +112,9 @@ export class Checkpoints extends Namespace { }, balance, ]) => { - checkpointsMultiParams.push(tuple(rawTicker, id)); + checkpointsMultiParams.push(tuple(rawAssetId, id)); checkpoints.push({ - checkpoint: new Checkpoint({ id: u64ToBigNumber(id), ticker }, context), + checkpoint: new Checkpoint({ id: u64ToBigNumber(id), assetId }, context), totalSupply: balanceToBigNumber(balance), }); } diff --git a/src/api/entities/Asset/Fungible/CorporateActions/Distributions.ts b/src/api/entities/Asset/Fungible/CorporateActions/Distributions.ts index df3645a899..cd6f3f4a10 100644 --- a/src/api/entities/Asset/Fungible/CorporateActions/Distributions.ts +++ b/src/api/entities/Asset/Fungible/CorporateActions/Distributions.ts @@ -15,13 +15,13 @@ import { ProcedureMethod, } from '~/types'; import { + assetToMeshAssetId, balanceToBigNumber, bigNumberToU32, boolToBoolean, corporateActionIdentifierToCaId, distributionToDividendDistributionParams, meshCorporateActionToCorporateActionParams, - stringToTicker, } from '~/utils/conversion'; import { createProcedureMethod } from '~/utils/internal'; @@ -46,10 +46,8 @@ export class Distributions extends Namespace { constructor(parent: FungibleAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.configureDividendDistribution = createProcedureMethod( - { getProcedureAndArgs: args => [configureDividendDistribution, { ticker, ...args }] }, + { getProcedureAndArgs: args => [configureDividendDistribution, { asset: parent, ...args }] }, context ); } @@ -61,7 +59,7 @@ export class Distributions extends Namespace { */ public async getOne(args: { id: BigNumber }): Promise { const { - parent: { ticker }, + parent, context: { polymeshApi: { query }, }, @@ -69,11 +67,12 @@ export class Distributions extends Namespace { } = this; const { id } = args; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); + const rawLocalId = bigNumberToU32(id, context); - const rawCaId = corporateActionIdentifierToCaId({ ticker, localId: id }, context); + const rawCaId = corporateActionIdentifierToCaId({ asset: parent, localId: id }, context); const [corporateAction, capitalDistribution, details] = await Promise.all([ - query.corporateAction.corporateActions(rawTicker, rawLocalId), + query.corporateAction.corporateActions(rawAssetId, rawLocalId), query.capitalDistribution.distributions(rawCaId), query.corporateAction.details(rawCaId), ]); @@ -90,7 +89,7 @@ export class Distributions extends Namespace { const distribution = new DividendDistribution( { id, - ticker, + assetId: parent.id, ...meshCorporateActionToCorporateActionParams(corporateAction.unwrap(), details, context), ...distributionToDividendDistributionParams(dist, context), }, diff --git a/src/api/entities/Asset/Fungible/CorporateActions/index.ts b/src/api/entities/Asset/Fungible/CorporateActions/index.ts index bb0701ead8..6443f8217f 100644 --- a/src/api/entities/Asset/Fungible/CorporateActions/index.ts +++ b/src/api/entities/Asset/Fungible/CorporateActions/index.ts @@ -8,9 +8,9 @@ import { } from '~/internal'; import { ModifyCaDefaultConfigParams, ProcedureMethod, RemoveCorporateActionParams } from '~/types'; import { + assetToMeshAssetId, identityIdToString, permillToBigNumber, - stringToTicker, targetIdentitiesToCorporateActionTargets, } from '~/utils/conversion'; import { createProcedureMethod, requestMulti } from '~/utils/internal'; @@ -30,17 +30,15 @@ export class CorporateActions extends Namespace { constructor(parent: FungibleAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.distributions = new Distributions(parent, context); this.setDefaultConfig = createProcedureMethod( - { getProcedureAndArgs: args => [modifyCaDefaultConfig, { ticker, ...args }] }, + { getProcedureAndArgs: args => [modifyCaDefaultConfig, { asset: parent, ...args }] }, context ); this.remove = createProcedureMethod( - { getProcedureAndArgs: args => [removeCorporateAction, { ticker, ...args }] }, + { getProcedureAndArgs: args => [removeCorporateAction, { asset: parent, ...args }] }, context ); } @@ -69,11 +67,12 @@ export class CorporateActions extends Namespace { query: { externalAgents }, }, }, - parent: { ticker }, + parent, context, } = this; - const groupOfAgent = await externalAgents.groupOfAgent.entries(stringToTicker(ticker, context)); + const rawAssetId = assetToMeshAssetId(parent, context); + const groupOfAgent = await externalAgents.groupOfAgent.entries(rawAssetId); const agentIdentities: Identity[] = []; @@ -99,7 +98,7 @@ export class CorporateActions extends Namespace { */ public async getDefaultConfig(): Promise { const { - parent: { ticker }, + parent, context: { polymeshApi: { query: { corporateAction }, @@ -108,7 +107,7 @@ export class CorporateActions extends Namespace { context, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); const [targets, defaultTaxWithholding, taxWithholdings] = await requestMulti< [ @@ -117,9 +116,9 @@ export class CorporateActions extends Namespace { typeof corporateAction.didWithholdingTax ] >(context, [ - [corporateAction.defaultTargetIdentities, rawTicker], - [corporateAction.defaultWithholdingTax, rawTicker], - [corporateAction.didWithholdingTax, rawTicker], + [corporateAction.defaultTargetIdentities, rawAssetId], + [corporateAction.defaultWithholdingTax, rawAssetId], + [corporateAction.didWithholdingTax, rawAssetId], ]); return { diff --git a/src/api/entities/Asset/Fungible/Issuance/index.ts b/src/api/entities/Asset/Fungible/Issuance/index.ts index 3da91c4b12..9ccacd62d4 100644 --- a/src/api/entities/Asset/Fungible/Issuance/index.ts +++ b/src/api/entities/Asset/Fungible/Issuance/index.ts @@ -12,10 +12,8 @@ export class Issuance extends Namespace { constructor(parent: FungibleAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.issue = createProcedureMethod( - { getProcedureAndArgs: args => [issueTokens, { ticker, ...args }] }, + { getProcedureAndArgs: args => [issueTokens, { asset: parent, ...args }] }, context ); } diff --git a/src/api/entities/Asset/Fungible/Offerings/index.ts b/src/api/entities/Asset/Fungible/Offerings/index.ts index b41219b8be..4f6196b18a 100644 --- a/src/api/entities/Asset/Fungible/Offerings/index.ts +++ b/src/api/entities/Asset/Fungible/Offerings/index.ts @@ -16,7 +16,11 @@ import { OfferingWithDetails, ProcedureMethod, } from '~/types'; -import { fundraiserToOfferingDetails, stringToTicker, u64ToBigNumber } from '~/utils/conversion'; +import { + assetToMeshAssetId, + fundraiserToOfferingDetails, + u64ToBigNumber, +} from '~/utils/conversion'; import { createProcedureMethod } from '~/utils/internal'; /** @@ -29,10 +33,8 @@ export class Offerings extends Namespace { constructor(parent: FungibleAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.launch = createProcedureMethod( - { getProcedureAndArgs: args => [launchOffering, { ticker, ...args }] }, + { getProcedureAndArgs: args => [launchOffering, { asset: parent, ...args }] }, context ); } @@ -52,12 +54,9 @@ export class Offerings extends Namespace { * @throws if there is no Offering with the passed ID */ public async getOne(args: { id: BigNumber }): Promise { - const { - parent: { ticker }, - context, - } = this; + const { parent, context } = this; const { id } = args; - const offering = new Offering({ ticker, id }, context); + const offering = new Offering({ assetId: parent.id, id }, context); const exists = await offering.exists(); @@ -80,7 +79,7 @@ export class Offerings extends Namespace { opts: { status?: Partial } = {} ): Promise { const { - parent: { ticker }, + parent, context: { polymeshApi: { query: { sto }, @@ -92,11 +91,11 @@ export class Offerings extends Namespace { const { status: { timing: timingFilter, balance: balanceFilter, sale: saleFilter } = {} } = opts; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(parent, context); const [fundraiserEntries, nameEntries] = await Promise.all([ - sto.fundraisers.entries(rawTicker), - sto.fundraiserNames.entries(rawTicker), + sto.fundraisers.entries(rawAssetId), + sto.fundraiserNames.entries(rawAssetId), ]); const offerings = fundraiserEntries.map( @@ -116,7 +115,7 @@ export class Offerings extends Namespace { ]) => u64ToBigNumber(rawId).eq(id) ); return { - offering: new Offering({ id, ticker }, context), + offering: new Offering({ id, assetId: parent.id }, context), details: fundraiserToOfferingDetails(fundraiser.unwrap(), name.unwrap(), context), }; } diff --git a/src/api/entities/Asset/Fungible/TransferRestrictions/TransferRestrictionBase.ts b/src/api/entities/Asset/Fungible/TransferRestrictions/TransferRestrictionBase.ts index f24cadbd0c..b914d59c82 100644 --- a/src/api/entities/Asset/Fungible/TransferRestrictions/TransferRestrictionBase.ts +++ b/src/api/entities/Asset/Fungible/TransferRestrictions/TransferRestrictionBase.ts @@ -40,14 +40,13 @@ import { identityIdToString, meshClaimTypeToClaimType, meshStatToStatType, - stringToTickerKey, transferConditionToTransferRestriction, transferRestrictionTypeToStatOpType, u32ToBigNumber, } from '~/utils/conversion'; -import { createProcedureMethod } from '~/utils/internal'; +import { createProcedureMethod, getAssetIdForStats } from '~/utils/internal'; -export type SetTransferRestrictionsParams = { ticker: string } & ( +export type SetTransferRestrictionsParams = { asset: FungibleAsset } & ( | SetCountTransferRestrictionsParams | SetPercentageTransferRestrictionsParams | SetClaimCountTransferRestrictionsParams @@ -86,8 +85,6 @@ export abstract class TransferRestrictionBase< constructor(parent: FungibleAsset, context: Context) { super(parent, context); - const { ticker } = parent; - this.addRestriction = createProcedureMethod< AddRestrictionParams, AddTransferRestrictionParams, @@ -96,7 +93,7 @@ export abstract class TransferRestrictionBase< { getProcedureAndArgs: args => [ addTransferRestriction, - { ...args, type: this.type, ticker } as unknown as AddTransferRestrictionParams, + { ...args, type: this.type, asset: parent } as unknown as AddTransferRestrictionParams, ], }, context @@ -111,7 +108,7 @@ export abstract class TransferRestrictionBase< { getProcedureAndArgs: args => [ setTransferRestrictions, - { ...args, type: this.type, ticker } as SetTransferRestrictionsParams, + { ...args, type: this.type, asset: parent } as SetTransferRestrictionsParams, ], }, context @@ -128,7 +125,7 @@ export abstract class TransferRestrictionBase< { restrictions: [], type: this.type, - ticker, + asset: parent, } as SetTransferRestrictionsParams, ], voidArgs: true, @@ -143,7 +140,7 @@ export abstract class TransferRestrictionBase< { ...args, type: restrictionTypeToStatType[this.type], - ticker, + asset: parent, } as AddAssetStatParams, ], }, @@ -161,7 +158,7 @@ export abstract class TransferRestrictionBase< { ...args, type: restrictionTypeToStatType[this.type], - ticker, + asset: parent, } as RemoveAssetStatParams, ], }, @@ -211,18 +208,21 @@ export abstract class TransferRestrictionBase< */ public async get(): Promise> { const { - parent: { ticker }, + parent, context: { polymeshApi: { query: { statistics }, consts, }, + isV6, }, context, type, } = this; - const tickerKey = stringToTickerKey(ticker, context); - const { requirements } = await statistics.assetTransferCompliances(tickerKey); + + const rawAssetId = getAssetIdForStats(parent, context); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const { requirements } = await (statistics.assetTransferCompliances as any)(rawAssetId); const existingRequirementCount = [...requirements].length; @@ -237,6 +237,8 @@ export abstract class TransferRestrictionBase< return requirement.isClaimOwnership; } }); + + const rawAssetKey = isV6 ? { asset: rawAssetId } : { assetId: rawAssetId }; const rawExemptedLists = await Promise.all( filteredRequirements.map(req => { const { value } = transferConditionToTransferRestriction(req, context); @@ -244,14 +246,14 @@ export abstract class TransferRestrictionBase< if (req.isClaimCount) { const { claim } = value as ClaimCountRestrictionValue; return statistics.transferConditionExemptEntities.entries({ - asset: tickerKey, + ...rawAssetKey, op: transferRestrictionTypeToStatOpType(TransferRestrictionType.ClaimCount, context), claimType: claim.type, }); } else if (req.isClaimOwnership) { const { claim } = value as ClaimPercentageRestrictionValue; return statistics.transferConditionExemptEntities.entries({ - asset: tickerKey, + ...rawAssetKey, op: transferRestrictionTypeToStatOpType( TransferRestrictionType.ClaimPercentage, context @@ -260,14 +262,15 @@ export abstract class TransferRestrictionBase< }); } else { return statistics.transferConditionExemptEntities.entries({ - asset: tickerKey, + ...rawAssetKey, op: transferRestrictionTypeToStatOpType(type, context), }); } }) ); - const restrictions = rawExemptedLists.map((list, index) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const restrictions = (rawExemptedLists as any[][]).map((list, index) => { const exemptedIds = list.map( ([ { @@ -325,7 +328,7 @@ export abstract class TransferRestrictionBase< */ public async getStat(): Promise { const { - parent: { ticker }, + parent, context, context: { polymeshApi: { @@ -334,8 +337,10 @@ export abstract class TransferRestrictionBase< }, type, } = this; - const tickerKey = stringToTickerKey(ticker, context); - const currentStats = await statistics.activeAssetStats(tickerKey); + + const rawAssetId = getAssetIdForStats(parent, context); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const currentStats = await (statistics.activeAssetStats as any)(rawAssetId); let isSet = false; const claims: ActiveStats['claims'] = []; @@ -349,7 +354,7 @@ export abstract class TransferRestrictionBase< }; [...currentStats].forEach(stat => { - const statType = meshStatToStatType(stat); + const statType = meshStatToStatType(stat, context); if (type === TransferRestrictionType.ClaimCount && statType === StatType.ScopedCount) { isSet = true; diff --git a/src/api/entities/Asset/Fungible/index.ts b/src/api/entities/Asset/Fungible/index.ts index c057f5cf52..f4d43b291a 100644 --- a/src/api/entities/Asset/Fungible/index.ts +++ b/src/api/entities/Asset/Fungible/index.ts @@ -17,12 +17,11 @@ import { } from '~/types'; import { Ensured } from '~/types/utils'; import { + assetToMeshAssetId, balanceToBigNumber, middlewareEventDetailsToEventIdentifier, middlewarePortfolioToPortfolio, portfolioIdStringToPortfolio, - stringToTicker, - tickerToDid, } from '~/utils/conversion'; import { calculateNextKey, @@ -59,11 +58,6 @@ export class FungibleAsset extends BaseAsset { constructor(identifiers: UniqueIdentifiers, context: Context) { super(identifiers, context); - const { ticker } = identifiers; - - this.ticker = ticker; - this.did = tickerToDid(ticker); - this.settlements = new FungibleSettlements(this, context); this.assetHolders = new AssetHolders(this, context); this.issuance = new Issuance(this, context); @@ -73,11 +67,11 @@ export class FungibleAsset extends BaseAsset { this.corporateActions = new CorporateActions(this, context); this.redeem = createProcedureMethod( - { getProcedureAndArgs: args => [redeemTokens, { ticker, ...args }] }, + { getProcedureAndArgs: args => [redeemTokens, { asset: this, ...args }] }, context ); this.controllerTransfer = createProcedureMethod( - { getProcedureAndArgs: args => [controllerTransfer, { ticker, ...args }] }, + { getProcedureAndArgs: args => [controllerTransfer, { asset: this, ...args }] }, context ); } @@ -124,12 +118,11 @@ export class FungibleAsset extends BaseAsset { }, }, context, - ticker, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); - const balanceEntries = await balanceOf.entries(rawTicker); + const balanceEntries = await balanceOf.entries(rawAssetId); const assetBalances = balanceEntries.filter( ([, balance]) => !balanceToBigNumber(balance).isZero() @@ -224,7 +217,7 @@ export class FungibleAsset extends BaseAsset { const assetId = getAssetIdFromMiddleware(asset); return { - asset: new FungibleAsset({ ticker: assetId }, context), + asset: new FungibleAsset({ assetId }, context), amount: new BigNumber(amount).shiftedBy(-6), event: eventId, from: optionize(middlewarePortfolioToPortfolio)(fromPortfolio, context), @@ -255,17 +248,28 @@ export class FungibleAsset extends BaseAsset { */ public override async exists(): Promise { const { - ticker, context, context: { - polymeshApi: { query }, + polymeshApi: { + query: { asset, nft }, + }, + isV6, }, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); + + let tokensStorage = asset.securityTokens; + let collectionsStorage = nft.collectionAsset; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + tokensStorage = (asset as any).tokens; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + collectionsStorage = (nft as any).collectionTicker; + } const [tokenSize, nftId] = await Promise.all([ - query.asset.tokens.size(rawTicker), - query.nft.collectionTicker(rawTicker), + tokensStorage.size(rawAssetId), + collectionsStorage(rawAssetId), ]); return !tokenSize.isZero() && nftId.isZero(); diff --git a/src/api/entities/Asset/NonFungible/AssetHolders/index.ts b/src/api/entities/Asset/NonFungible/AssetHolders/index.ts index 6f547e6649..61e5815de7 100644 --- a/src/api/entities/Asset/NonFungible/AssetHolders/index.ts +++ b/src/api/entities/Asset/NonFungible/AssetHolders/index.ts @@ -5,7 +5,7 @@ import { nftCollectionHolders } from '~/middleware/queries/assets'; import { Query } from '~/middleware/types'; import { IdentityHeldNfts, NftCollection, ResultSet } from '~/types'; import { Ensured } from '~/types/utils'; -import { calculateNextKey, getAssetIdForMiddleware } from '~/utils/internal'; +import { calculateNextKey } from '~/utils/internal'; /** * Handles all NFT Holders related functionality @@ -22,24 +22,22 @@ export class AssetHolders extends Namespace { }): Promise> { const { context, - parent: { ticker }, + parent: { id: assetId }, } = this; const { size, start } = opts; - const middlewareAssetId = await getAssetIdForMiddleware(ticker, context); - const { data: { nftHolders: { totalCount, nodes }, }, } = await context.queryMiddleware>( - nftCollectionHolders(middlewareAssetId, size, start) + nftCollectionHolders(assetId, size, start) ); const data = nodes.map(({ nftIds, identityId }) => ({ identity: new Identity({ did: identityId }, context), - nfts: nftIds.map((id: string) => new Nft({ id: new BigNumber(id), ticker }, context)), + nfts: nftIds.map((id: string) => new Nft({ id: new BigNumber(id), assetId }, context)), })); const next = calculateNextKey(new BigNumber(totalCount), nodes.length, start); diff --git a/src/api/entities/Asset/NonFungible/Nft.ts b/src/api/entities/Asset/NonFungible/Nft.ts index f1697dc0b7..76e12f83bc 100644 --- a/src/api/entities/Asset/NonFungible/Nft.ts +++ b/src/api/entities/Asset/NonFungible/Nft.ts @@ -16,19 +16,19 @@ import { GLOBAL_TOKEN_URI_NAME, } from '~/utils/constants'; import { + assetToMeshAssetId, bigNumberToU64, boolToBoolean, bytesToString, meshMetadataKeyToMetadataKey, meshPortfolioIdToPortfolio, portfolioToPortfolioId, - stringToTicker, u64ToBigNumber, } from '~/utils/conversion'; import { createProcedureMethod } from '~/utils/internal'; export type NftUniqueIdentifiers = { - ticker: string; + assetId: string; id: BigNumber; }; @@ -60,9 +60,9 @@ export class Nft extends Entity { public static override isUniqueIdentifiers( identifier: unknown ): identifier is NftUniqueIdentifiers { - const { ticker, id } = identifier as NftUniqueIdentifiers; + const { assetId, id } = identifier as NftUniqueIdentifiers; - return typeof ticker === 'string' && id instanceof BigNumber; + return typeof assetId === 'string' && id instanceof BigNumber; } /** @@ -71,14 +71,17 @@ export class Nft extends Entity { constructor(identifiers: NftUniqueIdentifiers, context: Context) { super(identifiers, context); - const { ticker, id } = identifiers; + const { id, assetId } = identifiers; this.id = id; - this.collection = new NftCollection({ ticker }, context); + this.collection = new NftCollection({ assetId }, context); this.redeem = createProcedureMethod( - { getProcedureAndArgs: args => [redeemNft, { ticker, id, ...args }], optionalArgs: true }, + { + getProcedureAndArgs: args => [redeemNft, { collection: this.collection, id, ...args }], + optionalArgs: true, + }, context ); } @@ -105,7 +108,7 @@ export class Nft extends Entity { return entries.map(([storageKey, rawValue]) => { const rawMetadataKey = storageKey.args[1]; - const key = meshMetadataKeyToMetadataKey(rawMetadataKey, collection.ticker); + const key = meshMetadataKeyToMetadataKey(rawMetadataKey, collection, context); const value = bytesToString(rawValue); return { key, value }; @@ -200,7 +203,7 @@ export class Nft extends Entity { */ public async getOwner(): Promise { const { - collection: { ticker }, + collection, id, context: { polymeshApi: { @@ -212,10 +215,11 @@ export class Nft extends Entity { context, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(collection, context); + const rawNftId = bigNumberToU64(id, context); - const owner = await nftOwner(rawTicker, rawNftId); + const owner = await nftOwner(rawAssetId, rawNftId); if (owner.isEmpty) { return null; @@ -231,7 +235,7 @@ export class Nft extends Entity { */ public async isLocked(): Promise { const { - collection: { ticker }, + collection, id, context: { polymeshApi: { @@ -250,8 +254,10 @@ export class Nft extends Entity { }); } + const rawAssetId = assetToMeshAssetId(collection, context); + const rawLocked = await portfolio.portfolioLockedNFT(portfolioToPortfolioId(owner), [ - stringToTicker(ticker, context), + rawAssetId, bigNumberToU64(id, context), ]); @@ -263,12 +269,12 @@ export class Nft extends Entity { */ public toHuman(): HumanReadable { const { - collection: { ticker }, + collection: { id: assetId }, id, } = this; return { - collection: ticker, + collection: assetId, id: id.toString(), }; } @@ -317,7 +323,7 @@ export class Nft extends Entity { */ private async getBaseUri(metadataId: BigNumber | null): Promise { const { - collection: { ticker }, + collection, context, context: { polymeshApi: { query }, @@ -329,8 +335,9 @@ export class Nft extends Entity { } const rawId = bigNumberToU64(metadataId, context); - const rawTicker = stringToTicker(ticker, context); - const rawValue = await query.asset.assetMetadataValues(rawTicker, { Global: rawId }); + const rawAssetId = assetToMeshAssetId(collection, context); + + const rawValue = await query.asset.assetMetadataValues(rawAssetId, { Global: rawId }); if (rawValue.isNone) { return null; diff --git a/src/api/entities/Asset/NonFungible/NftCollection.ts b/src/api/entities/Asset/NonFungible/NftCollection.ts index e779140750..5a9a8471a4 100644 --- a/src/api/entities/Asset/NonFungible/NftCollection.ts +++ b/src/api/entities/Asset/NonFungible/NftCollection.ts @@ -5,14 +5,7 @@ import BigNumber from 'bignumber.js'; import { BaseAsset } from '~/api/entities/Asset/Base'; import { NonFungibleSettlements } from '~/api/entities/Asset/Base/Settlements'; import { AssetHolders } from '~/api/entities/Asset/NonFungible/AssetHolders'; -import { - Context, - issueNft, - Nft, - nftControllerTransfer, - PolymeshError, - transferAssetOwnership, -} from '~/internal'; +import { Context, issueNft, Nft, nftControllerTransfer, PolymeshError } from '~/internal'; import { assetQuery, assetTransactionQuery } from '~/middleware/queries/assets'; import { Query } from '~/middleware/types'; import { @@ -32,17 +25,18 @@ import { } from '~/types'; import { Ensured } from '~/types/utils'; import { + assetToMeshAssetId, bigNumberToU64, meshMetadataKeyToMetadataKey, middlewareEventDetailsToEventIdentifier, middlewarePortfolioToPortfolio, portfolioIdStringToPortfolio, - stringToTicker, u64ToBigNumber, } from '~/utils/conversion'; import { calculateNextKey, createProcedureMethod, + getAssetIdAndTicker, getAssetIdFromMiddleware, optionize, } from '~/utils/internal'; @@ -90,25 +84,19 @@ export class NftCollection extends BaseAsset { constructor(identifiers: UniqueIdentifiers, context: Context) { super(identifiers, context); - const { ticker } = identifiers; this.assetHolders = new AssetHolders(this, context); this.settlements = new NonFungibleSettlements(this, context); - this.transferOwnership = createProcedureMethod( - { getProcedureAndArgs: args => [transferAssetOwnership, { ticker, ...args }] }, - context - ); - this.issue = createProcedureMethod( { - getProcedureAndArgs: args => [issueNft, { ticker, ...args }], + getProcedureAndArgs: args => [issueNft, { collection: this, ...args }], }, context ); this.controllerTransfer = createProcedureMethod( { - getProcedureAndArgs: args => [nftControllerTransfer, { ticker, ...args }], + getProcedureAndArgs: args => [nftControllerTransfer, { collection: this, ...args }], }, context ); @@ -130,13 +118,12 @@ export class NftCollection extends BaseAsset { context: { polymeshApi: { query }, }, - ticker, context, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); - const rawNumberNftsPromise = query.nft.numberOfNFTs.entries(rawTicker); + const rawNumberNftsPromise = query.nft.numberOfNFTs.entries(rawAssetId); if (callback) { context.assertSupportsSubscription(); @@ -173,7 +160,7 @@ export class NftCollection extends BaseAsset { public async collectionKeys(): Promise { const { context, - ticker, + id: assetId, context: { polymeshApi: { query }, }, @@ -183,7 +170,9 @@ export class NftCollection extends BaseAsset { const rawCollectionId = bigNumberToU64(collectionId, context); const rawKeys = await query.nft.collectionKeys(rawCollectionId); - const neededKeys = [...rawKeys].map(value => meshMetadataKeyToMetadataKey(value, ticker)); + const neededKeys = [...rawKeys].map(value => + meshMetadataKeyToMetadataKey(value, this, context) + ); const allMetadata = await this.metadata.get(); return Promise.all( @@ -200,7 +189,7 @@ export class NftCollection extends BaseAsset { const details = await neededMetadata.details(); if (type === MetadataType.Local) { - return { ...details, id, type, ticker }; + return { ...details, id, type, ...(await getAssetIdAndTicker(assetId, context)) }; } else { return { ...details, id, type }; } @@ -217,12 +206,11 @@ export class NftCollection extends BaseAsset { polymeshApi: { query }, }, context, - ticker, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(this, context); - const holderEntries = await query.nft.numberOfNFTs.entries(rawTicker); + const holderEntries = await query.nft.numberOfNFTs.entries(rawAssetId); const assetBalances = holderEntries.filter(([, balance]) => !balance.isZero()); @@ -235,10 +223,10 @@ export class NftCollection extends BaseAsset { * @throws if the given NFT does not exist */ public async getNft(args: { id: BigNumber }): Promise { - const { context, ticker } = this; + const { context, id: assetId } = this; const { id } = args; - const nft = new Nft({ ticker, id }, context); + const nft = new Nft({ assetId, id }, context); const exists = await nft.exists(); if (!exists) { @@ -280,11 +268,24 @@ export class NftCollection extends BaseAsset { * Determine whether this NftCollection exists on chain */ public override async exists(): Promise { - const { ticker, context } = this; + const { + context, + context: { + polymeshApi: { + query: { nft }, + }, + isV6, + }, + } = this; - const rawTokenId = await context.polymeshApi.query.nft.collectionTicker( - stringToTicker(ticker, context) - ); + let collectionStorage = nft.collectionAsset; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + collectionStorage = (nft as any).collectionTicker; + } + + const rawAssetId = assetToMeshAssetId(this, context); + const rawTokenId = await collectionStorage(rawAssetId); return !rawTokenId.isZero(); } @@ -294,10 +295,12 @@ export class NftCollection extends BaseAsset { */ public async getCollectionId(): Promise { const { - ticker, context, context: { - polymeshApi: { query }, + polymeshApi: { + query: { nft }, + }, + isV6, }, } = this; @@ -305,8 +308,14 @@ export class NftCollection extends BaseAsset { return this._id; } - const rawTicker = stringToTicker(ticker, context); - const rawId = await query.nft.collectionTicker(rawTicker); + let collectionStorage = nft.collectionAsset; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + collectionStorage = (nft as any).collectionTicker; + } + + const rawAssetId = assetToMeshAssetId(this, context); + const rawId = await collectionStorage(rawAssetId); this._id = u64ToBigNumber(rawId); @@ -357,12 +366,13 @@ export class NftCollection extends BaseAsset { const toPortfolio = optionize(portfolioIdStringToPortfolio)(toPortfolioId); const assetId = getAssetIdFromMiddleware(asset); - const collection = new NftCollection({ ticker: assetId }, context); + const collection = new NftCollection({ assetId }, context); return { asset: collection, nfts: nftIds.map( - (id: string) => new Nft({ ticker: assetId, id: new BigNumber(id) }, context) + // TODO @prashantasdeveloper + (id: string) => new Nft({ assetId, id: new BigNumber(id) }, context) ), event: eventId, to: optionize(middlewarePortfolioToPortfolio)(toPortfolio, context), diff --git a/src/api/entities/Asset/types.ts b/src/api/entities/Asset/types.ts index ba8390f349..80aede0922 100644 --- a/src/api/entities/Asset/types.ts +++ b/src/api/entities/Asset/types.ts @@ -83,9 +83,9 @@ export interface AssetDocument { */ export interface UniqueIdentifiers { /** - * ticker of the Asset + * id of the Asset */ - ticker: string; + assetId: string; } export interface AssetDetails { @@ -209,7 +209,15 @@ export type MetadataKeyId = | { type: MetadataType.Local; id: BigNumber; + /** + * @deprecated in favour of `assetId` + */ ticker: string; + } + | { + type: MetadataType.Local; + id: BigNumber; + assetId: string; }; export interface NftMetadata { diff --git a/src/api/entities/Checkpoint.ts b/src/api/entities/Checkpoint.ts index e39750c31d..ea43817af2 100644 --- a/src/api/entities/Checkpoint.ts +++ b/src/api/entities/Checkpoint.ts @@ -1,29 +1,33 @@ -import { u64 } from '@polkadot/types'; -import { PolymeshPrimitivesIdentityId, PolymeshPrimitivesTicker } from '@polkadot/types/lookup'; +import { U8aFixed, u64 } from '@polkadot/types'; +import { PolymeshPrimitivesIdentityId } from '@polkadot/types/lookup'; import BigNumber from 'bignumber.js'; import { Context, Entity, FungibleAsset, Identity } from '~/internal'; import { IdentityBalance, PaginationOptions, ResultSet } from '~/types'; import { tuple } from '~/types/utils'; import { + assetToMeshAssetId, balanceToBigNumber, bigNumberToU64, identityIdToString, momentToDate, stringToIdentityId, - stringToTicker, u64ToBigNumber, } from '~/utils/conversion'; import { getIdentity, requestPaginated, toHumanReadable } from '~/utils/internal'; export interface UniqueIdentifiers { id: BigNumber; - ticker: string; + assetId: string; } export interface HumanReadable { id: string; + /** + * @deprecated in favour of `assetId` + */ ticker: string; + assetId: string; } /** @@ -36,9 +40,9 @@ export class Checkpoint extends Entity { * Check if a value is of type {@link UniqueIdentifiers} */ public static override isUniqueIdentifiers(identifier: unknown): identifier is UniqueIdentifiers { - const { id, ticker } = identifier as UniqueIdentifiers; + const { id, assetId } = identifier as UniqueIdentifiers; - return id instanceof BigNumber && typeof ticker === 'string'; + return id instanceof BigNumber && typeof assetId === 'string'; } /** @@ -57,24 +61,21 @@ export class Checkpoint extends Entity { public constructor(identifiers: UniqueIdentifiers, context: Context) { super(identifiers, context); - const { id, ticker } = identifiers; + const { id, assetId } = identifiers; this.id = id; - this.asset = new FungibleAsset({ ticker }, context); + this.asset = new FungibleAsset({ assetId }, context); } /** * Retrieve the Asset's total supply at this checkpoint */ public async totalSupply(): Promise { - const { - context, - asset: { ticker }, - id, - } = this; + const { context, asset, id } = this; + const rawAssetId = assetToMeshAssetId(asset, context); const rawSupply = await context.polymeshApi.query.checkpoint.totalSupply( - stringToTicker(ticker, context), + rawAssetId, bigNumberToU64(id, context) ); @@ -85,14 +86,12 @@ export class Checkpoint extends Entity { * Retrieve this Checkpoint's creation date */ public async createdAt(): Promise { - const { - context, - asset: { ticker }, - id, - } = this; + const { context, asset, id } = this; + + const rawAssetId = assetToMeshAssetId(asset, context); const creationTime = await context.polymeshApi.query.checkpoint.timestamps( - stringToTicker(ticker, context), + rawAssetId, bigNumberToU64(id, context) ); @@ -116,21 +115,20 @@ export class Checkpoint extends Entity { }, }, context, - asset: { ticker }, + asset: assetEntity, id, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(assetEntity, context); // Get one page of current Asset balances const { entries, lastKey: next } = await requestPaginated(asset.balanceOf, { - arg: rawTicker, + arg: rawAssetId, paginationOpts, }); const currentDidBalances: { did: string; balance: BigNumber }[] = []; - const balanceUpdatesMultiParams: [PolymeshPrimitivesTicker, PolymeshPrimitivesIdentityId][] = - []; + const balanceUpdatesMultiParams: [U8aFixed, PolymeshPrimitivesIdentityId][] = []; // Prepare the query for balance updates. Push to currentDidBalances to be used if there are no updates for the balance entries.forEach(([storageKey, balance]) => { @@ -141,7 +139,7 @@ export class Checkpoint extends Entity { did: identityIdToString(identityId), balance: balanceToBigNumber(balance), }); - balanceUpdatesMultiParams.push(tuple(rawTicker, identityId)); + balanceUpdatesMultiParams.push(tuple(rawAssetId, identityId)); }); // Query for balance updates @@ -149,7 +147,7 @@ export class Checkpoint extends Entity { const checkpointBalanceMultiParams: { did: string; - params: [(PolymeshPrimitivesTicker | u64)[], PolymeshPrimitivesIdentityId]; + params: [(U8aFixed | u64)[], PolymeshPrimitivesIdentityId]; }[] = []; const currentIdentityBalances: IdentityBalance[] = []; @@ -162,7 +160,7 @@ export class Checkpoint extends Entity { // If a balance update has occurred for the Identity since the desired Checkpoint, then query Checkpoint storage directly checkpointBalanceMultiParams.push({ did, - params: tuple([rawTicker, firstUpdatedCheckpoint], stringToIdentityId(did, context)), + params: tuple([rawAssetId, firstUpdatedCheckpoint], stringToIdentityId(did, context)), }); } else { // Otherwise use the current balance @@ -206,16 +204,17 @@ export class Checkpoint extends Entity { query: { checkpoint }, }, }, - asset: { ticker }, + asset, id, } = this; const identity = await getIdentity(args?.identity, context); - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); + const rawIdentityId = stringToIdentityId(identity.did, context); - const balanceUpdates = await checkpoint.balanceUpdates(rawTicker, rawIdentityId); + const balanceUpdates = await checkpoint.balanceUpdates(rawAssetId, rawIdentityId); const firstUpdatedCheckpoint = balanceUpdates.find(checkpointId => u64ToBigNumber(checkpointId).gte(id) ); @@ -227,13 +226,13 @@ export class Checkpoint extends Entity { let balance: BigNumber; if (firstUpdatedCheckpoint) { const rawBalance = await checkpoint.balance( - tuple(rawTicker, firstUpdatedCheckpoint), + tuple(rawAssetId, firstUpdatedCheckpoint), rawIdentityId ); balance = balanceToBigNumber(rawBalance); } else { // if no balanceUpdate has occurred since the Checkpoint has been created, then the current balance should be used. The Checkpoint storage will not have an entry - balance = await identity.getAssetBalance({ ticker }); + balance = await identity.getAssetBalance({ ticker: asset.id }); } return balance; @@ -250,11 +249,13 @@ export class Checkpoint extends Entity { }, }, context, - asset: { ticker }, + asset, id, } = this; - const rawCheckpointId = await checkpoint.checkpointIdSequence(stringToTicker(ticker, context)); + const rawAssetId = assetToMeshAssetId(asset, context); + + const rawCheckpointId = await checkpoint.checkpointIdSequence(rawAssetId); return id.lte(u64ToBigNumber(rawCheckpointId)); } @@ -267,6 +268,7 @@ export class Checkpoint extends Entity { return toHumanReadable({ ticker: asset, + assetId: asset, id, }); } diff --git a/src/api/entities/CheckpointSchedule/index.ts b/src/api/entities/CheckpointSchedule/index.ts index 083aa2c430..9a29a154e2 100644 --- a/src/api/entities/CheckpointSchedule/index.ts +++ b/src/api/entities/CheckpointSchedule/index.ts @@ -2,17 +2,26 @@ import BigNumber from 'bignumber.js'; import { Checkpoint, Context, Entity, FungibleAsset, PolymeshError } from '~/internal'; import { ErrorCode, ScheduleDetails } from '~/types'; -import { bigNumberToU64, momentToDate, stringToTicker, u64ToBigNumber } from '~/utils/conversion'; +import { + assetToMeshAssetId, + bigNumberToU64, + momentToDate, + u64ToBigNumber, +} from '~/utils/conversion'; import { toHumanReadable } from '~/utils/internal'; export interface UniqueIdentifiers { id: BigNumber; - ticker: string; + assetId: string; } export interface HumanReadable { id: string; + /** + * @deprecated in favour of `assetId` + */ ticker: string; + assetId: string; pendingPoints: string[]; expiryDate: string | null; } @@ -32,9 +41,9 @@ export class CheckpointSchedule extends Entity * Check if a value is of type {@link UniqueIdentifiers} */ public static override isUniqueIdentifiers(identifier: unknown): identifier is UniqueIdentifiers { - const { id, ticker } = identifier as UniqueIdentifiers; + const { id, assetId } = identifier as UniqueIdentifiers; - return id instanceof BigNumber && typeof ticker === 'string'; + return id instanceof BigNumber && typeof assetId === 'string'; } /** @@ -65,13 +74,13 @@ export class CheckpointSchedule extends Entity super(identifiers, context); - const { id, ticker } = identifiers; + const { id, assetId } = identifiers; const sortedPoints = [...pendingPoints].sort((a, b) => a.getTime() - b.getTime()); this.pendingPoints = sortedPoints; this.expiryDate = sortedPoints[sortedPoints.length - 1]; this.id = id; - this.asset = new FungibleAsset({ ticker }, context); + this.asset = new FungibleAsset({ assetId }, context); } /** @@ -86,13 +95,13 @@ export class CheckpointSchedule extends Entity }, id, context, - asset: { ticker }, + asset, } = this; const rawId = bigNumberToU64(id, context); const scheduleOpt = await checkpoint.scheduledCheckpoints( - stringToTicker(ticker, context), + assetToMeshAssetId(asset, context), rawId ); @@ -123,7 +132,8 @@ export class CheckpointSchedule extends Entity }, }, context, - asset: { ticker }, + asset: { id: assetId }, + asset, id, } = this; @@ -137,11 +147,11 @@ export class CheckpointSchedule extends Entity } const result = await checkpoint.schedulePoints( - stringToTicker(ticker, context), + assetToMeshAssetId(asset, context), bigNumberToU64(id, context) ); - return result.map(rawId => new Checkpoint({ id: u64ToBigNumber(rawId), ticker }, context)); + return result.map(rawId => new Checkpoint({ id: u64ToBigNumber(rawId), assetId }, context)); } /** @@ -155,14 +165,14 @@ export class CheckpointSchedule extends Entity }, }, context, - asset: { ticker }, + asset, id, } = this; const rawId = bigNumberToU64(id, context); const rawSchedule = await checkpoint.scheduledCheckpoints( - stringToTicker(ticker, context), + assetToMeshAssetId(asset, context), rawId ); @@ -177,6 +187,7 @@ export class CheckpointSchedule extends Entity return toHumanReadable({ ticker: asset, + assetId: asset, id, pendingPoints, expiryDate: pendingPoints[pendingPoints.length - 1], diff --git a/src/api/entities/CorporateAction.ts b/src/api/entities/CorporateAction.ts index 523d1df136..ff2e5c28c8 100644 --- a/src/api/entities/CorporateAction.ts +++ b/src/api/entities/CorporateAction.ts @@ -13,12 +13,16 @@ import { createProcedureMethod } from '~/utils/internal'; export interface UniqueIdentifiers { id: BigNumber; - ticker: string; + assetId: string; } export interface HumanReadable { id: string; + /** + * @deprecated in favour of `assetId` + */ ticker: string; + assetId: string; declarationDate: string; description: string; targets: HumanReadableType; diff --git a/src/api/entities/CorporateActionBase/index.ts b/src/api/entities/CorporateActionBase/index.ts index 9e22bacd1e..00d0b83c97 100644 --- a/src/api/entities/CorporateActionBase/index.ts +++ b/src/api/entities/CorporateActionBase/index.ts @@ -19,19 +19,28 @@ import { ProcedureMethod, } from '~/types'; import { HumanReadableType, Modify } from '~/types/utils'; -import { bigNumberToU32, momentToDate, stringToTicker, u64ToBigNumber } from '~/utils/conversion'; +import { + assetToMeshAssetId, + bigNumberToU32, + momentToDate, + u64ToBigNumber, +} from '~/utils/conversion'; import { createProcedureMethod, toHumanReadable } from '~/utils/internal'; import { CorporateActionKind, CorporateActionTargets, TaxWithholding } from './types'; export interface UniqueIdentifiers { id: BigNumber; - ticker: string; + assetId: string; } export interface HumanReadable { id: string; + /** + * @deprecated in favour of `assetId` + */ ticker: string; + assetId: string; declarationDate: string; description: string; targets: HumanReadableType; @@ -58,9 +67,9 @@ export abstract class CorporateActionBase extends Entity [linkCaDocs, { id, ticker, ...procedureArgs }] }, + { + getProcedureAndArgs: procedureArgs => [ + linkCaDocs, + { id, asset: this.asset, ...procedureArgs }, + ], + }, context ); } @@ -178,10 +192,11 @@ export abstract class CorporateActionBase extends Entity momentToDate(rawPoint)); return new CheckpointSchedule( { - ticker, id, pendingPoints: points, + assetId, }, context ); } return new Checkpoint( - { ticker, id: u64ToBigNumber(rawCheckpointIds[createdCheckpointIndex]) }, + { assetId, id: u64ToBigNumber(rawCheckpointIds[createdCheckpointIndex]) }, context ); } @@ -240,12 +255,12 @@ export abstract class CorporateActionBase extends Entity { - const { - asset: { ticker }, - id, - context, - } = this; + const { asset, id, context } = this; - const currentId = await context.polymeshApi.query.externalAgents.agIdSequence( - stringToTicker(ticker, context) - ); + const rawAssetId = assetToMeshAssetId(asset, context); + + const currentId = await context.polymeshApi.query.externalAgents.agIdSequence(rawAssetId); // 1 <= id <= currentId return u32ToBigNumber(currentId).gte(id) && id.gte(1); @@ -115,6 +116,7 @@ export class CustomPermissionGroup extends PermissionGroup { return toHumanReadable({ id, ticker: asset, + assetId: asset, }); } } diff --git a/src/api/entities/DefaultTrustedClaimIssuer.ts b/src/api/entities/DefaultTrustedClaimIssuer.ts index 21a56fdf03..6439e5e685 100644 --- a/src/api/entities/DefaultTrustedClaimIssuer.ts +++ b/src/api/entities/DefaultTrustedClaimIssuer.ts @@ -4,15 +4,15 @@ import { Query } from '~/middleware/types'; import { ClaimType, ErrorCode, EventIdentifier } from '~/types'; import { Ensured } from '~/types/utils'; import { + assetToMeshAssetId, middlewareEventDetailsToEventIdentifier, - stringToTicker, trustedIssuerToTrustedClaimIssuer, } from '~/utils/conversion'; import { getAssetIdForMiddleware, optionize } from '~/utils/internal'; export interface UniqueIdentifiers { did: string; - ticker: string; + assetId: string; } /** @@ -24,9 +24,9 @@ export class DefaultTrustedClaimIssuer extends Identity { * Check if a value is of type {@link UniqueIdentifiers} */ public static override isUniqueIdentifiers(identifier: unknown): identifier is UniqueIdentifiers { - const { did, ticker } = identifier as UniqueIdentifiers; + const { did, assetId } = identifier as UniqueIdentifiers; - return typeof did === 'string' && typeof ticker === 'string'; + return typeof did === 'string' && typeof assetId === 'string'; } /** @@ -38,11 +38,11 @@ export class DefaultTrustedClaimIssuer extends Identity { * @hidden */ public constructor(args: UniqueIdentifiers, context: Context) { - const { ticker, ...identifiers } = args; + const { assetId, ...identifiers } = args; super(identifiers, context); - this.asset = new FungibleAsset({ ticker }, context); + this.asset = new FungibleAsset({ assetId }, context); } /** @@ -86,13 +86,13 @@ export class DefaultTrustedClaimIssuer extends Identity { }, }, context, - asset: { ticker }, + asset, did, } = this; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); - const claimIssuers = await complianceManager.trustedClaimIssuer(rawTicker); + const claimIssuers = await complianceManager.trustedClaimIssuer(rawAssetId); const claimIssuer = claimIssuers .map(issuer => trustedIssuerToTrustedClaimIssuer(issuer, context)) @@ -101,7 +101,7 @@ export class DefaultTrustedClaimIssuer extends Identity { if (!claimIssuer) { throw new PolymeshError({ code: ErrorCode.DataUnavailable, - message: `The Identity with DID "${did}" is no longer a trusted issuer for "${ticker}"`, + message: `The Identity with DID "${did}" is no longer a trusted issuer for "${asset.ticker}"`, }); } diff --git a/src/api/entities/DividendDistribution/index.ts b/src/api/entities/DividendDistribution/index.ts index 67d4feef9e..47e0b1d57e 100644 --- a/src/api/entities/DividendDistribution/index.ts +++ b/src/api/entities/DividendDistribution/index.ts @@ -346,7 +346,7 @@ export class DividendDistribution extends CorporateActionBase { }): Promise { const { id: localId, - asset: { ticker }, + asset, targets: { identities: targetIdentities, treatment }, paymentDate, context, @@ -384,7 +384,7 @@ export class DividendDistribution extends CorporateActionBase { } const rawDid = stringToIdentityId(identity.did, context); - const rawCaId = corporateActionIdentifierToCaId({ ticker, localId }, context); + const rawCaId = corporateActionIdentifierToCaId({ asset, localId }, context); const holderPaid = await query.capitalDistribution.holderPaid([rawCaId, rawDid]); const paid = boolToBoolean(holderPaid); @@ -427,14 +427,10 @@ export class DividendDistribution extends CorporateActionBase { * @hidden */ private fetchDistribution(): Promise> { - const { - asset: { ticker }, - id, - context, - } = this; + const { asset, id, context } = this; return context.polymeshApi.query.capitalDistribution.distributions( - corporateActionIdentifierToCaId({ ticker, localId: id }, context) + corporateActionIdentifierToCaId({ asset, localId: id }, context) ); } @@ -558,7 +554,7 @@ export class DividendDistribution extends CorporateActionBase { participants: DistributionParticipant[] ): Promise { const { - asset: { ticker }, + asset, id: localId, context: { polymeshApi: { @@ -577,7 +573,7 @@ export class DividendDistribution extends CorporateActionBase { let paidStatuses: boolean[] = []; - const caId = corporateActionIdentifierToCaId({ localId, ticker }, context); + const caId = corporateActionIdentifierToCaId({ localId, asset }, context); await P.each(parallelCallChunks, async callChunk => { const parallelMultiCalls = callChunk.map(participantChunk => { diff --git a/src/api/entities/Identity/AssetPermissions.ts b/src/api/entities/Identity/AssetPermissions.ts index f5d6dbc80f..8ebdeacd11 100644 --- a/src/api/entities/Identity/AssetPermissions.ts +++ b/src/api/entities/Identity/AssetPermissions.ts @@ -37,14 +37,15 @@ import { import { Ensured } from '~/types/utils'; import { agentGroupToPermissionGroup, + assetToMeshAssetId, extrinsicPermissionsToTransactionPermissions, + meshAssetToAssetId, middlewareEventDetailsToEventIdentifier, stringToIdentityId, - stringToTicker, - tickerToString, } from '~/utils/conversion'; import { - asTicker, + asAssetId, + asBaseAssetV2, calculateNextKey, createProcedureMethod, getAssetIdForMiddleware, @@ -115,8 +116,8 @@ export class AssetPermissions extends Namespace { const assetEntries = await externalAgents.agentOf.entries(rawDid); return P.map(assetEntries, async ([key]) => { - const ticker = tickerToString(key.args[1]); - const asset = new FungibleAsset({ ticker }, context); + const assetId = meshAssetToAssetId(key.args[1], context); + const asset = new FungibleAsset({ assetId }, context); const group = await this.getGroup({ asset }); return { @@ -151,11 +152,11 @@ export class AssetPermissions extends Namespace { }); } - const ticker = asTicker(asset); - const rawTicker = stringToTicker(ticker, context); + const baseAsset = await asBaseAssetV2(asset, context); + const rawAssetId = assetToMeshAssetId(baseAsset, context); const groupOption = await externalAgents.groupOfAgent( - rawTicker, + rawAssetId, stringToIdentityId(did, context) ); @@ -180,7 +181,7 @@ export class AssetPermissions extends Namespace { if (group.isCustom) { const groupId = group.asCustom; - const groupPermissionsOption = await externalAgents.groupPermissions(rawTicker, groupId); + const groupPermissionsOption = await externalAgents.groupPermissions(rawAssetId, groupId); const permissions = extrinsicPermissionsToTransactionPermissions( groupPermissionsOption.unwrap() @@ -294,12 +295,13 @@ export class AssetPermissions extends Namespace { parent: { did }, } = this; - const ticker = asTicker(asset); + const baseAsset = await asBaseAssetV2(asset, context); + + const rawAssetId = assetToMeshAssetId(baseAsset, context); - const rawTicker = stringToTicker(ticker, context); const rawIdentityId = stringToIdentityId(did, context); - const rawGroupPermissions = await externalAgents.groupOfAgent(rawTicker, rawIdentityId); + const rawGroupPermissions = await externalAgents.groupOfAgent(rawAssetId, rawIdentityId); if (rawGroupPermissions.isNone) { throw new PolymeshError({ @@ -309,7 +311,7 @@ export class AssetPermissions extends Namespace { } const agentGroup = rawGroupPermissions.unwrap(); - return agentGroupToPermissionGroup(agentGroup, ticker, context); + return agentGroupToPermissionGroup(agentGroup, baseAsset.id, context); } /** @@ -321,8 +323,7 @@ export class AssetPermissions extends Namespace { */ public async enabledAt({ asset }: { asset: string | Asset }): Promise { const { context } = this; - - const middlewareAssetId = await getAssetIdForMiddleware(asset, context); + const assetId = await asAssetId(asset, context); const { data: { @@ -332,7 +333,7 @@ export class AssetPermissions extends Namespace { }, } = await context.queryMiddleware>( tickerExternalAgentsQuery({ - assetId: middlewareAssetId, + assetId, }) ); @@ -377,7 +378,7 @@ export class AssetPermissions extends Namespace { const { asset, moduleId: palletName, eventId, size, start } = opts; - const middlewareAssetId = await getAssetIdForMiddleware(asset, context); + const assetId = await asAssetId(asset, context); const { data: { @@ -386,7 +387,7 @@ export class AssetPermissions extends Namespace { } = await context.queryMiddleware>( tickerExternalAgentActionsQuery( { - assetId: middlewareAssetId, + assetId, callerId: did, palletName, eventId, diff --git a/src/api/entities/Identity/index.ts b/src/api/entities/Identity/index.ts index ed3f3a8b3e..a75a2d6ef5 100644 --- a/src/api/entities/Identity/index.ts +++ b/src/api/entities/Identity/index.ts @@ -70,11 +70,13 @@ import { } from '~/utils/constants'; import { accountIdToString, + assetToMeshAssetId, balanceToBigNumber, boolToBoolean, cddStatusToBoolean, corporateActionIdentifierToCaId, identityIdToString, + meshAssetToAssetId, middlewareInstructionToHistoricInstruction, oldMiddlewareInstructionToHistoricInstruction, portfolioIdToMeshPortfolioId, @@ -83,18 +85,15 @@ import { signatoryToSignerValue, signerValueToSigner, stringToIdentityId, - stringToTicker, - tickerToString, transactionPermissionsToTxGroups, u64ToBigNumber, } from '~/utils/conversion'; import { asAsset, - asTicker, + asBaseAssetV2, calculateNextKey, createProcedureMethod, getAccount, - getAssetIdFromMiddleware, getLatestSqVersion, getSecondaryAccountPermissions, requestPaginated, @@ -227,14 +226,21 @@ export class Identity extends Entity { polymeshApi: { query: { asset }, }, + isV6, }, } = this; const { ticker } = args; - const rawTicker = stringToTicker(ticker, context); + const baseAsset = await asBaseAssetV2(ticker, context); + const rawAssetId = assetToMeshAssetId(baseAsset, context); const rawIdentityId = stringToIdentityId(did, context); - const meshAsset = await asset.tokens(rawTicker); + let tokensStorage = asset.securityTokens; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + tokensStorage = (asset as any).tokens; + } + const meshAsset = await tokensStorage(rawAssetId); if (meshAsset.isNone) { throw new PolymeshError({ @@ -246,13 +252,13 @@ export class Identity extends Entity { if (callback) { context.assertSupportsSubscription(); - return asset.balanceOf(rawTicker, rawIdentityId, res => { + return asset.balanceOf(rawAssetId, rawIdentityId, res => { // eslint-disable-next-line @typescript-eslint/no-floating-promises -- callback errors should be handled by the caller callback(balanceToBigNumber(res)); }); } - const balance = await asset.balanceOf(rawTicker, rawIdentityId); + const balance = await asset.balanceOf(rawAssetId, rawIdentityId); return balanceToBigNumber(balance); } @@ -404,9 +410,8 @@ export class Identity extends Entity { const count = new BigNumber(totalCount); - const data = nodes.map( - ({ asset }) => new FungibleAsset({ ticker: getAssetIdFromMiddleware(asset) }, context) - ); + const data = nodes.map(({ assetId }) => new FungibleAsset({ assetId }, context)); + const next = calculateNextKey(count, data.length, start); return { @@ -450,19 +455,9 @@ export class Identity extends Entity { const count = new BigNumber(totalCount); - const data = nodes.map(({ asset, nftIds }) => { - const assetId = getAssetIdFromMiddleware(asset); - const collection = new NftCollection({ ticker: assetId }, context); - const nfts = nftIds.map( - (id: number) => - new Nft( - { - ticker: assetId, - id: new BigNumber(id), - }, - context - ) - ); + const data = nodes.map(({ assetId, nftIds }) => { + const collection = new NftCollection({ assetId }, context); + const nfts = nftIds.map((id: number) => new Nft({ assetId, id: new BigNumber(id) }, context)); return { collection, nfts }; }); @@ -514,9 +509,7 @@ export class Identity extends Entity { trustingAssetsQuery({ issuer: did }) ); - return nodes.map( - ({ asset }) => new FungibleAsset({ ticker: getAssetIdFromMiddleware(asset) }, context) - ); + return nodes.map(({ assetId }) => new FungibleAsset({ assetId }, context)); } /** @@ -759,12 +752,7 @@ export class Identity extends Entity { * - This Identity has already been paid */ return P.filter(distributions, async ({ distribution }): Promise => { - const { - expiryDate, - asset: { ticker }, - id: localId, - paymentDate, - } = distribution; + const { expiryDate, asset, id: localId, paymentDate } = distribution; const isExpired = expiryDate && expiryDate < now; const hasNotStarted = paymentDate > now; @@ -775,7 +763,7 @@ export class Identity extends Entity { const holderPaid = await context.polymeshApi.query.capitalDistribution.holderPaid( tuple( - corporateActionIdentifierToCaId({ ticker, localId }, context), + corporateActionIdentifierToCaId({ asset, localId }, context), stringToIdentityId(did, context) ) ); @@ -996,16 +984,21 @@ export class Identity extends Entity { context, context: { polymeshApi: { - query: { - asset: { preApprovedTicker }, - }, + query: { asset }, }, + isV6, }, } = this; const rawDid = stringToIdentityId(this.did, context); - const { entries, lastKey: next } = await requestPaginated(preApprovedTicker, { + let preApprovedStorage = asset.preApprovedAsset; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + preApprovedStorage = (asset as any).preApprovedTicker; + } + + const { entries, lastKey: next } = await requestPaginated(preApprovedStorage, { arg: rawDid, paginationOpts, }); @@ -1013,11 +1006,11 @@ export class Identity extends Entity { const data = await Promise.all( entries.map(([storageKey]) => { const { - args: [, rawTicker], + args: [, rawAssetId], } = storageKey; - const ticker = tickerToString(rawTicker); + const assetId = meshAssetToAssetId(rawAssetId, context); - return asAsset(ticker, context); + return asAsset(assetId, context); }) ); @@ -1032,19 +1025,24 @@ export class Identity extends Entity { context, context: { polymeshApi: { - query: { - asset: { preApprovedTicker }, - }, + query: { asset: assetQuery }, }, + isV6, }, } = this; - const ticker = asTicker(asset); - const rawTicker = stringToTicker(ticker, context); + let preApprovedStorage = assetQuery.preApprovedAsset; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + preApprovedStorage = (asset as any).preApprovedTicker; + } + + const baseAsset = await asBaseAssetV2(asset, context); + const rawAssetId = assetToMeshAssetId(baseAsset, context); const rawDid = stringToIdentityId(this.did, context); - const rawIsApproved = await preApprovedTicker(rawDid, rawTicker); + const rawIsApproved = await preApprovedStorage(rawDid, rawAssetId); return boolToBoolean(rawIsApproved); } diff --git a/src/api/entities/Instruction/index.ts b/src/api/entities/Instruction/index.ts index c44c9f996e..d22296df1c 100644 --- a/src/api/entities/Instruction/index.ts +++ b/src/api/entities/Instruction/index.ts @@ -54,13 +54,13 @@ import { instructionMemoToString, mediatorAffirmationStatusToStatus, meshAffirmationStatusToAffirmationStatus, + meshAssetToAssetId, meshInstructionStatusToInstructionStatus, meshNftToNftId, meshPortfolioIdToPortfolio, meshSettlementTypeToEndCondition, middlewareEventDetailsToEventIdentifier, momentToDate, - tickerToString, u64ToBigNumber, } from '~/utils/conversion'; import { @@ -432,9 +432,16 @@ export class Instruction extends Entity { if (leg.isSome) { const legValue: PolymeshPrimitivesSettlementLeg = leg.unwrap(); if (legValue.isFungible) { - const { sender, receiver, amount, ticker: rawTicker } = legValue.asFungible; + const { + sender, + receiver, + amount, + ticker: rawTicker, + assetId: rawAssetId, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } = legValue.asFungible as any; - const ticker = tickerToString(rawTicker); + const assetId = meshAssetToAssetId(rawTicker || rawAssetId, context); const fromPortfolio = meshPortfolioIdToPortfolio(sender, context); const toPortfolio = meshPortfolioIdToPortfolio(receiver, context); @@ -442,20 +449,20 @@ export class Instruction extends Entity { from: fromPortfolio, to: toPortfolio, amount: balanceToBigNumber(amount), - asset: new FungibleAsset({ ticker }, context), + asset: new FungibleAsset({ assetId }, context), }; } else if (legValue.isNonFungible) { const { sender, receiver, nfts } = legValue.asNonFungible; const from = meshPortfolioIdToPortfolio(sender, context); const to = meshPortfolioIdToPortfolio(receiver, context); - const { ticker, ids } = meshNftToNftId(nfts); + const { assetId, ids } = meshNftToNftId(nfts, context); return { from, to, - nfts: ids.map(nftId => new Nft({ ticker, id: nftId }, context)), - asset: new NftCollection({ ticker }, context), + nfts: ids.map(nftId => new Nft({ assetId, id: nftId }, context)), + asset: new NftCollection({ assetId }, context), }; } else { const { @@ -463,9 +470,11 @@ export class Instruction extends Entity { receiverIdentity, amount, ticker: rawTicker, - } = legValue.asOffChain; + assetId: rawAssetId, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } = legValue.asOffChain as any; - const ticker = tickerToString(rawTicker); + const assetId = meshAssetToAssetId(rawTicker || rawAssetId, context); const from = identityIdToString(senderIdentity); const to = identityIdToString(receiverIdentity); @@ -473,7 +482,7 @@ export class Instruction extends Entity { from: new Identity({ did: from }, context), to: new Identity({ did: to }, context), offChainAmount: balanceToBigNumber(amount), - asset: ticker, + asset: assetId, }; } } else { @@ -848,7 +857,8 @@ export class Instruction extends Entity { }); } - const { senderIdentity, receiverIdentity, ticker, amount } = rawLeg.asOffChain; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const { senderIdentity, receiverIdentity, ticker, assetId, amount } = rawLeg.asOffChain as any; const rawUid = bigNumberToU64(uid, context); @@ -858,7 +868,7 @@ export class Instruction extends Entity { rawLegId.toHex(true), senderIdentity.toHex(), receiverIdentity.toHex(), - ticker.toHex(), + ticker?.toHex() || assetId?.toHex(), amount.toHex(true), ]; diff --git a/src/api/entities/KnownPermissionGroup.ts b/src/api/entities/KnownPermissionGroup.ts index 8d675b2421..a8784d375d 100644 --- a/src/api/entities/KnownPermissionGroup.ts +++ b/src/api/entities/KnownPermissionGroup.ts @@ -5,12 +5,16 @@ import { toHumanReadable } from '~/utils/internal'; export interface HumanReadable { type: PermissionGroupType; + /** + * @deprecated in favour of `assetId` + */ ticker: string; + assetId: string; } export interface UniqueIdentifiers { type: PermissionGroupType; - ticker: string; + assetId: string; } /** @@ -22,9 +26,9 @@ export class KnownPermissionGroup extends PermissionGroup { * Check if a value is of type {@link UniqueIdentifiers} */ public static override isUniqueIdentifiers(identifier: unknown): identifier is UniqueIdentifiers { - const { type, ticker } = identifier as UniqueIdentifiers; + const { type, assetId } = identifier as UniqueIdentifiers; - return type in PermissionGroupType && typeof ticker === 'string'; + return type in PermissionGroupType && typeof assetId === 'string'; } public type: PermissionGroupType; @@ -100,6 +104,7 @@ export class KnownPermissionGroup extends PermissionGroup { return toHumanReadable({ type, ticker: asset, + assetId: asset, }); } } diff --git a/src/api/entities/MetadataEntry/index.ts b/src/api/entities/MetadataEntry/index.ts index 6ce2d861b2..9c64a00fa3 100644 --- a/src/api/entities/MetadataEntry/index.ts +++ b/src/api/entities/MetadataEntry/index.ts @@ -12,26 +12,30 @@ import { } from '~/internal'; import { ErrorCode, NoArgsProcedureMethod, ProcedureMethod, SetMetadataParams } from '~/types'; import { + assetToMeshAssetId, bigNumberToU64, bytesToString, meshMetadataSpecToMetadataSpec, meshMetadataValueToMetadataValue, metadataToMeshMetadataKey, - stringToTicker, } from '~/utils/conversion'; import { createProcedureMethod, toHumanReadable } from '~/utils/internal'; import { MetadataDetails, MetadataLockStatus, MetadataType, MetadataValue } from './types'; export interface UniqueIdentifiers { - ticker: string; type: MetadataType; id: BigNumber; + assetId: string; } export interface HumanReadable { id: string; + /** + * @deprecated in favour of `assetId` + */ ticker: string; + assetId: string; type: MetadataType; } @@ -59,9 +63,9 @@ export class MetadataEntry extends Entity { * Check if a value is of type {@link UniqueIdentifiers} */ public static override isUniqueIdentifiers(identifier: unknown): identifier is UniqueIdentifiers { - const { id, ticker, type } = identifier as UniqueIdentifiers; + const { id, assetId, type } = identifier as UniqueIdentifiers; - return id instanceof BigNumber && typeof ticker === 'string' && type in MetadataType; + return id instanceof BigNumber && typeof assetId === 'string' && type in MetadataType; } /** @@ -70,9 +74,9 @@ export class MetadataEntry extends Entity { public constructor(identifiers: UniqueIdentifiers, context: Context) { super(identifiers, context); - const { ticker, type, id } = identifiers; + const { type, id, assetId } = identifiers; - this.asset = new BaseAsset({ ticker }, context); + this.asset = new BaseAsset({ assetId }, context); this.type = type; this.id = id; @@ -137,19 +141,19 @@ export class MetadataEntry extends Entity { }, }, id, - asset: { ticker }, + asset, type, context, } = this; const rawId = bigNumberToU64(id, context); - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); let rawName, rawSpecs; if (type === MetadataType.Local) { [rawName, rawSpecs] = await Promise.all([ - assetMetadataLocalKeyToName(rawTicker, rawId), - assetMetadataLocalSpecs(rawTicker, rawId), + assetMetadataLocalKeyToName(rawAssetId, rawId), + assetMetadataLocalSpecs(rawAssetId, rawId), ]); } else { [rawName, rawSpecs] = await Promise.all([ @@ -180,16 +184,16 @@ export class MetadataEntry extends Entity { }, id, type, - asset: { ticker }, + asset, context, } = this; const rawMetadataKey = metadataToMeshMetadataKey(type, id, context); - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const [rawValue, rawValueDetails] = await Promise.all([ - assetMetadataValues(rawTicker, rawMetadataKey), - assetMetadataValueDetails(rawTicker, rawMetadataKey), + assetMetadataValues(rawAssetId, rawMetadataKey), + assetMetadataValueDetails(rawAssetId, rawMetadataKey), ]); return meshMetadataValueToMetadataValue(rawValue, rawValueDetails); @@ -209,7 +213,7 @@ export class MetadataEntry extends Entity { }, id, type, - asset: { ticker }, + asset, context, } = this; @@ -220,8 +224,8 @@ export class MetadataEntry extends Entity { if (type === MetadataType.Global) { rawName = await assetMetadataGlobalKeyToName(rawId); } else { - const rawTicker = stringToTicker(ticker, context); - rawName = await assetMetadataLocalKeyToName(rawTicker, rawId); + const rawAssetId = assetToMeshAssetId(asset, context); + rawName = await assetMetadataLocalKeyToName(rawAssetId, rawId); } return rawName.isSome; @@ -299,6 +303,7 @@ export class MetadataEntry extends Entity { return toHumanReadable({ ticker: asset, + assetId: asset, id, type, }); diff --git a/src/api/entities/Offering/index.ts b/src/api/entities/Offering/index.ts index 831eeed76a..86e362e408 100644 --- a/src/api/entities/Offering/index.ts +++ b/src/api/entities/Offering/index.ts @@ -24,19 +24,27 @@ import { UnsubCallback, } from '~/types'; import { Ensured } from '~/types/utils'; -import { bigNumberToU64, fundraiserToOfferingDetails, stringToTicker } from '~/utils/conversion'; +import { + assetToMeshAssetId, + bigNumberToU64, + fundraiserToOfferingDetails, +} from '~/utils/conversion'; import { calculateNextKey, createProcedureMethod, toHumanReadable } from '~/utils/internal'; import { Investment, OfferingDetails } from './types'; export interface UniqueIdentifiers { id: BigNumber; - ticker: string; + assetId: string; } export interface HumanReadable { id: string; + /** + * @deprecated in favour of `assetId` + */ ticker: string; + assetId: string; } /** @@ -48,9 +56,9 @@ export class Offering extends Entity { * Check if a value is of type {@link UniqueIdentifiers} */ public static override isUniqueIdentifiers(identifier: unknown): identifier is UniqueIdentifiers { - const { id, ticker } = identifier as UniqueIdentifiers; + const { id, assetId } = identifier as UniqueIdentifiers; - return id instanceof BigNumber && typeof ticker === 'string'; + return id instanceof BigNumber && typeof assetId === 'string'; } /** @@ -69,35 +77,35 @@ export class Offering extends Entity { public constructor(identifiers: UniqueIdentifiers, context: Context) { super(identifiers, context); - const { id, ticker } = identifiers; + const { id, assetId } = identifiers; this.id = id; - this.asset = new FungibleAsset({ ticker }, context); + this.asset = new FungibleAsset({ assetId }, context); this.freeze = createProcedureMethod( { - getProcedureAndArgs: () => [toggleFreezeOffering, { ticker, id, freeze: true }], + getProcedureAndArgs: () => [toggleFreezeOffering, { asset: this.asset, id, freeze: true }], voidArgs: true, }, context ); this.unfreeze = createProcedureMethod( { - getProcedureAndArgs: () => [toggleFreezeOffering, { ticker, id, freeze: false }], + getProcedureAndArgs: () => [toggleFreezeOffering, { asset: this.asset, id, freeze: false }], voidArgs: true, }, context ); this.close = createProcedureMethod( - { getProcedureAndArgs: () => [closeOffering, { ticker, id }], voidArgs: true }, + { getProcedureAndArgs: () => [closeOffering, { asset: this.asset, id }], voidArgs: true }, context ); this.modifyTimes = createProcedureMethod( - { getProcedureAndArgs: args => [modifyOfferingTimes, { ticker, id, ...args }] }, + { getProcedureAndArgs: args => [modifyOfferingTimes, { asset: this.asset, id, ...args }] }, context ); this.invest = createProcedureMethod( - { getProcedureAndArgs: args => [investInOffering, { ticker, id, ...args }] }, + { getProcedureAndArgs: args => [investInOffering, { asset: this.asset, id, ...args }] }, context ); } @@ -121,7 +129,7 @@ export class Offering extends Entity { }, }, id, - asset: { ticker }, + asset, context, } = this; @@ -132,22 +140,25 @@ export class Offering extends Entity { return fundraiserToOfferingDetails(rawFundraiser.unwrap(), rawName.unwrap(), context); }; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const rawU64 = bigNumberToU64(id, context); - const fetchName = (): Promise> => sto.fundraiserNames(rawTicker, rawU64); + const fetchName = (): Promise> => sto.fundraiserNames(rawAssetId, rawU64); if (callback) { context.assertSupportsSubscription(); const fundraiserName = await fetchName(); - return sto.fundraisers(rawTicker, rawU64, fundraiserData => { + return sto.fundraisers(rawAssetId, rawU64, fundraiserData => { // eslint-disable-next-line @typescript-eslint/no-floating-promises -- callback errors should be handled by the caller callback(assembleResult(fundraiserData, fundraiserName)); }); } - const [fundraiser, name] = await Promise.all([sto.fundraisers(rawTicker, rawU64), fetchName()]); + const [fundraiser, name] = await Promise.all([ + sto.fundraisers(rawAssetId, rawU64), + fetchName(), + ]); return assembleResult(fundraiser, name); } @@ -245,14 +256,12 @@ export class Offering extends Entity { * Determine whether this Offering exists on chain */ public async exists(): Promise { - const { - asset: { ticker }, - id, - context, - } = this; + const { asset, id, context } = this; + + const rawAssetId = assetToMeshAssetId(asset, context); const fundraiser = await context.polymeshApi.query.sto.fundraisers( - stringToTicker(ticker, context), + rawAssetId, bigNumberToU64(id, context) ); @@ -267,6 +276,7 @@ export class Offering extends Entity { return toHumanReadable({ ticker: asset, + assetId: asset, id, }); } diff --git a/src/api/entities/PermissionGroup.ts b/src/api/entities/PermissionGroup.ts index ce1ff78ae1..d3fb4d8b95 100644 --- a/src/api/entities/PermissionGroup.ts +++ b/src/api/entities/PermissionGroup.ts @@ -1,10 +1,10 @@ import BigNumber from 'bignumber.js'; -import { Context, Entity, FungibleAsset } from '~/internal'; +import { BaseAsset, Context, Entity, FungibleAsset } from '~/internal'; import { GroupPermissions, PermissionGroupType } from '~/types'; export interface UniqueIdentifiers { - ticker: string; + assetId: string; id?: BigNumber; type?: PermissionGroupType; } @@ -16,7 +16,7 @@ export abstract class PermissionGroup extends Entity /** * Asset for which this group specifies permissions */ - public asset: FungibleAsset; + public asset: BaseAsset; /** * @hidden @@ -24,9 +24,9 @@ export abstract class PermissionGroup extends Entity public constructor(identifiers: UniqueIdentifiers, context: Context) { super(identifiers, context); - const { ticker } = identifiers; + const { assetId } = identifiers; - this.asset = new FungibleAsset({ ticker }, context); + this.asset = new FungibleAsset({ assetId }, context); } /** diff --git a/src/api/entities/Portfolio/index.ts b/src/api/entities/Portfolio/index.ts index 34c3c5e3cd..b413a08741 100644 --- a/src/api/entities/Portfolio/index.ts +++ b/src/api/entities/Portfolio/index.ts @@ -32,15 +32,15 @@ import { addressToKey, balanceToBigNumber, identityIdToString, + meshAssetToAssetId, oldMiddlewareDataToHistoricalSettlements, portfolioIdToMeshPortfolioId, - tickerToString, toHistoricalSettlements, u64ToBigNumber, } from '~/utils/conversion'; import { + asAssetId, asFungibleAsset, - asTicker, createProcedureMethod, getAssetIdForMiddleware, getIdentity, @@ -176,11 +176,11 @@ export abstract class Portfolio extends Entity const assetBalances: Record = {}; totalBalanceEntries.forEach(([key, balance]) => { - const ticker = tickerToString(key.args[1]); + const assetId = meshAssetToAssetId(key.args[1], context); const total = balanceToBigNumber(balance); - assetBalances[ticker] = { - asset: new FungibleAsset({ ticker }, context), + assetBalances[assetId] = { + asset: new FungibleAsset({ assetId }, context), total, locked: new BigNumber(0), free: total, @@ -188,14 +188,14 @@ export abstract class Portfolio extends Entity }); lockedBalanceEntries.forEach(([key, balance]) => { - const ticker = tickerToString(key.args[1]); + const assetId = meshAssetToAssetId(key.args[1], context); const locked = balanceToBigNumber(balance); if (!locked.isZero()) { - const tickerBalance = assetBalances[ticker]; + const tickerBalance = assetBalances[assetId]; tickerBalance.locked = locked; - tickerBalance.free = assetBalances[ticker].total.minus(locked); + tickerBalance.free = assetBalances[assetId].total.minus(locked); } }); @@ -209,10 +209,10 @@ export abstract class Portfolio extends Entity if (mask) { return mask.map(portfolioBalance => { const { - asset: { ticker }, + asset: { id: assetId }, } = portfolioBalance; - return assetBalances[ticker] ?? portfolioBalance; + return assetBalances[assetId] ?? portfolioBalance; }); } @@ -252,8 +252,10 @@ export abstract class Portfolio extends Entity }); } - const queriedCollections = args?.collections.map(asset => asTicker(asset)); - const seenTickers = new Set(); + const queriedCollections = await Promise.all( + args?.collections.map(asset => asAssetId(asset, context)) || [] + ); + const seenAssetIds = new Set(); const processCollectionEntry = ( collectionRecord: Record, @@ -261,26 +263,26 @@ export abstract class Portfolio extends Entity ): Record => { const [ { - args: [, [rawTicker, rawNftId]], + args: [, [rawAssetId, rawNftId]], }, ] = entry; - const ticker = tickerToString(rawTicker); + const assetId = meshAssetToAssetId(rawAssetId, context); const heldId = u64ToBigNumber(rawNftId); - if (queriedCollections && !queriedCollections.includes(ticker)) { + if (queriedCollections && !queriedCollections.includes(assetId)) { return collectionRecord; } // if the user provided a filter arg, then ignore any asset not specified - if (!queriedCollections || queriedCollections.includes(ticker)) { - seenTickers.add(ticker); - const nft = new Nft({ id: heldId, ticker }, context); + if (!queriedCollections || queriedCollections.includes(assetId)) { + seenAssetIds.add(assetId); + const nft = new Nft({ id: heldId, assetId }, context); - if (!collectionRecord[ticker]) { - collectionRecord[ticker] = [nft]; + if (!collectionRecord[assetId]) { + collectionRecord[assetId] = [nft]; } else { - collectionRecord[ticker].push(nft); + collectionRecord[assetId].push(nft); } } @@ -298,16 +300,16 @@ export abstract class Portfolio extends Entity ); const collections: PortfolioCollection[] = []; - seenTickers.forEach(ticker => { - const held = heldCollections[ticker]; - const locked = lockedCollections[ticker] || []; + seenAssetIds.forEach(assetId => { + const held = heldCollections[assetId]; + const locked = lockedCollections[assetId] || []; // calculate free NFTs by filtering held NFTs by locked NFT IDs const lockedIds = new Set(locked.map(({ id }) => id.toString())); const free = held.filter(({ id }) => !lockedIds.has(id.toString())); const total = new BigNumber(held.length); collections.push({ - collection: new NftCollection({ ticker }, context), + collection: new NftCollection({ assetId }, context), free, locked, total, diff --git a/src/api/entities/TickerReservation/index.ts b/src/api/entities/TickerReservation/index.ts index 3572f0ab32..f520dbcd88 100644 --- a/src/api/entities/TickerReservation/index.ts +++ b/src/api/entities/TickerReservation/index.ts @@ -102,6 +102,7 @@ export class TickerReservation extends Entity { polymeshApi: { query: { asset }, }, + isV6, }, ticker, context, @@ -138,14 +139,24 @@ export class TickerReservation extends Entity { }; }; + let tickerRegistrationStorage = asset.uniqueTickerRegistration; + let tokensStorage = asset.securityTokens; + + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + tickerRegistrationStorage = (asset as any).tickers; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + tokensStorage = (asset as any).tokens; + } + if (callback) { context.assertSupportsSubscription(); - return requestMulti<[typeof asset.tickers, typeof asset.tokens]>( + return requestMulti<[typeof tickerRegistrationStorage, typeof tokensStorage]>( context, [ - [asset.tickers, rawTicker], - [asset.tokens, rawTicker], + [tickerRegistrationStorage, rawTicker], + [tokensStorage, rawTicker], ], ([registration, token]) => { // eslint-disable-next-line @typescript-eslint/no-floating-promises -- callback errors should be handled by the caller @@ -155,10 +166,10 @@ export class TickerReservation extends Entity { } const [tickerRegistration, meshAsset] = await requestMulti< - [typeof asset.tickers, typeof asset.tokens] + [typeof tickerRegistrationStorage, typeof tokensStorage] >(context, [ - [asset.tickers, rawTicker], - [asset.tokens, rawTicker], + [tickerRegistrationStorage, rawTicker], + [tokensStorage, rawTicker], ]); return assembleResult(tickerRegistration, meshAsset); @@ -198,11 +209,24 @@ export class TickerReservation extends Entity { * Determine whether this Ticker Reservation exists on chain */ public async exists(): Promise { - const { ticker, context } = this; + const { + ticker, + context: { + polymeshApi: { + query: { asset }, + }, + isV6, + }, + context, + } = this; - const tickerSize = await context.polymeshApi.query.asset.tickers.size( - stringToTicker(ticker, context) - ); + let tickerRegistrationStorage = asset.uniqueTickerRegistration; + + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + tickerRegistrationStorage = (asset as any).tickers; + } + const tickerSize = await tickerRegistrationStorage.size(stringToTicker(ticker, context)); return !tickerSize.isZero(); } diff --git a/src/api/entities/types.ts b/src/api/entities/types.ts index b12fc415f8..87294aa875 100644 --- a/src/api/entities/types.ts +++ b/src/api/entities/types.ts @@ -143,7 +143,11 @@ export enum ConditionTarget { export enum ScopeType { // eslint-disable-next-line @typescript-eslint/no-shadow Identity = 'Identity', + /** + * @deprecated in favour of Asset + */ Ticker = 'Ticker', + Asset = 'Asset', Custom = 'Custom', } diff --git a/src/api/procedures/__tests__/moveFunds.ts b/src/api/procedures/__tests__/moveFunds.ts index 7a685a38bc..231cee6785 100644 --- a/src/api/procedures/__tests__/moveFunds.ts +++ b/src/api/procedures/__tests__/moveFunds.ts @@ -19,6 +19,7 @@ import { dsMockUtils, entityMockUtils, procedureMockUtils } from '~/testUtils/mo import { Mocked } from '~/testUtils/types'; import { ErrorCode, + FungibleAsset, FungiblePortfolioMovement, NonFungiblePortfolioMovement, PortfolioBalance, @@ -28,7 +29,6 @@ import { TxTags, } from '~/types'; import * as utilsConversionModule from '~/utils/conversion'; -import { asTicker } from '~/utils/internal'; jest.mock( '~/api/entities/NumberedPortfolio', @@ -482,7 +482,7 @@ describe('moveFunds procedure', () => { .mockReturnValue(rawToMeshPortfolioId); const rawMovePortfolioItem = dsMockUtils.createMockMovePortfolioItem({ - ticker: dsMockUtils.createMockTicker(asTicker(items[0].asset)), + ticker: dsMockUtils.createMockTicker((items[0].asset as FungibleAsset).ticker), amount: dsMockUtils.createMockBalance(items[0].amount), }); when(fungiblePortfolioMovementToMovePortfolioFundSpy) diff --git a/src/api/procedures/addAssetMediators.ts b/src/api/procedures/addAssetMediators.ts index 07a21b1ded..fb00e5070d 100644 --- a/src/api/procedures/addAssetMediators.ts +++ b/src/api/procedures/addAssetMediators.ts @@ -2,7 +2,7 @@ import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { AssetMediatorParams, ErrorCode, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { MAX_ASSET_MEDIATORS } from '~/utils/constants'; -import { identitiesToBtreeSet, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, identitiesToBtreeSet } from '~/utils/conversion'; import { asIdentity, assertIdentityExists } from '~/utils/internal'; /** * @hidden @@ -23,11 +23,7 @@ export async function prepareAddAssetMediators( context, } = this; - const { - asset, - asset: { ticker }, - mediators: mediatorInput, - } = args; + const { asset, mediators: mediatorInput } = args; const currentMediators = await asset.getRequiredMediators(); @@ -43,7 +39,7 @@ export async function prepareAddAssetMediators( throw new PolymeshError({ code: ErrorCode.ValidationError, message: 'One of the specified mediators is already set', - data: { ticker, did: alreadySetDid.did }, + data: { asset, did: alreadySetDid.did }, }); } }); @@ -59,11 +55,11 @@ export async function prepareAddAssetMediators( } const rawNewMediators = identitiesToBtreeSet(newMediators, context); - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); return { transaction: tx.asset.addMandatoryMediators, - args: [rawTicker, rawNewMediators], + args: [rawAssetId, rawNewMediators], resolver: undefined, }; } diff --git a/src/api/procedures/addAssetRequirement.ts b/src/api/procedures/addAssetRequirement.ts index 2263f2b697..9381feda49 100644 --- a/src/api/procedures/addAssetRequirement.ts +++ b/src/api/procedures/addAssetRequirement.ts @@ -5,14 +5,14 @@ import { assertRequirementsNotTooComplex } from '~/api/procedures/utils'; import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { AddAssetRequirementParams, ErrorCode, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { requirementToComplianceRequirement, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, requirementToComplianceRequirement } from '~/utils/conversion'; import { conditionsAreEqual, hasSameElements } from '~/utils/internal'; /** * @hidden */ export type Params = AddAssetRequirementParams & { - ticker: string; + asset: BaseAsset; }; /** @@ -30,11 +30,9 @@ export async function prepareAddAssetRequirement( }, context, } = this; - const { ticker, conditions } = args; + const { asset, conditions } = args; - const rawTicker = stringToTicker(ticker, context); - - const asset = new BaseAsset({ ticker }, context); + const rawAssetId = assetToMeshAssetId(asset, context); const { requirements: currentRequirements, defaultTrustedClaimIssuers } = await asset.compliance.requirements.get(); @@ -67,7 +65,7 @@ export async function prepareAddAssetRequirement( return { transaction: tx.complianceManager.addComplianceRequirement, - args: [rawTicker, senderConditions, receiverConditions], + args: [rawAssetId, senderConditions, receiverConditions], resolver: undefined, }; } @@ -77,12 +75,12 @@ export async function prepareAddAssetRequirement( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { return { permissions: { transactions: [TxTags.complianceManager.AddComplianceRequirement], - assets: [new BaseAsset({ ticker }, this.context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/addAssetStat.ts b/src/api/procedures/addAssetStat.ts index cc9e595c6d..8efa4311b8 100644 --- a/src/api/procedures/addAssetStat.ts +++ b/src/api/procedures/addAssetStat.ts @@ -1,4 +1,4 @@ -import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; +import { PolymeshError, Procedure } from '~/internal'; import { AddAssetStatParams, ErrorCode, StatType, TxTags } from '~/types'; import { BatchTransactionSpec, ProcedureAuthorization } from '~/types/internal'; import { @@ -8,9 +8,8 @@ import { statisticsOpTypeToStatType, statisticStatTypesToBtreeStatType, statTypeToStatOpType, - stringToTickerKey, } from '~/utils/conversion'; -import { checkTxType, compareStatsToInput } from '~/utils/internal'; +import { checkTxType, compareStatsToInput, getAssetIdForStats } from '~/utils/internal'; /** * @hidden @@ -28,11 +27,12 @@ export async function prepareAddAssetStat( }, context, } = this; - const { ticker, type } = args; + const { asset, type } = args; - const tickerKey = stringToTickerKey(ticker, context); - const currentStats = await statisticsQuery.activeAssetStats(tickerKey); - const needStat = ![...currentStats].find(s => compareStatsToInput(s, args)); + const rawAssetId = getAssetIdForStats(asset, context); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const currentStats = await statisticsQuery.activeAssetStats(rawAssetId as any); + const needStat = ![...currentStats].find(s => compareStatsToInput(s, args, context)); if (!needStat) { throw new PolymeshError({ @@ -55,7 +55,8 @@ export async function prepareAddAssetStat( transactions.push( checkTxType({ transaction: statistics.setActiveAssetStats, - args: [tickerKey, newStats], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + args: [rawAssetId as any, newStats], }) ); @@ -66,7 +67,8 @@ export async function prepareAddAssetStat( transactions.push( checkTxType({ transaction: statistics.batchUpdateAssetStats, - args: [tickerKey, newStat, statValue], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + args: [rawAssetId as any, newStat, statValue], }) ); } else if (args.type === StatType.ScopedCount) { @@ -74,7 +76,8 @@ export async function prepareAddAssetStat( transactions.push( checkTxType({ transaction: statistics.batchUpdateAssetStats, - args: [tickerKey, newStat, statValue], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + args: [rawAssetId as any, newStat, statValue], }) ); } @@ -86,13 +89,12 @@ export async function prepareAddAssetStat( */ export function getAuthorization( this: Procedure, - { type, ticker }: AddAssetStatParams + { type, asset }: AddAssetStatParams ): ProcedureAuthorization { const transactions = [TxTags.statistics.SetActiveAssetStats]; if (type === StatType.Count || type === StatType.ScopedCount) { transactions.push(TxTags.statistics.BatchUpdateAssetStats); } - const asset = new FungibleAsset({ ticker }, this.context); return { permissions: { transactions, diff --git a/src/api/procedures/addInstruction.ts b/src/api/procedures/addInstruction.ts index 7543527031..33f9522460 100644 --- a/src/api/procedures/addInstruction.ts +++ b/src/api/procedures/addInstruction.ts @@ -42,6 +42,7 @@ import { BatchTransactionSpec, ProcedureAuthorization } from '~/types/internal'; import { isFungibleLegBuilder, isNftLegBuilder, isOffChainLeg } from '~/utils'; import { MAX_LEGS_LENGTH } from '~/utils/constants'; import { + assetToMeshAssetInputParam, bigNumberToBalance, bigNumberToU64, dateToMoment, @@ -56,16 +57,16 @@ import { portfolioLikeToPortfolioId, stringToIdentityId, stringToMemo, - stringToTicker, u64ToBigNumber, } from '~/utils/conversion'; import { + asAssetId, asBaseAsset, + asBaseAssetV2, asDid, asIdentity, assembleBatchTransactions, assertIdentityExists, - asTicker, filterEventRecords, optionize, } from '~/utils/internal'; @@ -160,12 +161,12 @@ function getEndCondition( /** * @hidden */ -function validateFungibleLeg(leg: FungibleLeg, ticker: string): void { +function validateFungibleLeg(leg: FungibleLeg, assetId: string): void { if (!('amount' in leg)) { throw new PolymeshError({ code: ErrorCode.ValidationError, message: 'The key "amount" should be present in a fungible leg', - data: { ticker }, + data: { assetId }, }); } } @@ -173,12 +174,12 @@ function validateFungibleLeg(leg: FungibleLeg, ticker: string): void { /** * @hidden */ -function validateNonFungibleLeg(leg: NftLeg, ticker: string): void { +function validateNonFungibleLeg(leg: NftLeg, assetId: string): void { if (!('nfts' in leg)) { throw new PolymeshError({ code: ErrorCode.ValidationError, message: 'The key "nfts" should be present in an NFT leg', - data: { ticker }, + data: { assetId }, }); } } @@ -199,7 +200,7 @@ async function separateLegs( const offChainLegs: InstructionOffChainLeg[] = []; for (const leg of legs) { - const ticker = asTicker(leg.asset); + const assetId = await asAssetId(leg.asset, context); if (isOffChainLeg(leg)) { offChainLegs.push(leg); @@ -210,10 +211,10 @@ async function separateLegs( ]); if (isFungible(leg)) { - validateFungibleLeg(leg, ticker); + validateFungibleLeg(leg, assetId); fungibleLegs.push(leg); } else if (isNft(leg)) { - validateNonFungibleLeg(leg, ticker); + validateNonFungibleLeg(leg, assetId); nftLegs.push(leg); } } @@ -388,11 +389,12 @@ async function getTxArgsAndErrors( const rawFromPortfolio = portfolioIdToMeshPortfolioId(fromId, context); const rawToPortfolio = portfolioIdToMeshPortfolioId(toId, context); + const baseAsset = await asBaseAssetV2(asset, context); const rawLeg = legToFungibleLeg( { sender: rawFromPortfolio, receiver: rawToPortfolio, - ticker: stringToTicker(asTicker(asset), context), + ...assetToMeshAssetInputParam(baseAsset, context), amount: bigNumberToBalance(amount, context), }, context @@ -411,6 +413,8 @@ async function getTxArgsAndErrors( assertValidCdd(toId.did, context), ]); + const baseAsset = await asBaseAssetV2(asset, context); + const rawFromPortfolio = portfolioIdToMeshPortfolioId(fromId, context); const rawToPortfolio = portfolioIdToMeshPortfolioId(toId, context); @@ -418,7 +422,7 @@ async function getTxArgsAndErrors( { sender: rawFromPortfolio, receiver: rawToPortfolio, - nfts: nftToMeshNft(asTicker(asset), nfts, context), + nfts: nftToMeshNft(baseAsset, nfts, context), }, context ); @@ -436,7 +440,7 @@ async function getTxArgsAndErrors( { senderIdentity: rawFromIdentityId, receiverIdentity: rawToIdentityId, - ticker: stringToTicker(asset, context), + ...assetToMeshAssetInputParam(new BaseAsset({ assetId: asset }, context), context), amount: bigNumberToBalance(offChainAmount, context), }, context diff --git a/src/api/procedures/addTransferRestriction.ts b/src/api/procedures/addTransferRestriction.ts index ed1dbfdc2b..abbc9688c2 100644 --- a/src/api/procedures/addTransferRestriction.ts +++ b/src/api/procedures/addTransferRestriction.ts @@ -14,7 +14,6 @@ import { import { BatchTransactionSpec, ProcedureAuthorization } from '~/types/internal'; import { complianceConditionsToBtreeSet, - stringToTickerKey, toExemptKey, transferRestrictionToPolymeshTransferCondition, transferRestrictionTypeToStatOpType, @@ -23,6 +22,7 @@ import { import { assertStatIsSet, checkTxType, + getAssetIdForStats, getExemptedBtreeSet, neededStatTypeForRestrictionInput, requestMulti, @@ -31,7 +31,7 @@ import { /** * @hidden */ -export type AddTransferRestrictionParams = { ticker: string } & ( +export type AddTransferRestrictionParams = { asset: FungibleAsset } & ( | AddCountTransferRestrictionParams | AddPercentageTransferRestrictionParams | AddClaimCountTransferRestrictionParams @@ -55,8 +55,8 @@ export async function prepareAddTransferRestriction( }, context, } = this; - const { ticker, exemptedIdentities = [], type } = args; - const tickerKey = stringToTickerKey(ticker, context); + const { asset, exemptedIdentities = [], type } = args; + const rawAssetId = getAssetIdForStats(asset, context); let claimIssuer; if ( @@ -73,8 +73,10 @@ export async function prepareAddTransferRestriction( const [currentStats, { requirements: currentRestrictions }] = await requestMulti< [typeof statisticsQuery.activeAssetStats, typeof statisticsQuery.assetTransferCompliances] >(context, [ - [statisticsQuery.activeAssetStats, tickerKey], - [statisticsQuery.assetTransferCompliances, tickerKey], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [statisticsQuery.activeAssetStats, rawAssetId as any], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [statisticsQuery.assetTransferCompliances, rawAssetId as any], ]); const neededStat = neededStatTypeForRestrictionInput({ type, claimIssuer }, context); @@ -129,14 +131,15 @@ export async function prepareAddTransferRestriction( transactions.push( checkTxType({ transaction: statistics.setAssetTransferCompliance, - args: [tickerKey, conditions], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + args: [rawAssetId as any, conditions], }) ); if (exemptedIdentities.length) { const op = transferRestrictionTypeToStatOpType(type, context); - const exemptedIdBtreeSet = await getExemptedBtreeSet(exemptedIdentities, ticker, context); - const exemptKey = toExemptKey(tickerKey, op, claimType); + const exemptedIdBtreeSet = await getExemptedBtreeSet(exemptedIdentities, context); + const exemptKey = toExemptKey(context, rawAssetId, op, claimType); transactions.push( checkTxType({ transaction: statistics.setEntitiesExempt, @@ -154,7 +157,7 @@ export async function prepareAddTransferRestriction( */ export function getAuthorization( this: Procedure, - { ticker, exemptedIdentities = [] }: AddTransferRestrictionParams + { asset, exemptedIdentities = [] }: AddTransferRestrictionParams ): ProcedureAuthorization { const transactions = [TxTags.statistics.SetAssetTransferCompliance]; @@ -164,7 +167,7 @@ export function getAuthorization( return { permissions: { - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], transactions, portfolios: [], }, diff --git a/src/api/procedures/claimDividends.ts b/src/api/procedures/claimDividends.ts index 717b6468c1..1ebb2a4909 100644 --- a/src/api/procedures/claimDividends.ts +++ b/src/api/procedures/claimDividends.ts @@ -26,12 +26,7 @@ export async function prepareClaimDividends( } = this; const { distribution, - distribution: { - id: localId, - asset: { ticker }, - paymentDate, - expiryDate, - }, + distribution: { id: localId, asset, paymentDate, expiryDate }, } = args; assertDistributionOpen(paymentDate, expiryDate); @@ -54,7 +49,7 @@ export async function prepareClaimDividends( }); } - const rawCaId = corporateActionIdentifierToCaId({ ticker, localId }, context); + const rawCaId = corporateActionIdentifierToCaId({ asset, localId }, context); return { transaction: tx.capitalDistribution.claim, diff --git a/src/api/procedures/clearMetadata.ts b/src/api/procedures/clearMetadata.ts index c89e262555..d5e19e61d0 100644 --- a/src/api/procedures/clearMetadata.ts +++ b/src/api/procedures/clearMetadata.ts @@ -1,7 +1,7 @@ -import { FungibleAsset, MetadataEntry, Procedure } from '~/internal'; +import { MetadataEntry, Procedure } from '~/internal'; import { TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { metadataToMeshMetadataKey, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, metadataToMeshMetadataKey } from '~/utils/conversion'; /** * @hidden @@ -25,15 +25,11 @@ export async function prepareClearMetadata( } = this; const { - metadataEntry: { - id, - type, - asset: { ticker }, - }, + metadataEntry: { id, type, asset }, metadataEntry, } = params; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const rawMetadataKey = metadataToMeshMetadataKey(type, id, context); const { canModify, reason } = await metadataEntry.isModifiable(); @@ -44,7 +40,7 @@ export async function prepareClearMetadata( return { transaction: tx.asset.removeMetadataValue, - args: [rawTicker, rawMetadataKey], + args: [rawAssetId, rawMetadataKey], resolver: undefined, }; } @@ -54,20 +50,12 @@ export async function prepareClearMetadata( */ export function getAuthorization( this: Procedure, - params: Params + { metadataEntry: { asset } }: Params ): ProcedureAuthorization { - const { context } = this; - - const { - metadataEntry: { - asset: { ticker }, - }, - } = params; - return { permissions: { transactions: [TxTags.asset.RemoveMetadataValue], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/closeOffering.ts b/src/api/procedures/closeOffering.ts index f8e8f9cecf..d27f65d99a 100644 --- a/src/api/procedures/closeOffering.ts +++ b/src/api/procedures/closeOffering.ts @@ -3,13 +3,13 @@ import BigNumber from 'bignumber.js'; import { FungibleAsset, Offering, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, OfferingSaleStatus, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { bigNumberToU64, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, bigNumberToU64 } from '~/utils/conversion'; /** * @hidden */ export interface Params { - ticker: string; + asset: FungibleAsset; id: BigNumber; } @@ -28,9 +28,13 @@ export async function prepareCloseOffering( }, context, } = this; - const { ticker, id } = args; + const { + asset: { id: assetId }, + asset, + id, + } = args; - const offering = new Offering({ ticker, id }, context); + const offering = new Offering({ id, assetId }, context); const { status: { sale }, @@ -43,12 +47,12 @@ export async function prepareCloseOffering( }); } - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const rawId = bigNumberToU64(id, context); return { transaction: txSto.stop, - args: [rawTicker, rawId], + args: [rawAssetId, rawId], resolver: undefined, }; } @@ -58,13 +62,12 @@ export async function prepareCloseOffering( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { - const { context } = this; return { permissions: { transactions: [TxTags.sto.Stop], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/configureDividendDistribution.ts b/src/api/procedures/configureDividendDistribution.ts index 7e4a0abc49..91b249030f 100644 --- a/src/api/procedures/configureDividendDistribution.ts +++ b/src/api/procedures/configureDividendDistribution.ts @@ -21,15 +21,15 @@ import { } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, bigNumberToBalance, bigNumberToU64, corporateActionParamsToMeshCorporateActionArgs, dateToMoment, distributionToDividendDistributionParams, + meshAssetToAssetId, meshCorporateActionToCorporateActionParams, portfolioToPortfolioId, - stringToTicker, - tickerToString, u32ToBigNumber, } from '~/utils/conversion'; import { filterEventRecords, getCheckpointValue, optionize } from '~/utils/internal'; @@ -42,18 +42,18 @@ export const createDividendDistributionResolver = async (receipt: ISubmittableResult): Promise => { const [{ data }] = filterEventRecords(receipt, 'capitalDistribution', 'Created'); const [, caId, distribution] = data; - const { ticker, localId } = caId; + const { assetId, localId } = caId; const { corporateAction } = context.polymeshApi.query; const [corpAction, details] = await Promise.all([ - corporateAction.corporateActions(ticker, localId), + corporateAction.corporateActions(assetId, localId), corporateAction.details(caId), ]); return new DividendDistribution( { - ticker: tickerToString(ticker), + assetId: meshAssetToAssetId(assetId, context), id: u32ToBigNumber(localId), ...meshCorporateActionToCorporateActionParams(corpAction.unwrap(), details, context), ...distributionToDividendDistributionParams(distribution, context), @@ -66,7 +66,7 @@ export const createDividendDistributionResolver = * @hidden */ export type Params = ConfigureDividendDistributionParams & { - ticker: string; + asset: FungibleAsset; }; /** @@ -96,7 +96,7 @@ export async function prepareConfigureDividendDistribution( storage: { portfolio }, } = this; const { - ticker, + asset, originPortfolio = null, currency, perShare, @@ -111,7 +111,7 @@ export async function prepareConfigureDividendDistribution( taxWithholdings = null, } = args; - if (currency === ticker) { + if (currency === asset.id) { throw new PolymeshError({ code: ErrorCode.ValidationError, message: 'Cannot distribute Dividends using the Asset as currency', @@ -152,7 +152,7 @@ export async function prepareConfigureDividendDistribution( }); } - const checkpointValue = await getCheckpointValue(checkpoint, ticker, context); + const checkpointValue = await getCheckpointValue(checkpoint, asset, context); if (!(checkpointValue instanceof Checkpoint)) { await assertDistributionDatesValid(checkpointValue, paymentDate, expiryDate); @@ -187,7 +187,8 @@ export async function prepareConfigureDividendDistribution( originPortfolio instanceof BigNumber ? originPortfolio : originPortfolio.id, context ); - const rawCurrency = stringToTicker(currency, context); + const rawCurrency = assetToMeshAssetId(asset, context); + const rawPerShare = bigNumberToBalance(perShare, context); const rawAmount = bigNumberToBalance(maxAmount, context); const rawPaymentAt = dateToMoment(paymentDate, context); @@ -199,7 +200,7 @@ export async function prepareConfigureDividendDistribution( args: [ corporateActionParamsToMeshCorporateActionArgs( { - ticker, + asset, kind: CorporateActionKind.UnpredictableBenefit, declarationDate, checkpoint: checkpointValue, @@ -225,18 +226,17 @@ export async function prepareConfigureDividendDistribution( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { const { storage: { portfolio }, - context, } = this; return { roles: [{ type: RoleType.PortfolioCustodian, portfolioId: portfolioToPortfolioId(portfolio) }], permissions: { transactions: [TxTags.capitalDistribution.Distribute], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [portfolio], }, }; diff --git a/src/api/procedures/controllerTransfer.ts b/src/api/procedures/controllerTransfer.ts index 5f886cee95..634539ad64 100644 --- a/src/api/procedures/controllerTransfer.ts +++ b/src/api/procedures/controllerTransfer.ts @@ -2,11 +2,11 @@ import { DefaultPortfolio, FungibleAsset, PolymeshError, Procedure } from '~/int import { ControllerTransferParams, ErrorCode, RoleType, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, bigNumberToBalance, portfolioIdToMeshPortfolioId, portfolioIdToPortfolio, portfolioLikeToPortfolioId, - stringToTicker, } from '~/utils/conversion'; export interface Storage { @@ -16,7 +16,7 @@ export interface Storage { /** * @hidden */ -export type Params = { ticker: string } & ControllerTransferParams; +export type Params = { asset: FungibleAsset } & ControllerTransferParams; /** * @hidden @@ -32,9 +32,7 @@ export async function prepareControllerTransfer( storage: { did }, context, } = this; - const { ticker, originPortfolio, amount } = args; - - const asset = new FungibleAsset({ ticker }, context); + const { asset, originPortfolio, amount } = args; const originPortfolioId = portfolioLikeToPortfolioId(originPortfolio); @@ -59,10 +57,12 @@ export async function prepareControllerTransfer( }); } + const rawAssetId = assetToMeshAssetId(asset, context); + return { transaction: tx.asset.controllerTransfer, args: [ - stringToTicker(ticker, context), + rawAssetId, bigNumberToBalance(amount, context), portfolioIdToMeshPortfolioId(originPortfolioId, context), ], @@ -75,15 +75,13 @@ export async function prepareControllerTransfer( */ export async function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): Promise { const { context, storage: { did }, } = this; - const asset = new FungibleAsset({ ticker }, context); - const portfolioId = { did }; return { diff --git a/src/api/procedures/createAsset.ts b/src/api/procedures/createAsset.ts index 01e0e32b87..07e159da18 100644 --- a/src/api/procedures/createAsset.ts +++ b/src/api/procedures/createAsset.ts @@ -1,9 +1,17 @@ import { Bytes, u32 } from '@polkadot/types'; +import { ISubmittableResult } from '@polkadot/types/types'; import BigNumber from 'bignumber.js'; import { values } from 'lodash'; import { addManualFees } from '~/api/procedures/utils'; -import { FungibleAsset, Identity, PolymeshError, Procedure, TickerReservation } from '~/internal'; +import { + Context, + FungibleAsset, + Identity, + PolymeshError, + Procedure, + TickerReservation, +} from '~/internal'; import { AssetTx, CreateAssetWithTickerParams, @@ -20,17 +28,15 @@ import { bigNumberToBalance, booleanToBool, fundingRoundToAssetFundingRound, - inputStatTypeToMeshStatType, internalAssetTypeToAssetType, + meshAssetToAssetId, nameToAssetName, portfolioToPortfolioKind, securityIdentifierToAssetIdentifier, - statisticStatTypesToBtreeStatType, stringToBytes, stringToTicker, - stringToTickerKey, } from '~/utils/conversion'; -import { checkTxType, isAllowedCharacters, optionize } from '~/utils/internal'; +import { checkTxType, filterEventRecords, isAllowedCharacters, optionize } from '~/utils/internal'; /** * @hidden @@ -87,6 +93,18 @@ function assertTickerAvailable( } } +/** + * @hidden + */ +export const createAssetResolver = + (context: Context) => + (receipt: ISubmittableResult): FungibleAsset => { + const [{ data }] = filterEventRecords(receipt, 'asset', 'AssetCreated'); + const assetId = meshAssetToAssetId(data[1], context); + + return new FungibleAsset({ assetId }, context); + }; + /** * @hidden */ @@ -97,6 +115,7 @@ export async function prepareCreateAsset( const { context: { polymeshApi: { tx }, + isV6, }, context, storage: { customTypeData, status, signingIdentity }, @@ -112,21 +131,21 @@ export async function prepareCreateAsset( fundingRound, documents, reservationRequired, - initialStatistics, + // initialStatistics, } = args; assertTickerAvailable(ticker, status, reservationRequired); const rawTicker = stringToTicker(ticker, context); const rawName = nameToAssetName(name, context); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const rawNameTickerArgs: any[] = isV6 ? [rawName, rawTicker] : [rawName]; const rawIsDivisible = booleanToBool(isDivisible, context); const rawIdentifiers = securityIdentifiers.map(identifier => securityIdentifierToAssetIdentifier(identifier, context) ); const rawFundingRound = optionize(fundingRoundToAssetFundingRound)(fundingRound, context); - const newAsset = new FungibleAsset({ ticker }, context); - const transactions = []; let fee: BigNumber | undefined; @@ -157,9 +176,10 @@ export async function prepareCreateAsset( if (id.isEmpty) { transactions.push( checkTxType({ - transaction: tx.asset.createAssetWithCustomType, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + transaction: tx.asset.createAssetWithCustomType as any, fee, - args: [rawName, rawTicker, rawIsDivisible, rawValue, rawIdentifiers, rawFundingRound], + args: [...rawNameTickerArgs, rawIsDivisible, rawValue, rawIdentifiers, rawFundingRound], }) ); } else { @@ -167,9 +187,10 @@ export async function prepareCreateAsset( transactions.push( checkTxType({ - transaction: tx.asset.createAsset, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + transaction: tx.asset.createAsset as any, fee, - args: [rawName, rawTicker, rawIsDivisible, rawType, rawIdentifiers, rawFundingRound], + args: [...rawNameTickerArgs, rawIsDivisible, rawType, rawIdentifiers, rawFundingRound], }) ); } @@ -178,25 +199,26 @@ export async function prepareCreateAsset( transactions.push( checkTxType({ - transaction: tx.asset.createAsset, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + transaction: tx.asset.createAsset as any, fee, - args: [rawName, rawTicker, rawIsDivisible, rawType, rawIdentifiers, rawFundingRound], + args: [...rawNameTickerArgs, rawIsDivisible, rawType, rawIdentifiers, rawFundingRound], }) ); } - if (initialStatistics?.length) { - const tickerKey = stringToTickerKey(ticker, context); - const rawStats = initialStatistics.map(i => inputStatTypeToMeshStatType(i, context)); - const bTreeStats = statisticStatTypesToBtreeStatType(rawStats, context); + // if (initialStatistics?.length) { + // const tickerKey = stringToAssetIdKey(ticker, context); + // const rawStats = initialStatistics.map(i => inputStatTypeToMeshStatType(i, context)); + // const bTreeStats = statisticStatTypesToBtreeStatType(rawStats, context); - transactions.push( - checkTxType({ - transaction: tx.statistics.setActiveAssetStats, - args: [tickerKey, bTreeStats], - }) - ); - } + // transactions.push( + // checkTxType({ + // transaction: tx.statistics.setActiveAssetStats, + // args: [tickerKey, bTreeStats], + // }) + // ); + // } if (initialSupply?.gt(0)) { const rawInitialSupply = bigNumberToBalance(initialSupply, context, isDivisible); @@ -231,7 +253,7 @@ export async function prepareCreateAsset( return { transactions, - resolver: newAsset, + resolver: createAssetResolver(context), }; } diff --git a/src/api/procedures/createCheckpoint.ts b/src/api/procedures/createCheckpoint.ts index 15fe7ea8ae..7c43fa3fb2 100644 --- a/src/api/procedures/createCheckpoint.ts +++ b/src/api/procedures/createCheckpoint.ts @@ -3,26 +3,26 @@ import { ISubmittableResult } from '@polkadot/types/types'; import { Checkpoint, Context, FungibleAsset, Procedure } from '~/internal'; import { TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { stringToTicker, u64ToBigNumber } from '~/utils/conversion'; +import { assetToMeshAssetId, u64ToBigNumber } from '~/utils/conversion'; import { filterEventRecords } from '~/utils/internal'; /** * @hidden */ export interface Params { - ticker: string; + asset: FungibleAsset; } /** * @hidden */ export const createCheckpointResolver = - (ticker: string, context: Context) => + (assetId: string, context: Context) => (receipt: ISubmittableResult): Checkpoint => { const [{ data }] = filterEventRecords(receipt, 'checkpoint', 'CheckpointCreated'); const id = u64ToBigNumber(data[2]); - return new Checkpoint({ ticker, id }, context); + return new Checkpoint({ id, assetId }, context); }; /** @@ -33,14 +33,14 @@ export async function prepareCreateCheckpoint( args: Params ): Promise>> { const { context } = this; - const { ticker } = args; + const { asset } = args; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); return { transaction: context.polymeshApi.tx.checkpoint.createCheckpoint, - args: [rawTicker], - resolver: createCheckpointResolver(ticker, context), + args: [rawAssetId], + resolver: createCheckpointResolver(asset.id, context), }; } @@ -49,12 +49,12 @@ export async function prepareCreateCheckpoint( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { return { permissions: { transactions: [TxTags.checkpoint.CreateCheckpoint], - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/createCheckpointSchedule.ts b/src/api/procedures/createCheckpointSchedule.ts index 20e625bd3a..c0a1cc7f81 100644 --- a/src/api/procedures/createCheckpointSchedule.ts +++ b/src/api/procedures/createCheckpointSchedule.ts @@ -4,9 +4,9 @@ import { CheckpointSchedule, Context, FungibleAsset, PolymeshError, Procedure } import { CreateCheckpointScheduleParams, ErrorCode, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, datesToScheduleCheckpoints, momentToDate, - stringToTicker, u64ToBigNumber, } from '~/utils/conversion'; import { filterEventRecords } from '~/utils/internal'; @@ -15,14 +15,14 @@ import { filterEventRecords } from '~/utils/internal'; * @hidden */ export type Params = CreateCheckpointScheduleParams & { - ticker: string; + asset: FungibleAsset; }; /** * @hidden */ export const createCheckpointScheduleResolver = - (ticker: string, context: Context) => + (assetId: string, context: Context) => (receipt: ISubmittableResult): CheckpointSchedule => { const [{ data }] = filterEventRecords(receipt, 'checkpoint', 'ScheduleCreated'); const rawId = data[2]; @@ -34,7 +34,7 @@ export const createCheckpointScheduleResolver = return new CheckpointSchedule( { id, - ticker, + assetId, pendingPoints: points, }, context @@ -49,7 +49,7 @@ export async function prepareCreateCheckpointSchedule( args: Params ): Promise>> { const { context } = this; - const { ticker, points } = args; + const { asset, points } = args; const now = new Date(); @@ -61,13 +61,14 @@ export async function prepareCreateCheckpointSchedule( }); } - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); + const checkpointSchedule = datesToScheduleCheckpoints(points, context); return { transaction: context.polymeshApi.tx.checkpoint.createSchedule, - args: [rawTicker, checkpointSchedule], - resolver: createCheckpointScheduleResolver(ticker, context), + args: [rawAssetId, checkpointSchedule], + resolver: createCheckpointScheduleResolver(asset.id, context), }; } @@ -76,13 +77,12 @@ export async function prepareCreateCheckpointSchedule( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { - const { context } = this; return { permissions: { transactions: [TxTags.checkpoint.CreateSchedule], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/createGroup.ts b/src/api/procedures/createGroup.ts index d47146ecc5..90fa8598ee 100644 --- a/src/api/procedures/createGroup.ts +++ b/src/api/procedures/createGroup.ts @@ -1,10 +1,10 @@ import { assertGroupDoesNotExist, createCreateGroupResolver } from '~/api/procedures/utils'; -import { CustomPermissionGroup, FungibleAsset, Procedure } from '~/internal'; +import { BaseAsset, CustomPermissionGroup, FungibleAsset, Procedure } from '~/internal'; import { CreateGroupParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, permissionsLikeToPermissions, - stringToTicker, transactionPermissionsToExtrinsicPermissions, } from '~/utils/conversion'; @@ -12,7 +12,7 @@ import { * @hidden */ export type Params = CreateGroupParams & { - ticker: string; + asset: BaseAsset; }; /** @@ -26,7 +26,7 @@ export interface Storage { * @hidden */ export async function prepareCreateGroup( - this: Procedure, + this: Procedure, args: Params ): Promise< TransactionSpec> @@ -38,11 +38,10 @@ export async function prepareCreateGroup( }, }, context, - storage: { asset }, } = this; - const { ticker, permissions } = args; + const { asset, permissions } = args; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const { transactions } = permissionsLikeToPermissions(permissions, context); await assertGroupDoesNotExist(asset, transactions); @@ -54,7 +53,7 @@ export async function prepareCreateGroup( return { transaction: externalAgents.createGroup, - args: [rawTicker, rawExtrinsicPermissions], + args: [rawAssetId, rawExtrinsicPermissions], resolver: createCreateGroupResolver(context), }; } @@ -63,11 +62,9 @@ export async function prepareCreateGroup( * @hidden */ export function getAuthorization( - this: Procedure + this: Procedure, + { asset }: Params ): ProcedureAuthorization { - const { - storage: { asset }, - } = this; return { permissions: { transactions: [TxTags.externalAgents.CreateGroup], @@ -80,19 +77,5 @@ export function getAuthorization( /** * @hidden */ -export function prepareStorage( - this: Procedure, - { ticker }: Params -): Storage { - const { context } = this; - - return { - asset: new FungibleAsset({ ticker }, context), - }; -} - -/** - * @hidden - */ -export const createGroup = (): Procedure => - new Procedure(prepareCreateGroup, getAuthorization, prepareStorage); +export const createGroup = (): Procedure => + new Procedure(prepareCreateGroup, getAuthorization); diff --git a/src/api/procedures/createNftCollection.ts b/src/api/procedures/createNftCollection.ts index a9f8a50588..7b3a3fffee 100644 --- a/src/api/procedures/createNftCollection.ts +++ b/src/api/procedures/createNftCollection.ts @@ -1,3 +1,5 @@ +// TODO @prashantasdeveloper fix the logic here + import { Bytes, u32 } from '@polkadot/types'; import BigNumber from 'bignumber.js'; import { values } from 'lodash'; @@ -5,7 +7,6 @@ import { values } from 'lodash'; import { addManualFees } from '~/api/procedures/utils'; import { BaseAsset, - FungibleAsset, Identity, NftCollection, PolymeshError, @@ -32,7 +33,6 @@ import { booleanToBool, collectionKeysToMetadataKeys, internalAssetTypeToAssetType, - internalNftTypeToNftType, metadataSpecToMeshMetadataSpec, nameToAssetName, securityIdentifierToAssetIdentifier, @@ -102,6 +102,7 @@ export async function prepareCreateNftCollection( const { context: { polymeshApi: { tx }, + isV6, }, context, storage: { customTypeData, status }, @@ -124,14 +125,15 @@ export async function prepareCreateNftCollection( const rawTicker = stringToTicker(ticker, context); const rawName = nameToAssetName(name ?? ticker, context); - const rawType = internalNftTypeToNftType(internalNftType, context); + const rawNameTickerArgs = isV6 ? [rawName, rawTicker] : [rawName]; + // const rawType = internalNftTypeToNftType(internalNftType, context); const rawDivisibility = booleanToBool(false, context); const rawIdentifiers = securityIdentifiers.map(identifier => securityIdentifierToAssetIdentifier(identifier, context) ); const rawFundingRound = optionize(stringToBytes)(fundingRound, context); - let nextLocalId = new BigNumber(1); + const nextLocalId = new BigNumber(1); let fee: BigNumber | undefined; if (status === TickerReservationStatus.Free) { const rawAssetType = internalAssetTypeToAssetType({ NonFungible: internalNftType }, context); @@ -143,8 +145,15 @@ export async function prepareCreateNftCollection( transactions.push( checkTxType({ - transaction: tx.asset.createAsset, - args: [rawName, rawTicker, rawDivisibility, rawAssetType, rawIdentifiers, rawFundingRound], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + transaction: tx.asset.createAsset as any, + args: [ + ...rawNameTickerArgs, + rawDivisibility, + rawAssetType, + rawIdentifiers, + rawFundingRound, + ], }) ); } else if (status === TickerReservationStatus.Reserved) { @@ -156,8 +165,15 @@ export async function prepareCreateNftCollection( ); transactions.push( checkTxType({ - transaction: tx.asset.createAsset, - args: [rawName, rawTicker, rawDivisibility, rawAssetType, rawIdentifiers, rawFundingRound], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + transaction: tx.asset.createAsset as any, + args: [ + ...rawNameTickerArgs, + rawDivisibility, + rawAssetType, + rawIdentifiers, + rawFundingRound, + ], }) ); } else if (status === TickerReservationStatus.AssetCreated) { @@ -165,20 +181,19 @@ export async function prepareCreateNftCollection( * assets can be created with type Nft, but not have a created collection, * we handle this case to prevent a ticker getting stuck if it was initialized via non SDK methods */ - const asset = new FungibleAsset({ ticker }, context); - let nonFungible; - [fee, { nonFungible }, nextLocalId] = await Promise.all([ - addManualFees(new BigNumber(0), [TxTags.nft.CreateNftCollection], context), - asset.details(), - asset.metadata.getNextLocalId(), - ]); - - if (!nonFungible) { - throw new PolymeshError({ - code: ErrorCode.UnmetPrerequisite, - message: 'Only assets with type NFT can be turned into NFT collections', - }); - } + // const asset = new FungibleAsset({ ticker }, context); + // let nonFungible; + // [fee, { nonFungible }, nextLocalId] = await Promise.all([ + // addManualFees(new BigNumber(0), [TxTags.nft.CreateNftCollection], context), + // asset.details(), + // asset.metadata.getNextLocalId(), + // ]); + // if (!nonFungible) { + // throw new PolymeshError({ + // code: ErrorCode.UnmetPrerequisite, + // message: 'Only assets with type NFT can be turned into NFT collections', + // }); + // } } const globalMetadataKeys = collectionKeys.filter(isGlobalMetadata); @@ -227,13 +242,17 @@ export async function prepareCreateNftCollection( checkTxType({ transaction: tx.nft.createNftCollection, fee, - args: [rawTicker, rawType, rawCollectionKeys], + args: [ + rawTicker, + // rawType, + rawCollectionKeys, + ], }) ); return { transactions, - resolver: new NftCollection({ ticker }, context), + resolver: new NftCollection({ assetId: ticker }, context), }; } @@ -278,7 +297,7 @@ export async function getAuthorization( return { permissions: { ...permissions, - assets: [new BaseAsset({ ticker }, context)], + assets: [new BaseAsset({ assetId: ticker }, context)], }, }; } @@ -298,21 +317,25 @@ export async function prepareStorage( const needsLocalMetadata = collectionKeys.some(isLocalMetadata); const reservation = new TickerReservation({ ticker }, context); - const nft = new NftCollection({ ticker }, context); + // const nft = new NftCollection({ ticker }, context); - const [{ status }, signingIdentity, collectionExists] = await Promise.all([ + const [ + { status }, + signingIdentity, + // collectionExists + ] = await Promise.all([ reservation.details(), context.getSigningIdentity(), - nft.exists(), + // nft.exists(), ]); - if (collectionExists) { - throw new PolymeshError({ - code: ErrorCode.UnmetPrerequisite, - message: 'An NFT collection already exists with the ticker', - data: { ticker }, - }); - } + // if (collectionExists) { + // throw new PolymeshError({ + // code: ErrorCode.UnmetPrerequisite, + // message: 'An NFT collection already exists with the ticker', + // data: { ticker }, + // }); + // } let customTypeData: Storage['customTypeData']; diff --git a/src/api/procedures/investInOffering.ts b/src/api/procedures/investInOffering.ts index 9e98f3d03f..2f00dc5035 100644 --- a/src/api/procedures/investInOffering.ts +++ b/src/api/procedures/investInOffering.ts @@ -3,6 +3,7 @@ import BigNumber from 'bignumber.js'; import { Offering, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, + FungibleAsset, InvestInOfferingParams, OfferingSaleStatus, OfferingTimingStatus, @@ -13,12 +14,12 @@ import { } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, bigNumberToBalance, bigNumberToU64, portfolioIdToMeshPortfolioId, portfolioIdToPortfolio, portfolioLikeToPortfolioId, - stringToTicker, } from '~/utils/conversion'; import { optionize } from '~/utils/internal'; @@ -27,7 +28,7 @@ import { optionize } from '~/utils/internal'; */ export type Params = InvestInOfferingParams & { id: BigNumber; - ticker: string; + asset: FungibleAsset; }; /** @@ -115,9 +116,15 @@ export async function prepareInvestInSto( context, storage: { purchasePortfolioId, fundingPortfolioId }, } = this; - const { ticker, id, purchaseAmount, maxPrice } = args; + const { + asset: { id: assetId }, + asset, + id, + purchaseAmount, + maxPrice, + } = args; - const offering = new Offering({ ticker, id }, context); + const offering = new Offering({ id, assetId }, context); const portfolio = portfolioIdToPortfolio(fundingPortfolioId, context); @@ -166,12 +173,14 @@ export async function prepareInvestInSto( }); } + const rawAssetId = assetToMeshAssetId(asset, context); + return { transaction: txSto.invest, args: [ portfolioIdToMeshPortfolioId(purchasePortfolioId, context), portfolioIdToMeshPortfolioId(fundingPortfolioId, context), - stringToTicker(ticker, context), + rawAssetId, bigNumberToU64(id, context), bigNumberToBalance(purchaseAmount, context), optionize(bigNumberToBalance)(maxPrice, context), diff --git a/src/api/procedures/inviteExternalAgent.ts b/src/api/procedures/inviteExternalAgent.ts index 3f305998cd..db9a118a46 100644 --- a/src/api/procedures/inviteExternalAgent.ts +++ b/src/api/procedures/inviteExternalAgent.ts @@ -20,13 +20,13 @@ import { } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, authorizationToAuthorizationData, dateToMoment, permissionsLikeToPermissions, signerToString, signerValueToSignatory, stringToIdentityId, - stringToTicker, transactionPermissionsToExtrinsicPermissions, u64ToBigNumber, } from '~/utils/conversion'; @@ -46,21 +46,14 @@ export const createGroupAndAuthorizationResolver = * @hidden */ export type Params = InviteExternalAgentParams & { - ticker: string; -}; - -/** - * @hidden - */ -export interface Storage { asset: BaseAsset; -} +}; /** * @hidden */ export async function prepareInviteExternalAgent( - this: Procedure, + this: Procedure, args: Params ): Promise< | TransactionSpec< @@ -76,10 +69,9 @@ export async function prepareInviteExternalAgent( }, }, context, - storage: { asset }, } = this; - const { ticker, target, permissions, expiry = null } = args; + const { asset, target, permissions, expiry = null } = args; const issuer = await context.getSigningIdentity(); const targetIdentity = await context.getIdentity(target); @@ -117,7 +109,7 @@ export async function prepareInviteExternalAgent( newAuthorizationData = createBecomeAgentData(permissions); rawAuthorizationData = authorizationToAuthorizationData(newAuthorizationData, context); } else { - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const { transactions } = permissionsLikeToPermissions(permissions, context); const matchingGroup = await getGroupFromPermissions(asset, transactions); @@ -130,7 +122,7 @@ export async function prepareInviteExternalAgent( return { transaction: externalAgents.createGroupAndAddAuth, args: [ - rawTicker, + rawAssetId, transactionPermissionsToExtrinsicPermissions(transactions, context), stringToIdentityId(targetDid, context), null, @@ -162,11 +154,9 @@ export async function prepareInviteExternalAgent( * @hidden */ export function getAuthorization( - this: Procedure + this: Procedure, + { asset }: Params ): ProcedureAuthorization { - const { - storage: { asset }, - } = this; return { permissions: { transactions: [TxTags.identity.AddAuthorization], @@ -179,19 +169,5 @@ export function getAuthorization( /** * @hidden */ -export function prepareStorage( - this: Procedure, - { ticker }: Params -): Storage { - const { context } = this; - - return { - asset: new BaseAsset({ ticker }, context), - }; -} - -/** - * @hidden - */ -export const inviteExternalAgent = (): Procedure => - new Procedure(prepareInviteExternalAgent, getAuthorization, prepareStorage); +export const inviteExternalAgent = (): Procedure => + new Procedure(prepareInviteExternalAgent, getAuthorization); diff --git a/src/api/procedures/issueNft.ts b/src/api/procedures/issueNft.ts index c52cee0d28..72c7416241 100644 --- a/src/api/procedures/issueNft.ts +++ b/src/api/procedures/issueNft.ts @@ -5,20 +5,16 @@ import { Context, NftCollection, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, IssueNftParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, meshNftToNftId, nftInputToNftMetadataVec, portfolioToPortfolioKind, - stringToTicker, } from '~/utils/conversion'; import { filterEventRecords } from '~/utils/internal'; export type Params = IssueNftParams & { - ticker: string; -}; - -export interface Storage { collection: NftCollection; -} +}; /** * @hidden @@ -28,16 +24,16 @@ export const issueNftResolver = (receipt: ISubmittableResult): Nft => { const [{ data }] = filterEventRecords(receipt, 'nft', 'NFTPortfolioUpdated'); - const { ticker, ids } = meshNftToNftId(data[1]); + const { assetId, ids } = meshNftToNftId(data[1], context); - return new Nft({ ticker, id: ids[0] }, context); + return new Nft({ id: ids[0], assetId }, context); }; /** * @hidden */ export async function prepareIssueNft( - this: Procedure, + this: Procedure, args: Params ): Promise>> { const { @@ -45,9 +41,8 @@ export async function prepareIssueNft( polymeshApi: { tx }, }, context, - storage: { collection }, } = this; - const { ticker, portfolioId, metadata } = args; + const { portfolioId, metadata, collection } = args; const rawMetadataValues = nftInputToNftMetadataVec(metadata, context); const neededMetadata = await collection.collectionKeys(); @@ -62,7 +57,7 @@ export async function prepareIssueNft( throw new PolymeshError({ code: ErrorCode.ValidationError, message: 'A metadata value was given that is not required for this collection', - data: { ticker, type: value.type, id: value.id }, + data: { assetId: collection.id, type: value.type, id: value.id }, }); } @@ -83,12 +78,12 @@ export async function prepareIssueNft( ? await signingIdentity.portfolios.getPortfolio({ portfolioId }) : await signingIdentity.portfolios.getPortfolio(); - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(collection, context); const rawPortfolio = portfolioToPortfolioKind(portfolio, context); return { transaction: tx.nft.issueNft, - args: [rawTicker, rawMetadataValues, rawPortfolio], + args: [rawAssetId, rawMetadataValues, rawPortfolio], resolver: issueNftResolver(context), }; } @@ -96,10 +91,10 @@ export async function prepareIssueNft( /** * @hidden */ -export function getAuthorization(this: Procedure): ProcedureAuthorization { - const { - storage: { collection }, - } = this; +export function getAuthorization( + this: Procedure, + { collection }: Params +): ProcedureAuthorization { return { permissions: { transactions: [TxTags.nft.IssueNft], @@ -112,16 +107,5 @@ export function getAuthorization(this: Procedure): Procedu /** * @hidden */ -export function prepareStorage(this: Procedure, { ticker }: Params): Storage { - const { context } = this; - - return { - collection: new NftCollection({ ticker }, context), - }; -} - -/** - * @hidden - */ -export const issueNft = (): Procedure => - new Procedure(prepareIssueNft, getAuthorization, prepareStorage); +export const issueNft = (): Procedure => + new Procedure(prepareIssueNft, getAuthorization); diff --git a/src/api/procedures/issueTokens.ts b/src/api/procedures/issueTokens.ts index 7162a156cc..b857631d9e 100644 --- a/src/api/procedures/issueTokens.ts +++ b/src/api/procedures/issueTokens.ts @@ -2,21 +2,21 @@ import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, IssueTokensParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { MAX_BALANCE } from '~/utils/constants'; -import { bigNumberToBalance, portfolioToPortfolioKind, stringToTicker } from '~/utils/conversion'; +import { + assetToMeshAssetId, + bigNumberToBalance, + portfolioToPortfolioKind, +} from '~/utils/conversion'; export type Params = IssueTokensParams & { - ticker: string; -}; - -export interface Storage { asset: FungibleAsset; -} +}; /** * @hidden */ export async function prepareIssueTokens( - this: Procedure, + this: Procedure, args: Params ): Promise>> { const { @@ -26,9 +26,8 @@ export async function prepareIssueTokens( }, }, context, - storage: { asset: assetEntity }, } = this; - const { ticker, amount, portfolioId } = args; + const { asset: assetEntity, amount, portfolioId } = args; const [{ isDivisible, totalSupply }, signingIdentity] = await Promise.all([ assetEntity.details(), @@ -39,7 +38,7 @@ export async function prepareIssueTokens( if (supplyAfterMint.isGreaterThan(MAX_BALANCE)) { throw new PolymeshError({ code: ErrorCode.LimitExceeded, - message: `This issuance operation will cause the total supply of "${ticker}" to exceed the supply limit`, + message: `This issuance operation will cause the total supply of "${assetEntity.id}" to exceed the supply limit`, data: { currentSupply: totalSupply, supplyLimit: MAX_BALANCE, @@ -51,13 +50,13 @@ export async function prepareIssueTokens( ? await signingIdentity.portfolios.getPortfolio({ portfolioId }) : await signingIdentity.portfolios.getPortfolio(); - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(assetEntity, context); const rawValue = bigNumberToBalance(amount, context, isDivisible); const rawPortfolio = portfolioToPortfolioKind(portfolio, context); return { transaction: asset.issue, - args: [rawTicker, rawValue, rawPortfolio], + args: [rawAssetId, rawValue, rawPortfolio], resolver: assetEntity, }; } @@ -66,11 +65,9 @@ export async function prepareIssueTokens( * @hidden */ export function getAuthorization( - this: Procedure + this: Procedure, + { asset }: Params ): ProcedureAuthorization { - const { - storage: { asset }, - } = this; return { permissions: { transactions: [TxTags.asset.Issue], @@ -83,19 +80,5 @@ export function getAuthorization( /** * @hidden */ -export function prepareStorage( - this: Procedure, - { ticker }: Params -): Storage { - const { context } = this; - - return { - asset: new FungibleAsset({ ticker }, context), - }; -} - -/** - * @hidden - */ -export const issueTokens = (): Procedure => - new Procedure(prepareIssueTokens, getAuthorization, prepareStorage); +export const issueTokens = (): Procedure => + new Procedure(prepareIssueTokens, getAuthorization); diff --git a/src/api/procedures/launchOffering.ts b/src/api/procedures/launchOffering.ts index 7b3f478393..4e119c20c4 100644 --- a/src/api/procedures/launchOffering.ts +++ b/src/api/procedures/launchOffering.ts @@ -7,6 +7,7 @@ import { Context, FungibleAsset, Identity, Offering, PolymeshError, Procedure } import { ErrorCode, LaunchOfferingParams, PortfolioId, RoleType, TxTags, VenueType } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, bigNumberToBalance, bigNumberToU64, dateToMoment, @@ -15,16 +16,15 @@ import { portfolioIdToPortfolio, portfolioLikeToPortfolioId, stringToBytes, - stringToTicker, u64ToBigNumber, } from '~/utils/conversion'; -import { filterEventRecords, optionize } from '~/utils/internal'; +import { asBaseAssetV2, filterEventRecords, optionize } from '~/utils/internal'; /** * @hidden */ export type Params = LaunchOfferingParams & { - ticker: string; + asset: FungibleAsset; }; /** @@ -39,12 +39,12 @@ export interface Storage { * @hidden */ export const createOfferingResolver = - (ticker: string, context: Context) => + (assetId: string, context: Context) => (receipt: ISubmittableResult): Offering => { const [{ data }] = filterEventRecords(receipt, 'sto', 'FundraiserCreated'); const newFundraiserId = u64ToBigNumber(data[1]); - return new Offering({ id: newFundraiserId, ticker }, context); + return new Offering({ id: newFundraiserId, assetId }, context); }; /** @@ -61,7 +61,7 @@ export async function prepareLaunchOffering( context, storage: { offeringPortfolioId, raisingPortfolioId }, } = this; - const { ticker, raisingCurrency, venue, name, tiers, start, end, minInvestment } = args; + const { asset, raisingCurrency, venue, name, tiers, start, end, minInvestment } = args; const portfolio = portfolioIdToPortfolio(offeringPortfolioId, context); @@ -69,7 +69,7 @@ export async function prepareLaunchOffering( assertPortfolioExists(offeringPortfolioId, context), assertPortfolioExists(raisingPortfolioId, context), portfolio.getAssetBalances({ - assets: [ticker], + assets: [asset], }), ]); @@ -118,13 +118,16 @@ export async function prepareLaunchOffering( }); } + const rawAssetId = assetToMeshAssetId(asset, context); + const raisingAsset = await asBaseAssetV2(raisingCurrency, context); + return { transaction: tx.sto.createFundraiser, args: [ portfolioIdToMeshPortfolioId(offeringPortfolioId, context), - stringToTicker(ticker, context), + rawAssetId, portfolioIdToMeshPortfolioId(raisingPortfolioId, context), - stringToTicker(raisingCurrency, context), + assetToMeshAssetId(raisingAsset, context), tiers.map(tier => offeringTierToPriceTier(tier, context)), bigNumberToU64(venueId, context), optionize(dateToMoment)(start, context), @@ -132,7 +135,7 @@ export async function prepareLaunchOffering( bigNumberToBalance(minInvestment, context), stringToBytes(name, context), ], - resolver: createOfferingResolver(ticker, context), + resolver: createOfferingResolver(asset.id, context), }; } @@ -141,7 +144,7 @@ export async function prepareLaunchOffering( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { const { storage: { offeringPortfolioId, raisingPortfolioId }, @@ -155,7 +158,7 @@ export function getAuthorization( ], permissions: { transactions: [TxTags.sto.CreateFundraiser], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [ portfolioIdToPortfolio(offeringPortfolioId, context), portfolioIdToPortfolio(raisingPortfolioId, context), diff --git a/src/api/procedures/linkCaDocs.ts b/src/api/procedures/linkCaDocs.ts index 465d50de7b..4b5be4379f 100644 --- a/src/api/procedures/linkCaDocs.ts +++ b/src/api/procedures/linkCaDocs.ts @@ -6,9 +6,9 @@ import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, LinkCaDocsParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, corporateActionIdentifierToCaId, documentToAssetDocument, - stringToTicker, } from '~/utils/conversion'; /** @@ -16,7 +16,7 @@ import { */ export type Params = LinkCaDocsParams & { id: BigNumber; - ticker: string; + asset: FungibleAsset; }; /** @@ -37,9 +37,10 @@ export async function prepareLinkCaDocs( }, context, } = this; - const { id: caId, ticker, documents } = args; + const { id: caId, asset, documents } = args; - const rawAssetDocuments = await assetDocuments.entries(stringToTicker(ticker, context)); + const rawAssetId = assetToMeshAssetId(asset, context); + const rawAssetDocuments = await assetDocuments.entries(rawAssetId); const docIdsToLink: u32[] = []; const documentsCopy = [...documents]; // avoid mutation @@ -66,7 +67,7 @@ export async function prepareLinkCaDocs( }); } - const rawCaId = corporateActionIdentifierToCaId({ ticker, localId: caId }, context); + const rawCaId = corporateActionIdentifierToCaId({ asset, localId: caId }, context); return { transaction: corporateAction.linkCaDoc, @@ -80,11 +81,11 @@ export async function prepareLinkCaDocs( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { return { permissions: { - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], transactions: [TxTags.corporateAction.LinkCaDoc], portfolios: [], }, diff --git a/src/api/procedures/modifyAsset.ts b/src/api/procedures/modifyAsset.ts index b5e25ff9a4..fc5ed07d45 100644 --- a/src/api/procedures/modifyAsset.ts +++ b/src/api/procedures/modifyAsset.ts @@ -3,17 +3,17 @@ import { Asset, ErrorCode, ModifyAssetParams, TxTags } from '~/types'; import { BatchTransactionSpec, ProcedureAuthorization } from '~/types/internal'; import { isNftCollection } from '~/utils'; import { + assetToMeshAssetId, fundingRoundToAssetFundingRound, nameToAssetName, securityIdentifierToAssetIdentifier, - stringToTicker, } from '~/utils/conversion'; import { asAsset, checkTxType, hasSameElements } from '~/utils/internal'; /** * @hidden */ -export type Params = { ticker: string } & ModifyAssetParams; +export type Params = { asset: BaseAsset } & ModifyAssetParams; /** * @hidden @@ -29,7 +29,7 @@ export async function prepareModifyAsset( context, } = this; const { - ticker, + asset, makeDivisible, name: newName, fundingRound: newFundingRound, @@ -49,9 +49,7 @@ export async function prepareModifyAsset( }); } - const rawTicker = stringToTicker(ticker, context); - - const asset = await asAsset(ticker, context); + const rawAssetId = await assetToMeshAssetId(asset, context); const [{ isDivisible, name }, fundingRound, identifiers] = await Promise.all([ asset.details(), @@ -78,7 +76,7 @@ export async function prepareModifyAsset( transactions.push( checkTxType({ transaction: tx.asset.makeDivisible, - args: [rawTicker], + args: [rawAssetId], }) ); } @@ -95,7 +93,7 @@ export async function prepareModifyAsset( transactions.push( checkTxType({ transaction: tx.asset.renameAsset, - args: [rawTicker, nameBytes], + args: [rawAssetId, nameBytes], }) ); } @@ -112,7 +110,7 @@ export async function prepareModifyAsset( transactions.push( checkTxType({ transaction: tx.asset.setFundingRound, - args: [rawTicker, fundingBytes], + args: [rawAssetId, fundingBytes], }) ); } @@ -131,7 +129,7 @@ export async function prepareModifyAsset( checkTxType({ transaction: tx.asset.updateIdentifiers, args: [ - rawTicker, + rawAssetId, newIdentifiers.map(newIdentifier => securityIdentifierToAssetIdentifier(newIdentifier, context) ), @@ -140,7 +138,7 @@ export async function prepareModifyAsset( ); } - return { transactions, resolver: asset }; + return { transactions, resolver: await asAsset(asset.id, context) }; } /** @@ -148,7 +146,7 @@ export async function prepareModifyAsset( */ export function getAuthorization( this: Procedure, - { ticker, makeDivisible, name, fundingRound, identifiers }: Params + { asset, makeDivisible, name, fundingRound, identifiers }: Params ): ProcedureAuthorization { const transactions = []; @@ -172,7 +170,7 @@ export function getAuthorization( permissions: { transactions, portfolios: [], - assets: [new BaseAsset({ ticker }, this.context)], + assets: [asset], }, }; } diff --git a/src/api/procedures/modifyAssetTrustedClaimIssuers.ts b/src/api/procedures/modifyAssetTrustedClaimIssuers.ts index 2153b07220..6365e9689a 100644 --- a/src/api/procedures/modifyAssetTrustedClaimIssuers.ts +++ b/src/api/procedures/modifyAssetTrustedClaimIssuers.ts @@ -5,7 +5,7 @@ import { } from '@polkadot/types/lookup'; import { difference, intersection, isEqual, sortBy } from 'lodash'; -import { Context, FungibleAsset, PolymeshError, Procedure } from '~/internal'; +import { BaseAsset, Context, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, ModifyAssetTrustedClaimIssuersAddSetParams, @@ -20,9 +20,9 @@ import { } from '~/types/internal'; import { tuple } from '~/types/utils'; import { + assetToMeshAssetId, signerToString, stringToIdentityId, - stringToTicker, trustedClaimIssuerToTrustedIssuer, trustedIssuerToTrustedClaimIssuer, } from '~/utils/conversion'; @@ -31,7 +31,7 @@ import { asIdentity, assembleBatchTransactions, hasSameElements } from '~/utils/ /** * @hidden */ -export type Params = { ticker: string } & ( +export type Params = { asset: BaseAsset } & ( | (ModifyAssetTrustedClaimIssuersAddSetParams & { operation: TrustedClaimIssuerOperation.Add | TrustedClaimIssuerOperation.Set; }) @@ -101,9 +101,9 @@ export async function prepareModifyAssetTrustedClaimIssuers( }, context, } = this; - const { ticker } = args; + const { asset } = args; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); let claimIssuersToDelete: [PolymeshPrimitivesTicker, PolymeshPrimitivesIdentityId][] = []; let claimIssuersToAdd: [PolymeshPrimitivesTicker, PolymeshPrimitivesConditionTrustedIssuer][] = @@ -111,7 +111,7 @@ export async function prepareModifyAssetTrustedClaimIssuers( let inputDids: string[]; - const rawCurrentClaimIssuers = await query.complianceManager.trustedClaimIssuer(rawTicker); + const rawCurrentClaimIssuers = await query.complianceManager.trustedClaimIssuer(rawAssetId); const currentClaimIssuers = rawCurrentClaimIssuers.map(issuer => trustedIssuerToTrustedClaimIssuer(issuer, context) @@ -138,14 +138,14 @@ export async function prepareModifyAssetTrustedClaimIssuers( claimIssuersToDelete = currentClaimIssuers .filter(({ identity }) => inputDids.includes(signerToString(identity))) .map(({ identity }) => - tuple(rawTicker, stringToIdentityId(signerToString(identity), context)) + tuple(rawAssetId, stringToIdentityId(signerToString(identity), context)) ); } else { - ({ claimIssuersToAdd, inputDids } = convertArgsToRaw(args.claimIssuers, rawTicker, context)); + ({ claimIssuersToAdd, inputDids } = convertArgsToRaw(args.claimIssuers, rawAssetId, context)); } if (args.operation === TrustedClaimIssuerOperation.Set) { - claimIssuersToDelete = rawCurrentClaimIssuers.map(({ issuer }) => [rawTicker, issuer]); + claimIssuersToDelete = rawCurrentClaimIssuers.map(({ issuer }) => [rawAssetId, issuer]); if (areSameClaimIssuers(currentClaimIssuers, args.claimIssuers)) { throw new PolymeshError({ @@ -200,7 +200,7 @@ export async function prepareModifyAssetTrustedClaimIssuers( */ export function getAuthorization( this: Procedure, - { ticker, operation }: Params + { asset, operation }: Params ): ProcedureAuthorization { const transactions = []; if (operation !== TrustedClaimIssuerOperation.Add) { @@ -213,7 +213,7 @@ export function getAuthorization( return { permissions: { transactions, - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/modifyCaCheckpoint.ts b/src/api/procedures/modifyCaCheckpoint.ts index de42550c25..1269eec689 100644 --- a/src/api/procedures/modifyCaCheckpoint.ts +++ b/src/api/procedures/modifyCaCheckpoint.ts @@ -3,7 +3,6 @@ import { Checkpoint, CorporateActionBase, DividendDistribution, - FungibleAsset, PolymeshError, Procedure, } from '~/internal'; @@ -31,15 +30,12 @@ export async function prepareModifyCaCheckpoint( } = this; const { checkpoint, corporateAction } = args; - const { - id: localId, - asset: { ticker }, - } = corporateAction; + const { id: localId, asset } = corporateAction; let checkpointValue; if (checkpoint) { - checkpointValue = await getCheckpointValue(checkpoint, ticker, context); + checkpointValue = await getCheckpointValue(checkpoint, asset, context); await assertCaCheckpointValid(checkpointValue); } @@ -61,7 +57,7 @@ export async function prepareModifyCaCheckpoint( } } - const rawCaId = corporateActionIdentifierToCaId({ ticker, localId }, context); + const rawCaId = corporateActionIdentifierToCaId({ asset, localId }, context); const rawRecordDateSpec = optionize(checkpointToRecordDateSpec)(checkpointValue, context); return { @@ -76,18 +72,12 @@ export async function prepareModifyCaCheckpoint( */ export function getAuthorization( this: Procedure, - { - corporateAction: { - asset: { ticker }, - }, - }: Params + { corporateAction: { asset } }: Params ): ProcedureAuthorization { - const { context } = this; - return { permissions: { transactions: [TxTags.corporateAction.ChangeRecordDate], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/modifyCaDefaultConfig.ts b/src/api/procedures/modifyCaDefaultConfig.ts index 72dd630565..6da5e6c900 100644 --- a/src/api/procedures/modifyCaDefaultConfig.ts +++ b/src/api/procedures/modifyCaDefaultConfig.ts @@ -12,10 +12,10 @@ import { } from '~/types'; import { BatchTransactionSpec, ProcedureAuthorization } from '~/types/internal'; import { + assetToMeshAssetId, percentageToPermill, signerToString, stringToIdentityId, - stringToTicker, targetsToTargetIdentities, } from '~/utils/conversion'; import { assembleBatchTransactions, checkTxType, hasSameElements } from '~/utils/internal'; @@ -23,7 +23,7 @@ import { assembleBatchTransactions, checkTxType, hasSameElements } from '~/utils /** * @hidden */ -export type Params = { ticker: string } & ModifyCaDefaultConfigParams; +export type Params = { asset: FungibleAsset } & ModifyCaDefaultConfigParams; const areSameTargets = (targets: CorporateActionTargets, newTargets: InputTargets): boolean => { const { identities: newIdentities, treatment: newTreatment } = newTargets; @@ -52,7 +52,7 @@ export async function prepareModifyCaDefaultConfig( context, } = this; const { - ticker, + asset, targets: newTargets, defaultTaxWithholding: newDefaultTaxWithholding, taxWithholdings: newTaxWithholdings, @@ -74,9 +74,7 @@ export async function prepareModifyCaDefaultConfig( assertCaTaxWithholdingsValid(newTaxWithholdings, context); } - const rawTicker = stringToTicker(ticker, context); - - const asset = new FungibleAsset({ ticker }, context); + const rawAssetId = assetToMeshAssetId(asset, context); const { targets, defaultTaxWithholding, taxWithholdings } = await asset.corporateActions.getDefaultConfig(); @@ -94,7 +92,7 @@ export async function prepareModifyCaDefaultConfig( transactions.push( checkTxType({ transaction: tx.corporateAction.setDefaultTargets, - args: [rawTicker, targetsToTargetIdentities(newTargets, context)], + args: [rawAssetId, targetsToTargetIdentities(newTargets, context)], }) ); } @@ -110,7 +108,7 @@ export async function prepareModifyCaDefaultConfig( transactions.push( checkTxType({ transaction: tx.corporateAction.setDefaultWithholdingTax, - args: [rawTicker, percentageToPermill(newDefaultTaxWithholding, context)], + args: [rawAssetId, percentageToPermill(newDefaultTaxWithholding, context)], }) ); } @@ -133,7 +131,7 @@ export async function prepareModifyCaDefaultConfig( const transaction = tx.corporateAction.setDidWithholdingTax; const argsArray: [PolymeshPrimitivesTicker, PolymeshPrimitivesIdentityId, Permill][] = newTaxWithholdings.map(({ identity, percentage }) => [ - rawTicker, + rawAssetId, stringToIdentityId(signerToString(identity), context), percentageToPermill(percentage, context), ]); @@ -156,7 +154,7 @@ export async function prepareModifyCaDefaultConfig( */ export function getAuthorization( this: Procedure, - { ticker, targets, defaultTaxWithholding, taxWithholdings }: Params + { asset, targets, defaultTaxWithholding, taxWithholdings }: Params ): ProcedureAuthorization { const transactions = []; @@ -176,7 +174,7 @@ export function getAuthorization( permissions: { transactions, portfolios: [], - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], }, }; } diff --git a/src/api/procedures/modifyComplianceRequirement.ts b/src/api/procedures/modifyComplianceRequirement.ts index 2995c072b7..2be7ae0b58 100644 --- a/src/api/procedures/modifyComplianceRequirement.ts +++ b/src/api/procedures/modifyComplianceRequirement.ts @@ -2,17 +2,17 @@ import BigNumber from 'bignumber.js'; import { flatMap, remove } from 'lodash'; import { assertRequirementsNotTooComplex } from '~/api/procedures/utils'; -import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; +import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, ModifyComplianceRequirementParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { requirementToComplianceRequirement, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, requirementToComplianceRequirement } from '~/utils/conversion'; import { conditionsAreEqual, hasSameElements } from '~/utils/internal'; /** * @hidden */ export type Params = ModifyComplianceRequirementParams & { - ticker: string; + asset: BaseAsset; }; /** @@ -30,14 +30,12 @@ export async function prepareModifyComplianceRequirement( }, context, } = this; - const { ticker, id, conditions: newConditions } = args; + const { asset, id, conditions: newConditions } = args; - const rawTicker = stringToTicker(ticker, context); - - const token = new FungibleAsset({ ticker }, context); + const rawAssetId = assetToMeshAssetId(asset, context); const { requirements: currentRequirements, defaultTrustedClaimIssuers } = - await token.compliance.requirements.get(); + await asset.compliance.requirements.get(); const existingRequirements = remove(currentRequirements, ({ id: currentRequirementId }) => id.eq(currentRequirementId) @@ -74,7 +72,7 @@ export async function prepareModifyComplianceRequirement( return { transaction: tx.complianceManager.changeComplianceRequirement, - args: [rawTicker, rawComplianceRequirement], + args: [rawAssetId, rawComplianceRequirement], resolver: undefined, }; } @@ -84,12 +82,12 @@ export async function prepareModifyComplianceRequirement( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { return { permissions: { transactions: [TxTags.complianceManager.ChangeComplianceRequirement], - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/modifyCorporateActionsAgent.ts b/src/api/procedures/modifyCorporateActionsAgent.ts index d8dc6f112b..148a6594d9 100644 --- a/src/api/procedures/modifyCorporateActionsAgent.ts +++ b/src/api/procedures/modifyCorporateActionsAgent.ts @@ -18,7 +18,7 @@ import { /** * @hidden */ -export type Params = { ticker: string } & ModifyCorporateActionsAgentParams; +export type Params = { asset: FungibleAsset } & ModifyCorporateActionsAgentParams; /** * @hidden @@ -33,9 +33,7 @@ export async function prepareModifyCorporateActionsAgent( }, context, } = this; - const { ticker, target, requestExpiry } = args; - - const asset = new FungibleAsset({ ticker }, context); + const { asset, target, requestExpiry } = args; const [invalidDids, agents] = await Promise.all([ context.getInvalidDids([target]), @@ -64,7 +62,10 @@ export async function prepareModifyCorporateActionsAgent( const rawAuthorizationData = authorizationToAuthorizationData( { type: AuthorizationType.BecomeAgent, - value: new KnownPermissionGroup({ type: PermissionGroupType.PolymeshV1Caa, ticker }, context), + value: new KnownPermissionGroup( + { type: PermissionGroupType.PolymeshV1Caa, assetId: asset.id }, + context + ), }, context ); @@ -93,13 +94,13 @@ export async function prepareModifyCorporateActionsAgent( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { return { permissions: { transactions: [TxTags.identity.AddAuthorization], portfolios: [], - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], }, }; } diff --git a/src/api/procedures/modifyOfferingTimes.ts b/src/api/procedures/modifyOfferingTimes.ts index a4ed21916d..1d713461b8 100644 --- a/src/api/procedures/modifyOfferingTimes.ts +++ b/src/api/procedures/modifyOfferingTimes.ts @@ -10,7 +10,7 @@ import { TxTags, } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { bigNumberToU64, dateToMoment, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, bigNumberToU64, dateToMoment } from '~/utils/conversion'; /** * @hidden @@ -71,7 +71,7 @@ function validateInput( */ export type Params = ModifyOfferingTimesParams & { id: BigNumber; - ticker: string; + asset: FungibleAsset; }; /** @@ -89,9 +89,9 @@ export async function prepareModifyOfferingTimes( }, context, } = this; - const { ticker, id, start: newStart, end: newEnd } = args; + const { asset, id, start: newStart, end: newEnd } = args; - const offering = new Offering({ ticker, id }, context); + const offering = new Offering({ id, assetId: asset.id }, context); const { status: { sale, timing }, @@ -101,7 +101,8 @@ export async function prepareModifyOfferingTimes( validateInput(sale, newStart, start, newEnd, end, timing); - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); + const rawId = bigNumberToU64(id, context); const rawStart = newStart ? dateToMoment(newStart, context) : dateToMoment(start, context); let rawEnd: u64 | null; @@ -116,7 +117,7 @@ export async function prepareModifyOfferingTimes( return { transaction: txSto.modifyFundraiserWindow, - args: [rawTicker, rawId, rawStart, rawEnd], + args: [rawAssetId, rawId, rawStart, rawEnd], resolver: undefined, }; } @@ -126,13 +127,12 @@ export async function prepareModifyOfferingTimes( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { - const { context } = this; return { permissions: { transactions: [TxTags.sto.ModifyFundraiserWindow], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/moveFunds.ts b/src/api/procedures/moveFunds.ts index 1cc6488805..ffceaf3d27 100644 --- a/src/api/procedures/moveFunds.ts +++ b/src/api/procedures/moveFunds.ts @@ -21,7 +21,7 @@ import { portfolioIdToMeshPortfolioId, portfolioLikeToPortfolioId, } from '~/utils/conversion'; -import { asAsset, asNftId, asTicker } from '~/utils/internal'; +import { asAsset, asAssetId, asBaseAssetV2, asNftId } from '~/utils/internal'; /** * @hidden @@ -43,12 +43,12 @@ async function segregateItems( }> { const fungibleMovements: FungiblePortfolioMovement[] = []; const nftMovements: NonFungiblePortfolioMovement[] = []; - const tickers: string[] = []; + const assetIds: string[] = []; for (const item of items) { const { asset } = item; - const ticker = asTicker(asset); - tickers.push(ticker); + const assetId = await asAssetId(asset, context); + assetIds.push(assetId); const typedAsset = await asAsset(asset, context); if (isFungibleAsset(typedAsset)) { @@ -56,7 +56,7 @@ async function segregateItems( throw new PolymeshError({ code: ErrorCode.ValidationError, message: 'The key "amount" should be present in a fungible portfolio movement', - data: { ticker }, + data: { assetId }, }); } fungibleMovements.push(item as FungiblePortfolioMovement); @@ -65,14 +65,14 @@ async function segregateItems( throw new PolymeshError({ code: ErrorCode.ValidationError, message: 'The key "nfts" should be present in an NFT portfolio movement', - data: { ticker }, + data: { assetId }, }); } nftMovements.push(item as NonFungiblePortfolioMovement); } } - const hasDuplicates = uniq(tickers).length !== tickers.length; + const hasDuplicates = uniq(assetIds).length !== assetIds.length; if (hasDuplicates) { throw new PolymeshError({ @@ -148,21 +148,24 @@ export async function prepareMoveFunds( const [fungibleBalances, heldCollections] = await Promise.all([ fromPortfolio.getAssetBalances({ - assets: fungibleMovements.map(({ asset }) => asTicker(asset)), + assets: fungibleMovements.map(({ asset }) => asset), }), - fromPortfolio.getCollections({ collections: nftMovements.map(({ asset }) => asTicker(asset)) }), + fromPortfolio.getCollections({ collections: nftMovements.map(({ asset }) => asset) }), ]); const balanceExceeded: (PortfolioMovement & { free: BigNumber })[] = []; - fungibleBalances.forEach(({ asset: { ticker }, free }) => { - const transferItem = fungibleMovements.find( - ({ asset: itemAsset }) => asTicker(itemAsset) === ticker - )!; - - if (transferItem.amount.gt(free)) { - balanceExceeded.push({ ...transferItem, free }); + for (const fungibleBalance of fungibleBalances) { + const { + asset: { id }, + free, + } = fungibleBalance; + for (const fungibleMovement of fungibleMovements) { + const assetId = await asAssetId(fungibleMovement.asset, context); + if (assetId === id && fungibleMovement.amount.gt(free)) { + balanceExceeded.push({ ...fungibleMovement, free }); + } } - }); + } if (balanceExceeded.length) { throw new PolymeshError({ @@ -176,20 +179,20 @@ export async function prepareMoveFunds( const unavailableNfts: Record = {}; - nftMovements.forEach(movement => { - const ticker = asTicker(movement.asset); - const heldNfts = heldCollections.find(({ collection }) => collection.ticker === ticker); + for (const movement of nftMovements) { + const { id: assetId } = await asBaseAssetV2(movement.asset, context); + const heldNfts = heldCollections.find(({ collection }) => collection.id === assetId); movement.nfts.forEach(nftId => { const id = asNftId(nftId); const hasNft = heldNfts?.free.find(held => held.id.eq(id)); if (!hasNft) { - const entry = unavailableNfts[ticker] || []; + const entry = unavailableNfts[assetId] || []; entry.push(id); - unavailableNfts[ticker] = entry; + unavailableNfts[assetId] = entry; } }); - }); + } if (Object.keys(unavailableNfts).length > 0) { throw new PolymeshError({ @@ -202,11 +205,13 @@ export async function prepareMoveFunds( const rawFrom = portfolioIdToMeshPortfolioId(fromPortfolioId, context); const rawTo = portfolioIdToMeshPortfolioId(toPortfolioId, context); - const rawFungibleMovements = fungibleMovements.map(item => - fungibleMovementToPortfolioFund(item, context) + const rawFungibleMovements = await Promise.all( + fungibleMovements.map(item => fungibleMovementToPortfolioFund(item, context)) ); - const rawNftMovements = nftMovements.map(item => nftMovementToPortfolioFund(item, context)); + const rawNftMovements = await Promise.all( + nftMovements.map(item => nftMovementToPortfolioFund(item, context)) + ); return { transaction: portfolio.movePortfolioFunds, diff --git a/src/api/procedures/nftControllerTransfer.ts b/src/api/procedures/nftControllerTransfer.ts index c990e0bd0c..69af2b2eff 100644 --- a/src/api/procedures/nftControllerTransfer.ts +++ b/src/api/procedures/nftControllerTransfer.ts @@ -10,13 +10,13 @@ import { } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, nftToMeshNft, portfolioIdToMeshPortfolioId, portfolioIdToPortfolio, portfolioLikeToPortfolioId, portfolioToPortfolioId, portfolioToPortfolioKind, - stringToTicker, } from '~/utils/conversion'; import { asNftId } from '~/utils/internal'; @@ -28,7 +28,7 @@ export interface Storage { /** * @hidden */ -export type Params = { ticker: string } & NftControllerTransferParams; +export type Params = { collection: NftCollection } & NftControllerTransferParams; /** * @hidden @@ -40,15 +40,14 @@ export async function prepareNftControllerTransfer( const { context: { polymeshApi: { tx }, + isV6, }, storage: { did, destinationPortfolio }, context, } = this; - const { ticker, originPortfolio, nfts: givenNfts } = args; + const { collection, originPortfolio, nfts: givenNfts } = args; const nftIds = givenNfts.map(nft => asNftId(nft)); - const collection = new NftCollection({ ticker }, context); - const originPortfolioId = portfolioLikeToPortfolioId(originPortfolio); if (did === originPortfolioId.did) { @@ -79,17 +78,34 @@ export async function prepareNftControllerTransfer( throw new PolymeshError({ code: ErrorCode.InsufficientBalance, message: 'The origin Portfolio does not have all of the requested NFTs', - data: { unavailable: unavailableNfts.map(id => id.toString()) }, + data: { unavailable: unavailableNfts.map(nftId => nftId.toString()) }, }); } - const rawNfts = nftToMeshNft(ticker, nftIds, context); - + const rawNfts = nftToMeshNft(collection, nftIds, context); + + const rawAssetId = assetToMeshAssetId(collection, context); + + if (isV6) { + return { + transaction: tx.nft.controllerTransfer, + args: [ + rawAssetId, + rawNfts, + portfolioIdToMeshPortfolioId(originPortfolioId, context), + portfolioToPortfolioKind(destinationPortfolio, context), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ] as any, + resolver: undefined, + }; + } return { transaction: tx.nft.controllerTransfer, args: [ - stringToTicker(ticker, context), - rawNfts, + { + assetId: rawAssetId, + ids: rawNfts, + }, portfolioIdToMeshPortfolioId(originPortfolioId, context), portfolioToPortfolioKind(destinationPortfolio, context), ], @@ -102,21 +118,18 @@ export async function prepareNftControllerTransfer( */ export async function getAuthorization( this: Procedure, - { ticker }: Params + { collection }: Params ): Promise { const { - context, storage: { destinationPortfolio }, } = this; - const asset = new NftCollection({ ticker }, context); - const portfolioId = portfolioToPortfolioId(destinationPortfolio); return { roles: [{ type: RoleType.PortfolioCustodian, portfolioId }], permissions: { - assets: [asset], + assets: [collection], transactions: [TxTags.nft.ControllerTransfer], portfolios: [destinationPortfolio], }, diff --git a/src/api/procedures/payDividends.ts b/src/api/procedures/payDividends.ts index 6e17b147f3..956895d0be 100644 --- a/src/api/procedures/payDividends.ts +++ b/src/api/procedures/payDividends.ts @@ -36,7 +36,7 @@ export async function preparePayDividends( distribution: { targets: { identities, treatment }, id: localId, - asset: { ticker }, + asset, paymentDate, expiryDate, }, @@ -62,7 +62,7 @@ export async function preparePayDividends( }); } - const rawCaId = corporateActionIdentifierToCaId({ ticker, localId }, context); + const rawCaId = corporateActionIdentifierToCaId({ asset, localId }, context); const rawArgs = targets.map(target => tuple(rawCaId, stringToIdentityId(signerToString(target), context)) diff --git a/src/api/procedures/reclaimDividendDistributionFunds.ts b/src/api/procedures/reclaimDividendDistributionFunds.ts index 4cc968def8..7f989262f9 100644 --- a/src/api/procedures/reclaimDividendDistributionFunds.ts +++ b/src/api/procedures/reclaimDividendDistributionFunds.ts @@ -1,4 +1,4 @@ -import { DividendDistribution, FungibleAsset, PolymeshError, Procedure } from '~/internal'; +import { DividendDistribution, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, RoleType, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { corporateActionIdentifierToCaId, portfolioToPortfolioId } from '~/utils/conversion'; @@ -25,11 +25,7 @@ export async function prepareReclaimDividendDistributionFunds( } = this; const { - distribution: { - id: localId, - asset: { ticker }, - expiryDate, - }, + distribution: { id: localId, asset, expiryDate }, distribution, } = args; @@ -52,7 +48,7 @@ export async function prepareReclaimDividendDistributionFunds( }); } - const rawCaId = corporateActionIdentifierToCaId({ ticker, localId }, context); + const rawCaId = corporateActionIdentifierToCaId({ asset, localId }, context); return { transaction: tx.capitalDistribution.reclaim, @@ -66,20 +62,13 @@ export async function prepareReclaimDividendDistributionFunds( */ export async function getAuthorization( this: Procedure, - { - distribution: { - origin, - asset: { ticker }, - }, - }: Params + { distribution: { origin, asset } }: Params ): Promise { - const { context } = this; - return { roles: [{ type: RoleType.PortfolioCustodian, portfolioId: portfolioToPortfolioId(origin) }], permissions: { transactions: [TxTags.capitalDistribution.Reclaim], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [origin], }, }; diff --git a/src/api/procedures/redeemNft.ts b/src/api/procedures/redeemNft.ts index 737c0dd900..d08a7da480 100644 --- a/src/api/procedures/redeemNft.ts +++ b/src/api/procedures/redeemNft.ts @@ -9,7 +9,7 @@ import { } from '~/internal'; import { ErrorCode, RedeemNftParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { bigNumberToU64, portfolioToPortfolioKind, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, bigNumberToU64, portfolioToPortfolioKind } from '~/utils/conversion'; export interface Storage { fromPortfolio: DefaultPortfolio | NumberedPortfolio; @@ -18,7 +18,7 @@ export interface Storage { /** * @hidden */ -export type Params = { ticker: string; id: BigNumber } & RedeemNftParams; +export type Params = { collection: NftCollection; id: BigNumber } & RedeemNftParams; /** * @hidden @@ -35,11 +35,11 @@ export async function prepareRedeemNft( storage: { fromPortfolio }, } = this; - const { ticker, id } = args; + const { collection, id } = args; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(collection, context); - const [{ free }] = await fromPortfolio.getCollections({ collections: [ticker] }); + const [{ free }] = await fromPortfolio.getCollections({ collections: [collection.id] }); if (!free.find(heldNft => heldNft.id.eq(id))) { throw new PolymeshError({ @@ -55,7 +55,7 @@ export async function prepareRedeemNft( return { transaction: tx.nft.redeemNft, - args: [rawTicker, rawId, portfolioToPortfolioKind(fromPortfolio, context)], + args: [rawAssetId, rawId, portfolioToPortfolioKind(fromPortfolio, context)], resolver: undefined, }; } @@ -65,17 +65,16 @@ export async function prepareRedeemNft( */ export async function getAuthorization( this: Procedure, - { ticker }: Params + { collection }: Params ): Promise { const { - context, storage: { fromPortfolio }, } = this; return { permissions: { transactions: [TxTags.nft.RedeemNft], - assets: [new NftCollection({ ticker }, context)], + assets: [collection], portfolios: [fromPortfolio], }, }; diff --git a/src/api/procedures/redeemTokens.ts b/src/api/procedures/redeemTokens.ts index f66d72b353..ee1c78282b 100644 --- a/src/api/procedures/redeemTokens.ts +++ b/src/api/procedures/redeemTokens.ts @@ -9,7 +9,11 @@ import { } from '~/internal'; import { ErrorCode, RedeemTokensParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { bigNumberToBalance, portfolioToPortfolioKind, stringToTicker } from '~/utils/conversion'; +import { + assetToMeshAssetId, + bigNumberToBalance, + portfolioToPortfolioKind, +} from '~/utils/conversion'; export interface Storage { fromPortfolio: DefaultPortfolio | NumberedPortfolio; @@ -18,7 +22,7 @@ export interface Storage { /** * @hidden */ -export type Params = { ticker: string } & RedeemTokensParams; +export type Params = { asset: FungibleAsset } & RedeemTokensParams; /** * @hidden @@ -26,25 +30,22 @@ export type Params = { ticker: string } & RedeemTokensParams; export async function prepareRedeemTokens( this: Procedure, args: Params -): Promise< - | TransactionSpec> - | TransactionSpec> -> { +): Promise>> { const { context, context: { polymeshApi: { tx }, + isV6, }, storage: { fromPortfolio }, } = this; - const { ticker, amount, from } = args; + const { asset, amount } = args; - const asset = new FungibleAsset({ ticker }, context); - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const [[{ free }], { isDivisible }] = await Promise.all([ - fromPortfolio.getAssetBalances({ assets: [ticker] }), + fromPortfolio.getAssetBalances({ assets: [asset.id] }), asset.details(), ]); @@ -60,17 +61,14 @@ export async function prepareRedeemTokens( const rawAmount = bigNumberToBalance(amount, context, isDivisible); - if (from) { - return { - transaction: tx.asset.redeemFromPortfolio, - args: [rawTicker, rawAmount, portfolioToPortfolioKind(fromPortfolio, context)], - resolver: undefined, - }; + let transaction = tx.asset.redeem; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + transaction = (tx.asset as any).redeemFromPortfolio; } - return { - transaction: tx.asset.redeem, - args: [rawTicker, rawAmount], + transaction, + args: [rawAssetId, rawAmount, portfolioToPortfolioKind(fromPortfolio, context)], resolver: undefined, }; } @@ -80,17 +78,16 @@ export async function prepareRedeemTokens( */ export async function getAuthorization( this: Procedure, - { ticker, from }: Params + { asset, from }: Params ): Promise { const { - context, storage: { fromPortfolio }, } = this; return { permissions: { transactions: [from ? TxTags.asset.RedeemFromPortfolio : TxTags.asset.Redeem], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [fromPortfolio], }, }; diff --git a/src/api/procedures/registerMetadata.ts b/src/api/procedures/registerMetadata.ts index d952989662..b3d992bde4 100644 --- a/src/api/procedures/registerMetadata.ts +++ b/src/api/procedures/registerMetadata.ts @@ -1,14 +1,14 @@ import { ISubmittableResult } from '@polkadot/types/types'; -import { Context, FungibleAsset, MetadataEntry, PolymeshError, Procedure } from '~/internal'; +import { BaseAsset, Context, MetadataEntry, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, MetadataType, RegisterMetadataParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, metadataSpecToMeshMetadataSpec, metadataValueDetailToMeshMetadataValueDetail, metadataValueToMeshMetadataValue, stringToBytes, - stringToTicker, u32ToBigNumber, u64ToBigNumber, } from '~/utils/conversion'; @@ -18,20 +18,20 @@ import { filterEventRecords, optionize, requestMulti } from '~/utils/internal'; * @hidden */ export type Params = RegisterMetadataParams & { - ticker: string; + asset: BaseAsset; }; /** * @hidden */ export const createMetadataResolver = - (ticker: string, context: Context) => + (assetId: string, context: Context) => (receipt: ISubmittableResult): MetadataEntry => { const [{ data }] = filterEventRecords(receipt, 'asset', 'RegisterAssetMetadataLocalType'); const id = u64ToBigNumber(data[3]); - return new MetadataEntry({ id, ticker, type: MetadataType.Local }, context); + return new MetadataEntry({ id, assetId, type: MetadataType.Local }, context); }; /** @@ -58,9 +58,9 @@ export async function prepareRegisterMetadata( }, context, } = this; - const { name, ticker, specs } = params; + const { name, asset, specs } = params; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const metadataNameMaxLength = u32ToBigNumber(assetMetadataNameMaxLength); if (metadataNameMaxLength.lt(name.length)) { @@ -79,7 +79,7 @@ export async function prepareRegisterMetadata( [typeof assetMetadataGlobalNameToKey, typeof assetMetadataLocalNameToKey] >(context, [ [assetMetadataGlobalNameToKey, rawName], - [assetMetadataLocalNameToKey, [rawTicker, rawName]], + [assetMetadataLocalNameToKey, [rawAssetId, rawName]], ]); if (rawGlobalId.isSome || rawLocalId.isSome) { @@ -89,7 +89,7 @@ export async function prepareRegisterMetadata( }); } - const args = [rawTicker, rawName, metadataSpecToMeshMetadataSpec(specs, context)]; + const args = [rawAssetId, rawName, metadataSpecToMeshMetadataSpec(specs, context)]; if ('value' in params) { // eslint-disable-next-line @typescript-eslint/no-shadow, @typescript-eslint/no-unused-vars @@ -102,14 +102,14 @@ export async function prepareRegisterMetadata( metadataValueToMeshMetadataValue(value, context), optionize(metadataValueDetailToMeshMetadataValueDetail)(details, context), ], - resolver: createMetadataResolver(ticker, context), + resolver: createMetadataResolver(asset.id, context), }; } return { transaction: tx.asset.registerAssetMetadataLocalType, args, - resolver: createMetadataResolver(ticker, context), + resolver: createMetadataResolver(asset.id, context), }; } @@ -120,10 +120,6 @@ export function getAuthorization( this: Procedure, params: Params ): ProcedureAuthorization { - const { context } = this; - - const { ticker } = params; - const transactions = []; if ('value' in params) { @@ -135,7 +131,7 @@ export function getAuthorization( return { permissions: { transactions, - assets: [new FungibleAsset({ ticker }, context)], + assets: [params.asset], portfolios: [], }, }; diff --git a/src/api/procedures/removeAssetMediators.ts b/src/api/procedures/removeAssetMediators.ts index 3b53fa19fc..cd06b1db21 100644 --- a/src/api/procedures/removeAssetMediators.ts +++ b/src/api/procedures/removeAssetMediators.ts @@ -1,7 +1,7 @@ import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { AssetMediatorParams, ErrorCode, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { identitiesToBtreeSet, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, identitiesToBtreeSet } from '~/utils/conversion'; import { asIdentity } from '~/utils/internal'; /** * @hidden @@ -22,11 +22,7 @@ export async function prepareRemoveAssetMediators( context, } = this; - const { - asset, - asset: { ticker }, - mediators: mediatorInput, - } = args; + const { asset, mediators: mediatorInput } = args; const currentMediators = await asset.getRequiredMediators(); @@ -39,17 +35,17 @@ export async function prepareRemoveAssetMediators( throw new PolymeshError({ code: ErrorCode.ValidationError, message: 'One of the specified mediators to remove is not set', - data: { ticker, removeDid }, + data: { assetId: asset.id, removeDid }, }); } }); const rawNewMediators = identitiesToBtreeSet(removeMediators, context); - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); return { transaction: tx.asset.removeMandatoryMediators, - args: [rawTicker, rawNewMediators], + args: [rawAssetId, rawNewMediators], resolver: undefined, }; } diff --git a/src/api/procedures/removeAssetRequirement.ts b/src/api/procedures/removeAssetRequirement.ts index d9e2d51a83..a60da7a5e1 100644 --- a/src/api/procedures/removeAssetRequirement.ts +++ b/src/api/procedures/removeAssetRequirement.ts @@ -1,15 +1,15 @@ import BigNumber from 'bignumber.js'; -import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; +import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, RemoveAssetRequirementParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { bigNumberToU32, stringToTicker, u32ToBigNumber } from '~/utils/conversion'; +import { assetToMeshAssetId, bigNumberToU32, u32ToBigNumber } from '~/utils/conversion'; /** * @hidden */ export type Params = RemoveAssetRequirementParams & { - ticker: string; + asset: BaseAsset; }; /** @@ -27,13 +27,13 @@ export async function prepareRemoveAssetRequirement( }, context, } = this; - const { ticker, requirement } = args; + const { asset, requirement } = args; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const reqId = requirement instanceof BigNumber ? requirement : requirement.id; - const { requirements } = await query.complianceManager.assetCompliances(rawTicker); + const { requirements } = await query.complianceManager.assetCompliances(rawAssetId); if (!requirements.some(({ id: rawId }) => u32ToBigNumber(rawId).eq(reqId))) { throw new PolymeshError({ @@ -44,7 +44,7 @@ export async function prepareRemoveAssetRequirement( return { transaction: tx.complianceManager.removeComplianceRequirement, - args: [rawTicker, bigNumberToU32(reqId, context)], + args: [rawAssetId, bigNumberToU32(reqId, context)], resolver: undefined, }; } @@ -54,12 +54,12 @@ export async function prepareRemoveAssetRequirement( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { return { permissions: { transactions: [TxTags.complianceManager.RemoveComplianceRequirement], - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/removeAssetStat.ts b/src/api/procedures/removeAssetStat.ts index 3a882642fb..e995c0dbfa 100644 --- a/src/api/procedures/removeAssetStat.ts +++ b/src/api/procedures/removeAssetStat.ts @@ -3,7 +3,7 @@ import { PolymeshPrimitivesIdentityId, } from '@polkadot/types/lookup'; -import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; +import { PolymeshError, Procedure } from '~/internal'; import { ErrorCode, RemoveAssetStatParams, StatClaimIssuer, StatType, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { @@ -11,9 +11,12 @@ import { statisticsOpTypeToStatType, statisticStatTypesToBtreeStatType, statTypeToStatOpType, - stringToTickerKey, } from '~/utils/conversion'; -import { compareTransferRestrictionToStat, requestMulti } from '~/utils/internal'; +import { + compareTransferRestrictionToStat, + getAssetIdForStats, + requestMulti, +} from '~/utils/internal'; /** * @hidden @@ -31,14 +34,16 @@ export async function prepareRemoveAssetStat( }, context, } = this; - const { ticker, type } = args; - const tickerKey = stringToTickerKey(ticker, context); + const { asset, type } = args; + const rawAssetId = getAssetIdForStats(asset, context); const [currentStats, { requirements }] = await requestMulti< [typeof statisticsQuery.activeAssetStats, typeof statisticsQuery.assetTransferCompliances] >(context, [ - [statisticsQuery.activeAssetStats, tickerKey], - [statisticsQuery.assetTransferCompliances, tickerKey], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [statisticsQuery.activeAssetStats, rawAssetId as any], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [statisticsQuery.assetTransferCompliances, rawAssetId as any], ]); let claimIssuer: StatClaimIssuer; @@ -79,7 +84,8 @@ export async function prepareRemoveAssetStat( return { transaction: statistics.setActiveAssetStats, - args: [tickerKey, newStats], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + args: [rawAssetId as any, newStats], resolver: undefined, }; } @@ -89,10 +95,9 @@ export async function prepareRemoveAssetStat( */ export function getAuthorization( this: Procedure, - { ticker }: RemoveAssetStatParams + { asset }: RemoveAssetStatParams ): ProcedureAuthorization { const transactions = [TxTags.statistics.SetActiveAssetStats]; - const asset = new FungibleAsset({ ticker }, this.context); return { permissions: { transactions, diff --git a/src/api/procedures/removeCheckpointSchedule.ts b/src/api/procedures/removeCheckpointSchedule.ts index 7adac1fcd0..c792e793e1 100644 --- a/src/api/procedures/removeCheckpointSchedule.ts +++ b/src/api/procedures/removeCheckpointSchedule.ts @@ -3,13 +3,13 @@ import BigNumber from 'bignumber.js'; import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, RemoveCheckpointScheduleParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { bigNumberToU64, stringToTicker, u32ToBigNumber } from '~/utils/conversion'; +import { assetToMeshAssetId, bigNumberToU64, u32ToBigNumber } from '~/utils/conversion'; /** * @hidden */ export type Params = RemoveCheckpointScheduleParams & { - ticker: string; + asset: FungibleAsset; }; /** @@ -25,25 +25,23 @@ export async function prepareRemoveCheckpointSchedule( polymeshApi: { tx, query }, }, } = this; - const { ticker, schedule } = args; + const { asset, schedule } = args; - const id = schedule instanceof BigNumber ? schedule : schedule.id; - const rawTicker = stringToTicker(ticker, context); - const rawId = bigNumberToU64(id, context); + const scheduleId = schedule instanceof BigNumber ? schedule : schedule.id; + const rawAssetId = assetToMeshAssetId(asset, context); - const rawSchedule = await query.checkpoint.scheduledCheckpoints(rawTicker, rawId); - const exists = rawSchedule.isSome; + const rawScheduleId = bigNumberToU64(scheduleId, context); - if (!exists) { + const rawSchedule = await query.checkpoint.scheduledCheckpoints(rawAssetId, rawScheduleId); + + if (!rawSchedule.isSome) { throw new PolymeshError({ code: ErrorCode.DataUnavailable, message: 'Schedule was not found. It may have been removed or expired', }); } - const rawScheduleId = bigNumberToU64(id, context); - - const scheduleRefCount = await query.checkpoint.scheduleRefCount(rawTicker, rawScheduleId); + const scheduleRefCount = await query.checkpoint.scheduleRefCount(rawAssetId, rawScheduleId); const referenceCount = u32ToBigNumber(scheduleRefCount); if (referenceCount.gt(0)) { @@ -58,7 +56,7 @@ export async function prepareRemoveCheckpointSchedule( return { transaction: tx.checkpoint.removeSchedule, - args: [rawTicker, rawScheduleId], + args: [rawAssetId, rawScheduleId], resolver: undefined, }; } @@ -68,13 +66,12 @@ export async function prepareRemoveCheckpointSchedule( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { - const { context } = this; return { permissions: { transactions: [TxTags.checkpoint.RemoveSchedule], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/removeCorporateAction.ts b/src/api/procedures/removeCorporateAction.ts index ca3626ae40..862fdd8bb0 100644 --- a/src/api/procedures/removeCorporateAction.ts +++ b/src/api/procedures/removeCorporateAction.ts @@ -13,17 +13,17 @@ import { import { ErrorCode, RemoveCorporateActionParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, bigNumberToU32, corporateActionIdentifierToCaId, momentToDate, - stringToTicker, } from '~/utils/conversion'; /** * @hidden */ export type Params = RemoveCorporateActionParams & { - ticker: string; + asset: FungibleAsset; }; const caNotExistsMessage = "The Corporate Action doesn't exist"; @@ -34,7 +34,7 @@ const caNotExistsMessage = "The Corporate Action doesn't exist"; const assertCaIsRemovable = async ( rawCaId: PalletCorporateActionsCaId, query: QueryableStorage<'promise'>, - ticker: string, + asset: FungibleAsset, context: Context, corporateAction: CorporateActionBase | BigNumber ): Promise => { @@ -50,7 +50,7 @@ const assertCaIsRemovable = async ( if (corporateAction instanceof BigNumber) { const CA = await query.corporateAction.corporateActions( - stringToTicker(ticker, context), + assetToMeshAssetId(asset, context), bigNumberToU32(corporateAction, context) ); @@ -85,14 +85,14 @@ export async function prepareRemoveCorporateAction( polymeshApi: { tx, query }, }, } = this; - const { ticker, corporateAction } = args; + const { asset, corporateAction } = args; const localId = corporateAction instanceof CorporateActionBase ? corporateAction.id : corporateAction; - const rawCaId = corporateActionIdentifierToCaId({ ticker, localId }, context); + const rawCaId = corporateActionIdentifierToCaId({ asset, localId }, context); if (corporateAction instanceof DividendDistribution || corporateAction instanceof BigNumber) { - await assertCaIsRemovable(rawCaId, query, ticker, context, corporateAction); + await assertCaIsRemovable(rawCaId, query, asset, context, corporateAction); } else { const exists = await corporateAction.exists(); @@ -116,12 +116,12 @@ export async function prepareRemoveCorporateAction( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { return { permissions: { transactions: [TxTags.corporateAction.RemoveCa], - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/removeExternalAgent.ts b/src/api/procedures/removeExternalAgent.ts index 5e091fc3ea..adb544862e 100644 --- a/src/api/procedures/removeExternalAgent.ts +++ b/src/api/procedures/removeExternalAgent.ts @@ -1,29 +1,22 @@ import { isFullGroupType } from '~/api/procedures/utils'; -import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; +import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, RemoveExternalAgentParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { stringToIdentityId, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, stringToIdentityId } from '~/utils/conversion'; import { getIdentity } from '~/utils/internal'; /** * @hidden */ export type Params = RemoveExternalAgentParams & { - ticker: string; + asset: BaseAsset; }; -/** - * @hidden - */ -export interface Storage { - asset: FungibleAsset; -} - /** * @hidden */ export async function prepareRemoveExternalAgent( - this: Procedure, + this: Procedure, args: Params ): Promise>> { const { @@ -33,10 +26,9 @@ export async function prepareRemoveExternalAgent( }, }, context, - storage: { asset }, } = this; - const { ticker, target } = args; + const { asset, target } = args; const [currentAgents, targetIdentity] = await Promise.all([ asset.permissions.getAgents(), @@ -63,12 +55,13 @@ export async function prepareRemoveExternalAgent( } } - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); + const rawAgent = stringToIdentityId(targetIdentity.did, context); return { transaction: externalAgents.removeAgent, - args: [rawTicker, rawAgent], + args: [rawAssetId, rawAgent], resolver: undefined, }; } @@ -76,10 +69,10 @@ export async function prepareRemoveExternalAgent( /** * @hidden */ -export function getAuthorization(this: Procedure): ProcedureAuthorization { - const { - storage: { asset }, - } = this; +export function getAuthorization( + this: Procedure, + { asset }: Params +): ProcedureAuthorization { return { permissions: { transactions: [TxTags.externalAgents.RemoveAgent], @@ -92,19 +85,5 @@ export function getAuthorization(this: Procedure): Proced /** * @hidden */ -export function prepareStorage( - this: Procedure, - { ticker }: Params -): Storage { - const { context } = this; - - return { - asset: new FungibleAsset({ ticker }, context), - }; -} - -/** - * @hidden - */ -export const removeExternalAgent = (): Procedure => - new Procedure(prepareRemoveExternalAgent, getAuthorization, prepareStorage); +export const removeExternalAgent = (): Procedure => + new Procedure(prepareRemoveExternalAgent, getAuthorization); diff --git a/src/api/procedures/removeLocalMetadata.ts b/src/api/procedures/removeLocalMetadata.ts index f86c04e208..5c88ae7cdd 100644 --- a/src/api/procedures/removeLocalMetadata.ts +++ b/src/api/procedures/removeLocalMetadata.ts @@ -1,7 +1,11 @@ -import { FungibleAsset, MetadataEntry, PolymeshError, Procedure } from '~/internal'; +import { MetadataEntry, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, MetadataType, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { bigNumberToU64, meshMetadataKeyToMetadataKey, stringToTicker } from '~/utils/conversion'; +import { + assetToMeshAssetId, + bigNumberToU64, + meshMetadataKeyToMetadataKey, +} from '~/utils/conversion'; /** * @hidden @@ -21,20 +25,15 @@ export async function prepareRemoveLocalMetadata( context: { polymeshApi: { tx, - query: { - nft: { collectionKeys, collectionTicker }, - }, + query: { nft }, }, + isV6, }, context, } = this; const { - metadataEntry: { - id, - type, - asset: { ticker }, - }, + metadataEntry: { id, type, asset }, metadataEntry, } = params; @@ -45,18 +44,23 @@ export async function prepareRemoveLocalMetadata( }); } - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const rawKeyId = bigNumberToU64(id, context); + let collectionAssetStorage = nft.collectionAsset; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + collectionAssetStorage = (nft as any).collectionTicker; + } const [collectionKey, { canModify, reason }] = await Promise.all([ - collectionTicker(rawTicker), + collectionAssetStorage(rawAssetId), metadataEntry.isModifiable(), ]); if (!collectionKey.isZero()) { - const rawKeys = await collectionKeys(collectionKey); + const rawKeys = await nft.collectionKeys(collectionKey); const isRequired = [...rawKeys].some(value => - meshMetadataKeyToMetadataKey(value, ticker).id.eq(id) + meshMetadataKeyToMetadataKey(value, asset, context).id.eq(id) ); if (isRequired) { @@ -73,7 +77,7 @@ export async function prepareRemoveLocalMetadata( return { transaction: tx.asset.removeLocalMetadataKey, - args: [rawTicker, rawKeyId], + args: [rawAssetId, rawKeyId], resolver: undefined, }; } @@ -85,18 +89,14 @@ export function getAuthorization( this: Procedure, params: Params ): ProcedureAuthorization { - const { context } = this; - const { - metadataEntry: { - asset: { ticker }, - }, + metadataEntry: { asset }, } = params; return { permissions: { transactions: [TxTags.asset.RemoveLocalMetadataKey], - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/reserveTicker.ts b/src/api/procedures/reserveTicker.ts index 70a0f997ee..23e52b2b10 100644 --- a/src/api/procedures/reserveTicker.ts +++ b/src/api/procedures/reserveTicker.ts @@ -25,10 +25,11 @@ export const createTickerReservationResolver = export async function prepareReserveTicker( this: Procedure, args: ReserveTickerParams -): Promise>> { +): Promise>> { const { context: { polymeshApi: { tx }, + isV6, }, context, } = this; @@ -71,8 +72,14 @@ export async function prepareReserveTicker( } } + let transaction = tx.asset.registerUniqueTicker; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + transaction = (tx.asset as any).registerTicker; + } + return { - transaction: tx.asset.registerTicker, + transaction, args: [rawTicker], resolver: createTickerReservationResolver(context), }; diff --git a/src/api/procedures/setAssetDocuments.ts b/src/api/procedures/setAssetDocuments.ts index bdd80246e3..2beacaae2e 100644 --- a/src/api/procedures/setAssetDocuments.ts +++ b/src/api/procedures/setAssetDocuments.ts @@ -1,13 +1,13 @@ import { u32 } from '@polkadot/types'; import BigNumber from 'bignumber.js'; -import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; +import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { AssetDocument, ErrorCode, SetAssetDocumentsParams, TxTags } from '~/types'; import { BatchTransactionSpec, ProcedureAuthorization } from '~/types/internal'; import { assetDocumentToDocument, + assetToMeshAssetId, documentToAssetDocument, - stringToTicker, } from '~/utils/conversion'; import { checkTxType, hasSameElements } from '~/utils/internal'; @@ -20,7 +20,7 @@ export interface Storage { * @hidden */ export type Params = SetAssetDocumentsParams & { - ticker: string; + asset: BaseAsset; }; /** @@ -37,7 +37,7 @@ export async function prepareSetAssetDocuments( context, storage: { currentDocIds, currentDocs }, } = this; - const { ticker, documents } = args; + const { asset, documents } = args; if (hasSameElements(currentDocs, documents)) { throw new PolymeshError({ @@ -48,7 +48,7 @@ export async function prepareSetAssetDocuments( const rawDocuments = documents.map(doc => assetDocumentToDocument(doc, context)); - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const transactions = []; @@ -57,7 +57,7 @@ export async function prepareSetAssetDocuments( checkTxType({ transaction: tx.asset.removeDocuments, feeMultiplier: new BigNumber(currentDocIds.length), - args: [currentDocIds, rawTicker], + args: [currentDocIds, rawAssetId], }) ); } @@ -67,7 +67,7 @@ export async function prepareSetAssetDocuments( checkTxType({ transaction: tx.asset.addDocuments, feeMultiplier: new BigNumber(rawDocuments.length), - args: [rawDocuments, rawTicker], + args: [rawDocuments, rawAssetId], }) ); } @@ -80,7 +80,7 @@ export async function prepareSetAssetDocuments( */ export function getAuthorization( this: Procedure, - { ticker, documents }: Params + { asset, documents }: Params ): ProcedureAuthorization { const { storage: { currentDocIds }, @@ -97,7 +97,7 @@ export function getAuthorization( return { permissions: { - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], transactions, portfolios: [], }, @@ -109,7 +109,7 @@ export function getAuthorization( */ export async function prepareStorage( this: Procedure, - { ticker }: Params + { asset }: Params ): Promise { const { context: { @@ -118,17 +118,17 @@ export async function prepareStorage( context, } = this; - const currentDocEntries = await query.asset.assetDocuments.entries( - stringToTicker(ticker, context) - ); + const rawAssetId = assetToMeshAssetId(asset, context); + + const currentDocEntries = await query.asset.assetDocuments.entries(rawAssetId); const currentDocIds: u32[] = []; const currentDocs: AssetDocument[] = []; currentDocEntries.forEach(([key, doc]) => { - const [, id] = key.args; + const [, docId] = key.args; if (doc.isSome) { - currentDocIds.push(id); + currentDocIds.push(docId); currentDocs.push(documentToAssetDocument(doc.unwrap())); } }); diff --git a/src/api/procedures/setAssetRequirements.ts b/src/api/procedures/setAssetRequirements.ts index bdadb83bb0..1484555108 100644 --- a/src/api/procedures/setAssetRequirements.ts +++ b/src/api/procedures/setAssetRequirements.ts @@ -2,17 +2,17 @@ import BigNumber from 'bignumber.js'; import { flatten, map } from 'lodash'; import { assertRequirementsNotTooComplex } from '~/api/procedures/utils'; -import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; +import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { Condition, ErrorCode, InputCondition, SetAssetRequirementsParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { requirementToComplianceRequirement, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, requirementToComplianceRequirement } from '~/utils/conversion'; import { conditionsAreEqual, hasSameElements } from '~/utils/internal'; /** * @hidden */ export type Params = SetAssetRequirementsParams & { - ticker: string; + asset: BaseAsset; }; /** @@ -31,11 +31,9 @@ export async function prepareSetAssetRequirements( }, context, } = this; - const { ticker, requirements } = args; + const { asset, requirements } = args; - const rawTicker = stringToTicker(ticker, context); - - const asset = new FungibleAsset({ ticker }, context); + const rawAssetId = assetToMeshAssetId(asset, context); const { requirements: currentRequirements, defaultTrustedClaimIssuers } = await asset.compliance.requirements.get(); @@ -65,7 +63,7 @@ export async function prepareSetAssetRequirements( if (!requirements.length) { return { transaction: tx.complianceManager.resetAssetCompliance, - args: [rawTicker], + args: [rawAssetId], resolver: undefined, }; } @@ -78,7 +76,7 @@ export async function prepareSetAssetRequirements( return { transaction: tx.complianceManager.replaceAssetCompliance, - args: [rawTicker, rawAssetCompliance], + args: [rawAssetId, rawAssetCompliance], resolver: undefined, }; } @@ -88,14 +86,14 @@ export async function prepareSetAssetRequirements( */ export function getAuthorization( this: Procedure, - { ticker, requirements }: Params + { asset, requirements }: Params ): ProcedureAuthorization { return { permissions: { transactions: requirements.length ? [TxTags.complianceManager.ReplaceAssetCompliance] : [TxTags.complianceManager.ResetAssetCompliance], - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/setGroupPermissions.ts b/src/api/procedures/setGroupPermissions.ts index 0869865cd7..c33d8fa34f 100644 --- a/src/api/procedures/setGroupPermissions.ts +++ b/src/api/procedures/setGroupPermissions.ts @@ -4,9 +4,9 @@ import { CustomPermissionGroup, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, SetGroupPermissionsParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, bigNumberToU32, permissionsLikeToPermissions, - stringToTicker, transactionPermissionsToExtrinsicPermissions, } from '~/utils/conversion'; @@ -43,11 +43,8 @@ export async function prepareSetGroupPermissions( }); } - const { - asset: { ticker }, - id, - } = group; - const rawTicker = stringToTicker(ticker, context); + const { asset, id } = group; + const rawAssetId = assetToMeshAssetId(asset, context); const rawAgId = bigNumberToU32(id, context); const rawExtrinsicPermissions = transactionPermissionsToExtrinsicPermissions( transactions, @@ -56,7 +53,7 @@ export async function prepareSetGroupPermissions( return { transaction: externalAgents.setGroupPermissions, - args: [rawTicker, rawAgId, rawExtrinsicPermissions], + args: [rawAssetId, rawAgId, rawExtrinsicPermissions], resolver: undefined, }; } diff --git a/src/api/procedures/setMetadata.ts b/src/api/procedures/setMetadata.ts index 39fdfe71c9..b8cd9c97fa 100644 --- a/src/api/procedures/setMetadata.ts +++ b/src/api/procedures/setMetadata.ts @@ -1,11 +1,11 @@ -import { FungibleAsset, MetadataEntry, PolymeshError, Procedure } from '~/internal'; +import { MetadataEntry, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, MetadataLockStatus, SetMetadataParams, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { + assetToMeshAssetId, metadataToMeshMetadataKey, metadataValueDetailToMeshMetadataValueDetail, metadataValueToMeshMetadataValue, - stringToTicker, } from '~/utils/conversion'; import { optionize } from '~/utils/internal'; @@ -34,16 +34,12 @@ export async function prepareSetMetadata( } = this; const { - metadataEntry: { - id, - type, - asset: { ticker }, - }, + metadataEntry: { id, type, asset }, metadataEntry, ...rest } = params; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const rawMetadataKey = metadataToMeshMetadataKey(type, id, context); const currentValue = await metadataEntry.value(); @@ -96,8 +92,8 @@ export async function prepareSetMetadata( return { transaction, - args: [rawTicker, rawMetadataKey, ...args], - resolver: new MetadataEntry({ id, type, ticker }, context), + args: [rawAssetId, rawMetadataKey, ...args], + resolver: new MetadataEntry({ id, type, assetId: asset.id }, context), }; } @@ -108,12 +104,8 @@ export function getAuthorization( this: Procedure, params: Params ): ProcedureAuthorization { - const { context } = this; - const { - metadataEntry: { - asset: { ticker }, - }, + metadataEntry: { asset }, } = params; const transactions = []; @@ -127,7 +119,7 @@ export function getAuthorization( return { permissions: { transactions, - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/setPermissionGroup.ts b/src/api/procedures/setPermissionGroup.ts index cf1d7ab77b..7070ada2a9 100644 --- a/src/api/procedures/setPermissionGroup.ts +++ b/src/api/procedures/setPermissionGroup.ts @@ -20,10 +20,10 @@ import { import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; import { isEntity } from '~/utils'; import { + assetToMeshAssetId, permissionGroupIdentifierToAgentGroup, permissionsLikeToPermissions, stringToIdentityId, - stringToTicker, transactionPermissionsToExtrinsicPermissions, } from '~/utils/conversion'; import { asBaseAsset } from '~/utils/internal'; @@ -69,7 +69,6 @@ export async function prepareSetPermissionGroup( } = this; const { identity, group } = args; - const { ticker } = asset; const [currentGroup, currentAgents] = await Promise.all([ identity.assetPermissions.getGroup({ asset }), @@ -96,7 +95,7 @@ export async function prepareSetPermissionGroup( }); } - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const rawIdentityId = stringToIdentityId(identity.did, context); let existingGroup: KnownPermissionGroup | CustomPermissionGroup | undefined; @@ -119,7 +118,7 @@ export async function prepareSetPermissionGroup( return { transaction: externalAgents.createAndChangeCustomGroup, args: [ - rawTicker, + rawAssetId, transactionPermissionsToExtrinsicPermissions(transactions, context), rawIdentityId, ], @@ -140,7 +139,7 @@ export async function prepareSetPermissionGroup( return { transaction: externalAgents.changeGroup, args: [ - rawTicker, + rawAssetId, rawIdentityId, permissionGroupIdentifierToAgentGroup( existingGroup instanceof CustomPermissionGroup diff --git a/src/api/procedures/setTransferRestrictions.ts b/src/api/procedures/setTransferRestrictions.ts index f32e10b0ae..636b90f08c 100644 --- a/src/api/procedures/setTransferRestrictions.ts +++ b/src/api/procedures/setTransferRestrictions.ts @@ -8,7 +8,7 @@ import BigNumber from 'bignumber.js'; import { entries, flatten, forEach } from 'lodash'; import { SetTransferRestrictionsParams } from '~/api/entities/Asset/Fungible/TransferRestrictions/TransferRestrictionBase'; -import { Context, FungibleAsset, Identity, PolymeshError, Procedure } from '~/internal'; +import { Context, Identity, PolymeshError, Procedure } from '~/internal'; import { ClaimCountRestrictionValue, ClaimCountTransferRestriction, @@ -32,7 +32,6 @@ import { identitiesToBtreeSet, identityIdToString, meshClaimTypeToClaimType, - stringToTickerKey, toExemptKey, transferRestrictionToPolymeshTransferCondition, transferRestrictionTypeToStatOpType, @@ -43,6 +42,7 @@ import { assertStatIsSet, checkTxType, compareTransferRestrictionToInput, + getAssetIdForStats, neededStatTypeForRestrictionInput, requestMulti, } from '~/utils/internal'; @@ -256,9 +256,9 @@ export async function prepareSetTransferRestrictions( restrictions: { length: newRestrictionAmount }, restrictions, type, - ticker, + asset, } = args; - const tickerKey = stringToTickerKey(ticker, context); + const rawAssetId = getAssetIdForStats(asset, context); assertInputValid(restrictions, type); @@ -288,10 +288,10 @@ export async function prepareSetTransferRestrictions( transactions.push( checkTxType({ - transaction: statistics.setAssetTransferCompliance, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + transaction: statistics.setAssetTransferCompliance as any, args: [ - tickerKey, - // if we do not add the current restrictions (filteredRestrictions), then they will be removed + rawAssetId, // if we do not add the current restrictions (filteredRestrictions), then they will be removed complianceConditionsToBtreeSet([...filteredRestrictions, ...conditions], context), ], }) @@ -303,8 +303,7 @@ export async function prepareSetTransferRestrictions( return; } const rawClaimType = claimType === 'None' ? undefined : (claimType as ClaimType); - const exemptKey = toExemptKey(tickerKey, op, rawClaimType); - + const exemptKey = toExemptKey(context, rawAssetId, op, rawClaimType); const exemptedBtreeSet = identitiesToBtreeSet(exempted, context); const rawExempt = booleanToBool(exempt, context); @@ -329,7 +328,7 @@ export async function prepareSetTransferRestrictions( */ export function getAuthorization( this: Procedure, - { ticker, restrictions }: SetTransferRestrictionsParams + { asset, restrictions }: SetTransferRestrictionsParams ): ProcedureAuthorization { const transactions: TxTag[] = [TxTags.statistics.SetAssetTransferCompliance]; @@ -340,7 +339,7 @@ export function getAuthorization( return { permissions: { - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], transactions, portfolios: [], }, @@ -362,14 +361,17 @@ export async function prepareStorage( }, }, } = this; - const { ticker, type } = args; - const tickerKey = stringToTickerKey(ticker, context); + const { asset, type } = args; + + const rawAssetId = getAssetIdForStats(asset, context); const [currentStats, { requirements: currentRestrictions }] = await requestMulti< [typeof statistics.activeAssetStats, typeof statistics.assetTransferCompliances] >(context, [ - [statistics.activeAssetStats, tickerKey], - [statistics.assetTransferCompliances, tickerKey], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [statistics.activeAssetStats, rawAssetId as any], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [statistics.assetTransferCompliances, rawAssetId as any], ]); args.restrictions.forEach(restriction => { @@ -431,11 +433,9 @@ export async function prepareStorage( claimTypes.forEach(claimType => { exemptionFetchers.push( - statistics.transferConditionExemptEntities.entries({ - asset: tickerKey, - op, - claimType, - }) + statistics.transferConditionExemptEntities.entries( + toExemptKey(context, rawAssetId, op, claimType) + ) ); }); const rawCurrentExemptions = flatten(await Promise.all(exemptionFetchers)); diff --git a/src/api/procedures/setVenueFiltering.ts b/src/api/procedures/setVenueFiltering.ts index e66c57d7a8..0a3120b6e5 100644 --- a/src/api/procedures/setVenueFiltering.ts +++ b/src/api/procedures/setVenueFiltering.ts @@ -1,14 +1,13 @@ -import { FungibleAsset, Procedure } from '~/internal'; +import { BaseAsset, Procedure } from '~/internal'; import { SetVenueFilteringParams, TxTags } from '~/types'; import { BatchTransactionSpec, ProcedureAuthorization } from '~/types/internal'; -import { bigNumberToU64, booleanToBool, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, bigNumberToU64, booleanToBool } from '~/utils/conversion'; import { checkTxType } from '~/utils/internal'; - /** * @hidden */ export type Params = { - ticker: string; + asset: BaseAsset; } & SetVenueFilteringParams; /** @@ -25,17 +24,17 @@ export async function prepareVenueFiltering( context, } = this; - const { ticker, enabled, allowedVenues, disallowedVenues } = args; - const rawTicker = stringToTicker(ticker, context); + const { asset, enabled, allowedVenues, disallowedVenues } = args; + const rawAssetId = assetToMeshAssetId(asset, context); const transactions = []; - const isEnabled = await query.settlement.venueFiltering(rawTicker); + const isEnabled = await query.settlement.venueFiltering(rawAssetId); if (enabled !== undefined && isEnabled.valueOf() !== enabled) { transactions.push( checkTxType({ transaction: tx.settlement.setVenueFiltering, - args: [rawTicker, booleanToBool(enabled, context)], + args: [rawAssetId, booleanToBool(enabled, context)], }) ); } @@ -44,7 +43,7 @@ export async function prepareVenueFiltering( transactions.push( checkTxType({ transaction: tx.settlement.allowVenues, - args: [rawTicker, allowedVenues.map(venue => bigNumberToU64(venue, context))], + args: [rawAssetId, allowedVenues.map(venue => bigNumberToU64(venue, context))], }) ); } @@ -53,7 +52,7 @@ export async function prepareVenueFiltering( transactions.push( checkTxType({ transaction: tx.settlement.disallowVenues, - args: [rawTicker, disallowedVenues.map(venue => bigNumberToU64(venue, context))], + args: [rawAssetId, disallowedVenues.map(venue => bigNumberToU64(venue, context))], }) ); } @@ -66,10 +65,8 @@ export async function prepareVenueFiltering( */ export function getAuthorization( this: Procedure, - { ticker, enabled, disallowedVenues, allowedVenues }: Params + { asset, enabled, disallowedVenues, allowedVenues }: Params ): ProcedureAuthorization { - const { context } = this; - const transactions = []; if (enabled !== undefined) { @@ -87,7 +84,7 @@ export function getAuthorization( return { permissions: { transactions, - assets: [new FungibleAsset({ ticker }, context)], + assets: [asset], }, }; } diff --git a/src/api/procedures/toggleFreezeOffering.ts b/src/api/procedures/toggleFreezeOffering.ts index 3c093898de..9fa455f143 100644 --- a/src/api/procedures/toggleFreezeOffering.ts +++ b/src/api/procedures/toggleFreezeOffering.ts @@ -3,12 +3,12 @@ import BigNumber from 'bignumber.js'; import { FungibleAsset, Offering, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, OfferingSaleStatus, OfferingTimingStatus, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { bigNumberToU64, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, bigNumberToU64 } from '~/utils/conversion'; export interface ToggleFreezeOfferingParams { id: BigNumber; freeze: boolean; - ticker: string; + asset: FungibleAsset; } /** @@ -29,12 +29,12 @@ export async function prepareToggleFreezeOffering( }, context, } = this; - const { ticker, id, freeze } = args; + const { asset, id, freeze } = args; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); const rawId = bigNumberToU64(id, context); - const offering = new Offering({ ticker, id }, context); + const offering = new Offering({ id, assetId: asset.id }, context); const { status: { timing, sale }, @@ -57,7 +57,7 @@ export async function prepareToggleFreezeOffering( return { transaction: txSto.freezeFundraiser, - args: [rawTicker, rawId], + args: [rawAssetId, rawId], resolver: offering, }; } @@ -78,7 +78,7 @@ export async function prepareToggleFreezeOffering( return { transaction: txSto.unfreezeFundraiser, - args: [rawTicker, rawId], + args: [rawAssetId, rawId], resolver: offering, }; } @@ -88,12 +88,12 @@ export async function prepareToggleFreezeOffering( */ export function getAuthorization( this: Procedure, - { ticker, freeze }: ToggleFreezeOfferingParams + { asset, freeze }: ToggleFreezeOfferingParams ): ProcedureAuthorization { return { permissions: { transactions: [freeze ? TxTags.sto.FreezeFundraiser : TxTags.sto.UnfreezeFundraiser], - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/toggleFreezeTransfers.ts b/src/api/procedures/toggleFreezeTransfers.ts index 2c1639fd6f..6d524ca0e2 100644 --- a/src/api/procedures/toggleFreezeTransfers.ts +++ b/src/api/procedures/toggleFreezeTransfers.ts @@ -1,7 +1,7 @@ import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId } from '~/utils/conversion'; export interface ToggleFreezeTransfersParams { freeze: boolean; @@ -11,7 +11,7 @@ export interface ToggleFreezeTransfersParams { * @hidden */ export type Params = ToggleFreezeTransfersParams & { - ticker: string; + asset: BaseAsset; }; /** @@ -29,13 +29,12 @@ export async function prepareToggleFreezeTransfers( }, context, } = this; - const { ticker, freeze } = args; - const rawTicker = stringToTicker(ticker, context); + const { asset: assetEntity, freeze } = args; - const assetEntity = new BaseAsset({ ticker }, context); + const rawAssetId = assetToMeshAssetId(assetEntity, context); - const isFrozen = await assetEntity.isFrozen(); + const isFrozen = await args.asset.isFrozen(); if (freeze) { if (isFrozen) { @@ -47,7 +46,7 @@ export async function prepareToggleFreezeTransfers( return { transaction: asset.freeze, - args: [rawTicker], + args: [rawAssetId], resolver: undefined, }; } @@ -60,7 +59,7 @@ export async function prepareToggleFreezeTransfers( return { transaction: asset.unfreeze, - args: [rawTicker], + args: [rawAssetId], resolver: undefined, }; } @@ -70,12 +69,12 @@ export async function prepareToggleFreezeTransfers( */ export function getAuthorization( this: Procedure, - { ticker, freeze }: Params + { asset, freeze }: Params ): ProcedureAuthorization { return { permissions: { transactions: [freeze ? TxTags.asset.Freeze : TxTags.asset.Unfreeze], - assets: [new BaseAsset({ ticker }, this.context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/togglePauseRequirements.ts b/src/api/procedures/togglePauseRequirements.ts index e30e6d155d..e5dbb0c5ee 100644 --- a/src/api/procedures/togglePauseRequirements.ts +++ b/src/api/procedures/togglePauseRequirements.ts @@ -1,7 +1,7 @@ -import { FungibleAsset, PolymeshError, Procedure } from '~/internal'; +import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { boolToBoolean, stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId, boolToBoolean } from '~/utils/conversion'; export interface TogglePauseRequirementsParams { pause: boolean; @@ -11,7 +11,7 @@ export interface TogglePauseRequirementsParams { * @hidden */ export type Params = TogglePauseRequirementsParams & { - ticker: string; + asset: BaseAsset; }; /** @@ -30,11 +30,11 @@ export async function prepareTogglePauseRequirements( }, context, } = this; - const { ticker, pause } = args; + const { asset, pause } = args; - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); - const { paused } = await query.complianceManager.assetCompliances(rawTicker); + const { paused } = await query.complianceManager.assetCompliances(rawAssetId); if (pause === boolToBoolean(paused)) { throw new PolymeshError({ @@ -47,7 +47,7 @@ export async function prepareTogglePauseRequirements( transaction: pause ? tx.complianceManager.pauseAssetCompliance : tx.complianceManager.resumeAssetCompliance, - args: [rawTicker], + args: [rawAssetId], resolver: undefined, }; } @@ -57,7 +57,7 @@ export async function prepareTogglePauseRequirements( */ export function getAuthorization( this: Procedure, - { ticker, pause }: Params + { asset, pause }: Params ): ProcedureAuthorization { return { permissions: { @@ -66,7 +66,7 @@ export function getAuthorization( ? TxTags.complianceManager.PauseAssetCompliance : TxTags.complianceManager.ResumeAssetCompliance, ], - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], portfolios: [], }, }; diff --git a/src/api/procedures/toggleTickerPreApproval.ts b/src/api/procedures/toggleTickerPreApproval.ts index 1615dae452..017e830cb8 100644 --- a/src/api/procedures/toggleTickerPreApproval.ts +++ b/src/api/procedures/toggleTickerPreApproval.ts @@ -1,13 +1,13 @@ -import { PolymeshError, Procedure } from '~/internal'; +import { BaseAsset, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, TxTags } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId } from '~/utils/conversion'; /** * @hidden */ export interface Params { - ticker: string; + asset: BaseAsset; preApprove: boolean; } @@ -21,13 +21,14 @@ export async function prepareToggleTickerPreApproval( const { context: { polymeshApi: { tx }, + isV6, }, context, } = this; - const { ticker, preApprove } = args; + const { asset, preApprove } = args; const identity = await context.getSigningIdentity(); - const isPreApproved = await identity.isAssetPreApproved(ticker); + const isPreApproved = await identity.isAssetPreApproved(asset); if (isPreApproved === preApprove) { const message = isPreApproved @@ -36,17 +37,24 @@ export async function prepareToggleTickerPreApproval( throw new PolymeshError({ code: ErrorCode.NoDataChange, message, - data: { identity: identity.did, ticker }, + data: { identity: identity.did, assetId: asset.id }, }); } - const rawTicker = stringToTicker(ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); - const transaction = preApprove ? tx.asset.preApproveTicker : tx.asset.removeTickerPreApproval; + let transaction = preApprove ? tx.asset.preApproveAsset : tx.asset.removeAssetPreApproval; + if (isV6) { + transaction = preApprove + ? // eslint-disable-next-line @typescript-eslint/no-explicit-any + (tx.asset as any).preApproveTicker + : // eslint-disable-next-line @typescript-eslint/no-explicit-any + (tx.asset as any).removeTickerPreApproval; + } return { transaction, - args: [rawTicker], + args: [rawAssetId], resolver: undefined, }; } diff --git a/src/api/procedures/transferAssetOwnership.ts b/src/api/procedures/transferAssetOwnership.ts index 52e6e54ca0..f8234daeba 100644 --- a/src/api/procedures/transferAssetOwnership.ts +++ b/src/api/procedures/transferAssetOwnership.ts @@ -1,5 +1,5 @@ import { createAuthorizationResolver } from '~/api/procedures/utils'; -import { AuthorizationRequest, FungibleAsset, Procedure } from '~/internal'; +import { AuthorizationRequest, BaseAsset, Procedure } from '~/internal'; import { Authorization, AuthorizationType, @@ -19,7 +19,7 @@ import { asIdentity, assertNoPendingAuthorizationExists, optionize } from '~/uti /** * @hidden */ -export type Params = { ticker: string } & TransferAssetOwnershipParams; +export type Params = { asset: BaseAsset } & TransferAssetOwnershipParams; /** * @hidden @@ -34,7 +34,7 @@ export async function prepareTransferAssetOwnership( }, context, } = this; - const { ticker, target, expiry = null } = args; + const { asset, target, expiry = null } = args; const issuer = await context.getSigningIdentity(); const targetIdentity = asIdentity(target, context); @@ -50,7 +50,7 @@ export async function prepareTransferAssetOwnership( const authorization: Authorization = { type: AuthorizationType.TransferAssetOwnership, - value: ticker, + value: asset.id, }; assertNoPendingAuthorizationExists({ @@ -75,11 +75,11 @@ export async function prepareTransferAssetOwnership( */ export function getAuthorization( this: Procedure, - { ticker }: Params + { asset }: Params ): ProcedureAuthorization { return { permissions: { - assets: [new FungibleAsset({ ticker }, this.context)], + assets: [asset], transactions: [TxTags.identity.AddAuthorization], portfolios: [], }, diff --git a/src/api/procedures/types.ts b/src/api/procedures/types.ts index 98e4d3a676..f71789ed29 100644 --- a/src/api/procedures/types.ts +++ b/src/api/procedures/types.ts @@ -399,7 +399,7 @@ export type GetTransferRestrictionReturnType = ActiveTransferRestrictions< : ClaimPercentageTransferRestriction >; -export type RemoveAssetStatParams = { ticker: string } & ( +export type RemoveAssetStatParams = { asset: FungibleAsset } & ( | RemoveCountStatParams | RemoveBalanceStatParams | RemoveScopedCountParams @@ -422,7 +422,7 @@ export type AddClaimPercentageStatParams = StatClaimIssuer & { type: StatType.ScopedBalance; }; -export type AddAssetStatParams = { ticker: string } & ( +export type AddAssetStatParams = { asset: FungibleAsset } & ( | AddCountStatParams | AddPercentageStatParams | AddClaimCountStatParams diff --git a/src/api/procedures/utils.ts b/src/api/procedures/utils.ts index e21a0da215..8d966c457e 100644 --- a/src/api/procedures/utils.ts +++ b/src/api/procedures/utils.ts @@ -42,7 +42,7 @@ import { TransactionPermissions, TxTag, } from '~/types'; -import { tickerToString, u32ToBigNumber, u64ToBigNumber } from '~/utils/conversion'; +import { meshAssetToAssetId, u32ToBigNumber, u64ToBigNumber } from '~/utils/conversion'; import { asIdentity, filterEventRecords } from '~/utils/internal'; /** @@ -414,7 +414,7 @@ export async function assertTransferAssetOwnershipAuthorizationValid( data: GenericAuthorizationData, context: Context ): Promise { - const asset = new FungibleAsset({ ticker: data.value }, context); + const asset = new FungibleAsset({ assetId: data.value }, context); const exists = await asset.exists(); if (!exists) throw new PolymeshError({ @@ -660,7 +660,7 @@ export async function getGroupFromPermissions( * @hidden */ export async function assertGroupDoesNotExist( - asset: FungibleAsset, + asset: BaseAsset, permissions: TransactionPermissions | null ): Promise { const matchingGroup = await getGroupFromPermissions(asset, permissions); @@ -704,7 +704,7 @@ export const createCreateGroupResolver = const [{ data }] = filterEventRecords(receipt, 'externalAgents', 'GroupCreated'); return new CustomPermissionGroup( - { id: u32ToBigNumber(data[2]), ticker: tickerToString(data[1]) }, + { id: u32ToBigNumber(data[2]), assetId: meshAssetToAssetId(data[1], context) }, context ); }; diff --git a/src/api/procedures/waivePermissions.ts b/src/api/procedures/waivePermissions.ts index b59108de24..c45fe5c284 100644 --- a/src/api/procedures/waivePermissions.ts +++ b/src/api/procedures/waivePermissions.ts @@ -1,7 +1,7 @@ import { BaseAsset, Identity, PolymeshError, Procedure } from '~/internal'; import { ErrorCode, RoleType, TxTags, WaivePermissionsParams } from '~/types'; import { ExtrinsicParams, ProcedureAuthorization, TransactionSpec } from '~/types/internal'; -import { stringToTicker } from '~/utils/conversion'; +import { assetToMeshAssetId } from '~/utils/conversion'; import { asBaseAsset } from '~/utils/internal'; /** @@ -45,11 +45,11 @@ export async function prepareWaivePermissions( }); } - const rawTicker = stringToTicker(asset.ticker, context); + const rawAssetId = assetToMeshAssetId(asset, context); return { transaction: tx.externalAgents.abdicate, - args: [rawTicker], + args: [rawAssetId], resolver: undefined, }; } diff --git a/src/base/Context.ts b/src/base/Context.ts index 06ec16a258..ea07ada722 100644 --- a/src/base/Context.ts +++ b/src/base/Context.ts @@ -6,6 +6,7 @@ import { QueryOptions, } from '@apollo/client/core'; import { ApiPromise } from '@polkadot/api'; +import { UnsubscribePromise } from '@polkadot/api/types'; import { getTypeDef, Option } from '@polkadot/types'; import { AccountInfo, Header } from '@polkadot/types/interfaces'; import { @@ -57,6 +58,7 @@ import { Ensured } from '~/types/utils'; import { DEFAULT_GQL_PAGE_SIZE, MAX_CONCURRENT_REQUESTS, MAX_PAGE_SIZE } from '~/utils/constants'; import { accountIdToString, + assetToMeshAssetId, balanceToBigNumber, bigNumberToU32, boolToBoolean, @@ -64,6 +66,7 @@ import { corporateActionIdentifierToCaId, distributionToDividendDistributionParams, identityIdToString, + meshAssetToAssetId, meshClaimToClaim, meshCorporateActionToCorporateActionParams, middlewareClaimToClaimData, @@ -74,9 +77,7 @@ import { stringToAccountId, stringToHash, stringToIdentityId, - stringToTicker, textToString, - tickerToString, txTagToProtocolOp, u16ToBigNumber, u32ToBigNumber, @@ -126,6 +127,10 @@ export class Context { private _isArchiveNodeResult?: boolean; + public isV6 = false; + + private unsubChainVersion: UnsubscribePromise; + /** * @hidden */ @@ -135,6 +140,13 @@ export class Context { this._middlewareApi = middlewareApiV2; this.polymeshApi = polymeshApi; this.ss58Format = ss58Format; + + this.unsubChainVersion = polymeshApi.query.system.lastRuntimeUpgrade(upgrade => { + if (upgrade.isSome) { + const { specVersion } = upgrade.unwrap(); + this.isV6 = specVersion.toNumber() < 7000000; + } + }); } /** @@ -749,14 +761,14 @@ export class Context { const distributionsMultiParams: PalletCorporateActionsCaId[] = []; const corporateActionParams: CorporateActionParams[] = []; const corporateActionIds: BigNumber[] = []; - const tickers: string[] = []; + const assetIds: string[] = []; const assetChunks = chunk(assets, MAX_CONCURRENT_REQUESTS); await P.each(assetChunks, async assetChunk => { const corporateActions = await Promise.all( - assetChunk.map(({ ticker }) => - corporateActionQuery.corporateActions.entries(stringToTicker(ticker, this)) + assetChunk.map(assetValue => + corporateActionQuery.corporateActions.entries(assetToMeshAssetId(assetValue, this)) ) ); const eligibleCas = flatten(corporateActions).filter(([, action]) => { @@ -769,18 +781,21 @@ export class Context { eligibleCas, async ([ { - args: [rawTicker, rawId], + args: [rawAssetId, rawId], }, corporateAction, ]) => { const localId = u32ToBigNumber(rawId); - const ticker = tickerToString(rawTicker); - const caId = corporateActionIdentifierToCaId({ ticker, localId }, this); + const assetId = meshAssetToAssetId(rawAssetId, this); + const caId = corporateActionIdentifierToCaId( + { asset: new FungibleAsset({ assetId }, this), localId }, + this + ); const details = await corporateActionQuery.details(caId); const action = corporateAction.unwrap(); return { - ticker, + assetId, localId, caId, corporateAction: meshCorporateActionToCorporateActionParams(action, details, this), @@ -788,8 +803,8 @@ export class Context { } ); - corporateActionData.forEach(({ ticker, localId, caId, corporateAction }) => { - tickers.push(ticker); + corporateActionData.forEach(({ assetId, localId, caId, corporateAction }) => { + assetIds.push(assetId); corporateActionIds.push(localId); distributionsMultiParams.push(caId); corporateActionParams.push(corporateAction); @@ -822,7 +837,7 @@ export class Context { result.push({ distribution: new DividendDistribution( { - ticker: tickers[index], + assetId: assetIds[index], id: corporateActionIds[index], ...corporateActionParams[index], ...distributionToDividendDistributionParams(dist, this), @@ -899,7 +914,7 @@ export class Context { issuedAt: momentToDate(issuanceDate), lastUpdatedAt: momentToDate(lastUpdateDate), expiry, - claim: meshClaimToClaim(claim), + claim: meshClaimToClaim(claim, this), }); } }); @@ -1158,6 +1173,9 @@ export class Context { this.isDisconnected = true; + const unsub = await this.unsubChainVersion; + unsub(); + if (middlewareApi) { middlewareApi.stop(); } diff --git a/src/middleware/typesV1.ts b/src/middleware/typesV1.ts index 40e0191326..41c343e20d 100644 --- a/src/middleware/typesV1.ts +++ b/src/middleware/typesV1.ts @@ -2,7 +2,11 @@ import { Scalars } from '~/middleware/types'; export enum ClaimScopeTypeEnum { Identity = 'Identity', + /** + * @deprecated in favour of 'Asset' + */ Ticker = 'Ticker', + Asset = 'Asset', Custom = 'Custom', Asset = 'Asset', } diff --git a/src/polkadot/polymesh/types.ts b/src/polkadot/polymesh/types.ts index 4e3d6c141f..3182910b95 100644 --- a/src/polkadot/polymesh/types.ts +++ b/src/polkadot/polymesh/types.ts @@ -1815,11 +1815,11 @@ export interface ScheduleSpec extends Struct { export interface Scope extends Enum { readonly isIdentity: boolean; readonly asIdentity: IdentityId; - readonly isTicker: boolean; - readonly asTicker: Ticker; + readonly isAsset: boolean; + readonly asAsset: Ticker; readonly isCustom: boolean; readonly asCustom: Bytes; - readonly type: 'Identity' | 'Ticker' | 'Custom'; + readonly type: 'Identity' | 'Asset' | 'Custom'; } /** @name SecondaryKey */ diff --git a/src/types/internal.ts b/src/types/internal.ts index 23f7fd2c3a..33752bedc5 100644 --- a/src/types/internal.ts +++ b/src/types/internal.ts @@ -17,12 +17,14 @@ import { PolymeshPrimitivesTicker, } from '@polkadot/types/lookup'; import { ISubmittableResult, Signer as PolkadotSigner } from '@polkadot/types/types'; +import { U8aFixed } from '@polkadot/types-codec'; import BigNumber from 'bignumber.js'; import { Identity, Procedure } from '~/internal'; import { CallIdEnum, ModuleIdEnum } from '~/middleware/types'; import { ClaimType, + FungibleAsset, InputStatClaim, KnownAssetType, KnownNftType, @@ -272,8 +274,8 @@ export interface ExtrinsicIdentifier { } export interface CorporateActionIdentifier { - ticker: string; localId: BigNumber; + asset: FungibleAsset; } /** @@ -337,17 +339,27 @@ export interface TickerKey { Ticker: PolymeshPrimitivesTicker; } +export interface AssetIdKey { + AssetId: U8aFixed; +} + /** * Infer Procedure parameters parameters from a Procedure function */ export type ProcedureParams unknown> = ReturnType extends Procedure ? Params : never; -export interface ExemptKey { - asset: TickerKey; +export type ExemptKey = { op: PolymeshPrimitivesStatisticsStatOpType; claimType?: ClaimType; -} +} & ( + | { + asset: TickerKey; + } + | { + assetId: U8aFixed; + } +); export type StatClaimInputType = Omit; @@ -355,3 +367,11 @@ export interface StatClaimIssuer { issuer: Identity; claimType: StatClaimType; } + +export type MeshTickerOrAssetId = + | { + ticker: PolymeshPrimitivesTicker; + } + | { + assetId: U8aFixed; + }; diff --git a/src/utils/conversion.ts b/src/utils/conversion.ts index 5508187baa..7dd451e4d3 100644 --- a/src/utils/conversion.ts +++ b/src/utils/conversion.ts @@ -110,6 +110,7 @@ import { assertCaTaxWithholdingsValid, UnreachableCaseError } from '~/api/proced import { countryCodeToMeshCountryCode, meshCountryCodeToCountryCode } from '~/generated/utils'; import { Account, + BaseAsset, Checkpoint, CheckpointSchedule, Context, @@ -253,12 +254,14 @@ import { VenueType, } from '~/types'; import { + AssetIdKey, CorporateActionIdentifier, ExemptKey, ExtrinsicIdentifier, InstructionStatus, InternalAssetType, InternalNftType, + MeshTickerOrAssetId, PalletPermissions, PermissionGroupIdentifier, PermissionsEnum, @@ -279,16 +282,15 @@ import { } from '~/utils/constants'; import { asAccount, + asBaseAssetV2, asDid, asNftId, assertAddressValid, assertIsInteger, assertIsPositive, assertTickerValid, - asTicker, conditionsAreEqual, createClaim, - getAssetIdForMiddleware, getAssetIdFromMiddleware, isModuleOrTagMatch, optionize, @@ -350,6 +352,13 @@ export function stringToTicker(ticker: string, context: Context): PolymeshPrimit return context.createType('PolymeshPrimitivesTicker', padString(ticker, MAX_TICKER_LENGTH)); } +/** + * @hidden + */ +export function stringToAssetId(assetId: string, context: Context): U8aFixed { + return context.createType('U8aFixed', assetId); +} + /** * @hidden */ @@ -357,6 +366,13 @@ export function stringToTickerKey(ticker: string, context: Context): TickerKey { return { Ticker: stringToTicker(ticker, context) }; } +/** + * @hidden + */ +export function stringToAssetIdKey(assetId: string, context: Context): AssetIdKey { + return { AssetId: stringToAssetId(assetId, context) }; +} + /** * @hidden */ @@ -364,6 +380,77 @@ export function tickerToString(ticker: PolymeshPrimitivesTicker): string { return removePadding(u8aToString(ticker)); } +/** + * @hidden + */ +export function assetIdToString(assetId: U8aFixed): string { + return assetId.toString(); +} + +/** + * @hidden + */ +export function meshAssetToAssetId( + value: PolymeshPrimitivesTicker | U8aFixed, + context: Context +): string { + const { isV6 } = context; + if (isV6) { + return removePadding(u8aToString(value)); + } + return value.toString(); +} + +/** + * @hidden + */ +export function assetToMeshAssetIdKey(value: string, context: Context): TickerKey | AssetIdKey { + const { isV6 } = context; + if (isV6) { + return stringToTickerKey(value, context); + } + return stringToAssetIdKey(value, context); +} + +/** + * @hidden + */ +export function assetToMeshAssetId({ id }: BaseAsset, context: Context): U8aFixed { + const { isV6 } = context; + + if (isV6) { + return stringToTicker(id, context); + } + + return stringToAssetId(id, context); +} + +/** + * @hidden + */ +export function assetToMeshAssetInputParam( + { id }: BaseAsset, + context: Context +): + | { + ticker: U8aFixed; + } + | { + assetId: U8aFixed; + } { + const { isV6 } = context; + + if (isV6) { + return { + ticker: stringToTicker(id, context), + }; + } + + return { + assetId: stringToAssetId(id, context), + }; +} + /** * @hidden */ @@ -1054,8 +1141,8 @@ export function permissionsToMeshPermissions( let asset: PermissionsEnum = '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)); + assetValues.sort(({ id: assetIdA }, { id: assetIdB }) => assetIdA.localeCompare(assetIdB)); + const tickers = assetValues.map(assetValue => assetToMeshAssetId(assetValue, context)); if (type === PermissionType.Include) { asset = { These: tickers, @@ -1176,7 +1263,7 @@ export function meshPermissionsToPermissions( if (assetsPermissions) { assets = { values: [...assetsPermissions].map( - ticker => new FungibleAsset({ ticker: tickerToString(ticker) }, context) + assetId => new FungibleAsset({ assetId: meshAssetToAssetId(assetId, context) }, context) ), // eslint-disable-next-line @typescript-eslint/no-non-null-assertion type: assetsType!, @@ -1304,7 +1391,7 @@ export function authorizationToAuthorizationData( } else if (type === AuthorizationType.RotatePrimaryKeyToSecondary) { value = permissionsToMeshPermissions(auth.value, context); } else if (type === AuthorizationType.BecomeAgent) { - const ticker = stringToTicker(auth.value.asset.ticker, context); + const ticker = stringToTicker(auth.value.asset.id, context); if (auth.value instanceof CustomPermissionGroup) { const { id } = auth.value; value = [ticker, permissionGroupIdentifierToAgentGroup({ custom: id }, context)]; @@ -1383,7 +1470,7 @@ export function balanceToBigNumber(balance: Balance): BigNumber { */ function assemblePermissionGroup( permissionGroupIdentifier: PermissionGroupIdentifier, - ticker: string, + assetId: string, context: Context ): KnownPermissionGroup | CustomPermissionGroup { switch (permissionGroupIdentifier) { @@ -1391,11 +1478,11 @@ function assemblePermissionGroup( case PermissionGroupType.Full: case PermissionGroupType.PolymeshV1Caa: case PermissionGroupType.PolymeshV1Pia: { - return new KnownPermissionGroup({ type: permissionGroupIdentifier, ticker }, context); + return new KnownPermissionGroup({ type: permissionGroupIdentifier, assetId }, context); } default: { const { custom: id } = permissionGroupIdentifier; - return new CustomPermissionGroup({ id, ticker }, context); + return new CustomPermissionGroup({ id, assetId }, context); } } } @@ -1404,11 +1491,11 @@ function assemblePermissionGroup( */ export function agentGroupToPermissionGroup( agentGroup: PolymeshPrimitivesAgentAgentGroup, - ticker: string, + assetId: string, context: Context ): KnownPermissionGroup | CustomPermissionGroup { const permissionGroupIdentifier = agentGroupToPermissionGroupIdentifier(agentGroup); - return assemblePermissionGroup(permissionGroupIdentifier, ticker, context); + return assemblePermissionGroup(permissionGroupIdentifier, assetId, context); } /** @@ -1453,7 +1540,7 @@ export function authorizationDataToAuthorization( if (auth.isTransferAssetOwnership) { return { type: AuthorizationType.TransferAssetOwnership, - value: tickerToString(auth.asTransferAssetOwnership), + value: meshAssetToAssetId(auth.asTransferAssetOwnership, context), }; } @@ -1485,11 +1572,11 @@ export function authorizationDataToAuthorization( } if (auth.isBecomeAgent) { - const [ticker, agentGroup] = auth.asBecomeAgent; + const [assetId, agentGroup] = auth.asBecomeAgent; return { type: AuthorizationType.BecomeAgent, - value: agentGroupToPermissionGroup(agentGroup, tickerToString(ticker), context), + value: agentGroupToPermissionGroup(agentGroup, meshAssetToAssetId(assetId, context), context), }; } @@ -2122,10 +2209,15 @@ export function scopeToMeshScope( ): PolymeshPrimitivesIdentityClaimScope { const { type, value } = scope; + let scopeType: string = type; + const { isV6 } = context; + let scopeValue: PolymeshPrimitivesTicker | PolymeshPrimitivesIdentityId | string; switch (type) { case ScopeType.Ticker: - scopeValue = stringToTicker(value, context); + case ScopeType.Asset: + scopeValue = isV6 ? stringToTicker(value, context) : stringToAssetId(value, context); + scopeType = ScopeType.Asset; break; case ScopeType.Identity: scopeValue = stringToIdentityId(value, context); @@ -2135,20 +2227,35 @@ export function scopeToMeshScope( break; } - return context.createType('Scope', { - [type]: scopeValue, + return context.createType('PolymeshPrimitivesIdentityClaimScope', { + [scopeType]: scopeValue, }); } /** * @hidden */ -export function meshScopeToScope(scope: PolymeshPrimitivesIdentityClaimScope): Scope { - if (scope.isTicker) { - return { - type: ScopeType.Ticker, - value: tickerToString(scope.asTicker), - }; +export function meshScopeToScope( + scope: PolymeshPrimitivesIdentityClaimScope, + context: Context +): Scope { + const { isV6 } = context; + if (isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if ((scope as any).isTicker) { + return { + type: ScopeType.Asset, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + value: tickerToString((scope as any).asTicker), + }; + } + } else { + if (scope.isAsset) { + return { + type: ScopeType.Asset, + value: assetIdToString(scope.asAsset), + }; + } } if (scope.isIdentity) { @@ -2240,27 +2347,16 @@ export function middlewareScopeToScope(scope: MiddlewareScope): Scope { /** * @hidden */ -export async function scopeToMiddlewareScope( - scope: Scope, - context: Context -): Promise { +export function scopeToMiddlewareScope(scope: Scope): MiddlewareScope { const { type, value } = scope; switch (type) { - case ScopeType.Ticker: { - const middlewareAssetId = await getAssetIdForMiddleware(value, context); - if (value === middlewareAssetId) { - // old SQ is used - return { - type: ClaimScopeTypeEnum.Ticker, - value, - }; - } + case ScopeType.Ticker: + case ScopeType.Asset: return { type: ClaimScopeTypeEnum.Asset, - value: middlewareAssetId, + value, }; - } case ScopeType.Identity: case ScopeType.Custom: return { type: ClaimScopeTypeEnum[scope.type], value }; @@ -2287,42 +2383,45 @@ export function middlewareEventDetailsToEventIdentifier( /** * @hidden */ -export function meshClaimToClaim(claim: PolymeshPrimitivesIdentityClaimClaim): Claim { +export function meshClaimToClaim( + claim: PolymeshPrimitivesIdentityClaimClaim, + context: Context +): Claim { const type = claim.type; if (type === 'Jurisdiction') { const [code, scope] = claim.asJurisdiction; return { type: ClaimType.Jurisdiction, code: meshCountryCodeToCountryCode(code), - scope: meshScopeToScope(scope), + scope: meshScopeToScope(scope, context), }; } if (type === 'Accredited') { return { type: ClaimType.Accredited, - scope: meshScopeToScope(claim.asAccredited), + scope: meshScopeToScope(claim.asAccredited, context), }; } if (type === 'Affiliate') { return { type: ClaimType.Affiliate, - scope: meshScopeToScope(claim.asAffiliate), + scope: meshScopeToScope(claim.asAffiliate, context), }; } if (type === 'BuyLockup') { return { type: ClaimType.BuyLockup, - scope: meshScopeToScope(claim.asBuyLockup), + scope: meshScopeToScope(claim.asBuyLockup, context), }; } if (type === 'SellLockup') { return { type: ClaimType.SellLockup, - scope: meshScopeToScope(claim.asSellLockup), + scope: meshScopeToScope(claim.asSellLockup, context), }; } @@ -2336,14 +2435,14 @@ export function meshClaimToClaim(claim: PolymeshPrimitivesIdentityClaimClaim): C if (type === 'KnowYourCustomer') { return { type: ClaimType.KnowYourCustomer, - scope: meshScopeToScope(claim.asKnowYourCustomer), + scope: meshScopeToScope(claim.asKnowYourCustomer, context), }; } if (type === 'Exempted') { return { type: ClaimType.Exempted, - scope: meshScopeToScope(claim.asExempted), + scope: meshScopeToScope(claim.asExempted, context), }; } @@ -2351,7 +2450,7 @@ export function meshClaimToClaim(claim: PolymeshPrimitivesIdentityClaimClaim): C const [rawId, scope] = claim.asCustom; return { type: ClaimType.Custom, - scope: meshScopeToScope(scope.unwrapOrDefault()), + scope: meshScopeToScope(scope.unwrapOrDefault(), context), customClaimTypeId: u32ToBigNumber(rawId), }; } @@ -2359,7 +2458,7 @@ export function meshClaimToClaim(claim: PolymeshPrimitivesIdentityClaimClaim): C if (type === 'Blocked') { return { type: ClaimType.Blocked, - scope: meshScopeToScope(claim.asBlocked), + scope: meshScopeToScope(claim.asBlocked, context), }; } @@ -2569,21 +2668,21 @@ function meshConditionTypeToCondition( if (meshConditionType.isIsPresent) { return { type: ConditionType.IsPresent, - claim: meshClaimToClaim(meshConditionType.asIsPresent), + claim: meshClaimToClaim(meshConditionType.asIsPresent, context), }; } if (meshConditionType.isIsAbsent) { return { type: ConditionType.IsAbsent, - claim: meshClaimToClaim(meshConditionType.asIsAbsent), + claim: meshClaimToClaim(meshConditionType.asIsAbsent, context), }; } if (meshConditionType.isIsAnyOf) { return { type: ConditionType.IsAnyOf, - claims: meshConditionType.asIsAnyOf.map(claim => meshClaimToClaim(claim)), + claims: meshConditionType.asIsAnyOf.map(claim => meshClaimToClaim(claim, context)), }; } @@ -2604,7 +2703,7 @@ function meshConditionTypeToCondition( return { type: ConditionType.IsNoneOf, - claims: meshConditionType.asIsNoneOf.map(claim => meshClaimToClaim(claim)), + claims: meshConditionType.asIsNoneOf.map(claim => meshClaimToClaim(claim, context)), }; } @@ -3060,12 +3159,12 @@ export function toIdentityWithClaimsArray( * @hidden */ export function nftToMeshNft( - ticker: string, + assetArgs: BaseAsset, nfts: (Nft | BigNumber)[], context: Context ): PolymeshPrimitivesNftNfTs { return context.createType('PolymeshPrimitivesNftNfTs', { - ticker: stringToTicker(ticker, context), + ...assetToMeshAssetInputParam(assetArgs, context), ids: nfts.map(id => bigNumberToU64(asNftId(id), context)), }); } @@ -3073,17 +3172,19 @@ export function nftToMeshNft( /** * @hidden */ -export function fungibleMovementToPortfolioFund( +export async function fungibleMovementToPortfolioFund( portfolioItem: FungiblePortfolioMovement, context: Context -): PolymeshPrimitivesPortfolioFund { +): Promise { const { asset, amount, memo } = portfolioItem; + const baseAsset = await asBaseAssetV2(asset, context); + return context.createType('PolymeshPrimitivesPortfolioFund', { description: { Fungible: { - ticker: stringToTicker(asTicker(asset), context), amount: bigNumberToBalance(amount, context), + ...assetToMeshAssetInputParam(baseAsset, context), }, }, memo: optionize(stringToMemo)(memo, context), @@ -3093,16 +3194,18 @@ export function fungibleMovementToPortfolioFund( /** * @hidden */ -export function nftMovementToPortfolioFund( +export async function nftMovementToPortfolioFund( portfolioItem: NonFungiblePortfolioMovement, context: Context -): PolymeshPrimitivesPortfolioFund { +): Promise { const { asset, nfts, memo } = portfolioItem; + const baseAsset = await asBaseAssetV2(asset, context); + return context.createType('PolymeshPrimitivesPortfolioFund', { description: { NonFungible: { - ticker: stringToTicker(asTicker(asset), context), + ...assetToMeshAssetInputParam(baseAsset, context), ids: nfts.map(nftId => bigNumberToU64(asNftId(nftId), context)), }, }, @@ -3436,8 +3539,8 @@ export function permissionsLikeToPermissions( } else if (assets) { assetPermissions = { ...assets, - values: assets.values.map(ticker => - typeof ticker !== 'string' ? ticker : new FungibleAsset({ ticker }, context) + values: assets.values.map(assetId => + typeof assetId !== 'string' ? assetId : new FungibleAsset({ assetId }, context) ), }; } @@ -3576,7 +3679,7 @@ export function fundraiserToOfferingDetails( name: bytesToString(name), offeringPortfolio: meshPortfolioIdToPortfolio(offeringPortfolio, context), raisingPortfolio: meshPortfolioIdToPortfolio(raisingPortfolio, context), - raisingCurrency: tickerToString(raisingAsset), + raisingCurrency: meshAssetToAssetId(raisingAsset, context), tiers, venue: new Venue({ id: u64ToBigNumber(venueId) }, context), start, @@ -3758,7 +3861,7 @@ export function distributionToDividendDistributionParams( return { origin: meshPortfolioIdToPortfolio(from, context), - currency: tickerToString(currency), + currency: meshAssetToAssetId(currency, context), perShare: balanceToBigNumber(perShare), maxAmount: balanceToBigNumber(amount), expiryDate: expiryDate.isNone ? null : momentToDate(expiryDate.unwrap()), @@ -3773,9 +3876,9 @@ export function corporateActionIdentifierToCaId( corporateActionIdentifier: CorporateActionIdentifier, context: Context ): PalletCorporateActionsCaId { - const { ticker, localId } = corporateActionIdentifier; + const { asset, localId } = corporateActionIdentifier; return context.createType('PalletCorporateActionsCaId', { - ticker: stringToTicker(ticker, context), + ...assetToMeshAssetInputParam(asset, context), localId: bigNumberToU32(localId, context), }); } @@ -3785,7 +3888,7 @@ export function corporateActionIdentifierToCaId( */ export function corporateActionParamsToMeshCorporateActionArgs( params: { - ticker: string; + asset: FungibleAsset; kind: CorporateActionKind; declarationDate: Date; checkpoint: Date | Checkpoint | CheckpointSchedule; @@ -3797,7 +3900,7 @@ export function corporateActionParamsToMeshCorporateActionArgs( context: Context ): PalletCorporateActionsInitiateCorporateActionArgs { const { - ticker, + asset, kind, declarationDate, checkpoint, @@ -3806,7 +3909,10 @@ export function corporateActionParamsToMeshCorporateActionArgs( defaultTaxWithholding, taxWithholdings, } = params; - const rawTicker = stringToTicker(ticker, context); + + const { isV6 } = context; + + const rawAssetId = assetToMeshAssetId(asset, context); const rawKind = corporateActionKindToCaKind(kind, context); const rawDeclDate = dateToMoment(declarationDate, context); const rawRecordDate = optionize(checkpointToRecordDateSpec)(checkpoint, context); @@ -3818,8 +3924,10 @@ export function corporateActionParamsToMeshCorporateActionArgs( context ); + const key = isV6 ? 'ticker' : 'assetId'; + return context.createType('PalletCorporateActionsInitiateCorporateActionArgs', { - ticker: rawTicker, + [key]: rawAssetId, kind: rawKind, declDate: rawDeclDate, recordDate: rawRecordDate, @@ -3919,11 +4027,17 @@ export function statUpdatesToBtreeStatUpdate( /** * @hidden */ -export function meshStatToStatType(rawStat: PolymeshPrimitivesStatisticsStatType): StatType { - const { - op: { type }, - claimIssuer, - } = rawStat; +export function meshStatToStatType( + rawStat: PolymeshPrimitivesStatisticsStatType, + context: Context +): StatType { + const claimIssuer = rawStat.claimIssuer; + let type = rawStat.operationType.type; + + if (context.isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + type = (rawStat as any).op.type; + } if (claimIssuer.isNone) { if (type === 'Count') { @@ -4067,11 +4181,15 @@ export function complianceConditionsToBtreeSet( * @hidden */ export function toExemptKey( - tickerKey: TickerKey, + context: Context, + rawAssetId: TickerKey | U8aFixed, op: PolymeshPrimitivesStatisticsStatOpType, claimType?: ClaimType ): ExemptKey { - return { asset: tickerKey, op, claimType }; + if (context.isV6) { + return { asset: rawAssetId as TickerKey, op, claimType }; + } + return { assetId: rawAssetId as U8aFixed, op, claimType }; } /** @@ -4413,7 +4531,7 @@ export function oldMiddlewareInstructionToHistoricInstruction( venueId: new BigNumber(venueId), createdAt: new Date(datetime), legs: legs.map(({ fromId, toId, assetId, amount }) => ({ - asset: new FungibleAsset({ ticker: assetId }, context), + asset: new FungibleAsset({ assetId }, context), amount: new BigNumber(amount).shiftedBy(-6), from: middlewarePortfolioToPortfolio(portfolioIdStringToPortfolio(fromId), context), to: middlewarePortfolioToPortfolio(portfolioIdStringToPortfolio(toId), context), @@ -4431,10 +4549,7 @@ export function middlewareLegToLeg(leg: MiddlewareLeg, context: Context): Leg { if (legType === LegTypeEnum.Fungible) { return { - asset: new FungibleAsset( - { ticker: getAssetIdFromMiddleware({ id: assetId, ticker }) }, - context - ), + asset: new FungibleAsset({ assetId }, context), amount: new BigNumber(amount).shiftedBy(-6), from: middlewarePortfolioToPortfolio( { identityId: from, number: fromPortfolio! } as MiddlewarePortfolio, @@ -4448,7 +4563,6 @@ export function middlewareLegToLeg(leg: MiddlewareLeg, context: Context): Leg { } if (legType === LegTypeEnum.NonFungible) { - const id = getAssetIdFromMiddleware({ id: assetId, ticker }); return { from: middlewarePortfolioToPortfolio( { identityId: from, number: fromPortfolio! } as MiddlewarePortfolio, @@ -4458,10 +4572,8 @@ export function middlewareLegToLeg(leg: MiddlewareLeg, context: Context): Leg { { identityId: to, number: toPortfolio! } as MiddlewarePortfolio, context ), - nfts: nftIds.map( - (nftId: number) => new Nft({ ticker: id, id: new BigNumber(nftId) }, context) - ), - asset: new NftCollection({ ticker: id }, context), + nfts: nftIds.map((nftId: number) => new Nft({ assetId, id: new BigNumber(nftId) }, context)), + asset: new NftCollection({ assetId }, context), }; } @@ -4570,9 +4682,8 @@ export function legToFungibleLeg( leg: { sender: PolymeshPrimitivesIdentityIdPortfolioId; receiver: PolymeshPrimitivesIdentityIdPortfolioId; - ticker: PolymeshPrimitivesTicker; amount: Balance; - }, + } & MeshTickerOrAssetId, context: Context ): PolymeshPrimitivesSettlementLeg { return context.createType('PolymeshPrimitivesSettlementLeg', { Fungible: leg }); @@ -4599,9 +4710,8 @@ export function legToOffChainLeg( leg: { senderIdentity: PolymeshPrimitivesIdentityId; receiverIdentity: PolymeshPrimitivesIdentityId; - ticker: PolymeshPrimitivesTicker; amount: Balance; - }, + } & MeshTickerOrAssetId, context: Context ): PolymeshPrimitivesSettlementLeg { return context.createType('PolymeshPrimitivesSettlementLeg', { OffChain: leg }); @@ -4733,7 +4843,7 @@ export function middlewarePermissionsDataToPermissions( if (assetsPermissions) { assets = { values: [...assetsPermissions].map( - ticker => new FungibleAsset({ ticker: coerceHexToString(ticker) }, context) + ticker => new FungibleAsset({ assetId: coerceHexToString(ticker) }, context) ), // eslint-disable-next-line @typescript-eslint/no-non-null-assertion type: assetsType!, @@ -4879,26 +4989,41 @@ export function collectionKeysToMetadataKeys( */ export function meshMetadataKeyToMetadataKey( rawKey: PolymeshPrimitivesAssetMetadataAssetMetadataKey, - ticker: string + asset: BaseAsset, + context: Context ): MetadataKeyId { if (rawKey.isGlobal) { return { type: MetadataType.Global, id: u64ToBigNumber(rawKey.asGlobal) }; } else { - return { type: MetadataType.Local, id: u64ToBigNumber(rawKey.asLocal), ticker }; + const assetIdParams = context.isV6 ? { ticker: asset.id } : { assetId: asset.id }; + return { + type: MetadataType.Local, + id: u64ToBigNumber(rawKey.asLocal), + ...assetIdParams, + }; } } /** * @hidden */ -export function meshNftToNftId(rawInfo: PolymeshPrimitivesNftNfTs): { - ticker: string; +export function meshNftToNftId( + rawInfo: PolymeshPrimitivesNftNfTs, + context: Context +): { + assetId: string; ids: BigNumber[]; } { - const { ticker: rawTicker, ids: rawIds } = rawInfo; + let rawTicker: U8aFixed, rawIds: Vec; + if (context.isV6) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ({ ticker: rawTicker, ids: rawIds } = rawInfo as any); + } else { + ({ assetId: rawTicker, ids: rawIds } = rawInfo); + } return { - ticker: tickerToString(rawTicker), + assetId: meshAssetToAssetId(rawTicker, context), ids: rawIds.map(rawId => u64ToBigNumber(rawId)), }; } @@ -4964,7 +5089,7 @@ function portfolioMovementsToHistoricSettlements( accounts: [handleMiddlewareAddress(accountAddress, context)], legs: [ { - asset: new FungibleAsset({ ticker: getAssetIdFromMiddleware(asset) }, context), + asset: new FungibleAsset({ assetId: getAssetIdFromMiddleware(asset) }, context), amount: new BigNumber(amount).shiftedBy(-6), direction: SettlementDirectionEnum.None, from: middlewarePortfolioToPortfolio(portfolioIdStringToPortfolio(fromId), context), @@ -5041,7 +5166,7 @@ export function oldMiddlewareDataToHistoricalSettlements( ), instruction: new Instruction({ id: new BigNumber(instructionId) }, context), legs: legs.map(({ fromId, toId, assetId, amount }) => ({ - asset: new FungibleAsset({ ticker: assetId }, context), + asset: new FungibleAsset({ assetId }, context), amount: new BigNumber(amount).shiftedBy(-6), direction: getDirection(fromId, toId), from: middlewarePortfolioToPortfolio(portfolioIdStringToPortfolio(fromId), context), diff --git a/src/utils/internal.ts b/src/utils/internal.ts index 9cb134472a..70751c3286 100644 --- a/src/utils/internal.ts +++ b/src/utils/internal.ts @@ -7,7 +7,7 @@ import { DropLast, ObsInnerType, } from '@polkadot/api/types'; -import { BTreeSet, Bytes, Option, StorageKey, u32 } from '@polkadot/types'; +import { BTreeSet, Bytes, Option, StorageKey, U8aFixed, u32 } from '@polkadot/types'; import { EventRecord } from '@polkadot/types/interfaces'; import { BlockHash } from '@polkadot/types/interfaces/chain'; import { @@ -20,7 +20,7 @@ import { } from '@polkadot/types/lookup'; import type { Callback, Codec, Observable } from '@polkadot/types/types'; import { AnyFunction, AnyTuple, IEvent, ISubmittableResult } from '@polkadot/types/types'; -import { hexAddPrefix, hexStripPrefix, stringToHex, stringUpperFirst } from '@polkadot/util'; +import { hexAddPrefix, hexStripPrefix, isHex, stringToHex, stringUpperFirst } from '@polkadot/util'; import { blake2AsHex, decodeAddress, encodeAddress } from '@polkadot/util-crypto'; import BigNumber from 'bignumber.js'; import fetch from 'cross-fetch'; @@ -95,6 +95,7 @@ import { PolymeshTx, Queries, StatClaimIssuer, + TickerKey, TxWithArgs, } from '~/types/internal'; import { @@ -121,6 +122,8 @@ import { SYSTEM_VERSION_RPC_CALL, } from '~/utils/constants'; import { + assetIdToString, + assetToMeshAssetId, bigNumberToU32, claimIssuerToMeshClaimIssuer, coerceHexToString, @@ -135,7 +138,9 @@ import { statisticsOpTypeToStatType, statsClaimToStatClaimInputType, stringToAccountId, + stringToAssetId, stringToTicker, + tickerToString, transferRestrictionTypeToStatOpType, u64ToBigNumber, } from '~/utils/conversion'; @@ -962,11 +967,140 @@ export function assertAddressValid(address: string, ss58Format: BigNumber): void } } +/** + * @hidden + * + * Validates a ticker value + */ +export function assertTickerValid(ticker: string): void { + if (!ticker.length || ticker.length > MAX_TICKER_LENGTH) { + throw new PolymeshError({ + code: ErrorCode.ValidationError, + message: `Ticker length must be between 1 and ${MAX_TICKER_LENGTH} characters`, + }); + } + + if (!isPrintableAscii(ticker)) { + throw new PolymeshError({ + code: ErrorCode.ValidationError, + message: 'Only printable ASCII is allowed as ticker name', + }); + } + + if (ticker !== ticker.toUpperCase()) { + throw new PolymeshError({ + code: ErrorCode.ValidationError, + message: 'Ticker cannot contain lower case letters', + }); + } +} + +/** + * @hidden + */ +export async function getTickerForAsset(id: string, context: Context): Promise { + const { + polymeshApi: { + query: { asset }, + }, + } = context; + // TODO @prashantasdeveloper add comment + let ticker = ''; + const rawAssetId = stringToAssetId(id, context); + const rawTicker = await asset.assetIDTicker(rawAssetId); + if (rawTicker.isSome) { + ticker = tickerToString(rawTicker.unwrap()); + } + return ticker; +} + /** * @hidden */ -export function asTicker(asset: string | BaseAsset): string { - return typeof asset === 'string' ? asset : asset.ticker; +export async function getAssetIdForTicker(ticker: string, context: Context): Promise { + const { + polymeshApi: { + query: { asset }, + }, + } = context; + let assetId = ''; + assertTickerValid(ticker); + const rawTicker = stringToTicker(ticker, context); + const rawAssetId = await asset.assetIDTicker(rawTicker); + if (rawAssetId.isSome) { + assetId = assetIdToString(rawAssetId.unwrap()); + } + return assetId; +} + +/** + * @hidden + */ +export async function getAssetIdAndTicker( + id: string, + context: Context +): Promise<{ + ticker: string; + assetId: string; +}> { + const { isV6 } = context; + + if (isV6) { + return { + ticker: id, + assetId: id, + }; + } + return { + assetId: id, + ticker: await getTickerForAsset(id, context), + }; +} + +/** + * @hidden + */ +export async function asBaseAssetV2( + asset: string | BaseAsset, + context: Context +): Promise { + const { isV6 } = context; + if (asset instanceof BaseAsset) { + return asset; + } + if (isV6) { + assertTickerValid(asset); + return new BaseAsset({ assetId: asset }, context); + } + + if (isHex(asset) && asset.length === 34) { + const ticker = await getTickerForAsset(asset, context); + const baseAsset = new BaseAsset({ assetId: asset }, context); + baseAsset.ticker = ticker; + return baseAsset; + } else { + const id = await getAssetIdForTicker(asset, context); + const baseAsset = new BaseAsset({ assetId: id }, context); + baseAsset.ticker = asset; + return baseAsset; + } +} + +/** + * @hidden + */ +export async function asAssetId(asset: string | BaseAsset, context: Context): Promise { + const baseAsset = await asBaseAssetV2(asset, context); + return baseAsset.id; +} + +/** + * @hidden + * this will return ticker for v6 and assetId for v7 and later + */ +export async function asAssetInput(asset: string | Asset, context: Context): Promise { + const baseAsset = await asBaseAssetV2(asset, context); + return baseAsset.id; } /** @@ -975,7 +1109,7 @@ export function asTicker(asset: string | BaseAsset): string { * @note alternatively {@link asAsset} returns a more precise type but is async due to a network call */ export function asBaseAsset(asset: string | BaseAsset, context: Context): BaseAsset { - return typeof asset === 'string' ? new BaseAsset({ ticker: asset }, context) : asset; + return typeof asset === 'string' ? new BaseAsset({ assetId: asset }, context) : asset; } /** @@ -988,8 +1122,8 @@ export async function asAsset(asset: string | Asset, context: Context): Promise< return asset; } - const fungible = new FungibleAsset({ ticker: asset }, context); - const collection = new NftCollection({ ticker: asset }, context); + const fungible = new FungibleAsset({ assetId: asset }, context); + const collection = new NftCollection({ assetId: asset }, context); const [isAsset, isCollection] = await Promise.all([fungible.exists(), collection.exists()]); @@ -1015,9 +1149,9 @@ export function asFungibleAsset(asset: string | BaseAsset, context: Context): Fu return asset; } - const ticker = typeof asset === 'string' ? asset : asset.ticker; + const assetId = typeof asset === 'string' ? asset : asset.id; - return new FungibleAsset({ ticker }, context); + return new FungibleAsset({ assetId }, context); } /** @@ -1578,41 +1712,14 @@ export function assertExpectedChainVersion(nodeUrl: string): Promise { }); } -/** - * @hidden - * - * Validates a ticker value - */ -export function assertTickerValid(ticker: string): void { - if (!ticker.length || ticker.length > MAX_TICKER_LENGTH) { - throw new PolymeshError({ - code: ErrorCode.ValidationError, - message: `Ticker length must be between 1 and ${MAX_TICKER_LENGTH} characters`, - }); - } - - if (!isPrintableAscii(ticker)) { - throw new PolymeshError({ - code: ErrorCode.ValidationError, - message: 'Only printable ASCII is allowed as ticker name', - }); - } - - if (ticker !== ticker.toUpperCase()) { - throw new PolymeshError({ - code: ErrorCode.ValidationError, - message: 'Ticker cannot contain lower case letters', - }); - } -} - /** * @hidden * @returns true is the given stat is able to track the data for the given args */ export function compareStatsToInput( rawStatType: PolymeshPrimitivesStatisticsStatType, - args: RemoveAssetStatParams + args: RemoveAssetStatParams, + context: Context ): boolean { let claimIssuer; const { type } = args; @@ -1643,7 +1750,7 @@ export function compareStatsToInput( } } - const stat = meshStatToStatType(rawStatType); + const stat = meshStatToStatType(rawStatType, context); return stat === type; } @@ -1766,9 +1873,10 @@ export function compareTransferRestrictionToInput( */ export function compareStatTypeToTransferRestrictionType( statType: PolymeshPrimitivesStatisticsStatType, - transferRestrictionType: TransferRestrictionType + transferRestrictionType: TransferRestrictionType, + context: Context ): boolean { - const opType = meshStatToStatType(statType); + const opType = meshStatToStatType(statType, context); if (opType === StatType.Count) { return transferRestrictionType === TransferRestrictionType.Count; } else if (opType === StatType.Balance) { @@ -1897,7 +2005,6 @@ export async function getSecondaryAccountPermissions( */ export async function getExemptedBtreeSet( identities: (string | Identity)[], - ticker: string, context: Context ): Promise> { const exemptedIds = await getExemptedIds(identities, context); @@ -1951,13 +2058,13 @@ export function assembleAssetQuery( context: Context ): Asset[] { return assetDetails.map((rawDetails, index) => { - const ticker = tickers[index]; + const assetId = tickers[index]; const detail = rawDetails.unwrap(); if (detail.assetType.isNonFungible) { - return new NftCollection({ ticker }, context); + return new NftCollection({ assetId }, context); } else { - return new FungibleAsset({ ticker }, context); + return new FungibleAsset({ assetId }, context); } }); } @@ -2137,7 +2244,7 @@ export async function getAssetIdForMiddleware( asset: string | BaseAsset, context: Context ): Promise { - const ticker = asTicker(asset); + const ticker = await asAssetId(asset, context); const sqVersion = await getLatestSqVersion(context); @@ -2158,3 +2265,12 @@ export function getAssetIdFromMiddleware( const { ticker } = assetIdAndTicker!; return coerceHexToString(ticker!); } + +/** + * @hidden + */ +export function getAssetIdForStats(asset: Asset, context: Context): TickerKey | U8aFixed { + const rawAssetId = assetToMeshAssetId(asset, context); + + return context.isV6 ? { Ticker: rawAssetId } : rawAssetId; +}