From c619d536f529c079f9125baac05da1ca577b9b3d Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Thu, 7 Apr 2022 12:58:07 -0400 Subject: [PATCH 1/3] Clean up npm test commands Signed-off-by: Andrew Richardson --- package.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 5e191e9..94f74cb 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,8 @@ "start:prod": "node dist/src/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"", "lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", - "test": "jest", - "test:watch": "jest --watch", - "test:cov": "jest --coverage", - "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "test": "npm run test:unit && npm run test:e2e", + "test:unit": "jest", "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { From 61d5fd2893e277d09d7d098bf81fb6eafe45cb7d Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Thu, 7 Apr 2022 12:59:20 -0400 Subject: [PATCH 2/3] Clean up and group blockchain fields on outgoing events Make it clear which fields pertain to the item itself and which pertain to the underlying blockchain event. Signed-off-by: Andrew Richardson --- src/tokens/tokens.interfaces.ts | 129 +++++++-------- src/tokens/tokens.service.spec.ts | 10 -- src/tokens/tokens.service.ts | 154 ++++++++++-------- test/erc20.e2e-spec.ts | 5 - test/erc721.e2e-spec.ts | 3 - test/ws.e2e-spec.ts | 259 ++++++++++++++++-------------- 6 files changed, 281 insertions(+), 279 deletions(-) diff --git a/src/tokens/tokens.interfaces.ts b/src/tokens/tokens.interfaces.ts index adcf792..7209e1a 100644 --- a/src/tokens/tokens.interfaces.ts +++ b/src/tokens/tokens.interfaces.ts @@ -122,33 +122,33 @@ export class TokenPoolConfig { } export class TokenPool { + @ApiProperty({ enum: TokenType }) + @IsEnum(TokenType) + type: TokenType; + @ApiProperty() @IsNotEmpty() - name: string; + signer: string; @ApiProperty() @IsNotEmpty() - signer: string; + name: string; @ApiProperty() @IsOptional() symbol?: string; - @ApiProperty({ enum: TokenType }) - @IsEnum(TokenType) - type: TokenType; - - @ApiProperty() - @IsDefined() - config: TokenPoolConfig; + @ApiProperty({ description: requestIdDescription }) + @IsOptional() + requestId?: string; @ApiProperty() @IsOptional() data?: string; - @ApiProperty({ description: requestIdDescription }) - @IsOptional() - requestId?: string; + @ApiProperty() + @IsDefined() + config: TokenPoolConfig; } export class TokenApprovalConfig { @@ -191,32 +191,52 @@ export class TokenApproval { config?: TokenApprovalConfig; } -export class BlockchainTransaction { +export class BlockLocator { @ApiProperty() @IsNotEmpty() blockNumber: string; +} +export class BlockchainInfo extends BlockLocator { @ApiProperty() - @IsNotEmpty() - logIndex: string; + transactionIndex: string; @ApiProperty() - @IsNotEmpty() transactionHash: string; @ApiProperty() - @IsNotEmpty() - transactionIndex: string; + logIndex: string; @ApiProperty() - @IsOptional() signature: string; @ApiProperty() - @IsOptional() address: string; } +export class BlockchainEvent { + @ApiProperty() + id: string; + + @ApiProperty() + name: string; + + @ApiProperty() + output: any; + + @ApiProperty() + info: BlockchainInfo; + + @ApiProperty() + location: string; + + @ApiProperty() + signature: string; + + @ApiProperty() + timestamp: string; +} + export class TokenPoolActivate { @ApiProperty() @IsNotEmpty() @@ -228,7 +248,7 @@ export class TokenPoolActivate { @ApiProperty() @IsOptional() - transaction?: BlockchainTransaction; + transaction?: BlockLocator; @ApiProperty({ description: requestIdDescription }) @IsOptional() @@ -237,24 +257,20 @@ export class TokenPoolActivate { export class TokenTransfer { @ApiProperty() - @IsOptional() - amount?: string; + @IsNotEmpty() + poolId: string; @ApiProperty() @IsOptional() tokenIndex?: string; - @ApiProperty() - @IsNotEmpty() - from: string; - @ApiProperty() @IsNotEmpty() signer: string; @ApiProperty() @IsNotEmpty() - poolId: string; + from: string; @ApiProperty() @IsNotEmpty() @@ -262,11 +278,15 @@ export class TokenTransfer { @ApiProperty() @IsOptional() - data?: string; + amount?: string; @ApiProperty({ description: requestIdDescription }) @IsOptional() requestId?: string; + + @ApiProperty() + @IsOptional() + data?: string; } export class TokenMint extends OmitType(TokenTransfer, ['from']) {} @@ -275,32 +295,17 @@ export class TokenBurn extends OmitType(TokenTransfer, ['to']) {} // Websocket notifications class tokenEventBase { - @ApiProperty() - data?: string; - - @ApiProperty() - signer?: string; - - @ApiProperty() - rawOutput?: any; - @ApiProperty() poolId: string; @ApiProperty() - timestamp: string; - - @ApiProperty() - transaction?: BlockchainTransaction; - - @ApiProperty() - type: TokenType; + signer?: string; @ApiProperty() - location?: string; + data?: string; @ApiProperty() - signature?: string; + blockchain?: BlockchainEvent; } export class TokenPoolEventInfo { @@ -315,6 +320,9 @@ export class TokenPoolEventInfo { } export class TokenPoolEvent extends tokenEventBase { + @ApiProperty() + type: TokenType; + @ApiProperty() standard: string; @@ -332,6 +340,9 @@ export class TokenTransferEvent extends tokenEventBase { @ApiProperty() tokenIndex?: string; + @ApiProperty() + uri?: string; + @ApiProperty() from: string; @@ -340,9 +351,6 @@ export class TokenTransferEvent extends tokenEventBase { @ApiProperty() amount: string; - - @ApiProperty() - uri?: string; } export class TokenMintEvent extends OmitType(TokenTransferEvent, ['from']) {} @@ -356,27 +364,6 @@ export class TokenApprovalEvent extends tokenEventBase { approved: boolean; } -export interface TransactionDetails { - blockHash: string; - blockNumber: string; - blockNumberHex: string; - from: string; - to: string; - gas: string; - gasHex: string; - gasPrice: string; - gasPriceHex: string; - hash: string; - nonce: string; - nonceHex: string; - transactionIndex: string; - transactionIndexHex: string; - value: string; - valueHex: string; - input: string; - inputArgs: any; -} - export interface IAbiInput { indexed?: boolean; internalType: string; diff --git a/src/tokens/tokens.service.spec.ts b/src/tokens/tokens.service.spec.ts index 1c62cb9..adbe3f9 100644 --- a/src/tokens/tokens.service.spec.ts +++ b/src/tokens/tokens.service.spec.ts @@ -220,7 +220,6 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolId: ERC20_NO_DATA_POOL_ID, standard: 'ERC20', - timestamp: expect.any(String), type: 'fungible', symbol: SYMBOL, info: { @@ -245,7 +244,6 @@ describe('TokensService', () => { const response: TokenPoolEvent = { poolId: ERC20_NO_DATA_POOL_ID, standard: 'ERC20', - timestamp: expect.any(String), type: TokenType.FUNGIBLE, symbol: SYMBOL, info: { @@ -391,7 +389,6 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolId: ERC20_WITH_DATA_POOL_ID, standard: 'ERC20', - timestamp: expect.any(String), type: 'fungible', symbol: SYMBOL, info: { @@ -421,7 +418,6 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolId: ERC20_WITH_DATA_POOL_ID, standard: 'ERC20', - timestamp: expect.any(String), type: 'fungible', symbol: SYMBOL, info: { @@ -446,7 +442,6 @@ describe('TokensService', () => { const response: TokenPoolEvent = { poolId: ERC20_WITH_DATA_POOL_ID, standard: 'ERC20', - timestamp: expect.any(String), type: TokenType.FUNGIBLE, symbol: SYMBOL, info: { @@ -588,7 +583,6 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolId: ERC721_NO_DATA_POOL_ID, standard: 'ERC721', - timestamp: expect.any(String), type: 'nonfungible', symbol: SYMBOL, info: { @@ -613,7 +607,6 @@ describe('TokensService', () => { const response: TokenPoolEvent = { poolId: ERC721_NO_DATA_POOL_ID, standard: 'ERC721', - timestamp: expect.any(String), type: TokenType.NONFUNGIBLE, symbol: SYMBOL, info: { @@ -772,7 +765,6 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolId: ERC721_WITH_DATA_POOL_ID, standard: 'ERC721', - timestamp: expect.any(String), type: 'nonfungible', symbol: SYMBOL, info: { @@ -802,7 +794,6 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolId: ERC721_WITH_DATA_POOL_ID, standard: 'ERC721', - timestamp: expect.any(String), type: 'nonfungible', symbol: SYMBOL, info: { @@ -827,7 +818,6 @@ describe('TokensService', () => { const response: TokenPoolEvent = { poolId: ERC721_WITH_DATA_POOL_ID, standard: 'ERC721', - timestamp: expect.any(String), type: TokenType.NONFUNGIBLE, symbol: SYMBOL, info: { diff --git a/src/tokens/tokens.service.ts b/src/tokens/tokens.service.ts index 2eaa9f4..1f18474 100644 --- a/src/tokens/tokens.service.ts +++ b/src/tokens/tokens.service.ts @@ -405,7 +405,6 @@ export class TokensService { data: dto.data, poolId: encodedPoolId.toString(), standard: dto.type === TokenType.FUNGIBLE ? 'ERC20' : 'ERC721', - timestamp: Date.now().toString(), type: dto.type, symbol: nameAndSymbol.symbol, info: { @@ -503,7 +502,6 @@ export class TokensService { const tokenPoolEvent: TokenPoolEvent = { poolId: dto.poolId, standard: poolId.type === TokenType.FUNGIBLE ? 'ERC20' : 'ERC721', - timestamp: Date.now().toString(), type: poolId.type, symbol: nameAndSymbol.symbol, info: { @@ -715,16 +713,31 @@ class TokenListener implements EventListener { } } + private formatBlockchainEventId(event: Event) { + // This intentionally matches the formatting of protocol IDs for blockchain events in FireFly core + const blockNumber = event.blockNumber ?? '0'; + const txIndex = BigInt(event.transactionIndex).toString(10); + const logIndex = event.logIndex ?? '0'; + return [ + blockNumber.padStart(12, '0'), + txIndex.padStart(6, '0'), + logIndex.padStart(6, '0'), + ].join('/'); + } + + private stripParamsFromSignature(signature: string) { + return signature.substring(0, signature.indexOf('(')); + } + private async transformTransferEvent( subName: string, event: TransferEvent, - eventIndex?: number, ): Promise { - const { data } = event; + const { data: output } = event; const unpackedSub = unpackSubscriptionName(this.service.topic, subName); const decodedData = decodeHex(event.inputArgs?.data ?? ''); - if (data.from === ZERO_ADDRESS && data.to === ZERO_ADDRESS) { + if (output.from === ZERO_ADDRESS && output.to === ZERO_ADDRESS) { // should not happen return undefined; } @@ -733,64 +746,55 @@ class TokenListener implements EventListener { return undefined; } - // This intentionally matches the formatting of protocol IDs for blockchain events in FireFly core - const blockNumber = event.blockNumber ?? '0'; - const txIndex = BigInt(event.transactionIndex).toString(10); - const logIndex = event.logIndex ?? '0'; - let transferId = [ - blockNumber.padStart(12, '0'), - txIndex.padStart(6, '0'), - logIndex.padStart(6, '0'), - ].join('/'); - if (eventIndex !== undefined) { - transferId += '/' + eventIndex.toString(10).padStart(6, '0'); - } - + const blockchainId = this.formatBlockchainEventId(event); const poolId = unpackPoolId(unpackedSub.poolId); const commonData = { - id: transferId, - location: 'address=' + event.address, - signature: event.signature, - type: poolId.type, + id: blockchainId, poolId: unpackedSub.poolId, - amount: poolId.type === TokenType.FUNGIBLE ? data.value : '1', + amount: poolId.type === TokenType.FUNGIBLE ? output.value : '1', signer: event.inputSigner, data: decodedData, - timestamp: event.timestamp, - rawOutput: data, - transaction: { - address: event.address, - blockNumber: event.blockNumber, - transactionIndex: event.transactionIndex, - transactionHash: event.transactionHash, - logIndex: event.logIndex, + blockchain: { + id: blockchainId, + name: this.stripParamsFromSignature(event.signature), + location: 'address=' + event.address, signature: event.signature, + timestamp: event.timestamp, + output, + info: { + address: event.address, + blockNumber: event.blockNumber, + transactionIndex: event.transactionIndex, + transactionHash: event.transactionHash, + logIndex: event.logIndex, + signature: event.signature, + }, }, } as TokenTransferEvent; - if (poolId.type === TokenType.NONFUNGIBLE && data.tokenId !== undefined) { - commonData.tokenIndex = data.tokenId; + if (poolId.type === TokenType.NONFUNGIBLE && output.tokenId !== undefined) { + commonData.tokenIndex = output.tokenId; commonData.uri = await this.getTokenUri( - data.tokenId, + output.tokenId, event.inputSigner ?? '', poolId.address ?? '', ); } - if (data.from === ZERO_ADDRESS) { + if (output.from === ZERO_ADDRESS) { return { event: 'token-mint', - data: { ...commonData, to: data.to } as TokenMintEvent, + data: { ...commonData, to: output.to } as TokenMintEvent, }; - } else if (data.to === ZERO_ADDRESS) { + } else if (output.to === ZERO_ADDRESS) { return { event: 'token-burn', - data: { ...commonData, from: data.from } as TokenBurnEvent, + data: { ...commonData, from: output.from } as TokenBurnEvent, }; } else { return { event: 'token-transfer', - data: { ...commonData, from: data.from, to: data.to } as TokenTransferEvent, + data: { ...commonData, from: output.from, to: output.to } as TokenTransferEvent, }; } } @@ -799,7 +803,7 @@ class TokenListener implements EventListener { subName: string, event: ApprovalEvent, ): WebSocketMessage | undefined { - const { data } = event; + const { data: output } = event; const unpackedSub = unpackSubscriptionName(this.service.topic, subName); const decodedData = decodeHex(event.inputArgs?.data ?? ''); @@ -812,34 +816,38 @@ class TokenListener implements EventListener { let id: string | undefined; let approved = true; if (poolId.type === TokenType.FUNGIBLE) { - id = `${data.owner}:${data.spender}`; - approved = BigInt(data.value ?? 0) > BigInt(0); + id = `${output.owner}:${output.spender}`; + approved = BigInt(output.value ?? 0) > BigInt(0); } else { - id = data.tokenId; - approved = data.spender !== ZERO_ADDRESS; + id = output.tokenId; + approved = output.spender !== ZERO_ADDRESS; } return { event: 'token-approval', data: { id, - location: 'address=' + event.address, - signature: event.signature, type: poolId.type, poolId: unpackedSub.poolId, - operator: data.spender, + operator: output.spender, approved, - signer: data.owner, + signer: output.owner, data: decodedData, - timestamp: event.timestamp, - rawOutput: data, - transaction: { - blockNumber: event.blockNumber, - transactionIndex: event.transactionIndex, - transactionHash: event.transactionHash, - logIndex: event.logIndex, - address: event.address, + blockchain: { + id: this.formatBlockchainEventId(event), + name: this.stripParamsFromSignature(event.signature), + location: 'address=' + event.address, signature: event.signature, + timestamp: event.timestamp, + output, + info: { + blockNumber: event.blockNumber, + transactionIndex: event.transactionIndex, + transactionHash: event.transactionHash, + logIndex: event.logIndex, + address: event.address, + signature: event.signature, + }, }, }, }; @@ -849,7 +857,7 @@ class TokenListener implements EventListener { subName: string, event: ApprovalForAllEvent, ): WebSocketMessage | undefined { - const { data } = event; + const { data: output } = event; const unpackedSub = unpackSubscriptionName(this.service.topic, subName); const decodedData = decodeHex(event.inputArgs?.data ?? ''); @@ -862,24 +870,28 @@ class TokenListener implements EventListener { return { event: 'token-approval', data: { - id: `${data.owner}:${data.operator}`, - location: 'address=' + event.address, - signature: event.signature, + id: `${output.owner}:${output.operator}`, type: poolId.type, poolId: unpackedSub.poolId, - operator: data.operator, - approved: data.approved, - signer: data.owner, + operator: output.operator, + approved: output.approved, + signer: output.owner, data: decodedData, - timestamp: event.timestamp, - rawOutput: data, - transaction: { - blockNumber: event.blockNumber, - transactionIndex: event.transactionIndex, - transactionHash: event.transactionHash, - logIndex: event.logIndex, - address: event.address, + blockchain: { + id: this.formatBlockchainEventId(event), + name: this.stripParamsFromSignature(event.signature), + location: 'address=' + event.address, signature: event.signature, + timestamp: event.timestamp, + output, + info: { + blockNumber: event.blockNumber, + transactionIndex: event.transactionIndex, + transactionHash: event.transactionHash, + logIndex: event.logIndex, + address: event.address, + signature: event.signature, + }, }, }, }; diff --git a/test/erc20.e2e-spec.ts b/test/erc20.e2e-spec.ts index 1b61b91..b57ebc0 100644 --- a/test/erc20.e2e-spec.ts +++ b/test/erc20.e2e-spec.ts @@ -168,7 +168,6 @@ describe('ERC20 - e2e', () => { data: `{"tx":${TX}}`, poolId: `address=${CONTRACT_ADDRESS}&schema=${ERC20_WITH_DATA_SCHEMA}&type=${TokenType.FUNGIBLE}`, standard: 'ERC20', - timestamp: expect.any(String), type: TokenType.FUNGIBLE, symbol: SYMBOL, info: { @@ -221,7 +220,6 @@ describe('ERC20 - e2e', () => { data: `{"tx":${TX}}`, poolId: `address=${CONTRACT_ADDRESS}&schema=${ERC20_WITH_DATA_SCHEMA}&type=${TokenType.FUNGIBLE}`, standard: 'ERC20', - timestamp: expect.any(String), type: TokenType.FUNGIBLE, symbol: SYMBOL, info: { @@ -253,7 +251,6 @@ describe('ERC20 - e2e', () => { data: `{"tx":${TX}}`, poolId: `address=${CONTRACT_ADDRESS}&schema=${ERC20_WITH_DATA_SCHEMA}&type=${TokenType.FUNGIBLE}`, standard: 'ERC20', - timestamp: expect.any(String), type: TokenType.FUNGIBLE, symbol: SYMBOL, info: { @@ -384,7 +381,6 @@ describe('ERC20 - e2e', () => { data: `{"tx":${TX}}`, poolId: `address=${CONTRACT_ADDRESS}&schema=${ERC20_NO_DATA_SCHEMA}&type=${TokenType.FUNGIBLE}`, standard: 'ERC20', - timestamp: expect.any(String), type: TokenType.FUNGIBLE, symbol: SYMBOL, info: { @@ -436,7 +432,6 @@ describe('ERC20 - e2e', () => { data: `{"tx":${TX}}`, poolId: `address=${CONTRACT_ADDRESS}&schema=${ERC20_NO_DATA_SCHEMA}&type=${TokenType.FUNGIBLE}`, standard: 'ERC20', - timestamp: expect.any(String), type: TokenType.FUNGIBLE, symbol: SYMBOL, info: { diff --git a/test/erc721.e2e-spec.ts b/test/erc721.e2e-spec.ts index 1395cf0..5d6006b 100644 --- a/test/erc721.e2e-spec.ts +++ b/test/erc721.e2e-spec.ts @@ -166,7 +166,6 @@ describe('ERC721 - e2e', () => { data: `{"tx":${TX}}`, poolId: `address=${CONTRACT_ADDRESS}&schema=${ERC721_WITH_DATA_SCHEMA}&type=${TokenType.NONFUNGIBLE}`, standard: 'ERC721', - timestamp: expect.any(String), type: TokenType.NONFUNGIBLE, symbol: SYMBOL, info: { @@ -198,7 +197,6 @@ describe('ERC721 - e2e', () => { data: `{"tx":${TX}}`, poolId: `address=${CONTRACT_ADDRESS}&schema=${ERC721_WITH_DATA_SCHEMA}&type=${TokenType.NONFUNGIBLE}`, standard: 'ERC721', - timestamp: expect.any(String), type: TokenType.NONFUNGIBLE, symbol: SYMBOL, info: { @@ -332,7 +330,6 @@ describe('ERC721 - e2e', () => { data: `{"tx":${TX}}`, poolId: `address=${CONTRACT_ADDRESS}&schema=${ERC721_NO_DATA_SCHEMA}&type=${TokenType.NONFUNGIBLE}`, standard: 'ERC721', - timestamp: expect.any(String), type: TokenType.NONFUNGIBLE, symbol: SYMBOL, info: { diff --git a/test/ws.e2e-spec.ts b/test/ws.e2e-spec.ts index 335ecfc..23c5b00 100644 --- a/test/ws.e2e-spec.ts +++ b/test/ws.e2e-spec.ts @@ -208,31 +208,34 @@ describe('WebSocket AppController (e2e)', () => { const mockMintWebSocketMessage: WebSocketMessage = { event: 'token-mint', - data: { + data: { id: '000000000001/000000/000001', - location: 'address=bob', - signature: transferEventSignature, poolId: ERC20_POOL_ID, to: 'A', amount: '5', signer: IDENTITY, data: 'test', - timestamp: '2020-01-01 00:00:00Z', - rawOutput: { - from: ZERO_ADDRESS, - to: 'A', - value: '5', - }, - transaction: { - address: 'bob', - blockNumber: '1', - transactionIndex: '0x0', - transactionHash: '0x123', - logIndex: '1', + blockchain: { + id: '000000000001/000000/000001', + name: 'Transfer', + location: 'address=bob', signature: transferEventSignature, + timestamp: '2020-01-01 00:00:00Z', + output: { + from: ZERO_ADDRESS, + to: 'A', + value: '5', + }, + info: { + address: 'bob', + blockNumber: '1', + transactionIndex: '0x0', + transactionHash: '0x123', + logIndex: '1', + signature: transferEventSignature, + }, }, - type: 'fungible', - } as TokenMintEvent, + }, }; await server @@ -259,31 +262,34 @@ describe('WebSocket AppController (e2e)', () => { const mockMintWebSocketMessage: WebSocketMessage = { event: 'token-mint', - data: { + data: { id: '000000000001/000000/000001', - location: 'address=bob', - signature: transferEventSignature, poolId: `address=${CONTRACT_ADDRESS}&standard=${ERC20_STANDARD}&type=${TokenType.FUNGIBLE}`, to: 'A', amount: '5', signer: IDENTITY, data: 'test', - timestamp: '2020-01-01 00:00:00Z', - rawOutput: { - from: ZERO_ADDRESS, - to: 'A', - value: '5', - }, - transaction: { - address: 'bob', - blockNumber: '1', - transactionIndex: '0x0', - transactionHash: '0x123', - logIndex: '1', + blockchain: { + id: '000000000001/000000/000001', + name: 'Transfer', + location: 'address=bob', signature: transferEventSignature, + timestamp: '2020-01-01 00:00:00Z', + output: { + from: ZERO_ADDRESS, + to: 'A', + value: '5', + }, + info: { + address: 'bob', + blockNumber: '1', + transactionIndex: '0x0', + transactionHash: '0x123', + logIndex: '1', + signature: transferEventSignature, + }, }, - type: 'fungible', - } as TokenMintEvent, + }, }; await server @@ -337,33 +343,36 @@ describe('WebSocket AppController (e2e)', () => { const mockMintWebSocketMessage: WebSocketMessage = { event: 'token-mint', - data: { - location: 'address=bob', - signature: transferEventSignature, + data: { id: '000000000001/000000/000001', poolId: ERC721_POOL_ID, to: 'A', amount: '1', signer: IDENTITY, data: 'test', - timestamp: '2020-01-01 00:00:00Z', - rawOutput: { - from: ZERO_ADDRESS, - to: 'A', - tokenId: '721', - }, - transaction: { - address: 'bob', - blockNumber: '1', - transactionIndex: '0x0', - transactionHash: '0x123', - logIndex: '1', + blockchain: { + id: '000000000001/000000/000001', + name: 'Transfer', + location: 'address=bob', signature: transferEventSignature, + timestamp: '2020-01-01 00:00:00Z', + output: { + from: ZERO_ADDRESS, + to: 'A', + tokenId: '721', + }, + info: { + address: 'bob', + blockNumber: '1', + transactionIndex: '0x0', + transactionHash: '0x123', + logIndex: '1', + signature: transferEventSignature, + }, }, - type: 'nonfungible', tokenIndex: '721', uri: ERC721_BASE_URI, - } as TokenMintEvent, + }, }; await server @@ -387,32 +396,35 @@ describe('WebSocket AppController (e2e)', () => { const mockTransferWebSocketMessage: WebSocketMessage = { event: 'token-transfer', - data: { + data: { id: '000000000001/000000/000001', - location: 'address=bob', - signature: transferEventSignature, poolId: ERC20_POOL_ID, from: 'A', to: 'B', amount: '5', signer: IDENTITY, data: 'test', - timestamp: '2020-01-01 00:00:00Z', - rawOutput: { - from: 'A', - to: 'B', - value: '5', - }, - transaction: { - address: 'bob', - blockNumber: '1', - transactionIndex: '0x0', - transactionHash: '0x123', - logIndex: '1', + blockchain: { + id: '000000000001/000000/000001', + name: 'Transfer', + location: 'address=bob', signature: transferEventSignature, + timestamp: '2020-01-01 00:00:00Z', + output: { + from: 'A', + to: 'B', + value: '5', + }, + info: { + address: 'bob', + blockNumber: '1', + transactionIndex: '0x0', + transactionHash: '0x123', + logIndex: '1', + signature: transferEventSignature, + }, }, - type: 'fungible', - } as TokenTransferEvent, + }, }; await server @@ -467,34 +479,37 @@ describe('WebSocket AppController (e2e)', () => { const mockTransferWebSocketMessage: WebSocketMessage = { event: 'token-transfer', - data: { + data: { id: '000000000001/000000/000001', - location: 'address=bob', - signature: transferEventSignature, poolId: ERC721_POOL_ID, from: 'A', to: 'B', amount: '1', signer: IDENTITY, data: 'test', - timestamp: '2020-01-01 00:00:00Z', - rawOutput: { - from: 'A', - to: 'B', - tokenId: '721', - }, - transaction: { - address: 'bob', - blockNumber: '1', - transactionIndex: '0x0', - transactionHash: '0x123', - logIndex: '1', + blockchain: { + id: '000000000001/000000/000001', + name: 'Transfer', + location: 'address=bob', signature: transferEventSignature, + timestamp: '2020-01-01 00:00:00Z', + output: { + from: 'A', + to: 'B', + tokenId: '721', + }, + info: { + address: 'bob', + blockNumber: '1', + transactionIndex: '0x0', + transactionHash: '0x123', + logIndex: '1', + signature: transferEventSignature, + }, }, - type: 'nonfungible', tokenIndex: '721', uri: ERC721_BASE_URI, - } as TokenTransferEvent, + }, }; await server @@ -518,31 +533,34 @@ describe('WebSocket AppController (e2e)', () => { const mockBurnWebSocketMessage: WebSocketMessage = { event: 'token-burn', - data: { + data: { id: '000000000001/000000/000001', - location: 'address=bob', - signature: transferEventSignature, poolId: ERC20_POOL_ID, from: 'B', amount: '5', signer: IDENTITY, data: 'test', - timestamp: '2020-01-01 00:00:00Z', - rawOutput: { - from: 'B', - to: ZERO_ADDRESS, - value: '5', - }, - transaction: { - address: 'bob', - blockNumber: '1', - transactionIndex: '0x0', - transactionHash: '0x123', - logIndex: '1', + blockchain: { + id: '000000000001/000000/000001', + name: 'Transfer', + location: 'address=bob', signature: transferEventSignature, + timestamp: '2020-01-01 00:00:00Z', + output: { + from: 'B', + to: ZERO_ADDRESS, + value: '5', + }, + info: { + address: 'bob', + blockNumber: '1', + transactionIndex: '0x0', + transactionHash: '0x123', + logIndex: '1', + signature: transferEventSignature, + }, }, - type: 'fungible', - } as TokenBurnEvent, + }, }; await server @@ -596,33 +614,36 @@ describe('WebSocket AppController (e2e)', () => { const mockBurnWebSocketMessage: WebSocketMessage = { event: 'token-burn', - data: { + data: { id: '000000000001/000000/000001', - location: 'address=bob', - signature: transferEventSignature, poolId: ERC721_POOL_ID, from: 'B', amount: '1', signer: IDENTITY, data: 'test', - timestamp: '2020-01-01 00:00:00Z', - rawOutput: { - from: 'B', - to: ZERO_ADDRESS, - tokenId: '721', - }, - transaction: { - address: 'bob', - blockNumber: '1', - transactionIndex: '0x0', - transactionHash: '0x123', - logIndex: '1', + blockchain: { + id: '000000000001/000000/000001', + name: 'Transfer', + location: 'address=bob', signature: transferEventSignature, + timestamp: '2020-01-01 00:00:00Z', + output: { + from: 'B', + to: ZERO_ADDRESS, + tokenId: '721', + }, + info: { + address: 'bob', + blockNumber: '1', + transactionIndex: '0x0', + transactionHash: '0x123', + logIndex: '1', + signature: transferEventSignature, + }, }, - type: 'nonfungible', tokenIndex: '721', uri: '', // Burned tokens have no URI - } as TokenBurnEvent, + }, }; await server From cee58c49073d6eee6a49b05d21ae82db72658ac8 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Thu, 7 Apr 2022 14:09:57 -0400 Subject: [PATCH 3/3] Clean up block number logic Signed-off-by: Andrew Richardson --- src/tokens/tokens.interfaces.ts | 6 +++--- src/tokens/tokens.service.ts | 26 +++++++++++++------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/tokens/tokens.interfaces.ts b/src/tokens/tokens.interfaces.ts index 7209e1a..5f8cef5 100644 --- a/src/tokens/tokens.interfaces.ts +++ b/src/tokens/tokens.interfaces.ts @@ -114,7 +114,7 @@ export class TokenPoolConfig { @ApiProperty() @IsOptional() - blockNumber?: number; + blockNumber?: string; @ApiProperty() @IsOptional() @@ -244,11 +244,11 @@ export class TokenPoolActivate { @ApiProperty() @IsOptional() - poolConfig?: TokenPoolConfig; + config?: TokenPoolConfig; @ApiProperty() @IsOptional() - transaction?: BlockLocator; + locator?: BlockLocator; @ApiProperty({ description: requestIdDescription }) @IsOptional() diff --git a/src/tokens/tokens.service.ts b/src/tokens/tokens.service.ts index 1f18474..e86e4f5 100644 --- a/src/tokens/tokens.service.ts +++ b/src/tokens/tokens.service.ts @@ -37,7 +37,7 @@ import { ApprovalEvent, ApprovalForAllEvent, AsyncResponse, - BlockchainTransaction, + BlockLocator, ContractSchema, EthConnectAsyncResponse, EthConnectMsgRequest, @@ -46,7 +46,6 @@ import { ITokenPool, IValidTokenPool, TokenApproval, - TokenApprovalConfig, TokenApprovalEvent, TokenBurn, TokenBurnEvent, @@ -417,14 +416,14 @@ export class TokensService { return tokenPoolEvent; } - getSubscriptionBlockNumber(poolConfig?: TokenPoolConfig, transaction?: BlockchainTransaction): string { - let blockNumber = '0'; - if (poolConfig?.blockNumber) { - blockNumber = String(poolConfig.blockNumber) - } else if (transaction?.blockNumber) { - blockNumber = transaction.blockNumber; + getSubscriptionBlockNumber(config?: TokenPoolConfig, transaction?: BlockLocator): string { + if (config?.blockNumber !== undefined && config.blockNumber !== '') { + return config.blockNumber; + } else if (transaction?.blockNumber !== undefined && transaction.blockNumber !== '') { + return transaction.blockNumber; + } else { + return '0'; } - return blockNumber; } async activatePool(dto: TokenPoolActivate) { @@ -465,7 +464,7 @@ export class TokensService { packSubscriptionName(this.topic, dto.poolId, abiEvents.TRANSFER), poolId.address, methodsToSubTo, - this.getSubscriptionBlockNumber(dto.poolConfig, dto.transaction), + this.getSubscriptionBlockNumber(dto.config, dto.locator), ), this.eventstream.getOrCreateSubscription( `${this.baseUrl}`, @@ -475,7 +474,7 @@ export class TokensService { packSubscriptionName(this.topic, dto.poolId, abiEvents.APPROVAL), poolId.address, methodsToSubTo, - this.getSubscriptionBlockNumber(dto.poolConfig, dto.transaction), + this.getSubscriptionBlockNumber(dto.config, dto.locator), ), ]; if (abiEvents.APPROVALFORALL !== null) { @@ -492,7 +491,7 @@ export class TokensService { packSubscriptionName(this.topic, dto.poolId, abiEvents.APPROVALFORALL), poolId.address, methodsToSubTo, - this.getSubscriptionBlockNumber(dto.poolConfig, dto.transaction), + this.getSubscriptionBlockNumber(dto.config, dto.locator), ), ); } @@ -613,12 +612,13 @@ export class TokensService { const schema = poolId.schema as ContractSchemaStrings; switch (poolId.type) { - case TokenType.FUNGIBLE: + case TokenType.FUNGIBLE: { // Not approved means 0 allowance; approved with no allowance means unlimited allowance const allowance = !dto.approved ? '0' : dto.config?.allowance ?? UINT256_MAX.toString(); params.push(dto.operator, allowance); methodAbi = this.getMethodAbi(schema, 'APPROVE'); break; + } case TokenType.NONFUNGIBLE: if (dto.config?.tokenIndex !== undefined) { // Not approved means setting approved operator to 0