### Install mkcert on Linux Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Installs mkcert on Linux systems by downloading the binary and moving it to the local bin directory. It also installs the necessary NSS tools and sets up the local certificate authority. ```sh sudo apt install libnss3-tools curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/amd64" chmod +x mkcert-v*-linux-amd64 sudo mv mkcert-v*-linux-amd64 /usr/local/bin/mkcert mkcert -install ``` -------------------------------- ### Run the Development Server Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Starts the development server using npm. This command requires sudo privileges to bind to port 443 and makes the app available at https://circles-dev.gnosis.io. ```sh sudo npm run dev ``` -------------------------------- ### Load Mini App in Playground Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Provides example URLs and a keyboard shortcut for loading mini apps in the playground. The playground persists the loaded URL in the query parameter. ```bash # Load a mini app in the playground https://circles.gnosis.io/playground?url=https%3A%2F%2Fmy-app.example.com%2F # Keyboard shortcut: type URL in the address bar and press Enter to load ``` -------------------------------- ### Development and Build Commands Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Provides essential npm commands for installing dependencies, running a local development server, testing mini app demos, building for production, and type-checking the project. ```bash # Install dependencies npm install # Development server (requires mkcert TLS cert matching VITE_BASE_URL) sudo npm run dev # Available at https:// (port 443) # Run demo mini apps alongside the host for local testing npm run demo:tx # ERC20 Transfer demo → http://localhost:5180 npm run demo:sign # Sign Message demo → http://localhost:5181 # Production build npm run build # Output: build/ (static site with 404.html fallback) # Type-check npm run check ``` -------------------------------- ### Run Sign Message Demo Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Execute the sign message demonstration mini app locally. This command starts the demo on port 5181. ```sh npm run demo:sign ``` -------------------------------- ### Run ERC20 Transfer Demo Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Execute the ERC20 transfer demonstration mini app locally. This command starts the demo on port 5180. ```sh npm run demo:tx ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Installs all necessary Node.js dependencies for the project using npm. This command should be run from the project root directory. ```sh npm install ``` -------------------------------- ### Install mkcert on Windows Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Installs mkcert on Windows using Chocolatey and sets up the local certificate authority. This is a prerequisite for local TLS certificate generation. ```powershell choco install mkcert mkcert -install ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Copies the example environment file and prompts the user to fill in API keys and the base URL. The VITE_BASE_URL must match the TLS certificate and hosts file entry. ```sh cp .env.example .env ``` ```env VITE_COMETH_API_KEY=your_cometh_api_key VITE_PIMLICO_API_KEY=your_pimlico_api_key VITE_BASE_URL=circles.gnosis.io ``` -------------------------------- ### Install mkcert on macOS Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Installs mkcert using Homebrew and sets up the local certificate authority. This is required for generating local TLS certificates. ```sh brew install mkcert mkcert -install ``` -------------------------------- ### Encode ABI Parameters for App Data Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Example of encoding ABI parameters using viem to create data for the `?data=` URL parameter. This is useful for passing structured data like strings and addresses. ```js import { encodeAbiParameters } from 'viem' const encoded = encodeAbiParameters( [{ type: 'string' }, { type: 'address' }], ['Hello', '0xABC...'] ) const data = btoa(encoded) ``` -------------------------------- ### Encode JSON for App Data Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Example of how to base64 encode JSON data to be passed to a mini app via the `?data=` URL parameter. The host will decode this and send it via `app_data` postMessage. ```js const data = btoa(JSON.stringify({ message: 'Please sign this', context: 'my-app:v1' })) // use in URL: /miniapps/my-app?data= ``` -------------------------------- ### Mini App SDK: Event Listener and Message Handling Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Handles incoming messages from the host shell, updating wallet connection status and managing callback resolutions for asynchronous operations like transaction confirmations and signature verifications. Requires no specific setup beyond being included in the mini app's script. ```javascript // ---- Mini app side (runs inside the iframe) ---- let _walletAddress = null; let _pendingCallbacks = {}; window.addEventListener('message', (event) => { const { type, address, data, hashes, signature, verified, reason, requestId } = event.data ?? {}; switch (type) { case 'wallet_connected': _walletAddress = address; console.log('Wallet connected:', address); break; case 'wallet_disconnected': _walletAddress = null; break; case 'app_data': // Arbitrary data forwarded from the ?data= URL param console.log('App data received:', data); break; case 'tx_success': _pendingCallbacks[requestId]?.resolve(hashes); delete _pendingCallbacks[requestId]; break; case 'tx_rejected': _pendingCallbacks[requestId]?.reject(new Error(reason)); delete _pendingCallbacks[requestId]; break; case 'sign_success': _pendingCallbacks[requestId]?.resolve({ signature, verified }); delete _pendingCallbacks[requestId]; break; case 'sign_rejected': _pendingCallbacks[requestId]?.reject(new Error(reason)); delete _pendingCallbacks[requestId]; break; } }); ``` -------------------------------- ### Mini App SDK: ERC20 Transfer Transaction Example Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Demonstrates constructing an ERC20 transfer transaction payload and sending it using the `sendTransactions` function. The `erc20Interface` is a hardcoded ABI fragment for the transfer function. ```javascript // ERC20 transfer example const erc20Interface = '0xa9059cbb' + // transfer(address,uint256) '000000000000000000000000' + 'RecipientAddressWithout0x' + BigInt('1000000000000000000').toString(16).padStart(64, '0'); // 1 token (18 decimals) const [txHash] = await sendTransactions([ { to: '0xERC20TokenAddress...', data: erc20Interface, value: '0' } ]); console.log('Sent:', txHash); ``` -------------------------------- ### Mini App SDK: Signing for Authentication (Raw) Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Example of signing a message with 'raw' signature type, typically used for authentication purposes with services like the Circles auth service. This function requires the message string as input. ```javascript // Sign for auth (raw bytes — Circles auth service) const { signature } = await signMessage('Please sign in to My App', 'raw'); ``` -------------------------------- ### Invitation Redirect API Interaction Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Details the GET request to the referral API to resolve an invitation slug to a private key and the subsequent redirect. Includes HTTP status code handling and local storage caching. ```typescript // GET https://referrals.aboutcircles.com/d/:slug // Response: { privateKey: string } // Redirects to: https://app.gnosis.io/referral/[?originalQueryParams] // HTTP status handling: // 200 → redirect // 404 | 410 → "No more invitations available" // 423 → "This session is currently paused" // other → show error + retry button // The resolved key is cached: localStorage.setItem(`circles_inv_${slug}`, privateKey); // Subsequent visits use the cached key immediately without a network round-trip. ``` -------------------------------- ### Mini App SDK: Requesting Wallet Address Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Sends a 'request_address' message to the parent window to get the connected wallet address. This function initiates a communication flow that will eventually trigger a 'wallet_connected' or 'wallet_disconnected' event. ```javascript // Request the connected wallet address function requestAddress() { window.parent.postMessage({ type: 'request_address' }, '*'); } ``` -------------------------------- ### Environment Configuration (.env) Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Required environment variables for Cometh Connect SDK, Pimlico bundler, and base URL. ```bash # .env VITE_COMETH_API_KEY=your_cometh_api_key # Cometh Connect SDK key VITE_PIMLICO_API_KEY=your_pimlico_api_key # Pimlico bundler/paymaster key VITE_BASE_URL=circles.gnosis.io # Hostname for page titles and TLS cert # Optional: sponsor gas fees via Pimlico policy VITE_PIMLICO_SPONSORSHIP_POLICY_ID=your_policy_id ``` -------------------------------- ### Initialize and Use Wallet Store (Svelte) Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Manages a Cometh Connect Safe smart account on Gnosis Chain. Auto-connects on mount, supports explicit connection via passkey or direct Safe address, and provides methods for sending transactions and signing messages. State is persisted to localStorage. ```typescript import { wallet } from '$lib/wallet.svelte.ts'; // --- Auto-connect on page mount (restores from localStorage or prompts passkey) --- // Call once in onMount; skips if the user manually disconnected this session. await wallet.autoConnect(); // --- Connect explicitly via WebAuthn passkey --- await wallet.connectWithPasskey(); // wallet.connected === true // wallet.address === '0xAbCd...' // wallet.avatarName === 'Alice' (fetched from Circles RPC) // wallet.avatarImageUrl === 'https://...' // --- Connect to a known Safe address directly (bypasses passkey prompt) --- await wallet.connect('0xAbCd1234...'); // --- Read reactive state (works in Svelte templates and $derived/$effect runes) --- console.log(wallet.address); // '0xAbCd...' | '' console.log(wallet.connected); // true | false console.log(wallet.connecting); // true while async connect is in progress // --- Send a single transaction --- const txHash = await wallet.sendTransaction({ to: '0xRecipient...', value: '1000000000000000', // 0.001 xDAI in wei (as string) data: '0x' // optional calldata }); console.log(txHash); // '0xabc123...' // --- Send a batch of transactions atomically --- const batchHash = await wallet.sendTransactions([ { to: '0xToken...', data: '0xa9059cbb...' }, // ERC20 transfer { to: '0xOther...', value: '500000000000000000' } // 0.5 xDAI ]); // --- Sign a message (raw bytes path — for Circles auth service) --- // Uses EIP-712 SafeMessage with rawMsgBytes; verified via Safe.isValidSignature(rawBytes, sig) const { signature, verified } = await wallet.signMessage('Please authenticate'); console.log(verified); // true // --- Sign a message (EIP-191 + ERC-1271 standard path — for XMTP, standard wallets) --- // Uses account.signMessage which internally hashes via EIP-191 before SafeMessage wrapping const sig = await wallet.signErc1271Message('Hello XMTP'); console.log(sig); // '0x...' // --- Disconnect (clears localStorage and in-memory state) --- wallet.disconnect(); console.log(wallet.connected); // false ``` -------------------------------- ### Build Project Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Command to build the project for production. The output will be placed in the `build/` directory, creating a static site. ```sh npm run build ``` -------------------------------- ### Navigate to Playground Programmatically Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Demonstrates how to programmatically navigate to the playground route with a preloaded mini app URL using the `goto` function from SvelteKit. ```typescript // Programmatic navigation to playground with a preloaded URL import { goto } from '$app/navigation'; function openInPlayground(appUrl: string) { goto(`/playground?url=${encodeURIComponent(appUrl)}`); } openInPlayground('https://my-miniapp.vercel.app/'); // Playground renders the app in a sandboxed iframe and proxies all postMessage calls // sandbox: "allow-scripts allow-forms allow-same-origin" ``` -------------------------------- ### Mini App Registry Configuration (`static/miniapps.json`) Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Defines all apps available in the marketplace. Apps can be hidden from public view by setting `isHidden` to true or `category` to 'admin'. ```json // static/miniapps.json — add your entry via PR [ { "slug": "my-defi-app", // URL-safe unique id → /miniapps/my-defi-app "name": "My DeFi App", // Display name shown in the marketplace "logo": "https://example.com/logo.png", // Square image ≥64×64px (SVG or PNG) "url": "/apps/my-defi-app", // For embedded apps: route inside this repo "description": "Swap tokens and earn yield on Gnosis Chain.", "tags": ["defi", "tokens"], "category": "miniapp", // "miniapp" | "admin" "isHidden": false // omit or false to show in marketplace }, { "slug": "xmtp-circles-demo", "name": "XMTP Demo", "logo": "/app-logos/xmtp.png", "url": "https://zengzengzenghuy.github.io/xmtp-circles-miniapp/", "description": "Secure private and group messaging with Circles users using XMTP.", "tags": ["demo"], "category": "miniapp" } ] ``` -------------------------------- ### Mini App SDK: Sending Transactions Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Initiates a transaction request to the host shell, returning a Promise that resolves with transaction hashes upon success or rejects with an error upon failure. Requires a unique `requestId` for callback management. ```javascript // Request transaction approval (returns Promise of tx hashes) function sendTransactions(transactions) { return new Promise((resolve, reject) => { const requestId = crypto.randomUUID(); _pendingCallbacks[requestId] = { resolve, reject }; window.parent.postMessage({ type: 'send_transactions', transactions, requestId }, '*'); }); } ``` -------------------------------- ### Passing Data to Mini Apps via URL Parameters Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Demonstrates how to encode and pass arbitrary data or a Safe address to a mini app using URL query parameters. The data is base64-encoded before being appended to the URL. ```typescript // Navigate to a registered mini app — no extra setup needed // https://circles.gnosis.io/miniapps/xmtp-circles-demo // Pass arbitrary data to the mini app via ?data= (base64-encoded) import { encodeAbiParameters } from 'viem'; const payload = encodeAbiParameters( [{ type: 'string' }, { type: 'address' }], ['Hello', '0xAbCd1234...'] ); const data = btoa(payload); // Navigate to: /miniapps/my-app?data= // The iframe receives: { type: 'app_data', data: } // Pass a Safe address directly via ?address= to pre-fill the wallet // /miniapps/my-app?address=0xAbCd1234... // The layout normalizes it via viem.getAddress() and saves to localStorage before autoConnect runs // Iframe sandbox attributes used by the host: // allow-scripts allow-forms allow-same-origin allow-popups allow-top-navigation-by-user-activation ``` -------------------------------- ### Generate TLS Certificates Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Generates local TLS certificates using mkcert for the specified VITE_BASE_URL. This creates a .pem certificate file and a .key private key file in the project root. ```sh mkcert circles-dev.gnosis.io ``` -------------------------------- ### Add Host to hosts file on Windows Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Manually adds an entry to the Windows hosts file to map the development hostname to localhost. This ensures the dev server can bind to the specified hostname. ```text 127.0.0.1 circles-dev.gnosis.io ``` -------------------------------- ### Mini App SDK: Signing for XMTP / ERC-1271 Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Demonstrates signing a message using the default 'erc1271' signature type, suitable for protocols like XMTP or other ERC-1271 compliant verifications. The message string is provided as input. ```javascript // Sign for XMTP / ERC-1271 consumers const sig = await signMessage('XMTP identity key', 'erc1271'); ``` -------------------------------- ### Add Host to /etc/hosts on macOS/Linux Source: https://github.com/aboutcircles/circlesminiapps/blob/master/README.md Adds an entry to the system's hosts file to map the development hostname to localhost. This is necessary for the dev server to bind correctly to the hostname. ```sh sudo sh -c 'echo "127.0.0.1 circles-dev.gnosis.io" >> /etc/hosts' ``` -------------------------------- ### Minimum Mini App Registry Entry Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Defines the minimum required fields for a mini app entry in the `static/miniapps.json` registry. Ensures all necessary metadata for marketplace submission is present. ```json // Minimum valid entry in static/miniapps.json { "slug": "my-app", // unique, URL-safe "name": "My App", "logo": "https://my-app.example.com/logo.png", // ≥64×64px square, HTTPS "url": "https://my-app.example.com/", // must load in an iframe over HTTPS "description": "One-line description of my app.", "tags": ["defi"], "category": "miniapp" } ``` -------------------------------- ### requestAddress Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Requests the connected wallet address from the host shell. The host responds with `wallet_connected` or `wallet_disconnected` messages. ```APIDOC ## requestAddress ### Description Requests the connected wallet address from the host shell. ### Method JavaScript Function Call ### Endpoint N/A (In-app JavaScript function) ### Parameters None ### Request Example ```javascript requestAddress(); ``` ### Response Listens for `wallet_connected` or `wallet_disconnected` messages via `window.addEventListener('message', ...)`. ``` -------------------------------- ### Mini App SDK: Signing Messages Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Requests the host shell to sign a message, supporting 'erc1271' (default) or 'raw' signature types. Returns a Promise that resolves with the signature and verification status on success, or rejects on failure. A `requestId` is used for callback tracking. ```javascript // Request message signing — signatureType: 'erc1271' (default) | 'raw' function signMessage(message, signatureType = 'erc1271') { return new Promise((resolve, reject) => { const requestId = crypto.randomUUID(); _pendingCallbacks[requestId] = { resolve, reject }; window.parent.postMessage({ type: 'sign_message', message, signatureType, requestId }, '*'); }); } ``` -------------------------------- ### ApprovalPopup Component Logic Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Handles transaction and signature approvals within a modal. Manages different request types and communicates results back to the source window. ```svelte {#if pendingRequest} {/if} ``` -------------------------------- ### sendTransactions Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Requests transaction approval from the host shell. Returns a Promise that resolves with transaction hashes upon success or rejects with an error upon rejection. ```APIDOC ## sendTransactions ### Description Requests transaction approval from the host shell. Returns a Promise that resolves with transaction hashes upon success or rejects with an error upon rejection. ### Method JavaScript Function Call ### Endpoint N/A (In-app JavaScript function) ### Parameters * **transactions** (Array) - Required - An array of transaction objects. Each object should have `to`, `data`, and `value` fields. ### Request Example ```javascript const transactions = [ { to: '0xERC20TokenAddress...', data: '0xa9059cbb...', value: '0' } ]; try { const [txHash] = await sendTransactions(transactions); console.log('Sent:', txHash); } catch (error) { console.error('Transaction failed:', error.message); } ``` ### Response * **Success Response (Promise resolves)** * **hashes** (Array) - An array of transaction hashes. * **Error Response (Promise rejects)** * **Error** - An error object with a `reason` property describing the rejection. ``` -------------------------------- ### Service Worker Cache Strategy Summary Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt This comment block summarizes the caching strategies employed by the service worker for different types of assets and requests. It details cache names and the lifecycle of old caches. ```typescript // Cache strategy summary: // // Build/static assets → Cache-first (precached at install, served from APP_CACHE) // miniapps.json → Stale-while-revalidate (served from RUNTIME_CACHE, updated in background) // snapshot.json → Stale-while-revalidate // Navigation (HTML) → Network-first, falls back to runtime cache, then /offline // Images / app-logos/ → Cache-first with runtime cache population on miss // // Cache names are versioned: `app-cache-${version}` / `runtime-cache-${version}` // Old caches are deleted on activate, ensuring stale assets are never served after deploy. // The offline page (/offline) is always precached and served for failed navigations. // Mini app iframes themselves are NOT cached — they come from external origins. ``` -------------------------------- ### signMessage Source: https://context7.com/aboutcircles/circlesminiapps/llms.txt Requests message signing from the host shell. Supports 'erc1271' (default) and 'raw' signature types. Returns a Promise that resolves with the signature and verification status or rejects with an error. ```APIDOC ## signMessage ### Description Requests message signing from the host shell. Supports 'erc1271' (default) and 'raw' signature types. Returns a Promise that resolves with the signature and verification status or rejects with an error. ### Method JavaScript Function Call ### Endpoint N/A (In-app JavaScript function) ### Parameters * **message** (string) - Required - The message to sign. * **signatureType** (string) - Optional - The type of signature to request. Defaults to 'erc1271'. Can be 'erc1271' or 'raw'. ### Request Example ```javascript // Sign for auth (raw bytes — Circles auth service) try { const { signature, verified } = await signMessage('Please sign in to My App', 'raw'); console.log('Signature:', signature, 'Verified:', verified); } catch (error) { console.error('Signing failed:', error.message); } // Sign for XMTP / ERC-1271 consumers try { const { signature, verified } = await signMessage('XMTP identity key', 'erc1271'); console.log('Signature:', signature, 'Verified:', verified); } catch (error) { console.error('Signing failed:', error.message); } ``` ### Response * **Success Response (Promise resolves)** * **signature** (string) - The generated signature. * **verified** (boolean) - Indicates if the signature has been verified by the host. * **Error Response (Promise rejects)** * **Error** - An error object with a `reason` property describing the rejection. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.