@aptos-labs/wallet-adapter-react 3.8.0 → 4.0.1

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.
@@ -1,29 +1,27 @@
1
- import { FC, ReactNode, useCallback, useEffect, useRef, useState } from "react";
2
- import { WalletContext } from "./useWallet";
3
- import type {
1
+ import {
2
+ AvailableWallets,
3
+ DappConfig,
4
4
  AccountInfo,
5
+ AdapterWallet,
5
6
  NetworkInfo,
6
- SignMessagePayload,
7
- Wallet,
8
- WalletInfo,
9
- InputGenerateTransactionOptions,
7
+ InputTransactionData,
8
+ AptosSignAndSubmitTransactionOutput,
10
9
  AnyRawTransaction,
11
- InputSubmitTransactionData,
10
+ InputGenerateTransactionOptions,
12
11
  AccountAuthenticator,
13
- PendingTransactionResponse,
14
- SignMessageResponse,
15
- WalletName,
16
- Types,
17
- InputTransactionData,
12
+ AptosSignMessageInput,
13
+ AptosSignMessageOutput,
14
+ AdapterNotDetectedWallet,
15
+ WalletCore,
18
16
  Network,
19
- AptosStandardSupportedWallet,
20
- AvailableWallets,
17
+ InputSubmitTransactionData,
18
+ PendingTransactionResponse,
21
19
  } from "@aptos-labs/wallet-adapter-core";
22
- import { DappConfig, WalletCore } from "@aptos-labs/wallet-adapter-core";
20
+ import { ReactNode, FC, useState, useEffect, useCallback } from "react";
21
+ import { WalletContext } from "./useWallet";
23
22
 
24
23
  export interface AptosWalletProviderProps {
25
24
  children: ReactNode;
26
- plugins?: ReadonlyArray<Wallet>;
27
25
  optInWallets?: ReadonlyArray<AvailableWallets>;
28
26
  autoConnect?: boolean;
29
27
  dappConfig?: DappConfig;
@@ -35,7 +33,7 @@ const initialState: {
35
33
  account: AccountInfo | null;
36
34
  network: NetworkInfo | null;
37
35
  connected: boolean;
38
- wallet: WalletInfo | null;
36
+ wallet: AdapterWallet | null;
39
37
  } = {
40
38
  connected: false,
41
39
  account: null,
@@ -43,46 +41,30 @@ const initialState: {
43
41
  wallet: null,
44
42
  };
45
43
 
46
- /**
47
- * Supported props to pass into the provider
48
- *
49
- * @param plugins Non AIP-62 supported wallet plugins array
50
- * @param optInWallets AIP-62 supported wallet names array to only include in the adapter wallets
51
- * @param autoConnect A boolean flag to indicate if the adapter should auto connect to a wallet
52
- * @param dappConfig The dapp configurations to be used by SDK wallets to set their configurations
53
- * @param disableTelemetry A boolean flag to disable the adapter telemetry tool
54
- * @param onError A callback function to execute when there is an error in the adapter
55
- *
56
- */
57
44
  export const AptosWalletAdapterProvider: FC<AptosWalletProviderProps> = ({
58
45
  children,
59
- plugins,
60
46
  optInWallets,
61
47
  autoConnect = false,
62
48
  dappConfig,
63
49
  disableTelemetry = false,
64
50
  onError,
65
51
  }: AptosWalletProviderProps) => {
66
- const [{ connected, account, network, wallet }, setState] =
52
+ const [{ account, network, connected, wallet }, setState] =
67
53
  useState(initialState);
68
54
 
69
- // a local state to track whether wallet connect request is loading
70
- // https://github.com/aptos-labs/aptos-wallet-adapter/issues/94
71
55
  const [isLoading, setIsLoading] = useState<boolean>(true);
72
-
73
56
  const [walletCore, setWalletCore] = useState<WalletCore>();
74
57
 
75
- const [wallets, setWallets] = useState<
76
- ReadonlyArray<Wallet | AptosStandardSupportedWallet>
77
- >(plugins ?? []);
78
-
58
+ const [wallets, setWallets] = useState<ReadonlyArray<AdapterWallet>>([]);
59
+ const [notDetectedWallets, setNotDetectedWallets] = useState<
60
+ ReadonlyArray<AdapterNotDetectedWallet>
61
+ >([]);
79
62
  // Initialize WalletCore on first load
80
63
  useEffect(() => {
81
64
  const walletCore = new WalletCore(
82
- plugins ?? [],
83
- optInWallets ?? [],
65
+ optInWallets,
84
66
  dappConfig,
85
- disableTelemetry,
67
+ disableTelemetry
86
68
  );
87
69
  setWalletCore(walletCore);
88
70
  }, []);
@@ -90,9 +72,21 @@ export const AptosWalletAdapterProvider: FC<AptosWalletProviderProps> = ({
90
72
  // Update initial Wallets state once WalletCore has been initialized
91
73
  useEffect(() => {
92
74
  setWallets(walletCore?.wallets ?? []);
75
+ setNotDetectedWallets(walletCore?.notDetectedWallets ?? []);
93
76
  }, [walletCore]);
94
77
 
95
- const connect = async (walletName: WalletName) => {
78
+ useEffect(() => {
79
+ if (autoConnect) {
80
+ if (localStorage.getItem("AptosWalletName") && !connected) {
81
+ connect(localStorage.getItem("AptosWalletName") as string);
82
+ } else {
83
+ // if we dont use autoconnect set the connect is loading to false
84
+ setIsLoading(false);
85
+ }
86
+ }
87
+ }, [autoConnect, wallets]);
88
+
89
+ const connect = async (walletName: string): Promise<void> => {
96
90
  try {
97
91
  setIsLoading(true);
98
92
  await walletCore?.connect(walletName);
@@ -104,7 +98,7 @@ export const AptosWalletAdapterProvider: FC<AptosWalletProviderProps> = ({
104
98
  }
105
99
  };
106
100
 
107
- const disconnect = async () => {
101
+ const disconnect = async (): Promise<void> => {
108
102
  try {
109
103
  await walletCore?.disconnect();
110
104
  } catch (error) {
@@ -113,73 +107,82 @@ export const AptosWalletAdapterProvider: FC<AptosWalletProviderProps> = ({
113
107
  }
114
108
  };
115
109
 
116
- const signTransaction = async (
117
- transaction: AnyRawTransaction | Types.TransactionPayload,
118
- asFeePayer?: boolean,
119
- options?: InputGenerateTransactionOptions,
120
- ): Promise<AccountAuthenticator> => {
121
- if (!walletCore) {
122
- throw new Error("WalletCore is not initialized");
123
- }
110
+ const signAndSubmitTransaction = async (
111
+ transaction: InputTransactionData
112
+ ): Promise<AptosSignAndSubmitTransactionOutput> => {
124
113
  try {
125
- return await walletCore?.signTransaction(
126
- transaction,
127
- asFeePayer,
128
- options,
129
- );
114
+ if (!walletCore) {
115
+ throw new Error("WalletCore is not initialized");
116
+ }
117
+ return await walletCore.signAndSubmitTransaction(transaction);
130
118
  } catch (error: any) {
131
119
  if (onError) onError(error);
132
120
  return Promise.reject(error);
133
121
  }
134
122
  };
135
123
 
136
- const signMessage = async (
137
- message: SignMessagePayload,
138
- ): Promise<SignMessageResponse> => {
124
+ const signTransaction = async (args: {
125
+ transactionOrPayload: AnyRawTransaction | InputTransactionData;
126
+ asFeePayer?: boolean;
127
+ options?: InputGenerateTransactionOptions & {
128
+ expirationSecondsFromNow?: number;
129
+ expirationTimestamp?: number;
130
+ };
131
+ }): Promise<{
132
+ authenticator: AccountAuthenticator;
133
+ rawTransaction: Uint8Array;
134
+ }> => {
135
+ const { transactionOrPayload, asFeePayer, options } = args;
139
136
  if (!walletCore) {
140
137
  throw new Error("WalletCore is not initialized");
141
138
  }
142
139
  try {
143
- return await walletCore?.signMessage(message);
140
+ return await walletCore.signTransaction({
141
+ transactionOrPayload,
142
+ asFeePayer,
143
+ });
144
144
  } catch (error: any) {
145
145
  if (onError) onError(error);
146
146
  return Promise.reject(error);
147
147
  }
148
148
  };
149
149
 
150
- const signMessageAndVerify = async (
151
- message: SignMessagePayload,
152
- ): Promise<boolean> => {
150
+ const submitTransaction = async (
151
+ transaction: InputSubmitTransactionData
152
+ ): Promise<PendingTransactionResponse> => {
153
153
  if (!walletCore) {
154
154
  throw new Error("WalletCore is not initialized");
155
155
  }
156
156
  try {
157
- return await walletCore?.signMessageAndVerify(message);
157
+ return await walletCore?.submitTransaction(transaction);
158
158
  } catch (error: any) {
159
159
  if (onError) onError(error);
160
160
  return Promise.reject(error);
161
161
  }
162
162
  };
163
163
 
164
- const submitTransaction = async (
165
- transaction: InputSubmitTransactionData,
166
- ): Promise<PendingTransactionResponse> => {
164
+ const signMessage = async (
165
+ message: AptosSignMessageInput
166
+ ): Promise<AptosSignMessageOutput> => {
167
167
  if (!walletCore) {
168
168
  throw new Error("WalletCore is not initialized");
169
169
  }
170
170
  try {
171
- return await walletCore?.submitTransaction(transaction);
171
+ return await walletCore?.signMessage(message);
172
172
  } catch (error: any) {
173
173
  if (onError) onError(error);
174
174
  return Promise.reject(error);
175
175
  }
176
176
  };
177
177
 
178
- const signAndSubmitTransaction = async (
179
- transaction: InputTransactionData,
180
- ) => {
178
+ const signMessageAndVerify = async (
179
+ message: AptosSignMessageInput
180
+ ): Promise<boolean> => {
181
+ if (!walletCore) {
182
+ throw new Error("WalletCore is not initialized");
183
+ }
181
184
  try {
182
- return await walletCore?.signAndSubmitTransaction(transaction);
185
+ return await walletCore?.signMessageAndVerify(message);
183
186
  } catch (error: any) {
184
187
  if (onError) onError(error);
185
188
  return Promise.reject(error);
@@ -198,26 +201,8 @@ export const AptosWalletAdapterProvider: FC<AptosWalletProviderProps> = ({
198
201
  }
199
202
  };
200
203
 
201
- useEffect(() => {
202
- if (autoConnect) {
203
- if (localStorage.getItem("AptosWalletName") && !connected) {
204
- connect(localStorage.getItem("AptosWalletName") as WalletName);
205
- } else {
206
- // if we dont use autoconnect set the connect is loading to false
207
- setIsLoading(false);
208
- }
209
- }
210
- }, [autoConnect, wallets]);
211
-
212
- useEffect(() => {
213
- if (connected) {
214
- walletCore?.onAccountChange();
215
- walletCore?.onNetworkChange();
216
- }
217
- }, [connected]);
218
-
219
204
  // Handle the adapter's connect event
220
- const handleConnect = () => {
205
+ const handleConnect = (): void => {
221
206
  setState((state) => {
222
207
  return {
223
208
  ...state,
@@ -229,63 +214,56 @@ export const AptosWalletAdapterProvider: FC<AptosWalletProviderProps> = ({
229
214
  });
230
215
  };
231
216
 
232
- // Handle the adapter's disconnect event
233
- const handleDisconnect = () => {
217
+ // Handle the adapter's account change event
218
+ const handleAccountChange = useCallback((): void => {
234
219
  if (!connected) return;
220
+ if (!walletCore?.wallet) return;
235
221
  setState((state) => {
236
222
  return {
237
223
  ...state,
238
- connected: false,
239
224
  account: walletCore?.account || null,
240
- network: walletCore?.network || null,
241
- wallet: null,
242
225
  };
243
226
  });
244
- };
227
+ }, [connected]);
245
228
 
246
- // Handle the adapter's account change event
247
- const handleAccountChange = useCallback(() => {
229
+ // Handle the adapter's network event
230
+ const handleNetworkChange = useCallback((): void => {
248
231
  if (!connected) return;
249
232
  if (!walletCore?.wallet) return;
250
233
  setState((state) => {
251
234
  return {
252
235
  ...state,
253
- account: walletCore?.account || null,
236
+ network: walletCore?.network || null,
254
237
  };
255
238
  });
256
239
  }, [connected]);
257
240
 
258
- // Handle the adapter's network event
259
- const handleNetworkChange = useCallback(() => {
241
+ useEffect(() => {
242
+ if (connected) {
243
+ walletCore?.onAccountChange();
244
+ walletCore?.onNetworkChange();
245
+ }
246
+ }, [connected]);
247
+
248
+ // Handle the adapter's disconnect event
249
+ const handleDisconnect = (): void => {
260
250
  if (!connected) return;
261
- if (!walletCore?.wallet) return;
262
251
  setState((state) => {
263
252
  return {
264
253
  ...state,
254
+ connected: false,
255
+ account: walletCore?.account || null,
265
256
  network: walletCore?.network || null,
257
+ wallet: null,
266
258
  };
267
259
  });
268
- }, [connected]);
269
-
270
- const handleReadyStateChange = (updatedWallet: Wallet) => {
271
- // Create a new array with updated values
272
- const updatedWallets = (wallets as Wallet[])?.map((wallet) => {
273
- if (wallet.name === updatedWallet.name) {
274
- // Return a new object with updated value
275
- return { ...wallet, readyState: updatedWallet.readyState };
276
- }
277
- return wallet;
278
- });
279
- setWallets(updatedWallets);
280
260
  };
281
261
 
282
- const handleStandardWalletsAdded = (
283
- standardWallet: Wallet | AptosStandardSupportedWallet,
284
- ) => {
262
+ const handleStandardWalletsAdded = (standardWallet: AdapterWallet): void => {
285
263
  // Manage current wallet state by removing optional duplications
286
264
  // as new wallets are coming
287
265
  const existingWalletIndex = wallets.findIndex(
288
- (wallet) => wallet.name == standardWallet.name,
266
+ (wallet) => wallet.name == standardWallet.name
289
267
  );
290
268
  if (existingWalletIndex !== -1) {
291
269
  // If wallet exists, replace it with the new wallet
@@ -300,40 +278,67 @@ export const AptosWalletAdapterProvider: FC<AptosWalletProviderProps> = ({
300
278
  }
301
279
  };
302
280
 
281
+ const handleStandardNotDetectedWalletsAdded = (
282
+ notDetectedWallet: AdapterNotDetectedWallet
283
+ ): void => {
284
+ // Manage current wallet state by removing optional duplications
285
+ // as new wallets are coming
286
+ const existingWalletIndex = wallets.findIndex(
287
+ (wallet) => wallet.name == notDetectedWallet.name
288
+ );
289
+ if (existingWalletIndex !== -1) {
290
+ // If wallet exists, replace it with the new wallet
291
+ setNotDetectedWallets((wallets) => [
292
+ ...wallets.slice(0, existingWalletIndex),
293
+ notDetectedWallet,
294
+ ...wallets.slice(existingWalletIndex + 1),
295
+ ]);
296
+ } else {
297
+ // If wallet doesn't exist, add it to the array
298
+ setNotDetectedWallets((wallets) => [...wallets, notDetectedWallet]);
299
+ }
300
+ };
301
+
303
302
  useEffect(() => {
304
303
  walletCore?.on("connect", handleConnect);
305
- walletCore?.on("disconnect", handleDisconnect);
306
304
  walletCore?.on("accountChange", handleAccountChange);
307
305
  walletCore?.on("networkChange", handleNetworkChange);
308
- walletCore?.on("readyStateChange", handleReadyStateChange);
306
+ walletCore?.on("disconnect", handleDisconnect);
309
307
  walletCore?.on("standardWalletsAdded", handleStandardWalletsAdded);
308
+ walletCore?.on(
309
+ "standardNotDetectedWalletAdded",
310
+ handleStandardNotDetectedWalletsAdded
311
+ );
310
312
  return () => {
311
313
  walletCore?.off("connect", handleConnect);
312
- walletCore?.off("disconnect", handleDisconnect);
313
314
  walletCore?.off("accountChange", handleAccountChange);
314
315
  walletCore?.off("networkChange", handleNetworkChange);
315
- walletCore?.off("readyStateChange", handleReadyStateChange);
316
+ walletCore?.off("disconnect", handleDisconnect);
316
317
  walletCore?.off("standardWalletsAdded", handleStandardWalletsAdded);
318
+ walletCore?.off(
319
+ "standardNotDetectedWalletAdded",
320
+ handleStandardNotDetectedWalletsAdded
321
+ );
317
322
  };
318
323
  }, [wallets, account]);
319
-
320
324
  return (
321
325
  <WalletContext.Provider
322
326
  value={{
323
327
  connect,
324
- account,
325
- network,
326
- connected,
327
328
  disconnect,
328
- wallet,
329
- wallets,
330
329
  signAndSubmitTransaction,
331
330
  signTransaction,
332
331
  signMessage,
333
332
  signMessageAndVerify,
334
- isLoading,
335
- submitTransaction,
336
333
  changeNetwork,
334
+ submitTransaction,
335
+ account,
336
+ network,
337
+ connected,
338
+ wallet,
339
+ wallets,
340
+ notDetectedWallets,
341
+ isLoading,
337
342
  }}
338
343
  >
339
344
  {children}
@@ -1,5 +1,6 @@
1
1
  import {
2
- AnyAptosWallet,
2
+ AdapterNotDetectedWallet,
3
+ AdapterWallet,
3
4
  WalletReadyState,
4
5
  isRedirectable,
5
6
  } from "@aptos-labs/wallet-adapter-core";
@@ -10,7 +11,7 @@ import { HeadlessComponentProps, createHeadlessComponent } from "./utils";
10
11
 
11
12
  export interface WalletItemProps extends HeadlessComponentProps {
12
13
  /** The wallet option to be displayed. */
13
- wallet: AnyAptosWallet;
14
+ wallet: AdapterWallet | AdapterNotDetectedWallet;
14
15
  /** A callback to be invoked when the wallet is connected. */
15
16
  onConnect?: () => void;
16
17
  }
@@ -26,7 +27,7 @@ function useWalletItemContext(displayName: string) {
26
27
  }
27
28
 
28
29
  const WalletItemContext = createContext<{
29
- wallet: AnyAptosWallet;
30
+ wallet: AdapterWallet | AdapterNotDetectedWallet;
30
31
  connectWallet: () => void;
31
32
  } | null>(null);
32
33
 
@@ -39,9 +40,7 @@ const Root = forwardRef<HTMLDivElement, WalletItemProps>(
39
40
  onConnect?.();
40
41
  }, [connect, wallet.name, onConnect]);
41
42
 
42
- const isWalletReady =
43
- wallet.readyState === WalletReadyState.Installed ||
44
- wallet.readyState === WalletReadyState.Loadable;
43
+ const isWalletReady = wallet.readyState === WalletReadyState.Installed;
45
44
 
46
45
  const mobileSupport =
47
46
  "deeplinkProvider" in wallet && wallet.deeplinkProvider;
@@ -57,7 +56,7 @@ const Root = forwardRef<HTMLDivElement, WalletItemProps>(
57
56
  </Component>
58
57
  </WalletItemContext.Provider>
59
58
  );
60
- },
59
+ }
61
60
  );
62
61
  Root.displayName = "WalletItem";
63
62
 
@@ -71,7 +70,7 @@ const Icon = createHeadlessComponent(
71
70
  src: context.wallet.icon,
72
71
  alt: `${context.wallet.name} icon`,
73
72
  };
74
- },
73
+ }
75
74
  );
76
75
 
77
76
  const Name = createHeadlessComponent(
@@ -83,7 +82,7 @@ const Name = createHeadlessComponent(
83
82
  return {
84
83
  children: context.wallet.name,
85
84
  };
86
- },
85
+ }
87
86
  );
88
87
 
89
88
  const ConnectButton = createHeadlessComponent(
@@ -96,7 +95,7 @@ const ConnectButton = createHeadlessComponent(
96
95
  onClick: context.connectWallet,
97
96
  children: "Connect",
98
97
  };
99
- },
98
+ }
100
99
  );
101
100
 
102
101
  const InstallLink = createHeadlessComponent(
@@ -111,7 +110,7 @@ const InstallLink = createHeadlessComponent(
111
110
  rel: "noopener noreferrer",
112
111
  children: "Install",
113
112
  };
114
- },
113
+ }
115
114
  );
116
115
 
117
116
  /** A headless component for rendering a wallet option's name, icon, and either connect button or install link. */
package/src/useWallet.tsx CHANGED
@@ -1,45 +1,47 @@
1
+ import { useContext, createContext } from "react";
1
2
  import {
3
+ AccountAuthenticator,
2
4
  AccountInfo,
3
- NetworkInfo,
4
- WalletInfo,
5
- SignMessagePayload,
6
- SignMessageResponse,
7
- Wallet,
8
- InputGenerateTransactionOptions,
5
+ AdapterWallet,
9
6
  AnyRawTransaction,
7
+ AptosSignAndSubmitTransactionOutput,
10
8
  InputTransactionData,
11
- InputSubmitTransactionData,
12
- PendingTransactionResponse,
13
- AccountAuthenticator,
14
- Types,
15
- WalletName,
16
- AptosChangeNetworkOutput,
9
+ NetworkInfo,
10
+ AptosSignMessageInput,
11
+ AptosSignMessageOutput,
12
+ AdapterNotDetectedWallet,
17
13
  Network,
18
- AptosStandardSupportedWallet,
14
+ AptosChangeNetworkOutput,
15
+ PendingTransactionResponse,
16
+ InputSubmitTransactionData,
19
17
  } from "@aptos-labs/wallet-adapter-core";
20
- import { createContext, useContext } from "react";
21
18
 
22
19
  export interface WalletContextState {
23
20
  connected: boolean;
24
21
  isLoading: boolean;
25
22
  account: AccountInfo | null;
26
23
  network: NetworkInfo | null;
27
- connect(walletName: WalletName): void;
24
+ connect(walletName: string): void;
25
+ signAndSubmitTransaction(
26
+ transaction: InputTransactionData
27
+ ): Promise<AptosSignAndSubmitTransactionOutput>;
28
+ signTransaction(args: {
29
+ transactionOrPayload: AnyRawTransaction | InputTransactionData;
30
+ asFeePayer?: boolean;
31
+ }): Promise<{
32
+ authenticator: AccountAuthenticator;
33
+ rawTransaction: Uint8Array;
34
+ }>;
35
+ signMessage(message: AptosSignMessageInput): Promise<AptosSignMessageOutput>;
36
+ signMessageAndVerify(message: AptosSignMessageInput): Promise<boolean>;
28
37
  disconnect(): void;
29
- wallet: WalletInfo | null;
30
- wallets?: ReadonlyArray<Wallet | AptosStandardSupportedWallet>;
31
- signAndSubmitTransaction(transaction: InputTransactionData): Promise<any>;
32
- signTransaction(
33
- transactionOrPayload: AnyRawTransaction | Types.TransactionPayload,
34
- asFeePayer?: boolean,
35
- options?: InputGenerateTransactionOptions,
36
- ): Promise<AccountAuthenticator>;
38
+ changeNetwork(network: Network): Promise<AptosChangeNetworkOutput>;
37
39
  submitTransaction(
38
- transaction: InputSubmitTransactionData,
40
+ transaction: InputSubmitTransactionData
39
41
  ): Promise<PendingTransactionResponse>;
40
- signMessage(message: SignMessagePayload): Promise<SignMessageResponse>;
41
- signMessageAndVerify(message: SignMessagePayload): Promise<boolean>;
42
- changeNetwork(network: Network): Promise<AptosChangeNetworkOutput>;
42
+ wallet: AdapterWallet | null;
43
+ wallets: ReadonlyArray<AdapterWallet>;
44
+ notDetectedWallets: ReadonlyArray<AdapterNotDetectedWallet>;
43
45
  }
44
46
 
45
47
  const DEFAULT_CONTEXT = {
@@ -47,7 +49,7 @@ const DEFAULT_CONTEXT = {
47
49
  };
48
50
 
49
51
  export const WalletContext = createContext<WalletContextState>(
50
- DEFAULT_CONTEXT as WalletContextState,
52
+ DEFAULT_CONTEXT as WalletContextState
51
53
  );
52
54
 
53
55
  export function useWallet(): WalletContextState {