@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/LICENSE +674 -0
- package/README.md +31 -0
- package/dist/index.d.mts +100 -0
- package/dist/index.d.ts +100 -0
- package/dist/index.js +287 -0
- package/dist/index.mjs +278 -0
- package/package.json +45 -0
- package/src/SoterWalletAdapter.ts +356 -0
- package/src/index.ts +1 -0
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,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';
|
|
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
|
+
}
|