Docs menu

Hosted wallets: you are the wallet

If your user is already inside your wallet, there is nothing to connect. You hold the party and you sign natively, so the browser-connector flow on Connect a wallet does not apply to you. You implement one small seam and get the same WalletAdapter the reference integration uses, with the mainnet-proven plumbing riding along unchanged.

What you implement: one seam

Synfin builds each transfer as an UNSIGNED prepared exercise (the TransferFactory_Transfer against the token registry) and hands it to you. You sign it with your own key machinery and submit it through your participant, returning the ledger update id. That is the whole contract:

import {
  createCip0103WalletAdapter,
  MAINNET_REGISTRY_BASE_URL,
  type Cip0103Signer,
} from '@synfin/wallet-partylayer';

const signer: Cip0103Signer = {
  party: userParty, // you already know it; nothing connects
  async signAndSubmit(tx) {
    // tx.exercise + tx.disclosedContracts + tx.actAs: sign with YOUR key
    // machinery (interactive-submission prepare/sign/execute, or your own
    // internal path) and submit through YOUR participant.
    const updateId = await myWallet.signAndExecute(tx);
    return { updateId };
  },
};

const wallet = createCip0103WalletAdapter({
  ledger: { baseUrl: myParticipantJsonApi, token: myLedgerToken },
  registry: { baseUrl: MAINNET_REGISTRY_BASE_URL, token: '' },
  signer,
  instrumentAdmin, // the deposited instrument's admin party
});

Then execution is the standard client flow, unchanged: executePlan({ plan, wallet }) and track(...) from @synfin/client. Quote and plan are the same keyed REST calls as every other integrator.

No PartyLayer required

@partylayer/sdk is an optional peer used only by createPartyLayerWalletAdapter (the browser-connector path). Installing @synfin/wallet-partylayer without it is supported and tested: the package's runtime never imports the SDK on this path. If your build runs TypeScript with skipLibCheck disabled, import from the self-contained subpath instead, which never references the SDK's types:

import { createCip0103WalletAdapter } from '@synfin/wallet-partylayer/cip0103';

Reads, pacing, and your participant

Holdings and offer-liveness reads go through YOUR participant's JSON Ledger API (the ledger config), capability-aware: a full Ledger API (the normal case for a hosted wallet on its own participant) takes the standard offset read path and is never rate-paced. The 6-second fallback pacing exists only for partial browser bridges that reject /v2/state/ledger-end; by construction it does not run for you. The payout observation is the received-since baseline and delta, the same classifier proven in the 2026-07-21 mainnet run.

Support status, honestly

Synfin's capability model is answer-as-tested: a wallet's execute flag is true only with a cited mainnet update id from a real swap through the published packages on that wallet. The hosted class ships here as SUPPORTED-IN-ARCHITECTURE with the seam and plumbing proven elsewhere (the same adapter settled a real mainnet swap through the PartyLayer realization of this seam, and the same seam is devnet-proven with a raw key signer); no hosted wallet has run it live yet, so no hosted wallet is listed as proven. Run one real swap with us and your wallet's row flips to proven with the evidence attached: write info@cayvox.com.

Fees you can earn

A hosted wallet is an integrator like any other: send your API key on quote and plan with feeBps and feeRecipient and your disclosed fee line appears in every quote (see Earn with your fee). On-ledger collection is currently paused globally; disclosure works today.