Skip to content

Commit d1918f6

Browse files
Add expand.network aggregated state price adapter (#3467)
1 parent 97d0517 commit d1918f6

25 files changed

+453
-0
lines changed

.changeset/breezy-hounds-clean.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@chainlink/expand-network-adapter': minor
3+
---
4+
5+
Add adapter for expand network.

.pnp.cjs

+22
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

packages/sources/expand-network/CHANGELOG.md

Whitespace-only changes.
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# EXPAND_NETWORK
2+
3+
![0.0.0](https://img.shields.io/github/package-json/v/smartcontractkit/external-adapters-js?filename=packages/sources/expand-network/package.json) ![v3](https://img.shields.io/badge/framework%20version-v3-blueviolet)
4+
5+
This document was generated automatically. Please see [README Generator](../../scripts#readme-generator) for more info.
6+
7+
## Environment Variables
8+
9+
| Required? | Name | Description | Type | Options | Default |
10+
| :-------: | :-------------: | :---------------------------------------------: | :----: | :-----: | :------------------------------: |
11+
| | WS_API_ENDPOINT | WS endpoint for expand.network price aggregator | string | | `wss://aggregate.expand.network` |
12+
|| API_KEY | An API key for expand.network price aggregator | string | | |
13+
14+
---
15+
16+
## Data Provider Rate Limits
17+
18+
There are no rate limits for this adapter.
19+
20+
---
21+
22+
## Input Parameters
23+
24+
| Required? | Name | Description | Type | Options | Default |
25+
| :-------: | :------: | :-----------------: | :----: | :------------------------------------------------: | :-----: |
26+
| | endpoint | The endpoint to use | string | [price](#price-endpoint), [state](#price-endpoint) | `price` |
27+
28+
## Price Endpoint
29+
30+
Supported names for this endpoint are: `price`, `state`.
31+
32+
### Input Params
33+
34+
| Required? | Name | Aliases | Description | Type | Options | Default | Depends On | Not Valid With |
35+
| :-------: | :---: | :------------: | :--------------------------------------------: | :----: | :-----: | :-----: | :--------: | :------------: |
36+
|| base | `coin`, `from` | The symbol of symbols of the currency to query | string | | | | |
37+
|| quote | `market`, `to` | The symbol of the currency to convert to | string | | | | |
38+
39+
### Example
40+
41+
Request:
42+
43+
```json
44+
{
45+
"data": {
46+
"endpoint": "price",
47+
"base": "wstETH",
48+
"quote": "ETH"
49+
}
50+
}
51+
```
52+
53+
---
54+
55+
MIT License
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"name": "@chainlink/expand-network-adapter",
3+
"version": "0.0.1",
4+
"description": "Chainlink expand-network adapter.",
5+
"keywords": [
6+
"Chainlink",
7+
"LINK",
8+
"blockchain",
9+
"oracle",
10+
"expand-network"
11+
],
12+
"main": "dist/index.js",
13+
"types": "dist/index.d.ts",
14+
"files": [
15+
"dist"
16+
],
17+
"repository": {
18+
"url": "https://github.com/smartcontractkit/external-adapters-js",
19+
"type": "git"
20+
},
21+
"license": "MIT",
22+
"scripts": {
23+
"clean": "rm -rf dist && rm -f tsconfig.tsbuildinfo",
24+
"prepack": "yarn build",
25+
"build": "tsc -b",
26+
"server": "node -e 'require(\"./index.js\").server()'",
27+
"server:dist": "node -e 'require(\"./dist/index.js\").server()'",
28+
"start": "yarn server:dist"
29+
},
30+
"devDependencies": {
31+
"@sinonjs/fake-timers": "9.1.2",
32+
"@types/jest": "27.5.2",
33+
"@types/node": "16.11.68",
34+
"@types/sinonjs__fake-timers": "8.1.5",
35+
"nock": "13.5.4",
36+
"typescript": "5.0.4"
37+
},
38+
"dependencies": {
39+
"@chainlink/external-adapter-framework": "1.4.0",
40+
"tslib": "2.4.1"
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { AdapterConfig } from '@chainlink/external-adapter-framework/config'
2+
3+
export const config = new AdapterConfig({
4+
WS_API_ENDPOINT: {
5+
description: 'WS endpoint for expand.network price aggregator',
6+
type: 'string',
7+
default: 'wss://aggregate.expand.network',
8+
},
9+
API_KEY: {
10+
description: 'An API key for expand.network price aggregator',
11+
type: 'string',
12+
required: true,
13+
sensitive: true,
14+
},
15+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { endpoint as price } from './price'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {
2+
AdapterEndpoint,
3+
priceEndpointInputParametersDefinition,
4+
} from '@chainlink/external-adapter-framework/adapter'
5+
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
6+
import { SingleNumberResultResponse } from '@chainlink/external-adapter-framework/util'
7+
import { config } from '../config'
8+
import { wsTransport } from '../transport/price'
9+
10+
export const inputParameters = new InputParameters(priceEndpointInputParametersDefinition, [
11+
{
12+
base: 'wstETH',
13+
quote: 'ETH',
14+
},
15+
])
16+
17+
export type BaseEndpointTypes = {
18+
Parameters: typeof inputParameters.definition
19+
Response: SingleNumberResultResponse
20+
Settings: typeof config.settings
21+
}
22+
23+
export const endpoint = new AdapterEndpoint({
24+
name: 'price',
25+
aliases: ['state', 'crypto'],
26+
transport: wsTransport,
27+
inputParameters,
28+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { expose, ServerInstance } from '@chainlink/external-adapter-framework'
2+
import { Adapter } from '@chainlink/external-adapter-framework/adapter'
3+
import { config } from './config'
4+
import { price } from './endpoint'
5+
6+
export const adapter = new Adapter({
7+
defaultEndpoint: price.name,
8+
name: 'EXPAND_NETWORK',
9+
config,
10+
endpoints: [price],
11+
})
12+
13+
export const server = (): Promise<ServerInstance | undefined> => expose(adapter)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { WebSocketTransport } from '@chainlink/external-adapter-framework/transports'
2+
import { BaseEndpointTypes } from '../endpoint/price'
3+
4+
export interface WSResponse {
5+
blockTime: string
6+
baseSymbol: string
7+
quoteSymbol: string
8+
aggregatedStatePrice: string
9+
aggregatedStatePriceUSD: string
10+
aggregatedMarketDepthBaseToken: string
11+
aggregatedMarketDepthBaseTokenUSD: string
12+
aggregatedMarketDepthQuoteToken: string
13+
aggregatedMarketDepthQuoteTokenUSD: string
14+
totalTradingVolume: string
15+
}
16+
17+
export type WsTransportTypes = BaseEndpointTypes & {
18+
Provider: {
19+
WsMessage: WSResponse
20+
}
21+
}
22+
export const wsTransport = new WebSocketTransport<WsTransportTypes>({
23+
url: (context) => context.adapterSettings.WS_API_ENDPOINT,
24+
options: async (context) => ({
25+
headers: {
26+
authorization: 'secret-token',
27+
'x-api-key': context.adapterSettings.API_KEY,
28+
},
29+
}),
30+
handlers: {
31+
message(message) {
32+
if (!message.aggregatedStatePrice) {
33+
return
34+
}
35+
const result = Number(message.aggregatedStatePrice)
36+
const providerIndicatedTimeUnixMs = new Date(
37+
message.blockTime.split(' ').join('T').concat('Z'),
38+
).getTime()
39+
return [
40+
{
41+
params: { base: message.baseSymbol, quote: message.quoteSymbol },
42+
response: {
43+
result,
44+
data: {
45+
result,
46+
},
47+
timestamps: {
48+
providerIndicatedTimeUnixMs,
49+
},
50+
},
51+
},
52+
]
53+
},
54+
},
55+
builders: {
56+
subscribeMessage: (params) => {
57+
const pair = `${params.base}/${params.quote}`.toUpperCase()
58+
return {
59+
action: 'liquiditymetrics',
60+
asset: pair,
61+
}
62+
},
63+
},
64+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"requests": [
3+
{
4+
"base": "wstETH",
5+
"quote": "ETH"
6+
}
7+
]
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`websocket price endpoint should return error on empty base 1`] = `
4+
{
5+
"error": {
6+
"message": "[Param: base] param is required but no value was provided",
7+
"name": "AdapterError",
8+
},
9+
"status": "errored",
10+
"statusCode": 400,
11+
}
12+
`;
13+
14+
exports[`websocket price endpoint should return error on empty data 1`] = `
15+
{
16+
"error": {
17+
"message": "[Param: base] param is required but no value was provided",
18+
"name": "AdapterError",
19+
},
20+
"status": "errored",
21+
"statusCode": 400,
22+
}
23+
`;
24+
25+
exports[`websocket price endpoint should return error on empty quote 1`] = `
26+
{
27+
"error": {
28+
"message": "[Param: quote] param is required but no value was provided",
29+
"name": "AdapterError",
30+
},
31+
"status": "errored",
32+
"statusCode": 400,
33+
}
34+
`;
35+
36+
exports[`websocket price endpoint should return error on invalid pair 1`] = `
37+
{
38+
"error": {
39+
"message": "The EA has not received any values from the Data Provider for the requested data yet. Retry after a short delay, and if the problem persists raise this issue in the relevant channels.",
40+
"name": "AdapterError",
41+
},
42+
"status": "errored",
43+
"statusCode": 504,
44+
}
45+
`;
46+
47+
exports[`websocket price endpoint should return success 1`] = `
48+
{
49+
"data": {
50+
"result": 1.1803771088055002,
51+
},
52+
"result": 1.1803771088055002,
53+
"statusCode": 200,
54+
"timestamps": {
55+
"providerDataReceivedUnixMs": 1018,
56+
"providerDataStreamEstablishedUnixMs": 1010,
57+
"providerIndicatedTimeUnixMs": 1728302896000,
58+
},
59+
}
60+
`;

0 commit comments

Comments
 (0)