orderly-sdk-trading-workflows

Complete trading workflows for Orderly Network DEX applications, from wallet connection through order execution, position management, and withdrawal.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "orderly-sdk-trading-workflows" with this command: npx skills add orderlynetwork/skills/orderlynetwork-skills-orderly-sdk-trading-workflows

Orderly Network: SDK Trading Workflows

A comprehensive guide to implementing complete trading workflows in Orderly Network DEX applications, from wallet connection through order execution and position management.

When to Use

  • Building a complete trading interface
  • Implementing deposit → trade → withdraw flow
  • Understanding the end-to-end trading lifecycle
  • Creating automated trading bots

Prerequisites

  • Orderly SDK packages installed
  • Wallet connection configured
  • Account authenticated

Overview

This skill covers end-to-end trading workflows:

  1. Connect → Wallet connection and authentication
  2. Deposit → Fund your Orderly account
  3. Trade → Place and manage orders
  4. Monitor → Track positions and PnL
  5. Withdraw → Move funds back to wallet

Complete Trading Flow

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   Connect    │────▶│   Deposit    │────▶│    Trade     │
│   Wallet     │     │    Funds     │     │   (Orders)   │
└──────────────┘     └──────────────┘     └──────────────┘
                                                 │
                                                 ▼
┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   Withdraw   │◀────│    Close     │◀────│   Monitor    │
│    Funds     │     │  Positions   │     │  Positions   │
└──────────────┘     └──────────────┘     └──────────────┘

1. Connect & Authenticate

Check Account State

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

function TradingGuard({ children }) {
  const { state, createAccount, createOrderlyKey } = useAccount();

  switch (state.status) {
    case AccountStatusEnum.NotConnected:
      return <ConnectWalletPrompt />;

    case AccountStatusEnum.Connected:
      return (
        <div>
          <p>Create your Orderly account to start trading</p>
          <Button onClick={() => createAccount()}>Create Account</Button>
        </div>
      );

    case AccountStatusEnum.NotSignedIn:
      return (
        <div>
          <p>Enable trading by creating your trading key</p>
          <Button onClick={() => createOrderlyKey()}>Enable Trading</Button>
        </div>
      );

    case AccountStatusEnum.SignedIn:
      return children;
  }
}

Using AuthGuard (Simpler)

import { AuthGuard } from '@orderly.network/ui-connector';

function TradingPage() {
  return (
    <AuthGuard>
      <TradingInterface />
    </AuthGuard>
  );
}

2. Deposit Funds

Using useDeposit Hook

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

function DepositForm() {
  const { deposit, balance, allowance, approve, isNativeToken, quantity, setQuantity, depositFee } =
    useDeposit({
      address: '0xUSDC_ADDRESS',
      decimals: 6,
      srcChainId: 42161,
      srcToken: 'USDC',
    });

  const handleDeposit = async () => {
    try {
      // Check and approve if needed
      if (!isNativeToken && allowance < quantity) {
        await approve();
      }

      // Execute deposit
      const result = await deposit();
      toast.success('Deposit successful!');
    } catch (error) {
      toast.error(error.message);
    }
  };

  return (
    <div>
      <Input value={quantity} onChange={(e) => setQuantity(e.target.value)} placeholder="Amount" />
      <Text>Balance: {balance} USDC</Text>
      <Text>Fee: {depositFee} USDC</Text>
      <Button onClick={handleDeposit}>Deposit</Button>
    </div>
  );
}

Using DepositForm Component

import { DepositForm } from '@orderly.network/ui-transfer';

function DepositPage() {
  return (
    <DepositForm
      onDeposit={(result) => {
        toast.success('Deposited successfully!');
      }}
    />
  );
}

3. Check Account Balance

Using useCollateral

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

function AccountBalance() {
  const { totalCollateral, freeCollateral, totalValue, availableBalance, unsettledPnL } =
    useCollateral({ dp: 2 });

  return (
    <Card>
      <Text>Total Value: ${totalValue}</Text>
      <Text>Free Collateral: ${freeCollateral}</Text>
      <Text>Unsettled PnL: ${unsettledPnL}</Text>
    </Card>
  );
}

4. Place Orders

Market Order

import { useMutation } from '@orderly.network/hooks';
import { OrderType, OrderSide } from '@orderly.network/types';

function MarketOrderButton({ symbol, side, quantity }) {
  const [submitOrder] = useMutation('/v1/order');

  const placeMarketOrder = async () => {
    const order = {
      symbol,
      side,
      order_type: OrderType.MARKET,
      order_quantity: quantity,
    };

    try {
      const result = await submitOrder(order);
      if (result.success) {
        toast.success(`Order placed: ${result.data.order_id}`);
      }
    } catch (error) {
      toast.error(error.message);
    }
  };

  return (
    <Button color={side === OrderSide.BUY ? 'buy' : 'sell'} onClick={placeMarketOrder}>
      {side === OrderSide.BUY ? 'Buy' : 'Sell'} Market
    </Button>
  );
}

Limit Order

function LimitOrderForm({ symbol }) {
  const [submitOrder] = useMutation('/v1/order');
  const [price, setPrice] = useState('');
  const [quantity, setQuantity] = useState('');
  const [side, setSide] = useState(OrderSide.BUY);

  const placeLimitOrder = async () => {
    const order = {
      symbol,
      side,
      order_type: OrderType.LIMIT,
      order_price: parseFloat(price),
      order_quantity: parseFloat(quantity),
    };

    const result = await submitOrder(order);
    if (result.success) {
      toast.success('Limit order placed!');
    }
  };

  return (
    <div>
      <Input label="Price" value={price} onChange={(e) => setPrice(e.target.value)} />
      <Input label="Quantity" value={quantity} onChange={(e) => setQuantity(e.target.value)} />
      <Button
        color="buy"
        onClick={() => {
          setSide(OrderSide.BUY);
          placeLimitOrder();
        }}
      >
        Buy
      </Button>
      <Button
        color="sell"
        onClick={() => {
          setSide(OrderSide.SELL);
          placeLimitOrder();
        }}
      >
        Sell
      </Button>
    </div>
  );
}

Using useOrderEntry (Recommended)

import { useOrderEntry } from '@orderly.network/hooks';
import { OrderSide, OrderType } from '@orderly.network/types';

function OrderEntryForm({ symbol }) {
  const { formattedOrder, submit, maxQty, freeCollateral, errors, setValues } =
    useOrderEntry(symbol);

  useEffect(() => {
    setValues({
      side: OrderSide.BUY,
      order_type: OrderType.LIMIT,
    });
  }, []);

  const handleSubmit = async () => {
    if (Object.keys(errors).length > 0) {
      toast.error('Please fix validation errors');
      return;
    }

    try {
      await submit();
      toast.success('Order submitted!');
    } catch (error) {
      toast.error(error.message);
    }
  };

  return (
    <div>
      <Input
        label="Price"
        value={formattedOrder.order_price}
        onChange={(e) => setValues({ order_price: e.target.value })}
        error={errors.order_price}
      />
      <Input
        label="Quantity"
        value={formattedOrder.order_quantity}
        onChange={(e) => setValues({ order_quantity: e.target.value })}
        error={errors.order_quantity}
      />
      <Text>Max: {maxQty}</Text>
      <Text>Available: ${freeCollateral}</Text>
      <Button onClick={handleSubmit}>Submit Order</Button>
    </div>
  );
}

5. Monitor Orders

Active Orders

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

function ActiveOrders({ symbol }) {
  const [orders, { refresh }] = useOrderStream({
    symbol,
    status: 'OPEN',
  });

  return (
    <DataTable
      columns={[
        { header: 'Symbol', accessorKey: 'symbol' },
        { header: 'Side', accessorKey: 'side' },
        { header: 'Price', accessorKey: 'price' },
        { header: 'Quantity', accessorKey: 'quantity' },
        { header: 'Status', accessorKey: 'status' },
        {
          header: 'Actions',
          cell: ({ row }) => <Button onClick={() => cancelOrder(row.order_id)}>Cancel</Button>,
        },
      ]}
      data={orders}
    />
  );
}

Cancel Order

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

function useCancelOrder() {
  const [cancel] = useMutation('/v1/order', 'DELETE');

  return async (orderId: string, symbol: string) => {
    const result = await cancel({
      order_id: orderId,
      symbol,
    });
    return result;
  };
}

6. Monitor Positions

Real-time Position Stream

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

function PositionsTable({ symbol }) {
  const [positions, positionInfo, { loading }] = usePositionStream(symbol);

  return (
    <DataTable
      columns={[
        { header: 'Symbol', accessorKey: 'symbol' },
        { header: 'Size', accessorKey: 'position_qty' },
        { header: 'Entry Price', accessorKey: 'average_open_price' },
        { header: 'Mark Price', accessorKey: 'mark_price' },
        {
          header: 'Unrealized PnL',
          accessorKey: 'unrealized_pnl',
          cell: ({ getValue }) => (
            <Text color={getValue() >= 0 ? 'success' : 'danger'}>${getValue().toFixed(2)}</Text>
          ),
        },
      ]}
      data={positions}
    />
  );
}

7. Close Positions

Close Specific Position

import { useMutation } from '@orderly.network/hooks';
import { OrderType, OrderSide } from '@orderly.network/types';

function ClosePositionButton({ position }) {
  const [submitOrder] = useMutation('/v1/order');

  const closePosition = async () => {
    const order = {
      symbol: position.symbol,
      side: position.position_qty > 0 ? OrderSide.SELL : OrderSide.BUY,
      order_type: OrderType.MARKET,
      order_quantity: Math.abs(position.position_qty),
      reduce_only: true,
    };

    const result = await submitOrder(order);
    if (result.success) {
      toast.success('Position closed!');
    }
  };

  return (
    <Button color="danger" onClick={closePosition}>
      Close Position
    </Button>
  );
}

8. Withdraw Funds

Using useWithdraw Hook

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

function WithdrawForm() {
  const { withdraw, maxAmount, availableWithdraw, unsettledPnL } = useWithdraw({
    srcChainId: 42161,
    token: 'USDC',
    decimals: 6,
  });

  const [amount, setAmount] = useState('');

  const handleWithdraw = async () => {
    try {
      await withdraw(parseFloat(amount));
      toast.success('Withdrawal initiated!');
    } catch (error) {
      toast.error(error.message);
    }
  };

  return (
    <div>
      <Input value={amount} onChange={(e) => setAmount(e.target.value)} placeholder="Amount" />
      <Text>Available: {availableWithdraw} USDC</Text>
      <Text>Max: {maxAmount} USDC</Text>
      <Button onClick={handleWithdraw}>Withdraw</Button>
    </div>
  );
}

9. Leverage Management

Get/Set Leverage

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

function LeverageControl() {
  const { curLeverage, maxLeverage, leverageLevers, update, isLoading } = useLeverage();

  const changeLeverage = async (newLeverage: number) => {
    try {
      await update({ leverage: newLeverage });
      toast.success(`Leverage set to ${newLeverage}x`);
    } catch (error) {
      toast.error(error.message);
    }
  };

  return (
    <div>
      <Text>Current: {curLeverage}x</Text>
      <Slider
        value={[curLeverage]}
        onValueChange={([v]) => changeLeverage(v)}
        min={1}
        max={maxLeverage}
      />
    </div>
  );
}

10. Risk Monitoring

Margin Ratio

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

function RiskIndicator() {
  const { marginRatio, mmr, currentLeverage } = useMarginRatio();

  const isAtRisk = marginRatio < mmr * 1.5;

  return (
    <Card>
      <Text>Margin Ratio: {(marginRatio * 100).toFixed(2)}%</Text>
      <Text>MMR: {(mmr * 100).toFixed(2)}%</Text>
      {isAtRisk && <Badge color="warning">Approaching Liquidation</Badge>}
    </Card>
  );
}

Complete Trading Page Example

import { useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { TradingPage } from '@orderly.network/trading';
import { AuthGuard } from '@orderly.network/ui-connector';
import { API } from '@orderly.network/types';

export default function Trading() {
  const { symbol } = useParams();
  const navigate = useNavigate();

  const onSymbolChange = (data: API.Symbol) => {
    navigate(`/trade/${data.symbol}`);
  };

  return (
    <AuthGuard>
      <TradingPage
        symbol={symbol!}
        onSymbolChange={onSymbolChange}
        tradingViewConfig={{
          scriptSRC: '/tradingview/charting_library/charting_library.js',
          library_path: '/tradingview/charting_library/',
        }}
        sharePnLConfig={{
          backgroundImages: ['/pnl-bg-1.png', '/pnl-bg-2.png'],
        }}
      />
    </AuthGuard>
  );
}

Error Handling Patterns

Order-Specific Errors

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

function OrderForm() {
  const { errors, submit } = useOrderEntry('PERP_ETH_USDC');

  const handleSubmit = async () => {
    if (errors.order_price) {
      toast.error(`Price: ${errors.order_price}`);
      return;
    }

    try {
      await submit();
    } catch (error) {
      if (error.code === 'INSUFFICIENT_BALANCE') {
        toast.error('Insufficient balance. Please deposit more funds.');
      } else if (error.code === 'RISK_TOO_HIGH') {
        toast.error('Order rejected: would exceed risk limits.');
      } else {
        toast.error(error.message);
      }
    }
  };
}

Best Practices

1. Always Check Auth Before Trading

const { state } = useAccount();
if (state.status !== AccountStatusEnum.SignedIn) {
  return <AuthGuard>{children}</AuthGuard>;
}

2. Validate Orders Before Submission

const { errors, validated } = metaState;
if (!validated || Object.keys(errors).length > 0) {
  // Don't submit
}

3. Use Real-time Streams for Position Data

// Good - real-time updates
const [positions] = usePositionStream();

4. Handle Loading States

if (isLoading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;

5. Show Execution Feedback

toast.loading('Submitting order...');
try {
  await submit();
  toast.success('Order placed!');
} catch (e) {
  toast.error(e.message);
}

Related Skills

  • orderly-sdk-wallet-connection - Wallet integration
  • orderly-sdk-react-hooks - Hook reference
  • orderly-trading-orders - Order management details
  • orderly-positions-tpsl - Position management
  • orderly-deposit-withdraw - Fund management

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Web3

orderly-sdk-wallet-connection

No summary provided by upstream source.

Repository SourceNeeds Review
General

orderly-api-authentication

No summary provided by upstream source.

Repository SourceNeeds Review
General

orderly-deposit-withdraw

No summary provided by upstream source.

Repository SourceNeeds Review
General

orderly-trading-orders

No summary provided by upstream source.

Repository SourceNeeds Review