-
Notifications
You must be signed in to change notification settings - Fork 303
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adapters for Intrinio, Unibit, Twelvedata (#442)
* unibit adapter * intrinio adapter - untested * intrinio: tested + update documentation - only iex needed, others untested * twelvedata rest api adapter
- Loading branch information
Showing
37 changed files
with
1,061 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
...require('../.eslintrc.ts.js'), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Chainlink External Adapter for Intrinio | ||
|
||
This adapter uses the Intrinio WS stream | ||
|
||
### Environment variables | ||
|
||
| Required? | Name | Description | Options | Defaults to | | ||
| :-------: | :------------: | :--------------------------------------------------------------------------------------------------------------------: | :--------------------: | :---------: | | ||
| ✅ | `API_KEY` | Your API client key | | | | ||
| ✅ | `SYMBOLS` | A comma delimited list of symbols to fetch prices for. E.g: "MSFT,AAPL" | | | | ||
| | `API_PROVIDER` | Intrinio allows subscription to different [channels/resources](https://github.com/intrinio/intrinio-realtime-node-sdk) | `iex`, `quodd`, `fxcm` | `iex` | | ||
|
||
**NOTE: `quodd` and `fxcm` have not been tested. `iex` is the recommended (and default) websocket subscription** | ||
|
||
### Input Params | ||
|
||
| Required? | Name | Description | Options | Defaults to | | ||
| :-------: | :------------------------: | :------------------------------: | :--------------: | :---------: | | ||
| ✅ | `base`, `from`, or `asset` | The symbol of the asset to query | one of `SYMBOLS` | | | ||
|
||
### Sample Input | ||
|
||
```json | ||
{ | ||
"id": "1", | ||
"data": { | ||
"base": "FTSE" | ||
} | ||
} | ||
``` | ||
|
||
### Sample Output | ||
|
||
```json | ||
{ | ||
"jobRunID": "1", | ||
"data": { | ||
"result": 6663.73 | ||
}, | ||
"result": 6663.73, | ||
"statusCode": 200 | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
{ | ||
"name": "@chainlink/intrinio-adapter", | ||
"version": "0.0.1", | ||
"description": "Chainlink intrinio adapter.", | ||
"keywords": [ | ||
"Chainlink", | ||
"LINK", | ||
"blockchain", | ||
"oracle", | ||
"intrinio" | ||
], | ||
"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": { | ||
"prepublishOnly": "yarn build && yarn test:unit", | ||
"setup": "yarn build", | ||
"build": "tsc -b", | ||
"lint": "eslint --ignore-path ../.eslintignore . --ext .js,.jsx,.ts,.tsx", | ||
"lint:fix": "eslint --ignore-path ../.eslintignore . --ext .js,.jsx,.ts,.tsx --fix", | ||
"test": "mocha --exit --timeout 3000 -r ts-node/register 'test/**/*.test.ts'", | ||
"test:unit": "mocha --exit --grep @integration --invert -r ts-node/register 'test/**/*.test.ts'", | ||
"test:integration": "mocha --exit --timeout 3000 --grep @integration -r ts-node/register 'test/**/*.test.ts'", | ||
"server": "node -e 'require(\"./index.js\").server()'", | ||
"server:dist": "node -e 'require(\"./dist/index.js\").server()'", | ||
"start": "yarn server:dist" | ||
}, | ||
"devDependencies": { | ||
"@types/chai": "^4.2.11", | ||
"@types/express": "^4.17.6", | ||
"@types/mocha": "^7.0.2", | ||
"@types/node": "^14.0.13", | ||
"@typescript-eslint/eslint-plugin": "^3.9.0", | ||
"@typescript-eslint/parser": "^3.9.0", | ||
"ts-node": "^8.10.2", | ||
"typescript": "^3.9.7" | ||
}, | ||
"dependencies": { | ||
"express": "^4.17.1", | ||
"intrinio-realtime": "^2.3.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { Requester, Validator, AdapterError } from '@chainlink/external-adapter' | ||
import IntrinioRealtime from 'intrinio-realtime' | ||
import { AdapterRequest } from '@chainlink/types' | ||
import { Config, makeConfig, PROVIDER_OPTIONS } from './config' | ||
|
||
const prices: { [symbol: string]: { bid: number; ask: number } } = {} | ||
|
||
const subscribe = (assets: string[], config: Config) => { | ||
const client = new IntrinioRealtime({ | ||
api_key: config.key, | ||
provider: config.provider, | ||
}) | ||
|
||
client.join(assets) | ||
|
||
client.onQuote((quote: any) => { | ||
// https://github.com/intrinio/intrinio-realtime-node-sdk | ||
// handle different responses from different providers | ||
switch (config.provider) { | ||
case PROVIDER_OPTIONS[1]: //quodd (untested data provider) | ||
prices[quote.ticker] = { | ||
bid: quote?.bid_price_4d || prices[quote.ticker].bid, | ||
ask: quote?.ask_price_4d || prices[quote.ticker].ask, | ||
} | ||
break | ||
case PROVIDER_OPTIONS[2]: //fxcm (untested data provider) | ||
prices[quote.code] = { | ||
bid: quote.bid_price, | ||
ask: quote.ask_price, | ||
} | ||
break | ||
case PROVIDER_OPTIONS[0]: //iex | ||
default: | ||
if (quote.type == 'last') return | ||
prices[quote.ticker] = { | ||
...prices[quote.ticker], | ||
[quote.type]: quote.price, | ||
} | ||
break | ||
} | ||
}) | ||
} | ||
|
||
export const startService = (config: Config): void => { | ||
const symbols = config.symbols.toUpperCase().split(',') | ||
subscribe(symbols, config) | ||
} | ||
|
||
const customParams = { | ||
base: ['base', 'from', 'asset'], | ||
} | ||
|
||
export const execute = async (input: AdapterRequest, config: Config) => { | ||
const symbols = config.symbols.toUpperCase().split(',') | ||
const validator = new Validator(input, customParams) | ||
if (validator.error) throw validator.error | ||
|
||
const jobRunID = validator.validated.id | ||
const symbol = validator.validated.data.base.toUpperCase() | ||
|
||
if (!symbols.includes(symbol)) | ||
throw new AdapterError({ | ||
jobRunID, | ||
message: `Requested ${symbol} not in SYMBOLS environment variable`, | ||
}) | ||
|
||
const bid = Requester.validateResultNumber(prices, [symbol, 'bid']) | ||
const ask = Requester.validateResultNumber(prices, [symbol, 'ask']) | ||
const price = (bid + ask) / 2 | ||
|
||
const response = { | ||
data: { | ||
result: price, | ||
}, | ||
result: price, | ||
status: 200, | ||
} | ||
return Requester.success(jobRunID, response) | ||
} | ||
|
||
export const makeExecute = (config?: Config) => { | ||
return async (request: AdapterRequest) => execute(request, config || makeConfig()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { util } from '@chainlink/ea-bootstrap' | ||
|
||
export const NAME = 'INTRINIO' | ||
|
||
export const PROVIDER_OPTIONS = ['iex', 'quodd', 'fxcm'] | ||
|
||
export type Config = { | ||
key: string | ||
symbols: string | ||
provider: string | ||
} | ||
|
||
export const makeConfig = (prefix?: string): Config => { | ||
let provider = util.getEnv('API_PROVIDER', prefix) | ||
if (!PROVIDER_OPTIONS.includes(provider)) { | ||
provider = PROVIDER_OPTIONS[0] | ||
} | ||
|
||
return { | ||
key: util.getRequiredEnv('API_KEY', prefix), | ||
symbols: util.getRequiredEnv('SYMBOLS', prefix), | ||
provider: provider.toLowerCase(), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import * as bootstrap from '@chainlink/ea-bootstrap' | ||
import { makeExecute, startService } from './adapter' | ||
import { AdapterRequest, Execute, ExecuteSync } from '@chainlink/types' | ||
import { Requester } from '@chainlink/external-adapter' | ||
import { makeConfig } from './config' | ||
|
||
// Execution helper async => sync | ||
const executeSync = (execute: Execute): ExecuteSync => { | ||
return (data: AdapterRequest, callback: any) => { | ||
return execute(data) | ||
.then((result) => callback(result.statusCode, result)) | ||
.catch((error) => callback(error.statusCode || 500, Requester.errored(data.id, error))) | ||
} | ||
} | ||
|
||
export const server = (): void => { | ||
startService(makeConfig()) | ||
bootstrap.server.initHandler(executeSync(makeExecute()))() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { Requester } from '@chainlink/external-adapter' | ||
import { assertError } from '@chainlink/adapter-test-helpers' | ||
import { AdapterRequest } from '@chainlink/types' | ||
import { makeExecute } from '../src/adapter' | ||
|
||
describe('execute', () => { | ||
const jobID = '1' | ||
const execute = makeExecute({ key: '', symbols: '', provider: '' }) | ||
|
||
context('validation error', () => { | ||
const requests = [ | ||
{ name: 'empty body', testData: {} }, | ||
{ name: 'empty data', testData: { data: {} } }, | ||
{ | ||
name: 'base not supplied', | ||
testData: { id: jobID, data: { quote: 'USD' } }, | ||
}, | ||
] | ||
|
||
requests.forEach((req) => { | ||
it(`${req.name}`, async () => { | ||
try { | ||
await execute(req.testData as AdapterRequest) | ||
} catch (error) { | ||
const errorResp = Requester.errored(jobID, error) | ||
assertError({ expected: 400, actual: errorResp.statusCode }, errorResp, jobID) | ||
} | ||
}) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"extends": "../tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "dist", | ||
"rootDir": "src", | ||
"typeRoots": ["../node_modules/@types", "../typings", "./typings"] | ||
}, | ||
"include": ["src/**/*"], | ||
"exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
declare module 'intrinio-realtime' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
...require('../.eslintrc.ts.js'), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
# Chainlink External Adapter for Twelvedata | ||
|
||
### Environment Variables | ||
|
||
| Required? | Name | Description | Options | Defaults to | | ||
| :-------: | :----------: | :------------------------------: | :-----: | :---------------------------: | | ||
| ✅ | API_KEY | API key for Twelvedata | | | | ||
| | API_ENDPOINT | The endpoint for your Twelvedata | | `https://api.twelvedata.com/` | | ||
|
||
--- | ||
|
||
### Input Parameters | ||
|
||
| Required? | Name | Description | Options | Defaults to | | ||
| :-------: | :------: | :-----------------: | :---------------------------------------------------: | :---------: | | ||
| | endpoint | The endpoint to use | [closing](#Closing-Endpoint), [price](#Price-Endpoint) | `closing` | | ||
|
||
--- | ||
|
||
## Closing Endpoint | ||
|
||
This `closing` endpoint provides the closing price of the previous day as detailed in [Twelvedata documentation](https://twelvedata.com/docs#end-of-day-price). | ||
|
||
### Input Params | ||
|
||
| Required? | Name | Description | Options | Defaults to | | ||
| :-------: | :------------------------------: | :---------------------------------: | :-----: | :---------: | | ||
| ✅ | `base`, `from`, `coin`, `market` | The symbol of the currency to query | | | | ||
|
||
### Sample Input | ||
|
||
```json | ||
{ | ||
"id": "1", | ||
"data": { | ||
"base": "VXX" | ||
} | ||
} | ||
``` | ||
|
||
### Sample Output | ||
|
||
```json | ||
{ | ||
"jobRunID": "1", | ||
"result": 9.975, | ||
"statusCode": 200, | ||
"data": { | ||
"symbol": "VXX", | ||
"exchange": "CBOE", | ||
"currency": "USD", | ||
"datetime": "2021-04-14", | ||
"close": "9.97500", | ||
"result": 9.975 | ||
} | ||
} | ||
``` | ||
|
||
## Price Endpoint | ||
|
||
This `price` endpoint provides the real-time price as detailed in [Twelvedata documentation](https://twelvedata.com/docs#real-time-price). | ||
|
||
### Input Params | ||
|
||
| Required? | Name | Description | Options | Defaults to | | ||
| :-------: | :------------------------------: | :---------------------------------: | :-----: | :---------: | | ||
| ✅ | `base`, `from`, `coin`, `market` | The symbol of the currency to query | | | | ||
|
||
### Sample Input | ||
|
||
```json | ||
{ | ||
"id": "1", | ||
"data": { | ||
"base": "VXX", | ||
"endpoint": "price" | ||
} | ||
} | ||
``` | ||
|
||
### Sample Output | ||
|
||
```json | ||
{ | ||
"jobRunID": "1", | ||
"result": 10.0756, | ||
"statusCode": 200, | ||
"data": { | ||
"price": "10.07560", | ||
"result": 10.0756 | ||
} | ||
} | ||
``` |
Oops, something went wrong.