|
| 1 | +--- |
| 2 | +title: OEV Gateway (optional) |
| 3 | +docSetName: Airnode v0.11 |
| 4 | +folder: API Providers > Build an Airnode |
| 5 | +basePath: /airnode/v0.11 |
| 6 | +tags: |
| 7 | +--- |
| 8 | + |
| 9 | +<TitleSpan>{{$frontmatter.folder}}</TitleSpan> |
| 10 | + |
| 11 | +# {{$frontmatter.title}} |
| 12 | + |
| 13 | +<VersionWarning/> |
| 14 | + |
| 15 | +<TocHeader /> |
| 16 | +<TOC class="table-of-contents" :include-level="[2,3]" /> |
| 17 | + |
| 18 | +OEV gateway is used in the OEV flow to sign the data won in the auction. The |
| 19 | +data is signed by the Airnode so that only the searcher who won the auction can |
| 20 | +use it to update the data feed. |
| 21 | + |
| 22 | +## Setup |
| 23 | + |
| 24 | +Enable the gateway in the `config.json` file via `nodeSettings.oevGateway` |
| 25 | +section. |
| 26 | + |
| 27 | +- **enabled**: A boolean to enable/disable for the gateway. |
| 28 | +- **maxConcurrency**: (optional) A number higher than zero that represents the |
| 29 | + maximum number of serverless functions serving gateway requests. When omitted, |
| 30 | + there is no maximum concurrency set. This field is ignored for Airnode client |
| 31 | + gateways. |
| 32 | +- **corsOrigins**: A list of allowed origins, `['*']` to allow all origins or an |
| 33 | + empty array to disable CORS. |
| 34 | + |
| 35 | +```json |
| 36 | +"nodeSettings": { |
| 37 | + "cloudProvider": { |
| 38 | + "type": "aws", |
| 39 | + "region": "us-east-1" |
| 40 | + }, |
| 41 | + "airnodeWalletMnemonic": "${AIRNODE_WALLET_MNEMONIC}", |
| 42 | + "heartbeat": {...}, |
| 43 | + "oevGateway": { |
| 44 | + "enabled": true, |
| 45 | + "maxConcurrency": 20, |
| 46 | + "corsOrigins": [] |
| 47 | + }, |
| 48 | + ... |
| 49 | +}, |
| 50 | +``` |
| 51 | + |
| 52 | +## Gateway URL |
| 53 | + |
| 54 | +The gateway implementation is different depending on how Airnode is deployed. |
| 55 | +When deployed on a cloud provider, the serverless gateway is used. Inside |
| 56 | +Airnode client, the gateway is implemented via a simple web server inside the |
| 57 | +docker container. There are subtle differences in both how the gateways work and |
| 58 | +what the gateway URLs look like. |
| 59 | + |
| 60 | +The deployer generates a secret `UUID` path parameter which ensures that the |
| 61 | +endpoints are not openly accessible. Therefore, the gateway URL should be kept |
| 62 | +secret. |
| 63 | + |
| 64 | +The gateway URL is also available as part of the payload sent from Airnode's |
| 65 | +[heartbeat](./heartbeat.md) to your specified heartbeat URL. |
| 66 | + |
| 67 | +### When deployed on a cloud provider |
| 68 | + |
| 69 | +A gateway URL is generated when Airnode is deployed. You can see the URLs |
| 70 | +including the secret `UUID` path parameter, displayed on your terminal at the |
| 71 | +end of an Airnode deployment using a [Docker image](../../docker/). |
| 72 | + |
| 73 | +### When using Airnode client |
| 74 | + |
| 75 | +Airnode client can be used to run Airnode as a docker container locally. There |
| 76 | +is a common web server for the gateway, which is exposed on the host machine. |
| 77 | +Doing so will make the gateway API accessible like a regular web server running |
| 78 | +on the machine. Note the `PORT` which is exposed as part of the Airnode client |
| 79 | +container. See the [Airnode client usage](../../docker/client-image.md#usage) |
| 80 | +for more details. |
| 81 | + |
| 82 | +- `http://localhost:<PORT>/sign-oev/01234567-abcd-abcd-abcd-012345678abc` - |
| 83 | + Gateway URL for the OEV Gateway |
| 84 | + |
| 85 | +## Usage |
| 86 | + |
| 87 | +In order to execute the processing on the gateway, it needs to receive a |
| 88 | +properly constructed HTTP request: |
| 89 | + |
| 90 | +- It must be a `POST` request |
| 91 | +- It must contain a `Content-Type` header, set to `application/json`. |
| 92 | +- It must contain the following JSON body: |
| 93 | + |
| 94 | +```json |
| 95 | +{ |
| 96 | + "chainId": <CHAIN_ID>, |
| 97 | + "dapiServerAddress": <DAPI_SERVER_ADDRESS>, |
| 98 | + "oevProxyAddress": <OEV_PROXY_ADDRESS>, |
| 99 | + "updateId": <UPDATE_ID>, |
| 100 | + "bidderAddress": <BIDDER_ADDRESS>, |
| 101 | + "bidAmount": <BID_AMOUNT>, |
| 102 | + "signedData": [ |
| 103 | + { |
| 104 | + "airnodeAddress": <AIRNODE_ADDRESS>, |
| 105 | + "endpointId": <EDNPOINT_ID>, |
| 106 | + "encodedParameters": <ENCODED_PARAMETERS>, |
| 107 | + "timestamp": <TIMESTAMP>, |
| 108 | + "encodedValue": <ENCODED_VALUE>, |
| 109 | + "signature": <SIGNATURE> |
| 110 | + }, |
| 111 | + { |
| 112 | + "airnodeAddress": <AIRNODE_ADDRESS>, |
| 113 | + "endpointId": <EDNPOINT_ID>, |
| 114 | + "encodedParameters": <ENCODED_PARAMETERS> |
| 115 | + }, |
| 116 | + ... |
| 117 | + ] |
| 118 | +} |
| 119 | +``` |
| 120 | + |
| 121 | +where: |
| 122 | + |
| 123 | +- `chainId` - ID of the blockchain where the auction was held. |
| 124 | +- `dapiServerAddress` - Blockchain address of the dAPI server contract. |
| 125 | +- `oevProxyAddress` - Blockchain address of the proxy data feed contract. |
| 126 | +- `updateId` - Auction update ID. |
| 127 | +- `bidderAddress` - Blockchain address of the winning searcher. |
| 128 | +- `bidAmount` - Bid amount that won the auction. |
| 129 | +- `signedData` - A list of beacon data to be signed. It can contain two types: |
| 130 | + full beacon data, only beacon metadata |
| 131 | + - `airnodeAddress` - Airnode address identifying a beacon |
| 132 | + - `endpointId` - Endpoint ID identifying a beacon |
| 133 | + - `encodedParameters` - Parameters in their encoded form identifying a beacon |
| 134 | + - `timestamp` - UNIX timestamp of the beacon data |
| 135 | + - `encodedValue` - Beacon value in its encoded form |
| 136 | + - `signature` - Signature of the beacon data |
| 137 | + |
| 138 | +### Example request |
| 139 | + |
| 140 | +```sh |
| 141 | +curl \ |
| 142 | +-X POST \ |
| 143 | +-H 'Content-Type: application/json' \ |
| 144 | +-d '{"chainId":1,"dapiServerAddress":"0x...","oevProxyAddress":"0x...","updateId":"0x...","bidderAddress":"0x...","bidAmount":"0x...","signedData":[{"airnodeAddress":"0x...","endpointId":"0x...","encodedParameters":"0x...","timestamp":"16...","encodedValue":"0x...","signature":"0x..."},{"airnodeAddress":"0x...","endpointId":"0x...","encodedParameters":"0x..."}]}' \ |
| 145 | +'<gatewayUrl>' |
| 146 | +``` |
| 147 | + |
| 148 | +### Example response |
| 149 | + |
| 150 | +```json |
| 151 | +[ |
| 152 | + { |
| 153 | + "timestamp": "16...", |
| 154 | + "encodedValue": "0x...", |
| 155 | + "signature": "0x..." |
| 156 | + }, |
| 157 | + { |
| 158 | + "timestamp": "16...", |
| 159 | + "encodedValue": "0x...", |
| 160 | + "signature": "0x..." |
| 161 | + } |
| 162 | +] |
| 163 | +``` |
| 164 | + |
| 165 | +The gateway will return a list of signed beacon data, signing for each beacon |
| 166 | +within the data feed that is served by the given Airnode. There are two elements |
| 167 | +that are signed: template ID of the beacon and the OEV update hash, uniqly |
| 168 | +identifying given OEV update. |
| 169 | + |
| 170 | +- `timestamp` - UNIX timestamp of the signature |
| 171 | +- `encodedValue` - Encoded OEV update value |
| 172 | +- `signature` - Signature of the OEV update by Airnode |
0 commit comments