@aptos-labs/wallet-adapter-core 4.25.0 → 5.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.
Files changed (70) hide show
  1. package/README.md +10 -0
  2. package/dist/WalletCore.d.ts +71 -112
  3. package/dist/WalletCore.d.ts.map +1 -1
  4. package/dist/constants.d.ts +4 -14
  5. package/dist/constants.d.ts.map +1 -1
  6. package/dist/error/index.d.ts +3 -0
  7. package/dist/error/index.d.ts.map +1 -1
  8. package/dist/index.d.ts +3 -3
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +379 -859
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +408 -894
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/{AIP62StandardWallets/registry.d.ts → registry.d.ts} +1 -1
  15. package/dist/registry.d.ts.map +1 -0
  16. package/dist/sdkWallets.d.ts +3 -0
  17. package/dist/sdkWallets.d.ts.map +1 -0
  18. package/dist/utils/helpers.d.ts +7 -7
  19. package/dist/utils/helpers.d.ts.map +1 -1
  20. package/dist/utils/index.d.ts +1 -1
  21. package/dist/utils/index.d.ts.map +1 -1
  22. package/dist/utils/localStorage.d.ts +1 -2
  23. package/dist/utils/localStorage.d.ts.map +1 -1
  24. package/dist/utils/types.d.ts +26 -0
  25. package/dist/utils/types.d.ts.map +1 -0
  26. package/dist/utils/walletSelector.d.ts +18 -19
  27. package/dist/utils/walletSelector.d.ts.map +1 -1
  28. package/dist/version.d.ts +1 -1
  29. package/dist/version.d.ts.map +1 -1
  30. package/package.json +4 -5
  31. package/src/WalletCore.ts +474 -686
  32. package/src/constants.ts +3 -13
  33. package/src/error/index.ts +4 -0
  34. package/src/index.ts +3 -3
  35. package/src/{AIP62StandardWallets/registry.ts → registry.ts} +19 -6
  36. package/src/{AIP62StandardWallets/sdkWallets.ts → sdkWallets.ts} +6 -6
  37. package/src/utils/helpers.ts +46 -32
  38. package/src/utils/index.ts +1 -1
  39. package/src/utils/localStorage.ts +1 -3
  40. package/src/{AIP62StandardWallets → utils}/types.ts +22 -3
  41. package/src/utils/walletSelector.ts +32 -26
  42. package/src/version.ts +1 -1
  43. package/dist/AIP62StandardWallets/WalletStandard.d.ts +0 -44
  44. package/dist/AIP62StandardWallets/WalletStandard.d.ts.map +0 -1
  45. package/dist/AIP62StandardWallets/index.d.ts +0 -3
  46. package/dist/AIP62StandardWallets/index.d.ts.map +0 -1
  47. package/dist/AIP62StandardWallets/registry.d.ts.map +0 -1
  48. package/dist/AIP62StandardWallets/sdkWallets.d.ts +0 -4
  49. package/dist/AIP62StandardWallets/sdkWallets.d.ts.map +0 -1
  50. package/dist/AIP62StandardWallets/types.d.ts +0 -12
  51. package/dist/AIP62StandardWallets/types.d.ts.map +0 -1
  52. package/dist/LegacyWalletPlugins/WalletCoreV1.d.ts +0 -50
  53. package/dist/LegacyWalletPlugins/WalletCoreV1.d.ts.map +0 -1
  54. package/dist/LegacyWalletPlugins/conversion.d.ts +0 -21
  55. package/dist/LegacyWalletPlugins/conversion.d.ts.map +0 -1
  56. package/dist/LegacyWalletPlugins/index.d.ts +0 -4
  57. package/dist/LegacyWalletPlugins/index.d.ts.map +0 -1
  58. package/dist/LegacyWalletPlugins/types.d.ts +0 -116
  59. package/dist/LegacyWalletPlugins/types.d.ts.map +0 -1
  60. package/dist/__tests__/WalletCore.test.d.ts +0 -2
  61. package/dist/__tests__/WalletCore.test.d.ts.map +0 -1
  62. package/dist/utils/scopePollingDetectionStrategy.d.ts +0 -2
  63. package/dist/utils/scopePollingDetectionStrategy.d.ts.map +0 -1
  64. package/src/AIP62StandardWallets/WalletStandard.ts +0 -242
  65. package/src/AIP62StandardWallets/index.ts +0 -2
  66. package/src/LegacyWalletPlugins/WalletCoreV1.ts +0 -258
  67. package/src/LegacyWalletPlugins/conversion.ts +0 -124
  68. package/src/LegacyWalletPlugins/index.ts +0 -3
  69. package/src/LegacyWalletPlugins/types.ts +0 -188
  70. package/src/utils/scopePollingDetectionStrategy.ts +0 -46
package/src/WalletCore.ts CHANGED
@@ -1,69 +1,75 @@
1
- import { TxnBuilderTypes, Types, BCS } from "aptos";
1
+ import EventEmitter from "eventemitter3";
2
2
  import {
3
- Network,
4
- AnyRawTransaction,
5
3
  AccountAddress,
6
4
  AccountAuthenticator,
7
- AccountAuthenticatorEd25519,
8
- Ed25519PublicKey,
9
- InputGenerateTransactionOptions,
10
- Ed25519Signature,
11
- AptosConfig,
12
- InputSubmitTransactionData,
13
- PendingTransactionResponse,
5
+ AnyPublicKey,
6
+ AnyPublicKeyVariant,
7
+ AnyRawTransaction,
14
8
  Aptos,
15
- generateRawTransaction,
16
- SimpleTransaction,
9
+ InputSubmitTransactionData,
10
+ MultiEd25519PublicKey,
11
+ MultiEd25519Signature,
12
+ Network,
17
13
  NetworkToChainId,
18
- Hex,
14
+ PendingTransactionResponse,
19
15
  } from "@aptos-labs/ts-sdk";
20
- import EventEmitter from "eventemitter3";
21
16
  import {
22
- AccountInfo as StandardAccountInfo,
23
- AptosChangeNetworkOutput,
24
17
  AptosWallet,
25
18
  getAptosWallets,
26
- NetworkInfo as StandardNetworkInfo,
27
- UserResponse,
28
- UserResponseStatus,
29
19
  isWalletWithRequiredFeatureSet,
20
+ UserResponseStatus,
21
+ AptosSignAndSubmitTransactionOutput,
22
+ UserResponse,
23
+ AptosSignTransactionOutputV1_1,
24
+ AptosSignTransactionInputV1_1,
25
+ AptosSignTransactionMethod,
26
+ AptosSignTransactionMethodV1_1,
27
+ NetworkInfo,
28
+ AccountInfo,
29
+ AptosSignMessageInput,
30
+ AptosSignMessageOutput,
31
+ AptosChangeNetworkOutput,
30
32
  } from "@aptos-labs/wallet-standard";
33
+ import { AptosConnectWalletConfig } from "@aptos-connect/wallet-adapter-plugin";
31
34
 
32
- import { getSDKWallets } from "./AIP62StandardWallets/sdkWallets";
33
- import { ChainIdToAnsSupportedNetworkMap, WalletReadyState } from "./constants";
35
+ export type {
36
+ NetworkInfo,
37
+ AccountInfo,
38
+ AptosSignAndSubmitTransactionOutput,
39
+ AptosSignTransactionOutputV1_1,
40
+ AptosSignMessageInput,
41
+ AptosSignMessageOutput,
42
+ AptosChangeNetworkOutput,
43
+ } from "@aptos-labs/wallet-standard";
44
+ export type {
45
+ AccountAuthenticator,
46
+ AnyRawTransaction,
47
+ InputGenerateTransactionOptions,
48
+ PendingTransactionResponse,
49
+ InputSubmitTransactionData,
50
+ Network,
51
+ } from "@aptos-labs/ts-sdk";
52
+
53
+ import { GA4 } from "./ga";
34
54
  import {
55
+ WalletChangeNetworkError,
35
56
  WalletAccountChangeError,
36
57
  WalletAccountError,
37
- WalletChangeNetworkError,
38
58
  WalletConnectionError,
39
- WalletDisconnectionError,
40
59
  WalletGetNetworkError,
41
60
  WalletNetworkChangeError,
42
61
  WalletNotConnectedError,
43
62
  WalletNotReadyError,
44
63
  WalletNotSelectedError,
45
- WalletNotSupportedMethod,
46
64
  WalletSignAndSubmitMessageError,
47
- WalletSignMessageAndVerifyError,
48
65
  WalletSignMessageError,
49
66
  WalletSignTransactionError,
67
+ WalletSignMessageAndVerifyError,
68
+ WalletDisconnectionError,
69
+ WalletSubmitTransactionError,
50
70
  } from "./error";
51
- import {
52
- AccountInfo,
53
- InputTransactionData,
54
- NetworkInfo,
55
- SignMessagePayload,
56
- SignMessageResponse,
57
- Wallet,
58
- WalletCoreEvents,
59
- WalletInfo,
60
- WalletName,
61
- WalletCoreV1,
62
- CompatibleTransactionOptions,
63
- convertNetwork,
64
- convertPayloadInputV1ToV2,
65
- generateTransactionPayloadFromV1Input,
66
- } from "./LegacyWalletPlugins";
71
+ import { ChainIdToAnsSupportedNetworkMap, WalletReadyState } from "./constants";
72
+ import { WALLET_ADAPTER_CORE_VERSION } from "./version";
67
73
  import {
68
74
  fetchDevnetChainId,
69
75
  generalizedErrorMessage,
@@ -72,36 +78,32 @@ import {
72
78
  isAptosNetwork,
73
79
  isRedirectable,
74
80
  removeLocalStorage,
75
- scopePollingDetectionStrategy,
76
81
  setLocalStorage,
77
82
  } from "./utils";
83
+ import { aptosStandardSupportedWalletList } from "./registry";
84
+ import { getSDKWallets } from "./sdkWallets";
78
85
  import {
79
- AptosStandardWallet,
80
- WalletStandardCore,
81
- AptosStandardSupportedWallet,
82
86
  AvailableWallets,
83
- } from "./AIP62StandardWallets";
84
- import { GA4 } from "./ga";
85
- import { WALLET_ADAPTER_CORE_VERSION } from "./version";
86
- import { aptosStandardSupportedWalletList } from "./AIP62StandardWallets/registry";
87
- import type { AptosConnectWalletConfig } from "@aptos-connect/wallet-adapter-plugin";
88
-
89
- export type IAptosWallet = AptosStandardWallet & Wallet;
90
-
91
- /**
92
- * Interface for dapp configuration
93
- *
94
- * @network The network the dapp is working with
95
- * @aptosApiKeys A map of Network<>Api Key generated with {@link https://developers.aptoslabs.com/docs/api-access}
96
- * @aptosConnect Config used to initialize the AptosConnect wallet provider
97
- * @mizuwallet Config used to initialize the Mizu wallet provider
98
- */
87
+ AptosStandardSupportedWallet,
88
+ InputTransactionData,
89
+ } from "./utils/types";
90
+
91
+ // An adapter wallet types is a wallet that is compatible with the wallet standard and the wallet adapter properties
92
+ export type AdapterWallet = AptosWallet & {
93
+ readyState?: WalletReadyState;
94
+ };
95
+
96
+ // An adapter not detected wallet types is a wallet that is compatible with the wallet standard but not detected
97
+ export type AdapterNotDetectedWallet = Omit<
98
+ AdapterWallet,
99
+ "features" | "version" | "chains" | "accounts"
100
+ > & {
101
+ readyState: WalletReadyState.NotDetected;
102
+ };
103
+
99
104
  export interface DappConfig {
100
105
  network: Network;
101
106
  aptosApiKeys?: Partial<Record<Network, string>>;
102
- /** @deprecated */
103
- aptosApiKey?: string;
104
- /** @deprecated */
105
107
  aptosConnectDappId?: string;
106
108
  aptosConnect?: Omit<AptosConnectWalletConfig, "network">;
107
109
  mizuwallet?: {
@@ -110,143 +112,83 @@ export interface DappConfig {
110
112
  };
111
113
  }
112
114
 
113
- /** Any wallet that can be handled by `WalletCore`.
114
- * This includes both wallets from legacy wallet adapter plugins and compatible AIP-62 standard wallets.
115
- */
116
- export type AnyAptosWallet = Wallet | AptosStandardSupportedWallet;
117
-
118
- export class WalletCore extends EventEmitter<WalletCoreEvents> {
119
- // Private array to hold legacy wallet adapter plugins
120
- private _wallets: ReadonlyArray<Wallet> = [];
115
+ export declare interface WalletCoreEvents {
116
+ connect(account: AccountInfo | null): void;
117
+ disconnect(): void;
118
+ standardWalletsAdded(wallets: AdapterWallet): void;
119
+ standardNotDetectedWalletAdded(wallets: AdapterNotDetectedWallet): void;
120
+ networkChange(network: NetworkInfo | null): void;
121
+ accountChange(account: AccountInfo | null): void;
122
+ }
121
123
 
122
- // Private array that holds all the Wallets a dapp decided to opt-in to
123
- private _optInWallets: ReadonlyArray<AvailableWallets> = [];
124
+ export type AdapterAccountInfo = Omit<AccountInfo, "ansName"> & {
125
+ // ansName is a read-only property on the standard AccountInfo type
126
+ ansName?: string;
127
+ };
124
128
 
125
- // Private array to hold compatible AIP-62 standard wallets
126
- private _standard_wallets: Array<AptosStandardWallet> = [];
129
+ export class WalletCore extends EventEmitter<WalletCoreEvents> {
130
+ // Local private variable to hold the wallet that is currently connected
131
+ private _wallet: AdapterWallet | null = null;
127
132
 
128
- // Private array to hold all wallets (legacy wallet adapter plugins AND compatible AIP-62 standard wallets)
129
- // while providing support for legacy and new wallet standard
130
- private _all_wallets: Array<AnyAptosWallet> = [];
133
+ // Local private variable to hold SDK wallets in the adapter
134
+ private readonly _sdkWallets: AdapterWallet[] = [];
131
135
 
132
- // Current connected wallet
133
- private _wallet: Wallet | null = null;
136
+ // Local array that holds all the wallets that are AIP-62 standard compatible
137
+ private _standard_wallets: AdapterWallet[] = [];
134
138
 
135
- // Current connected account
136
- private _account: AccountInfo | null = null;
139
+ // Local array that holds all the wallets that are AIP-62 standard compatible but are not installed on the user machine
140
+ private _standard_not_detected_wallets: AdapterNotDetectedWallet[] = [];
137
141
 
138
- // Current connected network
142
+ // Local private variable to hold the network that is currently connected
139
143
  private _network: NetworkInfo | null = null;
140
144
 
141
- // WalletCoreV1 property to interact with wallet adapter v1 (legacy wallet adapter plugins) functionality
142
- private readonly walletCoreV1: WalletCoreV1 = new WalletCoreV1();
143
-
144
- // WalletStandardCore property to interact with wallet adapter v2 (compatible AIP-62 standard wallets) functionality
145
- private readonly walletStandardCore: WalletStandardCore =
146
- new WalletStandardCore();
145
+ // Local private variable to hold the wallet connected state
146
+ private _connected: boolean = false;
147
147
 
148
- // Indicates whether the dapp is currently connecting with a wallet
148
+ // Local private variable to hold the connecting state
149
149
  private _connecting: boolean = false;
150
150
 
151
- // Indicates whether the dapp is connected with a wallet
152
- private _connected: boolean = false;
153
-
154
- // Google Analytics 4 module
155
- private readonly ga4: GA4 | null = null;
151
+ // Local private variable to hold the account that is currently connected
152
+ private _account: AdapterAccountInfo | null = null;
156
153
 
157
154
  // JSON configuration for AptosConnect
158
155
  private _dappConfig: DappConfig | undefined;
159
156
 
160
- // Local private variable to hold SDK wallets in the adapter
161
- private readonly _sdkWallets: AptosStandardWallet[];
157
+ // Private array that holds all the Wallets a dapp decided to opt-in to
158
+ private _optInWallets: ReadonlyArray<AvailableWallets> = [];
162
159
 
163
160
  // Local flag to disable the adapter telemetry tool
164
- private _disableTelemetry: boolean | undefined = false;
161
+ private _disableTelemetry: boolean = false;
162
+
163
+ // Google Analytics 4 module
164
+ private readonly ga4: GA4 | null = null;
165
165
 
166
- /**
167
- * Core functionality constructor.
168
- * For legacy wallet adapter v1 support we expect the dapp to pass in wallet plugins,
169
- * since AIP-62 standard support this is optional for dapps.
170
- *
171
- * @param plugins legacy wallet adapter v1 wallet plugins
172
- */
173
166
  constructor(
174
- plugins: ReadonlyArray<Wallet>,
175
- optInWallets: ReadonlyArray<AvailableWallets>,
167
+ optInWallets?: ReadonlyArray<AvailableWallets>,
176
168
  dappConfig?: DappConfig,
177
- disableTelemetry?: boolean,
169
+ disableTelemetry?: boolean
178
170
  ) {
179
171
  super();
180
-
181
- this._wallets = plugins;
182
- this._optInWallets = optInWallets;
172
+ this._optInWallets = optInWallets || [];
183
173
  this._dappConfig = dappConfig;
184
- this._disableTelemetry = disableTelemetry;
174
+ this._disableTelemetry = disableTelemetry ?? false;
185
175
  this._sdkWallets = getSDKWallets(this._dappConfig);
186
176
 
187
177
  // If disableTelemetry set to false (by default), start GA4
188
178
  if (!this._disableTelemetry) {
189
179
  this.ga4 = new GA4();
190
180
  }
191
-
192
181
  // Strategy to detect AIP-62 standard compatible extension wallets
193
182
  this.fetchExtensionAIP62AptosWallets();
194
183
  // Strategy to detect AIP-62 standard compatible SDK wallets.
195
184
  // We separate the extension and sdk detection process so we dont refetch sdk wallets everytime a new
196
185
  // extension wallet is detected
197
186
  this.fetchSDKAIP62AptosWallets();
198
- // Strategy to detect legacy wallet adapter v1 wallet plugins
199
- this.scopePollingDetectionStrategy();
200
- // Append AIP-62 compatible wallets that are not detected on the user machine
187
+ // Strategy to append not detected AIP-62 standard compatible extension wallets
201
188
  this.appendNotDetectedStandardSupportedWallets();
202
189
  }
203
190
 
204
- private scopePollingDetectionStrategy() {
205
- this._wallets?.forEach((wallet: Wallet) => {
206
- // Hot fix to manage Pontem wallet to not show duplications if user has the
207
- // new standard version installed. Pontem uses "Pontem" wallet name for previous versions and
208
- // "Pontem Wallet" with new version
209
- const existingStandardPontemWallet = this._standard_wallets.find(
210
- (wallet) => wallet.name == "Pontem Wallet",
211
- );
212
- if (wallet.name === "Pontem" && existingStandardPontemWallet) {
213
- return;
214
- }
215
-
216
- /**
217
- * Manage potential duplications when a plugin is installed in a dapp
218
- * but the existing wallet installed is on AIP-62 new standard - in that case we dont want to
219
- * include the plugin wallet (i.e npm package)
220
- */
221
- const existingWalletIndex = this._standard_wallets.findIndex(
222
- (standardWallet) => standardWallet.name == wallet.name,
223
- );
224
- if (existingWalletIndex !== -1) return;
225
-
226
- // push the plugin wallet to the all_wallets array
227
- this._all_wallets.push(wallet);
228
- if (!wallet.readyState) {
229
- wallet.readyState =
230
- typeof window === "undefined" || typeof document === "undefined"
231
- ? WalletReadyState.Unsupported
232
- : WalletReadyState.NotDetected;
233
- }
234
- if (typeof window !== "undefined") {
235
- scopePollingDetectionStrategy(() => {
236
- const providerName = wallet.providerName || wallet.name.toLowerCase();
237
- if (Object.keys(window).includes(providerName)) {
238
- wallet.readyState = WalletReadyState.Installed;
239
- wallet.provider = window[providerName as any];
240
- this.emit("readyStateChange", wallet);
241
- return true;
242
- }
243
- return false;
244
- });
245
- }
246
- });
247
- }
248
-
249
- private fetchExtensionAIP62AptosWallets() {
191
+ private fetchExtensionAIP62AptosWallets(): void {
250
192
  let { aptosWallets, on } = getAptosWallets();
251
193
  this.setExtensionAIP62Wallets(aptosWallets);
252
194
 
@@ -265,53 +207,38 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
265
207
  });
266
208
  }
267
209
 
268
- // Since we can't discover AIP-62 wallets that are not installed on the user machine,
269
- // we hold a AIP-62 wallets registry to show on the wallet selector modal for the users.
270
- // Append wallets from wallet standard support registry to the `all_wallets` array
271
- // when wallet is not installed on the user machine
272
- private appendNotDetectedStandardSupportedWallets() {
273
- // Loop over the registry map
274
- aptosStandardSupportedWalletList.map((supportedWallet) => {
275
- // Check if we already have this wallet as an installed plugin
276
- const existingPluginWalletIndex = this.wallets.findIndex(
277
- (wallet) => wallet.name === supportedWallet.name,
278
- );
279
-
280
- // If the plugin wallet is installed, dont append and dont show it on the selector modal
281
- // as a not detected wallet
282
- if (existingPluginWalletIndex !== -1) return;
283
-
284
- // Hot fix to manage Pontem wallet to not show duplications if user has the
285
- // new standard version installed. Pontem uses "Pontem" wallet name for previous versions and
286
- // "Pontem Wallet" with new version
287
- const existingStandardPontemWallet = this.wallets.find(
288
- (wallet) => wallet.name == "Pontem",
289
- );
290
- if (
291
- supportedWallet.name === "Pontem Wallet" &&
292
- existingStandardPontemWallet
293
- ) {
210
+ /**
211
+ * Set AIP-62 extension wallets
212
+ *
213
+ * @param extensionwWallets
214
+ */
215
+ private setExtensionAIP62Wallets(
216
+ extensionwWallets: readonly AptosWallet[]
217
+ ): void {
218
+ extensionwWallets.map((wallet: AdapterWallet) => {
219
+ if (this.excludeWallet(wallet)) {
294
220
  return;
295
221
  }
296
222
 
297
- // Check if we already have this wallet as a AIP-62 wallet standard
298
- const existingStandardWallet = this._standard_wallets.find(
299
- (wallet) => wallet.name == supportedWallet.name,
223
+ // Remove optional duplications in the _all_wallets array
224
+ this._standard_wallets = this._standard_wallets.filter(
225
+ (item) => item.name !== wallet.name
300
226
  );
301
227
 
302
- // If AIP-62 wallet detected but it is excluded by the dapp, dont add it to the wallets array
303
- if (
304
- existingStandardWallet &&
305
- this.excludeWallet(existingStandardWallet)
306
- ) {
307
- return;
308
- }
228
+ const isValid = isWalletWithRequiredFeatureSet(wallet);
229
+ if (isValid) {
230
+ // check if we already have this wallet as a not detected wallet
231
+ const index = this._standard_not_detected_wallets.findIndex(
232
+ (notDetctedWallet) => notDetctedWallet.name == wallet.name
233
+ );
234
+ // if we do, remove it from the not detected wallets array as it is now become detected
235
+ if (index !== -1) {
236
+ this._standard_not_detected_wallets.splice(index, 1);
237
+ }
309
238
 
310
- // If AIP-62 wallet does not exist, append it to the wallet selector modal
311
- // as an undetected wallet
312
- if (!existingStandardWallet) {
313
- this._all_wallets.push(supportedWallet);
314
- this.emit("standardWalletsAdded", supportedWallet);
239
+ wallet.readyState = WalletReadyState.Installed;
240
+ this._standard_wallets.push(wallet);
241
+ this.emit("standardWalletsAdded", wallet);
315
242
  }
316
243
  });
317
244
  }
@@ -319,37 +246,55 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
319
246
  /**
320
247
  * Set AIP-62 SDK wallets
321
248
  */
322
- private fetchSDKAIP62AptosWallets() {
323
- this._sdkWallets.map((wallet: AptosStandardWallet) => {
324
- this.standardizeAIP62WalletType(wallet);
249
+ private fetchSDKAIP62AptosWallets(): void {
250
+ this._sdkWallets.map((wallet: AdapterWallet) => {
251
+ if (this.excludeWallet(wallet)) {
252
+ return;
253
+ }
254
+ const isValid = isWalletWithRequiredFeatureSet(wallet);
255
+
256
+ if (isValid) {
257
+ wallet.readyState = WalletReadyState.Installed;
258
+ this._standard_wallets.push(wallet);
259
+ }
325
260
  });
326
261
  }
327
262
 
328
- /**
329
- * Set AIP-62 extension wallets
330
- *
331
- * @param extensionwWallets
332
- */
333
- private setExtensionAIP62Wallets(extensionwWallets: readonly AptosWallet[]) {
334
- // Twallet SDK fires a register event so the adapter assumes it is an extension wallet
335
- // so filter out t wallet, remove it when twallet fixes it
336
- const wallets = extensionwWallets.filter(
337
- (wallet) => wallet.name !== "Dev T wallet" && wallet.name !== "T wallet",
338
- );
339
-
340
- wallets.map((wallet: AptosStandardWallet) => {
341
- this.standardizeAIP62WalletType(wallet);
342
- this._standard_wallets.push(wallet);
263
+ // Since we can't discover AIP-62 wallets that are not installed on the user machine,
264
+ // we hold a AIP-62 wallets registry to show on the wallet selector modal for the users.
265
+ // Append wallets from wallet standard support registry to the `_standard_not_detected_wallets` array
266
+ // when wallet is not installed on the user machine
267
+ private appendNotDetectedStandardSupportedWallets(): void {
268
+ // Loop over the registry map
269
+ aptosStandardSupportedWalletList.map((supportedWallet) => {
270
+ // Check if we already have this wallet as a detected AIP-62 wallet standard
271
+ const existingStandardWallet = this._standard_wallets.find(
272
+ (wallet) => wallet.name == supportedWallet.name
273
+ );
274
+ // If it is detected, it means the user has the wallet installed, so dont add it to the wallets array
275
+ if (existingStandardWallet) {
276
+ return;
277
+ }
278
+ // If AIP-62 wallet detected but it is excluded by the dapp, dont add it to the wallets array
279
+ if (this.excludeWallet(supportedWallet)) {
280
+ return;
281
+ }
282
+ // If AIP-62 wallet does not exist, append it to the wallet selector modal
283
+ // as an undetected wallet
284
+ if (!existingStandardWallet) {
285
+ this._standard_not_detected_wallets.push(supportedWallet);
286
+ this.emit("standardNotDetectedWalletAdded", supportedWallet);
287
+ }
343
288
  });
344
289
  }
345
290
 
346
291
  /**
347
292
  * A function that excludes an AIP-62 compatible wallet the dapp doesnt want to include
348
293
  *
349
- * @param walletName
350
- * @returns
294
+ * @param wallet AdapterWallet | AdapterNotDetectedWallet
295
+ * @returns boolean
351
296
  */
352
- excludeWallet(wallet: AptosStandardWallet): boolean {
297
+ excludeWallet(wallet: AdapterWallet | AdapterNotDetectedWallet): boolean {
353
298
  // If _optInWallets is not empty, and does not include the provided wallet,
354
299
  // return true to exclude the wallet, otherwise return false
355
300
  if (
@@ -361,78 +306,7 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
361
306
  return false;
362
307
  }
363
308
 
364
- /**
365
- * Standardize AIP62 wallet
366
- *
367
- * 1) check it is Standard compatible
368
- * 2) Update its readyState to Installed (for a future UI detection)
369
- * 3) convert it to the Wallet Plugin type interface for legacy compatibility
370
- * 4) push the wallet into a local standard wallets array
371
- *
372
- * @param wallet
373
- * @returns
374
- */
375
- private standardizeAIP62WalletType(wallet: AptosStandardWallet) {
376
- if (this.excludeWallet(wallet)) {
377
- return;
378
- }
379
- const isValid = isWalletWithRequiredFeatureSet(wallet);
380
- if (isValid) {
381
- wallet.readyState = WalletReadyState.Installed;
382
- this.standardizeStandardWalletToPluginWalletType(wallet);
383
- this._standard_wallets.push(wallet);
384
- }
385
- }
386
-
387
- /**
388
- * To maintain support for both plugins and AIP-62 standard wallets,
389
- * without introducing dapps breaking changes, we convert
390
- * AIP-62 standard compatible wallets to the legacy adapter wallet plugin type.
391
- *
392
- * @param standardWallet An AIP-62 standard compatible wallet
393
- */
394
- private standardizeStandardWalletToPluginWalletType = (
395
- standardWallet: AptosStandardWallet,
396
- ) => {
397
- let standardWalletConvertedToWallet: Wallet = {
398
- name: standardWallet.name as WalletName,
399
- url: standardWallet.url,
400
- icon: standardWallet.icon,
401
- provider: standardWallet,
402
- connect: standardWallet.features["aptos:connect"].connect,
403
- disconnect: standardWallet.features["aptos:disconnect"].disconnect,
404
- network: standardWallet.features["aptos:network"].network,
405
- account: standardWallet.features["aptos:account"].account,
406
- signAndSubmitTransaction:
407
- standardWallet.features["aptos:signAndSubmitTransaction"]
408
- ?.signAndSubmitTransaction,
409
- signMessage: standardWallet.features["aptos:signMessage"].signMessage,
410
- onAccountChange:
411
- standardWallet.features["aptos:onAccountChange"].onAccountChange,
412
- onNetworkChange:
413
- standardWallet.features["aptos:onNetworkChange"].onNetworkChange,
414
- signTransaction:
415
- standardWallet.features["aptos:signTransaction"].signTransaction,
416
- openInMobileApp:
417
- standardWallet.features["aptos:openInMobileApp"]?.openInMobileApp,
418
- changeNetwork:
419
- standardWallet.features["aptos:changeNetwork"]?.changeNetwork,
420
- readyState: WalletReadyState.Installed,
421
- isAIP62Standard: true,
422
- isSignTransactionV1_1:
423
- standardWallet.features["aptos:signTransaction"]?.version === "1.1",
424
- };
425
-
426
- // Remove optional duplications in the _all_wallets array
427
- this._all_wallets = this._all_wallets.filter(
428
- (item) => item.name !== standardWalletConvertedToWallet.name,
429
- );
430
- this._all_wallets.push(standardWalletConvertedToWallet);
431
-
432
- this.emit("standardWalletsAdded", standardWalletConvertedToWallet);
433
- };
434
-
435
- private recordEvent(eventName: string, additionalInfo?: object) {
309
+ private recordEvent(eventName: string, additionalInfo?: object): void {
436
310
  this.ga4?.gtag("event", `wallet_adapter_${eventName}`, {
437
311
  wallet: this._wallet?.name,
438
312
  network: this._network?.name,
@@ -448,16 +322,13 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
448
322
  *
449
323
  * @param wallet A wallet
450
324
  */
451
- private ensureWalletExists(wallet: Wallet | null): asserts wallet is Wallet {
325
+ private ensureWalletExists(
326
+ wallet: AdapterWallet | null
327
+ ): asserts wallet is AdapterWallet {
452
328
  if (!wallet) {
453
329
  throw new WalletNotConnectedError().name;
454
330
  }
455
- if (
456
- !(
457
- wallet.readyState === WalletReadyState.Loadable ||
458
- wallet.readyState === WalletReadyState.Installed
459
- )
460
- )
331
+ if (!(wallet.readyState === WalletReadyState.Installed))
461
332
  throw new WalletNotReadyError("Wallet is not set").name;
462
333
  }
463
334
 
@@ -467,50 +338,19 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
467
338
  * @param account An account
468
339
  */
469
340
  private ensureAccountExists(
470
- account: AccountInfo | null,
341
+ account: AccountInfo | null
471
342
  ): asserts account is AccountInfo {
472
343
  if (!account) {
473
344
  throw new WalletAccountError("Account is not set").name;
474
345
  }
475
346
  }
476
347
 
477
- /**
478
- * @deprecated use ensureWalletExists
479
- */
480
- private doesWalletExist(): boolean | WalletNotConnectedError {
481
- if (!this._connected || this._connecting || !this._wallet)
482
- throw new WalletNotConnectedError().name;
483
- if (
484
- !(
485
- this._wallet.readyState === WalletReadyState.Loadable ||
486
- this._wallet.readyState === WalletReadyState.Installed
487
- )
488
- )
489
- throw new WalletNotReadyError().name;
490
- return true;
491
- }
492
-
493
- /**
494
- * Function to cleat wallet adapter data.
495
- *
496
- * - Removes current connected wallet state
497
- * - Removes current connected account state
498
- * - Removes current connected network state
499
- * - Removes autoconnect local storage value
500
- */
501
- private clearData(): void {
502
- this._connected = false;
503
- this.setWallet(null);
504
- this.setAccount(null);
505
- this.setNetwork(null);
506
- removeLocalStorage();
507
- }
508
-
509
348
  /**
510
349
  * Queries and sets ANS name for the current connected wallet account
511
350
  */
512
351
  private async setAnsName(): Promise<void> {
513
352
  if (this._network?.chainId && this._account) {
353
+ if (this._account.ansName) return;
514
354
  // ANS supports only MAINNET or TESTNET
515
355
  if (
516
356
  !ChainIdToAnsSupportedNetworkMap[this._network.chainId] ||
@@ -530,108 +370,47 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
530
370
  }
531
371
  }
532
372
 
373
+ /**
374
+ * Function to cleat wallet adapter data.
375
+ *
376
+ * - Removes current connected wallet state
377
+ * - Removes current connected account state
378
+ * - Removes current connected network state
379
+ * - Removes autoconnect local storage value
380
+ */
381
+ private clearData(): void {
382
+ this._connected = false;
383
+ this.setWallet(null);
384
+ this.setAccount(null);
385
+ this.setNetwork(null);
386
+ removeLocalStorage();
387
+ }
388
+
533
389
  /**
534
390
  * Sets the connected wallet
535
391
  *
536
392
  * @param wallet A wallet
537
393
  */
538
- setWallet(wallet: Wallet | null): void {
394
+ setWallet(wallet: AptosWallet | null): void {
539
395
  this._wallet = wallet;
540
396
  }
541
397
 
542
398
  /**
543
399
  * Sets the connected account
544
400
  *
545
- * `AccountInfo` type comes from a legacy wallet adapter plugin
546
- * `StandardAccountInfo` type comes from AIP-62 standard compatible wallet when onAccountChange event is called
547
- * `UserResponse<StandardAccountInfo>` type comes from AIP-62 standard compatible wallet on wallet connect
548
- *
549
401
  * @param account An account
550
402
  */
551
- setAccount(
552
- account:
553
- | AccountInfo
554
- | StandardAccountInfo
555
- | UserResponse<StandardAccountInfo>
556
- | null,
557
- ): void {
558
- if (account === null) {
559
- this._account = null;
560
- return;
561
- }
562
-
563
- // Check if wallet is of type AIP-62 standard
564
- if (this._wallet?.isAIP62Standard) {
565
- // Check if account is of type UserResponse<StandardAccountInfo> which means the `account`
566
- // comes from the `connect` method
567
- if ("status" in account) {
568
- const connectStandardAccount =
569
- account as UserResponse<StandardAccountInfo>;
570
- if (connectStandardAccount.status === UserResponseStatus.REJECTED) {
571
- this._connecting = false;
572
- throw new WalletConnectionError("User has rejected the request")
573
- .message;
574
- }
575
- // account is of type
576
- this._account = {
577
- address: connectStandardAccount.args.address.toString(),
578
- publicKey: connectStandardAccount.args.publicKey.toString(),
579
- ansName: connectStandardAccount.args.ansName,
580
- };
581
- return;
582
- } else {
583
- // account is of type `StandardAccountInfo` which means it comes from onAccountChange event
584
- const standardAccount = account as StandardAccountInfo;
585
- this._account = {
586
- address: standardAccount.address.toString(),
587
- publicKey: standardAccount.publicKey.toString(),
588
- ansName: standardAccount.ansName,
589
- };
590
- return;
591
- }
592
- }
593
-
594
- // account is of type `AccountInfo`
595
- this._account = { ...(account as AccountInfo) };
596
- return;
403
+ setAccount(account: AccountInfo | null): void {
404
+ this._account = account;
597
405
  }
598
406
 
599
407
  /**
600
408
  * Sets the connected network
601
409
  *
602
- * `NetworkInfo` type comes from a legacy wallet adapter plugin
603
- * `StandardNetworkInfo` type comes from AIP-62 standard compatible wallet
604
- *
605
410
  * @param network A network
606
411
  */
607
- setNetwork(network: NetworkInfo | StandardNetworkInfo | null): void {
608
- if (network === null) {
609
- this._network = null;
610
- return;
611
- }
612
- if (this._wallet?.isAIP62Standard) {
613
- const standardizeNetwork = network as StandardNetworkInfo;
614
- this.recordEvent("network_change", {
615
- from: this._network?.name,
616
- to: standardizeNetwork.name,
617
- });
618
- this._network = {
619
- name: standardizeNetwork.name.toLowerCase() as Network,
620
- chainId: standardizeNetwork.chainId.toString(),
621
- url: standardizeNetwork.url,
622
- };
623
-
624
- return;
625
- }
626
-
627
- this.recordEvent("network_change", {
628
- from: this._network?.name,
629
- to: network.name,
630
- });
631
- this._network = {
632
- ...(network as NetworkInfo),
633
- name: network.name.toLowerCase() as Network,
634
- };
412
+ setNetwork(network: NetworkInfo | null): void {
413
+ this._network = network;
635
414
  }
636
415
 
637
416
  /**
@@ -646,22 +425,12 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
646
425
  /**
647
426
  * Getter to fetch all detected wallets
648
427
  */
649
- get wallets(): ReadonlyArray<AnyAptosWallet> {
650
- return this._all_wallets;
651
- }
652
-
653
- /**
654
- * Getter to fetch all detected plugin wallets
655
- */
656
- get pluginWallets(): ReadonlyArray<Wallet> {
657
- return this._wallets;
428
+ get wallets(): ReadonlyArray<AptosWallet> {
429
+ return this._standard_wallets;
658
430
  }
659
431
 
660
- /**
661
- * Getter to fetch all detected AIP-62 standard compatible wallets
662
- */
663
- get standardWallets(): ReadonlyArray<AptosStandardWallet> {
664
- return this._standard_wallets;
432
+ get notDetectedWallets(): ReadonlyArray<AdapterNotDetectedWallet> {
433
+ return this._standard_not_detected_wallets;
665
434
  }
666
435
 
667
436
  /**
@@ -670,14 +439,10 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
670
439
  * @return wallet info
671
440
  * @throws WalletNotSelectedError
672
441
  */
673
- get wallet(): WalletInfo | null {
442
+ get wallet(): AptosWallet | null {
674
443
  try {
675
444
  if (!this._wallet) return null;
676
- return {
677
- name: this._wallet.name,
678
- icon: this._wallet.icon,
679
- url: this._wallet.url,
680
- };
445
+ return this._wallet;
681
446
  } catch (error: any) {
682
447
  throw new WalletNotSelectedError(error).message;
683
448
  }
@@ -718,12 +483,12 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
718
483
  */
719
484
  async connect(walletName: string): Promise<void | string> {
720
485
  // Checks the wallet exists in the detected wallets array
721
-
722
- const allDetectedWallets = this._all_wallets as Array<Wallet>;
486
+ const allDetectedWallets = this._standard_wallets;
723
487
 
724
488
  const selectedWallet = allDetectedWallets.find(
725
- (wallet: Wallet) => wallet.name === walletName,
489
+ (wallet: AdapterWallet) => wallet.name === walletName
726
490
  );
491
+
727
492
  if (!selectedWallet) return;
728
493
 
729
494
  // Check if wallet is already connected
@@ -731,26 +496,25 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
731
496
  // if the selected wallet is already connected, we don't need to connect again
732
497
  if (this._wallet?.name === walletName)
733
498
  throw new WalletConnectionError(
734
- `${walletName} wallet is already connected`,
499
+ `${walletName} wallet is already connected`
735
500
  ).message;
736
501
  }
737
502
 
738
503
  // Check if we are in a redirectable view (i.e on mobile AND not in an in-app browser)
739
504
  // Ignore if wallet is installed (iOS extension)
740
- if (
741
- isRedirectable() &&
742
- selectedWallet.readyState !== WalletReadyState.Installed
743
- ) {
744
- // If wallet is AIP-62 compatible
745
- if (selectedWallet.isAIP62Standard) {
505
+ if (isRedirectable()) {
506
+ if (selectedWallet.readyState === WalletReadyState.Installed) {
746
507
  // If wallet has a openInMobileApp method, use it
747
- if (selectedWallet.openInMobileApp) {
748
- selectedWallet.openInMobileApp();
508
+ if (selectedWallet.features["aptos:openInMobileApp"]?.openInMobileApp) {
509
+ selectedWallet.features["aptos:openInMobileApp"]?.openInMobileApp();
749
510
  return;
750
511
  }
512
+ }
513
+
514
+ if (selectedWallet.readyState === WalletReadyState.NotDetected) {
751
515
  // If wallet has a deeplinkProvider property, i.e wallet is on the internal registry, use it
752
516
  const uninstalledWallet =
753
- selectedWallet as AptosStandardSupportedWallet;
517
+ selectedWallet as unknown as AptosStandardSupportedWallet;
754
518
  if (uninstalledWallet.deeplinkProvider) {
755
519
  const url = encodeURIComponent(window.location.href);
756
520
  const location = uninstalledWallet.deeplinkProvider.concat(url);
@@ -758,21 +522,6 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
758
522
  return;
759
523
  }
760
524
  }
761
- // Wallet is on the old standard, check if it has a deeplinkProvider method property
762
- if (selectedWallet.deeplinkProvider) {
763
- const url = encodeURIComponent(window.location.href);
764
- const location = selectedWallet.deeplinkProvider({ url });
765
- window.location.href = location;
766
- }
767
- return;
768
- }
769
-
770
- // Check wallet state is Installed or Loadable
771
- if (
772
- selectedWallet.readyState !== WalletReadyState.Installed &&
773
- selectedWallet.readyState !== WalletReadyState.Loadable
774
- ) {
775
- return;
776
525
  }
777
526
 
778
527
  // Now we can connect to the wallet
@@ -788,18 +537,18 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
788
537
  * @emit emits "connect" event
789
538
  * @throws WalletConnectionError
790
539
  */
791
- async connectWallet(selectedWallet: Wallet): Promise<void> {
540
+ async connectWallet(selectedWallet: AdapterWallet): Promise<void> {
792
541
  try {
793
542
  this._connecting = true;
794
543
  this.setWallet(selectedWallet);
795
- let account;
796
- if (selectedWallet.isAIP62Standard) {
797
- account = await this.walletStandardCore.connect(selectedWallet);
798
- } else {
799
- account = await this.walletCoreV1.connect(selectedWallet);
544
+ const response = await selectedWallet.features["aptos:connect"].connect();
545
+ if (response.status === UserResponseStatus.REJECTED) {
546
+ throw new WalletConnectionError("User has rejected the request")
547
+ .message;
800
548
  }
549
+ const account = response.args;
801
550
  this.setAccount(account);
802
- const network = await selectedWallet.network();
551
+ const network = await selectedWallet.features["aptos:network"].network();
803
552
  this.setNetwork(network);
804
553
  await this.setAnsName();
805
554
  setLocalStorage(selectedWallet.name);
@@ -825,7 +574,7 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
825
574
  async disconnect(): Promise<void> {
826
575
  try {
827
576
  this.ensureWalletExists(this._wallet);
828
- await this._wallet.disconnect();
577
+ await this._wallet.features["aptos:disconnect"].disconnect();
829
578
  this.clearData();
830
579
  this.recordEvent("wallet_disconnect");
831
580
  this.emit("disconnect");
@@ -839,14 +588,11 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
839
588
  * Signs and submits a transaction to chain
840
589
  *
841
590
  * @param transactionInput InputTransactionData
842
- * @param options optional. A configuration object to generate a transaction by
843
- * @returns The pending transaction hash (V1 output) | PendingTransactionResponse (V2 output)
591
+ * @returns AptosSignAndSubmitTransactionOutput
844
592
  */
845
593
  async signAndSubmitTransaction(
846
- transactionInput: InputTransactionData,
847
- ): Promise<
848
- { hash: Types.HexEncodedBytes; output?: any } | PendingTransactionResponse
849
- > {
594
+ transactionInput: InputTransactionData
595
+ ): Promise<AptosSignAndSubmitTransactionOutput> {
850
596
  try {
851
597
  if ("function" in transactionInput.data) {
852
598
  if (
@@ -866,58 +612,79 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
866
612
  } = handlePublishPackageTransaction(transactionInput));
867
613
  }
868
614
  }
869
-
870
615
  this.ensureWalletExists(this._wallet);
871
616
  this.ensureAccountExists(this._account);
872
617
  this.recordEvent("sign_and_submit_transaction");
873
- // get the payload piece from the input
874
- const payloadData = transactionInput.data;
875
- const aptosConfig = getAptosConfig(this._network, this._dappConfig);
876
618
 
877
- const aptos = new Aptos(aptosConfig);
619
+ if (this._wallet.features["aptos:signAndSubmitTransaction"]) {
620
+ // check for backward compatibility. before version 1.1.0 the standard expected
621
+ // AnyRawTransaction input so the adapter built the transaction before sending it to the wallet
622
+ if (
623
+ this._wallet.features["aptos:signAndSubmitTransaction"].version !==
624
+ "1.1.0"
625
+ ) {
626
+ const aptosConfig = getAptosConfig(this._network, this._dappConfig);
627
+
628
+ const aptos = new Aptos(aptosConfig);
629
+ const transaction = await aptos.transaction.build.simple({
630
+ sender: this._account.address.toString(),
631
+ data: transactionInput.data,
632
+ options: transactionInput.options,
633
+ });
634
+
635
+ type AptosSignAndSubmitTransactionV1Method = (
636
+ transaction: AnyRawTransaction
637
+ ) => Promise<UserResponse<AptosSignAndSubmitTransactionOutput>>;
638
+
639
+ const signAndSubmitTransactionMethod = this._wallet.features[
640
+ "aptos:signAndSubmitTransaction"
641
+ ]
642
+ .signAndSubmitTransaction as unknown as AptosSignAndSubmitTransactionV1Method;
643
+
644
+ const response = (await signAndSubmitTransactionMethod(
645
+ transaction
646
+ )) as UserResponse<AptosSignAndSubmitTransactionOutput>;
647
+
648
+ if (response.status === UserResponseStatus.REJECTED) {
649
+ throw new WalletConnectionError("User has rejected the request")
650
+ .message;
651
+ }
878
652
 
879
- if (this._wallet.signAndSubmitTransaction) {
880
- // if wallet is compatible with the AIP-62 standard
881
- if (this._wallet.isAIP62Standard) {
882
- const { hash, ...output } =
883
- await this.walletStandardCore.signAndSubmitTransaction(
884
- transactionInput,
885
- aptos,
886
- this._account,
887
- this._wallet,
888
- this._standard_wallets,
889
- );
890
- return { hash, output };
891
- } else {
892
- // Else use wallet plugin
893
- const { hash, ...output } =
894
- await this.walletCoreV1.resolveSignAndSubmitTransaction(
895
- payloadData,
896
- this._network,
897
- this._wallet,
898
- transactionInput,
899
- this._dappConfig,
900
- );
901
- return { hash, output };
653
+ return response.args;
654
+ }
655
+
656
+ const response = await this._wallet.features[
657
+ "aptos:signAndSubmitTransaction"
658
+ ].signAndSubmitTransaction({
659
+ payload: transactionInput.data,
660
+ gasUnitPrice: transactionInput.options?.gasUnitPrice,
661
+ maxGasAmount: transactionInput.options?.maxGasAmount,
662
+ });
663
+ if (response.status === UserResponseStatus.REJECTED) {
664
+ throw new WalletConnectionError("User has rejected the request")
665
+ .message;
902
666
  }
667
+ return response.args;
903
668
  }
904
669
 
905
670
  // If wallet does not support signAndSubmitTransaction
906
671
  // the adapter will sign and submit it for the dapp.
907
- // Note: This should happen only for AIP-62 standard compatible wallets since
908
- // signAndSubmitTransaction is not a required function implementation
672
+ const aptosConfig = getAptosConfig(this._network, this._dappConfig);
673
+ const aptos = new Aptos(aptosConfig);
909
674
  const transaction = await aptos.transaction.build.simple({
910
675
  sender: this._account.address,
911
676
  data: transactionInput.data,
912
677
  options: transactionInput.options,
913
678
  });
914
679
 
915
- const senderAuthenticator = await this.signTransaction(transaction);
680
+ const signTransactionResponse = await this.signTransaction({
681
+ transactionOrPayload: transaction,
682
+ });
916
683
  const response = await this.submitTransaction({
917
684
  transaction,
918
- senderAuthenticator,
685
+ senderAuthenticator: signTransactionResponse.authenticator,
919
686
  });
920
- return response;
687
+ return { hash: response.hash };
921
688
  } catch (error: any) {
922
689
  const errMsg = generalizedErrorMessage(error);
923
690
  throw new WalletSignAndSubmitMessageError(errMsg).message;
@@ -927,143 +694,120 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
927
694
  /**
928
695
  * Signs a transaction
929
696
  *
930
- * To support both existing wallet adapter V1 and V2, we support 2 input types
697
+ * This method supports 2 input types -
698
+ * 1. A raw transaction that was already built by the dapp,
699
+ * 2. A transaction data input as JSON. This is for the wallet to be able to simulate before signing
931
700
  *
932
- * @param transactionOrPayload AnyRawTransaction - V2 input | Types.TransactionPayload - V1 input
933
- * @param options optional. V1 input
701
+ * @param transactionOrPayload AnyRawTransaction | InputTransactionData
702
+ * @param asFeePayer optional. A flag indicates to sign the transaction as the fee payer
703
+ * @param options optional. Transaction options
934
704
  *
935
705
  * @returns AccountAuthenticator
936
706
  */
937
- async signTransaction(
938
- transactionOrPayload: AnyRawTransaction | Types.TransactionPayload,
939
- asFeePayer?: boolean,
940
- options?: InputGenerateTransactionOptions,
941
- ): Promise<AccountAuthenticator> {
707
+ async signTransaction(args: {
708
+ transactionOrPayload: AnyRawTransaction | InputTransactionData;
709
+ asFeePayer?: boolean;
710
+ }): Promise<{
711
+ authenticator: AccountAuthenticator;
712
+ rawTransaction: Uint8Array;
713
+ }> {
714
+ const { transactionOrPayload, asFeePayer } = args;
715
+ /**
716
+ * All standard compatible wallets should support AnyRawTransaction for signTransaction version 1.0.0
717
+ * For standard signTransaction version 1.1.0, the standard expects a transaction input
718
+ *
719
+ * So, if the input is AnyRawTransaction, we can directly call the wallet's signTransaction method
720
+ *
721
+ *
722
+ * If the input is InputTransactionData, we need to
723
+ * 1. check if the wallet supports signTransaction version 1.1.0 - if so, we convert the input to the standard expected input
724
+ * 2. if it does not support signTransaction version 1.1.0, we convert it to a rawTransaction input and call the wallet's signTransaction method
725
+ */
726
+
942
727
  try {
943
728
  this.ensureWalletExists(this._wallet);
729
+ this.ensureAccountExists(this._account);
944
730
  this.recordEvent("sign_transaction");
945
- // Make sure wallet supports signTransaction
946
- if (this._wallet.signTransaction) {
947
- // If current connected wallet is AIP-62 standard compatible
948
- // we want to make sure the transaction input is what the
949
- // standard expects, i,e new sdk v2 input
950
- if (this._wallet.isAIP62Standard) {
951
- // if rawTransaction prop it means transaction input data is
952
- // compatible with new sdk v2 input
953
- if ("rawTransaction" in transactionOrPayload) {
954
- return await this.walletStandardCore.signTransaction(
955
- transactionOrPayload,
956
- this._wallet,
957
- asFeePayer,
958
- );
959
- } else if (this._wallet.isSignTransactionV1_1) {
960
- // This wallet is AIP-62 compliant and supports transaction inputs
961
- const payload = convertPayloadInputV1ToV2(transactionOrPayload);
962
- const optionsV1 = options as
963
- | CompatibleTransactionOptions
964
- | undefined;
965
- const { authenticator } =
966
- await this.walletStandardCore.signTransaction(
967
- {
968
- payload,
969
- expirationTimestamp:
970
- optionsV1?.expireTimestamp ??
971
- optionsV1?.expirationTimestamp,
972
- expirationSecondsFromNow: optionsV1?.expirationSecondsFromNow,
973
- gasUnitPrice:
974
- optionsV1?.gasUnitPrice ?? optionsV1?.gas_unit_price,
975
- maxGasAmount:
976
- optionsV1?.maxGasAmount ?? optionsV1?.max_gas_amount,
977
- sequenceNumber: optionsV1?.sequenceNumber,
978
- sender: optionsV1?.sender
979
- ? { address: AccountAddress.from(optionsV1.sender) }
980
- : undefined,
981
- },
982
- this._wallet,
983
- );
984
- return authenticator;
985
- } else {
986
- const aptosConfig = getAptosConfig(this._network, this._dappConfig);
987
- this.ensureAccountExists(this._account);
988
- const sender = this._account.address;
989
- const payload = await generateTransactionPayloadFromV1Input(
990
- aptosConfig,
991
- transactionOrPayload,
992
- );
993
- const optionsV1 = options as CompatibleTransactionOptions;
994
- const optionsV2 = {
995
- accountSequenceNumber: optionsV1?.sequenceNumber,
996
- expireTimestamp:
997
- optionsV1?.expireTimestamp ?? optionsV1?.expirationTimestamp,
998
- gasUnitPrice:
999
- optionsV1?.gasUnitPrice ?? optionsV1?.gas_unit_price,
1000
- maxGasAmount:
1001
- optionsV1?.maxGasAmount ?? optionsV1?.max_gas_amount,
1002
- };
1003
- const rawTransaction = await generateRawTransaction({
1004
- aptosConfig,
1005
- payload,
1006
- sender,
1007
- options: optionsV2,
1008
- });
1009
- return await this.walletStandardCore.signTransaction(
1010
- new SimpleTransaction(rawTransaction),
1011
- this._wallet,
1012
- false,
1013
- );
1014
- }
1015
- }
1016
-
1017
- // If current connected wallet is legacy compatible with wallet standard
1018
-
1019
- // if input is AnyRawTransaction, i.e new sdk v2 input
1020
- if ("rawTransaction" in transactionOrPayload) {
1021
- const accountAuthenticator = (await this._wallet.signTransaction(
1022
- transactionOrPayload,
1023
- asFeePayer,
1024
- )) as AccountAuthenticator;
1025
-
1026
- return accountAuthenticator;
1027
- } else {
1028
- const response = await this.walletCoreV1.signTransaction(
1029
- transactionOrPayload as Types.TransactionPayload,
1030
- this._wallet!,
1031
- {
1032
- max_gas_amount: options?.maxGasAmount
1033
- ? BigInt(options?.maxGasAmount)
1034
- : undefined,
1035
- gas_unit_price: options?.gasUnitPrice
1036
- ? BigInt(options?.gasUnitPrice)
1037
- : undefined,
1038
- },
1039
- );
1040
-
1041
- if (!response) {
1042
- throw new Error("error");
1043
- }
1044
-
1045
- // Convert retuned bcs serialized SignedTransaction into V2 AccountAuthenticator
1046
- const deserializer1 = new BCS.Deserializer(response);
1047
- const deserializedSignature =
1048
- TxnBuilderTypes.SignedTransaction.deserialize(deserializer1);
1049
- const transactionAuthenticator =
1050
- deserializedSignature.authenticator as TxnBuilderTypes.TransactionAuthenticatorEd25519;
1051
731
 
1052
- const publicKey = transactionAuthenticator.public_key.value;
1053
- const signature = transactionAuthenticator.signature.value;
732
+ // dapp sends a generated transaction (i.e AnyRawTransaction), which is supported by the wallet standard at signTransaction version 1.0.0
733
+ if ("rawTransaction" in transactionOrPayload) {
734
+ const response = (await this._wallet?.features[
735
+ "aptos:signTransaction"
736
+ ].signTransaction(
737
+ transactionOrPayload,
738
+ asFeePayer
739
+ )) as UserResponse<AccountAuthenticator>;
740
+ if (response.status === UserResponseStatus.REJECTED) {
741
+ throw new WalletConnectionError("User has rejected the request")
742
+ .message;
743
+ }
744
+ return {
745
+ authenticator: response.args,
746
+ rawTransaction: transactionOrPayload.rawTransaction.bcsToBytes(),
747
+ };
748
+ } // dapp sends a transaction data input (i.e InputTransactionData), which is supported by the wallet standard at signTransaction version 1.1.0
749
+ else if (
750
+ this._wallet.features["aptos:signTransaction"]?.version === "1.1"
751
+ ) {
752
+ // convert input to standard expected input
753
+ const signTransactionV1_1StandardInput: AptosSignTransactionInputV1_1 =
754
+ {
755
+ payload: transactionOrPayload.data,
756
+ expirationTimestamp:
757
+ transactionOrPayload.options?.expirationTimestamp,
758
+ expirationSecondsFromNow:
759
+ transactionOrPayload.options?.expirationSecondsFromNow,
760
+ gasUnitPrice: transactionOrPayload.options?.gasUnitPrice,
761
+ maxGasAmount: transactionOrPayload.options?.maxGasAmount,
762
+ sequenceNumber: transactionOrPayload.options?.accountSequenceNumber,
763
+ sender: transactionOrPayload.sender
764
+ ? { address: AccountAddress.from(transactionOrPayload.sender) }
765
+ : undefined,
766
+ };
767
+
768
+ const walletSignTransactionMethod = this._wallet?.features[
769
+ "aptos:signTransaction"
770
+ ].signTransaction as AptosSignTransactionMethod &
771
+ AptosSignTransactionMethodV1_1;
772
+
773
+ const response = (await walletSignTransactionMethod(
774
+ signTransactionV1_1StandardInput
775
+ )) as UserResponse<AptosSignTransactionOutputV1_1>;
776
+ if (response.status === UserResponseStatus.REJECTED) {
777
+ throw new WalletConnectionError("User has rejected the request")
778
+ .message;
779
+ }
780
+ return {
781
+ authenticator: response.args.authenticator,
782
+ rawTransaction: response.args.rawTransaction.bcsToBytes(),
783
+ };
784
+ } else {
785
+ // dapp input is InputTransactionData but the wallet does not support it, so we convert it to a rawTransaction
786
+ const aptosConfig = getAptosConfig(this._network, this._dappConfig);
787
+ const aptos = new Aptos(aptosConfig);
788
+
789
+ const transaction = await aptos.transaction.build.simple({
790
+ sender: this._account.address,
791
+ data: transactionOrPayload.data,
792
+ options: transactionOrPayload.options,
793
+ });
1054
794
 
1055
- const accountAuthenticator = new AccountAuthenticatorEd25519(
1056
- new Ed25519PublicKey(publicKey),
1057
- new Ed25519Signature(signature),
1058
- );
1059
- return accountAuthenticator;
795
+ const response = (await this._wallet?.features[
796
+ "aptos:signTransaction"
797
+ ].signTransaction(
798
+ transaction,
799
+ asFeePayer
800
+ )) as UserResponse<AccountAuthenticator>;
801
+ if (response.status === UserResponseStatus.REJECTED) {
802
+ throw new WalletConnectionError("User has rejected the request")
803
+ .message;
1060
804
  }
1061
- }
1062
805
 
1063
- // If we are here it means this wallet does not support signTransaction
1064
- throw new WalletNotSupportedMethod(
1065
- `Sign Transaction is not supported by ${this.wallet?.name}`,
1066
- ).message;
806
+ return {
807
+ authenticator: response.args,
808
+ rawTransaction: transaction.bcsToBytes(),
809
+ };
810
+ }
1067
811
  } catch (error: any) {
1068
812
  const errMsg = generalizedErrorMessage(error);
1069
813
  throw new WalletSignTransactionError(errMsg).message;
@@ -1071,21 +815,27 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
1071
815
  }
1072
816
 
1073
817
  /**
1074
- * Sign message (doesnt submit to chain).
818
+ * Sign a message (doesnt submit to chain).
819
+ *
820
+ * @param message - AptosSignMessageInput
1075
821
  *
1076
- * @param message
1077
822
  * @return response from the wallet's signMessage function
1078
823
  * @throws WalletSignMessageError
1079
824
  */
1080
- async signMessage(message: SignMessagePayload): Promise<SignMessageResponse> {
825
+ async signMessage(
826
+ message: AptosSignMessageInput
827
+ ): Promise<AptosSignMessageOutput> {
1081
828
  try {
1082
829
  this.ensureWalletExists(this._wallet);
1083
830
  this.recordEvent("sign_message");
1084
- if (this._wallet.isAIP62Standard) {
1085
- return await this.walletStandardCore.signMessage(message, this._wallet);
831
+
832
+ const response =
833
+ await this._wallet?.features["aptos:signMessage"]?.signMessage(message);
834
+ if (response.status === UserResponseStatus.REJECTED) {
835
+ throw new WalletConnectionError("User has rejected the request")
836
+ .message;
1086
837
  }
1087
- const response = await this._wallet!.signMessage(message);
1088
- return response as SignMessageResponse;
838
+ return response.args;
1089
839
  } catch (error: any) {
1090
840
  const errMsg = generalizedErrorMessage(error);
1091
841
  throw new WalletSignMessageError(errMsg).message;
@@ -1095,12 +845,13 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
1095
845
  /**
1096
846
  * Submits transaction to chain
1097
847
  *
1098
- * @param transaction
848
+ * @param transaction - InputSubmitTransactionData
1099
849
  * @returns PendingTransactionResponse
1100
850
  */
1101
851
  async submitTransaction(
1102
- transaction: InputSubmitTransactionData,
852
+ transaction: InputSubmitTransactionData
1103
853
  ): Promise<PendingTransactionResponse> {
854
+ // The standard does not support submitTransaction, so we use the adapter to submit the transaction
1104
855
  try {
1105
856
  this.ensureWalletExists(this._wallet);
1106
857
 
@@ -1112,14 +863,6 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
1112
863
  this.recordEvent("submit_transaction", {
1113
864
  transaction_type: transactionType,
1114
865
  });
1115
- // If wallet supports submitTransaction transaction function
1116
- if (this._wallet.submitTransaction) {
1117
- const pendingTransaction =
1118
- await this._wallet.submitTransaction(transaction);
1119
- return pendingTransaction;
1120
- }
1121
-
1122
- // Else have the adapter submit the transaction
1123
866
 
1124
867
  const aptosConfig = getAptosConfig(this._network, this._dappConfig);
1125
868
  const aptos = new Aptos(aptosConfig);
@@ -1134,7 +877,7 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
1134
877
  }
1135
878
  } catch (error: any) {
1136
879
  const errMsg = generalizedErrorMessage(error);
1137
- throw new WalletSignTransactionError(errMsg).message;
880
+ throw new WalletSubmitTransactionError(errMsg).message;
1138
881
  }
1139
882
  }
1140
883
 
@@ -1146,13 +889,13 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
1146
889
  async onAccountChange(): Promise<void> {
1147
890
  try {
1148
891
  this.ensureWalletExists(this._wallet);
1149
- await this._wallet.onAccountChange(
1150
- async (data: AccountInfo | StandardAccountInfo) => {
892
+ await this._wallet.features["aptos:onAccountChange"]?.onAccountChange(
893
+ async (data: AccountInfo) => {
1151
894
  this.setAccount(data);
1152
895
  await this.setAnsName();
1153
896
  this.recordEvent("account_change");
1154
897
  this.emit("accountChange", this._account);
1155
- },
898
+ }
1156
899
  );
1157
900
  } catch (error: any) {
1158
901
  const errMsg = generalizedErrorMessage(error);
@@ -1168,12 +911,12 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
1168
911
  async onNetworkChange(): Promise<void> {
1169
912
  try {
1170
913
  this.ensureWalletExists(this._wallet);
1171
- await this._wallet.onNetworkChange(
1172
- async (data: NetworkInfo | StandardNetworkInfo) => {
914
+ await this._wallet.features["aptos:onNetworkChange"]?.onNetworkChange(
915
+ async (data: NetworkInfo) => {
1173
916
  this.setNetwork(data);
1174
917
  await this.setAnsName();
1175
918
  this.emit("networkChange", this._network);
1176
- },
919
+ }
1177
920
  );
1178
921
  } catch (error: any) {
1179
922
  const errMsg = generalizedErrorMessage(error);
@@ -1184,7 +927,7 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
1184
927
  /**
1185
928
  * Sends a change network request to the wallet to change the connected network
1186
929
  *
1187
- * @param network
930
+ * @param network - Network
1188
931
  * @returns AptosChangeNetworkOutput
1189
932
  */
1190
933
  async changeNetwork(network: Network): Promise<AptosChangeNetworkOutput> {
@@ -1198,20 +941,26 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
1198
941
  network === Network.DEVNET
1199
942
  ? await fetchDevnetChainId()
1200
943
  : NetworkToChainId[network];
1201
- if (this._wallet.changeNetwork) {
1202
- const networkInfo: StandardNetworkInfo = {
1203
- name: network,
1204
- chainId,
1205
- };
1206
- const response = await this._wallet.changeNetwork(networkInfo);
944
+
945
+ const networkInfo: NetworkInfo = {
946
+ name: network,
947
+ chainId,
948
+ };
949
+
950
+ if (this._wallet.features["aptos:changeNetwork"]) {
951
+ const response =
952
+ await this._wallet.features["aptos:changeNetwork"].changeNetwork(
953
+ networkInfo
954
+ );
1207
955
  if (response.status === UserResponseStatus.REJECTED) {
1208
956
  throw new WalletConnectionError("User has rejected the request")
1209
957
  .message;
1210
958
  }
1211
959
  return response.args;
1212
960
  }
961
+
1213
962
  throw new WalletChangeNetworkError(
1214
- `${this._wallet.name} does not support changing network request`,
963
+ `${this._wallet.name} does not support changing network request`
1215
964
  ).message;
1216
965
  } catch (error: any) {
1217
966
  const errMsg = generalizedErrorMessage(error);
@@ -1221,27 +970,66 @@ export class WalletCore extends EventEmitter<WalletCoreEvents> {
1221
970
 
1222
971
  /**
1223
972
  * Signs a message and verifies the signer
1224
- * @param message SignMessagePayload
973
+ * @param message - AptosSignMessageInput
1225
974
  * @returns boolean
1226
975
  */
1227
- async signMessageAndVerify(message: SignMessagePayload): Promise<boolean> {
976
+ async signMessageAndVerify(message: AptosSignMessageInput): Promise<boolean> {
1228
977
  try {
1229
978
  this.ensureWalletExists(this._wallet);
1230
979
  this.ensureAccountExists(this._account);
1231
980
  this.recordEvent("sign_message_and_verify");
1232
- // If current connected wallet is AIP-62 standard compatible
1233
- if (this._wallet.isAIP62Standard) {
1234
- return this.walletStandardCore.signMessageAndVerify(
1235
- message,
1236
- this._wallet,
1237
- );
1238
- }
1239
981
 
1240
- return await this.walletCoreV1.signMessageAndVerify(
1241
- message,
1242
- this._wallet,
1243
- this._account,
1244
- );
982
+ try {
983
+ // sign the message
984
+ const response = (await this._wallet.features[
985
+ "aptos:signMessage"
986
+ ].signMessage(message)) as UserResponse<AptosSignMessageOutput>;
987
+
988
+ if (response.status === UserResponseStatus.REJECTED) {
989
+ throw new WalletConnectionError("Failed to sign a message").message;
990
+ }
991
+
992
+ // For Keyless wallet accounts we skip verification for now.
993
+ // TODO: Remove when client-side verification is done in SDK.
994
+ if (
995
+ this._account.publicKey instanceof AnyPublicKey &&
996
+ this._account.publicKey.variant === AnyPublicKeyVariant.Keyless
997
+ ) {
998
+ return true;
999
+ }
1000
+
1001
+ let verified = false;
1002
+ // if is a multi sig wallet with a MultiEd25519Signature type
1003
+ if (response.args.signature instanceof MultiEd25519Signature) {
1004
+ if (!(this._account.publicKey instanceof MultiEd25519PublicKey)) {
1005
+ throw new WalletSignMessageAndVerifyError(
1006
+ "Public key and Signature type mismatch"
1007
+ ).message;
1008
+ }
1009
+ const { fullMessage, signature } = response.args;
1010
+ const bitmap = signature.bitmap;
1011
+ if (bitmap) {
1012
+ const minKeysRequired = this._account.publicKey.threshold;
1013
+ if (signature.signatures.length < minKeysRequired) {
1014
+ verified = false;
1015
+ } else {
1016
+ verified = this._account.publicKey.verifySignature({
1017
+ message: new TextEncoder().encode(fullMessage),
1018
+ signature,
1019
+ });
1020
+ }
1021
+ }
1022
+ } else {
1023
+ verified = this._account.publicKey.verifySignature({
1024
+ message: new TextEncoder().encode(response.args.fullMessage),
1025
+ signature: response.args.signature,
1026
+ });
1027
+ }
1028
+ return verified;
1029
+ } catch (error: any) {
1030
+ const errMsg = generalizedErrorMessage(error);
1031
+ throw new WalletSignMessageAndVerifyError(errMsg).message;
1032
+ }
1245
1033
  } catch (error: any) {
1246
1034
  const errMsg = generalizedErrorMessage(error);
1247
1035
  throw new WalletSignMessageAndVerifyError(errMsg).message;