### Setup and Run Local Bitcoin Node (Regtest) Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md This bash script is used to set up and run a local Bitcoin node in regtest mode. The first execution without arguments performs the initial setup, including downloading the Bitcoin node software from Bitcoin.org. Subsequent runs start the node without re-downloading. A `--reset` option is available to reset the node's data. ```bash #!/bin/bash # Default setup if [ "$1" != "--reset" ]; then echo "Setting up local Bitcoin node..." # Add download and setup commands here echo "Local Bitcoin node setup complete." fi echo "Starting local Bitcoin node..." # Add commands to start the Bitcoin node in regtest mode here if [ "$1" == "--reset" ]; then echo "Resetting local Bitcoin node..." # Add commands to reset the Bitcoin node data here fi echo "Local Bitcoin node is running." ``` -------------------------------- ### Start dfx with Bitcoin Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Starts the dfx tool with Bitcoin node awareness. Use the --clean flag if a local replica was previously run without Bitcoin. ```bash #!/bin/bash ./scripts/dfx.start-with-bitcoin.sh ``` ```bash #!/bin/bash ./scripts/dfx.start-with-bitcoin.sh --clean ``` -------------------------------- ### Deploy OISY Wallet Locally (Shell) Source: https://github.com/dfinity/oisy-wallet/blob/main/README.md Steps to deploy the OISY Wallet application locally. This involves installing frontend dependencies, creating an environment file, and running the deployment command. It outputs URLs for accessing the frontend and backend canisters. ```shell npm ci npm run deploy ``` -------------------------------- ### Start and Stop IC Local Replica (Shell) Source: https://github.com/dfinity/oisy-wallet/blob/main/README.md Commands to start and stop the local Internet Computer (IC) replica. Ensure dfx.json is present in the directory. The replica is essential for local development and testing. ```shell dfx start --background dfx stop ``` -------------------------------- ### Install Backend Canister on IC Network Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Installs or upgrades the backend canister on the Internet Computer (IC) network using dfx-orbit. Specifies the WASM file and arguments for installation. ```bash dfx-orbit request canister install backend --mode upgrade --wasm out/backend.wasm.gz --arg-file out/backend.args.did ``` -------------------------------- ### Install LLVM and Configure Environment for macOS Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Commands to install LLVM using Homebrew and configure the zsh shell environment variables for C compiler and archiver. This is a prerequisite for macOS development environments that might need specific LLVM versions. ```bash brew install llvm echo 'export CC=$(brew --prefix llvm)/bin/clang' >> ~/.zshrc echo 'export AR=$(brew --prefix llvm)/bin/llvm-ar' >> ~/.zshrc echo 'export PATH=$(brew --prefix llvm)/bin:$PATH' >> ~/.zshrc ``` -------------------------------- ### Build Docker Image for Oisy Wallet Frontend Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Builds the Docker image for the Oisy Wallet frontend using the specified Dockerfile. The image is tagged as 'oisy-wallet'. This command requires Docker to be installed and running. ```bash docker build . --file Dockerfile.frontend -t oisy-wallet --progress=plain ``` -------------------------------- ### Download Index-ng WASM and DID - Bash Script Source: https://github.com/dfinity/oisy-wallet/blob/main/HOW-TO.md This bash script downloads the index-ng WASM and DID files for ICRC-1 index canister setup. It specifies a particular commit of the Internet Computer repository to ensure version compatibility. Ensure the DIR environment variable is set to your desired download location. ```bash #!/bin/bash IC_COMMIT="43f31c0a1b0d9f9ecbc4e2e5f142c56c7d9b0c7b" curl -sSL https://download.dfinity.systems/ic/$IC_COMMIT/canisters/ic-icrc1-index-ng.wasm.gz -o "$DIR"/ckbtc_index.wasm.gz gunzip "$DIR"/ckbtc_index.wasm.gz curl -sSL https://raw.githubusercontent.com/dfinity/ic/$IC_COMMIT/rs/ledger_suite/icrc1/index-ng/index-ng.did -o "$DIR"/ckbtc_index.did ``` -------------------------------- ### Define Enabled EVM Networks Derived Store (TypeScript) Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Creates a derived store (`enabledPolygonNetworks`) that filters and provides a list of enabled Ethereum networks based on user preferences and testnet flags. This example shows the pattern for a specific network (Polygon). ```typescript export const enabledPolygonNetworks: Readable = derived( [testnetsEnabled, userNetworks], ([$testnetsEnabled, $userNetworks]) => defineEnabledNetworks({ $testnetsEnabled, $userNetworks, mainnetFlag: POLYGON_MAINNET_ENABLED, mainnetNetworks: [POLYGON_MAINNET_NETWORK], testnetNetworks: [POLYGON_AMOY_NETWORK] }) ); export const enabledEvmNetworks: Readable = derived( [enabledBaseNetworks, enabledBscNetworks, enabledPolygonNetworks], ([$enabledBaseNetworks, $enabledBscNetworks, $enabledPolygonNetworks]) => [ ...$enabledBaseNetworks, ...$enabledBscNetworks, ...$enabledPolygonNetworks ] ); ``` -------------------------------- ### Deploy Frontend to Beta Environment Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Command to deploy the frontend to the beta network using the dfx CLI. Requires a .env.beta file. Note that the beta frontend points to the production backend. ```bash dfx deploy frontend --network beta --wallet yit3i-lyaaa-aaaan-qeavq-cai ``` -------------------------------- ### Deploy Frontend and Backend to Staging Environment Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Commands to deploy the frontend and backend to the staging network using the dfx CLI. Requires a .env.staging file. Specifies the network and wallet canister for the frontend deployment. ```bash dfx deploy frontend --network staging --wallet cvthj-wyaaa-aaaad-aaaaq-cai dfx deploy backend --network staging ``` -------------------------------- ### Serve Oisy Wallet Frontend Locally Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Serves the frontend build output located in './tmp/frontend-output' using the 'serve' Node.js package. This is an optional step for local testing and requires 'npx' to be available (usually comes with Node.js/npm). ```bash npx serve ./tmp/frontend-output ``` -------------------------------- ### Deploy Frontend and Backend Locally Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Command to deploy the frontend and backend for local development. Requires a .env.development file. Assumes npm is used for package management. ```bash npm run deploy ``` -------------------------------- ### Initialize Theme from Local Storage and System Preferences Source: https://github.com/dfinity/oisy-wallet/blob/main/src/frontend/src/app.html This JavaScript snippet initializes the application's theme by checking local storage for a saved preference or falling back to the system's preferred color scheme (dark or light). It handles potential errors during theme initialization. ```javascript try { const isDarkPreferred = window.matchMedia('(prefers-color-scheme: dark)').matches; const currentTheme = localStorage.nnsTheme === null || localStorage.nnsTheme === undefined || localStorage.nnsTheme === '' ? undefined : JSON.parse(localStorage.nnsTheme); document.documentElement.setAttribute( 'theme', currentTheme ?? (isDarkPreferred ? 'dark' : 'light') ); } catch (error) { console.error('Error initializing theme', error); } ``` -------------------------------- ### Build Frontend Locally with Docker for IC Network Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Builds the frontend application using Docker for the IC network. Utilizes Docker BuildKit for enhanced build process and specifies build arguments for the network. ```bash DOCKER_BUILDKIT=1 docker build -f Dockerfile.frontend --progress=plain --build-arg network=ic -o target/ . ``` -------------------------------- ### Request Frontend Deployment to IC Network Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Requests the deployment of the frontend canister to the IC network using a custom dfx-oisy command. Requires a .env.production file for the frontend and specifies the network and wallet. ```bash dfx-oisy request deploy frontend --network ic --wallet yit3i-lyaaa-aaaan-qeavq-cai ``` -------------------------------- ### Build Backend Using Docker Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Builds the backend application using a local script that likely leverages Docker. Assumes the script `scripts/docker-build` exists and produces output artifacts. ```bash scripts/docker-build ``` -------------------------------- ### User Profile Creation API Source: https://context7.com/dfinity/oisy-wallet/llms.txt Creates a new user profile for authenticated principals, storing preferences and settings on-chain. ```APIDOC ## POST /api/user/profile ### Description Creates a new user profile for authenticated principals, storing preferences and settings on-chain. ### Method POST ### Endpoint /api/user/profile ### Parameters #### Request Body - **identity** (object) - Required - The authenticated user's identity. ### Request Example ```json { "identity": "user_identity_object" } ``` ### Response #### Success Response (200) - **version** (string) - The version of the created profile. - **created_timestamp** (bigint) - The timestamp when the profile was created. - **credentials** (array) - A list of credentials associated with the profile. #### Response Example ```json { "version": "1.0.0", "created_timestamp": "1700000000000000000", "credentials": ["cred1", "cred2"] } ``` ``` -------------------------------- ### Run E2E Visual Snapshot Tests Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Commands to run end-to-end visual regression tests. The first command generates new baseline screenshots, and the second command compares current screenshots against these baselines. ```bash npm run e2e:snapshots npm run e2e ``` -------------------------------- ### Extract Frontend Build Output from Docker Image Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Creates a temporary Docker container from the 'oisy-wallet' image, copies the frontend build output from the container to a local directory './tmp/frontend-output', and then removes the temporary container. Ensure './tmp' directory exists beforehand. ```bash docker create --name oisy-wallet oisy-wallet /bin/true docker cp oisy-wallet:/frontend ./tmp/frontend-output docker rm oisy-wallet ``` -------------------------------- ### Deploy Backend Canister Locally (Shell) Source: https://github.com/dfinity/oisy-wallet/blob/main/README.md Command to deploy only the backend canister of the OISY Wallet project. This is useful for backend-specific development or testing. Assumes the backend is written in Rust and utilizes the tECDSA API. ```shell dfx deploy backend ``` -------------------------------- ### Establish WalletConnect Session with dApp (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Establishes a WalletConnect session with a dApp using a provided URI. It also sets up an event listener to handle subsequent transaction requests from the dApp. This function relies on the `pair` function from `$eth/services/wallet-connect.services`. ```typescript import { pair } from '$eth/services/wallet-connect.services'; async function connectToDapp(wcUri: string) { try { await pair({ uri: wcUri }); console.log('WalletConnect paired successfully'); // Listen for session requests window.addEventListener('oisyWalletConnectRequest', (event) => { console.log('dApp request:', event.detail); }); } catch (error) { console.error('WalletConnect pairing failed:', error); throw error; } } ``` -------------------------------- ### Configure Blockchain Network Settings (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Defines configuration objects for Ethereum and Bitcoin mainnets, including chain IDs, native currencies, and RPC endpoints. It also includes flags to enable or disable specific networks based on environment variables. ```typescript // Ethereum networks export const ETHEREUM_MAINNET_NETWORK = { id: 'eth-mainnet', chainId: 1n, name: 'Ethereum', nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, rpcUrls: { infura: 'https://mainnet.infura.io/v3/', alchemy: 'https://eth-mainnet.g.alchemy.com/v2/' } }; // Bitcoin networks export const BITCOIN_MAINNET_NETWORK = { id: 'btc-mainnet', name: 'Bitcoin', network: { mainnet: null } }; // Enable/disable networks export const ETHEREUM_MAINNET_ENABLED = import.meta.env.VITE_ETHEREUM_MAINNET_DISABLED !== 'true'; ``` -------------------------------- ### Create User Profile (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Initializes a new user profile for authenticated principals. It stores user preferences and settings on the blockchain. This function requires an identity from the authStore and returns the created profile, logging details like version, creation timestamp, and credential count. ```typescript import { createUserProfile } from '$lib/api/backend.api'; import { authStore } from '$lib/stores/auth.store'; import { get } from 'svelte/store'; async function initializeUser() { try { const { identity } = get(authStore); const profile = await createUserProfile({ identity }); console.log('Profile created:', { version: profile.version, created: new Date(Number(profile.created_timestamp / 1000000n)), credentials: profile.credentials.length }); return profile; } catch (error) { console.error('Failed to create profile:', error); throw error; } } ``` -------------------------------- ### Add ckERC20 Tokens Script (SH) Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md This shell script automates the generation of environment files for new ckERC20 tokens. It requires an Etherscan API key to fetch token information from the Ethereum network and creates necessary environment files for tokens that have a corresponding testnet token and are not yet present in the repository. Users should follow the script's instructions and double-check the generated files. ```bash #!/bin/bash TOKEN_NAME=$1 CONTRACT_ADDRESS=$2 if [ -z "$TOKEN_NAME" ] || [ -z "$CONTRACT_ADDRESS" ]; then echo "Usage: $0 " exit 1 fi cp src/frontend/src/env/tokens.usdc.env.ts "src/frontend/src/env/tokens.${TOKEN_NAME,,}.env.ts" sed -i "s/USDC_CONTRACT_ADDRESS/$CONTRACT_ADDRESS/g" "src/frontend/src/env/tokens.${TOKEN_NAME,,}.env.ts" sed -i "s/usdc/${TOKEN_NAME,,}/g" "src/frontend/src/env/tokens.${TOKEN_NAME,,}.env.ts" sed -i "s/USDC/$TOKEN_NAME/g" "src/frontend/src/env/tokens.${TOKEN_NAME,,}.env.ts" echo "Successfully created src/frontend/src/env/tokens.${TOKEN_NAME,,}.env.ts" ``` -------------------------------- ### Load Token Transaction History with Pagination (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Loads the transaction history for a given token, supporting pagination. It fetches transactions using a service and logs them to the console. This function requires the `transactionsStore` and `authStore` to be initialized. ```typescript import { loadTransactions } from '$lib/services/transactions.services'; import { transactionsStore } from '$lib/stores/transactions.store'; import { get } from 'svelte/store'; async function loadTxHistory(tokenId: string) { try { const { identity } = get(authStore); await loadTransactions({ identity, tokenId, certified: true, start: undefined // Load from most recent }); const transactions = get(transactionsStore)[tokenId]; if (transactions?.length) { console.log(`Found ${transactions.length} transactions`); transactions.forEach(tx => { console.log({ hash: tx.id, type: tx.type, amount: tx.value, timestamp: new Date(Number(tx.timestamp / 1000000n)) }); }); } return transactions; } catch (error) { console.error('Transaction load error:', error); throw error; } } ``` -------------------------------- ### CSS Styling for Application Spinner Component Source: https://github.com/dfinity/oisy-wallet/blob/main/src/frontend/src/app.html This CSS defines the appearance and animation of the application's loading spinner. It includes properties for size, color, animation, and the circular path animation using keyframes. ```css #app-spinner { --spinner-size: 30px; color: rgb(0, 102, 255); width: var(--spinner-size); height: var(--spinner-size); animation: app-spinner-linear-rotate 2000ms linear infinite; position: absolute; top: calc(50% - (var(--spinner-size) / 2)); left: calc(50% - (var(--spinner-size) / 2)); --radius: 45px; --circumference: calc(3.14159265359 * var(--radius) * 2); --start: calc((1 - 0.05) * var(--circumference)); --end: calc((1 - 0.8) * var(--circumference)); } #app-spinner circle { stroke-dasharray: var(--circumference); stroke-width: 10%; transform-origin: 50% 50% 0; transition-property: stroke; animation-name: app-spinner-stroke-rotate-100; animation-duration: 4000ms; animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1); animation-iteration-count: infinite; fill: transparent; stroke: currentColor; transition: stroke-dashoffset 225ms linear; } @keyframes app-spinner-linear-rotate { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes app-spinner-stroke-rotate-100 { 0% { stroke-dashoffset: var(--start); transform: rotate(0); } 12.5% { stroke-dashoffset: var(--end); transform: rotate(0); } 12.5001% { stroke-dashoffset: var(--end); transform: rotateX(180deg) rotate(72.5deg); } 25% { stroke-dashoffset: var(--start); transform: rotateX(180deg) rotate(72.5deg); } 25.0001% { stroke-dashoffset: var(--start); transform: rotate(270deg); } 37.5% { stroke-dashoffset: var(--end); transform: rotate(270deg); } 37.5001% { stroke-dashoffset: var(--end); transform: rotateX(180deg) rotate(161.5deg); } 50% { stroke-dashoffset: var(--start); transform: rotateX(180deg) rotate(161.5deg); } 50.0001% { stroke-dashoffset: var(--start); transform: rotate(180deg); } 62.5% { stroke-dashoffset: var(--end); transform: rotate(180deg); } 62.5001% { stroke-dashoffset: var(--end); transform: rotateX(180deg) rotate(251.5deg); } 75% { stroke-dashoffset: var(--start); transform: rotateX(180deg) rotate(251.5deg); } 75.0001% { stroke-dashoffset: var(--start); transform: rotate(90deg); } 87.5% { stroke-dashoffset: var(--end); transform: rotate(90deg); } 87.5001% { stroke-dashoffset: var(--end); transform: rotateX(180deg) rotate(341.5deg); } 100% { stroke-dashoffset: var(--start); transform: rotateX(180deg) rotate(341.5deg); } } ``` -------------------------------- ### Add ckERC20 Tokens Script (MJS) Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md This script automates the generation of environment files for new ckERC20 tokens. It requires an Etherscan API key and fetches token information from the Ethereum network. The script generates necessary environment files for tokens that have a corresponding testnet token and are not yet present in the repository. Users should follow the script's instructions and double-check the generated files. ```javascript import fs from 'fs'; import path from 'path'; const tokenName = process.argv[2]; // e.g., 'USDC' const contractAddress = process.argv[3]; // e.g., '0xA0b86991c6218b36c1d1345860499186674e908a' const envTemplatePath = path.join(__dirname, '../src/frontend/src/env/tokens.usdc.env.ts'); const envTargetPath = path.join(__dirname, `../src/frontend/src/env/tokens.${tokenName.toLowerCase()}.env.ts`); if (!tokenName || !contractAddress) { console.error('Usage: node add.tokens.erc20.mjs '); process.exit(1); } const envTemplateContent = fs.readFileSync(envTemplatePath, 'utf-8'); let newEnvContent = envTemplateContent .replace(/USDC_CONTRACT_ADDRESS/g, contractAddress) .replace(/usdc/g, tokenName.toLowerCase()) .replace(/USDC/g, tokenName); fs.writeFileSync(envTargetPath, newEnvContent); console.log(`Successfully created ${envTargetPath}`); ``` -------------------------------- ### Sign In Flow with Internet Identity (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Handles user authentication using Internet Identity and WebAuthn. This TypeScript function initiates the sign-in process and proceeds with wallet initialization upon successful authentication. It includes error handling for cancelled or failed sign-in attempts. ```typescript import { signIn } from '$lib/services/auth.services'; import { authStore } from '$lib/stores/auth.store'; import { get } from 'svelte/store'; async function authenticateUser() { try { const result = await signIn({ domain: 'ic0.app' }); if (result.success === 'ok') { const { identity } = get(authStore); console.log('Signed in:', identity?.getPrincipal().toText()); // Proceed with app initialization await initializeWallet(); } else if (result.success === 'cancelled') { console.log('User cancelled sign-in'); } else { console.error('Sign-in error:', result.err); } } catch (error) { console.error('Authentication failed:', error); } } async function initializeWallet() { // Load user profile and tokens console.log('Initializing wallet...'); } ``` -------------------------------- ### Define Application Canister IDs and Network Settings (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Defines key application constants, including canister IDs for the backend, internet identity, and signer, as well as network detection flags based on environment variables. These constants are crucial for the application's interaction with the DFINITY blockchain. ```typescript // Backend canister export const BACKEND_CANISTER_ID = 'bkyz2-fmaaa-aaaaa-qaaaq-cai'; // Internet Identity export const II_CANISTER_ID = 'rdmx6-jaaaa-aaaaa-aaadq-cai'; // Signer canister for threshold signatures export const SIGNER_CANISTER_ID = 'grghe-syaaa-aaaar-qabyq-cai'; // Network detection export const LOCAL = import.meta.env.VITE_NETWORK === 'local'; export const MAINNET = import.meta.env.VITE_NETWORK === 'mainnet'; ``` -------------------------------- ### Estimate Bitcoin UTXO Fees - TypeScript Source: https://context7.com/dfinity/oisy-wallet/llms.txt Selects optimal UTXOs and calculates transaction fees for Bitcoin transfers. This function uses the `selectUserUtxosFee` API and requires user authentication identity. It outputs the estimated fee in satoshis and the selected UTXOs. ```typescript import { selectUserUtxosFee } from '$lib/api/backend.api'; import { authStore } from '$lib/stores/auth.store'; import { get } from 'svelte/store'; async function estimateBitcoinTransfer(destinationAddress: string, amountSats: bigint) { try { const { identity } = get(authStore); const result = await selectUserUtxosFee({ identity, network: { mainnet: null }, amount_satoshis: amountSats, min_confirmations: [6] }); if ('Ok' in result) { const { fee_satoshis, utxos } = result.Ok; console.log('Transaction estimate:', { fee: `${fee_satoshis} sats`, utxosCount: utxos.length, totalInput: utxos.reduce((sum, u) => sum + u.value, 0n), estimatedTotal: amountSats + fee_satoshis }); return { fee: fee_satoshis, utxos }; } else { console.error('Fee estimation failed:', result.Err); throw new Error('Cannot estimate fees'); } } catch (error) { console.error('UTXO selection error:', error); throw error; } } ``` -------------------------------- ### Send Solana SOL or SPL Tokens (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Shows how to send SOL or SPL tokens on Solana networks using TypeScript. The function incorporates priority fee settings and progress updates. It requires user identity, token details, recipient address, and the amount in lamports. The output is either a transaction signature or an error message. ```typescript import { send } from '$sol/services/sol-send.services'; import { authStore } from '$lib/stores/auth.store'; import { get } from 'svelte/store'; async function sendSOL(recipient: string, lamports: bigint) { try { const { identity } = get(authStore); const token = { id: 'SOL-mainnet', standard: 'solana', category: 'default', name: 'Solana', symbol: 'SOL', decimals: 9, network: { id: 'sol-mainnet', name: 'Solana Mainnet' } }; const result = await send({ identity, token, to: recipient, amount: lamports, priorityFee: 5000n, // microlamports progress: (step) => console.log('Sending:', step) }); if ('success' in result) { console.log('Signature:', result.success); return result.success; } else { console.error('Send failed:', result.err); throw new Error(result.err); } } catch (error) { console.error('Solana send error:', error); throw error; } } ``` -------------------------------- ### Query Token Balances (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Provides a TypeScript function to retrieve token balances across all networks. It uses a service to load balance information and updates a store. The function takes a `tokenId` and returns the balance details, including data, USD value, and last update timestamp, or logs an error if the query fails. ```typescript import { loadBalance } from '$lib/services/token.services'; import { balancesStore } from '$lib/stores/balances.store'; import { get } from 'svelte/store'; async function fetchBalances(tokenId: string) { try { const { identity } = get(authStore); await loadBalance({ identity, tokenId, certified: true }); const balances = get(balancesStore); const balance = balances[tokenId]; if (balance) { console.log(`${tokenId} balance:`, { data: balance.data, usdValue: balance.usdValue, lastUpdate: new Date(balance.timestamp) }); } return balance; } catch (error) { console.error('Balance query failed:', error); throw error; } } ``` -------------------------------- ### Update Supported EVM Tokens List (TypeScript) Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Includes a new network's token list into the main `SUPPORTED_EVM_TOKENS` array. This makes the new tokens discoverable and usable within the application. ```typescript export const SUPPORTED_EVM_TOKENS = [ ...SUPPORTED_BASE_TOKENS, ...SUPPORTED_BSC_TOKENS, ...SUPPORTED_POLYGON_TOKENS, ...(SUPPORTED_ < NETWORK > _TOKENS) ]; ``` -------------------------------- ### Threshold Signature Authorization API Source: https://context7.com/dfinity/oisy-wallet/llms.txt Approves cycles allowance for signing operations with optional proof-of-work challenge completion. ```APIDOC ## POST /api/auth/allow-signing ### Description Approves cycles allowance for signing operations with optional proof-of-work challenge completion. ### Method POST ### Endpoint /api/auth/allow-signing ### Parameters #### Request Body - **identity** (object) - Required - The authenticated user's identity. - **nonce** (bigint) - Required - The nonce obtained from creating a PoW challenge. ### Request Example ```json { "identity": "user_identity_object", "nonce": "1700000000000000000" } ``` ### Response #### Success Response (200) - **Ok** (object) - Contains the authorization result. - **status** (object) - The status of the authorization (e.g., "authorized"). - **allowed_cycles** (bigint) - The number of cycles allowed for signing operations. - **challenge_completion** (object) - Information about the next proof-of-work challenge if applicable. - **next_difficulty** (number) - The difficulty of the next challenge. #### Error Response (400) - **Err** (string) - Error message if authorization fails. #### Response Example ```json { "Ok": { "status": { "authorized": null }, "allowed_cycles": "1000000000000", "challenge_completion": { "next_difficulty": 10 } } } ``` ``` -------------------------------- ### Send Ethereum ERC-20 Tokens (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Demonstrates sending ERC-20 tokens on Ethereum networks using TypeScript. It includes fee estimation and progress tracking. The function requires user identity, token details (like address and decimals), recipient address, and amount. It handles both successful transactions and errors. ```typescript import { send } from '$eth/services/send.services'; import { authStore } from '$lib/stores/auth.store'; import { get } from 'svelte/store'; async function sendUSDC(recipient: string, amount: bigint) { try { const { identity } = get(authStore); const token = { id: 'USDC-eth', standard: 'erc20', category: 'default', name: 'USD Coin', symbol: 'USDC', decimals: 6, network: { id: 'eth-mainnet', chainId: 1n, name: 'Ethereum' }, address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' }; const progress = (step: string) => { console.log('Transfer progress:', step); }; const result = await send({ identity, token, to: recipient, amount, maxPriorityFeePerGas: 2000000000n, // 2 gwei progress }); if ('success' in result) { console.log('Transaction hash:', result.success); return result.success; } else { console.error('Transfer failed:', result.err); throw new Error(result.err); } } catch (error) { console.error('Send error:', error); throw error; } } ``` -------------------------------- ### Handle and Sign dApp Transaction Requests (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Handles incoming transaction requests from connected dApps, allowing the user to approve or reject them. If approved, it signs the transaction using the provided identity; otherwise, it rejects the request. This function utilizes `approve` and `reject` from `$eth/services/wallet-connect.services` and requires a `showApprovalDialog` function. ```typescript import { approve, reject } from '$eth/services/wallet-connect.services'; async function handleSignRequest(requestId: number, transaction: any) { try { const { identity } = get(authStore); // Show UI for user approval const userApproved = await showApprovalDialog(transaction); if (userApproved) { const signature = await approve({ identity, requestId, transaction }); console.log('Transaction signed:', signature); } else { await reject({ requestId, reason: 'User rejected' }); console.log('Transaction rejected'); } } catch (error) { console.error('Sign request error:', error); await reject({ requestId, reason: error.message }); } } ``` -------------------------------- ### Define Enabled EVM Tokens Derived Store (TypeScript) Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Creates a derived store (`enabledPolygonTokens`) that filters and provides a list of enabled tokens for a specific network (e.g., Polygon) based on user preferences and testnet flags. This is a pattern for defining token availability. ```typescript export const enabledPolygonTokens: Readable = derived( [testnetsEnabled, userNetworks], ([$testnetsEnabled, $userNetworks]) => defineEnabledTokens({ $testnetsEnabled, $userNetworks, mainnetFlag: POLYGON_MAINNET_ENABLED, mainnetTokens: [POL_MAINNET_TOKEN], testnetTokens: [POL_AMOY_TOKEN] }) ); export const enabledEvmTokens: Readable = derived( [enabledBaseTokens, enabledBscTokens, enabledPolygonTokens], ([$enabledBaseTokens, $enabledBscTokens, $enabledPolygonTokens]) => [ ...$enabledBaseTokens, ...$enabledBscTokens, ...$enabledPolygonTokens ] ); ``` -------------------------------- ### Manage Contacts with Multi-Chain Addresses - TypeScript Source: https://context7.com/dfinity/oisy-wallet/llms.txt Handles creation, retrieval, update, and deletion of contacts, supporting multi-chain addresses (Ethereum and Bitcoin). This function demonstrates the use of `createContact`, `updateContact`, `getContacts`, and `deleteContact` APIs, requiring user authentication. ```typescript import { createContact, updateContact, getContacts, deleteContact } from '$lib/api/backend.api'; import { authStore } from '$lib/stores/auth.store'; import { get } from 'svelte/store'; async function manageContacts() { try { const { identity } = get(authStore); // Create new contact const newContact = await createContact({ identity, name: 'Alice' }); console.log('Contact created:', newContact.id); // Update with addresses const updatedContact = await updateContact({ identity, contact: { ...newContact, addresses: [ { token_account_id: { Eth: { Public: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb' } }, label: ['Main Wallet'] }, { token_account_id: { Btc: { P2WPKH: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh' } }, label: ['Bitcoin Address'] } ] } }); // List all contacts const contacts = await getContacts({ identity }); console.log(`Total contacts: ${contacts.length}`); // Delete contact await deleteContact({ identity, contactId: newContact.id }); console.log('Contact deleted'); return contacts; } catch (error) { console.error('Contact management error:', error); throw error; } } ``` -------------------------------- ### Sign Out and Cleanup User Session (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Provides TypeScript functions to sign out a user and handle session timeouts. It utilizes imported services for authentication cleanup. The `signOut` function allows for options like resetting URLs, while `idleSignOut` handles automatic sign-out due to inactivity, displaying a warning. ```typescript import { signOut} from '$lib/services/auth.services'; async function logout() { try { await signOut({ resetUrl: true, clearAllPrincipalsStorages: false, source: 'user-menu' }); // Page will reload automatically } catch (error) { console.error('Logout error:', error); } } // Session timeout handler import { idleSignOut } from '$lib/services/auth.services'; async function handleSessionTimeout() { await idleSignOut(); // Shows warning message and clears session } ``` -------------------------------- ### Update Supported EVM Networks List (TypeScript) Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Appends a new network's supported networks to the global `SUPPORTED_EVM_NETWORKS` list. This ensures the new network is recognized and available within the application. ```typescript export const SUPPORTED_EVM_NETWORKS = [ ...SUPPORTED_BASE_NETWORKS, ...SUPPORTED_BSC_NETWORKS, ...SUPPORTED_POLYGON_NETWORKS, ...(SUPPORTED_ < NETWORK > _NETWORKS) ]; ``` -------------------------------- ### Retrieve User Profile (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Fetches the user's profile data, supporting optional certified queries for data integrity verification. It retrieves network settings, agreements, and experimental feature flags. The function uses the identity from authStore and logs the fetched settings or indicates if the profile is not found. ```typescript import { getUserProfile } from '$lib/api/backend.api'; import { authStore } from '$lib/stores/auth.store'; import { get } from 'svelte/store'; async function loadUserSettings() { try { const { identity } = get(authStore); // Get certified profile data const response = await getUserProfile({ identity, certified: true }); if ('Ok' in response) { const profile = response.Ok; console.log('User settings:', { networks: profile.settings?.networks, agreements: profile.agreements, experimentalFeatures: profile.settings?.experimental_features }); return profile; } else { console.log('Profile not found:', response.Err); return null; } } catch (error) { console.error('Error loading profile:', error); throw error; } } ``` -------------------------------- ### Load Route CSS Dynamically in Svelte Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Loads route-specific CSS dynamically at runtime for local development purposes within a Svelte application. This is controlled by a LOCAL flag. ```javascript ``` -------------------------------- ### Manage Custom ERC20 Tokens - TypeScript Source: https://context7.com/dfinity/oisy-wallet/llms.txt Allows users to add and list custom ERC20 tokens. This function uses `setCustomToken` to add a new token and `listCustomTokens` to retrieve all existing custom tokens. It requires user authentication and token metadata. ```typescript import { setCustomToken, listCustomTokens } from '$lib/api/backend.api'; import { authStore } from '$lib/stores/auth.store'; import { get } from 'svelte/store'; async function addERC20Token() { try { const { identity } = get(authStore); const token = { enabled: true, version: [1n], section: [{ Hidden: null }], allow_external_content_source: [true], token: { Erc20: { chain_id: 1n, token_address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' } } }; await setCustomToken({ identity, token }); console.log('Token added successfully'); // List all custom tokens const tokens = await listCustomTokens({ identity, certified: true }); console.log(`Total custom tokens: ${tokens.length}`); tokens.forEach(t => { if ('Erc20' in t.token) { console.log(` - ERC20: ${t.token.Erc20.token_address}`); } }); return tokens; } catch (error) { console.error('Token management error:', error); throw error; } } ``` -------------------------------- ### Retrieve User Profile API Source: https://context7.com/dfinity/oisy-wallet/llms.txt Fetches the user's profile with optional certified queries for verified data integrity. ```APIDOC ## GET /api/user/profile ### Description Fetches the user's profile with optional certified queries for verified data integrity. ### Method GET ### Endpoint /api/user/profile ### Parameters #### Query Parameters - **identity** (object) - Required - The authenticated user's identity. - **certified** (boolean) - Optional - If true, returns certified data. ### Request Example ```json { "identity": "user_identity_object", "certified": true } ``` ### Response #### Success Response (200) - **Ok** (object) - Contains the user profile data if found. - **settings** (object) - User settings. - **networks** (array) - List of configured networks. - **experimental_features** (boolean) - Flag for experimental features. - **agreements** (array) - List of user agreements. #### Error Response (404) - **Err** (string) - Error message if the profile is not found. #### Response Example ```json { "Ok": { "settings": { "networks": ["ICP", "Ethereum"], "experimental_features": false }, "agreements": ["terms_of_service"] } } ``` ``` -------------------------------- ### Define EVM Network Configuration (TypeScript) Source: https://github.com/dfinity/oisy-wallet/blob/main/HACKING.md Defines the configuration object for an EVM network, including its symbol, ID, name, chain ID, icons, explorer URL, providers, and exchange/buy parameters. This is used for integrating new EVM networks into the wallet. ```typescript export const BSC_MAINNET_NETWORK_SYMBOL = 'BSC'; export const BSC_MAINNET_NETWORK_ID: NetworkId = parseNetworkId(BSC_MAINNET_NETWORK_SYMBOL); export const BSC_MAINNET_NETWORK: EthereumNetwork = { id: BSC_MAINNET_NETWORK_ID, env: 'mainnet', name: 'BNB Smart Chain', chainId: 56n, iconLight: bscMainnetIconLight, iconDark: bscMainnetIconDark, explorerUrl: BSC_EXPLORER_URL, providers: { infura: 'bnb', alchemy: 'bnb', alchemyJsonRpcUrl: 'https://bnb-mainnet.g.alchemy.com/v2' }, exchange: { coingeckoId: 'binance-smart-chain' }, buy: { onramperId: 'bsc' } }; ``` -------------------------------- ### Configure User Settings (TypeScript) Source: https://context7.com/dfinity/oisy-wallet/llms.txt Updates user network preferences, experimental features, and agreements. It requires user identity and interacts with backend APIs. The function retrieves the current user version for optimistic locking before applying updates. ```typescript import { setUserShowTestnets, updateUserNetworkSettings, updateUserExperimentalFeatureSettings, updateUserAgreements, getUserProfile } from '$lib/api/backend.api'; import { authStore } from '$lib/stores/auth.store'; import { get } from 'svelte/store'; async function configureUserSettings() { try { const { identity } = get(authStore); // Get current version for optimistic locking const profileResponse = await getUserProfile({ identity, certified: true }); const currentVersion = 'Ok' in profileResponse ? profileResponse.Ok.version : []; // Enable testnets await setUserShowTestnets({ identity, show_testnets: true, current_user_version: currentVersion }); // Configure networks await updateUserNetworkSettings({ identity, networks: [ [{ EthereumMainnet: null }, { enabled: true, is_testnet: false }], [{ EthereumSepolia: null }, { enabled: true, is_testnet: true }], [{ BitcoinMainnet: null }, { enabled: true, is_testnet: false }] ], current_user_version: currentVersion }); // Enable experimental features await updateUserExperimentalFeatureSettings({ identity, experimental_features: [ [{ AiAssistantBeta: null }, { enabled: true }] ], current_user_version: currentVersion }); // Accept agreements await updateUserAgreements({ identity, agreements: { terms_of_use: { accepted: [true], last_accepted_at_ns: [BigInt(Date.now() * 1000000)], last_updated_at_ms: [], text_sha256: [] }, privacy_policy: { accepted: [true], last_accepted_at_ns: [BigInt(Date.now() * 1000000)], last_updated_at_ms: [], text_sha256: [] }, license_agreement: { accepted: [true], last_accepted_at_ns: [BigInt(Date.now() * 1000000)], last_updated_at_ms: [], text_sha256: [] } }, current_user_version: currentVersion }); console.log('Settings updated successfully'); } catch (error) { console.error('Settings update error:', error); throw error; } } ```