From 9c6a36fa05a4a0cc73be80d4b8cae3ce41a3a6eb Mon Sep 17 00:00:00 2001 From: Toms Veidemanis Date: Tue, 10 Jan 2023 17:45:06 +0200 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20withdraw=20affirmati?= =?UTF-8?q?on=20for=20an=20instruction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../settlements.controller.spec.ts | 13 ++++++++ src/settlements/settlements.controller.ts | 25 +++++++++++++++ src/settlements/settlements.service.spec.ts | 32 +++++++++++++++++++ src/settlements/settlements.service.ts | 9 ++++++ src/test-utils/mocks.ts | 1 + src/test-utils/service-mocks.ts | 1 + 6 files changed, 81 insertions(+) diff --git a/src/settlements/settlements.controller.spec.ts b/src/settlements/settlements.controller.spec.ts index 6524bf92..bea30d96 100644 --- a/src/settlements/settlements.controller.spec.ts +++ b/src/settlements/settlements.controller.spec.ts @@ -128,6 +128,19 @@ describe('SettlementsController', () => { }); }); + describe('withdrawAffirmation', () => { + it('should withdraw affirmation from an instruction and return the data returned by the service', async () => { + mockSettlementsService.withdrawAffirmation.mockResolvedValue(txResult); + + const result = await controller.withdrawAffirmation( + { id: new BigNumber(3) }, + { signer: 'signer' } + ); + + expect(result).toEqual(txResult); + }); + }); + describe('getAffirmations', () => { it('should return the list of affirmations generated for a Instruction', async () => { const mockAffirmations = { diff --git a/src/settlements/settlements.controller.ts b/src/settlements/settlements.controller.ts index e0a6daf3..50b112c2 100644 --- a/src/settlements/settlements.controller.ts +++ b/src/settlements/settlements.controller.ts @@ -133,6 +133,31 @@ export class SettlementsController { return handleServiceResult(result); } + @ApiTags('instructions') + @ApiOperation({ + summary: 'Withdraw affirmation from an existing Instruction', + description: 'This endpoint will withdraw an affirmation from an Instruction', + }) + @ApiParam({ + name: 'id', + description: 'The ID of the Instruction from which to withdraw the affirmation', + type: 'string', + example: '123', + }) + @ApiOkResponse({ + description: 'Details of the transaction', + type: TransactionQueueModel, + }) + @Post('instructions/:id/withdraw') + public async withdrawAffirmation( + @Param() { id }: IdParamsDto, + @Body() signerDto: TransactionBaseDto + ): Promise { + const result = await this.settlementsService.withdrawAffirmation(id, signerDto); + + return handleServiceResult(result); + } + @ApiTags('instructions') @ApiOperation({ summary: 'List of affirmations', diff --git a/src/settlements/settlements.service.spec.ts b/src/settlements/settlements.service.spec.ts index 64aa89eb..9f4fd755 100644 --- a/src/settlements/settlements.service.spec.ts +++ b/src/settlements/settlements.service.spec.ts @@ -422,4 +422,36 @@ describe('SettlementsService', () => { expect(result).toEqual(mockTransferBreakdown); }); }); + + describe('withdrawAffirmation', () => { + it('should run a withdraw affirmation procedure and return the queue data', async () => { + const mockInstruction = new MockInstruction(); + const transaction = { + blockHash: '0x1', + txHash: '0x2', + blockNumber: new BigNumber(1), + tag: TxTags.settlement.WithdrawAffirmation, + }; + const mockTransaction = new MockTransaction(transaction); + mockTransactionsService.submit.mockResolvedValue({ transactions: [mockTransaction] }); + + const findInstructionSpy = jest.spyOn(service, 'findInstruction'); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + findInstructionSpy.mockResolvedValue(mockInstruction as any); + + const result = await service.withdrawAffirmation(new BigNumber(123), { + signer, + }); + + expect(result).toEqual({ + result: undefined, + transactions: [mockTransaction], + }); + expect(mockTransactionsService.submit).toHaveBeenCalledWith( + mockInstruction.withdraw, + {}, + { signer } + ); + }); + }); }); diff --git a/src/settlements/settlements.service.ts b/src/settlements/settlements.service.ts index 71a09b70..c895e36e 100644 --- a/src/settlements/settlements.service.ts +++ b/src/settlements/settlements.service.ts @@ -138,4 +138,13 @@ export class SettlementsService { const assetDetails = await this.assetsService.findOne(ticker); return assetDetails.settlements.canTransfer({ from, to, amount }); } + + public async withdrawAffirmation( + id: BigNumber, + signerDto: TransactionBaseDto + ): ServiceReturn { + const instruction = await this.findInstruction(id); + + return this.transactionsService.submit(instruction.withdraw, {}, signerDto); + } } diff --git a/src/test-utils/mocks.ts b/src/test-utils/mocks.ts index 79c5da2a..d2046f9c 100644 --- a/src/test-utils/mocks.ts +++ b/src/test-utils/mocks.ts @@ -231,6 +231,7 @@ export class MockInstruction { public details = jest.fn(); public getLegs = jest.fn(); public getAffirmations = jest.fn(); + public withdraw = jest.fn(); } export class MockVenue { diff --git a/src/test-utils/service-mocks.ts b/src/test-utils/service-mocks.ts index a10e3e1e..b22d445f 100644 --- a/src/test-utils/service-mocks.ts +++ b/src/test-utils/service-mocks.ts @@ -146,6 +146,7 @@ export class MockSettlementsService { canTransfer = jest.fn(); findPendingInstructionsByDid = jest.fn(); findVenuesByOwner = jest.fn(); + withdrawAffirmation = jest.fn(); } export class MockClaimsService { From f5dcede7d94d818f5fd0e79e97354b813a851ba6 Mon Sep 17 00:00:00 2001 From: Toms Veidemanis Date: Wed, 18 Jan 2023 23:22:27 +0200 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20add=20api=20not?= =?UTF-8?q?=20found=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/settlements/settlements.controller.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/settlements/settlements.controller.ts b/src/settlements/settlements.controller.ts index 50b112c2..61cfa559 100644 --- a/src/settlements/settlements.controller.ts +++ b/src/settlements/settlements.controller.ts @@ -1,5 +1,12 @@ import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common'; -import { ApiOkResponse, ApiOperation, ApiParam, ApiQuery, ApiTags } from '@nestjs/swagger'; +import { + ApiNotFoundResponse, + ApiOkResponse, + ApiOperation, + ApiParam, + ApiQuery, + ApiTags, +} from '@nestjs/swagger'; import { Instruction, Venue } from '@polymeshassociation/polymesh-sdk/types'; import { ApiArrayResponse, ApiTransactionResponse } from '~/common/decorators/swagger'; @@ -148,6 +155,9 @@ export class SettlementsController { description: 'Details of the transaction', type: TransactionQueueModel, }) + @ApiNotFoundResponse({ + description: 'The requested Instruction was not found', + }) @Post('instructions/:id/withdraw') public async withdrawAffirmation( @Param() { id }: IdParamsDto, From 49a03d8ab659bd8bc40a1f42574de55e8562adc3 Mon Sep 17 00:00:00 2001 From: Toms Veidemanis Date: Wed, 25 Jan 2023 20:43:07 +0200 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20fix=20merge=20co?= =?UTF-8?q?nflict=20resolution?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/settlements/settlements.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settlements/settlements.service.spec.ts b/src/settlements/settlements.service.spec.ts index 044eb1d2..b04f1fc2 100644 --- a/src/settlements/settlements.service.spec.ts +++ b/src/settlements/settlements.service.spec.ts @@ -424,7 +424,7 @@ describe('SettlementsService', () => { }); describe('rescheduleInstruction', () => { - it('should run a withdraw affirmation procedure and return the queue data', async () => { + it('should run a reschedule procedure and return the queue data', async () => { const mockInstruction = new MockInstruction(); const transaction = { blockHash: '0x1',