Implementing the Transaction Filter

Now that our project is setup, the next step will be to implement the transaction filter. This is where we will map transaction data from an eligible transaction to standardized ActionParams which are used by Boost Protocol. In the following example we will show you how to implement the transaction filter for a swap action on Balancer.

Head on over to your newly created [Project].ts file. You will see a function with the name of the action type you selected. We can start by mapping the imported BALANCER_VAULT contract with the to parameter, and the chainId from the SwapActionParams to the chainId in the TransactionFilter object.

[Project].ts
import { BALANCER_VAULT } from './constants'

export const swap = async (
  swap: SwapActionParams,
): Promise<TransactionFilter> => {

  const { chainId } = swap

  return compressJson({
    chainId,
    to: BALANCER_VAULT, 
    input: {},
  })
}

Now lets look at this swap transaction on Balancer.

We want to map the transaction details that are relevant to the swap action with the standardized Boost SwapActionParams. The SwapActionParams will be passed in by the boost creator and will need to match the details of the transaction in order to pass the filter.

type SwapActionParams = {
  chainId: number
  contractAddress?: Address
  tokenIn?: Address
  tokenOut?: Address
  amountIn?: bigint | FilterOperator
  amountOut?: bigint | FilterOperator
  recipient?: Address
  deadline?: bigint | FilterOperator
}

Mapping the transaction details with the SwapActionParams:

  • singleSwap.assetIn -> tokenIn

  • singleSwap.assetOut -> tokenOut

  • singleSwap.amount -> amountIn

  • limit -> amountOut (this value is the minimum amount of tokens received, so it may be less than the actual amount received in the transaction)

  • funds.recipient -> recipient

Need help or have questions? Join the Boost Protocol Discord

Now that we know how to properly map the transaction details with the standard action params, we can start to implement the filter.

Balancer.ts
import { BALANCER_ABI, BALANCER_VAULT } from './constants'

export const swap = async (
  swap: SwapActionParams,
): Promise<TransactionFilter> => {
  const {
    chainId,
    contractAddress,
    tokenIn,
    tokenOut,
    amountIn,
    amountOut,
    recipient,
  } = swap

  return compressJson({
    chainId: chainId,
    to: BALANCER_VAULT
    input: {
      $abi: BALANCER_ABI,
      singleSwap: {
        assetIn: tokenIn,
        assetOut: tokenOut,
        amount: amountIn,
      },
      limit: amountOut,
      funds: {
        recipient: recipient,
      },
    },
  })
}

Please take note that not all parameters will map this easily together. It is often the case where the ActionParams need to be manipulated in some way to match the transaction inputs. For example, you may need to map tokens addresses to pools, or use one of the available Operators to isolate the value inside of an array or string.

Once you have your transaction filter setup, we need to make sure it passes the unit tests that were setup during the setup process. Make sure to cover as many edge cases as you can while testing and cover all possible contract functions a valid transaction may use. To run the tests:

terminal
pnpm test --filter=@rabbitholegg/questdk-plugin-[project]

If you would like more in-depth information on how to manually setup additional test cases for your plugin please check out our page on testing.

pageTesting

If all the tests are passing, you are ready to move on to the final steps.

Last updated