Skip to main content

Overview

Polymarket’s Builders Program enables developers to integrate prediction markets into their applications with gasless trading and builder order attribution. This guide demonstrates how to use Magic’s passwordless authentication with Polymarket’s CLOB Client and Builder Relayer Client. This guide covers the Safe Wallet implementation using Magic authentication for gasless prediction market trading.

Magic Safe Builder Example

Complete Next.js application showing Magic authentication with Safe wallet deployment for Polymarket trading.

Prerequisites

Before starting, ensure you have:
  1. A Magic Publishable API Key from your Magic Dashboard
  2. Polymarket Builder credentials (Builder ID and signing key)
  3. A Polygon RPC endpoint

Safe Wallet Architecture

The Safe Wallet flow uses Magic SDK for authentication and the Builder Relayer Client to deploy Gnosis Safe wallets:
  1. User authenticates with Magic (Email OTP or Social Login)
  2. Magic SDK creates an EOA signer for the user
  3. Builder Relayer Client deploys a Gnosis Safe wallet
  4. Token approvals are set via the Relayer
  5. User API credentials are generated by initializing a temporary ClobClient with the Magic signer and calling deriveApiKey() or createApiKey().
  6. Authenticated ClobClient is initialized for trading
Store Builder credentials server-side only. Never expose signing keys in client code.
For the complete implementation with step-by-step code, see the magic-safe-builder-example repository.

Placing Orders

With the authenticated ClobClient, you can place market and limit orders.
TypeScript
import { Side, OrderType } from "@polymarket/clob-client";

async function submitMarketOrder(
  clobClient: ClobClient,
  tokenId: string,
  size: number,
  side: "BUY" | "SELL",
  negRisk: boolean = false
) {
  // Get current price from orderbook
  const oppositeSide = side === "BUY" ? Side.SELL : Side.BUY;
  const priceResponse = await clobClient.getPrice(tokenId, oppositeSide);
  const marketPrice = parseFloat(priceResponse.price);

  // Apply aggressive pricing for immediate fills
  let aggressivePrice: number;
  if (side === "BUY") {
    aggressivePrice = Math.min(0.99, marketPrice * 1.05); // +5% above market
  } else {
    aggressivePrice = Math.max(0.01, marketPrice * 0.95); // -5% below market
  }

  const order = {
    tokenID: tokenId,
    price: aggressivePrice,
    size: size,
    side: side === "BUY" ? Side.BUY : Side.SELL,
    feeRateBps: 0,
    expiration: 0,
    taker: "0x0000000000000000000000000000000000000000",
  };

  const response = await clobClient.createAndPostOrder(
    order,
    { negRisk },
    OrderType.GTC
  );

  return response.orderID;
}
Polymarket’s CLOB doesn’t have true “market orders”. Market orders are simulated using limit orders with aggressive pricing that fills immediately.
Order Execution:
  • Orders are signed by the user’s EOA (Magic wallet)
  • Executed from the Safe wallet address
  • Gasless execution - no gas fees for users
  • Prompts user signature for each order

Position & Order Management

Fetch User Positions

TypeScript
// Fetch from Polymarket Data API
const response = await fetch(
  `https://data-api.polymarket.com/positions?user=${safeAddress}&sizeThreshold=0.01&limit=500`
);
const positions = await response.json();

Fetch Active Orders

TypeScript
// Fetch from CLOB client
const allOrders = await clobClient.getOpenOrders();
const userOrders = allOrders.filter(
  (order) =>
    order.maker_address.toLowerCase() === safeAddress.toLowerCase() &&
    order.status === "LIVE"
);

Cancel Order

TypeScript
await clobClient.cancelOrder({ orderID: orderId });

Token Addresses

Important contract addresses on Polygon:
TypeScript
// USDC.e (Bridged USDC) - The trading currency
export const USDC_E_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
export const USDC_E_DECIMALS = 6;

// Conditional Token Framework
export const CTF_ADDRESS = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045";

// Exchanges
export const CTF_EXCHANGE = "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E";
export const NEG_RISK_CTF_EXCHANGE = "0xC5d563A36AE78145C45a50134d48A1215220f80a";
export const NEG_RISK_ADAPTER = "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296";

Key Dependencies

PackageVersionPurpose
@polymarket/clob-client^4.22.8Order placement, User API credentials
@polymarket/builder-relayer-client^0.0.8Safe deployment, token approvals
@polymarket/builder-signing-sdk^0.0.8Builder configuration
magic-sdklatestMagic authentication
ethers^5.8.0Wallet creation, signing
viem^2.39.2Ethereum interactions

Troubleshooting

Symptoms: Cannot deploy Safe walletSolutions:
  • Ensure Builder credentials are valid
  • Check that the Relayer service is accessible
  • Verify the Magic user is authenticated
  • Check server-side logs for signing errors
Symptoms: Cannot place orders, trading session incompleteSolutions:
  • Click “Initialize Trading Session” button
  • Ensure Magic authentication is valid
  • Check browser console for authentication errors
  • Verify User API Credentials were obtained successfully
Symptoms: USDC.e balance appears as zeroSolutions:
  • Fund the Safe Wallet, not the EOA
  • Check Polygonscan for confirmation
  • Verify RPC endpoint is working in .env.local
  • The wallet address is shown in the header UI
Symptoms: Orders submitted but not visibleSolutions:
  • Wait 2-3 seconds for CLOB sync
  • Check USDC.e balance (need funds to trade)
  • Verify order was submitted successfully in browser console
  • Ensure the wallet is properly funded

Resources