Skip to content

Commit

Permalink
Aleno Base State Price Adapter - http price endpoint (#3571)
Browse files Browse the repository at this point in the history
* Aleno Base State Price Adpater - http price endpoint

Changeset added; Changes as per review

update package.json

fix PR deps

socket.io transport

remove custome test

socket.io transport

pnp.cjs file updated

tsconfig files updated

test payload updated

socket.io handlers updated

* Adjust soak test

* changes as per review

* remove comment

* fix integration test

* fix listeners

---------

Co-authored-by: Michael Xiao <michael.xiao@smartcontract.com>
  • Loading branch information
Subarna-Singh and mxiao-cll authored Nov 29, 2024
1 parent 88b3002 commit b7bd1ca
Show file tree
Hide file tree
Showing 27 changed files with 656 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/serious-bees-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'k6': patch
---

Accept 1% failure
5 changes: 5 additions & 0 deletions .changeset/sixty-plums-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@chainlink/aleno-adapter': major
---

Aleno Base State Adapter
42 changes: 42 additions & 0 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/k6/entry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ if [ ! -z ${PR_NUMBER+x} ]; then
TEST_OUTPUT_ASSERTIONS_FAILED=$(cat ~/output.log | grep "Failed: " | sort | uniq)
TEST_OUTPUT_ASSERTIONS_LOADED_COUNT=$(cat ~/output.log | grep "Assertion loaded: " | sort | uniq | wc -l)
TEST_OUTPUT_ASSERTIONS_COUNT=$(cat ~/output.log | grep "Assertion applied: " | sort | uniq | wc -l)
TEST_OUTPUT_SAMPLE=$(cat ~/output.log | grep -e "request: " -e "DEBUG: " | tail -n 200)
TEST_OUTPUT_SAMPLE=$(cat ~/output.log | tail -n 1000)
TEST_OUTPUT_PARAM_NUM=$(sed 's/^request: \(.*\) response.*/\1/' ~/output.log | sort | uniq | wc -l)
if [ "$TEST_OUTPUT_PARAM_NUM" -lt 5 ]; then
TEST_OUTPUT_MESSAGE=":warning: Only $TEST_OUTPUT_PARAM_NUM unique input parameter sets. Update test-payload.json to increase the coverage. "
Expand Down
2 changes: 1 addition & 1 deletion packages/k6/src/output-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ export const validateOutput = (
if (!response.body) {
return
}
console.log(`request: ${response.request.body} response: ${response.body}`)
const body = JSON.parse(response.body.toString())
const requestBody = JSON.parse(response.request.body)
console.log(`request: ${response.request.body} response: ${response.body}`)
for (const assertion of assertions) {
if (!matchRequest(assertion.request, requestBody)) {
continue
Expand Down
Empty file.
3 changes: 3 additions & 0 deletions packages/sources/aleno/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Chainlink External Adapter for aleno

This README will be generated automatically when code is merged to `main`. If you would like to generate a preview of the README, please run `yarn generate:readme aleno`.
42 changes: 42 additions & 0 deletions packages/sources/aleno/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@chainlink/aleno-adapter",
"version": "0.0.0",
"description": "Chainlink aleno adapter.",
"keywords": [
"Chainlink",
"LINK",
"blockchain",
"oracle",
"aleno"
],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"repository": {
"url": "https://github.com/smartcontractkit/external-adapters-js",
"type": "git"
},
"license": "MIT",
"scripts": {
"clean": "rm -rf dist && rm -f tsconfig.tsbuildinfo",
"prepack": "yarn build",
"build": "tsc -b",
"server": "node -e 'require(\"./index.js\").server()'",
"server:dist": "node -e 'require(\"./dist/index.js\").server()'",
"start": "yarn server:dist"
},
"devDependencies": {
"@types/jest": "27.5.2",
"@types/node": "16.18.119",
"nock": "13.5.5",
"socket.io-mock-ts": "1.0.2",
"typescript": "5.6.3"
},
"dependencies": {
"@chainlink/external-adapter-framework": "1.7.1",
"socket.io-client": "^4.8.1",
"tslib": "2.4.1"
}
}
27 changes: 27 additions & 0 deletions packages/sources/aleno/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { AdapterConfig } from '@chainlink/external-adapter-framework/config'

export const config = new AdapterConfig({
API_KEY: {
description: 'An API key for Aleno',
type: 'string',
required: true,
sensitive: true,
},
API_ENDPOINT: {
description: 'An API endpoint for Data Provider',
type: 'string',
default: 'https://state-price.aleno.ai',
},
WS_API_ENDPOINT: {
description: 'WS endpoint for Aleno',
type: 'string',
default: 'https://ws-state-price.aleno.ai',
},

BACKGROUND_EXECUTE_MS: {
description:
'The amount of time the background execute should sleep before performing the next request',
type: 'number',
default: 10_000,
},
})
1 change: 1 addition & 0 deletions packages/sources/aleno/src/endpoint/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { endpoint as price } from './price'
32 changes: 32 additions & 0 deletions packages/sources/aleno/src/endpoint/price.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
import { SingleNumberResultResponse } from '@chainlink/external-adapter-framework/util'
import { TransportRoutes } from '@chainlink/external-adapter-framework/transports'
import { priceEndpointInputParametersDefinition } from '@chainlink/external-adapter-framework/adapter'
import { config } from '../config'

import { httpTransport } from '../transport/price-http'
import { socketioTransport } from '../transport/price-socketio'

export const inputParameters = new InputParameters(priceEndpointInputParametersDefinition, [
{
base: 'FRAX',
quote: 'USD',
},
])

export type BaseEndpointTypes = {
Parameters: typeof inputParameters.definition
Response: SingleNumberResultResponse
Settings: typeof config.settings
}

export const endpoint = new AdapterEndpoint({
name: 'price',
aliases: ['crypto', 'state'],
transportRoutes: new TransportRoutes<BaseEndpointTypes>()
.register('rest', httpTransport)
.register('socketio', socketioTransport),
inputParameters,
defaultTransport: 'socketio',
})
20 changes: 20 additions & 0 deletions packages/sources/aleno/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { expose, ServerInstance } from '@chainlink/external-adapter-framework'
import { Adapter } from '@chainlink/external-adapter-framework/adapter'
import { config } from './config'
import { price } from './endpoint'

export const adapter = new Adapter({
defaultEndpoint: price.name,
name: 'ALENO',
config,
endpoints: [price],
rateLimiting: {
tiers: {
default: {
rateLimit1m: 30,
},
},
},
})

export const server = (): Promise<ServerInstance | undefined> => expose(adapter)
94 changes: 94 additions & 0 deletions packages/sources/aleno/src/transport/price-http.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { HttpTransport } from '@chainlink/external-adapter-framework/transports'
import { BaseEndpointTypes } from '../endpoint/price'

export interface ResponseSchema {
[index: number]: {
id: string
baseSymbol: string
quoteSymbol: string
processTimestamp: number
processBlockChainId: string
processBlockNumber: number
processBlockTimestamp: number
aggregatedLast7DaysBaseVolume: number
price: number
aggregatedMarketDepthMinusOnePercentUsdAmount: number
aggregatedMarketDepthPlusOnePercentUsdAmount: number
aggregatedMarketDepthUsdAmount: number
aggregatedLast7DaysUsdVolume: number
}
}

export type HttpTransportTypes = BaseEndpointTypes & {
Provider: {
RequestBody: never
ResponseBody: ResponseSchema
}
}

export const httpTransport = new HttpTransport<HttpTransportTypes>({
prepareRequests: (params, config) => {
return params.map((param) => {
return {
params: [param],
request: {
baseURL: config.API_ENDPOINT,
url: 'baseTokenStates/latest',
headers: {
'x-api-key': config.API_KEY,
},
},
}
})
},

parseResponse: (params, response) => {
if (!response.data) {
return params.map((param) => {
return {
params: param,
response: {
errorMessage: `The data provider didn't return any value for ${param.base}/${param.quote}`,
statusCode: 502,
},
}
})
}

return params.map((param) => {
let result
let processTimestamp

Object.values(response.data).forEach((row) => {
if (row.baseSymbol === param.base && row.quoteSymbol === param.quote) {
result = Number(row.price)
processTimestamp = row.processTimestamp
}
})

if (result === undefined || processTimestamp === undefined) {
return {
params: param,
response: {
errorMessage: `The data provider didn't return any value for ${param.base}/${param.quote}`,
statusCode: 502,
},
}
}

return {
params: param,
response: {
result,
data: {
result,
},
timestamps: {
providerDataReceivedUnixMs: Date.now(),
providerIndicatedTimeUnixMs: processTimestamp * 1000,
},
},
}
})
},
})
Loading

0 comments on commit b7bd1ca

Please sign in to comment.