Skip to content

Commit bd3d76b

Browse files
DF-20626 add bitgo-reserves EA (#3486)
* DF-20626 add bitgo-reserves EA * add changeset * update test-payload to remove default params * generate readme * review fixes --------- Co-authored-by: app-token-issuer-data-feeds[bot] <134377064+app-token-issuer-data-feeds[bot]@users.noreply.github.com>
1 parent 0542bcb commit bd3d76b

19 files changed

+353
-0
lines changed

.changeset/spicy-bears-burn.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@chainlink/bitgo-reserves-adapter': major
3+
---
4+
5+
bitgo-reserves EA initial release

.pnp.cjs

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/sources/bitgo-reserves/CHANGELOG.md

Whitespace-only changes.
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# BITGO_RESERVES
2+
3+
![0.0.0](https://img.shields.io/github/package-json/v/smartcontractkit/external-adapters-js?filename=packages/sources/bitgo-reserves/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+
| | API_ENDPOINT | An API endpoint for Data Provider | string | | `http://por.usdstandard-test.com` |
12+
13+
---
14+
15+
## Data Provider Rate Limits
16+
17+
| Name | Requests/credits per second | Requests/credits per minute | Requests/credits per hour | Note |
18+
| :-----: | :-------------------------: | :-------------------------: | :-----------------------: | :--: |
19+
| default | | 10 | | |
20+
21+
---
22+
23+
## Input Parameters
24+
25+
| Required? | Name | Description | Type | Options | Default |
26+
| :-------: | :------: | :-----------------: | :----: | :----------------------------: | :--------: |
27+
| | endpoint | The endpoint to use | string | [reserves](#reserves-endpoint) | `reserves` |
28+
29+
## Reserves Endpoint
30+
31+
`reserves` is the only supported name for this endpoint.
32+
33+
### Input Params
34+
35+
There are no input parameters for this endpoint.
36+
37+
### Example
38+
39+
Request:
40+
41+
```json
42+
{
43+
"data": {
44+
"endpoint": "reserves"
45+
}
46+
}
47+
```
48+
49+
---
50+
51+
MIT License
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "@chainlink/bitgo-reserves-adapter",
3+
"version": "0.0.0",
4+
"description": "Chainlink bitgo-reserves adapter.",
5+
"keywords": [
6+
"Chainlink",
7+
"LINK",
8+
"blockchain",
9+
"oracle",
10+
"bitgo-reserves"
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+
"@types/jest": "27.5.2",
32+
"@types/node": "16.11.68",
33+
"nock": "13.5.4",
34+
"typescript": "5.0.4"
35+
},
36+
"dependencies": {
37+
"@chainlink/external-adapter-framework": "1.5.0",
38+
"tslib": "2.4.1"
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { AdapterConfig } from '@chainlink/external-adapter-framework/config'
2+
3+
export const config = new AdapterConfig({
4+
API_ENDPOINT: {
5+
description: 'An API endpoint for Data Provider',
6+
type: 'string',
7+
default: 'http://por.usdstandard-test.com',
8+
},
9+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { endpoint as reserves } from './reserves'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
2+
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
3+
import { SingleNumberResultResponse } from '@chainlink/external-adapter-framework/util'
4+
import { config } from '../config'
5+
import { httpTransport } from '../transport/reserves'
6+
7+
export const inputParameters = new InputParameters({})
8+
9+
export type BaseEndpointTypes = {
10+
Parameters: typeof inputParameters.definition
11+
Response: SingleNumberResultResponse
12+
Settings: typeof config.settings
13+
}
14+
15+
export const endpoint = new AdapterEndpoint({
16+
name: 'reserves',
17+
transport: httpTransport,
18+
inputParameters,
19+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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 { reserves } from './endpoint'
5+
6+
export const adapter = new Adapter({
7+
defaultEndpoint: reserves.name,
8+
name: 'BITGO_RESERVES',
9+
config,
10+
endpoints: [reserves],
11+
rateLimiting: {
12+
tiers: {
13+
default: {
14+
rateLimit1m: 10, // setting a rate limit so we don't blast the server as fast as possible
15+
},
16+
},
17+
},
18+
})
19+
20+
export const server = (): Promise<ServerInstance | undefined> => expose(adapter)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { HttpTransport } from '@chainlink/external-adapter-framework/transports'
2+
import { BaseEndpointTypes } from '../endpoint/reserves'
3+
4+
export interface ResponseSchema {
5+
totalReserve: number
6+
lastUpdated: string
7+
cashReserve: number
8+
investedReserve: number
9+
}
10+
11+
export type HttpTransportTypes = BaseEndpointTypes & {
12+
Provider: {
13+
RequestBody: never
14+
ResponseBody: ResponseSchema
15+
}
16+
}
17+
18+
// returns reserves info for USDS
19+
export const httpTransport = new HttpTransport<HttpTransportTypes>({
20+
prepareRequests: (params, config) => {
21+
return params.map((param) => {
22+
return {
23+
params: [param],
24+
request: {
25+
baseURL: config.API_ENDPOINT,
26+
url: '/reserves.json',
27+
},
28+
}
29+
})
30+
},
31+
parseResponse: (params, response) => {
32+
const timestamps = {
33+
providerIndicatedTimeUnixMs: new Date(response.data.lastUpdated).getTime(),
34+
}
35+
36+
if (!response.data) {
37+
return params.map((param) => {
38+
return {
39+
params: param,
40+
response: {
41+
errorMessage: `The data provider didn't return any value`,
42+
statusCode: 502,
43+
timestamps,
44+
},
45+
}
46+
})
47+
}
48+
49+
return params.map((param) => {
50+
const result = response.data.totalReserve
51+
return {
52+
params: param,
53+
response: {
54+
result,
55+
data: {
56+
result,
57+
},
58+
timestamps,
59+
},
60+
}
61+
})
62+
},
63+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"requests": [{}]
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`execute reserves endpoint should return success 1`] = `
4+
{
5+
"data": {
6+
"result": 1234567.89,
7+
},
8+
"result": 1234567.89,
9+
"statusCode": 200,
10+
"timestamps": {
11+
"providerDataReceivedUnixMs": 978347471111,
12+
"providerDataRequestedUnixMs": 978347471111,
13+
"providerIndicatedTimeUnixMs": 1727745825000,
14+
},
15+
}
16+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import {
2+
TestAdapter,
3+
setEnvVariables,
4+
} from '@chainlink/external-adapter-framework/util/testing-utils'
5+
import * as nock from 'nock'
6+
import { mockResponseSuccess } from './fixtures'
7+
8+
describe('execute', () => {
9+
let spy: jest.SpyInstance
10+
let testAdapter: TestAdapter
11+
let oldEnv: NodeJS.ProcessEnv
12+
13+
beforeAll(async () => {
14+
oldEnv = JSON.parse(JSON.stringify(process.env))
15+
process.env.API_ENDPOINT = 'http://test-endpoint.com'
16+
17+
const mockDate = new Date('2001-01-01T11:11:11.111Z')
18+
spy = jest.spyOn(Date, 'now').mockReturnValue(mockDate.getTime())
19+
20+
const adapter = (await import('./../../src')).adapter
21+
adapter.rateLimiting = undefined
22+
testAdapter = await TestAdapter.startWithMockedCache(adapter, {
23+
testAdapter: {} as TestAdapter<never>,
24+
})
25+
})
26+
27+
afterAll(async () => {
28+
setEnvVariables(oldEnv)
29+
await testAdapter.api.close()
30+
nock.restore()
31+
nock.cleanAll()
32+
spy.mockRestore()
33+
})
34+
35+
describe('reserves endpoint', () => {
36+
it('should return success', async () => {
37+
const data = {
38+
endpoint: 'reserves',
39+
}
40+
mockResponseSuccess()
41+
const response = await testAdapter.request(data)
42+
expect(response.statusCode).toBe(200)
43+
expect(response.json()).toMatchSnapshot()
44+
})
45+
})
46+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import nock from 'nock'
2+
3+
export const mockResponseSuccess = (): nock.Scope =>
4+
nock('http://test-endpoint.com', {
5+
encodedQueryParams: true,
6+
})
7+
.get('/reserves.json')
8+
.reply(
9+
200,
10+
() => ({
11+
totalReserve: 1234567.89,
12+
lastUpdated: '2024-10-01T01:23:45Z',
13+
}),
14+
[
15+
'Content-Type',
16+
'application/json',
17+
'Connection',
18+
'close',
19+
'Vary',
20+
'Accept-Encoding',
21+
'Vary',
22+
'Origin',
23+
],
24+
)
25+
.persist()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"outDir": "dist",
5+
"rootDir": "src"
6+
},
7+
"include": ["src/**/*", "src/**/*.json"],
8+
"exclude": ["dist", "**/*.spec.ts", "**/*.test.ts"]
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"include": ["src/**/*", "**/test", "src/**/*.json"],
4+
"compilerOptions": {
5+
"noEmit": true
6+
}
7+
}

packages/tsconfig.json

+3
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@
176176
{
177177
"path": "./sources/bitgo"
178178
},
179+
{
180+
"path": "./sources/bitgo-reserves"
181+
},
179182
{
180183
"path": "./sources/bitso"
181184
},

packages/tsconfig.test.json

+3
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@
176176
{
177177
"path": "./sources/bitgo/tsconfig.test.json"
178178
},
179+
{
180+
"path": "./sources/bitgo-reserves/tsconfig.test.json"
181+
},
179182
{
180183
"path": "./sources/bitso/tsconfig.test.json"
181184
},

0 commit comments

Comments
 (0)