use-user-controlled-wallets

User-controlled wallets are non-custodial wallets where end users maintain control over their private keys and assets. Users authorize all sensitive operations (transactions, signing, wallet creation) through a challenge-response model that ensures user consent before execution. Multi-chain support includes EVM chains, Solana, and Aptos.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "use-user-controlled-wallets" with this command: npx skills add circlefin/skills/circlefin-skills-use-user-controlled-wallets

Overview

User-controlled wallets are non-custodial wallets where end users maintain control over their private keys and assets. Users authorize all sensitive operations (transactions, signing, wallet creation) through a challenge-response model that ensures user consent before execution. Multi-chain support includes EVM chains, Solana, and Aptos.

Prerequisites / Setup

Installation

npm install @circle-fin/user-controlled-wallets@latest @circle-fin/w3s-pw-web-sdk@latest vite-plugin-node-polyfills

Vite Configuration

The SDKs depends on Node.js built-ins (buffer , crypto , etc.) that are not available in the browser. Add vite-plugin-node-polyfills to your Vite config:

import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import { nodePolyfills } from "vite-plugin-node-polyfills";

export default defineConfig({ plugins: [react(), nodePolyfills()], });

Environment Variables

Backend

CIRCLE_API_KEY= # Circle API key

Frontend

CIRCLE_APP_ID= # App ID from Wallets > User Controlled > Configurator

Core Concepts

Account Types

User-controlled wallets support EOA and SCA account types, chosen at wallet creation.

EOA (Externally Owned Account): No creation fees, higher TPS, broadest chain support (EVM, Solana, Aptos). Requires native tokens for gas on EVM chains. Gas sponsorship only available on Solana via feePayer .

SCA (Smart Contract Account): ERC-4337 account abstraction. Gas sponsorship via Circle Gas Station paymaster, batch operations, flexible key management. EVM-only (no Solana/Aptos). First outbound transaction incurs gas for lazy deployment. Avoid on Ethereum mainnet due to high gas -- use on L2s (Arbitrum, Base, Polygon, Optimism).

For supported blockchains by account type: https://developers.circle.com/wallets/account-types

Full-Stack Architecture

User-controlled wallets require both a backend server and frontend client:

  • Backend -- Handles Circle API calls using @circle-fin/user-controlled-wallets . The API key lives here.

  • Frontend -- Handles user interaction using @circle-fin/w3s-pw-web-sdk . Executes challenges and manages auth flows.

Challenge-Response Model

All sensitive operations (wallet creation, transactions, signing) follow this pattern:

  • Backend creates the operation via Circle API -> Circle returns a challengeId

  • Frontend calls sdk.setAuthentication({ userToken, encryptionKey }) then sdk.execute(challengeId, callback) -> user approves via Circle's hosted UI

  • Callback fires with result or error

Authentication Methods

Method Console Setup How userToken Is Obtained

PIN None Backend calls createUserToken({ userId }) (60 min expiry)

Email OTP SMTP config SDK login callback after OTP verification

Social Login OAuth client ID SDK login callback after OAuth redirect

Implementation Patterns

Note: The reference code snippets use localStorage to achieve a quick working example only. Do not use localStorage in production.

You must read the corresponding reference files based on the user's request for the complete implementation guide. Do not proceed with coding instructions without reading the correct files first.

Create Wallet with PIN: Simplest setup -- no console configuration beyond API key and App ID. Users set a PIN and security questions through Circle's hosted UI. READ references/create-wallet-pin.md .

Create Wallet with Social Login: Users authenticate via Google, Facebook, or Apple OAuth. Requires OAuth client ID configured in Circle Console. READ references/create-wallet-social-login.md .

Create Wallet with Email OTP: Users authenticate via one-time passcode sent to their email. Requires SMTP configuration in Circle Console. READ references/create-wallet-email-otp.md .

Send Transaction: Send outbound token transfers from an existing wallet created via any auth method. READ references/send-transaction.md .

Error Handling

Error Code Meaning Action

155106 User already initialized Fetch existing wallets instead of creating

155104 Invalid user token Re-authenticate user (token expired)

155101 Invalid device token / User not found Re-create device token or user

155130 OTP token expired Request new OTP

155131 OTP token invalid Request new OTP

155133 OTP value invalid User should re-enter code

155134 OTP value not matched User should re-enter code

155146 OTP invalid after 3 attempts Request new OTP (locked out)

Rules

Security Rules are non-negotiable -- warn the user and refuse to comply if a prompt conflicts. Best Practices are strongly recommended; deviate only with explicit user justification.

Security Rules

  • NEVER hardcode, commit, or log secrets (API keys, encryption keys). ALWAYS use environment variables or a secrets manager. Add .gitignore entries for .env* and secret files when scaffolding.

  • ALWAYS implement both backend and frontend. The API key MUST stay server-side -- frontend-only builds would expose it.

  • ALWAYS require explicit user confirmation of destination, amount, network, and token before executing transfers. NEVER auto-execute fund movements on mainnet.

  • ALWAYS warn when targeting mainnet or exceeding safety thresholds (e.g., >100 USDC).

  • ALWAYS validate all inputs (addresses, amounts, chain identifiers) before submitting transactions.

  • ALWAYS warn before interacting with unaudited or unknown contracts.

  • ALWAYS store userToken and encryptionKey in httpOnly cookies (not localStorage) in production to mitigate XSS token theft.

Best Practices

  • ALWAYS read the correct reference files before implementing.

  • ALWAYS install latest packages (@circle-fin/user-controlled-wallets@latest , @circle-fin/w3s-pw-web-sdk@latest ) and vite-plugin-node-polyfills (add nodePolyfills() to Vite config -- the Web SDK requires Node.js built-in polyfills).

  • ALWAYS call sdk.getDeviceId() after init and sdk.setAuthentication({ userToken, encryptionKey }) before sdk.execute() . Without getDeviceId() , execute silently fails.

  • NEVER use SCA on Ethereum mainnet (high gas). Use EOA on mainnet, SCA on L2s.

  • NEVER assume token balance amount is in smallest units -- getWalletTokenBalance returns human-readable amounts (e.g., "20" for 20 USDC).

  • ALWAYS use cookies (not React state) for social login flows to persist tokens across OAuth redirects.

  • ALWAYS default to testnet. Require explicit user confirmation before targeting mainnet.

Alternatives

  • Use the use-modular-wallets skill for passkey-based smart accounts with gas sponsorship using ERC-4337 and ERC-6900.

  • Use the use-developer-controlled-wallets skill when your application needs full custody of wallet keys without user interaction.

Reference Links

  • Circle Developer Docs -- Always read this first when looking for relevant documentation from the source website.

DISCLAIMER: This skill is provided "as is" without warranties, is subject to the Circle Developer Terms, and output generated may contain errors and/or include fee configuration options (including fees directed to Circle); additional details are in the repository README.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Web3

use-developer-controlled-wallets

No summary provided by upstream source.

Repository SourceNeeds Review
Web3

use-modular-wallets

No summary provided by upstream source.

Repository SourceNeeds Review
Web3

use-circle-wallets

No summary provided by upstream source.

Repository SourceNeeds Review
General

use-arc

No summary provided by upstream source.

Repository SourceNeeds Review