Guides

React and Next.js

Use the SDK in React and Next.js with the provider and hooks.

@hydraone-sdk/core/react provides a provider and three hooks on top of the core client. It requires react 18 or later as a peer dependency.

Provider

Wrap your app once. The provider creates a WalletBridgeClient, a GameAuthManager and a storage adapter, and keeps them stable across renders.

import React from 'react';
import { HydraOneProvider, useWallet } from '@hydraone-sdk/core/react';

function Game() {
  const { isConnected, address, balanceADA, connect, disconnect } = useWallet();
  // TEMP auth hidden: const { isAuthenticated, signIn, signOut, error } = useHydraAuth();

  return (
    <div>
      <p>{isConnected ? `${address} (${balanceADA} ADA)` : 'Not connected'}</p>
      <button onClick={() => (isConnected ? disconnect() : connect())}>
        {isConnected ? 'Disconnect' : 'Connect'}
      </button>
      {/* TEMP auth hidden
      <button
        onClick={() => (isAuthenticated ? signOut() : signIn({ challenge: 'server-issued-nonce' }))}
      >
        {isAuthenticated ? 'Sign out' : 'Sign in'}
      </button>
      {error && <p role="alert">{error.message}</p>}
      */}
    </div>
  );
}

export function App() {
  return (
    <HydraOneProvider appCenterOrigin="https://alpha.hydraone.app" autoConnect>
      <Game />
    </HydraOneProvider>
  );
}

Provider props

PropTypeDefaultDescription
clientWalletBridgeClientcreatedProvide your own client.
storageIStoragecreatedDefaults to SafeLocalStorageAdapter in a browser, InMemoryStorageAdapter on the server.
appCenterOriginstring | string[]noneCreates a PostMessageTransport for the default client. The provider destroys it on unmount.
optionsPartial<WalletBridgeClientOptions>noneExtra client options.
autoConnectbooleanfalseRun client.init() after mount, in the browser only.
autoRefreshBalancebooleantrueDefault for useWallet.

Defaults worth knowing:

  • With appCenterOrigin, the provider creates a PostMessageTransport and destroys it on unmount. Pass an array to allow several hosts. Without it (and without options.transport) the provider throws, because the client has nothing to connect through. A client or options.transport you pass in is never destroyed for you.
  • In Next.js App Router you can import the provider from a Server Component such as layout.tsx; @hydraone-sdk/core/react already starts with "use client".
  • The default storage is SafeLocalStorageAdapter in the browser and InMemoryStorageAdapter on the server.
  • autoConnect calls client.init() in an effect, so it never runs during server rendering.

Use the host storage relay

To keep the session alive on Safari, pass a HostStorageRelayAdapter that shares the transport with the client:

import React from 'react';
import { PostMessageTransport, HostStorageRelayAdapter } from '@hydraone-sdk/core';
import { HydraOneProvider, useWallet } from '@hydraone-sdk/core/react';

const transport = new PostMessageTransport({ appCenterOrigin: 'https://alpha.hydraone.app' });
const storage = new HostStorageRelayAdapter({ transport });

function Balance() {
  const { balanceADA, isConnected } = useWallet();
  return <p>{isConnected ? `${balanceADA} ADA` : 'Not connected'}</p>;
}

export function App() {
  return (
    <HydraOneProvider options={{ transport }} storage={storage} autoConnect>
      <Balance />
    </HydraOneProvider>
  );
}

Hooks

useWallet(options?)

Returns reactive wallet state and actions.

State: client, connectionState, isConnected, address, usedAddresses, balanceADA (string or null), balanceLovelace (bigint or null), networkId, hostInfo, isAudioMuted, theme.

Actions: connect, disconnect, refreshBalance, signTx, submitTx, signData, setOrientation, triggerHaptic, requestDepositModal, getPlayerProfile.

Options: client, autoConnect, autoRefreshBalance (default true).

useHostStorage(options?)

Returns storage, isAvailable, getItem, setItem, removeItem, clear. It uses the provider's storage unless you pass storage.

useHydraOneContext()

Returns { client, authManager, storage, autoRefreshBalance }. It throws a clear error when used outside <HydraOneProvider>.

Next.js (App Center router)

The hooks use browser APIs, so use them in client components. Create the provider in a client component and render it from your layout:

'use client';

import React, { useMemo } from 'react';
import { PostMessageTransport, HostStorageRelayAdapter } from '@hydraone-sdk/core';
import { HydraOneProvider } from '@hydraone-sdk/core/react';

export function Providers({ children }: { children: React.ReactNode }) {
  const { transport, storage } = useMemo(() => {
    const t = new PostMessageTransport({ appCenterOrigin: 'https://alpha.hydraone.app' });
    return { transport: t, storage: new HostStorageRelayAdapter({ transport: t }) };
  }, []);

  return (
    <HydraOneProvider options={{ transport }} storage={storage}>
      {children}
    </HydraOneProvider>
  );
}

Server rendering is safe: nothing touches window until an effect runs. Balances and addresses are empty on the server and fill in after the client connects, so render a neutral state first to avoid hydration mismatches.

Testing

Mock the client in your component tests: provide a stub ITransport through options.transport and render with @testing-library/react. See Testing and health checks.