Skip to content

Commit

Permalink
fix: add support for new investor uniquenes claim v2
Browse files Browse the repository at this point in the history
  • Loading branch information
VictorVicente committed Apr 7, 2021
1 parent 46beef3 commit 3aa040a
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/Claims.ts
Expand Up @@ -181,7 +181,7 @@ export class Claims {
targets?: (string | Identity)[];
trustedClaimIssuers?: (string | Identity)[];
scope?: Scope;
claimTypes?: ClaimType[];
claimTypes?: Exclude<ClaimType, ClaimType.InvestorUniquenessV2>[];
includeExpired?: boolean;
size?: number;
start?: number;
Expand Down
44 changes: 33 additions & 11 deletions src/api/procedures/__tests__/addInvestorUniquenessClaim.ts
Expand Up @@ -3,6 +3,7 @@ import {
IdentityId,
InvestorZKProofData,
Moment,
Scope as MeshScope,
ScopeClaimProof as MeshScopeClaimProof,
ScopeId,
Ticker,
Expand All @@ -18,7 +19,7 @@ import {
import { Context } from '~/internal';
import { dsMockUtils, entityMockUtils, procedureMockUtils } from '~/testUtils/mocks';
import { Mocked } from '~/testUtils/types';
import { Claim, ClaimType, ScopeType } from '~/types';
import { Claim, ClaimType, Scope, ScopeType } from '~/types';
import { ScopeClaimProof } from '~/types/internal';
import * as utilsConversionModule from '~/utils/conversion';

Expand All @@ -27,6 +28,7 @@ describe('addInvestorUniquenessClaim procedure', () => {
let did: string;
let ticker: string;
let cddId: string;
let scope: Scope;
let scopeId: string;
let proof: string;
let proofScopeIdWellformed: string;
Expand All @@ -43,12 +45,15 @@ describe('addInvestorUniquenessClaim procedure', () => {
[ScopeClaimProof, string, Context],
MeshScopeClaimProof
>;
let scopeToMeshScopeStub: sinon.SinonStub<[Scope, Context], MeshScope>;
let stringToScopeIdStub: sinon.SinonStub<[string, Context], ScopeId>;
let dateToMomentStub: sinon.SinonStub<[Date, Context], Moment>;
let rawDid: IdentityId;
let rawTicker: Ticker;
let rawScope: MeshScope;
let rawScopeId: ScopeId;
let rawClaim: MeshClaim;
let rawClaimV2: MeshClaim;
let rawProof: InvestorZKProofData;
let rawScopeClaimProof: MeshScopeClaimProof;
let rawExpiry: Moment;
Expand All @@ -62,6 +67,7 @@ describe('addInvestorUniquenessClaim procedure', () => {

ticker = 'SOME_TOKEN';
cddId = 'someCddId';
scope = { type: ScopeType.Ticker, value: ticker };
scopeId = 'someScopeId';
proof = 'someProof';
proofScopeIdWellformed = 'someProofScopeIdWellformed';
Expand Down Expand Up @@ -91,7 +97,7 @@ describe('addInvestorUniquenessClaim procedure', () => {
);
dateToMomentStub = sinon.stub(utilsConversionModule, 'dateToMoment');
stringToScopeIdStub = sinon.stub(utilsConversionModule, 'stringToScopeId');

scopeToMeshScopeStub = sinon.stub(utilsConversionModule, 'scopeToMeshScope');
rawDid = dsMockUtils.createMockIdentityId(did);
rawTicker = dsMockUtils.createMockTicker(ticker);
rawClaim = dsMockUtils.createMockClaim({
Expand All @@ -101,6 +107,10 @@ describe('addInvestorUniquenessClaim procedure', () => {
dsMockUtils.createMockCddId(cddId),
],
});
rawClaimV2 = dsMockUtils.createMockClaim({
InvestorUniquenessV2: dsMockUtils.createMockCddId(cddId),
});
rawScope = dsMockUtils.createMockScope({ Ticker: rawTicker });
rawScopeId = dsMockUtils.createMockScopeId(scopeId);
rawProof = dsMockUtils.createMockInvestorZKProofData(proof);
rawScopeClaimProof = dsMockUtils.createMockScopeClaimProof({
Expand All @@ -126,19 +136,29 @@ describe('addInvestorUniquenessClaim procedure', () => {
.withArgs(
{
type: ClaimType.InvestorUniqueness,
scope: { type: ScopeType.Ticker, value: ticker },
scope,
cddId,
scopeId,
},
mockContext
)
.returns(rawClaim);
claimToMeshClaimStub
.withArgs(
{
type: ClaimType.InvestorUniquenessV2,
cddId,
},
mockContext
)
.returns(rawClaimV2);
stringToInvestorZKProofDataStub.withArgs(proof, mockContext).returns(rawProof);
scopeClaimProofToMeshScopeClaimProofStub
.withArgs(scopeClaimProof, scopeId, mockContext)
.returns(rawScopeClaimProof);
dateToMomentStub.withArgs(expiry, mockContext).returns(rawExpiry);
stringToScopeIdStub.withArgs(scopeId, mockContext).returns(rawScopeId);
scopeToMeshScopeStub.withArgs(scope, mockContext).returns(rawScope);
});

afterEach(() => {
Expand All @@ -163,7 +183,7 @@ describe('addInvestorUniquenessClaim procedure', () => {
);

await prepareAddInvestorUniquenessClaim.call(proc, {
scope: { type: ScopeType.Ticker, value: ticker },
scope,
proof,
cddId,
scopeId,
Expand All @@ -181,7 +201,7 @@ describe('addInvestorUniquenessClaim procedure', () => {
);

await prepareAddInvestorUniquenessClaim.call(proc, {
scope: { type: ScopeType.Ticker, value: ticker },
scope,
proof,
cddId,
scopeId,
Expand All @@ -208,7 +228,7 @@ describe('addInvestorUniquenessClaim procedure', () => {
);

await prepareAddInvestorUniquenessClaim.call(proc, {
scope: { type: ScopeType.Ticker, value: ticker },
scope,
proof: scopeClaimProof,
cddId,
scopeId,
Expand All @@ -220,13 +240,14 @@ describe('addInvestorUniquenessClaim procedure', () => {
addInvestorUniquenessClaimV2Transaction,
{},
rawDid,
rawClaim,
rawScope,
rawClaimV2,
rawScopeClaimProof,
rawExpiry
);

await prepareAddInvestorUniquenessClaim.call(proc, {
scope: { type: ScopeType.Ticker, value: ticker },
scope,
proof: scopeClaimProof,
cddId,
scopeId,
Expand All @@ -237,15 +258,16 @@ describe('addInvestorUniquenessClaim procedure', () => {
addInvestorUniquenessClaimV2Transaction,
{},
rawDid,
rawClaim,
rawScope,
rawClaimV2,
rawScopeClaimProof,
null
);
});

test('should throw an error if the expiry date is in the past', async () => {
const commonArgs = {
scope: { type: ScopeType.Ticker, value: ticker },
scope,
cddId,
scopeId,
expiry: new Date('10/14/1987'),
Expand All @@ -267,7 +289,7 @@ describe('addInvestorUniquenessClaim procedure', () => {
describe('getAuthorization', () => {
test('should return the appropriate roles and permissions', () => {
const commonArgs = {
scope: { type: ScopeType.Ticker, value: ticker },
scope,
cddId,
scopeId,
};
Expand Down
11 changes: 7 additions & 4 deletions src/api/procedures/addInvestorUniquenessClaim.ts
Expand Up @@ -6,6 +6,7 @@ import {
claimToMeshClaim,
dateToMoment,
scopeClaimProofToMeshScopeClaimProof,
scopeToMeshScope,
stringToIdentityId,
stringToInvestorZKProofData,
} from '~/utils/conversion';
Expand Down Expand Up @@ -43,12 +44,12 @@ export async function prepareAddInvestorUniquenessClaim(
}

const meshIdentityId = stringToIdentityId(did, context);
const meshClaim = claimToMeshClaim(
{ type: ClaimType.InvestorUniqueness, scope, cddId, scopeId },
context
);
const meshExpiry = expiry ? dateToMoment(expiry, context) : null;
if (typeof proof === 'string') {
const meshClaim = claimToMeshClaim(
{ type: ClaimType.InvestorUniqueness, scope, cddId, scopeId },
context
);
this.addTransaction(
tx.identity.addInvestorUniquenessClaim,
{},
Expand All @@ -58,10 +59,12 @@ export async function prepareAddInvestorUniquenessClaim(
meshExpiry
);
} else {
const meshClaim = claimToMeshClaim({ type: ClaimType.InvestorUniquenessV2, cddId }, context);
this.addTransaction(
tx.identity.addInvestorUniquenessClaimV2,
{},
meshIdentityId,
scopeToMeshScope(scope, context),
meshClaim,
scopeClaimProofToMeshScopeClaimProof(proof, scopeId, context),
meshExpiry
Expand Down
4 changes: 2 additions & 2 deletions src/base/Context.ts
Expand Up @@ -671,7 +671,7 @@ export class Context {
public async getIdentityClaimsFromMiddleware(args: {
targets?: (string | Identity)[];
trustedClaimIssuers?: (string | Identity)[];
claimTypes?: ClaimType[];
claimTypes?: Exclude<ClaimType, ClaimType.InvestorUniquenessV2>[];
includeExpired?: boolean;
size?: number;
start?: number;
Expand Down Expand Up @@ -747,7 +747,7 @@ export class Context {
opts: {
targets?: (string | Identity)[];
trustedClaimIssuers?: (string | Identity)[];
claimTypes?: ClaimType[];
claimTypes?: Exclude<ClaimType, ClaimType.InvestorUniquenessV2>[];
includeExpired?: boolean;
size?: number;
start?: number;
Expand Down
1 change: 1 addition & 0 deletions src/testUtils/mocks/dataSources.ts
Expand Up @@ -1966,6 +1966,7 @@ export const createMockClaim = (
| { Exempted: Scope }
| { Blocked: Scope }
| { InvestorUniqueness: [Scope, ScopeId, CddId] }
| { InvestorUniquenessV2: CddId }
| 'NoData'
): Claim => createMockEnum(claim) as Claim;

Expand Down
15 changes: 13 additions & 2 deletions src/types/index.ts
Expand Up @@ -292,6 +292,7 @@ export enum ClaimType {
Blocked = 'Blocked',
InvestorUniqueness = 'InvestorUniqueness',
NoData = 'NoData',
InvestorUniquenessV2 = 'InvestorUniquenessV2',
}

export type CddClaim = { type: ClaimType.CustomerDueDiligence; id: string };
Expand All @@ -303,6 +304,11 @@ export type InvestorUniquenessClaim = {
scopeId: string;
};

export type InvestorUniquenessV2Claim = {
type: ClaimType.InvestorUniquenessV2;
cddId: string;
};

export type ScopedClaim =
| { type: ClaimType.Jurisdiction; code: CountryCode; scope: Scope }
| InvestorUniquenessClaim
Expand All @@ -313,11 +319,12 @@ export type ScopedClaim =
| ClaimType.Jurisdiction
| ClaimType.CustomerDueDiligence
| ClaimType.InvestorUniqueness
| ClaimType.InvestorUniquenessV2
>;
scope: Scope;
};

export type UnscopedClaim = { type: ClaimType.NoData } | CddClaim;
export type UnscopedClaim = { type: ClaimType.NoData } | CddClaim | InvestorUniquenessV2Claim;

export type Claim = ScopedClaim | UnscopedClaim;

Expand All @@ -327,7 +334,11 @@ export type Claim = ScopedClaim | UnscopedClaim;
export function isScopedClaim(claim: Claim): claim is ScopedClaim {
const { type } = claim;

return ![ClaimType.NoData, ClaimType.CustomerDueDiligence].includes(type);
return ![
ClaimType.NoData,
ClaimType.CustomerDueDiligence,
ClaimType.InvestorUniquenessV2,
].includes(type);
}

/**
Expand Down
26 changes: 26 additions & 0 deletions src/utils/__tests__/conversion.ts
Expand Up @@ -2367,6 +2367,21 @@ describe('claimToMeshClaim and meshClaimToClaim', () => {
result = claimToMeshClaim(value, context);

expect(result).toBe(fakeResult);

value = {
type: ClaimType.InvestorUniquenessV2,
cddId: 'someCddId',
};

createTypeStub
.withArgs('Claim', {
[value.type]: [stringToCddId(value.cddId, context)],
})
.returns(fakeResult);

result = claimToMeshClaim(value, context);

expect(result).toBe(fakeResult);
});

test('meshClaimToClaim should convert a polkadot Claim object to a Claim', () => {
Expand Down Expand Up @@ -2517,6 +2532,17 @@ describe('claimToMeshClaim and meshClaimToClaim', () => {

result = meshClaimToClaim(claim);
expect(result).toEqual(fakeResult);

fakeResult = {
type: ClaimType.InvestorUniquenessV2,
cddId: 'cddId',
};
claim = dsMockUtils.createMockClaim({
InvestorUniquenessV2: dsMockUtils.createMockCddId(fakeResult.cddId),
});

result = meshClaimToClaim(claim);
expect(result).toEqual(fakeResult);
});
});

Expand Down
11 changes: 11 additions & 0 deletions src/utils/conversion.ts
Expand Up @@ -1504,6 +1504,10 @@ export function claimToMeshClaim(claim: Claim, context: Context): MeshClaim {
);
break;
}
case ClaimType.InvestorUniquenessV2: {
value = tuple(stringToCddId(claim.cddId, context));
break;
}
default: {
value = scopeToMeshScope(claim.scope, context);
}
Expand Down Expand Up @@ -1621,6 +1625,13 @@ export function meshClaimToClaim(claim: MeshClaim): Claim {
};
}

if (claim.isInvestorUniquenessV2) {
return {
type: ClaimType.InvestorUniquenessV2,
cddId: cddIdToString(claim.asInvestorUniquenessV2),
};
}

return {
type: ClaimType.Blocked,
scope: meshScopeToScope(claim.asBlocked),
Expand Down

0 comments on commit 3aa040a

Please sign in to comment.