# Split / Merge / Redeem

> Build Safe transactions for on-chain token operations.

All methods in this page follow the same pattern: **build** the transaction, have the **user sign** it, then **submit** it to the backend for relay.

## Common Pattern

```python
# 1. Build the transaction
tx_result = builder.build_split_tx(...)   # or build_merge_tx, build_redeem_tx, build_withdraw_tx

# 2. User signs the EIP-712 data
signature = user.sign_typed_data(tx_result["eip712_data"])

# 3. Submit to backend
result = builder.submit_safe_tx(
    wallet_address=user_address,
    safe_tx_result=tx_result,
    signature=signature,
)
```

All build methods return:

```python
{
    "safe_tx": <SafeTx>,             # SafeTx object
    "eip712_data": { ... },          # EIP-712 data for user signing
    "safe_tx_hash": "0xabcdef...",   # Safe transaction hash
    "submission_data_template": { ... },
}
```

## Split Position

Convert collateral tokens (e.g., USDC) into Yes and No outcome tokens.

```python
tx_result = builder.build_split_tx(
    safe_address="0xSafeAddress...",
    collateral_token="0xQuoteTokenAddress...",
    condition_id="0xConditionId...",
    amount=1000000,          # Amount in wei (e.g., 1 USDC = 1000000 for 6 decimals)
    partition=[1, 2],        # Default: [1, 2] for binary outcomes
)
```

| Parameter          | Type       | Required | Description                                           |
| ------------------ | ---------- | -------- | ----------------------------------------------------- |
| `safe_address`     | str        | Yes      | User's Safe wallet address                            |
| `collateral_token` | str        | Yes      | Quote token contract address                          |
| `condition_id`     | str        | Yes      | Market condition ID (hex string, from `get_market()`) |
| `amount`           | int        | Yes      | Amount in wei                                         |
| `partition`        | list\[int] | No       | Partition array (default: `[1, 2]`)                   |

## Merge Position

Convert equal amounts of Yes and No outcome tokens back into collateral.

```python
tx_result = builder.build_merge_tx(
    safe_address="0xSafeAddress...",
    collateral_token="0xQuoteTokenAddress...",
    condition_id="0xConditionId...",
    amount=1000000,
    partition=[1, 2],
)
```

Parameters are identical to `build_split_tx()`.

## Redeem Position

Claim winnings from a resolved market. Converts winning outcome tokens back into collateral.

```python
tx_result = builder.build_redeem_tx(
    safe_address="0xSafeAddress...",
    collateral_token="0xQuoteTokenAddress...",
    condition_id="0xConditionId...",
    partition=[1, 2],
)
```

| Parameter          | Type       | Required | Description                         |
| ------------------ | ---------- | -------- | ----------------------------------- |
| `safe_address`     | str        | Yes      | User's Safe wallet address          |
| `collateral_token` | str        | Yes      | Quote token contract address        |
| `condition_id`     | str        | Yes      | Market condition ID                 |
| `partition`        | list\[int] | No       | Partition array (default: `[1, 2]`) |

Note: `build_redeem_tx()` does not take an `amount` parameter. It redeems all eligible tokens.

## Withdraw Tokens

Transfer ERC20 tokens from the Safe wallet to any address.

```python
tx_result = builder.build_withdraw_tx(
    safe_address="0xSafeAddress...",
    token_address="0xTokenAddress...",
    amount=1000000,              # Amount in wei
    to_address="0xRecipientAddress...",
)
```

| Parameter       | Type | Required | Description                     |
| --------------- | ---- | -------- | ------------------------------- |
| `safe_address`  | str  | Yes      | User's Safe wallet address      |
| `token_address` | str  | Yes      | ERC20 token address to withdraw |
| `amount`        | int  | Yes      | Amount in wei                   |
| `to_address`    | str  | Yes      | Recipient address               |

## Submit Safe Transaction

All build methods produce a result that is submitted via `submit_safe_tx()`:

```python
result = builder.submit_safe_tx(
    wallet_address=user_address,      # User's EOA address
    safe_tx_result=tx_result,
    signature=signature,
)
```

| Parameter        | Type | Required | Description                            |
| ---------------- | ---- | -------- | -------------------------------------- |
| `wallet_address` | str  | Yes      | User's EOA wallet address (Safe owner) |
| `safe_tx_result` | dict | Yes      | Result from any `build_*_tx()` method  |
| `signature`      | str  | Yes      | User's signature on the EIP-712 data   |

## Testing Helper

For testing, you can sign Safe transactions with a private key directly:

```python
signature = BuilderClient.sign_safe_tx_with_private_key(
    tx_result["eip712_data"],
    "0xPrivateKey...",
)
```

## Notes

* All methods require `rpc_url` to be set in the `BuilderClient` constructor.
* Amounts for `build_split_tx()`, `build_merge_tx()`, and `build_withdraw_tx()` must be in **wei** (smallest token unit). Use `safe_amount_to_wei(amount, decimals)` from `opinion_clob_sdk.builder_sdk` for conversion.
* The backend relays these transactions on-chain; no gas is needed from the user.
* On-chain confirmation typically takes 30-60 seconds.
* The `condition_id` is available from `get_market()` response (`market.condition_id`).
