mcpField
O
orderly-sdk-debugging

orderly-sdk-debugging

github.com/orderlynetworkDevelopment248 installsUpdated 4d ago
Repository

About orderly-sdk-debugging

orderly-sdk-debugging is a troubleshooting skill for developers working with the Orderly SDK at runtime. It covers account and authentication state, streaming data, trading and transfer failures, and SDK errors.

Key features

  1. 01Inspect account and authentication states
  2. 02Diagnose WebSocket and preload issues
  3. 03Validate order submissions and rejections
  4. 04Troubleshoot deposits and withdrawals
  5. 05Interpret APIError and SDKError

Use cases

  1. 01Finding why private data is empty
  2. 02Investigating rejected or unsent orders
  3. 03Diagnosing deposit or withdrawal failures

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/orderlynetwork/skills --skill orderly-sdk-debugging

After installing, type/orderly-sdk-debuggingin Claude Code to confirm it loaded.

Details

From the project README

Orderly Network: SDK Debugging

A guide to debugging runtime behavior of the Orderly SDK — account/auth state, data streams, order and deposit/withdraw failures, and the errors the SDK throws.

This skill covers the SDK's own runtime surface. For build/setup problems (Vite polyfills, CSS imports, package versions) see orderly-sdk-install-dependency and orderly-sdk-dex-architecture; for wiring (provider props, .env config) see orderly-sdk-dex-architecture.

When to Use

  • Debugging account / authentication state ("stuck connecting", "not signed in")
  • Investigating data not loading (orderbook, positions, balances)
  • Troubleshooting order submission / rejections
  • Troubleshooting deposit / withdrawal failures
  • Understanding SDK-thrown errors (ApiError / SDKError)

Prerequisites

  • Orderly SDK providers mounted (OrderlyAppProvider from @orderly.network/react-app)
  • Browser DevTools familiarity

1. Account & Authentication State

The SDK account moves through a fixed ladder of states. Most "nothing works" bugs are an account stuck before SignedIn.

import { useAccount } from '@orderly.network/hooks';
import { AccountStatusEnum } from '@orderly.network/types';

function AccountDebugger() {
  const { state, account } = useAccount();

  // state.status is an AccountStatusEnum (numeric)
  console.log('account state', state.status, AccountStatusEnum[state.status]);
  console.log('accountId', account?.accountId);
}
AccountStatusEnum (from @orderly.network/types)
ValueNameMeaning
-1EnableTradingWithoutConnectedTrading enabled without a connected wallet
0NotConnectedNo wallet connected
1ConnectedWallet connected, Orderly account not yet resolved
2NotSignedInNeed an EIP-712 / Ed25519 signature to create the Orderly key
3SignedInFully authenticated — private streams/orders work
4DisabledTradingTrading disabled for this account
5EnableTradingTrading enabled
The authentication ladder & common stuck points
NotConnected ──connect wallet──▶ Connected ──resolve account──▶ NotSignedIn ──sign──▶ SignedIn
SymptomLikely stateFix
Private data (positions/balance) empty< SignedInDrive the user through sign-in (signature)
App keeps prompting to connectNotConnectedCheck WalletConnectorProvider is mounted & configured
"Sign" never completesNotSignedInWallet rejected; re-prompt. Key expires after 365 days
Orders rejected as unauthorizedNotSignedIn/ConnectedAccount must be SignedIn to submit orders
state.validating stays trueanyNetwork/request to resolve account hung — check WS/network

useAccount() returns { account, state, ... }; state is an AccountState with status: AccountStatusEnum and validating: boolean.

2. Data Not Loading

Public streams (orderbook, trades, mark price) work without auth. Private streams (positions, orders, balance, wallet) require the account to be SignedIn. If public data shows but private data is empty, check the account state first (§1).

WebSocket connection health
import { useWsStatus, WsNetworkStatus } from '@orderly.network/hooks';

function StreamHealth() {
  const ws = useWsStatus();
  // WsNetworkStatus is string-valued: 'connected' | 'unstable' | 'disconnected'
  return <span>{ws}</span>;
}
WsNetworkStatusMeaning
ConnectedWS up; streams flowing
UnstableDropped, SDK is reconnecting
DisconnectedLost and not reconnecting — re-mount provider
Boot / preload status
import { usePreLoadData } from '@orderly.network/hooks';

const { done, error } = usePreLoadData();
// done === false for the lifetime of the app = the initial data fetch failed/stalled
Checklist: data not loading
  • useWsStatus() is Connected?
  • For private data: state.status >= SignedIn?
  • networkId matches the chains you expect (mainnet vs testnet)?
  • usePreLoadData().done === true?
  • Symbol string is exact, e.g. PERP_ETH_USDC?
  • No SDK errors in the console (§5)?

3. Order Submission Errors

useOrderEntry(symbol, options) exposes order readiness and validation before you submit. Check metaState and call helper.validate().

import { useOrderEntry } from '@orderly.network/hooks';

function OrderDebugger() {
  const { formattedOrder, metaState, helper, maxQty, estLiqPrice, submit } =
    useOrderEntry('PERP_ETH_USDC');

  // metaState.errors: OrderValidationResult | null  (null = valid)
  // metaState.validated: boolean
  console.log({ ready: metaState.validated && !metaState.errors, maxQty, estLiqPrice });

  async function place() {
    try {
      const res = await submit({ resetOnSuccess: true });
      console.log('ok', res);
    } catch (e) {
      // SDK wraps REST failures in ApiError (see §5)
      console.error('order failed', e);
    }
  }
}

Field keys you set via setValue() are: side, order_type, order_price, order_quantity, reduce_only, tp_trigger_price, sl_price. The submit mutation flag is metaState-driven / isMutating on the hook — there is no isSubmitting.

Reading order states in the order stream
import { useOrderStream } from '@orderly.network/hooks';
import { OrderStatus } from '@orderly.network/types';

const [orders] = useOrderStream({ status: OrderStatus.INCOMPLETE });
// OrderStatus: OPEN | NEW | FILLED | PARTIAL_FILLED | CANCELLED | REPLACED | COMPLETED | INCOMPLETE | REJECTED

Use OrderStatus.INCOMPLETE (not the string 'OPEN') to query open orders. A REJECTED entry in the stream means the server rejected a submitted order — inspect its reason field.

Checklist: order not submitting / rejected
  • state.status is SignedIn?
  • Symbol exact (PERP_ETH_USDC)?
  • metaState.errors is null (validated)?
  • Quantity ≥ symbol minimum (check maxQty)?
  • Limit price within allowed range of mark?
  • Enough free collateral (useCollateral().freeCollateral)?

4. Deposit & Withdrawal Errors

Deposit (requires ERC-20 allowance first)
import { useDeposit } from '@orderly.network/hooks';

function DepositDebugger() {
  const { balance, allowance, approve, deposit, dst } = useDeposit({
    /* srcChainId, token, ... */
  });

  async function run(amount: string) {
    // allowance must cover amount, else approve first
    if (Number(amount) > Number(allowance)) {
      await approve(amount); // wallet prompt
    }
    await deposit(); // NOTE: deposit() takes NO arguments
  }
}
  • approve(amount?) and deposit() both trigger wallet prompts; wrap in try/catch.
  • deposit() takes no arguments — the amount comes from the hook's quantity/setQuantity state.
  • depositFee is a bigint.
Withdrawal
import { useWithdraw } from '@orderly.network/hooks';

const { withdraw, maxAmount, unsettledPnL } = useWithdraw({
  /* srcChainId, token, decimals */
});

await withdraw({
  chainId,
  token,
  amount,
  allowCrossChainWithdraw: true,
  // receiver?: '<optional custom address>'
});
  • Use maxAmount for the cap (not the deprecated availableWithdraw).
  • unsettledPnL reduces what you can withdraw — if withdrawals fail as insufficient, check it.
Reading withdrawal readiness

WithdrawStatus (@orderly.network/types): NotSupported | NotConnected | Unsettle (unsettled PnL blocks) | InsufficientBalance | Normal. Only Normal is withdrawable.

Detecting user-rejected / insufficient transactions

These failures come from the wallet/chain, not the Orderly API. Match on error.message:

catch (e) {
  const msg = String((e as Error)?.message ?? '');
  if (/reject|denied/i.test(msg))  /* user rejected the wallet prompt */;
  if (/insufficient/i.test(msg))   /* not enough gas/balance on-chain */;
}

5. Reading SDK Errors

The SDK surfaces two error classes from @orderly.network/types:

  • ApiError — REST API failures. Constructed with (message: string, code: number). The numeric code identifies the failure class; read error.message for detail.
  • SDKError — client-side / SDK-internal failures.
import { ApiError, SDKError } from '@orderly.network/types';

try {
  await someSdkAction();
} catch (e) {
  if (e instanceof ApiError) {
    console.error('API error', e.message /* numeric code lives on the instance */);
  } else if (e instanceof SDKError) {
    console.error('SDK error', e.message);
  }
}

Don't hard-code REST error code tables — codes can change. Log error.message, and branch on the codes you actually observe for your flow.

Rate limiting

REST -1003-style rate limits surface as ApiError. Retry with backoff:

async function withRetry<T>(fn: () => Promise<T>, retries = 3, base = 1000): Promise<T> {
  for (let i = 0; ; i++) {
    try {
      return await fn();
    } catch (e) {
      const code = (e as ApiError & { code?: number })?.code;
      if (code === -1003 && i < retries) {
        await new Promise((r) => setTimeout(r, base * 2 ** i));
        continue;
      }
      throw e;
    }
  }
}

5. Inspecting Hook State

A tiny logger helps track async hook output across renders:

function useDebugHook<T>(name: string, value: T): T {
  useEffect(() => {
    console.log(`[${name}]`, value);
  }, [name, value]);
  return value;
}
Remember the return shapes (common confusion)
HookShape
usePositionStream3-tuple: [positions, calc, { isLoading }]
useCollateralobject: { totalCollateral, freeCollateral, availableBalance, ... }
useOrderEntryobject: { submit, metaState, helper, setValue, ... }
useAccountobject: { account, state, ... } (state.status)
useOrderStream2-tuple: [orders, { total, isLoading, cancelOrder, ... }]

Destructuring the wrong arity is a frequent silent bug (e.g. reading isLoading off the first element).

Dev panel
function OrderlyDebugPanel() {
  const { state } = useAccount();
  const ws = useWsStatus();
  // mount this component only while developing (gate it however your app prefers)
  return (
    <div style={{ position: 'fixed', right: 8, bottom: 8, fontSize: 11 }}>
      <div>account: {state.status}</div>
      <div>ws: {ws}</div>
    </div>
  );
}

6. Error Boundary

For component errors, use the SDK's ErrorBoundary (@orderly.network/react-app):

import { ErrorBoundary } from '@orderly.network/react-app';

<ErrorBoundary fallback={<SomethingWentWrong />}>{children}</ErrorBoundary>;

Route-level errors (lazy-import failures, thrown loaders/actions) should be caught by your router's errorElement. ErrorBoundary is for the React tree.

Debugging Checklist

Nothing works / blank app
  • OrderlyAppProvider mounted with valid brokerId / networkId?
  • usePreLoadData().done === true?
  • useWsStatus() === Connected?
Private data empty
  • state.status is SignedIn?
  • Correct networkId for the chains shown?
  • WS Connected?
Order failing
  • SignedIn?
  • metaState.errors === null?
  • Quantity ≥ min, price in range?
  • Enough freeCollateral?
Deposit / withdraw failing
  • Allowance covers deposit amount (else approve)?
  • withdraw amount ≤ maxAmount?
  • unsettledPnL accounted for?
  • Wallet prompt not rejected?

Related Skills

  • orderly-sdk-dex-architecture — provider wiring & config
  • orderly-sdk-wallet-connection — wallet integration
  • orderly-api-authentication — the sign-in / key flow
  • orderly-sdk-install-dependency — package installation & build setup

Comments

Markdown supported