@silentswap/react 0.0.78 → 0.0.80

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.
@@ -582,7 +582,7 @@ export function useBridgeExecution(walletClient, connector, solanaConnector, sol
582
582
  */
583
583
  const executeEvmBridge = useCallback(async (sourceChainId, sourceTokenAddress, sourceAmount, usdcAmount, depositParams, evmSignerAddress, // EVM signer address (must match quote request signer, used for deposit calldata)
584
584
  evmSenderAddress, // Optional EVM sender address (used for bridge quotes, matches Svelte's s0x_sender)
585
- provider) => {
585
+ provider, allowanceTarget) => {
586
586
  try {
587
587
  if (!walletClient || !connector) {
588
588
  throw new Error('Wallet client and connector required for EVM bridge execution');
@@ -658,7 +658,7 @@ export function useBridgeExecution(walletClient, connector, solanaConnector, sol
658
658
  // DeBridge will provide its own allowanceTarget from the response if needed.
659
659
  try {
660
660
  return await executeDebridgeBridge(sourceChainId, sourceTokenAddress, isSourceNative, bridgeUsdcAmount, depositCalldata, evmSignerAddress, // Use EVM signer address for deposit calldata
661
- '', // allowanceTarget not needed - approval handled before bridge execution
661
+ allowanceTarget ?? '', // From solve phase; create-tx with enableEstimate:false is used for approval when needed
662
662
  depositorAddress, // Pass environment-based depositor address
663
663
  walletClient, connector, setCurrentStep, onStatus);
664
664
  }
@@ -835,56 +835,63 @@ walletClient, connector, setCurrentStep, onStatus) {
835
835
  // For deBridge, we need to use the wallet account address, not the extracted sender address
836
836
  // This ensures the transaction can be properly executed by the connected wallet
837
837
  const evmUserForBridge = getWalletAccountAddress(walletClient);
838
+ // Match Svelte Form.svelte / silentswap.ts: do NOT send enableEstimate so the API returns the tx
839
+ // (with allowanceTarget/allowanceValue). Approve if needed and retry, then send. Same as Svelte.
840
+ const debridgeParams = {
841
+ account: evmUserForBridge,
842
+ srcChainId: sourceChainId,
843
+ dstChainId: NI_CHAIN_ID_AVALANCHE,
844
+ srcChainTokenIn: isSourceNative ? S0X_ADDR_EVM_ZERO : sourceTokenAddress,
845
+ dstChainTokenOut: S0X_ADDR_USDC_AVALANCHE,
846
+ srcChainTokenInAmount: 'auto',
847
+ dstChainTokenOutAmount: `${BigInt(bridgeUsdcAmount)}`,
848
+ dstChainTokenOutRecipient: depositorAddress,
849
+ prependOperatingExpenses: true,
850
+ srcChainOrderAuthorityAddress: evmUserForBridge,
851
+ srcChainRefundAddress: evmUserForBridge,
852
+ dstChainOrderAuthorityAddress: evmUserForBridge,
853
+ dlnHook: JSON.stringify({
854
+ type: 'evm_transaction_call',
855
+ data: {
856
+ to: depositorAddress,
857
+ calldata: depositCalldata,
858
+ gas: 500_000,
859
+ },
860
+ }),
861
+ // omit enableEstimate so API returns tx with allowanceTarget (matches Svelte debridge_order call)
862
+ };
838
863
  while (retryCount < maxRetries) {
839
- debridgeQuote = await fetchDebridgeOrder({
840
- account: evmUserForBridge, // Use wallet account address (must match transaction sender)
841
- srcChainId: sourceChainId,
842
- dstChainId: NI_CHAIN_ID_AVALANCHE,
843
- srcChainTokenIn: isSourceNative ? S0X_ADDR_EVM_ZERO : sourceTokenAddress,
844
- dstChainTokenOut: S0X_ADDR_USDC_AVALANCHE,
845
- srcChainTokenInAmount: 'auto',
846
- dstChainTokenOutAmount: `${BigInt(bridgeUsdcAmount)}`,
847
- dstChainTokenOutRecipient: depositorAddress,
848
- prependOperatingExpenses: true,
849
- enableEstimate: true,
850
- srcChainOrderAuthorityAddress: evmUserForBridge, // Use wallet account address (must match transaction sender)
851
- srcChainRefundAddress: evmUserForBridge, // Use wallet account address (must match transaction sender)
852
- dstChainOrderAuthorityAddress: evmUserForBridge, // Use wallet account address (must match transaction sender)
853
- dlnHook: JSON.stringify({
854
- type: 'evm_transaction_call',
855
- data: {
856
- to: depositorAddress,
857
- calldata: depositCalldata,
858
- gas: 500_000,
859
- },
860
- }),
861
- });
864
+ debridgeQuote = await fetchDebridgeOrder(debridgeParams);
862
865
  debridgeTx = debridgeQuote.tx;
863
866
  debridgeResponse = debridgeQuote;
864
- // Check if approval is needed
865
- const targetAllowance = debridgeTx.allowanceTarget || allowanceTarget;
867
+ // If approval needed, approve and retry (matches Svelte: "if(g_debridge.tx.allowanceTarget) { await approve_spender(...); continue; }")
868
+ // Prefer API response; use allowanceTarget param (from solve phase) as fallback when API omits it
869
+ const targetAllowance = debridgeTx?.allowanceTarget || allowanceTarget;
866
870
  if (targetAllowance && !isSourceNative) {
867
- const allowanceValue = debridgeTx.allowanceValue;
868
- if (!allowanceValue) {
871
+ const allowanceValue = debridgeTx?.allowanceValue;
872
+ if (debridgeTx?.allowanceTarget && !allowanceValue) {
869
873
  throw new Error('DeBridge response missing allowance value');
870
874
  }
871
875
  setCurrentStep('Approving token spending');
872
876
  onStatus?.('Approving token spending');
873
- // Switch to source chain for approval
874
877
  const { publicClient } = await ensureChainAndCreateClient(sourceChainId, walletClient, connector);
878
+ // Match Svelte: allowance(owner, spender) where owner is the wallet that sends approve (s0x_sender)
875
879
  const currentAllowance = (await publicClient.readContract({
876
880
  address: sourceTokenAddress,
877
881
  abi: erc20Abi,
878
882
  functionName: 'allowance',
879
- args: [evmSignerAddress, targetAllowance],
883
+ args: [evmUserForBridge, targetAllowance],
880
884
  }));
881
- // Approve if needed
882
- if (currentAllowance < BigInt(allowanceValue)) {
885
+ // Need approval: when API gave a value, use it; otherwise (fallback from param) approve if allowance is zero
886
+ const needsApproval = allowanceValue
887
+ ? currentAllowance < BigInt(allowanceValue)
888
+ : currentAllowance === 0n;
889
+ if (needsApproval) {
883
890
  const hash = await walletClient.writeContract({
884
891
  address: sourceTokenAddress,
885
892
  abi: erc20Abi,
886
893
  functionName: 'approve',
887
- args: [targetAllowance, BigInt(allowanceValue)],
894
+ args: [targetAllowance, XG_UINT256_MAX],
888
895
  account: walletClient.account,
889
896
  chain: null,
890
897
  });
@@ -893,9 +900,8 @@ walletClient, connector, setCurrentStep, onStatus) {
893
900
  retryCount++;
894
901
  continue;
895
902
  }
896
- // Check price impact
903
+ // Check price impact (matches Svelte)
897
904
  const impactPercent = (100 * (debridgeQuote.usdPriceImpact ?? 0)) / (debridgeQuote.estimation.srcChainTokenIn.approximateUsdValue || 1);
898
- // TODO: check negative impact
899
905
  if (impactPercent > X_MAX_IMPACT_PERCENT) {
900
906
  throw new Error(`Price impact across bridge too high: ${impactPercent.toFixed(2)}%`);
901
907
  }
@@ -904,11 +910,11 @@ walletClient, connector, setCurrentStep, onStatus) {
904
910
  if (!debridgeQuote) {
905
911
  throw new Error('Failed to get deBridge quote after approvals');
906
912
  }
907
- setCurrentStep('Switching to source chain');
908
- onStatus?.('Switching to source chain');
909
- setCurrentStep('Sending bridge transaction');
910
- onStatus?.('Sending bridge transaction');
911
- // Send deBridge transaction
913
+ // Match Svelte: "Requesting deposit..." then ensure_chain + send (no separate "Switching"/"Sending" steps;
914
+ // sendTransactionAndWait does the chain switch and sets its own steps)
915
+ setCurrentStep('Requesting deposit...');
916
+ onStatus?.('Requesting deposit...');
917
+ // Send deBridge transaction (sendTransactionAndWait switches to sourceChainId and sends)
912
918
  console.log('Sending deBridge transaction:', {
913
919
  to: debridgeQuote.tx.to,
914
920
  value: debridgeQuote.tx.value,
@@ -1,136 +1,11 @@
1
- import type { SilentSwapClient } from '@silentswap/sdk';
2
- /**
3
- * Output stage enum matching Svelte's OutputStage (string values)
4
- */
5
- export declare enum OutputStage {
6
- NONE = "NONE",
7
- INIT = "INIT",
8
- FUNDED = "FUNDED",
9
- REDEEMED = "REDEEMED",
10
- IBC_SENT = "IBC_SENT",
11
- IBC_RCVD = "IBC_RCVD",
12
- BRIDGE_SENT = "BRIDGE_SENT",
13
- BRIDGE_CFRM = "BRIDGE_CFRM",
14
- BRIDGE_RCVD = "BRIDGE_RCVD",
15
- SWAP_USDC_GAS = "SWAP_USDC_GAS",
16
- SWAP_USDC_TRG = "SWAP_USDC_TRG",
17
- LTRL_TRG_SENT = "LTRL_TRG_SENT",
18
- LTRL_TRG_RCVD = "LTRL_TRG_RCVD",
19
- SWAP_TRG_DST = "SWAP_TRG_DST",
20
- XFER_TRG_DST = "XFER_TRG_DST",
21
- REFUND_NATIVE = "REFUND_NATIVE",
22
- FINALIZED = "FINALIZED"
23
- }
24
- /**
25
- * Deposit information
26
- */
27
- export type OrderDeposit = {
28
- amount: string;
29
- timestamp: number;
30
- duration: number;
31
- orderId?: string;
32
- tx?: string;
33
- };
34
- /**
35
- * Output status information
36
- */
37
- export type OutputStatus = {
38
- index: number;
39
- stage: OutputStage;
40
- timestamp: number;
41
- recipient?: string;
42
- asset?: {
43
- caip19: string;
44
- amount: string;
45
- decimals: number;
46
- priceUsd?: number;
47
- };
48
- txs?: OrderTransactions;
49
- };
50
- /**
51
- * Order transactions
52
- */
53
- export type OrderTransactions = {
54
- RECEIPT?: {
55
- chain: string;
56
- txId: string;
57
- };
58
- REFUND?: {
59
- chain: string;
60
- txId: string;
61
- };
62
- };
63
1
  /**
64
- * Order tracking status (matches Svelte's OrderStatus)
65
- */
66
- export type OrderStatus = {
67
- priority?: string;
68
- signer: string;
69
- deposit: OrderDeposit;
70
- outputs: Array<{
71
- stage: OutputStage;
72
- timestamp: number;
73
- asset: string;
74
- value: string;
75
- recipient: string;
76
- txs?: OrderTransactions;
77
- output?: {
78
- caip19: string;
79
- amount: string;
80
- decimals: number;
81
- priceUsd?: number;
82
- };
83
- }>;
84
- metadata?: {
85
- sourceAsset?: {
86
- caip19: string;
87
- amount: string;
88
- };
89
- sourceSender?: {
90
- contactId: string;
91
- };
92
- };
93
- };
94
- /**
95
- * Status update types (matches Svelte's StatusUpdate)
96
- */
97
- export type StatusUpdate = {
98
- type: 'deposit';
99
- data: OrderDeposit;
100
- } | {
101
- type: 'stage';
102
- data: {
103
- orderId: string;
104
- index: number;
105
- stage: OutputStage;
106
- timestamp: number;
107
- asset?: {
108
- caip19: string;
109
- amount: string;
110
- decimals: number;
111
- priceUsd?: number;
112
- };
113
- };
114
- } | {
115
- type: 'transaction';
116
- data: {
117
- orderId: string;
118
- index: number;
119
- chain: string;
120
- txId: string;
121
- kind: keyof OrderTransactions;
122
- };
123
- } | {
124
- type: 'error';
125
- data: {
126
- orderId: string;
127
- message: string;
128
- index?: number;
129
- };
130
- };
131
- /**
132
- * JSON-RPC error type
2
+ * Order tracking via WebSocket state and connections live in OrdersContext.
3
+ * This hook subscribes to tracking for (orderId, auth) and returns the state from context.
133
4
  */
5
+ import type { SilentSwapClient } from '@silentswap/sdk';
6
+ import { type OutputStage, type OrderDeposit, type OutputStatus, type OrderStatus } from '../../contexts/orderTrackingTypes.js';
7
+ export { OutputStage, getStatusTextFromStage, getProgressFromStage, getOrderTrackingCacheKey, } from '../../contexts/orderTrackingTypes.js';
8
+ export type { OrderDeposit, OutputStatus, OrderTransactions, OrderStatus, StatusUpdate, OrderTrackingState, OrderTrackingOptions, } from '../../contexts/orderTrackingTypes.js';
134
9
  export type JsonRpcError = {
135
10
  code: number;
136
11
  message: string;
@@ -143,6 +18,8 @@ export interface UseOrderTrackingOptions {
143
18
  onStatusUpdate?: (status: OrderStatus) => void;
144
19
  onError?: (error: Error) => void;
145
20
  onComplete?: () => void;
21
+ /** Fetch USD price for an asset when priceUsd is missing from WS response */
22
+ fetchAssetPrice?: (caip19: string) => Promise<number>;
146
23
  }
147
24
  export interface UseOrderTrackingReturn {
148
25
  isConnected: boolean;
@@ -160,15 +37,4 @@ export interface UseOrderTrackingReturn {
160
37
  getStatusText: (stage: OutputStage) => string;
161
38
  getProgress: (stage: OutputStage) => number;
162
39
  }
163
- /**
164
- * Get human-readable status text from output stage
165
- */
166
- export declare function getStatusTextFromStage(stage: OutputStage): string;
167
- /**
168
- * Get progress value (0-1) from output stage
169
- */
170
- export declare function getProgressFromStage(stage: OutputStage): number;
171
- /**
172
- * React hook for tracking SilentSwap orders via WebSocket
173
- */
174
- export declare function useOrderTracking({ client, orderId: initialOrderId, viewingAuth: initialAuth, onStatusUpdate, onError, onComplete, }?: UseOrderTrackingOptions): UseOrderTrackingReturn;
40
+ export declare function useOrderTracking({ client, orderId: initialOrderId, viewingAuth: initialAuth, onStatusUpdate, onError, onComplete, fetchAssetPrice, }?: UseOrderTrackingOptions): UseOrderTrackingReturn;