diff --git a/components/AddressSvmTable.tsx b/components/AddressSvmTable.tsx new file mode 100644 index 00000000..68d29434 --- /dev/null +++ b/components/AddressSvmTable.tsx @@ -0,0 +1,50 @@ +import { StyledTd } from "./Table"; + +const AddressSvmTable = ({ + entries, + explorer, +}: { + entries: { name: string; value: string; link?: boolean }[]; + explorer: string; +}) => { + return ( + + + {entries.map(({ name, value, link }) => { + const component = ( + + {value} + + ); + const addLink = explorer.includes("$ADDRESS") && link; + return ( + + {name} + + {addLink ? ( + + {component} + + ) : ( + component + )} + + + ); + })} + +
+ ); +}; + +export default AddressSvmTable; diff --git a/pages/express-relay/_meta.json b/pages/express-relay/_meta.json index d6c15e48..cb3ab5d1 100644 --- a/pages/express-relay/_meta.json +++ b/pages/express-relay/_meta.json @@ -33,7 +33,7 @@ "errors": "Error Codes", "examples": { "title": "Example Application ↗", - "href": "https://github.com/pyth-network/pyth-examples/tree/main/express-relay/easy_lend", + "href": "https://github.com/pyth-network/pyth-examples/tree/6cea7c9602c7949c6dacc94aec44c0fe78ccb128/express-relay/easy_lend", "newWindow": true }, "-- Understand Express Relay": { diff --git a/pages/express-relay/contract-addresses.mdx b/pages/express-relay/contract-addresses.mdx index c2eeb634..7ff03495 100644 --- a/pages/express-relay/contract-addresses.mdx +++ b/pages/express-relay/contract-addresses.mdx @@ -1,138 +1,6 @@ -import { Tabs } from "nextra/components"; -import AddressTable from "../../components/AddressTable"; +# Contract Addresses -Express Relay is currently deployed on the following networks: +This section covers the contract addresses for Express Relay on different networks. Please navigate to the relevant section below. - - - -Auction Server endpoint: https://pyth-express-relay-mainnet.asymmetric.re/ - -### Mode - -**Network Details:** - - - -This list contains the addresses of the commonly used assets present in opportunities on the Mode network: - - - - - -Auction Server endpoint: https://per-staging.dourolabs.app/ - -### Optimism Sepolia - -**Network Details:** - - - -This list contains the addresses of the commonly used assets present in opportunities on the Optimism Sepolia network: - - - - - +- [EVM](contract-addresses/evm) +- [SVM](contract-addresses/svm) diff --git a/pages/express-relay/contract-addresses/_meta.json b/pages/express-relay/contract-addresses/_meta.json new file mode 100644 index 00000000..882eb292 --- /dev/null +++ b/pages/express-relay/contract-addresses/_meta.json @@ -0,0 +1,4 @@ +{ + "evm": "EVM", + "svm": "SVM" +} diff --git a/pages/express-relay/contract-addresses/evm.mdx b/pages/express-relay/contract-addresses/evm.mdx new file mode 100644 index 00000000..d4626b0b --- /dev/null +++ b/pages/express-relay/contract-addresses/evm.mdx @@ -0,0 +1,138 @@ +import { Tabs } from "nextra/components"; +import AddressTable from "../../../components/AddressTable"; + +Express Relay is currently deployed on the following EVM networks: + + + + +Auction Server endpoint: https://pyth-express-relay-mainnet.asymmetric.re/ + +### Mode + +**Network Details:** + + + +This list contains the addresses of the commonly used assets present in opportunities on the Mode network: + + + + + +Auction Server endpoint: https://per-staging.dourolabs.app/ + +### Optimism Sepolia + +**Network Details:** + + + +This list contains the addresses of the commonly used assets present in opportunities on the Optimism Sepolia network: + + + + + diff --git a/pages/express-relay/contract-addresses/svm.mdx b/pages/express-relay/contract-addresses/svm.mdx new file mode 100644 index 00000000..10437213 --- /dev/null +++ b/pages/express-relay/contract-addresses/svm.mdx @@ -0,0 +1,76 @@ +import { Tabs, Callout } from "nextra/components"; +import AddressSvmTable from "../../../components/AddressSvmTable"; + +Express Relay is currently deployed on the following SVM environments: + + + + + To simulate real performance conditions and activity, the staging/testing + environment for Solana is on the mainnet-beta network. This environment is not + for production use and should only be used for testing. + + + +Auction Server endpoint: https://per-staging.dourolabs.app/ + +### Solana + +**Network Details:** + + + +This list contains the addresses of the commonly used assets present in opportunities on `development-solana`: + + + + + diff --git a/pages/express-relay/errors.mdx b/pages/express-relay/errors.mdx index c85bb60b..ba1a420c 100644 --- a/pages/express-relay/errors.mdx +++ b/pages/express-relay/errors.mdx @@ -1,33 +1,6 @@ # Error Codes -The following table lists the error codes and their explanations for [`ExpressRelay`](https://github.com/pyth-network/per/blob/main/contracts/src/express-relay/ExpressRelay.sol) and [`OpportunityAdapter`](https://github.com/pyth-network/per/blob/main/contracts/src/opportunity-adapter/OpportunityAdapter.sol) contracts. -They can be used to identify the cause of a failed transaction or bid. +This section covers error codes one may run into during integration. Please see the relevant section below for the environment of interest. -## ExpressRelay - -| Error | Selector | Explanation | -| -------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------- | -| `Unauthorized()` | `0x82b42900` | This function is called by an unauthorized party. | -| `InvalidMagicValue()` | `0x4ed848c1` | An upgrade was attempted to a contract that does not match the ExpressRelay specification. | -| `InvalidPermission()` | `0x868a64de` | The provided permissionKey is invalid (too short). | -| `InvalidFeeSplit()` | `0x0601f697` | The proposed fee split is invalid (fee is larger than feePrecision, 10\*\*18). | -| `InvalidTargetContract()` | `0x5569851a` | The provided target contract is not allowed. (e.g. can not call the ExpressRelay contract). | -| `DuplicateRelayerSubwallet()` | `0xb40d37c3` | The provided subwallet to add has already been added. | -| `RelayerSubwalletNotFound()` | `0xac4d92b3` | The provided subwallet to delete does not exist in the store. | -| `ExternalCallFailed(MulticallStatus status)` | `0x740d0306` | The external call failed with the following MulticallStatus output. | - -## OpportunityAdapter - -| Error | Selector | Explanation | -| -------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------- | -| `NotCalledByExpressRelay()` | `0xd5668c88` | The OpportunityAdapterFactory contract was not called by the ExpressRelay contract. | -| `NotCalledByFactory()` | `0xb02436cc` | The OpportunityAdapter contract was not called by the OpportunityAdapterFactory contract. | -| `AdapterOwnerMismatch()` | `0x446f3eeb` | The provided executor field does not match the owner of the called OpportunityAdapter contract. | -| `InsufficientTokenReceived()` | `0x4af147aa` | The specified buyTokens were not received after calling the target contract. | -| `InsufficientEthToSettleBid()` | `0x9caaa1d7` | The contract did not receive enough ETH to pay the specified bid. | -| `InsufficientWethForTargetCallValue()` | `0x5e520cd4` | The contract did not receive enough Wrapped ETH to pay the targetCallValue to the targetContract. | -| `TargetCallFailed(bytes returnData)` | `0xa932c97a` | The call to targetContract failed with the specified returnData. | -| `DuplicateToken()` | `0x464e3f6a` | There is a duplicate token in either the sellTokens or buyTokens. | -| `EthOrWethBalanceDecreased()` | `0x1979776d` | The ETH or WETH balance of the contract decreased as a result of the call to targetContract and the bid payment. | -| `TargetContractNotAllowed()` | `0x9c86e59e` | The provided targetContract is not allowed. (e.g. can not call the Permit2 contract). | -| `OnlyOwnerCanCall()` | `0x47a8ea58` | Only the owner of the contract can call this method. | +- [EVM](errors/evm) +- [SVM](errors/svm) diff --git a/pages/express-relay/errors/_meta.json b/pages/express-relay/errors/_meta.json new file mode 100644 index 00000000..882eb292 --- /dev/null +++ b/pages/express-relay/errors/_meta.json @@ -0,0 +1,4 @@ +{ + "evm": "EVM", + "svm": "SVM" +} diff --git a/pages/express-relay/errors/evm.mdx b/pages/express-relay/errors/evm.mdx new file mode 100644 index 00000000..eb4a944b --- /dev/null +++ b/pages/express-relay/errors/evm.mdx @@ -0,0 +1,33 @@ +# EVM Error Codes + +The following table lists the error codes and their explanations for [`ExpressRelay`](https://github.com/pyth-network/per/blob/fccac65b00cff1cfe5c278b333a582fe66bda0f8/contracts/evm/src/express-relay/ExpressRelay.sol) and [`OpportunityAdapter`](https://github.com/pyth-network/per/blob/fccac65b00cff1cfe5c278b333a582fe66bda0f8/contracts/evm/src/opportunity-adapter/OpportunityAdapter.sol) contracts. +They can be used to identify the cause of a failed transaction or bid. + +## ExpressRelay + +| Error | Selector | Explanation | +| -------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------- | +| `Unauthorized()` | `0x82b42900` | This function is called by an unauthorized party. | +| `InvalidMagicValue()` | `0x4ed848c1` | An upgrade was attempted to a contract that does not match the ExpressRelay specification. | +| `InvalidPermission()` | `0x868a64de` | The provided permissionKey is invalid (too short). | +| `InvalidFeeSplit()` | `0x0601f697` | The proposed fee split is invalid (fee is larger than feePrecision, 10\*\*18). | +| `InvalidTargetContract()` | `0x5569851a` | The provided target contract is not allowed. (e.g. can not call the ExpressRelay contract). | +| `DuplicateRelayerSubwallet()` | `0xb40d37c3` | The provided subwallet to add has already been added. | +| `RelayerSubwalletNotFound()` | `0xac4d92b3` | The provided subwallet to delete does not exist in the store. | +| `ExternalCallFailed(MulticallStatus status)` | `0x740d0306` | The external call failed with the following MulticallStatus output. | + +## OpportunityAdapter + +| Error | Selector | Explanation | +| -------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------- | +| `NotCalledByExpressRelay()` | `0xd5668c88` | The OpportunityAdapterFactory contract was not called by the ExpressRelay contract. | +| `NotCalledByFactory()` | `0xb02436cc` | The OpportunityAdapter contract was not called by the OpportunityAdapterFactory contract. | +| `AdapterOwnerMismatch()` | `0x446f3eeb` | The provided executor field does not match the owner of the called OpportunityAdapter contract. | +| `InsufficientTokenReceived()` | `0x4af147aa` | The specified buyTokens were not received after calling the target contract. | +| `InsufficientEthToSettleBid()` | `0x9caaa1d7` | The contract did not receive enough ETH to pay the specified bid. | +| `InsufficientWethForTargetCallValue()` | `0x5e520cd4` | The contract did not receive enough Wrapped ETH to pay the targetCallValue to the targetContract. | +| `TargetCallFailed(bytes returnData)` | `0xa932c97a` | The call to targetContract failed with the specified returnData. | +| `DuplicateToken()` | `0x464e3f6a` | There is a duplicate token in either the sellTokens or buyTokens. | +| `EthOrWethBalanceDecreased()` | `0x1979776d` | The ETH or WETH balance of the contract decreased as a result of the call to targetContract and the bid payment. | +| `TargetContractNotAllowed()` | `0x9c86e59e` | The provided targetContract is not allowed. (e.g. can not call the Permit2 contract). | +| `OnlyOwnerCanCall()` | `0x47a8ea58` | Only the owner of the contract can call this method. | diff --git a/pages/express-relay/errors/svm.mdx b/pages/express-relay/errors/svm.mdx new file mode 100644 index 00000000..950eb25f --- /dev/null +++ b/pages/express-relay/errors/svm.mdx @@ -0,0 +1,17 @@ +# SVM Error Codes + +The following table lists the error codes and their explanations for the [`ExpressRelay`](https://github.com/pyth-network/per/tree/fccac65b00cff1cfe5c278b333a582fe66bda0f8/contracts/svm/programs/express_relay) programs. +They can be used to identify the cause of a failed transaction or bid. + +## ExpressRelay + +| Error | Explanation | +| ----------------------------- | ------------------------------------------------------------------------------------------- | +| `FeeSplitLargerThanPrecision` | The proposed fee split is invalid (split is larger than `FEE_SPLIT_PRECISION`, 10000) | +| `FeesHigherThanBid` | The fees to pay out exceed the value of the bid amount. | +| `DeadlinePassed` | The bid is no longer valid, as the Unix time deadline has passed. | +| `InvalidCPISubmitBid` | The `SubmitBid` instruction should not be called via CPI. | +| `MissingPermission` | The transaction is missing a `SubmitBid` instruction with the matching permission key. | +| `MultiplePermissions` | The transaction should not contain more than one `SubmitBid` instruction. | +| `InsufficientSearcherFunds` | The searcher lacks the funds to pay the specified bid amount. | +| `InsufficientRent` | The fees splits received by different parties must be sufficient to cover the account rent. | diff --git a/pages/express-relay/how-express-relay-works/auction.mdx b/pages/express-relay/how-express-relay-works/auction.mdx index bf81f6fc..6084f582 100644 --- a/pages/express-relay/how-express-relay-works/auction.mdx +++ b/pages/express-relay/how-express-relay-works/auction.mdx @@ -6,7 +6,7 @@ A relayer selected by governance serves as the auctioneer and determines the auc Thus, the Express Relay auction is analogous to a sealed-bid auction, i.e., participants in the auction will not have the contents of their bid disclosed publicly unless they win the auction and are forwarded on-chain. -The forwarded subset of transactions is submitted on-chain and first processed by the [`ExpressRelay`](https://github.com/pyth-network/per/blob/main/contracts/src/express-relay/ExpressRelay.sol) contract before individual searchers' submissions are routed to their corresponding `targetContract`s. +The forwarded subset of transactions is submitted on-chain and first processed by the [`ExpressRelay`](https://github.com/pyth-network/per/blob/fccac65b00cff1cfe5c278b333a582fe66bda0f8/contracts/evm/src/express-relay/ExpressRelay.sol) contract before individual searchers' submissions are routed to their corresponding `targetContract`s. Generally, the auction server expects bids to execute successfully on-chain. Falback bids are also forwarded in case of execution failures for the predicted winners. diff --git a/pages/express-relay/index.mdx b/pages/express-relay/index.mdx index 857a2fdc..66a8df2a 100644 --- a/pages/express-relay/index.mdx +++ b/pages/express-relay/index.mdx @@ -47,6 +47,6 @@ To learn more about Express Relay, refer to the following resources: } title="Example Protocol Integration" - href="https://github.com/pyth-network/pyth-examples/tree/main/express-relay/easy_lend" + href="https://github.com/pyth-network/pyth-examples/tree/6cea7c9602c7949c6dacc94aec44c0fe78ccb128/express-relay/easy_lend" /> diff --git a/pages/express-relay/integrate-as-protocol.mdx b/pages/express-relay/integrate-as-protocol.mdx index fc5ecf74..383ad9e1 100644 --- a/pages/express-relay/integrate-as-protocol.mdx +++ b/pages/express-relay/integrate-as-protocol.mdx @@ -17,7 +17,7 @@ To integrate with Express Relay, your protocol's contract must check if Express ### Install the Express Relay SDK 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. -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. +The SDK exposes [`IExpressRelay`](https://github.com/pyth-network/per/blob/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/sdk/solidity/IExpressRelay.sol) and [`IExpressRelayFeeReceiver`](https://github.com/pyth-network/per/blob/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/sdk/solidity/IExpressRelayFeeReceiver.sol) interfaces to interact with Express Relay. @@ -49,8 +49,8 @@ Then add the following line to `remappings.txt` file: The following steps show how to modify your protocol's contract to verify if the current transaction is permissioned by Express Relay and to receive the auction proceeds. -1. Call the [`isPermissioned`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelay.sol#L10C14-L10C28) method from `IExpressRelay` interface to make sure the current transaction is permissioned by Express Relay. -1. Implement the [`IExpressRelayFeeReceiver`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelayFeeReceiver.sol#L4) interface to **receive** auction proceeds. +1. Call the [`isPermissioned`](https://github.com/pyth-network/per/blob/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/sdk/solidity/IExpressRelay.sol#L10C14-L10C28) method from `IExpressRelay` interface to make sure the current transaction is permissioned by Express Relay. +1. Implement the [`IExpressRelayFeeReceiver`](https://github.com/pyth-network/per/blob/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/sdk/solidity/IExpressRelayFeeReceiver.sol#L4) interface to **receive** auction proceeds. #### 1. Verify Permissioning @@ -64,7 +64,7 @@ import "@pythnetwork/express-relay-sdk-solidity/IExpressRelay.sol"; // Express Relay contract address on Optimism Sepolia // -// Check https://docs.pyth.network/express-relay/contract-addresses +// Check https://docs.pyth.network/express-relay/contract-addresses/evm // for the address deployed on other networks address expressRelay = 0xD6e417287b875A3932c1Ff5dcB26D4D2C8b90B40; @@ -211,8 +211,8 @@ The JSON payload should contain opportunities in the following format: Each protocol integrated with Express Relay must actively monitor for new opportunities. Protocols can do this by indexing the chain, listening to protocol events, or querying protocol state through an RPC provider. -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. +Check the [`monitor.ts`](https://github.com/pyth-network/per/blob/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/examples/easy_lend/src/monitor.ts) script, +which fetches opportunities for the below-mentioned [Easy Lend](https://github.com/pyth-network/per/tree/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/examples/easy_lend) example and exposes them to Express Relay for auction. ## Additional Resources @@ -220,16 +220,16 @@ You may find these additional resources helpful for integrating Express Relay as ### Example Application -[Easy Lend](https://github.com/pyth-network/pyth-crosschain/tree/main/express_relay/examples/easy_lend) is a dummy lending protocol contract that allows users to borrow and lend assets. +[Easy Lend](https://github.com/pyth-network/per/tree/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/examples/easy_lend) is a dummy lending protocol contract that allows users to borrow and lend assets. This lending protocol contract is updated to use Express Relay. ### Contract Address -The [Contract Address](./contract-addresses.mdx) page lists the addresses of Express Relay deployed on various networks. +The [EVM](./contract-addresses/evm.mdx) and [SVM](./contract-addresses/svm.mdx) Contract Addresses pages list the addresses of Express Relay deployed on various networks. ### Error Codes -The [Error Codes](./errors.mdx) page lists the error codes returned by Express Relay. +The [EVM](./errors/evm.mdx) and [SVM](./errors/svm.mdx) Error Codes pages list the error codes returned by Express Relay. ### API Reference diff --git a/pages/express-relay/integrate-as-searcher.mdx b/pages/express-relay/integrate-as-searcher.mdx index 2de02988..20326cd7 100644 --- a/pages/express-relay/integrate-as-searcher.mdx +++ b/pages/express-relay/integrate-as-searcher.mdx @@ -1,4 +1,5 @@ -import { Callout, Tabs, Steps } from "nextra/components"; +import { Cards, Card } from "nextra/components"; +import CodeIcon from "../../components/icons/CodeIcon"; # How to Integrate Express Relay as a Searcher @@ -13,251 +14,18 @@ Searchers can integrate with Express Relay in three steps: 2. Construct the bid 3. Submit the bid to Express Relay. - - -### Subscribe to New Opportunities - -Express Relay provides searchers with [Typescript](https://github.com/pyth-network/pyth-crosschain/tree/main/express_relay/sdk/js) and [Python](https://github.com/pyth-network/pyth-crosschain/tree/main/express_relay/sdk/python) SDKs to interact with Express Relay. -Searchers can also directly fetch available opportunities via HTTP or subscribe to them via WebSocket. - - - - -Pyth provides a Typescript SDK, which allows searchers to subscribe to opportunities: - -```typescript -import { Client, Opportunity } from "@pythnetwork/express-relay-evm-js"; - -const handleOpporunity = async (opportunity: Opportunity) => { - // Implement your opportunity handler here -}; - -const client = new Client( - { baseUrl: "https://pyth-express-relay-mainnet.asymmetric.re" }, - undefined, // Default WebSocket options - handleOpporunity -); -await client.subscribeChains(["op_sepolia"]); -``` - - - -Pyth provides a Python SDK, which allows searchers to subscribe to opportunities: - -```python copy -from express_relay.client import ( - ExpressRelayClient, -) -from express_relay.express_relay_types import Opportunity - -def opportunity_callback(opportunity: Opportunity): - # Implement your opportunity handler here - pass - -client = ExpressRelayClient( - 'server_url', - None, - opportunity_callback, - None, -) -await client.subscribe_chains(['op_sepolia']) -``` - - - -Searchers can request opportunities through an HTTP **GET** call to the [`/v1/opportunities`](https://pyth-express-relay-mainnet.asymmetric.re/docs#tag/opportunity/operation/get_opportunities) endpoint. - -```bash copy -curl -X 'GET' \ - 'https://pyth-express-relay-mainnet.asymmetric.re/v1/opportunities?chain_id=op_sepolia&mode=live' -``` - -Opportunities are short-lived and could be executed in a matter of seconds. So, the above endpoint could return an empty response. - - - -Searchers can connect to the server via WebSocket to reduce latency and subscribe to various events. The WebSocket endpoint lives at `/v1/ws`(e.g `wss://pyth-express-relay-mainnet.asymmetric.re/v1/ws`). -Here is a sample JSON payload to subscribe to opportunities: - -```bash copy -{ - "id": "1", - "method": "subscribe", - "params": { - "chain_ids": ["op_sepolia"] - } -} -``` - -Consult [`Websocket API reference`](./websocket-api-reference.mdx) for a complete list of methods and parameters. - - - - -The server responds with opportunities in the following format: - -```bash copy -{ - "target_calldata": "0xdeadbeef", // Calldata to execute the opportunity - "chain_id": "op_sepolia", - "target_contract": "0xcA11bde05977b3631167028862bE2a173976CA11", // Protocol contract address to call - "permission_key": "0xcafebabe", // Unique identifier for the opportunity - "target_call_value": "1", // Value (in Wei) to send to the protocol contract. - "sell_tokens": [ // Tokens the protocol expects to receive - { - "amount": "900", - "token": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599" - } - ], - "buy_tokens": [ // Tokens the protocol will send in return - { - "amount": "1000", - "token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - } - ], - "version": "v1" // Opportunity format version -} -``` - -### Construct the Bid - -Searchers should construct a bid by evaluating the fetched opportunity. -The SDKs provide an easy way to construct a bid using the [`OpportunityAdapter`](https://github.com/pyth-network/per/blob/main/contracts/src/opportunity-adapter/OpportunityAdapter.sol) contract. -The `OpportunityAdapter` contract handles asset transfers and ensures the opportunity is executed correctly. - - - Before constructing the bid, make sure your wallet has the required assets and - has made the necessary approvals. Refer to the [Prepare assets for Opportunity - Adapter](./integrate-as-searcher/opportunity-adapter.mdx) section for more - details. - - -Here is an example of how to construct a bid object using `OpportunityAdapter` via the SDKs: - - - -```typescript copy -const handleOpportunity = async (opportunity: Opportunity) => { - const nonce = BigInt(Math.floor(Math.random() * 2 ** 50)); - const privateKey = `0x0000`; // Private key of the searcher - const bidAmount = BigInt(1000); // The bidAmount should be determined based on opportunity - const deadline = BigInt(Math.round(Date.now() / 1000 + 60)) // Bid is valid for a minute - const bid = await client.signBid(opportunity, {bidAmount, nonce, deadline}, privateKey) -} -``` - - -```python copy -from datetime import datetime - -from express_relay.client import ( -ExpressRelayClient, -sign_bid -) -from secrets import randbits -from express_relay.express_relay_types import Opportunity, OpportunityBidParams - -def opportunity_callback(opportunity: Opportunity): -nonce = randbits(64) -deadline = datetime.utcnow().timestamp() + 60 # Bid is valid for a minute -bid_amount = 1000 # The bid_amount should be determined based on the opportunity -private_key = '0x00000' # Private key of the searcher -signed_bid = sign_bid(opportunity, -OpportunityBidParams(amount=bid_amount, deadline=int(deadline), nonce=nonce), -private_key) - -```` - - - - - - -If you prefer to use your custom contracts instead of the `OpportunityAdapter`, please refer to the [custom contracts](./integrate-as-searcher/custom-contract.mdx) section. - -### Submit Bids on Opportunities to Express Relay - -Searchers can submit the constructed bids to Express Relay via the SDKs, an HTTP POST request, or a WebSocket connection. - - - - - -The code snippet below demonstrates how to submit a bid using the Typescript SDK: - -```typescript {4} copy -const handleOpporunity = async (opportunity: Opportunity) => { - ... - const bid = await client.signBid(opportunity, {amount, nonce, deadline}, privateKey) - await client.submitBid(bid) -} -```` - - - - -The code snippet below demonstrates how to submit a bid using the Python SDK: - -```python {5} copy -def opportunity_callback(opportunity: Opportunity): - signed_bid = sign_bid(opportunity, - OpportunityBidParams(amount=amount, deadline=int(deadline), nonce=nonce), - private_key) - await client.submit_bid(signed_bid, subscribe_to_updates=True) -``` - - - -Searchers can submit bids through an HTTP POST call to the [`/v1/bids`](https://pyth-express-relay-mainnet.asymmetric.re/docs#tag/bid/operation/bid) endpoint. This endpoint accepts a JSON payload containing the details of the bid. - -```bash copy -curl -X POST https://pyth-express-relay-mainnet.asymmetric.re/v1/bids \ - -H "Content-Type: application/json" \ - -d '{ - "chain_id": "op_sepolia", - "permission_key": "0x000000000000000000000000", - "target_contract": "0x87ee27c5ae396b28a825968b277fece0720f5907", - "target_calldata": "0xeadb38050000000000000000000000000000000000000000000000000000000000000064", - "amount": "10" -}' -``` - - - - -Searchers can submit bids via Websocket to avoid additional network round-trips and get notified about changes to the bid status. - -```bash copy -{ - "id": "1", - "method": "post_bid", - "params": { - "bid": { - "chain_id": "op_sepolia", - "permission_key": "0x000000000000000000000000", - "target_contract": "0x87ee27c5ae396b28a825968b277fece0720f5907", - "target_calldata": "0xeadb38050000000000000000000000000000000000000000000000000000000000000064", - "amount": "10" - } - } -} -``` - -A successful response to a bid submission has the following schema: - -```bash copy -{ - "id": "1", // Websocket request id - "status": "success", - "result": { - "id": "beedbeed-b346-4fa1-8fab-2541a9e1872d", // Bid id - "status": "OK" - } -} -``` - -Consult [`Websocket API reference`](./websocket-api-reference.mdx) for more details. - - - - +Searchers can integrate with Express Relay on Ethereum Virtual Machine (EVM) and Solana Virtual Machine (SVM) chains. + + +} + title="Integrate with Express Relay on EVM Chains" + href="/express-relay/integrate-as-searcher/evm" +/> + +} + title="Integrate with Express Relay on SVM Chains" + href="/express-relay/integrate-as-searcher/svm" +/> + diff --git a/pages/express-relay/integrate-as-searcher/_meta.json b/pages/express-relay/integrate-as-searcher/_meta.json index 8b30349f..7c532053 100644 --- a/pages/express-relay/integrate-as-searcher/_meta.json +++ b/pages/express-relay/integrate-as-searcher/_meta.json @@ -1,4 +1,4 @@ { - "opportunity-adapter": "Prepare Assets for Opportunity Adapter", - "custom-contract": "Use a Custom Contract" + "evm": "Integrate on EVM chains", + "svm": "Integrate on SVM chains" } diff --git a/pages/express-relay/integrate-as-searcher/evm.mdx b/pages/express-relay/integrate-as-searcher/evm.mdx new file mode 100644 index 00000000..6fa68128 --- /dev/null +++ b/pages/express-relay/integrate-as-searcher/evm.mdx @@ -0,0 +1,252 @@ +import { Callout, Tabs, Steps } from "nextra/components"; + +# EVM Searcher Integration + + + +### Subscribe to New Opportunities + +Express Relay provides searchers with [Typescript](https://github.com/pyth-network/per/tree/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/sdk/js) and [Python](https://github.com/pyth-network/per/tree/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/sdk/python) SDKs to interact with Express Relay. +Searchers can also directly fetch available opportunities via HTTP or subscribe to them via WebSocket. + + + + +Pyth provides a Typescript SDK, which allows searchers to subscribe to opportunities: + +```typescript +import { Client, Opportunity } from "@pythnetwork/express-relay-js"; + +const handleOpporunity = async (opportunity: Opportunity) => { + // Implement your opportunity handler here +}; + +const client = new Client( + { baseUrl: "https://pyth-express-relay-mainnet.asymmetric.re" }, + undefined, // Default WebSocket options + handleOpporunity +); +await client.subscribeChains(["op_sepolia"]); +``` + + + +Pyth provides a Python SDK, which allows searchers to subscribe to opportunities: + +```python copy +from express_relay.client import ( + ExpressRelayClient, +) +from express_relay.express_relay_types import Opportunity + +def opportunity_callback(opportunity: Opportunity): + # Implement your opportunity handler here + pass + +client = ExpressRelayClient( + 'server_url', + None, + opportunity_callback, + None, +) +await client.subscribe_chains(['op_sepolia']) +``` + + + +Searchers can request opportunities through an HTTP **GET** call to the [`/v1/opportunities`](https://pyth-express-relay-mainnet.asymmetric.re/docs#tag/opportunity/operation/get_opportunities) endpoint. + +```bash copy +curl -X 'GET' \ + 'https://pyth-express-relay-mainnet.asymmetric.re/v1/opportunities?chain_id=op_sepolia&mode=live' +``` + +Opportunities are short-lived and could be executed in a matter of seconds. So, the above endpoint could return an empty response. + + + +Searchers can connect to the server via WebSocket to reduce latency and subscribe to various events. The WebSocket endpoint lives at `/v1/ws`(e.g `wss://pyth-express-relay-mainnet.asymmetric.re/v1/ws`). +Here is a sample JSON payload to subscribe to opportunities: + +```bash copy +{ + "id": "1", + "method": "subscribe", + "params": { + "chain_ids": ["op_sepolia"] + } +} +``` + +Consult [`Websocket API reference`](./websocket-api-reference.mdx) for a complete list of methods and parameters. + + + + +The server responds with opportunities in the following format: + +```bash copy +{ + "target_calldata": "0xdeadbeef", // Calldata to execute the opportunity + "chain_id": "op_sepolia", + "target_contract": "0xcA11bde05977b3631167028862bE2a173976CA11", // Protocol contract address to call + "permission_key": "0xcafebabe", // Unique identifier for the opportunity + "target_call_value": "1", // Value (in Wei) to send to the protocol contract. + "sell_tokens": [ // Tokens the protocol expects to receive + { + "amount": "900", + "token": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599" + } + ], + "buy_tokens": [ // Tokens the protocol will send in return + { + "amount": "1000", + "token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" + } + ], + "version": "v1" // Opportunity format version +} +``` + +### Construct the Bid + +Searchers should construct a bid by evaluating the fetched opportunity. +The SDKs provide an easy way to construct a bid using the [`OpportunityAdapter`](https://github.com/pyth-network/per/blob/fccac65b00cff1cfe5c278b333a582fe66bda0f8/contracts/evm/src/opportunity-adapter/OpportunityAdapter.sol) contract. +The `OpportunityAdapter` contract handles asset transfers and ensures the opportunity is executed correctly. + + + Before constructing the bid, make sure your wallet has the required assets and + has made the necessary approvals. Refer to the [Prepare assets for Opportunity + Adapter](./integrate-as-searcher/opportunity-adapter.mdx) section for more + details. + + +Here is an example of how to construct a bid object using `OpportunityAdapter` via the SDKs: + + + +```typescript copy +const handleOpportunity = async (opportunity: Opportunity) => { + const nonce = BigInt(Math.floor(Math.random() * 2 ** 50)); + const privateKey = `0x0000`; // Private key of the searcher + const bidAmount = BigInt(1000); // The bidAmount should be determined based on opportunity + const deadline = BigInt(Math.round(Date.now() / 1000 + 60)) // Bid is valid for a minute + const bid = await client.signBid(opportunity, {bidAmount, nonce, deadline}, privateKey) +} +``` + + +```python copy +from datetime import datetime + +from express_relay.client import ( +ExpressRelayClient, +sign_bid +) +from secrets import randbits +from express_relay.express_relay_types import Opportunity, OpportunityBidParams + +def opportunity_callback(opportunity: Opportunity): +nonce = randbits(64) +deadline = datetime.utcnow().timestamp() + 60 # Bid is valid for a minute +bid_amount = 1000 # The bid_amount should be determined based on the opportunity +private_key = '0x00000' # Private key of the searcher +signed_bid = sign_bid(opportunity, +OpportunityBidParams(amount=bid_amount, deadline=int(deadline), nonce=nonce), +private_key) + +```` + + + + + + +If you prefer to use your custom contracts instead of the `OpportunityAdapter`, please refer to the [custom contracts](./integrate-as-searcher/custom-contract.mdx) section. + +### Submit Bids on Opportunities to Express Relay + +Searchers can submit the constructed bids to Express Relay via the SDKs, an HTTP POST request, or a WebSocket connection. + + + + + +The code snippet below demonstrates how to submit a bid using the Typescript SDK: + +```typescript {4} copy +const handleOpporunity = async (opportunity: Opportunity) => { + ... + const bid = await client.signBid(opportunity, {amount, nonce, deadline}, privateKey) + await client.submitBid(bid) +} +```` + + + + +The code snippet below demonstrates how to submit a bid using the Python SDK: + +```python {5} copy +def opportunity_callback(opportunity: Opportunity): + signed_bid = sign_bid(opportunity, + OpportunityBidParams(amount=amount, deadline=int(deadline), nonce=nonce), + private_key) + await client.submit_bid(signed_bid, subscribe_to_updates=True) +``` + + + +Searchers can submit bids through an HTTP POST call to the [`/v1/bids`](https://pyth-express-relay-mainnet.asymmetric.re/docs#tag/bid/operation/bid) endpoint. This endpoint accepts a JSON payload containing the details of the bid. + +```bash copy +curl -X POST https://pyth-express-relay-mainnet.asymmetric.re/v1/bids \ + -H "Content-Type: application/json" \ + -d '{ + "chain_id": "op_sepolia", + "permission_key": "0x000000000000000000000000", + "target_contract": "0x87ee27c5ae396b28a825968b277fece0720f5907", + "target_calldata": "0xeadb38050000000000000000000000000000000000000000000000000000000000000064", + "amount": "10" +}' +``` + + + + +Searchers can submit bids via Websocket to avoid additional network round-trips and get notified about changes to the bid status. + +```bash copy +{ + "id": "1", + "method": "post_bid", + "params": { + "bid": { + "chain_id": "op_sepolia", + "permission_key": "0x000000000000000000000000", + "target_contract": "0x87ee27c5ae396b28a825968b277fece0720f5907", + "target_calldata": "0xeadb38050000000000000000000000000000000000000000000000000000000000000064", + "amount": "10" + } + } +} +``` + +A successful response to a bid submission has the following schema: + +```bash copy +{ + "id": "1", // Websocket request id + "status": "success", + "result": { + "id": "beedbeed-b346-4fa1-8fab-2541a9e1872d", // Bid id + "status": "OK" + } +} +``` + +Consult [`Websocket API reference`](./websocket-api-reference.mdx) for more details. + + + + diff --git a/pages/express-relay/integrate-as-searcher/evm/_meta.json b/pages/express-relay/integrate-as-searcher/evm/_meta.json new file mode 100644 index 00000000..8b30349f --- /dev/null +++ b/pages/express-relay/integrate-as-searcher/evm/_meta.json @@ -0,0 +1,4 @@ +{ + "opportunity-adapter": "Prepare Assets for Opportunity Adapter", + "custom-contract": "Use a Custom Contract" +} diff --git a/pages/express-relay/integrate-as-searcher/custom-contract.mdx b/pages/express-relay/integrate-as-searcher/evm/custom-contract.mdx similarity index 89% rename from pages/express-relay/integrate-as-searcher/custom-contract.mdx rename to pages/express-relay/integrate-as-searcher/evm/custom-contract.mdx index fc26e5e1..0d58950c 100644 --- a/pages/express-relay/integrate-as-searcher/custom-contract.mdx +++ b/pages/express-relay/integrate-as-searcher/evm/custom-contract.mdx @@ -35,6 +35,7 @@ function callLiquidation(Opportunity memory opp){ ``` - Make sure to allow the [Express Relay contract](../contract-addresses.mdx) to - call the relevant methods in your custom contract. + Make sure to allow the [Express Relay + contract](../../contract-addresses/evm.mdx) to call the relevant methods in + your custom contract. diff --git a/pages/express-relay/integrate-as-searcher/opportunity-adapter.mdx b/pages/express-relay/integrate-as-searcher/evm/opportunity-adapter.mdx similarity index 87% rename from pages/express-relay/integrate-as-searcher/opportunity-adapter.mdx rename to pages/express-relay/integrate-as-searcher/evm/opportunity-adapter.mdx index 3a0442da..2b83ca36 100644 --- a/pages/express-relay/integrate-as-searcher/opportunity-adapter.mdx +++ b/pages/express-relay/integrate-as-searcher/evm/opportunity-adapter.mdx @@ -2,7 +2,7 @@ import { Steps } from "nextra/components"; # Prepare Assets for Opportunity Adapter -The [`OpportunityAdapter`](https://github.com/pyth-network/per/blob/main/contracts/src/opportunity-adapter/OpportunityAdapter.sol) is a utility contract that can be used for easier integration with Express Relay while maintaining maximum security. +The [`OpportunityAdapter`](https://github.com/pyth-network/per/blob/fccac65b00cff1cfe5c278b333a582fe66bda0f8/contracts/evm/src/opportunity-adapter/OpportunityAdapter.sol) is a utility contract that can be used for easier integration with Express Relay while maintaining maximum security. In this integration, searchers use the [`Permit2`](https://github.com/Uniswap/permit2/) contract for safe asset management (`ERC20` tokens and Wrapped ETH) and the adapter contract to transfer bids, execute the opportunity, and ensure the assets are transferred correctly. Using the `OpportunityAdapter` means that a searcher does not need to deploy their own custom contract for inventory management and routing to the protocol contracts where liquidation takes place. @@ -14,7 +14,7 @@ In order to use `OpportunityAdapter`, you need to prepare your assets using the Searchers are expected to own all the tokens that they expect to provide as `sell_tokens` for different opportunities. They will also need to approve `WETH`, as the `OpportunityAdapter` will pay the bids by deducting the bid amounts from their wallet's `WETH` balance. -You can find the `WETH` contract address on the [contract address page](../contract-addresses). +You can find the `WETH` contract address on the [contract address page](../../contract-addresses/evm). Refer to the following command to deposit native ETH to `WETH`: ```bash copy @@ -30,7 +30,7 @@ $WETH_ADDRESS \ Approve your tokens, including `WETH`, to the `Permit2` contract at `0x000000000022D473030F116dDEE9F6B43aC78BA3`. This step enables token spending with off-chain signatures. -You can find the `Permit2` and `WETH` contract address on the [contract address page](../contract-addresses.mdx). +You can find the `Permit2` and `WETH` contract address on the [contract address page](../../contract-addresses/evm.mdx). Refer to the following command to approve a token to `Permit2`: diff --git a/pages/express-relay/integrate-as-searcher/svm.mdx b/pages/express-relay/integrate-as-searcher/svm.mdx new file mode 100644 index 00000000..6e3ea0b9 --- /dev/null +++ b/pages/express-relay/integrate-as-searcher/svm.mdx @@ -0,0 +1,208 @@ +import { Callout, Tabs, Steps } from "nextra/components"; + +# SVM Searcher Integration + +SVM Express Relay searchers fulfill opportunities representing limit orders on the [Limo]() program. + + + +### Subscribe to New Opportunities + +Express Relay provides searchers with [Typescript](https://github.com/pyth-network/per/tree/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/sdk/js) and [Python](https://github.com/pyth-network/per/tree/8e311d3dce7a54865ff98b25e57c6af2dd984d1f/sdk/python) SDKs to interact with Express Relay. +Searchers can also directly fetch available opportunities via HTTP or subscribe to them via WebSocket. + + + + +Pyth provides a Typescript SDK, which allows searchers to subscribe to opportunities: + +```typescript +import { Client, Opportunity } from "@pythnetwork/express-relay-js"; + +const handleOpporunity = async (opportunity: Opportunity) => { + // Implement your opportunity handler here +}; + +const client = new Client( + { baseUrl: "https://pyth-express-relay-mainnet.asymmetric.re" }, + undefined, // Default WebSocket options + handleOpporunity +); +await client.subscribeChains(["development-solana"]); +``` + + + +Pyth provides a Python SDK, which allows searchers to subscribe to opportunities: + +```python copy +from express_relay.client import ( + ExpressRelayClient, +) +from express_relay.express_relay_types import Opportunity + +def opportunity_callback(opportunity: Opportunity): + # Implement your opportunity handler here + pass + +client = ExpressRelayClient( + "https://per-staging.dourolabs.app", + None, + opportunity_callback, + None, +) +await client.subscribe_chains(['development-solana']) +``` + + + +Searchers can request opportunities through an HTTP **GET** call to the [`/v1/opportunities`](https://pyth-express-relay-mainnet.asymmetric.re/docs#tag/opportunity/operation/get_opportunities) endpoint. + +```bash copy +curl -X 'GET' \ + 'https://pyth-express-relay-mainnet.asymmetric.re/v1/opportunities?chain_id=development-solana&mode=live' +``` + +Opportunities are short-lived and could be executed in a matter of seconds. So, the above endpoint could return an empty response. + + + +Searchers can connect to the server via WebSocket to reduce latency and subscribe to various events. The WebSocket endpoint lives at `/v1/ws`(e.g `wss://pyth-express-relay-mainnet.asymmetric.re/v1/ws`). +Here is a sample JSON payload to subscribe to opportunities: + +```bash copy +{ + "id": "1", + "method": "subscribe", + "params": { + "chain_ids": ["development-solana"] + } +} +``` + +Consult [`Websocket API reference`](./websocket-api-reference.mdx) for a complete list of methods and parameters. + + + + +The server responds with opportunities in the following format: + +```bash copy +{ + "order": "UxMUbQAsjrfQUp5stVwMJ6Mucq7VWTvt4ICe69BJ8lVXqwM+0sysV8OqZTdM0W4p...", // The Limo order to be executed, encoded in base64 + "order_address": "DUcTi3rDyS5QEmZ4BNRBejtArmDCWaPYGfN44vBJXKL5", // Address of the order account + "program": "limo", // Identifier of the program that the order exists in + "chain_id": "development-solana", + "version": "v1" // Opportunity format version +} +``` + +### Construct the Bid + +Searchers should construct a bid by evaluating the fetched opportunity. +The SDKs provide an easy way to construct a bid; refer to these basic examples in [Typescript](https://github.com/pyth-network/per/blob/0bd47e39d704c4b19b596512e4be05db4f715e58/sdk/js/src/examples/simpleSearcherLimo.ts#L75) and [Python](https://github.com/pyth-network/per/blob/0bd47e39d704c4b19b596512e4be05db4f715e58/sdk/python/express_relay/searcher/examples/simple_searcher_svm.py#L110). + + + Before constructing the bid, make sure your wallet has the required assets. + + +The bid you construct will look like + +``` +{ + // serialized transaction object, in base-64 encoding + transaction: "SGVsbG8sIFdvcmxkIQ==", + chain_id: "solana", + env: "svm" +} +``` + +where the serialized transaction object should contain an Express Relay `SubmitBid` instruction that specifies the amount you are bidding and the permission details. + +### Submit Bids on Opportunities to Express Relay + +Searchers can submit their constructed bids to Express Relay via the SDKs, an HTTP POST request, or a WebSocket connection. + + + + + +The code snippet below demonstrates how to submit a bid using the Typescript SDK: + +```typescript {8} copy +const generateBid = async (opportunity: OpportunitySvm, recentBlockhash: Blockhash): BidSvm => { + ... +} + +const handleOpporunity = async (opportunity: Opportunity) => { + ... + const bid = await generateBid(opportunity as OpportunitySvm, this.recentBlockhash[this.chainId]); + await client.submitBid(bid); +} +``` + + + + +The code snippet below demonstrates how to submit a bid using the Python SDK: + +```python {5} copy +import typing + +async def generate_bid(opp: OpportunitySvm) -> BidSvm: + ... + +def opportunity_callback(opportunity: Opportunity): + bid = generate_bid(typing.cast(OpportunitySvm, opportunity)) + await client.submit_bid(bid, subscribe_to_updates=True) +``` + + + +Searchers can submit bids through an HTTP POST call to the [`/v1/bids`](https://pyth-express-relay-mainnet.asymmetric.re/docs#tag/bid/operation/bid) endpoint. This endpoint accepts a JSON payload containing the details of the bid. + +```bash copy +curl -X POST https://pyth-express-relay-mainnet.asymmetric.re/v1/bids \ + -H "Content-Type: application/json" \ + -d '{ + "chain_id": "development-solana", + "transaction": "SGVsbG8sIFdvcmxkIQ==" +}' +``` + + + + +Searchers can submit bids via Websocket to avoid additional network round-trips and get notified about changes to the bid status. + +```bash copy +{ + "id": "1", + "method": "post_bid", + "params": { + "bid": { + "chain_id": "development-solana", + "transaction": "SGVsbG8sIFdvcmxkIQ==" + } + } +} +``` + +A successful response to a bid submission has the following schema: + +```bash copy +{ + "id": "1", // Websocket request id + "status": "success", + "result": { + "id": "beedbeed-b346-4fa1-8fab-2541a9e1872d", // Bid id + "status": "OK" + } +} +``` + +Consult [`Websocket API reference`](./websocket-api-reference.mdx) for more details. + + + + diff --git a/pages/express-relay/websocket-api-reference.mdx b/pages/express-relay/websocket-api-reference.mdx index 795dfdc2..a20c364a 100644 --- a/pages/express-relay/websocket-api-reference.mdx +++ b/pages/express-relay/websocket-api-reference.mdx @@ -79,6 +79,10 @@ To unsubscribe from a list of chains, you can send the following message: In addition to the HTTP methods, you can submit your bids via WebSocket in order to avoid additional network round trips and get notified about changes to your bid status. Here is an example JSON payload for submitting a new bid: + + + + ```json copy { "id": "1", @@ -87,7 +91,7 @@ Here is an example JSON payload for submitting a new bid: "bid": { "amount": "10", "calldata": "0xdeadbeef", - "chain_id": "sepolia", + "chain_id": "op_sepolia", "contract": "0xcA11bde05977b3631167028862bE2a173976CA11", "permission_key": "0xcafebabe" } @@ -95,6 +99,25 @@ Here is an example JSON payload for submitting a new bid: } ``` + + + +```json copy +{ + "id": "1", + "method": "post_bid", + "params": { + "bid": { + "chain_id": "development-solana", + "transaction": "SGVsbG8sIFdvcmxkIQ==" + } + } +} +``` + + + + A successful response to a bid submission has the following schema: ```json @@ -109,84 +132,185 @@ A successful response to a bid submission has the following schema: ``` After submitting your bid via WebSocket, you will receive notifications about the bid status updates in JSON format. -Refer to the four examples below, one for each of the status options (`pending`, `submitted`, `lost`, `won`): +Refer to the examples below, one for each of the status options in EVM and SVM: + + - -```json -// pending -// The temporary state, which means the auction for this bid is pending -{ - "type": "bid_status_update", - "status": { - "id": "1eaee2a4-01bf-4f6c-8a76-21fadb2c43b1", - "bid_status": { - "type": "pending" + + + ```json + // pending + // The temporary state, which means the auction for this bid is pending + { + "type": "bid_status_update", + "status": { + "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", + "bid_status": { + "type": "pending" + } } } -} -``` - - -```json -// submitted -// The bid is submitted to the chain, which is placed at the given index of the transaction with the given hash -// This state is temporary and will be updated to either lost or won after the conclusion of the auction -{ - "type": "bid_status_update", - "status": { - "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", - "bid_status": { - // the enum for the bid_status - "type": "submitted", - // the hash of the transaction that the bid's calldata was included in - "result": "0xabc393b634fdf3eb45be8350fd16cd1b4add47b96059beacc1d8c20e51d75ec3", - // the index of the bid calldata within the multicall bundle for the above transaction - "index": 0 + ``` + + + ```json + // submitted + // The bid is submitted to the chain, which is placed at the given index of the transaction with the given hash + // This state is temporary and will be updated to either lost or won after the conclusion of the auction + { + "type": "bid_status_update", + "status": { + "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", + "bid_status": { + // the enum for the bid_status + "type": "submitted", + // the hash of the transaction that the bid's calldata was included in + "result": "0xabc393b634fdf3eb45be8350fd16cd1b4add47b96059beacc1d8c20e51d75ec3", + // the index of the bid calldata within the multicall bundle for the above transaction + "index": 0 + } } } -} -``` - - -```json -// lost -// The bid lost the auction, which is concluded with the transaction with the given hash and index -// The result will be None if the auction was concluded off-chain and no auction was submitted to the chain -// The index will be None if the bid was not submitted to the chain and lost the auction by off-chain calculation -// There are cases where the result is not none and the index is none. -// It is because other bids were selected for submission to the chain, but not this one. -{ - "type": "bid_status_update", - "status": { - "id": "1eaee2a4-01bf-4f6c-8a76-21fadb2c43b1", - "bid_status": { - "type": "lost", - "result": "0x99c2bf411330ae997632f88abe8f86c0d1f4c448f7d5061319d23814a0fb1135" + ``` + + + ```json + // lost + // The bid lost the auction, which is concluded with the transaction with the given hash and index + // The result will be None if the auction was concluded off-chain and no auction was submitted to the chain + // The index will be None if the bid was not submitted to the chain and lost the auction by off-chain calculation + // There are cases where the result is not none and the index is none. + // It is because other bids were selected for submission to the chain, but not this one. + { + "type": "bid_status_update", + "status": { + "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", + "bid_status": { + "type": "lost", + "result": "0x99c2bf411330ae997632f88abe8f86c0d1f4c448f7d5061319d23814a0fb1135" + } } } -} -``` + ``` + + + ```json + // won + // The bid won the auction, which is concluded with the transaction with the given hash and index + { + "type": "bid_status_update", + "status": { + "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", + "bid_status": { + // the enum for the bid_status + "type": "won", + // the hash of the transaction that the bid's calldata was included in + "result": "0xabc393b634fdf3eb45be8350fd16cd1b4add47b96059beacc1d8c20e51d75ec3", + // the index of the bid calldata within the multicall bundle for the above transaction + "index": 0 + } + } + } + ``` + + + -```json -// won -// The bid won the auction, which is concluded with the transaction with the given hash and index -{ - "type": "bid_status_update", - "status": { - "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", - "bid_status": { - // the enum for the bid_status - "type": "won", - // the hash of the transaction that the bid's calldata was included in - "result": "0xabc393b634fdf3eb45be8350fd16cd1b4add47b96059beacc1d8c20e51d75ec3", - // the index of the bid calldata within the multicall bundle for the above transaction - "index": 0 + + + ```json + // pending + // The temporary state, which means the auction for this bid is pending + { + "type": "bid_status_update", + "status": { + "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", + "bid_status": { + "type": "pending" + } } } -} -``` + ``` + + + ```json + // submitted + /// The bid is submitted to the chain, with the transaction with the signature. + /// This state is temporary and will be updated to either lost or won after conclusion of the auction. + { + "type": "bid_status_update", + "status": { + "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", + "bid_status": { + // the enum for the bid_status + "type": "submitted", + // the hash of the transaction that the bid's calldata was included in + "result": "0xabc393b634fdf3eb45be8350fd16cd1b4add47b96059beacc1d8c20e51d75ec3" + } + } + } + ``` + + + ```json + // lost + /// The bid lost the auction. + /// The result will be None if the auction was concluded off-chain and no auction was submitted to the chain. + /// The result will be not None if another bid were selected for submission to the chain. + /// The signature of the transaction for the submitted bid is the result value. + { + "type": "bid_status_update", + "status": { + "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", + "bid_status": { + "type": "lost", + "result": "0x99c2bf411330ae997632f88abe8f86c0d1f4c448f7d5061319d23814a0fb1135" + } + } + } + ``` + + + ```json + // won + /// The bid won the auction, with the transaction with the signature. + { + "type": "bid_status_update", + "status": { + "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", + "bid_status": { + // the enum for the bid_status + "type": "won", + // the hash of the transaction that the bid's calldata was included in + "result": "0xabc393b634fdf3eb45be8350fd16cd1b4add47b96059beacc1d8c20e51d75ec3" + } + } + } + ``` + + + + ```json + // expired + // /// The bid expired without being submitted on chain. + { + "type": "bid_status_update", + "status": { + "id": "beedbeed-0e42-400f-a8ef-d78aa5422252", + "bid_status": { + // the enum for the bid_status + "type": "expired", + // the hash of the transaction that the bid's calldata was included in + "result": "Jb2urXPyEh4xiBgzYvwEFe4q1iMxG1DNxWGGQg94AmKgqFTwLAiTiHrYiYxwHUB4DV8u5ahNEVtMMDm3sNSRdTg", + } + } + } + ``` + + +