# User Interaction Scenarios

Below are typical user flows. Each scenario assumes the user has a Web3 wallet connected and has retrieved a valid JWT via the SIWE login flow.

## Scenario 1: Normal Flow and Successful Instant Withdrawal

1. **Login via wallet (SIWE flow)**
   1. UI calls `POST /v1/auth/nonce` with `{ address }`.
   2. UI immediately calls `GET /v1/auth/sign-in-message` with the same address, domain, and URI; displays the returned message for signing.
   3. User signs; UI sends `POST /v1/auth/login` with `{ message, signature }`.
   4. UI receives `access_token` and sets `Authorization: Bearer <token>` on subsequent requests.
2. **Fetch Fee Options**
   1. User enters their wallet account address and desired amount in UI.
   2. UI calls `POST /v1/fee-options?account=<account>&amount=<amount>`.
   3. Backend validates, computes instant and fallback options, and locks them for `POLICY_VALID_TIME` (e.g., 30 s).
   4. UI displays the returned array of one or more `FeeOption` items.
3. **Bridge Funds**
   1. UI invokes on-chain call `symmio_contract.bridge(amount)` (or `_call(deallocate, bridge)` if bridging from a multi-account).
   2. Once on-chain transaction is mined, UI displays the `bridgeId` and instructs user to select a fee policy.
4. **Select Fee Policy**
   1. UI calls `POST /v1/bridges/{account}/{start}/{size}` to fetch the user’s bridges in `no_policy` state, e.g.:

      ```json
      {
        "bridge_state": "pending",
        "bridge_type": "no_policy"
      }
      ```
   2. For each bridge:
      1. UI calls `GET /v1/pending-fee-policy/{account}` and displays locked fee policies.
      2. User chooses one of the displayed `FeeOption`.
      3. *(Optional)* To specify a different receiver:
         1. UI calls

            ```
            GET /v1/get-select-receiver-message?receiver=<newReceiver>&bridgeId=<bridgeId>
            ```
         2. UI has user sign the returned EIP-712 payload and includes:

            ```json
            "receiver": {
              "address": "<newReceiver>",
              "signature": "<sig>"
            }
            ```
      4. UI calls `POST /v1/select-fee-policy` with:

         ```json
         {
           "symmioBridgeId": <bridgeId>,
           "cooldown": <chosenCooldown>,
           "feeAmount": <chosenFee>,
           "receiver": { … }      // optional
         }
         ```
      5. Backend validates, records in DB, calls `selectFeePolicyForBridge` on-chain, and schedules withdrawal at `execution_time = now + cooldown`.
      6. Backend returns:

         ```json
         {
           "bridge_id": <bridgeId>,
           "fee": <feeAmount>,
           "execution_time": <timestamp>
         }
         ```
5. **Automated Withdrawal**\
   After `cooldown` seconds, the backend bot automatically calls `processWithdrawal(bridgeId)` on-chain.

***

## Scenario 2: Fee Options Expire and Retry

1. Login via wallet (as in Scenario 1).
2. **Initial Fee Options**\
   UI calls `POST /v1/fee-options` but user waits beyond `POLICY_VALID_TIME` (e.g., 30 s).
3. Bridge funds and obtain `bridgeId`.
4. Lock expires (options TTL passed).
5. UI retrieves no-policy bridges via `POST /v1/bridges/{account}/{start}/{size}`.
6. **Retry Fee Options**\
   UI calls `POST /v1/fee-options?account=<account>&amount=<amount>` again; backend regenerates options and locks for another 30 s.
7. **Select & Withdraw**\
   User picks a new option, signs payload, calls `POST /v1/select-fee-policy`, and flow continues as in Scenario 1.

***

## Scenario 3: No Policy Selected (Withdrawal Pending)

#### **1. Login & Bridge Funds**

* The user logs in and initiates a bridge transaction through the frontend.
* The backend captures the bridge event and records it with\
  `bridge_type = no_policy` and `status = RECEIVED`.
* The funds are deducted from the user’s Symmio balance and reserved in the bridge contract — **no payout occurs yet.**

#### **2. User Does Not Select a Policy**

* If the user leaves or closes the UI before selecting a fee policy:
  * No withdrawal is scheduled.
  * The bridge transaction remains **pending** indefinitely.
  * The user’s reserved funds **cannot be used elsewhere**, but **can still be withdrawn later** once a policy is chosen.

#### **3. User Returns Later to Complete the Withdrawal**

* When the user logs back in, the UI must:
* Retrieve all pending bridges with\
  `POST /v1/bridges/{account}/{start}/{size}`\
  and look for entries where `bridge_type = no_policy`.
* For each pending bridge, request a **new set of fee options** using\
  `POST /v1/fee-options?account=<account>&amount=<amount>`.

{% hint style="info" %}
Previously shown fee options may have expired past their `POLICY_VALID_TIME,`in which case a new set of fee options must be fetched.
{% endhint %}

#### **4. Selecting a Policy and Processing the Withdrawal**

* Once the user selects a fee option:
  1. The frontend calls `POST /v1/select-fee-policy` with the chosen policy .
  2. The backend calls `selectFeePolicyForBridge` on-chain.
  3. After the configured cooldown period (usually 0), the backend or bot executes\
     `processWithdrawal(bridgeId)` to finalize the payout to the user.
* The transaction is then marked as **completed**, and the user receives the bridged funds.

***

## Scenario 4a: Bot Inactive, Then Reactivated

1. **Bot Down During Bridge**\
   – User bridges on-chain while event poller is offline → no record created.
2. **Bot Reactivation & Catch-Up**\
   – Bot scans missed events, creates `BridgeTransactions` with `no_policy`.
3. **User Resumes Normal Flow**\
   – UI requests fee options and follows Scenario 1 steps to select and execute withdrawal.

***

## Scenario 4b: Bot Inactive after Policy Selected, Manual Withdrawal

1. Follow Scenario 1 through fee-policy selection.
2. Bot goes down before scheduled withdrawal executes.
3. **Manual Withdrawal**
   1. UI displays “Withdraw After Cooldown” button next to bridges where `execution_time` has passed but state is still `pending`.
   2. When clicked, UI calls `processWithdrawal(bridgeId)` on-chain.
   3. Tokens arrive in user’s wallet.

***

## Scenario 5: Reset Locked Fee Options

1. Login via wallet.
2. UI calls `POST /v1/fee-options?account=<account>&amount=<amount>`, receives options.
3. UI calls `POST /v1/unlock/{account}` to clear locks.
4. UI calls `POST /v1/fee-options?account=<account>&amount=<amount>` again to fetch fresh options.

***

### 4. Additional UI Actions and Buttons

1. **Get Max Instant Value Button**
   * **Endpoint:** `GET /v1/max-instant-value/{account}`
   * **Purpose:** Show the maximum amount the user can withdraw instantly; guide the user to not bridge more than this.
2. **Refresh Fee Options Button**
   * **Combined Actions:**
     1. `POST /v1/unlock/{account}`
     2. `POST /v1/fee-options?account=<account>&amount=<amount>`
   * **Purpose:** Clear existing lock and fetch fresh fee/cooldown options in one click.
3. **Manual Process Withdrawal Button**
   * **Action:** Calls the contract’s `processWithdrawal(bridgeId)` method directly.
   * **Purpose:** Allow users to trigger on-chain withdrawal if scheduled withdrawal failed or bot is down.
   * **When to Show:** After fetching user’s bridge list, display “Withdraw Now” next to any entry where `execution_time` has passed but state is still `pending`.

***

### 5. Error Codes

All endpoints return structured error codes via the shared `ErrorInfoContainer`:

<table><thead><tr><th width="101">Code</th><th>Identifier</th><th>Message</th></tr></thead><tbody><tr><td>1</td><td><code>unhandled_error</code></td><td>Internal server error</td></tr><tr><td>2</td><td><code>could_not_get_excepted_response</code></td><td>Could not get expected response</td></tr><tr><td>3</td><td><code>model_validation_error</code></td><td>Model validation error</td></tr><tr><td>4</td><td><code>not_found_error</code></td><td>Not found</td></tr><tr><td>5</td><td><code>already_has_pending</code></td><td>Already has pending withdrawal options—try again in ? seconds</td></tr><tr><td>6</td><td><code>not_enough_balance</code></td><td>Not enough user balance</td></tr><tr><td>7</td><td><code>invalid_bridge_transaction</code></td><td>Invalid bridge transaction</td></tr><tr><td>8</td><td><code>invalid_bridge_policy_option</code></td><td>Invalid Bridge Policy Option—please check and select options again</td></tr><tr><td>9</td><td><code>already_has_withdrawal_option_or_executed</code></td><td>You already selected an option for this bridge or it has executed</td></tr><tr><td>10</td><td><code>low_amount_to_bridge</code></td><td>Requested amount for bridge is very low</td></tr><tr><td>11</td><td><code>unauthorized_access</code></td><td>Unauthorized</td></tr><tr><td>12</td><td><code>invalid_signature</code></td><td>Invalid Signature</td></tr><tr><td>13</td><td><code>signature_mismatch</code></td><td>Signature mismatch</td></tr><tr><td>14</td><td><code>expired_nonce</code></td><td>Nonce expired or not found</td></tr><tr><td>15</td><td><code>not_authenticated</code></td><td>Not authenticated</td></tr><tr><td>16</td><td><code>contract_validation_failed</code></td><td>Contract validation failed</td></tr><tr><td>17</td><td><code>rpc_connection_failed</code></td><td>RPC endpoint connection failed</td></tr><tr><td>18</td><td><code>nonce_mismatch</code></td><td>Nonce mismatch</td></tr><tr><td>19</td><td><code>user_creation_in_progress</code></td><td>User creation in progress for this address. Please retry in a moment.</td></tr></tbody></table>
