Skip to main content

Para — Embedded Wallet Infrastructure

Para provides MPC-based embedded wallets for web and mobile apps. Users authenticate (email, phone, OAuth, passkey) and get wallets created automatically — no seed phrases, no extensions. Docs: https://docs.getpara.com Developer Portal: https://developer.getpara.com Chains: EVM (Ethereum, Polygon, Base, etc.), Solana, Cosmos

Agent Setup

When you receive this file, complete these steps before anything else:
  1. Save this skill so it persists across sessions:
    For non-Claude Code agents, save to your project root:
  2. Install the Para CLI:
  3. Authenticate (opens browser for OAuth):
  4. Verify everything is working:
Once setup is complete, ask the user what they’d like to build.

Para CLI

Setup a New Project

The fastest way to start is para create, which scaffolds a working app:
This walks you through: template (Next.js or Expo), chains, auth methods, OAuth providers, and external wallets. It installs dependencies and writes your API key to .env. Non-interactive example:

Setup an Existing Project

If you already have a project, use the CLI to configure it:
Then install the SDK. For React:
The minimum integration requires:
  1. Environment variable — Set NEXT_PUBLIC_PARA_API_KEY (Next.js), VITE_PARA_API_KEY (Vite), or EXPO_PUBLIC_PARA_API_KEY (Expo)
  2. CSS importimport "@getpara/react-sdk/styles.css"
  3. ParaProvider — Wrap your app with <ParaProvider> (requires a QueryClient from @tanstack/react-query)
  4. “use client” — Add directive to files using Para hooks (Next.js only)

Diagnose Issues

Checks: API key env var, env var prefix for framework, CSS import, ParaProvider setup, QueryClient, “use client” directives, @getpara/* version consistency, chain dependencies, deprecated packages. Exit code 1 on errors — use para doctor --json in CI.

CLI Command Reference

Authentication

Configuration

Config resolution: CLI flags > env vars (PARA_ENVIRONMENT, PARA_ORG_ID, PARA_PROJECT_ID) > .pararc > global config (~/.config/para/config.json) > defaults (beta).

Organizations & Projects

API Keys

Key Configuration

Scaffold

Global Flags

All commands accept: -e beta|prod, --json, -q/--quiet, --no-input, --org <id>, --project <id>.

SDK Packages

Web & Server (JavaScript/TypeScript)

Mobile Native

Server (Go)

Webhook Events

user.created, wallet.created, transaction.signed, send.broadcasted, send.confirmed, send.failed, wallet.pregen_claimed, user.external_wallet_verified

API Environments

Troubleshooting

When a developer reports a bug, unexpected behavior, or asks for help debugging their Para integration, follow this process to generate a diagnostic bundle. This covers all supported platforms: Web (React, Next.js, Vite), React Native/Expo, Swift (iOS), Flutter, Go, and Node.js server.

Step 1: Detect the platform

Auto-detect the platform from project files. Check in this order: If multiple platforms are detected (e.g., Expo client + Node.js server), note all of them and trace across the boundary.

Step 2: Run para doctor (JS/TS projects only)

Capture the full JSON output. If para doctor finds errors, address those first — they may be the root cause. This only works for JS/TS projects; skip for Swift, Flutter, and Go.

Step 3: Understand the issue

If the developer hasn’t already explained, ask them:
  1. What’s happening? — The exact error message or unexpected behavior. Ask them to copy-paste the actual error, console output, or HTTP status code — not a paraphrase.
  2. What do you expect instead?
  3. Is this consistent or intermittent? When did it last work? Did anything change recently? (SDK upgrade, new auth method, deploy environment change, etc.)
Platform-specific clarifications to ask:
  • Swift/React Native: Ask for Xcode console output or adb logcat output
  • Flutter: Ask for Flutter debug console output
  • Web: Ask for browser DevTools console and Network tab errors
  • Server: Ask for server logs and HTTP response bodies
If they’ve already described the issue in conversation, don’t re-ask — use what they told you.

Step 4: Gather environment info

Collect automatically from the project (don’t ask the developer for these).

All platforms

  • Para environment from constructor args or env vars (BETA or PROD)
  • API key prefix only — environment prefix + first 4 hex chars (e.g., sandbox_5661****). Never include the full key.
  • Check for environment mismatch: does the API key prefix match the environment value? (e.g., a beta_* key with Environment.PROD is a common mistake)

Web / React Native / Expo (JS/TS)

  • Node.js version (node --version)
  • All @getpara/* package versions from package.json and lockfile
  • Integration package versions: viem, ethers, @solana/web3.js, @cosmjs/stargate if present
  • Framework and version (Next.js, Vite, Expo, Express, etc.)
  • Whether both client-side and server-side SDKs are in use
  • Full constructor options for every new Para(...), new ParaMobile(...), and new ParaServer(...) call — especially enableDebugLogs, disableWorkers, custom portalUrl, walletPregeneration

Swift (iOS)

  • Xcode version (from xcodebuild -version)
  • iOS deployment target (from .xcodeproj or Package.swift)
  • ParaSwift SDK version (from Package.resolved or SPM pins)
  • Full ParaManager(...) constructor — environment, apiKey, appScheme
  • Associated Domains configuration (from .entitlements file or Xcode project)
  • Info.plist: CFBundleURLTypes (URL schemes), NSFaceIDUsageDescription, PARA_API_KEY, PARA_ENVIRONMENT
  • Team ID and Bundle ID (from project settings)
  • Third-party dependencies: web3swift, SolanaSwift, MetaMaskSwift, BigInt versions

Flutter

  • Flutter version (flutter --version)
  • Dart version (dart --version)
  • para package version from pubspec.yaml and pubspec.lock
  • Full Para(...) or Para.fromConfig(...) constructor — environment, apiKey, appScheme (must NOT include :// suffix)
  • Android minSdkVersion from android/app/build.gradle
  • iOS deployment target from ios/Podfile
  • .env file contents (redact secrets)
  • Android namespace configuration in build.gradle
  • SHA-256 fingerprint registration status (for passkeys)
  • Third-party dependencies: web3dart, solana, passkeys, flutter_secure_storage versions

Go

  • Go version (go version)
  • go-sdk version from go.mod
  • NewSigner(...) constructor parameters — host, party IDs, threshold
  • MPC network host endpoint
  • Header configuration pattern

Step 5: Extract integration code

Find all code that touches the Para SDK and its immediate surroundings.

Find seed files by platform

Web / React / Next.js:
React Native / Expo: Same as Web, plus check for:
Swift:
Flutter:
Go:

For each seed file

  • Read the full file if it’s under 150 lines
  • If longer (especially 500+ lines), extract only the import block + functions/components that use Para SDK methods
  • Always include what happens with the return values of Para SDK calls

Trace one level out

This is critical. Bugs often live in the orchestration code, not the SDK call itself. For each exported function, component, or method in a seed file, find its callers and read those too. You’re looking for things like:
  • A logout() call that runs before an async operation completes
  • A loop that creates new SDK instances without cleanup
  • A missing await/try await on an async Para operation causing a race condition
  • What happens between client-side auth and server-side operations (timing, data passing)
  • Session blob being stored/transmitted in a way that might truncate it
Present code in execution order, not alphabetical by file. If the flow is: login -> export session -> (server) import session -> sign, present in that order. Annotate client/server or native/bridge transitions. Keep it focused. Total extracted code should not exceed ~500 lines. Prioritize files most likely related to the reported issue.

Step 6: Check for common pitfalls

Scan the codebase and flag these if found.

All platforms

  • Hardcoded API keys instead of environment variables / config files
  • Environment mismatch (beta key with prod environment or vice versa)
  • No error handling around Para SDK operations
  • Missing await / try await on async Para SDK calls

Web (React, Next.js, Vite)

  • logout() called anywhere near exportSession, importSession, or signing flows
  • Missing keepSessionAlive() in server-side flows that use imported sessions
  • Creating new Para or ParaServer instances in a loop or on every request
  • Mixing @usecapsule/* (old) and @getpara/* (new) packages in the same project
  • Session blob stored in cookies (4KB limit) or URL query params (length limits)
  • Double JSON.stringify/parse encoding of session blobs
  • Using Para hooks (usePara, useModal) outside of ParaProvider context
  • Multiple ParaProvider instances
  • Missing CSS import (@getpara/react-sdk/styles.css)
  • Missing "use client" directive in Next.js files using Para hooks

React Native / Expo

  • All Web pitfalls above, plus:
  • Missing crypto polyfill shim (must be FIRST import in entry file)
  • Missing Metro config for crypto and buffer resolver
  • Missing PolyfillCrypto component in app root
  • Using Expo Go instead of expo prebuild / expo build (native modules don’t work in Expo Go)
  • Missing disableWorkers: true in constructor (required for React Native)
  • Pod linking failures on iOS (need manual pod install)
  • Keychain decryption errors after app rebuild (expected during development — clear app data)
  • RP ID validation error 50152 on Android (debug vs release keystore SHA-256 mismatch)
  • Missing Associated Domains for passkeys (webcredentials:app.beta.usecapsule.com, webcredentials:app.usecapsule.com)
  • Team ID + Bundle ID not registered in Para Developer Portal

Swift (iOS)

  • Missing Associated Domains entitlement (webcredentials:app.usecapsule.com, webcredentials:app.beta.usecapsule.com)
  • Team ID + Bundle ID not registered in Para Developer Portal (required for passkeys, up to 24hr propagation)
  • Missing NSFaceIDUsageDescription in Info.plist (required for biometric prompts)
  • Missing or mismatched URL scheme in Info.plist vs appScheme parameter
  • Not handling ASAuthorizationError.canceled (user dismissed biometric prompt)
  • ParaError.bridgeTimeoutError without retry logic (WebView bridge can be slow on first load)
  • Deep link handler not checking URL scheme correctly for MetaMask/external wallets
  • Calling Para SDK methods before WebView is ready
  • iOS deployment target below 13.0

Flutter

  • Missing appScheme parameter in constructor (required in v2, must NOT include :// suffix)
  • Using v1 API method names after v2 migration (signUpOrLogIn -> initiateAuthFlow, verifyNewAccount -> verifyOtp, loginWithPasskey -> handleLogin, init() removed)
  • Not awaiting .future property on ParaFuture operations (e.g., para.createWallet(...) returns ParaFuture, must await result.future)
  • Not catching ParaBridgeException specifically (has code and details fields for diagnosis)
  • Missing extension method imports (package:para/src/auth_extensions.dart)
  • .env not loaded before building UI (dotenv.load() must run before runApp())
  • Android: missing namespace config in android/app/build.gradle
  • Android: SHA-256 fingerprint not registered for passkeys (up to 24hr propagation, separate debug/release fingerprints)
  • Android: no Google account signed in on device (required for passkey management)
  • iOS: missing ITSAppUsesNonExemptEncryption: false in Info.plist
  • UI thread blocking — heavy Para operations should use compute() for isolation

Go

  • Party configuration mismatch — all parties must agree on IDs, threshold, and protocol
  • Must create protocol (CreateProtocol) before calling SendTransaction
  • Inconsistent useWebSocket parameter across calls (must be same for entire flow)
  • SignHash(), Decrypt(), ComputeSharedSecret() are stubs — not implemented
  • Config state not persisted between operations (config bytes from GetConfig() must be saved)
  • Network host not reachable (MPC network connectivity)

Server (Node.js / Bun / Deno)

  • Missing disableWebSockets: true for Bun, Deno, or Cloudflare Workers
  • Missing keepSessionAlive() after importing client session
  • Creating new ParaServer instances per request instead of reusing
  • Session imported but not refreshed — sessions expire after 90 minutes by default

Step 7: Produce the diagnostic bundle

Generate two outputs: 1. Short summary — for pasting into Slack or a support channel:
2. Detailed file — write to para-diagnostic.md in the project root (remind the developer to add this to .gitignore or delete it after sharing — it contains source code):
Before including code in the bundle, redact:
  • Para API keys -> show environment prefix + first 4 hex chars only (e.g., sandbox_5661****)
  • Session tokens or cookie values -> [REDACTED]
  • Private keys or mnemonics -> [REDACTED] (and warn the developer if these appear in their code)
  • Third-party secrets — Stripe keys, database URIs (postgres://, mongodb://), AWS keys (AKIA...), JWT tokens (eyJ...), Infura/Alchemy keys, or anything matching common secret patterns in .env files

After generating the bundle

Tell the developer:
I’ve generated a diagnostic report. The short summary above can be pasted into your support channel or shared with Para’s team. The detailed para-diagnostic.md file has the full context — share that too if possible. Review both before sending to make sure you’re comfortable with what’s included.
If the issue is hard to capture from static code alone (e.g., intermittent failures, timing-dependent bugs), suggest platform-appropriate debug logging:
  • Web/RN/Expo: Add enableDebugLogs: true to the Para constructor
  • Swift: Use Xcode’s network debugger or Charles Proxy to inspect bridge traffic
  • Flutter: Add logLevel: ParaLogLevel.verbose to ParaConfig
  • Go: Inspect HTTP/WebSocket traffic to the MPC network host
  • Server: Add enableDebugLogs: true to the ParaServer constructor