Use the decoded_logs and decoded_tracesdirect indexing datasets. These are pre-decoded datasets, with coverage for common contracts, events, and functions.
Use the raw_logs dataset and decode inside a pipeline transform.
In this guide we are going to focus on the third method. We will use as example the Friendtech contract deployed in Base but the same logic applies to any other contract and chain for which there’s an availabe Raw Log Direct Indexing dataset as per this list.
In the _gs_fetch_abi function call below, we pull from a gist. You can also pull from basescan directly with an api key.
_gs_fetch_abi('<basescan-link>', 'etherscan'),
v3
v2 (deprecated)
event-decoding-pipeline.yaml
Copy
Ask AI
name: decoding-contract-eventsapiVersion: 3sources: my_base_raw_logs: type: dataset dataset_name: base.raw_logs version: 1.0.0transforms: friendtech_decoded: primary_key: id # Fetch the ABI from a gist (raw) sql: > SELECT `id`, _gs_log_decode( _gs_fetch_abi('https://gist.githubusercontent.com/jeffling/0320808b7f3cc0e8d9cc6c3b113e8156/raw/99bde70acecd4dc339b5a81aae39954973f5d178/gistfile1.txt', 'raw'), `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 NULLsinks: friendtech_events: secret_name: EXAMPLE_SECRET type: postgres from: friendtech_clean schema: decoded_events table: friendtech
Copy
Ask AI
sources: - type: dataset referenceName: base.raw_logs version: 1.0.0transforms: - referenceName: friendtech_decoded type: sql primaryKey: 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', 'etherscan'), `topics`, `data` ) AS `decoded`, block_number, transaction_hash FROM base.raw_logs WHERE address='0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4' - referenceName: friendtech_clean primaryKey: id type: sql # 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 NULLsinks: - referenceName: friendtech_events secretName: EXAMPLE_SECRET type: postgres sourceStreamName: friendtech_clean schema: decoded_events 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:
Your secret_name (v2: secretName). If you already created a secret, you can find it via the CLI commandgoldsky secret list.
The schema and table you want the data written to, by default it writes to decoded_events.friendtech.
SELECT `id`, _gs_log_decode( _gs_fetch_abi('https://api.basescan.org/api?module=contract&action=getabi&address=0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4', 'etherscan'), `topics`, `data` ) AS `decoded`, block_number, transaction_hash FROM base.raw_logs WHERE address='0xcf205808ed36593aa40a44f10c7f7c2f67d4a4d4'
Looking at the Raw Logs schema we see there are standard log columns such as id, block_number and transaction_hash. Since its columns
topics and data are encoded we need to make use of the _gs_log_decode to decode the data. This function takes the following parameters:
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 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.
topics: as a second argument to the decode function we pass in the name of the column in our dataset that contains the topics as comma-separated string.
data: as a third argument to the decode function we pass in the name of the column in our dataset that contains the encoded data.
Some columns are surrounded by backticks, this is because they are reserved words in Flink SQL. Common columns that need backticks are: data, output, value, and a full list can be found here.
We are storing the decoding result in a new column called decoded which is a nested 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:
Transform: friendtech_clean
Copy
Ask AI
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
Notice how we add a filter for decoded IS NOT NULL as a safety measure to discard processing potential issues in the decoding phase.
In this guide we have explored an example implementation of how we can use Mirror Decoding Functions to decode raw contract events 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).Goldsky also provides alternative decoding methods:
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 for help.