@aptos-labs/wallet-adapter-core 3.5.0 → 3.7.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aptos-labs/wallet-adapter-core",
3
- "version": "3.5.0",
3
+ "version": "3.7.0",
4
4
  "description": "Aptos Wallet Adapter Core",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -38,13 +38,14 @@
38
38
  "@aptos-labs/wallet-adapter-tsconfig": "0.0.0"
39
39
  },
40
40
  "dependencies": {
41
+ "@aptos-labs/wallet-standard": "^0.0.11",
41
42
  "buffer": "^6.0.3",
42
43
  "eventemitter3": "^4.0.7",
43
44
  "tweetnacl": "^1.0.3"
44
45
  },
45
46
  "peerDependencies": {
46
- "aptos": "^1.21.0",
47
- "@aptos-labs/ts-sdk": "^1.3.0"
47
+ "@aptos-labs/ts-sdk": "^1.11.0",
48
+ "aptos": "^1.21.0"
48
49
  },
49
50
  "scripts": {
50
51
  "build": "tsup src/index.ts --format esm,cjs --dts",
@@ -0,0 +1,176 @@
1
+ import {
2
+ UserResponse,
3
+ AptosSignTransactionOutput,
4
+ AptosSignMessageOutput,
5
+ AptosSignMessageInput,
6
+ AptosWallet,
7
+ UserResponseStatus,
8
+ AptosSignAndSubmitTransactionOutput,
9
+ AccountInfo as StandardAccountInfo,
10
+ } from "@aptos-labs/wallet-standard";
11
+ import {
12
+ AnyRawTransaction,
13
+ PendingTransactionResponse,
14
+ Aptos,
15
+ MultiEd25519Signature,
16
+ MultiEd25519PublicKey,
17
+ } from "@aptos-labs/ts-sdk";
18
+
19
+ import { WalletReadyState } from "../constants";
20
+ import {
21
+ WalletConnectionError,
22
+ WalletSignAndSubmitMessageError,
23
+ WalletSignMessageAndVerifyError,
24
+ WalletSignMessageError,
25
+ } from "../error";
26
+ import {
27
+ AccountInfo,
28
+ InputTransactionData,
29
+ Wallet,
30
+ } from "../LegacyWalletPlugins/types";
31
+ import { generalizedErrorMessage } from "../utils";
32
+
33
+ export type AptosStandardWallet = AptosWallet & {
34
+ readyState?: WalletReadyState;
35
+ };
36
+
37
+ export class WalletStandardCore {
38
+ /**
39
+ * Signs and submits a transaction to chain
40
+ *
41
+ * @param transactionInput InputTransactionData
42
+ * @returns PendingTransactionResponse
43
+ */
44
+ async signAndSubmitTransaction(
45
+ transactionInput: InputTransactionData,
46
+ aptos: Aptos,
47
+ account: AccountInfo,
48
+ wallet: Wallet
49
+ ): Promise<PendingTransactionResponse> {
50
+ try {
51
+ const transaction = await aptos.transaction.build.simple({
52
+ sender: account.address.toString(),
53
+ data: transactionInput.data,
54
+ options: transactionInput.options,
55
+ });
56
+ const response = (await wallet.signAndSubmitTransaction!(
57
+ transaction
58
+ )) as UserResponse<AptosSignAndSubmitTransactionOutput>;
59
+ if (response.status === UserResponseStatus.REJECTED) {
60
+ throw new WalletConnectionError("User has rejected the request")
61
+ .message;
62
+ }
63
+
64
+ return response.args;
65
+ } catch (error: any) {
66
+ const errMsg = generalizedErrorMessage(error);
67
+ throw new WalletSignAndSubmitMessageError(errMsg).message;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Signs a transaction
73
+ *
74
+ * To support both existing wallet adapter V1 and V2, we support 2 input types
75
+ *
76
+ * @param transactionOrPayload AnyRawTransaction
77
+ * @param options asFeePayer. To sign a transaction as the fee payer sponsor
78
+ *
79
+ * @returns AptosSignTransactionOutput
80
+ */
81
+ async signTransaction(
82
+ transaction: AnyRawTransaction,
83
+ wallet: Wallet,
84
+ asFeePayer?: boolean
85
+ ): Promise<AptosSignTransactionOutput> {
86
+ const response = (await wallet.signTransaction!(
87
+ transaction,
88
+ asFeePayer
89
+ )) as UserResponse<AptosSignTransactionOutput>;
90
+ if (response.status === UserResponseStatus.REJECTED) {
91
+ throw new WalletConnectionError("User has rejected the request").message;
92
+ }
93
+ return response.args;
94
+ }
95
+
96
+ /**
97
+ * Sign message
98
+ *
99
+ * @param message AptosSignMessageInput
100
+ * @return AptosSignMessageOutput
101
+ * @throws WalletSignMessageError
102
+ */
103
+ async signMessage(
104
+ message: AptosSignMessageInput,
105
+ wallet: Wallet
106
+ ): Promise<AptosSignMessageOutput> {
107
+ try {
108
+ const response = (await wallet.signMessage(
109
+ message
110
+ )) as UserResponse<AptosSignMessageOutput>;
111
+ if (response.status === UserResponseStatus.REJECTED) {
112
+ throw new WalletConnectionError("User has rejected the request")
113
+ .message;
114
+ }
115
+ return response.args;
116
+ } catch (error: any) {
117
+ const errMsg = generalizedErrorMessage(error);
118
+ throw new WalletSignMessageError(errMsg).message;
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Signs a message and verifies the signer
124
+ * @param message AptosSignMessageInput
125
+ * @returns boolean
126
+ */
127
+ async signMessageAndVerify(
128
+ message: AptosSignMessageInput,
129
+ wallet: Wallet
130
+ ): Promise<boolean> {
131
+ try {
132
+ // sign the message
133
+ const response = (await wallet.signMessage(
134
+ message
135
+ )) as UserResponse<AptosSignMessageOutput>;
136
+ // standard wallet account() method is a required method
137
+ const account = (await wallet.account!()) as StandardAccountInfo;
138
+
139
+ if (response.status === UserResponseStatus.REJECTED) {
140
+ throw new WalletConnectionError("Failed to sign a message").message;
141
+ }
142
+
143
+ let verified = false;
144
+ // if is a multi sig wallet with a MultiEd25519Signature type
145
+ if (response.args.signature instanceof MultiEd25519Signature) {
146
+ if (!(account.publicKey instanceof MultiEd25519PublicKey)) {
147
+ throw new WalletSignMessageAndVerifyError(
148
+ "Public key and Signature type mismatch"
149
+ ).message;
150
+ }
151
+ const { fullMessage, signature } = response.args;
152
+ const bitmap = signature.bitmap;
153
+ if (bitmap) {
154
+ const minKeysRequired = account.publicKey.threshold;
155
+ if (signature.signatures.length < minKeysRequired) {
156
+ verified = false;
157
+ } else {
158
+ verified = account.publicKey.verifySignature({
159
+ message: new TextEncoder().encode(fullMessage),
160
+ signature,
161
+ });
162
+ }
163
+ }
164
+ } else {
165
+ verified = account.publicKey.verifySignature({
166
+ message: new TextEncoder().encode(response.args.fullMessage),
167
+ signature: response.args.signature,
168
+ });
169
+ }
170
+ return verified;
171
+ } catch (error: any) {
172
+ const errMsg = generalizedErrorMessage(error);
173
+ throw new WalletSignMessageAndVerifyError(errMsg).message;
174
+ }
175
+ }
176
+ }
@@ -0,0 +1,251 @@
1
+ import { HexString, TxnBuilderTypes, Types } from "aptos";
2
+ import EventEmitter from "eventemitter3";
3
+ import { Buffer } from "buffer";
4
+ import {
5
+ AptosConfig,
6
+ InputEntryFunctionDataWithRemoteABI,
7
+ InputGenerateTransactionPayloadData,
8
+ generateTransactionPayload,
9
+ } from "@aptos-labs/ts-sdk";
10
+ import nacl from "tweetnacl";
11
+ import {
12
+ WalletNotSupportedMethod,
13
+ WalletSignAndSubmitMessageError,
14
+ WalletSignMessageAndVerifyError,
15
+ WalletSignTransactionError,
16
+ } from "../error";
17
+ import {
18
+ Wallet,
19
+ WalletCoreEvents,
20
+ TransactionOptions,
21
+ NetworkInfo,
22
+ InputTransactionData,
23
+ AccountInfo,
24
+ SignMessagePayload,
25
+ SignMessageResponse,
26
+ } from "./types";
27
+
28
+ import {
29
+ convertNetwork,
30
+ convertV2PayloadToV1JSONPayload,
31
+ convertV2TransactionPayloadToV1BCSPayload,
32
+ } from "./conversion";
33
+ import { areBCSArguments, generalizedErrorMessage } from "../utils";
34
+
35
+ export class WalletCoreV1 extends EventEmitter<WalletCoreEvents> {
36
+ /**
37
+ * Resolve the transaction type (BCS arguments or Simple arguments)
38
+ *
39
+ * @param payloadData
40
+ * @param network
41
+ * @param wallet
42
+ * @param transactionInput
43
+ *
44
+ * @returns
45
+ */
46
+ async resolveSignAndSubmitTransaction(
47
+ payloadData: InputGenerateTransactionPayloadData,
48
+ network: NetworkInfo | null,
49
+ wallet: Wallet,
50
+ transactionInput: InputTransactionData
51
+ ) {
52
+ // first check if each argument is a BCS serialized argument
53
+ if (areBCSArguments(payloadData.functionArguments)) {
54
+ const aptosConfig = new AptosConfig({
55
+ network: convertNetwork(network),
56
+ });
57
+ const newPayload = await generateTransactionPayload({
58
+ ...(payloadData as InputEntryFunctionDataWithRemoteABI),
59
+ aptosConfig: aptosConfig,
60
+ });
61
+ const oldTransactionPayload =
62
+ convertV2TransactionPayloadToV1BCSPayload(newPayload);
63
+ // Call and return signAndSubmitBCSTransaction response
64
+ return await this.signAndSubmitBCSTransaction(
65
+ oldTransactionPayload,
66
+ wallet!,
67
+ {
68
+ max_gas_amount: transactionInput.options?.maxGasAmount
69
+ ? BigInt(transactionInput.options?.maxGasAmount)
70
+ : undefined,
71
+ gas_unit_price: transactionInput.options?.gasUnitPrice
72
+ ? BigInt(transactionInput.options?.gasUnitPrice)
73
+ : undefined,
74
+ }
75
+ );
76
+ }
77
+
78
+ // if it is not a bcs serialized arguments transaction, convert to the old
79
+ // json format
80
+ const oldTransactionPayload = convertV2PayloadToV1JSONPayload(payloadData);
81
+ return await this.signAndSubmitTransaction(oldTransactionPayload, wallet!, {
82
+ max_gas_amount: transactionInput.options?.maxGasAmount
83
+ ? BigInt(transactionInput.options?.maxGasAmount)
84
+ : undefined,
85
+ gas_unit_price: transactionInput.options?.gasUnitPrice
86
+ ? BigInt(transactionInput.options?.gasUnitPrice)
87
+ : undefined,
88
+ });
89
+ }
90
+
91
+ /**
92
+ Sign and submit an entry (not bcs serialized) transaction type to chain.
93
+ @param transaction a non-bcs serialized transaction
94
+ @param options max_gas_amount and gas_unit_limit
95
+ @return response from the wallet's signAndSubmitTransaction function
96
+ @throws WalletSignAndSubmitMessageError
97
+ */
98
+ async signAndSubmitTransaction(
99
+ transaction: Types.TransactionPayload,
100
+ wallet: Wallet,
101
+ options?: TransactionOptions
102
+ ): Promise<any> {
103
+ try {
104
+ const response = await (wallet as any).signAndSubmitTransaction(
105
+ transaction,
106
+ options
107
+ );
108
+ return response;
109
+ } catch (error: any) {
110
+ const errMsg =
111
+ typeof error == "object" && "message" in error ? error.message : error;
112
+ throw new WalletSignAndSubmitMessageError(errMsg).message;
113
+ }
114
+ }
115
+
116
+ /**
117
+ Sign and submit a bsc serialized transaction type to chain.
118
+ @param transaction a bcs serialized transaction
119
+ @param options max_gas_amount and gas_unit_limit
120
+ @return response from the wallet's signAndSubmitBCSTransaction function
121
+ @throws WalletSignAndSubmitMessageError
122
+ */
123
+ async signAndSubmitBCSTransaction(
124
+ transaction: TxnBuilderTypes.TransactionPayload,
125
+ wallet: Wallet,
126
+ options?: TransactionOptions
127
+ ): Promise<any> {
128
+ if (!("signAndSubmitBCSTransaction" in wallet)) {
129
+ throw new WalletNotSupportedMethod(
130
+ `Submit a BCS Transaction is not supported by ${wallet.name}`
131
+ ).message;
132
+ }
133
+ try {
134
+ const response = await (wallet as any).signAndSubmitBCSTransaction(
135
+ transaction,
136
+ options
137
+ );
138
+ return response;
139
+ } catch (error: any) {
140
+ const errMsg =
141
+ typeof error == "object" && "message" in error ? error.message : error;
142
+ throw new WalletSignAndSubmitMessageError(errMsg).message;
143
+ }
144
+ }
145
+
146
+ /**
147
+ Sign transaction
148
+ @param transaction
149
+ @param options max_gas_amount and gas_unit_limit
150
+ @return response from the wallet's signTransaction function
151
+ @throws WalletSignTransactionError
152
+ */
153
+ async signTransaction(
154
+ transaction: Types.TransactionPayload,
155
+ wallet: Wallet,
156
+ options?: TransactionOptions
157
+ ): Promise<Uint8Array | null> {
158
+ try {
159
+ const response = await (wallet as any).signTransaction(
160
+ transaction,
161
+ options
162
+ );
163
+ return response;
164
+ } catch (error: any) {
165
+ const errMsg =
166
+ typeof error == "object" && "message" in error ? error.message : error;
167
+ throw new WalletSignTransactionError(errMsg).message;
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Signs a message and verifies the signer
173
+ * @param message SignMessagePayload
174
+ * @returns boolean
175
+ */
176
+ async signMessageAndVerify(
177
+ message: SignMessagePayload,
178
+ wallet: Wallet,
179
+ account: AccountInfo
180
+ ): Promise<boolean> {
181
+ try {
182
+ const response = await wallet.signMessage(message);
183
+ if (!response)
184
+ throw new WalletSignMessageAndVerifyError("Failed to sign a message")
185
+ .message;
186
+ console.log("signMessageAndVerify signMessage response", response);
187
+
188
+ // Verify that the bytes were signed using the private key that matches the known public key
189
+ let verified = false;
190
+ if (Array.isArray((response as SignMessageResponse).signature)) {
191
+ // multi sig wallets
192
+ const { fullMessage, signature, bitmap } =
193
+ response as SignMessageResponse;
194
+ if (bitmap) {
195
+ const minKeysRequired = account.minKeysRequired as number;
196
+ if ((signature as string[]).length < minKeysRequired) {
197
+ verified = false;
198
+ } else {
199
+ // Getting an array which marks the keys signing the message with 1, while marking 0 for the keys not being used.
200
+ const bits = Array.from(bitmap).flatMap((n) =>
201
+ Array.from({ length: 8 }).map((_, i) => (n >> i) & 1)
202
+ );
203
+ // Filter out indexes of the keys we need
204
+ const index = bits.map((_, i) => i).filter((i) => bits[i]);
205
+
206
+ const publicKeys = account.publicKey as string[];
207
+ const matchedPublicKeys = publicKeys.filter(
208
+ (_: string, i: number) => index.includes(i)
209
+ );
210
+
211
+ verified = true;
212
+ for (let i = 0; i < (signature as string[]).length; i++) {
213
+ const isSigVerified = nacl.sign.detached.verify(
214
+ Buffer.from(fullMessage),
215
+ Buffer.from((signature as string[])[i], "hex"),
216
+ Buffer.from(matchedPublicKeys[i], "hex")
217
+ ); // `isSigVerified` should be `true` for every signature
218
+
219
+ if (!isSigVerified) {
220
+ verified = false;
221
+ break;
222
+ }
223
+ }
224
+ }
225
+ } else {
226
+ throw new WalletSignMessageAndVerifyError("Failed to get a bitmap")
227
+ .message;
228
+ }
229
+ } else {
230
+ // single sig wallets
231
+ // support for when address doesnt have hex prefix (0x)
232
+ const currentAccountPublicKey = new HexString(
233
+ account.publicKey as string
234
+ );
235
+ // support for when address doesnt have hex prefix (0x)
236
+ const signature = new HexString(
237
+ (response as SignMessageResponse).signature as string
238
+ );
239
+ verified = nacl.sign.detached.verify(
240
+ Buffer.from((response as SignMessageResponse).fullMessage),
241
+ Buffer.from(signature.noPrefix(), "hex"),
242
+ Buffer.from(currentAccountPublicKey.noPrefix(), "hex")
243
+ );
244
+ }
245
+ return verified;
246
+ } catch (error: any) {
247
+ const errMsg = generalizedErrorMessage(error);
248
+ throw new WalletSignMessageAndVerifyError(errMsg).message;
249
+ }
250
+ }
251
+ }
@@ -4,11 +4,14 @@ import {
4
4
  InputGenerateTransactionPayloadData,
5
5
  TypeTag,
6
6
  } from "@aptos-labs/ts-sdk";
7
+ import { NetworkInfo as StandardNetworkInfo } from "@aptos-labs/wallet-standard";
7
8
  import { BCS, TxnBuilderTypes, Types } from "aptos";
8
9
  import { NetworkInfo } from "./types";
9
10
 
10
11
  // old => new
11
- export function convertNetwork(networkInfo: NetworkInfo | null): Network {
12
+ export function convertNetwork(
13
+ networkInfo: NetworkInfo | StandardNetworkInfo | null
14
+ ): Network {
12
15
  switch (networkInfo?.name.toLowerCase()) {
13
16
  case "mainnet" as Network:
14
17
  return Network.MAINNET;
@@ -1,14 +1,22 @@
1
1
  import { Types } from "aptos";
2
2
  import {
3
3
  Network,
4
- InputGenerateTransactionData,
5
4
  InputGenerateTransactionOptions,
6
5
  InputSubmitTransactionData,
7
6
  PendingTransactionResponse,
8
7
  AccountAddressInput,
9
8
  InputGenerateTransactionPayloadData,
9
+ AnyRawTransaction,
10
+ Signature,
10
11
  } from "@aptos-labs/ts-sdk";
11
- import { WalletReadyState } from "./constants";
12
+ import { WalletReadyState } from "../constants";
13
+ import {
14
+ AptosSignAndSubmitTransactionOutput,
15
+ AptosSignMessageOutput,
16
+ UserResponse,
17
+ AccountInfo as StandardAccountInfo,
18
+ NetworkInfo as StandardNetworkInfo,
19
+ } from "@aptos-labs/wallet-standard";
12
20
 
13
21
  export { TxnBuilderTypes, Types } from "aptos";
14
22
  export type {
@@ -54,6 +62,7 @@ export declare interface WalletCoreEvents {
54
62
  connect(account: AccountInfo | null): void;
55
63
  disconnect(): void;
56
64
  readyStateChange(wallet: Wallet): void;
65
+ standardWalletsAdded(wallets: Wallet): void;
57
66
  networkChange(network: NetworkInfo | null): void;
58
67
  accountChange(account: AccountInfo | null): void;
59
68
  }
@@ -74,16 +83,16 @@ export interface SignMessageResponse {
74
83
  message: string; // The message passed in by the user
75
84
  nonce: string;
76
85
  prefix: "APTOS"; // Should always be APTOS
77
- signature: string | string[]; // The signed full message
86
+ signature: string | string[] | Signature; // The signed full message
78
87
  bitmap?: Uint8Array; // a 4-byte (32 bits) bit-vector of length N
79
88
  }
80
89
 
81
90
  export type OnNetworkChange = (
82
- callBack: (networkInfo: NetworkInfo) => Promise<void>
91
+ callBack: (networkInfo: NetworkInfo | StandardNetworkInfo) => Promise<void>
83
92
  ) => Promise<void>;
84
93
 
85
94
  export type OnAccountChange = (
86
- callBack: (accountInfo: AccountInfo) => Promise<any>
95
+ callBack: (accountInfo: AccountInfo | StandardAccountInfo) => Promise<any>
87
96
  ) => Promise<void>;
88
97
 
89
98
  export interface AdapterPluginEvents {
@@ -96,25 +105,37 @@ export interface AdapterPluginProps<Name extends string = string> {
96
105
  name: WalletName<Name>;
97
106
  url: string;
98
107
  icon: `data:image/${"svg+xml" | "webp" | "png" | "gif"};base64,${string}`;
99
- version?: "v1" | "v2";
100
108
  providerName?: string;
101
109
  provider: any;
110
+ // Compatible with legacy wallet plugin
102
111
  deeplinkProvider?: (data: { url: string }) => string;
112
+ // Comaptible with AIP-62 standard wallet
113
+ openInMobileApp?: () => void;
103
114
  connect(): Promise<any>;
104
115
  disconnect: () => Promise<any>;
105
116
  network: () => Promise<any>;
106
- signAndSubmitTransaction(
107
- transaction: Types.TransactionPayload | InputGenerateTransactionData,
117
+ signAndSubmitTransaction?(
118
+ transaction:
119
+ | Types.TransactionPayload
120
+ | InputTransactionData
121
+ | AnyRawTransaction,
108
122
  options?: InputGenerateTransactionOptions
109
123
  ): Promise<
110
- { hash: Types.HexEncodedBytes; output?: any } | PendingTransactionResponse
124
+ | { hash: Types.HexEncodedBytes; output?: any }
125
+ | PendingTransactionResponse
126
+ | UserResponse<AptosSignAndSubmitTransactionOutput>
111
127
  >;
112
128
  submitTransaction?(
113
129
  transaction: InputSubmitTransactionData
114
130
  ): Promise<PendingTransactionResponse>;
115
131
  signMessage<T extends SignMessagePayload>(
116
132
  message: T
117
- ): Promise<SignMessageResponse>;
133
+ ): Promise<SignMessageResponse | UserResponse<AptosSignMessageOutput>>;
134
+ signTransaction?( // `any` type for backwards compatibility, especially for identity connect
135
+ transactionOrPayload: any,
136
+ optionsOrAsFeePayer?: any
137
+ ): Promise<any>;
138
+ account?: () => Promise<AccountInfo | StandardAccountInfo>;
118
139
  }
119
140
 
120
141
  export type AdapterPlugin<Name extends string = string> =
@@ -122,6 +143,7 @@ export type AdapterPlugin<Name extends string = string> =
122
143
 
123
144
  export type Wallet<Name extends string = string> = AdapterPlugin<Name> & {
124
145
  readyState?: WalletReadyState;
146
+ isAIP62Standard?: boolean;
125
147
  };
126
148
 
127
149
  export interface TransactionOptions {