Skip to main content
Embedded wallets are provisioned by your app through a provider such as Privy, instead of being installed by the user as a browser extension. Trustware treats an embedded wallet like any other host wallet: your app owns the wallet session and hands the wallet to the SDK. Your app and the embedded wallet provider control the wallet; Trustware builds routes, helps send transactions through the SDK, and tracks settlement. It never takes custody of the wallet or its funds. This guide covers the adapter pattern and the two widget flows: swapping with an embedded wallet and depositing into one. For moving funds back out, see embedded wallet withdrawals.

Embedded wallets vs EOA wallets

  • EOA wallets (MetaMask, Phantom, Coinbase Wallet, etc.) are injected into the page and expose a public address as soon as they connect. The SDK can discover them on its own with auto-detection.
  • Embedded wallets are created or connected after the user logs in. No address exists at app boot, and the SDK cannot discover them. Your app must resolve the wallet from the embedded wallet provider and pass it to Trustware explicitly.

Adapt the embedded wallet

useEIP1193 from @trustware/sdk/wallet adapts any EIP-1193 provider into the WalletInterFaceAPI that TrustwareProvider accepts. The pattern is always the same three steps: resolve the embedded wallet, get its EIP-1193 provider, and wrap it. This example uses Privy, but any embedded wallet provider that exposes an EIP-1193 provider works the same way:
import { useEffect, useState } from "react";
import { useWallets, getEmbeddedConnectedWallet } from "@privy-io/react-auth";
import { type WalletInterFaceAPI } from "@trustware/sdk";
import { useEIP1193 } from "@trustware/sdk/wallet";

export function useEmbeddedWallet() {
  const { wallets } = useWallets();
  const [state, setState] = useState<{
    address: string;
    wallet?: WalletInterFaceAPI;
  }>({ address: "" });

  useEffect(() => {
    let cancelled = false;
    const embedded = getEmbeddedConnectedWallet(wallets);

    if (!embedded?.address) {
      setState({ address: "" });
      return;
    }

    embedded.getEthereumProvider().then((provider) => {
      if (!cancelled) {
        setState({
          address: embedded.address,
          wallet: useEIP1193(provider),
        });
      }
    });

    return () => {
      cancelled = true;
    };
  }, [wallets]);

  return state;
}
Resolve the actual embedded wallet, for example with Privy’s getEmbeddedConnectedWallet. Do not fall back to the first wallet in the provider’s list: if the user also has an EOA connected, that EOA could silently be treated as the embedded wallet.

Swap with an embedded wallet

In this flow the embedded wallet is the host wallet: it signs the swap and receives the output. Enable swap mode in features, pass the adapted wallet through the wallet prop, and set autoDetect={false} so the SDK does not run its own wallet discovery alongside it.
import {
  TrustwareProvider,
  TrustwareWidget,
  type TrustwareConfigOptions,
} from "@trustware/sdk";

const swapConfig = {
  apiKey: process.env.NEXT_PUBLIC_TRUSTWARE_API_KEY!,
  features: {
    swapMode: true,
    swapDefaultDestToken: {
      address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC on Base
      chainId: 8453,
    },
  },
} satisfies TrustwareConfigOptions;

export function EmbeddedSwap() {
  const { wallet } = useEmbeddedWallet();

  if (!wallet) return <p>Log in to create or connect an embedded wallet.</p>;

  return (
    <TrustwareProvider config={swapConfig} wallet={wallet} autoDetect={false}>
      <TrustwareWidget />
    </TrustwareProvider>
  );
}
The widget handles the full swap flow from there. See host wallet for why autoDetect={false} is required whenever you pass a wallet prop.

Deposit into an embedded wallet

In this flow the embedded wallet is only the destination. The payer is an EOA the user connects inside the widget, so leave auto-detection on. Because the embedded wallet address does not exist until after login, set it at runtime with Trustware.setDestinationAddress() once the provider is ready:
import { useEffect } from "react";
import {
  Trustware,
  TrustwareProvider,
  TrustwareWidget,
  useTrustware,
  type TrustwareConfigOptions,
} from "@trustware/sdk";

function SyncDestinationAddress({ address }: { address: string }) {
  const { status } = useTrustware();

  useEffect(() => {
    if (status === "ready" && address) {
      Trustware.setDestinationAddress(address);
    }
  }, [address, status]);

  return null;
}

export function DepositIntoEmbeddedWallet({ address }: { address: string }) {
  const depositConfig = {
    apiKey: process.env.NEXT_PUBLIC_TRUSTWARE_API_KEY!,
    routes: {
      toChain: "8453",
      toToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC on Base
      toAddress: address || undefined,
    },
  } satisfies TrustwareConfigOptions;

  return (
    <TrustwareProvider config={depositConfig} autoDetect>
      <SyncDestinationAddress address={address} />
      <TrustwareWidget />
    </TrustwareProvider>
  );
}
Setting routes.toAddress in config covers the case where the address is already known at mount; the runtime setter covers wallets provisioned after mount. See runtime destination for the full setter reference.

Refresh balances after a deposit

If your app displays the embedded wallet balance, refresh it when a deposit lands. Both onSuccess and the transaction_success event work; the example below uses both so the balance updates as soon as the transaction succeeds and again when settlement completes.
const depositConfig = {
  apiKey: process.env.NEXT_PUBLIC_TRUSTWARE_API_KEY!,
  routes: {
    toChain: "8453",
    toToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    toAddress: address || undefined,
  },
  onSuccess: () => refreshEmbeddedBalances(),
  onEvent: (event) => {
    if (event.type === "transaction_success") {
      refreshEmbeddedBalances();
    }
  },
} satisfies TrustwareConfigOptions;

Next: withdrawals

There is no prebuilt widget for moving funds back out of an embedded wallet. Withdrawals use the headless core with the embedded wallet as the source.

Embedded wallet withdrawals

Build and send a withdrawal route from an embedded wallet with getBalances, buildRoute, useWallet, sendRouteTransaction, and submitReceipt.
Both flows on this page are available as complete Next.js apps in the Trustware examples repo.