diff --git a/src/__tests__/unit/bundled-filtering.test.ts b/src/__tests__/unit/bundled-filtering.test.ts new file mode 100644 index 0000000..da9d92c --- /dev/null +++ b/src/__tests__/unit/bundled-filtering.test.ts @@ -0,0 +1,133 @@ +import {bundledTxsFilter, GQLEdgeInterface} from '@smartweave'; + +describe('Bundled transactions filtering', () => { + + it('should properly filter bundled transaction if only "parent" field available', async () => { + // given + const tx = { + node: { + id: 'DSan2S2AwuyZZwragrI_5L8RiraWjOsgMxaEpiYN2BY', + parent: { + id: 'kCdI59JIWPp6VTC9IKbSr9dRVgd1MxLk3z10N3NnUX4' + } + } + }; + + // when + const result = bundledTxsFilter(tx as unknown as GQLEdgeInterface); + + // then + expect(result).toBeFalsy(); + }); + + + it('should properly filter bundled transaction if only "bundledIn" field available', async () => { + // given + const tx = { + node: { + id: 'DSan2S2AwuyZZwragrI_5L8RiraWjOsgMxaEpiYN2BY', + bundledIn: { + id: 'kCdI59JIWPp6VTC9IKbSr9dRVgd1MxLk3z10N3NnUX4' + } + } + }; + + // when + const result = bundledTxsFilter(tx as unknown as GQLEdgeInterface); + + // then + expect(result).toBeFalsy(); + }); + + it('should properly filter bundled transaction if both "bundledIn" and "parent" field available', async () => { + // given + const tx = { + node: { + id: 'DSan2S2AwuyZZwragrI_5L8RiraWjOsgMxaEpiYN2BY', + bundledIn: { + id: 'kCdI59JIWPp6VTC9IKbSr9dRVgd1MxLk3z10N3NnUX4' + }, + parent: { + id: 'kCdI59JIWPp6VTC9IKbSr9dRVgd1MxLk3z10N3NnUX4' + } + } + }; + + // when + const result = bundledTxsFilter(tx as unknown as GQLEdgeInterface); + + // then + expect(result).toBeFalsy(); + }); + + + + it('should not filter transaction if "bundledIn" and "parent" not available', async () => { + // given + const tx = { + node: { + id: 'DSan2S2AwuyZZwragrI_5L8RiraWjOsgMxaEpiYN2BY', + } + }; + + // when + const result = bundledTxsFilter(tx as unknown as GQLEdgeInterface); + + // then + expect(result).toBeTruthy(); + }); + + + it('should not filter bundled transaction if "parent" field available and no id', async () => { + // given + const tx = { + node: { + id: 'DSan2S2AwuyZZwragrI_5L8RiraWjOsgMxaEpiYN2BY', + parent: { + } + } + }; + + // when + const result = bundledTxsFilter(tx as unknown as GQLEdgeInterface); + + // then + expect(result).toBeTruthy(); + }); + + it('should not filter bundled transaction if "bundledIn" field available and no id', async () => { + // given + const tx = { + node: { + id: 'DSan2S2AwuyZZwragrI_5L8RiraWjOsgMxaEpiYN2BY', + bundledIn: { + } + } + }; + + // when + const result = bundledTxsFilter(tx as unknown as GQLEdgeInterface); + + // then + expect(result).toBeTruthy(); + }); + + it('should not filter bundled transaction if both "bundledIn" and "parent" fields available with no ids', async () => { + // given + const tx = { + node: { + id: 'DSan2S2AwuyZZwragrI_5L8RiraWjOsgMxaEpiYN2BY', + parent: { + }, + bundledIn: { + } + } + }; + + // when + const result = bundledTxsFilter(tx as unknown as GQLEdgeInterface); + + // then + expect(result).toBeTruthy(); + }); +}); diff --git a/src/core/modules/impl/ArweaveGatewayInteractionsLoader.ts b/src/core/modules/impl/ArweaveGatewayInteractionsLoader.ts index 003dc83..5990f79 100644 --- a/src/core/modules/impl/ArweaveGatewayInteractionsLoader.ts +++ b/src/core/modules/impl/ArweaveGatewayInteractionsLoader.ts @@ -31,6 +31,10 @@ export interface GqlReqVariables { after?: string; } +export function bundledTxsFilter(tx: GQLEdgeInterface) { + return !tx.node.parent?.id && !tx.node.bundledIn?.id; +} + export class ArweaveGatewayInteractionsLoader implements InteractionsLoader { private readonly logger = LoggerFactory.INST.create('ArweaveGatewayInteractionsLoader'); @@ -56,6 +60,7 @@ export class ArweaveGatewayInteractionsLoader implements InteractionsLoader { fee { winston } quantity { winston } parent { id } + bundledIn { id } } cursor } @@ -133,8 +138,9 @@ export class ArweaveGatewayInteractionsLoader implements InteractionsLoader { // note: according to https://discord.com/channels/357957786904166400/756557551234973696/920918240702660638 // protection against "bundledIn" should not be necessary..but..better safe than sorry :-) + // note: it will be now necessary - with RedStone Sequencer const txInfos: GQLEdgeInterface[] = transactions.edges.filter( - (tx) => !tx.node.parent || !tx.node.parent.id || !tx.node.bundledIn || !tx.node.bundledIn.id + (tx) => bundledTxsFilter(tx) ); while (transactions.pageInfo.hasNextPage) { @@ -147,7 +153,7 @@ export class ArweaveGatewayInteractionsLoader implements InteractionsLoader { transactions = await this.getNextPage(variables); - txInfos.push(...transactions.edges.filter((tx) => !tx.node.parent || !tx.node.parent.id)); + txInfos.push(...transactions.edges.filter((tx) => bundledTxsFilter(tx))); } return txInfos; }