diff --git a/README.md b/README.md index 2567943a4d..919d2d64b1 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ ## Polymesh version -This release is compatible with Polymesh v6.x.x and Polymesh Private v1.x.x +This release is compatible with Polymesh v6.0, v6.1, v6.2 and Polymesh Private v1.0 diff --git a/package.json b/package.json index 81b05ce977..5fe772b1e5 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "@polkadot/api": "10.9.1", "@polkadot/util": "12.4.2", "@polkadot/util-crypto": "12.4.2", - "@polymeshassociation/polymesh-sdk": "24.1.0", + "@polymeshassociation/polymesh-sdk": "24.2.1", "bignumber.js": "9.0.1", "bluebird": "^3.7.2", "cross-fetch": "^4.0.0", diff --git a/scripts/consts.js b/scripts/consts.js deleted file mode 100644 index e128edeff4..0000000000 --- a/scripts/consts.js +++ /dev/null @@ -1,6 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -module.exports = { - NODE_URL: 'localhost', - WS_PORT: '9944', - SCHEMA_PORT: '3008', -}; diff --git a/scripts/updateReadme.js b/scripts/updateReadme.js index 5f55b65454..4714401061 100644 --- a/scripts/updateReadme.js +++ b/scripts/updateReadme.js @@ -1,12 +1,22 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -const W3CWebSocket = require('websocket').w3cwebsocket; -const WebSocketAsPromised = require('websocket-as-promised'); -/* eslint-enable @typescript-eslint/naming-convention */ +/* eslint-disable */ +const fs = require('fs'); +const path = require('path'); const replace = require('replace-in-file'); -const { NODE_URL, WS_PORT } = require('./consts'); +const versionRegex = /This release is compatible with Polymesh v(.*) and Polymesh Private .*/; +const ppVersionRegex = /This release is compatible with Polymesh v.* and Polymesh Private v(.*)/; -const versionRegex = /This release is compatible with Polymesh v(\d+\.\d+\.\d+)/; +const getSupportedNodeVersion = path => { + const constantsFile = fs.readFileSync(path, { + encoding: 'utf8', + }); + + const regex = /export const SUPPORTED_NODE_VERSION_RANGE = '([^']+)';/g; + + const match = regex.exec(constantsFile); + + return match[1]; +}; /** * Replace the version number in the README @@ -15,29 +25,28 @@ const createReplacementVersion = newVersion => (text, prevVersion) => { return text.replace(prevVersion, newVersion); }; -// eslint-disable-next-line @typescript-eslint/no-floating-promises -(async () => { - const wsp = new WebSocketAsPromised(`ws://${NODE_URL}:${WS_PORT}`, { - createWebSocket: url => new W3CWebSocket(url), - packMessage: data => JSON.stringify(data), - unpackMessage: data => JSON.parse(data.toString()), - attachRequestId: (data, requestId) => Object.assign({ id: requestId }, data), - extractRequestId: data => data && data.id, - }); - - await wsp.open(); - - const { result: version } = await wsp.sendRequest({ - jsonrpc: '2.0', - method: 'system_version', - params: [], - }); - - replace.sync({ - files: 'README.md', - from: versionRegex, - to: createReplacementVersion(version), - }); - - process.exit(0); -})(); +const supportedNodeVersionString = supportedNodeVersion => + supportedNodeVersion + .split('||') + .map(version => version.trim()) + .join(', v'); + +const { + SUPPORTED_NODE_VERSION_RANGE: supportedNodeVersionForPolymesh, +} = require('@polymeshassociation/polymesh-sdk/utils/constants'); + +replace.sync({ + files: 'README.md', + from: versionRegex, + to: createReplacementVersion(supportedNodeVersionString(supportedNodeVersionForPolymesh)), +}); + +const supportedNodeVersionForPolymeshPrivate = getSupportedNodeVersion( + path.resolve('src', 'utils', 'constants.ts') +); + +replace.sync({ + files: 'README.md', + from: ppVersionRegex, + to: createReplacementVersion(supportedNodeVersionString(supportedNodeVersionForPolymeshPrivate)), +}); diff --git a/sdk-docs-typedoc.json b/sdk-docs-typedoc.json index 6c9638a432..db47b12d07 100644 --- a/sdk-docs-typedoc.json +++ b/sdk-docs-typedoc.json @@ -7,7 +7,7 @@ "src/generated/types.ts", "src/types/index.ts", "src/types/utils", - "src/utils/index.ts", + "src/entities/types.ts", "src/base" ], "entryPointStrategy": "expand", @@ -19,7 +19,6 @@ "src/base/Context.ts", "src/base/Procedure.ts", "**/sandbox.ts", - "src/api/entities/types.ts", "src/api/entities/Namespace.ts", "src/types/internal.ts", "src/utils/**", diff --git a/src/api/client/Polymesh.ts b/src/api/client/Polymesh.ts index 035ad08c68..5d86a3a5c4 100644 --- a/src/api/client/Polymesh.ts +++ b/src/api/client/Polymesh.ts @@ -19,11 +19,10 @@ import { import { SigningManager } from '@polymeshassociation/signing-manager-types'; import { ConfidentialAccounts } from '~/api/client/ConfidentialAccounts'; +import { ConfidentialAssets } from '~/api/client/ConfidentialAssets'; import { ConfidentialSettlements } from '~/api/client/ConfidentialSettlements'; import schema from '~/polkadot/schema'; -import { ConfidentialAssets } from './ConfidentialAssets'; - export interface ConnectParams { /** * The websocket URL for the Polymesh node to connect to diff --git a/src/api/entities/ConfidentialAsset/types.ts b/src/api/entities/ConfidentialAsset/types.ts index 71fbccf6eb..c994b1d515 100644 --- a/src/api/entities/ConfidentialAsset/types.ts +++ b/src/api/entities/ConfidentialAsset/types.ts @@ -1,9 +1,7 @@ import { EventIdEnum } from '@polymeshassociation/polymesh-sdk/middleware/types'; -import { Identity } from '@polymeshassociation/polymesh-sdk/types'; import BigNumber from 'bignumber.js'; -import { ConfidentialVenue } from '~/internal'; -import { ConfidentialAccount } from '~/types'; +import { ConfidentialAccount, ConfidentialVenue, Identity } from '~/internal'; export interface ConfidentialAssetDetails { owner: Identity; diff --git a/src/api/entities/Identity/__tests__/index.ts b/src/api/entities/Identity/__tests__/index.ts new file mode 100644 index 0000000000..f8d8c9f0e4 --- /dev/null +++ b/src/api/entities/Identity/__tests__/index.ts @@ -0,0 +1,158 @@ +import { u64 } from '@polkadot/types'; +import { PolymeshPrimitivesIdentityId } from '@polkadot/types/lookup'; +import BigNumber from 'bignumber.js'; +import { when } from 'jest-when'; + +import { Context, Entity, Identity } from '~/internal'; +import { dsMockUtils, entityMockUtils, procedureMockUtils } from '~/testUtils/mocks'; +import { MockContext } from '~/testUtils/mocks/dataSources'; +import { ConfidentialLegParty } from '~/types'; +import { tuple } from '~/types/utils'; +import * as utilsConversionModule from '~/utils/conversion'; + +jest.mock( + '~/api/entities/ConfidentialAsset', + require('~/testUtils/mocks/entities').mockConfidentialAssetModule( + '~/api/entities/ConfidentialAsset' + ) +); + +jest.mock( + '~/api/entities/ConfidentialVenue', + require('~/testUtils/mocks/entities').mockConfidentialVenueModule( + '~/api/entities/ConfidentialVenue' + ) +); + +describe('Identity class', () => { + let context: MockContext; + let stringToIdentityIdSpy: jest.SpyInstance; + let u64ToBigNumberSpy: jest.SpyInstance; + + beforeAll(() => { + dsMockUtils.initMocks(); + entityMockUtils.initMocks(); + procedureMockUtils.initMocks(); + stringToIdentityIdSpy = jest.spyOn(utilsConversionModule, 'stringToIdentityId'); + u64ToBigNumberSpy = jest.spyOn(utilsConversionModule, 'u64ToBigNumber'); + }); + + beforeEach(() => { + context = dsMockUtils.getContextInstance({ + middlewareEnabled: true, + }); + }); + + afterEach(() => { + dsMockUtils.reset(); + entityMockUtils.reset(); + procedureMockUtils.reset(); + }); + + afterAll(() => { + dsMockUtils.cleanup(); + procedureMockUtils.cleanup(); + }); + + it('should extend Entity', () => { + expect(Identity.prototype instanceof Entity).toBe(true); + }); + + describe('constructor', () => { + it('should assign did to instance', () => { + const did = 'abc'; + const identity = new Identity({ did }, context); + + expect(identity.did).toBe(did); + }); + }); + + describe('method: isUniqueIdentifiers', () => { + it('should return true if the object conforms to the interface', () => { + expect(Identity.isUniqueIdentifiers({ did: 'someDid' })).toBe(true); + expect(Identity.isUniqueIdentifiers({})).toBe(false); + expect(Identity.isUniqueIdentifiers({ did: 3 })).toBe(false); + }); + }); + + describe('method: getInvolvedConfidentialTransactions', () => { + const transactionId = new BigNumber(1); + const legId = new BigNumber(2); + + it('should return the transactions with the identity affirmation status', async () => { + dsMockUtils.createQueryMock('confidentialAsset', 'userAffirmations', { + entries: [ + tuple( + [ + dsMockUtils.createMockIdentityId('someDid'), + [ + dsMockUtils.createMockConfidentialTransactionId(transactionId), + dsMockUtils.createMockConfidentialTransactionLegId(legId), + dsMockUtils.createMockConfidentialLegParty('Sender'), + ], + ], + dsMockUtils.createMockOption(dsMockUtils.createMockBool(false)) + ), + ], + }); + + const identity = new Identity({ did: 'someDid' }, context); + + const result = await identity.getInvolvedConfidentialTransactions(); + + expect(result).toEqual({ + data: expect.arrayContaining([ + expect.objectContaining({ + affirmed: false, + legId: new BigNumber(2), + role: ConfidentialLegParty.Sender, + transaction: expect.objectContaining({ id: transactionId }), + }), + ]), + next: null, + }); + }); + }); + + describe('method: getConfidentialVenues', () => { + let did: string; + let confidentialVenueId: BigNumber; + + let rawDid: PolymeshPrimitivesIdentityId; + let rawConfidentialVenueId: u64; + + beforeAll(() => { + did = 'someDid'; + confidentialVenueId = new BigNumber(5); + + rawDid = dsMockUtils.createMockIdentityId(did); + rawConfidentialVenueId = dsMockUtils.createMockU64(confidentialVenueId); + }); + + beforeEach(() => { + when(stringToIdentityIdSpy).calledWith(did, context).mockReturnValue(rawDid); + }); + + afterAll(() => { + jest.restoreAllMocks(); + }); + + it('should return a list of Confidential Venues', async () => { + when(u64ToBigNumberSpy) + .calledWith(rawConfidentialVenueId) + .mockReturnValue(confidentialVenueId); + + const mock = dsMockUtils.createQueryMock('confidentialAsset', 'identityVenues'); + const mockStorageKey = { args: [rawDid, rawConfidentialVenueId] }; + + mock.keys = jest.fn().mockResolvedValue([mockStorageKey]); + + const identity = new Identity({ did }, context); + + const result = await identity.getConfidentialVenues(); + expect(result).toEqual( + expect.arrayContaining([expect.objectContaining({ id: confidentialVenueId })]) + ); + }); + }); +}); diff --git a/src/api/entities/Identity/index.ts b/src/api/entities/Identity/index.ts new file mode 100644 index 0000000000..129d6868d6 --- /dev/null +++ b/src/api/entities/Identity/index.ts @@ -0,0 +1,100 @@ +import { Identity as PublicIdentity } from '@polymeshassociation/polymesh-sdk/internal'; +import { + boolToBoolean, + stringToIdentityId, + u64ToBigNumber, +} from '@polymeshassociation/polymesh-sdk/utils/conversion'; +import { requestPaginated } from '@polymeshassociation/polymesh-sdk/utils/internal'; + +import { ConfidentialTransaction, ConfidentialVenue } from '~/internal'; +import { ConfidentialAffirmation, PaginationOptions, ResultSet } from '~/types'; +import { + confidentialLegPartyToRole, + confidentialTransactionIdToBigNumber, + confidentialTransactionLegIdToBigNumber, +} from '~/utils/conversion'; + +/** + * Properties that uniquely identify an Identity + */ +export interface UniqueIdentifiers { + did: string; +} + +/** + * Represents an Identity in the Polymesh blockchain + */ +export class Identity extends PublicIdentity { + /** + * Get Confidential Transactions affirmations involving this identity + * + * @note supports pagination + */ + public async getInvolvedConfidentialTransactions( + paginationOpts?: PaginationOptions + ): Promise> { + const { + did, + context, + context: { + polymeshApi: { + query: { confidentialAsset }, + }, + }, + } = this; + + const { entries, lastKey: next } = await requestPaginated(confidentialAsset.userAffirmations, { + arg: did, + paginationOpts, + }); + + const data = entries.map(entry => { + const [key, value] = entry; + const affirmed = boolToBoolean(value.unwrap()); + const [rawTransactionId, rawLegId, rawLegParty] = key.args[1]; + + const transactionId = confidentialTransactionIdToBigNumber(rawTransactionId); + const legId = confidentialTransactionLegIdToBigNumber(rawLegId); + const role = confidentialLegPartyToRole(rawLegParty); + + const transaction = new ConfidentialTransaction({ id: transactionId }, context); + + return { + affirmed, + legId, + transaction, + role, + }; + }); + + return { + data, + next, + }; + } + + /** + * Retrieve all Confidential Venues created by this Identity + */ + public async getConfidentialVenues(): Promise { + const { + context: { + polymeshApi: { + query: { confidentialAsset }, + }, + }, + did, + context, + } = this; + + const rawDid = stringToIdentityId(did, context); + + const venueIdsKeys = await confidentialAsset.identityVenues.keys(rawDid); + + return venueIdsKeys.map(key => { + const rawVenueId = key.args[1]; + + return new ConfidentialVenue({ id: u64ToBigNumber(rawVenueId) }, context); + }); + } +} diff --git a/src/api/entities/types.ts b/src/api/entities/types.ts index 59f7ea9ab8..46372ba811 100644 --- a/src/api/entities/types.ts +++ b/src/api/entities/types.ts @@ -1,15 +1,68 @@ +import { + BaseAsset, + Identity as PublicIdentityClass, +} from '@polymeshassociation/polymesh-sdk/internal'; +import { + DefaultPortfolio, + NumberedPortfolio, + SignerType, +} from '@polymeshassociation/polymesh-sdk/types'; + +import { TxTag } from '~/generated/types'; import { ConfidentialAccount as ConfidentialAccountClass, ConfidentialAsset as ConfidentialAssetClass, ConfidentialTransaction as ConfidentialTransactionClass, ConfidentialVenue as ConfidentialVenueClass, + Identity as IdentityClass, } from '~/internal'; +export * from '@polymeshassociation/polymesh-sdk/api/entities/types'; + +export type Identity = IdentityClass; +export type PublicIdentity = PublicIdentityClass; export type ConfidentialAccount = ConfidentialAccountClass; export type ConfidentialAsset = ConfidentialAssetClass; export type ConfidentialVenue = ConfidentialVenueClass; export type ConfidentialTransaction = ConfidentialTransactionClass; +export * from './ConfidentialAccount/types'; export * from './ConfidentialAsset/types'; export * from './ConfidentialTransaction/types'; -export * from './ConfidentialAccount/types'; + +/** + * This represents positive permissions (i.e. only "includes"). It is used + * for specifying procedure requirements and querying if an Account has certain + * permissions. Null values represent full permissions in that category + */ +export interface SimplePermissions { + /** + * list of required Asset permissions + */ + assets?: BaseAsset[] | null; + /** + * list of required Transaction permissions + */ + transactions?: TxTag[] | null; + portfolios?: (DefaultPortfolio | NumberedPortfolio)[] | null; +} + +/** + * Result of a `checkPermissions` call. If `Type` is `Account`, represents whether the Account + * has all the necessary secondary key Permissions. If `Type` is `Identity`, represents whether the + * Identity has all the necessary external agent Permissions + */ +export interface CheckPermissionsResult { + /** + * required permissions which the signer *DOESN'T* have. Only present if `result` is `false` + */ + missingPermissions?: Type extends SignerType.Account ? SimplePermissions : TxTag[] | null; + /** + * whether the signer complies with the required permissions or not + */ + result: boolean; + /** + * optional message explaining the reason for failure in special cases + */ + message?: string; +} diff --git a/src/api/procedures/__tests__/applyIncomingAssetBalance.ts b/src/api/procedures/__tests__/applyIncomingAssetBalance.ts index 6268aaaa65..cef5dc559d 100644 --- a/src/api/procedures/__tests__/applyIncomingAssetBalance.ts +++ b/src/api/procedures/__tests__/applyIncomingAssetBalance.ts @@ -5,14 +5,12 @@ import { getAuthorization, prepareApplyIncomingBalance, } from '~/api/procedures/applyIncomingAssetBalance'; -import { Context, PolymeshError } from '~/internal'; +import { ConfidentialAccount, Context, PolymeshError } from '~/internal'; import { dsMockUtils, entityMockUtils, procedureMockUtils } from '~/testUtils/mocks'; import { Mocked } from '~/testUtils/types'; import { ApplyIncomingBalanceParams, ConfidentialAsset, TxTags } from '~/types'; import * as utilsConversionModule from '~/utils/conversion'; -import { ConfidentialAccount } from './../../entities/types'; - describe('applyIncomingAssetBalance procedure', () => { let mockContext: Mocked; let account: ConfidentialAccount; diff --git a/src/api/procedures/createConfidentialAsset.ts b/src/api/procedures/createConfidentialAsset.ts index 54194bc9f7..0ce10c106d 100644 --- a/src/api/procedures/createConfidentialAsset.ts +++ b/src/api/procedures/createConfidentialAsset.ts @@ -1,7 +1,6 @@ import { ISubmittableResult } from '@polkadot/types/types'; import { TransactionSpec } from '@polymeshassociation/polymesh-sdk/types/internal'; import { - asIdentity, assertIdentityExists, filterEventRecords, } from '@polymeshassociation/polymesh-sdk/utils/internal'; @@ -15,7 +14,7 @@ import { meshConfidentialAssetToAssetId, stringToBytes, } from '~/utils/conversion'; -import { asConfidentialAccount } from '~/utils/internal'; +import { asConfidentialAccount, asIdentity } from '~/utils/internal'; /** * @hidden diff --git a/src/api/procedures/types.ts b/src/api/procedures/types.ts index 12bc14330b..2380d32bd9 100644 --- a/src/api/procedures/types.ts +++ b/src/api/procedures/types.ts @@ -1,5 +1,7 @@ import { Identity } from '~/internal'; import { ConfidentialAccount, ConfidentialAsset } from '~/types'; + +export * from '@polymeshassociation/polymesh-sdk/api/procedures/types'; export interface ConfidentialTransactionLeg { /** * The assets (or their IDs) for this leg of the transaction. Amounts are specified in the later proof generation steps diff --git a/src/base/ConfidentialProcedure.ts b/src/base/ConfidentialProcedure.ts index 18c35af7d0..23fcfecec0 100644 --- a/src/base/ConfidentialProcedure.ts +++ b/src/base/ConfidentialProcedure.ts @@ -8,7 +8,7 @@ import { import { ErrorCode, GenericPolymeshTransaction, - Identity, + Identity as PublicIdentity, ProcedureOpts, SignerType, TxTag as PublicTxTag, @@ -19,13 +19,14 @@ import { } from '@polymeshassociation/polymesh-sdk/types/internal'; import { signerToString } from '@polymeshassociation/polymesh-sdk/utils/conversion'; +import { Identity } from '~/internal'; import { + CheckPermissionsResult, ConfidentialCheckRolesResult, ConfidentialProcedureAuthorization, ConfidentialProcedureAuthorizationStatus, TxTag, } from '~/types'; -import { CheckPermissionsResult } from '~/types/internal'; import { checkConfidentialPermissions, checkConfidentialRoles } from '~/utils/internal'; /** @@ -54,7 +55,7 @@ async function getAgentPermissionsResult( asset, transactions: transactions as PublicTxTag[], }) - : { result: false, missingPermissions: transactions as PublicTxTag[] }; + : { result: false, missingPermissions: transactions }; } /** @@ -183,7 +184,7 @@ export class ConfidentialProcedure< const account = ctx.getSigningAccount(); - const fetchIdentity = async (): Promise => { + const fetchIdentity = async (): Promise => { if (identity) return identity; return account.getIdentity(); @@ -194,7 +195,7 @@ export class ConfidentialProcedure< } else if (typeof roles === 'string') { rolesResult = { result: false, message: roles }; } else { - identity = await fetchIdentity(); + identity = (await fetchIdentity()) as unknown as Identity; noIdentity = !identity; rolesResult = { result: false, missingRoles: roles }; @@ -230,7 +231,7 @@ export class ConfidentialProcedure< if (assets?.length && transactions?.length) { assertOnlyOneAsset(assets); - identity = await fetchIdentity(); + identity = (await fetchIdentity()) as unknown as Identity; noIdentity = !identity; diff --git a/src/internal.ts b/src/internal.ts index e23a105046..b9b7331be4 100644 --- a/src/internal.ts +++ b/src/internal.ts @@ -2,6 +2,7 @@ export * from '@polymeshassociation/polymesh-sdk/internal'; +export { Identity } from '~/api/entities/Identity'; export { ConfidentialProcedure } from '~/base/ConfidentialProcedure'; export { addConfidentialTransaction } from '~/api/procedures/addConfidentialTransaction'; export { executeConfidentialTransaction } from '~/api/procedures/executeConfidentialTransaction'; diff --git a/src/polkadot/augment-api-events.ts b/src/polkadot/augment-api-events.ts index 922eb007ac..353e4e9d27 100644 --- a/src/polkadot/augment-api-events.ts +++ b/src/polkadot/augment-api-events.ts @@ -2274,6 +2274,11 @@ declare module '@polkadot/api-base/types/events' { * Instruction failed execution (did, instruction_id) **/ InstructionFailed: AugmentedEvent; + /** + * An instruction with mediators has been created. + * Parameters: [`InstructionId`] of the instruction and the [`IdentityId`] of all mediators. + **/ + InstructionMediators: AugmentedEvent]>; /** * An instruction has been rejected (did, instruction_id) **/ diff --git a/src/polkadot/lookup.ts b/src/polkadot/lookup.ts index 07804efefe..2a85acc779 100644 --- a/src/polkadot/lookup.ts +++ b/src/polkadot/lookup.ts @@ -1647,6 +1647,7 @@ export default { '(PolymeshPrimitivesIdentityId,PolymeshPrimitivesIdentityIdPortfolioId,u64)', MediatorAffirmationReceived: '(PolymeshPrimitivesIdentityId,u64,Option)', MediatorAffirmationWithdrawn: '(PolymeshPrimitivesIdentityId,u64)', + InstructionMediators: '(u64,BTreeSet)', }, }, /** @@ -4954,21 +4955,21 @@ export default { _enum: ['RequireSudo'], }, /** - * Lookup666: pallet_asset::TickerRegistration + * Lookup666: pallet_asset::types::TickerRegistration **/ PalletAssetTickerRegistration: { owner: 'PolymeshPrimitivesIdentityId', expiry: 'Option', }, /** - * Lookup667: pallet_asset::TickerRegistrationConfig + * Lookup667: pallet_asset::types::TickerRegistrationConfig **/ PalletAssetTickerRegistrationConfig: { maxTickerLength: 'u8', registrationLength: 'Option', }, /** - * Lookup668: pallet_asset::SecurityToken + * Lookup668: pallet_asset::types::SecurityToken **/ PalletAssetSecurityToken: { totalSupply: 'u128', @@ -4977,13 +4978,13 @@ export default { assetType: 'PolymeshPrimitivesAssetAssetType', }, /** - * Lookup672: pallet_asset::AssetOwnershipRelation + * Lookup672: pallet_asset::types::AssetOwnershipRelation **/ PalletAssetAssetOwnershipRelation: { _enum: ['NotOwned', 'TickerOwned', 'AssetOwned'], }, /** - * Lookup678: pallet_asset::Error + * Lookup678: pallet_asset::error::Error **/ PalletAssetError: { _enum: [ diff --git a/src/polkadot/types-lookup.ts b/src/polkadot/types-lookup.ts index eb490b92b1..7ef225d85c 100644 --- a/src/polkadot/types-lookup.ts +++ b/src/polkadot/types-lookup.ts @@ -2798,6 +2798,8 @@ declare module '@polkadot/types/lookup' { >; readonly isMediatorAffirmationWithdrawn: boolean; readonly asMediatorAffirmationWithdrawn: ITuple<[PolymeshPrimitivesIdentityId, u64]>; + readonly isInstructionMediators: boolean; + readonly asInstructionMediators: ITuple<[u64, BTreeSet]>; readonly type: | 'VenueCreated' | 'VenueDetailsUpdated' @@ -2821,7 +2823,8 @@ declare module '@polkadot/types/lookup' { | 'FailedToExecuteInstruction' | 'InstructionAutomaticallyAffirmed' | 'MediatorAffirmationReceived' - | 'MediatorAffirmationWithdrawn'; + | 'MediatorAffirmationWithdrawn' + | 'InstructionMediators'; } /** @name PolymeshPrimitivesSettlementVenueType (249) */ diff --git a/src/testUtils/mocks/dataSources.ts b/src/testUtils/mocks/dataSources.ts index cfd38d9567..e6c91480e2 100644 --- a/src/testUtils/mocks/dataSources.ts +++ b/src/testUtils/mocks/dataSources.ts @@ -172,8 +172,12 @@ import { } from '~/polkadot/polymesh'; import { dsMockUtils } from '~/testUtils/mocks'; import { Mocked } from '~/testUtils/types'; -import { ConfidentialCheckRolesResult, CountryCode as CountryCodeEnum } from '~/types'; -import { CheckPermissionsResult, Consts, Extrinsics, Queries, Rpcs } from '~/types/internal'; +import { + CheckPermissionsResult, + ConfidentialCheckRolesResult, + CountryCode as CountryCodeEnum, +} from '~/types'; +import { Consts, Extrinsics, Queries, Rpcs } from '~/types/internal'; import { ArgsType, Mutable, tuple } from '~/types/utils'; import { STATE_RUNTIME_VERSION_CALL, SYSTEM_VERSION_RPC_CALL } from '~/utils/constants'; diff --git a/src/testUtils/mocks/entities.ts b/src/testUtils/mocks/entities.ts index aada177d50..ed1c568a2c 100644 --- a/src/testUtils/mocks/entities.ts +++ b/src/testUtils/mocks/entities.ts @@ -1,8 +1,10 @@ /* istanbul ignore file */ + /* eslint-disable @typescript-eslint/explicit-function-return-type */ /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-use-before-define */ +import { Identity } from '@polymeshassociation/polymesh-sdk/internal'; import { AccountBalance, ActiveTransferRestrictions, @@ -11,7 +13,6 @@ import { AssetWithGroup, Authorization, AuthorizationType, - CheckPermissionsResult, CheckRolesResult, CollectionKey, ComplianceRequirements, @@ -82,7 +83,7 @@ import { DefaultPortfolio, DividendDistribution, FungibleAsset, - Identity, + Identity as PrivateIdentity, Instruction, KnownPermissionGroup, MetadataEntry, @@ -100,6 +101,7 @@ import { import { entityMockUtils } from '~/testUtils/mocks'; import { Mocked } from '~/testUtils/types'; import { + CheckPermissionsResult, ConfidentialAssetBalance, ConfidentialAssetDetails, ConfidentialLeg, @@ -110,7 +112,7 @@ import { ConfidentialVenueFilteringDetails, } from '~/types'; -export type MockIdentity = Mocked; +export type MockIdentity = Mocked; export type MockChildIdentity = Mocked; export type MockAccount = Mocked; export type MockSubsidy = Mocked; diff --git a/src/types/index.ts b/src/types/index.ts index 8d3dd3b9eb..5e30fc61f3 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -20,10 +20,11 @@ import { import BigNumber from 'bignumber.js'; import { CountryCode, ModuleName, TxTag, TxTags } from '~/generated/types'; -import { CheckPermissionsResult } from '~/types/internal'; +import { CheckPermissionsResult } from '~/types'; export { EventRecord } from '@polkadot/types/interfaces'; export { ConnectParams } from '~/api/client/Polymesh'; +export * from '@polymeshassociation/polymesh-sdk/api/client/types'; export * from '~/api/entities/types'; export * from '~/api/procedures/types'; export * from '@polymeshassociation/polymesh-sdk/base/types'; @@ -52,7 +53,6 @@ export { export { CountryCode, ModuleName, TxTag, TxTags }; // Roles - export enum RoleType { TickerOwner = 'TickerOwner', CddProvider = 'CddProvider', diff --git a/src/types/internal.ts b/src/types/internal.ts index 9700620b41..b271ed4571 100644 --- a/src/types/internal.ts +++ b/src/types/internal.ts @@ -8,14 +8,6 @@ import { SubmittableExtrinsics, } from '@polkadot/api/types'; import { RpcInterface } from '@polkadot/rpc-core/types'; -import { BaseAsset } from '@polymeshassociation/polymesh-sdk/internal'; -import { - DefaultPortfolio, - NumberedPortfolio, - SignerType, -} from '@polymeshassociation/polymesh-sdk/types'; - -import { TxTag } from '~/generated/types'; /** * Polkadot's `tx` submodule @@ -49,40 +41,3 @@ export type Queries = QueryableStorage<'promise'>; export type Consts = QueryableConsts<'promise'>; export type Rpcs = DecoratedRpc<'promise', RpcInterface>; - -/** - * This represents positive permissions (i.e. only "includes"). It is used - * for specifying procedure requirements and querying if an Account has certain - * permissions. Null values represent full permissions in that category - */ -export interface SimplePermissions { - /** - * list of required Asset permissions - */ - assets?: BaseAsset[] | null; - /** - * list of required Transaction permissions - */ - transactions?: TxTag[] | null; - portfolios?: (DefaultPortfolio | NumberedPortfolio)[] | null; -} - -/** - * Result of a `checkPermissions` call. If `Type` is `Account`, represents whether the Account - * has all the necessary secondary key Permissions. If `Type` is `Identity`, represents whether the - * Identity has all the necessary external agent Permissions - */ -export interface CheckPermissionsResult { - /** - * required permissions which the signer *DOESN'T* have. Only present if `result` is `false` - */ - missingPermissions?: Type extends SignerType.Account ? SimplePermissions : TxTag[] | null; - /** - * whether the signer complies with the required permissions or not - */ - result: boolean; - /** - * optional message explaining the reason for failure in special cases - */ - message?: string; -} diff --git a/src/utils/__tests__/internal.ts b/src/utils/__tests__/internal.ts index 00291bd9ea..5f5a1e47a3 100644 --- a/src/utils/__tests__/internal.ts +++ b/src/utils/__tests__/internal.ts @@ -31,6 +31,7 @@ import * as utilsInternalModule from '~/utils/internal'; import { asConfidentialAccount, asConfidentialAsset, + asIdentity, assertCaAssetValid, assertElgamalPubKeyValid, checkConfidentialPermissions, @@ -80,6 +81,25 @@ jest.mock( ) ); +describe('asIdentity', () => { + it('should return identity instance', () => { + const mockContext = dsMockUtils.getContextInstance(); + + const did = 'did'; + const identity = entityMockUtils.getIdentityInstance({ + did, + }); + + let result = asIdentity(did, mockContext); + + expect(result).toEqual(expect.objectContaining({ did })); + + result = asIdentity(identity, mockContext); + + expect(result).toEqual(expect.objectContaining({ did })); + }); +}); + describe('createProcedureMethod', () => { let context: Context; let prepare: jest.Mock; diff --git a/src/utils/conversion.ts b/src/utils/conversion.ts index 6e0f80e4a2..6e19bbd42e 100644 --- a/src/utils/conversion.ts +++ b/src/utils/conversion.ts @@ -63,6 +63,11 @@ import { export * from '~/generated/utils'; +export { + stringToIdentityId, + u64ToBigNumber, +} from '@polymeshassociation/polymesh-sdk/utils/conversion'; + /** * @hidden */ diff --git a/src/utils/internal.ts b/src/utils/internal.ts index ff14344fc6..6a242d9e78 100644 --- a/src/utils/internal.ts +++ b/src/utils/internal.ts @@ -6,7 +6,6 @@ import { DefaultPortfolio, ErrorCode, GenericPolymeshTransaction, - Identity, NumberedPortfolio, PermissionType, ProcedureOpts, @@ -34,11 +33,13 @@ import { ConfidentialAsset, ConfidentialVenue, Context, + Identity, PolymeshError, TickerReservation, Venue, } from '~/internal'; import { + CheckPermissionsResult, ConfidentialCheckRolesResult, ConfidentialNoArgsProcedureMethod, ConfidentialOptionalArgsProcedureMethod, @@ -46,16 +47,24 @@ import { ConfidentialProcedureMethod, ModuleName, Role, + SimplePermissions, TransactionPermissions, TxTag, TxTags, } from '~/types'; -import { CheckPermissionsResult, SimplePermissions } from '~/types/internal'; import { ConfidentialProcedureFunc } from '~/types/utils'; import { isConfidentialAssetOwnerRole, isConfidentialVenueOwnerRole } from '~/utils'; export * from '~/generated/utils'; +/** + * @hidden + * Given a DID return the corresponding Identity, given an Identity return the Identity + */ +export function asIdentity(value: string | Identity, context: Context): Identity { + return typeof value === 'string' ? new Identity({ did: value }, context) : value; +} + /** * @hidden */ @@ -565,7 +574,11 @@ export const checkConfidentialPermissions = async ( /** * Check whether an Identity possesses the specified Role */ -const hasRole = async (identity: Identity, role: Role, context: Context): Promise => { +const hasRole = async ( + identity: T, + role: Role, + context: Context +): Promise => { const { did } = identity; if (isConfidentialAssetOwnerRole(role)) { @@ -625,8 +638,8 @@ const hasRole = async (identity: Identity, role: Role, context: Context): Promis /** * Check whether this Identity possesses all specified roles */ -export const checkConfidentialRoles = async ( - identity: Identity, +export const checkConfidentialRoles = async ( + identity: T, roles: Role[], context: Context ): Promise => { diff --git a/src/utils/typeguards.ts b/src/utils/typeguards.ts index 3d65ff20e6..337c48aee6 100644 --- a/src/utils/typeguards.ts +++ b/src/utils/typeguards.ts @@ -2,6 +2,8 @@ import { ConfidentialAssetOwnerRole, ConfidentialVenueOwnerRole, Role, RoleType } from '~/types'; +export * from '@polymeshassociation/polymesh-sdk/utils'; + /** * Return whether Role is VenueOwnerRole */ diff --git a/tsconfig.json b/tsconfig.json index 60b6d6770d..3837de73cc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,28 +4,16 @@ "rootDir": "src", "baseUrl": ".", "paths": { - "~/*": [ - "src/*" - ], - "polymesh-types/*": [ - "src/polkadot/*" - ], - "@polkadot/api/augment": [ - "src/polkadot/augment-api.ts" - ], - "@polkadot/types/augment": [ - "src/polkadot/augment-types.ts" - ], - "@polkadot/types/lookup": [ - "src/polkadot/types-lookup.ts" - ] + "~/*": ["src/*"], + "polymesh-types/*": ["src/polkadot/*"], + "@polkadot/api/augment": ["src/polkadot/augment-api.ts"], + "@polkadot/types/augment": ["src/polkadot/augment-types.ts"], + "@polkadot/types/lookup": ["src/polkadot/types-lookup.ts"] }, "plugins": [ { "transform": "@ovos-media/ts-transform-paths", - "exclude": [ - "*" - ], + "exclude": ["*"] } ], "useUnknownInCatchVariables": false, @@ -40,20 +28,8 @@ "esModuleInterop": true, "resolveJsonModule": true, "skipLibCheck": true, - "lib": [ - "es2017", - "dom" - ], - "typeRoots": [ - "./node_modules/@types", - "./src/typings" - ] + "lib": ["es2017", "dom"], + "typeRoots": ["./node_modules/@types", "./src/typings"] }, - "exclude": [ - "dist", - "node_modules", - "src/sandbox.ts", - "test.ts", - "src-temp" - ] -} \ No newline at end of file + "exclude": ["dist", "node_modules", "sandbox.ts", "test.ts", "src-temp"] +} diff --git a/yarn.lock b/yarn.lock index ee17ced7d0..458c474074 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2261,10 +2261,10 @@ dependencies: "@polymeshassociation/signing-manager-types" "^3.2.0" -"@polymeshassociation/polymesh-sdk@24.1.0": - version "24.1.0" - resolved "https://registry.yarnpkg.com/@polymeshassociation/polymesh-sdk/-/polymesh-sdk-24.1.0.tgz#542e8fa43f830578988659ba50732ed97a36109f" - integrity sha512-8v4+WDX8f1PVxCWdfrNnftriyjSrMT5I8zysxRBCHwNv/riP/3BpqFkdhipg3ksR+5GCYER6ghiFB1Mw0rbh1w== +"@polymeshassociation/polymesh-sdk@24.2.1": + version "24.2.1" + resolved "https://registry.yarnpkg.com/@polymeshassociation/polymesh-sdk/-/polymesh-sdk-24.2.1.tgz#3fd4c8da94e39b80e2778bdc3c62b17348d6c331" + integrity sha512-mKFqSEC98akG+F/50alDLXnOD/VrkKdf5pXRM6KRY0OCJxOV0JYfEk23NApHx/OCgzu9CiTHElgBMjoRywAp3A== dependencies: "@apollo/client" "^3.8.1" "@polkadot/api" "10.9.1"