Submission Methods
Last updated
Last updated
can be submitted to the using JSON-RPC 2.0 over HTTPS and Websocket.
Searchers can send their submissions to the FastLane Relay API by calling the methods for Bundles
More information on the FastLane Relay API and API calls can be found here:
Rate limits (for both HTTP and websocket):
Request/message limit per second: 2
Burst limit: 32
Repeatedly going over the rate limit will result in temporary IP ban, ranging from 3 minutes to 24 hours.
It's recommended that you use HTTP Keep-Alive connections to connect to the RPC endpoint to minimize TLS connection establishment times as it significantly reduces request latency when sending a bundle if the TLS handshake is already complete.
The /ping
endpoint is available for establishing a session, you can have a maximum of 2 sessions per IP address, and sessions will persist for a maximum of 15 minutes.
Example:
import axios from 'axios';
// Abstracted function to create the PFL bundle
function createPflBundle(bundleId, opportunityRawTx, solverOpStruct) {
return {
id: bundleId,
jsonrpc: "2.0",
method: "pfl_addSearcherBundle",
params: [opportunityRawTx, solverOpStruct]
};
}
// Helper function to submit the bundle to the Fastlane endpoint
async function submitBundle(bundle) {
const httpFastlaneEndpoint = "https://polygon-rpc.fastlane.xyz";
try {
const response = await axios.post(httpFastlaneEndpoint, bundle, {
timeout: 1000
});
if (response.data.error) {
console.error(`Error submitting bundle ${bundle.id}`, response.data);
} else {
console.log(`Response received for bundle ${bundle.id}`, response.data);
}
} catch (error) {
console.error(`Error submitting bundle ${bundle.id}`, error);
}
}
// Main function to submit the bundle
async function main() {
// Define your variables
const bundleId = 1;
const opportunityRawTx = "0x..."; // Replace with your actual opportunity raw transaction
const solverOpStruct = "0x..."; // Replace with your actual solver operation structure
// Create the PFL bundle
const pflBundle = createPflBundle(bundleId, opportunityRawTx, solverOpStruct);
// Submit the bundle to the Fastlane endpoint
await submitBundle(pflBundle);
}
main().catch(console.error);
import asyncio
import aiohttp
import json
# Asynchronous function to test the connection to the Fastlane endpoint
async def ping_fastlane():
http_fastlane_ping_endpoint = "https://polygon-rpc.fastlane.xyz/ping"
try:
async with aiohttp.ClientSession() as session:
async with session.get(http_fastlane_ping_endpoint, timeout=10) as response:
if response.status == 200:
text = await response.text()
print("Ping successful:", text)
else:
print("Ping failed with status code:", response.status)
except aiohttp.ClientError as e:
print("Ping failed:", e)
except asyncio.TimeoutError:
print("Ping failed: Request timed out")
# Function to create the PFL bundle with specified arguments
def create_pfl_bundle(bundle_id, opportunity_raw_tx, solver_op_struct):
return {
"id": bundle_id,
"jsonrpc": "2.0",
"method": "submitBundle",
"params": [opportunity_raw_tx, solver_op_struct]
}
# Asynchronous function to submit the bundle to the Fastlane endpoint
async def submit_bundle(bundle):
http_fastlane_endpoint = "https://polygon-rpc.fastlane.xyz"
try:
async with aiohttp.ClientSession() as session:
async with session.post(http_fastlane_endpoint, json=bundle, timeout=10) as response:
response.raise_for_status() # Raise an error for bad HTTP status codes
response_data = await response.json()
if 'error' in response_data:
print(f"Error submitting bundle {bundle['id']}: {response_data['error']}")
else:
print(f"Response received for bundle {bundle['id']}: {response_data['result']}")
except aiohttp.ClientResponseError as http_err:
print(f"HTTP error occurred while submitting bundle {bundle['id']}: {http_err}")
except aiohttp.ClientError as client_err:
print(f"Client error occurred while submitting bundle {bundle['id']}: {client_err}")
except asyncio.TimeoutError:
print(f"Error submitting bundle {bundle['id']}: Request timed out")
except json.JSONDecodeError as json_err:
print(f"JSON decode error for bundle {bundle['id']}: {json_err}")
# Asynchronous main function to test connection and submit the bundle
async def main():
# Test the connection to the Fastlane endpoint
await ping_fastlane()
# Wait until you're ready to send a bundle, refreshing session as necessary
# You might include a delay or a condition here if needed
# Define your variables
bundle_id = 1
opportunity_raw_tx = "0x..." # Replace with your actual opportunity raw transaction
solver_op_struct = "0x..." # Replace with your actual solver operation structure
# Create the PFL bundle with the specified arguments
pfl_bundle = create_pfl_bundle(bundle_id, opportunity_raw_tx, solver_op_struct)
# Submit the bundle to the Fastlane endpoint
await submit_bundle(pfl_bundle)
if __name__ == "__main__":
asyncio.run(main())
Ping
messages will be sent to your connection every 60 seconds. A pong
response must be sent to avoid disconnection. Alternatively, you can send ping
messages yourself to the server every minutes and get pong
responses.
To keep a websocket connection open and stable on a long term, we highly recommend to send ping
messages to the server every minutes, and to answer pong
every time the server sends a ping
message.
To better track responses (e.g. when sending multiple concurrent requests), it is highly advised to specify a unique id
for each new requests, see example below.
Example:
const WebSocket = require('ws');
// Abstracted function to create the PFL bundle with arguments
function createPflBundle(bundleId, opportunityRawTx, solverOpStruct) {
return {
id: bundleId,
jsonrpc: "2.0",
method: "pfl_addSearcherBundle",
params: [`${opportunityRawTx}`, `${JSON.stringify(solverOpStruct)}`]
};
}
// Helper function to submit the bundle to the Fastlane endpoint over WebSocket
async function submitBundle(bundle) {
const wsFastlaneEndpoint = "wss://beta-rpc.fastlane-labs.xyz/ws";
return new Promise((resolve, reject) => {
const ws = new WebSocket(wsFastlaneEndpoint);
ws.on('open', function open() {
// Send the bundle as a JSON-RPC request
ws.send(JSON.stringify(bundle));
});
ws.on('message', function incoming(data) {
const response = JSON.parse(data);
if (response.error) {
console.error(`Error submitting bundle ${bundle.id}`, response);
ws.close();
reject(response.error);
} else {
console.log(`Response received for bundle ${bundle.id}`, response);
ws.close();
resolve(response.result);
}
});
ws.on('error', function error(err) {
console.error(`WebSocket error for bundle ${bundle.id}`, err);
ws.close();
reject(err);
});
ws.on('close', function close(code, reason) {
console.log(`WebSocket connection closed: ${code} ${reason}`);
});
});
}
// Main function to submit the bundle
async function main() {
// Define your variables
const bundleId = 1;
const opportunityRawTx = "0x..."; // Replace with your actual opportunity raw transaction
const solverOpStruct = "0x..."; // Replace with your actual solver operation structure
// Create the PFL bundle
const pflBundle = createPflBundle(bundleId, opportunityRawTx, solverOpStruct);
// Submit the bundle to the Fastlane endpoint
await submitBundle(pflBundle);
}
main().catch(console.error);
import asyncio
import websockets
import json
# Function to create the PFL bundle with arguments
def create_pfl_bundle(bundleId, opportunityRawTx, solverOpStruct):
return {
"id": bundleId,
"jsonrpc": "2.0",
"method": "pfl_addSearcherBundle", # Ensure the method name matches the JS version
"params": [
f"{opportunityRawTx}", # Convert opportunityRawTx to string
f"{json.dumps(solverOpStruct)}" # Serialize solverOpStruct to JSON string
]
}
# Helper function to submit the bundle via WebSocket
async def submit_bundle(bundle):
websocket_endpoint = "wss://polygon-rpc.fastlane.xyz"
try:
async with websockets.connect(websocket_endpoint) as websocket:
await websocket.send(json.dumps(bundle))
response = await websocket.recv()
response_data = json.loads(response)
if 'error' in response_data:
print(f"Error submitting bundle {bundle['id']}:", response_data['error'])
else:
print(f"Response received for bundle {bundle['id']}:", response_data['result'])
except Exception as e:
print(f"Error submitting bundle {bundle['id']}:", e)
# Main function to submit the bundle
async def main():
# Wait until you're ready to send a bundle, refreshing session as necessary
# You might want to include some delay or conditions here
# Define your variables
bundleId = 1
opportunityRawTx = "0x..." # Replace with your actual opportunity raw transaction
solverOpStruct = "0x..." # Replace with your actual solver operation structure
# Create the PFL bundle with the specified arguments
pfl_bundle = create_pfl_bundle(bundleId, opportunityRawTx, solverOpStruct)
# Submit the bundle to the Fastlane endpoint
await submit_bundle(pfl_bundle)
if __name__ == "__main__":
asyncio.run(main())