> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 免 Gas 交易

> 无需支付 gas 费即可执行链上操作

Polymarket 的 **Relayer Client** 为你的用户提供免 gas 交易功能。用户无需持有 POL 来支付 gas 费,Polymarket 的基础设施会支付所有交易费用。这创造了一种无缝体验,用户只需要 pUSD 就能交易。

## 工作原理

relayer 充当交易赞助者:

1. 你的应用创建一笔交易
2. 用户用私钥签名
3. 你的应用将交易发送到 Polymarket 的 relayer
4. relayer 将交易提交到链上并支付 gas 费
5. 交易从用户钱包执行

## 覆盖范围

Polymarket 为通过 relayer 路由的所有操作支付 gas:

| 操作                    | 说明                     |
| --------------------- | ---------------------- |
| **Wallet deployment** | 为新用户部署 Safe 或 Proxy 钱包 |
| **Token approvals**   | 授权合约使用 pUSD 或结果代币      |
| **CTF operations**    | 拆分、合并和兑换仓位             |
| **Transfers**         | 在地址之间转移代币              |

## 身份验证

relayer 使用 **Relayer API Keys**。你可以在 Polymarket 网站的 [Settings > API Keys](https://polymarket.com/settings?tab=api-keys) 创建。

<Note>
  **已经有 builder 签名密钥？** 你现有的基于 HMAC 的 builder API key 在 Relayer 上继续有效 — 无需轮换或重新签发。CLOB V2 中只有订单签名迁移到原生的 `builderCode` 字段。详见[迁移到 CLOB V2](/v2-migration#builder-program)。
</Note>

请求中需要包含以下 header:

| Header                    | 说明                 |
| ------------------------- | ------------------ |
| `RELAYER_API_KEY`         | 你的 Relayer API key |
| `RELAYER_API_KEY_ADDRESS` | 拥有该 key 的地址        |

<Info>
  如果你想直接使用 Relayer API Key 而不使用 SDK,请参阅 [Relayer API Reference](/api-reference/relayer)。
</Info>

## 前置要求

使用 relayer 之前,你需要:

| 要求              | 来源                                                                  |
| --------------- | ------------------------------------------------------------------- |
| Relayer API Key | [Settings > API Keys](https://polymarket.com/settings?tab=api-keys) |
| 用户的私钥或签名器       | 你的钱包集成                                                              |
| pUSD 余额         | 用于交易(不是用于 gas)                                                      |

## 安装

<CodeGroup>
  ```bash npm theme={null}
  npm install @polymarket/builder-relayer-client
  ```

  ```bash pip theme={null}
  pip install py-builder-relayer-client
  ```
</CodeGroup>

## 客户端设置

使用你的 Relayer API Key 初始化 relayer 客户端:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { createWalletClient, http, Hex } from "viem";
  import { privateKeyToAccount } from "viem/accounts";
  import { polygon } from "viem/chains";
  import { RelayClient } from "@polymarket/builder-relayer-client";

  const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);
  const wallet = createWalletClient({
    account,
    chain: polygon,
    transport: http(process.env.RPC_URL),
  });

  const client = new RelayClient({
    host: "https://relayer-v2.polymarket.com/",
    chain: 137,
    signer: wallet,
    relayerApiKey: process.env.RELAYER_API_KEY!,
    relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
  });
  ```

  ```python Python theme={null}
  import os
  from py_builder_relayer_client.client import RelayClient

  client = RelayClient(
      host="https://relayer-v2.polymarket.com",
      chain=137,
      signer=os.getenv("PRIVATE_KEY"),
      relayer_api_key=os.environ["RELAYER_API_KEY"],
      relayer_api_key_address=os.environ["RELAYER_API_KEY_ADDRESS"],
  )
  ```
</CodeGroup>

<Warning>
  永远不要在客户端代码中暴露你的 Relayer API Key。使用环境变量或密钥管理器。
</Warning>

## 钱包类型

初始化客户端时选择钱包类型:

| 类型        | 部署方式                | 最适用于           |
| --------- | ------------------- | -------------- |
| **Safe**  | 在首次交易前调用 `deploy()` | 大多数 builder 集成 |
| **Proxy** | 首次交易时自动部署           | Magic Link 用户  |

<CodeGroup>
  ```typescript Safe Wallet (TypeScript) theme={null}
  import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client";

  const client = new RelayClient({
    host: "https://relayer-v2.polymarket.com/",
    chain: 137,
    signer: wallet,
    relayerApiKey: process.env.RELAYER_API_KEY!,
    relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
    txType: 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 (Python) theme={null}
  from py_builder_relayer_client.client import RelayClient

  # client initialized with relayer credentials (see Client Setup above)

  # Deploy before first transaction
  response = client.deploy()
  result = response.wait()
  print("Safe Address:", result.get("proxyAddress"))
  ```

  ```typescript Proxy Wallet (TypeScript) theme={null}
  import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client";

  const client = new RelayClient({
    host: "https://relayer-v2.polymarket.com/",
    chain: 137,
    signer: wallet,
    relayerApiKey: process.env.RELAYER_API_KEY!,
    relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
    txType: RelayerTxType.PROXY,
  });

  // No deploy needed - auto-deploys on first transaction
  ```

  ```python Proxy Wallet (Python) theme={null}
  from py_builder_relayer_client.client import RelayClient

  # client initialized with relayer credentials (see Client Setup above)
  # No deploy needed - auto-deploys on first transaction
  ```
</CodeGroup>

## 执行交易

使用 `execute` 方法通过 relayer 发送交易:

```typescript theme={null}
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();
```

### 代币授权

授权合约使用代币:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { encodeFunctionData, maxUint256 } from "viem";

  const pUSD = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB";
  const CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045";

  const approveTx = {
    to: pUSD,
    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 pUSD for CTF");
  await response.wait();
  ```

  ```python Python theme={null}
  from web3 import Web3

  pUSD = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"
  CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
  MAX_UINT256 = 2**256 - 1

  approve_tx = {
      "to": pUSD,
      "data": Web3().eth.contract(
          address=pUSD,
          abi=[{
              "name": "approve",
              "type": "function",
              "inputs": [
                  {"name": "spender", "type": "address"},
                  {"name": "amount", "type": "uint256"}
              ],
              "outputs": [{"type": "bool"}]
          }]
      ).encode_abi(abi_element_identifier="approve", args=[CTF, MAX_UINT256]),
      "value": "0"
  }

  response = client.execute([approve_tx], "Approve pUSD for CTF")
  response.wait()
  ```
</CodeGroup>

### 兑换仓位

市场判定后,将获胜代币兑换为 pUSD:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { encodeFunctionData } from "viem";

  const redeemTx = {
    to: CTF_ADDRESS,
    data: encodeFunctionData({
      abi: [
        {
          name: "redeemPositions",
          type: "function",
          inputs: [
            { name: "collateralToken", type: "address" },
            { name: "parentCollectionId", type: "bytes32" },
            { name: "conditionId", type: "bytes32" },
            { name: "indexSets", type: "uint256[]" },
          ],
          outputs: [],
        },
      ],
      functionName: "redeemPositions",
      args: [collateralToken, parentCollectionId, conditionId, indexSets],
    }),
    value: "0",
  };

  const response = await client.execute([redeemTx], "Redeem positions");
  await response.wait();
  ```

  ```python Python theme={null}
  CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"

  redeem_tx = {
      "to": CTF,
      "data": Web3().eth.contract(
          address=CTF,
          abi=[{
              "name": "redeemPositions",
              "type": "function",
              "inputs": [
                  {"name": "collateralToken", "type": "address"},
                  {"name": "parentCollectionId", "type": "bytes32"},
                  {"name": "conditionId", "type": "bytes32"},
                  {"name": "indexSets", "type": "uint256[]"}
              ],
              "outputs": []
          }]
      ).encode_abi(
          abi_element_identifier="redeemPositions",
          args=[collateral_token, parent_collection_id, condition_id, index_sets]
      ),
      "value": "0"
  }

  response = client.execute([redeem_tx], "Redeem positions")
  response.wait()
  ```
</CodeGroup>

### 批量交易

在单次调用中原子性地执行多个操作:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const approveTx = {
    to: pUSD,
    data: encodeFunctionData({
      abi: erc20Abi,
      functionName: "approve",
      args: [CTF, maxUint256],
    }),
    value: "0",
  };

  const transferTx = {
    to: pUSD,
    data: encodeFunctionData({
      abi: erc20Abi,
      functionName: "transfer",
      args: [recipientAddress, parseUnits("50", 6)],
    }),
    value: "0",
  };

  // Both execute atomically
  const response = await client.execute(
    [approveTx, transferTx],
    "Approve and transfer",
  );
  await response.wait();
  ```

  ```python Python theme={null}
  approve_tx = {
      "to": pUSD,
      "data": contract.encode_abi(
          abi_element_identifier="approve",
          args=[CTF, MAX_UINT256]
      ),
      "value": "0"
  }

  transfer_tx = {
      "to": pUSD,
      "data": contract.encode_abi(
          abi_element_identifier="transfer",
          args=[recipient_address, 50 * 10**6]
      ),
      "value": "0"
  }

  # Both execute atomically
  response = client.execute([approve_tx, transfer_tx], "Approve and transfer")
  response.wait()
  ```
</CodeGroup>

<Tip>
  批量处理可以减少延迟,并确保所有交易要么全部成功,要么全部失败。
</Tip>

## 交易状态

通过这些状态跟踪交易进度:

| 状态                | 终态 | 说明            |
| ----------------- | -- | ------------- |
| `STATE_NEW`       | 否  | relayer 已收到交易 |
| `STATE_EXECUTED`  | 否  | 已提交到链上        |
| `STATE_MINED`     | 否  | 已打包进区块        |
| `STATE_CONFIRMED` | 是  | 成功确认          |
| `STATE_FAILED`    | 是  | 永久失败          |
| `STATE_INVALID`   | 是  | 被拒绝为无效        |

## 合约地址

所有 Polymarket 智能合约地址详见[合约](/resources/contracts)。

## 资源

* [Builder Relayer Client (TypeScript)](https://github.com/Polymarket/builder-relayer-client)
* [Builder Relayer Client (Python)](https://github.com/Polymarket/py-builder-relayer-client)

## 下一步

<CardGroup cols={2}>
  <Card title="Negative Risk Markets" icon="scale-balanced" href="/advanced/neg-risk">
    了解多结果事件的资本高效交易。
  </Card>

  <Card title="Positions & Tokens" icon="coins" href="/concepts/positions-tokens">
    理解拆分、合并和兑换等代币操作。
  </Card>
</CardGroup>
