> ## 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.

# Decode traces

> Sync traces to a database with the contract ABI using Mirror.

This guide explains how to decode traces on-the-fly using [Mirror Decoding Functions](/mirror/reference/mirror-functions/decoding-functions) within transforms in Mirror pipelines.

## What you'll need

1. A Goldky account and the CLI installed

<Accordion title="Install Goldsky's CLI and log in">
  1) Install the Goldsky CLI:

     **For macOS/Linux:**

     ```shell theme={null}
     curl https://goldsky.com | sh
     ```

     **For Windows:**

     ```shell theme={null}
     npm install -g @goldskycom/cli
     ```

     <Note>Windows users need to have Node.js and npm installed first. Download from [nodejs.org](https://nodejs.org) if not already installed.</Note>
  2) Go to your [Project Settings](https://app.goldsky.com/dashboard/settings) page and create an API key.
  3) Back in your Goldsky CLI, log into your Project by running the command `goldsky login` and paste your API key.
  4) Now that you are logged in, run `goldsky` to get started:
     ```shell theme={null}
     goldsky
     ```
</Accordion>

1. A basic understanding of the [Mirror product](/mirror)
2. A destination sink to write your data to. In this example, we will use [PostgresSQL Sink](/mirror/sinks/postgres)

## Preface

In this guide we are going to show how to decode traces of a contract with Goldsky Mirror. We will use as example the [Friendtech contract](https://basescan.org/address/0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4) deployed in Base but the same logic applies to any other contract and chain for which there's an availabe Raw Traces Direct Indexing dataset as per [this list](/mirror/sources/direct-indexing).

## Pipeline definition

```yaml traces-decoding-pipeline.yaml expandable theme={null}
    name: decoding-traces
    apiVersion: 3
    sources:
      my_base_raw_traces:
        type: dataset
        dataset_name: base.raw_traces
        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_tx_decode(
              	_gs_fetch_abi('https://gist.githubusercontent.com/jeffling/0320808b7f3cc0e8d9cc6c3b113e8156/raw/99bde70acecd4dc339b5a81aae39954973f5d178/gistfile1.txt', 'raw'), 
                `input`, 
                `output`
            ) AS `decoded`, 
            block_number, 
            transaction_hash 
          FROM my_base_raw_traces
          WHERE address='0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4'
      friendtech_clean:
        primary_key: id
        # Clean up the previous transform, unnest the values from the `decoded` object.
        sql: >
          SELECT 
            `id`, 
            decoded.`function` AS `function_name`,
            decoded.decoded_inputs AS `decoded_inputs`,
            decoded.decoded_outputs AS `decoded_outputs`,
            block_number,
            transaction_hash
            FROM friendtech_decoded 
            WHERE decoded IS NOT NULL
    sinks:
      friendtech_logs:
        secret_name: EXAMPLE_SECRET
        type: postgres
        from: friendtech_clean
        schema: decoded_logs
        table: friendtech
```

There are two important transforms in this pipeline definition which are responsible for decoding the contract; we'll explain how they work in detail. If you copy and use this configuration file, make sure to update:

1. Your `secret_name`. If you already [created a secret](/mirror/manage-secrets), you can find it via the [CLI command](/reference/cli#secret) `goldsky secret list`.
2. The schema and table you want the data written to, by default it writes to `decoded_logs.friendtech`.

### Decoding transforms

Let's start analyzing the first transform:

```sql Transform: friendtech_decoded theme={null}
SELECT 
    `id`,
    _gs_tx_decode(
        _gs_fetch_abi('https://api.basescan.org/api?module=contract&action=getabi&address=0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4&apikey=YOUR_KEY', 'etherscan'), 
        `input`, 
        `output`
    ) AS `decoded`, 
    block_number, 
    transaction_hash 
    FROM base.raw_traces
    WHERE address='0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4'
```

Looking at the [Raw Traces schema](/reference/schema/EVM-schemas#raw-traces) we see there are standard traces columns such as `id`, `block_number` and `transaction_hash`. Since the columns
`input` and `output` are encoded we need to make use of the [\_gs\_tx\_decode](/mirror/reference/mirror-functions/decoding-functions#gs-tx-decode) to decode the data. This function takes the following parameters:

1. The contract ABI: rather than specifying ABI directly into the SQL query, which would made the code considerably less legible, we have decided to make use of the [\_gs\_fetch\_abi](/mirror/reference/mirror-functions/decoding-functions#gs_fetch_abi) function
   to fetch the ABI from the BaseScan API but you could also fetch it from an external public repository like Github Gist if you preferred.
2. `input`: as a second argument which refer to the data sent along with the message call.
3. `output`: as a third argument which refer to the data returned by the message call.

We are storing the decoding result in a new column called `decoded` which is a [nested ROW](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/types/#row) with the properties `event_param::TEXT[]` and `event_signature::TEXT`. We create a second transform that reads from the resulting dataset of this first SELECT query to access the decoded data:

```sql Transform: friendtech_clean theme={null}
SELECT 
    `id`, 
    decoded.`function` AS `function_name`,
    decoded.decoded_inputs AS `decoded_inputs`,
    decoded.decoded_outputs AS `decoded_outputs`,
    block_number,
    transaction_hash
    FROM friendtech_decoded 
    WHERE decoded IS NOT NULL
```

Notice how we add a filter for `decoded IS NOT NULL` as a safety measure to discard processing potential issues in the decoding phase.

## Deploying the pipeline

As a last step, to deploy this pipeline and start sinking decoded data into your database simply execute:

`goldsky pipeline apply <yaml file>`

## Conclusion

In this guide we have explored an example implementation of how we can use [Mirror Decoding Functions](/mirror/reference/mirror-functions/decoding-functions) to decode raw logs and stream them into our PostgreSQL database.
This same methodology can be applied to any contract of interest for any chain with `raw_log` and `raw_traces` Direct Indexing datasets available ([see list](/mirror/sources/direct-indexing)).

Goldsky also provides alternative decoding methods:

* [Subgraphs entity sources](/mirror/sources/subgraphs) to your pipelines.

Decoding contracts on the flight is a very powerful way of understanding onchain data and making it usable for your users.

Can't find what you're looking for? Reach out to us at [support@goldsky.com](mailto:support@goldsky.com) for help.
