Skip to main content
Glama
integratedWallet.ts3.44 kB
import { P2PKH, type PrivateKey, Script } from "@bsv/sdk"; import { DropletClient, type DropletConfig } from "../../utils/droplet"; import { Wallet } from "./wallet"; export interface IntegratedWalletConfig { // Local wallet config paymentKey?: PrivateKey; identityKey?: PrivateKey; // Droplet API config useDropletApi?: boolean; dropletConfig?: DropletConfig; } /** * Integrated wallet that can use either local keys or Droplet API */ export class IntegratedWallet { private localWallet?: Wallet; private dropletClient?: DropletClient; constructor(private config: IntegratedWalletConfig) { if (config.useDropletApi && config.dropletConfig) { // If we have a payment key, use it for auth with Droplet API if (config.paymentKey) { config.dropletConfig.authKey = config.paymentKey; } this.dropletClient = new DropletClient(config.dropletConfig); console.error("IntegratedWallet: Using Droplet API mode"); } else if (config.paymentKey) { this.localWallet = new Wallet(config.paymentKey, config.identityKey); console.error("IntegratedWallet: Using local wallet mode"); } else { console.error( "IntegratedWallet: No wallet configured (limited functionality)", ); } } get isDropletMode(): boolean { return !!this.dropletClient; } get hasWallet(): boolean { return !!this.localWallet || !!this.dropletClient; } async getBalance(): Promise<number> { if (this.dropletClient) { const status = await this.dropletClient.getFaucetStatus(); return status.balance_satoshis; } if (this.localWallet) { return this.localWallet.getTotalBalance(); } throw new Error("No wallet configured"); } async sendToAddress( address: string, satoshis: number, description?: string, ): Promise<{ txid: string }> { if (this.dropletClient) { // For Droplet API, we use the tap endpoint which sends the faucet's fixed amount // Note: Droplet API doesn't support custom amounts, it uses fixed_drop_sats const response = await this.dropletClient.tap(address); return { txid: response.txid }; } if (this.localWallet) { const tx = await this.localWallet.createAction({ description: description || "Send to address", outputs: [ { lockingScript: new P2PKH().lock(address).toHex(), satoshis, outputDescription: `Payment to ${address}`, }, ], }); return { txid: tx.txid }; } throw new Error("No wallet configured"); } async pushData(data: string[], encoding = "hex"): Promise<{ txid: string }> { if (this.dropletClient) { const response = await this.dropletClient.push(data, encoding); return { txid: response.txid }; } if (this.localWallet) { // For local wallet, we need to implement OP_RETURN transaction // This is a simplified version - you might want to enhance this const opReturnScript = Script.fromASM( `OP_FALSE OP_RETURN ${data.join(" ")}`, ); const tx = await this.localWallet.createAction({ description: "Push data", outputs: [ { lockingScript: opReturnScript.toHex(), satoshis: 0, outputDescription: "OP_RETURN data", }, ], }); return { txid: tx.txid }; } throw new Error("No wallet configured"); } // Delegate other methods to the appropriate implementation getLocalWallet(): Wallet | undefined { return this.localWallet; } getDropletClient(): DropletClient | undefined { return this.dropletClient; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/b-open-io/bsv-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server