Skip to content

Commit fed374f

Browse files
committed
Use TaggedRequest for request to allow for equality check in cache
1 parent aaf587d commit fed374f

File tree

5 files changed

+86
-35
lines changed

5 files changed

+86
-35
lines changed
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+
Use TaggedRequest for request to allow for equality check for in-memory caching of requests

packages/transaction-decoder/src/abi-loader.ts

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1-
import { Context, Effect, Either, RequestResolver, Request, Array, pipe, Data } from 'effect'
1+
import {
2+
Context,
3+
Effect,
4+
Either,
5+
RequestResolver,
6+
Request,
7+
Array,
8+
pipe,
9+
Data,
10+
PrimaryKey,
11+
Schema,
12+
SchemaAST,
13+
} from 'effect'
214
import { ContractABI, ContractAbiResolverStrategy, GetContractABIStrategy } from './abi-strategy/request-model.js'
315
import { Abi } from 'viem'
416

@@ -63,12 +75,22 @@ export class EmptyCalldataError extends Data.TaggedError('DecodeError')<
6375
}
6476
}
6577

66-
export interface AbiLoader extends Request.Request<Abi, MissingABIError>, LoadParameters {
67-
_tag: 'AbiLoader'
78+
class SchemaAbi extends Schema.make<Abi>(SchemaAST.objectKeyword) {}
79+
class AbiLoader extends Schema.TaggedRequest<AbiLoader>()('AbiLoader', {
80+
failure: Schema.instanceOf(MissingABIError),
81+
success: SchemaAbi, // Abi
82+
payload: {
83+
chainID: Schema.Number,
84+
address: Schema.String,
85+
event: Schema.optional(Schema.String),
86+
signature: Schema.optional(Schema.String),
87+
},
88+
}) {
89+
[PrimaryKey.symbol]() {
90+
return `abi::${this.chainID}:${this.address}:${this.event}:${this.signature}`
91+
}
6892
}
6993

70-
const AbiLoader = Request.tagged<AbiLoader>('AbiLoader')
71-
7294
function makeRequestKey(key: AbiLoader) {
7395
return `abi::${key.chainID}:${key.address}:${key.event}:${key.signature}`
7496
}
@@ -191,7 +213,7 @@ const AbiLoaderRequestResolver: Effect.Effect<
191213

192214
// NOTE: Firstly we batch strategies by address because in a transaction most of events and traces are from the same abi
193215
const response = yield* Effect.forEach(remaining, (req) => {
194-
const strategyRequest = GetContractABIStrategy({
216+
const strategyRequest = new GetContractABIStrategy({
195217
address: req.address,
196218
chainID: req.chainID,
197219
})
@@ -216,7 +238,7 @@ const AbiLoaderRequestResolver: Effect.Effect<
216238

217239
// NOTE: Secondly we request strategies to fetch fragments
218240
const fragmentStrategyResults = yield* Effect.forEach(notFound, ({ chainID, address, event, signature }) => {
219-
const strategyRequest = GetContractABIStrategy({
241+
const strategyRequest = new GetContractABIStrategy({
220242
address,
221243
chainID,
222244
event,
@@ -271,7 +293,7 @@ export const getAndCacheAbi = (params: AbiParams) =>
271293
return yield* Effect.fail(new EmptyCalldataError(params))
272294
}
273295

274-
return yield* Effect.request(AbiLoader(params), AbiLoaderRequestResolver)
296+
return yield* Effect.request(new AbiLoader(params), AbiLoaderRequestResolver)
275297
}).pipe(
276298
Effect.withSpan('AbiLoader.GetAndCacheAbi', {
277299
attributes: {

packages/transaction-decoder/src/abi-strategy/request-model.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Request, RequestResolver } from 'effect'
1+
import { PrimaryKey, RequestResolver, Schema, SchemaAST } from 'effect'
22

33
export interface FetchABIParams {
44
readonly chainID: number
@@ -41,16 +41,23 @@ interface AddressABI {
4141

4242
export type ContractABI = FunctionFragmentABI | EventFragmentABI | AddressABI
4343

44-
// NOTE: We might want to return a list of ABIs, this might be helpful when fetching for signature
45-
export interface GetContractABIStrategy
46-
extends Request.Request<ContractABI[], ResolveStrategyABIError>,
47-
FetchABIParams {
48-
readonly _tag: 'GetContractABIStrategy'
49-
}
50-
51-
export const GetContractABIStrategy = Request.tagged<GetContractABIStrategy>('GetContractABIStrategy')
52-
5344
export interface ContractAbiResolverStrategy {
5445
type: 'address' | 'fragment'
5546
resolver: RequestResolver.RequestResolver<GetContractABIStrategy, never>
5647
}
48+
49+
class SchemaContractAbi extends Schema.make<ContractABI>(SchemaAST.objectKeyword) {}
50+
export class GetContractABIStrategy extends Schema.TaggedRequest<GetContractABIStrategy>()('GetContractABIStrategy', {
51+
failure: Schema.instanceOf(ResolveStrategyABIError),
52+
success: Schema.Array(SchemaContractAbi),
53+
payload: {
54+
chainID: Schema.Number,
55+
address: Schema.String,
56+
event: Schema.optional(Schema.String),
57+
signature: Schema.optional(Schema.String),
58+
},
59+
}) {
60+
[PrimaryKey.symbol]() {
61+
return `abi-strategy::${this.chainID}:${this.address}:${this.event}:${this.signature}`
62+
}
63+
}

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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Context, Effect, RequestResolver, Request, Array, Either, pipe } from 'effect'
1+
import { Context, Effect, RequestResolver, Request, Array, Either, pipe, Schema, PrimaryKey, SchemaAST } from 'effect'
22
import { ContractData } from './types.js'
33
import { GetContractMetaStrategy } from './meta-strategy/request-model.js'
44
import { Address } from 'viem'
@@ -50,14 +50,22 @@ export interface ContractMetaStore<Key = ContractMetaParams, Value = ContractMet
5050

5151
export const ContractMetaStore = Context.GenericTag<ContractMetaStore>('@3loop-decoder/ContractMetaStore')
5252

53-
export interface ContractMetaLoader extends Request.Request<ContractData | null, never> {
54-
_tag: 'ContractMetaLoader'
55-
address: Address
56-
chainID: number
53+
class SchemaContractData extends Schema.make<ContractData>(SchemaAST.objectKeyword) {}
54+
class SchemaAddress extends Schema.make<Address>(SchemaAST.stringKeyword) {}
55+
56+
class ContractMetaLoader extends Schema.TaggedRequest<ContractMetaLoader>()('ContractMetaLoader', {
57+
failure: Schema.Never,
58+
success: Schema.NullOr(SchemaContractData),
59+
payload: {
60+
address: SchemaAddress,
61+
chainID: Schema.Number,
62+
},
63+
}) {
64+
[PrimaryKey.symbol]() {
65+
return `contract-meta::${this.chainID}:${this.address}`
66+
}
5767
}
5868

59-
const ContractMetaLoader = Request.tagged<ContractMetaLoader>('ContractMetaLoader')
60-
6169
function makeKey(key: ContractMetaLoader) {
6270
return `contract-meta::${key.chainID}:${key.address}`
6371
}
@@ -148,7 +156,7 @@ const ContractMetaLoaderRequestResolver = RequestResolver.makeBatched((requests:
148156

149157
// Fetch ContractMeta from the strategies
150158
const strategyResults = yield* Effect.forEach(remaining, ({ chainID, address }) => {
151-
const strategyRequest = GetContractMetaStrategy({
159+
const strategyRequest = new GetContractMetaStrategy({
152160
address,
153161
chainID,
154162
})
@@ -186,7 +194,7 @@ export const getAndCacheContractMeta = ({
186194
readonly address: Address
187195
}) => {
188196
return Effect.withSpan(
189-
Effect.request(ContractMetaLoader({ chainID, address }), ContractMetaLoaderRequestResolver),
197+
Effect.request(new ContractMetaLoader({ chainID, address }), ContractMetaLoaderRequestResolver),
190198
'GetAndCacheContractMeta',
191199
{ attributes: { chainID, address } },
192200
)

packages/transaction-decoder/src/meta-strategy/request-model.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { UnknownNetwork } from '../public-client.js'
22
import { ContractData } from '../types.js'
3-
import { Request } from 'effect'
3+
import { PrimaryKey, Schema, SchemaAST } from 'effect'
44
import { Address } from 'viem'
55

66
export interface FetchMetaParams {
@@ -17,11 +17,20 @@ export class ResolveStrategyMetaError {
1717
) {}
1818
}
1919

20-
// TODO: Remove UnknownNetwork
21-
export interface GetContractMetaStrategy
22-
extends Request.Request<ContractData, ResolveStrategyMetaError | UnknownNetwork>,
23-
FetchMetaParams {
24-
readonly _tag: 'GetContractMetaStrategy'
20+
class SchemaAddress extends Schema.make<Address>(SchemaAST.stringKeyword) {}
21+
class SchemaContractData extends Schema.make<ContractData>(SchemaAST.objectKeyword) {}
22+
export class GetContractMetaStrategy extends Schema.TaggedRequest<GetContractMetaStrategy>()(
23+
'GetContractMetaStrategy',
24+
{
25+
failure: Schema.Union(Schema.instanceOf(ResolveStrategyMetaError), Schema.instanceOf(UnknownNetwork)),
26+
success: SchemaContractData,
27+
payload: {
28+
chainID: Schema.Number,
29+
address: SchemaAddress,
30+
},
31+
},
32+
) {
33+
[PrimaryKey.symbol]() {
34+
return `contract-meta-strategy::${this.chainID}:${this.address}`
35+
}
2536
}
26-
27-
export const GetContractMetaStrategy = Request.tagged<GetContractMetaStrategy>('GetContractMetaStrategy')

0 commit comments

Comments
 (0)