@multiversx/sdk-dapp-liquidity 2.0.0 → 2.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/helpers/assertRateConfirmationMatchesIntent.d.ts +8 -0
  2. package/helpers/assertRateConfirmationMatchesIntent.js +24 -0
  3. package/helpers/assertRateConfirmationMatchesIntent.mjs +23 -0
  4. package/helpers/index.d.ts +2 -0
  5. package/helpers/index.js +4 -0
  6. package/helpers/index.mjs +4 -0
  7. package/helpers/safeImageUrl.d.ts +1 -0
  8. package/helpers/safeImageUrl.js +24 -0
  9. package/helpers/safeImageUrl.mjs +23 -0
  10. package/helpers/serializeTransaction.js +1 -1
  11. package/helpers/serializeTransaction.mjs +1 -1
  12. package/helpers/tests/assertRateConfirmationMatchesIntent.spec.d.ts +1 -0
  13. package/helpers/tests/assertRateConfirmationMatchesIntent.spec.js +64 -0
  14. package/helpers/tests/assertRateConfirmationMatchesIntent.spec.mjs +62 -0
  15. package/helpers/tests/safeImageUrl.spec.d.ts +1 -0
  16. package/helpers/tests/safeImageUrl.spec.js +49 -0
  17. package/helpers/tests/safeImageUrl.spec.mjs +47 -0
  18. package/helpers/tests/serializeTransaction.spec.d.ts +1 -0
  19. package/helpers/tests/serializeTransaction.spec.js +37 -0
  20. package/helpers/tests/serializeTransaction.spec.mjs +35 -0
  21. package/index.js +7 -3
  22. package/index.mjs +10 -6
  23. package/package.json +13 -8
  24. package/react.esm-7GsOwMPq.js +11815 -0
  25. package/react.esm-CU-Iqz8D.mjs +11796 -0
  26. package/reactjs/adapters/SuiAdapter.d.ts +14 -0
  27. package/reactjs/adapters/SuiAdapter.js +31 -2
  28. package/reactjs/adapters/SuiAdapter.mjs +31 -2
  29. package/reactjs/components/BridgeForm/Deposit.js +9 -7
  30. package/reactjs/components/BridgeForm/Deposit.mjs +8 -6
  31. package/reactjs/components/BridgeForm/Transfer.js +8 -6
  32. package/reactjs/components/BridgeForm/Transfer.mjs +7 -5
  33. package/reactjs/components/BridgeHistory/BridgeHistory.js +20 -6
  34. package/reactjs/components/BridgeHistory/BridgeHistory.mjs +20 -6
  35. package/reactjs/components/Connect/BridgeConnectButton.js +2 -1
  36. package/reactjs/components/Connect/BridgeConnectButton.mjs +2 -1
  37. package/reactjs/components/CopyButton/CopyButton.mjs +2 -2
  38. package/reactjs/components/TokenSelector/components/ChainSelect/components/ChainOptionLabel.js +5 -1
  39. package/reactjs/components/TokenSelector/components/ChainSelect/components/ChainOptionLabel.mjs +6 -2
  40. package/reactjs/components/TokenSelector/components/ChainSelect/components/SelectedChainOption.js +5 -1
  41. package/reactjs/components/TokenSelector/components/ChainSelect/components/SelectedChainOption.mjs +6 -2
  42. package/reactjs/components/TokenSelector/components/TokenIcon.js +2 -1
  43. package/reactjs/components/TokenSelector/components/TokenIcon.mjs +2 -1
  44. package/reactjs/context/Web3AppProvider.js +4 -2
  45. package/reactjs/context/Web3AppProvider.mjs +6 -4
  46. package/reactjs/hooks/tests/useGenericSignMessage.spec.d.ts +1 -0
  47. package/reactjs/hooks/tests/useGenericSignMessage.spec.js +69 -0
  48. package/reactjs/hooks/tests/useGenericSignMessage.spec.mjs +67 -0
  49. package/reactjs/hooks/tests/useSignTransaction.spec.d.ts +1 -0
  50. package/reactjs/hooks/tests/useSignTransaction.spec.js +196 -0
  51. package/reactjs/hooks/tests/useSignTransaction.spec.mjs +194 -0
  52. package/reactjs/hooks/useBridgeFormik.js +5 -0
  53. package/reactjs/hooks/useBridgeFormik.mjs +5 -0
  54. package/reactjs/hooks/useFetchTokens.js +4 -2
  55. package/reactjs/hooks/useFetchTokens.mjs +4 -2
  56. package/reactjs/hooks/useGenericSignMessage.js +23 -3
  57. package/reactjs/hooks/useGenericSignMessage.mjs +23 -3
  58. package/reactjs/hooks/useSignTransaction.js +27 -1
  59. package/reactjs/hooks/useSignTransaction.mjs +28 -2
  60. package/reactjs/index.js +3 -3
  61. package/reactjs/index.mjs +6 -6
  62. package/reactjs/init/init.d.ts +1 -0
  63. package/reactjs/init/init.js +11 -3
  64. package/reactjs/init/init.mjs +11 -3
  65. package/reactjs/queries/index.js +3 -3
  66. package/reactjs/queries/index.mjs +7 -7
  67. package/reactjs/queries/useCheckAccount.query.js +1 -1
  68. package/reactjs/queries/useCheckAccount.query.mjs +1 -1
  69. package/reactjs/queries/useGetAllTokens.query.js +1 -1
  70. package/reactjs/queries/useGetAllTokens.query.mjs +1 -1
  71. package/reactjs/queries/useGetChains.query.js +1 -1
  72. package/reactjs/queries/useGetChains.query.mjs +1 -1
  73. package/reactjs/queries/useGetHistory.query.d.ts +1 -1
  74. package/reactjs/queries/useGetHistory.query.js +10 -9
  75. package/reactjs/queries/useGetHistory.query.mjs +12 -11
  76. package/reactjs/queries/useGetMvxTokensBalances.query.d.ts +1 -1
  77. package/reactjs/queries/useGetMvxTokensBalances.query.js +9 -14
  78. package/reactjs/queries/useGetMvxTokensBalances.query.mjs +12 -17
  79. package/reactjs/queries/useGetNonMvxTokensBalances.query.d.ts +1 -1
  80. package/reactjs/queries/useGetNonMvxTokensBalances.query.js +8 -8
  81. package/reactjs/queries/useGetNonMvxTokensBalances.query.mjs +11 -11
  82. package/types/errors.d.ts +3 -0
  83. package/types/errors.js +10 -0
  84. package/types/errors.mjs +9 -0
  85. package/reactjs/hooks/useSignTransaction.d.ts +0 -511
@@ -0,0 +1,194 @@
1
+ import { useAppKitProvider, useAppKitAccount } from "@reown/appkit/react";
2
+ import { r as renderHook } from "../../../react.esm-CU-Iqz8D.mjs";
3
+ import { useSendTransaction } from "wagmi";
4
+ import { useSignTransaction } from "../useSignTransaction.mjs";
5
+ jest.mock("@reown/appkit-adapter-solana/react", () => ({
6
+ useAppKitConnection: jest.fn(() => ({ connection: null }))
7
+ }));
8
+ jest.mock("@solana/web3.js", () => ({
9
+ PublicKey: jest.fn(),
10
+ Transaction: jest.fn(() => ({ add: jest.fn().mockReturnThis() })),
11
+ TransactionInstruction: jest.fn()
12
+ }));
13
+ const mockUseAppKitProvider = jest.mocked(useAppKitProvider);
14
+ const mockUseAppKitAccount = jest.mocked(useAppKitAccount);
15
+ const mockUseSendTransaction = jest.mocked(useSendTransaction);
16
+ beforeEach(() => {
17
+ mockUseSendTransaction.mockReturnValue({
18
+ data: void 0,
19
+ sendTransactionAsync: jest.fn(),
20
+ error: null,
21
+ isError: false,
22
+ isIdle: true,
23
+ isPending: false,
24
+ isSuccess: false,
25
+ reset: jest.fn(),
26
+ sendTransaction: jest.fn(),
27
+ status: "idle",
28
+ variables: void 0,
29
+ context: void 0,
30
+ failureCount: 0,
31
+ failureReason: null,
32
+ isPaused: false,
33
+ submittedAt: 0,
34
+ mutate: jest.fn(),
35
+ mutateAsync: jest.fn()
36
+ });
37
+ });
38
+ const CONNECTED_SUI_ADDRESS = "0xabc123def456aaa000111222333444555666777888999aaabbbcccdddeeefff00";
39
+ function setupSuiMocks(suiRequest) {
40
+ mockUseAppKitProvider.mockImplementation((namespace) => {
41
+ if (namespace === "sui") {
42
+ return { walletProvider: { request: suiRequest } };
43
+ }
44
+ return { walletProvider: void 0 };
45
+ });
46
+ mockUseAppKitAccount.mockImplementation((opts) => {
47
+ if ((opts == null ? void 0 : opts.namespace) === "sui") {
48
+ return {
49
+ address: CONNECTED_SUI_ADDRESS,
50
+ isConnected: true,
51
+ status: "connected"
52
+ };
53
+ }
54
+ return {
55
+ address: void 0,
56
+ isConnected: false,
57
+ status: "disconnected"
58
+ };
59
+ });
60
+ }
61
+ describe("useSignTransaction — signSuiTransaction", () => {
62
+ const validBase64 = btoa("valid transaction bytes");
63
+ beforeEach(() => {
64
+ mockUseSendTransaction.mockReturnValue({
65
+ data: void 0,
66
+ sendTransactionAsync: jest.fn(),
67
+ error: null,
68
+ isError: false,
69
+ isIdle: true,
70
+ isPending: false,
71
+ isSuccess: false,
72
+ reset: jest.fn(),
73
+ sendTransaction: jest.fn(),
74
+ status: "idle",
75
+ variables: void 0,
76
+ context: void 0,
77
+ failureCount: 0,
78
+ failureReason: null,
79
+ isPaused: false,
80
+ submittedAt: 0,
81
+ mutate: jest.fn(),
82
+ mutateAsync: jest.fn()
83
+ });
84
+ });
85
+ it("succeeds with valid base64 payload", async () => {
86
+ const mockRequest = jest.fn().mockResolvedValue({ signature: "sui-sig-ok" });
87
+ setupSuiMocks(mockRequest);
88
+ const { result } = renderHook(() => useSignTransaction());
89
+ const sig = await result.current.sui.signTransaction({
90
+ transaction: validBase64,
91
+ address: CONNECTED_SUI_ADDRESS
92
+ });
93
+ expect(sig).toBe("sui-sig-ok");
94
+ expect(mockRequest).toHaveBeenCalledWith(
95
+ expect.objectContaining({ method: "sui_signTransaction" })
96
+ );
97
+ });
98
+ it("throws when payload is not valid base64", async () => {
99
+ const mockRequest = jest.fn();
100
+ setupSuiMocks(mockRequest);
101
+ const { result } = renderHook(() => useSignTransaction());
102
+ await expect(
103
+ result.current.sui.signTransaction({
104
+ transaction: "not-valid-base64!!!",
105
+ address: CONNECTED_SUI_ADDRESS
106
+ })
107
+ ).rejects.toThrow("not valid base64");
108
+ expect(mockRequest).not.toHaveBeenCalled();
109
+ });
110
+ it("throws when payload exceeds 32 KiB", async () => {
111
+ const mockRequest = jest.fn();
112
+ setupSuiMocks(mockRequest);
113
+ const largeBytes = new Uint8Array(32 * 1024 + 1);
114
+ const largeBase64 = btoa(String.fromCharCode(...largeBytes));
115
+ const { result } = renderHook(() => useSignTransaction());
116
+ await expect(
117
+ result.current.sui.signTransaction({
118
+ transaction: largeBase64,
119
+ address: CONNECTED_SUI_ADDRESS
120
+ })
121
+ ).rejects.toThrow("maximum size");
122
+ expect(mockRequest).not.toHaveBeenCalled();
123
+ });
124
+ it("throws when payload is an empty string", async () => {
125
+ const mockRequest = jest.fn();
126
+ setupSuiMocks(mockRequest);
127
+ const { result } = renderHook(() => useSignTransaction());
128
+ await expect(
129
+ result.current.sui.signTransaction({
130
+ transaction: "",
131
+ address: CONNECTED_SUI_ADDRESS
132
+ })
133
+ ).rejects.toThrow("No Sui transaction bytes provided");
134
+ expect(mockRequest).not.toHaveBeenCalled();
135
+ });
136
+ });
137
+ describe("useSignTransaction — signPSBT", () => {
138
+ it("forwards signInputs verbatim to btcWalletProvider.signPSBT", async () => {
139
+ const mockSignPSBT = jest.fn().mockResolvedValue({ psbt: "signed-psbt" });
140
+ mockUseAppKitProvider.mockImplementation((namespace) => {
141
+ if (namespace === "bip122") {
142
+ return { walletProvider: { signPSBT: mockSignPSBT } };
143
+ }
144
+ return { walletProvider: void 0 };
145
+ });
146
+ const { result } = renderHook(() => useSignTransaction());
147
+ const signInputs = [
148
+ {
149
+ address: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
150
+ index: 0,
151
+ sighashTypes: [1]
152
+ }
153
+ ];
154
+ const params = {
155
+ psbt: "base64psbt==",
156
+ signInputs: [...signInputs],
157
+ broadcast: false
158
+ };
159
+ const originalSignInputs = params.signInputs;
160
+ const psbt = await result.current.bitcoin.signTransaction(params);
161
+ expect(mockSignPSBT).toHaveBeenCalledWith(
162
+ expect.objectContaining({
163
+ signInputs: [
164
+ {
165
+ address: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
166
+ index: 0,
167
+ sighashTypes: [1]
168
+ }
169
+ ]
170
+ })
171
+ );
172
+ expect(mockSignPSBT).not.toHaveBeenCalledWith(
173
+ expect.objectContaining({ signInputs: [] })
174
+ );
175
+ expect(params.signInputs).toBe(originalSignInputs);
176
+ expect(params.signInputs).toEqual(signInputs);
177
+ expect(psbt).toBe("signed-psbt");
178
+ });
179
+ it("throws when btcWalletProvider is not available", async () => {
180
+ mockUseAppKitProvider.mockImplementation(
181
+ () => ({
182
+ walletProvider: void 0
183
+ })
184
+ );
185
+ const { result } = renderHook(() => useSignTransaction());
186
+ await expect(
187
+ result.current.bitcoin.signTransaction({
188
+ psbt: "base64psbt==",
189
+ signInputs: [],
190
+ broadcast: false
191
+ })
192
+ ).rejects.toThrow("user is disconnected");
193
+ });
194
+ });
@@ -7,6 +7,7 @@ const yup = require("yup");
7
7
  const reactjs_hooks_validation_useAmountSchema = require("./validation/useAmountSchema.js");
8
8
  const reactjs_hooks_validation_useSecondAmountSchema = require("./validation/useSecondAmountSchema.js");
9
9
  const api_confirmRate = require("../../api/confirmRate.js");
10
+ const helpers_assertRateConfirmationMatchesIntent = require("../../helpers/assertRateConfirmationMatchesIntent.js");
10
11
  const helpers_getApiURL = require("../../helpers/getApiURL.js");
11
12
  const types_providerType = require("../../types/providerType.js");
12
13
  const reactjs_context_useWeb3App = require("../context/useWeb3App.js");
@@ -76,6 +77,10 @@ const useBridgeFormik = ({
76
77
  pendingSigningRef.current = false;
77
78
  return;
78
79
  }
80
+ helpers_assertRateConfirmationMatchesIntent.assertRateConfirmationMatchesIntent(
81
+ { fromChainId: values.fromChainId ?? "", sender: sender ?? "" },
82
+ transactions
83
+ );
79
84
  resetSwapForm();
80
85
  onSubmit({
81
86
  transactions,
@@ -4,6 +4,7 @@ import { object, string } from "yup";
4
4
  import { useAmountSchema } from "./validation/useAmountSchema.mjs";
5
5
  import { useSecondAmountSchema } from "./validation/useSecondAmountSchema.mjs";
6
6
  import { confirmRate } from "../../api/confirmRate.mjs";
7
+ import { assertRateConfirmationMatchesIntent } from "../../helpers/assertRateConfirmationMatchesIntent.mjs";
7
8
  import { getApiURL } from "../../helpers/getApiURL.mjs";
8
9
  import { ProviderType } from "../../types/providerType.mjs";
9
10
  import { useWeb3App } from "../context/useWeb3App.mjs";
@@ -73,6 +74,10 @@ const useBridgeFormik = ({
73
74
  pendingSigningRef.current = false;
74
75
  return;
75
76
  }
77
+ assertRateConfirmationMatchesIntent(
78
+ { fromChainId: values.fromChainId ?? "", sender: sender ?? "" },
79
+ transactions
80
+ );
76
81
  resetSwapForm();
77
82
  onSubmit({
78
83
  transactions,
@@ -17,6 +17,8 @@ const useFetchTokens = ({
17
17
  const bridgeApiChainId = reactjs_hooks_useBridgeApiChainId.useBridgeApiChainId();
18
18
  const account = reactjs_hooks_useAccount.useAccount();
19
19
  const { nativeAuthToken, bridgeOnly } = reactjs_context_useWeb3App.useWeb3App();
20
+ const invalidateMvxTokensBalancesQuery = reactjs_queries_useGetMvxTokensBalances_query.useInvalidateMvxTokensBalancesQuery();
21
+ const invalidateEvmTokensBalances = reactjs_queries_useGetNonMvxTokensBalances_query.useInvalidateEvmTokensBalances();
20
22
  const {
21
23
  data: tokens,
22
24
  isLoading: isTokensLoading,
@@ -90,14 +92,14 @@ const useFetchTokens = ({
90
92
  }, [nonMvxTokens, nonMvxTokensBalances]);
91
93
  React.useEffect(() => {
92
94
  if (mvxAddress) {
93
- reactjs_queries_useGetMvxTokensBalances_query.invalidateMvxTokensBalancesQuery();
95
+ invalidateMvxTokensBalancesQuery();
94
96
  }
95
97
  }, [refetchTrigger, mvxAddress]);
96
98
  React.useEffect(() => {
97
99
  if (!account.address) {
98
100
  return;
99
101
  }
100
- reactjs_queries_useGetNonMvxTokensBalances_query.invalidateEvmTokensBalances();
102
+ invalidateEvmTokensBalances();
101
103
  }, [refetchTrigger, bridgeApiChainId, account.address]);
102
104
  return {
103
105
  isTokensLoading,
@@ -4,8 +4,8 @@ import { useBridgeApiChainId } from "./useBridgeApiChainId.mjs";
4
4
  import { MVX_CHAIN_IDS } from "../../constants/index.mjs";
5
5
  import { useWeb3App } from "../context/useWeb3App.mjs";
6
6
  import { useGetAllTokensQuery } from "../queries/useGetAllTokens.query.mjs";
7
- import { useGetMvxTokensBalancesQuery, invalidateMvxTokensBalancesQuery } from "../queries/useGetMvxTokensBalances.query.mjs";
8
- import { useGetNonMvxTokensBalancesQuery, invalidateEvmTokensBalances } from "../queries/useGetNonMvxTokensBalances.query.mjs";
7
+ import { useInvalidateMvxTokensBalancesQuery, useGetMvxTokensBalancesQuery } from "../queries/useGetMvxTokensBalances.query.mjs";
8
+ import { useInvalidateEvmTokensBalances, useGetNonMvxTokensBalancesQuery } from "../queries/useGetNonMvxTokensBalances.query.mjs";
9
9
  const useFetchTokens = ({
10
10
  mvxAddress,
11
11
  mvxApiURL,
@@ -14,6 +14,8 @@ const useFetchTokens = ({
14
14
  const bridgeApiChainId = useBridgeApiChainId();
15
15
  const account = useAccount();
16
16
  const { nativeAuthToken, bridgeOnly } = useWeb3App();
17
+ const invalidateMvxTokensBalancesQuery = useInvalidateMvxTokensBalancesQuery();
18
+ const invalidateEvmTokensBalances = useInvalidateEvmTokensBalances();
17
19
  const {
18
20
  data: tokens,
19
21
  isLoading: isTokensLoading,
@@ -35,11 +35,31 @@ const useGenericSignMessage = () => {
35
35
  throw new Error("Sui wallet not connected");
36
36
  }
37
37
  const encodedMessage = new TextEncoder().encode(message);
38
+ const params = {
39
+ message: Buffer.from(encodedMessage).toString("base64")
40
+ };
41
+ const MAX_SUI_MESSAGE_BYTES = 32 * 1024;
42
+ if (!params.message || typeof params.message !== "string") {
43
+ throw new Error(
44
+ "Invalid Sui message: payload must be a non-empty string"
45
+ );
46
+ }
47
+ try {
48
+ const decoded = atob(params.message);
49
+ if (decoded.length > MAX_SUI_MESSAGE_BYTES) {
50
+ throw new Error(
51
+ `Sui message payload exceeds maximum size of ${MAX_SUI_MESSAGE_BYTES} bytes`
52
+ );
53
+ }
54
+ } catch (e) {
55
+ if (e instanceof Error && e.message.includes("maximum size")) {
56
+ throw e;
57
+ }
58
+ throw new Error("Invalid Sui message: payload is not valid base64");
59
+ }
38
60
  const result = await suiWalletProvider.request({
39
61
  method: "sui_signPersonalMessage",
40
- params: {
41
- message: Buffer.from(encodedMessage).toString("base64")
42
- }
62
+ params
43
63
  });
44
64
  return result.signature;
45
65
  }
@@ -32,11 +32,31 @@ const useGenericSignMessage = () => {
32
32
  throw new Error("Sui wallet not connected");
33
33
  }
34
34
  const encodedMessage = new TextEncoder().encode(message);
35
+ const params = {
36
+ message: Buffer.from(encodedMessage).toString("base64")
37
+ };
38
+ const MAX_SUI_MESSAGE_BYTES = 32 * 1024;
39
+ if (!params.message || typeof params.message !== "string") {
40
+ throw new Error(
41
+ "Invalid Sui message: payload must be a non-empty string"
42
+ );
43
+ }
44
+ try {
45
+ const decoded = atob(params.message);
46
+ if (decoded.length > MAX_SUI_MESSAGE_BYTES) {
47
+ throw new Error(
48
+ `Sui message payload exceeds maximum size of ${MAX_SUI_MESSAGE_BYTES} bytes`
49
+ );
50
+ }
51
+ } catch (e) {
52
+ if (e instanceof Error && e.message.includes("maximum size")) {
53
+ throw e;
54
+ }
55
+ throw new Error("Invalid Sui message: payload is not valid base64");
56
+ }
35
57
  const result = await suiWalletProvider.request({
36
58
  method: "sui_signPersonalMessage",
37
- params: {
38
- message: Buffer.from(encodedMessage).toString("base64")
39
- }
59
+ params
40
60
  });
41
61
  return result.signature;
42
62
  }
@@ -15,6 +15,9 @@ const useSignTransaction = () => {
15
15
  const { walletProvider: solWalletProvider } = react$1.useAppKitProvider("solana");
16
16
  const { walletProvider: btcWalletProvider } = react$1.useAppKitProvider("bip122");
17
17
  const { walletProvider: suiWalletProvider } = react$1.useAppKitProvider("sui");
18
+ const { address: suiAddress } = react$1.useAppKitAccount({
19
+ namespace: "sui"
20
+ });
18
21
  const signTransactionSolanaTransaction = async ({
19
22
  feePayer,
20
23
  instructions,
@@ -36,7 +39,6 @@ const useSignTransaction = () => {
36
39
  if (!btcWalletProvider) {
37
40
  throw Error("user is disconnected");
38
41
  }
39
- params.signInputs = [];
40
42
  const signature = await btcWalletProvider.signPSBT(params);
41
43
  return signature.psbt;
42
44
  };
@@ -51,6 +53,30 @@ const useSignTransaction = () => {
51
53
  if (!suiWalletProvider) {
52
54
  throw new Error("Sui wallet not connected");
53
55
  }
56
+ const MAX_SUI_PAYLOAD_BYTES = 32 * 1024;
57
+ if (!transaction || typeof transaction !== "string") {
58
+ throw new Error(
59
+ "Invalid Sui transaction: payload must be a non-empty string"
60
+ );
61
+ }
62
+ try {
63
+ const decoded = atob(transaction);
64
+ if (decoded.length > MAX_SUI_PAYLOAD_BYTES) {
65
+ throw new Error(
66
+ `Sui transaction payload exceeds maximum size of ${MAX_SUI_PAYLOAD_BYTES} bytes`
67
+ );
68
+ }
69
+ } catch (e) {
70
+ if (e instanceof Error && e.message.includes("maximum size")) {
71
+ throw e;
72
+ }
73
+ throw new Error("Invalid Sui transaction: payload is not valid base64");
74
+ }
75
+ if (suiParams.address && suiAddress && suiParams.address !== suiAddress) {
76
+ throw new Error(
77
+ `Sui address mismatch: expected ${suiAddress}, got ${suiParams.address}`
78
+ );
79
+ }
54
80
  const result = await suiWalletProvider.request({
55
81
  method: "sui_signTransaction",
56
82
  params: {
@@ -1,4 +1,4 @@
1
- import { useAppKitProvider } from "@reown/appkit/react";
1
+ import { useAppKitProvider, useAppKitAccount } from "@reown/appkit/react";
2
2
  import { useAppKitConnection } from "@reown/appkit-adapter-solana/react";
3
3
  import { TransactionInstruction, Transaction, PublicKey } from "@solana/web3.js";
4
4
  import { useSendTransaction } from "wagmi";
@@ -12,6 +12,9 @@ const useSignTransaction = () => {
12
12
  const { walletProvider: solWalletProvider } = useAppKitProvider("solana");
13
13
  const { walletProvider: btcWalletProvider } = useAppKitProvider("bip122");
14
14
  const { walletProvider: suiWalletProvider } = useAppKitProvider("sui");
15
+ const { address: suiAddress } = useAppKitAccount({
16
+ namespace: "sui"
17
+ });
15
18
  const signTransactionSolanaTransaction = async ({
16
19
  feePayer,
17
20
  instructions,
@@ -33,7 +36,6 @@ const useSignTransaction = () => {
33
36
  if (!btcWalletProvider) {
34
37
  throw Error("user is disconnected");
35
38
  }
36
- params.signInputs = [];
37
39
  const signature = await btcWalletProvider.signPSBT(params);
38
40
  return signature.psbt;
39
41
  };
@@ -48,6 +50,30 @@ const useSignTransaction = () => {
48
50
  if (!suiWalletProvider) {
49
51
  throw new Error("Sui wallet not connected");
50
52
  }
53
+ const MAX_SUI_PAYLOAD_BYTES = 32 * 1024;
54
+ if (!transaction || typeof transaction !== "string") {
55
+ throw new Error(
56
+ "Invalid Sui transaction: payload must be a non-empty string"
57
+ );
58
+ }
59
+ try {
60
+ const decoded = atob(transaction);
61
+ if (decoded.length > MAX_SUI_PAYLOAD_BYTES) {
62
+ throw new Error(
63
+ `Sui transaction payload exceeds maximum size of ${MAX_SUI_PAYLOAD_BYTES} bytes`
64
+ );
65
+ }
66
+ } catch (e) {
67
+ if (e instanceof Error && e.message.includes("maximum size")) {
68
+ throw e;
69
+ }
70
+ throw new Error("Invalid Sui transaction: payload is not valid base64");
71
+ }
72
+ if (suiParams.address && suiAddress && suiParams.address !== suiAddress) {
73
+ throw new Error(
74
+ `Sui address mismatch: expected ${suiAddress}, got ${suiParams.address}`
75
+ );
76
+ }
51
77
  const result = await suiWalletProvider.request({
52
78
  method: "sui_signTransaction",
53
79
  params: {
package/reactjs/index.js CHANGED
@@ -123,12 +123,12 @@ exports.SuiMethods = reactjs_init_init.SuiMethods;
123
123
  exports.init = reactjs_init_init.init;
124
124
  exports.useGetAllTokensQuery = reactjs_queries_useGetAllTokens_query.useGetAllTokensQuery;
125
125
  exports.useGetChainsQuery = reactjs_queries_useGetChains_query.useGetChainsQuery;
126
- exports.invalidateEvmTokensBalances = reactjs_queries_useGetNonMvxTokensBalances_query.invalidateEvmTokensBalances;
127
126
  exports.useGetNonMvxTokensBalancesQuery = reactjs_queries_useGetNonMvxTokensBalances_query.useGetNonMvxTokensBalancesQuery;
128
- exports.invalidateHistoryQuery = reactjs_queries_useGetHistory_query.invalidateHistoryQuery;
127
+ exports.useInvalidateEvmTokensBalances = reactjs_queries_useGetNonMvxTokensBalances_query.useInvalidateEvmTokensBalances;
129
128
  exports.useGetHistoryQuery = reactjs_queries_useGetHistory_query.useGetHistoryQuery;
130
- exports.invalidateMvxTokensBalancesQuery = reactjs_queries_useGetMvxTokensBalances_query.invalidateMvxTokensBalancesQuery;
129
+ exports.useInvalidateHistoryQuery = reactjs_queries_useGetHistory_query.useInvalidateHistoryQuery;
131
130
  exports.useGetMvxTokensBalancesQuery = reactjs_queries_useGetMvxTokensBalances_query.useGetMvxTokensBalancesQuery;
131
+ exports.useInvalidateMvxTokensBalancesQuery = reactjs_queries_useGetMvxTokensBalances_query.useInvalidateMvxTokensBalancesQuery;
132
132
  exports.useGetRateMutation = reactjs_queries_useGetRate_mutation.useGetRateMutation;
133
133
  exports.delay = reactjs_utils_delay.delay;
134
134
  exports.formatAmount = reactjs_utils_formatAmount.formatAmount;
package/reactjs/index.mjs CHANGED
@@ -48,9 +48,9 @@ import { useSuiConnect } from "./hooks/useSuiConnect.mjs";
48
48
  import { SuiMethods, init } from "./init/init.mjs";
49
49
  import { useGetAllTokensQuery } from "./queries/useGetAllTokens.query.mjs";
50
50
  import { useGetChainsQuery } from "./queries/useGetChains.query.mjs";
51
- import { invalidateEvmTokensBalances, useGetNonMvxTokensBalancesQuery } from "./queries/useGetNonMvxTokensBalances.query.mjs";
52
- import { invalidateHistoryQuery, useGetHistoryQuery } from "./queries/useGetHistory.query.mjs";
53
- import { invalidateMvxTokensBalancesQuery, useGetMvxTokensBalancesQuery } from "./queries/useGetMvxTokensBalances.query.mjs";
51
+ import { useGetNonMvxTokensBalancesQuery, useInvalidateEvmTokensBalances } from "./queries/useGetNonMvxTokensBalances.query.mjs";
52
+ import { useGetHistoryQuery, useInvalidateHistoryQuery } from "./queries/useGetHistory.query.mjs";
53
+ import { useGetMvxTokensBalancesQuery, useInvalidateMvxTokensBalancesQuery } from "./queries/useGetMvxTokensBalances.query.mjs";
54
54
  import { useGetRateMutation } from "./queries/useGetRate.mutation.mjs";
55
55
  import { delay } from "./utils/delay.mjs";
56
56
  import { formatAmount } from "./utils/formatAmount.mjs";
@@ -109,9 +109,6 @@ export {
109
109
  getQueryClient,
110
110
  hasEnoughFunds,
111
111
  init,
112
- invalidateEvmTokensBalances,
113
- invalidateHistoryQuery,
114
- invalidateMvxTokensBalancesQuery,
115
112
  isStringFloat,
116
113
  mxClsx,
117
114
  pipe,
@@ -144,6 +141,9 @@ export {
144
141
  useGetMvxTokensBalancesQuery,
145
142
  useGetNonMvxTokensBalancesQuery,
146
143
  useGetRateMutation,
144
+ useInvalidateEvmTokensBalances,
145
+ useInvalidateHistoryQuery,
146
+ useInvalidateMvxTokensBalancesQuery,
147
147
  useResolveTokenChain,
148
148
  useSecondAmountSchema,
149
149
  useSendTransactions,
@@ -14,6 +14,7 @@ export type InitOptions = {
14
14
  mvxChainId: '31' | '44' | '54';
15
15
  suiEnvironment?: 'mainnet' | 'testnet' | 'devnet';
16
16
  suiFeaturedWalletIds?: string[];
17
+ expectedSuiAddress?: string;
17
18
  };
18
19
  export declare enum SuiMethods {
19
20
  SIGN_TRANSACTION = "sui_signTransaction",
@@ -82,7 +82,7 @@ var SuiMethods = /* @__PURE__ */ ((SuiMethods2) => {
82
82
  return SuiMethods2;
83
83
  })(SuiMethods || {});
84
84
  async function init(options) {
85
- var _a, _b, _c, _d;
85
+ var _a, _b, _c, _d, _e;
86
86
  const store = store_inMemoryStore.InMemoryStore.getInstance();
87
87
  store.setItem("apiURL", options.apiURL);
88
88
  store.setItem("bridgeURL", options.bridgeURL);
@@ -114,7 +114,12 @@ async function init(options) {
114
114
  if (options.suiEnvironment) {
115
115
  const suiNetwork = suiNetworkDefinitions[options.suiEnvironment];
116
116
  const explicitSuiCaip = suiNetwork.caipNetworkId ?? `sui:${suiNetwork.id}`;
117
- adapters.push(new reactjs_adapters_SuiAdapter.SuiAdapter({ explicitCaipChains: [explicitSuiCaip] }));
117
+ adapters.push(
118
+ new reactjs_adapters_SuiAdapter.SuiAdapter({
119
+ explicitCaipChains: [explicitSuiCaip],
120
+ expectedSuiAddress: options.expectedSuiAddress
121
+ })
122
+ );
118
123
  }
119
124
  const appKit = react.createAppKit({
120
125
  ...options.appKitOptions,
@@ -126,7 +131,10 @@ async function init(options) {
126
131
  const wc = await appKit.getUniversalProvider();
127
132
  const suiNs = (_b = (_a = wc == null ? void 0 : wc.session) == null ? void 0 : _a.namespaces) == null ? void 0 : _b["sui"];
128
133
  if (((_c = suiNs == null ? void 0 : suiNs.accounts) == null ? void 0 : _c.length) && !appKit.getCaipAddress("sui")) {
129
- await ((_d = appKit.syncWalletConnectAccount) == null ? void 0 : _d.call(appKit));
134
+ const firstSuiAddress = (_d = suiNs.accounts[0]) == null ? void 0 : _d.split(":").pop();
135
+ if (!options.expectedSuiAddress || firstSuiAddress === options.expectedSuiAddress) {
136
+ await ((_e = appKit.syncWalletConnectAccount) == null ? void 0 : _e.call(appKit));
137
+ }
130
138
  }
131
139
  }
132
140
  return {
@@ -62,7 +62,7 @@ var SuiMethods = /* @__PURE__ */ ((SuiMethods2) => {
62
62
  return SuiMethods2;
63
63
  })(SuiMethods || {});
64
64
  async function init(options) {
65
- var _a, _b, _c, _d;
65
+ var _a, _b, _c, _d, _e;
66
66
  const store = InMemoryStore.getInstance();
67
67
  store.setItem("apiURL", options.apiURL);
68
68
  store.setItem("bridgeURL", options.bridgeURL);
@@ -94,7 +94,12 @@ async function init(options) {
94
94
  if (options.suiEnvironment) {
95
95
  const suiNetwork = suiNetworkDefinitions[options.suiEnvironment];
96
96
  const explicitSuiCaip = suiNetwork.caipNetworkId ?? `sui:${suiNetwork.id}`;
97
- adapters.push(new SuiAdapter({ explicitCaipChains: [explicitSuiCaip] }));
97
+ adapters.push(
98
+ new SuiAdapter({
99
+ explicitCaipChains: [explicitSuiCaip],
100
+ expectedSuiAddress: options.expectedSuiAddress
101
+ })
102
+ );
98
103
  }
99
104
  const appKit = createAppKit({
100
105
  ...options.appKitOptions,
@@ -106,7 +111,10 @@ async function init(options) {
106
111
  const wc = await appKit.getUniversalProvider();
107
112
  const suiNs = (_b = (_a = wc == null ? void 0 : wc.session) == null ? void 0 : _a.namespaces) == null ? void 0 : _b["sui"];
108
113
  if (((_c = suiNs == null ? void 0 : suiNs.accounts) == null ? void 0 : _c.length) && !appKit.getCaipAddress("sui")) {
109
- await ((_d = appKit.syncWalletConnectAccount) == null ? void 0 : _d.call(appKit));
114
+ const firstSuiAddress = (_d = suiNs.accounts[0]) == null ? void 0 : _d.split(":").pop();
115
+ if (!options.expectedSuiAddress || firstSuiAddress === options.expectedSuiAddress) {
116
+ await ((_e = appKit.syncWalletConnectAccount) == null ? void 0 : _e.call(appKit));
117
+ }
110
118
  }
111
119
  }
112
120
  return {
@@ -9,10 +9,10 @@ const reactjs_queries_useGetMvxTokensBalances_query = require("./useGetMvxTokens
9
9
  const reactjs_queries_useGetRate_mutation = require("./useGetRate.mutation.js");
10
10
  exports.useGetAllTokensQuery = reactjs_queries_useGetAllTokens_query.useGetAllTokensQuery;
11
11
  exports.useGetChainsQuery = reactjs_queries_useGetChains_query.useGetChainsQuery;
12
- exports.invalidateEvmTokensBalances = reactjs_queries_useGetNonMvxTokensBalances_query.invalidateEvmTokensBalances;
13
12
  exports.useGetNonMvxTokensBalancesQuery = reactjs_queries_useGetNonMvxTokensBalances_query.useGetNonMvxTokensBalancesQuery;
14
- exports.invalidateHistoryQuery = reactjs_queries_useGetHistory_query.invalidateHistoryQuery;
13
+ exports.useInvalidateEvmTokensBalances = reactjs_queries_useGetNonMvxTokensBalances_query.useInvalidateEvmTokensBalances;
15
14
  exports.useGetHistoryQuery = reactjs_queries_useGetHistory_query.useGetHistoryQuery;
16
- exports.invalidateMvxTokensBalancesQuery = reactjs_queries_useGetMvxTokensBalances_query.invalidateMvxTokensBalancesQuery;
15
+ exports.useInvalidateHistoryQuery = reactjs_queries_useGetHistory_query.useInvalidateHistoryQuery;
17
16
  exports.useGetMvxTokensBalancesQuery = reactjs_queries_useGetMvxTokensBalances_query.useGetMvxTokensBalancesQuery;
17
+ exports.useInvalidateMvxTokensBalancesQuery = reactjs_queries_useGetMvxTokensBalances_query.useInvalidateMvxTokensBalancesQuery;
18
18
  exports.useGetRateMutation = reactjs_queries_useGetRate_mutation.useGetRateMutation;
@@ -1,17 +1,17 @@
1
1
  import { useGetAllTokensQuery } from "./useGetAllTokens.query.mjs";
2
2
  import { useGetChainsQuery } from "./useGetChains.query.mjs";
3
- import { invalidateEvmTokensBalances, useGetNonMvxTokensBalancesQuery } from "./useGetNonMvxTokensBalances.query.mjs";
4
- import { invalidateHistoryQuery, useGetHistoryQuery } from "./useGetHistory.query.mjs";
5
- import { invalidateMvxTokensBalancesQuery, useGetMvxTokensBalancesQuery } from "./useGetMvxTokensBalances.query.mjs";
3
+ import { useGetNonMvxTokensBalancesQuery, useInvalidateEvmTokensBalances } from "./useGetNonMvxTokensBalances.query.mjs";
4
+ import { useGetHistoryQuery, useInvalidateHistoryQuery } from "./useGetHistory.query.mjs";
5
+ import { useGetMvxTokensBalancesQuery, useInvalidateMvxTokensBalancesQuery } from "./useGetMvxTokensBalances.query.mjs";
6
6
  import { useGetRateMutation } from "./useGetRate.mutation.mjs";
7
7
  export {
8
- invalidateEvmTokensBalances,
9
- invalidateHistoryQuery,
10
- invalidateMvxTokensBalancesQuery,
11
8
  useGetAllTokensQuery,
12
9
  useGetChainsQuery,
13
10
  useGetHistoryQuery,
14
11
  useGetMvxTokensBalancesQuery,
15
12
  useGetNonMvxTokensBalancesQuery,
16
- useGetRateMutation
13
+ useGetRateMutation,
14
+ useInvalidateEvmTokensBalances,
15
+ useInvalidateHistoryQuery,
16
+ useInvalidateMvxTokensBalancesQuery
17
17
  };
@@ -29,7 +29,7 @@ const useCheckAccountQuery = () => {
29
29
  return ((_a = error.response) == null ? void 0 : _a.status) === 404;
30
30
  };
31
31
  return reactQuery.useQuery({
32
- queryKey: ["check-account", address, bridgeApiChainId, nativeAuthToken],
32
+ queryKey: ["check-account", address, bridgeApiChainId],
33
33
  queryFn,
34
34
  retry,
35
35
  refetchOnWindowFocus: false,
@@ -26,7 +26,7 @@ const useCheckAccountQuery = () => {
26
26
  return ((_a = error.response) == null ? void 0 : _a.status) === 404;
27
27
  };
28
28
  return useQuery({
29
- queryKey: ["check-account", address, bridgeApiChainId, nativeAuthToken],
29
+ queryKey: ["check-account", address, bridgeApiChainId],
30
30
  queryFn,
31
31
  retry,
32
32
  refetchOnWindowFocus: false,
@@ -25,7 +25,7 @@ const useGetAllTokensQuery = ({
25
25
  return ((_a = error.response) == null ? void 0 : _a.status) === 404;
26
26
  };
27
27
  return reactQuery.useQuery({
28
- queryKey: ["all-tokens", nativeAuthToken],
28
+ queryKey: ["all-tokens", bridgeOnly],
29
29
  queryFn,
30
30
  retry,
31
31
  refetchOnWindowFocus: false,
@@ -22,7 +22,7 @@ const useGetAllTokensQuery = ({
22
22
  return ((_a = error.response) == null ? void 0 : _a.status) === 404;
23
23
  };
24
24
  return useQuery({
25
- queryKey: ["all-tokens", nativeAuthToken],
25
+ queryKey: ["all-tokens", bridgeOnly],
26
26
  queryFn,
27
27
  retry,
28
28
  refetchOnWindowFocus: false,