-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcontract-meta-store.ts
More file actions
112 lines (103 loc) · 3.6 KB
/
contract-meta-store.ts
File metadata and controls
112 lines (103 loc) · 3.6 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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { SqlClient } from '@effect/sql'
import { Effect, Layer } from 'effect'
import * as ContractMetaStore from '../contract-meta-store.js'
import { ContractData } from '../types.js'
export const make = (strategies: ContractMetaStore.ContractMetaStore['strategies']) =>
Layer.effect(
ContractMetaStore.ContractMetaStore,
Effect.gen(function* () {
const sql = yield* SqlClient.SqlClient
const table = sql('_loop_decoder_contract_meta_')
yield* sql`
CREATE TABLE IF NOT EXISTS ${table} (
address TEXT NOT NULL,
chain INTEGER NOT NULL,
contract_name TEXT,
token_symbol TEXT,
decimals INTEGER,
type TEXT,
status TEXT NOT NULL,
timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (address, chain)
)
`.pipe(
Effect.tapError(Effect.logError),
Effect.catchAll(() => Effect.dieMessage('Failed to create contractMeta table')),
)
return yield* ContractMetaStore.make({
strategies,
set: (key, value) =>
Effect.gen(function* () {
if (value.status === 'success') {
const name = value.result.contractName ?? ''
const symbol = value.result.tokenSymbol ?? ''
const decimals = value.result.decimals ?? undefined
const clear = Object.fromEntries(
Object.entries({
address: key.address.toLowerCase(),
chain: key.chainID,
contract_name: name,
token_symbol: symbol,
decimals,
type: value.result.type,
status: 'success',
}).filter(([_, v]) => v !== undefined),
)
yield* sql`
INSERT INTO ${table}
${sql.insert([clear])}
`
} else {
yield* sql`
INSERT INTO ${table}
${sql.insert([
{
address: key.address.toLowerCase(),
chain: key.chainID,
status: 'not-found',
},
])}
`
}
}).pipe(
Effect.tapError(Effect.logError),
Effect.catchAll(() => Effect.succeed(null)),
),
get: ({ address, chainID }) =>
Effect.gen(function* () {
const items = yield* sql`
SELECT * FROM ${table}
WHERE ${sql.and([sql`address = ${address.toLowerCase()}`, sql`chain = ${chainID}`])}
`.pipe(
Effect.tapError(Effect.logError),
Effect.catchAll(() => Effect.succeed([])),
)
const successItems = items.filter((item) => item.status === 'success')
const item = successItems[0]
if (item != null && item.status === 'success') {
return {
status: 'success',
result: {
contractAddress: address,
contractName: item.contract_name,
tokenSymbol: item.token_symbol,
decimals: item.decimals,
type: item.type,
address,
chainID,
} as ContractData,
}
} else if (items[0] != null && items[0].status === 'not-found') {
return {
status: 'not-found',
result: null,
}
}
return {
status: 'empty',
result: null,
}
}),
})
}),
)