Skip to content

Commit

Permalink
Refactoring rfq-indexer API and adding swagger docs [SLT-228] (#3167)
Browse files Browse the repository at this point in the history
* refactoring and adding swagger

* remove testing scripts

* fix typos and consistency with 404 errors
  • Loading branch information
Defi-Moses authored Sep 22, 2024
1 parent 3b507bd commit f4101f2
Show file tree
Hide file tree
Showing 27 changed files with 1,065 additions and 109 deletions.
26 changes: 19 additions & 7 deletions packages/rfq-indexer/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
"main": "index.js",
"scripts": {
"check-env": "dotenv -e .env.local -- printenv | grep DATABASE_URL",
"dev:local": "dotenv -e .env.local -- tsx watch src/index.ts",
"dev:prod": "dotenv -e .env.production -- tsx watch src/index.ts",
"start": "tsx src/index.ts",
"start:local": "dotenv -e .env -- tsx src/index.ts",
"dev": "dotenv -e .env -- tsx watch src/index.ts",
"dev:local": "dotenv -e .env.local -- tsx watch src/app.ts",
"dev:prod": "dotenv -e .env.production -- tsx watch src/app.ts",
"start": "tsx src/app.ts",
"start:local": "dotenv -e .env -- tsx src/app.ts",
"dev": "dotenv -e .env -- tsx watch src/app.ts",
"lint:check": " ",
"ci:lint": " ",
"build:go": " ",
"build": " ",
"build:slither": " ",
"test:coverage": "echo 'No tests defined.'"
"test": "",
"test:coverage": "echo no tests defined"
},
"keywords": [],
"author": "",
Expand All @@ -29,10 +30,12 @@
"@types/node": "^22.5.4",
"dotenv-cli": "^7.4.2",
"express": "^4.21.0",
"express-validator": "^7.2.0",
"graphql": "^16.9.0",
"graphql-yoga": "^5.7.0",
"kysely": "^0.27.4",
"pg": "^8.12.0",
"supertest": "^7.0.0",
"ts-node": "^10.9.2",
"tsx": "^4.19.1",
"typescript": "^5.6.2",
Expand All @@ -42,8 +45,17 @@
"node": ">=18.17"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.4",
"@babel/preset-typescript": "^7.24.7",
"@types/pg": "^8.11.9",
"dotenv": "^16.4.5"
"@types/supertest": "^6.0.2",
"@types/swagger-jsdoc": "6.0.4",
"@types/swagger-ui-express": "4.1.6",
"dotenv": "^16.4.5",
"express-validator": "^7.2.0",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.1"
},
"repository": {
"type": "git",
Expand Down
3 changes: 3 additions & 0 deletions packages/rfq-indexer/api/src/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env", "@babel/preset-typescript"]
}
32 changes: 32 additions & 0 deletions packages/rfq-indexer/api/src/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import express from 'express'
import swaggerUi from 'swagger-ui-express'
import { createYoga } from 'graphql-yoga'

import { specs } from './swagger'
import routes from './routes'
import { schema } from './graphql/schema'
import { overrideJsonBigIntSerialization } from './utils/overrideJsonBigIntSerialization'

const app = express()
const port = process.env.PORT || 3001

overrideJsonBigIntSerialization()

app.use(express.json())

// Swagger UI setup
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs))

// REST API routes
app.use('/api', routes)

// GraphQL setup
const yoga = createYoga({ schema })
app.use('/graphql', yoga)

export const server = app.listen(port, () => {
console.log(`Server listening at ${port}`)
console.info('API server runs on http://localhost:3001')
console.info('REST requests go through http://localhost:3001/api')
console.info('GraphQL requests go through http://localhost:3001/graphql')
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Request, Response } from 'express'
import { sql } from 'kysely'

import { db } from '../db'
import { qDeposits, qRelays, qProofs } from '../queries'
import { nest_results } from '../utils/nestResults'

export const conflictingProofsController = async (
req: Request,
res: Response
) => {
try {
const query = db
.with('deposits', () => qDeposits())
.with('relays', () => qRelays())
.with('proofs', () => qProofs())
.with('combined', (qb) =>
qb
.selectFrom('deposits')
.leftJoin('relays', 'transactionId_deposit', 'transactionId_relay')
.leftJoin('proofs', 'transactionId_deposit', 'transactionId_proof')
.selectAll('deposits')
.selectAll('relays')
.selectAll('proofs')
)
.selectFrom('combined')
.selectAll()
.where('relayer_proof', 'is not', null)
.where('relayer_relay', 'is not', null)
.where(
(eb) =>
sql<boolean>`LOWER(${eb.ref('relayer_relay')}) != LOWER(${eb.ref(
'relayer_proof'
)})`
)
.orderBy('blockTimestamp_proof', 'desc')

const results = await query.execute()
const conflictingProofs = nest_results(results)

if (conflictingProofs && conflictingProofs.length > 0) {
res.json(conflictingProofs)
} else {
res.status(200).json({ message: 'No conflicting proofs found' })
}
} catch (error) {
console.error('Error fetching conflicting proofs:', error)
res.status(500).json({ message: 'Internal server error' })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Request, Response } from 'express'

import { db } from '../db'

export const recentInvalidRelaysController = async (
req: Request,
res: Response
) => {
try {
const query = db
.selectFrom('BridgeRelayedEvents')
.leftJoin(
'BridgeRequestEvents',
'BridgeRelayedEvents.transactionId',
'BridgeRequestEvents.transactionId'
)
.select([
'BridgeRelayedEvents.transactionId',
'BridgeRelayedEvents.blockNumber',
'BridgeRelayedEvents.blockTimestamp',
'BridgeRelayedEvents.transactionHash',
'BridgeRelayedEvents.originChain',
'BridgeRelayedEvents.destChain',
'BridgeRelayedEvents.originChainId',
'BridgeRelayedEvents.destChainId',
'BridgeRelayedEvents.originToken',
'BridgeRelayedEvents.destToken',
'BridgeRelayedEvents.originAmountFormatted',
'BridgeRelayedEvents.destAmountFormatted',
'BridgeRelayedEvents.to',
'BridgeRelayedEvents.relayer',
])
// lookback approx 2 weeks
.where(
'BridgeRelayedEvents.blockTimestamp',
'>',
Math.floor(Date.now() / 1000) - 2 * 7 * 24 * 60 * 60
)
.where('BridgeRequestEvents.transactionId', 'is', null)

const results = await query.execute()

if (results && results.length > 0) {
res.json(results)
} else {
res.status(200).json({ message: 'No recent invalid relays found' })
}
} catch (error) {
console.error('Error fetching recent invalid relays:', error)
res.status(500).json({ message: 'Internal server error' })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { Request, Response } from 'express'

import { db } from '../db'
import { qDeposits, qRelays, qProofs, qClaims, qRefunds } from '../queries'
import { nest_results } from '../utils/nestResults'

export const pendingTransactionsMissingClaimController = async (
req: Request,
res: Response
) => {
try {
const query = db
.with('deposits', () => qDeposits())
.with('relays', () => qRelays())
.with('proofs', () => qProofs())
.with('claims', () => qClaims())
.with('combined', (qb) =>
qb
.selectFrom('deposits')
.innerJoin('relays', 'transactionId_deposit', 'transactionId_relay')
.innerJoin('proofs', 'transactionId_deposit', 'transactionId_proof')
.leftJoin('claims', 'transactionId_deposit', 'transactionId_claim')
.selectAll('deposits')
.selectAll('relays')
.selectAll('proofs')
.where('transactionId_claim', 'is', null)
)
.selectFrom('combined')
.selectAll()
.orderBy('blockTimestamp_proof', 'desc')

const results = await query.execute()
const nestedResults = nest_results(results)

if (nestedResults && nestedResults.length > 0) {
res.json(nestedResults)
} else {
res
.status(404)
.json({ message: 'No pending transactions missing claim found' })
}
} catch (error) {
console.error('Error fetching pending transactions missing claim:', error)
res.status(500).json({ message: 'Internal server error' })
}
}


export const pendingTransactionsMissingProofController = async (
req: Request,
res: Response
) => {
try {
const query = db
.with('deposits', () => qDeposits())
.with('relays', () => qRelays())
.with('proofs', () => qProofs())
.with('combined', (qb) =>
qb
.selectFrom('deposits')
.innerJoin('relays', 'transactionId_deposit', 'transactionId_relay')
.leftJoin('proofs', 'transactionId_deposit', 'transactionId_proof')
.selectAll('deposits')
.selectAll('relays')
.where('transactionId_proof', 'is', null)
)
.selectFrom('combined')
.selectAll()
.orderBy('blockTimestamp_relay', 'desc')

const results = await query.execute()
const nestedResults = nest_results(results)

if (nestedResults && nestedResults.length > 0) {
res.json(nestedResults)
} else {
res
.status(404)
.json({ message: 'No pending transactions missing proof found' })
}
} catch (error) {
console.error('Error fetching pending transactions missing proof:', error)
res.status(500).json({ message: 'Internal server error' })
}
}

export const pendingTransactionsMissingRelayController = async (
req: Request,
res: Response
) => {
try {
const query = db
.with('deposits', () => qDeposits())
.with('relays', () => qRelays())
.with('refunds', () => qRefunds())
.with(
'combined',
(qb) =>
qb
.selectFrom('deposits')
.selectAll('deposits')
.leftJoin('relays', 'transactionId_deposit', 'transactionId_relay')
.leftJoin(
'refunds',
'transactionId_deposit',
'transactionId_refund'
)
.where('transactionId_relay', 'is', null) // is not relayed
.where('transactionId_refund', 'is', null) // is not refunded
)
.selectFrom('combined')
.selectAll()
.orderBy('blockTimestamp_deposit', 'desc')

const results = await query.execute()
const nestedResults = nest_results(results)

if (nestedResults && nestedResults.length > 0) {
res.json(nestedResults)
} else {
res
.status(404)
.json({ message: 'No pending transactions missing relay found' })
}
} catch (error) {
console.error('Error fetching pending transactions missing relay:', error)
res.status(500).json({ message: 'Internal server error' })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Request, Response } from 'express'

import { db } from '../db'
import { qDeposits, qRelays, qRefunds } from '../queries'
import { nest_results } from '../utils/nestResults'

export const refundedAndRelayedTransactionsController = async (
req: Request,
res: Response
) => {
try {
const query = db
.with('deposits', () => qDeposits())
.with('relays', () => qRelays())
.with('refunds', () => qRefunds())
.with('combined', (qb) =>
qb
.selectFrom('deposits')
.innerJoin('relays', 'transactionId_deposit', 'transactionId_relay')
.innerJoin('refunds', 'transactionId_deposit', 'transactionId_refund')
.selectAll('deposits')
.selectAll('relays')
.selectAll('refunds')
)
.selectFrom('combined')
.selectAll()
.orderBy('blockTimestamp_refund', 'desc')

const results = await query.execute()
const nestedResults = nest_results(results)

if (nestedResults && nestedResults.length > 0) {
res.json(nestedResults)
} else {
res
.status(200)
.json({ message: 'No refunded and relayed transactions found' })
}
} catch (error) {
console.error('Error fetching refunded and relayed transactions:', error)
res.status(500).json({ message: 'Internal server error' })
}
}
Loading

0 comments on commit f4101f2

Please sign in to comment.