> ## Documentation Index
> Fetch the complete documentation index at: https://docs.goldsky.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Event decoding functions

Mirror provides 3 custom functions which can be in used within transforms to decode raw contract events during processing: `_gs_log_decode`, `_gs_tx_decode` and `_gs_fetch_abi`.

## \_gs\_log\_decode

This function decodes [Raw Logs](/mirror/reference/schema/EVM-schemas#raw-logs) data given a json string representing the ABI string. Since it is stateless it will scale very well across different pipeline sizes.

It will automatically use the matching event in the ABI, but partial ABIs that only contain the target event will also work.

```Function Function definition theme={null}
_gs_log_decode(string abi, string topics, string data)
```

#### Params

<ParamField path="abi" type="string" required>
  A string representing a json array of events and functions
</ParamField>

<ParamField path="topics" type="string" required>
  Name of the column the dataset which contains a string containing the topics, comma separated.
</ParamField>

<ParamField path="data" type="string" required>
  Name of the column the dataset which contains a string containing the payload of the event.
</ParamField>

#### Return

<ResponseField name="ROW ( event_param TEXT[], event_signature TEXT )" type="ROW">
  The function will output a [nested ROW](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/types/#row) type with `event_param::TEXT[]` and `event_signature::TEXT`. If you're planning on using a sink that doesn't support nested ROWs, you may want to do a further transformation to unnest the result.
</ResponseField>

#### Examples

<ResponseField name="Function Call">
  If you were using the [Raw Logs](/mirror/reference/schema/EVM-schemas#raw-logs) source dataset, you would call this function passing your ABI and using the 'topics' and 'data' columns. For example:

  ```sql theme={null}
  SELECT
   _gs_log_decode('[
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "name": "src",
          "type": "address"
        },
        {
          "indexed": true,
          "name": "dst",
          "type": "address"
        },
        {
          "indexed": false,
          "name": "wad",
          "type": "uint256"
        }
      ],
      "name": "Transfer",
      "type": "event"
    }
  ]', `topics`, `data`) as decoded
  from base.raw_logs
  ```

  You would then able to access both topics and data from the decoded column as `decoded.event_params` and `decoded.event_signature` in a second transform. See below for a complete example pipeline.
</ResponseField>

## \_gs\_tx\_decode

This function decodes [Raw Traces](/mirror/reference/schema/EVM-schemas#raw-traces) data given a json string representing the ABI string. Since it is stateless it will scale very well across different pipeline sizes.

It will automatically use the matching function in the ABI, but partial ABIs that only contain the target function will also work.

```Function Function definition theme={null}
_gs_tx_decode(string abi, string input, string output)
```

#### Params

<ParamField path="abi" type="string" required>
  A string representing a json array of events and functions
</ParamField>

<ParamField path="input" type="string" required>
  Name of the column the dataset which contains a string containing the data sent along with the message call.
</ParamField>

<ParamField path="data" type="string" required>
  Name of the column the dataset which contains a string containing the data returned by the message call.
</ParamField>

#### Return

<ResponseField name="ROW ( function TEXT, decoded_inputs TEXT[], decoded_outputs TEXT[] )" type="ROW">
  The function will output a [nested ROW](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/types/#row) type with the name of the function along with its inputs and outputs as arrays of strings. If you're planning on using a sink that doesn't support nested ROWs, you may want to do a further transformation to unnest the result.
</ResponseField>

#### Examples

<ResponseField name="Function Call">
  If you were using the [Raw Traces](/mirror/reference/schema/EVM-schemas#raw-traces) source dataset, you would call this function passing your ABI and using the 'input' and 'output' columns. For example:

  ```sql theme={null}
  SELECT
   _gs_tx_decode('[
     {
        "inputs": [
          {
            "internalType": "address",
            "name": "sharesSubject",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "amount",
            "type": "uint256"
          }
        ],
        "name": "getBuyPriceAfterFee",
        "outputs": [
          {
            "internalType": "uint256",
            "name": "",
            "type": "uint256"
          }
        ],
        "stateMutability": "view",
        "type": "function"
      }
  ]', `input`, `output`) as decoded
  from base.raw_logs
  ```

  You would then able to access both function and its inputs and outputs from the decoded columns as `decoded.function`, `decoded.decoded_inputs` and `decoded.decoded_outputs` in a second transform. You can see an example in [this guide](/mirror/guides/decoding-traces).
</ResponseField>

## \_gs\_fetch\_abi

We provide a convenient function for fetching ABIs, as often they are too big to copy and paste into the yaml definition.

<Warning>The ABI will be fetched once when a pipeline starts. If a pipeline is updated to a new version, or restarted, the ABI will be fetched again. It will not be re-read at any point while a pipeline is running.</Warning>

```Function Function definition theme={null}
_gs_fetch_abi(string url, string type)
```

#### Params

<ParamField path="url" type="string" required>
  The URL from where the ABI will be fetched
</ParamField>

<ParamField path="type" type="string" required>
  The type of url. Two types of value are accepted:

  * `etherscan` for etherscan or etherscan-compatible APIs
  * `raw` for json array ABIs.

  If you use etherscan-compatible APIs it's highly recommended to include your own API key if you are using this function with a large pipeline. The amount of workers may result in the
  API limits being surpassed.
</ParamField>

#### Examples

<ResponseField name="Function Call">
  Following up on the previous example, we can replace the raw ABI definition by a call to basescan using the \_gs\_log\_decode function:

  ```sql theme={null}
  select
      # Call the EVM decoding function
      _gs_log_decode(
          # This fetches the ABI from basescan, a `etherscan` compatible site.
          _gs_fetch_abi('https://api.basescan.org/api?module=contract&action=getabi&address=0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4&apikey=YOUR_KEY', 'etherscan'),
          `topics`,
          `data`
      ) as `decoded`,
  from base.raw_logs
  ```

  In some cases, you may prefer to host the ABI yourself and retrieve it from your a separate server such as Github Gist:

  ```sql theme={null}
  select
      # Call the EVM decoding function
      _gs_log_decode(
          # This fetches the ABI from Github Gist
          _gs_fetch_abi('https://gist.githubusercontent.com/JavierTrujilloG/bde43d5079ea5d03edcc68b4516fd297/raw/7b32cf313cd4810f65e726e531ad065eecc47dc1/friendtech_base.json', 'raw'),
          `topics`,
          `data`
      ) as `decoded`,
  from base.raw_logs
  ```
</ResponseField>

## Pipeline Example

Below is an example pipeline definition for decoding events for Friendtech contract in Base, make sure to visit [this guide](/mirror/guides/decoding-contract-events) for a more in-depth explanation of this pipeline:

```yaml theme={null}
name: friendtech-decoded-events
apiVersion: 3
sources:
  my_base_raw_logs:
    type: dataset
    dataset_name: base.raw_logs
    version: 1.0.0
transforms:
  friendtech_decoded:
    primary_key: id
    # Fetch the ABI from basescan, then use it to decode from the friendtech address.
    sql: >
      select 
        `id`,
        _gs_log_decode(
            _gs_fetch_abi('https://api.basescan.org/api?module=contract&action=getabi&address=0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4&apikey=YOUR_KEY', 'etherscan'), 
            `topics`, 
            `data`
        ) as `decoded`, 
        block_number, 
        transaction_hash 
      from my_base_raw_logs
      where address='0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4'
  friendtech_clean:
    primary_key: id
    # Clean up the previous transform, unnest the values from the `decoded` object.
    sql: >
      select 
        `id`, 
        decoded.event_params as `event_params`, 
        decoded.event_signature as `event_signature`,
        block_number,
        transaction_hash
      from friendtech_decoded 
      where decoded is not null
sinks:
  friendtech_events:
    secret_name: EXAMPLE_SECRET
    type: postgres
    from: friendtech_clean
    schema: decoded_events
    table: friendtech
```
