enclave-wallet-sdk
Version:
A simple enclave wallet SDK for React applications
511 lines (460 loc) • 12.5 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: TokenBalance[];
}
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;
proMode?: boolean;
txsGasLimit?: number;
}
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;
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[];
}
/**
* 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}/relay/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.outputDetails || null;
} catch (error) {
console.error("Error fetching multi relay buy 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/api/balance/crypto?username=${username}`,
{
headers: {
Authorization: `${apiKey}`,
},
}
);
if (!response.ok) throw new Error("Failed to fetch balance");
const data = await response.json();
return data;
} 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;
}
};
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;
}
};
export { API_BASE_URL };