UNPKG

@enclavemoney/enclave-wallet-sdk

Version:

A simple enclave wallet SDK for React applications

818 lines (748 loc) 22.4 kB
const API_BASE_URL = typeof window !== "undefined" && window.location.href.includes("stage.enclave.money") ? "https://enclave-b2b-api-stage-160004845895.asia-south1.run.app" : "https://hyperapp.in"; // Import necessary types from services.ts import { QuoteType, QuoteChoice } from "./services"; // Define action interface export interface IAction { action: | string | { encodedData: string; targetContractAddress: string; value: string; }[]; } // API request interfaces export interface getSourceTokensFromIdentifierRequest { body: { chainId: number; tokenAddress: string; }; } export interface CalculateQuoteAmountInRequest { body: { username: string; fromTokens: UserBalance[]; toToken: { tokenAddress: string; chainId: number; }; quoteType: QuoteType; action?: IAction["action"]; }; } export interface CalculateQuoteAmountOutRequest { body: { username: string; fromTokens: getSourceTokensFromIdentifierRequest["body"][]; toToken: { tokenAddress: string; chainId: number; outputAmount: string; }; quoteType: QuoteType; action?: IAction["action"]; }; } // Add interfaces for calculateQuoteAmountInWithAction function export interface UserBalance { chainId: number; address: string; balance: string; } export interface CalculateQuoteAmountInInput { fromTokens: UserBalance[]; toToken: { tokenAddress: string; chainId: number; }; action: IAction["action"]; } export interface CalculateQuoteAmountInParams { username: string; fromTokens: UserBalance[]; toToken: { tokenAddress: string; chainId: number; }; quoteType: QuoteType; action?: IAction["action"]; } export interface ModifiedSpendPlan { total_fees: string; spend_distribution: Record<string, string>; total_withdrawn: string; remaining_balance: string; enclave_fee_distribution: Record<string, string>; enclave_fee: string; } export interface QuoteDetailsWithAction { success: boolean; provider: string; fees: string; estimatedTime: number; inputDetails: { amount: string; amountUsd: string | number; }; outputDetails: { amount: string; amountFormatted: string; amountUsd: string; minimumAmount: string; }; rate: string; modifiedSpendPlan: ModifiedSpendPlan; } export interface CalculateQuoteResponse { success: boolean; bestQuote: QuoteDetailsWithAction; fastestQuote: QuoteDetailsWithAction; } // Add interfaces for calculateQuoteAmountOut function export interface CalculateQuoteAmountOutInput { fromTokens: getSourceTokensFromIdentifierRequest["body"][]; toToken: { tokenAddress: string; chainId: number; outputAmount: string; }; quoteType: QuoteType; action?: IAction["action"]; } export interface CalculateQuoteAmountOutParams { username: string; fromTokens: getSourceTokensFromIdentifierRequest["body"][]; toToken: { tokenAddress: string; chainId: number; outputAmount: string; }; quoteType: QuoteType; action?: IAction["action"]; } // Add interfaces for executeSwapAmountIn function export interface ExecuteSwapAmountInRequest { body: { username: string; fromTokens: UserBalance[]; toToken: { tokenAddress: string; chainId: number; }; isHeadless: boolean; quoteChoice: QuoteChoice; quoteType: QuoteType; quoteId?: string; action?: IAction["action"]; }; } export interface ExecuteSwapAmountInInput { fromTokens: UserBalance[]; toToken: { tokenAddress: string; chainId: number; }; isHeadless: boolean; quoteChoice: QuoteChoice; quoteType: QuoteType; quoteId?: string; action?: IAction["action"]; } export interface ExecuteSwapAmountInParams { username: string; fromTokens: UserBalance[]; toToken: { tokenAddress: string; chainId: number; }; isHeadless: boolean; quoteChoice: QuoteChoice; quoteType: QuoteType; quoteId?: string; action?: IAction["action"]; } export interface ExecuteSwapAmountInResponse { success: boolean; transactionDetails?: { multiTransactionId: string; overallStatus: string; }; // Add other response fields as needed } // Add interfaces for executeSwapAmountOut function export interface ExecuteSwapAmountOutRequest { body: { username: string; fromTokens: getSourceTokensFromIdentifierRequest["body"][]; toToken: { tokenAddress: string; chainId: number; outputAmount: string; }; isHeadless: boolean; quoteChoice: QuoteChoice; quoteType: QuoteType; quoteId?: string; action?: IAction["action"]; }; } export interface ExecuteSwapAmountOutInput { fromTokens: UserBalance[]; toToken: { tokenAddress: string; chainId: number; outputAmount: string; }; isHeadless: boolean; quoteChoice: QuoteChoice; quoteType: QuoteType; quoteId?: string; action?: IAction["action"]; } export interface ExecuteSwapAmountOutParams { username: string; fromTokens: getSourceTokensFromIdentifierRequest["body"][]; toToken: { tokenAddress: string; chainId: number; outputAmount: string; }; isHeadless: boolean; quoteChoice: QuoteChoice; quoteType: QuoteType; quoteId?: string; action?: IAction["action"]; } export interface ExecuteSwapAmountOutResponse { success: boolean; transactionDetails?: { multiTransactionId: string; overallStatus: string; }; // Add other response fields as needed } // Unified interface for calculateQuote function export interface CalculateQuoteInput { fromTokens: UserBalance[]; toToken: { tokenAddress: string; chainId: number; outputAmount?: string; // Optional for AMOUNT_IN, required for AMOUNT_OUT }; quoteType: QuoteType; action?: IAction["action"]; } export interface CalculateQuoteParams { username: string; fromTokens: UserBalance[] | getSourceTokensFromIdentifierRequest["body"][]; toToken: { tokenAddress: string; chainId: number; outputAmount?: string; }; quoteType: QuoteType; action?: IAction["action"]; } // Unified interface for executeSwap function export interface ExecuteSwapInput { fromTokens: UserBalance[]; toToken: { tokenAddress: string; chainId: number; outputAmount?: string; // Optional for AMOUNT_IN, required for AMOUNT_OUT }; isHeadless: boolean; quoteChoice: QuoteChoice; quoteType: QuoteType; quoteId?: string; action?: IAction["action"]; } export interface ExecuteSwapParams { username: string; fromTokens: UserBalance[] | getSourceTokensFromIdentifierRequest["body"][]; toToken: { tokenAddress: string; chainId: number; outputAmount?: string; }; isHeadless: boolean; quoteChoice: QuoteChoice; quoteType: QuoteType; quoteId?: string; action?: IAction["action"]; } export type ExecuteSwapResponse = | ExecuteSwapAmountInResponse | ExecuteSwapAmountOutResponse; // Add interfaces for getQuoteForActionAmountOut function export interface CalculateQuoteForActionAmountOutRequest { body: { username: string; fromTokens?: getSourceTokensFromIdentifierRequest["body"][]; toToken: { tokenAddress: string; chainId: number; }; outputAmount: string; quoteType: QuoteType; action?: IAction["action"]; }; } export interface GetQuoteForActionInput { fromTokens?: getSourceTokensFromIdentifierRequest["body"][]; toToken: { tokenAddress: string; chainId: number; }; outputAmount: string; quoteType: QuoteType; action?: IAction["action"]; } export interface GetQuoteForActionParams { username: string; fromTokens?: getSourceTokensFromIdentifierRequest["body"][]; toToken: { tokenAddress: string; chainId: number; }; outputAmount: string; quoteType: QuoteType; action?: IAction["action"]; } export interface GetQuoteForActionResponse { success: boolean; bestQuote: QuoteDetailsWithAction; fastestQuote: QuoteDetailsWithAction; } // Add interfaces for executeAction function export interface ExecuteActionAmountOutRequest { body: { quoteChoice: QuoteChoice; quoteId: string; }; } export interface ExecuteActionInput { quoteChoice: QuoteChoice; quoteId: string; username: string; fromTokens?: getSourceTokensFromIdentifierRequest["body"][]; toToken?: { tokenAddress: string; chainId: number; }; outputAmount?: string; action?: IAction["action"]; } export interface ExecuteActionParams { quoteChoice: QuoteChoice; quoteId: string; username: string; fromTokens?: getSourceTokensFromIdentifierRequest["body"][]; toToken?: { tokenAddress: string; chainId: number; }; outputAmount?: string; action?: IAction["action"]; } export interface ExecuteActionResponse { success: boolean; transactionDetails?: { multiTransactionId: string; overallStatus: string; }; // Add other response fields as needed } /** * Calculates quote amount in with action * @param params The request parameters * @param apiKey The wallet SDK key for authorization * @returns The calculate quote amount in with action response */ export const calculateQuoteAmountIn = async ( params: CalculateQuoteAmountInParams, apiKey: string ): Promise<CalculateQuoteResponse | null> => { try { // Construct the request body in the format expected by the API const requestBody: CalculateQuoteAmountInRequest = { body: { username: params.username, fromTokens: params.fromTokens, toToken: params.toToken, quoteType: params.quoteType, ...(params.action && { action: params.action }), }, }; const response = await fetch(`${API_BASE_URL}/sdk/calculateQuoteAmountIn`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: apiKey, }, body: JSON.stringify(requestBody), }); if (!response.ok) { throw new Error("Failed to calculate quote amount in"); } const data = await response.json(); return data; } catch (error) { console.error("Error calculating quote amount in:", error); return null; } }; /** * Calculates quote amount out * @param params The request parameters * @param apiKey The wallet SDK key for authorization * @returns The calculate quote amount out response */ export const calculateQuoteAmountOut = async ( params: CalculateQuoteAmountOutParams, apiKey: string ): Promise<CalculateQuoteResponse | null> => { try { // Use the appropriate endpoint based on whether action is provided const endpoint = params.action ? `${API_BASE_URL}/sdk/calculateQuoteAmountOutWithAction` : `${API_BASE_URL}/sdk/calculateQuoteAmountOut`; // Construct the request body in the format expected by the API const requestBody: CalculateQuoteAmountOutRequest = { body: { username: params.username, fromTokens: params.fromTokens, toToken: params.toToken, quoteType: params.quoteType, ...(params.action && { action: params.action }), }, }; const response = await fetch(endpoint, { method: "POST", headers: { "Content-Type": "application/json", Authorization: apiKey, }, body: JSON.stringify(requestBody), }); if (!response.ok) { throw new Error("Failed to calculate quote amount out"); } const data = await response.json(); return data; } catch (error) { console.error("Error calculating quote amount out:", error); return null; } }; /** * Executes swap amount in * @param params The request parameters * @param apiKey The wallet SDK key for authorization * @returns The execute swap amount in response */ export const executeSwapAmountIn = async ( params: ExecuteSwapAmountInParams, apiKey: string ): Promise<ExecuteSwapAmountInResponse | null> => { try { // Get userSession from SDK instance const sdkInstance = (window as any).__walletSDKInstance; const userSession = sdkInstance?.getUserSession?.() || sdkInstance?.userSession; // Determine auth type based on userSession const authType = userSession?.authMethod || "passkey"; const authToken = userSession?.token; // Construct the request body in the format expected by the API const requestBody: ExecuteSwapAmountInRequest = { body: { username: params.username, fromTokens: params.fromTokens, toToken: params.toToken, isHeadless: params.isHeadless, quoteChoice: params.quoteChoice, quoteType: params.quoteType, ...(params.quoteId && { quoteId: params.quoteId }), ...(params.action && { action: params.action }), }, }; const response = await fetch(`${API_BASE_URL}/sdk/executeSwapAmountIn`, { method: "POST", headers: { "Content-Type": "application/json", "x-user-auth": authType, "x-user-authToken": authToken, Authorization: apiKey, }, body: JSON.stringify(requestBody), }); if (!response.ok) { throw new Error("Failed to execute swap amount in"); } const data = await response.json(); return data; } catch (error) { console.error("Error executing swap amount in:", error); return null; } }; /** * Executes swap amount out * @param params The request parameters * @param apiKey The wallet SDK key for authorization * @returns The execute swap amount out response */ export const executeSwapAmountOut = async ( params: ExecuteSwapAmountOutParams, apiKey: string ): Promise<ExecuteSwapAmountOutResponse | null> => { try { // Get userSession from SDK instance const sdkInstance = (window as any).__walletSDKInstance; const userSession = sdkInstance?.getUserSession?.() || sdkInstance?.userSession; // Determine auth type based on userSession const authType = userSession?.authMethod || "passkey"; const authToken = userSession?.token; // Construct the request body in the format expected by the API const requestBody: ExecuteSwapAmountOutRequest = { body: { username: params.username, fromTokens: params.fromTokens, toToken: params.toToken, isHeadless: params.isHeadless, quoteChoice: params.quoteChoice, quoteType: params.quoteType, ...(params.quoteId && { quoteId: params.quoteId }), ...(params.action && { action: params.action }), }, }; const response = await fetch(`${API_BASE_URL}/sdk/executeSwapAmountOut`, { method: "POST", headers: { "Content-Type": "application/json", "x-user-auth": authType, "x-user-authToken": authToken, Authorization: apiKey, }, body: JSON.stringify(requestBody), }); if (!response.ok) { throw new Error("Failed to execute swap amount out"); } const data = await response.json(); return data; } catch (error) { console.error("Error executing swap amount out:", error); return null; } }; /** * Unified execute swap function that routes to appropriate endpoint based on quoteType * @param params The request parameters * @param apiKey The wallet SDK key for authorization * @returns The execute swap response */ export const executeSwapQuote = async ( params: ExecuteSwapParams, apiKey: string ): Promise<ExecuteSwapResponse | null> => { try { if (params.quoteType === QuoteType.AMOUNT_IN) { // For AMOUNT_IN, use executeSwapAmountIn const amountInParams: ExecuteSwapAmountInParams = { username: params.username, fromTokens: params.fromTokens as UserBalance[], toToken: { tokenAddress: params.toToken.tokenAddress, chainId: params.toToken.chainId, }, isHeadless: params.isHeadless, quoteChoice: params.quoteChoice, quoteType: params.quoteType, quoteId: params.quoteId, action: params.action, }; return await executeSwapAmountIn(amountInParams, apiKey); } else if (params.quoteType === QuoteType.AMOUNT_OUT) { // For AMOUNT_OUT, use executeSwapAmountOut if (!params.toToken.outputAmount) { throw new Error("outputAmount is required for AMOUNT_OUT quote type"); } const amountOutParams: ExecuteSwapAmountOutParams = { username: params.username, fromTokens: Array.isArray(params.fromTokens) && params.fromTokens.length > 0 && "balance" in params.fromTokens[0] ? (params.fromTokens as UserBalance[]).map((token) => ({ chainId: token.chainId, tokenAddress: token.address, })) : (params.fromTokens as getSourceTokensFromIdentifierRequest["body"][]), toToken: { tokenAddress: params.toToken.tokenAddress, chainId: params.toToken.chainId, outputAmount: params.toToken.outputAmount, }, isHeadless: params.isHeadless, quoteChoice: params.quoteChoice, quoteType: params.quoteType, quoteId: params.quoteId, action: params.action, }; return await executeSwapAmountOut(amountOutParams, apiKey); } else { throw new Error(`Unsupported quote type: ${params.quoteType}`); } } catch (error) { console.error("Error executing swap:", error); return null; } }; /** * Unified calculate quote function that routes to appropriate endpoint based on quoteType * @param params The request parameters * @param apiKey The wallet SDK key for authorization * @returns The calculate quote response */ export const calculateQuote = async ( params: CalculateQuoteParams, apiKey: string ): Promise<CalculateQuoteResponse | null> => { try { if (params.quoteType === QuoteType.AMOUNT_IN) { // For AMOUNT_IN, use calculateQuoteAmountIn const amountInParams: CalculateQuoteAmountInParams = { username: params.username, fromTokens: params.fromTokens as UserBalance[], toToken: { tokenAddress: params.toToken.tokenAddress, chainId: params.toToken.chainId, }, quoteType: params.quoteType, action: params.action, }; return await calculateQuoteAmountIn(amountInParams, apiKey); } else if (params.quoteType === QuoteType.AMOUNT_OUT) { // For AMOUNT_OUT, use calculateQuoteAmountOut if (!params.toToken.outputAmount) { throw new Error("outputAmount is required for AMOUNT_OUT quote type"); } const amountOutParams: CalculateQuoteAmountOutParams = { username: params.username, fromTokens: Array.isArray(params.fromTokens) && params.fromTokens.length > 0 && "balance" in params.fromTokens[0] ? (params.fromTokens as UserBalance[]).map((token) => ({ chainId: token.chainId, tokenAddress: token.address, })) : (params.fromTokens as getSourceTokensFromIdentifierRequest["body"][]), toToken: { tokenAddress: params.toToken.tokenAddress, chainId: params.toToken.chainId, outputAmount: params.toToken.outputAmount, }, quoteType: params.quoteType, action: params.action, }; return await calculateQuoteAmountOut(amountOutParams, apiKey); } else { throw new Error(`Unsupported quote type: ${params.quoteType}`); } } catch (error) { console.error("Error calculating quote:", error); return null; } }; /** * Gets quote for action amount out * @param params The request parameters * @param apiKey The wallet SDK key for authorization * @returns The get quote for action response */ export const getQuoteForActionAmountOut = async ( params: GetQuoteForActionParams, apiKey: string ): Promise<GetQuoteForActionResponse | null> => { try { // Construct the request body in the format expected by the API const requestBody: CalculateQuoteForActionAmountOutRequest = { body: { username: params.username, ...(params.fromTokens && { fromTokens: params.fromTokens }), toToken: params.toToken, outputAmount: params.outputAmount, quoteType: params.quoteType, ...(params.action && { action: params.action }), }, }; const response = await fetch( `${API_BASE_URL}/sdk/getQuoteForActionAmountOut`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: apiKey, }, body: JSON.stringify(requestBody), } ); if (!response.ok) { throw new Error("Failed to get quote for action amount out"); } const data = await response.json(); return data; } catch (error) { console.error("Error getting quote for action amount out:", error); return null; } }; /** * Executes action amount out * @param params The request parameters * @param apiKey The wallet SDK key for authorization * @returns The execute action response */ export const executeActionAmountOut = async ( params: ExecuteActionParams, apiKey: string ): Promise<ExecuteActionResponse | null> => { try { // Get userSession from SDK instance const sdkInstance = (window as any).__walletSDKInstance; const userSession = sdkInstance?.getUserSession?.() || sdkInstance?.userSession; // Determine auth type based on userSession const authType = userSession?.authMethod || "passkey"; const authToken = userSession?.token; // Construct the request body in the format expected by the API const requestBody: ExecuteActionAmountOutRequest = { body: params, }; const response = await fetch(`${API_BASE_URL}/sdk/executeActionAmountOut`, { method: "POST", headers: { "Content-Type": "application/json", "x-user-auth": authType, "x-user-authToken": authToken, Authorization: apiKey, }, body: JSON.stringify(requestBody), }); if (!response.ok) { throw new Error("Failed to execute action amount out"); } const data = await response.json(); return data; } catch (error) { console.error("Error executing action amount out:", error); return null; } };