-
Notifications
You must be signed in to change notification settings - Fork 308
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added new view-function-multi-chain EA (#3217)
* add view-function-multi-chain EA * update test-payload
- Loading branch information
1 parent
7324bac
commit 240f191
Showing
20 changed files
with
649 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@chainlink/view-function-multi-chain-adapter': major | ||
--- | ||
|
||
Initial version of the EA |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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 |
---|---|---|
|
@@ -57,6 +57,7 @@ | |
"the-graph", | ||
"token-allocation", | ||
"vesper", | ||
"view-function-multi-chain", | ||
"xsushi-price" | ||
] | ||
} |
Empty file.
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,57 @@ | ||
# VIEW_FUNCTION_MULTI_CHAIN | ||
|
||
![v3](https://img.shields.io/badge/framework%20version-v3-blueviolet) | ||
|
||
## Environment Variables | ||
|
||
| Required? | Name | Description | Type | Options | Default | | ||
| :-------: | :-------------------: | :---------------------------------------------------------------------------------------: | :----: | :-----: | :-----: | | ||
| ✅ | {NETWORK}\_RPC_URL | RPC url for a NETWORK. NETWORK is the value of `network` input param | string | | | | ||
| ✅ | {NETWORK}\_CHAIN_ID | Chain id for a NETWORK. NETWORK is the value of `network` input param | number | | | | ||
| | BACKGROUND_EXECUTE_MS | The amount of time the background execute should sleep before performing the next request | number | | `10000` | | ||
|
||
--- | ||
|
||
## Data Provider Rate Limits | ||
|
||
There are no rate limits for this adapter. | ||
|
||
--- | ||
|
||
## Input Parameters | ||
|
||
| Required? | Name | Description | Type | Options | Default | | ||
| :-------: | :------: | :-----------------: | :----: | :----------------------------: | :--------: | | ||
| | endpoint | The endpoint to use | string | [function](#function-endpoint) | `function` | | ||
|
||
## Function Endpoint | ||
|
||
`function` is the only supported name for this endpoint. | ||
|
||
### Input Params | ||
|
||
| Required? | Name | Aliases | Description | Type | Options | Default | Depends On | Not Valid With | | ||
| :-------: | :---------: | :--------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------: | :------: | :-----: | :-----: | :--------: | :------------: | | ||
| ✅ | signature | `function` | Function signature. Should be formatted as [human readable ABI](https://docs.ethers.io/v5/single-page/#/v5/getting-started/-%23-getting-started--contracts) | string | | | | | | ||
| ✅ | address | `contract` | Address of the contract | string | | | | | | ||
| | inputParams | | Array of function parameters in order | string[] | | | | | | ||
| ✅ | network | | RPC network name | string | | | | | | ||
|
||
### Example | ||
|
||
Request: | ||
|
||
```json | ||
{ | ||
"data": { | ||
"endpoint": "function", | ||
"signature": "function latestAnswer() view returns (int256)", | ||
"address": "0x779877A7B0D9E8603169DdbD7836e478b4624789", | ||
"network": "ETHEREUM_GOERLI" | ||
} | ||
} | ||
``` | ||
|
||
--- | ||
|
||
MIT License |
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,41 @@ | ||
{ | ||
"name": "@chainlink/view-function-multi-chain-adapter", | ||
"version": "0.0.0", | ||
"description": "Chainlink view-function-multi-chain adapter.", | ||
"keywords": [ | ||
"Chainlink", | ||
"LINK", | ||
"blockchain", | ||
"oracle", | ||
"view-function-multi-chain" | ||
], | ||
"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.11.68", | ||
"nock": "13.2.9", | ||
"typescript": "5.0.4" | ||
}, | ||
"dependencies": { | ||
"@chainlink/external-adapter-framework": "0.33.4", | ||
"ethers": "^5.4.6", | ||
"tslib": "2.4.1" | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
packages/sources/view-function-multi-chain/src/config/index.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,10 @@ | ||
import { AdapterConfig } from '@chainlink/external-adapter-framework/config' | ||
|
||
export const config = new AdapterConfig({ | ||
BACKGROUND_EXECUTE_MS: { | ||
description: | ||
'The amount of time the background execute should sleep before performing the next request', | ||
type: 'number', | ||
default: 10_000, | ||
}, | ||
}) |
47 changes: 47 additions & 0 deletions
47
packages/sources/view-function-multi-chain/src/endpoint/function.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,47 @@ | ||
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter' | ||
import { InputParameters } from '@chainlink/external-adapter-framework/validation' | ||
import { config } from '../config' | ||
import { multiChainFunctionTransport } from '../transport/function' | ||
|
||
export const inputParameters = new InputParameters({ | ||
signature: { | ||
type: 'string', | ||
aliases: ['function'], | ||
required: true, | ||
description: | ||
'Function signature. Should be formatted as [human readable ABI](https://docs.ethers.io/v5/single-page/#/v5/getting-started/-%23-getting-started--contracts)', | ||
}, | ||
address: { | ||
aliases: ['contract'], | ||
required: true, | ||
description: 'Address of the contract', | ||
type: 'string', | ||
}, | ||
inputParams: { | ||
array: true, | ||
description: 'Array of function parameters in order', | ||
type: 'string', | ||
}, | ||
network: { | ||
required: true, | ||
description: 'RPC network name', | ||
type: 'string', | ||
}, | ||
}) | ||
|
||
export type BaseEndpointTypes = { | ||
Parameters: typeof inputParameters.definition | ||
Response: { | ||
Data: { | ||
result: string | ||
} | ||
Result: string | ||
} | ||
Settings: typeof config.settings | ||
} | ||
|
||
export const endpoint = new AdapterEndpoint({ | ||
name: 'function', | ||
transport: multiChainFunctionTransport, | ||
inputParameters, | ||
}) |
1 change: 1 addition & 0 deletions
1
packages/sources/view-function-multi-chain/src/endpoint/index.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 @@ | ||
export { endpoint as functionEndpoint } from './function' |
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,13 @@ | ||
import { expose, ServerInstance } from '@chainlink/external-adapter-framework' | ||
import { Adapter } from '@chainlink/external-adapter-framework/adapter' | ||
import { config } from './config' | ||
import { functionEndpoint } from './endpoint' | ||
|
||
export const adapter = new Adapter({ | ||
defaultEndpoint: functionEndpoint.name, | ||
name: 'VIEW_FUNCTION_MULTI_CHAIN', | ||
config, | ||
endpoints: [functionEndpoint], | ||
}) | ||
|
||
export const server = (): Promise<ServerInstance | undefined> => expose(adapter) |
110 changes: 110 additions & 0 deletions
110
packages/sources/view-function-multi-chain/src/transport/function.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,110 @@ | ||
import { TransportDependencies } from '@chainlink/external-adapter-framework/transports' | ||
import { AdapterResponse, makeLogger, sleep } from '@chainlink/external-adapter-framework/util' | ||
import { SubscriptionTransport } from '@chainlink/external-adapter-framework/transports/abstract/subscription' | ||
import { EndpointContext } from '@chainlink/external-adapter-framework/adapter' | ||
import { ethers, utils } from 'ethers' | ||
import { BaseEndpointTypes, inputParameters } from '../endpoint/function' | ||
import { AdapterInputError } from '@chainlink/external-adapter-framework/validation/error' | ||
|
||
const logger = makeLogger('View Function Multi Chain') | ||
|
||
export type MultiChainFunctionTransportTypes = BaseEndpointTypes | ||
|
||
type RequestParams = typeof inputParameters.validated | ||
|
||
export class MultiChainFunctionTransport extends SubscriptionTransport<MultiChainFunctionTransportTypes> { | ||
providers: Record<string, ethers.providers.JsonRpcProvider> = {} | ||
|
||
async initialize( | ||
dependencies: TransportDependencies<MultiChainFunctionTransportTypes>, | ||
adapterSettings: MultiChainFunctionTransportTypes['Settings'], | ||
endpointName: string, | ||
transportName: string, | ||
): Promise<void> { | ||
await super.initialize(dependencies, adapterSettings, endpointName, transportName) | ||
} | ||
|
||
async backgroundHandler( | ||
context: EndpointContext<MultiChainFunctionTransportTypes>, | ||
entries: RequestParams[], | ||
) { | ||
await Promise.all(entries.map(async (param) => this.handleRequest(param))) | ||
await sleep(context.adapterSettings.BACKGROUND_EXECUTE_MS) | ||
} | ||
|
||
async handleRequest(param: RequestParams) { | ||
let response: AdapterResponse<MultiChainFunctionTransportTypes['Response']> | ||
try { | ||
response = await this._handleRequest(param) | ||
} catch (e: unknown) { | ||
const errorMessage = e instanceof Error ? e.message : 'Unknown error occurred' | ||
logger.error(e, errorMessage) | ||
response = { | ||
statusCode: (e as AdapterInputError)?.statusCode || 502, | ||
errorMessage, | ||
timestamps: { | ||
providerDataRequestedUnixMs: 0, | ||
providerDataReceivedUnixMs: 0, | ||
providerIndicatedTimeUnixMs: undefined, | ||
}, | ||
} | ||
} | ||
await this.responseCache.write(this.name, [{ params: param, response }]) | ||
} | ||
|
||
async _handleRequest( | ||
param: RequestParams, | ||
): Promise<AdapterResponse<MultiChainFunctionTransportTypes['Response']>> { | ||
const { address, signature, inputParams, network } = param | ||
|
||
const networkName = network.toUpperCase() | ||
const networkEnvName = `${networkName}_RPC_URL` | ||
const chainIdEnvName = `${networkName}_CHAIN_ID` | ||
|
||
const rpcUrl = process.env[networkEnvName] | ||
const chainId = Number(process.env[chainIdEnvName]) | ||
|
||
if (!rpcUrl || isNaN(chainId)) { | ||
throw new AdapterInputError({ | ||
statusCode: 400, | ||
message: `Missing '${networkEnvName}' or '${chainIdEnvName}' environment variables.`, | ||
}) | ||
} | ||
|
||
if (!this.providers[networkName]) { | ||
this.providers[networkName] = new ethers.providers.JsonRpcProvider(rpcUrl, chainId) | ||
} | ||
|
||
const iface = new utils.Interface([signature]) | ||
const fnName = iface.functions[Object.keys(iface.functions)[0]].name | ||
|
||
const encoded = iface.encodeFunctionData(fnName, [...(inputParams || [])]) | ||
|
||
const providerDataRequestedUnixMs = Date.now() | ||
const result = await this.providers[networkName].call({ | ||
to: address, | ||
data: encoded, | ||
}) | ||
|
||
return { | ||
data: { | ||
result, | ||
}, | ||
statusCode: 200, | ||
result, | ||
timestamps: { | ||
providerDataRequestedUnixMs, | ||
providerDataReceivedUnixMs: Date.now(), | ||
providerIndicatedTimeUnixMs: undefined, | ||
}, | ||
} | ||
} | ||
|
||
getSubscriptionTtlFromConfig( | ||
adapterSettings: MultiChainFunctionTransportTypes['Settings'], | ||
): number { | ||
return adapterSettings.WARMUP_SUBSCRIPTION_TTL | ||
} | ||
} | ||
|
||
export const multiChainFunctionTransport = new MultiChainFunctionTransport() |
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,7 @@ | ||
{ | ||
"requests": [{ | ||
"contract": "0x2c1d072e956AFFC0D435Cb7AC38EF18d24d9127c", | ||
"function": "function latestAnswer() view returns (int256)", | ||
"network": "ETHEREUM_MAINNET" | ||
}] | ||
} |
Oops, something went wrong.