@sodax/dapp-kit 1.3.0-beta → 1.3.1-beta-rc2

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.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Sodax, SpokeProvider, GetEstimateGasReturnType, TxReturnType, SpokeChainId, StellarSpokeProvider, EvmHubProvider, IWalletProvider, MoneyMarketBorrowParams, MoneyMarketError, RelayErrorCode, MoneyMarketRepayParams, MoneyMarketSupplyParams, MoneyMarketWithdrawParams, UserReserveData, AggregatedReserveData, BaseCurrencyInfo, MoneyMarketParams, XToken, ReserveData, FormatReserveUSDResponse, FormatUserSummaryResponse, SolverIntentQuoteRequest, Result, SolverIntentQuoteResponse, SolverErrorResponse, SolverExecutionResponse, Intent, IntentDeliveryInfo, IntentError, IntentErrorCode, CreateIntentParams, Hex, SolverIntentStatusResponse, CreateLimitOrderParams, IntentResponse, Address as Address$1, UserIntentsResponse, OrderbookResponse, MoneyMarketPosition, MoneyMarketAsset, MoneyMarketAssetBorrowers, MoneyMarketAssetSuppliers, MoneyMarketBorrowers, CreateBridgeIntentParams, SpokeTxHash, HubTxHash, BridgeError, BridgeErrorCode, BridgeLimit, StakeParams, UnstakeParams, ClaimParams, CancelUnstakeParams, StakingInfo, UnstakingInfo, UnstakeRequestWithPenalty, StakingConfig, InstantUnstakeParams, SodaxConfig } from '@sodax/sdk';
1
+ import { Sodax, SpokeProvider, GetEstimateGasReturnType, TxReturnType, SpokeChainId, StellarSpokeProvider, EvmHubProvider, IWalletProvider, BitcoinSpokeProvider, RadfiWalletBalance, RadfiUtxo, MoneyMarketBorrowParams, MoneyMarketError, RelayErrorCode, MoneyMarketRepayParams, MoneyMarketSupplyParams, MoneyMarketWithdrawParams, UserReserveData, AggregatedReserveData, BaseCurrencyInfo, MoneyMarketParams, XToken, ReserveData, FormatReserveUSDResponse, FormatUserSummaryResponse, SolverIntentQuoteRequest, Result, SolverIntentQuoteResponse, SolverErrorResponse, SolverExecutionResponse, Intent, IntentDeliveryInfo, IntentError, IntentErrorCode, CreateIntentParams, Hex, SolverIntentStatusResponse, CreateLimitOrderParams, IntentResponse, Address as Address$1, UserIntentsResponse, OrderbookResponse, MoneyMarketPosition, MoneyMarketAsset, MoneyMarketAssetBorrowers, MoneyMarketAssetSuppliers, MoneyMarketBorrowers, CreateBridgeIntentParams, SpokeTxHash, HubTxHash, BridgeError, BridgeErrorCode, BridgeLimit, StakeParams, UnstakeParams, ClaimParams, CancelUnstakeParams, StakingInfo, UnstakingInfo, UnstakeRequestWithPenalty, StakingConfig, InstantUnstakeParams, SodaxConfig } from '@sodax/sdk';
2
2
  import { RpcConfig, SpokeChainId as SpokeChainId$1, XToken as XToken$1 } from '@sodax/types';
3
3
  import { UseMutationResult, UseQueryResult, UseQueryOptions } from '@tanstack/react-query';
4
4
  import { Address } from 'viem';
@@ -179,6 +179,109 @@ declare function useHubProvider(): EvmHubProvider;
179
179
  */
180
180
  declare function useSpokeProvider(spokeChainId: SpokeChainId$1 | undefined, walletProvider?: IWalletProvider | undefined): SpokeProvider | undefined;
181
181
 
182
+ type RadfiSession = {
183
+ accessToken: string;
184
+ refreshToken: string;
185
+ tradingAddress: string;
186
+ publicKey: string;
187
+ accessTokenExpiry: number;
188
+ refreshTokenExpiry: number;
189
+ };
190
+ type RadfiAuthResult = {
191
+ accessToken: string;
192
+ refreshToken: string;
193
+ tradingAddress: string;
194
+ };
195
+ declare function saveRadfiSession(address: string, session: RadfiSession): void;
196
+ declare function loadRadfiSession(address: string): RadfiSession | null;
197
+ declare function clearRadfiSession(address: string): void;
198
+ declare function isAccessTokenExpired(address: string): boolean;
199
+ declare function isRefreshTokenExpired(address: string): boolean;
200
+ /**
201
+ * Hook to authenticate with Radfi using BIP322 message signing.
202
+ * Saves full session (accessToken, refreshToken, tradingAddress, expiry) to localStorage.
203
+ */
204
+ declare function useRadfiAuth(spokeProvider: BitcoinSpokeProvider | undefined): UseMutationResult<RadfiAuthResult, Error, void>;
205
+
206
+ type UseRadfiSessionReturn = {
207
+ walletAddress: string | undefined;
208
+ isAuthed: boolean;
209
+ tradingAddress: string | undefined;
210
+ login: () => Promise<void>;
211
+ isLoginPending: boolean;
212
+ };
213
+ /**
214
+ * Manages the full Radfi session lifecycle:
215
+ * - Restores session from localStorage on mount
216
+ * - Polls every 2s: silently refreshes accessToken before expiry, resets auth when refreshToken expires
217
+ * - Exposes login() and isAuthed for UI
218
+ */
219
+ declare function useRadfiSession(spokeProvider: BitcoinSpokeProvider | undefined): UseRadfiSessionReturn;
220
+
221
+ /**
222
+ * Hook to fund the Radfi trading wallet by sending BTC from the user's personal wallet.
223
+ *
224
+ * @param {BitcoinSpokeProvider | undefined} spokeProvider - The Bitcoin spoke provider with signing capability
225
+ * @returns {UseMutationResult} Mutation result — input is amount in satoshis, output is transaction ID
226
+ *
227
+ * @example
228
+ * ```tsx
229
+ * const { mutateAsync: fundWallet, isPending } = useFundTradingWallet(spokeProvider);
230
+ *
231
+ * const handleFund = async () => {
232
+ * const txId = await fundWallet(100_000n); // fund 100,000 satoshis
233
+ * console.log('Funded:', txId);
234
+ * };
235
+ * ```
236
+ */
237
+ declare function useFundTradingWallet(spokeProvider: BitcoinSpokeProvider | undefined): UseMutationResult<string, Error, bigint>;
238
+
239
+ /**
240
+ * Hook to fetch BTC balance for any Bitcoin address.
241
+ * Sums all UTXOs (confirmed + unconfirmed) from mempool.space API.
242
+ *
243
+ * The UTXO set already excludes spent outputs (even from unconfirmed txs),
244
+ * so the total is always the correct spendable balance.
245
+ */
246
+ declare function useBitcoinBalance(address: string | undefined, rpcUrl?: string): UseQueryResult<bigint, Error>;
247
+
248
+ /**
249
+ * Hook to fetch trading wallet balance from Radfi API.
250
+ * Returns confirmed + pending satoshi balances.
251
+ */
252
+ declare function useTradingWalletBalance(spokeProvider: BitcoinSpokeProvider | undefined, tradingAddress: string | undefined): UseQueryResult<RadfiWalletBalance, Error>;
253
+
254
+ /**
255
+ * Hook to fetch expired UTXOs for a trading wallet address.
256
+ * UTXOs that are expired or within 2 weeks of expiry are considered invalid for trading
257
+ * and need to be renewed via the Radfi renew-utxo flow.
258
+ */
259
+ declare function useExpiredUtxos(spokeProvider: BitcoinSpokeProvider | undefined, tradingAddress: string | undefined): UseQueryResult<RadfiUtxo[], Error>;
260
+
261
+ type RenewUtxosParams = {
262
+ txIdVouts: string[];
263
+ };
264
+ /**
265
+ * Hook to renew expired UTXOs in the Radfi trading wallet.
266
+ *
267
+ * Flow:
268
+ * 1. Build renew-utxo transaction via Radfi API (returns unsigned PSBT)
269
+ * 2. User signs the PSBT with their wallet
270
+ * 3. Submit signed PSBT back to Radfi for co-signing and broadcasting
271
+ *
272
+ * @example
273
+ * ```tsx
274
+ * const { mutateAsync: renewUtxos, isPending } = useRenewUtxos(spokeProvider);
275
+ *
276
+ * const handleRenew = async (expiredUtxos: RadfiUtxo[]) => {
277
+ * const txIdVouts = expiredUtxos.map(u => `${u.txId}:${u.vout}`);
278
+ * const txId = await renewUtxos({ txIdVouts });
279
+ * console.log('Renewed:', txId);
280
+ * };
281
+ * ```
282
+ */
283
+ declare function useRenewUtxos(spokeProvider: BitcoinSpokeProvider | undefined): UseMutationResult<string, Error, RenewUtxosParams>;
284
+
182
285
  interface BorrowResponse {
183
286
  ok: true;
184
287
  value: [string, string];
@@ -1837,4 +1940,4 @@ interface SodaxProviderProps {
1837
1940
  }
1838
1941
  declare const SodaxProvider: ({ children, testnet, config, rpcConfig }: SodaxProviderProps) => ReactElement;
1839
1942
 
1840
- export { type BackendPaginationParams, MIGRATION_MODE_BNUSD, MIGRATION_MODE_ICX_SODA, type MigrationIntentParams, type MigrationMode, SodaxProvider, type UseATokenParams, type UseATokensBalancesParams, type UseBorrowParams, type UseMMAllowanceParams, type UseMMApproveParams, type UseRepayParams, type UseReservesDataParams, type UseReservesUsdFormatParams, type UseSupplyParams, type UseUserFormattedSummaryParams, type UseUserReservesDataParams, type UseWithdrawParams, useAToken, useATokensBalances, useBackendAllMoneyMarketAssets, useBackendAllMoneyMarketBorrowers, useBackendIntentByHash, useBackendIntentByTxHash, useBackendMoneyMarketAsset, useBackendMoneyMarketAssetBorrowers, useBackendMoneyMarketAssetSuppliers, useBackendMoneyMarketPosition, useBackendOrderbook, useBackendUserIntents, useBorrow, useBridge, useBridgeAllowance, useBridgeApprove, useCancelLimitOrder, useCancelSwap, useCancelUnstake, useClaim, useConvertedAssets, useCreateLimitOrder, useDeriveUserWalletAddress, useEstimateGas, useGetBridgeableAmount, useGetBridgeableTokens, useGetUserHubWalletAddress, useHubProvider, useInstantUnstake, useInstantUnstakeAllowance, useInstantUnstakeApprove, useInstantUnstakeRatio, useMMAllowance, useMMApprove, useMigrate, useMigrationAllowance, useMigrationApprove, useQuote, useRepay, useRequestTrustline, useReservesData, useReservesUsdFormat, useSodaxContext, useSpokeProvider, useStake, useStakeAllowance, useStakeApprove, useStakeRatio, useStakingConfig, useStakingInfo, useStatus, useStellarTrustlineCheck, useSupply, useSwap, useSwapAllowance, useSwapApprove, useUnstake, useUnstakeAllowance, useUnstakeApprove, useUnstakingInfo, useUnstakingInfoWithPenalty, useUserFormattedSummary, useUserReservesData, useWithdraw };
1943
+ export { type BackendPaginationParams, MIGRATION_MODE_BNUSD, MIGRATION_MODE_ICX_SODA, type MigrationIntentParams, type MigrationMode, type RadfiSession, SodaxProvider, type UseATokenParams, type UseATokensBalancesParams, type UseBorrowParams, type UseMMAllowanceParams, type UseMMApproveParams, type UseRadfiSessionReturn, type UseRepayParams, type UseReservesDataParams, type UseReservesUsdFormatParams, type UseSupplyParams, type UseUserFormattedSummaryParams, type UseUserReservesDataParams, type UseWithdrawParams, clearRadfiSession, isAccessTokenExpired, isRefreshTokenExpired, loadRadfiSession, saveRadfiSession, useAToken, useATokensBalances, useBackendAllMoneyMarketAssets, useBackendAllMoneyMarketBorrowers, useBackendIntentByHash, useBackendIntentByTxHash, useBackendMoneyMarketAsset, useBackendMoneyMarketAssetBorrowers, useBackendMoneyMarketAssetSuppliers, useBackendMoneyMarketPosition, useBackendOrderbook, useBackendUserIntents, useBitcoinBalance, useBorrow, useBridge, useBridgeAllowance, useBridgeApprove, useCancelLimitOrder, useCancelSwap, useCancelUnstake, useClaim, useConvertedAssets, useCreateLimitOrder, useDeriveUserWalletAddress, useEstimateGas, useExpiredUtxos, useFundTradingWallet, useGetBridgeableAmount, useGetBridgeableTokens, useGetUserHubWalletAddress, useHubProvider, useInstantUnstake, useInstantUnstakeAllowance, useInstantUnstakeApprove, useInstantUnstakeRatio, useMMAllowance, useMMApprove, useMigrate, useMigrationAllowance, useMigrationApprove, useQuote, useRadfiAuth, useRadfiSession, useRenewUtxos, useRepay, useRequestTrustline, useReservesData, useReservesUsdFormat, useSodaxContext, useSpokeProvider, useStake, useStakeAllowance, useStakeApprove, useStakeRatio, useStakingConfig, useStakingInfo, useStatus, useStellarTrustlineCheck, useSupply, useSwap, useSwapAllowance, useSwapApprove, useTradingWalletBalance, useUnstake, useUnstakeAllowance, useUnstakeApprove, useUnstakingInfo, useUnstakingInfoWithPenalty, useUserFormattedSummary, useUserReservesData, useWithdraw };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Sodax, SpokeProvider, GetEstimateGasReturnType, TxReturnType, SpokeChainId, StellarSpokeProvider, EvmHubProvider, IWalletProvider, MoneyMarketBorrowParams, MoneyMarketError, RelayErrorCode, MoneyMarketRepayParams, MoneyMarketSupplyParams, MoneyMarketWithdrawParams, UserReserveData, AggregatedReserveData, BaseCurrencyInfo, MoneyMarketParams, XToken, ReserveData, FormatReserveUSDResponse, FormatUserSummaryResponse, SolverIntentQuoteRequest, Result, SolverIntentQuoteResponse, SolverErrorResponse, SolverExecutionResponse, Intent, IntentDeliveryInfo, IntentError, IntentErrorCode, CreateIntentParams, Hex, SolverIntentStatusResponse, CreateLimitOrderParams, IntentResponse, Address as Address$1, UserIntentsResponse, OrderbookResponse, MoneyMarketPosition, MoneyMarketAsset, MoneyMarketAssetBorrowers, MoneyMarketAssetSuppliers, MoneyMarketBorrowers, CreateBridgeIntentParams, SpokeTxHash, HubTxHash, BridgeError, BridgeErrorCode, BridgeLimit, StakeParams, UnstakeParams, ClaimParams, CancelUnstakeParams, StakingInfo, UnstakingInfo, UnstakeRequestWithPenalty, StakingConfig, InstantUnstakeParams, SodaxConfig } from '@sodax/sdk';
1
+ import { Sodax, SpokeProvider, GetEstimateGasReturnType, TxReturnType, SpokeChainId, StellarSpokeProvider, EvmHubProvider, IWalletProvider, BitcoinSpokeProvider, RadfiWalletBalance, RadfiUtxo, MoneyMarketBorrowParams, MoneyMarketError, RelayErrorCode, MoneyMarketRepayParams, MoneyMarketSupplyParams, MoneyMarketWithdrawParams, UserReserveData, AggregatedReserveData, BaseCurrencyInfo, MoneyMarketParams, XToken, ReserveData, FormatReserveUSDResponse, FormatUserSummaryResponse, SolverIntentQuoteRequest, Result, SolverIntentQuoteResponse, SolverErrorResponse, SolverExecutionResponse, Intent, IntentDeliveryInfo, IntentError, IntentErrorCode, CreateIntentParams, Hex, SolverIntentStatusResponse, CreateLimitOrderParams, IntentResponse, Address as Address$1, UserIntentsResponse, OrderbookResponse, MoneyMarketPosition, MoneyMarketAsset, MoneyMarketAssetBorrowers, MoneyMarketAssetSuppliers, MoneyMarketBorrowers, CreateBridgeIntentParams, SpokeTxHash, HubTxHash, BridgeError, BridgeErrorCode, BridgeLimit, StakeParams, UnstakeParams, ClaimParams, CancelUnstakeParams, StakingInfo, UnstakingInfo, UnstakeRequestWithPenalty, StakingConfig, InstantUnstakeParams, SodaxConfig } from '@sodax/sdk';
2
2
  import { RpcConfig, SpokeChainId as SpokeChainId$1, XToken as XToken$1 } from '@sodax/types';
3
3
  import { UseMutationResult, UseQueryResult, UseQueryOptions } from '@tanstack/react-query';
4
4
  import { Address } from 'viem';
@@ -179,6 +179,109 @@ declare function useHubProvider(): EvmHubProvider;
179
179
  */
180
180
  declare function useSpokeProvider(spokeChainId: SpokeChainId$1 | undefined, walletProvider?: IWalletProvider | undefined): SpokeProvider | undefined;
181
181
 
182
+ type RadfiSession = {
183
+ accessToken: string;
184
+ refreshToken: string;
185
+ tradingAddress: string;
186
+ publicKey: string;
187
+ accessTokenExpiry: number;
188
+ refreshTokenExpiry: number;
189
+ };
190
+ type RadfiAuthResult = {
191
+ accessToken: string;
192
+ refreshToken: string;
193
+ tradingAddress: string;
194
+ };
195
+ declare function saveRadfiSession(address: string, session: RadfiSession): void;
196
+ declare function loadRadfiSession(address: string): RadfiSession | null;
197
+ declare function clearRadfiSession(address: string): void;
198
+ declare function isAccessTokenExpired(address: string): boolean;
199
+ declare function isRefreshTokenExpired(address: string): boolean;
200
+ /**
201
+ * Hook to authenticate with Radfi using BIP322 message signing.
202
+ * Saves full session (accessToken, refreshToken, tradingAddress, expiry) to localStorage.
203
+ */
204
+ declare function useRadfiAuth(spokeProvider: BitcoinSpokeProvider | undefined): UseMutationResult<RadfiAuthResult, Error, void>;
205
+
206
+ type UseRadfiSessionReturn = {
207
+ walletAddress: string | undefined;
208
+ isAuthed: boolean;
209
+ tradingAddress: string | undefined;
210
+ login: () => Promise<void>;
211
+ isLoginPending: boolean;
212
+ };
213
+ /**
214
+ * Manages the full Radfi session lifecycle:
215
+ * - Restores session from localStorage on mount
216
+ * - Polls every 2s: silently refreshes accessToken before expiry, resets auth when refreshToken expires
217
+ * - Exposes login() and isAuthed for UI
218
+ */
219
+ declare function useRadfiSession(spokeProvider: BitcoinSpokeProvider | undefined): UseRadfiSessionReturn;
220
+
221
+ /**
222
+ * Hook to fund the Radfi trading wallet by sending BTC from the user's personal wallet.
223
+ *
224
+ * @param {BitcoinSpokeProvider | undefined} spokeProvider - The Bitcoin spoke provider with signing capability
225
+ * @returns {UseMutationResult} Mutation result — input is amount in satoshis, output is transaction ID
226
+ *
227
+ * @example
228
+ * ```tsx
229
+ * const { mutateAsync: fundWallet, isPending } = useFundTradingWallet(spokeProvider);
230
+ *
231
+ * const handleFund = async () => {
232
+ * const txId = await fundWallet(100_000n); // fund 100,000 satoshis
233
+ * console.log('Funded:', txId);
234
+ * };
235
+ * ```
236
+ */
237
+ declare function useFundTradingWallet(spokeProvider: BitcoinSpokeProvider | undefined): UseMutationResult<string, Error, bigint>;
238
+
239
+ /**
240
+ * Hook to fetch BTC balance for any Bitcoin address.
241
+ * Sums all UTXOs (confirmed + unconfirmed) from mempool.space API.
242
+ *
243
+ * The UTXO set already excludes spent outputs (even from unconfirmed txs),
244
+ * so the total is always the correct spendable balance.
245
+ */
246
+ declare function useBitcoinBalance(address: string | undefined, rpcUrl?: string): UseQueryResult<bigint, Error>;
247
+
248
+ /**
249
+ * Hook to fetch trading wallet balance from Radfi API.
250
+ * Returns confirmed + pending satoshi balances.
251
+ */
252
+ declare function useTradingWalletBalance(spokeProvider: BitcoinSpokeProvider | undefined, tradingAddress: string | undefined): UseQueryResult<RadfiWalletBalance, Error>;
253
+
254
+ /**
255
+ * Hook to fetch expired UTXOs for a trading wallet address.
256
+ * UTXOs that are expired or within 2 weeks of expiry are considered invalid for trading
257
+ * and need to be renewed via the Radfi renew-utxo flow.
258
+ */
259
+ declare function useExpiredUtxos(spokeProvider: BitcoinSpokeProvider | undefined, tradingAddress: string | undefined): UseQueryResult<RadfiUtxo[], Error>;
260
+
261
+ type RenewUtxosParams = {
262
+ txIdVouts: string[];
263
+ };
264
+ /**
265
+ * Hook to renew expired UTXOs in the Radfi trading wallet.
266
+ *
267
+ * Flow:
268
+ * 1. Build renew-utxo transaction via Radfi API (returns unsigned PSBT)
269
+ * 2. User signs the PSBT with their wallet
270
+ * 3. Submit signed PSBT back to Radfi for co-signing and broadcasting
271
+ *
272
+ * @example
273
+ * ```tsx
274
+ * const { mutateAsync: renewUtxos, isPending } = useRenewUtxos(spokeProvider);
275
+ *
276
+ * const handleRenew = async (expiredUtxos: RadfiUtxo[]) => {
277
+ * const txIdVouts = expiredUtxos.map(u => `${u.txId}:${u.vout}`);
278
+ * const txId = await renewUtxos({ txIdVouts });
279
+ * console.log('Renewed:', txId);
280
+ * };
281
+ * ```
282
+ */
283
+ declare function useRenewUtxos(spokeProvider: BitcoinSpokeProvider | undefined): UseMutationResult<string, Error, RenewUtxosParams>;
284
+
182
285
  interface BorrowResponse {
183
286
  ok: true;
184
287
  value: [string, string];
@@ -1837,4 +1940,4 @@ interface SodaxProviderProps {
1837
1940
  }
1838
1941
  declare const SodaxProvider: ({ children, testnet, config, rpcConfig }: SodaxProviderProps) => ReactElement;
1839
1942
 
1840
- export { type BackendPaginationParams, MIGRATION_MODE_BNUSD, MIGRATION_MODE_ICX_SODA, type MigrationIntentParams, type MigrationMode, SodaxProvider, type UseATokenParams, type UseATokensBalancesParams, type UseBorrowParams, type UseMMAllowanceParams, type UseMMApproveParams, type UseRepayParams, type UseReservesDataParams, type UseReservesUsdFormatParams, type UseSupplyParams, type UseUserFormattedSummaryParams, type UseUserReservesDataParams, type UseWithdrawParams, useAToken, useATokensBalances, useBackendAllMoneyMarketAssets, useBackendAllMoneyMarketBorrowers, useBackendIntentByHash, useBackendIntentByTxHash, useBackendMoneyMarketAsset, useBackendMoneyMarketAssetBorrowers, useBackendMoneyMarketAssetSuppliers, useBackendMoneyMarketPosition, useBackendOrderbook, useBackendUserIntents, useBorrow, useBridge, useBridgeAllowance, useBridgeApprove, useCancelLimitOrder, useCancelSwap, useCancelUnstake, useClaim, useConvertedAssets, useCreateLimitOrder, useDeriveUserWalletAddress, useEstimateGas, useGetBridgeableAmount, useGetBridgeableTokens, useGetUserHubWalletAddress, useHubProvider, useInstantUnstake, useInstantUnstakeAllowance, useInstantUnstakeApprove, useInstantUnstakeRatio, useMMAllowance, useMMApprove, useMigrate, useMigrationAllowance, useMigrationApprove, useQuote, useRepay, useRequestTrustline, useReservesData, useReservesUsdFormat, useSodaxContext, useSpokeProvider, useStake, useStakeAllowance, useStakeApprove, useStakeRatio, useStakingConfig, useStakingInfo, useStatus, useStellarTrustlineCheck, useSupply, useSwap, useSwapAllowance, useSwapApprove, useUnstake, useUnstakeAllowance, useUnstakeApprove, useUnstakingInfo, useUnstakingInfoWithPenalty, useUserFormattedSummary, useUserReservesData, useWithdraw };
1943
+ export { type BackendPaginationParams, MIGRATION_MODE_BNUSD, MIGRATION_MODE_ICX_SODA, type MigrationIntentParams, type MigrationMode, type RadfiSession, SodaxProvider, type UseATokenParams, type UseATokensBalancesParams, type UseBorrowParams, type UseMMAllowanceParams, type UseMMApproveParams, type UseRadfiSessionReturn, type UseRepayParams, type UseReservesDataParams, type UseReservesUsdFormatParams, type UseSupplyParams, type UseUserFormattedSummaryParams, type UseUserReservesDataParams, type UseWithdrawParams, clearRadfiSession, isAccessTokenExpired, isRefreshTokenExpired, loadRadfiSession, saveRadfiSession, useAToken, useATokensBalances, useBackendAllMoneyMarketAssets, useBackendAllMoneyMarketBorrowers, useBackendIntentByHash, useBackendIntentByTxHash, useBackendMoneyMarketAsset, useBackendMoneyMarketAssetBorrowers, useBackendMoneyMarketAssetSuppliers, useBackendMoneyMarketPosition, useBackendOrderbook, useBackendUserIntents, useBitcoinBalance, useBorrow, useBridge, useBridgeAllowance, useBridgeApprove, useCancelLimitOrder, useCancelSwap, useCancelUnstake, useClaim, useConvertedAssets, useCreateLimitOrder, useDeriveUserWalletAddress, useEstimateGas, useExpiredUtxos, useFundTradingWallet, useGetBridgeableAmount, useGetBridgeableTokens, useGetUserHubWalletAddress, useHubProvider, useInstantUnstake, useInstantUnstakeAllowance, useInstantUnstakeApprove, useInstantUnstakeRatio, useMMAllowance, useMMApprove, useMigrate, useMigrationAllowance, useMigrationApprove, useQuote, useRadfiAuth, useRadfiSession, useRenewUtxos, useRepay, useRequestTrustline, useReservesData, useReservesUsdFormat, useSodaxContext, useSpokeProvider, useStake, useStakeAllowance, useStakeApprove, useStakeRatio, useStakingConfig, useStakingInfo, useStatus, useStellarTrustlineCheck, useSupply, useSwap, useSwapAllowance, useSwapApprove, useTradingWalletBalance, useUnstake, useUnstakeAllowance, useUnstakeApprove, useUnstakingInfo, useUnstakingInfoWithPenalty, useUserFormattedSummary, useUserReservesData, useWithdraw };
package/dist/index.js CHANGED
@@ -143,6 +143,21 @@ function useSpokeProvider(spokeChainId, walletProvider) {
143
143
  if (!spokeChainId) return void 0;
144
144
  if (!xChainType) return void 0;
145
145
  if (!rpcConfig) return void 0;
146
+ if (xChainType === "BITCOIN") {
147
+ const bitcoinConfig = sdk.spokeChainConfig[spokeChainId];
148
+ const btcRpcOverride = rpcConfig[spokeChainId];
149
+ return new sdk.BitcoinSpokeProvider(
150
+ walletProvider,
151
+ bitcoinConfig,
152
+ {
153
+ url: btcRpcOverride?.radfiApiUrl || bitcoinConfig.radfiApiUrl,
154
+ apiKey: bitcoinConfig.radfiApiKey,
155
+ umsUrl: btcRpcOverride?.radfiUmsUrl || bitcoinConfig.radfiUmsUrl
156
+ },
157
+ "TRADING",
158
+ btcRpcOverride?.rpcUrl || bitcoinConfig.rpcUrl
159
+ );
160
+ }
146
161
  if (xChainType === "EVM") {
147
162
  if (spokeChainId === sdk.SONIC_MAINNET_CHAIN_ID) {
148
163
  return new sdk.SonicSpokeProvider(
@@ -150,9 +165,11 @@ function useSpokeProvider(spokeChainId, walletProvider) {
150
165
  sdk.spokeChainConfig[spokeChainId]
151
166
  );
152
167
  }
168
+ const evmRpcUrl = rpcConfig[spokeChainId];
153
169
  return new sdk.EvmSpokeProvider(
154
170
  walletProvider,
155
- sdk.spokeChainConfig[spokeChainId]
171
+ sdk.spokeChainConfig[spokeChainId],
172
+ typeof evmRpcUrl === "string" ? evmRpcUrl : void 0
156
173
  );
157
174
  }
158
175
  if (xChainType === "SUI") {
@@ -203,6 +220,258 @@ function useSpokeProvider(spokeChainId, walletProvider) {
203
220
  }, [spokeChainId, xChainType, walletProvider, rpcConfig]);
204
221
  return spokeProvider;
205
222
  }
223
+
224
+ // src/hooks/bitcoin/radfiConstants.ts
225
+ var ACCESS_TOKEN_TTL = 10 * 60 * 1e3;
226
+ var REFRESH_TOKEN_TTL = 7 * 24 * 60 * 60 * 1e3;
227
+
228
+ // src/hooks/bitcoin/useRadfiAuth.ts
229
+ var SESSION_KEY = (address) => `radfi_session_${address}`;
230
+ function saveRadfiSession(address, session) {
231
+ try {
232
+ localStorage.setItem(SESSION_KEY(address), JSON.stringify(session));
233
+ } catch {
234
+ }
235
+ }
236
+ function loadRadfiSession(address) {
237
+ try {
238
+ const raw = localStorage.getItem(SESSION_KEY(address));
239
+ return raw ? JSON.parse(raw) : null;
240
+ } catch {
241
+ return null;
242
+ }
243
+ }
244
+ function clearRadfiSession(address) {
245
+ try {
246
+ localStorage.removeItem(SESSION_KEY(address));
247
+ } catch {
248
+ }
249
+ }
250
+ function isAccessTokenExpired(address) {
251
+ const session = loadRadfiSession(address);
252
+ if (!session) return true;
253
+ return Date.now() >= session.accessTokenExpiry;
254
+ }
255
+ function isRefreshTokenExpired(address) {
256
+ const session = loadRadfiSession(address);
257
+ if (!session) return true;
258
+ return Date.now() >= session.refreshTokenExpiry;
259
+ }
260
+ function useRadfiAuth(spokeProvider) {
261
+ return reactQuery.useMutation({
262
+ mutationFn: async () => {
263
+ if (!spokeProvider) {
264
+ throw new Error("Bitcoin spoke provider not found");
265
+ }
266
+ const walletAddress = await spokeProvider.walletProvider.getWalletAddress();
267
+ const existingSession = loadRadfiSession(walletAddress);
268
+ const cachedPublicKey = existingSession?.publicKey;
269
+ try {
270
+ const { accessToken, refreshToken, tradingAddress, publicKey } = await spokeProvider.authenticateWithWallet(cachedPublicKey);
271
+ const session = {
272
+ accessToken,
273
+ refreshToken,
274
+ tradingAddress,
275
+ publicKey,
276
+ accessTokenExpiry: Date.now() + ACCESS_TOKEN_TTL,
277
+ refreshTokenExpiry: Date.now() + REFRESH_TOKEN_TTL
278
+ };
279
+ saveRadfiSession(walletAddress, session);
280
+ return { accessToken, refreshToken, tradingAddress };
281
+ } catch (err) {
282
+ const isAlreadyRegistered = err instanceof Error && (err.message.includes("duplicatedPubKey") || err.message.includes("4008"));
283
+ if (isAlreadyRegistered) {
284
+ if (existingSession && !isRefreshTokenExpired(walletAddress)) {
285
+ const refreshed = await spokeProvider.radfi.refreshAccessToken(existingSession.refreshToken);
286
+ const session = {
287
+ ...existingSession,
288
+ accessToken: refreshed.accessToken,
289
+ refreshToken: refreshed.refreshToken,
290
+ accessTokenExpiry: Date.now() + ACCESS_TOKEN_TTL,
291
+ refreshTokenExpiry: Date.now() + REFRESH_TOKEN_TTL
292
+ };
293
+ spokeProvider.setRadfiAccessToken(refreshed.accessToken);
294
+ saveRadfiSession(walletAddress, session);
295
+ return { accessToken: refreshed.accessToken, refreshToken: refreshed.refreshToken, tradingAddress: existingSession.tradingAddress };
296
+ }
297
+ throw new Error(
298
+ "This wallet is already registered with Radfi from another session. Please clear your browser storage for this site and try again, or wait for the previous session to expire."
299
+ );
300
+ }
301
+ throw err;
302
+ }
303
+ }
304
+ });
305
+ }
306
+ var POLL_INTERVAL = 3e4;
307
+ function useRadfiSession(spokeProvider) {
308
+ const [walletAddress, setWalletAddress] = React.useState();
309
+ const [isAuthed, setIsAuthed] = React.useState(false);
310
+ const [tradingAddress, setTradingAddress] = React.useState();
311
+ const isRefreshingRef = React.useRef(false);
312
+ const silentRefresh = React.useCallback(async (address) => {
313
+ if (!spokeProvider || isRefreshingRef.current) return;
314
+ isRefreshingRef.current = true;
315
+ try {
316
+ const session = loadRadfiSession(address);
317
+ if (!session?.refreshToken) {
318
+ setIsAuthed(false);
319
+ return;
320
+ }
321
+ const { accessToken, refreshToken } = await spokeProvider.radfi.refreshAccessToken(session.refreshToken);
322
+ const updated = {
323
+ ...session,
324
+ accessToken,
325
+ refreshToken,
326
+ accessTokenExpiry: Date.now() + ACCESS_TOKEN_TTL
327
+ // Keep the original refreshTokenExpiry — don't roll it forward on every silent refresh
328
+ };
329
+ saveRadfiSession(address, updated);
330
+ spokeProvider.setRadfiAccessToken(accessToken);
331
+ setIsAuthed(true);
332
+ setTradingAddress(updated.tradingAddress || void 0);
333
+ } catch {
334
+ clearRadfiSession(address);
335
+ spokeProvider.setRadfiAccessToken("");
336
+ setIsAuthed(false);
337
+ setTradingAddress(void 0);
338
+ } finally {
339
+ isRefreshingRef.current = false;
340
+ }
341
+ }, [spokeProvider]);
342
+ React.useEffect(() => {
343
+ if (!spokeProvider) return;
344
+ const fetchAndRestore = () => {
345
+ spokeProvider.walletProvider.getWalletAddress().then((addr) => {
346
+ setWalletAddress(addr);
347
+ const session = loadRadfiSession(addr);
348
+ if (!session || isRefreshTokenExpired(addr)) return;
349
+ if (!isAccessTokenExpired(addr)) {
350
+ spokeProvider.setRadfiAccessToken(session.accessToken);
351
+ setIsAuthed(true);
352
+ setTradingAddress(session.tradingAddress || void 0);
353
+ } else {
354
+ silentRefresh(addr);
355
+ }
356
+ }).catch(() => {
357
+ });
358
+ };
359
+ fetchAndRestore();
360
+ const id = setInterval(fetchAndRestore, 3e3);
361
+ return () => clearInterval(id);
362
+ }, [spokeProvider, silentRefresh]);
363
+ React.useEffect(() => {
364
+ if (!walletAddress || !spokeProvider) return;
365
+ const id = setInterval(() => {
366
+ if (isRefreshTokenExpired(walletAddress)) {
367
+ clearRadfiSession(walletAddress);
368
+ spokeProvider.setRadfiAccessToken("");
369
+ setIsAuthed(false);
370
+ setTradingAddress(void 0);
371
+ return;
372
+ }
373
+ if (isAccessTokenExpired(walletAddress)) {
374
+ silentRefresh(walletAddress);
375
+ }
376
+ }, POLL_INTERVAL);
377
+ return () => clearInterval(id);
378
+ }, [walletAddress, spokeProvider, silentRefresh]);
379
+ const { mutateAsync: loginMutate, isPending: isLoginPending } = useRadfiAuth(spokeProvider);
380
+ const login = React.useCallback(async () => {
381
+ const result = await loginMutate();
382
+ setIsAuthed(true);
383
+ setTradingAddress(result.tradingAddress || void 0);
384
+ }, [loginMutate]);
385
+ return { walletAddress, isAuthed, tradingAddress, login, isLoginPending };
386
+ }
387
+ function useFundTradingWallet(spokeProvider) {
388
+ const queryClient = reactQuery.useQueryClient();
389
+ return reactQuery.useMutation({
390
+ mutationFn: async (amount) => {
391
+ if (!spokeProvider) {
392
+ throw new Error("Bitcoin spoke provider not found");
393
+ }
394
+ return sdk.BitcoinSpokeService.fundTradingWallet(amount, spokeProvider);
395
+ },
396
+ onSuccess: () => {
397
+ queryClient.invalidateQueries({ queryKey: ["btc-balance"] });
398
+ queryClient.invalidateQueries({ queryKey: ["xBalances"] });
399
+ }
400
+ });
401
+ }
402
+ function useBitcoinBalance(address, rpcUrl = "https://mempool.space/api") {
403
+ return reactQuery.useQuery({
404
+ queryKey: ["btc-balance", address],
405
+ queryFn: async () => {
406
+ if (!address) return 0n;
407
+ const response = await fetch(`${rpcUrl}/address/${address}/utxo`);
408
+ if (!response.ok) return 0n;
409
+ const utxos = await response.json();
410
+ return BigInt(utxos.reduce((sum, utxo) => sum + utxo.value, 0));
411
+ },
412
+ enabled: !!address
413
+ });
414
+ }
415
+ function useTradingWalletBalance(spokeProvider, tradingAddress) {
416
+ return reactQuery.useQuery({
417
+ queryKey: ["trading-wallet-balance", tradingAddress],
418
+ queryFn: () => {
419
+ if (!spokeProvider || !tradingAddress) {
420
+ throw new Error("spokeProvider and tradingAddress are required");
421
+ }
422
+ return spokeProvider.radfi.getBalance(tradingAddress);
423
+ },
424
+ enabled: !!spokeProvider && !!tradingAddress
425
+ });
426
+ }
427
+ function useExpiredUtxos(spokeProvider, tradingAddress) {
428
+ return reactQuery.useQuery({
429
+ queryKey: ["expired-utxos", tradingAddress],
430
+ queryFn: async () => {
431
+ if (!spokeProvider || !tradingAddress) {
432
+ throw new Error("spokeProvider and tradingAddress are required");
433
+ }
434
+ const result = await spokeProvider.radfi.getExpiredUtxos(tradingAddress);
435
+ return result.data;
436
+ },
437
+ enabled: !!spokeProvider && !!tradingAddress,
438
+ refetchInterval: 6e4
439
+ // refetch every minute
440
+ });
441
+ }
442
+ function useRenewUtxos(spokeProvider) {
443
+ const queryClient = reactQuery.useQueryClient();
444
+ return reactQuery.useMutation({
445
+ mutationFn: async ({ txIdVouts }) => {
446
+ if (!spokeProvider) {
447
+ throw new Error("Bitcoin spoke provider not found");
448
+ }
449
+ const userAddress = await spokeProvider.walletProvider.getWalletAddress();
450
+ const session = loadRadfiSession(userAddress);
451
+ const accessToken = session?.accessToken || spokeProvider.radfiAccessToken;
452
+ if (!accessToken) {
453
+ throw new Error("Radfi authentication required. Please login first.");
454
+ }
455
+ const buildResult = await spokeProvider.radfi.buildRenewUtxoTransaction(
456
+ { userAddress, txIdVouts },
457
+ accessToken
458
+ );
459
+ const signedTx = await spokeProvider.walletProvider.signTransaction(
460
+ buildResult.base64Psbt,
461
+ false
462
+ );
463
+ const signedBase64Tx = sdk.normalizePsbtToBase64(signedTx);
464
+ return spokeProvider.radfi.signAndBroadcastRenewUtxo(
465
+ { userAddress, signedBase64Tx },
466
+ accessToken
467
+ );
468
+ },
469
+ onSuccess: () => {
470
+ queryClient.invalidateQueries({ queryKey: ["expired-utxos"] });
471
+ queryClient.invalidateQueries({ queryKey: ["trading-wallet-balance"] });
472
+ }
473
+ });
474
+ }
206
475
  function useBorrow() {
207
476
  const { sodax } = useSodaxContext();
208
477
  return reactQuery.useMutation({
@@ -324,8 +593,22 @@ function useMMAllowance({
324
593
  const { sodax } = useSodaxContext();
325
594
  const defaultQueryOptions = {
326
595
  queryKey: ["mm", "allowance", params?.token, params?.action],
327
- enabled: !!spokeProvider,
328
- refetchInterval: 5e3
596
+ /**
597
+ * IMPORTANT: Skip allowance checks for 'borrow' and 'withdraw' actions.
598
+ *
599
+ * Reason: According to the SDK's MoneyMarketService.isAllowanceValid() implementation,
600
+ * borrow and withdraw actions do NOT require ERC-20 token approval. The SDK's
601
+ * isAllowanceValid() method always returns `true` for these actions without making
602
+ * any on-chain allowance checks.
603
+ *
604
+ * This optimization prevents unnecessary RPC calls and avoids showing confusing states for actions that don't actually need approval.
605
+ *
606
+ * Only 'supply' and 'repay' actions require token approval and should trigger allowance checks.
607
+ */
608
+ enabled: !!spokeProvider && !!params && params.action !== "borrow" && params.action !== "withdraw",
609
+ refetchInterval: 5e3,
610
+ gcTime: 0
611
+ // Don't cache failed queries
329
612
  };
330
613
  queryOptions = {
331
614
  ...defaultQueryOptions,
@@ -337,6 +620,9 @@ function useMMAllowance({
337
620
  queryFn: async () => {
338
621
  if (!spokeProvider) throw new Error("Spoke provider is required");
339
622
  if (!params) throw new Error("Params are required");
623
+ if (params.action === "borrow" || params.action === "withdraw") {
624
+ return true;
625
+ }
340
626
  const allowance = await sodax.moneyMarket.isAllowanceValid(params, spokeProvider);
341
627
  if (!allowance.ok) {
342
628
  throw allowance.error;
@@ -1176,11 +1462,9 @@ function useInstantUnstakeRatio(amount, refetchInterval = 1e4) {
1176
1462
  }
1177
1463
  function useConvertedAssets(amount, refetchInterval = 1e4) {
1178
1464
  const { sodax } = useSodaxContext();
1179
- console.log("useConvertedAssets hook called with:", { amount: amount?.toString(), sodax: !!sodax });
1180
1465
  return reactQuery.useQuery({
1181
1466
  queryKey: ["soda", "convertedAssets", amount?.toString()],
1182
1467
  queryFn: async () => {
1183
- console.log("useConvertedAssets queryFn called with amount:", amount?.toString());
1184
1468
  if (!amount || amount <= 0n) {
1185
1469
  throw new Error("Amount must be greater than 0");
1186
1470
  }
@@ -1504,6 +1788,11 @@ var SodaxProvider = ({ children, testnet = false, config, rpcConfig }) => {
1504
1788
  exports.MIGRATION_MODE_BNUSD = MIGRATION_MODE_BNUSD;
1505
1789
  exports.MIGRATION_MODE_ICX_SODA = MIGRATION_MODE_ICX_SODA;
1506
1790
  exports.SodaxProvider = SodaxProvider;
1791
+ exports.clearRadfiSession = clearRadfiSession;
1792
+ exports.isAccessTokenExpired = isAccessTokenExpired;
1793
+ exports.isRefreshTokenExpired = isRefreshTokenExpired;
1794
+ exports.loadRadfiSession = loadRadfiSession;
1795
+ exports.saveRadfiSession = saveRadfiSession;
1507
1796
  exports.useAToken = useAToken;
1508
1797
  exports.useATokensBalances = useATokensBalances;
1509
1798
  exports.useBackendAllMoneyMarketAssets = useBackendAllMoneyMarketAssets;
@@ -1516,6 +1805,7 @@ exports.useBackendMoneyMarketAssetSuppliers = useBackendMoneyMarketAssetSupplier
1516
1805
  exports.useBackendMoneyMarketPosition = useBackendMoneyMarketPosition;
1517
1806
  exports.useBackendOrderbook = useBackendOrderbook;
1518
1807
  exports.useBackendUserIntents = useBackendUserIntents;
1808
+ exports.useBitcoinBalance = useBitcoinBalance;
1519
1809
  exports.useBorrow = useBorrow;
1520
1810
  exports.useBridge = useBridge;
1521
1811
  exports.useBridgeAllowance = useBridgeAllowance;
@@ -1528,6 +1818,8 @@ exports.useConvertedAssets = useConvertedAssets;
1528
1818
  exports.useCreateLimitOrder = useCreateLimitOrder;
1529
1819
  exports.useDeriveUserWalletAddress = useDeriveUserWalletAddress;
1530
1820
  exports.useEstimateGas = useEstimateGas;
1821
+ exports.useExpiredUtxos = useExpiredUtxos;
1822
+ exports.useFundTradingWallet = useFundTradingWallet;
1531
1823
  exports.useGetBridgeableAmount = useGetBridgeableAmount;
1532
1824
  exports.useGetBridgeableTokens = useGetBridgeableTokens;
1533
1825
  exports.useGetUserHubWalletAddress = useGetUserHubWalletAddress;
@@ -1542,6 +1834,9 @@ exports.useMigrate = useMigrate;
1542
1834
  exports.useMigrationAllowance = useMigrationAllowance;
1543
1835
  exports.useMigrationApprove = useMigrationApprove;
1544
1836
  exports.useQuote = useQuote;
1837
+ exports.useRadfiAuth = useRadfiAuth;
1838
+ exports.useRadfiSession = useRadfiSession;
1839
+ exports.useRenewUtxos = useRenewUtxos;
1545
1840
  exports.useRepay = useRepay;
1546
1841
  exports.useRequestTrustline = useRequestTrustline;
1547
1842
  exports.useReservesData = useReservesData;
@@ -1560,6 +1855,7 @@ exports.useSupply = useSupply;
1560
1855
  exports.useSwap = useSwap;
1561
1856
  exports.useSwapAllowance = useSwapAllowance;
1562
1857
  exports.useSwapApprove = useSwapApprove;
1858
+ exports.useTradingWalletBalance = useTradingWalletBalance;
1563
1859
  exports.useUnstake = useUnstake;
1564
1860
  exports.useUnstakeAllowance = useUnstakeAllowance;
1565
1861
  exports.useUnstakeApprove = useUnstakeApprove;