generated from PolymeshAssociation/typescript-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 🎸 add register did with cdd in
Identities
namespace
allow a DID to be created with a CDD claim using the new chain extrinsic. Previously these were unbatchable since the CDD claim needed the DID as an argument ✅ Closes: DA-498
- Loading branch information
1 parent
047552b
commit 0ff4b24
Showing
6 changed files
with
271 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
146 changes: 146 additions & 0 deletions
146
src/api/procedures/__tests__/registerIdentityWithCdd.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import { AccountId } from '@polkadot/types/interfaces'; | ||
import { PolymeshPrimitivesSecondaryKey } from '@polkadot/types/lookup'; | ||
import { ISubmittableResult } from '@polkadot/types/types'; | ||
import BigNumber from 'bignumber.js'; | ||
import { when } from 'jest-when'; | ||
|
||
import { | ||
createRegisterIdentityWithDidResolver, | ||
prepareRegisterIdentityWithCdd, | ||
} from '~/api/procedures/registerIdentityWithCdd'; | ||
import { Context, Identity } from '~/internal'; | ||
import { Moment } from '~/polkadot'; | ||
import { dsMockUtils, entityMockUtils, procedureMockUtils } from '~/testUtils/mocks'; | ||
import { Mocked } from '~/testUtils/types'; | ||
import { PermissionedAccount, RegisterIdentityWithCddParams } from '~/types'; | ||
import { PolymeshTx } from '~/types/internal'; | ||
import * as utilsConversionModule from '~/utils/conversion'; | ||
import * as utilsInternalModule from '~/utils/internal'; | ||
|
||
describe('registerIdentityWithCdd procedure', () => { | ||
let mockContext: Mocked<Context>; | ||
let stringToAccountIdSpy: jest.SpyInstance<AccountId, [string, Context]>; | ||
let dateToMomentSpy: jest.SpyInstance<Moment, [Date, Context]>; | ||
let secondaryAccountToMeshSecondaryKeySpy: jest.SpyInstance< | ||
PolymeshPrimitivesSecondaryKey, | ||
[PermissionedAccount, Context] | ||
>; | ||
let registerIdentityWithCddTransaction: PolymeshTx<unknown[]>; | ||
|
||
beforeAll(() => { | ||
entityMockUtils.initMocks(); | ||
procedureMockUtils.initMocks(); | ||
dsMockUtils.initMocks(); | ||
secondaryAccountToMeshSecondaryKeySpy = jest.spyOn( | ||
utilsConversionModule, | ||
'secondaryAccountToMeshSecondaryKey' | ||
); | ||
stringToAccountIdSpy = jest.spyOn(utilsConversionModule, 'stringToAccountId'); | ||
dateToMomentSpy = jest.spyOn(utilsConversionModule, 'dateToMoment'); | ||
}); | ||
|
||
beforeEach(() => { | ||
mockContext = dsMockUtils.getContextInstance(); | ||
registerIdentityWithCddTransaction = dsMockUtils.createTxMock( | ||
'identity', | ||
'cddRegisterDidWithCdd' | ||
); | ||
}); | ||
|
||
afterEach(() => { | ||
entityMockUtils.reset(); | ||
procedureMockUtils.reset(); | ||
dsMockUtils.reset(); | ||
}); | ||
|
||
afterAll(() => { | ||
procedureMockUtils.cleanup(); | ||
dsMockUtils.cleanup(); | ||
}); | ||
|
||
it('should return a cddRegisterIdentity transaction spec', async () => { | ||
const targetAccount = 'someAccount'; | ||
const secondaryAccounts = [ | ||
{ | ||
account: entityMockUtils.getAccountInstance({ address: 'someValue' }), | ||
permissions: { | ||
assets: null, | ||
portfolios: null, | ||
transactions: null, | ||
transactionGroups: [], | ||
}, | ||
}, | ||
]; | ||
const args = { | ||
targetAccount, | ||
secondaryAccounts, | ||
}; | ||
const expiry = new Date('12/12/2050'); | ||
const rawExpiry = dsMockUtils.createMockMoment(new BigNumber(expiry.getTime())); | ||
when(dateToMomentSpy).calledWith(expiry, mockContext).mockReturnValue(rawExpiry); | ||
const rawAccountId = dsMockUtils.createMockAccountId(targetAccount); | ||
const rawSecondaryAccount = dsMockUtils.createMockSecondaryKey({ | ||
signer: dsMockUtils.createMockSignatory({ | ||
Account: dsMockUtils.createMockAccountId(secondaryAccounts[0].account.address), | ||
}), | ||
permissions: dsMockUtils.createMockPermissions(), | ||
}); | ||
|
||
const proc = procedureMockUtils.getInstance<RegisterIdentityWithCddParams, Identity>( | ||
mockContext | ||
); | ||
|
||
when(stringToAccountIdSpy).calledWith(targetAccount, mockContext).mockReturnValue(rawAccountId); | ||
when(secondaryAccountToMeshSecondaryKeySpy) | ||
.calledWith(secondaryAccounts[0], mockContext) | ||
.mockReturnValue(rawSecondaryAccount); | ||
|
||
let result = await prepareRegisterIdentityWithCdd.call(proc, args); | ||
|
||
expect(result).toEqual({ | ||
transaction: registerIdentityWithCddTransaction, | ||
args: [rawAccountId, [rawSecondaryAccount], null], | ||
resolver: expect.any(Function), | ||
}); | ||
|
||
result = await prepareRegisterIdentityWithCdd.call(proc, { targetAccount, expiry }); | ||
|
||
expect(result).toEqual({ | ||
transaction: registerIdentityWithCddTransaction, | ||
args: [rawAccountId, [], rawExpiry], | ||
resolver: expect.any(Function), | ||
}); | ||
}); | ||
}); | ||
|
||
describe('createRegisterIdentityResolver', () => { | ||
const did = 'someDid'; | ||
const rawDid = dsMockUtils.createMockIdentityId(did); | ||
const filterEventRecordsSpy = jest.spyOn(utilsInternalModule, 'filterEventRecords'); | ||
|
||
beforeAll(() => { | ||
entityMockUtils.initMocks({ | ||
identityOptions: { | ||
did, | ||
}, | ||
}); | ||
}); | ||
|
||
beforeEach(() => { | ||
filterEventRecordsSpy.mockReturnValue([ | ||
dsMockUtils.createMockIEvent([rawDid, 'accountId', 'signedItem']), | ||
]); | ||
}); | ||
|
||
afterEach(() => { | ||
filterEventRecordsSpy.mockReset(); | ||
}); | ||
|
||
it('should return the new Identity', () => { | ||
const fakeContext = {} as Context; | ||
|
||
const result = createRegisterIdentityWithDidResolver(fakeContext)({} as ISubmittableResult); | ||
|
||
expect(result.did).toEqual(did); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { ISubmittableResult } from '@polkadot/types/types'; | ||
|
||
import { Context, Identity, Procedure } from '~/internal'; | ||
import { RegisterIdentityParams, RegisterIdentityWithCddParams, RoleType, TxTags } from '~/types'; | ||
import { ExtrinsicParams, TransactionSpec } from '~/types/internal'; | ||
import { | ||
dateToMoment, | ||
identityIdToString, | ||
permissionsLikeToPermissions, | ||
secondaryAccountToMeshSecondaryKey, | ||
signerToString, | ||
stringToAccountId, | ||
} from '~/utils/conversion'; | ||
import { filterEventRecords, optionize } from '~/utils/internal'; | ||
|
||
/** | ||
* @hidden | ||
*/ | ||
export const createRegisterIdentityWithDidResolver = | ||
(context: Context) => | ||
(receipt: ISubmittableResult): Identity => { | ||
const [{ data }] = filterEventRecords(receipt, 'identity', 'DidCreated'); | ||
const did = identityIdToString(data[0]); | ||
|
||
return new Identity({ did }, context); | ||
}; | ||
|
||
/** | ||
* @hidden | ||
*/ | ||
export async function prepareRegisterIdentityWithCdd( | ||
this: Procedure<RegisterIdentityParams, Identity>, | ||
args: RegisterIdentityWithCddParams | ||
): Promise<TransactionSpec<Identity, ExtrinsicParams<'identity', 'cddRegisterDidWithCdd'>>> { | ||
const { | ||
context: { | ||
polymeshApi: { | ||
tx: { identity }, | ||
}, | ||
}, | ||
context, | ||
} = this; | ||
const { targetAccount, secondaryAccounts = [], expiry } = args; | ||
|
||
const rawTargetAccount = stringToAccountId(signerToString(targetAccount), context); | ||
const rawSecondaryKeys = secondaryAccounts.map(({ permissions, ...rest }) => | ||
secondaryAccountToMeshSecondaryKey( | ||
{ ...rest, permissions: permissionsLikeToPermissions(permissions, context) }, | ||
context | ||
) | ||
); | ||
const cddExpiry = optionize(dateToMoment)(expiry, context); | ||
|
||
return { | ||
transaction: identity.cddRegisterDidWithCdd, | ||
args: [rawTargetAccount, rawSecondaryKeys, cddExpiry], | ||
resolver: createRegisterIdentityWithDidResolver(context), | ||
}; | ||
} | ||
|
||
/** | ||
* @hidden | ||
*/ | ||
export const registerIdentityWithCdd = (): Procedure<RegisterIdentityWithCddParams, Identity> => | ||
new Procedure(prepareRegisterIdentityWithCdd, { | ||
roles: [{ type: RoleType.CddProvider }], | ||
permissions: { | ||
assets: [], | ||
portfolios: [], | ||
transactions: [TxTags.identity.CddRegisterDidWithCdd], | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters