# 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;
