6.3 KiB
6.3 KiB
Gasless Transactions
Polymarket's Relayer Client enables gasless transactions. Instead of requiring users to hold POL, Polymarket's infrastructure pays gas fees. Users only need USDC.e to trade.
Requires Builder Program membership. You need Builder API credentials.
How It Works
- Your app creates a transaction
- User signs it with their private key
- App sends to Polymarket's relayer
- Relayer submits onchain and pays gas
- Transaction executes from the user's wallet
What's Covered
| Operation | Description |
|---|---|
| Wallet deployment | Deploy Safe or Proxy wallets for new users |
| Token approvals | Approve contracts to spend USDC.e or outcome tokens |
| CTF operations | Split, merge, redeem positions |
| Transfers | Move tokens between addresses |
Installation
# TypeScript
npm install @polymarket/builder-relayer-client @polymarket/builder-signing-sdk
# Python
pip install py-builder-relayer-client py-builder-signing-sdk
Client Setup
TypeScript (Local Signing)
import { createWalletClient, http, Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { polygon } from "viem/chains";
import { RelayClient } from "@polymarket/builder-relayer-client";
import { BuilderConfig } from "@polymarket/builder-signing-sdk";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);
const wallet = createWalletClient({
account,
chain: polygon,
transport: http(process.env.RPC_URL),
});
const builderConfig = new BuilderConfig({
localBuilderCreds: {
key: process.env.POLY_BUILDER_API_KEY!,
secret: process.env.POLY_BUILDER_SECRET!,
passphrase: process.env.POLY_BUILDER_PASSPHRASE!,
},
});
const client = new RelayClient(
"https://relayer-v2.polymarket.com/",
137,
wallet,
builderConfig
);
Python (Local Signing)
import os
from py_builder_relayer_client.client import RelayClient
from py_builder_signing_sdk import BuilderConfig, BuilderApiKeyCreds
builder_config = BuilderConfig(
local_builder_creds=BuilderApiKeyCreds(
key=os.getenv("POLY_BUILDER_API_KEY"),
secret=os.getenv("POLY_BUILDER_SECRET"),
passphrase=os.getenv("POLY_BUILDER_PASSPHRASE"),
)
)
client = RelayClient(
"https://relayer-v2.polymarket.com",
137,
os.getenv("PRIVATE_KEY"),
builder_config,
)
Remote Signing
Keep credentials on your server. Client points to signing endpoint:
// TypeScript
const builderConfig = new BuilderConfig({
remoteBuilderConfig: { url: "https://your-server.com/sign" },
});
const client = new RelayClient(
"https://relayer-v2.polymarket.com/",
137,
wallet,
builderConfig
);
# Python
from py_builder_signing_sdk import BuilderConfig, RemoteBuilderConfig
builder_config = BuilderConfig(
remote_builder_config=RemoteBuilderConfig(url="https://your-server.com/sign")
)
client = RelayClient("https://relayer-v2.polymarket.com", 137, pk, builder_config)
Wallet Types
| Type | Deployment | Best For |
|---|---|---|
| Safe | Call deploy() before first transaction |
Most builder integrations |
| Proxy | Auto-deploys on first transaction | Magic Link users |
// TypeScript — Safe wallet
import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client";
const client = new RelayClient(
"https://relayer-v2.polymarket.com/",
137,
wallet,
builderConfig,
RelayerTxType.SAFE
);
// Deploy before first transaction
const response = await client.deploy();
const result = await response.wait();
console.log("Safe Address:", result?.proxyAddress);
# Python — Safe wallet
response = client.deploy()
result = response.wait()
print("Safe Address:", result.get("proxyAddress"))
Executing Transactions
interface Transaction {
to: string; // Target contract address
data: string; // Encoded function call
value: string; // POL to send (usually "0")
}
const response = await client.execute(transactions, "Description");
const result = await response.wait();
Token Approval Example
import { encodeFunctionData, maxUint256 } from "viem";
const USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045";
const approveTx = {
to: USDC,
data: encodeFunctionData({
abi: [{
name: "approve", type: "function",
inputs: [{ name: "spender", type: "address" }, { name: "amount", type: "uint256" }],
outputs: [{ type: "bool" }],
}],
functionName: "approve",
args: [CTF, maxUint256],
}),
value: "0",
};
const response = await client.execute([approveTx], "Approve USDC.e for CTF");
await response.wait();
Batch Transactions
Execute multiple operations atomically in a single call:
const response = await client.execute(
[approveTx, transferTx],
"Approve and transfer"
);
await response.wait();
Transaction States
| State | Terminal | Description |
|---|---|---|
STATE_NEW |
No | Received by relayer |
STATE_EXECUTED |
No | Submitted onchain |
STATE_MINED |
No | Included in a block |
STATE_CONFIRMED |
Yes | Finalized successfully |
STATE_FAILED |
Yes | Failed permanently |
STATE_INVALID |
Yes | Rejected as invalid |
Builder Setup
- Go to polymarket.com/settings?tab=builder
- Create builder profile + generate API keys
- Implement builder signing in your CLOB client
- All orders automatically attributed to your builder account
Contract Addresses
| Contract | Address | Approval Needed |
|---|---|---|
| USDC.e (Bridged USDC) | 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 |
— |
| CTF | 0x4D97DCd97eC945f40cF65F87097ACe5EA0476045 |
USDC.e |
| CTF Exchange | 0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E |
USDC.e, Tokens |
| Neg Risk CTF Exchange | 0xC5d563A36AE78145C45a50134d48A1215220f80a |
USDC.e, Tokens |
| Neg Risk Adapter | 0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296 |
Tokens |