# Instant Withdrawal Script

An Instant Withdrawal lets you withdraw funds without waiting for the normal cooldown period, which is 12 hours. Instead, you select a fee option that matches how fast you want your withdrawal processed and withdraw funds through a bridge. This guide shows how to do this without using a frontend application.

Instant withdrawals work in two steps :

1. **On-chain**: You transfer your allocated balance to a bridge.
2. **Off-chain**: You select a fee option, and the backend schedules the withdrawal to execution.

### Before You Start

You’ll need:

* **Python 3.8** or newer
* A wallet private key (used for signing and paying gas)
* An RPC URL for the chain you are withdrawing from
* The Python script from the reference repo

***

### Setup

Create and activate a virtual environment, then install dependencies:

```bash
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```

***

### Configure .env

The script reads configuration from a .env file.\
You’ll need to use the private key corresponding with the wallet that you wish to withdraw from, and an RPC provider:

```dotenv
PRIVATE_KEY=0x...
RPC_URL=https://...
CHAIN_ID=8453
BASE_URL=https://instant-withdrawal-backend...
```

{% hint style="info" %}
Withdrawing 1 USDC means passing `1000000` since on Base USDC has 6 decimals.
{% endhint %}

***

### Running the Script

From the project root:

```bash
python instant_withdrawal.py
```

Once started, the script walks through all steps automatically.

***

### What the Script Does (Step by Step)

Below is the exact flow, mapped directly to the Python code.

***

#### 1. Sign in with your wallet (SIWE)

The script first proves wallet ownership using Sign-In With Ethereum and gets an access token.

This gives it an **access token** so it can talk to the Instant Withdrawal backend.

```python
nonce = requests.post(
    f"{BASE_URL}/v1/auth/nonce",
    json={"address": wallet_address}
).json()["nonce"]
```

```python
message = requests.get(
    f"{BASE_URL}/v1/auth/sign-in-message",
    params={"address": wallet_address, "domain": DOMAIN, "uri": ORIGIN}
).json()["message"]
```

```python
signed = account.sign_message(encode_defunct(text=message))
```

```python
token = requests.post(
    f"{BASE_URL}/v1/auth/login",
    json={"message": payload, "signature": signature}
).json()["accessToken"]
```

This token is required for all Instant Withdrawal API calls.

***

#### 2. Lock fee options for your withdrawal amount

Next, the script asks the backend for available fee options for a specific amount.\
This temporarily locks the options so rates can't change.

```python
options = requests.post(
    f"{BASE_URL}/v1/fee-options",
    params={"account": subaccount, "amount": AMOUNT},
    headers={"Authorization": f"Bearer {token}"}
).json()["options"]

```

***

#### 3. Deallocate funds from trading (on-chain)

If your funds are currently allocated to trading, they must be freed first.

The script fetches a Muon uPNL signature, formats it for the contract and sends the transaction.

```python
call_data = diamond.functions.deallocate(
    amount, upnl_sig
)._encode_transaction_data()
```

```python
tx = multi_account.functions._call(
    subaccount,
    [call_data]
)
```

This step must complete on-chain before continuing.

***

#### 4. Transfer funds to the withdrawal bridge (on-chain)

Once funds are free, they are transferred into the Instant Withdrawal bridge.

```python
call_data = diamond.functions.transferToBridge(
    amount, BRIDGE_ADDRESS
)._encode_transaction_data()
```

```python
tx = multi_account.functions._call(
    subaccount,
    [call_data]
)
```

After confirmation, the script extracts a `transactionId` from the emitted event. This ID is required for the next step.

***

#### 5. Fetch pending fee policies

Now that the bridge transfer exists on-chain, the script fetches again the valid fee options tied to that transfer.

```python
policies = requests.get(
    f"{BASE_URL}/v1/pending-fee-policy/{subaccount}",
    headers={"Authorization": f"Bearer {token}"}
).json()["policies"]
```

***

#### 6. Select a fee policy and schedule the withdrawal

The script automatically picks the fastest option and submits it.

```python
fastest = min(policies, key=lambda p: p["cooldown"])
```

```python
result = requests.post(
    f"{BASE_URL}/v1/select-fee-policy",
    json={
        "symmioBridgeId": bridge_id,
        "cooldown": fastest["cooldown"],
        "feeAmount": fastest["fee"],
    },
    headers={"Authorization": f"Bearer {token}"}
).json()
```

Once this is done, the withdrawal is scheduled and will execute automatically.

## Reference Implementation

[This repository](https://github.com/academy17/instant_withdrawal_reference) contains a python script showcasing the full flow for Instant Withdrawal.&#x20;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.symm.io/exchange-builder-documentation/frontend-builder-technical-guidance/instant-withdrawal-for-frontend-builders/instant-withdrawal-script.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
