@seams/wallet
v0.5.25
Published
Seams web and runtime TypeScript SDK for NEAR and EVM-family wallets
Maintainers
Readme
Seams wallet SDK
Embedded passkey wallet SDK for platforms that provision persistent wallets for their users. It supports NEAR and EVM-family signing through SecureConfirm WebAuthn, cross-origin iframe isolation, and WASM-based cryptography.
Strong fits include marketplaces, trading platforms, games, payout and remittance products, stablecoin accounts, rewards networks, and applications that sponsor or automate onchain operations. Read the wallet vision for the complete use-case boundary.
Featuring:
- Core SDK: Framework-agnostic JavaScript/TypeScript library
- React Components: Drop-in components and hooks for React applications
- Hosted wallet runtime: static wallet-service, worker, WASM, and export viewer support assets for the wallet origin
Installation
Install the published package:
npm install @seams/wallet
# or
pnpm add @seams/wallet
# or
yarn add @seams/walletFor SDK Developers
Build:
# From repo root
pnpm install
pnpm build:wasm # Builds Rust/WASM packages
pnpm build:sdk # Builds SDK dist from existing WASM outputs
pnpm build:sdk-full # Builds WASM packages + SDK dist
pnpm -C packages/wallet dev # Watch modeTest:
pnpm -C packages/wallet test # Playwright tests
pnpm -C packages/wallet run type-check # TypeScript validationQuick Start
React Integration
The easiest way to get started with React (React 18+)
import { SeamsWebProvider, useSeams } from '@seams/wallet/react';
function App() {
return (
<SeamsWebProvider
config={{
chains: [
{
network: 'near-testnet',
rpcUrl: 'https://rpc.testnet.fastnear.com',
explorerUrl: 'https://testnet.nearblocks.io',
},
],
iframeWallet: {
walletOrigin: 'https://wallet.web3authn.org',
},
relayer: {
url: 'https://router-api.example.com',
},
}}
>
<YourApp />
</SeamsWebProvider>
);
}
function SignInButton() {
const seams = useSeams();
const handleSignIn = async () => {
const result = await seams.registerPasskey();
console.log('Registered:', result.success);
};
return <button onClick={handleSignIn}>Sign In with Passkey</button>;
}Google SSO + Email OTP Wallet Auth
For the standard Google SSO plus Email OTP wallet flow, the app owns Google Identity token acquisition and the SDK owns wallet registration, unlock, challenge routing, signing-session readiness, and wallet-iframe routing.
import { SeamsAuthMenu } from '@seams/wallet/react';
function AuthMenu() {
const seams = useSeams();
return (
<SeamsAuthMenu
socialLogin={{
google: async ({ mode, emailOtpAuthPolicy }) => {
const idToken = await getGoogleIdTokenFromYourApp();
const flow = await seams.auth.beginGoogleEmailOtpWalletAuth({
idToken,
mode,
emailOtpAuthPolicy,
});
if (!flow.ok) throw new Error(flow.error.message);
return {
kind: 'otp_flow',
flow: flow.value,
onComplete: async ({ walletId }) => {
console.log('Wallet ready:', walletId);
},
};
},
}}
/>
);
}When the wallet runs in iframe mode, SeamsAuthMenu renders the passkey
registration CTA through the wallet iframe activation surface. The visible
wrapper keeps the app's normal styling, while the wallet-origin iframe owns the
actual click that opens WebAuthn. Direct SDK calls such as
seams.registerPasskey() keep the wallet-origin confirmation modal so the user
can click inside the iframe before Touch ID or the platform authenticator prompt
appears.
The public flow only exposes UI-safe data: wallet id, email hint, prompt copy,
delivery status, expiry, and resend/reroll/submit/cancel methods. It
does not expose Wallet Session operation credentials, runtime policy scope,
recovery codes, or ECDSA bootstrap material.
Low-level Email OTP methods such as requestEmailOtpChallenge,
requestEmailOtpEnrollmentChallenge, enrollEmailOtp, and
loginWithEmailOtpEcdsaCapability remain available for advanced custom
integrations. Prefer beginGoogleEmailOtpWalletAuth for the standard Google
SSO wallet registration and login path.
In wallet-iframe mode, the same public API is used by the app origin. The wallet origin owns Email OTP recovery-code backup UI, acknowledgement, workers, sealed refresh state, and exact Wallet Session persistence. App-origin iframe responses carry only non-secret flow metadata and submit results.
Exact Wallet Session authorization
Wallet operations are scoped to one exact wallet, authority, and authentication
method. The authorization also binds its authorization id, quota id, authority
digest and revocation epoch, capability subjects, and expiry. A primary
WalletSessionOperationCredentialV1 authenticates ordinary wallet operations.
Hosted iframe sessions redeem an origin-bound exchange into a
HostedWalletSessionOperationCredentialV1 child for the same parent
authorization.
The wallet origin persists the active authorization in the exact V6 IndexedDB
record wallet_session_authorization_v6 through
WalletSessionAuthorizationRepository. It stores the scoped wallet, authority,
auth-method, authorization, and Wallet Session ids; quota, authority
digest/revocation epoch, capability subjects, issue/expiry times; and the
matching operation credential. Credential and record identities must match
exactly. Replacing a session retires the predecessor for that exact scope while
sibling authentication methods remain independent.
Hosted Wallet Integration
Applications import the SDK as package code and configure the hosted wallet origin. They do not serve Seams wallet assets from the app Vite config.
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
});During the stabilization milestone, configure the hosted wallet through the
existing iframeWallet surface:
const config = {
relayer: { url: 'https://router.example.com' },
iframeWallet: {
walletOrigin: 'https://sign.seams.sh',
walletServicePath: '/wallet-service',
sdkBasePath: '/sdk',
},
};The Seams-operated wallet origin serves /wallet-service, /sdk/*, and
/sdk/workers/* from @seams/wallet/dist/public. Private-key export uses a
wallet-origin inline viewer document that loads its support files from /sdk/*.
App origins should not route those paths.
The SDK-created wallet iframe carries the default WebAuthn delegation through
its allow attribute. App-platform Permissions-Policy should only be added
if hosted-origin browser smokes prove a supported browser requires it.
Stable API Surfaces
Use @seams/wallet for the main surface (for example SeamsWeb and core types).
Threshold APIs are stable under an explicit subpath:
import { keygenEcdsa } from '@seams/wallet/threshold';Configuration Options
interface SeamsWebConfig {
// Chain settings
chains: Array<{
network:
| 'near-mainnet'
| 'near-testnet'
| 'tempo-mainnet'
| 'tempo-testnet'
| 'arc-mainnet'
| 'arc-testnet';
rpcUrl: string;
explorerUrl: string;
chainId?: number; // EVM (arc-*) chains only
}>;
relayerAccount: string; // Parent account used for new subaccounts
// Wallet iframe settings (recommended)
iframeWallet?: {
walletOrigin: string; // e.g., 'https://wallet.web3authn.org'
walletServicePath?: string; // Default: '/wallet-service'
sdkBasePath?: string; // Default: '/sdk'
walletHostVariant?: 'runtime' | 'full' | 'near' | 'ecdsa'; // Default: 'runtime'
rpIdOverride?: string; // Optional: Credential scope override
};
// Optional Router API server (for account creation & Shamir 3-pass)
relayer?: {
url: string;
};
}Wallet Iframe Architecture
The SDK isolates all sensitive operations in a cross-origin iframe such as
wallet.web3authn.org. Your app communicates via secure MessageChannel, and app
code cannot access keys directly.
Configuration
Recommended (dedicated wallet origin):
iframeWallet: {
walletOrigin: 'https://wallet.web3authn.org',
walletServicePath: '/wallet-service',
walletHostVariant: 'runtime',
}Project Structure
repo/
├── apps/
│ ├── web-client/ # Browser app/site
│ ├── web-server/ # Deployable Router API server app
│ └── docs/ # Documentation app
├── packages/
│ ├── wallet/ # Browser SDK package and build output
│ ├── wallet-server/ # Server library source
│ └── shared-ts/ # Shared TypeScript utils/types
├── crates/
│ ├── signer-core/ # Shared signer core primitives
│ └── seams-embedded/ # Embedded Rust SDK facade
├── wasm/ # Rust WASM packages
└── tests/ # Playwright + unit testsLicense
MIT License - see LICENSE for details.
Support
- Documentation: ../../apps/docs/
- Issues: GitHub Issues
