Skip to content

Commit

Permalink
Metis support for the Layer2 Sequencer Health EA (#1913)
Browse files Browse the repository at this point in the history
* add support to track metis health

* remove unused code in l2 sequencer health EA

* address PR feedback

* force pipeline
  • Loading branch information
cds95 authored Jun 3, 2022
1 parent 125badb commit f805344
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .changeset/curly-lions-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@chainlink/layer2-sequencer-health-adapter': minor
---

add support for metis to layer2-sequencer-health EA
22 changes: 14 additions & 8 deletions packages/sources/layer2-sequencer-health/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@ Adapter that checks the Layer 2 Sequencer status
| | `ARBITRUM_HEALTH_ENDPOINT` | Arbitrum Health Endpoint | | |
| | `OPTIMISM_RPC_ENDPOINT` | Optimism RPC Endpoint | | https://mainnet.optimism.io |
| | `OPTIMISM_HEALTH_ENDPOINT` | Optimism Health Endpoint | | https://mainnet-sequencer.optimism.io/health |
| | `METIS_RPC_ENDPOINT` | Metis RPC Endpoint | | https://andromeda.metis.io/?owner=1088 |
| | `METIS_HEALTH_ENDPOINT` | Metis Health Endpoint | | https://tokenapi.metis.io/andromeda/health |

For the adapter to be useful on the desired network, at least one endpoint (RPC or HEALTH) needs to provided

---

### Input Parameters

| Required? | Name | Description | Options | Defaults to |
| :-------: | :-----: | :----------------------: | :------------------: | :---------: |
|| network | Layer 2 Network to check | arbitrum or optimism | |
| Required? | Name | Description | Options | Defaults to |
| :-------: | :-----: | :----------------------: | :-----------------------------: | :---------: |
|| network | Layer 2 Network to check | `arbitrum`, `optimism`, `metis` | |

---

Expand All @@ -39,13 +41,17 @@ For the adapter to be useful on the desired network, at least one endpoint (RPC

### Sample Output

0 = Sequencer is healthy
1 = Sequencer is unhealthy

```json
{
"jobRunID": "278c97ffadb54a5bbb93cfec5f7b5503",
"jobRunID": "1",
"result": 0,
"statusCode": 200,
"data": {
"result": true,
"isHealthy": true
},
"statusCode": 200
"isHealthy": true,
"result": 0
}
}
```
8 changes: 8 additions & 0 deletions packages/sources/layer2-sequencer-health/schemas/env.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
"OPTIMISM_HEALTH_ENDPOINT": {
"type": "string",
"default": "https://mainnet-sequencer.optimism.io/health"
},
"METIS_RPC_ENDPOINT": {
"type": "string",
"default": "https://andromeda.metis.io/?owner=1088"
},
"METIS_HEALTH_ENDPOINT": {
"type": "string",
"default": "https://tokenapi.metis.io/andromeda/health"
}
},
"allOf": [
Expand Down
9 changes: 9 additions & 0 deletions packages/sources/layer2-sequencer-health/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,21 @@ export const DEFAULT_TIMEOUT_LIMIT = 5 * 1000
export enum Networks {
Arbitrum = 'arbitrum',
Optimism = 'optimism',
Metis = 'metis',
}

const DEFAULT_ARBITRUM_RPC_ENDPOINT = 'https://arb1.arbitrum.io/rpc'
const DEFAULT_OPTIMISM_RPC_ENDPOINT = 'https://mainnet.optimism.io'
const DEFAULT_METIS_RPC_ENDPOINT = 'https://andromeda.metis.io/?owner=1088'

export const RPC_ENDPOINTS = {
[Networks.Arbitrum]: util.getEnv('ARBITRUM_RPC_ENDPOINT') || DEFAULT_ARBITRUM_RPC_ENDPOINT,
[Networks.Optimism]: util.getEnv('OPTIMISM_RPC_ENDPOINT') || DEFAULT_OPTIMISM_RPC_ENDPOINT,
[Networks.Metis]: util.getEnv('METIS_RPC_ENDPOINT') || DEFAULT_METIS_RPC_ENDPOINT,
}

const DEFAULT_OPTIMISM_HEALTH_ENDPOINT = 'https://mainnet-sequencer.optimism.io/health'
const DEFAULT_METIS_HEALTH_ENDPOINT = 'https://tokenapi.metis.io/andromeda/health'
export const HEALTH_ENDPOINTS = {
[Networks.Arbitrum]: {
endpoint: util.getEnv('ARBITRUM_HEALTH_ENDPOINT'),
Expand All @@ -37,6 +42,10 @@ export const HEALTH_ENDPOINTS = {
endpoint: util.getEnv('OPTIMISM_HEALTH_ENDPOINT') || DEFAULT_OPTIMISM_HEALTH_ENDPOINT,
responsePath: ['healthy'],
},
[Networks.Metis]: {
endpoint: util.getEnv('METIS_HEALTH_ENDPOINT') || DEFAULT_METIS_HEALTH_ENDPOINT,
responsePath: ['healthy'],
},
}

export interface ExtendedConfig extends Config {
Expand Down
19 changes: 8 additions & 11 deletions packages/sources/layer2-sequencer-health/src/endpoint/health.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { ExtendedConfig, Networks } from '../config'
import {
requestBlockHeight,
getSequencerHealth,
// getL1RollupStatus,
NetworkHealthCheck,
getStatusByTransaction,
} from '../network'
Expand Down Expand Up @@ -60,6 +59,7 @@ export const makeNetworkStatusCheck = (
const networks: Record<Networks, (delta: number, deltaBlocks: number) => Promise<boolean>> = {
[Networks.Arbitrum]: makeNetworkStatusCheck(Networks.Arbitrum),
[Networks.Optimism]: makeNetworkStatusCheck(Networks.Optimism),
[Networks.Metis]: makeNetworkStatusCheck(Networks.Metis),
}

export const getL2NetworkStatus: NetworkHealthCheck = (
Expand All @@ -86,17 +86,19 @@ export const execute: ExecuteWithConfig<ExtendedConfig> = async (request, _, con
return isHealthy ? 0 : 1
}

const _respond = (isHealthy: boolean) =>
Requester.success(
const _respond = (isHealthy: boolean) => {
const result = _translateIntoFeedResponse(isHealthy)
return Requester.success(
jobRunID,
{
data: {
isHealthy: _translateIntoFeedResponse(isHealthy),
result: _translateIntoFeedResponse(isHealthy),
isHealthy: result === 0,
result,
},
},
config.verbose,
)
}

const _tryMethod =
(fn: NetworkHealthCheck) =>
Expand All @@ -120,14 +122,9 @@ export const execute: ExecuteWithConfig<ExtendedConfig> = async (request, _, con

// #1 Option: Direct check on health endpoint
// #2 Option: Check block height
// #3 Option: Check L1 Rollup Contract
// If every method succeeds, the Network is considered healthy
// If any method fails, an empty tx is sent. This determines the final state
const wrappedMethods = [
getSequencerHealth,
getL2NetworkStatus,
// , getL1RollupStatus // TODO
].map(_tryMethod)
const wrappedMethods = [getSequencerHealth, getL2NetworkStatus].map(_tryMethod)
for (let i = 0; i < wrappedMethods.length; i++) {
const method = wrappedMethods[i]
const isHealthy = await method(network, config.delta, config.deltaBlocks)
Expand Down
8 changes: 8 additions & 0 deletions packages/sources/layer2-sequencer-health/src/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const getStatusByTransaction = async (
[Networks.Arbitrum]: ['gas price too low', 'forbidden sender address'],
// TODO: Optimism error needs to be confirmed by their team
[Networks.Optimism]: ['cannot accept 0 gas price transaction'],
[Networks.Metis]: ['cannot accept 0 gas price transaction'],
}

const networkTx: Record<Networks, ethers.providers.TransactionRequest> = {
Expand All @@ -88,11 +89,18 @@ export const getStatusByTransaction = async (
gasPrice: 0,
to: wallet.address,
},
[Networks.Metis]: {
value: 0,
gasLimit: 0,
gasPrice: 0,
to: wallet.address,
},
}
const _getErrorMessage = (e: Record<string, unknown>): string => {
const paths = {
[Networks.Arbitrum]: ['error', 'message'],
[Networks.Optimism]: ['error', 'message'],
[Networks.Metis]: ['error', 'message'],
}
return (Requester.getResult(e, paths[network]) as string) || ''
}
Expand Down

0 comments on commit f805344

Please sign in to comment.