For the complete documentation index, see llms.txt. This page is also available as Markdown.

User Interaction Scenarios

Instant Withdrawal Flow

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.:

      {
        "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:

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

        {
          "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:

        {
          "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>.

Previously shown fee options may have expired past their POLICY_VALID_TIME,in which case a new set of fee options must be fetched.

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:

Code
Identifier
Message

1

unhandled_error

Internal server error

2

could_not_get_excepted_response

Could not get expected response

3

model_validation_error

Model validation error

4

not_found_error

Not found

5

already_has_pending

Already has pending withdrawal options—try again in ? seconds

6

not_enough_balance

Not enough user balance

7

invalid_bridge_transaction

Invalid bridge transaction

8

invalid_bridge_policy_option

Invalid Bridge Policy Option—please check and select options again

9

already_has_withdrawal_option_or_executed

You already selected an option for this bridge or it has executed

10

low_amount_to_bridge

Requested amount for bridge is very low

11

unauthorized_access

Unauthorized

12

invalid_signature

Invalid Signature

13

signature_mismatch

Signature mismatch

14

expired_nonce

Nonce expired or not found

15

not_authenticated

Not authenticated

16

contract_validation_failed

Contract validation failed

17

rpc_connection_failed

RPC endpoint connection failed

18

nonce_mismatch

Nonce mismatch

19

user_creation_in_progress

User creation in progress for this address. Please retry in a moment.

Last updated