From 1d49672c831fb8f6c2501802fb2be85180edc19d Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 3 Jan 2023 13:50:29 -0500 Subject: [PATCH 1/4] Include "interfaceFormat" in token pool responses Signed-off-by: Andrew Richardson --- src/tokens/tokens.interfaces.ts | 8 ++++++++ src/tokens/tokens.listener.ts | 2 ++ src/tokens/tokens.service.ts | 3 +++ 3 files changed, 13 insertions(+) diff --git a/src/tokens/tokens.interfaces.ts b/src/tokens/tokens.interfaces.ts index 07b01c1..fdddb65 100644 --- a/src/tokens/tokens.interfaces.ts +++ b/src/tokens/tokens.interfaces.ts @@ -95,6 +95,11 @@ export enum TokenType { NONFUNGIBLE = 'nonfungible', } +export enum InterfaceFormat { + ABI = 'abi', + FFI = 'ffi', +} + export interface IPoolLocator { address: string | null; schema: string | null; @@ -353,6 +358,9 @@ export class TokenPoolEvent extends tokenEventBase { @ApiProperty() standard: string; + @ApiProperty() + interfaceFormat: InterfaceFormat; + @ApiProperty() symbol: string; diff --git a/src/tokens/tokens.listener.ts b/src/tokens/tokens.listener.ts index 2af2a8f..055986a 100644 --- a/src/tokens/tokens.listener.ts +++ b/src/tokens/tokens.listener.ts @@ -32,6 +32,7 @@ import { TokenTransferEvent, TokenType, TransferEvent, + InterfaceFormat, } from './tokens.interfaces'; import { decodeHex, @@ -150,6 +151,7 @@ export class TokenListener implements EventListener { event: 'token-pool', data: { standard: type === TokenType.FUNGIBLE ? 'ERC20' : 'ERC721', + interfaceFormat: InterfaceFormat.ABI, poolLocator: packPoolLocator(poolLocator), type, signer: event.inputSigner, diff --git a/src/tokens/tokens.service.ts b/src/tokens/tokens.service.ts index e1e00be..f75055f 100644 --- a/src/tokens/tokens.service.ts +++ b/src/tokens/tokens.service.ts @@ -21,6 +21,7 @@ import { EventStreamProxyGateway } from '../eventstream-proxy/eventstream-proxy. import { Context, newContext } from '../request-context/request-context.decorator'; import { AsyncResponse, + InterfaceFormat, IPoolLocator, IValidPoolLocator, TokenApproval, @@ -263,6 +264,7 @@ export class TokensService { data: dto.data, poolLocator: packPoolLocator(poolLocator), standard: dto.type === TokenType.FUNGIBLE ? 'ERC20' : 'ERC721', + interfaceFormat: InterfaceFormat.ABI, type: dto.type, symbol: poolInfo.symbol, decimals: poolInfo.decimals, @@ -363,6 +365,7 @@ export class TokensService { const tokenPoolEvent: TokenPoolEvent = { poolLocator: dto.poolLocator, standard: poolLocator.type === TokenType.FUNGIBLE ? 'ERC20' : 'ERC721', + interfaceFormat: InterfaceFormat.ABI, type: poolLocator.type, symbol: poolInfo.symbol, decimals: poolInfo.decimals, From 75892807bfaa146cccb7b6849cf56c1d39ae1665 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 3 Jan 2023 14:00:00 -0500 Subject: [PATCH 2/4] Add missing type annotations Signed-off-by: Andrew Richardson --- src/tokens/tokens.controller.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/tokens/tokens.controller.ts b/src/tokens/tokens.controller.ts index a56a278..4343431 100644 --- a/src/tokens/tokens.controller.ts +++ b/src/tokens/tokens.controller.ts @@ -17,7 +17,7 @@ import { Body, Controller, Get, HttpCode, HttpStatus, Param, Post, Res } from '@nestjs/common'; import { ApiBody, ApiOperation, ApiResponse } from '@nestjs/swagger'; import { Response } from 'express'; -import { RequestContext } from '../request-context/request-context.decorator'; +import { Context, RequestContext } from '../request-context/request-context.decorator'; import { EventStreamReply } from '../event-stream/event-stream.interfaces'; import { BlockchainConnectorService } from './blockchain.service'; import { @@ -39,7 +39,7 @@ export class TokensController { @Post('init') @HttpCode(204) @ApiOperation({ summary: 'Perform one-time initialization (if not auto-initialized)' }) - init(@RequestContext() ctx) { + init(@RequestContext() ctx: Context) { return this.service.init(ctx); } @@ -53,7 +53,7 @@ export class TokensController { @ApiResponse({ status: 200, type: TokenPoolEvent }) @ApiResponse({ status: 202, type: AsyncResponse }) async createPool( - @RequestContext() ctx, + @RequestContext() ctx: Context, @Body() dto: TokenPool, @Res({ passthrough: true }) res: Response, ) { @@ -72,7 +72,7 @@ export class TokensController { summary: 'Activate a token pool to begin receiving transfer events', }) @ApiBody({ type: TokenPoolActivate }) - activatePool(@RequestContext() ctx, @Body() dto: TokenPoolActivate) { + activatePool(@RequestContext() ctx: Context, @Body() dto: TokenPoolActivate) { return this.service.activatePool(ctx, dto); } @@ -85,7 +85,7 @@ export class TokensController { }) @ApiBody({ type: TokenMint }) @ApiResponse({ status: 202, type: AsyncResponse }) - mint(@RequestContext() ctx, @Body() dto: TokenMint) { + mint(@RequestContext() ctx: Context, @Body() dto: TokenMint) { return this.service.mint(ctx, dto); } @@ -98,7 +98,7 @@ export class TokensController { }) @ApiBody({ type: TokenTransfer }) @ApiResponse({ status: 202, type: AsyncResponse }) - transfer(@RequestContext() ctx, @Body() dto: TokenTransfer) { + transfer(@RequestContext() ctx: Context, @Body() dto: TokenTransfer) { return this.service.transfer(ctx, dto); } @@ -110,7 +110,7 @@ export class TokensController { }) @ApiBody({ type: TokenApproval }) @ApiResponse({ status: 202, type: AsyncResponse }) - approve(@RequestContext() ctx, @Body() dto: TokenApproval) { + approve(@RequestContext() ctx: Context, @Body() dto: TokenApproval) { return this.service.approval(ctx, dto); } @@ -123,14 +123,14 @@ export class TokensController { }) @ApiBody({ type: TokenBurn }) @ApiResponse({ status: 202, type: AsyncResponse }) - burn(@RequestContext() ctx, @Body() dto: TokenBurn) { + burn(@RequestContext() ctx: Context, @Body() dto: TokenBurn) { return this.service.burn(ctx, dto); } @Get('receipt/:id') @ApiOperation({ summary: 'Retrieve the result of an async operation' }) @ApiResponse({ status: 200, type: EventStreamReply }) - getReceipt(@RequestContext() ctx, @Param('id') id: string) { + getReceipt(@RequestContext() ctx: Context, @Param('id') id: string) { return this.blockchain.getReceipt(ctx, id); } } From f4920942613af2f3f106b91e5c42cc86cbc5b9e5 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Tue, 3 Jan 2023 14:21:01 -0500 Subject: [PATCH 3/4] Add /checkinterface API This can be queried with a full ABI to determine which methods are understood by this token connector. Signed-off-by: Andrew Richardson --- src/tokens/abimapper.service.ts | 2 +- src/tokens/tokens.controller.ts | 11 ++++++++ src/tokens/tokens.interfaces.ts | 34 +++++++++++++++++++++--- src/tokens/tokens.service.spec.ts | 11 ++++++++ src/tokens/tokens.service.ts | 25 ++++++++++++++++++ test/suites/erc20.ts | 41 +++++++++++++++++++++++++++++ test/suites/erc721.ts | 43 +++++++++++++++++++++++++++++++ 7 files changed, 163 insertions(+), 4 deletions(-) diff --git a/src/tokens/abimapper.service.ts b/src/tokens/abimapper.service.ts index 0147ceb..3317fe0 100644 --- a/src/tokens/abimapper.service.ts +++ b/src/tokens/abimapper.service.ts @@ -132,7 +132,7 @@ export class AbiMapperService { return true; } - private getAllMethods(abi: IAbiMethod[], signatures: MethodSignature[]) { + getAllMethods(abi: IAbiMethod[], signatures: MethodSignature[]) { const methods: IAbiMethod[] = []; for (const signature of signatures) { for (const method of abi) { diff --git a/src/tokens/tokens.controller.ts b/src/tokens/tokens.controller.ts index 4343431..5b9da16 100644 --- a/src/tokens/tokens.controller.ts +++ b/src/tokens/tokens.controller.ts @@ -22,6 +22,7 @@ import { EventStreamReply } from '../event-stream/event-stream.interfaces'; import { BlockchainConnectorService } from './blockchain.service'; import { AsyncResponse, + CheckInterfaceRequest, TokenApproval, TokenBurn, TokenMint, @@ -76,6 +77,16 @@ export class TokensController { return this.service.activatePool(ctx, dto); } + @Post('checkinterface') + @HttpCode(200) + @ApiOperation({ + summary: 'Check which interface methods are supported by this connector', + }) + @ApiBody({ type: CheckInterfaceRequest }) + checkInterface(@Body() dto: CheckInterfaceRequest) { + return this.service.checkInterface(dto); + } + @Post('mint') @HttpCode(202) @ApiOperation({ diff --git a/src/tokens/tokens.interfaces.ts b/src/tokens/tokens.interfaces.ts index fdddb65..5c88b1b 100644 --- a/src/tokens/tokens.interfaces.ts +++ b/src/tokens/tokens.interfaces.ts @@ -15,7 +15,7 @@ // limitations under the License. import { ApiProperty, OmitType } from '@nestjs/swagger'; -import { IsEnum, IsNotEmpty, IsOptional } from 'class-validator'; +import { Equals, IsDefined, IsEnum, IsNotEmpty, IsOptional } from 'class-validator'; import { Event } from '../event-stream/event-stream.interfaces'; // Ethconnect interfaces @@ -226,9 +226,37 @@ export class TokenPoolActivate { } export class TokenInterface { + @ApiProperty({ enum: InterfaceFormat }) + @Equals(InterfaceFormat.ABI) + format: InterfaceFormat; + @ApiProperty({ isArray: true }) - @IsOptional() - abi?: IAbiMethod[]; + @IsDefined() + abi: IAbiMethod[]; +} + +export class CheckInterfaceRequest extends TokenInterface { + @ApiProperty() + @IsNotEmpty() + poolLocator: string; +} + +type TokenAbi = { + [op in TokenOperation]: TokenInterface; +}; + +export class CheckInterfaceResponse implements TokenAbi { + @ApiProperty() + approval: TokenInterface; + + @ApiProperty() + burn: TokenInterface; + + @ApiProperty() + mint: TokenInterface; + + @ApiProperty() + transfer: TokenInterface; } export class TokenTransfer { diff --git a/src/tokens/tokens.service.spec.ts b/src/tokens/tokens.service.spec.ts index 7463799..790e06a 100644 --- a/src/tokens/tokens.service.spec.ts +++ b/src/tokens/tokens.service.spec.ts @@ -39,6 +39,7 @@ import { EthConnectMsgRequest, EthConnectReturn, IAbiMethod, + InterfaceFormat, TokenBurn, TokenMint, TokenPool, @@ -267,6 +268,7 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolLocator: ERC20_NO_DATA_POOL_ID, standard: 'ERC20', + interfaceFormat: InterfaceFormat.ABI, type: 'fungible', symbol: SYMBOL, decimals: 18, @@ -295,6 +297,7 @@ describe('TokensService', () => { const response: TokenPoolEvent = { poolLocator: ERC20_NO_DATA_POOL_ID, standard: 'ERC20', + interfaceFormat: InterfaceFormat.ABI, type: TokenType.FUNGIBLE, symbol: SYMBOL, decimals: 18, @@ -458,6 +461,7 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolLocator: ERC20_WITH_DATA_POOL_ID, standard: 'ERC20', + interfaceFormat: InterfaceFormat.ABI, type: 'fungible', symbol: SYMBOL, decimals: 18, @@ -490,6 +494,7 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolLocator: ERC20_WITH_DATA_POOL_ID, standard: 'ERC20', + interfaceFormat: InterfaceFormat.ABI, type: 'fungible', symbol: SYMBOL, decimals: 18, @@ -518,6 +523,7 @@ describe('TokensService', () => { const response: TokenPoolEvent = { poolLocator: ERC20_WITH_DATA_POOL_ID, standard: 'ERC20', + interfaceFormat: InterfaceFormat.ABI, type: TokenType.FUNGIBLE, symbol: SYMBOL, decimals: 18, @@ -680,6 +686,7 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolLocator: ERC721_NO_DATA_POOL_ID, standard: 'ERC721', + interfaceFormat: InterfaceFormat.ABI, type: 'nonfungible', symbol: SYMBOL, decimals: 0, @@ -708,6 +715,7 @@ describe('TokensService', () => { const response: TokenPoolEvent = { poolLocator: ERC721_NO_DATA_POOL_ID, standard: 'ERC721', + interfaceFormat: InterfaceFormat.ABI, type: TokenType.NONFUNGIBLE, symbol: SYMBOL, decimals: 0, @@ -888,6 +896,7 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolLocator: ERC721_WITH_DATA_POOL_ID, standard: 'ERC721', + interfaceFormat: InterfaceFormat.ABI, type: 'nonfungible', symbol: SYMBOL, decimals: 0, @@ -921,6 +930,7 @@ describe('TokensService', () => { data: `{"tx":${TX}}`, poolLocator: ERC721_WITH_DATA_POOL_ID, standard: 'ERC721', + interfaceFormat: InterfaceFormat.ABI, type: 'nonfungible', symbol: SYMBOL, decimals: 0, @@ -949,6 +959,7 @@ describe('TokensService', () => { const response: TokenPoolEvent = { poolLocator: ERC721_WITH_DATA_POOL_ID, standard: 'ERC721', + interfaceFormat: InterfaceFormat.ABI, type: TokenType.NONFUNGIBLE, symbol: SYMBOL, decimals: 0, diff --git a/src/tokens/tokens.service.ts b/src/tokens/tokens.service.ts index f75055f..db90520 100644 --- a/src/tokens/tokens.service.ts +++ b/src/tokens/tokens.service.ts @@ -21,11 +21,15 @@ import { EventStreamProxyGateway } from '../eventstream-proxy/eventstream-proxy. import { Context, newContext } from '../request-context/request-context.decorator'; import { AsyncResponse, + CheckInterfaceRequest, + CheckInterfaceResponse, + IAbiMethod, InterfaceFormat, IPoolLocator, IValidPoolLocator, TokenApproval, TokenBurn, + TokenInterface, TokenMint, TokenPool, TokenPoolActivate, @@ -49,6 +53,7 @@ import { Transfer as ERC20Transfer, Name as ERC20Name, Symbol as ERC20Symbol, + DynamicMethods as ERC20Methods, } from './erc20'; import { Approval as ERC721Approval, @@ -56,6 +61,7 @@ import { Transfer as ERC721Transfer, Name as ERC721Name, Symbol as ERC721Symbol, + DynamicMethods as ERC721Methods, } from './erc721'; @Injectable() @@ -379,6 +385,25 @@ export class TokensService { return tokenPoolEvent; } + checkInterface(dto: CheckInterfaceRequest): CheckInterfaceResponse { + const poolLocator = unpackPoolLocator(dto.poolLocator); + if (!validatePoolLocator(poolLocator)) { + throw new BadRequestException('Invalid pool locator'); + } + + const wrapMethods = (methods: IAbiMethod[]): TokenInterface => { + return { format: InterfaceFormat.ABI, abi: methods }; + }; + + const methods = poolLocator.type === TokenType.FUNGIBLE ? ERC20Methods : ERC721Methods; + return { + approval: wrapMethods(this.mapper.getAllMethods(dto.abi, methods.approval)), + burn: wrapMethods(this.mapper.getAllMethods(dto.abi, methods.burn)), + mint: wrapMethods(this.mapper.getAllMethods(dto.abi, methods.mint)), + transfer: wrapMethods(this.mapper.getAllMethods(dto.abi, methods.transfer)), + }; + } + private async getAbiForMint(ctx: Context, poolLocator: IValidPoolLocator, dto: TokenMint) { const supportsUri = dto.uri !== undefined && (await this.mapper.supportsMintWithUri(ctx, poolLocator.address)); diff --git a/test/suites/erc20.ts b/test/suites/erc20.ts index 9fa2167..c42c7cf 100644 --- a/test/suites/erc20.ts +++ b/test/suites/erc20.ts @@ -17,10 +17,13 @@ import ERC20WithDataABI from '../../src/abi/ERC20WithData.json'; import ERC20NoDataABI from '../../src/abi/ERC20NoData.json'; import { + CheckInterfaceRequest, + CheckInterfaceResponse, EthConnectAsyncResponse, EthConnectMsgRequest, EthConnectReturn, IAbiMethod, + InterfaceFormat, TokenApproval, TokenBurn, TokenMint, @@ -50,7 +53,9 @@ const ERC20_WITH_DATA_SCHEMA = 'ERC20WithData'; const ERC20_WITH_DATA_POOL_ID = `address=${CONTRACT_ADDRESS}&schema=${ERC20_WITH_DATA_SCHEMA}&type=${TokenType.FUNGIBLE}`; const MINT_NO_DATA = 'mint'; +const TRANSFER_FROM_NO_DATA = 'transferFrom'; const TRANSFER_NO_DATA = 'transfer'; +const BURN_FROM_NO_DATA = 'burnFrom'; const BURN_NO_DATA = 'burn'; const APPROVE_NO_DATA = 'approve'; const MINT_WITH_DATA = 'mintWithData'; @@ -559,6 +564,7 @@ export default (context: TestContext) => { poolLocator: ERC20_NO_DATA_POOL_ID, from: IDENTITY, interface: { + format: InterfaceFormat.ABI, abi: burnMethods, }, }; @@ -627,6 +633,7 @@ export default (context: TestContext) => { poolLocator: ERC20_NO_DATA_POOL_ID, from: '0x2', interface: { + format: InterfaceFormat.ABI, abi: burnMethods, }, }; @@ -653,5 +660,39 @@ export default (context: TestContext) => { expect(context.http.post).toHaveBeenCalledTimes(1); expect(context.http.post).toHaveBeenCalledWith(BASE_URL, mockEthConnectRequest, OPTIONS); }); + + it('Check interface', async () => { + const request: CheckInterfaceRequest = { + poolLocator: ERC20_NO_DATA_POOL_ID, + format: InterfaceFormat.ABI, + abi: ERC20NoDataABI.abi, + }; + + const response: CheckInterfaceResponse = { + approval: { + format: InterfaceFormat.ABI, + abi: ERC20NoDataABI.abi.filter(m => m.name === APPROVE_NO_DATA), + }, + burn: { + format: InterfaceFormat.ABI, + abi: ERC20NoDataABI.abi.filter( + m => m.name === BURN_NO_DATA || m.name === BURN_FROM_NO_DATA, + ), + }, + mint: { + format: InterfaceFormat.ABI, + abi: ERC20NoDataABI.abi.filter(m => m.name === MINT_NO_DATA), + }, + transfer: { + format: InterfaceFormat.ABI, + abi: [ + ...ERC20NoDataABI.abi.filter(m => m.name === TRANSFER_NO_DATA), + ...ERC20NoDataABI.abi.filter(m => m.name === TRANSFER_FROM_NO_DATA), + ], + }, + }; + + await context.server.post('/checkinterface').send(request).expect(200).expect(response); + }); }); }; diff --git a/test/suites/erc721.ts b/test/suites/erc721.ts index 36638ca..d1e8406 100644 --- a/test/suites/erc721.ts +++ b/test/suites/erc721.ts @@ -17,10 +17,13 @@ import ERC721NoDataABI from '../../src/abi/ERC721NoData.json'; import ERC721WithDataABI from '../../src/abi/ERC721WithData.json'; import { + CheckInterfaceRequest, + CheckInterfaceResponse, EthConnectAsyncResponse, EthConnectMsgRequest, EthConnectReturn, IAbiMethod, + InterfaceFormat, TokenApproval, TokenBurn, TokenMint, @@ -540,6 +543,7 @@ export default (context: TestContext) => { poolLocator: ERC721_NO_DATA_POOL_ID, to: '0x123', interface: { + format: InterfaceFormat.ABI, abi: [safeMintAutoIndex], }, }; @@ -566,5 +570,44 @@ export default (context: TestContext) => { expect(context.http.post).toHaveBeenCalledTimes(1); expect(context.http.post).toHaveBeenCalledWith(BASE_URL, mockEthConnectRequest, OPTIONS); }); + + it('Check interface', async () => { + const request: CheckInterfaceRequest = { + poolLocator: ERC721_NO_DATA_POOL_ID, + format: InterfaceFormat.ABI, + abi: ERC721NoDataABI.abi, + }; + + const response: CheckInterfaceResponse = { + approval: { + format: InterfaceFormat.ABI, + abi: [ + ...ERC721NoDataABI.abi.filter(m => m.name === APPROVE_NO_DATA), + ...ERC721NoDataABI.abi.filter(m => m.name === APPROVE_FOR_ALL_NO_DATA), + ], + }, + burn: { + format: InterfaceFormat.ABI, + abi: ERC721NoDataABI.abi.filter(m => m.name === BURN_NO_DATA), + }, + mint: { + format: InterfaceFormat.ABI, + abi: ERC721NoDataABI.abi.filter(m => m.name === MINT_NO_DATA), + }, + transfer: { + format: InterfaceFormat.ABI, + abi: [ + ...ERC721NoDataABI.abi.filter( + m => m.name === TRANSFER_NO_DATA && m.inputs.length === 4, + ), + ...ERC721NoDataABI.abi.filter( + m => m.name === TRANSFER_NO_DATA && m.inputs.length === 3, + ), + ], + }, + }; + + await context.server.post('/checkinterface').send(request).expect(200).expect(response); + }); }); }; From ba1a6286320dcd86a97aa13c4b41defe6f7b5351 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Thu, 5 Jan 2023 14:59:36 -0500 Subject: [PATCH 4/4] Rename "abi" parameter to "methods" This parameter is not the full ABI, but a list of methods encoded in ABI format. Signed-off-by: Andrew Richardson --- src/tokens/tokens.interfaces.ts | 2 +- src/tokens/tokens.service.ts | 18 +++++++++--------- test/suites/erc20.ts | 14 +++++++------- test/suites/erc721.ts | 12 ++++++------ 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/tokens/tokens.interfaces.ts b/src/tokens/tokens.interfaces.ts index 5c88b1b..39ea7c5 100644 --- a/src/tokens/tokens.interfaces.ts +++ b/src/tokens/tokens.interfaces.ts @@ -232,7 +232,7 @@ export class TokenInterface { @ApiProperty({ isArray: true }) @IsDefined() - abi: IAbiMethod[]; + methods: IAbiMethod[]; } export class CheckInterfaceRequest extends TokenInterface { diff --git a/src/tokens/tokens.service.ts b/src/tokens/tokens.service.ts index db90520..f22d6b9 100644 --- a/src/tokens/tokens.service.ts +++ b/src/tokens/tokens.service.ts @@ -392,15 +392,15 @@ export class TokensService { } const wrapMethods = (methods: IAbiMethod[]): TokenInterface => { - return { format: InterfaceFormat.ABI, abi: methods }; + return { format: InterfaceFormat.ABI, methods }; }; const methods = poolLocator.type === TokenType.FUNGIBLE ? ERC20Methods : ERC721Methods; return { - approval: wrapMethods(this.mapper.getAllMethods(dto.abi, methods.approval)), - burn: wrapMethods(this.mapper.getAllMethods(dto.abi, methods.burn)), - mint: wrapMethods(this.mapper.getAllMethods(dto.abi, methods.mint)), - transfer: wrapMethods(this.mapper.getAllMethods(dto.abi, methods.transfer)), + approval: wrapMethods(this.mapper.getAllMethods(dto.methods, methods.approval)), + burn: wrapMethods(this.mapper.getAllMethods(dto.methods, methods.burn)), + mint: wrapMethods(this.mapper.getAllMethods(dto.methods, methods.mint)), + transfer: wrapMethods(this.mapper.getAllMethods(dto.methods, methods.transfer)), }; } @@ -416,7 +416,7 @@ export class TokensService { throw new BadRequestException('Invalid pool locator'); } - const abi = dto.interface?.abi || (await this.getAbiForMint(ctx, poolLocator, dto)); + const abi = dto.interface?.methods || (await this.getAbiForMint(ctx, poolLocator, dto)); const { method, params } = this.mapper.getMethodAndParams( abi, poolLocator.type === TokenType.FUNGIBLE, @@ -440,7 +440,7 @@ export class TokensService { throw new BadRequestException('Invalid pool locator'); } - const abi = dto.interface?.abi || this.mapper.getAbi(poolLocator.schema); + const abi = dto.interface?.methods || this.mapper.getAbi(poolLocator.schema); const { method, params } = this.mapper.getMethodAndParams( abi, poolLocator.type === TokenType.FUNGIBLE, @@ -464,7 +464,7 @@ export class TokensService { throw new BadRequestException('Invalid pool locator'); } - const abi = dto.interface?.abi || this.mapper.getAbi(poolLocator.schema); + const abi = dto.interface?.methods || this.mapper.getAbi(poolLocator.schema); const { method, params } = this.mapper.getMethodAndParams( abi, poolLocator.type === TokenType.FUNGIBLE, @@ -488,7 +488,7 @@ export class TokensService { throw new BadRequestException('Invalid pool locator'); } - const abi = dto.interface?.abi || this.mapper.getAbi(poolLocator.schema); + const abi = dto.interface?.methods || this.mapper.getAbi(poolLocator.schema); const { method, params } = this.mapper.getMethodAndParams( abi, poolLocator.type === TokenType.FUNGIBLE, diff --git a/test/suites/erc20.ts b/test/suites/erc20.ts index c42c7cf..7e7e9d8 100644 --- a/test/suites/erc20.ts +++ b/test/suites/erc20.ts @@ -565,7 +565,7 @@ export default (context: TestContext) => { from: IDENTITY, interface: { format: InterfaceFormat.ABI, - abi: burnMethods, + methods: burnMethods, }, }; @@ -634,7 +634,7 @@ export default (context: TestContext) => { from: '0x2', interface: { format: InterfaceFormat.ABI, - abi: burnMethods, + methods: burnMethods, }, }; @@ -665,27 +665,27 @@ export default (context: TestContext) => { const request: CheckInterfaceRequest = { poolLocator: ERC20_NO_DATA_POOL_ID, format: InterfaceFormat.ABI, - abi: ERC20NoDataABI.abi, + methods: ERC20NoDataABI.abi, }; const response: CheckInterfaceResponse = { approval: { format: InterfaceFormat.ABI, - abi: ERC20NoDataABI.abi.filter(m => m.name === APPROVE_NO_DATA), + methods: ERC20NoDataABI.abi.filter(m => m.name === APPROVE_NO_DATA), }, burn: { format: InterfaceFormat.ABI, - abi: ERC20NoDataABI.abi.filter( + methods: ERC20NoDataABI.abi.filter( m => m.name === BURN_NO_DATA || m.name === BURN_FROM_NO_DATA, ), }, mint: { format: InterfaceFormat.ABI, - abi: ERC20NoDataABI.abi.filter(m => m.name === MINT_NO_DATA), + methods: ERC20NoDataABI.abi.filter(m => m.name === MINT_NO_DATA), }, transfer: { format: InterfaceFormat.ABI, - abi: [ + methods: [ ...ERC20NoDataABI.abi.filter(m => m.name === TRANSFER_NO_DATA), ...ERC20NoDataABI.abi.filter(m => m.name === TRANSFER_FROM_NO_DATA), ], diff --git a/test/suites/erc721.ts b/test/suites/erc721.ts index d1e8406..86eb866 100644 --- a/test/suites/erc721.ts +++ b/test/suites/erc721.ts @@ -544,7 +544,7 @@ export default (context: TestContext) => { to: '0x123', interface: { format: InterfaceFormat.ABI, - abi: [safeMintAutoIndex], + methods: [safeMintAutoIndex], }, }; @@ -575,28 +575,28 @@ export default (context: TestContext) => { const request: CheckInterfaceRequest = { poolLocator: ERC721_NO_DATA_POOL_ID, format: InterfaceFormat.ABI, - abi: ERC721NoDataABI.abi, + methods: ERC721NoDataABI.abi, }; const response: CheckInterfaceResponse = { approval: { format: InterfaceFormat.ABI, - abi: [ + methods: [ ...ERC721NoDataABI.abi.filter(m => m.name === APPROVE_NO_DATA), ...ERC721NoDataABI.abi.filter(m => m.name === APPROVE_FOR_ALL_NO_DATA), ], }, burn: { format: InterfaceFormat.ABI, - abi: ERC721NoDataABI.abi.filter(m => m.name === BURN_NO_DATA), + methods: ERC721NoDataABI.abi.filter(m => m.name === BURN_NO_DATA), }, mint: { format: InterfaceFormat.ABI, - abi: ERC721NoDataABI.abi.filter(m => m.name === MINT_NO_DATA), + methods: ERC721NoDataABI.abi.filter(m => m.name === MINT_NO_DATA), }, transfer: { format: InterfaceFormat.ABI, - abi: [ + methods: [ ...ERC721NoDataABI.abi.filter( m => m.name === TRANSFER_NO_DATA && m.inputs.length === 4, ),