@provablehq/aleo-wallet-adaptor-soter 0.1.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,278 @@
1
+ // src/SoterWalletAdapter.ts
2
+ import {
3
+ Network
4
+ } from "@provablehq/aleo-types";
5
+ import {
6
+ WalletDecryptPermission,
7
+ WalletReadyState
8
+ } from "@provablehq/aleo-wallet-standard";
9
+ import {
10
+ BaseAleoWalletAdapter,
11
+ MethodNotImplementedError,
12
+ WalletConnectionError,
13
+ WalletDecryptionError,
14
+ WalletDecryptionNotAllowedError,
15
+ WalletDisconnectionError,
16
+ WalletError,
17
+ WalletNotConnectedError,
18
+ WalletSignMessageError,
19
+ WalletTransactionError
20
+ } from "@provablehq/aleo-wallet-adaptor-core";
21
+ import {
22
+ LEO_NETWORK_MAP
23
+ } from "@provablehq/aleo-wallet-adaptor-leo";
24
+ var SoterWalletAdapter = class extends BaseAleoWalletAdapter {
25
+ /**
26
+ * Create a new Soter wallet adapter
27
+ * @param config Adapter configuration
28
+ */
29
+ constructor(config) {
30
+ super();
31
+ /**
32
+ * The wallet name
33
+ */
34
+ this.name = "Soter Wallet";
35
+ /**
36
+ * The wallet URL
37
+ */
38
+ this.url = "https://chromewebstore.google.com/detail/soter-aleo-wallet/gkodhkbmiflnmkipcmlhhgadebbeijhh";
39
+ /**
40
+ * The wallet icon (base64-encoded SVG)
41
+ */
42
+ this.icon = "data:image/png;base64,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";
43
+ /**
44
+ * Current network
45
+ */
46
+ this.network = Network.MAINNET;
47
+ /**
48
+ * The wallet's decrypt permission
49
+ */
50
+ this.decryptPermission = WalletDecryptPermission.NoDecrypt;
51
+ /**
52
+ * Public key
53
+ */
54
+ this._publicKey = "";
55
+ this._readyState = typeof window === "undefined" || typeof document === "undefined" ? WalletReadyState.UNSUPPORTED : WalletReadyState.NOT_DETECTED;
56
+ console.debug("SoterWalletAdapter constructor", config);
57
+ this.network = Network.MAINNET;
58
+ this._checkAvailability();
59
+ this._soterWallet = this._window?.soter || this._window?.soterWallet;
60
+ }
61
+ /**
62
+ * Check if Soter wallet is available
63
+ */
64
+ _checkAvailability() {
65
+ if (typeof window === "undefined" || typeof document === "undefined") {
66
+ this.readyState = WalletReadyState.UNSUPPORTED;
67
+ return;
68
+ }
69
+ this._window = window;
70
+ if (this._window.soter || this._window.soterWallet) {
71
+ this.readyState = WalletReadyState.INSTALLED;
72
+ this._soterWallet = this._window?.soter || this._window?.soterWallet;
73
+ } else {
74
+ const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
75
+ if (isMobile) {
76
+ this.readyState = WalletReadyState.LOADABLE;
77
+ }
78
+ }
79
+ }
80
+ /**
81
+ * Connect to Soter wallet
82
+ * @returns The connected account
83
+ */
84
+ async connect(network, decryptPermission, programs) {
85
+ try {
86
+ if (this.readyState !== WalletReadyState.INSTALLED) {
87
+ throw new WalletConnectionError("Soter Wallet is not available");
88
+ }
89
+ if (network !== Network.MAINNET) {
90
+ throw new WalletConnectionError("Soter Wallet only support mainnet");
91
+ }
92
+ try {
93
+ await this._soterWallet?.connect(decryptPermission, LEO_NETWORK_MAP[network], programs);
94
+ if (!this._soterWallet?.publicKey) {
95
+ throw new WalletConnectionError(
96
+ "Soter Wallet did not return address, maybe canceled by user"
97
+ );
98
+ }
99
+ } catch (error) {
100
+ throw new WalletConnectionError(
101
+ error instanceof Error ? error.message : "Connection failed"
102
+ );
103
+ }
104
+ this._publicKey = this._soterWallet?.publicKey || "";
105
+ if (!this._publicKey) {
106
+ throw new WalletConnectionError("No address returned from wallet");
107
+ }
108
+ const account = {
109
+ address: this._publicKey
110
+ };
111
+ this.account = account;
112
+ this.decryptPermission = decryptPermission;
113
+ this.emit("connect", account);
114
+ return account;
115
+ } catch (err) {
116
+ this.emit("error", err instanceof Error ? err : new Error(String(err)));
117
+ throw new WalletConnectionError(err instanceof Error ? err.message : "Connection failed");
118
+ }
119
+ }
120
+ /**
121
+ * Disconnect from Soter wallet
122
+ */
123
+ async disconnect() {
124
+ try {
125
+ await this._soterWallet?.disconnect();
126
+ this._publicKey = "";
127
+ this.account = void 0;
128
+ this.emit("disconnect");
129
+ } catch (err) {
130
+ this.emit("error", err instanceof Error ? err : new Error(String(err)));
131
+ throw new WalletDisconnectionError(
132
+ err instanceof Error ? err.message : "Disconnection failed"
133
+ );
134
+ }
135
+ }
136
+ /**
137
+ * Sign a transaction with Soter wallet
138
+ * @param options Transaction options
139
+ * @returns The signed transaction
140
+ */
141
+ async signMessage(message) {
142
+ if (!this._publicKey || !this.account) {
143
+ throw new WalletNotConnectedError();
144
+ }
145
+ try {
146
+ const signature = await this._soterWallet?.signMessage(message);
147
+ if (signature.signature.errorCode != 0) {
148
+ throw new Error("Permission Not Granted");
149
+ }
150
+ return new TextEncoder().encode(signature.signature.result);
151
+ } catch (error) {
152
+ throw new WalletSignMessageError(
153
+ error instanceof Error ? error.message : "Failed to sign message"
154
+ );
155
+ }
156
+ }
157
+ async decrypt(cipherText, tpk, programId, functionName, index) {
158
+ if (!this._soterWallet || !this._publicKey) {
159
+ throw new WalletNotConnectedError();
160
+ }
161
+ switch (this.decryptPermission) {
162
+ case WalletDecryptPermission.NoDecrypt:
163
+ throw new WalletDecryptionNotAllowedError();
164
+ case WalletDecryptPermission.UponRequest:
165
+ case WalletDecryptPermission.AutoDecrypt:
166
+ case WalletDecryptPermission.OnChainHistory: {
167
+ try {
168
+ const result = await this._soterWallet.decrypt(
169
+ cipherText,
170
+ tpk,
171
+ programId,
172
+ functionName,
173
+ index
174
+ );
175
+ return result.text;
176
+ } catch (error) {
177
+ throw new WalletDecryptionError(
178
+ error instanceof Error ? error.message : "Failed to decrypt"
179
+ );
180
+ }
181
+ }
182
+ default:
183
+ throw new WalletDecryptionError();
184
+ }
185
+ }
186
+ /**
187
+ * Execute a transaction with Soter wallet
188
+ * @param options Transaction options
189
+ * @returns The executed temporary transaction ID
190
+ */
191
+ async executeTransaction(options) {
192
+ if (!this._publicKey || !this.account) {
193
+ throw new WalletNotConnectedError();
194
+ }
195
+ try {
196
+ const requestData = {
197
+ address: this._publicKey,
198
+ chainId: LEO_NETWORK_MAP[this.network],
199
+ fee: options.fee ? options.fee : 1e-3,
200
+ feePrivate: false,
201
+ transitions: [
202
+ {
203
+ program: options.program,
204
+ functionName: options.function,
205
+ inputs: options.inputs
206
+ }
207
+ ]
208
+ };
209
+ const result = await this._soterWallet?.requestTransaction(requestData);
210
+ if (!result?.transactionId) {
211
+ throw new WalletTransactionError("Could not create transaction");
212
+ }
213
+ return {
214
+ transactionId: result.transactionId
215
+ };
216
+ } catch (error) {
217
+ console.error("Soter Wallet executeTransaction error", error);
218
+ if (error instanceof WalletError) {
219
+ throw error;
220
+ }
221
+ throw new WalletTransactionError(
222
+ error instanceof Error ? error.message : "Failed to execute transaction"
223
+ );
224
+ }
225
+ }
226
+ /**
227
+ * Get transaction status
228
+ * @param transactionId The transaction ID
229
+ * @returns The transaction status
230
+ */
231
+ async transactionStatus(transactionId) {
232
+ if (!this._publicKey || !this.account) {
233
+ throw new WalletNotConnectedError();
234
+ }
235
+ try {
236
+ const result = await this._soterWallet?.transactionStatus(transactionId);
237
+ if (!result?.status) {
238
+ throw new WalletTransactionError("Could not get transaction status");
239
+ }
240
+ return {
241
+ status: result.status
242
+ };
243
+ } catch (error) {
244
+ throw new WalletTransactionError(
245
+ error instanceof Error ? error.message : "Failed to get transaction status"
246
+ );
247
+ }
248
+ }
249
+ /**
250
+ * Request records from Soter wallet
251
+ * @param program The program to request records from
252
+ * @param includePlaintext Whether to include plaintext on each record
253
+ * @returns The records
254
+ */
255
+ async requestRecords(program, includePlaintext) {
256
+ if (!this._publicKey || !this.account) {
257
+ throw new WalletNotConnectedError();
258
+ }
259
+ try {
260
+ const result = includePlaintext ? await this._soterWallet?.requestRecordPlaintexts(program) : await this._soterWallet?.requestRecords(program);
261
+ return result?.records || [];
262
+ } catch (error) {
263
+ throw new WalletError(error instanceof Error ? error.message : "Failed to request records");
264
+ }
265
+ }
266
+ /**
267
+ * Switch the network
268
+ * @param network The network to switch to
269
+ */
270
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
271
+ async switchNetwork(_network) {
272
+ console.error("Soter Wallet does not support switching networks");
273
+ throw new MethodNotImplementedError("switchNetwork");
274
+ }
275
+ };
276
+ export {
277
+ SoterWalletAdapter
278
+ };
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@provablehq/aleo-wallet-adaptor-soter",
3
+ "version": "0.1.1-alpha.0",
4
+ "description": "Soter wallet adapter for Aleo",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "license": "GPL-3.0-or-later",
9
+ "files": [
10
+ "dist",
11
+ "src"
12
+ ],
13
+ "dependencies": {
14
+ "@provablehq/aleo-types": "0.1.1-alpha.0",
15
+ "@provablehq/aleo-wallet-adaptor-leo": "0.1.1-alpha.0",
16
+ "@provablehq/aleo-wallet-standard": "0.1.1-alpha.0",
17
+ "@provablehq/aleo-wallet-adaptor-core": "0.1.1-alpha.0"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/ProvableHQ/aleo-dev-toolkit.git",
22
+ "directory": "packages/aleo-wallet-adaptor/wallets/soter"
23
+ },
24
+ "homepage": "https://provable.com/",
25
+ "keywords": [
26
+ "aleo",
27
+ "wallet",
28
+ "adapter",
29
+ "soter"
30
+ ],
31
+ "author": "Provable Labs",
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "devDependencies": {
36
+ "rimraf": "^5.0.5",
37
+ "tsup": "^7.0.0",
38
+ "typescript": "^5.0.0"
39
+ },
40
+ "scripts": {
41
+ "build": "tsup",
42
+ "clean": "rimraf dist",
43
+ "dev": "tsup --watch"
44
+ }
45
+ }
@@ -0,0 +1,356 @@
1
+ import {
2
+ Account,
3
+ Network,
4
+ TransactionOptions,
5
+ TransactionStatusResponse,
6
+ } from '@provablehq/aleo-types';
7
+ import {
8
+ WalletDecryptPermission,
9
+ WalletName,
10
+ WalletReadyState,
11
+ } from '@provablehq/aleo-wallet-standard';
12
+ import {
13
+ BaseAleoWalletAdapter,
14
+ MethodNotImplementedError,
15
+ WalletConnectionError,
16
+ WalletDecryptionError,
17
+ WalletDecryptionNotAllowedError,
18
+ WalletDisconnectionError,
19
+ WalletError,
20
+ WalletNotConnectedError,
21
+ WalletSignMessageError,
22
+ WalletTransactionError,
23
+ } from '@provablehq/aleo-wallet-adaptor-core';
24
+ import {
25
+ AleoTransaction,
26
+ LEO_NETWORK_MAP,
27
+ LeoWallet,
28
+ LeoWalletAdapterConfig,
29
+ } from '@provablehq/aleo-wallet-adaptor-leo';
30
+
31
+ export interface SoterWindow extends Window {
32
+ soterWallet?: LeoWallet;
33
+ soter?: LeoWallet;
34
+ }
35
+
36
+ /**
37
+ * Soter wallet adapter
38
+ */
39
+ export class SoterWalletAdapter extends BaseAleoWalletAdapter {
40
+ /**
41
+ * The wallet name
42
+ */
43
+ readonly name = 'Soter Wallet' as WalletName<'Soter Wallet'>;
44
+
45
+ /**
46
+ * The wallet URL
47
+ */
48
+ url =
49
+ 'https://chromewebstore.google.com/detail/soter-aleo-wallet/gkodhkbmiflnmkipcmlhhgadebbeijhh';
50
+
51
+ /**
52
+ * The wallet icon (base64-encoded SVG)
53
+ */
54
+ readonly icon =
55
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAA21BMVEVHcEwnytsh6M8px+Ml0tgj4tMnzd0zlvsmzdol0Ncqw+UqxuQi588m1dook94su+ki5tAqweUe9sYtt+wf8skh680e9sYh6s0k39QbaL0xnvUyl/gebsQxlPQvr/Ei588l2tcqw+T///8rvugtte0g7cwvqvQyofkozd4n0dwj4tIj3tQidc8m1Nopx+Ivr/EsueopyuAxpvYXY7Qd+8Mf8cknf9we9cYtiewqhOUwjvMdbMHl+Pw/1+CU5fD2/f521PCu5PjD7/jT9flf4uNZxPFEufEoneAdoMEPXCHCAAAAH3RSTlMAJpCvEUUz/Qgbz17r3k+OtHbY5MJj8Hnh05rRj7PywcYstQAAEa5JREFUeNrsmF9X4loSxUMgLMKfbnCB6J2eJQgqgYAgAs1AEBEv/f0/0eyqfU4I3lbBOw/zcCuIefLsVP2qakfH+Sf+iX/i/zn81EH4v4uM4+QSdxmJnONkcrn/wfn54l/jTK5ElDOOZ+5yTp13ruNXq2W3lv2bIr79ukLc8NKYIG7k0rvJZDabnWcd73w2e3x8PE85tUeNs0yuKr/Pq97fEvBDBVwZFRIHOiYz/XiOfzYTBeeekz1XARDlUoqb8/yvC7gc9666PJ4fc3wsQnNQd3LVmcRjHVIeJRePns1FNeOefTkL/uW4AQHdRBL4uWEZjISy47gqYFZ2NPOQ4Ma5SNUez90vovBtPO7o0d2rfdwkQwWcZZwaM1DNIPOagbLkQsMTJW7mawiMx7+YgS7LYIBkKWIUUfDs+czyCB2zPYWPj/WMKPmagksI6CL0fMuCJiGZh8lNDY8rMExmQqHmYk9hOVcmjKefn4KAca9rJXRjEq7idmAWXCdXJo+uk6lqCma1fUdSyekk5oDAeNzo2jhkYT8abm6qOcdlR2AUlYnDnsKsRyGpryAwHvft8QdpMKcbFs58x1MaZrirsyGquYztyBSVuCdnQCoACHq9XlLCHgXbEVcygIo6m4TCiQqAlDJ5dDNVO5xObEIKwPFGgZHQPayCqKih9NoRuEsVJ9IREFXX8fhYJYWnp0AREAGiIJGFq0RXmizgT5cJpVDIFVGTjhQJZ5m6wdH/AgKgUE+X67AQXR3O+iMU1ilgzyMoLKoCUDhjDU5rhMwlBfR7PdVwmIWDfrgqCoW6IvCUNQ5oUGg2RM0v6ng+sQasAIZxo0EB3Z5NwxsWIMFD6TUFeErvXAVAlKvjceZiV6mCau4rAn41NGwO4sHUTbBgKCSPfpEDGhROTEe6hgb/CwgYAfsyUMF2tVptrzgZIAHJdTkYMBWr3FJ1zYV2ZI0NeVIj+pd7AT2ThEa03UYiIdo8XV9fP63iImAN1jichELbECkdDsiFd25o+EIFQKGeLTmIXp6etpKE1TVjZXuimHI89iTuaqYhsBC1HyY1dUxCwxcqIBT2TQai5bUI6EYvRsBLZFMAW3ZBHmQhqgBIsR1pHNPsBApzl7EAgaCfFCC/r19WK5Rha4GELSuzIcSWcUTDltE2gUKdjrMTKPSTAg4z0Oht5WgtxMpOJ7FlzAUpFByEQsWx6NeMgfZOQGCBiwL6/QYvSf26oQIkE1vkwc6FklBoeXRpGMomF5Mb2DL6hdppCFBD2JfQFGzwzPiNk5eRVmIZmRQUYcuKlscCV4RQSB5hy+x8Ph4BPj++Fx1JgWSggaRvGvrLCFAmNQqOX+Jokt2sOEAUO/LGpWMSGk5xY5qAxTgc9FUBvrbS/NFWGIykK8mkalAKdS7VMRU5oQv7jnSNgfaPR8AcjxK0+iwCIMDR10sZQhuZCy/KIjclzJjLoQAey+xIWYiKYzHlcToeS2Hux4Kni4ppOwj6RoOdQIpCA+M4svO55DsF4gAe6+SxnPOrNG5elrtqUjt2FS/iFCzm90FgJUQbnr+JdDx29ztCKVQFuPO4KiGqTMdSz1QNDccJyC4WVCASft52AiuhEa1elsvNKmokQxVgIZaYggKWgCgQCusc0Hg5iA3LUQgsFlbCePGfh0HA6IuIKIr6OhvZmXK8KsCzpdkRrlIoPNS4IWQ40DHJqjgSgYXVEN7dNYOkgngsHIb8d4IdoTyaqRh3pGecvHfcHF7EMQ4f7oadTifWILFdr543m81qG+2zcAFbxpZA6evcEeWc6cirmjqmK5nPR1fABAS0OwEUdDQFQT9ab5a2GV62cQaKsGUXmgLceeQRouyGyFVjA32MgHAvYPpwdzvqdIyCILCNwFhu7apqCIU9w2PqggMatowNUc65xLF6xGtyRhAIrYjd7d3DoGMjCA7ONw2pIbZMcWzIyyoHNCikhb7wza46hkL/MgxFASVAwF3TnI5rzQd/ecYUWkkp1rYhwF6FPSkUckfAll1wRXlebF0+r0AYLnjJ1+724a41Go2Mhmep/DrSjghkP2/0dIi4gC0rKpQofc02RKasrxHdmjgmGpbPV7E9XxNxCwHt0chKeJFFJDAqknAGy6hvUiAUWh69otIAUS5f7V06JjXQn/5jJAz1cDk+VAH3I0ZnJM+8iruyrxvZrqoKSm959C84oGHLSINS2KVh+RwBk3/5nt5DwO3AKuhYAUaCWJS+sUxpoVAjDSlsiPq+I2vc1sXs5wgsmALVAQFog+ZgYDRsKMAkof9MAZqDPGyZ4TEjUkRAWnKhCjwZit1jKPwRmvrr711batAaDIwEMUX7ntSKBKYGJVAYqING6QvcUqWM5kIci3/RNYblMzcWahgRu7bUoD1gjAZow6etaYlOJP5gFa9KsWVsCbFlbAjYMv5/wbWzofypGwttSBnaKuB+YBXoO8EaKzHCQtAXlHW8pYRCdkQFU5E4FExHIhfsBzHQH/9vLAwTChb3KuC22WwaCfLQT0u4gif7dhTvqTQGEFclKExzT9WRC1VwkaJj6n5G4Y9wmpAwlQwIhU0rIVoejOLlOu7JAM9WYEeILbMNgbKoYwCFBsdP3FiYjOlQBdy1mk2rYZ1Q8LTZyqa0GmDLSEMpKxQiFUqh4tioc1eJgf7QjU3DaSIHuyEhaMvhuETB9lnTjzqsgOOIO0IFFFB69mTByZYUR3k5oG9L59I9a6A/R2AaUsWutRdgk9AcAMD1ehtxMkQRFxU+WINppgAU5iUD0hoF9SyAr24MdOYzBBIpsAJAYYun8wszoalzIXp+EQw4HEFhhT2JuzSNm2s6ErnwGtZAfziHpzYHctNuEYLbViIDBseRfIRJMxo7/TxeDggkbFmFxcBCLNG3FbCrVEHhozk8DadxDvDTMgIeWq1Ws5WUYNsSs3kTL2ssxJLl0Qv0jQ5S0hzQLpWogX6/AtMp608IpiJAh3G7JRKshjgLg5G+qdplDQrzgeExpTw2IKqiDYFcpGMD/S6D/46ff6o/KuDeCngjQTVwNhu/IC8H7Em8HORZA9gyvkiUMhUKKPkfIDDVsCp2TSvgXkpwIKGp0/hZxvHKbOuRUMixIFNReYQU5EJSEIBCpeEDCr+Zw20hIMC2AXIRS4he5cUgnsbXz3ZZ60LUYoDHCrcUKMzzVQa2zBqWDxAwGeBnN2haCoc8HD94PXw6tMYvEZf1QClkCmDLFIYORKW1FgEWosHxAwT2IQpaVoBAMGxRxOrw9Ceh0PoFLMR8x/Dom4bw2JFCoUv/+i6F/vQgwmlz0ExQOORnbZ4fs3jzvFrLv+vWdlt/d5zvimPwHVORA7qiHdmXjjSO6V0Kv03nuBKREHA/HA4pIVo+LeXk1yhSFmUU2akAW1ZgR+RBIbdUWoeD1MCDEsXxvYX4Q8+PJYS70WBP4XBoJby+RoaHpvSEvByYnmwKhU3LY8HMRyxE8ljxS3SwtfcQmM+n80QWdp1RM6awPYwlGBi0I5rNZ4HAjoVvjp/nVIAtY0NAissBDQrpH933VvE8VjB/K+DOCLCFiOdCa416RHZKg8I0m7ICKRzQBbsh8jlXMxC8Q+G3ucZewi4YJShsv5GwnwscTjoc5eWAHSG2jAO6YjoyKKUKnI4Xv6fwDx6/19BMCrhvv5GQiCjOgFDIhsDdd8URFEouZCZ4WRrozm8pzPxrblMwtwI6CQrb7aQEI8IMxU3sF2DL2BJCIWkAhWlOp0qmZHB8F4G9BHzBZCQpbA9xGQmtP/VkOxSXr9YuYADl2RFiy9gQWelI8UywZSzGbymszH/iSsQueCNAM4CfV90EB/Nwbf2CDCB2hNgy7oiC6UjkokIB+d9R+MfPnz8TGqbzHYpFAQaCe6Nhff2XeLabEmvwO3EAj/9t32p7E0Wj6DgKVJmBJWSbja5aR4u702yxJM06xii2Af//P9pzXx54ENuNTSfzpddW/ND0Hu49594DpV2m418haqGK9OWa8uuZGyX9kaavMBwhmBMWCoTCWkY0FFGMJzMXyJZVfIyEj10sRLEsPu0qpuMZEa7XXII1Y6ASzAGgwcJUEZRbuU1z2PKpr3gUmdEEFsaiSfdTMBNBwJbJgI56A6XjGQqs1wpBXz9mBIB6YAHAd7paPBHtQEkcD2AkuaLcSJJsmeFj5yuXAFAi41i6wobumTm8rkIRPBgAysK0YgGdcmmOqzm1ZGemIxZiV0QZMhQqAVh4r4oUx4QPZyhgByEgJ2lYyHdqUoaAF58yANCxWK1KbQV/kS0T12b4eH8fci1Ykc6DWRAtCmzwsuN4wwBqFiYpQ1AW7vSYYzBoJbgIaHggA5ps2UyhQJGsCLCQ6fjQYuGfm/XGxvBjfcQVZUMGAoAg8Ckv6uMO7gSV4A0xgy2LRRG4OJBLiEGHFYn4fDVQOrYosEFQ/grC8ftdUwaZ9IAC7HumWhy2T6jEqsiLQgYkMBALDR87ykdHFXnfvQplPp+ysONxfrsMcwFgsTBJtQjMvoJKUC50SZklwSwMBYBORRaEI35h0Bc6PpyyMNhUYcowm+KCzgKAHiQKIcnhygozl1YLe08taCEKAGGhCIJrAUU6zkzoeMLCYZXdFGL9NwFosjAxEMqiTM1YoGNZFHmpCGKyZQwArfdlQNNClPno9w0dmxQYbTy7BoTgZvr95oSFiYGQmF6k9VbMTRFgy2JRBGzZjOkIUKHwMbwSOj40Weh6no2A4ng3bbEw4dSavTy9PtJ+rMiWiXOk3SyCCMyGAAuVjg0APgBsahDUiON02mahiSw/tK+PzL7Grw5FEcRCoUPEiuTh4CsdGywcehuGYJVhcXsKAD3ItAfJyUbe71UWFMRCUQTZMnGuZMuEj44r03HmNtyYJ0FlEBTr+e20xcIsyQRDZm3k7eGQF3TvLFcAaLgbGz764uOJhTKgI14QRMcWBbyNZ8qAw0wB2CzMMqRnBJiBe13IOTPimUigu4pYaPjoCh9jl2tBihQ93EOa1ir2OLm+C4Z/bqctFnIJuArLPIcSkwQT6cAA8OFJVLlYUOtFEbBlsSwpX4cDFBnqgrAAjCX5poKAr7vHFgmWVIJM+sDFSDivAcAbmkAQC4WQZMvEP4eiSNSi4ysdeycAECPEeDwcDsMo/PIiAGUC3kr6E9I+J12SRynFMqUxbBnnT4mFYuG7qsj5LOjE4l8tFvaDIHBdeni9eibdvRYANw1j2oCQlU96vzjPD3sGIC2YkC0TPsKW6XyELVNFYlfpgngtnH8fz7CQQzEsi2frJsU30wuCgIUYy5LAQmRBKAtXvCG6ctMvfBXA7wzAsDCOB130xR8h/TITCAVZ0/2hRpEbACnZMpEE2TLhoy+KpOEQSS+6r/4t37l+vP7yx9ffup8jP0B3evzTQ60BXpJ/lxRbc+PeLOs0oTUom4ru2cqOCGk4MAvdQHoxePWJkivHcVxNW0e4XBoIueTPshIbAbOorJZ1SiwMpAL4FMlwIFsmA9pnxzSbzy59zJVsQ5Xfwyzc7zLlA6kyrZZ1ChZ2Yh4K+BTofOyTIinC2jFdHK6n+RHbb1X+rFrUCoFsmSiCWMgAJrBlAgALca6z4fIn/kfLKg47YaNOhWpVEoIh6CKMxFQcGEEEQse4Xzumi592HtcAymxpzwUpQyoYcPUbiSIGxEcuRii1AADX4elIs+HiGC7RBG9Zc7HCoMOJMWRYg8GEBWGm4gKgSJEEwe/HTMf4DSyMPCs9A8iaA1rKMAlwuiwItN6ZcAnIlgkfw6uB2daXy4AAeFYZMqsKZlXine7ZMh2TiHYzD4VAa4G2hKs4jrtvUAGuHzwFYJehmo5mTSXEQuEjsVAu6GDLJhOaqWHPpdn2pv88Ie9katCCUUNYki2TbtBCTDkvtBk4ndZwuzDGWv9GFZQKFoQJbNkE50un+6mD8+29w39+yTCmCnD+F6swiUfjYQen+9Yy/68MDIST9DA042GI1dXvvX9e27/WQvC8OnH0nnV+bRjr+auFGw+jn1Ppl4fx8Bcltv2jK4l/RfaP+IiP+AnxH6PbxkISaxsWAAAAAElFTkSuQmCC';
56
+ /**
57
+ * The window object
58
+ */
59
+ private _window: SoterWindow | undefined;
60
+
61
+ /**
62
+ * Current network
63
+ */
64
+ network: Network = Network.MAINNET;
65
+
66
+ /**
67
+ * The wallet's decrypt permission
68
+ */
69
+ decryptPermission: WalletDecryptPermission = WalletDecryptPermission.NoDecrypt;
70
+
71
+ /**
72
+ * Public key
73
+ */
74
+ private _publicKey: string = '';
75
+
76
+ _readyState: WalletReadyState =
77
+ typeof window === 'undefined' || typeof document === 'undefined'
78
+ ? WalletReadyState.UNSUPPORTED
79
+ : WalletReadyState.NOT_DETECTED;
80
+
81
+ /**
82
+ * Soter wallet instance
83
+ */
84
+ private _soterWallet: LeoWallet | undefined;
85
+
86
+ /**
87
+ * Create a new Soter wallet adapter
88
+ * @param config Adapter configuration
89
+ */
90
+ constructor(config?: LeoWalletAdapterConfig) {
91
+ super();
92
+ console.debug('SoterWalletAdapter constructor', config);
93
+ this.network = Network.MAINNET;
94
+ this._checkAvailability();
95
+ this._soterWallet = this._window?.soter || this._window?.soterWallet;
96
+ }
97
+
98
+ /**
99
+ * Check if Soter wallet is available
100
+ */
101
+ private _checkAvailability(): void {
102
+ if (typeof window === 'undefined' || typeof document === 'undefined') {
103
+ this.readyState = WalletReadyState.UNSUPPORTED;
104
+ return;
105
+ }
106
+
107
+ this._window = window as SoterWindow;
108
+
109
+ if (this._window.soter || this._window.soterWallet) {
110
+ this.readyState = WalletReadyState.INSTALLED;
111
+ this._soterWallet = this._window?.soter || this._window?.soterWallet;
112
+ } else {
113
+ // Check if user is on a mobile device
114
+ const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
115
+ if (isMobile) {
116
+ this.readyState = WalletReadyState.LOADABLE;
117
+ }
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Connect to Soter wallet
123
+ * @returns The connected account
124
+ */
125
+ async connect(
126
+ network: Network,
127
+ decryptPermission: WalletDecryptPermission,
128
+ programs?: string[],
129
+ ): Promise<Account> {
130
+ try {
131
+ if (this.readyState !== WalletReadyState.INSTALLED) {
132
+ throw new WalletConnectionError('Soter Wallet is not available');
133
+ }
134
+ if (network !== Network.MAINNET) {
135
+ throw new WalletConnectionError('Soter Wallet only support mainnet');
136
+ }
137
+
138
+ // Call connect and extract address safely
139
+ try {
140
+ await this._soterWallet?.connect(decryptPermission, LEO_NETWORK_MAP[network], programs);
141
+ if (!this._soterWallet?.publicKey) {
142
+ throw new WalletConnectionError(
143
+ 'Soter Wallet did not return address, maybe canceled by user',
144
+ );
145
+ }
146
+ } catch (error: unknown) {
147
+ throw new WalletConnectionError(
148
+ error instanceof Error ? error.message : 'Connection failed',
149
+ );
150
+ }
151
+
152
+ this._publicKey = this._soterWallet?.publicKey || '';
153
+ if (!this._publicKey) {
154
+ throw new WalletConnectionError('No address returned from wallet');
155
+ }
156
+
157
+ const account: Account = {
158
+ address: this._publicKey,
159
+ };
160
+
161
+ this.account = account;
162
+ this.decryptPermission = decryptPermission;
163
+ this.emit('connect', account);
164
+
165
+ return account;
166
+ } catch (err: Error | unknown) {
167
+ this.emit('error', err instanceof Error ? err : new Error(String(err)));
168
+ throw new WalletConnectionError(err instanceof Error ? err.message : 'Connection failed');
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Disconnect from Soter wallet
174
+ */
175
+ async disconnect(): Promise<void> {
176
+ try {
177
+ await this._soterWallet?.disconnect();
178
+ this._publicKey = '';
179
+ this.account = undefined;
180
+ this.emit('disconnect');
181
+ } catch (err: Error | unknown) {
182
+ this.emit('error', err instanceof Error ? err : new Error(String(err)));
183
+ throw new WalletDisconnectionError(
184
+ err instanceof Error ? err.message : 'Disconnection failed',
185
+ );
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Sign a transaction with Soter wallet
191
+ * @param options Transaction options
192
+ * @returns The signed transaction
193
+ */
194
+ async signMessage(message: Uint8Array): Promise<Uint8Array> {
195
+ if (!this._publicKey || !this.account) {
196
+ throw new WalletNotConnectedError();
197
+ }
198
+
199
+ try {
200
+ // Pass only the parameters expected by the Soter SDK
201
+ // @ts-expect-error soter's own definition
202
+ const signature: {
203
+ signature: { errorCode: number; result: string };
204
+ } = await this._soterWallet?.signMessage(message);
205
+
206
+ if (signature.signature.errorCode != 0) {
207
+ throw new Error('Permission Not Granted');
208
+ }
209
+ return new TextEncoder().encode(signature.signature.result);
210
+ } catch (error: Error | unknown) {
211
+ throw new WalletSignMessageError(
212
+ error instanceof Error ? error.message : 'Failed to sign message',
213
+ );
214
+ }
215
+ }
216
+
217
+ async decrypt(
218
+ cipherText: string,
219
+ tpk?: string,
220
+ programId?: string,
221
+ functionName?: string,
222
+ index?: number,
223
+ ) {
224
+ if (!this._soterWallet || !this._publicKey) {
225
+ throw new WalletNotConnectedError();
226
+ }
227
+ switch (this.decryptPermission) {
228
+ case WalletDecryptPermission.NoDecrypt:
229
+ throw new WalletDecryptionNotAllowedError();
230
+ case WalletDecryptPermission.UponRequest:
231
+ case WalletDecryptPermission.AutoDecrypt:
232
+ case WalletDecryptPermission.OnChainHistory: {
233
+ try {
234
+ const result = await this._soterWallet.decrypt(
235
+ cipherText,
236
+ tpk,
237
+ programId,
238
+ functionName,
239
+ index,
240
+ );
241
+ return result.text;
242
+ } catch (error: Error | unknown) {
243
+ throw new WalletDecryptionError(
244
+ error instanceof Error ? error.message : 'Failed to decrypt',
245
+ );
246
+ }
247
+ }
248
+ default:
249
+ throw new WalletDecryptionError();
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Execute a transaction with Soter wallet
255
+ * @param options Transaction options
256
+ * @returns The executed temporary transaction ID
257
+ */
258
+ async executeTransaction(options: TransactionOptions): Promise<{ transactionId: string }> {
259
+ if (!this._publicKey || !this.account) {
260
+ throw new WalletNotConnectedError();
261
+ }
262
+
263
+ try {
264
+ const requestData = {
265
+ address: this._publicKey,
266
+ chainId: LEO_NETWORK_MAP[this.network],
267
+ fee: options.fee ? options.fee : 0.001,
268
+ feePrivate: false,
269
+ transitions: [
270
+ {
271
+ program: options.program,
272
+ functionName: options.function,
273
+ inputs: options.inputs,
274
+ },
275
+ ],
276
+ } as AleoTransaction;
277
+
278
+ const result = await this._soterWallet?.requestTransaction(requestData);
279
+
280
+ if (!result?.transactionId) {
281
+ throw new WalletTransactionError('Could not create transaction');
282
+ }
283
+
284
+ return {
285
+ transactionId: result.transactionId,
286
+ };
287
+ } catch (error: Error | unknown) {
288
+ console.error('Soter Wallet executeTransaction error', error);
289
+ if (error instanceof WalletError) {
290
+ throw error;
291
+ }
292
+ throw new WalletTransactionError(
293
+ error instanceof Error ? error.message : 'Failed to execute transaction',
294
+ );
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Get transaction status
300
+ * @param transactionId The transaction ID
301
+ * @returns The transaction status
302
+ */
303
+ async transactionStatus(transactionId: string): Promise<TransactionStatusResponse> {
304
+ if (!this._publicKey || !this.account) {
305
+ throw new WalletNotConnectedError();
306
+ }
307
+
308
+ try {
309
+ const result = await this._soterWallet?.transactionStatus(transactionId);
310
+
311
+ if (!result?.status) {
312
+ throw new WalletTransactionError('Could not get transaction status');
313
+ }
314
+
315
+ return {
316
+ status: result.status,
317
+ };
318
+ } catch (error: Error | unknown) {
319
+ throw new WalletTransactionError(
320
+ error instanceof Error ? error.message : 'Failed to get transaction status',
321
+ );
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Request records from Soter wallet
327
+ * @param program The program to request records from
328
+ * @param includePlaintext Whether to include plaintext on each record
329
+ * @returns The records
330
+ */
331
+ async requestRecords(program: string, includePlaintext: boolean): Promise<unknown[]> {
332
+ if (!this._publicKey || !this.account) {
333
+ throw new WalletNotConnectedError();
334
+ }
335
+
336
+ try {
337
+ const result = includePlaintext
338
+ ? await this._soterWallet?.requestRecordPlaintexts(program)
339
+ : await this._soterWallet?.requestRecords(program);
340
+
341
+ return result?.records || [];
342
+ } catch (error: Error | unknown) {
343
+ throw new WalletError(error instanceof Error ? error.message : 'Failed to request records');
344
+ }
345
+ }
346
+
347
+ /**
348
+ * Switch the network
349
+ * @param network The network to switch to
350
+ */
351
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
352
+ async switchNetwork(_network: Network): Promise<void> {
353
+ console.error('Soter Wallet does not support switching networks');
354
+ throw new MethodNotImplementedError('switchNetwork');
355
+ }
356
+ }