@enclavemoney/enclave-wallet-sdk
Version:
A simple enclave wallet SDK for React applications
1,097 lines (989 loc) • 26.1 kB
text/typescript
const API_BASE_URL = "https://hyperapp.in";
import {
IMultiTransaction,
MultiTransactionType,
TransactionStatus,
OverallStatus,
TokenURI,
} from "../types/activity";
// Define interface for the output details
export interface OutputDetails {
amount: string;
amountFormatted: string;
amountUsd: string;
minimumAmount: string;
}
// Define interface for the request parameters
export interface MultiRelayBuyQuoteParams {
username: string;
amount: number;
outputToken: string;
outputChainId: number;
}
// Balance interfaces
export interface TokenBalance {
// Add balance properties as needed
symbol: string;
balance: string;
balanceInUsd: string;
// Other properties from the API response
}
export interface BalanceResponse {
success: boolean;
data: any;
portfolioSummary?: any;
}
export interface MultiRelaySellQuoteParams {
username: string;
amount: number;
inputToken: string;
chainId: number;
}
export interface MultiRelaySwapQuoteParams {
username: string;
userBalance: any[] | undefined;
outputToken: string;
outputChainId: number;
inputAmount?: number | string;
proMode?: boolean;
txsGasLimit?: number;
metadata?: {
inputToken: TokenURI;
outputToken: TokenURI;
};
}
export interface BuyFlowParams {
username: string;
amount: number;
outputToken: string;
outputChainId: number;
txGasLimit: number;
}
export interface SellFlowParams {
username: string;
amount: number;
inputToken: string;
chainId: number;
}
export interface SwapInput {
chainId: number;
tokenAddress: string;
amount: string;
}
export interface SwapFlowParams {
username: string;
userBalance: any[] | undefined;
outputToken: string | undefined;
outputChainId: number | undefined;
metadata: {
inputToken: TokenURI;
outputToken: TokenURI;
};
inputAmount?: number | string;
proMode?: boolean;
txsGasLimit?: number;
}
export interface TransactionResult {
chainId: number;
success: boolean;
txnHash: string;
requestId?: string;
}
export interface TransferFlowParams {
username: string;
inputAmount: string;
outputToken: string;
outputDecimals: number;
outputChainId: number;
recipient: string;
userBalance: any[];
metadata?: any;
}
export interface TransferResponse {
spendPlan: {
total_withdrawn: string;
spend_distribution: { [key: string]: string };
remaining_balance: string;
};
onChainTransfer?: {
chainId: number;
txHash: string;
};
relayTransfer?: {
type: string;
success: boolean;
evmTransactions: TransactionResult[];
solanaTransactions: TransactionResult[];
};
outputDetails: {
amount: string;
minimumAmount: string;
amountFormatted: string;
};
}
export interface User {
username: string;
walletAddress: string;
solana_program_wallet: string;
ens: string;
}
export interface TokenDetail {
amount: string;
amountFormatted: string;
tokenAddress: string;
tokenName: string;
tokenSymbol: string;
receiver?: User;
}
export interface ChainTokenDetails {
[chainId: string]: TokenDetail[];
}
export interface ChainTransactions {
[chainId: string]: {
[txHash: string]: string;
};
}
export interface TransactionMetadata {
senderDetails: User;
receiverDetails: User[];
inputAmounts: ChainTokenDetails;
destinationAmounts: ChainTokenDetails;
status: string;
lastUpdatedTimestamp: number;
transactions: ChainTransactions;
requestIdsMap?: {
[chainId: string]: string;
};
}
export interface ActivityItem {
_id: string;
multiTransactionId: string;
sender: User;
transactionType: string;
transactionDescription: string;
receivers: User[];
sourceChains: number[];
destinationChains: number[];
inputTokens: ChainTokenDetails;
outputTokens: ChainTokenDetails;
transactions: ChainTransactions;
overallStatus: string;
metadata: TransactionMetadata;
createdTimestamp: number;
lastUpdatedTimestamp: number;
updatedAt: string;
__v: number;
}
export interface ActivityResponse {
success: boolean;
data: IMultiTransaction[];
}
// Add new interface for BTC swap quote params
export interface BTCRelaySwapQuoteParams {
username: string;
amount: number | string;
outputToken: string;
outputChainId: number;
}
// Add new interface for BTC swap quote params
export interface ToBTCRelaySwapQuoteParams {
username: string;
userBalance: any[] | undefined;
inputAmount?: number | string;
proMode?: boolean;
txsGasLimit?: number;
}
// Add new interface for BTC swap execution params
export interface ToBTCSwapFlowParams {
username: string;
userBalance: any[] | undefined;
inputAmount?: number | string;
proMode: boolean;
metadata: {
inputToken: TokenURI;
outputToken: TokenURI;
};
}
// Add new interface for from BTC swap execution params
export interface FromBTCSwapFlowParams {
username: string;
amount: number | string;
outputToken: string;
outputChainId: number;
metadata: {
inputToken: TokenURI;
outputToken: TokenURI;
};
}
export interface BitcoinTransferParams {
username: string;
inputAmount: string;
recipient: string;
outputChainId: number;
metadata?: {
token: {
tokenSymbol: string;
tokenName: string;
decimals: number;
logoURI?: string;
};
receiver: {
username?: string;
walletAddress?: string;
solanaWalletAddress?: string;
ensName?: string;
sns?: string;
};
};
}
export interface BitcoinTransferResponse {
success: boolean;
transactionDetails: {
multiTransactionId: string;
txHash?: string;
};
}
/**
* Fetches a buy quote from the multi-relay endpoint
* @param params Request parameters for the quote
* @param apiKey The wallet SDK key for authorization
* @returns The output details from the quote response
*/
export const getMultiRelayBuyQuote = async (
params: MultiRelayBuyQuoteParams,
apiKey: string
): Promise<OutputDetails | string> => {
try {
const response = await fetch(`${API_BASE_URL}/relay/buy/quote`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
const errorData = await response.json();
console.log("errorData", errorData);
return errorData.message;
}
const data = await response.json();
return data.outputDetails || null;
} catch (error) {
console.error("Error fetching multi relay buy quote:", error);
return "Error fetching quote";
}
};
export const getMultiRelaySellQuote = async (
params: MultiRelaySellQuoteParams,
apiKey: string
): Promise<OutputDetails | string> => {
try {
const response = await fetch(`${API_BASE_URL}/relay/sell/quote`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
const errorData = await response.json();
console.log("errorData", errorData);
return errorData.message;
}
const data = await response.json();
return data.outputDetails || null;
} catch (error) {
console.error("Error fetching multi relay buy quote:", error);
return "Error fetching quote";
}
};
export const getMultiRelaySwapQuote = async (
params: MultiRelaySwapQuoteParams,
apiKey: string
): Promise<OutputDetails | any> => {
try {
const response = await fetch(`${API_BASE_URL}/swap/unified/quote`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
const errorData = await response.json();
console.log("errorData", errorData);
return errorData;
}
const data = await response.json();
return data || null;
} catch (error) {
console.error("Error fetching multi relay buy quote:", error);
return "Error fetching quote";
}
};
export const getMultiFromBTCRelaySwapQuote = async (
params: BTCRelaySwapQuoteParams,
apiKey: string
): Promise<OutputDetails | any> => {
try {
const response = await fetch(
`${API_BASE_URL}/relay/fromBitcoin/swap/quote`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
}
);
if (!response.ok) {
const errorData = await response.json();
console.log("errorData", errorData);
return errorData;
}
const data = await response.json();
return data || null;
} catch (error) {
console.error("Error fetching BTC relay swap quote:", error);
return "Error fetching quote";
}
};
export const getMultiToBTCRelaySwapQuote = async (
params: ToBTCRelaySwapQuoteParams,
apiKey: string
): Promise<OutputDetails | any> => {
try {
const response = await fetch(`${API_BASE_URL}/relay/toBitcoin/swap/quote`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
const errorData = await response.json();
console.log("errorData", errorData);
return errorData;
}
const data = await response.json();
return data || null;
} catch (error) {
console.error("Error fetching to BTC relay swap quote:", error);
return "Error fetching quote";
}
};
/**
* Fetches the user's crypto balance
* @param username The user's username
* @param apiKey The wallet SDK key for authorization
* @returns The user's crypto balance data
*/
export const getUserCryptoBalance = async (
username: string,
apiKey: string
): Promise<BalanceResponse | null> => {
try {
const response = await fetch(
`${API_BASE_URL}/v1/userbalance?username=${username}`,
{
headers: {
Authorization: `${apiKey}`,
},
}
);
if (!response.ok) throw new Error("Failed to fetch balance");
const data = await response.json();
return {
success: data.success,
data: data.userBalances,
portfolioSummary: data.portfolioSummary,
};
} catch (error) {
console.error("Error fetching crypto balance:", error);
return null;
}
};
/**
* Executes a buy flow transaction
* @param params The buy flow parameters
* @param apiKey The wallet SDK key for authorization
* @returns The transaction response
*/
export const executeBuyFlow = async (
params: BuyFlowParams,
apiKey: string
): Promise<any> => {
try {
const response = await fetch(`${API_BASE_URL}/relay/buy/full-flow`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("Error executing buy flow:", error);
throw error;
}
};
/**
* Executes a sell flow transaction
* @param params The sell flow parameters
* @param apiKey The wallet SDK key for authorization
* @returns The transaction response
*/
export const executeSellFlow = async (
params: SellFlowParams,
apiKey: string
): Promise<any> => {
try {
const response = await fetch(`${API_BASE_URL}/relay/sell/full-flow`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("Error executing sell flow:", error);
throw error;
}
};
/**
* Executes a swap flow transaction
* @param params The swap flow parameters
* @param apiKey The wallet SDK key for authorization
* @returns The transaction response
*/
export const executeSwapFlow = async (
params: SwapFlowParams,
apiKey: string
): Promise<any> => {
try {
const response = await fetch(`${API_BASE_URL}/relay/swap/full-flow`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("Error executing swap flow:", error);
throw error;
}
};
/**
* Executes a bungee swap flow transaction
* @param params The swap flow parameters
* @param apiKey The wallet SDK key for authorization
* @returns The transaction response
*/
export const executeBungeeSwapFlow = async (
params: SwapFlowParams,
apiKey: string
): Promise<any> => {
try {
const response = await fetch(`${API_BASE_URL}/bungee/swap/full-flow`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("Error executing bungee swap flow:", error);
throw error;
}
};
/**
* Executes a CCTP swap flow transaction for USDC to USDC transfers
* @param params The swap flow parameters
* @param apiKey The wallet SDK key for authorization
* @returns The transaction response
*/
export const executeCCTPSwapFlow = async (
params: SwapFlowParams,
apiKey: string
): Promise<any> => {
try {
const response = await fetch(`${API_BASE_URL}/cctp/v1/swap/full-flow`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("Error executing CCTP swap flow:", error);
throw error;
}
};
/**
* Executes a LiFi swap flow transaction
* @param params The swap flow parameters
* @param apiKey The wallet SDK key for authorization
* @returns The transaction response
*/
export const executeLiFiSwapFlow = async (
params: SwapFlowParams,
apiKey: string
): Promise<any> => {
try {
const response = await fetch(`${API_BASE_URL}/lifi/swap/full-flow`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("Error executing LiFi swap flow:", error);
throw error;
}
};
export const executeCCTPV2SwapFlow = async (
params: SwapFlowParams,
apiKey: string
): Promise<any> => {
try {
const response = await fetch(`${API_BASE_URL}/cctp/v2/swap/full-flow`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("Error executing CCTP swap flow:", error);
throw error;
}
};
export const executeTransferFlow = async (
params: TransferFlowParams,
apiKey: string
): Promise<TransferResponse> => {
try {
// Log the request parameters with detailed balance info
console.log("Transfer Flow Request Details:", {
username: params.username,
inputAmount: params.inputAmount,
inputAmountFormatted: `${
Number(params.inputAmount) / Math.pow(10, params.outputDecimals)
} USDC`,
outputToken: params.outputToken,
outputChainId: params.outputChainId,
recipient: params.recipient,
availableBalance: params.userBalance.find(
(token) => token.chainId === params.outputChainId
)?.balance,
});
// Validate required parameters
if (
!params.username ||
!params.inputAmount ||
!params.outputToken ||
!params.outputChainId ||
!params.recipient
) {
throw new Error("Missing required parameters");
}
// Validate userBalance array
if (!Array.isArray(params.userBalance) || params.userBalance.length === 0) {
throw new Error("Invalid user balance data");
}
// // Find the token balance for the output chain
// const tokenBalance = params.userBalance.find(
// (token) => token.chainId === params.outputChainId
// );
// if (!tokenBalance) {
// throw new Error(`No balance found for chain ${params.outputChainId}`);
// }
const response = await fetch(`${API_BASE_URL}/relay/transfer/full-flow`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: apiKey,
},
body: JSON.stringify(params),
});
// Log the response status and headers
console.log("Transfer Flow Response Status:", response.status);
console.log("Transfer Flow Response Headers:", {
"content-type": response.headers.get("content-type"),
"content-length": response.headers.get("content-length"),
});
if (!response.ok) {
const errorData = await response.json();
console.error("Transfer Flow Error Response:", errorData);
throw new Error(errorData.message || "Transfer failed");
}
const data = await response.json();
console.log("Transfer Flow Success Response:", data);
return data;
} catch (error: any) {
console.error("Error executing transfer flow:", {
error,
message: error.message,
params: JSON.stringify(params, null, 2),
});
throw error;
}
};
export const getMultiTransactionsList = async (
username: string,
apiKey: string
): Promise<ActivityResponse | null> => {
try {
const response = await fetch(
`${API_BASE_URL}/api/multiTransactions/list?username=${username}`,
{
headers: {
Authorization: `${apiKey}`,
},
}
);
if (!response.ok) throw new Error("Failed to fetch activity");
const data = await response.json();
return data;
} catch (error) {
console.error("Error fetching activity:", error);
return null;
}
};
// Interface for transaction info response
export interface TxnInfoResponse {
transaction: IMultiTransaction;
}
// Function to fetch transaction details by ID
export const getTransactionInfo = async (
multiTransactionId: string,
apiKey: string
): Promise<IMultiTransaction | null> => {
try {
const response = await fetch(
`${API_BASE_URL}/relay/txnInfo?multiTransactionId=${multiTransactionId}`,
{
headers: {
Authorization: `${apiKey}`,
},
}
);
if (!response.ok) {
throw new Error("Failed to fetch transaction details");
}
const data = await response.json();
return data;
} catch (error) {
console.error("Error fetching transaction details:", error);
return null;
}
};
// Interface for token info
export interface TokenInfo {
symbol: string;
name: string;
logoURI?: string;
icon?: string;
address: string;
chainId: number;
chainIds?: Array<{
chainId: number;
address: string;
}>;
decimals: number;
balance?: string;
amount?: number;
priceUsd?: number;
price?: number;
}
export interface AllTokensResponse {
success: boolean;
tokens: TokenInfo[];
}
export const getAllTokens = async (
apiKey: string
): Promise<AllTokensResponse | null> => {
try {
const response = await fetch(`${API_BASE_URL}/paginated-tokens`, {
headers: {
Authorization: `${apiKey}`,
},
});
if (!response.ok) {
throw new Error("Failed to fetch tokens");
}
const data = await response.json();
return {
success: true,
tokens: data.data,
};
} catch (error) {
console.error("Error fetching all tokens:", error);
return null;
}
};
// Update search token interface to match actual response
export interface SearchTokenResponse {
success: boolean;
data: {
name: string;
symbol: string;
decimals: number;
logoURI: string;
chainIds: Array<{
chainId: string;
address: string;
}>;
price: number;
};
}
export const searchToken = async (
tokenAddress: string,
chainId: number,
apiKey: string
): Promise<SearchTokenResponse | null> => {
try {
const response = await fetch(`${API_BASE_URL}/search-token`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: apiKey,
},
body: JSON.stringify({
tokenAddress,
chainId: chainId.toString(),
}),
});
if (!response.ok) {
throw new Error("Failed to search token");
}
const data = await response.json();
return data;
} catch (error) {
console.error("Error searching token:", error);
return null;
}
};
// Add new interface for token search response
export interface TokenSearchResponse {
success: boolean;
data: TokenInfo[];
}
export const searchTokensByQuery = async (
query: string,
apiKey: string
): Promise<TokenSearchResponse | null> => {
try {
const response = await fetch(
`${API_BASE_URL}/token/final/search?query=${encodeURIComponent(query)}`,
{
headers: {
Authorization: `${apiKey}`,
},
}
);
if (!response.ok) {
throw new Error("Failed to search tokens");
}
const data = await response.json();
return data;
} catch (error) {
console.error("Error searching tokens:", error);
return null;
}
};
/**
* Executes a swap to BTC flow transaction
* @param params The swap to BTC flow parameters
* @param apiKey The wallet SDK key for authorization
* @returns The transaction response
*/
export const executeToBTCSwapFlow = async (
params: ToBTCSwapFlowParams,
apiKey: string
): Promise<any> => {
try {
const response = await fetch(
`${API_BASE_URL}/relay/toBitcoin/swap/full-flow`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
}
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("Error executing swap to BTC flow:", error);
throw error;
}
};
/**
* Executes a swap from BTC flow transaction
* @param params The swap from BTC flow parameters
* @param apiKey The wallet SDK key for authorization
* @returns The transaction response
*/
export const executeFromBTCSwapFlow = async (
params: FromBTCSwapFlowParams,
apiKey: string
): Promise<any> => {
try {
const response = await fetch(
`${API_BASE_URL}/relay/fromBitcoin/swap/full-flow`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `${apiKey}`,
},
body: JSON.stringify(params),
}
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("Error executing swap from BTC flow:", error);
throw error;
}
};
export const executeBitcoinTransfer = async (
params: BitcoinTransferParams,
apiKey: string
): Promise<BitcoinTransferResponse> => {
try {
const response = await fetch(`${API_BASE_URL}/bitcoin/send-transaction`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: apiKey,
},
body: JSON.stringify(params),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || "Bitcoin transfer failed");
}
const data = await response.json();
return data;
} catch (error: any) {
console.error("Error executing Bitcoin transfer:", error);
throw error;
}
};
// Social login interfaces
export interface SocialLoginParams {
googleUser: any; // The complete Google user object from Firebase
}
export interface SocialLoginResponse {
username: string;
socialLoginDetails: {
googleUser: {
email: string;
displayName: string;
photoURL: string;
uid: string;
};
};
verified: boolean;
multiUserOps: any;
wallet: {
scw_address: string;
type: string;
multi_scw: Array<{
network: number;
address: string;
deployed: boolean;
}>;
eoa_address: string;
solana_public_key: string;
solana_program_wallet: string;
bitcoin_wallet: {
legacy_address: string;
segwit_address: string;
native_segwit_address: string;
taproot_address: string;
};
};
orgId: string;
addedOn: number;
updatedOn: number;
version: number;
smartBalanceEnabled: boolean;
_id: string;
__v: number;
}
export const getSocialAccount = async (
params: SocialLoginParams,
apiKey: string
): Promise<SocialLoginResponse> => {
const url = `${API_BASE_URL}/social/get-account`;
const headers = {
"Content-Type": "application/json",
Authorization: apiKey,
};
try {
const response = await fetch(url, {
method: "POST",
headers,
body: JSON.stringify(params),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || "Social login failed");
}
const data = await response.json();
return data;
} catch (error: any) {
console.error("Error getting social account:", error);
throw error;
}
};
export { API_BASE_URL };