UNPKG

@smoothsend/sdk

Version:

Multi-chain gasless transaction SDK for seamless dApp integration

563 lines (553 loc) 19.2 kB
import { AxiosRequestConfig } from 'axios'; type SupportedChain = 'avalanche' | 'aptos-testnet'; type ChainEcosystem = 'evm' | 'aptos'; declare const CHAIN_ECOSYSTEM_MAP: Record<SupportedChain, ChainEcosystem>; interface SuccessResponse { success: true; } interface ErrorResponse { success: false; error: string; details?: string[]; requestId?: string; } interface ChainInfo { name: string; displayName: string; chainId: number; explorerUrl: string; tokens: string[]; } interface TokenInfo { symbol: string; address: string; decimals: number; name: string; } interface ChainConfig { name: string; displayName: string; chainId: number; rpcUrl: string; relayerUrl: string; explorerUrl: string; tokens: string[]; nativeCurrency: { name: string; symbol: string; decimals: number; }; } interface TransferRequest { from: string; to: string; token: string; amount: string; chain: SupportedChain; } interface TransferQuoteResponse extends SuccessResponse { chainName: string; token: string; amount: string; relayerFee: string; total: string; feePercentage: number; contractAddress: string; } interface TransferQuote { amount: string; relayerFee: string; total: string; feePercentage: number; contractAddress: string; aptosTransactionData?: any; } interface RelayTransferResponse extends SuccessResponse { transferId: string; txHash: string; blockNumber: number; gasUsed: string; explorerUrl: string; fee: string; executionTime: number; } interface TransferResult { success: boolean; txHash: string; blockNumber?: number; gasUsed?: string; transferId?: string; explorerUrl?: string; fee?: string; executionTime?: number; gasFeePaidBy?: string; userPaidAPT?: boolean; transparency?: string; vmStatus?: string; sender?: string; chain?: string; relayerFee?: string; message?: string; } interface BatchTransferRequest { transfers: TransferRequest[]; chain: SupportedChain; } interface EVMTransferData { chainName: string; from: string; to: string; tokenSymbol: string; amount: string; relayerFee: string; nonce: string; deadline: number; signature: string; permitData?: { value: string; deadline: number; v: number; r: string; s: string; }; } type AvalancheTransferData = EVMTransferData; interface AptosTransferData { transactionBytes: number[]; authenticatorBytes: number[]; functionName?: string; fromAddress?: string; toAddress?: string; amount?: string; coinType?: string; } interface SignatureData { domain: any; types: any; message: any; primaryType: string; metadata?: { chain?: SupportedChain; fromAddress?: string; toAddress?: string; amount?: string; token?: string; relayerFee?: string; signatureVersion?: string; requiresPublicKey?: boolean; verificationMethod?: string; }; } interface SignedTransferData { transferData: any; signature: string; signatureType: 'EIP712' | 'Ed25519'; publicKey?: string; metadata?: { signatureVersion?: string; verificationMethod?: string; requiresPublicKey?: boolean; }; } interface TokenBalance { token: string; balance: string; decimals: number; symbol: string; name?: string; } interface TransferQuoteRequest { chainName: string; token: string; amount: string; } interface PrepareSignatureRequest { chainName: string; from: string; to: string; tokenSymbol: string; amount: string; relayerFee: string; nonce: string; deadline: number; } interface RelayTransferRequest { chainName: string; from: string; to: string; tokenSymbol: string; amount: string; relayerFee: string; nonce: string; deadline: number; signature: string; permitData?: PermitData; } interface BatchRelayTransferRequest { chainName: string; transfers: RelayTransferRequest[]; } interface EstimateGasRequest { chainName: string; transfers: TransferData[]; } interface TransferData { from: string; to: string; token: string; amount: string; relayerFee: string; nonce: string; deadline: number; signature: string; permitData?: PermitData; } interface PermitData { value: string; deadline: number; v: number; r: string; s: string; } interface PrepareSignatureResponse extends SuccessResponse { typedData: any; messageHash: string; message: string; } interface GasEstimateResponse extends SuccessResponse { chainName: string; gasEstimate: string; gasPrice: string; estimatedCost: string; transferCount: number; } interface HealthResponse extends SuccessResponse { status: string; timestamp: string; version: string; } interface DomainSeparatorResponse extends SuccessResponse { chainName: string; domainSeparator: string; } interface TransferStatusResponse extends SuccessResponse { chainName: string; transferHash: string; executed: boolean; } declare class SmoothSendError extends Error { code: string; chain?: SupportedChain | undefined; details?: any | undefined; constructor(message: string, code: string, chain?: SupportedChain | undefined, details?: any | undefined); } declare const APTOS_ERROR_CODES: { readonly MISSING_SIGNATURE: "APTOS_MISSING_SIGNATURE"; readonly MISSING_PUBLIC_KEY: "APTOS_MISSING_PUBLIC_KEY"; readonly INVALID_SIGNATURE_FORMAT: "APTOS_INVALID_SIGNATURE_FORMAT"; readonly INVALID_PUBLIC_KEY_FORMAT: "APTOS_INVALID_PUBLIC_KEY_FORMAT"; readonly ADDRESS_MISMATCH: "APTOS_ADDRESS_MISMATCH"; readonly SIGNATURE_VERIFICATION_FAILED: "APTOS_SIGNATURE_VERIFICATION_FAILED"; readonly MISSING_TRANSACTION_DATA: "APTOS_MISSING_TRANSACTION_DATA"; readonly INVALID_TRANSACTION_FORMAT: "APTOS_INVALID_TRANSACTION_FORMAT"; readonly EMPTY_ADDRESS: "APTOS_EMPTY_ADDRESS"; readonly INVALID_ADDRESS_FORMAT: "APTOS_INVALID_ADDRESS_FORMAT"; readonly QUOTE_ERROR: "APTOS_QUOTE_ERROR"; readonly EXECUTE_ERROR: "APTOS_EXECUTE_ERROR"; readonly BALANCE_ERROR: "APTOS_BALANCE_ERROR"; readonly TOKEN_INFO_ERROR: "APTOS_TOKEN_INFO_ERROR"; readonly STATUS_ERROR: "APTOS_STATUS_ERROR"; readonly MOVE_CALL_ERROR: "APTOS_MOVE_CALL_ERROR"; readonly UNSUPPORTED_TOKEN: "APTOS_UNSUPPORTED_TOKEN"; }; type AptosErrorCode = typeof APTOS_ERROR_CODES[keyof typeof APTOS_ERROR_CODES]; interface ApiResponse<T = any> { success: boolean; data?: T; error?: string; details?: string[]; requestId?: string; errorCode?: string; chain?: SupportedChain; timestamp?: string; } interface SmoothSendConfig { timeout?: number; retries?: number; customChainConfigs?: Partial<Record<SupportedChain, Partial<ChainConfig>>>; useDynamicConfig?: boolean; configCacheTtl?: number; relayerUrls?: { evm?: string; aptos?: string; }; } interface TransferEvent { type: 'transfer_initiated' | 'transfer_signed' | 'transfer_submitted' | 'transfer_confirmed' | 'transfer_failed'; data: any; timestamp: number; chain: SupportedChain; } type EventListener = (event: TransferEvent) => void; interface IChainAdapter { readonly chain: SupportedChain; readonly config: ChainConfig; getQuote(request: TransferRequest): Promise<TransferQuote>; prepareTransfer(request: TransferRequest, quote: TransferQuote): Promise<SignatureData>; executeTransfer(signedData: SignedTransferData): Promise<TransferResult>; executeBatchTransfer?(signedTransfers: SignedTransferData[]): Promise<TransferResult[]>; getBalance?(address: string, token?: string): Promise<TokenBalance[]>; getTokenInfo(token: string): Promise<TokenInfo>; getNonce(address: string): Promise<string>; getTransactionStatus(txHash: string): Promise<any>; validateAddress(address: string): boolean; validateAmount(amount: string, token: string): Promise<boolean>; } declare class SmoothSendSDK { private adapters; private eventListeners; private config; private initialized; private initializationPromise; constructor(config?: SmoothSendConfig); /** * Initialize adapters with dynamic or static configuration */ private initializeAdapters; private _doInitialize; private initializeDynamicAdapters; private initializeStaticAdapters; private createAdapter; /** * Fetch supported chains from both relayers */ private fetchSupportedChains; /** * Fetch chain configuration from the appropriate relayer */ private fetchChainConfig; /** * Get default configuration for a chain (fallback when dynamic config fails) */ private getDefaultChainConfig; /** * Refresh chain configurations from relayers */ refreshChainConfigs(): Promise<void>; addEventListener(listener: EventListener): void; removeEventListener(listener: EventListener): void; private emitEvent; getQuote(request: TransferRequest): Promise<TransferQuote>; prepareTransfer(request: TransferRequest, quote: TransferQuote): Promise<SignatureData>; executeTransfer(signedData: SignedTransferData, chain: SupportedChain): Promise<TransferResult>; transfer(request: TransferRequest, signer: any): Promise<TransferResult>; batchTransfer(request: BatchTransferRequest, signer: any): Promise<TransferResult[]>; getBalance(chain: SupportedChain, address: string, token?: string): Promise<TokenBalance[]>; getTokenInfo(chain: SupportedChain, token: string): Promise<TokenInfo>; getNonce(chain: SupportedChain, address: string): Promise<string>; getTransactionStatus(chain: SupportedChain, txHash: string): Promise<any>; validateAddress(chain: SupportedChain, address: string): Promise<boolean>; validateAmount(chain: SupportedChain, amount: string, token: string): Promise<boolean>; getSupportedChains(): Promise<SupportedChain[]>; getChainConfig(chain: SupportedChain): Promise<ChainConfig>; isChainSupported(chain: string): Promise<boolean>; /** * Get supported tokens for a specific chain (from dynamic config) */ getSupportedTokens(chain: SupportedChain): Promise<string[]>; /** * Health check endpoint */ getHealth(): Promise<HealthResponse>; /** * Get supported blockchain networks */ getSupportedChainsInfo(): Promise<ChainInfo[]>; /** * Get supported tokens for a specific chain */ getSupportedTokensForChain(chainName: string): Promise<TokenInfo[]>; /** * Estimate gas cost for transfers */ estimateGas(chainName: string, transfers: any[]): Promise<GasEstimateResponse>; /** * Get EIP-712 domain separator for a specific chain */ getDomainSeparator(chainName: string): Promise<DomainSeparatorResponse>; /** * Check transfer execution status */ getTransferStatus(chainName: string, transferHash: string): Promise<TransferStatusResponse>; /** * Check if a chain belongs to a specific ecosystem */ getChainEcosystem(chain: SupportedChain): ChainEcosystem; private getAdapter; static getSupportedChains(): SupportedChain[]; static getChainConfig(chain: SupportedChain): ChainConfig; static getAllChainConfigs(): Record<SupportedChain, ChainConfig>; } /** * EVM Multi-Chain Adapter * Handles all EVM-compatible chains (Avalanche, Polygon, Ethereum, Arbitrum, Base) * Routes requests to the appropriate chain endpoint on the EVM relayer */ declare class EVMAdapter implements IChainAdapter { readonly chain: SupportedChain; readonly config: ChainConfig; private httpClient; constructor(chain: SupportedChain, config: ChainConfig, relayerUrl: string); /** * Build API path with chain name for EVM relayer * EVM relayer uses /chains/{chainName} prefix for most endpoints */ private getApiPath; getQuote(request: TransferRequest): Promise<TransferQuote>; prepareTransfer(request: TransferRequest, quote: TransferQuote): Promise<SignatureData>; executeTransfer(signedData: SignedTransferData): Promise<TransferResult>; /** * EVM-specific batch transfer support * Takes advantage of the EVM relayer's native batch capabilities */ executeBatchTransfer?(signedTransfers: SignedTransferData[]): Promise<TransferResult[]>; getTokenInfo(token: string): Promise<TokenInfo>; getNonce(address: string): Promise<string>; getTransactionStatus(txHash: string): Promise<any>; validateAddress(address: string): boolean; validateAmount(amount: string, token: string): Promise<boolean>; /** * EVM-specific gas estimation */ estimateGas(transfers: any[]): Promise<any>; /** * EVM-specific permit support check */ supportsPermit(tokenAddress: string): Promise<boolean>; } /** * Aptos Multi-Chain Adapter * Handles all Aptos chains (aptos-testnet, aptos-mainnet) * Routes requests to the appropriate chain endpoint on the Aptos relayer * Supports Aptos-specific features like gasless transactions and Move-based contracts */ declare class AptosAdapter implements IChainAdapter { readonly chain: SupportedChain; readonly config: ChainConfig; private httpClient; constructor(chain: SupportedChain, config: ChainConfig, relayerUrl: string); /** * Build API path with chain name for Aptos relayer */ private getApiPath; getQuote(request: TransferRequest): Promise<TransferQuote>; prepareTransfer(request: TransferRequest, quote: TransferQuote): Promise<SignatureData>; executeTransfer(signedData: SignedTransferData): Promise<TransferResult>; getBalance(address: string, token?: string): Promise<TokenBalance[]>; getTokenInfo(token: string): Promise<TokenInfo>; getNonce(address: string): Promise<string>; getTransactionStatus(txHash: string): Promise<any>; validateAddress(address: string): boolean; validateAmount(amount: string, token: string): Promise<boolean>; /** * Get Aptos token address from symbol */ private getAptosTokenAddress; /** * Build Aptos explorer URL for transaction */ private buildAptosExplorerUrl; /** * Validate serialized transaction data for the new safe endpoint * @param signedData The signed transfer data to validate */ private validateSerializedTransactionData; /** * Enhanced address validation with detailed error messages * @param address The address to validate * @returns true if valid, throws error if invalid */ validateAddressStrict(address: string): boolean; /** * Verify that a public key corresponds to an expected address * This mirrors the enhanced verification in the relayer * @param publicKey The public key to verify * @param expectedAddress The expected address * @returns true if they match */ verifyPublicKeyAddress(publicKey: string, expectedAddress: string): Promise<boolean>; /** * Enhanced transaction preparation with better signature data structure * @param request Transfer request * @param quote Transfer quote * @returns Signature data with enhanced structure */ prepareTransferEnhanced(request: TransferRequest, quote: TransferQuote): Promise<SignatureData & { metadata: any; }>; /** * Aptos-specific Move contract interaction */ callMoveFunction(functionName: string, args: any[]): Promise<any>; } declare const CHAIN_CONFIGS: Record<SupportedChain, ChainConfig>; declare function getChainConfig(chain: SupportedChain): ChainConfig; declare function getAllChainConfigs(): Record<SupportedChain, ChainConfig>; declare const TOKEN_DECIMALS: Record<string, number>; declare function getTokenDecimals(token: string): number; interface DynamicChainConfig extends ChainConfig { tokens: string[]; contractAddress?: string; feeSettings?: { baseFeeBps: number; minFeeWei: string; maxFeeBps: number; }; } declare class ChainConfigService { private configCache; private cacheExpiry; private readonly CACHE_TTL; /** * Fetch chain configuration from relayer's API endpoints */ fetchChainConfig(relayerUrl: string, chainName?: string): Promise<DynamicChainConfig[]>; /** * Get configuration for a specific supported chain */ getChainConfig(chain: SupportedChain, fallbackConfig?: ChainConfig): Promise<DynamicChainConfig>; /** * Get all available chain configurations */ getAllChainConfigs(fallbackConfigs?: Record<SupportedChain, ChainConfig>): Promise<Record<string, DynamicChainConfig>>; /** * Clear the configuration cache */ clearCache(): void; /** * Set custom cache TTL */ setCacheTtl(ttlMs: number): void; private mapRelayerChainToConfig; private getRelayerUrlForChain; private matchesChain; private matchesChainName; private getChainKey; private getDefaultRpcUrl; private getNativeCurrencyForChain; private getDefaultTokensForChain; } declare const chainConfigService: ChainConfigService; declare class HttpClient { private client; constructor(baseURL: string, timeout?: number); get<T = any>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>>; post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<ApiResponse<T>>; put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<ApiResponse<T>>; delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>>; private handleError; retry<T>(operation: () => Promise<ApiResponse<T>>, maxRetries?: number, delay?: number): Promise<ApiResponse<T>>; } declare const VERSION = "2.0.0-beta.1"; export { APTOS_ERROR_CODES, AptosAdapter, CHAIN_CONFIGS, CHAIN_ECOSYSTEM_MAP, ChainConfigService, EVMAdapter, HttpClient, SmoothSendError, SmoothSendSDK, TOKEN_DECIMALS, VERSION, chainConfigService, SmoothSendSDK as default, getAllChainConfigs, getChainConfig, getTokenDecimals }; export type { ApiResponse, AptosErrorCode, AptosTransferData, AvalancheTransferData, BatchRelayTransferRequest, BatchTransferRequest, ChainConfig, ChainEcosystem, ChainInfo, DomainSeparatorResponse, DynamicChainConfig, EVMTransferData, ErrorResponse, EstimateGasRequest, EventListener, GasEstimateResponse, HealthResponse, IChainAdapter, PermitData, PrepareSignatureRequest, PrepareSignatureResponse, RelayTransferRequest, RelayTransferResponse, SignatureData, SignedTransferData, SmoothSendConfig, SuccessResponse, SupportedChain, TokenBalance, TokenInfo, TransferData, TransferEvent, TransferQuote, TransferQuoteRequest, TransferQuoteResponse, TransferRequest, TransferResult, TransferStatusResponse };