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

# Deposit Wallets

> Everything you need to know about Polymarket's new deposit wallet system and how it affects your integration.

Polymarket is rolling out **deposit wallets** as a new account type alongside the existing Gnosis Safe proxy wallets. This guide explains what changed, whether you need to do anything, and how to handle both wallet types in your integration.

## What are deposit wallets?

Deposit wallets are Polymarket's new smart contract wallet type for new accounts. They replace the Gnosis Safe proxy that existing accounts use.

**Heard the term "beacon wallet"?** It's the same thing. Newer deposit wallets are built so Polymarket can upgrade all of them at once — that upgradeable variant is what gets called a beacon wallet. There's also an earlier standalone variant from before that change. Both behave identically, and everything on this page (and the [/resolve endpoint](/api-reference/wallets/resolve)) handles both — you never need to tell them apart.

From your perspective as a builder, the key differences are:

|                               | Safe proxy (existing)      | Deposit wallet (new)                        |
| ----------------------------- | -------------------------- | ------------------------------------------- |
| **Signature type**            | `2` (POLY\_GNOSIS\_SAFE)   | `3` (POLY\_1271)                            |
| **How addresses are derived** | CREATE2 from Safe factory  | CREATE2 from deposit wallet factory         |
| **Order signing**             | Standard EIP-712           | EIP-712 with ERC-7739 TypedDataSign wrapper |
| **Approvals**                 | Gasless via Safe multisend | Gasless via WALLET batch                    |
| **V1 support**                | Yes                        | No (V2 only)                                |

**The good news:** if you use the polynode SDK, all of this is handled automatically. `ensureReady()` detects the wallet type, `order()` signs correctly, and the `/resolve` endpoint resolves both wallet types.

## Do I need to change anything?

**If you use the polynode SDK for trading:** update to the latest version. Everything else is automatic.

```bash theme={null}
# Current beacon-aware wallet resolution and onboarding
cargo add polynode@0.17.0 --features trading
npm install polynode-sdk@^0.14.1
python -m pip install "polynode[trading]>=0.14.0,<0.15"
```

**If you only read data (positions, trades, /resolve):** existing fields are unchanged. `/resolve` still returns `safe`, `eoa`, `username`, and `type` exactly as before. It also returns the deployed-only `wallets` object and a `wallet_details` list with plain `wallet_type`, `deployed`, and `current` status for each relevant address.

**If you call the Polymarket CLOB directly (without our SDK):** you need to implement ERC-7739 TypedDataSign wrapping for `signatureType: 3` orders. See the [signing details](#how-poly_1271-signing-works) below.

## How to detect wallet type

For trading, the SDK auto-detects wallet type when you call `ensureReady()` or `detectWalletType()`. Detection checks on-chain in this order:

1. Safe deployed? -> `POLY_GNOSIS_SAFE` (type 2)
2. Proxy deployed? -> `POLY_PROXY` (type 1)
3. Deposit wallet deployed? -> `POLY_1271` (type 3)
4. Nothing deployed -> defaults to `POLY_GNOSIS_SAFE` (new Safe will be created)

This controls how the SDK signs orders. The `/resolve` identity endpoint uses a different rule for compatibility with Polymarket's deposit-wallet migration: if a resolved EOA has a deployed deposit wallet, `/resolve` returns that deposit wallet in `safe`.

That list describes the general server-signer trader. The dedicated
`BrowserUserOwnedSession` used by [Connect Wallet to order](/sdks/user-owned-web-app)
defaults a new injected-wallet session to type 3, supports an explicit type 0
EOA, and preserves an existing type 2 Safe through the backend-vault model.

```typescript theme={null}
import { PolyNodeTrader } from 'polynode-sdk';

const trader = new PolyNodeTrader({ polynodeKey: 'pn_live_...' });
const status = await trader.ensureReady(privateKey);

console.log(status.signatureType);
// 2 = Safe (existing user)
// 3 = Deposit wallet (new user)

// Either way, order() works the same:
await trader.order({ tokenId: '...', side: 'BUY', price: 0.55, size: 100 });
```

## How to handle mixed user bases

If your platform has existing Safe users and new deposit wallet users, no special handling is needed. The SDK stores each user's wallet type in the local database and uses the correct signing method automatically.

```typescript theme={null}
// User A: existing Safe wallet
await trader.ensureReady(userA_privateKey);
// status.signatureType === 2, uses standard EIP-712

await trader.order({ tokenId: '...', side: 'BUY', price: 0.5, size: 50 });

// User B: new deposit wallet
await trader.ensureReady(userB_privateKey);
// status.signatureType === 3, uses ERC-7739 TypedDataSign wrapper

await trader.order({ tokenId: '...', side: 'BUY', price: 0.5, size: 50 });
// Same API, different signing under the hood
```

## Wallet address resolution

Current deposit wallets can use either the earlier standalone UUPS deployment
or the active factory beacon. Resolve the current address against Polygon before
funding it. The older synchronous `deriveDepositWalletAddress()` /
`derive_deposit_wallet_address()` helpers derive only the legacy UUPS address
and are deprecated for live wallet selection.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { deriveSafeAddress, resolveDepositWalletAddress } from 'polynode-sdk';
  import { createPublicClient, http } from 'viem';
  import { polygon } from 'viem/chains';

  const eoa = '0xA60601A4d903af91855C52BFB3814f6bA342f201';
  const provider = createPublicClient({
    chain: polygon,
    transport: http(process.env.POLYGON_RPC_URL),
  });
  const depositWallet = await resolveDepositWalletAddress(provider, eoa);
  const safe = await deriveSafeAddress(eoa);
  ```

  ```python Python theme={null}
  import os
  from polynode.trading import resolve_deposit_wallet_address, derive_safe_address

  eoa = "0xA60601A4d903af91855C52BFB3814f6bA342f201"
  deposit_wallet = await resolve_deposit_wallet_address(
      eoa,
      rpc_url=os.environ["POLYGON_RPC_URL"],
  )
  safe = derive_safe_address(eoa)
  ```

  ```rust Rust theme={null}
  use polynode::trading::{
      derive_safe_address, resolve_deposit_wallet_address, Address,
  };

  let eoa: Address = "0xA60601A4d903af91855C52BFB3814f6bA342f201".parse()?;
  let rpc_url = std::env::var("POLYGON_RPC_URL")?;
  let deposit_wallet = resolve_deposit_wallet_address(eoa, &rpc_url).await?;
  let safe = derive_safe_address(eoa);
  ```
</CodeGroup>

Both possible deposit addresses are deterministic for an EOA, but the factory's
current beacon state determines which address is active. A deployed legacy UUPS
wallet remains authoritative.

## The /resolve endpoint

The [Resolve Wallet](/api-reference/wallets/resolve) endpoint keeps the same fields and prioritizes deposit wallets in the existing `safe` field. The field name remains `safe` for backward compatibility.

```bash theme={null}
curl "https://api.polynode.dev/v1/resolve/0x8b60bf0f650bf7a0d93f10d72375b37de18f8c40" \
  -H "x-api-key: YOUR_KEY"
```

```json theme={null}
{
  "safe": "0x8b60bf0f650bf7a0d93f10d72375b37de18f8c40",
  "eoa": "0xa60601a4d903af91855c52bfb3814f6ba342f201",
  "username": null,
  "type": "deposit_wallet",
  "wallets": {
    "deposit_wallet": "0x8b60bf0f650bf7a0d93f10d72375b37de18f8c40",
    "safe": null,
    "proxy_wallet": null
  },
  "wallet_details": [
    {
      "address": "0x8b60bf0f650bf7a0d93f10d72375b37de18f8c40",
      "wallet_type": "deposit_wallet",
      "deployed": true,
      "current": true
    }
  ]
}
```

The `safe` field contains the preferred trading wallet address. If the controlling EOA has a deployed deposit wallet, `safe` is the deposit wallet. Otherwise it is the existing Safe/proxy wallet. The `type` field tells you which kind of wallet was returned. `deployed` and `current` are separate booleans in `wallet_details`, so an address can still be identified as a deposit wallet before its contract is deployed.

| `type` value       | Description                                |
| ------------------ | ------------------------------------------ |
| `"safe"`           | Gnosis Safe proxy (most existing accounts) |
| `"deposit_wallet"` | Deposit wallet (newer accounts)            |
| `"proxy"`          | Legacy proxy wallet                        |

Both forward resolution (EOA -> wallet) and reverse resolution (wallet -> EOA) work for all wallet types. When both a Safe and deposit wallet exist, deposit wallet wins.

## How POLY\_1271 signing works

<Note>
  You only need this section if you're implementing signing without the polynode SDK. If you use `signV2Order()` or `trader.order()`, this is handled automatically.
</Note>

For deposit wallet users, V2 orders use `signatureType: 3` (POLY\_1271). The signing process wraps the standard Order EIP-712 hash in a Solady TypedDataSign struct:

1. Build the standard V2 Order struct (same fields as type 0/1/2)
2. Set `maker` and `signer` to the **deposit wallet address** (not the EOA)
3. Sign using `TypedDataSign` as the EIP-712 primary type under the exchange domain, with the deposit wallet parameters as struct fields
4. Wrap the resulting signature: `innerSig (65 bytes) + appDomainSeparator (32 bytes) + contentsHash (32 bytes) + orderTypeString (186 bytes) + typeStringLength (2 bytes)`

The final wrapped signature is 317 bytes (634 hex chars + "0x" prefix = 636 total).

The `TypedDataSign` struct includes the deposit wallet's identity:

* `name`: `"DepositWallet"`
* `version`: `"1"`
* `verifyingContract`: the deposit wallet address
* `salt`: `bytes32(0)`

## FAQ

<AccordionGroup>
  <Accordion title="Do existing Safe wallet users need to change anything?">
    No. Safe wallets continue to work exactly as before. The SDK detects your wallet type automatically. All existing integrations are backward compatible.
  </Accordion>

  <Accordion title="Will my /resolve API responses break?">
    No. No existing field was renamed or removed. The endpoint still returns `safe`, `eoa`, `username`, `type`, and `wallets`; `wallet_details` is additive.
  </Accordion>

  <Accordion title="Can I still create new Safe wallets?">
    Yes. The general server-signer trader defaults to a Safe when no wallet is
    detected on-chain. The specialized injected-wallet user-owned session instead
    defaults to an order-capable deposit wallet and completes its readiness flow
    through the connected wallet. Choose the documented entry point deliberately;
    neither silently changes an existing account type.
  </Accordion>

  <Accordion title="What SDK version do I need?">
    For current beacon-aware resolution, wallet-owned authorization, and full
    onboarding, use TypeScript `polynode-sdk >= 0.14.1`, Python
    `polynode >= 0.14.0,<0.15`, or Rust `polynode >= 0.17.0` with the `trading`
    feature. These releases also include the complete browser-signing flow in
    [Connect Wallet to order](/sdks/user-owned-web-app).
  </Accordion>

  <Accordion title="What if a user has both a Safe and a deposit wallet?">
    For `/resolve`, the deposit wallet is returned in `safe` when it is deployed. The field name stays `safe` so existing clients do not need to parse a new field. `wallet_details` lists both addresses and shows which one is current and whether each is deployed.
  </Accordion>

  <Accordion title="Do deposit wallets work with V1 orders?">
    No. POLY\_1271 (signature type 3) is V2 only. V1 orders only support types 0 (EOA), 1 (POLY\_PROXY), and 2 (POLY\_GNOSIS\_SAFE). Since Polymarket's V2 exchange is now live, all new activity uses V2.
  </Accordion>

  <Accordion title="How do I know which wallet type to use for copy trading?">
    Register followers with their actual `sig_type` (2 for Safe, 3 for deposit wallet). The copy trading engine automatically generates the correct typed data for each follower's wallet type. Your signing code should use `signV2Order()` from the SDK, which handles both types transparently.
  </Accordion>

  <Accordion title="Is there a performance difference?">
    Deposit wallet signatures are larger (317 bytes vs 65 bytes) due to the ERC-7739 wrapping, but this has no meaningful impact on order submission speed or gas costs. The CLOB processes both types identically.
  </Accordion>
</AccordionGroup>
