Skip to content

Commit cdb8027

Browse files
committed
Implement getMany for meta and abi sql store
1 parent 7e88411 commit cdb8027

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

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

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,93 @@ export const make = (strategies: AbiStore.AbiStore['strategies']) =>
139139
result: null,
140140
}
141141
}),
142+
143+
getMany: (keys) =>
144+
Effect.gen(function* () {
145+
if (keys.length === 0) {
146+
return []
147+
}
148+
149+
// Build a batch query for all the keys
150+
const conditions = keys.map(({ address, signature, event, chainID }) => {
151+
const addressQuery = sql.and([
152+
sql`address = ${address.toLowerCase()}`,
153+
sql`chain = ${chainID}`,
154+
sql`type = 'address'`,
155+
])
156+
157+
const signatureQuery = signature
158+
? sql.and([sql`signature = ${signature}`, sql`type = 'func'`])
159+
: undefined
160+
const eventQuery = event ? sql.and([sql`event = ${event}`, sql`type = 'event'`]) : undefined
161+
162+
return signature == null && event == null
163+
? addressQuery
164+
: sql.or([addressQuery, signatureQuery, eventQuery].filter(Boolean))
165+
})
166+
167+
const batchQuery = sql.or(conditions)
168+
169+
const allItems = yield* sql`SELECT * FROM ${table} WHERE ${batchQuery}`.pipe(
170+
Effect.tapError(Effect.logError),
171+
Effect.catchAll(() => Effect.succeed([])),
172+
)
173+
174+
// Process results for each key
175+
return keys.map(({ address, signature, event, chainID }) => {
176+
const keyItems = allItems.filter((item) => {
177+
// Match by address and chain
178+
if (
179+
typeof item.address === 'string' &&
180+
item.address.toLowerCase() === address.toLowerCase() &&
181+
item.chain === chainID
182+
) {
183+
return true
184+
}
185+
// Match by signature
186+
if (signature && item.signature === signature && item.type === 'func') {
187+
return true
188+
}
189+
// Match by event
190+
if (event && item.event === event && item.type === 'event') {
191+
return true
192+
}
193+
return false
194+
})
195+
196+
const successItems = keyItems.filter((item) => item.status === 'success')
197+
198+
const item =
199+
successItems.find((item) => {
200+
// Prioritize address over fragments
201+
return item.type === 'address'
202+
}) ?? successItems[0]
203+
204+
if (item != null) {
205+
return {
206+
status: 'success',
207+
result: {
208+
type: item.type,
209+
event: item.event,
210+
signature: item.signature,
211+
address,
212+
chainID,
213+
abi: item.abi,
214+
},
215+
} as AbiStore.ContractAbiResult
216+
} else if (keyItems[0] != null && keyItems[0].status === 'not-found') {
217+
return {
218+
status: 'not-found',
219+
result: null,
220+
}
221+
}
222+
223+
return {
224+
status: 'empty',
225+
result: null,
226+
}
227+
})
228+
}),
142229
})
143230
}),
144231
)

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

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,65 @@ export const make = (strategies: ContractMetaStore.ContractMetaStore['strategies
107107
result: null,
108108
}
109109
}),
110+
getMany: (params) =>
111+
Effect.gen(function* () {
112+
if (params.length === 0) {
113+
return []
114+
}
115+
116+
// Build WHERE conditions for batch select using OR clauses
117+
const whereConditions = params.map(({ address, chainID }) =>
118+
sql.and([sql`address = ${address.toLowerCase()}`, sql`chain = ${chainID}`]),
119+
)
120+
121+
const items = yield* sql`
122+
SELECT * FROM ${table}
123+
WHERE ${sql.or(whereConditions)}
124+
`.pipe(
125+
Effect.tapError(Effect.logError),
126+
Effect.catchAll(() => Effect.succeed([])),
127+
)
128+
129+
// Create a map for O(1) lookup of results
130+
const itemsMap = new Map<string, any>()
131+
items.forEach((item) => {
132+
const address =
133+
typeof item.address === 'string' ? item.address.toLowerCase() : String(item.address).toLowerCase()
134+
const key = `${address}-${item.chain}`
135+
itemsMap.set(key, item)
136+
})
137+
138+
// Build results array in the same order as input params
139+
return params.map(({ address, chainID }) => {
140+
const key = `${address.toLowerCase()}-${chainID}`
141+
const item = itemsMap.get(key)
142+
143+
if (item && item.status === 'success') {
144+
return {
145+
status: 'success',
146+
result: {
147+
contractAddress: address,
148+
contractName: item.contract_name,
149+
tokenSymbol: item.token_symbol,
150+
decimals: item.decimals,
151+
type: item.type,
152+
address,
153+
chainID,
154+
} as ContractData,
155+
}
156+
} else if (item && item.status === 'not-found') {
157+
return {
158+
status: 'not-found',
159+
result: null,
160+
}
161+
}
162+
163+
return {
164+
status: 'empty',
165+
result: null,
166+
}
167+
}) as ContractMetaStore.ContractMetaResult[]
168+
}),
110169
})
111170
}),
112171
)

0 commit comments

Comments
 (0)