Skip to content

Commit

Permalink
feat: 🎸 test instruction mediator functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
polymath-eric committed Feb 21, 2024
1 parent 5916be0 commit 7d5cf3c
Show file tree
Hide file tree
Showing 11 changed files with 286 additions and 10 deletions.
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ services:
ports:
- 3002:3000
environment:
START_BLOCK: 1
NETWORK_ENDPOINT: ws://alice:9944
NETWORK_HTTP_ENDPOINT: http://alice:9933
DB_USER: '${PG_USER:-postgres}'
Expand Down
7 changes: 4 additions & 3 deletions envs/6.1.2.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
CHAIN_IMAGE=polymeshassociation/polymesh:6.1.2-testnet-debian
SUBQUERY_INDEXER_IMAGE=polymeshassociation/polymesh-subquery:v10.1.0
CHAIN_IMAGE=polymeshassociation/polymesh:6.2.0-staging-debian
SUBQUERY_INDEXER_IMAGE=polymeshassociation/polymesh-subquery:v12.2.0-alpha.4

SUBQUERY_QUERY_IMAGE=onfinality/subql-query:v2.6.0
REST_IMAGE=polymeshassociation/polymesh-rest-api:v5.0.0-alpha.5
REST_IMAGE=polymeshassociation/polymesh-rest-api:v5.0.0-alpha.9
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"@polkadot/wasm-crypto": "7.2.2",
"@polymeshassociation/hashicorp-vault-signing-manager": "^3.0.1",
"@polymeshassociation/local-signing-manager": "^3.1.0",
"@polymeshassociation/polymesh-sdk": "24.0.0-alpha.6",
"@polymeshassociation/polymesh-sdk": "24.0.0-alpha.12",
"cross-fetch": "^4.0.0",
"dotenv": "^16.0.3"
},
Expand Down
86 changes: 86 additions & 0 deletions src/__tests__/rest/assets/required-mediators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { expectBasicTxInfo } from '~/__tests__/rest/utils';
import { TestFactory } from '~/helpers';
import { RestClient } from '~/rest';
import { assetMediatorsParams, createAssetParams } from '~/rest/assets';
import { ProcessMode } from '~/rest/common';
import { Identity } from '~/rest/identities/interfaces';

const handles = ['issuer'];
let factory: TestFactory;

describe('AssetDocument', () => {
let restClient: RestClient;
let signer: string;
let issuer: Identity;
let assetParams: ReturnType<typeof createAssetParams>;
let asset: string;

beforeAll(async () => {
factory = await TestFactory.create({ handles });
({ restClient } = factory);
issuer = factory.getSignerIdentity(handles[0]);

asset = factory.nextTicker();
signer = issuer.signer;

assetParams = createAssetParams(asset, {
options: { processMode: ProcessMode.Submit, signer },
});
await restClient.assets.createAsset(assetParams);
});

afterAll(async () => {
await factory.close();
});

it('should add asset mediators', async () => {
const params = assetMediatorsParams([issuer.did], {
options: { processMode: ProcessMode.Submit, signer },
});
const txData = await restClient.assets.addAssetMediators(asset, params);

expect(txData).toMatchObject({
transactions: expect.arrayContaining([
{
transactionTag: 'asset.addMandatoryMediators',
type: 'single',
...expectBasicTxInfo,
},
]),
});
});

it('should get the asset mediators', async () => {
const result = await restClient.assets.getAssetMediators(asset);

expect(result).toEqual(
expect.objectContaining({
mediators: [issuer.did],
})
);
});

it('should remove asset mediators', async () => {
const params = assetMediatorsParams([issuer.did], {
options: { processMode: ProcessMode.Submit, signer },
});

const txData = await restClient.assets.removeAssetMediators(asset, params);

expect(txData).toMatchObject({
transactions: expect.arrayContaining([
{
transactionTag: 'asset.removeMandatoryMediators',
type: 'single',
...expectBasicTxInfo,
},
]),
});

const result = await restClient.assets.getAssetMediators(asset);

expect(result).toEqual({
mediators: [],
});
});
});
2 changes: 1 addition & 1 deletion src/__tests__/rest/nfts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ describe('NFTs', () => {
expect(result).toMatchObject({
transactions: expect.arrayContaining([
expect.objectContaining({
transactionTag: 'settlement.addAndAffirmInstruction',
transactionTag: 'settlement.addAndAffirmWithMediators',
...expectBasicTxInfo,
}),
]),
Expand Down
139 changes: 139 additions & 0 deletions src/__tests__/rest/settlements/asMediator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { expectBasicTxInfo } from '~/__tests__/rest/utils';
import { TestFactory } from '~/helpers';
import { RestClient } from '~/rest';
import { createAssetParams } from '~/rest/assets/params';
import { ProcessMode } from '~/rest/common';
import { Identity } from '~/rest/identities/interfaces';
import { fungibleInstructionParams, venueParams } from '~/rest/settlements';

const handles = ['issuer', 'investor', 'mediator'];
let factory: TestFactory;

describe('Create and trading an Asset with mediators', () => {
let restClient: RestClient;
let signer: string;
let issuer: Identity;
let investor: Identity;
let mediator: Identity;
let venueId: string;
let assetParams: ReturnType<typeof createAssetParams>;
let ticker: string;
let instructionId: string;

beforeAll(async () => {
factory = await TestFactory.create({ handles });
({ restClient } = factory);
issuer = factory.getSignerIdentity(handles[0]);
investor = factory.getSignerIdentity(handles[1]);
mediator = factory.getSignerIdentity(handles[2]);

ticker = factory.nextTicker();
signer = issuer.signer;

assetParams = createAssetParams(ticker, {
options: { processMode: ProcessMode.Submit, signer },
});
});

afterAll(async () => {
await factory.close();
});

it('should create and fetch the Asset', async () => {
await restClient.assets.createAsset(assetParams);

const asset = await restClient.assets.getAsset(ticker);
expect(asset).toMatchObject({
name: assetParams.name,
assetType: assetParams.assetType,
});
});

it('should create a Venue to trade the Asset', async () => {
const params = venueParams({
options: { processMode: ProcessMode.Submit, signer },
});
const txData = await restClient.settlements.createVenue(params);

({ venue: venueId } = txData as { venue: string });
});

it('should create an instruction', async () => {
const sender = issuer.did;
const receiver = investor.did;
const params = fungibleInstructionParams(
ticker,
sender,
receiver,
{
options: { processMode: ProcessMode.Submit, signer },
},
{
mediators: [mediator.did],
}
);
const instructionData = await restClient.settlements.createInstruction(venueId, params);

expect(instructionData).toMatchObject({
instruction: expect.any(String),
transactions: expect.arrayContaining([
{
transactionTag: 'settlement.addAndAffirmWithMediators',
type: 'single',
...expectBasicTxInfo,
},
]),
});

instructionId = (instructionData as unknown as { instruction: string }).instruction;
});

it('should allow the mediator to affirm the instruction', async () => {
const affirmResult = await restClient.settlements.affirmInstructionAsMediator(
instructionId,
new Date('2055/01/01'),
{
options: { processMode: ProcessMode.Submit, signer: mediator.signer },
}
);

expect(affirmResult).toMatchObject({
transactions: expect.arrayContaining([
expect.objectContaining({
transactionTag: 'settlement.affirmInstructionAsMediator',
...expectBasicTxInfo,
}),
]),
});
});

it('should allow the mediator to withdraw affirmation', async () => {
const withdrawResult = await restClient.settlements.withdrawAsMediator(instructionId, {
options: { processMode: ProcessMode.Submit, signer: mediator.signer },
});

expect(withdrawResult).toMatchObject({
transactions: expect.arrayContaining([
expect.objectContaining({
transactionTag: 'settlement.withdrawAffirmationAsMediator',
...expectBasicTxInfo,
}),
]),
});
});

it('should allow the mediator to reject the instruction', async () => {
const affirmResult = await restClient.settlements.rejectAsMediator(instructionId, {
options: { processMode: ProcessMode.Submit, signer: mediator.signer },
});

expect(affirmResult).toMatchObject({
transactions: expect.arrayContaining([
expect.objectContaining({
transactionTag: 'settlement.rejectInstructionAsMediator',
...expectBasicTxInfo,
}),
]),
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ describe('Create and trading an Asset', () => {
expect(instructionData).toMatchObject({
transactions: expect.arrayContaining([
{
transactionTag: expect.stringMatching(/settlement.addAndAffirmInstruction(WithMemo)?/),
transactionTag: expect.stringMatching('settlement.addAndAffirmWithMediators'),
type: 'single',
...expectBasicTxInfo,
},
Expand Down
19 changes: 19 additions & 0 deletions src/rest/assets/client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
assetMediatorsParams,
createAssetParams,
createMetadataParams,
MetadataType,
Expand Down Expand Up @@ -52,6 +53,10 @@ export class Assets {
return this.client.get(`assets/${ticker}/documents`);
}

public async getAssetMediators(ticker: string): Promise<unknown> {
return this.client.get(`assets/${ticker}/required-mediators`);
}

public async setDocuments(
ticker: string,
params: ReturnType<typeof setAssetDocumentParams>
Expand All @@ -65,4 +70,18 @@ export class Assets {
): Promise<PostResult> {
return this.client.post(`assets/${ticker}/redeem`, params);
}

public async addAssetMediators(
ticker: string,
params: ReturnType<typeof assetMediatorsParams>
): Promise<PostResult> {
return this.client.post(`assets/${ticker}/add-required-mediators`, params);
}

public async removeAssetMediators(
ticker: string,
params: ReturnType<typeof assetMediatorsParams>
): Promise<PostResult> {
return this.client.post(`assets/${ticker}/remove-required-mediators`, params);
}
}
7 changes: 7 additions & 0 deletions src/rest/assets/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,10 @@ export const redeemTokenParams = (from: string, base: TxBase, extras: TxExtras =
...extras,
...base,
} as const);

export const assetMediatorsParams = (mediators: string[], base: TxBase, extras: TxExtras = {}) =>
({
mediators,
...extras,
...base,
} as const);
23 changes: 23 additions & 0 deletions src/rest/settlements/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,29 @@ export class Settlements {
return this.client.post(`/instructions/${instructionId}/affirm`, { ...txBase });
}

public async affirmInstructionAsMediator(
instructionId: string,
expiry: Date | undefined,
txBase: TxBase
): Promise<PostResult> {
return this.client.post(`/instructions/${instructionId}/affirm-as-mediator`, {
expiry,
...txBase,
});
}

public async withdrawAsMediator(instructionId: string, txBase: TxBase): Promise<PostResult> {
return this.client.post(`/instructions/${instructionId}/withdraw-as-mediator`, {
...txBase,
});
}

public async rejectAsMediator(instructionId: string, txBase: TxBase): Promise<PostResult> {
return this.client.post(`/instructions/${instructionId}/reject-as-mediator`, {
...txBase,
});
}

public async getInstruction(instructionId: string): Promise<unknown> {
return this.client.get(`/instructions/${instructionId}`);
}
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1415,10 +1415,10 @@
dependencies:
"@polymeshassociation/signing-manager-types" "^3.2.0"

"@polymeshassociation/[email protected].6":
version "24.0.0-alpha.6"
resolved "https://registry.yarnpkg.com/@polymeshassociation/polymesh-sdk/-/polymesh-sdk-24.0.0-alpha.6.tgz#51c644d20f993968930a16756a5faca824f4a251"
integrity sha512-+fth+uNLse4/idIThhMOGWc2e9uyHLFLZ/Ga+TWPHi95xKJfuXvJlIApNq5ZVXg3+mk9obOJUK3Rzk0dBRwifg==
"@polymeshassociation/[email protected].12":
version "24.0.0-alpha.12"
resolved "https://registry.yarnpkg.com/@polymeshassociation/polymesh-sdk/-/polymesh-sdk-24.0.0-alpha.12.tgz#7021b2591e48050d8e4074c4ba2ee9c6b58e2dba"
integrity sha512-sm6MZOnIFQiQUGc07Te7QKR9xBIripKFEOG6CNONyIVV2xzQCBbSR+zozF/kmsUkgEAYeIYxN5ywfFxLnlOfyA==
dependencies:
"@apollo/client" "^3.8.1"
"@polkadot/api" "10.9.1"
Expand Down

0 comments on commit 7d5cf3c

Please sign in to comment.