Skip to content

Commit

Permalink
Merge pull request #4 from smartcontractkit/add-index-adapters
Browse files Browse the repository at this point in the history
Add index adapters
  • Loading branch information
thodges-gh authored Apr 24, 2020
2 parents 69ff662 + a2b079e commit 6ac1047
Show file tree
Hide file tree
Showing 17 changed files with 580 additions and 0 deletions.
30 changes: 30 additions & 0 deletions eodhistoricaldata/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Chainlink EOD Historical Data External Adapter

## Input Params
- `asset`, `base`, `from` or `symbol`: The symbol to get the price from (required)
- `endpoint`: The endpoint to use (optional)


## Output

```json
{
"jobRunID":"278c97ffadb54a5bbb93cfec5f7b5503",
"data":{
"code":"CL.COMM",
"timestamp":1585167540,
"gmtoffset":0,
"open":24.37,
"high":25.24,
"low":22.91,
"close":24.3,
"volume":590048,
"previousClose":24.01,
"change":0.29,
"change_p":1.208,
"result":24.3
},
"result":24.3,
"statusCode":200
}
```
45 changes: 45 additions & 0 deletions eodhistoricaldata/adapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const { Requester, Validator } = require('external-adapter')

const commonKeys = {
N225: 'N225.INDX',
FTSE: 'FTSE.INDX',
BZ: 'BZ.COMM'
}

const customParams = {
base: ['base', 'asset', 'from', 'symbol'],
endpoint: false
}

const createRequest = (input, callback) => {
const validator = new Validator(input, customParams, callback)
const jobRunID = validator.validated.id
const endpoint = validator.validated.data.endpoint || 'real-time'
let symbol = validator.validated.data.base.toUpperCase()
if (commonKeys[symbol]) {
symbol = commonKeys[symbol]
}
const url = `https://eodhistoricaldata.com/api/${endpoint}/${symbol}`
const api_token = process.env.API_KEY // eslint-disable-line camelcase

const qs = {
api_token,
fmt: 'json'
}

const options = {
url,
qs
}

Requester.requestRetry(options)
.then(response => {
response.body.result = Requester.validateResult(response.body, ['close'])
callback(response.statusCode, Requester.success(jobRunID, response))
})
.catch(error => {
callback(500, Requester.errored(jobRunID, error))
})
}

module.exports.createRequest = createRequest
8 changes: 8 additions & 0 deletions eodhistoricaldata/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "eodhistoricaldata",
"version": "0.1.0",
"license": "MIT",
"scripts": {
"test": "yarn _mocha --timeout 0"
}
}
48 changes: 48 additions & 0 deletions eodhistoricaldata/test/adapter_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const assert = require('chai').assert
const createRequest = require('../adapter').createRequest

describe('createRequest', () => {
const jobID = '1'

context('successful calls', () => {
const requests = [
{ name: 'id not supplied', testData: { data: { base: 'N225.INDX' } } },
{ name: 'base', testData: { id: jobID, data: { base: 'N225' } } },
{ name: 'from', testData: { id: jobID, data: { from: 'N225' } } },
{ name: 'asset', testData: { id: jobID, data: { asset: 'N225' } } }
]

requests.forEach(req => {
it(`${req.name}`, (done) => {
createRequest(req.testData, (statusCode, data) => {
assert.equal(statusCode, 200)
assert.equal(data.jobRunID, jobID)
assert.isNotEmpty(data.data)
assert.isAbove(Number(data.result), 0)
assert.isAbove(Number(data.data.result), 0)
done()
})
})
})
})

context('error calls', () => {
const requests = [
{ name: 'empty body', testData: {} },
{ name: 'empty data', testData: { data: {} } },
{ name: 'unknown base', testData: { id: jobID, data: { base: 'not_real' } } }
]

requests.forEach(req => {
it(`${req.name}`, (done) => {
createRequest(req.testData, (statusCode, data) => {
assert.equal(statusCode, 500)
assert.equal(data.jobRunID, jobID)
assert.equal(data.status, 'errored')
assert.isNotEmpty(data.error)
done()
})
})
})
})
})
38 changes: 38 additions & 0 deletions fcsapi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Chainlink External Adapter for FCS API

## Input Params

- `asset`, `base`, `from`: The target currency to query (required)
- `endpoint`: The endpoint to use (optional)

## Output Format

```json
{
"jobRunID": "1",
"data": {
"status": true,
"code": 200,
"msg": "Successfully",
"response": [
{
"price": "5770.60",
"high": "5770.60",
"low": "5725.00",
"chg": "-56.01",
"chg_percent": "-0.96%",
"dateTime": "2020-04-24 09:10:08",
"id": "529",
"name": "FTSE 100"
}
],
"info": {
"server_time": "2020-04-24 09:10:58 UTC",
"credit_count": 1
},
"result": 5770.6
},
"result": 5770.6,
"statusCode": 200
}
```
57 changes: 57 additions & 0 deletions fcsapi/adapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const { Requester, Validator } = require('external-adapter')

const customError = (body) => {
if (body.msg !== 'Successfully') return true
return false
}

const commonKeys = {
AUD: { id: '13', endpoint: 'forex/latest' },
CHF: { id: '466', endpoint: 'forex/latest' },
EUR: { id: '1', endpoint: 'forex/latest' },
GBP: { id: '39', endpoint: 'forex/latest' },
JPY: { id: '1075', endpoint: 'forex/latest' },
XAU: { id: '1984', endpoint: 'forex/latest' },
XAG: { id: '1975', endpoint: 'forex/latest' },
N225: { id: '268', endpoint: 'stock/indices_latest' },
FTSE: { id: '529', endpoint: 'stock/indices_latest' }
}

const customParams = {
base: ['base', 'asset', 'from'],
endpoint: false
}

const createRequest = (input, callback) => {
const validator = new Validator(input, customParams, callback)
const jobRunID = validator.validated.id
let symbol = validator.validated.data.base.toUpperCase()
let endpoint = validator.validated.data.endpoint
if (commonKeys[symbol]) {
endpoint = commonKeys[symbol].endpoint
symbol = commonKeys[symbol].id
}
const url = `https://fcsapi.com/api-v2/${endpoint}`
const access_key = process.env.API_KEY // eslint-disable-line camelcase

const qs = {
access_key,
id: symbol
}

const options = {
url,
qs
}

Requester.requestRetry(options, customError)
.then(response => {
response.body.result = Requester.validateResult(response.body, ['response', 0, 'price'])
callback(response.statusCode, Requester.success(jobRunID, response))
})
.catch(error => {
callback(500, Requester.errored(jobRunID, error))
})
}

module.exports.createRequest = createRequest
8 changes: 8 additions & 0 deletions fcsapi/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "fcsapi",
"version": "0.1.0",
"license": "MIT",
"scripts": {
"test": "yarn _mocha --timeout 0"
}
}
56 changes: 56 additions & 0 deletions fcsapi/test/adapter_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const assert = require('chai').assert
const createRequest = require('../adapter').createRequest

describe('createRequest', () => {
const jobID = '1'

context('successful calls', () => {
const requests = [
{ name: 'id not supplied', testData: { data: { base: 'FTSE' } } },
{ name: 'base', testData: { id: jobID, data: { base: 'N225' } } },
{ name: 'from', testData: { id: jobID, data: { from: 'N225' } } },
{ name: 'asset', testData: { id: jobID, data: { asset: 'N225' } } },
{ name: 'AUD', testData: { id: jobID, data: { asset: 'AUD' } } },
{ name: 'CHF', testData: { id: jobID, data: { asset: 'CHF' } } },
{ name: 'EUR', testData: { id: jobID, data: { asset: 'EUR' } } },
{ name: 'GBP', testData: { id: jobID, data: { asset: 'GBP' } } },
{ name: 'JPY', testData: { id: jobID, data: { asset: 'JPY' } } },
{ name: 'XAU', testData: { id: jobID, data: { asset: 'XAU' } } },
{ name: 'XAG', testData: { id: jobID, data: { asset: 'XAG' } } }
]

requests.forEach(req => {
it(`${req.name}`, (done) => {
createRequest(req.testData, (statusCode, data) => {
console.log(JSON.stringify(data, null, 1))
assert.equal(statusCode, 200)
assert.equal(data.jobRunID, jobID)
assert.isNotEmpty(data.data)
assert.isAbove(Number(data.result), 0)
assert.isAbove(Number(data.data.result), 0)
done()
})
})
})
})

context('error calls', () => {
const requests = [
{ name: 'empty body', testData: {} },
{ name: 'empty data', testData: { data: {} } },
{ name: 'unknown base', testData: { id: jobID, data: { base: 'not_real' } } }
]

requests.forEach(req => {
it(`${req.name}`, (done) => {
createRequest(req.testData, (statusCode, data) => {
assert.equal(statusCode, 500)
assert.equal(data.jobRunID, jobID)
assert.equal(data.status, 'errored')
assert.isNotEmpty(data.error)
done()
})
})
})
})
})
41 changes: 41 additions & 0 deletions fmpcloud/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Chainlink External Adapter for Fmp Cloud

## Input Params

- `asset`, `base`, `from`: The target currency to query (required)
- `endpoint`: The endpoint to use (optional)

## Output Format

```json
{
"jobRunID": "278c97ffadb54a5bbb93cfec5f7b5503",
"data": [
{
"symbol": "AAPL",
"name": "Apple Inc.",
"price": 245.52,
"changesPercentage": -0.55,
"change": -1.36,
"dayLow": 244.3,
"dayHigh": 258,
"yearHigh": 327.85,
"yearLow": 170.27,
"marketCap": 1074267815936,
"priceAvg50": 287.00342,
"priceAvg200": 269.64044,
"volume": 68684527,
"avgVolume": 47970853,
"exchange": "NASDAQ",
"open": 250.75,
"previousClose": 246.88,
"eps": 12.595,
"pe": 19.49345,
"earningsAnnouncement": "2020-01-28T21:30:00.000+0000",
"sharesOutstanding": 4375479808,
"timestamp": 1585227237
}
],
"statusCode": 200
}
```
52 changes: 52 additions & 0 deletions fmpcloud/adapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const { Requester, Validator } = require('external-adapter')

const commonKeys = {
N225: '^N225',
FTSE: '^FTSE',
AUD: 'AUDUSD',
CHF: 'CHFUSD',
EUR: 'EURUSD',
GBP: 'GBPUSD',
JPY: 'JPYUSD'
}

const customError = (body) => {
return body.length === 0
}

const customParams = {
base: ['base', 'asset', 'from'],
endpoint: false
}

const createRequest = (input, callback) => {
const validator = new Validator(input, customParams, callback)
const jobRunID = validator.validated.id
const endpoint = validator.validated.data.endpoint || 'quote'
let symbol = validator.validated.data.base.toUpperCase()
if (commonKeys[symbol]) {
symbol = commonKeys[symbol]
}
const url = `https://fmpcloud.io/api/v3/${endpoint}/${symbol}`
const apikey = process.env.API_KEY

const qs = {
apikey
}

const options = {
url,
qs
}

Requester.requestRetry(options, customError)
.then(response => {
response.body.result = Requester.validateResult(response.body, [0, 'price'])
callback(response.statusCode, Requester.success(jobRunID, response))
})
.catch(error => {
callback(500, Requester.errored(jobRunID, error))
})
}

module.exports.createRequest = createRequest
Loading

0 comments on commit 6ac1047

Please sign in to comment.