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

NWN ea re-commit to main branch instead of develop #2869

Closed
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/tough-mugs-raise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@chainlink/northwestnodes-adapter': major
---

Initial release of the Northwest Nodes EA
22 changes: 22 additions & 0 deletions .pnp.cjs

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

111 changes: 111 additions & 0 deletions packages/sources/northwestnodes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Northwest Nodes

## Environment Variables

| Required? | Name | Description | Type | Options | Default |
| :-------: | :-----------------------: | :-----------------------------------------: | :------: | :-----: | :---------------------------------: |
| | `API_ENDPOINT` | Base URL for Northwest Nodes REST endpoints | `string` | | `https://api.northwestnodes.com/v2` |
| ✅ | `API_KEY` | Key for the Northwest Nodes API | `string` | | |
| ✅ | `WARMUP_SUBSCRIPTION_TTL` | Reduced cache warmup TTL | `number` | | 10000 |

---

## Ethereum Staking Single Epoch Endpoint

Supported names for this endpoint are: `staking-ethereum-epoch-single`.

### Input Params

| Required? | Name | Aliases | Description | Type | Options | Default | Depends On | Not Valid With |
| :-------: | :--: | :-----: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------: | :-----: | :---------: | :--------: | :------------: |
| | `id` | | The ID of the Ethereum staking Epoch. Defaults to `finalized` to get the latest, can be the numeric ID of a specific epoch within a rolling 90-day, or 21,000 epoch, window. | `string` | | `finalized` |

### Example

Example request: `GET https://api.northwestnodes.com/v2/staking/ethereum/epoch/single/finalized`

Example response:

```
{
"fees": 0.8334600920754772,
"apr_1d": 0.05333348952037061,
"apr_7d": 0.04982447950037814,
"apr_30d": 0.04742649766194572,
"apr_90d": 0.05334137717711991,
"rewards": 8.759989702,
"deposits": 0,
"end_slot": 6659359,
"epoch_id": 208104,
"penalties": -0.040515392,
"slashings": 0,
"start_slot": 6659328,
"base_reward": 0.000003645,
"withdrawals": 8.187745192,
"total_return": 9.552934402075477,
"total_rewards": 9.593449794075477,
"total_deductions": -0.040515392,
"total_validators": 776589,
"active_validators": 612494,
"attestation_count": 32,
"total_dep_balance": 19720252.834956083,
"total_eff_balance": 19599617,
"pending_validators": 94592,
"slashed_validators": 252,
"attestation_penalties": -0.040515392,
"validator_participation_rate": 0.7886977538955612
}
```

## Ethereum Staking Single Epoch Endpoint

Supported names for this endpoint are: `staking-ethereum-epoch-list`.

### Input Params

| Required? | Name | Aliases | Description | Type | Options | Default | Depends On | Not Valid With |
| :-------: | :-----: | :-----: | :-------------------------------------------------------------------------------------------------------------------------------------: | :------: | :-----: | :-----: | :--------: | :------------: |
| | `count` | | The number of the Ethereum staking Epochs to return. Defaults to `225`, or one day of Epochs. Can be a number ranging from 1 to 21,000. | `number` | | `255` |

### Example

Example request: `GET https://api.northwestnodes.com/v2/staking/ethereum/epoch/list/225`

Example response:

```
[{
"fees": 0.8334600920754772,
"apr_1d": 0.05333348952037061,
"apr_7d": 0.04982447950037814,
"apr_30d": 0.04742649766194572,
"apr_90d": 0.05334137717711991,
"rewards": 8.759989702,
"deposits": 0,
"end_slot": 6659359,
"epoch_id": 208104,
"penalties": -0.040515392,
"slashings": 0,
"start_slot": 6659328,
"base_reward": 0.000003645,
"withdrawals": 8.187745192,
"total_return": 9.552934402075477,
"total_rewards": 9.593449794075477,
"total_deductions": -0.040515392,
"total_validators": 776589,
"active_validators": 612494,
"attestation_count": 32,
"total_dep_balance": 19720252.834956083,
"total_eff_balance": 19599617,
"pending_validators": 94592,
"slashed_validators": 252,
"attestation_penalties": -0.040515392,
"validator_participation_rate": 0.7886977538955612
},
(...)
]
```

---

MIT License
42 changes: 42 additions & 0 deletions packages/sources/northwestnodes/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@chainlink/northwestnodes-adapter",
"version": "0.0.1",
"description": "Chainlink Northwest Nodes API adapter.",
"keywords": [
"Chainlink",
"LINK",
"blockchain",
"oracle",
"northwestnodes"
],
"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"
},
"dependencies": {
"@chainlink/external-adapter-framework": "0.29.12",
"tslib": "^2.3.1"
},
"devDependencies": {
"@types/jest": "27.5.2",
"@types/node": "16.11.51",
"@types/supertest": "2.0.12",
"nock": "13.2.9",
"supertest": "6.2.4",
"typescript": "5.0.4"
}
}
18 changes: 18 additions & 0 deletions packages/sources/northwestnodes/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { AdapterConfig } from '@chainlink/external-adapter-framework/config'

export const defaultEndpoint = 'staking_ethereum_epoch_single'

export const config = new AdapterConfig({
API_KEY: {
description: 'The Northwest Nodes API key',
type: 'string',
required: true,
sensitive: true,
},
API_ENDPOINT: {
description: 'The default HTTP API base url',
type: 'string',
required: false,
default: 'https://api.northwestnodes.com/v2',
},
})
2 changes: 2 additions & 0 deletions packages/sources/northwestnodes/src/endpoint/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { endpoint as staking_ethereum_epoch_single } from './staking/ethereum/epoch/single'
export { endpoint as staking_ethereum_epoch_list } from './staking/ethereum/epoch/list'
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
import { HttpTransport } from '@chainlink/external-adapter-framework/transports'
import { IEpochResponse } from '../../../../responses/IEpochResponse'
import { makeLogger } from '@chainlink/external-adapter-framework/util'
import { config } from '../../../../config'

const logger = makeLogger('NWN_EthStakingListEpochEndpoint')

const inputParameters = new InputParameters({
count: {
description:
'The number of past epochs to download, minimum 1 and maximum of 21,000. Default 225 (1 day)',
type: 'number',
required: false,
default: 225,
},
})

type EndpointType = {
Parameters: typeof inputParameters.definition
Settings: typeof config.settings
Response: {
Data: string
Result: string
}
Provider: {
ResponseBody: IEpochResponse[]
RequestBody: null
}
}

const transport = new HttpTransport<EndpointType>({
prepareRequests: (params, settings) =>
params.map((p) => {
const url = '/staking/ethereum/epoch/list/' + p.count
logger.debug('prepareRequests: ' + url)
return {
params,
request: {
baseURL: settings.API_ENDPOINT,
url: url,
method: 'GET',
params: settings.API_KEY ? { key: settings.API_KEY } : undefined,
},
}
}),
parseResponse: (params: (typeof inputParameters.validated)[], res) => {
return params.map((p) => {
if (res.status == 200) {
const json = JSON.stringify(res.data)
logger.debug('parseResponse: ' + res.status + ' OK; ' + json)
return {
params: p,
response: {
data: json,
result: json,
statusCode: res.status,
},
}
} else {
logger.error('parseResponse: ' + res.status + ' ' + res.statusText)
return {
params: p,
response: {
statusCode: res.status,
errorMessage: res.statusText,
},
}
}
})
},
})

export const endpoint = new AdapterEndpoint<EndpointType>({
name: 'staking-ethereum-epoch-list',
transport,
inputParameters,
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
import { HttpTransport } from '@chainlink/external-adapter-framework/transports'
import { IEpochResponse } from '../../../../responses/IEpochResponse'
import { makeLogger } from '@chainlink/external-adapter-framework/util'
import { config } from '../../../../config'

const logger = makeLogger('NWN_EthStakingSingleEpochEndpoint')

const inputParameters = new InputParameters({
id: {
description: 'The id of the epoch, can be "finalized" or a numeric',
type: 'string',
required: false,
default: 'finalized',
},
})

type EndpointType = {
Parameters: typeof inputParameters.definition
Settings: typeof config.settings
Response: {
Data: string
Result: string
}
Provider: {
ResponseBody: IEpochResponse
RequestBody: null
}
}

const transport = new HttpTransport<EndpointType>({
prepareRequests: (params, settings) =>
params.map((p) => {
const url = '/staking/ethereum/epoch/single/' + p.id
logger.debug('prepareRequests: ' + url)
return {
params,
request: {
baseURL: settings.API_ENDPOINT,
url: url,
method: 'GET',
params: settings.API_KEY ? { key: settings.API_KEY } : undefined,
},
}
}),
parseResponse: (params, res) => {
return params.map((p) => {
const statusCode = res.status
const statusText = res.statusText
if (statusCode == 200) {
const json = JSON.stringify(res.data)
logger.debug('parseResponse: ' + statusCode + ' OK; ' + json)
return {
params: p,
response: {
data: json,
result: json,
statusCode,
},
}
} else {
logger.error('parseResponse: ' + statusCode + ' ' + statusText)
return {
params: p,
response: {
statusCode: statusCode,
errorMessage: statusText,
},
}
}
})
},
})

export const endpoint = new AdapterEndpoint<EndpointType>({
name: 'staking-ethereum-epoch-single',
transport,
inputParameters,
})
Loading