@sodax/dapp-kit 1.3.1-beta-rc1 → 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(
@@ -205,6 +220,258 @@ function useSpokeProvider(spokeChainId, walletProvider) {
205
220
  }, [spokeChainId, xChainType, walletProvider, rpcConfig]);
206
221
  return spokeProvider;
207
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
+ }
208
475
  function useBorrow() {
209
476
  const { sodax } = useSodaxContext();
210
477
  return reactQuery.useMutation({
@@ -1521,6 +1788,11 @@ var SodaxProvider = ({ children, testnet = false, config, rpcConfig }) => {
1521
1788
  exports.MIGRATION_MODE_BNUSD = MIGRATION_MODE_BNUSD;
1522
1789
  exports.MIGRATION_MODE_ICX_SODA = MIGRATION_MODE_ICX_SODA;
1523
1790
  exports.SodaxProvider = SodaxProvider;
1791
+ exports.clearRadfiSession = clearRadfiSession;
1792
+ exports.isAccessTokenExpired = isAccessTokenExpired;
1793
+ exports.isRefreshTokenExpired = isRefreshTokenExpired;
1794
+ exports.loadRadfiSession = loadRadfiSession;
1795
+ exports.saveRadfiSession = saveRadfiSession;
1524
1796
  exports.useAToken = useAToken;
1525
1797
  exports.useATokensBalances = useATokensBalances;
1526
1798
  exports.useBackendAllMoneyMarketAssets = useBackendAllMoneyMarketAssets;
@@ -1533,6 +1805,7 @@ exports.useBackendMoneyMarketAssetSuppliers = useBackendMoneyMarketAssetSupplier
1533
1805
  exports.useBackendMoneyMarketPosition = useBackendMoneyMarketPosition;
1534
1806
  exports.useBackendOrderbook = useBackendOrderbook;
1535
1807
  exports.useBackendUserIntents = useBackendUserIntents;
1808
+ exports.useBitcoinBalance = useBitcoinBalance;
1536
1809
  exports.useBorrow = useBorrow;
1537
1810
  exports.useBridge = useBridge;
1538
1811
  exports.useBridgeAllowance = useBridgeAllowance;
@@ -1545,6 +1818,8 @@ exports.useConvertedAssets = useConvertedAssets;
1545
1818
  exports.useCreateLimitOrder = useCreateLimitOrder;
1546
1819
  exports.useDeriveUserWalletAddress = useDeriveUserWalletAddress;
1547
1820
  exports.useEstimateGas = useEstimateGas;
1821
+ exports.useExpiredUtxos = useExpiredUtxos;
1822
+ exports.useFundTradingWallet = useFundTradingWallet;
1548
1823
  exports.useGetBridgeableAmount = useGetBridgeableAmount;
1549
1824
  exports.useGetBridgeableTokens = useGetBridgeableTokens;
1550
1825
  exports.useGetUserHubWalletAddress = useGetUserHubWalletAddress;
@@ -1559,6 +1834,9 @@ exports.useMigrate = useMigrate;
1559
1834
  exports.useMigrationAllowance = useMigrationAllowance;
1560
1835
  exports.useMigrationApprove = useMigrationApprove;
1561
1836
  exports.useQuote = useQuote;
1837
+ exports.useRadfiAuth = useRadfiAuth;
1838
+ exports.useRadfiSession = useRadfiSession;
1839
+ exports.useRenewUtxos = useRenewUtxos;
1562
1840
  exports.useRepay = useRepay;
1563
1841
  exports.useRequestTrustline = useRequestTrustline;
1564
1842
  exports.useReservesData = useReservesData;
@@ -1577,6 +1855,7 @@ exports.useSupply = useSupply;
1577
1855
  exports.useSwap = useSwap;
1578
1856
  exports.useSwapAllowance = useSwapAllowance;
1579
1857
  exports.useSwapApprove = useSwapApprove;
1858
+ exports.useTradingWalletBalance = useTradingWalletBalance;
1580
1859
  exports.useUnstake = useUnstake;
1581
1860
  exports.useUnstakeAllowance = useUnstakeAllowance;
1582
1861
  exports.useUnstakeApprove = useUnstakeApprove;