Repository contains implementation of bETH/USD JSON-RPC Price Feed. Price feed built as Cloudflare's worker.
Worker contains currentPrice
method which returns current bETH price in USD rounded to 8 decimal places.
bETH price calculation based on a next formula: bETHPrice = ethPrice * stETHRate / bETHRate
, where:
ethPrice
- current ETH/USD price retrieved from the Chainlink's ETH/USD feed contractstETHRate
- current stETH/ETH spot price retrieved from the Curve stETH pool contractbETHRate
- current stETH/bETH rate retrieved from the AnchorVault contract. Always greater than or equal 1.
Feed can use multiple Ethereum JSON-RPC nodes to improve fault-tolerance.
Example of request:
curl https://beth-price-feed-staging.psirex.workers.dev \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method": "currentPrice", "id": 1}'
Example of response:
{
"jsonrpc": "2.0",
"id": 1,
"result": "2525.37222247"
}
For the resulting bETH price value (bETHPrice
) and for each value of: ethPrice
, stETHRate
, bETHRate
might be added validations to check that values belong to the allowed range. For each of the above values might be set next validations:
maxValue
- maximum value which might be reachedminValue
- minimum value which might be reachedmaxDeviations
- an array of max deviations in percent. Each element will be compared to element from reference values array at the same index.
Reference values - it's an array of values of bETHPrice
, ethPrice
, stETHRate
and bETHRate
taken from different blocks. The number of such reference values and block numbers where to retrieve values from might be set via ENV variable DEVIATION_BLOCK_OFFSETS
in wrangler.toml file.
DEVIATION_BLOCK_OFFSETS
must contain a valid JSON array of numbers (empty array is allowed).
Example of DEVIATION_BLOCK_OFFSETS
value: [10000, 1000, 100]
- use three points as reference values, with block numbers: [currentBlockNumber - 10000, currentBlockNumber - 1000, currentBlockNumber - 100]
.
Validations for values bETHPrice
, ethPrice
, stETHRate
and bETHRate
might be set via next corresponding ENV variables in wrangler.toml file:
BETH_RATE_LIMITS
BETH_PRICE_LIMITS
STETH_RATE_LIMITS
ETH_PRICE_LIMITS
Each of these variables must contain a valid JSON string of next type:
{
maxValue?: number | string;
minValue?: number | string;
maxDeviations: (number | string)[];
}
Example of declaration of validations for BETH_PRICE_LIMITS
in wrangler.toml file:
BETH_PRICE_LIMITS = '{"maxValue":3100,"minValue":"3000","deviations":[20.5,15,5]}'
which requires that the value bETHPrice
variable contains in the range [3000,3100], and deviation from reference blocks less than 20.5 % for value with zero index, 15 with index equal to one, and 5 % with index three.
When some validation of price safety fails, an error will be returned instead of a default response.
Example of response with an error when bETHPrice
's max value validation failed:
{
"jsonrpc": "2.0",
"id": null,
"error": {
"message": "Unsafe Price: value of \"bEthPrice\" too high",
"code": -40001,
"data": {
"maxValue": "3100",
"currentValue": "3324.64747392728265104149"
}
}
}
Example of response with an error when bETHPrice
's min value validation failed:
{
"jsonrpc": "2.0",
"id": null,
"error": {
"message": "Unsafe Price: value of \"bEthPrice\" too low",
"code": -40002,
"data": {
"minValue": "3400",
"currentValue": "3324.8884429858988432267"
}
}
}
Example of response with an error when bETHPrice
's max deviation validation failed:
{
"jsonrpc": "2.0",
"id": null,
"error": {
"message": "Unsafe Price: Max deviation of \"bEthPrice\" exceeded",
"code": -40003,
"data": {
"maxDeviation": "2",
"currentDeviation": "4.278974120495502111",
"currentValue": {
"block": 13082521,
"value": "3324.64747392728265104149"
},
"referenceValue": {
"block": 13076121,
"value": "3182.38666892022678037954"
}
}
}
}
Requirements:
node.js >= 12
@cloudflare/wrangler >= 1.17
- Sign up for a Cloudflare Workers account.
- Install the Workers CLI:
npm install -g @cloudflare/wrangler
- Login to Wrangler account:
wrangler login
(If the login command get stuck on login, see instructions in this comment to fix the issue: cloudflare/wrangler-legacy#1703 (comment)) - Run command
wrangler whoami
to check that login was succeed. - Fill
account_id
inwrangler.toml
with youraccount ID
value.
Navigate to root directory of the project and run npm install
command
-
Run
wrangler build
to add encrypted env variables. -
Run
wrangler secret put ETH_RPCS --env ENVIRONMENT_NAME
command to set list of Ethereum JSON-RPC URLs. Example of variable format:["https://eth-mainnet.alchemyapi.io/v2/foo","https://mainnet.infura.io/v3/baz"]
.--env
might be one ofstaging
,production
. If omitted would be used development environment. -
Fill values
SENTRY_PORJECT_ID
andSENTRY_KEY
inwrangler.toml
file to activate errors reporting via Sentry. This variables might be get from from the "DSN". The "DSN" will be in the form:https://<SENTRY_KEY>@sentry.io/<SENTRY_PROJECT_ID>
. DSN might be found in the Sentry project settings. -
Fill
zone_id
androute
to publishstaging
/production
builds. See deployment instructions for more details. This step might be skipped if only local development supposed.
Run npm run build
command to build the current version of bETH price feed.
To start a local server for developing your worker run wrangler dev
.
To deploy build run wrangler publish --env ENVIRONMENT_NAME
, where ENVIRONMENT_NAME
one of staging
, production
To make it easier to publish the worker:
- copy
sample.env
to.env
, change the values - fill all described above config settings in
wrangler.toml
- to publish in staging environment - run the
./publish.sh
script without params - run
./publish.sh production
script to publish in production
To run tests:
- Run local Ethereum RPC node on address:
http://127.0.0.1:8545/
. For example:npx hardhat node
. - In other console run command:
npm run test