diff --git a/docs/code/interfaces/types_arc_28.Arc28Event.md b/docs/code/interfaces/types_arc_28.Arc28Event.md index 4e44c34..666ef37 100644 --- a/docs/code/interfaces/types_arc_28.Arc28Event.md +++ b/docs/code/interfaces/types_arc_28.Arc28Event.md @@ -24,7 +24,7 @@ The arguments of the event, in order #### Defined in -[types/arc-28.ts:15](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L15) +[types/arc-28.ts:14](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L14) ___ @@ -36,7 +36,7 @@ Optional, user-friendly description for the event #### Defined in -[types/arc-28.ts:13](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L13) +[types/arc-28.ts:12](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L12) ___ @@ -48,4 +48,4 @@ The name of the event #### Defined in -[types/arc-28.ts:11](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L11) +[types/arc-28.ts:10](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L10) diff --git a/docs/code/interfaces/types_arc_28.Arc28EventGroup.md b/docs/code/interfaces/types_arc_28.Arc28EventGroup.md index a012e9e..2784ab0 100644 --- a/docs/code/interfaces/types_arc_28.Arc28EventGroup.md +++ b/docs/code/interfaces/types_arc_28.Arc28EventGroup.md @@ -26,7 +26,7 @@ Whether or not to silently (with warning log) continue if an error is encountere #### Defined in -[types/arc-28.ts:56](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L56) +[types/arc-28.ts:55](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L55) ___ @@ -38,7 +38,7 @@ The list of ARC-28 event definitions #### Defined in -[types/arc-28.ts:58](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L58) +[types/arc-28.ts:57](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L57) ___ @@ -50,7 +50,7 @@ The name to designate for this group of events. #### Defined in -[types/arc-28.ts:50](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L50) +[types/arc-28.ts:49](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L49) ___ @@ -62,7 +62,7 @@ Optional list of app IDs that this event should apply to #### Defined in -[types/arc-28.ts:52](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L52) +[types/arc-28.ts:51](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L51) ___ @@ -88,4 +88,4 @@ Optional predicate to indicate if these ARC-28 events should be processed for th #### Defined in -[types/arc-28.ts:54](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L54) +[types/arc-28.ts:53](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L53) diff --git a/docs/code/interfaces/types_arc_28.Arc28EventToProcess.md b/docs/code/interfaces/types_arc_28.Arc28EventToProcess.md index dafb5b0..ee76e81 100644 --- a/docs/code/interfaces/types_arc_28.Arc28EventToProcess.md +++ b/docs/code/interfaces/types_arc_28.Arc28EventToProcess.md @@ -32,7 +32,7 @@ The ARC-28 definition of the event #### Defined in -[types/arc-28.ts:36](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L36) +[types/arc-28.ts:35](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L35) ___ @@ -44,7 +44,7 @@ The name of the ARC-28 event that was triggered #### Defined in -[types/arc-28.ts:30](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L30) +[types/arc-28.ts:29](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L29) ___ @@ -56,7 +56,7 @@ The 4-byte hex prefix for the event #### Defined in -[types/arc-28.ts:34](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L34) +[types/arc-28.ts:33](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L33) ___ @@ -68,7 +68,7 @@ The signature of the event e.g. `EventName(type1,type2)` #### Defined in -[types/arc-28.ts:32](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L32) +[types/arc-28.ts:31](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L31) ___ @@ -80,4 +80,4 @@ The name of the ARC-28 event group the event belongs to #### Defined in -[types/arc-28.ts:28](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L28) +[types/arc-28.ts:27](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L27) diff --git a/docs/code/interfaces/types_arc_28.EmittedArc28Event.md b/docs/code/interfaces/types_arc_28.EmittedArc28Event.md index 9984565..55b95fb 100644 --- a/docs/code/interfaces/types_arc_28.EmittedArc28Event.md +++ b/docs/code/interfaces/types_arc_28.EmittedArc28Event.md @@ -34,7 +34,7 @@ The ordered arguments extracted from the event that was emitted #### Defined in -[types/arc-28.ts:42](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L42) +[types/arc-28.ts:41](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L41) ___ @@ -46,7 +46,7 @@ The named arguments extracted from the event that was emitted (where the argumen #### Defined in -[types/arc-28.ts:44](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L44) +[types/arc-28.ts:43](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L43) ___ @@ -62,7 +62,7 @@ The ARC-28 definition of the event #### Defined in -[types/arc-28.ts:36](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L36) +[types/arc-28.ts:35](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L35) ___ @@ -78,7 +78,7 @@ The name of the ARC-28 event that was triggered #### Defined in -[types/arc-28.ts:30](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L30) +[types/arc-28.ts:29](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L29) ___ @@ -94,7 +94,7 @@ The 4-byte hex prefix for the event #### Defined in -[types/arc-28.ts:34](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L34) +[types/arc-28.ts:33](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L33) ___ @@ -110,7 +110,7 @@ The signature of the event e.g. `EventName(type1,type2)` #### Defined in -[types/arc-28.ts:32](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L32) +[types/arc-28.ts:31](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L31) ___ @@ -126,4 +126,4 @@ The name of the ARC-28 event group the event belongs to #### Defined in -[types/arc-28.ts:28](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L28) +[types/arc-28.ts:27](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/types/arc-28.ts#L27) diff --git a/docs/code/modules/index.md b/docs/code/modules/index.md index bf4b9b9..4841c04 100644 --- a/docs/code/modules/index.md +++ b/docs/code/modules/index.md @@ -38,7 +38,7 @@ The blocks #### Defined in -[subscriptions.ts:867](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/subscriptions.ts#L867) +[subscriptions.ts:868](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/subscriptions.ts#L868) ___ @@ -65,4 +65,4 @@ The result of this subscription pull/poll. #### Defined in -[subscriptions.ts:53](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/subscriptions.ts#L53) +[subscriptions.ts:54](https://github.com/algorandfoundation/algokit-subscriber-ts/blob/main/src/subscriptions.ts#L54) diff --git a/src/subscriptions.ts b/src/subscriptions.ts index 16da28b..a29af20 100644 --- a/src/subscriptions.ts +++ b/src/subscriptions.ts @@ -1,7 +1,7 @@ import * as algokit from '@algorandfoundation/algokit-utils' import type { TransactionResult } from '@algorandfoundation/algokit-utils/types/indexer' import * as msgpack from 'algorand-msgpack' -import algosdk, { OnApplicationComplete } from 'algosdk' +import algosdk from 'algosdk' import type SearchForTransactions from 'algosdk/dist/types/client/v2/indexer/searchForTransactions' import sha512, { sha512_256 } from 'js-sha512' import { @@ -27,6 +27,7 @@ import ABIValue = algosdk.ABIValue import Algodv2 = algosdk.Algodv2 import Indexer = algosdk.Indexer import TransactionType = algosdk.TransactionType +import OnApplicationComplete = algosdk.OnApplicationComplete const deduplicateSubscribedTransactionsReducer = (dedupedTransactions: SubscribedTransaction[], t: SubscribedTransaction) => { const existing = dedupedTransactions.find((e) => e.id === t.id) diff --git a/src/types/arc-28.ts b/src/types/arc-28.ts index 2c84c15..a1ee438 100644 --- a/src/types/arc-28.ts +++ b/src/types/arc-28.ts @@ -1,7 +1,6 @@ import type { TransactionResult } from '@algorandfoundation/algokit-utils/types/indexer' import algosdk from 'algosdk' import ABIValue = algosdk.ABIValue -import TransactionType = algosdk.TransactionType /** * The definition of metadata for an ARC-28 event per https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0028.md#event. diff --git a/tests/scenarios/filters.spec.ts b/tests/scenarios/filters.spec.ts index f7fe2f3..9b5d26d 100644 --- a/tests/scenarios/filters.spec.ts +++ b/tests/scenarios/filters.spec.ts @@ -1,5 +1,6 @@ import * as algokit from '@algorandfoundation/algokit-utils' import { ApplicationOnComplete } from '@algorandfoundation/algokit-utils/types/indexer' +import { SendAtomicTransactionComposerResults } from '@algorandfoundation/algokit-utils/types/transaction' import algosdk, { Account, TransactionType } from 'algosdk' import { afterEach, beforeAll, beforeEach, describe, test } from 'vitest' import { TestingAppClient } from '../contract/client' @@ -7,7 +8,12 @@ import { filterFixture } from '../filterFixture' describe('Subscribing using various filters', () => { const { localnet, systemAccount, subscribeAndVerifyFilter, extractFromGroupResult, ...hooks } = filterFixture() - beforeAll(hooks.beforeAll, 10_000) + const beforeAllFixtures: (() => Promise)[] = [] + beforeAll(async () => { + await hooks.beforeAll() + await beforeAllFixtures.map(async (fixture) => await fixture()) + await localnet.context.waitForIndexer() + }, 30_000) beforeEach(hooks.beforeEach, 10_000) afterEach(hooks.afterEach) @@ -57,17 +63,25 @@ describe('Subscribing using various filters', () => { } } - test('Works for receiver(s) and sender(s)', async () => { - const { testAccount, algod, generateAccount } = localnet.context + let algoTransfersData: + | { + testAccount: Account + account2: Account + account3: Account + txns: SendAtomicTransactionComposerResults + } + | undefined = undefined + const algoTransfersFixture = async () => { + const { algod, generateAccount } = localnet.context + const testAccount = await generateAccount({ initialFunds: (10).algos() }) const account2 = await generateAccount({ initialFunds: (3).algos() }) const account3 = algokit.randomAccount() - const amount = (1).algos() const txns = await algokit.sendGroupOfTransactions( { transactions: [ - await algokit.transferAlgos({ amount, from: testAccount, to: account2, skipSending: true }, algod), - await algokit.transferAlgos({ amount, from: testAccount, to: account3, skipSending: true }, algod), - await algokit.transferAlgos({ amount, from: account2, to: testAccount, skipSending: true }, algod), + await algokit.transferAlgos({ amount: (1).algos(), from: testAccount, to: account2, note: 'a', skipSending: true }, algod), + await algokit.transferAlgos({ amount: (2).algos(), from: testAccount, to: account3, note: 'b', skipSending: true }, algod), + await algokit.transferAlgos({ amount: (1).algos(), from: account2, to: testAccount, note: 'c', skipSending: true }, algod), ].map((t) => ({ transaction: t.transaction, signer: algosdk.encodeAddress(t.transaction.from.publicKey) === testAccount.addr ? testAccount : account2, @@ -76,202 +90,121 @@ describe('Subscribing using various filters', () => { algod, ) - await subscribeAndVerifyFilter( - { - receiver: account2.addr, - }, - extractFromGroupResult(txns, 0), - ) - - await subscribeAndVerifyFilter( - { - receiver: [account2.addr, account3.addr], - }, - [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1)], - ) - - await subscribeAndVerifyFilter( - { - sender: account2.addr, - }, - extractFromGroupResult(txns, 2), - ) - - await subscribeAndVerifyFilter( - { - sender: [testAccount.addr, account2.addr], - }, - [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1), extractFromGroupResult(txns, 2)], - ) - }) + algoTransfersData = { + testAccount, + account2, + account3, + txns, + } + } + beforeAllFixtures.push(algoTransfersFixture) + + describe('Algo transfers', () => { + test('Single receiver', async () => { + const { account2, txns } = algoTransfersData! + + await subscribeAndVerifyFilter( + { + receiver: account2.addr, + }, + extractFromGroupResult(txns, 0), + ) + }) + test('Single sender', async () => { + const { account2, txns } = algoTransfersData! + + await subscribeAndVerifyFilter( + { + sender: account2.addr, + }, + extractFromGroupResult(txns, 2), + ) + }) + test('Multiple receivers', async () => { + const { account2, account3, txns } = algoTransfersData! + + await subscribeAndVerifyFilter( + { + receiver: [account2.addr, account3.addr], + }, + [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1)], + ) + }) + test('Multiple senders', async () => { + const { testAccount, account2, txns } = algoTransfersData! + + await subscribeAndVerifyFilter( + { + sender: [testAccount.addr, account2.addr], + }, + [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1), extractFromGroupResult(txns, 2)], + ) + }) - test('Works for min amount of algos', async () => { - const { testAccount, algod } = localnet.context - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - algokit.transferAlgos({ amount: (1).algos(), from: testAccount, to: testAccount, skipSending: true }, algod), - algokit.transferAlgos({ amount: (2).algos(), from: testAccount, to: testAccount, skipSending: true }, algod), - ], - signer: testAccount, - }, - algod, - ) + test('Works for min amount of algos', async () => { + const { testAccount, txns } = algoTransfersData! - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - minAmount: (1).algos().microAlgos + 1, - }, - extractFromGroupResult(txns, 1), - ) - }) - - test('Works for max amount of algos', async () => { - const { testAccount, algod } = localnet.context - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - algokit.transferAlgos({ amount: (1).algos(), from: testAccount, to: testAccount, skipSending: true }, algod), - algokit.transferAlgos({ amount: (2).algos(), from: testAccount, to: testAccount, skipSending: true }, algod), - ], - signer: testAccount, - }, - algod, - ) + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + minAmount: (1).algos().microAlgos + 1, + }, + extractFromGroupResult(txns, 1), + ) + }) - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - maxAmount: (1).algos().microAlgos + 1, - }, - extractFromGroupResult(txns, 0), - ) - }) + test('Works for max amount of algos', async () => { + const { testAccount, txns } = algoTransfersData! - test('Works for note prefix', async () => { - const { testAccount, algod } = localnet.context - const amount = (1).algos() - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - algokit.transferAlgos({ amount, from: testAccount, to: testAccount, note: 'a', skipSending: true }, algod), - algokit.transferAlgos({ amount, from: testAccount, to: testAccount, note: 'b', skipSending: true }, algod), - ], - signer: testAccount, - }, - algod, - ) + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + maxAmount: (1).algos().microAlgos + 1, + }, + extractFromGroupResult(txns, 0), + ) + }) - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - notePrefix: 'a', - }, - extractFromGroupResult(txns, 0), - ) + test('Works for note prefix', async () => { + const { testAccount, txns } = algoTransfersData! + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + notePrefix: 'a', + }, + extractFromGroupResult(txns, 0), + ) + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + notePrefix: 'b', + }, + extractFromGroupResult(txns, 1), + ) + }) }) - test('Works for asset ID(s)', async () => { - const { testAccount, algod } = localnet.context - const asset1 = await createAsset() + let assetsData: + | { + asset1: Awaited> + asset2: Awaited> + testAccount: Account + txns: SendAtomicTransactionComposerResults + } + | undefined = undefined + const assetsFixture = async () => { + const { algod, generateAccount } = localnet.context + const testAccount = await generateAccount({ initialFunds: (10).algos() }) + const asset1 = await createAsset(testAccount) const asset2 = await createAsset() const txns = await algokit.sendGroupOfTransactions( { transactions: [ algokit.assetOptIn({ account: testAccount, assetId: asset1.assetId, skipSending: true }, algod), algokit.assetOptIn({ account: testAccount, assetId: asset2.assetId, skipSending: true }, algod), - ], - signer: testAccount, - }, - algod, - ) - - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - assetId: asset1.assetId, - }, - extractFromGroupResult(txns, 0), - ) - - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - assetId: [asset1.assetId, asset2.assetId], - }, - [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1)], - ) - }) - - test('Works for asset create', async () => { - const { testAccount, algod } = localnet.context - const asset1 = await createAsset() - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - algokit.assetOptIn({ account: testAccount, assetId: asset1.assetId, skipSending: true }, algod), await createAssetTxn(testAccount), - ], - signer: testAccount, - }, - algod, - ) - - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - assetCreate: true, - }, - extractFromGroupResult(txns, 1), - ) - }) - - test('Works for transaction type(s)', async () => { - const { testAccount, algod } = localnet.context - const asset1 = await createAsset() - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - algokit.assetOptIn({ account: testAccount, assetId: asset1.assetId, skipSending: true }, algod), - await createAssetTxn(testAccount), - ], - signer: testAccount, - }, - algod, - ) - - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - type: TransactionType.axfer, - }, - extractFromGroupResult(txns, 0), - ) - - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - type: TransactionType.acfg, - }, - extractFromGroupResult(txns, 1), - ) - - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - type: [TransactionType.acfg, TransactionType.axfer], - }, - [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1)], - ) - }) - - test('Works for min amount of asset', async () => { - const { testAccount, algod } = localnet.context - const asset1 = await createAsset(testAccount) - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ algokit.transferAsset({ assetId: asset1.assetId, amount: 1, from: testAccount, to: testAccount, skipSending: true }, algod), algokit.transferAsset({ assetId: asset1.assetId, amount: 2, from: testAccount, to: testAccount, skipSending: true }, algod), ], @@ -280,133 +213,170 @@ describe('Subscribing using various filters', () => { algod, ) - await subscribeAndVerifyFilter( - { - type: TransactionType.axfer, - sender: testAccount.addr, - minAmount: 2, - }, - extractFromGroupResult(txns, 1), - ) - }) + assetsData = { + asset1, + asset2, + testAccount, + txns, + } + } + beforeAllFixtures.push(assetsFixture) + + describe('Asset transactions', () => { + test('Works for single asset ID', async () => { + const { testAccount, asset1, txns } = assetsData! + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + assetId: asset1.assetId, + }, + [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 3), extractFromGroupResult(txns, 4)], + ) + }) - test('Works for max amount of asset', async () => { - const { testAccount, algod } = localnet.context - const asset1 = await createAsset(testAccount) - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - algokit.transferAsset({ assetId: asset1.assetId, amount: 1, from: testAccount, to: testAccount, skipSending: true }, algod), - algokit.transferAsset({ assetId: asset1.assetId, amount: 2, from: testAccount, to: testAccount, skipSending: true }, algod), + test('Works for multiple asset IDs', async () => { + const { testAccount, asset1, asset2, txns } = assetsData! + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + assetId: [asset1.assetId, asset2.assetId], + }, + [ + extractFromGroupResult(txns, 0), + extractFromGroupResult(txns, 1), + extractFromGroupResult(txns, 3), + extractFromGroupResult(txns, 4), ], - signer: testAccount, - }, - algod, - ) - - await subscribeAndVerifyFilter( - { - type: TransactionType.axfer, - sender: testAccount.addr, - maxAmount: 1, - }, - extractFromGroupResult(txns, 0), - ) - }) + ) + }) - test('Works for app create', async () => { - const { testAccount, algod } = localnet.context - const app1 = await app({ create: true }) - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - app1.app.callAbi({ value: 'test' }, { sender: testAccount, sendParams: { skipSending: true } }), - (await app({ create: false }, testAccount)).creation.transaction, - ], - signer: testAccount, - }, - algod, - ) + test('Works for asset create', async () => { + const { testAccount, txns } = assetsData! - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - appCreate: true, - }, - extractFromGroupResult(txns, 1), - ) - }) + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + assetCreate: true, + }, + extractFromGroupResult(txns, 2), + ) + }) - test('Works for app ID(s)', async () => { - const { testAccount, algod } = localnet.context - const app1 = await app({ create: true }) - const app2 = await app({ create: true }) - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - app1.app.callAbi({ value: 'test' }, { sender: testAccount, sendParams: { skipSending: true } }), - app2.app.callAbi({ value: 'test' }, { sender: testAccount, sendParams: { skipSending: true } }), + test('Works for transaction type(s)', async () => { + const { testAccount, txns } = assetsData! + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + type: TransactionType.axfer, + }, + [ + extractFromGroupResult(txns, 0), + extractFromGroupResult(txns, 1), + extractFromGroupResult(txns, 3), + extractFromGroupResult(txns, 4), ], - signer: testAccount, - }, - algod, - ) - - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - appId: Number(app1.creation.confirmation!.applicationIndex!), - }, - extractFromGroupResult(txns, 0), - ) + ) + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + type: TransactionType.acfg, + }, + extractFromGroupResult(txns, 2), + ) + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + type: [TransactionType.acfg, TransactionType.axfer], + }, + [ + extractFromGroupResult(txns, 0), + extractFromGroupResult(txns, 1), + extractFromGroupResult(txns, 2), + extractFromGroupResult(txns, 3), + extractFromGroupResult(txns, 4), + ], + ) + }) - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - appId: [Number(app1.creation.confirmation!.applicationIndex!), Number(app2.creation.confirmation!.applicationIndex!)], - }, - [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1)], - ) - }) + test('Works for min amount of asset', async () => { + const { testAccount, txns } = assetsData! + + await subscribeAndVerifyFilter( + { + type: TransactionType.axfer, + sender: testAccount.addr, + minAmount: 2, + }, + extractFromGroupResult(txns, 4), + ) + }) - test('Works for on-complete(s)', async () => { - const { testAccount, algod } = localnet.context - const app1 = await app({ create: true }) - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - app1.app.callAbi({ value: 'test' }, { sender: testAccount, sendParams: { skipSending: true } }), - app1.app.optIn.optIn({}, { sender: testAccount, sendParams: { skipSending: true } }), - ], - signer: testAccount, - }, - algod, - ) + test('Works for max amount of asset', async () => { + const { testAccount, txns } = assetsData! + + await subscribeAndVerifyFilter( + { + type: TransactionType.axfer, + sender: testAccount.addr, + maxAmount: 1, + }, + [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1), extractFromGroupResult(txns, 3)], + ) + }) - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - appOnComplete: ApplicationOnComplete.optin, - }, - extractFromGroupResult(txns, 1), - ) + test('Works for max amount of asset with asset ID', async () => { + const { testAccount, txns, asset1 } = assetsData! + + await subscribeAndVerifyFilter( + { + type: TransactionType.axfer, + sender: testAccount.addr, + maxAmount: 1, + assetId: asset1.assetId, + }, + [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 3)], + ) + }) - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - appOnComplete: [ApplicationOnComplete.optin, ApplicationOnComplete.noop], - }, - [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1)], - ) + test('Works for min and max amount of asset with asset ID', async () => { + const { testAccount, txns, asset1 } = assetsData! + + await subscribeAndVerifyFilter( + { + type: TransactionType.axfer, + sender: testAccount.addr, + minAmount: 1, + maxAmount: 1, + assetId: asset1.assetId, + }, + [extractFromGroupResult(txns, 3)], + ) + }) }) - test('Works for method signature(s)', async () => { - const { testAccount, algod } = localnet.context + let appData: + | { + app1: Awaited> + app2: Awaited> + testAccount: Account + txns: SendAtomicTransactionComposerResults + } + | undefined = undefined + const appsFixture = async () => { + const { algod, generateAccount } = localnet.context + const testAccount = await generateAccount({ initialFunds: (10).algos() }) const app1 = await app({ create: true }) + const app2 = await app({ create: true }) const txns = await algokit.sendGroupOfTransactions( { transactions: [ - app1.app.callAbi({ value: 'test' }, { sender: testAccount, sendParams: { skipSending: true } }), + app1.app.callAbi({ value: 'test1' }, { sender: testAccount, sendParams: { skipSending: true } }), + app2.app.callAbi({ value: 'test2' }, { sender: testAccount, sendParams: { skipSending: true } }), + (await app({ create: false }, testAccount)).creation.transaction, app1.app.optIn.optIn({}, { sender: testAccount, sendParams: { skipSending: true } }), ], signer: testAccount, @@ -414,67 +384,117 @@ describe('Subscribing using various filters', () => { algod, ) - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - methodSignature: 'opt_in()void', - }, - extractFromGroupResult(txns, 1), - ) - - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - methodSignature: ['opt_in()void', 'madeUpMethod()void'], - }, - extractFromGroupResult(txns, 1), - ) + appData = { + app1, + app2, + testAccount, + txns, + } + } + beforeAllFixtures.push(appsFixture) + + describe('App transactions', () => { + test('Works for app create', async () => { + const { testAccount, txns } = appData! + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + appCreate: true, + }, + extractFromGroupResult(txns, 2), + ) + }) - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - methodSignature: ['opt_in()void', 'call_abi(string)string'], - }, - [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1)], - ) - }) + test('Works for app ID(s)', async () => { + const { testAccount, app1, app2, txns } = appData! + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + appId: Number(app1.creation.confirmation!.applicationIndex!), + }, + [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 3)], + ) + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + appId: [Number(app1.creation.confirmation!.applicationIndex!), Number(app2.creation.confirmation!.applicationIndex!)], + }, + [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1), extractFromGroupResult(txns, 3)], + ) + }) - test('Works for app args', async () => { - const { testAccount, algod } = localnet.context - const app1 = await app({ create: true }) - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - app1.app.callAbi({ value: 'test1' }, { sender: testAccount, sendParams: { skipSending: true } }), - app1.app.callAbi({ value: 'test2' }, { sender: testAccount, sendParams: { skipSending: true } }), + test('Works for on-complete(s)', async () => { + const { testAccount, txns } = appData! + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + appOnComplete: ApplicationOnComplete.optin, + }, + extractFromGroupResult(txns, 3), + ) + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + appOnComplete: [ApplicationOnComplete.optin, ApplicationOnComplete.noop], + }, + [ + extractFromGroupResult(txns, 0), + extractFromGroupResult(txns, 1), + extractFromGroupResult(txns, 2), + extractFromGroupResult(txns, 3), ], - signer: testAccount, - }, - algod, - ) + ) + }) - await subscribeAndVerifyFilter( - { - sender: testAccount.addr, - // ARC-4 string has first 2 bytes with length of the string so slice them off before comparing - appCallArgumentsMatch: (args) => !!args && Buffer.from(args[1].slice(2)).toString('utf-8') === 'test1', - }, - extractFromGroupResult(txns, 0), - ) + test('Works for method signature(s)', async () => { + const { testAccount, txns } = appData! + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + methodSignature: 'opt_in()void', + }, + extractFromGroupResult(txns, 3), + ) + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + methodSignature: ['opt_in()void', 'madeUpMethod()void'], + }, + extractFromGroupResult(txns, 3), + ) + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + methodSignature: ['opt_in()void', 'call_abi(string)string'], + }, + [extractFromGroupResult(txns, 0), extractFromGroupResult(txns, 1), extractFromGroupResult(txns, 3)], + ) + }) + + test('Works for app args', async () => { + const { testAccount, txns } = appData! + + await subscribeAndVerifyFilter( + { + sender: testAccount.addr, + // ARC-4 string has first 2 bytes with length of the string so slice them off before comparing + appCallArgumentsMatch: (args) => !!args && args.length > 1 && Buffer.from(args[1].slice(2)).toString('utf-8') === 'test1', + }, + extractFromGroupResult(txns, 0), + ) + }) }) test('Works for custom filter', async () => { - const { testAccount, algod } = localnet.context - const txns = await algokit.sendGroupOfTransactions( - { - transactions: [ - algokit.transferAlgos({ amount: (1).algos(), from: testAccount, to: testAccount, skipSending: true }, algod), - algokit.transferAlgos({ amount: (2).algos(), from: testAccount, to: testAccount, skipSending: true }, algod), - ], - signer: testAccount, - }, - algod, - ) + const { testAccount, txns } = algoTransfersData! await subscribeAndVerifyFilter( {