Skip to content

Commit

Permalink
Adding validations and custom errors
Browse files Browse the repository at this point in the history
  • Loading branch information
sleyter93 committed May 22, 2024
1 parent f546495 commit 0d0900f
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 13 deletions.
62 changes: 62 additions & 0 deletions src/api/openapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ module.exports = {
}
}
}
},
400: {
description: 'Validation Error',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/ValidationError'
}
}
}
}
}
}
Expand Down Expand Up @@ -184,6 +194,16 @@ module.exports = {
}
}
}
},
400: {
description: 'Validation Error',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/ValidationError'
}
}
}
}
}
}
Expand Down Expand Up @@ -237,6 +257,16 @@ module.exports = {
}
}
}
},
400: {
description: 'Validation Error',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/ValidationError'
}
}
}
}
}
}
Expand Down Expand Up @@ -341,6 +371,16 @@ module.exports = {
}
}
}
},
400: {
description: 'Validation Error',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/ValidationError'
}
}
}
}
}
}
Expand Down Expand Up @@ -402,6 +442,16 @@ module.exports = {
}
}
}
},
400: {
description: 'Validation Error',
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/ValidationError'
}
}
}
}
}
}
Expand Down Expand Up @@ -1281,6 +1331,18 @@ module.exports = {
lastUpdated: { type: 'string', format: 'date-time' }
}
}
},
ValidationError: {
type: 'object',
properties: {
errors: {
type: 'array',
items: {
type: 'string',
example: 'An address is invalid'
}
}
}
}
}
}
Expand Down
29 changes: 21 additions & 8 deletions src/controller/httpsAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import BitcoinRouter from '../service/bitcoin/BitcoinRouter'
import { ValidationError, object, string } from 'yup'
import { utils } from 'ethers'
import { AddressService } from '../service/address/AddressService'
import { supportedFiat } from '../coinmarketcap/support'

interface HttpsAPIDependencies {
app: Express,
Expand Down Expand Up @@ -49,12 +50,19 @@ export class HttpsAPI {
.oneOf(Object.keys(this.dataSourceMapping), 'The current chainId is not supported')
})
const addressSchema = object({
address: string().required('we required a valid address')
address: string().required('An address is invalid')
.trim()
.transform(address => utils.isAddress(address.toLowerCase()) ? address : '')
}).required()
const currencySchema = object({
convert: string().optional()
.trim()
.oneOf(supportedFiat, 'The current currency is not supported')
})

const whilelist = ['https://dapp.testnet.dao.rif.technology', 'https://dapp.mainnet.dao.rif.technology']
const whilelist = ['https://dapp.testnet.dao.rif.technology',
'https://dapp.mainnet.dao.rif.technology',
'https://rif-wallet-services.testnet.rifcomputing.net']
this.app.use(cors({
origin: (origin, callback) => {
if (!origin || whilelist.indexOf(origin) !== -1) {
Expand Down Expand Up @@ -135,15 +143,18 @@ export class HttpsAPI {

this.app.get(
'/price',
async (req: Request<{}, {}, {}, PricesQueryParams>, res: Response, next: NextFunction) => {
async (req: Request<{}, {}, {}, PricesQueryParams>, res: Response) => {
try {
const { convert = 'USD', addresses = '' } = req.query
currencySchema.validateSync({ convert })
addresses.split(',').forEach(address => addressSchema.validateSync({ address }))
const prices = await this.addressService.getPrices({
addresses: req.query.addresses || '',
convert: req.query.convert || 'USD'
addresses,
convert
})
return this.responseJsonOk(res)(prices)
} catch (error) {
next(error)
this.handleValidationError(error, res)
}
}
)
Expand All @@ -162,10 +173,12 @@ export class HttpsAPI {

this.app.get(
'/address/:address',
async (req, res, next: NextFunction) => {
async (req, res) => {
try {
const { limit, prev, next, chainId = '31', blockNumber = '0' } = req.query
const { address } = req.params
chainIdSchema.validateSync({ chainId })
addressSchema.validateSync({ address })
const data = await this.addressService.getAddressDetails({
chainId: chainId as string,
address,
Expand All @@ -176,7 +189,7 @@ export class HttpsAPI {
})
return this.responseJsonOk(res)(data)
} catch (error) {
next(error)
this.handleValidationError(error, res)
}
}
)
Expand Down
2 changes: 1 addition & 1 deletion src/service/address/AddressService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export class AddressService {
}

async getPrices ({ addresses, convert }: GetPricesFunction) {
const addressesArr = addresses.split(',')
const addressesArr = addresses.toLowerCase().split(',')
return this.lastPrice.getPrices(addressesArr, convert)
}

Expand Down
16 changes: 12 additions & 4 deletions test/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,13 @@ describe('coin market cap', () => {
]
const res = await request(app)
.get(`/price?convert=asd&addresses=${addresses.join(',')}`)
.expect(500)
.expect(400)

expect(res.text).toEqual('Convert not supported')
expect(res.body).toEqual({
errors: [
'The current currency is not supported'
]
})
expect(axiosMock.get).toHaveBeenCalledTimes(1)
})

Expand All @@ -110,9 +114,13 @@ describe('coin market cap', () => {

const res = await request(app)
.get('/price?convert=USD&addresses=0x2acc95758f8b5f583470ba265eb685a8f45fc9d')
.expect(200)
.expect(400)

expect(res.text).toEqual('{}')
expect(res.body).toEqual({
errors: [
'An address is invalid'
]
})
expect(axiosMock.get).toHaveBeenCalledTimes(1)
})
})
Expand Down

0 comments on commit 0d0900f

Please sign in to comment.