From e052e6b073c1e19e8d64fabb1bfa9e9d5e9d3a94 Mon Sep 17 00:00:00 2001 From: Andrew Skubarenko Date: Fri, 22 Mar 2024 03:05:52 +0300 Subject: [PATCH] Add a filter for token transfers; Make the fields of fetch options as nullable --- .../tzKTBalancesProvider.ts | 6 +- .../dipDupBridgeDataProvider.ts | 25 +- .../dipDupGraphQLQueryBuilder.ts | 89 ++++++-- .../dipDupGraphQLQueryBuilder/index.ts | 2 +- .../dipDupBridgeDataProvider/dtos.ts | 1 + .../dipDupBridgeDataProvider/index.ts | 2 +- .../dipDupBridgeDataProvider/mappers.ts | 42 ++++ .../localTokensBridgeDataProvider.ts | 2 +- .../transfersFetchOptions.ts | 5 + src/common/fetchOptions.ts | 4 +- .../dipDupGraphQLQueryBuilder.test.ts | 4 +- ...ansfersQueryByAccountAddressesTestCases.ts | 216 ++++++++++++++++-- .../getTokenTransfersQueryTestCases.ts | 177 +++++++++++++- ...ubscriptionsByAccountAddressesTestCases.ts | 23 +- 14 files changed, 534 insertions(+), 64 deletions(-) diff --git a/src/bridgeDataProviders/balancesBridgeDataProvider/tzKTBalancesProvider/tzKTBalancesProvider.ts b/src/bridgeDataProviders/balancesBridgeDataProvider/tzKTBalancesProvider/tzKTBalancesProvider.ts index 4124f8f..be7080f 100644 --- a/src/bridgeDataProviders/balancesBridgeDataProvider/tzKTBalancesProvider/tzKTBalancesProvider.ts +++ b/src/bridgeDataProviders/balancesBridgeDataProvider/tzKTBalancesProvider/tzKTBalancesProvider.ts @@ -40,7 +40,7 @@ export class TzKTBalancesProvider extends RemoteService implements BalancesBridg : this.getAllTokenBalances(accountAddress, tokensOrFetchOptions?.offset, tokensOrFetchOptions?.limit); } - protected async getAllTokenBalances(accountAddress: string, offset?: number, limit?: number) { + protected async getAllTokenBalances(accountAddress: string, offset?: number | null, limit?: number | null) { loggerProvider.logger.log(`Getting balances of the all tokens for the ${accountAddress} address`); let accountTokenBalances: AccountTokenBalances; @@ -127,8 +127,8 @@ export class TzKTBalancesProvider extends RemoteService implements BalancesBridg protected async getNonNativeTezosTokenBalances( address: string, tokenOrTokens: NonNativeTezosToken | readonly NonNativeTezosToken[] | null | undefined, - offset?: number, - limit?: number + offset?: number | null, + limit?: number | null ): Promise { const queryParams = this.getNonNativeTezosTokenBalancesQueryParams(address, tokenOrTokens); if (offset && offset > 0) diff --git a/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupBridgeDataProvider.ts b/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupBridgeDataProvider.ts index 73ba005..f4e2da6 100644 --- a/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupBridgeDataProvider.ts +++ b/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupBridgeDataProvider.ts @@ -1,5 +1,5 @@ import type { DipDupBridgeDataProviderOptions } from './dipDupBridgeDataProviderOptions'; -import { DipDupGraphQLQueryBuilder } from './dipDupGraphQLQueryBuilder'; +import { DipDupGraphQLQueryBuilder, type GraphQLTransfersFilter } from './dipDupGraphQLQueryBuilder'; import type { GraphQLResponse, BridgeOperationsDto, TokenBalancesDto } from './dtos'; import { DipDupAutoUpdateIsDisabledError, DipDupGraphQLError, DipDupTokenBalanceNotSupported, DipDupTokenTransferIdInvalid } from './errors'; import * as mappers from './mappers'; @@ -314,19 +314,21 @@ export class DipDupBridgeDataProvider extends RemoteService implements Transfers ): Promise { const offset = this.getPreparedOffsetParameter(fetchOptions); const limit = this.getPreparedLimitParameter(fetchOptions); + const filter = this.mapTransfersFilterToGraphQLTransfersFilter(fetchOptions?.filter); loggerProvider.lazyLogger.log?.(addressOrAddresses ? `Getting token transfers for ${typeof addressOrAddresses === 'string' ? `${addressOrAddresses} address.` : `[${addressOrAddresses.join(', ')}] addresses.`}` : 'Getting all token transfers.', - `Offset == ${offset}; Limit == ${limit}` + `Offset == ${offset}; Limit == ${limit}.`, + `Filter: ${JSON.stringify(filter)}.` ); const bridgeOperationsResponse = await this.fetch>('/v1/graphql', 'json', { method: 'POST', body: JSON.stringify({ - query: this.dipDupGraphQLQueryBuilder.getTokenTransfersQuery(addressOrAddresses, offset, limit) + query: this.dipDupGraphQLQueryBuilder.getTokenTransfersQuery(addressOrAddresses, offset, limit, filter) }) }); this.ensureNoDipDupGraphQLErrors(bridgeOperationsResponse); @@ -400,6 +402,23 @@ export class DipDupBridgeDataProvider extends RemoteService implements Transfers return new DipDupGraphQLQueryBuilder(); } + protected mapTransfersFilterToGraphQLTransfersFilter(filter: TransfersFetchOptions['filter']): GraphQLTransfersFilter | null { + if (!filter || (!filter.kind && !filter.status)) + return null; + + const type = filter.kind + ? mappers.mapBridgeTokenTransferKindsToBridgeOperationDtoTypes(filter.kind) + : undefined; + const status = filter.status + ? mappers.mapBridgeTokenTransferStatusesToBridgeOperationDtoStatuses(filter.status) + : undefined; + + return { + type, + status + }; + } + protected ensureNoDipDupGraphQLErrors(response: GraphQLResponse) { if (!response.errors || !response.errors.length) return; diff --git a/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupGraphQLQueryBuilder/dipDupGraphQLQueryBuilder.ts b/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupGraphQLQueryBuilder/dipDupGraphQLQueryBuilder.ts index 220cffa..b6dea2d 100644 --- a/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupGraphQLQueryBuilder/dipDupGraphQLQueryBuilder.ts +++ b/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupGraphQLQueryBuilder/dipDupGraphQLQueryBuilder.ts @@ -10,6 +10,11 @@ interface DipDupGraphQLQueryBuilderQueryParts { readonly l2TokenHolderFields: string; } +export interface GraphQLTransfersFilter { + type?: Array<'deposit' | 'withdrawal'> | null; + status?: Array<'Created' | 'Sealed' | 'Finished' | 'Failed'> | null; +} + export class DipDupGraphQLQueryBuilder { protected static readonly defaultQueryParts: DipDupGraphQLQueryBuilderQueryParts = { getBridgeOperationsFields, @@ -49,12 +54,14 @@ export class DipDupGraphQLQueryBuilder { getTokenTransfersQuery( addressOrAddresses: string | readonly string[] | undefined | null, offset: number, - limit: number + limit: number, + filter?: GraphQLTransfersFilter | undefined | null ): string { return this.getTokenTransfersQueryOrSteamSubscription( addressOrAddresses, 'query', 'bridge_operation', + this.getTransfersFilterWhereCondition(filter), `order_by: { created_at: desc }, offset: ${offset}, limit: ${limit}` ); } @@ -68,6 +75,7 @@ export class DipDupGraphQLQueryBuilder { addressOrAddresses, 'subscription', 'bridge_operation_stream', + undefined, `batch_size: ${batchSize}, cursor: {initial_value: {updated_at: "${startUpdatedAt.toISOString()}"}, ordering: ASC}` ); } @@ -167,22 +175,17 @@ export class DipDupGraphQLQueryBuilder { addressOrAddresses: string | readonly string[] | undefined | null, queryType: string, rootFieldName: string, + transfersFilterWhereCondition: string | undefined | null, queryExtraArguments: string ): GraphQLQuery { - let whereArgument = ''; - - if (addressOrAddresses) { - if (typeof addressOrAddresses === 'string' || (addressOrAddresses.length === 1)) { - const address = typeof addressOrAddresses === 'string' ? addressOrAddresses : addressOrAddresses[0]!; - whereArgument = this.getTokenTransfersWhereArgumentForOneAddress(address); - } - else if (addressOrAddresses.length > 1) { - whereArgument = this.getTokenTransfersWhereArgumentForMultipleAddresses(addressOrAddresses); - } - } - - if (whereArgument) - whereArgument += ','; + const addressOrAddressesWhereCondition = this.getTokenTransfersByAddressOrAddressesWhereCondition(addressOrAddresses); + const whereArgument = transfersFilterWhereCondition && addressOrAddressesWhereCondition + ? `where: { ${transfersFilterWhereCondition}, ${addressOrAddressesWhereCondition} },` + : transfersFilterWhereCondition + ? `where: { ${transfersFilterWhereCondition} },` + : addressOrAddressesWhereCondition + ? `where: { ${addressOrAddressesWhereCondition} },` + : ''; return `${queryType} TokenTransfers { ${rootFieldName}( @@ -194,7 +197,45 @@ export class DipDupGraphQLQueryBuilder { }`; } - private getTokenTransfersWhereArgumentForOneAddress(address: string): string { + protected getTransfersFilterWhereCondition(filter: GraphQLTransfersFilter | undefined | null): string { + if (!filter) + return ''; + + let condition = ''; + + if (filter.type) { + condition += filter.type.length === 1 + ? `type: { _eq: "${filter.type[0]}" }` + : `type: { _in: ${this.arrayToInOperatorValue(filter.type)} }`; + } + + if (filter.status) { + if (condition) + condition += ', '; + + condition += filter.status.length === 1 + ? `status: { _eq: "${filter.status[0]}" }` + : `status: { _in: ${this.arrayToInOperatorValue(filter.status)} }`; + } + + return condition; + } + + private getTokenTransfersByAddressOrAddressesWhereCondition(addressOrAddresses: string | readonly string[] | undefined | null) { + if (addressOrAddresses) { + if (typeof addressOrAddresses === 'string' || (addressOrAddresses.length === 1)) { + const address = typeof addressOrAddresses === 'string' ? addressOrAddresses : addressOrAddresses[0]!; + return this.getTokenTransfersByOneAddressWhereCondition(address); + } + else if (addressOrAddresses.length > 1) { + return this.getTokenTransfersByMultipleAddressesWhereCondition(addressOrAddresses); + } + } + + return ''; + } + + private getTokenTransfersByOneAddressWhereCondition(address: string): string { let accountFieldName: string; let preparedAddress = address; @@ -206,15 +247,13 @@ export class DipDupGraphQLQueryBuilder { accountFieldName = 'l1_account'; } - return `where: { - _or: [ - { deposit: { l1_transaction: { ${accountFieldName}: { _eq: "${preparedAddress}" } } } } - { withdrawal: { l2_transaction: { ${accountFieldName}: { _eq: "${preparedAddress}" } } } } - ] - }`; + return `_or: [ + { deposit: { l1_transaction: { ${accountFieldName}: { _eq: "${preparedAddress}" } } } } + { withdrawal: { l2_transaction: { ${accountFieldName}: { _eq: "${preparedAddress}" } } } } + ]`; } - private getTokenTransfersWhereArgumentForMultipleAddresses(addresses: readonly string[]): string { + private getTokenTransfersByMultipleAddressesWhereCondition(addresses: readonly string[]): string { const { tezosAddresses, etherlinkAddresses } = this.splitAddressesToTezosAndEtherlinkAddresses(addresses); const isNeedRootOrOperator = tezosAddresses.length > 0 && etherlinkAddresses.length > 0; @@ -239,7 +278,7 @@ export class DipDupGraphQLQueryBuilder { if (isNeedRootOrOperator) transactionCondition += ' ] }'; - return `where: { _or: [ + return `_or: [ { deposit: { l1_transaction: ${transactionCondition} @@ -250,7 +289,7 @@ export class DipDupGraphQLQueryBuilder { l2_transaction: ${transactionCondition} } } - ] }`; + ]`; } private splitAddressesToTezosAndEtherlinkAddresses( diff --git a/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupGraphQLQueryBuilder/index.ts b/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupGraphQLQueryBuilder/index.ts index 391d637..4f4b506 100644 --- a/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupGraphQLQueryBuilder/index.ts +++ b/src/bridgeDataProviders/dipDupBridgeDataProvider/dipDupGraphQLQueryBuilder/index.ts @@ -1 +1 @@ -export { DipDupGraphQLQueryBuilder } from './dipDupGraphQLQueryBuilder'; +export { DipDupGraphQLQueryBuilder, type GraphQLTransfersFilter } from './dipDupGraphQLQueryBuilder'; diff --git a/src/bridgeDataProviders/dipDupBridgeDataProvider/dtos.ts b/src/bridgeDataProviders/dipDupBridgeDataProvider/dtos.ts index 28230ac..28f6955 100644 --- a/src/bridgeDataProviders/dipDupBridgeDataProvider/dtos.ts +++ b/src/bridgeDataProviders/dipDupBridgeDataProvider/dtos.ts @@ -79,6 +79,7 @@ export interface BridgeWithdrawalDto { export interface BridgeOperationDto { type: 'deposit' | 'withdrawal'; + status: 'Created' | 'Sealed' | 'Finished' | 'Failed'; is_completed: boolean; is_successful: boolean; created_at: string; diff --git a/src/bridgeDataProviders/dipDupBridgeDataProvider/index.ts b/src/bridgeDataProviders/dipDupBridgeDataProvider/index.ts index 00e0024..21489c2 100644 --- a/src/bridgeDataProviders/dipDupBridgeDataProvider/index.ts +++ b/src/bridgeDataProviders/dipDupBridgeDataProvider/index.ts @@ -1,4 +1,4 @@ export { DipDupBridgeDataProvider } from './dipDupBridgeDataProvider'; export type { DipDupBridgeDataProviderOptions } from './dipDupBridgeDataProviderOptions'; -export { DipDupGraphQLQueryBuilder } from './dipDupGraphQLQueryBuilder'; +export { DipDupGraphQLQueryBuilder, type GraphQLTransfersFilter } from './dipDupGraphQLQueryBuilder'; diff --git a/src/bridgeDataProviders/dipDupBridgeDataProvider/mappers.ts b/src/bridgeDataProviders/dipDupBridgeDataProvider/mappers.ts index f0f57d3..18a2014 100644 --- a/src/bridgeDataProviders/dipDupBridgeDataProvider/mappers.ts +++ b/src/bridgeDataProviders/dipDupBridgeDataProvider/mappers.ts @@ -248,3 +248,45 @@ export const mapTokenBalancesDtoToAccountTokenBalances = (dto: TokenBalancesDto, } satisfies AccountTokenBalances; } }; + +const tokenTransferKindToBridgeOperationDtoTypeMap = new Map() + .set(BridgeTokenTransferKind.Deposit, 'deposit') + .set(BridgeTokenTransferKind.Withdrawal, 'withdrawal'); + +export const mapBridgeTokenTransferKindToBridgeOperationDtoType = (kind: BridgeTokenTransferKind): BridgeOperationDto['type'] | null => { + return tokenTransferKindToBridgeOperationDtoTypeMap.get(kind) || null; +}; + +export const mapBridgeTokenTransferKindsToBridgeOperationDtoTypes = (kinds: readonly BridgeTokenTransferKind[]): Array => { + const result: Array = []; + + for (const kind of kinds) { + const type = mapBridgeTokenTransferKindToBridgeOperationDtoType(kind); + if (type) + result.push(type); + } + + return result; +}; + +const tokenTransferStatusToBridgeOperationDtoStatusMap = new Map() + .set(BridgeTokenTransferStatus.Created, 'Created') + .set(BridgeTokenTransferStatus.Sealed, 'Sealed') + .set(BridgeTokenTransferStatus.Finished, 'Finished') + .set(BridgeTokenTransferStatus.Failed, 'Failed'); + +export const mapBridgeTokenTransferStatusToBridgeOperationDtoStatus = (status: BridgeTokenTransferStatus): BridgeOperationDto['status'] | null => { + return tokenTransferStatusToBridgeOperationDtoStatusMap.get(status) || null; +}; + +export const mapBridgeTokenTransferStatusesToBridgeOperationDtoStatuses = (statuses: readonly BridgeTokenTransferStatus[]): Array => { + const result: Array = []; + + for (const status of statuses) { + const type = mapBridgeTokenTransferStatusToBridgeOperationDtoStatus(status); + if (type) + result.push(type); + } + + return result; +}; diff --git a/src/bridgeDataProviders/tokensBridgeDataProvider/localTokensBridgeDataProvider.ts b/src/bridgeDataProviders/tokensBridgeDataProvider/localTokensBridgeDataProvider.ts index 147c3aa..a10fa45 100644 --- a/src/bridgeDataProviders/tokensBridgeDataProvider/localTokensBridgeDataProvider.ts +++ b/src/bridgeDataProviders/tokensBridgeDataProvider/localTokensBridgeDataProvider.ts @@ -63,7 +63,7 @@ export class LocalTokensBridgeDataProvider implements TokensBridgeDataProvider { const offset = fetchOptions.offset || 0; const limit = fetchOptions.limit && (fetchOptions.limit + offset); - return Promise.resolve(this.tokenPairs.slice(offset, limit)); + return Promise.resolve(this.tokenPairs.slice(offset, limit || undefined)); } private createTokenPairsByTokenMap(tokenPairs: readonly TokenPair[]): TokenPairsByTokenMap { diff --git a/src/bridgeDataProviders/transfersBridgeDataProvider/transfersFetchOptions.ts b/src/bridgeDataProviders/transfersBridgeDataProvider/transfersFetchOptions.ts index a3a3773..e1b3326 100644 --- a/src/bridgeDataProviders/transfersBridgeDataProvider/transfersFetchOptions.ts +++ b/src/bridgeDataProviders/transfersBridgeDataProvider/transfersFetchOptions.ts @@ -1,4 +1,9 @@ +import type { BridgeTokenTransferKind, BridgeTokenTransferStatus } from '../../bridgeCore'; import type { FetchOptions } from '../../common'; export interface TransfersFetchOptions extends FetchOptions { + filter?: { + kind?: BridgeTokenTransferKind[] | null; + status?: BridgeTokenTransferStatus[] | null; + } } diff --git a/src/common/fetchOptions.ts b/src/common/fetchOptions.ts index 72cc1c4..c41cc6a 100644 --- a/src/common/fetchOptions.ts +++ b/src/common/fetchOptions.ts @@ -1,4 +1,4 @@ export interface FetchOptions { - offset?: number; - limit?: number; + offset?: number | null; + limit?: number | null; } diff --git a/tests/dipDupGraphQLQueryBuilder/dipDupGraphQLQueryBuilder.test.ts b/tests/dipDupGraphQLQueryBuilder/dipDupGraphQLQueryBuilder.test.ts index 61e0d66..ff24203 100644 --- a/tests/dipDupGraphQLQueryBuilder/dipDupGraphQLQueryBuilder.test.ts +++ b/tests/dipDupGraphQLQueryBuilder/dipDupGraphQLQueryBuilder.test.ts @@ -41,7 +41,7 @@ describe('DipDup GraphQL Query Builder', () => { test.each(getTokenTransfersQueryTestCases)( 'Build the getTokenTransfers query %s', (_, testData) => { - const query = queryBuilder.getTokenTransfersQuery(null, testData.offset, testData.limit); + const query = queryBuilder.getTokenTransfersQuery(null, testData.offset, testData.limit, testData.filter); const preparedQuery = prepareQueryFormatting(query); expect(preparedQuery).toBe(testData.expectedQuery); @@ -51,7 +51,7 @@ describe('DipDup GraphQL Query Builder', () => { test.each(getTokenTransfersQueryByAccountAddressesTestCases)( 'Build the getTokenTransfers query %s', (_, testData) => { - const query = queryBuilder.getTokenTransfersQuery(testData.address, testData.offset, testData.limit); + const query = queryBuilder.getTokenTransfersQuery(testData.address, testData.offset, testData.limit, testData.filter); const preparedQuery = prepareQueryFormatting(query); expect(preparedQuery).toBe(testData.expectedQuery); diff --git a/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersQueryByAccountAddressesTestCases.ts b/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersQueryByAccountAddressesTestCases.ts index 267e826..1919395 100644 --- a/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersQueryByAccountAddressesTestCases.ts +++ b/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersQueryByAccountAddressesTestCases.ts @@ -1,16 +1,18 @@ /* eslint-disable max-len */ import { PositiveTestCaseBase } from './testCase'; +import type { GraphQLTransfersFilter } from '../../../src/bridgeDataProviders/dipDupBridgeDataProvider'; type TestCase = PositiveTestCaseBase<{ address: string | string[] | undefined | null, offset: number, - limit: number + limit: number, + filter?: GraphQLTransfersFilter }>; type TestCases = readonly TestCase[]; export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ [ - 'by one Tezos address (as string), offset: 0, limit: 100', + 'transfers by one Tezos address (as string), offset: 0, limit: 100', { address: 'tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', offset: 0, @@ -19,7 +21,7 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ } ], [ - 'by one Tezos address (as array of strings), offset: 0, limit: 100', + 'transfers by one Tezos address (as array of strings), offset: 0, limit: 100', { address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF'], offset: 0, @@ -28,7 +30,7 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ } ], [ - 'by one Etherlink address (as string), offset: 0, limit: 100', + 'transfers by one Etherlink address (as string), offset: 0, limit: 100', { address: '0x4A1819c83A78C948db50f80fED82721Dd0401c9b', offset: 0, @@ -37,7 +39,7 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ } ], [ - 'by one Etherlink address (as array of strings), offset: 0, limit: 100', + 'transfers by one Etherlink address (as array of strings), offset: 0, limit: 100', { address: ['0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], offset: 0, @@ -47,7 +49,7 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ ], [ - 'by two Tezos addresses, offset: 0, limit: 100', + 'transfers by two Tezos addresses, offset: 0, limit: 100', { address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', 'tz1YG6P2GTQKFpd9jeuESam2vg6aA9HHRkKo'], offset: 0, @@ -56,7 +58,7 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ } ], [ - 'by two Etherlink addresses, offset: 0, limit: 100', + 'transfers by two Etherlink addresses, offset: 0, limit: 100', { address: ['0x4A1819c83A78C948db50f80fED82721Dd0401c9b', '0xBefD2C6fFC36249ebEbd21d6DF6376ecF3BAc448'], offset: 0, @@ -65,7 +67,7 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ } ], [ - 'by three Tezos addresses, offset: 0, limit: 100', + 'transfers by three Tezos addresses, offset: 0, limit: 100', { address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', 'tz1YG6P2GTQKFpd9jeuESam2vg6aA9HHRkKo', 'tz1N96ka7u5cKVbrLdK6wa6KyLoAgdfDzKns'], offset: 0, @@ -74,7 +76,7 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ } ], [ - 'by three Etherlink addresses, offset: 0, limit: 100', + 'transfers by three Etherlink addresses, offset: 0, limit: 100', { address: ['0x4A1819c83A78C948db50f80fED82721Dd0401c9b', '0xBefD2C6fFC36249ebEbd21d6DF6376ecF3BAc448', '0xce912ad4F73dBC149110091044a8f58Fd17B2b53'], offset: 0, @@ -84,7 +86,7 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ ], [ - 'by Tezos address and Etherlink address, offset: 0, limit: 100', + 'transfers by Tezos address and Etherlink address, offset: 0, limit: 100', { address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], offset: 0, @@ -93,7 +95,7 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ } ], [ - 'by two Tezos addresses and two Etherlink addresses, offset: 0, limit: 100', + 'transfers by two Tezos addresses and two Etherlink addresses, offset: 0, limit: 100', { address: [ 'tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', @@ -107,7 +109,7 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ } ], [ - 'by three Tezos addresses and three Etherlink addresses, offset: 0, limit: 100', + 'transfers by three Tezos addresses and three Etherlink addresses, offset: 0, limit: 100', { address: [ 'tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', @@ -121,5 +123,193 @@ export const getTokenTransfersQueryByAccountAddressesTestCases: TestCases = [ limit: 100, expectedQuery: 'query TokenTransfers { bridge_operation( where: { _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _in: ["tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF","tz1YG6P2GTQKFpd9jeuESam2vg6aA9HHRkKo","tz1N96ka7u5cKVbrLdK6wa6KyLoAgdfDzKns"] } }{ l2_account: { _in: ["4a1819c83a78c948db50f80fed82721dd0401c9b","befd2c6ffc36249ebebd21d6df6376ecf3bac448","ce912ad4f73dbc149110091044a8f58fd17b2b53"] } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _in: ["tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF","tz1YG6P2GTQKFpd9jeuESam2vg6aA9HHRkKo","tz1N96ka7u5cKVbrLdK6wa6KyLoAgdfDzKns"] } }{ l2_account: { _in: ["4a1819c83a78c948db50f80fed82721dd0401c9b","befd2c6ffc36249ebebd21d6df6376ecf3bac448","ce912ad4f73dbc149110091044a8f58fd17b2b53"] } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' } - ] + ], + + [ + 'transfers by Tezos address and Etherlink address, offset: 0, limit: 100 (with empty type filter)', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + type: [] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _in: [] }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'transfers by Tezos address and Etherlink address, offset: 0, limit: 100 (with empty status filter)', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + status: [] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _in: [] }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'transfers by Tezos address and Etherlink address, offset: 0, limit: 100 (with empty type and status filters)', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + type: [], + status: [] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _in: [] }, status: { _in: [] }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + + [ + 'deposits by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + type: ['deposit'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _eq: "deposit" }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'withdrawals by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + type: ['withdrawal'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _eq: "withdrawal" }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'deposit and withdrawals by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + type: ['deposit', 'withdrawal'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _in: ["deposit","withdrawal"] }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + + [ + 'created transfers by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + status: ['Created'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _eq: "Created" }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'sealed transfers by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + status: ['Sealed'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _eq: "Sealed" }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'finished transfers by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + status: ['Finished'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _eq: "Finished" }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'failed transfers by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + status: ['Failed'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _eq: "Failed" }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'created and finished transfers by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + status: ['Created', 'Finished'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _in: ["Created","Finished"] }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'created, sealed and finished transfers by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + status: ['Created', 'Sealed', 'Finished'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _in: ["Created","Sealed","Finished"] }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + + [ + 'created and finished deposits by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + type: ['deposit'], + status: ['Created', 'Finished'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _eq: "deposit" }, status: { _in: ["Created","Finished"] }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'created and sealed withdrawals by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + type: ['withdrawal'], + status: ['Created', 'Sealed'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _eq: "withdrawal" }, status: { _in: ["Created","Sealed"] }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'deposit and withdrawals with created and finished statuses by Tezos address and Etherlink address, offset: 0, limit: 100', + { + address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], + offset: 0, + limit: 100, + filter: { + type: ['deposit', 'withdrawal'], + status: ['Created', 'Finished'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _in: ["deposit","withdrawal"] }, status: { _in: ["Created","Finished"] }, _or: [ { deposit: { l1_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } { withdrawal: { l2_transaction: { _or: [ { l1_account: { _eq: "tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF" } }{ l2_account: { _eq: "4a1819c83a78c948db50f80fed82721dd0401c9b" } } ] } } } ] }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], ]; diff --git a/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersQueryTestCases.ts b/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersQueryTestCases.ts index 2e0bb0a..c9141cf 100644 --- a/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersQueryTestCases.ts +++ b/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersQueryTestCases.ts @@ -1,9 +1,11 @@ /* eslint-disable max-len */ import { PositiveTestCaseBase } from './testCase'; +import type { GraphQLTransfersFilter } from '../../../src/bridgeDataProviders/dipDupBridgeDataProvider'; type TestCase = PositiveTestCaseBase<{ offset: number, - limit: number + limit: number, + filter?: GraphQLTransfersFilter }>; type TestCases = readonly TestCase[]; @@ -24,4 +26,177 @@ export const getTokenTransfersQueryTestCases: TestCases = [ expectedQuery: 'query TokenTransfers { bridge_operation( order_by: { created_at: desc }, offset: 300, limit: 10 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' } ], + + [ + 'all, offset: 0, limit: 100 (with empty type filter)', + { + offset: 0, + limit: 100, + filter: { + type: [] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _in: [] } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all, offset: 0, limit: 100 (with empty status filter)', + { + offset: 0, + limit: 100, + filter: { + status: [] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _in: [] } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all, offset: 0, limit: 100 (with empty type and status filters)', + { + offset: 0, + limit: 100, + filter: { + type: [], + status: [] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _in: [] }, status: { _in: [] } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + + [ + 'all deposits, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + type: ['deposit'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _eq: "deposit" } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all withdrawals, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + type: ['withdrawal'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _eq: "withdrawal" } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all deposit and withdrawals, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + type: ['deposit', 'withdrawal'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _in: ["deposit","withdrawal"] } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + + [ + 'all created transfers, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + status: ['Created'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _eq: "Created" } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all sealed transfers, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + status: ['Sealed'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _eq: "Sealed" } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all finished transfers, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + status: ['Finished'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _eq: "Finished" } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all failed transfers, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + status: ['Failed'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _eq: "Failed" } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all created and finished transfers, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + status: ['Created', 'Finished'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _in: ["Created","Finished"] } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all created, sealed and finished transfers, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + status: ['Created', 'Sealed', 'Finished'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { status: { _in: ["Created","Sealed","Finished"] } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + + [ + 'all created and finished deposits, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + type: ['deposit'], + status: ['Created', 'Finished'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _eq: "deposit" }, status: { _in: ["Created","Finished"] } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all created and sealed withdrawals, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + type: ['withdrawal'], + status: ['Created', 'Sealed'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _eq: "withdrawal" }, status: { _in: ["Created","Sealed"] } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], + [ + 'all deposit and withdrawals with created and finished statuses, offset: 0, limit: 100', + { + offset: 0, + limit: 100, + filter: { + type: ['deposit', 'withdrawal'], + status: ['Created', 'Finished'] + }, + expectedQuery: 'query TokenTransfers { bridge_operation( where: { type: { _in: ["deposit","withdrawal"] }, status: { _in: ["Created","Finished"] } }, order_by: { created_at: desc }, offset: 0, limit: 100 ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' + } + ], ]; diff --git a/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersSubscriptionsByAccountAddressesTestCases.ts b/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersSubscriptionsByAccountAddressesTestCases.ts index 0d63f05..8d15292 100644 --- a/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersSubscriptionsByAccountAddressesTestCases.ts +++ b/tests/dipDupGraphQLQueryBuilder/testCases/getTokenTransfersSubscriptionsByAccountAddressesTestCases.ts @@ -9,7 +9,7 @@ type TestCases = readonly TestCase[]; export const getTokenTransfersSubscriptionsByAccountAddressesTestCases: TestCases = [ [ - 'by one Tezos address (as string)', + 'transfers by one Tezos address (as string)', { address: 'tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', startUpdatedAt: new Date('2024-03-17T12:13:10.104Z'), @@ -17,7 +17,7 @@ export const getTokenTransfersSubscriptionsByAccountAddressesTestCases: TestCase } ], [ - 'by one Tezos address (as array of strings)', + 'transfers by one Tezos address (as array of strings)', { address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF'], startUpdatedAt: new Date('2024-03-17T12:13:10.104Z'), @@ -25,7 +25,7 @@ export const getTokenTransfersSubscriptionsByAccountAddressesTestCases: TestCase } ], [ - 'by one Etherlink address (as string)', + 'transfers by one Etherlink address (as string)', { address: '0x4A1819c83A78C948db50f80fED82721Dd0401c9b', startUpdatedAt: new Date('2024-03-17T12:13:10.104Z'), @@ -33,7 +33,7 @@ export const getTokenTransfersSubscriptionsByAccountAddressesTestCases: TestCase } ], [ - 'by one Etherlink address (as array of strings)', + 'transfers by one Etherlink address (as array of strings)', { address: ['0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], startUpdatedAt: new Date('2024-03-17T12:13:10.104Z'), @@ -42,7 +42,7 @@ export const getTokenTransfersSubscriptionsByAccountAddressesTestCases: TestCase ], [ - 'by two Tezos addresses', + 'transfers by two Tezos addresses', { address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', 'tz1YG6P2GTQKFpd9jeuESam2vg6aA9HHRkKo'], startUpdatedAt: new Date('2024-03-17T12:13:10.104Z'), @@ -50,7 +50,7 @@ export const getTokenTransfersSubscriptionsByAccountAddressesTestCases: TestCase } ], [ - 'by two Etherlink addresses', + 'transfers by two Etherlink addresses', { address: ['0x4A1819c83A78C948db50f80fED82721Dd0401c9b', '0xBefD2C6fFC36249ebEbd21d6DF6376ecF3BAc448'], startUpdatedAt: new Date('2024-03-17T12:13:10.104Z'), @@ -58,7 +58,7 @@ export const getTokenTransfersSubscriptionsByAccountAddressesTestCases: TestCase } ], [ - 'by three Tezos addresses', + 'transfers by three Tezos addresses', { address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', 'tz1YG6P2GTQKFpd9jeuESam2vg6aA9HHRkKo', 'tz1N96ka7u5cKVbrLdK6wa6KyLoAgdfDzKns'], startUpdatedAt: new Date('2024-03-17T12:13:10.104Z'), @@ -66,16 +66,15 @@ export const getTokenTransfersSubscriptionsByAccountAddressesTestCases: TestCase } ], [ - 'by three Etherlink addresses', + 'transfers by three Etherlink addresses', { address: ['0x4A1819c83A78C948db50f80fED82721Dd0401c9b', '0xBefD2C6fFC36249ebEbd21d6DF6376ecF3BAc448', '0xce912ad4F73dBC149110091044a8f58Fd17B2b53'], startUpdatedAt: new Date('2024-03-17T12:13:10.104Z'), expectedQuery: 'subscription TokenTransfers { bridge_operation_stream( where: { _or: [ { deposit: { l1_transaction: { l2_account: { _in: ["4a1819c83a78c948db50f80fed82721dd0401c9b","befd2c6ffc36249ebebd21d6df6376ecf3bac448","ce912ad4f73dbc149110091044a8f58fd17b2b53"] } } } } { withdrawal: { l2_transaction: { l2_account: { _in: ["4a1819c83a78c948db50f80fed82721dd0401c9b","befd2c6ffc36249ebebd21d6df6376ecf3bac448","ce912ad4f73dbc149110091044a8f58fd17b2b53"] } } } } ] }, batch_size: 10, cursor: {initial_value: {updated_at: "2024-03-17T12:13:10.104Z"}, ordering: ASC} ) { type is_completed is_successful created_at updated_at deposit { l1_transaction { level operation_hash counter nonce amount ticket { token { type contract_address token_id } } l1_account l2_account timestamp inbox_message { type level index } } l2_transaction { level transaction_hash log_index amount l2_token { id } timestamp } } withdrawal { l1_transaction { level operation_hash counter nonce timestamp } l2_transaction { level transaction_hash log_index amount l2_token { id ticket { token { type contract_address token_id } } } l1_account l2_account timestamp outbox_message { level index commitment { hash } proof cemented_at } } } } }' } ], - [ - 'by Tezos address and Etherlink address', + 'transfers by Tezos address and Etherlink address', { address: ['tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', '0x4A1819c83A78C948db50f80fED82721Dd0401c9b'], startUpdatedAt: new Date('2024-03-17T12:13:10.104Z'), @@ -83,7 +82,7 @@ export const getTokenTransfersSubscriptionsByAccountAddressesTestCases: TestCase } ], [ - 'by two Tezos addresses and two Etherlink addresses', + 'transfers by two Tezos addresses and two Etherlink addresses', { address: [ 'tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF', @@ -96,7 +95,7 @@ export const getTokenTransfersSubscriptionsByAccountAddressesTestCases: TestCase } ], [ - 'by three Tezos addresses and three Etherlink addresses', + 'transfers by three Tezos addresses and three Etherlink addresses', { address: [ 'tz1M6VFkpALGXYoP5CvobR3z1pYu7KvirpMF',