@naviprotocol/wallet-client 2.0.3 → 2.0.5-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +703 -590
- package/dist/index.esm.js.map +1 -1
- package/dist/modules/balanceModule/index.d.ts +10 -0
- package/dist/modules/balanceModule/index.d.ts.map +1 -1
- package/dist/modules/balanceModule/portfolio.d.ts +25 -2
- package/dist/modules/balanceModule/portfolio.d.ts.map +1 -1
- package/dist/modules/haedalModule/index.d.ts.map +1 -1
- package/dist/modules/lendingModule/index.d.ts.map +1 -1
- package/dist/modules/lendingModule/migrate.d.ts.map +1 -1
- package/dist/modules/swapModule/index.d.ts.map +1 -1
- package/dist/modules/voloModule/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/modules/module.ts","../src/modules/balanceModule/portfolio.ts","../src/modules/balanceModule/index.ts","../src/transaction-result.ts","../src/modules/lendingModule/migrate.ts","../src/modules/lendingModule/protocols/navi.ts","../src/modules/lendingModule/index.ts","../src/modules/voloModule/index.ts","../src/modules/swapModule/index.ts","../src/modules/haedalModule/index.ts","../src/modules/index.ts","../src/client.ts","../src/signer.ts"],"sourcesContent":["/**\n * Wallet Client Module System\n *\n * This module defines the base architecture for the wallet client's modular system.\n * It provides the foundation for different functionality modules like swap, lending,\n * balance management, and other DeFi operations.\n *\n * @module WalletClientModule\n */\n\nimport { WalletClient } from '../client'\nimport { ModuleName } from '.'\n\n/**\n * Base interface for module configuration\n *\n * All modules must implement this interface to define their configuration structure.\n */\nexport interface ModuleConfig {\n [key: string]: any\n}\n\n/**\n * Base interface for module events\n *\n * All modules must implement this interface to define their event structure.\n */\nexport type ModuleEvents = {\n [key: string]: any\n}\n\n/**\n * Abstract base class for all wallet client modules\n *\n * This class provides the foundation for modular functionality in the wallet client.\n * Each module (swap, lending, balance, etc.) extends this class to provide\n * specific functionality while maintaining a consistent interface.\n *\n * @template TConfig - The configuration type for this module\n * @template TEvents - The events type for this module\n */\nexport abstract class Module<TConfig extends ModuleConfig, TEvents extends ModuleEvents> {\n /** The unique name identifier for this module */\n abstract readonly name: string\n\n /** Default configuration values for this module */\n abstract readonly defaultConfig: TConfig\n\n /** Reference to the wallet client instance that owns this module */\n protected walletClient?: WalletClient\n\n /**\n * Gets the current configuration for this module\n *\n * This combines the default configuration with any user-provided overrides\n * from the wallet client configuration.\n *\n * @returns The merged configuration for this module\n */\n get config(): TConfig {\n return this.walletClient\n ? (this.walletClient.config(this.name as ModuleName) as unknown as TConfig)\n : this.defaultConfig\n }\n\n /**\n * Emits an event through the wallet client's event system\n *\n * @param event - The event name to emit\n * @param data - The event data to emit\n */\n emit(event: keyof TEvents, data: TEvents[keyof TEvents]) {\n this.walletClient?.events.emit(event as any, data)\n }\n\n /**\n * Installs this module into a wallet client\n *\n * This method is called by the wallet client during initialization\n * to establish the connection between the module and the client.\n *\n * @param walletClient - The wallet client instance to install into\n */\n install(walletClient: WalletClient): void {\n this.walletClient = walletClient\n }\n\n /**\n * Uninstalls this module from the wallet client\n *\n * This method removes the reference to the wallet client,\n * effectively disconnecting the module.\n */\n uninstall() {\n this.walletClient = undefined\n }\n}\n","/**\n * User Portfolio Management\n *\n * This module provides portfolio management functionality for tracking\n * user coin balances across different token types. It aggregates coin\n * objects by type and provides convenient methods for balance queries\n * and portfolio operations.\n *\n * @module UserPortfolio\n */\n\nimport type { CoinStruct } from '@mysten/sui/jsonRpc'\nimport { BigNumber } from 'bignumber.js'\nimport { normalizeStructTag } from '@mysten/sui/utils'\n\n/**\n * User portfolio for managing coin balances\n *\n * This class provides functionality to:\n * - Aggregate coins by type and calculate total balances\n * - Query balances for specific coin types\n * - Clone portfolio state for safe operations\n * - Normalize coin types for consistent comparison\n */\nexport class UserPortfolio {\n /** Mapping of coin types to their balance information */\n balances: { [key in string]: UserCoinBalance }\n\n /**\n * Creates a new user portfolio\n *\n * @param coins - Array of coin objects or existing portfolio to copy from\n */\n constructor(coins?: CoinStruct[] | UserPortfolio) {\n if (coins instanceof UserPortfolio) {\n // Copy from existing portfolio\n this.balances = JSON.parse(JSON.stringify(coins.balances))\n } else {\n // Build portfolio from coin objects\n const balances: { [key in string]: UserCoinBalance } = {}\n\n coins?.forEach((item) => {\n if (!item.coinType || item.balance === undefined || item.balance === null) {\n return\n }\n // Normalize coin type for consistent key usage\n const normalizedCoinType = normalizeStructTag(item.coinType)\n let existPofolio = balances[normalizedCoinType]\n\n // Create new balance entry if it doesn't exist\n if (!existPofolio) {\n existPofolio = {\n coinType: normalizedCoinType,\n amount: BigNumber(0),\n coins: []\n }\n balances[normalizedCoinType] = existPofolio\n }\n\n // Add coin to balance and update total amount\n existPofolio.coins.push(item)\n existPofolio.amount = existPofolio.amount.plus(item.balance)\n })\n\n this.balances = balances\n }\n }\n\n /**\n * Gets balance information for a specific coin type\n *\n * @param coinType - The coin type to query\n * @returns UserCoinBalance object with coin type, total amount, and coin objects\n */\n getBalance(coinType: string): UserCoinBalance {\n coinType = normalizeStructTag(coinType)\n return this.balances[coinType] || { coinType, amount: BigNumber(0), coins: [] }\n }\n\n /**\n * Gets all coin types in the portfolio\n *\n * @returns Array of coin type strings\n */\n getCoinTypes() {\n return Object.values(this.balances).map((item) => {\n return item.coinType\n })\n }\n\n /**\n * Gets the total balance amount for a specific coin type\n *\n * @param coinType - The coin type to query\n * @returns BigNumber representing the total balance\n */\n balanceOf(coinType: string) {\n coinType = normalizeStructTag(coinType)\n const balance = this.getBalance(coinType)\n return balance?.amount || BigNumber(0)\n }\n\n /**\n * Creates a deep copy of the portfolio\n *\n * This method creates a completely independent copy of the portfolio\n * that can be modified without affecting the original.\n *\n * @returns New UserPortfolio instance with copied data\n */\n clone() {\n const newBalances = JSON.parse(JSON.stringify(this.balances))\n const userPortfolio = new UserPortfolio()\n userPortfolio.balances = newBalances\n return userPortfolio\n }\n}\n\n/**\n * Balance information for a specific coin type\n *\n * This type represents the aggregated balance information for all\n * coins of a particular type in the user's portfolio.\n */\nexport type UserCoinBalance = {\n /** Normalized coin type string */\n coinType: string\n /** Total balance amount across all coins of this type */\n amount: BigNumber\n /** Array of individual coin objects */\n coins: CoinStruct[]\n}\n","/**\n * Balance Module Implementation\n *\n * This module provides comprehensive balance management functionality for the wallet client.\n * It handles coin tracking, portfolio management, coin transfers, and automatic balance updates\n * through polling mechanisms.\n *\n * @module BalanceModule\n */\n\nimport { Module } from '../module'\nimport { getCoins, mergeCoinsPTB, withSingleton } from '@naviprotocol/lending'\nimport type { CoinStruct } from '@mysten/sui/jsonRpc'\nimport type { WalletClient } from '../../client'\nimport { UserPortfolio } from './portfolio'\nimport BigNumber from 'bignumber.js'\nimport { Transaction } from '@mysten/sui/transactions'\nimport type { NaviWalletTransactionResult } from '../../types'\nimport { normalizeStructTag } from '@mysten/sui/utils'\n\n/**\n * Configuration options for the balance module\n */\nexport interface BalanceModuleConfig {\n /** Interval in milliseconds for polling coin balances */\n coinPollingInterval: number\n /** Whether to disable coin polling */\n disableCoinPolling: boolean\n}\n\n/**\n * Events emitted by the balance module\n */\nexport type Events = {\n /** Emitted when the portfolio is updated with new balance information */\n 'balance:portfolio-updated': {}\n}\n\n/**\n * Balance management module for wallet operations\n *\n * This module provides functionality for:\n * - Tracking coin balances and portfolio information\n * - Sending coins to recipients\n * - Transferring objects\n * - Automatic balance updates through polling\n * - Portfolio management and balance queries\n */\nexport class BalanceModule extends Module<BalanceModuleConfig, Events> {\n /** Module name identifier */\n readonly name = 'balance'\n\n /** Default configuration values */\n readonly defaultConfig = {\n coinPollingInterval: 6000,\n disableCoinPolling: false\n }\n\n /**\n * Gets the current coin objects from the wallet\n *\n * @returns Array of coin objects owned by the wallet\n */\n public get coins() {\n return this._coins\n }\n\n /**\n * Gets the current portfolio information\n *\n * @returns UserPortfolio instance with current balance information\n */\n public get portfolio() {\n return this._portfolio\n }\n\n /**\n * Waits for the next portfolio update to complete\n *\n * @returns Promise that resolves when the portfolio is updated\n * @throws Error if no update promise is available\n */\n public async waitForUpdate() {\n if (!this._updatePromise) {\n throw new Error('Update promise not found')\n }\n return await this._updatePromise\n }\n\n /**\n * Sends a single coin to a recipient\n *\n * @param coinType - Type of coin to send\n * @param recipient - Recipient address\n * @param amount - Amount to send\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n public async sendCoin<T extends boolean = false>(\n coinType: string,\n recipient: string,\n amount: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n return this.sendCoinBatch(coinType, [recipient], [amount], options)\n }\n\n /**\n * Sends coins to multiple recipients in a single transaction\n *\n * @param coinType - Type of coin to send\n * @param recipients - Array of recipient addresses\n * @param amounts - Array of amounts to send (must match recipients length)\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n public async sendCoinBatch<T extends boolean = false>(\n coinType: string,\n recipients: string[],\n amounts: number[],\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n if (recipients.length !== amounts.length) {\n throw new Error('Recipients and amounts must have the same length')\n }\n\n // Wait for latest portfolio update\n await this.waitForUpdate()\n\n // Check if sufficient balance is available\n const coinBalance = this.portfolio.getBalance(coinType)\n const totalAmount = amounts.reduce((acc, curr) => acc.plus(curr), BigNumber(0))\n if (coinBalance.amount.lt(totalAmount)) {\n throw new Error('Insufficient balance')\n }\n\n // Build transaction\n const tx = new Transaction()\n\n let mergedCoin: any = tx.gas\n\n if (normalizeStructTag(coinType) !== normalizeStructTag('0x2::sui::SUI')) {\n mergedCoin = mergeCoinsPTB(tx, coinBalance.coins, {\n balance: totalAmount.toNumber()\n })\n }\n\n const coins = tx.splitCoins(mergedCoin, amounts)\n\n // Transfer coins to recipients\n recipients.forEach((address, index) => {\n tx.transferObjects([coins[index]], address)\n })\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n return result as any\n }\n\n /**\n * Transfers a single object to a recipient\n *\n * @param object - Object ID to transfer\n * @param recipient - Recipient address\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n async transferObject<T extends boolean = false>(\n object: string,\n recipient: string,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n return this.transferObjectBatch([object], [recipient], options)\n }\n\n /**\n * Transfers multiple objects to their respective recipients in a single transaction\n *\n * Each object is transferred to its corresponding recipient by index\n * (first object → first recipient, second object → second recipient, etc.)\n *\n * @param objects - Object IDs to transfer\n * @param recipients - Recipient addresses (must match objects array length)\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n async transferObjectBatch<T extends boolean = false>(\n objects: string[],\n recipients: string[],\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n if (objects.length !== recipients.length) {\n throw new Error('Objects and recipients must have the same length')\n }\n\n // Wait for latest portfolio update\n await this.waitForUpdate()\n\n // Build transaction\n const tx = new Transaction()\n\n // Transfer objects to recipients\n objects.forEach((object, index) => {\n tx.transferObjects([tx.object(object)], recipients[index])\n })\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n return result as any\n }\n\n /**\n * Updates the portfolio with current coin information\n *\n * This function is wrapped with singleton behavior to prevent\n * concurrent updates and ensure data consistency.\n */\n updatePortfolio = withSingleton(async () => {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Fetch current coins from the wallet\n this._coins = await getCoins(this.walletClient.address, {\n client: this.walletClient.client\n })\n\n // Update portfolio with new coin data\n this._portfolio = new UserPortfolio(this._coins)\n\n // Emit portfolio update event\n this.emit('balance:portfolio-updated', {})\n })\n\n /** Current coin objects from the wallet */\n private _coins: CoinStruct[] = []\n\n /** Current portfolio information */\n private _portfolio: UserPortfolio = new UserPortfolio()\n\n /** Timer for polling balance updates */\n private pollingTimer: NodeJS.Timeout | null = null\n\n /** Promise for waiting on portfolio updates */\n private _updatePromise: Promise<void> | null = null\n\n /**\n * Starts polling for portfolio updates\n *\n * This method recursively schedules itself to run at the configured\n * interval, ensuring regular balance updates.\n */\n private async startPolling() {\n if (this.config.disableCoinPolling) {\n return\n }\n\n try {\n await this.updatePortfolio()\n } catch (error) {\n console.error(error)\n } finally {\n this.pollingTimer = setTimeout(this.startPolling, this.config.coinPollingInterval)\n }\n }\n\n /**\n * Installs the balance module into a wallet client\n *\n * @param walletClient - The wallet client instance to install into\n */\n install(walletClient: WalletClient) {\n super.install(walletClient)\n\n // Bind the polling method and start polling\n this.startPolling = this.startPolling.bind(this)\n this.startPolling()\n\n // Create update promise for waiting on portfolio updates\n this._updatePromise = new Promise((resolve) => {\n walletClient.events.on('balance:portfolio-updated', () => {\n resolve()\n })\n })\n }\n\n /**\n * Uninstalls the balance module from the wallet client\n *\n * This method cleans up timers and stops polling to prevent memory leaks.\n */\n uninstall() {\n super.uninstall()\n if (this.pollingTimer) {\n clearTimeout(this.pollingTimer)\n this.pollingTimer = null\n }\n }\n}\n","import type {\n NaviDryRunTransactionResult,\n NaviExecuteTransactionResult,\n NaviTransactionEffects,\n NaviTransactionEvent,\n NaviTransactionResponseOptions\n} from './types'\n\nexport const defaultTransactionResponseOptions: NaviTransactionResponseOptions = {\n showEffects: true,\n showEvents: true,\n showBalanceChanges: true,\n showObjectChanges: true\n}\n\nexport function mergeTransactionResponseOptions(\n options?: NaviTransactionResponseOptions\n): NaviTransactionResponseOptions {\n return {\n ...defaultTransactionResponseOptions,\n ...options\n }\n}\n\n/**\n * Whether a (normalized) transaction result succeeded.\n *\n * Handles both shapes: v1 JSON-RPC effects `status.status === 'success'` (string)\n * and Sui v2 Core `status.success === true` (boolean). Using only the v1 string\n * check makes success events silently never fire on the gRPC/Core path.\n */\nexport function isSuccessfulTransaction(result: {\n effects?: { status?: unknown } | null\n}): boolean {\n const status = result?.effects?.status as Record<string, unknown> | undefined\n return status?.status === 'success' || status?.success === true\n}\n\nexport function normalizeTransactionResult(\n kind: 'dryRun',\n result: unknown\n): NaviDryRunTransactionResult\nexport function normalizeTransactionResult(\n kind: 'execute',\n result: unknown\n): NaviExecuteTransactionResult\nexport function normalizeTransactionResult(\n kind: 'dryRun' | 'execute',\n result: unknown\n): NaviDryRunTransactionResult | NaviExecuteTransactionResult {\n const source = (result ?? {}) as Record<string, unknown>\n const raw = unwrapTransactionResult(source)\n const effects = normalizeEffects(raw)\n\n return {\n ...raw,\n kind,\n effects,\n events: normalizeEvents(raw.events),\n balanceChanges: Array.isArray(raw.balanceChanges) ? raw.balanceChanges : [],\n objectChanges: Array.isArray(raw.objectChanges) ? raw.objectChanges : []\n }\n}\n\nfunction unwrapTransactionResult(result: Record<string, unknown>) {\n const transaction = result.Transaction\n if (isRecord(transaction)) {\n return transaction\n }\n\n const failedTransaction = result.FailedTransaction\n if (isRecord(failedTransaction)) {\n return failedTransaction\n }\n\n return result\n}\n\nfunction normalizeEffects(raw: Record<string, unknown>): NaviTransactionEffects | undefined {\n if (isRecord(raw.effects)) {\n return raw.effects as NaviTransactionEffects\n }\n\n if (isRecord(raw.status)) {\n return {\n status: raw.status as NaviTransactionEffects['status']\n }\n }\n\n return undefined\n}\n\nfunction normalizeEvents(events: unknown): NaviTransactionEvent[] {\n if (!Array.isArray(events)) {\n return []\n }\n\n return events.map((event) => {\n if (!isRecord(event)) {\n return event\n }\n\n return {\n ...event,\n type: event.type ?? event.eventType,\n parsedJson: event.parsedJson ?? event.json\n }\n }) as NaviTransactionEvent[]\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n","import { Transaction } from '@mysten/sui/transactions'\nimport {\n AssetIdentifier,\n getFlashLoanAsset,\n flashloanPTB,\n depositCoinPTB,\n repayFlashLoanPTB,\n borrowCoinPTB,\n mergeCoinsPTB,\n updateOraclePricesPTB,\n getCoins\n} from '@naviprotocol/lending'\nimport { buildSwapPTBFromQuote } from '@naviprotocol/astros-aggregator-sdk'\nimport type { LendingModule } from '.'\nimport BigNumber from 'bignumber.js'\nimport { normalizeStructTag } from '@mysten/sui/utils'\nimport { getPriceFeeds, filterPriceFeeds } from '@naviprotocol/lending'\nimport { UserPortfolio } from '../balanceModule/portfolio'\n\nexport async function migrateBetweenSupplyPTB(\n this: LendingModule,\n tx: Transaction,\n from: AssetIdentifier,\n to: AssetIdentifier,\n options?: Partial<{\n protocol?: 'navi' | 'suilend'\n amount?: number\n slippage?: number\n }>\n) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n const fromPool = await this.getPool(from)\n const toPool = await this.getPool(to)\n const lendingState = await this.getLendingState()\n const address = this.walletClient.address\n\n const protocolName = options?.protocol ?? 'navi'\n const fromProtocol = await this.getProtocol(protocolName)\n if (!fromProtocol) {\n throw new Error(`Protocol ${protocolName} not found`)\n }\n const fromPoolLending = await fromProtocol.getPool(fromPool.coinType)\n\n console.log('migrateBetweenSupplyPTB', {\n fromPoolLending\n })\n\n if (protocolName === 'navi' && fromPoolLending.supplyBalance === 0) {\n throw new Error('No supply balance')\n }\n\n if (options?.amount && options.amount > fromPoolLending.supplyBalance) {\n throw new Error('Amount is less than supply balance')\n }\n\n const slippage = options?.slippage ?? 0.005\n\n const formAmount = options?.amount ?? Number(fromPoolLending.supplyBalance)\n\n const priceFeeds = await getPriceFeeds(this.naviServiceOptions)\n const pools = await Promise.all([fromPool, toPool])\n await updateOraclePricesPTB(\n tx,\n filterPriceFeeds(priceFeeds, {\n lendingState,\n pools\n }),\n this.naviServiceOptions\n )\n\n if (protocolName !== 'navi' && fromPool.id === toPool.id) {\n const withdrawnFromCoin = await fromProtocol.withdrawCoinPTB(\n tx,\n fromPool.suiCoinType,\n formAmount\n )\n await depositCoinPTB(tx, toPool, withdrawnFromCoin, {\n ...this.naviServiceOptions,\n amount: formAmount\n })\n return tx\n }\n\n const toPoolFlashloanAsset = await getFlashLoanAsset(toPool, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n if (!toPoolFlashloanAsset) {\n throw new Error(`${toPool.token.symbol} pool not support flashloan`)\n }\n\n const quote = await this.walletClient.swap.getQuote(\n fromPool.suiCoinType,\n toPool.suiCoinType,\n formAmount\n )\n\n const shouldSwapAmount = Number(quote.amount_out)\n\n if (shouldSwapAmount <= 0) {\n throw new Error('The amount of swapAmountOut must be greater than 0.')\n }\n\n const minAmountOut = Math.floor(shouldSwapAmount * (1 - slippage))\n\n const borrowAmountInMin = Math.floor(minAmountOut / (1 + toPoolFlashloanAsset.flashloanFee))\n\n if (borrowAmountInMin <= 0) {\n throw new Error('The calculated borrow amount must be positive.')\n }\n\n const [flashloanBalance, receipt] = await flashloanPTB(\n tx,\n toPool,\n borrowAmountInMin,\n this.naviServiceOptions\n )\n\n const [flashCoin] = tx.moveCall({\n target: '0x2::coin::from_balance',\n arguments: [flashloanBalance],\n typeArguments: [toPool.suiCoinType]\n })\n\n await depositCoinPTB(tx, toPool, flashCoin, {\n ...this.naviServiceOptions,\n amount: borrowAmountInMin\n })\n\n const withdrawnFromCoin = await fromProtocol.withdrawCoinPTB(tx, fromPool.suiCoinType, formAmount)\n\n const swappedToCoin = await buildSwapPTBFromQuote(\n address,\n tx,\n minAmountOut,\n withdrawnFromCoin,\n quote\n )\n\n const repayBalance = tx.moveCall({\n target: '0x2::coin::into_balance',\n arguments: [swappedToCoin],\n typeArguments: [toPool.suiCoinType]\n })\n\n const [leftBalance] = await repayFlashLoanPTB(\n tx,\n toPool,\n receipt,\n repayBalance,\n this.naviServiceOptions\n )\n\n const [extraCoin] = tx.moveCall({\n target: '0x2::coin::from_balance',\n arguments: [leftBalance],\n typeArguments: [toPool.suiCoinType]\n })\n\n await depositCoinPTB(tx, toPool, extraCoin, this.naviServiceOptions)\n\n return tx\n}\n\nexport async function migrateBetweenBorrowPTB(\n this: LendingModule,\n tx: Transaction,\n from: AssetIdentifier,\n to: AssetIdentifier,\n options?: Partial<{\n amount?: number\n slippage?: number\n protocol?: 'navi' | 'suilend'\n }>\n) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n const address = this.walletClient.address\n const fromPool = await this.getPool(from)\n const toPool = await this.getPool(to)\n const lendingState = await this.getLendingState()\n\n const protocolName = options?.protocol ?? 'navi'\n const fromProtocol = await this.getProtocol(protocolName)\n if (!fromProtocol) {\n throw new Error(`Protocol ${protocolName} not found`)\n }\n const fromPoolLending = await fromProtocol.getPool(fromPool.coinType)\n\n console.log('migrateBetweenBorrowPTB', {\n fromPoolLending\n })\n\n if (fromPoolLending.borrowBalance === 0) {\n throw new Error('No borrow balance')\n }\n\n if (options?.amount && options.amount > fromPoolLending.borrowBalance) {\n throw new Error('Amount is more than borrow balance')\n }\n\n const priceFeeds = await getPriceFeeds(this.naviServiceOptions)\n const pools = await Promise.all([fromPool, toPool])\n await updateOraclePricesPTB(\n tx,\n filterPriceFeeds(priceFeeds, {\n lendingState,\n pools\n }),\n this.naviServiceOptions\n )\n\n let formAmount = options?.amount ?? Number(fromPoolLending.borrowBalance)\n\n if (Number(fromPoolLending.borrowBalance) === formAmount) {\n const borrowRate = fromPoolLending.borrowAPR / 100\n formAmount = Math.ceil(\n new BigNumber(formAmount)\n .multipliedBy((borrowRate * (60 * 3)) / (365 * 24 * 3600))\n .plus(new BigNumber(1).shiftedBy(-fromPool.token.decimals))\n .plus(formAmount)\n .toNumber()\n )\n }\n\n const fromPoolFlashloanAsset = await getFlashLoanAsset(fromPool, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n if (!fromPoolFlashloanAsset) {\n throw new Error(`${fromPool.token.symbol} pool not support flashloan`)\n }\n\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const slippage = options?.slippage ?? 0.005\n\n const flashloanRepayAmount = Math.ceil(formAmount * (1 + fromPoolFlashloanAsset.flashloanFee))\n const minSwapAmount = flashloanRepayAmount\n\n const fromQuote = await this.walletClient.swap.getQuote(\n fromPool.suiCoinType,\n toPool.suiCoinType,\n minSwapAmount\n )\n\n let rate = 1 + slippage\n\n let shouldBorrowAmount = Math.ceil(Number(fromQuote.amount_out) * rate)\n\n let toQuote = await this.walletClient.swap.getQuote(\n toPool.suiCoinType,\n fromPool.suiCoinType,\n shouldBorrowAmount\n )\n\n while (Number(toQuote.amount_out) < minSwapAmount) {\n rate = rate * Math.max(minSwapAmount / Number(toQuote.amount_out), 1.001)\n shouldBorrowAmount = Math.ceil(Number(fromQuote.amount_out) * rate)\n toQuote = await this.walletClient.swap.getQuote(\n toPool.suiCoinType,\n fromPool.suiCoinType,\n shouldBorrowAmount\n )\n }\n\n const [flashloanBalance, receipt] = await flashloanPTB(\n tx,\n fromPool,\n formAmount,\n this.naviServiceOptions\n )\n\n const [flashCoin]: any = tx.moveCall({\n target: '0x2::coin::from_balance',\n arguments: [flashloanBalance],\n typeArguments: [fromPool.suiCoinType]\n })\n\n await fromProtocol.repayCoinPTB(tx, fromPool.suiCoinType, flashCoin, formAmount)\n\n const borrowCoin = await borrowCoinPTB(tx, toPool, shouldBorrowAmount, this.naviServiceOptions)\n\n const swappedFromCoin = await buildSwapPTBFromQuote(\n address,\n tx,\n flashloanRepayAmount,\n borrowCoin,\n toQuote\n )\n\n const repayBalance = tx.moveCall({\n target: '0x2::coin::into_balance',\n arguments: [swappedFromCoin],\n typeArguments: [fromPool.suiCoinType]\n })\n\n const [leftBalance] = await repayFlashLoanPTB(\n tx,\n fromPool,\n receipt,\n repayBalance,\n this.naviServiceOptions\n )\n\n const [extraCoin] = tx.moveCall({\n target: '0x2::coin::from_balance',\n arguments: [leftBalance],\n typeArguments: [fromPool.suiCoinType]\n })\n tx.transferObjects([extraCoin], address)\n\n return tx\n}\n\nexport async function migrateBalanceToSupplyPTB(\n this: LendingModule,\n tx: Transaction,\n coinType: string,\n to: AssetIdentifier,\n options?: Partial<{\n amount?: number\n slippage?: number\n }>\n) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const coins = await getCoins(this.walletClient.address, {\n client: this.walletClient.client,\n coinType\n })\n const toPool = await this.getPool(to)\n const portfolio = new UserPortfolio(coins)\n const balance = portfolio.getBalance(coinType)\n\n if (balance.amount.eq(0)) {\n throw new Error(`No balance of ${coinType}`)\n }\n\n console.log('migrateBalanceToSupplyPTB', {\n balance: balance.amount.toNumber()\n })\n\n if (options?.amount && balance.amount.lt(options.amount)) {\n throw new Error('Amount is greater than balance')\n }\n\n const formAmount = options?.amount ?? balance.amount.toNumber()\n\n const slippage = options?.slippage ?? 0.005\n\n let depositCoin = await mergeCoinsPTB(tx, balance.coins, {\n balance: formAmount,\n useGasCoin: true\n })\n\n if (normalizeStructTag(coinType) !== normalizeStructTag(toPool.suiCoinType)) {\n const quote = await this.walletClient.swap.getQuote(coinType, toPool.suiCoinType, formAmount)\n depositCoin = (await this.walletClient.swap.buildSwapPTBFromQuote(\n tx,\n quote,\n depositCoin,\n slippage\n )) as typeof depositCoin\n }\n\n await depositCoinPTB(tx, toPool, depositCoin, this.naviServiceOptions)\n\n return tx\n}\n","import { LendingPool, LendingProtocol } from '.'\nimport { Transaction, TransactionObjectInput, TransactionResult } from '@mysten/sui/transactions'\nimport { withdrawCoinPTB, repayCoinPTB, CoinObject, getPool } from '@naviprotocol/lending'\nimport { WalletClient } from '../../../client'\nimport BigNumber from 'bignumber.js'\nimport { normalizeStructTag } from '@mysten/sui/utils'\n\nclass NaviProtocol implements LendingProtocol {\n readonly name = 'navi'\n private walletClient: WalletClient\n\n constructor(walletClient: WalletClient) {\n this.walletClient = walletClient\n }\n\n async getPool(coinType: string): Promise<LendingPool> {\n const pool = await this.walletClient.lending.getPool(coinType)\n const lendingState = await this.walletClient.lending.getLendingState()\n const userPosition = lendingState.find(\n (position) => position.pool.suiCoinType === normalizeStructTag(coinType)\n )\n\n const supplyBalance = userPosition ? new BigNumber(userPosition.supplyBalance).toNumber() : 0\n const borrowBalance = userPosition ? new BigNumber(userPosition.borrowBalance).toNumber() : 0\n\n return {\n supplyBalance: supplyBalance,\n borrowBalance: borrowBalance,\n borrowAPR: parseFloat(pool.borrowIncentiveApyInfo.apy)\n }\n }\n\n async depositCoinPTB(\n tx: Transaction,\n coinType: string,\n coinObject: TransactionObjectInput,\n amount: number\n ): Promise<void> {\n throw new Error('Not implemented')\n }\n\n async withdrawCoinPTB(\n tx: Transaction,\n coinType: string,\n amount: number\n ): Promise<TransactionResult> {\n return withdrawCoinPTB(tx, coinType, amount, this.walletClient.lending.naviServiceOptions)\n }\n\n async borrowCoinPTB(\n tx: Transaction,\n coinType: string,\n amount: number\n ): Promise<TransactionResult> {\n throw new Error('Not implemented')\n }\n\n async repayCoinPTB(\n tx: Transaction,\n coinType: string,\n coinObject: CoinObject,\n amount: number\n ): Promise<void> {\n repayCoinPTB(tx, coinType, coinObject, {\n ...this.walletClient.lending.naviServiceOptions,\n amount\n })\n }\n}\n\nexport default NaviProtocol\n","/**\n * Lending Module Implementation\n *\n * This module provides comprehensive lending protocol functionality for the wallet client.\n * It handles deposit, withdraw, borrow, repay operations, liquidation, reward claiming,\n * and oracle price updates for the Navi lending protocol.\n *\n * @module LendingModule\n */\n\nimport { isSuccessfulTransaction } from '../../transaction-result'\nimport type { NaviWalletTransactionResult } from '../../types'\nimport { Module } from '../module'\nimport {\n depositCoinPTB,\n withdrawCoinPTB,\n borrowCoinPTB,\n repayCoinPTB,\n AssetIdentifier,\n getPool,\n getPools,\n mergeCoinsPTB,\n getHealthFactor,\n liquidatePTB,\n claimLendingRewardsPTB,\n getUserAvailableLendingRewards,\n updateOraclePricesPTB,\n getPriceFeeds,\n getLendingState,\n filterPriceFeeds,\n CacheOption,\n LendingReward,\n AccountCapOption,\n Pool,\n createAccountCapPTB,\n getUserClaimedRewardHistory,\n type NaviSdkServiceOptions\n} from '@naviprotocol/lending'\nimport { Transaction } from '@mysten/sui/transactions'\nimport type { SuiGrpcClient } from '@mysten/sui/grpc'\nimport {\n migrateBalanceToSupplyPTB,\n migrateBetweenBorrowPTB,\n migrateBetweenSupplyPTB\n} from './migrate'\nimport NaviProtocol from './protocols/navi'\nimport { LendingProtocol } from './protocols'\nimport { WalletClient } from '../../client'\n\n/**\n * Configuration options for the lending module\n */\nexport interface LendingModuleConfig {\n /** Environment setting for protocol interaction */\n env: 'dev' | 'prod'\n /** Lending protocols */\n protocols: LendingProtocol[]\n /** Enable the optional Suilend adapter. Defaults to true to preserve v1 business behavior. */\n enableSuilend: boolean\n /** Optional Suilend v3 gRPC client. Defaults to a client derived from the wallet Sui network. */\n suilendGrpcClient?: SuiGrpcClient\n /** Optional Suilend v3 gRPC endpoint. Used when suilendGrpcClient is not provided. */\n suilendGrpcUrl?: string\n /** Optional NAVI service endpoint overrides. */\n services?: NaviSdkServiceOptions\n}\n\n/**\n * Events emitted by the lending module\n */\nexport type Events = {\n /** Emitted when a deposit is successfully completed */\n 'lending:deposit-success': {\n /** Asset identifier for the deposited asset */\n identifier: AssetIdentifier\n /** Amount deposited */\n amount: number\n }\n /** Emitted when a withdrawal is successfully completed */\n 'lending:withdraw-success': {\n /** Asset identifier for the withdrawn asset */\n identifier: AssetIdentifier\n /** Amount withdrawn */\n amount: number\n }\n /** Emitted when a borrow is successfully completed */\n 'lending:borrow-success': {\n /** Asset identifier for the borrowed asset */\n identifier: AssetIdentifier\n /** Amount borrowed */\n amount: number\n }\n /** Emitted when a repayment is successfully completed */\n 'lending:repay-success': {\n /** Asset identifier for the repaid asset */\n identifier: AssetIdentifier\n /** Amount repaid */\n amount: number\n }\n /** Emitted when a liquidation is successfully completed */\n 'lending:liquidate-success': {\n /** Asset identifier for the debt being paid */\n payIdentifier: AssetIdentifier\n /** Amount of debt paid */\n payAmount: number\n /** Asset identifier for the collateral being liquidated */\n collateralIdentifier: AssetIdentifier\n /** Address of the account being liquidated */\n liquidationAddress: string\n }\n /** Emitted when rewards are successfully claimed */\n 'lending:claim-rewards-success': {\n /** Array of claimed rewards */\n rewards: LendingReward[]\n }\n}\n\n/**\n * Lending protocol module for wallet operations\n *\n * This module provides comprehensive lending functionality including:\n * - Deposit and withdraw operations\n * - Borrow and repay operations\n * - Liquidation functionality\n * - Reward claiming\n * - Oracle price updates\n * - Health factor monitoring\n * - Pool information retrieval\n */\nexport class LendingModule extends Module<LendingModuleConfig, Events> {\n /** Module name identifier */\n readonly name = 'lending'\n\n /** Default configuration values */\n readonly defaultConfig: LendingModuleConfig = {\n env: 'prod',\n protocols: [],\n enableSuilend: true\n }\n\n /** Internal protocols storage */\n private _protocols: LendingProtocol[] = []\n\n /** Get protocols (either from internal storage or config) */\n get protocols(): LendingProtocol[] {\n return this._protocols.length > 0 ? this._protocols : this.config.protocols\n }\n\n get naviServiceOptions() {\n const services = this.config.services ?? this.walletClient?.clientBundle.services\n return {\n ...(services ? { services } : {})\n }\n }\n\n install(walletClient: WalletClient): void {\n super.install(walletClient)\n this._protocols = []\n }\n\n async getProtocol(name: string) {\n if (!this.protocols || this.protocols.length === 0) {\n await this.initializeProtocols()\n }\n return this.protocols.find((p) => p.name === name)\n }\n\n /**\n * Gets all available lending pools\n *\n * @param options - Optional caching options\n * @returns Array of pool information\n */\n async getPools(options?: Partial<CacheOption>) {\n return await getPools({\n ...this.naviServiceOptions,\n env: this.config.env,\n ...options\n })\n }\n\n /**\n * Gets information for a specific lending pool\n *\n * @param identifier - Asset identifier (string, Pool object, or number)\n * @param options - Optional caching options\n * @returns Pool information\n */\n async getPool(identifier: AssetIdentifier, options?: Partial<CacheOption>) {\n return await getPool(identifier, {\n ...this.naviServiceOptions,\n env: this.config.env,\n ...options\n })\n }\n\n /**\n * Deposits coins into a lending pool\n *\n * @param identifier - Asset identifier for the pool\n * @param amount - Amount to deposit\n * @param options - Optional parameters including dry run mode and account capability\n * @returns Transaction response or dry run response\n */\n async deposit<T extends boolean = false>(\n identifier: AssetIdentifier,\n amount: number,\n options?: { dryRun: T } & Partial<AccountCapOption>\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Get pool information\n const pool = await getPool(identifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n // Wait for latest balance update\n await this.walletClient.module('balance').waitForUpdate()\n\n // Build transaction\n const tx = new Transaction()\n\n // Get coin balance and merge coins for deposit\n const coinBalance = this.walletClient.module('balance').portfolio.getBalance(pool.suiCoinType)\n\n const mergedCoin = mergeCoinsPTB(tx, coinBalance.coins, {\n balance: amount,\n useGasCoin: true\n })\n\n // Build deposit transaction\n await depositCoinPTB(tx, pool, mergedCoin, {\n ...this.naviServiceOptions,\n env: this.config.env,\n amount,\n accountCap: options?.accountCap\n })\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n // Handle successful deposit\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:deposit-success', {\n identifier,\n amount\n })\n\n // Update balance portfolio\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Withdraws coins from a lending pool\n *\n * @param identifier - Asset identifier for the pool\n * @param amount - Amount to withdraw\n * @param options - Optional parameters including dry run mode and account capability\n * @returns Transaction response or dry run response\n */\n async withdraw<T extends boolean = false>(\n identifier: AssetIdentifier,\n amount: number,\n options?: { dryRun: T; disableUpdateOracle?: boolean } & Partial<AccountCapOption>\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Get pool information\n const pool = await getPool(identifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n // Build transaction\n const tx = new Transaction()\n\n if (!options?.disableUpdateOracle) {\n await this.updateOraclePTB(tx, [pool])\n }\n\n // Build withdraw transaction\n const coin = await withdrawCoinPTB(tx, pool, amount, {\n ...this.naviServiceOptions,\n env: this.config.env,\n accountCap: options?.accountCap\n })\n\n // Transfer withdrawn coins to wallet\n tx.transferObjects([coin], this.walletClient.address)\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n // Handle successful withdrawal\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:withdraw-success', {\n identifier,\n amount\n })\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Borrows coins from a lending pool\n *\n * @param identifier - Asset identifier for the pool\n * @param amount - Amount to borrow\n * @param options - Optional parameters including dry run mode and account capability\n * @returns Transaction response or dry run response\n */\n async borrow<T extends boolean = false>(\n identifier: AssetIdentifier,\n amount: number,\n options?: { dryRun: T; disableUpdateOracle?: boolean } & Partial<AccountCapOption>\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Get pool information\n const pool = await getPool(identifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n // Build transaction\n const tx = new Transaction()\n\n if (!options?.disableUpdateOracle) {\n await this.updateOraclePTB(tx, [pool])\n }\n\n // Build borrow transaction\n const coin = await borrowCoinPTB(tx, pool, amount, {\n ...this.naviServiceOptions,\n env: this.config.env,\n accountCap: options?.accountCap\n })\n\n // Transfer borrowed coins to wallet\n tx.transferObjects([coin], this.walletClient.address)\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n // Handle successful borrow\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:borrow-success', {\n identifier,\n amount\n })\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Repays borrowed coins to a lending pool\n *\n * @param identifier - Asset identifier for the pool\n * @param amount - Amount to repay\n * @param options - Optional parameters including dry run mode and account capability\n * @returns Transaction response or dry run response\n */\n async repay<T extends boolean = false>(\n identifier: AssetIdentifier,\n amount: number,\n options?: { dryRun: T } & Partial<AccountCapOption>\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Wait for latest balance update\n await this.walletClient.module('balance').waitForUpdate()\n\n // Get pool information\n const pool = await getPool(identifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n // Build transaction\n const tx = new Transaction()\n\n // Get coin balance and merge coins for repayment\n const coinBalance = this.walletClient.module('balance').portfolio.getBalance(pool.suiCoinType)\n\n const mergedCoin = mergeCoinsPTB(tx, coinBalance.coins, {\n balance: amount,\n useGasCoin: true\n })\n\n // Build repay transaction\n await repayCoinPTB(tx, pool, mergedCoin, {\n ...this.naviServiceOptions,\n env: this.config.env,\n amount,\n accountCap: options?.accountCap\n })\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n // Handle successful repayment\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:repay-success', {\n identifier,\n amount\n })\n\n // Update balance portfolio\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Gets the current health factor for the user\n *\n * @returns Current health factor value\n */\n async getHealthFactor() {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const address = this.walletClient.address\n\n const healthFactor = await getHealthFactor(address, {\n ...this.naviServiceOptions,\n env: this.config.env,\n client: this.walletClient.client\n })\n\n return healthFactor\n }\n\n /**\n * Initiates a liquidation process\n *\n * @param payIdentifier - Asset identifier for the debt being paid\n * @param payAmount - Amount of debt to pay\n * @param collateralIdentifier - Asset identifier for the collateral being liquidated\n * @param liquidationAddress - Address of the account being liquidated\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n async liquidate<T extends boolean = false>(\n payIdentifier: AssetIdentifier,\n payAmount: number,\n collateralIdentifier: AssetIdentifier,\n liquidationAddress: string,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const payPool = await getPool(payIdentifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n const collateralPool = await getPool(collateralIdentifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n const tx = new Transaction()\n\n const payCoinBalance = this.walletClient\n .module('balance')\n .portfolio.getBalance(payPool.suiCoinType)\n\n const mergedCoin = mergeCoinsPTB(tx, payCoinBalance.coins, {\n balance: payAmount,\n useGasCoin: true\n })\n\n const [collateralBalance, remainDebtBalance] = await liquidatePTB(\n tx,\n payPool,\n mergedCoin,\n collateralPool,\n liquidationAddress,\n {\n ...this.naviServiceOptions,\n env: this.config.env\n }\n )\n\n const [collateralCoin] = tx.moveCall({\n target: `0x2::coin::from_balance`,\n arguments: [collateralBalance],\n typeArguments: [collateralPool.suiCoinType]\n })\n\n const [leftDebtCoin] = tx.moveCall({\n target: `0x2::coin::from_balance`,\n arguments: [remainDebtBalance],\n typeArguments: [payPool.suiCoinType]\n })\n\n tx.transferObjects([collateralCoin, leftDebtCoin], this.walletClient.address)\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:liquidate-success', {\n payIdentifier,\n payAmount,\n collateralIdentifier,\n liquidationAddress\n })\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Gets the available lending rewards for the current user.\n *\n * @param options - Optional cache options.\n * @returns The available lending rewards for the user.\n * @throws If the wallet client is not found.\n */\n async getAvailableRewards(options?: Partial<CacheOption>) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n return getUserAvailableLendingRewards(this.walletClient.address, {\n ...this.naviServiceOptions,\n ...options,\n env: this.config.env,\n client: this.walletClient.client\n })\n }\n\n /**\n * Gets the claimed reward history for the current user.\n *\n * @param options - Optional cache options.\n * @returns The claimed reward history for the user.\n * @throws If the wallet client is not found.\n */\n async getClaimedRewardHistory(\n options?: Partial<CacheOption> & {\n page?: number\n size?: number\n }\n ) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n return getUserClaimedRewardHistory(this.walletClient.address, {\n ...this.naviServiceOptions,\n ...options\n })\n }\n\n /**\n * Claims all available lending rewards for the user\n *\n * @param options - Optional parameters including dry run mode and account capability\n * @returns Transaction response or dry run response\n */\n async claimAllRewards<T extends boolean = false>(\n options?: { dryRun: T } & Partial<AccountCapOption>\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const tx = new Transaction()\n\n const rewards = await getUserAvailableLendingRewards(this.walletClient.address, {\n ...this.naviServiceOptions,\n env: this.config.env,\n client: this.walletClient.client\n })\n\n await claimLendingRewardsPTB(tx, rewards, {\n ...this.naviServiceOptions,\n env: this.config.env,\n accountCap: options?.accountCap\n })\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:claim-rewards-success', {\n rewards\n })\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n private async updateOraclePTB(tx: Transaction, pools?: Pool[]) {\n const feeds = await getPriceFeeds({\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n const lendingState = await this.getLendingState({\n cacheTime: 60 * 1000\n })\n\n const filteredFeeds = filterPriceFeeds(feeds, {\n lendingState,\n pools\n })\n\n await updateOraclePricesPTB(tx, filteredFeeds, {\n ...this.naviServiceOptions,\n env: this.config.env,\n updatePythPriceFeeds: true,\n client: this.walletClient?.client\n })\n }\n\n /**\n * Updates the oracle prices for the lending protocol\n *\n * @param options - Optional parameters including dry run mode and pools\n * @param options.dryRun - Whether to perform a dry run\n * @returns Transaction response or dry run response\n */\n async updateOracle<T extends boolean = false>(options?: {\n dryRun: T\n pools?: Pool[]\n }): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const tx = new Transaction()\n\n await this.updateOraclePTB(tx, options?.pools)\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n return result as any\n }\n\n /**\n * Gets all active lending positions for the user\n *\n * @param options - Optional caching options\n * @returns User's lending state information\n */\n async getLendingState(options?: Partial<CacheOption>) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n return await getLendingState(this.walletClient.address, {\n ...this.naviServiceOptions,\n env: this.config.env,\n ...options,\n client: this.walletClient.client\n })\n }\n\n /**\n * Creates an account capability for the lending protocol\n *\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n async createAccountCap<T extends boolean = false>(options?: {\n dryRun: T\n }): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const tx = new Transaction()\n\n const cap = await createAccountCapPTB(tx)\n\n tx.transferObjects([cap], this.walletClient.address)\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n return result as any\n }\n\n migrateBetweenSupplyPTB = migrateBetweenSupplyPTB\n migrateBetweenBorrowPTB = migrateBetweenBorrowPTB\n migrateBalanceToSupplyPTB = migrateBalanceToSupplyPTB\n\n constructor() {\n super()\n this.migrateBetweenSupplyPTB = migrateBetweenSupplyPTB.bind(this)\n this.migrateBetweenBorrowPTB = migrateBetweenBorrowPTB.bind(this)\n this.migrateBalanceToSupplyPTB = migrateBalanceToSupplyPTB.bind(this)\n }\n\n async initializeProtocols() {\n if (!this.walletClient) {\n console.warn('Wallet client not available during protocol initialization')\n return\n }\n\n const protocols = []\n protocols.push(new NaviProtocol(this.walletClient))\n\n if (this.config.enableSuilend) {\n try {\n const { default: SuilendProtocol } = await import('./protocols/suilend')\n protocols.push(\n await SuilendProtocol.create(this.walletClient, {\n grpcClient: this.config.suilendGrpcClient,\n grpcUrl: this.config.suilendGrpcUrl\n })\n )\n } catch (error) {\n console.warn('Failed to initialize SuilendProtocol:', error)\n }\n }\n\n this._protocols = protocols as LendingProtocol[]\n }\n}\n","/**\n * Volo Module for Sui Staking Protocol Integration\n *\n * This module provides functionality to interact with the Volo staking protocol on Sui.\n * Volo allows users to stake SUI tokens and receive vSUI (volo SUI) tokens in return,\n * enabling liquid staking with potential rewards and instant unstaking capabilities.\n */\n\nimport { isSuccessfulTransaction } from '../../transaction-result'\nimport {\n CoinObject,\n buildNaviOpenApiUrl,\n mergeCoinsPTB,\n mergeServiceHeaders,\n parseTxValue,\n resolveNaviOpenApiEndpoint,\n withCache,\n withSingleton,\n type NaviSdkServiceOptions\n} from '@naviprotocol/lending'\nimport { Transaction } from '@mysten/sui/transactions'\nimport { Module } from '../module'\nimport type { NaviWalletTransactionResult } from '../../types'\n\n/**\n * Configuration interface for the Volo staking module\n */\nexport interface VoloModuleConfig {\n /** The package ID of the Volo staking contract */\n packageId: string\n /** The pool ID for the staking pool */\n poolId: string\n /** The coin type for vSUI tokens */\n coinType: string\n /** The metadata ID for the staking pool */\n metadataId: string\n /** Optional NAVI service endpoint overrides. */\n services?: NaviSdkServiceOptions\n}\n\nexport type VoloStatsOptions = {\n services?: NaviSdkServiceOptions\n}\n\n/**\n * Event types emitted by the Volo module\n */\nexport type Events = {\n /** Emitted when staking is successful */\n 'volo:stake-success': {\n /** Amount of SUI staked */\n suiAmount: number\n }\n /** Emitted when unstaking is successful */\n 'volo:unstake-success': {\n /** Amount of vSUI unstaked */\n vSuiAmount: number\n }\n}\n\n/**\n * Statistics and information about the Volo staking pool\n */\nexport type VoloStats = {\n /** Current operator balance */\n operatorBalance: string\n /** Collectable fees in the pool */\n collectableFee: string\n /** Pending stakes waiting to be processed */\n pendingStakes: string\n /** Total amount staked in the pool */\n totalStaked: string\n /** Total rewards distributed to stakers */\n totalRewardsInStakes: string\n /** Currently active stake amount */\n activeStake: string\n /** Current epoch number */\n currentEpoch: string\n /** List of validators in the pool */\n validators: {\n /** Validator address */\n address: string\n /** Total amount staked with this validator */\n totalStaked: string\n /** Assigned weight for this validator */\n assigned_weight: string\n /** Annual percentage yield for this validator */\n apy: string\n /** Validator name */\n name: string\n }[]\n /** Current exchange rate between SUI and vSUI */\n exchangeRate: number\n /** Total supply of vSUI tokens */\n totalSupply: string\n /** Overall APY for the staking pool */\n apy: number\n /** Maximum amount that can be instantly unstaked */\n maxInstantUnstake: string\n /** Maximum amount that can be unstaked without fees */\n maxNoFeeUnstake: string\n /** Total number of stakers in the pool */\n totalStakers: number\n /** Timestamp of last update */\n lastUpdated: number\n}\n\n/**\n * Volo Module for Sui Staking Protocol\n *\n * Provides functionality to stake SUI tokens and receive vSUI tokens,\n * enabling liquid staking with potential rewards and instant unstaking.\n */\nexport class VoloModule extends Module<VoloModuleConfig, Events> {\n /** Module name identifier */\n readonly name = 'volo'\n\n /** Default configuration for the Volo staking protocol */\n readonly defaultConfig: VoloModuleConfig = {\n packageId: '0x68d22cf8bdbcd11ecba1e094922873e4080d4d11133e2443fddda0bfd11dae20',\n poolId: '0x2d914e23d82fedef1b5f56a32d5c64bdcc3087ccfea2b4d6ea51a71f587840e5',\n metadataId: '0x680cd26af32b2bde8d3361e804c53ec1d1cfe24c7f039eb7f549e8dfde389a60',\n coinType: '0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT'\n }\n\n /**\n * Get current statistics and information about the Volo staking pool\n * Uses caching to avoid repeated API calls\n *\n * @returns Volo staking pool information\n */\n private getStatsCached = withCache(\n withSingleton(async (options?: VoloStatsOptions) => {\n const serviceOptions = { services: options?.services }\n const endpoint = resolveNaviOpenApiEndpoint(serviceOptions)\n const resp: {\n data: VoloStats\n } = await fetch(buildNaviOpenApiUrl('/volo/stats', serviceOptions), {\n headers: mergeServiceHeaders({}, endpoint)\n }).then((res) => res.json())\n\n return resp.data\n })\n )\n\n getStats(options?: VoloStatsOptions) {\n return this.getStatsCached({\n services: options?.services ?? this.config.services\n })\n }\n\n /**\n * Adds staking operation to a transaction black\n *\n * @param tx - The transaction block to add the staking operation to\n * @param suiCoin - The SUI coin object to stake\n * @returns The vSUI coin object received from staking\n */\n async stakePTB(tx: Transaction, suiCoin: CoinObject) {\n const [coin] = tx.moveCall({\n target: `${this.config.packageId}::stake_pool::stake`,\n arguments: [\n tx.object(this.config.poolId),\n tx.object(this.config.metadataId),\n tx.object('0x05'),\n parseTxValue(suiCoin, tx.object)\n ],\n typeArguments: []\n })\n return coin\n }\n\n /**\n * Adds unstaking operation to a transaction black\n *\n * @param tx - The transaction block to add the unstaking operation to\n * @param vSuiCoin - The vSUI coin object to unstake\n * @returns The SUI coin object received from unstaking\n */\n async unstakePTB(tx: Transaction, vSuiCoin: CoinObject) {\n const [coin] = tx.moveCall({\n target: `${this.config.packageId}::stake_pool::unstake`,\n arguments: [\n tx.object(this.config.poolId),\n tx.object(this.config.metadataId),\n tx.object('0x05'),\n parseTxValue(vSuiCoin, tx.object)\n ],\n typeArguments: []\n })\n return coin\n }\n\n /**\n * Stake SUI tokens to receive vSUI tokens\n *\n * @param suiAmount - Amount of SUI to stake (in MIST units)\n * @param options - Optional parameters including dryRun flag\n * @returns Transaction response or dry run response\n * @throws Error if wallet client not found or stake amount is too low\n */\n async stake<T extends boolean = false>(\n suiAmount: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n if (suiAmount < 1e9) {\n throw new Error('Stake amount should be greater than 1Sui')\n }\n\n const tx = new Transaction()\n\n await this.walletClient.module('balance').waitForUpdate()\n\n const suiBalance = this.walletClient.module('balance').portfolio.getBalance('0x2::sui::SUI')\n\n const mergedCoin = mergeCoinsPTB(tx, suiBalance.coins, {\n balance: suiAmount,\n useGasCoin: true\n })\n\n const vSuiCoin = await this.stakePTB(tx, mergedCoin)\n\n tx.transferObjects([vSuiCoin], this.walletClient.address)\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('volo:stake-success', {\n suiAmount\n })\n\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Unstake vSUI tokens to receive SUI tokens\n *\n * @param vSuiAmount - Amount of vSUI to unstake (in MIST units)\n * @param options - Optional parameters including dryRun flag\n * @returns Transaction response or dry run response\n * @throws Error if wallet client not found or unstake amount is too low\n */\n async unstake<T extends boolean = false>(\n vSuiAmount: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n if (vSuiAmount < 1e9) {\n throw new Error('Unstake amount should >= 1vSui')\n }\n\n await this.walletClient.module('balance').waitForUpdate()\n\n const tx = new Transaction()\n\n const vSuiBalance = this.walletClient\n .module('balance')\n .portfolio.getBalance(this.config.coinType)\n\n const mergedCoin = mergeCoinsPTB(tx, vSuiBalance.coins, {\n balance: vSuiAmount\n })\n\n const suiCoin = await this.unstakePTB(tx, mergedCoin)\n\n tx.transferObjects([suiCoin], this.walletClient.address)\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('volo:unstake-success', {\n vSuiAmount\n })\n\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n}\n","/**\n * Swap Module Implementation\n *\n * This module provides DEX swapping functionality for the wallet client.\n * It integrates with the Astros aggregator to find the best swap routes\n * and execute trades across multiple decentralized exchanges.\n *\n * @module SwapModule\n */\n\nimport {\n buildSwapPTBFromQuote,\n getQuote,\n Dex,\n FeeOption,\n generateRefId,\n Quote\n} from '@naviprotocol/astros-aggregator-sdk'\nimport { Transaction } from '@mysten/sui/transactions'\nimport { fromBase64 } from '@mysten/sui/utils'\nimport { Module } from '../module'\nimport { isSuccessfulTransaction } from '../../transaction-result'\nimport type { NaviWalletTransactionResult } from '../../types'\nimport BigNumber from 'bignumber.js'\nimport { mergeCoinsPTB, type NaviSdkServiceOptions } from '@naviprotocol/lending'\nimport { executeAuction } from 'shio-sdk'\nimport {\n defaultTransactionResponseOptions,\n mergeTransactionResponseOptions,\n normalizeTransactionResult\n} from '../../transaction-result'\n\n/**\n * Configuration options for the swap module\n */\nexport interface SwapModuleConfig {\n /** API key for aggregator access */\n apiKey: string\n /** Base URL for the aggregator API */\n baseUrl: string\n /** List of DEXes to use for routing */\n dexList: Dex[]\n /** Maximum routing depth for finding optimal paths */\n depth: number\n /** Service fee configuration */\n serviceFee: FeeOption | undefined\n /** Environment setting */\n env: 'dev' | 'prod'\n /** Optional NAVI service endpoint overrides. */\n services?: NaviSdkServiceOptions\n}\n\n/**\n * Events emitted by the swap module\n */\nexport type Events = {\n /** Emitted when a swap is successfully completed */\n 'swap:swap-success': {\n /** Source coin type */\n fromCoinType: string\n /** Target coin type */\n toCoinType: string\n /** Input amount */\n fromAmount: number\n /** Applied slippage tolerance */\n slippage: number\n /** Output amount received */\n toAmount: number\n }\n}\n\nfunction transactionIncludeOptions() {\n const merged = mergeTransactionResponseOptions(defaultTransactionResponseOptions)\n return {\n effects: merged.showEffects,\n events: merged.showEvents,\n balanceChanges: merged.showBalanceChanges,\n objectTypes: merged.showObjectChanges\n }\n}\n\nfunction getCoreExecutor(client: unknown) {\n return (client as { core?: unknown }).core as\n | {\n executeTransaction?(options: any): Promise<any>\n }\n | undefined\n}\n\n/**\n * DEX swapping module for wallet operations\n *\n * This module provides functionality for:\n * - Getting swap quotes from multiple DEXes\n * - Executing swaps with slippage protection\n * - Managing swap transactions and events\n * - Integrating with the balance module for coin management\n */\nexport class SwapModule extends Module<SwapModuleConfig, Events> {\n /** Module name identifier */\n readonly name = 'swap'\n\n /** Default configuration values */\n readonly defaultConfig: SwapModuleConfig = {\n apiKey: '',\n baseUrl: 'https://open-aggregator-api.naviprotocol.io/find_routes',\n dexList: [],\n depth: 3,\n serviceFee: undefined,\n env: 'prod'\n }\n\n /**\n * Gets the referral ID for this swap module\n *\n * @returns Referral ID if API key is configured, otherwise 0\n */\n get referral() {\n return this.config.apiKey ? generateRefId(this.config.apiKey) : 0\n }\n\n /**\n * Get the swap options\n * @returns The swap options\n */\n get swapOptions() {\n return {\n baseUrl: this.config.baseUrl,\n dexList: this.config.dexList,\n depth: this.config.depth,\n serviceFee: this.config.serviceFee,\n services: this.config.services ?? this.walletClient?.clientBundle.services\n }\n }\n\n /**\n * Get a quote for a swap\n * @param fromCoinType - The type of the coin being swapped from\n * @param toCoinType - The type of the coin being swapped to\n * @param fromAmount - The amount of the coin being swapped from\n * @returns A promise that resolves with the quote\n */\n async getQuote(fromCoinType: string, toCoinType: string, fromAmount: number) {\n return getQuote(fromCoinType, toCoinType, fromAmount, this.config.apiKey, this.swapOptions)\n }\n\n /**\n * Builds a swap transaction from a quote\n * @param tx - The transaction to build the swap from\n * @param quote - The quote to build the swap from\n * @param fromCoin - The coin to swap from\n * @param slippage - The slippage tolerance\n * @returns The swap transaction\n */\n async buildSwapPTBFromQuote(tx: Transaction, quote: Quote, fromCoin: any, slippage: number) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n const minAmountOut = new BigNumber(quote.amount_out).multipliedBy(1 - slippage).toFixed(0)\n return await buildSwapPTBFromQuote(\n this.walletClient.address,\n tx,\n Number(minAmountOut),\n fromCoin as any,\n quote,\n this.referral,\n false,\n this.config.apiKey,\n this.swapOptions\n )\n }\n\n /**\n * Executes a swap between two coin types\n *\n * This method performs a complete swap operation including:\n * - Balance validation\n * - Quote retrieval from aggregator\n * - Transaction building with slippage protection\n * - Transaction execution\n * - Event emission on success\n *\n * @param fromCoinType - Source coin type\n * @param toCoinType - Target coin type\n * @param fromAmount - Amount to swap\n * @param slippage - Slippage tolerance (0-1)\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n async swap<T extends boolean = false>(\n fromCoinType: string,\n toCoinType: string,\n fromAmount: number,\n slippage: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Wait for latest balance update\n await this.walletClient.module('balance').waitForUpdate()\n\n // Get current balance for the source coin\n const fromCoinBalance = this.walletClient.module('balance').portfolio.getBalance(fromCoinType)\n\n // Build transaction\n const tx = new Transaction()\n\n // Merge coins for the swap input\n const fromCoin = mergeCoinsPTB(tx, fromCoinBalance.coins, {\n balance: fromAmount,\n useGasCoin: true\n })\n\n // Get quote from aggregator\n const quote = await this.getQuote(fromCoinType, toCoinType, fromAmount)\n\n // Build swap transaction from quote\n const coinOut = await this.buildSwapPTBFromQuote(tx, quote, fromCoin, slippage)\n\n // Transfer output coins to wallet\n tx.transferObjects([coinOut], this.walletClient.address)\n\n // Set sender address\n tx.setSender(this.walletClient.address)\n\n if (options?.dryRun) {\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: true\n })\n return result as any\n }\n\n const builtTx = await tx.build({\n client: this.walletClient.client as any\n })\n\n const signed = await this.walletClient.signer.signTransaction(builtTx)\n const signatures = [signed.signature]\n\n try {\n await executeAuction(signed.bytes, signatures)\n } catch (e) {\n console.error(e)\n }\n\n const core = getCoreExecutor(this.walletClient.client)\n const result =\n typeof core?.executeTransaction === 'function'\n ? await core.executeTransaction({\n transaction: fromBase64(signed.bytes),\n signatures,\n include: transactionIncludeOptions()\n })\n : await (() => {\n const legacyJsonRpc = this.walletClient.clientBundle.legacyJsonRpc\n if (!legacyJsonRpc) {\n throw new Error(\n 'Swap execution requires core.executeTransaction or an explicit legacyJsonRpc client'\n )\n }\n return legacyJsonRpc.executeTransactionBlock({\n transactionBlock: signed!.bytes,\n signature: signatures,\n options: defaultTransactionResponseOptions\n })\n })()\n\n const normalizedResult = normalizeTransactionResult('execute', result)\n\n if (isSuccessfulTransaction(normalizedResult)) {\n // Find slippage event to get actual output amount\n const slippageEvent = normalizedResult.events?.find((event) => {\n return event.type?.includes('::slippage::SwapEvent')\n })\n\n if (slippageEvent) {\n // Emit swap success event with actual amounts\n this.emit('swap:swap-success', {\n fromCoinType,\n toCoinType,\n fromAmount,\n slippage,\n toAmount: Number((slippageEvent.parsedJson as any).amount_out)\n })\n }\n\n // Update balance portfolio after successful swap\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return normalizedResult as any\n }\n}\n","/**\n * Haedal Staking Module\n *\n * This module provides staking and unstaking functionality for the Haedal protocol.\n * It allows users to stake SUI for haSUI and unstake haSUI back to SUI, and fetches APY stats.\n *\n * @module HaedalModule\n */\n\nimport { isSuccessfulTransaction } from '../../transaction-result'\nimport {\n CoinObject,\n buildNaviOpenApiUrl,\n mergeCoinsPTB,\n mergeServiceHeaders,\n parseTxValue,\n resolveNaviOpenApiEndpoint,\n withCache,\n withSingleton,\n type NaviSdkServiceOptions\n} from '@naviprotocol/lending'\nimport { Transaction } from '@mysten/sui/transactions'\nimport { Module } from '../module'\nimport type { NaviWalletTransactionResult } from '../../types'\n\n/**\n * Configuration for the Haedal module\n */\nexport interface HaedalModuleConfig {\n /** Haedal package ID on Sui */\n packageId: string\n /** Haedal config object ID */\n configId: string\n /** haSUI coin type */\n coinType: string\n /** Optional NAVI service endpoint overrides. */\n services?: NaviSdkServiceOptions\n}\n\nexport type HaedalApyOptions = {\n services?: NaviSdkServiceOptions\n}\n\n/**\n * Events emitted by the Haedal module\n */\nexport type Events = {\n /** Emitted when staking SUI is successful */\n 'haedal:stake-success': {\n suiAmount: number\n }\n /** Emitted when unstaking haSUI is successful */\n 'haedal:unstake-success': {\n haSUIAmount: number\n }\n}\n\n/**\n * Haedal staking/unstaking module for wallet client\n */\nexport class HaedalModule extends Module<HaedalModuleConfig, Events> {\n /** Module name identifier */\n readonly name = 'haedal'\n /** Default configuration values */\n readonly defaultConfig: HaedalModuleConfig = {\n packageId: '0x19e6ea7f5ced4f090e20da794cc80349a03e638940ddb95155a4e301f5f4967c',\n configId: '0x47b224762220393057ebf4f70501b6e657c3e56684737568439a04f80849b2ca',\n coinType: '0xbde4ba4c2e274a60ce15c1cfff9e5c42e41654ac8b6d906a57efa4bd3c29f47d::hasui::HASUI'\n }\n\n /**\n * Fetches the current APY for Haedal staking\n *\n * @returns Current APY of haSUI\n */\n private getApyCached = withCache(\n withSingleton(async (options?: HaedalApyOptions) => {\n const serviceOptions = { services: options?.services }\n const endpoint = resolveNaviOpenApiEndpoint(serviceOptions)\n const resp: {\n data: {\n apy: number\n }\n } = await fetch(buildNaviOpenApiUrl('/haedal/stats', serviceOptions), {\n headers: mergeServiceHeaders({}, endpoint)\n }).then((res) => res.json())\n\n return resp.data.apy\n })\n )\n\n getApy(options?: HaedalApyOptions) {\n return this.getApyCached({\n services: options?.services ?? this.config.services\n })\n }\n\n /**\n * Builds a transaction block for staking SUI to haSUI\n *\n * @param tx - Transaction to add staking operation to\n * @param suiCoin - Sui coin object to stake\n * @returns haSUI coin object\n */\n async stakePTB(tx: Transaction, suiCoin: CoinObject) {\n const [coin] = tx.moveCall({\n target: `${this.config.packageId}::staking::request_stake_coin`,\n arguments: [\n tx.object('0x05'),\n tx.object(this.config.configId),\n parseTxValue(suiCoin, tx.object),\n tx.pure.address('0x0000000000000000000000000000000000000000000000000000000000000000')\n ],\n typeArguments: []\n })\n return coin\n }\n\n /**\n * Builds a transaction block for unstaking haSUI to SUI\n *\n * @param tx - Transaction to add unstaking operation to\n * @param haSUICoin - haSUI coin object to unstake\n * @returns SUI coin object\n */\n async unstakePTB(tx: Transaction, haSUICoin: CoinObject) {\n const [coin] = tx.moveCall({\n target: `${this.config.packageId}::staking::request_unstake_instant_coin`,\n arguments: [\n tx.object('0x05'),\n tx.object(this.config.configId),\n parseTxValue(haSUICoin, tx.object)\n ],\n typeArguments: []\n })\n return coin\n }\n\n /**\n * Stake SUI for haSUI\n *\n * @param suiAmount - Amount of SUI to stake\n * @param options Optional dry run\n */\n async stake<T extends boolean = false>(\n suiAmount: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const tx = new Transaction()\n await this.walletClient.module('balance').waitForUpdate()\n const suiBalance = this.walletClient.module('balance').portfolio.getBalance('0x2::sui::SUI')\n const mergedCoin = mergeCoinsPTB(tx, suiBalance.coins, {\n balance: suiAmount,\n useGasCoin: true\n })\n const haSUICoin = await this.stakePTB(tx, mergedCoin)\n tx.transferObjects([haSUICoin], this.walletClient.address)\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('haedal:stake-success', { suiAmount })\n this.walletClient.module('balance').updatePortfolio()\n }\n return result as any\n }\n\n /**\n * Unstake haSUI for SUI\n *\n * @param haSUIAmount - Amount of haSUI to unstake\n * @param options Optional dry run\n */\n async unstake<T extends boolean = false>(\n haSUIAmount: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n await this.walletClient.module('balance').waitForUpdate()\n const tx = new Transaction()\n const haSuiBalance = this.walletClient\n .module('balance')\n .portfolio.getBalance(this.config.coinType)\n const mergedCoin = mergeCoinsPTB(tx, haSuiBalance.coins, {\n balance: haSUIAmount\n })\n const suiCoin = await this.unstakePTB(tx, mergedCoin)\n tx.transferObjects([suiCoin], this.walletClient.address)\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('haedal:unstake-success', { haSUIAmount })\n this.walletClient.module('balance').updatePortfolio()\n }\n return result as any\n }\n}\n","/**\n * Wallet Client Modules - Main Index\n *\n * This module serves as the central registry for all wallet client modules.\n * It imports and exports all available modules (balance, lending, volo, swap, haedal)\n * and provides type definitions for module management.\n *\n * @module WalletClientModules\n */\n\nimport { BalanceModule, Events as BalanceEvents } from './balanceModule'\nimport { LendingModule, Events as LendingEvents } from './lendingModule'\nimport { VoloModule, Events as VoloEvents } from './voloModule'\nimport { SwapModule, Events as SwapEvents } from './swapModule'\nimport { HaedalModule, Events as HaedalEvents } from './haedalModule'\n\n/**\n * Registry of all available wallet client modules\n *\n * This object contains instances of all modules that provide different\n * functionalities for the wallet client (balance management, lending,\n * volo operations, swapping, and haedal integration).\n */\nexport const modules = {\n /** Balance management module */\n balance: new BalanceModule(),\n /** Lending protocol module */\n lending: new LendingModule(),\n /** Volo protocol module */\n volo: new VoloModule(),\n /** DEX swapping module */\n swap: new SwapModule(),\n /** Haedal protocol module */\n haedal: new HaedalModule()\n}\n\n/**\n * Union type of all module events\n *\n * This type combines all event types from different modules,\n * allowing the wallet client to handle events from any module.\n */\nexport type ModuleEvents = BalanceEvents & LendingEvents & VoloEvents & SwapEvents & HaedalEvents\n\n/**\n * Type for module names\n *\n * This type represents the keys of the modules object,\n * allowing type-safe access to specific modules.\n */\nexport type ModuleName = keyof typeof modules\n\n/**\n * Type for module instances\n *\n * This type represents any module instance from the modules registry.\n */\nexport type Module = (typeof modules)[ModuleName]\n\n/**\n * Type for module configurations\n *\n * This type represents the configuration type of any module,\n * extracted from the defaultConfig property.\n */\nexport type ModuleConfig = Module['defaultConfig']\n","/**\n * Wallet Client - Core Client Implementation\n *\n * This module provides the main wallet client for interacting with the Sui blockchain.\n * It manages transaction signing, module integration, and provides a unified interface\n * for various DeFi operations including swaps, lending, and balance management.\n *\n * @module WalletClient\n */\n\nimport { Signer } from '@mysten/sui/cryptography'\nimport mitt, { Emitter } from 'mitt'\nimport { Module, ModuleConfig } from './modules/module'\nimport { modules, ModuleName, ModuleEvents } from './modules'\nimport { Transaction } from '@mysten/sui/transactions'\nimport { fromBase64 } from '@mysten/sui/utils'\nimport {\n DryRunOptions,\n NaviTransactionExecutionOptions,\n NaviWalletTransactionResult\n} from './types'\nimport { mergeTransactionResponseOptions, normalizeTransactionResult } from './transaction-result'\nimport {\n createNaviLegacyJsonRpcClient,\n createNaviSuiClientBundle,\n type NaviCoreClient,\n type NaviJsonRpcCompatClient,\n type NaviSdkServiceOptions,\n type NaviSuiClientBundle,\n type NaviSuiClientOptions,\n type NaviSuiLegacyJsonRpcOptions,\n type NaviSuiNetwork,\n PUBLIC_MAINNET_GRPC_URL\n} from '@naviprotocol/lending'\n\n/**\n * Extracts the configuration type from a module\n */\ntype ExtractModuleConfig<T> = T extends Module<infer TConfig, any> ? TConfig : never\n\n/**\n * User configuration type for all modules\n */\nexport type UserConfigs = {\n [K in ModuleName]: Partial<ExtractModuleConfig<(typeof modules)[K]>>\n}\n\n/**\n * Options for initializing the wallet client\n */\nexport type WalletClientOptions = {\n /** The signer for transaction signing */\n signer: Signer\n /** Optional module-specific configurations */\n configs?: Partial<UserConfigs>\n /**\n * Sui v2 client configuration. Optional (v1 parity): when omitted, a public\n * mainnet gRPC client is used — fine for development and low volume;\n * production should pass its own client (private endpoint / auth headers).\n */\n client?: NaviSuiClientOptions | WalletLegacyJsonRpcClientOptions\n}\n\nexport type WalletLegacyJsonRpcClientOptions = {\n network?: NaviSuiNetwork\n /**\n * @deprecated JSON-RPC is a short-lived compatibility transport. New paths must use `grpc`.\n */\n legacyJsonRpc: NaviSuiLegacyJsonRpcOptions\n services?: NaviSdkServiceOptions\n}\n\nfunction transactionIncludeOptions(options?: NaviTransactionExecutionOptions['options']) {\n const merged = mergeTransactionResponseOptions(options)\n return {\n effects: merged.showEffects,\n events: merged.showEvents,\n balanceChanges: merged.showBalanceChanges,\n objectTypes: merged.showObjectChanges\n }\n}\n\nfunction getCoreTransactionClient(client: unknown) {\n return (client as { core?: unknown }).core as\n | {\n simulateTransaction?(options: any): Promise<any>\n executeTransaction?(options: any): Promise<any>\n }\n | undefined\n}\n\nfunction isNaviSuiClientOptions(\n options: NaviSuiClientOptions | WalletLegacyJsonRpcClientOptions\n): options is NaviSuiClientOptions {\n return 'grpc' in options\n}\n\nfunction createWalletClientBundle(\n options: NaviSuiClientOptions | WalletLegacyJsonRpcClientOptions\n): NaviSuiClientBundle {\n if (isNaviSuiClientOptions(options)) {\n return createNaviSuiClientBundle(options)\n }\n const network = options.network ?? 'mainnet'\n const legacyJsonRpc = createNaviLegacyJsonRpcClient(network, options.legacyJsonRpc)\n return {\n network,\n coreClient: legacyJsonRpc,\n grpc: legacyJsonRpc,\n legacyJsonRpc,\n services: options.services\n }\n}\n\n/**\n * Main wallet client class that provides unified access to blockchain operations\n *\n * This class integrates various modules (swap, lending, balance, etc.) and provides\n * a consistent interface for interacting with the Sui blockchain. It handles\n * transaction signing, module management, and event emission.\n */\nexport class WalletClient {\n /** The signer instance for transaction signing */\n public readonly signer: Signer\n\n /** Available modules for different functionalities */\n private readonly modules = modules\n\n /** User-provided module configurations */\n private readonly userConfigs: Partial<UserConfigs> = {}\n\n /** Event emitter for module events */\n public readonly events: Emitter<ModuleEvents> = mitt()\n\n /** The Sui client instance */\n public readonly client: NaviCoreClient & Partial<NaviJsonRpcCompatClient>\n\n /** Normalized transport bundle for modules that need transport-specific clients. */\n public readonly clientBundle: NaviSuiClientBundle\n\n /** URL used by the default JSON-RPC client, when available. */\n public readonly clientUrl?: string\n\n public get lending() {\n return this.modules.lending\n }\n\n public get balance() {\n return this.modules.balance\n }\n\n public get volo() {\n return this.modules.volo\n }\n\n public get swap() {\n return this.modules.swap\n }\n\n public get haedal() {\n return this.modules.haedal\n }\n\n /**\n * Creates a new wallet client instance\n * @param options - Configuration options for the wallet client\n */\n constructor(options: WalletClientOptions) {\n // v1 parity: default to the public mainnet node when no client is given.\n const clientOptions = options.client ?? {\n network: 'mainnet' as const,\n grpc: { url: PUBLIC_MAINNET_GRPC_URL }\n }\n this.clientBundle = createWalletClientBundle(clientOptions)\n this.client = this.clientBundle.coreClient as NaviCoreClient & Partial<NaviJsonRpcCompatClient>\n this.clientUrl =\n 'grpc' in clientOptions\n ? clientOptions.legacyJsonRpc && 'url' in clientOptions.legacyJsonRpc\n ? clientOptions.legacyJsonRpc.url\n : undefined\n : 'url' in clientOptions.legacyJsonRpc\n ? clientOptions.legacyJsonRpc.url\n : undefined\n this.signer = options.signer\n this.userConfigs = options.configs || {}\n\n // Install all modules and validate their names\n Object.entries(this.modules).forEach(([name, module]) => {\n if (name !== module.name) {\n throw new Error(`Module name ${name} does not match module name ${module.name}`)\n }\n module.install(this)\n })\n }\n\n /**\n * Signs and executes a transaction block\n * @param options - Transaction execution options including dry run support\n * @returns Promise with transaction execution result\n */\n async signExecuteTransaction(\n options: {\n transaction: Uint8Array | Transaction\n } & NaviTransactionExecutionOptions &\n Partial<DryRunOptions>\n ): Promise<NaviWalletTransactionResult<boolean>> {\n const { dryRun = false, ...rest } = options\n\n if (dryRun) {\n const core = getCoreTransactionClient(this.client)\n if (typeof core?.simulateTransaction === 'function') {\n if (options.transaction instanceof Transaction) {\n options.transaction.setSenderIfNotSet(this.address)\n }\n const result = await core.simulateTransaction({\n transaction: options.transaction,\n include: transactionIncludeOptions(rest.options)\n })\n return normalizeTransactionResult('dryRun', result)\n }\n\n const legacyJsonRpc = this.clientBundle.legacyJsonRpc\n if (!legacyJsonRpc) {\n throw new Error(\n 'WalletClient dry-run requires core.simulateTransaction or an explicit legacyJsonRpc client'\n )\n }\n // Handle dry run mode for transaction simulation\n let txBytes\n if (options.transaction instanceof Transaction) {\n options.transaction.setSenderIfNotSet(this.address)\n txBytes = await options.transaction.build({\n client: legacyJsonRpc as any\n })\n } else {\n txBytes = options.transaction\n }\n const result = await legacyJsonRpc.dryRunTransactionBlock({\n transactionBlock: txBytes\n })\n return normalizeTransactionResult('dryRun', result)\n }\n\n const core = getCoreTransactionClient(this.client)\n if (typeof core?.executeTransaction === 'function') {\n let txBytes: Uint8Array\n if (options.transaction instanceof Transaction) {\n options.transaction.setSenderIfNotSet(this.address)\n txBytes = await options.transaction.build({\n client: this.client as any\n })\n } else {\n txBytes = options.transaction\n }\n const signed = await this.signer.signTransaction(txBytes)\n const result = await core.executeTransaction({\n transaction: fromBase64(signed.bytes),\n signatures: [signed.signature],\n include: transactionIncludeOptions(rest.options)\n })\n return normalizeTransactionResult('execute', result)\n }\n\n const legacyJsonRpc = this.clientBundle.legacyJsonRpc\n if (!legacyJsonRpc) {\n throw new Error(\n 'WalletClient execution requires core.executeTransaction or an explicit legacyJsonRpc client'\n )\n }\n // Execute the actual transaction\n const result = await legacyJsonRpc.signAndExecuteTransaction({\n ...rest,\n options: mergeTransactionResponseOptions(rest.options),\n signer: this.signer\n } as any)\n return normalizeTransactionResult('execute', result)\n }\n\n /**\n * Gets the wallet address from the signer's public key\n * @returns The wallet address as a string\n */\n get address(): string {\n return this.signer.getPublicKey().toSuiAddress()\n }\n\n /**\n * Gets a specific module by name\n * @param name - The name of the module to retrieve\n * @returns The requested module instance\n */\n module<TName extends ModuleName>(name: TName): (typeof modules)[TName] {\n return this.modules[name]\n }\n\n /**\n * Gets the configuration for a specific module\n * @param name - The name of the module\n * @returns The merged configuration (default + user config)\n */\n config<TName extends ModuleName>(name: TName): ExtractModuleConfig<(typeof modules)[TName]> {\n const mergedConfig = {\n ...this.modules[name].defaultConfig,\n ...this.userConfigs[name]\n }\n return mergedConfig as ExtractModuleConfig<(typeof modules)[TName]>\n }\n\n /**\n * Checks if a module is available\n * @param name - The name of the module to check\n * @returns True if the module exists, false otherwise\n */\n hasModule(name: ModuleName): boolean {\n return name in this.modules\n }\n}\n\nexport type { ModuleConfig }\n","/**\n * Watch Signer Implementation\n *\n * This module provides a watch-only signer implementation for the wallet client.\n * It allows users to view wallet information and transaction details without\n * the ability to sign transactions, useful for read-only operations.\n *\n * @module WatchSigner\n */\n\nimport { Signer } from '@mysten/sui/cryptography'\nimport { Transaction } from '@mysten/sui/transactions'\nimport type { PublicKey, SignatureScheme, SignatureWithBytes } from '@mysten/sui/cryptography'\nimport type { NaviWalletExecutionClient } from './types'\n\n/**\n * Minimal mock public key used by watch-only / web signers. It exposes the\n * address but cannot perform real cryptography; typed as `PublicKey` for the\n * `Signer` contract via a cast since it is intentionally incomplete.\n */\nfunction createMockPublicKey(address: string): PublicKey {\n return {\n toSuiAddress: () => address,\n toBytes: () => new Uint8Array(32),\n toRawBytes: () => new Uint8Array(32),\n flag: () => 0,\n verify: async () => false\n } as unknown as PublicKey\n}\n\n/**\n * Options for signing and executing transactions\n */\ninterface SignAndExecuteOptions {\n /** Transaction to sign and execute */\n transaction: Transaction\n /** Sui client instance */\n client: NaviWalletExecutionClient\n}\n\n/**\n * Watch-only signer implementation\n *\n * This signer provides read-only access to wallet information without\n * the ability to sign transactions. It's useful for viewing wallet\n * balances, transaction history, and other non-signing operations.\n *\n * Note: This signer cannot actually sign transactions and will return\n * empty signatures or throw errors when signing is attempted.\n */\nexport class WatchSigner extends Signer {\n /** The wallet address this signer represents */\n private address: string\n\n /**\n * Creates a new watch-only signer\n *\n * @param address - The wallet address to watch\n */\n constructor(address: string) {\n super()\n this.address = address\n }\n\n /**\n * Signs transaction bytes (not implemented for watch-only mode)\n *\n * This method is required by the Signer interface but cannot\n * actually sign transactions in watch-only mode.\n *\n * @param bytes - Transaction bytes to sign\n * @returns Promise<Uint8Array> - Empty signature (not valid)\n */\n override async sign(bytes: Uint8Array): Promise<Uint8Array<ArrayBuffer>> {\n return Promise.resolve(new Uint8Array(0))\n }\n\n /**\n * Gets the public key information for this signer\n *\n * Returns a mock public key object that provides the wallet address\n * but cannot be used for actual cryptographic operations.\n */\n getPublicKey(): PublicKey {\n return createMockPublicKey(this.address)\n }\n\n /**\n * Gets the key scheme for this signer\n *\n * @returns Key scheme (ed25519 for compatibility)\n */\n getKeyScheme(): SignatureScheme {\n return 'ED25519'\n }\n\n /**\n * Signs and executes a transaction (not implemented for watch-only mode)\n *\n * This method is required by the Signer interface but cannot\n * actually sign and execute transactions in watch-only mode.\n */\n override async signAndExecuteTransaction(\n options: SignAndExecuteOptions\n ): ReturnType<Signer['signAndExecuteTransaction']> {\n return {} as Awaited<ReturnType<Signer['signAndExecuteTransaction']>>\n }\n}\n\n/**\n * Web signer implementation\n *\n * For use in browser environments\n */\nexport abstract class WebSigner extends Signer {\n private address: string\n\n /**\n * Creates a new watch-only signer\n *\n * @param address - The wallet address to watch\n */\n constructor(address: string) {\n super()\n this.address = address\n }\n\n /**\n * Signs transaction bytes (not implemented for watch-only mode)\n *\n * This method is required by the Signer interface but cannot\n * actually sign transactions in watch-only mode.\n *\n * @param bytes - Transaction bytes to sign\n * @returns Promise<Uint8Array> - Empty signature (not valid)\n */\n override async sign(bytes: Uint8Array): Promise<Uint8Array<ArrayBuffer>> {\n return Promise.resolve(new Uint8Array(0))\n }\n\n /**\n * Gets the public key information for this signer\n *\n * Returns a mock public key object that provides the wallet address\n * but cannot be used for actual cryptographic operations.\n */\n getPublicKey(): PublicKey {\n return createMockPublicKey(this.address)\n }\n\n /**\n * Gets the key scheme for this signer\n *\n * @returns Key scheme (ed25519 for compatibility)\n */\n getKeyScheme(): SignatureScheme {\n return 'ED25519'\n }\n\n abstract signPersonalMessage(bytes: Uint8Array): Promise<SignatureWithBytes>\n\n abstract signTransaction(bytes: Uint8Array): Promise<SignatureWithBytes>\n}\n"],"names":["Module","event","data","walletClient","UserPortfolio","coins","balances","item","normalizedCoinType","normalizeStructTag","existPofolio","BigNumber","coinType","newBalances","userPortfolio","BalanceModule","withSingleton","getCoins","recipient","amount","options","recipients","amounts","coinBalance","totalAmount","acc","curr","tx","Transaction","mergedCoin","mergeCoinsPTB","address","index","object","objects","error","resolve","defaultTransactionResponseOptions","mergeTransactionResponseOptions","isSuccessfulTransaction","result","status","normalizeTransactionResult","kind","raw","unwrapTransactionResult","effects","normalizeEffects","normalizeEvents","transaction","isRecord","failedTransaction","events","value","migrateBetweenSupplyPTB","from","to","fromPool","toPool","lendingState","protocolName","fromProtocol","fromPoolLending","slippage","formAmount","priceFeeds","getPriceFeeds","pools","updateOraclePricesPTB","filterPriceFeeds","withdrawnFromCoin","depositCoinPTB","toPoolFlashloanAsset","getFlashLoanAsset","quote","shouldSwapAmount","minAmountOut","borrowAmountInMin","flashloanBalance","receipt","flashloanPTB","flashCoin","swappedToCoin","buildSwapPTBFromQuote","repayBalance","leftBalance","repayFlashLoanPTB","extraCoin","migrateBetweenBorrowPTB","borrowRate","fromPoolFlashloanAsset","flashloanRepayAmount","minSwapAmount","fromQuote","rate","shouldBorrowAmount","toQuote","borrowCoin","borrowCoinPTB","swappedFromCoin","migrateBalanceToSupplyPTB","balance","depositCoin","NaviProtocol","pool","userPosition","position","supplyBalance","borrowBalance","coinObject","withdrawCoinPTB","repayCoinPTB","LendingModule","services","name","p","getPools","identifier","getPool","coin","getHealthFactor","payIdentifier","payAmount","collateralIdentifier","liquidationAddress","payPool","collateralPool","payCoinBalance","collateralBalance","remainDebtBalance","liquidatePTB","collateralCoin","leftDebtCoin","getUserAvailableLendingRewards","getUserClaimedRewardHistory","rewards","claimLendingRewardsPTB","feeds","filteredFeeds","getLendingState","cap","createAccountCapPTB","protocols","SuilendProtocol","VoloModule","withCache","serviceOptions","endpoint","resolveNaviOpenApiEndpoint","buildNaviOpenApiUrl","mergeServiceHeaders","res","suiCoin","parseTxValue","vSuiCoin","suiAmount","suiBalance","vSuiAmount","vSuiBalance","transactionIncludeOptions","merged","getCoreExecutor","client","SwapModule","generateRefId","fromCoinType","toCoinType","fromAmount","getQuote","fromCoin","fromCoinBalance","coinOut","builtTx","signed","signatures","executeAuction","e","core","fromBase64","legacyJsonRpc","normalizedResult","slippageEvent","HaedalModule","haSUICoin","haSUIAmount","haSuiBalance","modules","getCoreTransactionClient","isNaviSuiClientOptions","createWalletClientBundle","createNaviSuiClientBundle","network","createNaviLegacyJsonRpcClient","WalletClient","mitt","clientOptions","PUBLIC_MAINNET_GRPC_URL","module","dryRun","rest","txBytes","createMockPublicKey","WatchSigner","Signer","bytes","WebSigner"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/modules/module.ts","../src/modules/balanceModule/portfolio.ts","../src/modules/balanceModule/index.ts","../src/transaction-result.ts","../src/modules/lendingModule/migrate.ts","../src/modules/lendingModule/protocols/navi.ts","../src/modules/lendingModule/index.ts","../src/modules/voloModule/index.ts","../src/modules/swapModule/index.ts","../src/modules/haedalModule/index.ts","../src/modules/index.ts","../src/client.ts","../src/signer.ts"],"sourcesContent":["/**\n * Wallet Client Module System\n *\n * This module defines the base architecture for the wallet client's modular system.\n * It provides the foundation for different functionality modules like swap, lending,\n * balance management, and other DeFi operations.\n *\n * @module WalletClientModule\n */\n\nimport { WalletClient } from '../client'\nimport { ModuleName } from '.'\n\n/**\n * Base interface for module configuration\n *\n * All modules must implement this interface to define their configuration structure.\n */\nexport interface ModuleConfig {\n [key: string]: any\n}\n\n/**\n * Base interface for module events\n *\n * All modules must implement this interface to define their event structure.\n */\nexport type ModuleEvents = {\n [key: string]: any\n}\n\n/**\n * Abstract base class for all wallet client modules\n *\n * This class provides the foundation for modular functionality in the wallet client.\n * Each module (swap, lending, balance, etc.) extends this class to provide\n * specific functionality while maintaining a consistent interface.\n *\n * @template TConfig - The configuration type for this module\n * @template TEvents - The events type for this module\n */\nexport abstract class Module<TConfig extends ModuleConfig, TEvents extends ModuleEvents> {\n /** The unique name identifier for this module */\n abstract readonly name: string\n\n /** Default configuration values for this module */\n abstract readonly defaultConfig: TConfig\n\n /** Reference to the wallet client instance that owns this module */\n protected walletClient?: WalletClient\n\n /**\n * Gets the current configuration for this module\n *\n * This combines the default configuration with any user-provided overrides\n * from the wallet client configuration.\n *\n * @returns The merged configuration for this module\n */\n get config(): TConfig {\n return this.walletClient\n ? (this.walletClient.config(this.name as ModuleName) as unknown as TConfig)\n : this.defaultConfig\n }\n\n /**\n * Emits an event through the wallet client's event system\n *\n * @param event - The event name to emit\n * @param data - The event data to emit\n */\n emit(event: keyof TEvents, data: TEvents[keyof TEvents]) {\n this.walletClient?.events.emit(event as any, data)\n }\n\n /**\n * Installs this module into a wallet client\n *\n * This method is called by the wallet client during initialization\n * to establish the connection between the module and the client.\n *\n * @param walletClient - The wallet client instance to install into\n */\n install(walletClient: WalletClient): void {\n this.walletClient = walletClient\n }\n\n /**\n * Uninstalls this module from the wallet client\n *\n * This method removes the reference to the wallet client,\n * effectively disconnecting the module.\n */\n uninstall() {\n this.walletClient = undefined\n }\n}\n","/**\n * User Portfolio Management\n *\n * This module provides portfolio management functionality for tracking\n * user coin balances across different token types. It aggregates coin\n * objects by type and provides convenient methods for balance queries\n * and portfolio operations.\n *\n * @module UserPortfolio\n */\n\nimport type { CoinStruct } from '@mysten/sui/jsonRpc'\nimport { BigNumber } from 'bignumber.js'\nimport { normalizeStructTag } from '@mysten/sui/utils'\n\n/**\n * User portfolio for managing coin balances\n *\n * This class provides functionality to:\n * - Aggregate coins by type and calculate total balances\n * - Query balances for specific coin types\n * - Clone portfolio state for safe operations\n * - Normalize coin types for consistent comparison\n */\nexport class UserPortfolio {\n /** Mapping of coin types to their balance information */\n balances: { [key in string]: UserCoinBalance }\n\n /**\n * Creates a new user portfolio\n *\n * @param coins - Array of coin objects or existing portfolio to copy from\n * @param addressBalances - Optional map of normalized coin type to funds held\n * directly at the address level (v2 address balances). Coin objects only\n * account for `Coin<T>` objects, so this carries the balance that lives at\n * the address and is not represented by any object. Defaults to empty,\n * which preserves legacy coin-object-only behavior.\n */\n constructor(\n coins?: CoinStruct[] | UserPortfolio,\n addressBalances?: { [key in string]?: BigNumber.Value }\n ) {\n if (coins instanceof UserPortfolio) {\n // Copy from existing portfolio\n this.balances = JSON.parse(JSON.stringify(coins.balances))\n // JSON round-trips BigNumber to string, so rehydrate BigNumber fields.\n Object.values(this.balances).forEach((balance) => {\n balance.amount = BigNumber(balance.amount)\n balance.addressBalance = BigNumber(balance.addressBalance ?? 0)\n })\n } else {\n // Build portfolio from coin objects\n const balances: { [key in string]: UserCoinBalance } = {}\n\n coins?.forEach((item) => {\n if (!item.coinType || item.balance === undefined || item.balance === null) {\n return\n }\n // Normalize coin type for consistent key usage\n const normalizedCoinType = normalizeStructTag(item.coinType)\n let existPofolio = balances[normalizedCoinType]\n\n // Create new balance entry if it doesn't exist\n if (!existPofolio) {\n existPofolio = {\n coinType: normalizedCoinType,\n amount: BigNumber(0),\n addressBalance: BigNumber(0),\n coins: []\n }\n balances[normalizedCoinType] = existPofolio\n }\n\n // Add coin to balance and update total amount\n existPofolio.coins.push(item)\n existPofolio.amount = existPofolio.amount.plus(item.balance)\n })\n\n // Merge in address-level balances (v2). A coin type may have an address\n // balance without any coin objects, so create entries as needed.\n if (addressBalances) {\n Object.entries(addressBalances).forEach(([coinType, value]) => {\n if (value === undefined || value === null) {\n return\n }\n const normalizedCoinType = normalizeStructTag(coinType)\n let existPofolio = balances[normalizedCoinType]\n if (!existPofolio) {\n existPofolio = {\n coinType: normalizedCoinType,\n amount: BigNumber(0),\n addressBalance: BigNumber(0),\n coins: []\n }\n balances[normalizedCoinType] = existPofolio\n }\n existPofolio.addressBalance = BigNumber(value)\n })\n }\n\n this.balances = balances\n }\n }\n\n /**\n * Gets balance information for a specific coin type\n *\n * @param coinType - The coin type to query\n * @returns UserCoinBalance object with coin type, total amount, and coin objects\n */\n getBalance(coinType: string): UserCoinBalance {\n coinType = normalizeStructTag(coinType)\n return (\n this.balances[coinType] || {\n coinType,\n amount: BigNumber(0),\n addressBalance: BigNumber(0),\n coins: []\n }\n )\n }\n\n /**\n * Gets the combined total balance for a coin type: the sum of coin objects\n * (`amount`) plus funds held at the address level (`addressBalance`). Use\n * this for sufficiency checks; use `.amount` when you specifically need the\n * coin-object-only sum.\n *\n * @param coinType - The coin type to query\n * @returns BigNumber representing the combined total balance\n */\n combinedBalanceOf(coinType: string) {\n const balance = this.getBalance(coinType)\n return balance.amount.plus(balance.addressBalance ?? 0)\n }\n\n /**\n * Gets all coin types in the portfolio\n *\n * @returns Array of coin type strings\n */\n getCoinTypes() {\n return Object.values(this.balances).map((item) => {\n return item.coinType\n })\n }\n\n /**\n * Gets the total balance amount for a specific coin type\n *\n * @param coinType - The coin type to query\n * @returns BigNumber representing the total balance\n */\n balanceOf(coinType: string) {\n coinType = normalizeStructTag(coinType)\n const balance = this.getBalance(coinType)\n return balance?.amount || BigNumber(0)\n }\n\n /**\n * Creates a deep copy of the portfolio\n *\n * This method creates a completely independent copy of the portfolio\n * that can be modified without affecting the original.\n *\n * @returns New UserPortfolio instance with copied data\n */\n clone() {\n // Reuse the copy constructor, which deep-copies and rehydrates the\n // BigNumber fields (amount / addressBalance). Assigning JSON-parsed\n // balances directly would leave them as plain strings and break `.plus` /\n // `.toFixed` on the clone.\n return new UserPortfolio(this)\n }\n}\n\n/**\n * Balance information for a specific coin type\n *\n * This type represents the aggregated balance information for all\n * coins of a particular type in the user's portfolio.\n */\nexport type UserCoinBalance = {\n /** Normalized coin type string */\n coinType: string\n /** Total balance across all coin objects (`Coin<T>`) of this type */\n amount: BigNumber\n /**\n * Funds held directly at the address level (v2 address balances) for this\n * coin type. Not represented by any coin object. Defaults to `0`. The\n * combined spendable total is `amount + addressBalance`.\n */\n addressBalance: BigNumber\n /** Array of individual coin objects */\n coins: CoinStruct[]\n}\n","/**\n * Balance Module Implementation\n *\n * This module provides comprehensive balance management functionality for the wallet client.\n * It handles coin tracking, portfolio management, coin transfers, and automatic balance updates\n * through polling mechanisms.\n *\n * @module BalanceModule\n */\n\nimport { Module } from '../module'\nimport { getCoins, mergeCoinsPTB, withSingleton, listAddressBalances } from '@naviprotocol/lending'\nimport type { CoinStruct } from '@mysten/sui/jsonRpc'\nimport type { WalletClient } from '../../client'\nimport { UserPortfolio } from './portfolio'\nimport BigNumber from 'bignumber.js'\nimport { Transaction } from '@mysten/sui/transactions'\nimport type { NaviWalletTransactionResult } from '../../types'\nimport { normalizeStructTag } from '@mysten/sui/utils'\n\n/**\n * Configuration options for the balance module\n */\nexport interface BalanceModuleConfig {\n /** Interval in milliseconds for polling coin balances */\n coinPollingInterval: number\n /** Whether to disable coin polling */\n disableCoinPolling: boolean\n}\n\n/**\n * Events emitted by the balance module\n */\nexport type Events = {\n /** Emitted when the portfolio is updated with new balance information */\n 'balance:portfolio-updated': {}\n}\n\n/**\n * Balance management module for wallet operations\n *\n * This module provides functionality for:\n * - Tracking coin balances and portfolio information\n * - Sending coins to recipients\n * - Transferring objects\n * - Automatic balance updates through polling\n * - Portfolio management and balance queries\n */\nexport class BalanceModule extends Module<BalanceModuleConfig, Events> {\n /** Module name identifier */\n readonly name = 'balance'\n\n /** Default configuration values */\n readonly defaultConfig = {\n coinPollingInterval: 6000,\n disableCoinPolling: false\n }\n\n /**\n * Gets the current coin objects from the wallet\n *\n * @returns Array of coin objects owned by the wallet\n */\n public get coins() {\n return this._coins\n }\n\n /**\n * Gets the current portfolio information\n *\n * @returns UserPortfolio instance with current balance information\n */\n public get portfolio() {\n return this._portfolio\n }\n\n /**\n * Waits for the next portfolio update to complete\n *\n * @returns Promise that resolves when the portfolio is updated\n * @throws Error if no update promise is available\n */\n public async waitForUpdate() {\n if (!this._updatePromise) {\n throw new Error('Update promise not found')\n }\n return await this._updatePromise\n }\n\n /**\n * Sends a single coin to a recipient\n *\n * @param coinType - Type of coin to send\n * @param recipient - Recipient address\n * @param amount - Amount to send\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n public async sendCoin<T extends boolean = false>(\n coinType: string,\n recipient: string,\n amount: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n return this.sendCoinBatch(coinType, [recipient], [amount], options)\n }\n\n /**\n * Sends coins to multiple recipients in a single transaction\n *\n * @param coinType - Type of coin to send\n * @param recipients - Array of recipient addresses\n * @param amounts - Array of amounts to send (must match recipients length)\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n public async sendCoinBatch<T extends boolean = false>(\n coinType: string,\n recipients: string[],\n amounts: number[],\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n if (recipients.length !== amounts.length) {\n throw new Error('Recipients and amounts must have the same length')\n }\n\n // Wait for latest portfolio update\n await this.waitForUpdate()\n\n // Check if sufficient balance is available. SUI is funded from the gas coin\n // below (address balance is not spendable on that path), so its sufficiency\n // counts coin objects only; other coins can redeem the address balance via\n // mergeCoinsPTB, so they count the combined total.\n const coinBalance = this.portfolio.getBalance(coinType)\n const isSui = normalizeStructTag(coinType) === normalizeStructTag('0x2::sui::SUI')\n const spendable = isSui ? coinBalance.amount : this.portfolio.combinedBalanceOf(coinType)\n const totalAmount = amounts.reduce((acc, curr) => acc.plus(curr), BigNumber(0))\n if (spendable.lt(totalAmount)) {\n throw new Error('Insufficient balance')\n }\n\n // Build transaction\n const tx = new Transaction()\n\n if (isSui) {\n // SUI: split each share from the gas coin; the leftover stays on the gas\n // coin, so there is no dangling zero-balance result.\n const shares = tx.splitCoins(tx.gas, amounts)\n recipients.forEach((address, index) => {\n tx.transferObjects([shares[index]], address)\n })\n } else {\n // Non-SUI: mergeCoinsPTB returns a coin holding EXACTLY totalAmount. It may\n // be a redeem_funds result (address balance) with no owned object to\n // absorb leftover, so a plain splitCoins of every share would leave the\n // source at zero balance and unused (Coin has no `drop` ability → PTB\n // fails). Instead split the first n-1 shares and transfer the source coin\n // itself as the last share, fully consuming it.\n const mergedCoin = mergeCoinsPTB(tx, coinBalance.coins, {\n balance: totalAmount.toNumber(),\n addressBalance: coinBalance.addressBalance.toFixed(0),\n coinType\n })\n if (recipients.length === 1) {\n tx.transferObjects([mergedCoin], recipients[0])\n } else {\n const headShares = tx.splitCoins(mergedCoin, amounts.slice(0, -1))\n recipients.slice(0, -1).forEach((address, index) => {\n tx.transferObjects([headShares[index]], address)\n })\n tx.transferObjects([mergedCoin], recipients[recipients.length - 1])\n }\n }\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n return result as any\n }\n\n /**\n * Transfers a single object to a recipient\n *\n * @param object - Object ID to transfer\n * @param recipient - Recipient address\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n async transferObject<T extends boolean = false>(\n object: string,\n recipient: string,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n return this.transferObjectBatch([object], [recipient], options)\n }\n\n /**\n * Transfers multiple objects to their respective recipients in a single transaction\n *\n * Each object is transferred to its corresponding recipient by index\n * (first object → first recipient, second object → second recipient, etc.)\n *\n * @param objects - Object IDs to transfer\n * @param recipients - Recipient addresses (must match objects array length)\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n async transferObjectBatch<T extends boolean = false>(\n objects: string[],\n recipients: string[],\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n if (objects.length !== recipients.length) {\n throw new Error('Objects and recipients must have the same length')\n }\n\n // Wait for latest portfolio update\n await this.waitForUpdate()\n\n // Build transaction\n const tx = new Transaction()\n\n // Transfer objects to recipients\n objects.forEach((object, index) => {\n tx.transferObjects([tx.object(object)], recipients[index])\n })\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n return result as any\n }\n\n /**\n * Updates the portfolio with current coin information\n *\n * This function is wrapped with singleton behavior to prevent\n * concurrent updates and ensure data consistency.\n */\n updatePortfolio = withSingleton(async () => {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Fetch current coins from the wallet\n this._coins = await getCoins(this.walletClient.address, {\n client: this.walletClient.client\n })\n\n // Also fetch funds held at the address level (v2 address balances). Coin\n // objects only cover `Coin<T>` objects, so this map lets sufficiency checks\n // and coin selection see the full spendable total.\n const addressBalances = await this.getAddressBalanceMap()\n\n // Update portfolio with new coin data\n this._portfolio = new UserPortfolio(this._coins, addressBalances)\n\n // Emit portfolio update event\n this.emit('balance:portfolio-updated', {})\n })\n\n /**\n * Builds a map of coin type to address-level balance (v2 address balances).\n *\n * Feature-detects the v2 Core balance API on the injected client; when it is\n * unavailable (legacy JSON-RPC only), returns an empty map so the portfolio\n * falls back to coin-object-only behavior.\n *\n * @returns Map of normalized coin type to address balance (atomic units)\n */\n private async getAddressBalanceMap(): Promise<{ [key in string]?: string }> {\n const map: { [key in string]?: string } = {}\n if (!this.walletClient) {\n return map\n }\n const core = (this.walletClient.client as { core?: Record<string, unknown> }).core\n if (typeof core?.listBalances !== 'function' || typeof core?.getBalance !== 'function') {\n return map\n }\n try {\n let cursor: string | null | undefined = null\n do {\n const { balances, nextCursor } = await listAddressBalances(this.walletClient.client, {\n owner: this.walletClient.address,\n cursor,\n limit: 100\n })\n for (const balance of balances) {\n // Only track coin types that actually hold funds at the address level\n // to avoid creating empty portfolio entries.\n if (balance.addressBalance && balance.addressBalance !== '0') {\n map[balance.coinType] = balance.addressBalance\n }\n }\n cursor = nextCursor\n } while (cursor)\n } catch (error) {\n console.error(error)\n }\n return map\n }\n\n /** Current coin objects from the wallet */\n private _coins: CoinStruct[] = []\n\n /** Current portfolio information */\n private _portfolio: UserPortfolio = new UserPortfolio()\n\n /** Timer for polling balance updates */\n private pollingTimer: NodeJS.Timeout | null = null\n\n /** Promise for waiting on portfolio updates */\n private _updatePromise: Promise<void> | null = null\n\n /**\n * Starts polling for portfolio updates\n *\n * This method recursively schedules itself to run at the configured\n * interval, ensuring regular balance updates.\n */\n private async startPolling() {\n if (this.config.disableCoinPolling) {\n return\n }\n\n try {\n await this.updatePortfolio()\n } catch (error) {\n console.error(error)\n } finally {\n this.pollingTimer = setTimeout(this.startPolling, this.config.coinPollingInterval)\n }\n }\n\n /**\n * Installs the balance module into a wallet client\n *\n * @param walletClient - The wallet client instance to install into\n */\n install(walletClient: WalletClient) {\n super.install(walletClient)\n\n // Bind the polling method and start polling\n this.startPolling = this.startPolling.bind(this)\n this.startPolling()\n\n // Create update promise for waiting on portfolio updates\n this._updatePromise = new Promise((resolve) => {\n walletClient.events.on('balance:portfolio-updated', () => {\n resolve()\n })\n })\n }\n\n /**\n * Uninstalls the balance module from the wallet client\n *\n * This method cleans up timers and stops polling to prevent memory leaks.\n */\n uninstall() {\n super.uninstall()\n if (this.pollingTimer) {\n clearTimeout(this.pollingTimer)\n this.pollingTimer = null\n }\n }\n}\n","import type {\n NaviDryRunTransactionResult,\n NaviExecuteTransactionResult,\n NaviTransactionEffects,\n NaviTransactionEvent,\n NaviTransactionResponseOptions\n} from './types'\n\nexport const defaultTransactionResponseOptions: NaviTransactionResponseOptions = {\n showEffects: true,\n showEvents: true,\n showBalanceChanges: true,\n showObjectChanges: true\n}\n\nexport function mergeTransactionResponseOptions(\n options?: NaviTransactionResponseOptions\n): NaviTransactionResponseOptions {\n return {\n ...defaultTransactionResponseOptions,\n ...options\n }\n}\n\n/**\n * Whether a (normalized) transaction result succeeded.\n *\n * Handles both shapes: v1 JSON-RPC effects `status.status === 'success'` (string)\n * and Sui v2 Core `status.success === true` (boolean). Using only the v1 string\n * check makes success events silently never fire on the gRPC/Core path.\n */\nexport function isSuccessfulTransaction(result: {\n effects?: { status?: unknown } | null\n}): boolean {\n const status = result?.effects?.status as Record<string, unknown> | undefined\n return status?.status === 'success' || status?.success === true\n}\n\nexport function normalizeTransactionResult(\n kind: 'dryRun',\n result: unknown\n): NaviDryRunTransactionResult\nexport function normalizeTransactionResult(\n kind: 'execute',\n result: unknown\n): NaviExecuteTransactionResult\nexport function normalizeTransactionResult(\n kind: 'dryRun' | 'execute',\n result: unknown\n): NaviDryRunTransactionResult | NaviExecuteTransactionResult {\n const source = (result ?? {}) as Record<string, unknown>\n const raw = unwrapTransactionResult(source)\n const effects = normalizeEffects(raw)\n\n return {\n ...raw,\n kind,\n effects,\n events: normalizeEvents(raw.events),\n balanceChanges: Array.isArray(raw.balanceChanges) ? raw.balanceChanges : [],\n objectChanges: Array.isArray(raw.objectChanges) ? raw.objectChanges : []\n }\n}\n\nfunction unwrapTransactionResult(result: Record<string, unknown>) {\n const transaction = result.Transaction\n if (isRecord(transaction)) {\n return transaction\n }\n\n const failedTransaction = result.FailedTransaction\n if (isRecord(failedTransaction)) {\n return failedTransaction\n }\n\n return result\n}\n\nfunction normalizeEffects(raw: Record<string, unknown>): NaviTransactionEffects | undefined {\n if (isRecord(raw.effects)) {\n return raw.effects as NaviTransactionEffects\n }\n\n if (isRecord(raw.status)) {\n return {\n status: raw.status as NaviTransactionEffects['status']\n }\n }\n\n return undefined\n}\n\nfunction normalizeEvents(events: unknown): NaviTransactionEvent[] {\n if (!Array.isArray(events)) {\n return []\n }\n\n return events.map((event) => {\n if (!isRecord(event)) {\n return event\n }\n\n return {\n ...event,\n type: event.type ?? event.eventType,\n parsedJson: event.parsedJson ?? event.json\n }\n }) as NaviTransactionEvent[]\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n","import { Transaction } from '@mysten/sui/transactions'\nimport {\n AssetIdentifier,\n getFlashLoanAsset,\n flashloanPTB,\n depositCoinPTB,\n repayFlashLoanPTB,\n borrowCoinPTB,\n mergeCoinsPTB,\n updateOraclePricesPTB,\n getCoins,\n getAddressBalance\n} from '@naviprotocol/lending'\nimport { buildSwapPTBFromQuote } from '@naviprotocol/astros-aggregator-sdk'\nimport type { LendingModule } from '.'\nimport BigNumber from 'bignumber.js'\nimport { normalizeStructTag } from '@mysten/sui/utils'\nimport { getPriceFeeds, filterPriceFeeds } from '@naviprotocol/lending'\nimport { UserPortfolio } from '../balanceModule/portfolio'\n\nexport async function migrateBetweenSupplyPTB(\n this: LendingModule,\n tx: Transaction,\n from: AssetIdentifier,\n to: AssetIdentifier,\n options?: Partial<{\n protocol?: 'navi' | 'suilend'\n amount?: number\n slippage?: number\n }>\n) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n const fromPool = await this.getPool(from)\n const toPool = await this.getPool(to)\n const lendingState = await this.getLendingState()\n const address = this.walletClient.address\n\n const protocolName = options?.protocol ?? 'navi'\n const fromProtocol = await this.getProtocol(protocolName)\n if (!fromProtocol) {\n throw new Error(`Protocol ${protocolName} not found`)\n }\n const fromPoolLending = await fromProtocol.getPool(fromPool.coinType)\n\n console.log('migrateBetweenSupplyPTB', {\n fromPoolLending\n })\n\n if (protocolName === 'navi' && fromPoolLending.supplyBalance === 0) {\n throw new Error('No supply balance')\n }\n\n if (options?.amount && options.amount > fromPoolLending.supplyBalance) {\n throw new Error('Amount is less than supply balance')\n }\n\n const slippage = options?.slippage ?? 0.005\n\n const formAmount = options?.amount ?? Number(fromPoolLending.supplyBalance)\n\n const priceFeeds = await getPriceFeeds(this.naviServiceOptions)\n const pools = await Promise.all([fromPool, toPool])\n await updateOraclePricesPTB(\n tx,\n filterPriceFeeds(priceFeeds, {\n lendingState,\n pools\n }),\n this.naviServiceOptions\n )\n\n if (protocolName !== 'navi' && fromPool.id === toPool.id) {\n const withdrawnFromCoin = await fromProtocol.withdrawCoinPTB(\n tx,\n fromPool.suiCoinType,\n formAmount\n )\n await depositCoinPTB(tx, toPool, withdrawnFromCoin, {\n ...this.naviServiceOptions,\n amount: formAmount\n })\n return tx\n }\n\n const toPoolFlashloanAsset = await getFlashLoanAsset(toPool, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n if (!toPoolFlashloanAsset) {\n throw new Error(`${toPool.token.symbol} pool not support flashloan`)\n }\n\n const quote = await this.walletClient.swap.getQuote(\n fromPool.suiCoinType,\n toPool.suiCoinType,\n formAmount\n )\n\n const shouldSwapAmount = Number(quote.amount_out)\n\n if (shouldSwapAmount <= 0) {\n throw new Error('The amount of swapAmountOut must be greater than 0.')\n }\n\n const minAmountOut = Math.floor(shouldSwapAmount * (1 - slippage))\n\n const borrowAmountInMin = Math.floor(minAmountOut / (1 + toPoolFlashloanAsset.flashloanFee))\n\n if (borrowAmountInMin <= 0) {\n throw new Error('The calculated borrow amount must be positive.')\n }\n\n const [flashloanBalance, receipt] = await flashloanPTB(\n tx,\n toPool,\n borrowAmountInMin,\n this.naviServiceOptions\n )\n\n const [flashCoin] = tx.moveCall({\n target: '0x2::coin::from_balance',\n arguments: [flashloanBalance],\n typeArguments: [toPool.suiCoinType]\n })\n\n await depositCoinPTB(tx, toPool, flashCoin, {\n ...this.naviServiceOptions,\n amount: borrowAmountInMin\n })\n\n const withdrawnFromCoin = await fromProtocol.withdrawCoinPTB(tx, fromPool.suiCoinType, formAmount)\n\n const swappedToCoin = await buildSwapPTBFromQuote(\n address,\n tx,\n minAmountOut,\n withdrawnFromCoin,\n quote\n )\n\n const repayBalance = tx.moveCall({\n target: '0x2::coin::into_balance',\n arguments: [swappedToCoin],\n typeArguments: [toPool.suiCoinType]\n })\n\n const [leftBalance] = await repayFlashLoanPTB(\n tx,\n toPool,\n receipt,\n repayBalance,\n this.naviServiceOptions\n )\n\n const [extraCoin] = tx.moveCall({\n target: '0x2::coin::from_balance',\n arguments: [leftBalance],\n typeArguments: [toPool.suiCoinType]\n })\n\n await depositCoinPTB(tx, toPool, extraCoin, this.naviServiceOptions)\n\n return tx\n}\n\nexport async function migrateBetweenBorrowPTB(\n this: LendingModule,\n tx: Transaction,\n from: AssetIdentifier,\n to: AssetIdentifier,\n options?: Partial<{\n amount?: number\n slippage?: number\n protocol?: 'navi' | 'suilend'\n }>\n) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n const address = this.walletClient.address\n const fromPool = await this.getPool(from)\n const toPool = await this.getPool(to)\n const lendingState = await this.getLendingState()\n\n const protocolName = options?.protocol ?? 'navi'\n const fromProtocol = await this.getProtocol(protocolName)\n if (!fromProtocol) {\n throw new Error(`Protocol ${protocolName} not found`)\n }\n const fromPoolLending = await fromProtocol.getPool(fromPool.coinType)\n\n console.log('migrateBetweenBorrowPTB', {\n fromPoolLending\n })\n\n if (fromPoolLending.borrowBalance === 0) {\n throw new Error('No borrow balance')\n }\n\n if (options?.amount && options.amount > fromPoolLending.borrowBalance) {\n throw new Error('Amount is more than borrow balance')\n }\n\n const priceFeeds = await getPriceFeeds(this.naviServiceOptions)\n const pools = await Promise.all([fromPool, toPool])\n await updateOraclePricesPTB(\n tx,\n filterPriceFeeds(priceFeeds, {\n lendingState,\n pools\n }),\n this.naviServiceOptions\n )\n\n let formAmount = options?.amount ?? Number(fromPoolLending.borrowBalance)\n\n if (Number(fromPoolLending.borrowBalance) === formAmount) {\n const borrowRate = fromPoolLending.borrowAPR / 100\n formAmount = Math.ceil(\n new BigNumber(formAmount)\n .multipliedBy((borrowRate * (60 * 3)) / (365 * 24 * 3600))\n .plus(new BigNumber(1).shiftedBy(-fromPool.token.decimals))\n .plus(formAmount)\n .toNumber()\n )\n }\n\n const fromPoolFlashloanAsset = await getFlashLoanAsset(fromPool, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n if (!fromPoolFlashloanAsset) {\n throw new Error(`${fromPool.token.symbol} pool not support flashloan`)\n }\n\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const slippage = options?.slippage ?? 0.005\n\n const flashloanRepayAmount = Math.ceil(formAmount * (1 + fromPoolFlashloanAsset.flashloanFee))\n const minSwapAmount = flashloanRepayAmount\n\n const fromQuote = await this.walletClient.swap.getQuote(\n fromPool.suiCoinType,\n toPool.suiCoinType,\n minSwapAmount\n )\n\n let rate = 1 + slippage\n\n let shouldBorrowAmount = Math.ceil(Number(fromQuote.amount_out) * rate)\n\n let toQuote = await this.walletClient.swap.getQuote(\n toPool.suiCoinType,\n fromPool.suiCoinType,\n shouldBorrowAmount\n )\n\n while (Number(toQuote.amount_out) < minSwapAmount) {\n rate = rate * Math.max(minSwapAmount / Number(toQuote.amount_out), 1.001)\n shouldBorrowAmount = Math.ceil(Number(fromQuote.amount_out) * rate)\n toQuote = await this.walletClient.swap.getQuote(\n toPool.suiCoinType,\n fromPool.suiCoinType,\n shouldBorrowAmount\n )\n }\n\n const [flashloanBalance, receipt] = await flashloanPTB(\n tx,\n fromPool,\n formAmount,\n this.naviServiceOptions\n )\n\n const [flashCoin]: any = tx.moveCall({\n target: '0x2::coin::from_balance',\n arguments: [flashloanBalance],\n typeArguments: [fromPool.suiCoinType]\n })\n\n await fromProtocol.repayCoinPTB(tx, fromPool.suiCoinType, flashCoin, formAmount)\n\n const borrowCoin = await borrowCoinPTB(tx, toPool, shouldBorrowAmount, this.naviServiceOptions)\n\n const swappedFromCoin = await buildSwapPTBFromQuote(\n address,\n tx,\n flashloanRepayAmount,\n borrowCoin,\n toQuote\n )\n\n const repayBalance = tx.moveCall({\n target: '0x2::coin::into_balance',\n arguments: [swappedFromCoin],\n typeArguments: [fromPool.suiCoinType]\n })\n\n const [leftBalance] = await repayFlashLoanPTB(\n tx,\n fromPool,\n receipt,\n repayBalance,\n this.naviServiceOptions\n )\n\n const [extraCoin] = tx.moveCall({\n target: '0x2::coin::from_balance',\n arguments: [leftBalance],\n typeArguments: [fromPool.suiCoinType]\n })\n tx.transferObjects([extraCoin], address)\n\n return tx\n}\n\nexport async function migrateBalanceToSupplyPTB(\n this: LendingModule,\n tx: Transaction,\n coinType: string,\n to: AssetIdentifier,\n options?: Partial<{\n amount?: number\n slippage?: number\n }>\n) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const coins = await getCoins(this.walletClient.address, {\n client: this.walletClient.client,\n coinType\n })\n const toPool = await this.getPool(to)\n\n // Include v2 address-level funds for this coin type when the core client\n // supports it; otherwise fall back to coin-object-only balances.\n let addressBalance = '0'\n const core = (this.walletClient.client as { core?: Record<string, unknown> }).core\n if (typeof core?.getBalance === 'function') {\n try {\n const balanceInfo = await getAddressBalance(this.walletClient.client, {\n owner: this.walletClient.address,\n coinType\n })\n addressBalance = balanceInfo.addressBalance\n } catch (error) {\n console.error(error)\n }\n }\n\n const portfolio = new UserPortfolio(coins, { [coinType]: addressBalance })\n const balance = portfolio.getBalance(coinType)\n // SUI is supplied via the gas coin (useGasCoin below), which cannot draw from\n // the address balance, so its spendable total counts coin objects only; other\n // coins can redeem the address balance through mergeCoinsPTB.\n const isSui = normalizeStructTag(coinType) === normalizeStructTag('0x2::sui::SUI')\n const spendableBalance = isSui ? balance.amount : portfolio.combinedBalanceOf(coinType)\n\n if (spendableBalance.eq(0)) {\n throw new Error(`No balance of ${coinType}`)\n }\n\n console.log('migrateBalanceToSupplyPTB', {\n balance: spendableBalance.toNumber()\n })\n\n if (options?.amount && spendableBalance.lt(options.amount)) {\n throw new Error('Amount is greater than balance')\n }\n\n const formAmount = options?.amount ?? spendableBalance.toNumber()\n\n const slippage = options?.slippage ?? 0.005\n\n let depositCoin = await mergeCoinsPTB(tx, balance.coins, {\n balance: formAmount,\n useGasCoin: true,\n addressBalance: balance.addressBalance.toFixed(0),\n coinType\n })\n\n if (normalizeStructTag(coinType) !== normalizeStructTag(toPool.suiCoinType)) {\n const quote = await this.walletClient.swap.getQuote(coinType, toPool.suiCoinType, formAmount)\n depositCoin = (await this.walletClient.swap.buildSwapPTBFromQuote(\n tx,\n quote,\n depositCoin,\n slippage\n )) as typeof depositCoin\n }\n\n await depositCoinPTB(tx, toPool, depositCoin, this.naviServiceOptions)\n\n return tx\n}\n","import { LendingPool, LendingProtocol } from '.'\nimport { Transaction, TransactionObjectInput, TransactionResult } from '@mysten/sui/transactions'\nimport { withdrawCoinPTB, repayCoinPTB, CoinObject, getPool } from '@naviprotocol/lending'\nimport { WalletClient } from '../../../client'\nimport BigNumber from 'bignumber.js'\nimport { normalizeStructTag } from '@mysten/sui/utils'\n\nclass NaviProtocol implements LendingProtocol {\n readonly name = 'navi'\n private walletClient: WalletClient\n\n constructor(walletClient: WalletClient) {\n this.walletClient = walletClient\n }\n\n async getPool(coinType: string): Promise<LendingPool> {\n const pool = await this.walletClient.lending.getPool(coinType)\n const lendingState = await this.walletClient.lending.getLendingState()\n const userPosition = lendingState.find(\n (position) => position.pool.suiCoinType === normalizeStructTag(coinType)\n )\n\n const supplyBalance = userPosition ? new BigNumber(userPosition.supplyBalance).toNumber() : 0\n const borrowBalance = userPosition ? new BigNumber(userPosition.borrowBalance).toNumber() : 0\n\n return {\n supplyBalance: supplyBalance,\n borrowBalance: borrowBalance,\n borrowAPR: parseFloat(pool.borrowIncentiveApyInfo.apy)\n }\n }\n\n async depositCoinPTB(\n tx: Transaction,\n coinType: string,\n coinObject: TransactionObjectInput,\n amount: number\n ): Promise<void> {\n throw new Error('Not implemented')\n }\n\n async withdrawCoinPTB(\n tx: Transaction,\n coinType: string,\n amount: number\n ): Promise<TransactionResult> {\n return withdrawCoinPTB(tx, coinType, amount, this.walletClient.lending.naviServiceOptions)\n }\n\n async borrowCoinPTB(\n tx: Transaction,\n coinType: string,\n amount: number\n ): Promise<TransactionResult> {\n throw new Error('Not implemented')\n }\n\n async repayCoinPTB(\n tx: Transaction,\n coinType: string,\n coinObject: CoinObject,\n amount: number\n ): Promise<void> {\n repayCoinPTB(tx, coinType, coinObject, {\n ...this.walletClient.lending.naviServiceOptions,\n amount\n })\n }\n}\n\nexport default NaviProtocol\n","/**\n * Lending Module Implementation\n *\n * This module provides comprehensive lending protocol functionality for the wallet client.\n * It handles deposit, withdraw, borrow, repay operations, liquidation, reward claiming,\n * and oracle price updates for the Navi lending protocol.\n *\n * @module LendingModule\n */\n\nimport { isSuccessfulTransaction } from '../../transaction-result'\nimport type { NaviWalletTransactionResult } from '../../types'\nimport { Module } from '../module'\nimport {\n depositCoinPTB,\n withdrawCoinPTB,\n borrowCoinPTB,\n repayCoinPTB,\n AssetIdentifier,\n getPool,\n getPools,\n mergeCoinsPTB,\n getHealthFactor,\n liquidatePTB,\n claimLendingRewardsPTB,\n getUserAvailableLendingRewards,\n updateOraclePricesPTB,\n getPriceFeeds,\n getLendingState,\n filterPriceFeeds,\n CacheOption,\n LendingReward,\n AccountCapOption,\n Pool,\n createAccountCapPTB,\n getUserClaimedRewardHistory,\n type NaviSdkServiceOptions\n} from '@naviprotocol/lending'\nimport { Transaction } from '@mysten/sui/transactions'\nimport type { SuiGrpcClient } from '@mysten/sui/grpc'\nimport {\n migrateBalanceToSupplyPTB,\n migrateBetweenBorrowPTB,\n migrateBetweenSupplyPTB\n} from './migrate'\nimport NaviProtocol from './protocols/navi'\nimport { LendingProtocol } from './protocols'\nimport { WalletClient } from '../../client'\n\n/**\n * Configuration options for the lending module\n */\nexport interface LendingModuleConfig {\n /** Environment setting for protocol interaction */\n env: 'dev' | 'prod'\n /** Lending protocols */\n protocols: LendingProtocol[]\n /** Enable the optional Suilend adapter. Defaults to true to preserve v1 business behavior. */\n enableSuilend: boolean\n /** Optional Suilend v3 gRPC client. Defaults to a client derived from the wallet Sui network. */\n suilendGrpcClient?: SuiGrpcClient\n /** Optional Suilend v3 gRPC endpoint. Used when suilendGrpcClient is not provided. */\n suilendGrpcUrl?: string\n /** Optional NAVI service endpoint overrides. */\n services?: NaviSdkServiceOptions\n}\n\n/**\n * Events emitted by the lending module\n */\nexport type Events = {\n /** Emitted when a deposit is successfully completed */\n 'lending:deposit-success': {\n /** Asset identifier for the deposited asset */\n identifier: AssetIdentifier\n /** Amount deposited */\n amount: number\n }\n /** Emitted when a withdrawal is successfully completed */\n 'lending:withdraw-success': {\n /** Asset identifier for the withdrawn asset */\n identifier: AssetIdentifier\n /** Amount withdrawn */\n amount: number\n }\n /** Emitted when a borrow is successfully completed */\n 'lending:borrow-success': {\n /** Asset identifier for the borrowed asset */\n identifier: AssetIdentifier\n /** Amount borrowed */\n amount: number\n }\n /** Emitted when a repayment is successfully completed */\n 'lending:repay-success': {\n /** Asset identifier for the repaid asset */\n identifier: AssetIdentifier\n /** Amount repaid */\n amount: number\n }\n /** Emitted when a liquidation is successfully completed */\n 'lending:liquidate-success': {\n /** Asset identifier for the debt being paid */\n payIdentifier: AssetIdentifier\n /** Amount of debt paid */\n payAmount: number\n /** Asset identifier for the collateral being liquidated */\n collateralIdentifier: AssetIdentifier\n /** Address of the account being liquidated */\n liquidationAddress: string\n }\n /** Emitted when rewards are successfully claimed */\n 'lending:claim-rewards-success': {\n /** Array of claimed rewards */\n rewards: LendingReward[]\n }\n}\n\n/**\n * Lending protocol module for wallet operations\n *\n * This module provides comprehensive lending functionality including:\n * - Deposit and withdraw operations\n * - Borrow and repay operations\n * - Liquidation functionality\n * - Reward claiming\n * - Oracle price updates\n * - Health factor monitoring\n * - Pool information retrieval\n */\nexport class LendingModule extends Module<LendingModuleConfig, Events> {\n /** Module name identifier */\n readonly name = 'lending'\n\n /** Default configuration values */\n readonly defaultConfig: LendingModuleConfig = {\n env: 'prod',\n protocols: [],\n enableSuilend: true\n }\n\n /** Internal protocols storage */\n private _protocols: LendingProtocol[] = []\n\n /** Get protocols (either from internal storage or config) */\n get protocols(): LendingProtocol[] {\n return this._protocols.length > 0 ? this._protocols : this.config.protocols\n }\n\n get naviServiceOptions() {\n const services = this.config.services ?? this.walletClient?.clientBundle.services\n return {\n ...(services ? { services } : {})\n }\n }\n\n install(walletClient: WalletClient): void {\n super.install(walletClient)\n this._protocols = []\n }\n\n async getProtocol(name: string) {\n if (!this.protocols || this.protocols.length === 0) {\n await this.initializeProtocols()\n }\n return this.protocols.find((p) => p.name === name)\n }\n\n /**\n * Gets all available lending pools\n *\n * @param options - Optional caching options\n * @returns Array of pool information\n */\n async getPools(options?: Partial<CacheOption>) {\n return await getPools({\n ...this.naviServiceOptions,\n env: this.config.env,\n ...options\n })\n }\n\n /**\n * Gets information for a specific lending pool\n *\n * @param identifier - Asset identifier (string, Pool object, or number)\n * @param options - Optional caching options\n * @returns Pool information\n */\n async getPool(identifier: AssetIdentifier, options?: Partial<CacheOption>) {\n return await getPool(identifier, {\n ...this.naviServiceOptions,\n env: this.config.env,\n ...options\n })\n }\n\n /**\n * Deposits coins into a lending pool\n *\n * @param identifier - Asset identifier for the pool\n * @param amount - Amount to deposit\n * @param options - Optional parameters including dry run mode and account capability\n * @returns Transaction response or dry run response\n */\n async deposit<T extends boolean = false>(\n identifier: AssetIdentifier,\n amount: number,\n options?: { dryRun: T } & Partial<AccountCapOption>\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Get pool information\n const pool = await getPool(identifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n // Wait for latest balance update\n await this.walletClient.module('balance').waitForUpdate()\n\n // Build transaction\n const tx = new Transaction()\n\n // Get coin balance and merge coins for deposit\n const coinBalance = this.walletClient.module('balance').portfolio.getBalance(pool.suiCoinType)\n\n const mergedCoin = mergeCoinsPTB(tx, coinBalance.coins, {\n balance: amount,\n useGasCoin: true,\n addressBalance: coinBalance.addressBalance.toFixed(0),\n coinType: pool.suiCoinType\n })\n\n // Build deposit transaction\n await depositCoinPTB(tx, pool, mergedCoin, {\n ...this.naviServiceOptions,\n env: this.config.env,\n amount,\n accountCap: options?.accountCap\n })\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n // Handle successful deposit\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:deposit-success', {\n identifier,\n amount\n })\n\n // Update balance portfolio\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Withdraws coins from a lending pool\n *\n * @param identifier - Asset identifier for the pool\n * @param amount - Amount to withdraw\n * @param options - Optional parameters including dry run mode and account capability\n * @returns Transaction response or dry run response\n */\n async withdraw<T extends boolean = false>(\n identifier: AssetIdentifier,\n amount: number,\n options?: { dryRun: T; disableUpdateOracle?: boolean } & Partial<AccountCapOption>\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Get pool information\n const pool = await getPool(identifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n // Build transaction\n const tx = new Transaction()\n\n if (!options?.disableUpdateOracle) {\n await this.updateOraclePTB(tx, [pool])\n }\n\n // Build withdraw transaction\n const coin = await withdrawCoinPTB(tx, pool, amount, {\n ...this.naviServiceOptions,\n env: this.config.env,\n accountCap: options?.accountCap\n })\n\n // Transfer withdrawn coins to wallet\n tx.transferObjects([coin], this.walletClient.address)\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n // Handle successful withdrawal\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:withdraw-success', {\n identifier,\n amount\n })\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Borrows coins from a lending pool\n *\n * @param identifier - Asset identifier for the pool\n * @param amount - Amount to borrow\n * @param options - Optional parameters including dry run mode and account capability\n * @returns Transaction response or dry run response\n */\n async borrow<T extends boolean = false>(\n identifier: AssetIdentifier,\n amount: number,\n options?: { dryRun: T; disableUpdateOracle?: boolean } & Partial<AccountCapOption>\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Get pool information\n const pool = await getPool(identifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n // Build transaction\n const tx = new Transaction()\n\n if (!options?.disableUpdateOracle) {\n await this.updateOraclePTB(tx, [pool])\n }\n\n // Build borrow transaction\n const coin = await borrowCoinPTB(tx, pool, amount, {\n ...this.naviServiceOptions,\n env: this.config.env,\n accountCap: options?.accountCap\n })\n\n // Transfer borrowed coins to wallet\n tx.transferObjects([coin], this.walletClient.address)\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n // Handle successful borrow\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:borrow-success', {\n identifier,\n amount\n })\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Repays borrowed coins to a lending pool\n *\n * @param identifier - Asset identifier for the pool\n * @param amount - Amount to repay\n * @param options - Optional parameters including dry run mode and account capability\n * @returns Transaction response or dry run response\n */\n async repay<T extends boolean = false>(\n identifier: AssetIdentifier,\n amount: number,\n options?: { dryRun: T } & Partial<AccountCapOption>\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Wait for latest balance update\n await this.walletClient.module('balance').waitForUpdate()\n\n // Get pool information\n const pool = await getPool(identifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n // Build transaction\n const tx = new Transaction()\n\n // Get coin balance and merge coins for repayment\n const coinBalance = this.walletClient.module('balance').portfolio.getBalance(pool.suiCoinType)\n\n const mergedCoin = mergeCoinsPTB(tx, coinBalance.coins, {\n balance: amount,\n useGasCoin: true,\n addressBalance: coinBalance.addressBalance.toFixed(0),\n coinType: pool.suiCoinType\n })\n\n // Build repay transaction\n await repayCoinPTB(tx, pool, mergedCoin, {\n ...this.naviServiceOptions,\n env: this.config.env,\n amount,\n accountCap: options?.accountCap\n })\n\n // Execute transaction\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n // Handle successful repayment\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:repay-success', {\n identifier,\n amount\n })\n\n // Update balance portfolio\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Gets the current health factor for the user\n *\n * @returns Current health factor value\n */\n async getHealthFactor() {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const address = this.walletClient.address\n\n const healthFactor = await getHealthFactor(address, {\n ...this.naviServiceOptions,\n env: this.config.env,\n client: this.walletClient.client\n })\n\n return healthFactor\n }\n\n /**\n * Initiates a liquidation process\n *\n * @param payIdentifier - Asset identifier for the debt being paid\n * @param payAmount - Amount of debt to pay\n * @param collateralIdentifier - Asset identifier for the collateral being liquidated\n * @param liquidationAddress - Address of the account being liquidated\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n async liquidate<T extends boolean = false>(\n payIdentifier: AssetIdentifier,\n payAmount: number,\n collateralIdentifier: AssetIdentifier,\n liquidationAddress: string,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const payPool = await getPool(payIdentifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n const collateralPool = await getPool(collateralIdentifier, {\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n const tx = new Transaction()\n\n const payCoinBalance = this.walletClient\n .module('balance')\n .portfolio.getBalance(payPool.suiCoinType)\n\n const mergedCoin = mergeCoinsPTB(tx, payCoinBalance.coins, {\n balance: payAmount,\n useGasCoin: true,\n addressBalance: payCoinBalance.addressBalance.toFixed(0),\n coinType: payPool.suiCoinType\n })\n\n const [collateralBalance, remainDebtBalance] = await liquidatePTB(\n tx,\n payPool,\n mergedCoin,\n collateralPool,\n liquidationAddress,\n {\n ...this.naviServiceOptions,\n env: this.config.env\n }\n )\n\n const [collateralCoin] = tx.moveCall({\n target: `0x2::coin::from_balance`,\n arguments: [collateralBalance],\n typeArguments: [collateralPool.suiCoinType]\n })\n\n const [leftDebtCoin] = tx.moveCall({\n target: `0x2::coin::from_balance`,\n arguments: [remainDebtBalance],\n typeArguments: [payPool.suiCoinType]\n })\n\n tx.transferObjects([collateralCoin, leftDebtCoin], this.walletClient.address)\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:liquidate-success', {\n payIdentifier,\n payAmount,\n collateralIdentifier,\n liquidationAddress\n })\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Gets the available lending rewards for the current user.\n *\n * @param options - Optional cache options.\n * @returns The available lending rewards for the user.\n * @throws If the wallet client is not found.\n */\n async getAvailableRewards(options?: Partial<CacheOption>) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n return getUserAvailableLendingRewards(this.walletClient.address, {\n ...this.naviServiceOptions,\n ...options,\n env: this.config.env,\n client: this.walletClient.client\n })\n }\n\n /**\n * Gets the claimed reward history for the current user.\n *\n * @param options - Optional cache options.\n * @returns The claimed reward history for the user.\n * @throws If the wallet client is not found.\n */\n async getClaimedRewardHistory(\n options?: Partial<CacheOption> & {\n page?: number\n size?: number\n }\n ) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n return getUserClaimedRewardHistory(this.walletClient.address, {\n ...this.naviServiceOptions,\n ...options\n })\n }\n\n /**\n * Claims all available lending rewards for the user\n *\n * @param options - Optional parameters including dry run mode and account capability\n * @returns Transaction response or dry run response\n */\n async claimAllRewards<T extends boolean = false>(\n options?: { dryRun: T } & Partial<AccountCapOption>\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const tx = new Transaction()\n\n const rewards = await getUserAvailableLendingRewards(this.walletClient.address, {\n ...this.naviServiceOptions,\n env: this.config.env,\n client: this.walletClient.client\n })\n\n await claimLendingRewardsPTB(tx, rewards, {\n ...this.naviServiceOptions,\n env: this.config.env,\n accountCap: options?.accountCap\n })\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('lending:claim-rewards-success', {\n rewards\n })\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n private async updateOraclePTB(tx: Transaction, pools?: Pool[]) {\n const feeds = await getPriceFeeds({\n ...this.naviServiceOptions,\n env: this.config.env\n })\n\n const lendingState = await this.getLendingState({\n cacheTime: 60 * 1000\n })\n\n const filteredFeeds = filterPriceFeeds(feeds, {\n lendingState,\n pools\n })\n\n await updateOraclePricesPTB(tx, filteredFeeds, {\n ...this.naviServiceOptions,\n env: this.config.env,\n updatePythPriceFeeds: true,\n client: this.walletClient?.client\n })\n }\n\n /**\n * Updates the oracle prices for the lending protocol\n *\n * @param options - Optional parameters including dry run mode and pools\n * @param options.dryRun - Whether to perform a dry run\n * @returns Transaction response or dry run response\n */\n async updateOracle<T extends boolean = false>(options?: {\n dryRun: T\n pools?: Pool[]\n }): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const tx = new Transaction()\n\n await this.updateOraclePTB(tx, options?.pools)\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n return result as any\n }\n\n /**\n * Gets all active lending positions for the user\n *\n * @param options - Optional caching options\n * @returns User's lending state information\n */\n async getLendingState(options?: Partial<CacheOption>) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n return await getLendingState(this.walletClient.address, {\n ...this.naviServiceOptions,\n env: this.config.env,\n ...options,\n client: this.walletClient.client\n })\n }\n\n /**\n * Creates an account capability for the lending protocol\n *\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n async createAccountCap<T extends boolean = false>(options?: {\n dryRun: T\n }): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const tx = new Transaction()\n\n const cap = await createAccountCapPTB(tx)\n\n tx.transferObjects([cap], this.walletClient.address)\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n return result as any\n }\n\n migrateBetweenSupplyPTB = migrateBetweenSupplyPTB\n migrateBetweenBorrowPTB = migrateBetweenBorrowPTB\n migrateBalanceToSupplyPTB = migrateBalanceToSupplyPTB\n\n constructor() {\n super()\n this.migrateBetweenSupplyPTB = migrateBetweenSupplyPTB.bind(this)\n this.migrateBetweenBorrowPTB = migrateBetweenBorrowPTB.bind(this)\n this.migrateBalanceToSupplyPTB = migrateBalanceToSupplyPTB.bind(this)\n }\n\n async initializeProtocols() {\n if (!this.walletClient) {\n console.warn('Wallet client not available during protocol initialization')\n return\n }\n\n const protocols = []\n protocols.push(new NaviProtocol(this.walletClient))\n\n if (this.config.enableSuilend) {\n try {\n const { default: SuilendProtocol } = await import('./protocols/suilend')\n protocols.push(\n await SuilendProtocol.create(this.walletClient, {\n grpcClient: this.config.suilendGrpcClient,\n grpcUrl: this.config.suilendGrpcUrl\n })\n )\n } catch (error) {\n console.warn('Failed to initialize SuilendProtocol:', error)\n }\n }\n\n this._protocols = protocols as LendingProtocol[]\n }\n}\n","/**\n * Volo Module for Sui Staking Protocol Integration\n *\n * This module provides functionality to interact with the Volo staking protocol on Sui.\n * Volo allows users to stake SUI tokens and receive vSUI (volo SUI) tokens in return,\n * enabling liquid staking with potential rewards and instant unstaking capabilities.\n */\n\nimport { isSuccessfulTransaction } from '../../transaction-result'\nimport {\n CoinObject,\n buildNaviOpenApiUrl,\n mergeCoinsPTB,\n mergeServiceHeaders,\n parseTxValue,\n resolveNaviOpenApiEndpoint,\n withCache,\n withSingleton,\n type NaviSdkServiceOptions\n} from '@naviprotocol/lending'\nimport { Transaction } from '@mysten/sui/transactions'\nimport { Module } from '../module'\nimport type { NaviWalletTransactionResult } from '../../types'\n\n/**\n * Configuration interface for the Volo staking module\n */\nexport interface VoloModuleConfig {\n /** The package ID of the Volo staking contract */\n packageId: string\n /** The pool ID for the staking pool */\n poolId: string\n /** The coin type for vSUI tokens */\n coinType: string\n /** The metadata ID for the staking pool */\n metadataId: string\n /** Optional NAVI service endpoint overrides. */\n services?: NaviSdkServiceOptions\n}\n\nexport type VoloStatsOptions = {\n services?: NaviSdkServiceOptions\n}\n\n/**\n * Event types emitted by the Volo module\n */\nexport type Events = {\n /** Emitted when staking is successful */\n 'volo:stake-success': {\n /** Amount of SUI staked */\n suiAmount: number\n }\n /** Emitted when unstaking is successful */\n 'volo:unstake-success': {\n /** Amount of vSUI unstaked */\n vSuiAmount: number\n }\n}\n\n/**\n * Statistics and information about the Volo staking pool\n */\nexport type VoloStats = {\n /** Current operator balance */\n operatorBalance: string\n /** Collectable fees in the pool */\n collectableFee: string\n /** Pending stakes waiting to be processed */\n pendingStakes: string\n /** Total amount staked in the pool */\n totalStaked: string\n /** Total rewards distributed to stakers */\n totalRewardsInStakes: string\n /** Currently active stake amount */\n activeStake: string\n /** Current epoch number */\n currentEpoch: string\n /** List of validators in the pool */\n validators: {\n /** Validator address */\n address: string\n /** Total amount staked with this validator */\n totalStaked: string\n /** Assigned weight for this validator */\n assigned_weight: string\n /** Annual percentage yield for this validator */\n apy: string\n /** Validator name */\n name: string\n }[]\n /** Current exchange rate between SUI and vSUI */\n exchangeRate: number\n /** Total supply of vSUI tokens */\n totalSupply: string\n /** Overall APY for the staking pool */\n apy: number\n /** Maximum amount that can be instantly unstaked */\n maxInstantUnstake: string\n /** Maximum amount that can be unstaked without fees */\n maxNoFeeUnstake: string\n /** Total number of stakers in the pool */\n totalStakers: number\n /** Timestamp of last update */\n lastUpdated: number\n}\n\n/**\n * Volo Module for Sui Staking Protocol\n *\n * Provides functionality to stake SUI tokens and receive vSUI tokens,\n * enabling liquid staking with potential rewards and instant unstaking.\n */\nexport class VoloModule extends Module<VoloModuleConfig, Events> {\n /** Module name identifier */\n readonly name = 'volo'\n\n /** Default configuration for the Volo staking protocol */\n readonly defaultConfig: VoloModuleConfig = {\n packageId: '0x68d22cf8bdbcd11ecba1e094922873e4080d4d11133e2443fddda0bfd11dae20',\n poolId: '0x2d914e23d82fedef1b5f56a32d5c64bdcc3087ccfea2b4d6ea51a71f587840e5',\n metadataId: '0x680cd26af32b2bde8d3361e804c53ec1d1cfe24c7f039eb7f549e8dfde389a60',\n coinType: '0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT'\n }\n\n /**\n * Get current statistics and information about the Volo staking pool\n * Uses caching to avoid repeated API calls\n *\n * @returns Volo staking pool information\n */\n private getStatsCached = withCache(\n withSingleton(async (options?: VoloStatsOptions) => {\n const serviceOptions = { services: options?.services }\n const endpoint = resolveNaviOpenApiEndpoint(serviceOptions)\n const resp: {\n data: VoloStats\n } = await fetch(buildNaviOpenApiUrl('/volo/stats', serviceOptions), {\n headers: mergeServiceHeaders({}, endpoint)\n }).then((res) => res.json())\n\n return resp.data\n })\n )\n\n getStats(options?: VoloStatsOptions) {\n return this.getStatsCached({\n services: options?.services ?? this.config.services\n })\n }\n\n /**\n * Adds staking operation to a transaction black\n *\n * @param tx - The transaction block to add the staking operation to\n * @param suiCoin - The SUI coin object to stake\n * @returns The vSUI coin object received from staking\n */\n async stakePTB(tx: Transaction, suiCoin: CoinObject) {\n const [coin] = tx.moveCall({\n target: `${this.config.packageId}::stake_pool::stake`,\n arguments: [\n tx.object(this.config.poolId),\n tx.object(this.config.metadataId),\n tx.object('0x05'),\n parseTxValue(suiCoin, tx.object)\n ],\n typeArguments: []\n })\n return coin\n }\n\n /**\n * Adds unstaking operation to a transaction black\n *\n * @param tx - The transaction block to add the unstaking operation to\n * @param vSuiCoin - The vSUI coin object to unstake\n * @returns The SUI coin object received from unstaking\n */\n async unstakePTB(tx: Transaction, vSuiCoin: CoinObject) {\n const [coin] = tx.moveCall({\n target: `${this.config.packageId}::stake_pool::unstake`,\n arguments: [\n tx.object(this.config.poolId),\n tx.object(this.config.metadataId),\n tx.object('0x05'),\n parseTxValue(vSuiCoin, tx.object)\n ],\n typeArguments: []\n })\n return coin\n }\n\n /**\n * Stake SUI tokens to receive vSUI tokens\n *\n * @param suiAmount - Amount of SUI to stake (in MIST units)\n * @param options - Optional parameters including dryRun flag\n * @returns Transaction response or dry run response\n * @throws Error if wallet client not found or stake amount is too low\n */\n async stake<T extends boolean = false>(\n suiAmount: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n if (suiAmount < 1e9) {\n throw new Error('Stake amount should be greater than 1Sui')\n }\n\n const tx = new Transaction()\n\n await this.walletClient.module('balance').waitForUpdate()\n\n const suiBalance = this.walletClient.module('balance').portfolio.getBalance('0x2::sui::SUI')\n\n const mergedCoin = mergeCoinsPTB(tx, suiBalance.coins, {\n balance: suiAmount,\n useGasCoin: true,\n addressBalance: suiBalance.addressBalance.toFixed(0),\n coinType: '0x2::sui::SUI'\n })\n\n const vSuiCoin = await this.stakePTB(tx, mergedCoin)\n\n tx.transferObjects([vSuiCoin], this.walletClient.address)\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('volo:stake-success', {\n suiAmount\n })\n\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n\n /**\n * Unstake vSUI tokens to receive SUI tokens\n *\n * @param vSuiAmount - Amount of vSUI to unstake (in MIST units)\n * @param options - Optional parameters including dryRun flag\n * @returns Transaction response or dry run response\n * @throws Error if wallet client not found or unstake amount is too low\n */\n async unstake<T extends boolean = false>(\n vSuiAmount: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n if (vSuiAmount < 1e9) {\n throw new Error('Unstake amount should >= 1vSui')\n }\n\n await this.walletClient.module('balance').waitForUpdate()\n\n const tx = new Transaction()\n\n const vSuiBalance = this.walletClient\n .module('balance')\n .portfolio.getBalance(this.config.coinType)\n\n const mergedCoin = mergeCoinsPTB(tx, vSuiBalance.coins, {\n balance: vSuiAmount,\n addressBalance: vSuiBalance.addressBalance.toFixed(0),\n coinType: this.config.coinType\n })\n\n const suiCoin = await this.unstakePTB(tx, mergedCoin)\n\n tx.transferObjects([suiCoin], this.walletClient.address)\n\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('volo:unstake-success', {\n vSuiAmount\n })\n\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return result as any\n }\n}\n","/**\n * Swap Module Implementation\n *\n * This module provides DEX swapping functionality for the wallet client.\n * It integrates with the Astros aggregator to find the best swap routes\n * and execute trades across multiple decentralized exchanges.\n *\n * @module SwapModule\n */\n\nimport {\n buildSwapPTBFromQuote,\n getQuote,\n Dex,\n FeeOption,\n generateRefId,\n Quote\n} from '@naviprotocol/astros-aggregator-sdk'\nimport { Transaction } from '@mysten/sui/transactions'\nimport { fromBase64 } from '@mysten/sui/utils'\nimport { Module } from '../module'\nimport { isSuccessfulTransaction } from '../../transaction-result'\nimport type { NaviWalletTransactionResult } from '../../types'\nimport BigNumber from 'bignumber.js'\nimport { mergeCoinsPTB, type NaviSdkServiceOptions } from '@naviprotocol/lending'\nimport { executeAuction } from 'shio-sdk'\nimport {\n defaultTransactionResponseOptions,\n mergeTransactionResponseOptions,\n normalizeTransactionResult\n} from '../../transaction-result'\n\n/**\n * Configuration options for the swap module\n */\nexport interface SwapModuleConfig {\n /** API key for aggregator access */\n apiKey: string\n /** Base URL for the aggregator API */\n baseUrl: string\n /** List of DEXes to use for routing */\n dexList: Dex[]\n /** Maximum routing depth for finding optimal paths */\n depth: number\n /** Service fee configuration */\n serviceFee: FeeOption | undefined\n /** Environment setting */\n env: 'dev' | 'prod'\n /** Optional NAVI service endpoint overrides. */\n services?: NaviSdkServiceOptions\n}\n\n/**\n * Events emitted by the swap module\n */\nexport type Events = {\n /** Emitted when a swap is successfully completed */\n 'swap:swap-success': {\n /** Source coin type */\n fromCoinType: string\n /** Target coin type */\n toCoinType: string\n /** Input amount */\n fromAmount: number\n /** Applied slippage tolerance */\n slippage: number\n /** Output amount received */\n toAmount: number\n }\n}\n\nfunction transactionIncludeOptions() {\n const merged = mergeTransactionResponseOptions(defaultTransactionResponseOptions)\n return {\n effects: merged.showEffects,\n events: merged.showEvents,\n balanceChanges: merged.showBalanceChanges,\n objectTypes: merged.showObjectChanges\n }\n}\n\nfunction getCoreExecutor(client: unknown) {\n return (client as { core?: unknown }).core as\n | {\n executeTransaction?(options: any): Promise<any>\n }\n | undefined\n}\n\n/**\n * DEX swapping module for wallet operations\n *\n * This module provides functionality for:\n * - Getting swap quotes from multiple DEXes\n * - Executing swaps with slippage protection\n * - Managing swap transactions and events\n * - Integrating with the balance module for coin management\n */\nexport class SwapModule extends Module<SwapModuleConfig, Events> {\n /** Module name identifier */\n readonly name = 'swap'\n\n /** Default configuration values */\n readonly defaultConfig: SwapModuleConfig = {\n apiKey: '',\n baseUrl: 'https://open-aggregator-api.naviprotocol.io/find_routes',\n dexList: [],\n depth: 3,\n serviceFee: undefined,\n env: 'prod'\n }\n\n /**\n * Gets the referral ID for this swap module\n *\n * @returns Referral ID if API key is configured, otherwise 0\n */\n get referral() {\n return this.config.apiKey ? generateRefId(this.config.apiKey) : 0\n }\n\n /**\n * Get the swap options\n * @returns The swap options\n */\n get swapOptions() {\n return {\n baseUrl: this.config.baseUrl,\n dexList: this.config.dexList,\n depth: this.config.depth,\n serviceFee: this.config.serviceFee,\n services: this.config.services ?? this.walletClient?.clientBundle.services\n }\n }\n\n /**\n * Get a quote for a swap\n * @param fromCoinType - The type of the coin being swapped from\n * @param toCoinType - The type of the coin being swapped to\n * @param fromAmount - The amount of the coin being swapped from\n * @returns A promise that resolves with the quote\n */\n async getQuote(fromCoinType: string, toCoinType: string, fromAmount: number) {\n return getQuote(fromCoinType, toCoinType, fromAmount, this.config.apiKey, this.swapOptions)\n }\n\n /**\n * Builds a swap transaction from a quote\n * @param tx - The transaction to build the swap from\n * @param quote - The quote to build the swap from\n * @param fromCoin - The coin to swap from\n * @param slippage - The slippage tolerance\n * @returns The swap transaction\n */\n async buildSwapPTBFromQuote(tx: Transaction, quote: Quote, fromCoin: any, slippage: number) {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n const minAmountOut = new BigNumber(quote.amount_out).multipliedBy(1 - slippage).toFixed(0)\n return await buildSwapPTBFromQuote(\n this.walletClient.address,\n tx,\n Number(minAmountOut),\n fromCoin as any,\n quote,\n this.referral,\n false,\n this.config.apiKey,\n this.swapOptions\n )\n }\n\n /**\n * Executes a swap between two coin types\n *\n * This method performs a complete swap operation including:\n * - Balance validation\n * - Quote retrieval from aggregator\n * - Transaction building with slippage protection\n * - Transaction execution\n * - Event emission on success\n *\n * @param fromCoinType - Source coin type\n * @param toCoinType - Target coin type\n * @param fromAmount - Amount to swap\n * @param slippage - Slippage tolerance (0-1)\n * @param options - Optional parameters including dry run mode\n * @returns Transaction response or dry run response\n */\n async swap<T extends boolean = false>(\n fromCoinType: string,\n toCoinType: string,\n fromAmount: number,\n slippage: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n // Wait for latest balance update\n await this.walletClient.module('balance').waitForUpdate()\n\n // Get current balance for the source coin\n const fromCoinBalance = this.walletClient.module('balance').portfolio.getBalance(fromCoinType)\n\n // Build transaction\n const tx = new Transaction()\n\n // Merge coins for the swap input (coin objects + address balance)\n const fromCoin = mergeCoinsPTB(tx, fromCoinBalance.coins, {\n balance: fromAmount,\n useGasCoin: true,\n addressBalance: fromCoinBalance.addressBalance.toFixed(0),\n coinType: fromCoinType\n })\n\n // Get quote from aggregator\n const quote = await this.getQuote(fromCoinType, toCoinType, fromAmount)\n\n // Build swap transaction from quote\n const coinOut = await this.buildSwapPTBFromQuote(tx, quote, fromCoin, slippage)\n\n // Transfer output coins to wallet\n tx.transferObjects([coinOut], this.walletClient.address)\n\n // Set sender address\n tx.setSender(this.walletClient.address)\n\n if (options?.dryRun) {\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: true\n })\n return result as any\n }\n\n const builtTx = await tx.build({\n client: this.walletClient.client as any\n })\n\n const signed = await this.walletClient.signer.signTransaction(builtTx)\n const signatures = [signed.signature]\n\n try {\n await executeAuction(signed.bytes, signatures)\n } catch (e) {\n console.error(e)\n }\n\n const core = getCoreExecutor(this.walletClient.client)\n const result =\n typeof core?.executeTransaction === 'function'\n ? await core.executeTransaction({\n transaction: fromBase64(signed.bytes),\n signatures,\n include: transactionIncludeOptions()\n })\n : await (() => {\n const legacyJsonRpc = this.walletClient.clientBundle.legacyJsonRpc\n if (!legacyJsonRpc) {\n throw new Error(\n 'Swap execution requires core.executeTransaction or an explicit legacyJsonRpc client'\n )\n }\n return legacyJsonRpc.executeTransactionBlock({\n transactionBlock: signed!.bytes,\n signature: signatures,\n options: defaultTransactionResponseOptions\n })\n })()\n\n const normalizedResult = normalizeTransactionResult('execute', result)\n\n if (isSuccessfulTransaction(normalizedResult)) {\n // Find slippage event to get actual output amount\n const slippageEvent = normalizedResult.events?.find((event) => {\n return event.type?.includes('::slippage::SwapEvent')\n })\n\n if (slippageEvent) {\n // Emit swap success event with actual amounts\n this.emit('swap:swap-success', {\n fromCoinType,\n toCoinType,\n fromAmount,\n slippage,\n toAmount: Number((slippageEvent.parsedJson as any).amount_out)\n })\n }\n\n // Update balance portfolio after successful swap\n this.walletClient.module('balance').updatePortfolio()\n }\n\n return normalizedResult as any\n }\n}\n","/**\n * Haedal Staking Module\n *\n * This module provides staking and unstaking functionality for the Haedal protocol.\n * It allows users to stake SUI for haSUI and unstake haSUI back to SUI, and fetches APY stats.\n *\n * @module HaedalModule\n */\n\nimport { isSuccessfulTransaction } from '../../transaction-result'\nimport {\n CoinObject,\n buildNaviOpenApiUrl,\n mergeCoinsPTB,\n mergeServiceHeaders,\n parseTxValue,\n resolveNaviOpenApiEndpoint,\n withCache,\n withSingleton,\n type NaviSdkServiceOptions\n} from '@naviprotocol/lending'\nimport { Transaction } from '@mysten/sui/transactions'\nimport { Module } from '../module'\nimport type { NaviWalletTransactionResult } from '../../types'\n\n/**\n * Configuration for the Haedal module\n */\nexport interface HaedalModuleConfig {\n /** Haedal package ID on Sui */\n packageId: string\n /** Haedal config object ID */\n configId: string\n /** haSUI coin type */\n coinType: string\n /** Optional NAVI service endpoint overrides. */\n services?: NaviSdkServiceOptions\n}\n\nexport type HaedalApyOptions = {\n services?: NaviSdkServiceOptions\n}\n\n/**\n * Events emitted by the Haedal module\n */\nexport type Events = {\n /** Emitted when staking SUI is successful */\n 'haedal:stake-success': {\n suiAmount: number\n }\n /** Emitted when unstaking haSUI is successful */\n 'haedal:unstake-success': {\n haSUIAmount: number\n }\n}\n\n/**\n * Haedal staking/unstaking module for wallet client\n */\nexport class HaedalModule extends Module<HaedalModuleConfig, Events> {\n /** Module name identifier */\n readonly name = 'haedal'\n /** Default configuration values */\n readonly defaultConfig: HaedalModuleConfig = {\n packageId: '0x19e6ea7f5ced4f090e20da794cc80349a03e638940ddb95155a4e301f5f4967c',\n configId: '0x47b224762220393057ebf4f70501b6e657c3e56684737568439a04f80849b2ca',\n coinType: '0xbde4ba4c2e274a60ce15c1cfff9e5c42e41654ac8b6d906a57efa4bd3c29f47d::hasui::HASUI'\n }\n\n /**\n * Fetches the current APY for Haedal staking\n *\n * @returns Current APY of haSUI\n */\n private getApyCached = withCache(\n withSingleton(async (options?: HaedalApyOptions) => {\n const serviceOptions = { services: options?.services }\n const endpoint = resolveNaviOpenApiEndpoint(serviceOptions)\n const resp: {\n data: {\n apy: number\n }\n } = await fetch(buildNaviOpenApiUrl('/haedal/stats', serviceOptions), {\n headers: mergeServiceHeaders({}, endpoint)\n }).then((res) => res.json())\n\n return resp.data.apy\n })\n )\n\n getApy(options?: HaedalApyOptions) {\n return this.getApyCached({\n services: options?.services ?? this.config.services\n })\n }\n\n /**\n * Builds a transaction block for staking SUI to haSUI\n *\n * @param tx - Transaction to add staking operation to\n * @param suiCoin - Sui coin object to stake\n * @returns haSUI coin object\n */\n async stakePTB(tx: Transaction, suiCoin: CoinObject) {\n const [coin] = tx.moveCall({\n target: `${this.config.packageId}::staking::request_stake_coin`,\n arguments: [\n tx.object('0x05'),\n tx.object(this.config.configId),\n parseTxValue(suiCoin, tx.object),\n tx.pure.address('0x0000000000000000000000000000000000000000000000000000000000000000')\n ],\n typeArguments: []\n })\n return coin\n }\n\n /**\n * Builds a transaction block for unstaking haSUI to SUI\n *\n * @param tx - Transaction to add unstaking operation to\n * @param haSUICoin - haSUI coin object to unstake\n * @returns SUI coin object\n */\n async unstakePTB(tx: Transaction, haSUICoin: CoinObject) {\n const [coin] = tx.moveCall({\n target: `${this.config.packageId}::staking::request_unstake_instant_coin`,\n arguments: [\n tx.object('0x05'),\n tx.object(this.config.configId),\n parseTxValue(haSUICoin, tx.object)\n ],\n typeArguments: []\n })\n return coin\n }\n\n /**\n * Stake SUI for haSUI\n *\n * @param suiAmount - Amount of SUI to stake\n * @param options Optional dry run\n */\n async stake<T extends boolean = false>(\n suiAmount: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n\n const tx = new Transaction()\n await this.walletClient.module('balance').waitForUpdate()\n const suiBalance = this.walletClient.module('balance').portfolio.getBalance('0x2::sui::SUI')\n const mergedCoin = mergeCoinsPTB(tx, suiBalance.coins, {\n balance: suiAmount,\n useGasCoin: true,\n addressBalance: suiBalance.addressBalance.toFixed(0),\n coinType: '0x2::sui::SUI'\n })\n const haSUICoin = await this.stakePTB(tx, mergedCoin)\n tx.transferObjects([haSUICoin], this.walletClient.address)\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('haedal:stake-success', { suiAmount })\n this.walletClient.module('balance').updatePortfolio()\n }\n return result as any\n }\n\n /**\n * Unstake haSUI for SUI\n *\n * @param haSUIAmount - Amount of haSUI to unstake\n * @param options Optional dry run\n */\n async unstake<T extends boolean = false>(\n haSUIAmount: number,\n options?: { dryRun: T }\n ): Promise<NaviWalletTransactionResult<T>> {\n if (!this.walletClient) {\n throw new Error('Wallet client not found')\n }\n await this.walletClient.module('balance').waitForUpdate()\n const tx = new Transaction()\n const haSuiBalance = this.walletClient\n .module('balance')\n .portfolio.getBalance(this.config.coinType)\n const mergedCoin = mergeCoinsPTB(tx, haSuiBalance.coins, {\n balance: haSUIAmount,\n addressBalance: haSuiBalance.addressBalance.toFixed(0),\n coinType: this.config.coinType\n })\n const suiCoin = await this.unstakePTB(tx, mergedCoin)\n tx.transferObjects([suiCoin], this.walletClient.address)\n const result = await this.walletClient.signExecuteTransaction({\n transaction: tx,\n dryRun: options?.dryRun ?? false\n })\n if (!options?.dryRun && isSuccessfulTransaction(result)) {\n this.emit('haedal:unstake-success', { haSUIAmount })\n this.walletClient.module('balance').updatePortfolio()\n }\n return result as any\n }\n}\n","/**\n * Wallet Client Modules - Main Index\n *\n * This module serves as the central registry for all wallet client modules.\n * It imports and exports all available modules (balance, lending, volo, swap, haedal)\n * and provides type definitions for module management.\n *\n * @module WalletClientModules\n */\n\nimport { BalanceModule, Events as BalanceEvents } from './balanceModule'\nimport { LendingModule, Events as LendingEvents } from './lendingModule'\nimport { VoloModule, Events as VoloEvents } from './voloModule'\nimport { SwapModule, Events as SwapEvents } from './swapModule'\nimport { HaedalModule, Events as HaedalEvents } from './haedalModule'\n\n/**\n * Registry of all available wallet client modules\n *\n * This object contains instances of all modules that provide different\n * functionalities for the wallet client (balance management, lending,\n * volo operations, swapping, and haedal integration).\n */\nexport const modules = {\n /** Balance management module */\n balance: new BalanceModule(),\n /** Lending protocol module */\n lending: new LendingModule(),\n /** Volo protocol module */\n volo: new VoloModule(),\n /** DEX swapping module */\n swap: new SwapModule(),\n /** Haedal protocol module */\n haedal: new HaedalModule()\n}\n\n/**\n * Union type of all module events\n *\n * This type combines all event types from different modules,\n * allowing the wallet client to handle events from any module.\n */\nexport type ModuleEvents = BalanceEvents & LendingEvents & VoloEvents & SwapEvents & HaedalEvents\n\n/**\n * Type for module names\n *\n * This type represents the keys of the modules object,\n * allowing type-safe access to specific modules.\n */\nexport type ModuleName = keyof typeof modules\n\n/**\n * Type for module instances\n *\n * This type represents any module instance from the modules registry.\n */\nexport type Module = (typeof modules)[ModuleName]\n\n/**\n * Type for module configurations\n *\n * This type represents the configuration type of any module,\n * extracted from the defaultConfig property.\n */\nexport type ModuleConfig = Module['defaultConfig']\n","/**\n * Wallet Client - Core Client Implementation\n *\n * This module provides the main wallet client for interacting with the Sui blockchain.\n * It manages transaction signing, module integration, and provides a unified interface\n * for various DeFi operations including swaps, lending, and balance management.\n *\n * @module WalletClient\n */\n\nimport { Signer } from '@mysten/sui/cryptography'\nimport mitt, { Emitter } from 'mitt'\nimport { Module, ModuleConfig } from './modules/module'\nimport { modules, ModuleName, ModuleEvents } from './modules'\nimport { Transaction } from '@mysten/sui/transactions'\nimport { fromBase64 } from '@mysten/sui/utils'\nimport {\n DryRunOptions,\n NaviTransactionExecutionOptions,\n NaviWalletTransactionResult\n} from './types'\nimport { mergeTransactionResponseOptions, normalizeTransactionResult } from './transaction-result'\nimport {\n createNaviLegacyJsonRpcClient,\n createNaviSuiClientBundle,\n type NaviCoreClient,\n type NaviJsonRpcCompatClient,\n type NaviSdkServiceOptions,\n type NaviSuiClientBundle,\n type NaviSuiClientOptions,\n type NaviSuiLegacyJsonRpcOptions,\n type NaviSuiNetwork,\n PUBLIC_MAINNET_GRPC_URL\n} from '@naviprotocol/lending'\n\n/**\n * Extracts the configuration type from a module\n */\ntype ExtractModuleConfig<T> = T extends Module<infer TConfig, any> ? TConfig : never\n\n/**\n * User configuration type for all modules\n */\nexport type UserConfigs = {\n [K in ModuleName]: Partial<ExtractModuleConfig<(typeof modules)[K]>>\n}\n\n/**\n * Options for initializing the wallet client\n */\nexport type WalletClientOptions = {\n /** The signer for transaction signing */\n signer: Signer\n /** Optional module-specific configurations */\n configs?: Partial<UserConfigs>\n /**\n * Sui v2 client configuration. Optional (v1 parity): when omitted, a public\n * mainnet gRPC client is used — fine for development and low volume;\n * production should pass its own client (private endpoint / auth headers).\n */\n client?: NaviSuiClientOptions | WalletLegacyJsonRpcClientOptions\n}\n\nexport type WalletLegacyJsonRpcClientOptions = {\n network?: NaviSuiNetwork\n /**\n * @deprecated JSON-RPC is a short-lived compatibility transport. New paths must use `grpc`.\n */\n legacyJsonRpc: NaviSuiLegacyJsonRpcOptions\n services?: NaviSdkServiceOptions\n}\n\nfunction transactionIncludeOptions(options?: NaviTransactionExecutionOptions['options']) {\n const merged = mergeTransactionResponseOptions(options)\n return {\n effects: merged.showEffects,\n events: merged.showEvents,\n balanceChanges: merged.showBalanceChanges,\n objectTypes: merged.showObjectChanges\n }\n}\n\nfunction getCoreTransactionClient(client: unknown) {\n return (client as { core?: unknown }).core as\n | {\n simulateTransaction?(options: any): Promise<any>\n executeTransaction?(options: any): Promise<any>\n }\n | undefined\n}\n\nfunction isNaviSuiClientOptions(\n options: NaviSuiClientOptions | WalletLegacyJsonRpcClientOptions\n): options is NaviSuiClientOptions {\n return 'grpc' in options\n}\n\nfunction createWalletClientBundle(\n options: NaviSuiClientOptions | WalletLegacyJsonRpcClientOptions\n): NaviSuiClientBundle {\n if (isNaviSuiClientOptions(options)) {\n return createNaviSuiClientBundle(options)\n }\n const network = options.network ?? 'mainnet'\n const legacyJsonRpc = createNaviLegacyJsonRpcClient(network, options.legacyJsonRpc)\n return {\n network,\n coreClient: legacyJsonRpc,\n grpc: legacyJsonRpc,\n legacyJsonRpc,\n services: options.services\n }\n}\n\n/**\n * Main wallet client class that provides unified access to blockchain operations\n *\n * This class integrates various modules (swap, lending, balance, etc.) and provides\n * a consistent interface for interacting with the Sui blockchain. It handles\n * transaction signing, module management, and event emission.\n */\nexport class WalletClient {\n /** The signer instance for transaction signing */\n public readonly signer: Signer\n\n /** Available modules for different functionalities */\n private readonly modules = modules\n\n /** User-provided module configurations */\n private readonly userConfigs: Partial<UserConfigs> = {}\n\n /** Event emitter for module events */\n public readonly events: Emitter<ModuleEvents> = mitt()\n\n /** The Sui client instance */\n public readonly client: NaviCoreClient & Partial<NaviJsonRpcCompatClient>\n\n /** Normalized transport bundle for modules that need transport-specific clients. */\n public readonly clientBundle: NaviSuiClientBundle\n\n /** URL used by the default JSON-RPC client, when available. */\n public readonly clientUrl?: string\n\n public get lending() {\n return this.modules.lending\n }\n\n public get balance() {\n return this.modules.balance\n }\n\n public get volo() {\n return this.modules.volo\n }\n\n public get swap() {\n return this.modules.swap\n }\n\n public get haedal() {\n return this.modules.haedal\n }\n\n /**\n * Creates a new wallet client instance\n * @param options - Configuration options for the wallet client\n */\n constructor(options: WalletClientOptions) {\n // v1 parity: default to the public mainnet node when no client is given.\n const clientOptions = options.client ?? {\n network: 'mainnet' as const,\n grpc: { url: PUBLIC_MAINNET_GRPC_URL }\n }\n this.clientBundle = createWalletClientBundle(clientOptions)\n this.client = this.clientBundle.coreClient as NaviCoreClient & Partial<NaviJsonRpcCompatClient>\n this.clientUrl =\n 'grpc' in clientOptions\n ? clientOptions.legacyJsonRpc && 'url' in clientOptions.legacyJsonRpc\n ? clientOptions.legacyJsonRpc.url\n : undefined\n : 'url' in clientOptions.legacyJsonRpc\n ? clientOptions.legacyJsonRpc.url\n : undefined\n this.signer = options.signer\n this.userConfigs = options.configs || {}\n\n // Install all modules and validate their names\n Object.entries(this.modules).forEach(([name, module]) => {\n if (name !== module.name) {\n throw new Error(`Module name ${name} does not match module name ${module.name}`)\n }\n module.install(this)\n })\n }\n\n /**\n * Signs and executes a transaction block\n * @param options - Transaction execution options including dry run support\n * @returns Promise with transaction execution result\n */\n async signExecuteTransaction(\n options: {\n transaction: Uint8Array | Transaction\n } & NaviTransactionExecutionOptions &\n Partial<DryRunOptions>\n ): Promise<NaviWalletTransactionResult<boolean>> {\n const { dryRun = false, ...rest } = options\n\n if (dryRun) {\n const core = getCoreTransactionClient(this.client)\n if (typeof core?.simulateTransaction === 'function') {\n if (options.transaction instanceof Transaction) {\n options.transaction.setSenderIfNotSet(this.address)\n }\n const result = await core.simulateTransaction({\n transaction: options.transaction,\n include: transactionIncludeOptions(rest.options)\n })\n return normalizeTransactionResult('dryRun', result)\n }\n\n const legacyJsonRpc = this.clientBundle.legacyJsonRpc\n if (!legacyJsonRpc) {\n throw new Error(\n 'WalletClient dry-run requires core.simulateTransaction or an explicit legacyJsonRpc client'\n )\n }\n // Handle dry run mode for transaction simulation\n let txBytes\n if (options.transaction instanceof Transaction) {\n options.transaction.setSenderIfNotSet(this.address)\n txBytes = await options.transaction.build({\n client: legacyJsonRpc as any\n })\n } else {\n txBytes = options.transaction\n }\n const result = await legacyJsonRpc.dryRunTransactionBlock({\n transactionBlock: txBytes\n })\n return normalizeTransactionResult('dryRun', result)\n }\n\n const core = getCoreTransactionClient(this.client)\n if (typeof core?.executeTransaction === 'function') {\n let txBytes: Uint8Array\n if (options.transaction instanceof Transaction) {\n options.transaction.setSenderIfNotSet(this.address)\n txBytes = await options.transaction.build({\n client: this.client as any\n })\n } else {\n txBytes = options.transaction\n }\n const signed = await this.signer.signTransaction(txBytes)\n const result = await core.executeTransaction({\n transaction: fromBase64(signed.bytes),\n signatures: [signed.signature],\n include: transactionIncludeOptions(rest.options)\n })\n return normalizeTransactionResult('execute', result)\n }\n\n const legacyJsonRpc = this.clientBundle.legacyJsonRpc\n if (!legacyJsonRpc) {\n throw new Error(\n 'WalletClient execution requires core.executeTransaction or an explicit legacyJsonRpc client'\n )\n }\n // Execute the actual transaction\n const result = await legacyJsonRpc.signAndExecuteTransaction({\n ...rest,\n options: mergeTransactionResponseOptions(rest.options),\n signer: this.signer\n } as any)\n return normalizeTransactionResult('execute', result)\n }\n\n /**\n * Gets the wallet address from the signer's public key\n * @returns The wallet address as a string\n */\n get address(): string {\n return this.signer.getPublicKey().toSuiAddress()\n }\n\n /**\n * Gets a specific module by name\n * @param name - The name of the module to retrieve\n * @returns The requested module instance\n */\n module<TName extends ModuleName>(name: TName): (typeof modules)[TName] {\n return this.modules[name]\n }\n\n /**\n * Gets the configuration for a specific module\n * @param name - The name of the module\n * @returns The merged configuration (default + user config)\n */\n config<TName extends ModuleName>(name: TName): ExtractModuleConfig<(typeof modules)[TName]> {\n const mergedConfig = {\n ...this.modules[name].defaultConfig,\n ...this.userConfigs[name]\n }\n return mergedConfig as ExtractModuleConfig<(typeof modules)[TName]>\n }\n\n /**\n * Checks if a module is available\n * @param name - The name of the module to check\n * @returns True if the module exists, false otherwise\n */\n hasModule(name: ModuleName): boolean {\n return name in this.modules\n }\n}\n\nexport type { ModuleConfig }\n","/**\n * Watch Signer Implementation\n *\n * This module provides a watch-only signer implementation for the wallet client.\n * It allows users to view wallet information and transaction details without\n * the ability to sign transactions, useful for read-only operations.\n *\n * @module WatchSigner\n */\n\nimport { Signer } from '@mysten/sui/cryptography'\nimport { Transaction } from '@mysten/sui/transactions'\nimport type { PublicKey, SignatureScheme, SignatureWithBytes } from '@mysten/sui/cryptography'\nimport type { NaviWalletExecutionClient } from './types'\n\n/**\n * Minimal mock public key used by watch-only / web signers. It exposes the\n * address but cannot perform real cryptography; typed as `PublicKey` for the\n * `Signer` contract via a cast since it is intentionally incomplete.\n */\nfunction createMockPublicKey(address: string): PublicKey {\n return {\n toSuiAddress: () => address,\n toBytes: () => new Uint8Array(32),\n toRawBytes: () => new Uint8Array(32),\n flag: () => 0,\n verify: async () => false\n } as unknown as PublicKey\n}\n\n/**\n * Options for signing and executing transactions\n */\ninterface SignAndExecuteOptions {\n /** Transaction to sign and execute */\n transaction: Transaction\n /** Sui client instance */\n client: NaviWalletExecutionClient\n}\n\n/**\n * Watch-only signer implementation\n *\n * This signer provides read-only access to wallet information without\n * the ability to sign transactions. It's useful for viewing wallet\n * balances, transaction history, and other non-signing operations.\n *\n * Note: This signer cannot actually sign transactions and will return\n * empty signatures or throw errors when signing is attempted.\n */\nexport class WatchSigner extends Signer {\n /** The wallet address this signer represents */\n private address: string\n\n /**\n * Creates a new watch-only signer\n *\n * @param address - The wallet address to watch\n */\n constructor(address: string) {\n super()\n this.address = address\n }\n\n /**\n * Signs transaction bytes (not implemented for watch-only mode)\n *\n * This method is required by the Signer interface but cannot\n * actually sign transactions in watch-only mode.\n *\n * @param bytes - Transaction bytes to sign\n * @returns Promise<Uint8Array> - Empty signature (not valid)\n */\n override async sign(bytes: Uint8Array): Promise<Uint8Array<ArrayBuffer>> {\n return Promise.resolve(new Uint8Array(0))\n }\n\n /**\n * Gets the public key information for this signer\n *\n * Returns a mock public key object that provides the wallet address\n * but cannot be used for actual cryptographic operations.\n */\n getPublicKey(): PublicKey {\n return createMockPublicKey(this.address)\n }\n\n /**\n * Gets the key scheme for this signer\n *\n * @returns Key scheme (ed25519 for compatibility)\n */\n getKeyScheme(): SignatureScheme {\n return 'ED25519'\n }\n\n /**\n * Signs and executes a transaction (not implemented for watch-only mode)\n *\n * This method is required by the Signer interface but cannot\n * actually sign and execute transactions in watch-only mode.\n */\n override async signAndExecuteTransaction(\n options: SignAndExecuteOptions\n ): ReturnType<Signer['signAndExecuteTransaction']> {\n return {} as Awaited<ReturnType<Signer['signAndExecuteTransaction']>>\n }\n}\n\n/**\n * Web signer implementation\n *\n * For use in browser environments\n */\nexport abstract class WebSigner extends Signer {\n private address: string\n\n /**\n * Creates a new watch-only signer\n *\n * @param address - The wallet address to watch\n */\n constructor(address: string) {\n super()\n this.address = address\n }\n\n /**\n * Signs transaction bytes (not implemented for watch-only mode)\n *\n * This method is required by the Signer interface but cannot\n * actually sign transactions in watch-only mode.\n *\n * @param bytes - Transaction bytes to sign\n * @returns Promise<Uint8Array> - Empty signature (not valid)\n */\n override async sign(bytes: Uint8Array): Promise<Uint8Array<ArrayBuffer>> {\n return Promise.resolve(new Uint8Array(0))\n }\n\n /**\n * Gets the public key information for this signer\n *\n * Returns a mock public key object that provides the wallet address\n * but cannot be used for actual cryptographic operations.\n */\n getPublicKey(): PublicKey {\n return createMockPublicKey(this.address)\n }\n\n /**\n * Gets the key scheme for this signer\n *\n * @returns Key scheme (ed25519 for compatibility)\n */\n getKeyScheme(): SignatureScheme {\n return 'ED25519'\n }\n\n abstract signPersonalMessage(bytes: Uint8Array): Promise<SignatureWithBytes>\n\n abstract signTransaction(bytes: Uint8Array): Promise<SignatureWithBytes>\n}\n"],"names":["Module","event","data","walletClient","UserPortfolio","coins","addressBalances","balance","BigNumber","balances","item","normalizedCoinType","normalizeStructTag","existPofolio","coinType","value","BalanceModule","withSingleton","getCoins","recipient","amount","options","recipients","amounts","coinBalance","isSui","spendable","totalAmount","acc","curr","tx","Transaction","shares","address","index","mergedCoin","mergeCoinsPTB","headShares","object","objects","map","core","cursor","nextCursor","listAddressBalances","error","resolve","defaultTransactionResponseOptions","mergeTransactionResponseOptions","isSuccessfulTransaction","result","status","normalizeTransactionResult","kind","raw","unwrapTransactionResult","effects","normalizeEffects","normalizeEvents","transaction","isRecord","failedTransaction","events","migrateBetweenSupplyPTB","from","to","fromPool","toPool","lendingState","protocolName","fromProtocol","fromPoolLending","slippage","formAmount","priceFeeds","getPriceFeeds","pools","updateOraclePricesPTB","filterPriceFeeds","withdrawnFromCoin","depositCoinPTB","toPoolFlashloanAsset","getFlashLoanAsset","quote","shouldSwapAmount","minAmountOut","borrowAmountInMin","flashloanBalance","receipt","flashloanPTB","flashCoin","swappedToCoin","buildSwapPTBFromQuote","repayBalance","leftBalance","repayFlashLoanPTB","extraCoin","migrateBetweenBorrowPTB","borrowRate","fromPoolFlashloanAsset","flashloanRepayAmount","minSwapAmount","fromQuote","rate","shouldBorrowAmount","toQuote","borrowCoin","borrowCoinPTB","swappedFromCoin","migrateBalanceToSupplyPTB","addressBalance","getAddressBalance","portfolio","spendableBalance","depositCoin","NaviProtocol","pool","userPosition","position","supplyBalance","borrowBalance","coinObject","withdrawCoinPTB","repayCoinPTB","LendingModule","services","name","p","getPools","identifier","getPool","coin","getHealthFactor","payIdentifier","payAmount","collateralIdentifier","liquidationAddress","payPool","collateralPool","payCoinBalance","collateralBalance","remainDebtBalance","liquidatePTB","collateralCoin","leftDebtCoin","getUserAvailableLendingRewards","getUserClaimedRewardHistory","rewards","claimLendingRewardsPTB","feeds","filteredFeeds","getLendingState","cap","createAccountCapPTB","protocols","SuilendProtocol","VoloModule","withCache","serviceOptions","endpoint","resolveNaviOpenApiEndpoint","buildNaviOpenApiUrl","mergeServiceHeaders","res","suiCoin","parseTxValue","vSuiCoin","suiAmount","suiBalance","vSuiAmount","vSuiBalance","transactionIncludeOptions","merged","getCoreExecutor","client","SwapModule","generateRefId","fromCoinType","toCoinType","fromAmount","getQuote","fromCoin","fromCoinBalance","coinOut","builtTx","signed","signatures","executeAuction","e","fromBase64","legacyJsonRpc","normalizedResult","slippageEvent","HaedalModule","haSUICoin","haSUIAmount","haSuiBalance","modules","getCoreTransactionClient","isNaviSuiClientOptions","createWalletClientBundle","createNaviSuiClientBundle","network","createNaviLegacyJsonRpcClient","WalletClient","mitt","clientOptions","PUBLIC_MAINNET_GRPC_URL","module","dryRun","rest","txBytes","createMockPublicKey","WatchSigner","Signer","bytes","WebSigner"],"mappings":"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"}
|