### Install Handcash SDK Source: https://docs.handcash.io Install the Handcash SDK using npm. This is the first step to integrate Handcash features into your application. ```bash npm install @handcash/sdk ``` -------------------------------- ### Basic Handcash SDK v3 Setup Source: https://docs.handcash.io/v3/getting-started Initialize the Handcash SDK instance with your application credentials and obtain an authenticated client. This setup is required before making API calls. ```typescript import { getInstance, Connect } from '@handcash/sdk'; const sdk = getInstance({ appId: 'YOUR_APP_ID', appSecret: 'YOUR_APP_SECRET', }); // Get user client after authentication const client = sdk.getAccountClient(''); ``` -------------------------------- ### Install Handcash SDK v3 Source: https://docs.handcash.io/v3/getting-started Install the Handcash SDK v3 package using npm. This is the first step to integrating Handcash services into your Node.js application. ```bash npm install @handcash/sdk ``` -------------------------------- ### Get Items Inventory - Search Source: https://docs.handcash.io/v3/items/inventory Searches for items in the user's inventory that match a specific string. ```APIDOC ## Get Items Inventory - Search ### Description Searches for items in the user's inventory that match a specific string. ### Method POST ### Endpoint /items/inventory ### Parameters #### Request Body - **client** (object) - Required - The authenticated Handcash client. - **body** (object) - Required - An object containing query parameters. - **searchString** (string) - Required - The string to search for within item names or descriptions. - **limit** (number) - Optional - The maximum number of items to return. ``` -------------------------------- ### Get All Balances Source: https://docs.handcash.io/v3/connect/payments Fetches all of the user's balances, including those that may not be immediately spendable. This provides a comprehensive view of their holdings. ```typescript const { data: allBalances } = await Connect.getBalances({ client }); console.log('All balances:', allBalances); ``` -------------------------------- ### Get Items Inventory - Basic Source: https://docs.handcash.io/v3/items/inventory Fetches the user's basic item inventory. This call returns a list of items, potentially grouped by type. ```APIDOC ## Get Items Inventory - Basic ### Description Fetches the user's basic item inventory. This call returns a list of items, potentially grouped by type. ### Method POST ### Endpoint /items/inventory ### Parameters #### Request Body - **client** (object) - Required - The authenticated Handcash client. - **body** (object) - Optional - An object containing query parameters for filtering and pagination. - **searchString** (string) - Optional - Filters items by a search string. - **limit** (number) - Optional - The maximum number of items to return. - **collectionId** (string) - Optional - Filters items by a specific collection ID. - **group** (boolean) - Optional - If false, returns all individual item instances instead of grouped quantities. Defaults to true. - **groupingValue** (string) - Optional - Filters items by a specific grouping value. - **from** (number) - Optional - The starting index for pagination. - **to** (number) - Optional - The ending index for pagination. - **sort** (string) - Optional - The field to sort the results by (e.g., 'name'). - **order** (string) - Optional - The order of sorting ('asc' or 'desc'). ### Request Example ```json { "client": "", "body": {} } ``` ### Response #### Success Response (200) - **data** (array) - An array of item objects. - **items** (array) - Contains the list of items retrieved based on the query parameters. ``` -------------------------------- ### Get User Permissions Source: https://docs.handcash.io/v3/connect/authentication Retrieves the permissions granted by the user to your application. ```typescript const { data } = await Connect.getPermissions({ client }) console.log('User granted permissions:', data?.items) ``` -------------------------------- ### Simple Profile Card Component Source: https://docs.handcash.io/v3/connect/profiles A React component example for displaying a simple user profile card using the UserProfile interface. ```typescript function ProfileCard({ profile }: { profile: UserProfile }) { return { handle: profile.publicProfile.handle, displayName: profile.publicProfile.displayName, avatar: profile.publicProfile.avatarUrl, email: profile.privateProfile.email }; } ``` -------------------------------- ### Send a Basic Payment Source: https://docs.handcash.io/v3/connect/payments Initiates a basic payment transaction. Requires user authentication and a business wallet setup. Specifies instrument and denomination currency codes, and receiver details. ```typescript import { getInstance, Connect } from '@handcash/sdk'; const sdk = getInstance({ appId, appSecret }); const client = sdk.getAccountClient(authToken); const { data, error } = await Connect.pay({ client, body: { instrumentCurrencyCode: 'BSV', denominationCurrencyCode: 'USD', receivers: [ { destination: 'recipient-handle', sendAmount: 0.01 } ] } }); if (error) { console.error('Payment failed:', error); } else { console.log('Payment successful:', data); } ``` -------------------------------- ### Get Spendable Balances Source: https://docs.handcash.io/v3/connect/payments Retrieves the user's spendable balances. This is useful for checking available funds before initiating a transaction. ```typescript const { data: balances } = await Connect.getSpendableBalances({ client }); console.log('Spendable balances:', balances); ``` -------------------------------- ### Get Public Profiles by Handle Source: https://docs.handcash.io/v3/connect/profiles Retrieves public profile information for a list of user handles. Use a static client for accessing public data. ```typescript const { data: profiles } = await Connect.getPublicUserProfiles({ client: sdk.client, // Static client for public data body: { handles: ['user1', 'user2', 'user3'] } }); profiles.forEach(profile => { console.log(`${profile.handle}: ${profile.displayName}`); }); ``` -------------------------------- ### Get Items Inventory - All Items Ungrouped Source: https://docs.handcash.io/v3/items/inventory Fetches all individual item instances from the user's inventory, without grouping identical items. Useful for displaying each item instance separately. ```APIDOC ## Get Items Inventory - All Items Ungrouped ### Description Fetches all individual item instances from the user's inventory, without grouping identical items. Useful for displaying each item instance separately. ### Method POST ### Endpoint /items/inventory ### Parameters #### Request Body - **client** (object) - Required - The authenticated Handcash client. - **body** (object) - Required - An object containing query parameters. - **group** (boolean) - Required - Set to `false` to retrieve ungrouped items. - **limit** (number) - Optional - The maximum number of items to return. ``` -------------------------------- ### Friends List Component Source: https://docs.handcash.io/v3/connect/profiles A React component example for rendering a list of friends, extracting key public profile information for each friend. ```typescript function FriendsList({ friends }: { friends: UserProfile[] }) { return friends.map(friend => ({ handle: friend.publicProfile.handle, displayName: friend.publicProfile.displayName, avatar: friend.publicProfile.avatarUrl })); } ``` -------------------------------- ### Get Current User Profile Source: https://docs.handcash.io/v3/connect/profiles Fetches the profile of the currently authenticated user. Requires a valid authentication token and client. ```APIDOC ## Get Current User Profile ### Description Fetches the profile of the currently authenticated user. This includes both public and private profile information. ### Method POST ### Endpoint /connect/profiles/me ### Parameters #### Request Body - **client** (object) - Required - The Handcash Connect client instance. ### Request Example ```json { "client": "{client_instance}" } ``` ### Response #### Success Response (200) - **publicProfile** (object) - Contains public profile details like id, handle, paymail, displayName, avatarUrl, and createdAt. - **privateProfile** (object) - Contains private profile details, such as email. ### Response Example ```json { "publicProfile": { "id": "string", "handle": "string", "paymail": "string", "displayName": "string", "avatarUrl": "string", "createdAt": "string" }, "privateProfile": { "email": "string" } } ``` ``` -------------------------------- ### Get Basic User Inventory Source: https://docs.handcash.io/v3/items/inventory Fetches the user's complete item inventory. Ensure user authentication and items permissions are granted before use. Requires the Handcash SDK instance and an authenticated account client. ```typescript import { getInstance, Connect } from '@handcash/sdk'; const sdk = getInstance({ appId, appSecret }); const client = sdk.getAccountClient(authToken); const { data: items } = await Connect.getItemsInventory({ client, body: {} }); console.log(`User has ${items.length} items`); ``` -------------------------------- ### Get Items Inventory - Filter by Collection Source: https://docs.handcash.io/v3/items/inventory Retrieves items from the user's inventory that belong to a specific collection. ```APIDOC ## Get Items Inventory - Filter by Collection ### Description Retrieves items from the user's inventory that belong to a specific collection. ### Method POST ### Endpoint /items/inventory ### Parameters #### Request Body - **client** (object) - Required - The authenticated Handcash client. - **body** (object) - Required - An object containing query parameters. - **collectionId** (string) - Required - The ID of the collection to filter by. - **limit** (number) - Optional - The maximum number of items to return. ``` -------------------------------- ### Get Exchange Rates Source: https://docs.handcash.io/v3/business-wallet/payouts Fetch the current exchange rate between currencies. This is useful for determining payout amounts in different denominations. ```typescript // Get current exchange rates const rates = await Connect.getExchangeRate({ client: businessClient, path: { currencyCode: 'USD' } }); console.log('USD to BSV rate:', rates.data?.rate); ``` -------------------------------- ### Get Payment Details Source: https://docs.handcash.io/v3/connect/payments Fetches the details of a specific payment using its transaction ID. Requires the client and the transaction ID. ```typescript const { data: payment } = await Connect.getPaymentDetails({ client, path: { transactionId: 'transaction-id' } }); console.log('Payment details:', payment); ``` -------------------------------- ### Get Public Profiles by Handle Source: https://docs.handcash.io/v3/connect/profiles Retrieves public profile information for a list of user handles. Useful for displaying user information in social contexts. ```APIDOC ## Get Public Profiles by Handle ### Description Retrieves public profile information for a list of user handles. This is useful for displaying user information in social contexts or for lookups. ### Method POST ### Endpoint /connect/profiles/public ### Parameters #### Query Parameters - **client** (object) - Required - The Handcash Connect client instance. Can be a static client for public data. #### Request Body - **handles** (array of strings) - Required - A list of user handles to retrieve profiles for. ### Request Example ```json { "handles": ["user1", "user2", "user3"] } ``` ### Response #### Success Response (200) - **profiles** (array of objects) - A list of public profile objects, each containing at least 'handle', 'displayName', and 'avatarUrl'. ### Response Example ```json [ { "handle": "user1", "displayName": "User One", "avatarUrl": "http://example.com/avatar.png" }, { "handle": "user2", "displayName": "User Two", "avatarUrl": "http://example.com/avatar2.png" } ] ``` ``` -------------------------------- ### Get User's Friends Source: https://docs.handcash.io/v3/connect/profiles Fetches the list of friends for the authenticated user. An empty handles array retrieves friends. ```typescript const { data: friends } = await Connect.getPublicUserProfiles({ client, body: { handles: [] // Empty array gets user's friends } }); console.log(`User has ${friends.length} friends`); ``` -------------------------------- ### Get Exchange Rate Source: https://docs.handcash.io/v3/connect/payments Retrieves the current exchange rate for a specified currency. Uses a static client and requires the currency code. ```typescript const { data: rate } = await Connect.getExchangeRate({ client: sdk.client, // Use static client for exchange rates path: { currencyCode: 'USD' } }); console.log('USD exchange rate:', rate); ``` -------------------------------- ### Get Current User Profile Source: https://docs.handcash.io/v3/connect/profiles Fetches the authenticated user's profile data. Ensure user authentication is completed and profile permissions are granted. ```typescript import { getInstance, Connect } from '@handcash/sdk'; const sdk = getInstance({ appId, appSecret }); const client = sdk.getAccountClient(authToken); const { data: profile } = await Connect.getCurrentUserProfile({ client }); console.log('User profile:', profile); ``` -------------------------------- ### Get Items Inventory - Advanced Filtering Source: https://docs.handcash.io/v3/items/inventory Performs advanced filtering on the user's inventory using multiple criteria including search string, collection ID, grouping, pagination, sorting, and ordering. ```APIDOC ## Get Items Inventory - Advanced Filtering ### Description Performs advanced filtering on the user's inventory using multiple criteria including search string, collection ID, grouping, pagination, sorting, and ordering. ### Method POST ### Endpoint /items/inventory ### Parameters #### Request Body - **client** (object) - Required - The authenticated Handcash client. - **body** (object) - Required - An object containing advanced query parameters. - **searchString** (string) - Optional - Filters items by a search string. - **collectionId** (string) - Optional - Filters items by a specific collection ID. - **groupingValue** (string) - Optional - Filters items by a specific grouping value. - **from** (number) - Optional - The starting index for pagination. - **to** (number) - Optional - The ending index for pagination. - **sort** (string) - Optional - The field to sort the results by (e.g., 'name'). - **order** (string) - Optional - The order of sorting ('asc' or 'desc'). - **limit** (number) - Optional - The maximum number of items to return. ``` -------------------------------- ### Get All Individual Items (Ungrouped) Source: https://docs.handcash.io/v3/items/inventory Fetches all individual item instances, rather than grouped quantities. This is useful for displaying each item separately or tracking unique item IDs. Set 'group: false' to enable this behavior. ```typescript const { data: items } = await Connect.getItemsInventory({ client, body: { group: false, limit: 100 } }); console.log(`Found ${items.length} individual items (ungrouped)`); ``` -------------------------------- ### Get User's Friends Source: https://docs.handcash.io/v3/connect/profiles Retrieves the list of friends for the current user. This is achieved by calling the public profiles endpoint with an empty handles array. ```APIDOC ## Get User's Friends ### Description Retrieves the list of friends for the current user. This is achieved by calling the public profiles endpoint with an empty handles array in the request body. ### Method POST ### Endpoint /connect/profiles/public ### Parameters #### Query Parameters - **client** (object) - Required - The Handcash Connect client instance. #### Request Body - **handles** (array of strings) - Required - An empty array `[]` to signify fetching the current user's friends. ### Request Example ```json { "handles": [] } ``` ### Response #### Success Response (200) - **friends** (array of objects) - A list of public profile objects representing the user's friends. ### Response Example ```json [ { "handle": "friend1", "displayName": "Friend One", "avatarUrl": "http://example.com/friend1.png" } ] ``` ``` -------------------------------- ### Initialize Handcash Items Client Source: https://docs.handcash.io/v3/items/creation Instantiate the Items client using your application's credentials. Ensure you have your business wallet token for authentication. ```typescript import { Items } from '@handcash/sdk'; const itemsClient = Items.fromAppCredentials({ appId: 'YOUR_APP_ID', authToken: 'YOUR_AUTH_TOKEN', // Business wallet token appSecret: 'YOUR_APP_SECRET' }); ``` -------------------------------- ### Create Item Order with Error Handling Source: https://docs.handcash.io/v3/items/creation Demonstrates how to create an item order and handle potential errors such as invalid collections, insufficient permissions, or invalid media. ```typescript try { const creationOrder = await itemsClient.createItemsOrder({ collectionId, items: [/* item data */] }); } catch (error) { if (error.message.includes('Invalid collection')) { console.log('Collection ID is invalid'); } else if (error.message.includes('Insufficient permissions')) { console.log('Business wallet needs item creation permissions'); } else if (error.message.includes('Invalid media')) { console.log('Media URL or content type is invalid'); } } ``` -------------------------------- ### Error Handling for User Creation Source: https://docs.handcash.io/v3/connect/user-creation Demonstrates how to catch and handle potential errors during user account creation, such as taken handles, invalid emails, or insufficient permissions. ```typescript try { const account = await Connect.createUserAccount({ client: sdk.client, email: 'user@example.com', handle: 'username', displayName: 'User Name' }); } catch (error) { if (error.message.includes('Handle already exists')) { console.log('Handle is already taken'); } else if (error.message.includes('Invalid email')) { console.log('Email format is invalid'); } else if (error.message.includes('Insufficient permissions')) { console.log('App needs user creation permissions'); } else { console.log('Unexpected error:', error.message); } } ``` -------------------------------- ### Create a Basic Item Order Source: https://docs.handcash.io/v3/items/creation Create a single digital item with specified metadata, attributes, and image details. This is the fundamental structure for item creation. ```typescript const creationOrder = await itemsClient.createItemsOrder({ collectionId: 'collection-id-here', items: [ { name: 'Legendary Sword', description: 'A powerful weapon forged in dragon fire', rarity: 'Legendary', quantity: 1, color: '#FF4500', attributes: [ { name: 'Attack', value: '100', displayType: 'number' }, { name: 'Element', value: 'Fire', displayType: 'string' }, { name: 'Durability', value: '95', displayType: 'number' } ], mediaDetails: { image: { url: 'https://example.com/sword.png', contentType: 'image/png' } } } ] }); console.log('Items order created:', creationOrder.id); ``` -------------------------------- ### Complete User Creation Flow Source: https://docs.handcash.io/v3/connect/user-creation A comprehensive function that first checks handle availability, then creates the user account, and finally sends a verification email. It returns account and verification details. ```typescript async function createCompleteUser(email: string, handle: string, displayName: string) { try { // 1. Check handle availability const handleCheck = await Connect.checkHandleAvailability({ client: sdk.client, handle: handle }); if (!handleCheck.available) { throw new Error('Handle not available'); } // 2. Create user account const account = await Connect.createUserAccount({ client: sdk.client, email: email, handle: handle, displayName: displayName }); console.log('Wallet created successfully'); console.log('User ID:', account.userId); console.log('Handle:', account.handle); // 3. Send verification email const verification = await Connect.sendVerificationCode({ client: sdk.client, email: email }); return { account, verification }; } catch (error) { console.error('Error creating user:', error); throw error; } } ``` -------------------------------- ### Basic User Account Creation Source: https://docs.handcash.io/v3/connect/user-creation Create a new user account with basic email verification. Ensure you have your app ID and secret configured. ```typescript import { getInstance, Connect } from '@handcash/sdk'; const sdk = getInstance({ appId: 'your-app-id', appSecret: 'your-app-secret' }); // Create user account with email verification const account = await Connect.createUserAccount({ client: sdk.client, email: 'user@example.com', handle: 'username', displayName: 'User Display Name' }); console.log('Account created:', account.userId); ``` -------------------------------- ### Error Handling for Profile Fetching Source: https://docs.handcash.io/v3/connect/profiles Demonstrates how to handle potential errors when fetching user profiles, including invalid tokens and permission denials. Redirects or logs errors as appropriate. ```typescript try { const { data: profile } = await Connect.getCurrentUserProfile({ client }); } catch (error) { if (error.message.includes('Invalid token')) { // Redirect to re-authenticate res.redirect(sdk.getRedirectionUrl()); } else if (error.message.includes('Permission denied')) { // Handle insufficient permissions console.log('User needs to grant profile permission'); } } ``` -------------------------------- ### Create Items with Actions Source: https://docs.handcash.io/v3/items/creation Define interactive actions for your items, such as 'Open' for a mystery box, by providing a name, description, URL, and enabled status. ```typescript const creationOrder = await itemsClient.createItemsOrder({ collectionId: 'collection-id-here', items: [ { name: 'Mystery Box', rarity: 'Rare', quantity: 1, color: '#FFD700', attributes: [ { name: 'Type', value: 'Container', displayType: 'string' } ], mediaDetails: { image: { url: 'https://example.com/mystery-box.png', contentType: 'image/png' } }, actions: [ { name: 'Open', description: 'Open this box to reveal random items', url: 'https://yourgame.com/open-box', enabled: true } ] } ] }); ``` -------------------------------- ### User Account Creation with Custom Verification Email Source: https://docs.handcash.io/v3/connect/user-creation Create a user account and specify a custom subject and body for the verification email. This allows for branded communication. ```typescript // Create account with custom verification email const account = await Connect.createUserAccount({ client: sdk.client, email: 'user@example.com', handle: 'username', displayName: 'User Display Name', customVerificationEmail: { subject: 'Welcome to Our App!', body: 'Please verify your account by clicking the link below...' } }); ``` -------------------------------- ### Handle HandCash Callback and Authenticate User Source: https://docs.handcash.io/v3/connect/authentication On callback, retrieve the stored private key, initialize the HandCash SDK, and fetch the user's profile to verify authentication. Requires your appId and appSecret. ```typescript import { getInstance, Connect } from '@handcash/sdk' const privateKey = sessionStorage.getItem('handcash_private_key') // Retrieve stored key const sdk = getInstance({ appId: 'YOUR_APP_ID', appSecret: 'YOUR_APP_SECRET' }) const client = sdk.getAccountClient(privateKey) // Validate by fetching user profile const { data: profile } = await Connect.getCurrentUserProfile({ client }) console.log('User authenticated:', profile.publicProfile.handle) ``` -------------------------------- ### Batch Item Creation Source: https://docs.handcash.io/v3/items/creation Creates multiple items in a single order using provided item templates. Useful for bulk item creation based on predefined configurations. ```typescript async function createItemBatch(collectionId: string, itemTemplates: any[]) { const items = itemTemplates.map(template => ({ name: template.name, rarity: template.rarity, quantity: template.quantity, color: template.color, attributes: template.attributes, mediaDetails: template.mediaDetails, externalId: template.externalId // For tracking in your system })); return await itemsClient.createItemsOrder({ collectionId, items }); } ``` -------------------------------- ### Implement Tipping System Source: https://docs.handcash.io/v3/connect/payments A function to facilitate sending tips to a specified recipient. It encapsulates the payment logic for a simple tipping feature. ```typescript async function sendTip(recipientHandle: string, amount: number) { const { data, error } = await Connect.pay({ client, body: { instrumentCurrencyCode: 'BSV', denominationCurrencyCode: 'USD', description: 'Tip', receivers: [{ destination: recipientHandle, sendAmount: amount }] } }); return { success: !error, data, error }; } ``` -------------------------------- ### Initialize Handcash SDK Instance Source: https://docs.handcash.io Initialize the Handcash SDK instance with your application's appId and appSecret. This instance is used to access various Handcash functionalities. ```javascript import { getInstance, Connect } from '@handcash/sdk'; const sdk = getInstance({ appId: 'your-app-id', appSecret: 'your-app-secret' }); ``` -------------------------------- ### Create Items with 3D Models Source: https://docs.handcash.io/v3/items/creation Include 3D model assets for your digital items by specifying a multimedia URL with the appropriate content type (e.g., 'application/glb'). ```typescript const creationOrder = await itemsClient.createItemsOrder({ collectionId: 'collection-id-here', items: [ { name: '3D Dragon', rarity: 'Epic', quantity: 1, color: '#FF0000', attributes: [ { name: 'Size', value: 'Large', displayType: 'string' }, { name: 'Power', value: '1000', displayType: 'number' } ], mediaDetails: { image: { url: 'https://example.com/dragon-thumb.png', contentType: 'image/png' }, multimedia: { url: 'https://example.com/dragon-model.glb', contentType: 'application/glb' } } } ] }); ``` -------------------------------- ### Redirect to HandCash for Authorization Source: https://docs.handcash.io/v3/connect/authentication Construct the authorization URL and redirect the user to HandCash. Ensure you replace 'YOUR_APP_ID' with your actual application ID. ```typescript const authUrl = `https://handcash.io/connect?appId=YOUR_APP_ID&publicKey=${publicKey}` window.location.href = authUrl ``` -------------------------------- ### Search and Filter Items by Rarity Source: https://docs.handcash.io/v3/items/inventory Fetches items from the user's inventory that match a specified rarity. It performs an initial search and then filters the results client-side for exact matches. Requires an authentication token. ```typescript async function getRareItems(authToken: string, rarity: string) { const client = sdk.getAccountClient(authToken); const { data: items } = await Connect.getItemsInventory({ client, body: { searchString: rarity, limit: 50 } }); return items.filter(item => item.rarity.toLowerCase() === rarity.toLowerCase() ); } ``` -------------------------------- ### Required Dependency for Key Generation Source: https://docs.handcash.io/v3/connect/authentication This snippet shows the required dependency for generating cryptographic keys using the @noble/secp256k1 library. ```json { "@noble/secp256k1": "2.2.3" } ``` -------------------------------- ### Check Business Wallet Balance Source: https://docs.handcash.io/v3/business-wallet/payouts Retrieve the spendable balances for your business wallet. This helps in monitoring funds available for payouts. ```typescript // Get business wallet balance const balance = await Connect.getSpendableBalances({ client: businessClient }); console.log('Business wallet balance:', balance); ``` -------------------------------- ### Check User Permissions Source: https://docs.handcash.io/v3/connect/profiles Fetches the list of permissions granted by the user to the application. Used to determine what actions the application is allowed to perform on behalf of the user. ```APIDOC ## Check User Permissions ### Description Fetches the list of permissions granted by the user to the application. This is crucial for understanding the scope of actions the application can perform on behalf of the user. ### Method GET ### Endpoint /connect/permissions ### Parameters #### Query Parameters - **client** (object) - Required - The Handcash Connect client instance. ### Response #### Success Response (200) - **permissions** (array of strings) - A list of strings, where each string represents a granted permission (e.g., 'PAY', 'USER_PUBLIC_PROFILE'). ### Response Example ```json [ "PAY", "USER_PUBLIC_PROFILE" ] ``` ``` -------------------------------- ### CreateItemMetadata Interface Source: https://docs.handcash.io/v3/items/creation Defines the structure for metadata used when creating items. Includes properties for name, rarity, quantity, attributes, and media details. ```typescript interface CreateItemMetadata { name: string; description?: string; rarity?: string; quantity: number; color?: string; attributes: ItemAttributeMetadata[]; mediaDetails: MediaDetails; actions?: Action[]; groupingValue?: string; externalId?: string; user?: string; // If not provided, items go to business wallet } interface ItemAttributeMetadata { name: string; value: string | number; displayType: 'string' | 'number' | 'date'; } interface MediaDetails { image: File; multimedia?: File; // For 3D models } interface File { url: string; contentType: string; } interface Action { name: string; description: string; url: string; enabled?: boolean; } ``` -------------------------------- ### Fetch User's Item Collection Source: https://docs.handcash.io/v3/items/inventory Retrieves a user's item inventory using an authentication token and groups the items by their collection name. Requires the SDK and Connect modules to be initialized. ```typescript async function getUserCollection(authToken: string) { const client = sdk.getAccountClient(authToken); const { data: items } = await Connect.getItemsInventory({ client, body: { limit: 100 } }); // Group by collection const grouped = items.reduce((acc, item) => { const collectionName = item.collection.name; if (!acc[collectionName]) { acc[collectionName] = []; } acc[collectionName].push(item); return acc; }, {}); return grouped; } ``` -------------------------------- ### User Dashboard Data Fetching Source: https://docs.handcash.io/v3/connect/profiles Asynchronously fetches user profile, spendable balances, and permissions for a user dashboard. Requires a valid authentication token. ```typescript async function getUserDashboard(authToken: string) { const client = sdk.getAccountClient(authToken); const [profile, balances, permissions] = await Promise.all([ Connect.getCurrentUserProfile({ client }), Connect.getSpendableBalances({ client }), Connect.getPermissions({ client }) ]); return { user: profile.data, balance: balances.data, permissions: permissions.data }; } ``` -------------------------------- ### Check Handle Availability Source: https://docs.handcash.io/v3/connect/user-creation Checks if a desired username handle is available for registration. Returns an object indicating availability. ```typescript // Check if handle is available const availability = await Connect.checkHandleAvailability({ client: sdk.client, handle: 'desired-handle' }); if (!availability.available) { console.log('Handle is not available, try another one'); } ``` -------------------------------- ### Search Items in Inventory Source: https://docs.handcash.io/v3/items/inventory Searches the user's inventory for items matching a specific string. Useful for finding items by name or description. The 'limit' parameter controls the maximum number of results returned. ```typescript const { data: items } = await Connect.getItemsInventory({ client, body: { searchString: 'dragon', limit: 20 } }); console.log(`Found ${items.length} items matching "dragon"`); ``` -------------------------------- ### Generate Authentication Key Pair Source: https://docs.handcash.io/v3/connect/authentication Generates a public and private key pair for authentication. This is the first step in the HandCash authentication process. ```typescript const { privateKey, publicKey } = generateAuthenticationKeyPair() ``` -------------------------------- ### Associate Private Key with User Session Source: https://docs.handcash.io/v3/connect/authentication After successful authentication, associate the private key with the user's server-side session or store it persistently in the database. ```typescript req.session.handcashPrivateKey = privateKey ``` ```typescript // or await db.users.update(userId, { handcashPrivateKey: privateKey }) ``` -------------------------------- ### Include State in Authorization URL Source: https://docs.handcash.io/v3/connect/authentication Constructs the HandCash authorization URL by appending the generated public key and state parameter. ```typescript const authUrl = `https://handcash.io/connect?appId=YOUR_APP_ID&publicKey=${publicKey}&state=${state}` window.location.href = authUrl ``` -------------------------------- ### Send a Payment with Description Source: https://docs.handcash.io/v3/connect/payments Sends a payment with an optional description. Useful for providing context to the transaction. ```typescript const { data, error } = await Connect.pay({ client, body: { instrumentCurrencyCode: 'BSV', denominationCurrencyCode: 'USD', description: 'Payment for services', receivers: [ { destination: 'recipient-handle', sendAmount: 10.00 } ] } }); ``` -------------------------------- ### Send Basic Payout Source: https://docs.handcash.io/v3/business-wallet/payouts Send a single payout from a business wallet. Specify the instrument and denomination currency codes, and the recipient's destination and send amount. ```typescript // Send payout from business wallet const payout = await Connect.pay({ client: businessClient, body: { instrumentCurrencyCode: 'BSV', denominationCurrencyCode: 'USD', receivers: [ { destination: 'recipient@handcash.io', sendAmount: 0.01 } ] } }); ``` -------------------------------- ### Generate Authentication Key Pair Source: https://docs.handcash.io/v3/connect/authentication Generates a new private and public key pair using the @noble/secp256k1 library. This is essential for signing authentication requests. ```typescript import * as secp256k1 from "@noble/secp256k1" export function generateAuthenticationKeyPair() { const privateKey = secp256k1.utils.randomSecretKey() const publicKey = secp256k1.getPublicKey(privateKey, true) return { privateKey: Buffer.from(privateKey).toString("hex"), publicKey: Buffer.from(publicKey).toString("hex"), } } ``` -------------------------------- ### Check User Permissions Source: https://docs.handcash.io/v3/connect/profiles Retrieves the permissions granted by the user. Allows checking for specific permissions like 'PAY' or 'USER_PUBLIC_PROFILE'. ```typescript const { data: permissions } = await Connect.getPermissions({ client }); console.log('Granted permissions:', permissions); // Check specific permission const hasPayPermission = permissions.includes('PAY'); const hasProfilePermission = permissions.includes('USER_PUBLIC_PROFILE'); ``` -------------------------------- ### Store Private Key Source: https://docs.handcash.io/v3/connect/authentication Securely store the generated private key. Client-side storage options include localStorage or sessionStorage, while server-side options include databases or Redis. ```typescript // Client example sessionStorage.setItem('handcash_private_key', privateKey) ``` ```typescript // Server example await db.users.update(userId, { handcashPrivateKey: privateKey }) ``` -------------------------------- ### Business Wallet Authentication Source: https://docs.handcash.io/v3/business-wallet/payouts Obtain a business wallet client using a business authentication token. Ensure you have obtained this token from the Handcash Developer Dashboard. ```typescript import { getInstance, Connect } from '@handcash/sdk'; const sdk = getInstance({ appId: 'your-app-id', appSecret: 'your-app-secret' }); // Get business wallet client using business auth token const businessClient = sdk.getAccountClient(''); ``` -------------------------------- ### Calculate Item Statistics Source: https://docs.handcash.io/v3/items/inventory Aggregates statistics from a user's entire item inventory, including total item count and counts broken down by rarity, collection, and application. Requires an authentication token and fetches up to 1000 items. ```typescript async function getItemStats(authToken: string) { const client = sdk.getAccountClient(authToken); const { data: items } = await Connect.getItemsInventory({ client, body: { limit: 1000 } }); const stats = { total: items.length, byRarity: {}, byCollection: {}, byApp: {} }; items.forEach(item => { // Count by rarity stats.byRarity[item.rarity] = (stats.byRarity[item.rarity] || 0) + 1; // Count by collection const collectionName = item.collection.name; stats.byCollection[collectionName] = (stats.byCollection[collectionName] || 0) + 1; // Count by app const appName = item.app.name; stats.byApp[appName] = (stats.byApp[appName] || 0) + 1; }); return stats; } ``` -------------------------------- ### Implement Batch Payments Source: https://docs.handcash.io/v3/connect/payments A function to send payments to multiple recipients in a batch. It maps an array of recipient objects to the required format for the SDK. ```typescript async function sendBatchPayments(recipients: Array<{handle: string, amount: number}>) { const { data, error } = await Connect.pay({ client, body: { instrumentCurrencyCode: 'BSV', denominationCurrencyCode: 'USD', description: 'Batch payment', receivers: recipients.map(r => ({ destination: r.handle, sendAmount: r.amount })) } }); return { success: !error, data, error }; } ``` -------------------------------- ### Handle Inventory API Errors Source: https://docs.handcash.io/v3/items/inventory Use this try-catch block to gracefully handle potential errors when fetching inventory items. It specifically checks for invalid tokens and permission denials, allowing for appropriate redirection or user feedback. ```typescript try { const { data: items } = await Connect.getItemsInventory({ client, body: { searchString: 'dragon' } }); } catch (error) { if (error.message.includes('Invalid token')) { // Redirect to re-authenticate res.redirect(sdk.getRedirectionUrl()); } else if (error.message.includes('Permission denied')) { // Handle insufficient permissions console.log('User needs to grant items permission'); } } ``` -------------------------------- ### Create Multiple Items in One Order Source: https://docs.handcash.io/v3/items/creation Efficiently create multiple distinct items within a single order request. This is useful for batching related items like consumables or sets. ```typescript const creationOrder = await itemsClient.createItemsOrder({ collectionId: 'collection-id-here', items: [ { name: 'Health Potion', rarity: 'Common', quantity: 10, color: '#00FF00', attributes: [ { name: 'Healing', value: '50', displayType: 'number' }, { name: 'Type', value: 'Consumable', displayType: 'string' } ], mediaDetails: { image: { url: 'https://example.com/potion.png', contentType: 'image/png' } } }, { name: 'Magic Ring', rarity: 'Rare', quantity: 1, color: '#800080', attributes: [ { name: 'Magic Power', value: '75', displayType: 'number' }, { name: 'Enchantment', value: 'Protection', displayType: 'string' } ], mediaDetails: { image: { url: 'https://example.com/ring.png', contentType: 'image/png' } } } ] }); ``` -------------------------------- ### Verify Email Code Source: https://docs.handcash.io/v3/connect/user-creation Verifies the code provided by the user against the one sent via email. Requires the email, the code, and the request ID from the sendVerificationCode step. ```typescript // Verify the code provided by user const verified = await Connect.verifyEmailCode({ client: sdk.client, email: 'user@example.com', verificationCode: '123456', requestId: 'request-id-from-send-verification' }); if (verified.success) { console.log('Email verified successfully'); } ``` -------------------------------- ### Send Email Verification Code Source: https://docs.handcash.io/v3/connect/user-creation Initiates the process of sending a verification code to the user's email address. This is a prerequisite for verifying the email. ```typescript // Send verification code to user's email const verification = await Connect.sendVerificationCode({ client: sdk.client, email: 'user@example.com' }); console.log('Verification code sent to:', verification.email); console.log('Request ID:', verification.requestId); ``` -------------------------------- ### Handle Payout Errors Source: https://docs.handcash.io/v3/business-wallet/payouts Implement error handling for payout operations. The try-catch block allows you to gracefully manage potential failures during the payout process. ```typescript try { const payout = await Connect.pay({ client: businessClient, body: { instrumentCurrencyCode: 'BSV', denominationCurrencyCode: 'USD', receivers: [ { destination: 'recipient@handcash.io', sendAmount: 0.01 } ] } }); if (payout.data) { console.log('Payout successful:', payout.data); } } catch (error) { console.error('Payout failed:', error.message); } ``` -------------------------------- ### Inventory Grid Data Transformation Source: https://docs.handcash.io/v3/items/inventory Transforms an array of item objects into a format suitable for an inventory grid, including essential display properties like id, name, image, rarity, and color. ```typescript function InventoryGrid({ items }: { items: Item[] }) { return items.map(item => ({ id: item.id, name: item.name, image: item.imageUrl, rarity: item.rarity, color: item.color })); } ``` -------------------------------- ### Friend Lookup Function Source: https://docs.handcash.io/v3/connect/profiles Searches for public profiles of given handles and returns a mapped array with handle, display name, and avatar URL. Uses a static client. ```typescript async function findFriends(handles: string[]) { const { data: profiles } = await Connect.getPublicUserProfiles({ client: sdk.client, body: { handles } }); return profiles.map(profile => ({ handle: profile.handle, displayName: profile.displayName, avatar: profile.avatarUrl })); } ``` -------------------------------- ### Filter Inventory by Collection Source: https://docs.handcash.io/v3/items/inventory Retrieves items belonging to a specific collection. Use this to display or manage items from a particular set. The 'limit' parameter restricts the number of items fetched. ```typescript const { data: items } = await Connect.getItemsInventory({ client, body: { collectionId: 'collection-id-here', limit: 50 } }); console.log(`Found ${items.length} items in collection`); ``` -------------------------------- ### Generate Game Items Source: https://docs.handcash.io/v3/items/creation Generates a specified number of game items with random rarity, color, and attributes. Useful for populating game inventories or testing. ```typescript async function generateGameItems(collectionId: string, itemCount: number) { const items = []; for (let i = 0; i < itemCount; i++) { const rarity = ['Common', 'Rare', 'Epic', 'Legendary'][Math.floor(Math.random() * 4)]; const colors = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF']; items.push({ name: `Generated Item ${i + 1}`, rarity, quantity: 1, color: colors[Math.floor(Math.random() * colors.length)], attributes: [ { name: 'Level', value: Math.floor(Math.random() * 100), displayType: 'number' }, { name: 'Type', value: 'Generated', displayType: 'string' } ], mediaDetails: { image: { url: `https://example.com/generated-${i}.png`, contentType: 'image/png' } } }); } return await itemsClient.createItemsOrder({ collectionId, items }); } ``` -------------------------------- ### Send Bulk Payouts Source: https://docs.handcash.io/v3/business-wallet/payouts Send multiple payouts efficiently in a single request. Provide a list of receivers, each with a destination and send amount. ```typescript // Send multiple payouts const bulkPayout = await Connect.pay({ client: businessClient, body: { instrumentCurrencyCode: 'BSV', denominationCurrencyCode: 'USD', receivers: [ { destination: 'user1@handcash.io', sendAmount: 0.01 }, { destination: 'user2@handcash.io', sendAmount: 0.02 } ] } }); ``` -------------------------------- ### Handle Payment Errors Source: https://docs.handcash.io/v3/connect/payments Provides a structured way to handle various payment-related errors, such as insufficient funds or invalid destinations. Implement a robust error handling system. ```typescript try { const { data, error } = await Connect.pay({ client, body: { /* payment details */ } }); if (error) { switch (error.code) { case 'INSUFFICIENT_FUNDS': console.log('User has insufficient funds'); break; case 'INVALID_DESTINATION': console.log('Invalid recipient address'); break; case 'PERMISSION_DENIED': console.log('User denied payment permission'); break; default: console.log('Payment failed:', error.message); } } } catch (err) { console.error('Unexpected error:', err); } ``` -------------------------------- ### Generate and Store State for Connect Source: https://docs.handcash.io/v3/connect/authentication Generates a random state parameter using Node.js crypto and stores it in either server-side session or client-side sessionStorage. This state is used to prevent CSRF attacks. ```typescript import crypto from 'crypto' // Generate random state const state = crypto.randomBytes(32).toString('hex') // Store in session (server-side example) req.session.handcashState = state // Or client-side (sessionStorage) sessionStorage.setItem('handcash_state', state) ``` -------------------------------- ### Advanced Inventory Filtering Source: https://docs.handcash.io/v3/items/inventory Applies multiple filters including search string, collection ID, grouping value, range, sort order, and direction. This allows for highly specific inventory queries. ```typescript const { data: items } = await Connect.getItemsInventory({ client, body: { searchString: 'legendary', collectionId: 'collection-id', groupingValue: 'group-id', from: 0, to: 20, sort: 'name', order: 'asc' } }); ``` -------------------------------- ### UserProfile Data Structure Source: https://docs.handcash.io/v3/connect/profiles Defines the structure for user profile data, including public and private fields. ```typescript interface UserProfile { publicProfile: { id: string; handle: string; paymail: string; displayName: string; avatarUrl: string; createdAt: string; }; privateProfile: { email: string; }; } ``` -------------------------------- ### Item Data Structure Definition Source: https://docs.handcash.io/v3/items/inventory Defines the TypeScript interfaces for an Item and its associated attributes, used to represent digital assets within the HandCash ecosystem. ```typescript interface Item { id: string; origin: string; name: string; description: string; imageUrl: string; multimediaUrl?: string; rarity: string; color: string; attributes: ItemAttribute[]; collection: { id: string; name: string; description: string; }; user: { alias: string; displayName: string; profilePictureUrl: string; }; app: { id: string; name: string; iconUrl: string; }; } interface ItemAttribute { name: string; value: string | number; displayType: 'string' | 'number' | 'date'; } ``` -------------------------------- ### Send a Payment to Multiple Recipients Source: https://docs.handcash.io/v3/connect/payments Distributes a payment across multiple recipients in a single transaction. Ensure your payment processing infrastructure can handle this. ```typescript const { data, error } = await Connect.pay({ client, body: { instrumentCurrencyCode: 'BSV', denominationCurrencyCode: 'USD', receivers: [ { destination: 'user1', sendAmount: 5.00 }, { destination: 'user2', sendAmount: 3.00 }, { destination: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', sendAmount: 2.00 } ] } }); ``` -------------------------------- ### Permission Check Utility Source: https://docs.handcash.io/v3/connect/profiles A utility function to check if a given permission is included in a list of granted permissions. Returns a boolean. ```typescript function checkPermission(permissions: string[], required: string): boolean { return permissions.includes(required); } // Usage const canPay = checkPermission(permissions, 'PAY'); const canReadProfile = checkPermission(permissions, 'USER_PUBLIC_PROFILE'); ```