-
Notifications
You must be signed in to change notification settings - Fork 317
Merc6933 GMCI EA - Data Link Feed #3919
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
26760dc
8d5f2a8
9f4b9f2
59231d6
c06fdd5
3c6f4b5
60a33d5
17a621f
d98103a
7c0c771
4fe40f2
000a15e
ff19d55
2e4d6fd
4f55e23
f4431aa
e8c8c2b
66174dc
9a5e303
c5659a7
0b8a763
da09e6c
a80b239
c727a96
50d4d42
437bfb0
b9247df
f80198a
0912899
30b8375
6edb102
e126611
bf6b59d
418ed2f
d4d4720
871b36d
dd06ecd
9916d51
2292dcd
90ae121
e28958d
3833941
81abf28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@chainlink/gmci-adapter': major | ||
--- | ||
|
||
Version 1.0.0 of GMCI EA |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# GMCI | ||
|
||
  | ||
|
||
This document was generated automatically. Please see [README Generator](../../scripts#readme-generator) for more info. | ||
|
||
## Environment Variables | ||
|
||
| Required? | Name | Description | Type | Options | Default | | ||
| :-------: | :-------------: | :--------------------------------: | :----: | :-----: | :-----: | | ||
| ✅ | API_KEY | An API key for Data Provider | string | | | | ||
| | WS_API_ENDPOINT | WS endpoint for GMCI Data Provider | string | | | | ||
|
||
--- | ||
|
||
## Data Provider Rate Limits | ||
|
||
There are no rate limits for this adapter. | ||
|
||
--- | ||
|
||
## Input Parameters | ||
|
||
| Required? | Name | Description | Type | Options | Default | | ||
| :-------: | :------: | :-----------------: | :----: | :----------------------: | :-----: | | ||
| | endpoint | The endpoint to use | string | [price](#price-endpoint) | `price` | | ||
|
||
## Price Endpoint | ||
|
||
`price` is the only supported name for this endpoint. | ||
|
||
### Input Params | ||
|
||
| Required? | Name | Aliases | Description | Type | Options | Default | Depends On | Not Valid With | | ||
| :-------: | :----: | :-----: | :---------: | :----: | :-----: | :-----: | :--------: | :------------: | | ||
| ✅ | symbol | | Index name | string | | | | | | ||
|
||
### Example | ||
|
||
Request: | ||
|
||
```json | ||
{ | ||
"data": { | ||
"endpoint": "price", | ||
"symbol": "GMCI30" | ||
} | ||
} | ||
``` | ||
|
||
--- | ||
|
||
MIT License |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"name": "@chainlink/gmci-adapter", | ||
"version": "0.0.0", | ||
"description": "Chainlink gmci adapter.", | ||
"keywords": [ | ||
"Chainlink", | ||
"LINK", | ||
"blockchain", | ||
"oracle", | ||
"gmci" | ||
], | ||
"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": { | ||
"@sinonjs/fake-timers": "9.1.2", | ||
"@types/jest": "29.5.14", | ||
"@types/node": "22.14.1", | ||
"@types/sinonjs__fake-timers": "8.1.5", | ||
"nock": "13.5.6", | ||
"typescript": "5.8.3" | ||
}, | ||
"dependencies": { | ||
"@chainlink/external-adapter-framework": "2.6.0", | ||
"tslib": "2.4.1" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { AdapterConfig } from '@chainlink/external-adapter-framework/config' | ||
|
||
export const config = new AdapterConfig({ | ||
API_KEY: { | ||
description: 'An API key for Data Provider', | ||
type: 'string', | ||
required: true, | ||
sensitive: true, | ||
}, | ||
WS_API_ENDPOINT: { | ||
description: 'WS endpoint for GMCI Data Provider', | ||
type: 'string', | ||
required: true, | ||
}, | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { endpoint as price } from './price' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter' | ||
import { InputParameters } from '@chainlink/external-adapter-framework/validation' | ||
import { config } from '../config' | ||
import { transport } from '../transport/price' | ||
|
||
export const inputParameters = new InputParameters( | ||
{ | ||
symbol: { | ||
required: true, | ||
type: 'string', | ||
description: 'Index name', | ||
}, | ||
}, | ||
[ | ||
{ | ||
symbol: 'GMCI30', | ||
}, | ||
], | ||
) | ||
|
||
export type GMCIResultResponse = { | ||
Result: number | ||
Data: { | ||
symbol: string | ||
result: number | ||
} | ||
} | ||
|
||
export type BaseEndpointTypes = { | ||
Parameters: typeof inputParameters.definition | ||
Response: GMCIResultResponse | ||
Settings: typeof config.settings | ||
} | ||
|
||
export const endpoint = new AdapterEndpoint({ | ||
name: 'price', | ||
aliases: [], | ||
transport: transport, | ||
inputParameters, | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
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: 'GMCI', | ||
config, | ||
endpoints: [price], | ||
}) | ||
|
||
export const server = (): Promise<ServerInstance | undefined> => expose(adapter) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { EndpointContext } from '@chainlink/external-adapter-framework/adapter' | ||
import { | ||
WebSocketTransport, | ||
WebSocketTransportConfig, | ||
} from '@chainlink/external-adapter-framework/transports' | ||
import { makeLogger } from '@chainlink/external-adapter-framework/util' | ||
import { BaseEndpointTypes } from '../endpoint/price' | ||
import { convertTimetoUnixMs } from './util' | ||
|
||
export interface PriceMessage { | ||
last_updated: string | ||
price: number | ||
symbol: string | ||
} | ||
|
||
export interface RebalanceMessage { | ||
end_time: string | ||
start_time: string | ||
status: string | ||
symbol: string | ||
} | ||
|
||
interface WsPriceResponse { | ||
success: boolean | ||
data: Array<PriceMessage> | ||
topic: 'price' | ||
} | ||
|
||
interface WsRebalanceResponse { | ||
success: boolean | ||
data: Array<RebalanceMessage> | ||
topic: 'rebalance_status' | ||
} | ||
|
||
export type WsResponse = WsPriceResponse | WsRebalanceResponse | ||
|
||
export type WsTransportTypes = BaseEndpointTypes & { | ||
Provider: { | ||
WsMessage: WsResponse | ||
} | ||
} | ||
|
||
const logger = makeLogger('GmciTransport') | ||
|
||
export const options: WebSocketTransportConfig<WsTransportTypes> = { | ||
url: (context: EndpointContext<WsTransportTypes>) => context.adapterSettings.WS_API_ENDPOINT, | ||
options: async (context: EndpointContext<WsTransportTypes>) => ({ | ||
headers: { | ||
'X-GMCI-API-KEY': context.adapterSettings.API_KEY, | ||
}, | ||
}), | ||
|
||
handlers: { | ||
message(message: WsResponse) { | ||
if (message.success === false) { | ||
logger.info(message) | ||
return | ||
} | ||
|
||
const results = [] | ||
|
||
if (message.topic === 'price') { | ||
for (const item of message.data) { | ||
results.push({ | ||
params: { symbol: item.symbol }, | ||
response: { | ||
result: item.price, | ||
data: { | ||
result: item.price, | ||
symbol: item.symbol, | ||
}, | ||
timestamps: { | ||
providerIndicatedTimeUnixMs: convertTimetoUnixMs(item.last_updated), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Weren't there multiple different timestamps before? How do we decide which timestamps to provide? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The others get written here. |
||
}, | ||
}, | ||
}) | ||
} | ||
} | ||
return results | ||
}, | ||
}, | ||
|
||
builders: { | ||
subscribeMessage: (params) => { | ||
return { | ||
op: 'subscribe', | ||
args: [`price.${params.symbol}`.toLowerCase()], | ||
} | ||
}, | ||
|
||
unsubscribeMessage: (params) => { | ||
return { | ||
op: 'unsubscribe', | ||
args: [`price.${params.symbol}`.toLowerCase()], | ||
} | ||
}, | ||
}, | ||
} | ||
|
||
export const transport = new WebSocketTransport(options) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export function convertTimetoUnixMs(isoTime: string) { | ||
return Date.parse(isoTime) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"requests": [{ | ||
"symbol": "GMCI30" | ||
}] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`websocket price endpoint should return success 1`] = ` | ||
{ | ||
"data": { | ||
"result": 183.7141917913536, | ||
"symbol": "GMCI30", | ||
}, | ||
"result": 183.7141917913536, | ||
"statusCode": 200, | ||
"timestamps": { | ||
"providerDataReceivedUnixMs": 1018, | ||
"providerDataStreamEstablishedUnixMs": 1010, | ||
"providerIndicatedTimeUnixMs": 1752394072746, | ||
}, | ||
} | ||
`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we expect unsuccessful messages that we don't care about?
Or should we log something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should expect unsuccessful message. Added log for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a log.