@hongming-wang/usdc-bridge-widget 0.2.1 → 0.2.2
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 +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +19 -8
- package/dist/index.mjs +19 -8
- package/package.json +1 -1
- package/src/BridgeWidget.tsx +4 -3
- package/src/__tests__/BridgeWidget.test.tsx +31 -0
- package/src/constants.ts +1 -0
- package/src/hooks.ts +22 -10
- package/src/types.ts +6 -1
- package/src/useBridge.ts +5 -2
package/dist/index.d.mts
CHANGED
|
@@ -59,7 +59,12 @@ interface BridgeChainConfig {
|
|
|
59
59
|
chain: Chain;
|
|
60
60
|
/** USDC token contract address on this chain (checksummed) */
|
|
61
61
|
usdcAddress: `0x${string}`;
|
|
62
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Circle TokenMessenger contract address for CCTP transfers.
|
|
64
|
+
* While marked optional for type flexibility, this address is required
|
|
65
|
+
* for bridging to work. The widget will use TOKEN_MESSENGER_ADDRESSES
|
|
66
|
+
* from constants.ts as defaults if not provided via createChainConfig().
|
|
67
|
+
*/
|
|
63
68
|
tokenMessengerAddress?: `0x${string}`;
|
|
64
69
|
/** URL for the chain's icon/logo image (optional, falls back to initial) */
|
|
65
70
|
iconUrl?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -59,7 +59,12 @@ interface BridgeChainConfig {
|
|
|
59
59
|
chain: Chain;
|
|
60
60
|
/** USDC token contract address on this chain (checksummed) */
|
|
61
61
|
usdcAddress: `0x${string}`;
|
|
62
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Circle TokenMessenger contract address for CCTP transfers.
|
|
64
|
+
* While marked optional for type flexibility, this address is required
|
|
65
|
+
* for bridging to work. The widget will use TOKEN_MESSENGER_ADDRESSES
|
|
66
|
+
* from constants.ts as defaults if not provided via createChainConfig().
|
|
67
|
+
*/
|
|
63
68
|
tokenMessengerAddress?: `0x${string}`;
|
|
64
69
|
/** URL for the chain's icon/logo image (optional, falls back to initial) */
|
|
65
70
|
iconUrl?: string;
|
package/dist/index.js
CHANGED
|
@@ -127,6 +127,7 @@ var USDC_ADDRESSES = {
|
|
|
127
127
|
// Sonic
|
|
128
128
|
480: "0x79A02482A880bCE3F13e09Da970dC34db4CD24d1",
|
|
129
129
|
// World Chain
|
|
130
|
+
// Note: Monad is defined but not yet supported by Circle Bridge Kit SDK
|
|
130
131
|
10200: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
|
|
131
132
|
// Monad
|
|
132
133
|
1329: "0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392",
|
|
@@ -617,6 +618,8 @@ function useBridgeQuote(sourceChainId, destChainId, amount) {
|
|
|
617
618
|
}
|
|
618
619
|
|
|
619
620
|
// src/hooks.ts
|
|
621
|
+
var _useBridgeEstimateWarned = false;
|
|
622
|
+
var _useFormatNumberWarned = false;
|
|
620
623
|
function useUSDCBalance(chainConfig) {
|
|
621
624
|
const { address } = (0, import_wagmi2.useAccount)();
|
|
622
625
|
const {
|
|
@@ -685,6 +688,8 @@ function useAllUSDCBalances(chainConfigs) {
|
|
|
685
688
|
return {
|
|
686
689
|
balances,
|
|
687
690
|
isLoading,
|
|
691
|
+
// Cast to () => void since we don't need the Promise return value.
|
|
692
|
+
// The caller just needs to trigger a refetch, not await it.
|
|
688
693
|
refetch
|
|
689
694
|
};
|
|
690
695
|
}
|
|
@@ -767,9 +772,12 @@ function useUSDCAllowance(chainConfig, spenderAddress) {
|
|
|
767
772
|
}
|
|
768
773
|
function useBridgeEstimate(sourceChainId, destChainId, amount) {
|
|
769
774
|
(0, import_react2.useEffect)(() => {
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
775
|
+
if (!_useBridgeEstimateWarned) {
|
|
776
|
+
_useBridgeEstimateWarned = true;
|
|
777
|
+
console.warn(
|
|
778
|
+
"[DEPRECATED] useBridgeEstimate is deprecated and will be removed in a future version. Use useBridgeQuote from './useBridge' instead."
|
|
779
|
+
);
|
|
780
|
+
}
|
|
773
781
|
}, []);
|
|
774
782
|
const [estimate, setEstimate] = (0, import_react2.useState)(null);
|
|
775
783
|
const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
|
|
@@ -825,9 +833,12 @@ function useBridgeEstimate(sourceChainId, destChainId, amount) {
|
|
|
825
833
|
}
|
|
826
834
|
function useFormatNumber() {
|
|
827
835
|
(0, import_react2.useEffect)(() => {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
836
|
+
if (!_useFormatNumberWarned) {
|
|
837
|
+
_useFormatNumberWarned = true;
|
|
838
|
+
console.warn(
|
|
839
|
+
"[DEPRECATED] useFormatNumber is deprecated and will be removed in a future version. Use the formatNumber utility function from './utils' directly instead."
|
|
840
|
+
);
|
|
841
|
+
}
|
|
831
842
|
}, []);
|
|
832
843
|
return (0, import_react2.useCallback)(
|
|
833
844
|
(value, decimals = 2) => {
|
|
@@ -1995,10 +2006,10 @@ function BridgeWidget({
|
|
|
1995
2006
|
sourceChainConfig
|
|
1996
2007
|
);
|
|
1997
2008
|
(0, import_react3.useEffect)(() => {
|
|
1998
|
-
if (address) {
|
|
2009
|
+
if (isConnected && address) {
|
|
1999
2010
|
refetchAllBalances();
|
|
2000
2011
|
}
|
|
2001
|
-
}, [address, refetchAllBalances]);
|
|
2012
|
+
}, [isConnected, address, refetchAllBalances]);
|
|
2002
2013
|
const { bridge: executeBridge, state: bridgeState, reset: resetBridge } = useBridge();
|
|
2003
2014
|
const { isLoading: isConfirming, isSuccess } = (0, import_wagmi3.useWaitForTransactionReceipt)({
|
|
2004
2015
|
hash: txHash
|
package/dist/index.mjs
CHANGED
|
@@ -47,6 +47,7 @@ var USDC_ADDRESSES = {
|
|
|
47
47
|
// Sonic
|
|
48
48
|
480: "0x79A02482A880bCE3F13e09Da970dC34db4CD24d1",
|
|
49
49
|
// World Chain
|
|
50
|
+
// Note: Monad is defined but not yet supported by Circle Bridge Kit SDK
|
|
50
51
|
10200: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
|
|
51
52
|
// Monad
|
|
52
53
|
1329: "0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392",
|
|
@@ -537,6 +538,8 @@ function useBridgeQuote(sourceChainId, destChainId, amount) {
|
|
|
537
538
|
}
|
|
538
539
|
|
|
539
540
|
// src/hooks.ts
|
|
541
|
+
var _useBridgeEstimateWarned = false;
|
|
542
|
+
var _useFormatNumberWarned = false;
|
|
540
543
|
function useUSDCBalance(chainConfig) {
|
|
541
544
|
const { address } = useAccount2();
|
|
542
545
|
const {
|
|
@@ -605,6 +608,8 @@ function useAllUSDCBalances(chainConfigs) {
|
|
|
605
608
|
return {
|
|
606
609
|
balances,
|
|
607
610
|
isLoading,
|
|
611
|
+
// Cast to () => void since we don't need the Promise return value.
|
|
612
|
+
// The caller just needs to trigger a refetch, not await it.
|
|
608
613
|
refetch
|
|
609
614
|
};
|
|
610
615
|
}
|
|
@@ -687,9 +692,12 @@ function useUSDCAllowance(chainConfig, spenderAddress) {
|
|
|
687
692
|
}
|
|
688
693
|
function useBridgeEstimate(sourceChainId, destChainId, amount) {
|
|
689
694
|
useEffect2(() => {
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
695
|
+
if (!_useBridgeEstimateWarned) {
|
|
696
|
+
_useBridgeEstimateWarned = true;
|
|
697
|
+
console.warn(
|
|
698
|
+
"[DEPRECATED] useBridgeEstimate is deprecated and will be removed in a future version. Use useBridgeQuote from './useBridge' instead."
|
|
699
|
+
);
|
|
700
|
+
}
|
|
693
701
|
}, []);
|
|
694
702
|
const [estimate, setEstimate] = useState2(null);
|
|
695
703
|
const [isLoading, setIsLoading] = useState2(false);
|
|
@@ -745,9 +753,12 @@ function useBridgeEstimate(sourceChainId, destChainId, amount) {
|
|
|
745
753
|
}
|
|
746
754
|
function useFormatNumber() {
|
|
747
755
|
useEffect2(() => {
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
756
|
+
if (!_useFormatNumberWarned) {
|
|
757
|
+
_useFormatNumberWarned = true;
|
|
758
|
+
console.warn(
|
|
759
|
+
"[DEPRECATED] useFormatNumber is deprecated and will be removed in a future version. Use the formatNumber utility function from './utils' directly instead."
|
|
760
|
+
);
|
|
761
|
+
}
|
|
751
762
|
}, []);
|
|
752
763
|
return useCallback2(
|
|
753
764
|
(value, decimals = 2) => {
|
|
@@ -1934,10 +1945,10 @@ function BridgeWidget({
|
|
|
1934
1945
|
sourceChainConfig
|
|
1935
1946
|
);
|
|
1936
1947
|
useEffect3(() => {
|
|
1937
|
-
if (address) {
|
|
1948
|
+
if (isConnected && address) {
|
|
1938
1949
|
refetchAllBalances();
|
|
1939
1950
|
}
|
|
1940
|
-
}, [address, refetchAllBalances]);
|
|
1951
|
+
}, [isConnected, address, refetchAllBalances]);
|
|
1941
1952
|
const { bridge: executeBridge, state: bridgeState, reset: resetBridge } = useBridge();
|
|
1942
1953
|
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt2({
|
|
1943
1954
|
hash: txHash
|
package/package.json
CHANGED
package/src/BridgeWidget.tsx
CHANGED
|
@@ -804,12 +804,12 @@ export function BridgeWidget({
|
|
|
804
804
|
sourceChainConfig
|
|
805
805
|
);
|
|
806
806
|
|
|
807
|
-
// Refetch balances when wallet connects or address changes
|
|
807
|
+
// Refetch balances when wallet connects, disconnects, or address changes
|
|
808
808
|
useEffect(() => {
|
|
809
|
-
if (address) {
|
|
809
|
+
if (isConnected && address) {
|
|
810
810
|
refetchAllBalances();
|
|
811
811
|
}
|
|
812
|
-
}, [address, refetchAllBalances]);
|
|
812
|
+
}, [isConnected, address, refetchAllBalances]);
|
|
813
813
|
|
|
814
814
|
// Bridge hook
|
|
815
815
|
const { bridge: executeBridge, state: bridgeState, reset: resetBridge } = useBridge();
|
|
@@ -1027,6 +1027,7 @@ export function BridgeWidget({
|
|
|
1027
1027
|
onConnectWallet();
|
|
1028
1028
|
} else {
|
|
1029
1029
|
// Warn when onConnectWallet is not provided - helps developers debug
|
|
1030
|
+
// Note: Bundlers typically strip console.warn in production builds
|
|
1030
1031
|
console.warn(
|
|
1031
1032
|
"[BridgeWidget] onConnectWallet prop is not provided. " +
|
|
1032
1033
|
"Please provide onConnectWallet to handle wallet connection " +
|
|
@@ -293,6 +293,37 @@ describe("BridgeWidget - Disconnected State", () => {
|
|
|
293
293
|
expect(screen.queryByText(/1,000.00 USDC/)).toBeNull();
|
|
294
294
|
expect(screen.queryByText(/500.00 USDC/)).toBeNull();
|
|
295
295
|
});
|
|
296
|
+
|
|
297
|
+
it("refetches balances when isConnected changes to true", () => {
|
|
298
|
+
const refetchMock = vi.fn();
|
|
299
|
+
mockUseAllUSDCBalances.mockReturnValue({
|
|
300
|
+
balances: {},
|
|
301
|
+
isLoading: false,
|
|
302
|
+
refetch: refetchMock,
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// Start disconnected
|
|
306
|
+
mockUseAccount.mockReturnValue({
|
|
307
|
+
address: undefined,
|
|
308
|
+
isConnected: false,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const { rerender } = render(<BridgeWidget />);
|
|
312
|
+
|
|
313
|
+
// Refetch should not be called when disconnected
|
|
314
|
+
expect(refetchMock).not.toHaveBeenCalled();
|
|
315
|
+
|
|
316
|
+
// Simulate wallet connection
|
|
317
|
+
mockUseAccount.mockReturnValue({
|
|
318
|
+
address: "0x1234567890123456789012345678901234567890",
|
|
319
|
+
isConnected: true,
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
rerender(<BridgeWidget />);
|
|
323
|
+
|
|
324
|
+
// Refetch should be called after connection
|
|
325
|
+
expect(refetchMock).toHaveBeenCalled();
|
|
326
|
+
});
|
|
296
327
|
});
|
|
297
328
|
|
|
298
329
|
describe("BridgeWidget - Chain Switch Required", () => {
|
package/src/constants.ts
CHANGED
|
@@ -29,6 +29,7 @@ export const USDC_ADDRESSES: Record<number, `0x${string}`> = {
|
|
|
29
29
|
130: "0x078D782b760474a361dDA0AF3839290b0EF57AD6", // Unichain
|
|
30
30
|
146: "0x29219dd400f2Bf60E5a23d13Be72B486D4038894", // Sonic
|
|
31
31
|
480: "0x79A02482A880bCE3F13e09Da970dC34db4CD24d1", // World Chain
|
|
32
|
+
// Note: Monad is defined but not yet supported by Circle Bridge Kit SDK
|
|
32
33
|
10200: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603", // Monad
|
|
33
34
|
1329: "0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392", // Sei
|
|
34
35
|
50: "0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1", // XDC
|
package/src/hooks.ts
CHANGED
|
@@ -12,6 +12,10 @@ import { USDC_DECIMALS } from "./constants";
|
|
|
12
12
|
import { formatNumber } from "./utils";
|
|
13
13
|
import { getBridgeChain } from "./useBridge";
|
|
14
14
|
|
|
15
|
+
// Module-level flags to emit deprecation warnings only once per session
|
|
16
|
+
let _useBridgeEstimateWarned = false;
|
|
17
|
+
let _useFormatNumberWarned = false;
|
|
18
|
+
|
|
15
19
|
/**
|
|
16
20
|
* Hook to get USDC balance for a specific chain
|
|
17
21
|
*/
|
|
@@ -119,6 +123,8 @@ export function useAllUSDCBalances(chainConfigs: BridgeChainConfig[]): {
|
|
|
119
123
|
return {
|
|
120
124
|
balances,
|
|
121
125
|
isLoading,
|
|
126
|
+
// Cast to () => void since we don't need the Promise return value.
|
|
127
|
+
// The caller just needs to trigger a refetch, not await it.
|
|
122
128
|
refetch: refetch as () => void,
|
|
123
129
|
};
|
|
124
130
|
}
|
|
@@ -249,12 +255,15 @@ export function useBridgeEstimate(
|
|
|
249
255
|
destChainId: number | undefined,
|
|
250
256
|
amount: string
|
|
251
257
|
) {
|
|
252
|
-
// Emit deprecation warning once
|
|
258
|
+
// Emit deprecation warning once per session
|
|
253
259
|
useEffect(() => {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
260
|
+
if (!_useBridgeEstimateWarned) {
|
|
261
|
+
_useBridgeEstimateWarned = true;
|
|
262
|
+
console.warn(
|
|
263
|
+
"[DEPRECATED] useBridgeEstimate is deprecated and will be removed in a future version. " +
|
|
264
|
+
"Use useBridgeQuote from './useBridge' instead."
|
|
265
|
+
);
|
|
266
|
+
}
|
|
258
267
|
}, []);
|
|
259
268
|
|
|
260
269
|
const [estimate, setEstimate] = useState<BridgeEstimate | null>(null);
|
|
@@ -341,12 +350,15 @@ export function useBridgeEstimate(
|
|
|
341
350
|
* const formatted = formatNumber(1234.56, 2);
|
|
342
351
|
*/
|
|
343
352
|
export function useFormatNumber() {
|
|
344
|
-
// Emit deprecation warning once
|
|
353
|
+
// Emit deprecation warning once per session
|
|
345
354
|
useEffect(() => {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
355
|
+
if (!_useFormatNumberWarned) {
|
|
356
|
+
_useFormatNumberWarned = true;
|
|
357
|
+
console.warn(
|
|
358
|
+
"[DEPRECATED] useFormatNumber is deprecated and will be removed in a future version. " +
|
|
359
|
+
"Use the formatNumber utility function from './utils' directly instead."
|
|
360
|
+
);
|
|
361
|
+
}
|
|
350
362
|
}, []);
|
|
351
363
|
|
|
352
364
|
return useCallback(
|
package/src/types.ts
CHANGED
|
@@ -55,7 +55,12 @@ export interface BridgeChainConfig {
|
|
|
55
55
|
chain: Chain;
|
|
56
56
|
/** USDC token contract address on this chain (checksummed) */
|
|
57
57
|
usdcAddress: `0x${string}`;
|
|
58
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Circle TokenMessenger contract address for CCTP transfers.
|
|
60
|
+
* While marked optional for type flexibility, this address is required
|
|
61
|
+
* for bridging to work. The widget will use TOKEN_MESSENGER_ADDRESSES
|
|
62
|
+
* from constants.ts as defaults if not provided via createChainConfig().
|
|
63
|
+
*/
|
|
59
64
|
tokenMessengerAddress?: `0x${string}`;
|
|
60
65
|
/** URL for the chain's icon/logo image (optional, falls back to initial) */
|
|
61
66
|
iconUrl?: string;
|
package/src/useBridge.ts
CHANGED
|
@@ -5,7 +5,9 @@ import { createViemAdapterFromProvider } from "@circle-fin/adapter-viem-v2";
|
|
|
5
5
|
import type { BridgeChainConfig } from "./types";
|
|
6
6
|
import type { EIP1193Provider } from "viem";
|
|
7
7
|
|
|
8
|
-
// Maximum number of events to retain to prevent memory growth
|
|
8
|
+
// Maximum number of events to retain to prevent memory growth.
|
|
9
|
+
// 100 events is sufficient to track a full bridge lifecycle (approve, burn, attestation, mint)
|
|
10
|
+
// while preventing unbounded memory growth in long-running sessions.
|
|
9
11
|
const MAX_EVENTS = 100;
|
|
10
12
|
|
|
11
13
|
// Chain ID to BridgeChain enum mapping
|
|
@@ -256,7 +258,8 @@ export function useBridge(): UseBridgeResult {
|
|
|
256
258
|
kit.off("fetchAttestation", handleFetchAttestation);
|
|
257
259
|
kit.off("mint", handleMint);
|
|
258
260
|
} catch {
|
|
259
|
-
//
|
|
261
|
+
// Bridge Kit's off() method may not exist in all versions or may throw
|
|
262
|
+
// if listeners were already removed. Safe to ignore during cleanup.
|
|
260
263
|
}
|
|
261
264
|
};
|
|
262
265
|
|