@wormhole-labs/wallet-aggregator-core 0.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.
package/src/wallet.ts ADDED
@@ -0,0 +1,241 @@
1
+ import EventEmitter from "eventemitter3";
2
+ import { ChainId } from "./constants";
3
+
4
+ export class NotSupported extends Error {
5
+ constructor() {
6
+ super("Not supported");
7
+ }
8
+ }
9
+
10
+ export class NotConnected extends Error {
11
+ constructor() {
12
+ super("Not connected");
13
+ }
14
+ }
15
+
16
+ export enum BaseFeatures {
17
+ SignTransaction = "SignTransaction",
18
+ SendTransaction = "SendTransaction",
19
+ SignAndSendTransaction = "SignAndSendTransaction",
20
+ SignMessage = "SignMessage",
21
+ }
22
+
23
+ /**
24
+ * Events the wallet can be listened on
25
+ */
26
+ export interface WalletEvents {
27
+ connect(): void;
28
+ disconnect(): void;
29
+ networkChanged(): void;
30
+ }
31
+
32
+ export enum WalletState {
33
+ Installed = "Installed",
34
+ NotDetected = "NotDetected",
35
+ Loadable = "Loadable",
36
+ Unsupported = "Unsupported",
37
+ }
38
+
39
+ export interface SendTransactionResult<R> {
40
+ id: string;
41
+ data?: R;
42
+ }
43
+
44
+ export type Address = string;
45
+ export type IconSource = string;
46
+ export type Signature = Uint8Array;
47
+
48
+ export type BaseUnsignedTransaction = any; // eslint-disable-line @typescript-eslint/no-explicit-any
49
+ export type BaseSignedTransaction = any; // eslint-disable-line @typescript-eslint/no-explicit-any
50
+ export type BaseSubmitTransactionInput = any; // eslint-disable-line @typescript-eslint/no-explicit-any
51
+ export type BaseSubmitTransactionResult = any; // eslint-disable-line @typescript-eslint/no-explicit-any
52
+ export type BaseMessage = any; // eslint-disable-line @typescript-eslint/no-explicit-any
53
+ export type BaseSignedMessage = any; // eslint-disable-line @typescript-eslint/no-explicit-any
54
+ export type NetworkInfo = any; // eslint-disable-line @typescript-eslint/no-explicit-any
55
+
56
+ /**
57
+ * Base Wallet abstraction.
58
+ *
59
+ * Generic arguments (all of them `any` by default):
60
+ * * `ChainId` - The Wormhole chain id for the network
61
+ * * `ConnectOptions` - Options to pass to the `connect` method
62
+ * * `SignTransactionInput` - Transaction object to sign
63
+ * * `SignTransactionResult` - Result of the `signTransaction` method
64
+ * * `SendTransactionInput` - Transaction object to send. Might be signed or not, depending on the wallet implementation
65
+ * * `SendTransactionResultData` - Result of the `sendTransaction` method
66
+ * * `SignAndSendTransactionInput` - Transaction object to sign and send
67
+ * * `SignAndSendTransactionResultData` - Result of the `signAndSendTransaction` method
68
+ * * `SignMessageInput` - Message to sign
69
+ * * `SignMessageResult` - Result of the `signMessage` method
70
+ * * `NetworkInfo` - Object type that describes the blockchain's network information or state
71
+ * * `WalletFeatures` - Object type which describes the features the wallet implements
72
+ * * `WalletEvents` - Object type which describes the events the wallet can be listened on
73
+ */
74
+ export abstract class Wallet<
75
+ CID extends ChainId = ChainId,
76
+ ConnectOptions = any,
77
+ SignTransactionInput = any,
78
+ SignTransactionResult = any,
79
+ SendTransactionInput = any,
80
+ SendTransactionResultData = any,
81
+ SignAndSendTransactionInput = SignTransactionInput,
82
+ SignAndSendTransactionResultData = SendTransactionResultData,
83
+ SignMessageInput = any,
84
+ SignMessageResult = any,
85
+ NetworkInfo = any,
86
+ WalletFeatures = any,
87
+ E extends WalletEvents = any
88
+ > extends EventEmitter<E> {
89
+ /** Retrieve the wallet's name */
90
+ abstract getName(): string;
91
+
92
+ /** Retrieve the wallet's project url */
93
+ abstract getUrl(): string;
94
+
95
+ /**
96
+ * @async
97
+ * @description Connect to the wallet. Implementors are expected to emmit a `connect` event upon success
98
+ * @returns A list of connected addresses
99
+ */
100
+ abstract connect(opts?: ConnectOptions): Promise<Address[]>;
101
+
102
+ /**
103
+ * @async
104
+ * @description Disconnect from the wallet. Implementors are expected to emmit a `disconnect` event upon success
105
+ */
106
+ abstract disconnect(): Promise<void>;
107
+
108
+ /**
109
+ * @description Retrieve the wallet's blockchain's wormhole chain id
110
+ * @see The {@link https://github.com/wormholelabs-xyz/wallet-aggregator-sdk/blob/e00efc8aba5fcea1f65b54bf8953a405bdeaf52b/packages/wallets/core/src/constants.ts constants} file for a detailed map of the available chains
111
+ */
112
+ abstract getChainId(): CID;
113
+
114
+ /**
115
+ * @description Returns the connected wallet's address
116
+ * @returns A string address if the wallet is connected, undefined if not
117
+ */
118
+ abstract getAddress(): Address | undefined;
119
+
120
+ /**
121
+ * @description Returns a collection of connected addresses
122
+ * @returns A non-empty array of addresses if connected, an empty array if not. The returned value from `getAddress` should be present in this array.
123
+ */
124
+ abstract getAddresses(): Address[];
125
+
126
+ /**
127
+ * @description Set the main address to operate with (sign transactions, etc.)
128
+ * @param address The new address to operate with
129
+ * @throws Throws if the address can not be set as the main address
130
+ * @throws {NotSupported} May throw NotSupported error if the wallet does not implement it
131
+ */
132
+ abstract setMainAddress(address: Address): void;
133
+
134
+ /**
135
+ * @async
136
+ * @description Retrieve the connected account's balance
137
+ * @param [assetAddress] The asset address to retrieve the balance from. If not provided, the balance of the native asset will be returned
138
+ * @throws {NotSupported} May throw NotSupported error if the wallet does not implement it
139
+ */
140
+ abstract getBalance(assetAddress?: string): Promise<string>;
141
+
142
+ /**
143
+ * @async
144
+ * @description Sign an unsigned transaction
145
+ *
146
+ * Caveat: some wallets/libraries do not implement separate workflows for signing and sending the tx (e.g. ethers.js); instead, they implement a Sign & Send flow.
147
+ *
148
+ * In order not to break the abstract workflow, implementors of this wallets should return the same unsigned transaction object, so that from a Dapp developer perspective a signing operation for any wallet can be implemented as following
149
+ *
150
+ * ```ts
151
+ * const unsigned = buildTx();
152
+ * const signed = await wallet.signTransaction(unsigned);
153
+ * const result = await wallet.sendTransaction(signed);
154
+ * ```
155
+ *
156
+ * @param {BUT} tx The transaction object or parameters to sign
157
+ * @returns {BST} A signed transaction object, ready to send to the network
158
+ */
159
+ abstract signTransaction(
160
+ tx: SignTransactionInput
161
+ ): Promise<SignTransactionResult>;
162
+
163
+ /**
164
+ * @async
165
+ * @description Send a signed transaction to the network
166
+ *
167
+ * @param {BST} tx The signed transaction to send to the network
168
+ * @returns {SendTransactionResult<R>} A SendTransactionResult object, comprised of a string `id` field, which indicates the resulting transaction/receipt id/hash, and a `data` field, which holds details on the operation result (e.g. a transaction receipt)
169
+ */
170
+ abstract sendTransaction(
171
+ tx: SendTransactionInput
172
+ ): Promise<SendTransactionResult<SendTransactionResultData>>;
173
+
174
+ /**
175
+ * @async
176
+ * @description Sign a message
177
+ * @param {BM} msg The message to sign
178
+ * @returns {BSM} A signature of the message, signed by the connected account
179
+ * @throws {NotSupported} May throw NotSupported error if the wallet does not implement it
180
+ */
181
+ abstract signMessage(msg: SignMessageInput): Promise<SignMessageResult>;
182
+
183
+ /** Retrieve the wallet's icon encoded as a base64 string */
184
+ abstract getIcon(): IconSource;
185
+
186
+ /** Retrieve whether the wallet is connected or not */
187
+ abstract isConnected(): boolean;
188
+
189
+ /**
190
+ * Retrieve the wallet's blockchain's network info.
191
+ * @returns An object holding the network information (e.g. chainId for EVM chains), if possible. If the value is undefined it does not strictly mean the wallet is not connected.
192
+ */
193
+ abstract getNetworkInfo(): NetworkInfo | undefined;
194
+
195
+ /**
196
+ * Wraps the `signTransaction` and `sendTransaction` methods into one operation
197
+ * @param {BUT} tx The transaction object or parameters to sign and send
198
+ * @returns {SendTransactionResult<R>} A SendTransactionResult object
199
+ * @see See {@link signTransaction} and {@link sendTransaction} for a detailed description on each step
200
+ */
201
+ abstract signAndSendTransaction(
202
+ tx: SignAndSendTransactionInput
203
+ ): Promise<SendTransactionResult<SignAndSendTransactionResultData>>;
204
+
205
+ /**
206
+ * Retrieve the wallet's current state
207
+ *
208
+ * The possible states are as those used by the {@link https://github.com/solana-labs/wallet-adapter solana} and {@link https://github.com/aptos-labs/aptos-wallet-adapter aptos} libraries, summarized as follows:
209
+ * * `Installed`: the wallet was detected through the global scope or any other mechanism and can be interacted with. Example: `window.ethereum` for Metamask or `window.phantom` for Phantom wallet)
210
+ * * `NotDetected`: as opposed to `Installed`, no point of interaction with the wallet was found, and thus it is not available. Users can be redirected to the project url offered by `getUrl`
211
+ * * `Loadable`: the wallet might not require installation, and thus can be interacted with after being loaded
212
+ * * `Unsupported`: the wallet is not supported by the environment
213
+ *
214
+ * @returns The wallet's state. Defaults to Installed.
215
+ */
216
+ getWalletState(): WalletState {
217
+ // default
218
+ return WalletState.Installed;
219
+ }
220
+
221
+ abstract getFeatures(): WalletFeatures[];
222
+
223
+ /**
224
+ * Query whether a feature or set of features is supported by the wallet.
225
+ * For a list of features see {@link BaseFeatures}.
226
+ * Some chains might add additional features of their own.
227
+ */
228
+ public supportsFeature(feature: WalletFeatures | WalletFeatures[]): boolean {
229
+ const features = this.getFeatures();
230
+
231
+ return Array.isArray(feature)
232
+ ? feature.every((f) => features.includes(f))
233
+ : features.includes(feature);
234
+ }
235
+
236
+ /**
237
+ * Checks whether the wallet supports a given chain id
238
+ * @param chainId The chain id to check support for
239
+ */
240
+ abstract supportsChain(chainId: ChainId): boolean;
241
+ }