Skip to content

Commit

Permalink
feat: finish implementation and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
monitz87 committed May 8, 2020
1 parent 7ff1c33 commit ddadd2b
Show file tree
Hide file tree
Showing 16 changed files with 274 additions and 80 deletions.
2 changes: 1 addition & 1 deletion src/Polymesh.ts
Expand Up @@ -14,7 +14,7 @@ import { signerToSignatory, tickerToString, valueToDid } from '~/utils';
* Main entry point of the Polymesh SDK
*/
export class Polymesh {
private context: Context = {} as Context;
public context: Context = {} as Context;

/**
* @hidden
Expand Down
6 changes: 3 additions & 3 deletions src/api/entities/SecurityToken/Compliance/Rules.ts
Expand Up @@ -36,16 +36,16 @@ export class Rules extends Namespace<SecurityToken> {
parent: { ticker },
context: {
polymeshApi: {
query: { generalTm },
query: { complianceManager },
},
},
context,
} = this;
// TODO: queryMulti
const rawTicker = stringToTicker(ticker, context);
const [tokenRules, defaultClaimIssuers] = await Promise.all([
generalTm.assetRulesMap(rawTicker),
generalTm.trustedClaimIssuer(rawTicker),
complianceManager.assetRulesMap(rawTicker),
complianceManager.trustedClaimIssuer(rawTicker),
]);

return tokenRules.rules.map(assetTransferRule => {
Expand Down
Expand Up @@ -33,7 +33,7 @@ export class TrustedClaimIssuers extends Namespace<SecurityToken> {
parent: { ticker },
} = this;

const claimIssuers = await context.polymeshApi.query.generalTm.trustedClaimIssuer(
const claimIssuers = await context.polymeshApi.query.complianceManager.trustedClaimIssuer(
stringToTicker(ticker, context)
);

Expand Down
4 changes: 2 additions & 2 deletions src/api/entities/SecurityToken/Compliance/__tests__/Rules.ts
Expand Up @@ -125,7 +125,7 @@ describe('Rules class', () => {
issuers: [],
});

polkadotMockUtils.createQueryStub('generalTm', 'assetRulesMap', {
polkadotMockUtils.createQueryStub('complianceManager', 'assetRulesMap', {
returnValue: {
rules: [
polkadotMockUtils.createMockAssetTransferRule({
Expand Down Expand Up @@ -163,7 +163,7 @@ describe('Rules class', () => {
},
});

polkadotMockUtils.createQueryStub('generalTm', 'trustedClaimIssuer', {
polkadotMockUtils.createQueryStub('complianceManager', 'trustedClaimIssuer', {
returnValue: defaultClaimIssuers,
});

Expand Down
Expand Up @@ -84,7 +84,7 @@ describe('TrustedClaimIssuers class', () => {

stringToTickerStub.withArgs(ticker, context).returns(rawTicker);
polkadotMockUtils
.createQueryStub('generalTm', 'trustedClaimIssuer')
.createQueryStub('complianceManager', 'trustedClaimIssuer')
.withArgs(rawTicker)
.resolves(claimIssuers);

Expand Down
21 changes: 11 additions & 10 deletions src/api/entities/SecurityToken/Transfers.ts
@@ -1,19 +1,21 @@
import { u8 } from '@polkadot/types';
import BigNumber from 'bignumber.js';

import { Identity } from '~/api/entities/Identity';
import { toggleFreezeTransfers } from '~/api/procedures';
import { Namespace, TransactionQueue } from '~/base';
import { CanTransferResult } from '~/polkadot';
import { TransferStatus } from '~/types';
import {
boolToBoolean,
canTransferResultToTransferStatus,
numberToBalance,
stringToAccountId,
stringToIdentityId,
stringToTicker,
u8ToTransferStatus,
valueToDid,
} from '~/utils';
import { DUMMY_ACCOUNT_ID } from '~/utils/constants';

import { SecurityToken } from './';

Expand Down Expand Up @@ -63,6 +65,10 @@ export class Transfers extends Namespace<SecurityToken> {

/**
* Check whether it is possible to transfer a certain amount of this asset between two identities
*
* @param args.from - sender identity (optional, defaults to the current identity)
* @param args.to - receiver identity
* @param args.amount - amount of tokens to transfer
*/
public async canTransfer(args: {
from?: string | Identity;
Expand All @@ -72,7 +78,7 @@ export class Transfers extends Namespace<SecurityToken> {
const {
parent: { ticker },
context: {
polymeshApi: { rpc, query },
polymeshApi: { rpc },
},
context,
} = this;
Expand All @@ -86,22 +92,17 @@ export class Transfers extends Namespace<SecurityToken> {
* The RPC requires a sender account ID (although it's not being used at the moment). We use the current account
* or a dummy account (Alice's in testnet) if the SDK was instanced without one
*/
const senderAddress =
context.currentPair?.address || '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY';

const hash = await query.system.parentHash();
const senderAddress = context.currentPair?.address || DUMMY_ACCOUNT_ID;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const status: u8 = await (rpc as any).asset.canTransfer(
const res: CanTransferResult = await (rpc as any).asset.canTransfer(
stringToAccountId(senderAddress, context),
stringToTicker(ticker, context),
stringToIdentityId(fromDid, context),
stringToIdentityId(toDid, context),
numberToBalance(amount, context)
);

console.log('STATUS', status);

return u8ToTransferStatus(status);
return canTransferResultToTransferStatus(res);
}
}
100 changes: 98 additions & 2 deletions src/api/entities/SecurityToken/__tests__/Transfers.ts
@@ -1,11 +1,17 @@
import sinon from 'sinon';
import { AccountId, Balance } from '@polkadot/types/interfaces';
import BigNumber from 'bignumber.js';
import sinon, { SinonStub } from 'sinon';

import { toggleFreezeTransfers } from '~/api/procedures';
import { Params } from '~/api/procedures/toggleFreezeTransfers';
import { Namespace, TransactionQueue } from '~/base';
import { Context } from '~/context';
import { IdentityId, Ticker } from '~/polkadot';
import { entityMockUtils, polkadotMockUtils } from '~/testUtils/mocks';
import { Mocked } from '~/testUtils/types';
import { TransferStatus } from '~/types';
import * as utilsModule from '~/utils';
import { DUMMY_ACCOUNT_ID } from '~/utils/constants';

import { SecurityToken } from '../';
import { Transfers } from '../Transfers';
Expand All @@ -14,7 +20,7 @@ describe('Transfers class', () => {
let mockContext: Mocked<Context>;
let mockSecurityToken: Mocked<SecurityToken>;
let transfers: Transfers;
let prepareStub: sinon.SinonStub<
let prepareStub: SinonStub<
[Params, Context],
Promise<TransactionQueue<SecurityToken, unknown[][]>>
>;
Expand Down Expand Up @@ -85,4 +91,94 @@ describe('Transfers class', () => {
expect(result).toBe(boolValue);
});
});

describe('method: canTransfer', () => {
let stringToAccountIdStub: SinonStub<[string, Context], AccountId>;
let stringToTickerStub: SinonStub<[string, Context], Ticker>;
let stringToIdentityIdStub: SinonStub<[string, Context], IdentityId>;
let numberToBalanceStub: SinonStub<[number | BigNumber, Context], Balance>;

let statusCode: number;
let fromDid: string;
let toDid: string;
let ticker: string;
let amount: BigNumber;
let accountId: string;

let rawAccountId: AccountId;
let rawFromDid: IdentityId;
let rawToDid: IdentityId;
let rawTicker: Ticker;
let rawAmount: Balance;

beforeAll(() => {
stringToAccountIdStub = sinon.stub(utilsModule, 'stringToAccountId');
stringToTickerStub = sinon.stub(utilsModule, 'stringToTicker');
stringToIdentityIdStub = sinon.stub(utilsModule, 'stringToIdentityId');
numberToBalanceStub = sinon.stub(utilsModule, 'numberToBalance');

statusCode = 81;
fromDid = 'fromDid';
toDid = 'toDid';
({ ticker } = mockSecurityToken);
amount = new BigNumber(100);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
accountId = mockContext.currentPair?.address!;

rawAccountId = polkadotMockUtils.createMockAccountId(accountId);
rawFromDid = polkadotMockUtils.createMockIdentityId(fromDid);
rawToDid = polkadotMockUtils.createMockIdentityId(toDid);
rawTicker = polkadotMockUtils.createMockTicker(ticker);
rawAmount = polkadotMockUtils.createMockBalance(amount.toNumber());
});

beforeEach(() => {
stringToAccountIdStub.withArgs(accountId, mockContext).returns(rawAccountId);
stringToTickerStub.withArgs(ticker, mockContext).returns(rawTicker);
stringToIdentityIdStub.withArgs(fromDid, mockContext).returns(rawFromDid);
stringToIdentityIdStub.withArgs(toDid, mockContext).returns(rawToDid);
numberToBalanceStub.withArgs(amount, mockContext).returns(rawAmount);
});

test('should return a status value representing whether the transaction can be made from the current identity', async () => {
const currentDid = mockContext.getCurrentIdentity().did;

const rawCurrentDid = polkadotMockUtils.createMockIdentityId(currentDid);
const rawDummyAccountId = polkadotMockUtils.createMockAccountId(DUMMY_ACCOUNT_ID);

stringToIdentityIdStub.withArgs(currentDid, mockContext).returns(rawCurrentDid);

// also test the case where the SDK was instanced without an account
mockContext.currentPair = undefined;
stringToAccountIdStub.withArgs(DUMMY_ACCOUNT_ID, mockContext).returns(rawDummyAccountId);

const rawResponse = polkadotMockUtils.createMockCanTransferResult({
Ok: polkadotMockUtils.createMockU8(statusCode),
});

polkadotMockUtils
.createRpcStub('asset', 'canTransfer')
.withArgs(rawDummyAccountId, rawTicker, rawCurrentDid, rawToDid, rawAmount)
.returns(rawResponse);

const result = await transfers.canTransfer({ to: toDid, amount });

expect(result).toBe(TransferStatus.Success);
});

test('should return a status value representing whether the transaction can be made from another identity', async () => {
const rawResponse = polkadotMockUtils.createMockCanTransferResult({
Ok: polkadotMockUtils.createMockU8(statusCode),
});

polkadotMockUtils
.createRpcStub('asset', 'canTransfer')
.withArgs(rawAccountId, rawTicker, rawFromDid, rawToDid, rawAmount)
.returns(rawResponse);

const result = await transfers.canTransfer({ from: fromDid, to: toDid, amount });

expect(result).toBe(TransferStatus.Success);
});
});
});
9 changes: 6 additions & 3 deletions src/api/procedures/__tests__/setTokenRules.ts
Expand Up @@ -73,12 +73,15 @@ describe('setTokenTrustedClaimIssuers procedure', () => {
beforeEach(() => {
addTransactionStub = procedureMockUtils.getAddTransactionStub();

assetRulesMapStub = polkadotMockUtils.createQueryStub('generalTm', 'assetRulesMap', {
assetRulesMapStub = polkadotMockUtils.createQueryStub('complianceManager', 'assetRulesMap', {
returnValue: [],
});

resetActiveRulesTransaction = polkadotMockUtils.createTxStub('generalTm', 'resetActiveRules');
addActiveRuleTransaction = polkadotMockUtils.createTxStub('generalTm', 'addActiveRule');
resetActiveRulesTransaction = polkadotMockUtils.createTxStub(
'complianceManager',
'resetActiveRules'
);
addActiveRuleTransaction = polkadotMockUtils.createTxStub('complianceManager', 'addActiveRule');

mockContext = polkadotMockUtils.getContextInstance();

Expand Down
14 changes: 9 additions & 5 deletions src/api/procedures/__tests__/setTokenTrustedClaimIssuers.ts
Expand Up @@ -54,19 +54,23 @@ describe('setTokenTrustedClaimIssuers procedure', () => {
beforeEach(() => {
addTransactionStub = procedureMockUtils.getAddTransactionStub();

trustedClaimIssuerStub = polkadotMockUtils.createQueryStub('generalTm', 'trustedClaimIssuer', {
returnValue: [],
});
trustedClaimIssuerStub = polkadotMockUtils.createQueryStub(
'complianceManager',
'trustedClaimIssuer',
{
returnValue: [],
}
);
didRecordsStub = polkadotMockUtils.createQueryStub('identity', 'didRecords', {
size: 1,
});

removeDefaultTrustedClaimIssuersBatchTransaction = polkadotMockUtils.createTxStub(
'generalTm',
'complianceManager',
'removeDefaultTrustedClaimIssuersBatch'
);
addDefaultTrustedClaimIssuersBatchTransaction = polkadotMockUtils.createTxStub(
'generalTm',
'complianceManager',
'addDefaultTrustedClaimIssuersBatch'
);

Expand Down
12 changes: 9 additions & 3 deletions src/api/procedures/setTokenRules.ts
Expand Up @@ -30,7 +30,7 @@ export async function prepareSetTokenRules(

const rawTicker = stringToTicker(ticker, context);

const currentRulesRaw = await query.generalTm.assetRulesMap(rawTicker);
const currentRulesRaw = await query.complianceManager.assetRulesMap(rawTicker);

const currentRules = currentRulesRaw.rules.map(rule => assetTransferRuleToRule(rule).conditions);

Expand Down Expand Up @@ -61,11 +61,17 @@ export async function prepareSetTokenRules(
});

if (currentRules.length) {
this.addTransaction(tx.generalTm.resetActiveRules, {}, rawTicker);
this.addTransaction(tx.complianceManager.resetActiveRules, {}, rawTicker);
}

rawRules.forEach(({ senderRules, receiverRules }) => {
this.addTransaction(tx.generalTm.addActiveRule, {}, rawTicker, senderRules, receiverRules);
this.addTransaction(
tx.complianceManager.addActiveRule,
{},
rawTicker,
senderRules,
receiverRules
);
});

return new SecurityToken({ ticker }, context);
Expand Down
6 changes: 3 additions & 3 deletions src/api/procedures/setTokenTrustedClaimIssuers.ts
Expand Up @@ -31,7 +31,7 @@ export async function prepareSetTokenTrustedClaimIssuers(

const rawTicker = stringToTicker(ticker, context);

const rawCurrentClaimIssuers = await query.generalTm.trustedClaimIssuer(rawTicker);
const rawCurrentClaimIssuers = await query.complianceManager.trustedClaimIssuer(rawTicker);
const currentClaimIssuers = rawCurrentClaimIssuers.map(issuer => identityIdToString(issuer));

if (
Expand Down Expand Up @@ -76,7 +76,7 @@ export async function prepareSetTokenTrustedClaimIssuers(

if (rawCurrentClaimIssuers.length) {
this.addTransaction(
tx.generalTm.removeDefaultTrustedClaimIssuersBatch,
tx.complianceManager.removeDefaultTrustedClaimIssuersBatch,
{},
rawTicker,
rawCurrentClaimIssuers
Expand All @@ -85,7 +85,7 @@ export async function prepareSetTokenTrustedClaimIssuers(

if (rawNewClaimIssuers.length) {
this.addTransaction(
tx.generalTm.addDefaultTrustedClaimIssuersBatch,
tx.complianceManager.addDefaultTrustedClaimIssuersBatch,
{},
rawTicker,
rawNewClaimIssuers
Expand Down
1 change: 0 additions & 1 deletion src/context/index.ts
Expand Up @@ -111,7 +111,6 @@ export class Context {
currentPair.publicKey
);
const did = identityIds.unwrap().asUnique;
console.log('ADDRESS', currentPair.address);

return new Context({ polymeshApi, keyring, pair: { currentPair, did } });
} catch (err) {
Expand Down

0 comments on commit ddadd2b

Please sign in to comment.