Skip to content

Commit

Permalink
Update the documentation for data loaders
Browse files Browse the repository at this point in the history
  • Loading branch information
Ferossgp committed Apr 28, 2024
1 parent 454f7e5 commit bc56b28
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 20 deletions.
2 changes: 1 addition & 1 deletion apps/docs/src/content/docs/guides/tg-bot.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,6 @@ Your Telegram bot is now set up and will monitor blockchain transactions and sen

In this guide, you've learned how to create a Telegram bot that monitors blockchain transactions and sends human-readable alerts. By using the Loop Decoder library, you can easily set up a bot to track specific contract addresses and chains without needing in-depth knowledge of EVM transaction decoding.

Let us know on Twitter ([@3loop_io](twitter.com/3loop_io)) if you encounter any problems or have any questions, we'd love to help you!
Let us know on X/Twitter ([@3loop_io](https://x.com/3loop_io)) if you encounter any problems or have any questions, we'd love to help you!

Happy coding!
18 changes: 0 additions & 18 deletions apps/docs/src/content/docs/reference/abi-loaders.md

This file was deleted.

33 changes: 33 additions & 0 deletions apps/docs/src/content/docs/reference/data-loaders.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: Data Loaders
description: Data Loaders used to fetch ABI and Contract Metadata required for decoding transactions
sidebar:
order: 2
---

Data Loaders are mechanisms designed to retrieve the required ABI and Contract Metadata for transaction decoding. Internally, they automatically batch and cache requests when processing logs and traces in parallel. Users are encouraged to create a persistent store to cache data, thus avoiding unnecessary API requests. Additionally, the custom store should include all proprietary contracts.

The `AbiStore` and `ContractMetadataStore` accept strategies that resolve data from third-party APIs when the data is missing from the store. Upon successful resolution, the data is cached in the store to prevent unnecessary API requests in the future.

The Loop Decoder implements various optimizations to reduce the number of API requests made to third-party APIs. For instance, if the ABI of a contract is resolved from Etherscan, the ABI is then cached in the store. Subsequently, if the ABI is requested again, the store will return the cached ABI instead of making another API request.

## Contract metadata

Contract metadata is a collection of information about a contract, such as the contract's name, symbol, and decimals.

Loop Decoder provides some strategies out of the box:

- `ERC20RPCStrategyResolver` - resolves the contract metadata of an ERC20 token from the RPC
- `NFTRPCStrategyResolver` - resolves the contract metadata of an NFT token (ERC721, ERC1155) from the RPC

## ABI Strategies

ABI strategies will receive the contract address, and event or function signature as input and would return the ABI as a stringified JSON. Loop Decoder provides some strategies out of the box:

- `EtherscanStrategyResolver` - resolves the ABI from Etherscan
- `SourcifyStrategyResolver` - resolves the ABI from Sourcify
- `FourByteStrategyResolver` - resolves the ABI from 4byte.directory
- `OpenchainStrategyResolver` - resolves the ABI from Openchain
- `BlockscoutStrategyResolver` - resolves the ABI from Blockscout

You can create your strategy by implementing the `GetContractABIStrategy` Effect RequestResolver.
90 changes: 90 additions & 0 deletions apps/docs/src/content/docs/reference/data-store.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
title: Data Store
description: Data Storages are simple APIs that implement a key-value store for persistent cache.
sidebar:
order: 1
---

Loop decoder relays on two data stores for caching the ABI and contract metadata. The user of the library is free to choose which data layer to use depending on their environment and requirements.

If your application is designed to decode a fixed subset of contracts, you can provide a hardcoded map of ABIs and contract metadata. For more flexible applications, you can use any persistent database. When running in a browser, you can implement a REST API to fetch the ABIs and contract metadata from a server.

A store also requires a set of strategies that we cover separately in the [Data Loaders](../data-loaders) section.

## AbiStore

ABI Store Interface requires 2 methods `set` and `get` to store and retrieve the ABI of a contract. Optionally you can provide a batch get method `getMany` for further optimization. Because our API supports ABI fragments, the get method will receive both the contract address and the fragment signature.

```typescript
interface GetAbiParams {
chainID: number
address: string
event?: string | undefined // event signature
signature?: string | undefined // function signature
}
```

The `set` method will receive a map of ABIs indexed by the contract address, event signature, and function signature. You can choose to store the data in the best format that fits your database.

```typescript
type Address = string
type Signature = string
type ABI = string // JSON stringified ABI

interface ContractABI {
address?: Record<Address, ABI>
func?: Record<Signature, ABI>
event?: Record<Signature, ABI>
}
```

The full interface looks as follows:

```typescript
interface AbiStore {
readonly strategies: Record<ChainOrDefault, readonly RequestResolver.RequestResolver<GetContractABIStrategy>[]>
readonly set: (value: ContractABI) => Effect.Effect<void, never>
readonly get: (arg: GetAbiParams) => Effect.Effect<string | null, never>
readonly getMany?: (arg: Array<GetAbiParams>) => Effect.Effect<Array<string | null>, never>
}
```

## ContractMetadataStore

Similar to the ABI Store, the Contract Metadata Store Interface requires 2 methods `set`, `get`, and optionally `getMany` to store and retrieve the contract metadata.

The `get` method will receive the contract address and the chain ID as input.

```typescript
interface ContractMetaParams {
address: string
chainID: number
}
```

And, the `set` method will be called with 2 pramaters, the key in the same format as the `get` method, and the metadata value.

Contract metadata is a map of the following interface:

```typescript
export interface ContractData {
address: string
contractName: string
contractAddress: string
tokenSymbol: string
decimals?: number
type: ContractType
chainID: number
}
```

The full interface looks as follows:

```typescript
interface ContractMetaStore {
readonly strategies: Record<ChainOrDefault, readonly RequestResolver.RequestResolver<GetContractMetaStrategy>[]>
readonly set: (arg: ContractMetaParams, value: ContractData) => Effect.Effect<void, never>
readonly get: (arg: ContractMetaParams) => Effect.Effect<ContractData | null, never>
readonly getMany?: (arg: Array<ContractMetaParams>) => Effect.Effect<Array<ContractData | null>, never>
}
```
2 changes: 1 addition & 1 deletion packages/transaction-decoder/src/abi-loader.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Context, Effect, Either, RequestResolver, Request, Array, Console, pipe } from 'effect'
import { Context, Effect, Either, RequestResolver, Request, Array, pipe } from 'effect'
import { ContractABI, GetContractABIStrategy } from './abi-strategy/request-model.js'

export interface GetAbiParams {
Expand Down

0 comments on commit bc56b28

Please sign in to comment.