### Install ICSI Library using npm, pnpm, or yarn Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Install the ICSI library using your preferred package manager. This is the first step before importing and using the library's functions. ```bash npm install @jagad/icsi # or pnpm install @jagad/icsi # or yarn add @jagad/icsi ``` -------------------------------- ### Install Dependencies and Start Local Replica Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/CLAUDE.md Installs all workspace dependencies using pnpm and starts a local Internet Computer replica with old metering enabled. This is a foundational step for local development and testing. ```bash pnpm install pnpm run start:local:env ``` -------------------------------- ### TypeScript: ICP Subaccount Indexer Quick Start Example Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Demonstrates the full lifecycle of interacting with the ICP Subaccount Indexer. It sets up an agent, creates subaccounts for multiple tokens (ICP, ckUSDC, ckUSDT, ckBTC), retrieves deposit addresses and balances, and fetches recent transaction data. Includes optional webhook configuration and basic error handling. Requires '@dfinity/agent' and '@jagad/icsi' packages. ```typescript import { HttpAgent, } from '@dfinity/agent'; import { createHostAgentAndIdentityFromSeed, addSubaccountForToken, getUserVaultTransactions, getDepositAddresses, getBalances, setWebhookUrl, Tokens, } from '@jagad/icsi'; async function quickStart() { try { // 1. Setup const { agent } = await createHostAgentAndIdentityFromSeed( 'your twelve word seed phrase here', 'https://ic0.app' ); const canisterId = 'qvn3w-rqaaa-aaaam-qd4kq-cai'; // 2. Set webhook (optional) const webhookResult = await setWebhookUrl( agent, canisterId, 'https://your-api.com/webhook' ); console.log('Webhook set:', 'Ok' in webhookResult); // 3. Create subaccounts for all tokens console.log('Creating subaccounts...'); const icpAddr = await addSubaccountForToken(agent, canisterId, Tokens.ICP); const usdcAddr = await addSubaccountForToken( agent, canisterId, Tokens.CKUSDC ); const usdtAddr = await addSubaccountForToken( agent, canisterId, Tokens.CKUSDT ); const btcAddr = await addSubaccountForToken( agent, canisterId, Tokens.CKBTC ); if ('Ok' in icpAddr) console.log('ICP address:', icpAddr.Ok); if ('Ok' in usdcAddr) console.log('ckUSDC address:', usdcAddr.Ok); if ('Ok' in usdtAddr) console.log('ckUSDT address:', usdtAddr.Ok); if ('Ok' in btcAddr) console.log('ckBTC address:', btcAddr.Ok); // 4. Get all addresses console.log('\nAll deposit addresses:'); const addresses = await getDepositAddresses(agent, canisterId); addresses.forEach((addr) => { const tokenType = Object.keys(addr.tokenType)[0]; console.log(`${tokenType}: ${addr.depositAddress}`); }); // 5. Check balances console.log('\nToken balances:'); const balances = await getBalances(agent, canisterId); balances.forEach((balance) => { const tokenType = Object.keys(balance.tokenType)[0]; console.log(`${tokenType}: ${balance.balance}`); }); // 6. Get recent transactions console.log('\nRecent transactions:'); const txResult = await getUserVaultTransactions( agent, canisterId, BigInt(5) ); if ('Ok' in txResult) { txResult.Ok.forEach((tx) => { const tokenType = Object.keys(tx.token_type)[0]; const status = Object.keys(tx.sweep_status)[0]; console.log(`${tokenType}: ${tx.amount} (${status})`); }); } console.log('\nSetup complete! Send tokens to the addresses above.'); } catch (error) { console.error('Error in quickStart:', error); } } // Run the example quickStart(); ``` -------------------------------- ### Local Development Setup and Deployment with DFX and pnpm Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/README.md This set of commands installs project dependencies using pnpm, starts a local replica with specific configurations, and deploys the project locally. It includes steps for generating a test wallet. ```bash # Install all dependencies (monorepo) pnpm install # Start local replica with old metering (required for ICP ledger) pnpm run start:local:env # Deploy locally with ICP ledger pnpm run deploy:local # OR use the deployment script directly .maintain/deploy.sh --network local [--clean] # Generate test wallet for testing pnpm run lib:generate:wallet ``` -------------------------------- ### Create Agent and Identity using Seed Phrase or Private Key Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Set up an agent and identity for interacting with the Internet Computer. This example shows how to create them using either a seed phrase or a PEM-formatted private key, connecting to the 'ic0.app' host. ```typescript // Using seed phrase (recommended) const { agent, identity } = await createHostAgentAndIdentityFromSeed( 'your twelve word seed phrase here', 'https://ic0.app' ); // Or using private key const privateKey = `-----BEGIN EC PRIVATE KEY----- Your PEM private key here -----END EC PRIVATE KEY-----`; const { agent, identity } = await createHostAgentAndIdentityFromPrivateKey( privateKey, 'https://ic0.app' ); ``` -------------------------------- ### Quick Start: Initialize Agent and Interact with ICSI-Lib Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/README.md A quick start guide demonstrating how to initialize an HttpAgent and use key functions from the ICSI-Lib to manage subaccounts, retrieve deposit addresses, and fetch transactions. This example showcases basic usage for ckUSDC tokens. ```typescript import { HttpAgent, getUserVaultTransactions, addSubaccountForToken, getDepositAddresses, Tokens, } from '@jagad/icsi'; // Initialize agent const agent = new HttpAgent({ host: 'https://ic0.app' }); const canisterId = 'your-canister-id'; // Create a new subaccount for ckUSDC const subaccount = await addSubaccountForToken( agent, canisterId, Tokens.CKUSDC ); console.log('New ckUSDC subaccount:', subaccount); // Get all deposit addresses const addresses = await getDepositAddresses(agent, canisterId); console.log('Deposit addresses:', addresses); // Fetch recent transactions const transactions = await getUserVaultTransactions( agent, canisterId, BigInt(10) ); console.log('Recent transactions:', transactions); ``` -------------------------------- ### Initial Project Setup (Bash) Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/WORKSPACE.md Clones the repository and installs project dependencies using pnpm. This is the first step for setting up the development environment. ```bash git clone cd icp-subaccount-indexer pnpm install ``` -------------------------------- ### Quick Testing Workflow for ICP Subaccount Indexer Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/TESTING_GUIDE.md This comprehensive workflow guides users through setting up and testing the ICP Subaccount Indexer. It covers generating test wallets, funding them, deploying the mainnet canister, configuring the environment, starting a webhook server, testing various token deposits, and finally restoring production settings. ```bash # 1. Generate test wallet pnpm run lib:generate:wallet # 2. Fund wallet with test tokens # 3. Deploy canister ./scripts/deploy-mainnet.sh deploy # 4. Configure environment echo 'USER_VAULT_CANISTER_ID="your-canister-id"' >> packages/icsi-lib/.env.test # 5. Start webhook server pnpm run lib:test:webhook # 6. Test deposits pnpm run lib:test:icp pnpm run lib:test:usdc pnpm run lib:test:usdt # 7. Restore production settings dfx canister call CANISTER_ID set_interval '(500 : nat64)' --network ic ``` -------------------------------- ### Import ICSI Library Functions for TypeScript Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Import necessary functions and types from the '@jagad/icsi' library. These imports are required for setting up the agent, identity, and interacting with ICSI functionalities. ```typescript import { HttpAgent } from '@dfinity/agent'; import { createHostAgentAndIdentityFromSeed, addSubaccountForToken, getUserVaultTransactions, getDepositAddresses, Tokens, } from '@jagad/icsi'; ``` -------------------------------- ### Environment Setup Commands Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/CANISTER_DEBUGGING_GUIDE.md This section provides commands for setting up the development environment for both testnet and devnet. It includes setting the `DFX_WARNING` environment variable and using `dfx identity use` to switch identities. It also shows how to retrieve the canister ID from JSON configuration files using `cat` and `jq`. ```bash # Testnet setup export DFX_WARNING=-mainnet_plaintext_identity dfx identity use testnet_custodian CANISTER_ID=$(cat test_canister_ids.json | jq -r '.icp_subaccount_indexer.ic') # Devnet setup export DFX_WARNING=-mainnet_plaintext_identity dfx identity use default CANISTER_ID=$(cat canister_ids.json | jq -r '.icp_subaccount_indexer.ic') ``` -------------------------------- ### Set ICSI Canister ID Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Define the canister ID for the ICSI service. This example provides the mainnet canister ID. ```typescript const canisterId = 'qvn3w-rqaaa-aaaam-qd4kq-cai'; // Mainnet canister ``` -------------------------------- ### Troubleshoot 'Module hash is already installed' Error Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/CANISTER_DEBUGGING_GUIDE.md Provides steps to resolve the error where the module hash is already installed, which typically requires a force upgrade with explicit arguments and verification of the WASM file's recency. ```bash # Force upgrade with explicit arguments dfx canister install $CANISTER_ID --network ic --mode upgrade \ --argument '(variant { Mainnet }, 15 : nat64, 10 : nat32, "ryjl3-tyaaa-aaaaa-aaaba-cai", "YOUR-PRINCIPAL")' # Verify WASM file is recent ls -la target/wasm32-unknown-unknown/release/icp_subaccount_indexer.wasm ``` -------------------------------- ### Payment Processing Workflow Example Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/README.md An example demonstrating a typical payment processing workflow using the '@jagad/icsi' library. It includes setting up webhooks, creating deposit addresses, monitoring payments, and sweeping collected funds. ```typescript import { HttpAgent } from '@dfinity/agent'; import { addSubaccountForToken, getUserVaultTransactions, sweepByTokenType, setWebhookUrl, Tokens, } from '@jagad/icsi'; const agent = new HttpAgent({ host: 'https://ic0.app' }); const canisterId = 'your-canister-id'; // 1. Set up webhook for real-time notifications await setWebhookUrl(agent, canisterId, 'https://your-api.com/webhook'); // 2. Create deposit addresses for customers const usdcAddress = await addSubaccountForToken( agent, canisterId, Tokens.CKUSDC ); console.log('Customer USDC deposit address:', usdcAddress); // 3. Monitor for incoming payments const checkPayments = async () => { const transactions = await getUserVaultTransactions( agent, canisterId, BigInt(50) ); if ('Ok' in transactions) { const recentTransactions = transactions.Ok.filter( (tx) => tx.token_type.CKUSDC !== undefined && tx.sweep_status.Pending !== undefined ); console.log(`Found ${recentTransactions.length} pending USDC payments`); } }; // 4. Sweep collected funds const sweepFunds = async () => { const result = await sweepByTokenType(agent, canisterId, Tokens.CKUSDC); console.log('Sweep result:', result); }; ``` -------------------------------- ### Devnet Setup with DFX CLI Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/CANISTER_DEBUGGING_GUIDE.md Configures the DFX CLI for local development (devnet), sets the default identity, and retrieves the devnet canister ID using jq. This setup is for individual developer control. ```bash # Set environment variables export DFX_WARNING=-mainnet_plaintext_identity # Use your default identity (or preferred development identity) dfx identity use default # Get canister ID CANISTER_ID=$(cat canister_ids.json | jq -r '.icp_subaccount_indexer.ic') echo "Devnet Canister ID: $CANISTER_ID" # Verify identity and principal dfx identity whoami dfx identity get-principal ``` -------------------------------- ### Work with ICSI Token Types Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Utilize the `Tokens` enum to represent different token types (ICP, ckUSDC, ckUSDT, CKBTC) when interacting with ICSI functions. This example also shows how to check token types within transaction data. ```typescript import { Tokens } from '@jagad/icsi'; // Available tokens const icpToken = Tokens.ICP; // { ICP: null } const usdcToken = Tokens.CKUSDC; // { CKUSDC: null } const usdtToken = Tokens.CKUSDT; // { CKUSDT: null } const btcToken = Tokens.CKBTC; // { CKBTC: null } // Check token type in transactions transactions.forEach((tx) => { if (tx.tokenType.ICP) { console.log('ICP transaction'); } else if (tx.tokenType.CKUSDC) { console.log('ckUSDC transaction'); } else if (tx.tokenType.CKUSDT) { console.log('ckUSDT transaction'); } else if (tx.tokenType.CKBTC) { console.log('ckBTC transaction'); } }); ``` -------------------------------- ### Install ICP Subaccount Indexer Canister (Bash) Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/logs/TESTING_ATTEMPT.md Command to install the ICP subaccount indexer canister on the Mainnet. It specifies environment variables, the canister name, network, installation arguments, and mode. The command failed due to insufficient cycles. ```bash export DFX_WARNING=-mainnet_plaintext_identity && dfx canister install icp_subaccount_indexer --network ic --argument '(variant { Mainnet }, 5: nat64, 0: nat32, "ryjl3-tyaaa-aaaaa-aaaba-cai", "$(dfx identity get-principal)")' --mode install ``` -------------------------------- ### Testnet Setup with DFX CLI Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/CANISTER_DEBUGGING_GUIDE.md Configures the DFX CLI for testnet operations, sets the correct identity, and retrieves the testnet canister ID using jq. It emphasizes using the correct identity for operations versus upgrades. ```bash # Set environment variables export DFX_WARNING=-mainnet_plaintext_identity # Switch to testnet custodian identity for operations dfx identity use testnet_custodian # Get canister ID CANISTER_ID=$(cat test_canister_ids.json | jq -r '.icp_subaccount_indexer.ic') echo "Testnet Canister ID: $CANISTER_ID" # Verify identity and principal dfx identity whoami dfx identity get-principal ``` -------------------------------- ### Pre-Upgrade Canister Preparation Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/CANISTER_DEBUGGING_GUIDE.md Steps to prepare for a canister upgrade, including listing and verifying identities, checking canister controllers, and ensuring adequate cycle balance. ```bash # Step 1: Identity Verification dfx identity list for identity in $(dfx identity list | grep -v "^anonymous$"); do echo "$identity: $(dfx identity use $identity && dfx identity get-principal)" done # Step 2: Controller Verification dfx canister info $CANISTER_ID --network ic dfx identity get-principal # Ensure match with controllers # Step 3: Cycle Management dfx canister status $CANISTER_ID --network ic dfx canister deposit-cycles 200000000000 $CANISTER_ID --network ic # 200B minimum ``` -------------------------------- ### NPM Version Update Examples Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/README.md Illustrates bash commands for updating package versions according to semantic versioning principles. It shows examples for patch, minor, and major version increments. ```bash # Bug fix release npm version patch # 1.0.0 → 1.0.1 # New feature release npm version minor # 1.0.1 → 1.1.0 # Breaking change release npm version major # 1.1.0 → 2.0.0 ``` -------------------------------- ### Local Package Testing with NPM Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/README.md Outlines the bash commands for building, packing, and locally installing an NPM package. This is useful for testing the package before publishing. ```bash # Build the package pnpm run build # Test locally with npm pack npm pack # Test installation in another project npm install ./jagad-icsi-1.0.0.tgz ``` -------------------------------- ### Create Subaccount for ICP or ckTokens Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Create a new subaccount for depositing ICP or ckTokens (like ckUSDC). The function returns the deposit address on success or an error object. ```typescript // Create an ICP subaccount const icpResult = await addSubaccountForToken(agent, canisterId, Tokens.ICP); if ('Ok' in icpResult) { console.log('ICP deposit address:', icpResult.Ok); } else { console.error('Error creating ICP subaccount:', icpResult.Err); } // Create a ckUSDC subaccount const usdcResult = await addSubaccountForToken( agent, canisterId, Tokens.CKUSDC ); if ('Ok' in usdcResult) { console.log('ckUSDC deposit address:', usdcResult.Ok); } else { console.error('Error creating ckUSDC subaccount:', usdcResult.Err); } ``` -------------------------------- ### Environment Setup: Wallet and Canister ID Management Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/CLAUDE.md Commands and configurations for setting up the test environment, including generating new test wallets and managing canister IDs by saving them to .env.test. ```bash # Generate fresh: pnpm run lib:generate:wallet # Add to .env.test: USER_VAULT_CANISTER_ID="your-id" ``` -------------------------------- ### GitHub Actions Workflow for NPM Publishing Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/README.md A YAML configuration file for a GitHub Actions workflow that automates the publishing of a package to NPM. It handles Node.js setup, dependency installation, building, and publishing using NPM_TOKEN for authentication. ```yaml name: Publish to NPM on: push: tags: - 'v*' jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' registry-url: 'https://registry.npmjs.org/' - name: Install pnpm uses: pnpm/action-setup@v2 with: version: 8 - name: Install dependencies run: pnpm install - name: Build package run: pnpm run build working-directory: packages/icsi-lib - name: Publish to NPM run: npm publish --access public working-directory: packages/icsi-lib env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} ``` -------------------------------- ### Create and Deploy ICSI Canister Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/TESTING_GUIDE.md Guides through the process of creating a new canister for the ICSI and deploying it to the IC network with a specified amount of cycles. It strongly advises against using command substitution for principal arguments during deployment, recommending hardcoded principals instead. ```bash # Create canister with sufficient cycles dfx canister create icp_subaccount_indexer --network ic --with-cycles 500000000000 # Get your principal and use it as hardcoded string (DO NOT use command substitution) echo "Use this principal in deployment: $(dfx identity get-principal)" ``` -------------------------------- ### Handle 'Ok' and 'Err' Results in ICSI Functions Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Implement robust error handling by checking the 'Ok' and 'Err' properties of function results. This pattern ensures proper handling of both successful operations and potential errors. ```typescript const result = await someICSIFunction(); if ('Ok' in result) { // Success - use result.Ok console.log('Success:', result.Ok); } else { // Error - handle result.Err console.error('Error:', result.Err); } ``` -------------------------------- ### Get All Deposit Addresses Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Retrieve all associated deposit addresses for different token types. The function returns an array of objects, each containing the token type and its corresponding deposit address. ```typescript const addresses = await getDepositAddresses(agent, canisterId); console.log('All deposit addresses:'); addresses.forEach((addr) => { const tokenName = Object.keys(addr.tokenType)[0]; console.log(`${tokenName}: ${addr.depositAddress}`); }); ``` -------------------------------- ### Get All Token Balances with @jagad/icsi Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/EXAMPLES.md Fetches all token balances for a given canister ID and iterates through them to log token names and their respective balances. This function requires an initialized agent and canister ID as input. ```typescript import { getBalances } from '@jagad/icsi'; const balances = await getBalances(agent, canisterId); balances.forEach((balance) => { const tokenName = Object.keys(balance.tokenType)[0]; console.log(`${tokenName}: ${balance.balance}`); }); ``` -------------------------------- ### Setting up ICSI Local Test Environment (Scripts) Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/test/README.md These commands are used to manage the local test environment for the ICSI library. They include starting the local DFX environment, deploying test tokens, and running the full test suite. ```bash # Start local DFX environment pnpm run start:local:env # Deploy test tokens locally ./packages/icsi-lib/scripts/deploy-test-tokens.sh # Run full test suite pnpm run test ``` -------------------------------- ### Check for User Vault Transactions Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Fetch user vault transactions, specifying the number of recent transactions to retrieve. The result indicates success with transaction details or an error. ```typescript const transactionsResult = await getUserVaultTransactions( agent, canisterId, BigInt(10) // Get last 10 transactions ); if ('Ok' in transactionsResult) { const transactions = transactionsResult.Ok; console.log(`Found ${transactions.length} transactions`); transactions.forEach((tx) => { const tokenType = Object.keys(tx.tokenType)[0]; console.log(`${tokenType} transaction: ${tx.amount} (${tx.tx_hash})`); }); } else { console.error('Error fetching transactions:', transactionsResult.Err); } ``` -------------------------------- ### Local Development Commands (Bash) Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/WORKSPACE.md Starts a local replica, deploys the project, generates wallets, and runs ICP tests. These commands are essential for local development and testing. ```bash # Terminal 1: Start local replica pnpm run start:local:env # Terminal 2: Deploy and test pnpm run deploy:local pnpm run lib:generate:wallet pnpm run lib:test:icp ``` -------------------------------- ### Funding and Deploying ICP Subaccount Indexer Canister Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/CANISTER_DEBUGGING_GUIDE.md Commands to ensure adequate funding, create the canister with maximum cycles, and deploy it. These steps are crucial for setting up the indexer service on the Internet Computer. ```bash # Ensure adequate funding (minimum 0.5 ICP) dfx ledger balance --network ic dfx cycles convert --amount=0.5 --network ic # Create canister with maximum cycles dfx canister create icp_subaccount_indexer --network ic --with-cycles 800000000000 # Deploy immediately after creation dfx deploy icp_subaccount_indexer --network ic --argument '(...)' ``` -------------------------------- ### Debug ICRC-3 Connectivity: Test Direct Ledger Access Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/TESTING_GUIDE.md This step involves directly querying specific ICRC token ledgers to isolate connectivity issues. It provides example commands to test access to the ckUSDC and ckBTC ledgers by calling their respective `icrc3_get_blocks` functions with specified start block numbers and lengths. ```bash # Test ckUSDC ledger directly df_canister call xevnm-gaaaa-aaaar-qafnq-cai icrc3_get_blocks '(vec {record { start = 448800 : nat; length = 5 : nat }})' --network ic # Test ckBTC ledger directly df_canister call mxzaz-hqaaa-aaaar-qaada-cai icrc3_get_blocks '(vec {record { start = 3111616 : nat; length = 5 : nat }})' --network ic ``` -------------------------------- ### Execute Canister Upgrade (Testnet) Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/CANISTER_DEBUGGING_GUIDE.md Performs a canister upgrade on the testnet using the STAGING_DEPLOYER identity. This involves building the code, specifying the WASM file, and providing necessary installation arguments. ```bash # Use correct controller identity dfx identity use STAGING_DEPLOYER # Build latest code pnpm run build:canister # Execute upgrade with proper arguments dfx canister install $CANISTER_ID --network ic \ --wasm target/wasm32-unknown-unknown/release/icp_subaccount_indexer.wasm \ --argument '(variant { Mainnet }, 500: nat64, 25002500: nat32, "ryjl3-tyaaa-aaaaa-aaaba-cai", "controller-principal")' \ --mode upgrade # Switch back for operations dfx identity use testnet_custodian ``` -------------------------------- ### Install All Dependencies with pnpm Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/WORKSPACE.md Installs all project dependencies across the entire workspace, including the root project, the icsi-lib package, and any legacy scripts. This command ensures a consistent environment for development and testing. ```bash pnpm install ``` -------------------------------- ### Troubleshooting Installation Issues (Bash) Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/WORKSPACE.md Provides commands to perform a clean installation by removing existing dependencies and lock files, then reinstalling them. It also includes a command to prune the pnpm store, freeing up disk space. ```bash # Clean install rm -rf node_modules packages/*/node_modules pnpm-lock.yaml pnpm install # Clear pnpm cache pnpm store prune ``` -------------------------------- ### Set up ICSI Agent and Identity with Seed Phrase Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/EXAMPLES.md Initializes an HttpAgent and an identity using a seed phrase. This is a prerequisite for most operations and requires the '@dfinity/agent' and '@jagad/icsi' libraries. It takes a seed phrase and the canister host URL as input. ```typescript import { HttpAgent } from '@dfinity/agent'; import { createHostAgentAndIdentityFromSeed } from '@jagad/icsi'; // Create agent with seed phrase const { agent, identity } = await createHostAgentAndIdentityFromSeed( 'your twelve word seed phrase here', 'https://ic0.app' ); const canisterId = 'qvn3w-rqaaa-aaaam-qd4kq-cai'; ``` -------------------------------- ### Install/Upgrade Testnet Canister Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/logs/TESTING_ATTEMPT_11.md Installs or upgrades the canister on the testnet using the correct controller identity and the latest Wasm module. This is the critical step for deploying the multi-token capable indexer to the live testnet environment. ```bash dfx identity use STAGING_DEPLOYER export DFX_WARNING=-mainnet_plaintext_identity dfx canister install uiz2m-baaaa-aaaal-qjbxq-cai --network ic \ --wasm target/wasm32-unknown-unknown/release/icp_subaccount_indexer.wasm \ --argument '(variant { Mainnet }, 15: nat64, 25002500: nat32, "ryjl3-tyaaa-aaaaa-aaaba-cai", "pztcx-5wpjw-ko6rv-3cjff-466eb-4ywbn-a5jww-rs6yy-ypk4a-ceqfb-nqe")' \ --mode upgrade ``` -------------------------------- ### Local Development Commands for ICSI Canister Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/WORKSPACE.md Provides commands for local development of the ICSI canister. This includes starting a local replica, deploying the canister, building the project, and generating TypeScript declarations. Dependencies should be installed before running these commands. ```bash # Start local IC replica pnpm run start:local:env # Deploy to local network pnpm run deploy:local # Build everything pnpm run build # Build just the canister pnpm run build:canister # Build just the TypeScript library pnpm run build:lib # Generate TypeScript declarations pnpm run generate ``` -------------------------------- ### Install/Upgrade Devnet Canister Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/logs/TESTING_ATTEMPT_11.md Installs or upgrades a canister on the IC network with a new Wasm module and initialization arguments. This command is used to deploy the latest version of the subaccount indexer to the devnet for testing. ```bash dfx canister install y3hne-ryaaa-aaaag-aucea-cai --network ic \ --wasm target/wasm32-unknown-unknown/release/icp_subaccount_indexer.wasm \ --argument '(variant { Mainnet }, 15: nat64, 25002500: nat32, "ryjl3-tyaaa-aaaaa-aaaba-cai", "gf3g2-eaeha-ii22q-ij5tb-bep3w-xxwgx-h4roh-6c2sm-cx2sw-tppv4-qqe")' \ --mode upgrade ``` -------------------------------- ### Upgrade ICP Subaccount Indexer Canister Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/TESTING_GUIDE.md Executes the upgrade of the ICP Subaccount Indexer canister. This involves selecting the correct controller identity, building the latest code, and then calling the dfx canister install command with the appropriate arguments and mode. ```bash # Use correct controller identity dfx identity use STAGING_DEPLOYER # Build latest code pnpm run build:canister # Execute upgrade with proper arguments dfx canister install --network ic \ --wasm target/wasm32-unknown-unknown/release/icp_subaccount_indexer.wasm \ --argument '(variant { Mainnet }, 500: nat64, 25002500: nat32, "ryjl3-tyaaa-aaaaa-aaaba-cai", "controller-principal")' \ --mode upgrade ``` -------------------------------- ### Rust: Example Usage of AccountIdentifier::new Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/SUBACCOUNT_DERIVATION_MECHANISM.md Provides a practical example of how to use the `AccountIdentifier::new` function in Rust. It shows the creation of a Principal and then deriving an AccountIdentifier with a default subaccount. ```rust let principal = Principal::from_text("some-principal-id").unwrap(); let account_id = AccountIdentifier::new(principal, None); ``` -------------------------------- ### Build ICSI Library with pnpm Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/test/integration/README.md Commands to build the ICSI library using pnpm. This involves navigating to the library's directory, installing dependencies, and running the build script. It's a prerequisite for running the test scripts. ```bash cd packages/icsi-lib pnpm install pnpm run build ``` -------------------------------- ### Running ICSI Library Tests Locally (pnpm) Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/test/README.md This snippet outlines the commands to install dependencies and run various test suites for the ICSI library using pnpm. It includes commands for running all tests, unit tests, integration tests, tests with coverage, and tests in watch mode. ```bash # Install dependencies pnpm install # Run all tests (includes local setup) pnpm run test # Run only unit tests (fast) pnpm run test:unit # Run only integration tests pnpm run test:integration # Run tests with coverage pnpm run test:coverage # Watch mode for development pnpm run test:watch ``` -------------------------------- ### Get Registered Tokens from Testnet Canister Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/logs/TESTING_ATTEMPT_11.md Retrieves a list of all tokens that have been registered with the ICP subaccount indexer canister on the testnet. This is used to verify that multi-token support is functioning correctly after the upgrade. ```bash dfx identity use testnet_custodian dfx canister call uiz2m-baaaa-aaaal-qjbxq-cai get_registered_tokens --network ic ``` -------------------------------- ### Transaction Monitoring Commands Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/CANISTER_DEBUGGING_GUIDE.md This section outlines commands for monitoring transaction activity within the ICP subaccount indexer. It includes commands to get the total count of transactions, list recent transactions with an optional limit, retrieve a specific transaction by its hash, get the token type of a transaction, and check the balance for various tokens (ICP, CKUSDC, CKUSDT, CKBTC) using `dfx canister call`. ```bash # Check transaction activity dfx canister call $CANISTER_ID get_transactions_count --network ic dfx canister call $CANISTER_ID list_transactions '(opt 10)' --network ic dfx canister call $CANISTER_ID get_transaction '("transaction-hash-here")' --network ic dfx canister call $CANISTER_ID get_transaction_token_type '("tx-hash")' --network ic # Check token balances dfx canister call $CANISTER_ID get_balance '(variant { ICP })' --network ic dfx canister call $CANISTER_ID get_balance '(variant { CKUSDC })' --network ic dfx canister call $CANISTER_ID get_balance '(variant { CKUSDT })' --network ic dfx canister call $CANISTER_ID get_balance '(variant { CKBTC })' --network ic ``` -------------------------------- ### Configure DFX Environment and Identity Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/TESTING_GUIDE.md Sets up the DFX CLI environment for testing, including disabling mainnet plaintext identity warnings and verifying the current identity configuration. It also captures the deployer's principal, which is crucial for deployment arguments. ```bash # Set up environment for testing export DFX_WARNING=-mainnet_plaintext_identity # Verify identity configuration dfx identity list dfx identity whoami dfx identity get-principal # Record your principal for deployment arguments DEPLOYER_PRINCIPAL=$(dfx identity get-principal) echo "Deployer Principal: $DEPLOYER_PRINCIPAL" # Check cycles balance (need substantial amount for large WASM) dfx cycles balance --network ic # Minimum required: 1.0 TC (trillion cycles) ``` -------------------------------- ### Prepare Deployment Environment with DFX Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/TESTING_GUIDE.md This snippet prepares the local environment for deploying the ICP subaccount indexer. It involves setting DFX warnings, selecting the correct controller identity, and verifying ICP funding in the deployer wallet. Finally, it demonstrates converting ICP to cycles, which are necessary for canister operations. ```bash # Set environment export DFX_WARNING=-mainnet_plaintext_identity df_identity use # Verify funding df_ledger balance --network ic # Minimum: 0.5 ICP # Convert to cycles df_cycles convert --amount=0.5 --network ic ``` -------------------------------- ### Webhook POST Request Example Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/README.md Illustrates the format of a POST request sent to a configured webhook URL. The request includes the transaction hash as a query parameter, enabling real-time transaction updates. ```http POST https://your-webhook.com/endpoint?tx_hash= ``` -------------------------------- ### Start Webhook Script Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/logs/TESTING_ATTEMPT_10.md Initiates the webhook script for testing purposes. This command assumes the project utilizes pnpm as its package manager and has a 'lib:test:webhook' script defined. ```bash pnpm run lib:test:webhook ``` -------------------------------- ### Complete Payment System Implementation Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/EXAMPLES.md A comprehensive payment processing system that initializes webhook URLs, creates customer wallets with subaccounts for various tokens, and processes incoming payments by fetching pending transactions and sweeping them. It uses a class-based structure for organization. ```typescript import { addSubaccountForToken, setWebhookUrl, getUserVaultTransactions, sweepByTokenType, Tokens, } from '@jagad/icsi'; class PaymentProcessor { constructor( private agent: HttpAgent, private canisterId: string ) {} async initialize(webhookUrl: string) { // Set webhook for notifications await setWebhookUrl(this.agent, this.canisterId, webhookUrl); console.log('Payment processor initialized'); } async createCustomerWallet(customerId: string) { const addresses = { customerId, icp: await addSubaccountForToken(this.agent, this.canisterId, Tokens.ICP), usdc: await addSubaccountForToken( this.agent, this.canisterId, Tokens.CKUSDC ), usdt: await addSubaccountForToken( this.agent, this.canisterId, Tokens.CKUSDT ), btc: await addSubaccountForToken( this.agent, this.canisterId, Tokens.CKBTC ), }; console.log(`Created wallet for customer ${customerId}:`, addresses); return addresses; } async processPayments() { // Get recent transactions const result = await getUserVaultTransactions( this.agent, this.canisterId, BigInt(100) ); if ('Ok' in result) { const pendingTransactions = result.Ok.filter( (tx) => tx.sweep_status.Pending !== undefined ); console.log(`Found ${pendingTransactions.length} pending payments`); // Process each transaction for (const tx of pendingTransactions) { await this.processTransaction(tx); } } } private async processTransaction(tx: any) { console.log(`Processing transaction: ${tx.tx_hash}`); // Your business logic here // e.g., update database, send notifications, etc. // Mark as processed by sweeping const tokenType = tx.token_type.ICP ? Tokens.ICP : tx.token_type.CKUSDC ? Tokens.CKUSDC : tx.token_type.CKUSDT ? Tokens.CKUSDT : Tokens.CKBTC; await sweepByTokenType(this.agent, this.canisterId, tokenType); } } // Usage const processor = new PaymentProcessor(agent, canisterId); await processor.initialize('https://your-api.com/webhook'); // Create customer wallets const wallet1 = await processor.createCustomerWallet('customer-123'); const wallet2 = await processor.createCustomerWallet('customer-456'); // Process incoming payments setInterval(async () => { await processor.processPayments(); }, 30000); // Check every 30 seconds ``` -------------------------------- ### Use BigInt for Amounts and Intervals in ICSI Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/GETTING_STARTED.md Handle numerical values like transaction amounts and polling intervals using JavaScript's `BigInt` type. This is crucial for precise financial calculations and time intervals within the ICSI library. ```typescript import { setUserVaultInterval } from '@jagad/icsi'; // Set polling interval to 30 seconds await setUserVaultInterval(agent, canisterId, BigInt(30)); // Get specific number of transactions await getUserVaultTransactions(agent, canisterId, BigInt(50)); ``` -------------------------------- ### Handle Fee Amount Confusion for Different Token Types Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/TESTING_GUIDE.md Examples demonstrating how to correctly set fees for ICRC-1 token transfers, specifically highlighting the differences between ckUSDC/ckUSDT and ckBTC fee structures. This ensures that transactions are not rejected due to incorrect fee amounts or units. ```bash # ckUSDC transfer (correct fee) dfx canister call xevnm-gaaaa-aaaar-qafnq-cai icrc1_transfer '(record { amount = 100000 : nat; # 0.1 ckUSDC fee = opt (10000 : nat); # ✅ CORRECT: 0.01 ckUSDC ... })' --network ic # ckBTC transfer (different fee structure) dfx canister call mxzaz-hqaaa-aaaar-qaada-cai icrc1_transfer '(record { amount = 100 : nat; # 100 satoshis fee = opt (10 : nat); # ✅ CORRECT: 10 satoshis ... })' --network ic ``` -------------------------------- ### Identity and Authorization Troubleshooting for DFX Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/docs/CANISTER_DEBUGGING_GUIDE.md Commands and configurations to resolve identity and authorization errors when interacting with canisters. This includes listing and using identities, checking canister controllers, and managing DFX security warnings for mainnet operations. ```bash # 1. Map all available identities to their principals dfx identity list for identity in $(dfx identity list | grep -v "^anonymous$"); do echo "$identity: $(dfx identity use $identity && dfx identity get-principal)" done # 2. Check canister controllers dfx canister info $CANISTER_ID --network ic # 3. Use correct identity for specific operations: # - Controller identity (e.g., STAGING_DEPLOYER): For canister upgrades # - Custodian identity (e.g., testnet_custodian): For operations # - Operator identity (e.g., default): For daily operations # 4. Fix corrupted identity configuration if needed cat ~/.config/dfx/identity.json # Should be: {"default": "default"} # 5. Suppress security warnings export DFX_WARNING=-mainnet_plaintext_identity ``` -------------------------------- ### Get Balances (Legacy TypeScript) Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/test/README.md Legacy TypeScript script to check balances for all subaccounts. Requires .env configuration and is run via 'pnpm run test:script'. ```bash pnpm run test:script -- test/scripts/legacy/getBalances.ts ``` -------------------------------- ### Smart Sweep Operation with Fee Calculation using ICSI Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/packages/icsi-lib/docs/EXAMPLES.md Performs a 'smart sweep' operation for a specified token type, ensuring sufficient balance and calculating minimum sweep amounts based on predefined fees. This function uses authenticated ICSI calls to get balances and initiate the sweep. It returns an error if the balance is too low. ```typescript import { getBalances, sweepByTokenType, Tokens } from '@jagad/icsi'; export const smartSweep = async ( userVaultCanisterId: string, tokenType: typeof Tokens.CKUSDC ) => { // Check balance first const balances = await addHttpAgent(getBalances, [userVaultCanisterId]); const tokenName = Object.keys(tokenType)[0]; const balance = balances.find( (b) => Object.keys(b.tokenType)[0] === tokenName ); if (!balance || balance.balance === 0) { return { Err: 'No balance to sweep' }; } // Calculate fees and minimum amounts const fees = { ICP: 10000, // 0.0001 ICP CKUSDC: 10000, // 0.01 CKUSDC CKUSDT: 10000, // 0.01 CKUSDT CKBTC: 10, // 0.0000001 BTC }; const fee = fees[tokenName] || 10000; const minAmount = fee * 10; // 10x fee as minimum if (balance.balance < minAmount) { return { Err: `Balance ${balance.balance} too low for efficient sweep (min: ${minAmount})`, }; } // Perform sweep return await addHttpAgent(sweepByTokenType, [userVaultCanisterId, tokenType]); }; ``` -------------------------------- ### Generate and Fund Test Wallet using pnpm Source: https://github.com/garudaidr/icp-subaccount-indexer/blob/main/README.md This sequence of commands is part of the testing setup. First, it generates a test wallet. Second, it instructs to fund the generated wallet with test tokens, referring to `TESTING_GUIDE.md` for detailed instructions on obtaining and transferring test tokens. ```bash pnpm run lib:generate:wallet # Fund the wallet with test tokens (see TESTING_GUIDE.md) ```