Skip to content

Commit d172628

Browse files
committed
WIP-ER
1 parent 4f2f9e4 commit d172628

File tree

3 files changed

+58
-50
lines changed

3 files changed

+58
-50
lines changed

pages/express-relay/index.mdx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ import ContractIcon from "../../components/icons/ContractIcon";
88

99
Express Relay is a priority auction that enables protocols to eliminate maximal extractable value (MEV).
1010

11-
- **For Protocol Developers:** Express Relay’s auction primitive allows your protocol to prioritize access to permissionless operations, eliminating the extractive role of miners in ordering transactions.
12-
A network of established searchers compete in the auctions, allowing you to avoid spending time and energy bootstrapping your own protocol-specific searcher network.
1311

14-
- **For Searchers:** Express Relay aggregates liquidation and other MEV opportunities across integrated DeFi protocols, providing easy and unified access.
12+
13+
- **For Protocol Developers:** Express Relay allows protocols to recapture MEV and access a network of searchers.
14+
With Express Relay, protocols don't need to spend time and energy bootstrapping the protocol-specific searcher network.
15+
16+
- **For Searchers:** Express Relay provides easy and unified access by aggregating liquidation and other MEV opportunities across integrated DeFi protocols.
17+
Searchers integrate once and gain access to all existing and future opportunities.
1518

1619
<Cards>
1720
<Card
@@ -29,3 +32,5 @@ A network of established searchers compete in the auctions, allowing you to avoi
2932
To learn more about Express Relay's design and how it eliminates MEV, please see [How Express Relay Works](/express-relay/how-express-relay-works).
3033

3134
## Useful Links
35+
36+
TODO: Add Useful Links

pages/express-relay/integrate-as-protocol.mdx

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@ import { Callout, Tabs, Steps } from 'nextra/components'
22

33
# How to Integrate Express Relay as a Protocol
44

5-
Defi protocols can **permissionlessly** integrate with Express Relay to recapture MEV and access a network of searchers.
5+
This guide will explain how DeFi protocols can integrate Express Relay.
66

77
Integrating with Express Relay involves two main steps:
88

9-
- Update your defi protocol's contract to **permit** Express Relay transactions.
10-
- Write a script to **expose** opportunities to searchers for auction.
9+
- **Update** your DeFi protocol's contract.
10+
- **Expose** opportunities to searchers for auction.
1111

1212
## Update your defi Protocol's Contract
1313

14-
To integrate with Express Relay, your protocol's contract must permit Express Relay to access opportunities.
14+
To integrate with Express Relay, your protocol's contract must check if Express Relay has permissioned the current transaction.
1515

1616
<Steps>
1717
### Install the Express Relay SDK
1818

19-
Pyth provides a [Solidity SDK](https://www.npmjs.com/package/@pythnetwork/express-relay-sdk-solidity) to help developers integrate Express Relay into their defi protocol.
19+
Pyth provides a [Solidity SDK](https://www.npmjs.com/package/@pythnetwork/express-relay-sdk-solidity) to help developers integrate Express Relay into their DeFi protocol.
2020
The SDK exposes [`IExpressRelay`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelay.sol) and [`IExpressRelayFeeReceiver`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelayFeeReceiver.sol) interfaces to interact with Express Relay.
2121

2222
<Tabs items={['Hardhat', 'Foundry']}>
@@ -47,39 +47,40 @@ Then add the following line to `remappings.txt` file:
4747

4848
The following steps show how to modify your protocol's contract to permit Express Relay transactions and receive funds from Express Relay.
4949

50-
1. Utilize [`isPermissioned`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelay.sol#L10C14-L10C28) method from `IExpressRelay` interface to **permit** Express Relay transactions.
51-
1. Implement the [`IExpressRelayFeeReceiver`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelayFeeReceiver.sol#L4) interface to **receive** funds from Express Relay.
50+
1. Call [`isPermissioned`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelay.sol#L10C14-L10C28) method from `IExpressRelay` interface to **permit** Express Relay transactions.
51+
1. Implement the [`IExpressRelayFeeReceiver`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelayFeeReceiver.sol#L4) interface to **receive** auction proceedings.
5252

5353
#### 1. Permit Express Relay Transactions
5454

5555
The `isPermissioned` function takes two arguments:
56-
1. `protocolFeeReceiver`: The contract address that will receive the protocol fee from the winning searcher after a successful auction.
57-
1. `permissionId`: A unique identifier of a vault or position eligible to expose as an opportunity.
56+
1. `protocolFeeReceiver`: The address to receive the protocol's share of auction proceedings.
57+
1. `permissionId`: A unique identifier for the opportunity.
5858

5959
```solidity copy
6060
import "@pythnetwork/express-relay-sdk-solidity/IExpressRelay.sol";
6161
6262
// Express Relay contract address on Optimism Sepolia
63-
// Check https://docs.pyth.network/express-relay/contract-addresses for the address deployed on other networks
63+
//
64+
// Check https://docs.pyth.network/express-relay/contract-addresses
65+
// for the address deployed on other networks
6466
address expressRelay = 0xD6e417287b875A3932c1Ff5dcB26D4D2C8b90B40;
6567
6668
require(
6769
IExpressRelay(expressRelay).isPermissioned(
6870
protocolFeeReceiver,
6971
permissionId
7072
),
71-
"invalid liquidation"
73+
"not permissioned"
7274
);
7375
```
7476
<Callout type="info" emoji="ℹ️">
75-
The `permissionId` represents unique identifying information for the vault or position within a protocol.
76-
It can be the vault address or the vault ID, concatenated into `bytes` format.
77+
The `permissionId` represents unique identifying information of an opportunity.
78+
For a liquidation opportunity, the vault address or ID could be concatenated into `bytes` format.
7779
Consult [`Permissioning`](./how-express-relay-works/permissioning.mdx) for more information on generating permission IDs.
7880
</Callout>
7981

8082
#### 2. Set up Fee Receiver
81-
82-
After a successful auction, the Express Relay calls the `receiveAuctionProceedings` function present in `IExpressRelayFeeReceiver` to send the portion of the fee paid by the winning searcher to the Protocol's contract
83+
The Express Relay will call the `receiveAuctionProceedings` method present in `IExpressRelayFeeReceiver`. The call will transfer the protocol's share of the auction proceeding to the `protocolFeeReceiver` address.
8384

8485
```solidity copy
8586
interface IExpressRelayFeeReceiver {
@@ -89,7 +90,6 @@ interface IExpressRelayFeeReceiver {
8990
}
9091
```
9192

92-
9393
The following code snippet shows a sample liquidation opportunity via Express Relay.
9494
Note: The highlighted lines show the contract's relevant additions for Express Relay integration.
9595

@@ -163,26 +163,26 @@ contract EasyLend is IExpressRelayFeeReceiver {
163163

164164
## Expose Opportunities to Searchers
165165

166-
Your defi protocol should fetch vaults and positions eligible as opportunites and expose them to Express Relay for auction.
166+
DeFi protocols must fetch opportunities and expose them to Express Relay for auction.
167167

168-
The Express Relay auction server provides a **POST** method, `/v1/opportunities`, which accepts a JSON payload containing the details of the opportunity.
168+
The Express Relay provides a **POST** method, [`/v1/opportunities`](https://per-staging.dourolabs.app/redoc#tag/opportunity/operation/post_opportunity), which accepts a JSON payload containing the details of the opportunity.
169169

170-
The JSON payload should contain liquidation opportunities in the following format:
170+
The JSON payload should contain opportunities in the following format:
171171

172172
```json
173173
{
174-
"target_calldata": "0xdeadbeef", // Calldata to perform liquidation
174+
"target_calldata": "0xdeadbeef", // Calldata to the execute opportunity
175175
"chain_id": "op_sepolia",
176-
"target_contract": "0xcA11bde05977b3631167028862bE2a173976CA11", // Protocol contract address to call for liquidation
177-
"permission_key": "0xcafebabe", // Unique identifier for the liquidation opportunity
176+
"target_contract": "0xcA11bde05977b3631167028862bE2a173976CA11", // Protocol contract address to call for
177+
"permission_key": "0xcafebabe", // Unique identifier for the opportunity
178178
"target_call_value": "1", // Value(in Wei) to send with to the Protocol contract.
179-
"buy_tokens": [ // Tokens to buy (Collateral)
179+
"buy_tokens": [ // Tokens to buy
180180
{
181181
"amount": "1000",
182182
"token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
183183
}
184184
],
185-
"sell_tokens": [ // Tokens to sell (Oustadaing Debt)
185+
"sell_tokens": [ // Tokens to S
186186
{
187187
"amount": "900",
188188
"token": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599"
@@ -196,7 +196,7 @@ The JSON payload should contain liquidation opportunities in the following forma
196196
Each protocol integrated with Express Relay must evaluate every position's health using the latest Oracle prices before exposing them to Express Relay.
197197
You can do this by indexing the chain, listening to protocol events, or querying open positions through an RPC provider.
198198

199-
Check the [`monitor.ts`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/examples/easy_lend/src/monitor.ts) script, which fetches liquidation opportunities for the below-mentioned [Easy Lend](https://github.com/pyth-network/pyth-crosschain/tree/main/express_relay/examples/easy_lend) example and exposes them to Express Relay for auction.
199+
Check the [`monitor.ts`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/examples/easy_lend/src/monitor.ts) script, which fetches opportunities for the below-mentioned [Easy Lend](https://github.com/pyth-network/pyth-crosschain/tree/main/express_relay/examples/easy_lend) example and exposes them to Express Relay for auction.
200200

201201

202202
## Additional Resources

pages/express-relay/integrate-as-searcher.mdx

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ You can fetch historical opportunities by setting the `mode` parameter to `histo
8080

8181
</Tabs.Tab>
8282
<Tabs.Tab>
83-
Searchers can connect to the server via WebSocket to reduce latency and subscribe to various events. The WebSocket endpoint relies at `/v1/ws`(e.g `wss://pyth-express-relay-mainnet.asymmetric.re/v1/ws`)
83+
Searchers can connect to the server via WebSocket to reduce latency and subscribe to various events. The WebSocket endpoint relies at `/v1/ws`(e.g `wss://pyth-express-relay-mainnet.asymmetric.re/v1/ws`).
8484
Here is a sample JSON payload to subscribe to opportunities:
8585

8686
```bash copy
@@ -107,15 +107,13 @@ The server responds with opportunities in the following format:
107107
"target_contract": "0xcA11bde05977b3631167028862bE2a173976CA11", // Protocol contract address to call for execution
108108
"permission_key": "0xcafebabe", // Permission key required for the liquidation opportunity
109109
"target_call_value": "1", // Value(in Wei) to send with to the Protocol contract.
110-
"buy_tokens": [
111-
// Tokens to buy
110+
"buy_tokens": [ // Tokens to buy
112111
{
113112
"amount": "1000",
114113
"token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
115114
}
116115
],
117-
"sell_tokens": [
118-
// Tokens to sell
116+
"sell_tokens": [ // Tokens to sell
119117
{
120118
"amount": "900",
121119
"token": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599"
@@ -132,9 +130,11 @@ The SDKs provide an easy way to construct a bid using the `OpportunityAdapter` c
132130
The `OpportunityAdapter` contract handles asset transfers and ensures the opportunity is executed correctly.
133131

134132
You can learn more about the `OpportunityAdapter` contract and how to prepare your assets in the [Opportunity Adapter](./integrate-as-searcher/opportunity-adapter.mdx) section.
135-
If you have already developed an in-house searcher contract there is no need to integrate using the Opportunity Adapter contract.
136-
You can use our lower level APIs which allows higher flexibility for advanced users.
137-
Please refer to the [custom contracts](./custom-contract) section for more details.
133+
If you have already developed an in-house searcher contract, integrating using the Opportunity Adapter contract is unnecessary.
134+
You can use our lower-level APIs, which allow higher flexibility for advanced users.
135+
Please refer to the [custom contracts](./integrate-as-searcher/custom-contract.mdx) section for more details.
136+
137+
Here is an example of how to construct a bid using the SDKs:
138138

139139
<Tabs items={['Typescript', 'Python']}>
140140
<Tabs.Tab>
@@ -153,32 +153,34 @@ const handleOpportunity = async (opportunity: Opportunity) => {
153153
from datetime import datetime
154154

155155
from express_relay.client import (
156-
ExpressRelayClient,
157-
sign_bid
156+
ExpressRelayClient,
157+
sign_bid
158158
)
159159
from secrets import randbits
160160
from express_relay.express_relay_types import Opportunity, OpportunityBidParams
161161

162162
def opportunity_callback(opportunity: Opportunity):
163-
nonce = randbits(64)
164-
deadline = datetime.utcnow().timestamp() + 60 # bid is valid for a minute
165-
amount = 1000 # This should be determined based on opportunity
166-
private_key = '0x00000'
167-
signed_bid = sign_bid(opportunity,
168-
OpportunityBidParams(amount=amount, deadline=int(deadline), nonce=nonce),
169-
private_key)
170-
163+
nonce = randbits(64)
164+
deadline = datetime.utcnow().timestamp() + 60 # bid is valid for a minute
165+
amount = 1000 # This should be determined based on the opportunity
166+
private_key = '0x00000'
167+
signed_bid = sign_bid(opportunity,
168+
OpportunityBidParams(amount=amount, deadline=int(deadline), nonce=nonce),
169+
private_key)
171170
```
172171
</Tabs.Tab>
173172
</Tabs>
174173

175174
### Submit bids on opportunities to the auction server
176175

177-
Searchers can submit the constructed bids to the auction server via the SDKs, an HTTP POST request, or through a WebSocket connection.
176+
Searchers can submit the constructed bids to the auction server via the SDKs, an HTTP POST request, or a WebSocket connection.
178177

179178
<Tabs items={['Typescript', 'Python', 'HTTP', 'Websocket']}>
180179

181180
<Tabs.Tab>
181+
182+
The code snippet below demonstrates how to submit a bid using the Typescript SDK:
183+
182184
```typescript {4} copy
183185
const handleOpporunity = async (opportunity: Opportunity) => {
184186
...
@@ -189,6 +191,9 @@ const handleOpporunity = async (opportunity: Opportunity) => {
189191

190192
</Tabs.Tab>
191193
<Tabs.Tab>
194+
195+
The code snippet below demonstrates how to submit a bid using the Python SDK:
196+
192197
```python {5} copy
193198
def opportunity_callback(opportunity: Opportunity):
194199
signed_bid = sign_bid(opportunity,
@@ -212,14 +217,12 @@ curl -X POST https://pyth-express-relay-mainnet.asymmetric.re/v1/bids \
212217
}'
213218
```
214219

215-
TODO: Explain the fields here.
216-
217220
</Tabs.Tab>
218221
<Tabs.Tab>
219222

220223
Searchers can submit bids via Websocket to avoid additional network round-trips and get notified about changes to the bid status.
221224

222-
```json copy
225+
```bash copy
223226
{
224227
"id": "1",
225228
"method": "post_bid",

0 commit comments

Comments
 (0)