Skip to content
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

Peregrine Data External Adapter Submission #3590

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/hip-cows-serve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@chainlink/peregrine-fund-admin-adapter': patch
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'@chainlink/peregrine-fund-admin-adapter': patch
'@chainlink/peregrine-fund-admin-adapter': major

---

Peregrine Fund Admin Init
5 changes: 5 additions & 0 deletions .changeset/warm-vans-divide.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this file

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@chainlink/peregrine-fund-admin-adapter': patch
---

Peregrine PR refactor and testing
20 changes: 20 additions & 0 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
3 changes: 3 additions & 0 deletions packages/sources/peregrine-fund-admin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Chainlink External Adapter for peregrine-fund-admin

This README will be generated automatically when code is merged to `main`. If you would like to generate a preview of the README, please run `yarn generate:readme peregrine-fund-admin`.
40 changes: 40 additions & 0 deletions packages/sources/peregrine-fund-admin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "@chainlink/peregrine-fund-admin-adapter",
"version": "0.0.1",
"description": "Chainlink peregrine-fund-admin adapter.",
"keywords": [
"Chainlink",
"LINK",
"blockchain",
"oracle",
"peregrine-fund-admin"
],
"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": {
"@types/jest": "27.5.2",
"@types/node": "16.18.115",
"nock": "13.5.4",
"typescript": "5.6.3"
},
"dependencies": {
"@chainlink/external-adapter-framework": "1.7.3",
"tslib": "2.4.1"
}
}
27 changes: 27 additions & 0 deletions packages/sources/peregrine-fund-admin/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { AdapterConfig } from '@chainlink/external-adapter-framework/config'
droconnel22 marked this conversation as resolved.
Show resolved Hide resolved

export const config = new AdapterConfig({
API_KEY: {
description: 'An API key for Data Provider',
type: 'string',
required: true,
sensitive: true,
default: '',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this line

},
API_BASE_URL: {
droconnel22 marked this conversation as resolved.
Show resolved Hide resolved
description: 'Base URL to Fund Admin Server Endpoint',
type: 'string',
default: '',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
default: '',
default: 'https://fund-admin-data-adapter-v1-960005989691.europe-west2.run.app',

},
API_NAV_ENDPOINT: {
description:
'An API endpoint for the latest Net Asset Value (NAV) calculation for a given asset',
type: 'string',
default: '',
Copy link
Contributor

@mmcallister-cll mmcallister-cll Jan 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
default: '',
default: '/api/v1/nav',

},
API_RESERVE_ENDPOINT: {
description: 'API Endpoint to get the latest Proof of Reserves for a given asset',
type: 'string',
droconnel22 marked this conversation as resolved.
Show resolved Hide resolved
default: '',
Copy link
Contributor

@mmcallister-cll mmcallister-cll Jan 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
default: '',
default: '/api/v1/reserves',

},
})
2 changes: 2 additions & 0 deletions packages/sources/peregrine-fund-admin/src/endpoint/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { endpoint as nav } from './nav'
export { endpoint as reserve } from './reserve'
32 changes: 32 additions & 0 deletions packages/sources/peregrine-fund-admin/src/endpoint/nav.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
import { httpTransport } from '../transport/nav'
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
import { SingleNumberResultResponse } from '@chainlink/external-adapter-framework/util'
import { config } from '../config'

export const inputParameters = new InputParameters(
{
assetId: {
required: true,
type: 'string',
description: 'The identifying number for the requested asset',
},
},
[
{
assetId: '100',
},
],
)

export type BaseEndpointTypes = {
Parameters: typeof inputParameters.definition
Response: SingleNumberResultResponse
Settings: typeof config.settings
}

export const endpoint = new AdapterEndpoint({
name: 'nav',
transport: httpTransport,
inputParameters,
})
32 changes: 32 additions & 0 deletions packages/sources/peregrine-fund-admin/src/endpoint/reserve.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
import { httpTransport } from '../transport/reserve'
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
import { SingleNumberResultResponse } from '@chainlink/external-adapter-framework/util'
import { config } from '../config'

export const inputParameters = new InputParameters(
{
assetId: {
required: true,
type: 'string',
description: 'The identifying number for the requested asset',
},
},
[
{
assetId: '100',
},
],
)

export type BaseEndpointTypes = {
Parameters: typeof inputParameters.definition
Response: SingleNumberResultResponse
Settings: typeof config.settings
}

export const endpoint = new AdapterEndpoint({
name: 'reserve',
inputParameters,
transport: httpTransport,
})
20 changes: 20 additions & 0 deletions packages/sources/peregrine-fund-admin/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { expose, ServerInstance } from '@chainlink/external-adapter-framework'
import { Adapter } from '@chainlink/external-adapter-framework/adapter'
import { config } from './config'
import { nav, reserve } from './endpoint'

export const adapter = new Adapter({
defaultEndpoint: nav.name,
name: 'PEREGRINE_FUND_ADMIN',
config,
endpoints: [nav, reserve],
droconnel22 marked this conversation as resolved.
Show resolved Hide resolved
rateLimiting: {
tiers: {
default: {
rateLimit1m: 30,
},
},
},
})

export const server = (): Promise<ServerInstance | undefined> => expose(adapter)
76 changes: 76 additions & 0 deletions packages/sources/peregrine-fund-admin/src/transport/nav.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { HttpTransport } from '@chainlink/external-adapter-framework/transports'
import { BaseEndpointTypes } from '../endpoint/nav'

export interface ResponseSchema {
equityNav: number
seniorNav: number
Copy link
Contributor

@mmcallister-cll mmcallister-cll Jan 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this changed on your side in the API response?

juniorNav: number
totalCollateral: number
totalAccounts: number
totalLiability: number
updateDateTime: string
assetId: string
}

export type HttpTransportTypes = BaseEndpointTypes & {
Provider: {
RequestBody: never
ResponseBody: ResponseSchema
}
}

export const httpTransport = new HttpTransport<HttpTransportTypes>({
prepareRequests: (params, config) => {
return params.map((param) => {
return {
params: [param],
request: {
baseURL: config.API_BASE_URL,
url: config.API_NAV_ENDPOINT,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
url: config.API_NAV_ENDPOINT,
url: `${config.API_NAV_ENDPOINT}/${param.assetId}`,

headers: {
X_API_KEY: config.API_KEY,
},
},
}
})
},
parseResponse: (params, response) => {
if (!response.data) {
return params.map((param) => {
return {
params: param,
response: {
errorMessage: `The data provider didn't return any value`,
statusCode: 502,
},
}
})
}

return params.map((param) => {
const equityNav = response.data.equityNav
if (equityNav) {
return {
params: param,
response: {
result: Number(response.data.equityNav),
droconnel22 marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
result: Number(response.data.equityNav),
result: Number(equityNav),

data: {
result: Number(response.data.equityNav),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
result: Number(response.data.equityNav),
result: Number(equityNav),

timestamps: {
providerIndicatedTimeUnixMs: Number(response.data.updateDateTime) * 1000,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updateDateTime returns a formatted string, not a number that can be cast. Please use a proper conversion here.

},
},
},
}
} else {
return {
params: param,
response: {
errorMessage: `The data provider didn't return any value for asset id: ${param}`,
statusCode: 502,
},
}
}
})
},
})
72 changes: 72 additions & 0 deletions packages/sources/peregrine-fund-admin/src/transport/reserve.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make the same changes as above nav.ts file in this file as well.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { HttpTransport } from '@chainlink/external-adapter-framework/transports'
import { BaseEndpointTypes } from '../endpoint/reserve'

export interface ResponseSchema {
assetId: string
totalValue: number
currencyBase: string
accountIds: number[]
updateDateTime: string
}

export type HttpTransportTypes = BaseEndpointTypes & {
Provider: {
RequestBody: never
ResponseBody: ResponseSchema
}
}

export const httpTransport = new HttpTransport<HttpTransportTypes>({
prepareRequests: (params, config) => {
return params.map((param) => {
return {
params: [param],
request: {
baseURL: config.API_BASE_URL,
url: config.API_RESERVE_ENDPOINT,
headers: {
X_API_KEY: config.API_KEY,
},
},
}
})
},
parseResponse: (params, response) => {
if (!response.data) {
return params.map((param) => {
return {
params: param,
response: {
errorMessage: `The data provider didn't return any value`,
statusCode: 502,
},
}
})
}
return params.map((param) => {
const totalValue = response.data.totalValue
if (totalValue) {
return {
params: param,
response: {
result: Number(response.data.totalValue),
data: {
result: Number(response.data.totalValue),
},
timestamps: {
providerIndicatedTimeUnixMs: Number(response.data.updateDateTime) * 1000,
},
},
}
} else {
return {
params: param,
response: {
errorMessage: `The data provider didn't return any value for asset id: ${param}`,
statusCode: 502,
},
}
}
})
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`execute nav endpoint should return success 1`] = `
{
"data": {
"result": 4.377e+21,
"timestamps": {
"providerIndicatedTimeUnixMs": null,
},
},
"result": 4.377e+21,
"statusCode": 200,
"timestamps": {
"providerDataReceivedUnixMs": 978347471111,
"providerDataRequestedUnixMs": 978347471111,
},
}
`;

exports[`execute reserve endpoint should return success 1`] = `
{
"data": {
"result": 1e+23,
},
"result": 1e+23,
"statusCode": 200,
"timestamps": {
"providerDataReceivedUnixMs": 978347471111,
"providerDataRequestedUnixMs": 978347471111,
"providerIndicatedTimeUnixMs": null,
},
}
`;
Loading