Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions core-api/src/routes/event-version/eventVersionPayloads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export interface GetEventVersionDataAfterPayload {
cursors: StringKeyMap
}

export interface SearchEventVersionPayload {
name: string
}

export function parseResolveEventVersionsPayload(
data: StringKeyMap
): ValidatedPayload<ResolveEventVersionsPayload> {
Expand Down Expand Up @@ -78,4 +82,13 @@ export function parseGetEventVersionDataAfterPayload(
cursors,
},
}
}

export function parseSearchEventVersionPayload(data: StringKeyMap): ValidatedPayload<SearchEventVersionPayload> {
const name = data?.name || null

return {
isValid: true,
payload: { name, },
}
}
21 changes: 20 additions & 1 deletion core-api/src/routes/event-version/eventVersionRoutes.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { app } from '../express'
import paths from '../../utils/paths'
import { parseResolveEventVersionsPayload, parseResolveEventVersionCursorsPayload, parseGetEventVersionDataAfterPayload } from './eventVersionPayloads'
import { parseResolveEventVersionsPayload, parseResolveEventVersionCursorsPayload, parseGetEventVersionDataAfterPayload, parseSearchEventVersionPayload } from './eventVersionPayloads'
import { codes, errors, authorizeRequestWithProjectApiKey } from '../../utils/requests'
import { resolveEventVersionNames, resolveEventVersionCursors, getPublishedEventsAfterEventCursors } from '../../../../shared'
import { searchEventVersions } from '../../services/searchEventVersions'

/**
* Resolve full event version names for a set of given event "inputs".
Expand Down Expand Up @@ -62,4 +63,22 @@ app.post(paths.RESOLVE_EVENT_VERSION_CURSORS, async (req, res) => {
}

return res.status(codes.SUCCESS).json({ events })
})

/**
* Search event versions.
*/
app.get(paths.EVENT_VERSIONS_SEARCH, async (req, res) => {
// Parse & validate payload.
const { payload, isValid, error } = parseSearchEventVersionPayload(req.query)
if (!isValid) {
return res.status(codes.BAD_REQUEST).json({ error: error || errors.INVALID_PAYLOAD })
}
const { name} = payload

// Find event versions by search terms.
const { data, error: searchError } = await searchEventVersions(name)
return searchError
? res.status(codes.INTERNAL_SERVER_ERROR).json({ error: searchError || errors.UNKNOWN_ERROR })
: res.status(codes.SUCCESS).json(data)
})
90 changes: 90 additions & 0 deletions core-api/src/services/searchEventVersions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { AbiItemType, CoreDB, camelizeKeys, getContractGroupAbi, logger } from '../../../shared'
import { StringKeyMap } from '../types'

export async function searchEventVersions(name: string): Promise<StringKeyMap> {
let results
let uniqueContractGroupsSet = new Set()
let contractGroupAbisMap = {}

// Query database.
try {
results = await CoreDB.query(
`SELECT DISTINCT ON (search_id)
name,
version,
search_id,
contract_group
FROM
(SELECT
nsp,
name,
version,
CASE
WHEN nsp LIKE '%.%'
THEN CONCAT(ARRAY_TO_STRING((STRING_TO_ARRAY(nsp, '.'))[3:4], '.'), '.', name, '@', version)
ELSE CONCAT(nsp, '.', name, '@', version)
END as search_id,
CASE
WHEN nsp LIKE '%.%'
THEN ARRAY_TO_STRING((STRING_TO_ARRAY(nsp, '.'))[3:4], '.')
ELSE nsp
END as contract_group
FROM event_versions
WHERE
CASE
WHEN $1::text IS NOT NULL
THEN (nsp || '.' || name) ILIKE CONCAT('%.contracts.', $1, '%')
ELSE TRUE
END) AS uev
LIMIT 5;`, [name]
)
} catch (err) {
logger.error(`Error searching event versions: ${err}`)
return { error: err?.message || err }
}

// Camelize result keys.
results = camelizeKeys(results)

// Store unique contract groups.
results.forEach(result => uniqueContractGroupsSet.add(result.contractGroup))
const uniqueContractGroups = Array.from(uniqueContractGroupsSet) as string[]

// Retrieve and store redis abi data for each contract group.
const abis = await Promise.all(
uniqueContractGroups.map((group: string) => getContractGroupAbi(group))
)

for (let i = 0; i < uniqueContractGroups.length; i++) {
const group = uniqueContractGroups[i]
const abi = abis[i]
contractGroupAbisMap[group] = abi
}

// Format results for CLI.
function formatForCLI(result) {
let finalResult = {
searchId: result.searchId,
addressProperties: []
}

const abi = contractGroupAbisMap[result.contractGroup]
if (!abi?.length) return finalResult

const event = abi.find(item => (
item.type === AbiItemType.Event &&
item.name === result.name &&
item.signature === result.version
))
if (!event) return finalResult

const addressProperties = event.inputs
.filter(input => input.type === 'address')
.map(input => input.name)
if (!addressProperties.length) return finalResult

return {...finalResult, addressProperties}
}

return { data: results.map(formatForCLI) }
}
1 change: 1 addition & 0 deletions core-api/src/utils/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const paths = {
RESOLVE_EVENT_VERSIONS: prefix.EVENT_VERSION + 's' + '/resolve',
RESOLVE_EVENT_VERSION_CURSORS: prefix.EVENT_VERSION + 's' + '/resolve/cursors',
GET_EVENT_VERSION_DATA_AFTER: prefix.EVENT_VERSION + 's' + '/data/after',
EVENT_VERSIONS_SEARCH: prefix.EVENT_VERSION + 's' + '/search',

// Call Version paths.
RESOLVE_CALL_VERSIONS: prefix.CALL_VERSION + 's' + '/resolve',
Expand Down