Browser Extension

React and Vanilla

Use the Joey browser extension from React with JoeyProvider and hooks, or from plain JavaScript with a session helper.

React

Import from @joeywallet/wallet-sdk/react. In the Next.js App Router, put these components inside a 'use client' file.

'use client'
import { JoeyProvider, useJoey, useSignAndSubmit } from '@joeywallet/wallet-sdk/react'

export function App() {
  return (
    <JoeyProvider autoConnect>
      <Wallet />
    </JoeyProvider>
  )
}

function Wallet() {
  const { isReady, isAvailable, account, network, connect, disconnect } = useJoey()
  const { mutate, isPending, error, data } = useSignAndSubmit()

  if (!isReady) return null
  if (!isAvailable) return <a href="https://joeywallet.xyz/extension">Install Joey</a>
  if (account === null) return <button onClick={() => void connect()}>Connect</button>

  return (
    <div>
      <p>
        {account} on {network?.name}
      </p>
      <button
        disabled={isPending}
        onClick={() =>
          mutate({
            account,
            tx_json: {
              TransactionType: 'Payment',
              Account: account,
              Destination: 'rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe',
              Amount: '1000000',
            },
          })
        }
      >
        {isPending ? 'Approve in Joey…' : 'Send 1 XRP'}
      </button>
      {error && <p>{error.message}</p>}
      {data && <p>Submitted: {data.hash}</p>}
      <button onClick={() => void disconnect()}>Disconnect</button>
    </div>
  )
}

<JoeyProvider>

Prop Default Description
autoConnect false On load, reconnect silently if the user already approved your site. Never shows a prompt.
detectTimeoutMs 3000 How long to wait for the extension before deciding it isn't installed.

useJoey()

Returns { joey, isAvailable, isReady, accounts, account, network, isConnected, connect(params?), disconnect(), refresh() }. It throws if used outside <JoeyProvider>.

Mutation hooks

useConnect, useDisconnect, useSignTransaction, useSignAndSubmit, useSignTransactionFor, useSignTransactionBulk and useSignIn all return:

{ mutate, mutateAsync, reset, status, data, error, variables, isIdle, isPending, isSuccess, isError }
  • mutate() never rejects; read error instead. mutateAsync() returns a promise you can await.
  • If a newer call starts before an older one finishes, the older response is ignored.
  • Options: onSuccess, onError and onSettled.
  • For anything else, wrap your own call with useJoeyMutation(run, options).
  • There's no separate Batch hook; pass a Batch transaction to useSignAndSubmit.

Vanilla JavaScript

@joeywallet/wallet-sdk/vanilla gives you a small session object and a helper that wires up a connect button.

<button id="connect"></button>
<script type="module">
  import { bindConnectButton, createJoeySession } from '@joeywallet/wallet-sdk/vanilla'

  const session = createJoeySession() // detects Joey, then reconnects silently
  bindConnectButton(document.getElementById('connect'), session, {
    installUrl: 'https://joeywallet.xyz/extension',
    onError: (error) => console.warn(error.message),
  })
  session.subscribe((state) => console.log(state.account, state.network?.name))
</script>

createJoeySession(options?)

Option Default Description
autoConnect true Reconnect silently on start
detectTimeoutMs 3000 Detection timeout

The session has getState(), subscribe(fn) (calls fn immediately and returns an unsubscribe function), connect(params?), disconnect() and destroy(). State is { joey, isAvailable, isReady, isConnecting, accounts, account, network, error }.

bindConnectButton(button, session, options?)

Keeps the button's label and behaviour in sync with the session: install, connect, or connected. Options: connectLabel, connectedLabel, notInstalledLabel, installUrl and onError. It returns a teardown function.