UNPKG

@faktoryfun/styx-sdk

Version:

Bitcoin deposit SDK for Stacks applications, enabling trustless Bitcoin-to-sBTC deposits

330 lines (329 loc) 11.6 kB
export class BitcoinDepositAPI { constructor(baseUrl, apiKey) { this.baseUrl = baseUrl; // Use provided API key or fall back to a hardcoded one this.apiKey = apiKey || "key"; // Create headers with authorization this.headers = { Authorization: `Bearer ${this.apiKey}`, "Content-Type": "application/json", }; } async fetch(endpoint, options = {}) { const url = `${this.baseUrl}${endpoint}`; const response = await fetch(url, { ...options, headers: { ...this.headers, ...options.headers, }, }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); } // =========================================== // ALL YOUR EXISTING METHODS STAY EXACTLY THE SAME // =========================================== async getFeeEstimates() { try { const data = await this.fetch("/deposits/sdk/bitcoin-fees"); return data; } catch (error) { console.error("Error fetching fee rates:", error); // Default fallback values with proper separation return { low: 1, medium: 2, high: 5 }; } } async createDeposit(data) { var _a, _b, _c; try { const depositData = { ...data, isBlaze: (_a = data.isBlaze) !== null && _a !== void 0 ? _a : false, poolId: (_b = data.poolId) !== null && _b !== void 0 ? _b : "main", swapType: (_c = data.swapType) !== null && _c !== void 0 ? _c : "sbtc", // Default to regular sBTC deposit }; // Only add these fields if they exist (for AI BTC pool or swaps) if (data.minTokenOut !== undefined) { depositData.minTokenOut = data.minTokenOut; } if (data.dexId !== undefined) { depositData.dexId = data.dexId; } if (data.aiAccountReceiver) { depositData.aiAccountReceiver = data.aiAccountReceiver; } // Use the same endpoint as the frontend hook const responseData = await this.fetch("/deposits", { method: "POST", body: JSON.stringify(depositData), }); // Handle different response formats, matching the logic in your hook const result = typeof responseData === "object" && "data" in responseData ? responseData.data : responseData; if (result && typeof result === "object" && "id" in result) { return result.id; } if (typeof result === "string") { return result; } console.error("Unexpected response format:", result); throw new Error("Invalid response format from server"); } catch (error) { console.error("Error creating deposit:", error); throw error; } } async updateDeposit(data) { try { const responseData = await this.fetch(`/deposits/sdk/${data.id}`, { method: "PATCH", body: JSON.stringify(data.data), }); return responseData; } catch (error) { console.error("Error updating deposit:", error); throw error; } } async getDepositHistory(userAddress) { try { const responseData = await this.fetch(`/deposits/sdk/user/${userAddress}`); return responseData; } catch (error) { console.error("Error fetching deposit history:", error); return []; } } async getAllDepositsHistory(poolId) { try { // Add support for optional poolId parameter let endpoint = "/deposits/sdk/list"; if (poolId) { endpoint += `?poolId=${encodeURIComponent(poolId)}`; } const responseData = await this.fetch(endpoint); return responseData; } catch (error) { console.error("Error fetching all deposits:", error); return { aggregateData: { totalDeposits: 0, totalVolume: 0, uniqueUsers: 0, }, recentDeposits: [], }; } } async prepareTransaction(params) { var _a; try { const prepareParams = { ...params, poolId: (_a = params.poolId) !== null && _a !== void 0 ? _a : "main", }; // Only add these fields if they exist if (params.swapType) { prepareParams.swapType = params.swapType; } if (params.minTokenOut !== undefined) { prepareParams.minTokenOut = params.minTokenOut; } if (params.dexId) { prepareParams.dexId = params.dexId; } if (params.aiAccountReceiver) { prepareParams.aiAccountReceiver = params.aiAccountReceiver; } const responseData = await this.fetch("/deposits/sdk/prepare-transaction", { method: "POST", body: JSON.stringify(prepareParams), }); return responseData; } catch (error) { console.error("Error preparing transaction:", error); throw error; } } async updateDepositStatus(params) { try { // Use PUT instead of PATCH to match the frontend hook const responseData = await this.fetch(`/deposits/${params.id}`, { method: "PUT", body: JSON.stringify(params.data), }); // Check if responseData is of type { data?: Deposit } if (responseData && typeof responseData === "object" && "data" in responseData) { if (responseData.data) { return responseData.data; } throw new Error("Invalid response: missing deposit data"); } // If we get here, responseData should be a Deposit // We need to verify it has the required fields if (responseData && typeof responseData === "object" && "id" in responseData && "btcAmount" in responseData && "stxReceiver" in responseData) { return responseData; } throw new Error("Invalid response format from server"); } catch (error) { console.error("Error updating deposit status:", error); throw error; } } async executeTransaction(params) { try { const responseData = await this.fetch("/deposits/sdk/execute-transaction", { method: "POST", body: JSON.stringify(params), }); return responseData; } catch (error) { console.error("Error executing transaction:", error); throw error; } } async getPoolStatus(poolId) { try { let endpoint = "/pool-status"; if (poolId) { endpoint += `?poolId=${encodeURIComponent(poolId)}`; } const responseData = await this.fetch(endpoint); return responseData; } catch (error) { console.error("Error fetching pool status:", error); return { realAvailable: 0, estimatedAvailable: 0, lastUpdated: Date.now(), }; } } async getBTCPrice() { try { const responseData = await this.fetch("/fetchBtcPrice"); return responseData.price || null; } catch (error) { console.error("Error fetching BTC price:", error); return null; } } async getDepositStatus(depositId) { try { const responseData = await this.fetch(`/deposits/sdk/${depositId}`); return responseData; } catch (error) { console.error(`Error fetching status for deposit ${depositId}:`, error); throw error; } } async getDepositStatusByTxId(btcTxId) { try { const responseData = await this.fetch(`/deposits/sdk/tx/${btcTxId}`); return responseData; } catch (error) { console.error(`Error fetching status for Bitcoin transaction ${btcTxId}:`, error); throw error; } } // =========================================== // NEW: AI BTC Pool specific methods (minimal additions) // =========================================== async getAvailablePools() { try { const pools = await this.fetch("/pools/available"); return pools; } catch (error) { console.error("Error fetching available pools:", error); return []; } } async getAllowlistedPairs(poolId = "aibtc") { try { const pairs = await this.fetch(`/pools/${poolId}/allowlisted-pairs`); return pairs; } catch (error) { console.error("Error fetching allowlisted pairs:", error); return []; } } async getSwapStatus(poolId = "aibtc") { try { const status = await this.fetch(`/pools/${poolId}/swap-status`); return status; } catch (error) { console.error("Error fetching swap status:", error); return { paused: false, poolId, network: "unknown", checkedAt: Date.now(), error: "Failed to fetch swap status", }; } } // Admin method to check/add FT pairs async checkFtPair(ftContract, poolId = "aibtc") { try { const response = await this.fetch(`/admin/pools/${poolId}/check-ft-pair`, { method: "POST", body: JSON.stringify({ ftContract }), }); return response; } catch (error) { console.error("Error checking FT pair:", error); return { success: false, error: "Failed to check FT pair", ftContract, }; } } // Helper method to check if a specific FT/DEX pair is allowlisted async isTokenAllowlisted(ftContract, poolId = "aibtc") { try { const pairs = await this.getAllowlistedPairs(poolId); return pairs.some((pair) => pair.ftContract === ftContract && pair.isActive); } catch (error) { console.error("Error checking if token is allowlisted:", error); return false; } } async areSwapsPaused(poolId = "aibtc") { try { const response = await this.fetch(`/pools/${poolId}/swap-status`); return response.paused; } catch (error) { console.error("Error checking swap status:", error); return false; // Default to not paused } } }