{"version":3,"sources":["../src/user-balance-store.ts"],"names":["createClerkClient","fetchCallReadOnlyFunction","Cl","STACKS_MAINNET","ClarityType"],"mappings":"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","file":"user-balance-store.cjs","sourcesContent":["import { fetchCallReadOnlyFunction, Cl, ClarityType } from '@stacks/transactions';\nimport { STACKS_MAINNET } from '@stacks/network';\nimport { createClerkClient } from '@clerk/backend';\n\nconst CONTRACT_ADDRESS = 'SP2ZNGJ85ENDY6QRHQ5P2D4FXKGZWCKTB2T0Z55KS';\nconst CONTRACT_NAME = 'blaze-welsh-v1';\n\nconst clerkClient = createClerkClient({\n  secretKey: process.env.CLERK_SECRET_KEY,\n  publishableKey: process.env.CLERK_PUBLISHABLE_KEY\n});\n\n// User balance store with Clerk integration\nexport const userBalanceStore = {\n  /**\n   * Get the user's Stacks address from Clerk's publicMetadata\n   */\n  async getUserStacksAddress(userId: string): Promise<string | null> {\n    try {\n      // Get the user from Clerk\n      const user = await clerkClient.users.getUser(userId);\n\n      // Check for Stacks address in public metadata\n      if (user.publicMetadata && typeof user.publicMetadata === 'object') {\n        const metadata = user.publicMetadata as Record<string, any>;\n        if (metadata.stacksAddress) {\n          return metadata.stacksAddress as string;\n        }\n      }\n\n      // No Stacks address found\n      console.warn(`No Stacks address found for user ${userId}`);\n      return null;\n    } catch (error) {\n      console.error(`Error getting Stacks address for user ${userId}:`, error);\n      return null;\n    }\n  },\n\n  /**\n   * Fetch a user's on-chain balance from the contract\n   */\n  async fetchContractBalance(user: string): Promise<number> {\n    try {\n      const result = await fetchCallReadOnlyFunction({\n        contractAddress: CONTRACT_ADDRESS,\n        contractName: CONTRACT_NAME,\n        functionName: 'get-balance',\n        functionArgs: [Cl.principal(user)],\n        network: STACKS_MAINNET,\n        senderAddress: user\n      });\n      const balance = result.type === ClarityType.UInt ? Number(result.value) : 0;\n\n      return balance;\n    } catch (error: unknown) {\n      console.error('Failed to fetch contract balance:', error);\n      return 0;\n    }\n  },\n\n  /**\n   * Get user balance using their Clerk ID\n   * Fetches directly from blockchain if Stacks address is available\n   */\n  async getUserBalance(userId: string) {\n    try {\n      if (!userId) return null;\n\n      // Get stacks address from Clerk\n      const stacksAddress = await this.getUserStacksAddress(userId);\n\n      // Get stored balance data\n      let balance = await kvStore.getEntity('USER_BALANCE', userId);\n\n      // If no balance exists, initialize it\n      if (!balance) {\n        balance = {\n          userId,\n          availableBalance: 0,\n          totalDeposited: 0,\n          totalWithdrawn: 0,\n          inPredictions: 0,\n          lastUpdated: new Date().toISOString(),\n          stacksAddress: null\n        };\n      }\n\n      // If we have a Stacks address, update with real blockchain balance\n      if (stacksAddress) {\n        balance.stacksAddress = stacksAddress;\n        const contractBalance = await this.fetchContractBalance(stacksAddress);\n        balance.availableBalance = contractBalance;\n      }\n\n      return balance;\n    } catch (error) {\n      console.error(`Error getting user balance for ${userId}:`, error);\n      return null;\n    }\n  },\n\n  // Update user balance when making a prediction\n  async updateBalanceForPrediction(userId: string, amount: number) {\n    try {\n      const balance: any = await this.getUserBalance(userId);\n      if (!balance) return null;\n\n      // Check if user has enough balance\n      if (balance.availableBalance < amount) {\n        throw new Error('Insufficient balance');\n      }\n\n      const updatedBalance = {\n        ...balance,\n        availableBalance: balance.availableBalance - amount,\n        inPredictions: balance.inPredictions + amount,\n        lastUpdated: new Date().toISOString()\n      };\n\n      await kvStore.storeEntity('USER_BALANCE', userId, updatedBalance);\n      return updatedBalance;\n    } catch (error) {\n      console.error(`Error updating balance for prediction, user ${userId}:`, error);\n      throw error;\n    }\n  },\n\n  // Update user balance when a prediction is resolved\n  async updateBalanceForResolvedPrediction(\n    userId: string,\n    originalAmount: number,\n    winnings: number = 0\n  ) {\n    try {\n      const balance: any = await this.getUserBalance(userId);\n      if (!balance) return null;\n\n      const updatedBalance = {\n        ...balance,\n        availableBalance: balance.availableBalance + winnings,\n        inPredictions: balance.inPredictions - originalAmount,\n        lastUpdated: new Date().toISOString()\n      };\n\n      await kvStore.storeEntity('USER_BALANCE', userId, updatedBalance);\n      return updatedBalance;\n    } catch (error) {\n      console.error(`Error updating balance for resolved prediction, user ${userId}:`, error);\n      throw error;\n    }\n  },\n\n  // Add funds to user balance (for deposit functionality)\n  async addFunds(userId: string, amount: number) {\n    try {\n      const balance: any = await this.getUserBalance(userId);\n      if (!balance) return null;\n\n      const updatedBalance = {\n        ...balance,\n        availableBalance: balance.availableBalance + amount,\n        totalDeposited: balance.totalDeposited + amount,\n        lastUpdated: new Date().toISOString()\n      };\n\n      await kvStore.storeEntity('USER_BALANCE', userId, updatedBalance);\n      return updatedBalance;\n    } catch (error) {\n      console.error(`Error adding funds for user ${userId}:`, error);\n      throw error;\n    }\n  },\n\n  // Withdraw funds from user balance\n  async withdrawFunds(userId: string, amount: number) {\n    try {\n      const balance: any = await this.getUserBalance(userId);\n      if (!balance) return null;\n\n      // Check if user has enough balance\n      if (balance.availableBalance < amount) {\n        throw new Error('Insufficient balance');\n      }\n\n      const updatedBalance = {\n        ...balance,\n        availableBalance: balance.availableBalance - amount,\n        totalWithdrawn: balance.totalWithdrawn + amount,\n        lastUpdated: new Date().toISOString()\n      };\n\n      await kvStore.storeEntity('USER_BALANCE', userId, updatedBalance);\n      return updatedBalance;\n    } catch (error) {\n      console.error(`Error withdrawing funds for user ${userId}:`, error);\n      throw error;\n    }\n  },\n\n  // Force refresh a user's balance from the blockchain\n  async refreshBalance(userId: string) {\n    try {\n      const stacksAddress = await this.getUserStacksAddress(userId);\n      if (!stacksAddress) {\n        throw new Error(`No Stacks address found for user ${userId}`);\n      }\n\n      const contractBalance = await this.fetchContractBalance(stacksAddress);\n      const balance = await kvStore.getEntity('USER_BALANCE', userId) || {\n        userId,\n        availableBalance: 0,\n        totalDeposited: 0,\n        totalWithdrawn: 0,\n        inPredictions: 0,\n        lastUpdated: new Date().toISOString()\n      };\n\n      const updatedBalance = {\n        ...balance,\n        availableBalance: contractBalance,\n        stacksAddress,\n        lastUpdated: new Date().toISOString()\n      };\n\n      await kvStore.storeEntity('USER_BALANCE', userId, updatedBalance);\n      return updatedBalance;\n    } catch (error) {\n      console.error(`Error refreshing balance for user ${userId}:`, error);\n      throw error;\n    }\n  }\n};\n\nconst kvStore = {\n  async getEntity(collection: string, id: string) {\n    console.log({ collection, id });\n    // Get the user's Stacks address\n    const stacksAddress = await userBalanceStore.getUserStacksAddress(id);\n\n    let availableBalance = 0;\n    if (stacksAddress) {\n      availableBalance = await userBalanceStore.fetchContractBalance(stacksAddress);\n    }\n\n    const balance = {\n      userId: id,\n      availableBalance,\n      totalDeposited: 0,\n      totalWithdrawn: 0,\n      inPredictions: 0,\n      lastUpdated: new Date().toISOString(),\n      stacksAddress\n    };\n    return balance;\n  },\n\n  async storeEntity(collection: string, id: string, entity: any) {\n    console.log({ collection, id, entity });\n    return null;\n  }\n};"]}