Skip to content

Commit

Permalink
Merge pull request #31 from PolymathNetwork/feat/MSDK-33-extend-ticke…
Browse files Browse the repository at this point in the history
…r-period

feat: extend the registration period before it expires
  • Loading branch information
monitz87 authored Mar 12, 2020
2 parents e5f18c9 + def9e45 commit e84c8dc
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 21 deletions.
28 changes: 27 additions & 1 deletion src/api/entities/TickerReservation/__tests__/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Ticker } from '@polymathnetwork/polkadot/types/interfaces';
import { Callback, Codec } from '@polymathnetwork/polkadot/types/types';
import sinon from 'sinon';

import { Entity } from '~/base';
import { reserveTicker } from '~/api/procedures';
import { Entity, TransactionQueue } from '~/base';
import {
createMockAssetType,
createMockBalance,
Expand Down Expand Up @@ -189,4 +191,28 @@ describe('TickerReservation class', () => {
});
});
});

describe('method: extend', () => {
test('should prepare the procedure with the correct arguments and context, and return the resulting transaction queue', async () => {
const ticker = 'TEST';
const context = polkadotMockFactory.getContextInstance();
const tickerReservation = new TickerReservation({ ticker }, context);

const args = {
ticker,
extendPeriod: true,
};

const expectedQueue = ('someQueue' as unknown) as TransactionQueue<TickerReservation>;

sinon
.stub(reserveTicker, 'prepare')
.withArgs(args, context)
.resolves(expectedQueue);

const queue = await tickerReservation.extend();

expect(queue).toBe(expectedQueue);
});
});
});
19 changes: 18 additions & 1 deletion src/api/entities/TickerReservation/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Entity } from '~/base';
import { reserveTicker } from '~/api/procedures';
import { Entity, TransactionQueue } from '~/base';
import { Context } from '~/context';
import { identityIdToString, momentToDate } from '~/utils';

Expand Down Expand Up @@ -89,4 +90,20 @@ export class TickerReservation extends Entity<UniqueIdentifiers> {
status,
};
}

/**
* Extend the reservation time period of the ticker for 60 days from now
* to later use it in the creation of a Security Token.
*/
public async extend(): Promise<TransactionQueue<TickerReservation>> {
const { ticker, context } = this;
const extendPeriod = true;
return reserveTicker.prepare(
{
ticker,
extendPeriod,
},
context
);
}
}
45 changes: 45 additions & 0 deletions src/api/procedures/__tests__/reserveTicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,51 @@ describe('reserveTicker procedure', () => {
);
});

test('should throw an error if extendPeriod property is set to true and the ticker has not been reserved or the reservation has expired', async () => {
const expiryDate = new Date(2019, 1, 1);
mockTickerReservation.mock('details', {
ownerDid: 'someDid',
expiryDate,
status: TickerReservationStatus.Free,
});
const proc = mockProcedure.getMockInstance();
proc.context = mockContext;

return expect(prepareReserveTicker.call(proc, { ...args, extendPeriod: true })).rejects.toThrow(
'Ticker not reserved or the reservation has expired'
);
});

test("should throw an error if extendPeriod property is set to true and the signing account doesn't have enough balance", () => {
const expiryDate = new Date(new Date().getTime() + 1000);
mockTickerReservation.mock('details', {
ownerDid: 'someDid',
expiryDate,
});
mockFactory.createQueryStub('asset', 'tickerRegistrationFee', createMockBalance(600000000));
const proc = mockProcedure.getMockInstance();
proc.context = mockContext;

return expect(prepareReserveTicker.call(proc, { ...args, extendPeriod: true })).rejects.toThrow(
'Not enough POLY balance to pay for ticker period extension'
);
});

test('should throw an error if extendPeriod property is set to true and the signing account is not the ticker owner', () => {
const expiryDate = new Date(new Date().getTime() + 1000);
mockTickerReservation.mock('details', {
ownerDid: 'anotherDid',
expiryDate,
status: TickerReservationStatus.Reserved,
});
const proc = mockProcedure.getMockInstance();
proc.context = mockContext;

return expect(prepareReserveTicker.call(proc, { ...args, extendPeriod: true })).rejects.toThrow(
'You must be the owner of the ticker to extend its reservation period'
);
});

test('should add a register ticker transaction to the queue', async () => {
const proc = mockProcedure.getMockInstance();
proc.context = mockContext;
Expand Down
55 changes: 37 additions & 18 deletions src/api/procedures/reserveTicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { balanceToBigNumber, findEventRecord, stringToTicker, tickerToString } f

export interface ReserveTickerParams {
ticker: string;
extendPeriod?: boolean;
}

/**
Expand Down Expand Up @@ -39,7 +40,7 @@ export async function prepareReserveTicker(
},
context,
} = this;
const { ticker } = args;
const { ticker, extendPeriod = false } = args;

const rawTicker = stringToTicker(ticker, context);

Expand All @@ -49,7 +50,7 @@ export async function prepareReserveTicker(
rawFee,
balance,
{ max_ticker_length: rawMaxTickerLength },
{ expiryDate, status },
{ ownerDid, expiryDate, status },
] = await Promise.all([
query.asset.tickerRegistrationFee(),
context.accountBalance(),
Expand All @@ -65,31 +66,49 @@ export async function prepareReserveTicker(
}

if (status === TickerReservationStatus.Reserved) {
const isPermanent = expiryDate === null;

throw new PolymeshError({
code: ErrorCode.ValidationError,
message: `Ticker "${ticker}" already reserved. The current reservation will ${
!isPermanent ? '' : 'not '
}expire${!isPermanent ? ` at ${expiryDate}` : ''}`,
});
if (!extendPeriod) {
const isPermanent = expiryDate === null;

throw new PolymeshError({
code: ErrorCode.ValidationError,
message: `Ticker "${ticker}" already reserved. The current reservation will ${
!isPermanent ? '' : 'not '
}expire${!isPermanent ? ` at ${expiryDate}` : ''}`,
});
} else if (ownerDid !== context.currentIdentity?.did) {
throw new PolymeshError({
code: ErrorCode.ValidationError,
message: 'You must be the owner of the ticker to extend its reservation period',
});
}
}

const maxTickerLength = rawMaxTickerLength.toNumber();

if (ticker.length > maxTickerLength) {
throw new PolymeshError({
code: ErrorCode.ValidationError,
message: `Ticker length cannot exceed ${maxTickerLength}`,
});
if (!extendPeriod) {
const maxTickerLength = rawMaxTickerLength.toNumber();

if (ticker.length > maxTickerLength) {
throw new PolymeshError({
code: ErrorCode.ValidationError,
message: `Ticker length cannot exceed ${maxTickerLength}`,
});
}
} else {
if (status === TickerReservationStatus.Free) {
throw new PolymeshError({
code: ErrorCode.ValidationError,
message: 'Ticker not reserved or the reservation has expired',
});
}
}

const fee = balanceToBigNumber(rawFee);

if (balance.lt(fee)) {
throw new PolymeshError({
code: ErrorCode.ValidationError,
message: 'Not enough POLY balance to pay for ticker reservation',
message: `Not enough POLY balance to pay for ticker ${
extendPeriod ? 'period extension' : 'reservation'
}`,
});
}

Expand Down
4 changes: 3 additions & 1 deletion src/testUtils/mocks/PolkadotMockFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface TxMockData {
}

interface ContextOptions {
did?: string;
withSeed?: boolean;
balance?: BigNumber;
}
Expand Down Expand Up @@ -177,6 +178,7 @@ export class PolkadotMockFactory {
private isMockingContext = false;

private mockingContextOptions: ContextOptions = {
did: 'someDid',
withSeed: true,
balance: new BigNumber(100),
};
Expand Down Expand Up @@ -233,7 +235,7 @@ export class PolkadotMockFactory {
*/
private initContext(opts: ContextOptions): void {
const currentIdentity = opts.withSeed
? { getIdentityBalance: sinon.stub().resolves(opts.balance) }
? { getIdentityBalance: sinon.stub().resolves(opts.balance), did: opts.did }
: undefined;
const currentPair = opts.withSeed
? ({
Expand Down

0 comments on commit e84c8dc

Please sign in to comment.