Skip to content

Gasless Transactions

Openfish provides a relayer that covers gas costs on behalf of users. You sign a meta-transaction, hand it off to the relayer, and the relayer broadcasts it on-chain. The only token you need to trade is USDC.e — no POL required.


  1. Client requests a structured payload from GET /relay-payload specifying the transaction type and parameters
  2. Server builds an EIP-712 typed payload that includes the user’s next nonce
  3. Client signs the payload with their private key
  4. Client posts the signed result to POST /submit
  5. Relayer bumps the nonce, logs the transaction, and submits it on-chain
  6. Client polls GET /transaction?id={id} to watch progress

Send a signed meta-transaction for on-chain execution. L2 authentication is required.

Request body:

{
"txType": "APPROVE",
"data": {
"signature": "0x...",
"conditionId": "0x...",
"amount": "1000000"
}
}

Response:

{
"id": "a1b2c3d4-...",
"status": "PENDING",
"nonce": 1
}

Retrieve the current meta-transaction nonce for an address. No authentication needed.

Terminal window
GET /nonce?address=0x...

Response:

{
"nonce": 5
}

Build an EIP-712 meta-transaction payload ready for the user to sign. The payload bundles the next nonce and every parameter needed for the on-chain call.

Terminal window
GET /relay-payload?address=0x...&txType=APPROVE&conditionId=0x...&amount=1000000

Response:

{
"types": {
"EIP712Domain": [
{ "name": "name", "type": "string" },
{ "name": "version", "type": "string" },
{ "name": "chainId", "type": "uint256" }
],
"MetaTransaction": [
{ "name": "nonce", "type": "uint256" },
{ "name": "from", "type": "address" },
{ "name": "txType", "type": "string" },
{ "name": "conditionId", "type": "bytes32" },
{ "name": "amount", "type": "uint256" }
]
},
"primaryType": "MetaTransaction",
"domain": {
"name": "Openfish CTF Relayer",
"version": "1",
"chainId": 137
},
"message": {
"nonce": 6,
"from": "0x...",
"txType": "APPROVE",
"conditionId": "0x...",
"amount": "1000000"
}
}

Determine whether a proxy wallet has been deployed for a given address.

Terminal window
GET /deployed?address=0x...

Response:

{
"deployed": true
}

Look up the current state of a relay transaction by its ID.

Terminal window
GET /transaction?id=a1b2c3d4-...

Response:

{
"id": "a1b2c3d4-...",
"owner": "0x...",
"txType": "APPROVE",
"status": "CONFIRMED",
"txHash": "0x...",
"nonce": 1,
"data": { ... },
"createdAt": "2025-01-15T10:30:00Z"
}

List relay transactions for an address, with pagination support.

Terminal window
GET /transactions?address=0x...&limit=50&offset=0

Below is a complete Rust example that fetches a relay payload, signs it, and submits it:

use openfish_client_sdk::auth::{LocalSigner, Signer};
use reqwest::Client as HttpClient;
use serde_json::Value;
let http = HttpClient::new();
let host = "https://api.openfish.fun";
// Step 1: Get the relay payload
let payload: Value = http
.get(format!("{host}/relay-payload"))
.query(&[
("address", signer.address().to_string().as_str()),
("txType", "APPROVE"),
])
.send()
.await?
.json()
.await?;
// Step 2: Sign the EIP-712 payload with your wallet
// (Use alloy's EIP-712 signing utilities to hash and sign the typed data)
// Step 3: Submit to the relayer
let response: Value = http
.post(format!("{host}/submit"))
.header("OPENFISH_ADDRESS", signer.address().to_string())
.header("OPENFISH_API_KEY", api_key)
.header("OPENFISH_PASSPHRASE", passphrase)
.header("OPENFISH_SIGNATURE", hmac_signature)
.header("OPENFISH_TIMESTAMP", timestamp)
.json(&serde_json::json!({
"txType": "APPROVE",
"data": {
"signature": signed_payload,
}
}))
.send()
.await?
.json()
.await?;
println!("Relay TX: {}", response["id"]);

StateTerminalDescription
PENDINGNoTransaction received by the relayer
SUBMITTEDNoSubmitted onchain, awaiting confirmation
CONFIRMEDYesFinalized successfully
FAILEDYesTransaction failed permanently

Transaction TypeDescription
APPROVEApprove the Exchange contract to spend USDC.e or outcome tokens
SPLITSplit USDC.e into Yes/No outcome token pairs
MERGEMerge outcome token pairs back into USDC.e
REDEEMRedeem winning tokens for USDC.e after market resolution