-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathabi-store.ts
More file actions
84 lines (70 loc) · 2.75 KB
/
abi-store.ts
File metadata and controls
84 lines (70 loc) · 2.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { Context, Effect, RateLimiter, Function, Layer, MetricLabel } from 'effect'
import { ContractABI, ContractAbiResolverStrategy, GetContractABIStrategyParams } from './abi-strategy/request-model.js'
import * as CircuitBreaker from './circuit-breaker/circuit-breaker.js'
import * as RequestPool from './circuit-breaker/request-pool.js'
export interface AbiParams {
chainID: number
address: string
event?: string | undefined
signature?: string | undefined
}
export interface ContractAbiSuccess {
status: 'success'
result: ContractABI
}
export interface ContractAbiNotFound {
status: 'not-found'
result: null
}
export interface ContractAbiEmpty {
status: 'empty'
result: null
}
export type ContractAbiResult = ContractAbiSuccess | ContractAbiNotFound | ContractAbiEmpty
type ChainOrDefault = number | 'default'
export interface AbiStore {
readonly strategies: Record<ChainOrDefault, readonly ContractAbiResolverStrategy[]>
readonly set: (key: AbiParams, value: ContractAbiResult) => Effect.Effect<void, never>
readonly get: (arg: AbiParams) => Effect.Effect<ContractAbiResult, never>
readonly getMany?: (arg: Array<AbiParams>) => Effect.Effect<Array<ContractAbiResult>, never>
readonly circuitBreaker: CircuitBreaker.CircuitBreaker<unknown>
readonly requestPool: RequestPool.RequestPool
}
export const AbiStore = Context.GenericTag<AbiStore>('@3loop-decoder/AbiStore')
export const make = ({
strategies: strategiesWithoutRateLimit,
...rest
}: Omit<AbiStore, 'circuitBreaker' | 'requestPool'>) =>
Effect.gen(function* () {
const strategies = yield* Effect.reduce(
Object.entries(strategiesWithoutRateLimit),
{} as Record<ChainOrDefault, ContractAbiResolverStrategy[]>,
(acc, [chainID, specific]) =>
Effect.gen(function* () {
const all = yield* Effect.forEach(specific, (strategy) =>
Effect.gen(function* () {
const rateLimit = strategy.rateLimit ? yield* RateLimiter.make(strategy.rateLimit) : Function.identity
return yield* Effect.succeed({
...strategy,
resolver: (params: GetContractABIStrategyParams) => strategy.resolver(params).pipe(rateLimit),
})
}),
)
return {
...acc,
[chainID]: all,
}
}),
)
const circuitBreaker = yield* CircuitBreaker.make({
metricLabels: [MetricLabel.make('service', 'abi-loader')],
})
const requestPool = yield* RequestPool.make({ metricLabels: [MetricLabel.make('service', 'abi-loader')] })
return {
strategies,
circuitBreaker,
requestPool,
...rest,
}
})
export const layer = (args: Omit<AbiStore, 'circuitBreaker' | 'requestPool'>) => Layer.scoped(AbiStore, make(args))