Skip to content

Commit 610f7e2

Browse files
authored
Do not cache meta strategies when request fails (#160)
* Do not cache meta strategies when request fails * Batch meta loader in log-decode
1 parent 21d534e commit 610f7e2

File tree

6 files changed

+47
-30
lines changed

6 files changed

+47
-30
lines changed

.changeset/two-shoes-brush.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@3loop/transaction-decoder': patch
3+
---
4+
5+
Do not cache failed request to meta strategies

packages/transaction-decoder/src/contract-meta-loader.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ const getMany = (requests: Array<ContractMetaLoader>) =>
9090
const setValue = ({ chainID, address }: ContractMetaLoader, result: ContractData | null) =>
9191
Effect.gen(function* () {
9292
const { set } = yield* ContractMetaStore
93+
if (result == null) return
94+
// NOTE: Now when RPC fails if we store not-found it causes issues and not retries, for now we will just always retry
9395
yield* set(
9496
{ chainID, address },
9597
result == null ? { status: 'not-found', result: null } : { status: 'success', result },

packages/transaction-decoder/src/decoding/log-decode.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const decodedLog = (transaction: GetTransactionReturnType, logItem: Log) =>
4545
],
4646
{
4747
concurrency: 'unbounded',
48+
batching: true,
4849
},
4950
)
5051

packages/transaction-decoder/src/meta-strategy/erc20-rpc-strategy.ts

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,54 @@ import { ContractData, ContractType } from '../types.js'
22
import * as RequestModel from './request-model.js'
33
import { Effect, RequestResolver } from 'effect'
44
import { PublicClient } from '../public-client.js'
5-
import { erc20Abi, getContract } from 'viem'
5+
import { erc20Abi } from 'viem'
6+
import { MULTICALL3_ADDRESS } from '../decoding/constants.js'
67

78
export const ERC20RPCStrategyResolver = (publicClientLive: PublicClient) =>
89
RequestResolver.fromEffect(({ chainID, address }: RequestModel.GetContractMetaStrategy) =>
910
Effect.gen(function* () {
1011
const service = yield* PublicClient
1112
const { client } = yield* service.getPublicClient(chainID)
1213

13-
const inst = getContract({
14-
abi: erc20Abi,
15-
address,
16-
client,
17-
})
18-
1914
const fail = new RequestModel.ResolveStrategyMetaError('ERC20RPCStrategy', address, chainID)
2015

21-
const decimals = yield* Effect.tryPromise({
22-
try: () => inst.read.decimals(),
23-
catch: () => fail,
16+
const [symbolResponse, decimalsResponse, nameResponse] = yield* Effect.tryPromise({
17+
try: () =>
18+
client.multicall({
19+
multicallAddress: MULTICALL3_ADDRESS,
20+
contracts: [
21+
{
22+
abi: erc20Abi,
23+
address,
24+
functionName: 'symbol',
25+
},
26+
{
27+
abi: erc20Abi,
28+
address,
29+
functionName: 'decimals',
30+
},
31+
{
32+
abi: erc20Abi,
33+
address,
34+
functionName: 'name',
35+
},
36+
],
37+
}),
38+
catch: () => {
39+
return fail
40+
},
2441
})
2542

26-
if (decimals == null) {
43+
if (decimalsResponse.status !== 'success') {
2744
return yield* Effect.fail(fail)
2845
}
2946

30-
//NOTE: keep for now to support blur pools
31-
const [symbol, name] = yield* Effect.all(
32-
[
33-
Effect.tryPromise({ try: () => inst.read.symbol().catch(() => ''), catch: () => fail }),
34-
Effect.tryPromise({ try: () => inst.read.name().catch(() => ''), catch: () => fail }),
35-
],
36-
{
37-
concurrency: 'inherit',
38-
batching: 'inherit',
39-
},
40-
)
41-
4247
const meta: ContractData = {
4348
address,
4449
contractAddress: address,
45-
contractName: name,
46-
tokenSymbol: symbol,
47-
decimals: Number(decimals),
50+
contractName: nameResponse.result,
51+
tokenSymbol: symbolResponse.result,
52+
decimals: Number(decimalsResponse.result),
4853
type: 'ERC20' as ContractType,
4954
chainID,
5055
}

packages/transaction-decoder/src/sql/abi-store.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const make = (strategies: AbiStore['strategies']) =>
88
Effect.gen(function* () {
99
const sql = yield* SqlClient.SqlClient
1010

11-
const table = sql('loop_decoder_contract_abi__')
11+
const table = sql('_loop_decoder_contract_abi_')
1212

1313
// TODO; add timestamp to the table
1414
yield* sql`
@@ -19,7 +19,9 @@ export const make = (strategies: AbiStore['strategies']) =>
1919
signature TEXT,
2020
chain INTEGER,
2121
abi TEXT,
22-
status TEXT NOT NULL
22+
status TEXT NOT NULL,
23+
timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
24+
PRIMARY KEY (address, chain)
2325
)
2426
`.pipe(
2527
Effect.tapError(Effect.logError),

packages/transaction-decoder/src/sql/contract-meta-store.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const make = () =>
1616
const sql = yield* SqlClient.SqlClient
1717
const publicClient = yield* PublicClient
1818

19-
const table = sql('loop_decoder_contract_meta__')
19+
const table = sql('_loop_decoder_contract_meta_')
2020

2121
// TODO; add timestamp to the table
2222
yield* sql`
@@ -27,7 +27,9 @@ export const make = () =>
2727
token_symbol TEXT,
2828
decimals INTEGER,
2929
type TEXT,
30-
status TEXT NOT NULL
30+
status TEXT NOT NULL,
31+
timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
32+
PRIMARY KEY (address, chain)
3133
)
3234
`.pipe(
3335
Effect.tapError(Effect.logError),

0 commit comments

Comments
 (0)