@orderly.network/react-app is an application layer of the Orderly API. It is mainly responsible for rendering the UI, handling user interaction events, and completing trading actions. Therefore, it does not include built-in wallet connection functionality.

In places where wallet connection needs to be handled, @orderly.network/react-app utilizes React’s context mechanism to obtain information about the currently connected wallet or call wallet connection functions provided by the context. To facilitate this, @orderly.network/react-app defines a context named WalletConnectorContext. Any component that implements the WalletConnectorContext.Provider defined in WalletConnectorContextState can serve as the wallet connection component for the app. Please refer to this link for more details.

Using the wallet connection component provided by Orderly

Orderly SDK provides a built-in wallet connection component supporting both EVM and Solana. Here’s how to integrate it:

Install Wallet Connector Dependencies

npm install @orderly.network/wallet-connector

Add the WalletConnectorProvider Component

Wrap your application with the WalletConnectorProvider for wallet connection functionality:

import { WalletConnectorProvider } from "@orderly.network/wallet-connector";

const App: FC<{ children: ReactNode }> = (props) => {
  return (
    <WalletConnectorProvider>
      <OrderlyAppProvider brokerId="orderly" brokerName="Orderly" networkId="testnet" appIcons={""}>
        {props.children}
      </OrderlyAppProvider>
    </WalletConnectorProvider>
  );
};

Alternatively, you can integrate third-party wallet libraries by implementing the WalletConnectorContextState interface from @orderly.network/hooks.

Custom wallet connection provider

You can also customize wallet connections by implementing all the properties defined in WalletConnectorContextState. Define the component in the following format:

import { PropsWithChildren } from "react";
import { WalletConnectorContext } from "@orderly.network/hooks";

export const WalletConnector = ({ children }: PropsWithChildren) => {
  return (
    <WalletConnectorContext.Provider
      value={
        {
          /*
           * implement all properties defined in WalletConnectorContextState
           */
        }
      }
    >
      {children}
    </WalletConnectorContext.Provider>
  );
};

After defining the component, you also need to add this component to the parent of OrderlyAppProvider.

Interface & Context

export type ConnectedChain = {
  id: string;
};

export interface WalletConnectorContextState {
  connect: () => Promise<any[]>;
  disconnect: (options: any) => Promise<any[]>;
  connecting: boolean;
  setChain: (options: any) => Promise<any>;
  chains: any[];
  switchChain: (options: { chainId: string }) => Promise<any>;
  wallet: any;
  connectedChain: ConnectedChain | null;

  settingChain: boolean;
}

export const WalletConnectorContext = createContext<WalletConnectorContextState>(
  {} as WalletConnectorContextState
);

export const useWalletConnector = () => {
  return useContext(WalletConnectorContext);
};

Implementation

The following example demonstrates a wallet connection component implemented using web3modal. You can use this example as a reference to implement your own wallet connection component.

import { WalletConnectorContext, WalletState } from "@orderly.network/hooks";
import { ChainNamespace } from "@orderly.network/types";
import { createWeb3Modal, defaultWagmiConfig, useWeb3Modal } from "@web3modal/wagmi/react";
import { FC, PropsWithChildren, useEffect, useState } from "react";
import { useAccount as useWagmiAccount } from "wagmi";
import { arbitrum, mainnet } from "wagmi/chains";

// 1. Get projectId at https://cloud.reown.com/
const projectId = "YOUR_PROJECT_ID";

// 2. Create wagmiConfig
const metadata = {
  name: "Web3Modal",
  description: "Web3Modal Example",
  url: "https://web3modal.com",
  icons: ["https://avatars.githubusercontent.com/u/37784886"]
};

const chains = [mainnet, arbitrum];
export const wagmiConfig = defaultWagmiConfig({ chains, projectId, metadata });

// 3. Create modal
createWeb3Modal({ wagmiConfig, projectId });

export const OrderlyProvider: FC<PropsWithChildren> = ({ children }) => {
  const [wallet, setWallet] = useState<WalletState>({
    chains: chains.map((chain) => ({
      namespace: ChainNamespace.evm,
      id: chain.id
    })),
    accounts: [],
    icon: "",
    label: "",
    provider: null
  });

  const { open } = useWeb3Modal();
  const { address, isConnecting, chain, connector, status } = useWagmiAccount();

  useEffect(() => {
    const run = async () => {
      if (!connector) return;
      setWallet({
        ...wallet,
        accounts: await connector.getAccounts().then((addresses) =>
          addresses.map((addr) => ({
            address: addr
          }))
        ),
        provider: await connector.getProvider(),
        label: (await connector.getClient?.().then((client) => client.name)) ?? ""
      });
    };
    run();
  }, [address, wallet, setWallet, connector]);

  return (
    <WalletConnectorContext.Provider
      value={{
        connect: () => {
          return open().then(() => []);
        },
        disconnect: async () => {
          connector?.disconnect();
          return [];
        },
        setChain: async ({ chainId }) => {
          return connector?.switchChain?.({ chainId: Number(chainId) });
        },
        chains,
        connectedChain: chain ? { id: chain.id, namespace: ChainNamespace.evm } : null,
        namespace: ChainNamespace.evm,
        connecting: isConnecting,
        settingChain: status === "reconnecting",
        wallet
      }}
    >
      {children}
    </WalletConnectorContext.Provider>
  );
};