wative-core 1.2.2 → 2.2.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/CHANGELOG.md +136 -0
- package/LICENSE +55 -0
- package/README.md +496 -0
- package/dist/artifacts/evm/index.cjs +1 -0
- package/dist/artifacts/evm/index.d.cts +6 -0
- package/dist/artifacts/evm/index.d.ts +6 -0
- package/dist/artifacts/evm/index.js +1 -0
- package/dist/artifacts/svm/index.cjs +1 -0
- package/dist/artifacts/svm/index.d.cts +9 -0
- package/dist/artifacts/svm/index.d.ts +9 -0
- package/dist/artifacts/svm/index.js +1 -0
- package/dist/container-provider-C59yqd5Z.d.ts +48 -0
- package/dist/container-provider-i614LDE1.d.cts +48 -0
- package/dist/evm-BLml33LX.d.cts +34 -0
- package/dist/evm-DTzqGlL6.d.ts +34 -0
- package/dist/file-sink-B73MuigK.d.cts +44 -0
- package/dist/file-sink-LS4hyXXi.d.ts +44 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +194 -0
- package/dist/index.d.ts +194 -0
- package/dist/index.js +1 -0
- package/dist/index.node.cjs +1 -0
- package/dist/index.node.d.cts +6 -0
- package/dist/index.node.d.ts +6 -0
- package/dist/index.node.js +1 -0
- package/dist/node/index.cjs +1 -0
- package/dist/node/index.d.cts +7 -0
- package/dist/node/index.d.ts +7 -0
- package/dist/node/index.js +1 -0
- package/dist/svm-CCzqNAWM.d.cts +59 -0
- package/dist/svm-DieFbh9k.d.ts +59 -0
- package/dist/workspace-CamTHxso.d.cts +737 -0
- package/dist/workspace-CamTHxso.d.ts +737 -0
- package/package.json +85 -39
- package/tests/01-quick-start.test.cjs +37 -0
- package/tests/02-hd-account.test.cjs +71 -0
- package/tests/03-pk-account.test.cjs +59 -0
- package/tests/04-network-management.test.cjs +94 -0
- package/tests/05-asset-management.test.cjs +117 -0
- package/tests/06-address-signing.test.cjs +55 -0
- package/tests/07-custom-provider.test.cjs +164 -0
- package/tests/08-persistence.test.cjs +105 -0
- package/tests/09-workspace-filter.test.cjs +84 -0
- package/tests/10-default-network.test.cjs +70 -0
- package/tests/11-subpath-imports.test.cjs +21 -0
- package/tests/12-logger.test.cjs +44 -0
- package/tests/13-workspace-config.test.cjs +43 -0
- package/tests/14-esm-runtime.test.mjs +81 -0
- package/tests/15-package-resolution.test.cjs +76 -0
- package/tests/16-known-answer-vectors.test.cjs +141 -0
- package/tests/17-locked-state.test.cjs +162 -0
- package/tests/README.md +72 -0
- package/lib/account.d.ts +0 -69
- package/lib/index.d.ts +0 -6
- package/lib/index.esm.js +0 -1
- package/lib/index.umd.js +0 -1
- package/lib/mnemonic.d.ts +0 -3
- package/lib/utils.d.ts +0 -21
- package/src/account.ts +0 -749
- package/src/index.ts +0 -11
- package/src/mnemonic.ts +0 -2084
- package/src/utils.ts +0 -132
package/src/account.ts
DELETED
|
@@ -1,749 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs"
|
|
2
|
-
import * as path from "path"
|
|
3
|
-
import Web3 from 'web3';
|
|
4
|
-
import * as nacl from "tweetnacl";
|
|
5
|
-
import * as bs58 from 'bs58';
|
|
6
|
-
import * as bip39 from 'bip39'
|
|
7
|
-
import { Keypair, Connection } from '@solana/web3.js';
|
|
8
|
-
import { Wallet } from "@coral-xyz/anchor"
|
|
9
|
-
import * as CryptoJS from "crypto-js";
|
|
10
|
-
import { EvmGasUtil, Result, checkAccountLabelsExistence, encryptMessage, decryptMessage, excutePromiseFunction, checkFileExistence, getJsonParams, setJsonParams, hexToUint8Array, getAccountLabels } from "./utils";
|
|
11
|
-
import { checkMnemonic } from "./mnemonic";
|
|
12
|
-
import { hdkey as evmHdKey } from 'ethereumjs-wallet';
|
|
13
|
-
import { HDKey as solanaHdKey } from 'micro-ed25519-hdkey';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const web3 = new Web3(Web3.givenProvider);
|
|
17
|
-
|
|
18
|
-
export class Account {
|
|
19
|
-
private setting_path: string;
|
|
20
|
-
private account_labels: string[];
|
|
21
|
-
private account_passwords: any = {};
|
|
22
|
-
private account_ciphertexts: any = {};
|
|
23
|
-
|
|
24
|
-
private disable_address = false;
|
|
25
|
-
private account_signatures = "";
|
|
26
|
-
|
|
27
|
-
constructor(setting_path: string, account_labels: string[], account_passwords?: string[], disable_address?: boolean) {
|
|
28
|
-
this.setting_path = setting_path;
|
|
29
|
-
this.account_labels = account_labels;
|
|
30
|
-
|
|
31
|
-
if (account_labels.length === 0) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (account_passwords) {
|
|
36
|
-
if (account_labels.length !== account_passwords.length) {
|
|
37
|
-
throw new Error("account_labels should have same length for account_passwords");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
for (let i = 0; i < account_labels.length; i++) {
|
|
41
|
-
if (!this.checkPassword(account_labels[i], account_passwords[i].trim())) {
|
|
42
|
-
throw new Error("account_passwords is not correct");
|
|
43
|
-
};
|
|
44
|
-
this.account_passwords[account_labels[i]] = account_passwords[i].trim();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (disable_address) {
|
|
49
|
-
this.disable_address = disable_address;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
this.reload();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
public isLogin(account_label: string) {
|
|
56
|
-
return account_label in this.account_passwords;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
public reloadAccount() {
|
|
60
|
-
this.reload();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
public getAccountLabel(account_address: string) {
|
|
64
|
-
let _account_address: any = null;
|
|
65
|
-
for (let _address in this.account_ciphertexts) {
|
|
66
|
-
if (_address.toLocaleLowerCase().includes(account_address.toLocaleLowerCase())) {
|
|
67
|
-
_account_address = _address;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
if (_account_address === null) {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
let result = {
|
|
75
|
-
account_address: _account_address,
|
|
76
|
-
account_label: this.account_ciphertexts[_account_address].account_label
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return result;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
public login(account_label: string, password: string) {
|
|
83
|
-
if (!this.checkPassword(account_label, password)) {
|
|
84
|
-
return {
|
|
85
|
-
status: false,
|
|
86
|
-
output: "Password is not correct"
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
this.account_passwords[account_label] = password;
|
|
90
|
-
this.account_labels.push(account_label);
|
|
91
|
-
this.reload();
|
|
92
|
-
return {
|
|
93
|
-
status: true,
|
|
94
|
-
output: "Login success"
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
public getAccounts(account_chain_type: string) {
|
|
99
|
-
let new_account_signature = this.getAccountSignature();
|
|
100
|
-
if (new_account_signature !== this.account_signatures) {
|
|
101
|
-
this.account_signatures = new_account_signature;
|
|
102
|
-
this.reload();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
let account_type_list = Object.keys(this.account_ciphertexts);
|
|
106
|
-
let account_address_list: string[] = [];
|
|
107
|
-
for (let i = 0; i < account_type_list.length; i++) {
|
|
108
|
-
if (this.getAccountChainType(account_type_list[i]) === account_chain_type) {
|
|
109
|
-
account_address_list.push(account_type_list[i]);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return account_address_list;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
public checkAccountLabelIsExist(account_label: string) {
|
|
116
|
-
return checkAccountLabelsExistence(this.setting_path, [account_label]);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
public checkAccountIsExist(account_address: string) {
|
|
120
|
-
account_address = this.getAccountChecksumAddress(account_address);
|
|
121
|
-
if (account_address in this.account_ciphertexts) {
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
this.reload();
|
|
126
|
-
return account_address in this.account_ciphertexts;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
public checkPassword(account_label: string, password: string) {
|
|
130
|
-
let json_data_path = path.join(this.setting_path, `accounts/${account_label}.json`);
|
|
131
|
-
|
|
132
|
-
if (!checkFileExistence(json_data_path)) {
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
let account_label_data = getJsonParams(json_data_path);
|
|
137
|
-
|
|
138
|
-
let message: any;
|
|
139
|
-
if (account_label_data.account_type === "PK") {
|
|
140
|
-
message = {
|
|
141
|
-
salt: password,
|
|
142
|
-
...account_label_data.data[0].ciphertexts
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
} else {
|
|
146
|
-
message = {
|
|
147
|
-
slat: password,
|
|
148
|
-
data: account_label_data.pp_ciphertexts
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
let signature = CryptoJS.SHA256(JSON.stringify(message)).toString();
|
|
153
|
-
|
|
154
|
-
return account_label_data.signature === signature;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
public showPrivateKey(account_address: string) {
|
|
158
|
-
let account_is_exist = this.checkAccountIsExist(account_address);
|
|
159
|
-
if (!account_is_exist) {
|
|
160
|
-
throw new Error("Account is not exist");
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
account_address = this.getAccountChecksumAddress(account_address);
|
|
164
|
-
let account_data = this.account_ciphertexts[account_address];
|
|
165
|
-
let password = this.account_passwords[account_data.account_label];
|
|
166
|
-
return decryptMessage(account_data.data, password);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
public getAccountChainType(account_address: string): string {
|
|
170
|
-
if (account_address.startsWith("0x") && account_address.length === 42) {
|
|
171
|
-
return "evm";
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (/^[A-HJ-NP-Za-km-z1-9]*$/.test(account_address)) {
|
|
175
|
-
return "solana";
|
|
176
|
-
}
|
|
177
|
-
return "unknown";
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
public generatePKAccount(account_label: string, pk: string, password: string, chain_id: string, generate_account_label: boolean) {
|
|
181
|
-
if (generate_account_label && this.checkAccountLabelIsExist(account_label)) {
|
|
182
|
-
throw new Error("Account labels already exist");
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (!generate_account_label && !this.account_passwords[account_label]) {
|
|
186
|
-
throw new Error("Password is not correct");
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (!generate_account_label) {
|
|
190
|
-
password = this.account_passwords[account_label];
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
let ciphertext_data = encryptMessage(pk, password);
|
|
194
|
-
|
|
195
|
-
let account_address: string;
|
|
196
|
-
try {
|
|
197
|
-
account_address = this.getAccountAddressByPrivateKey(pk, chain_id);
|
|
198
|
-
} catch (err: any) {
|
|
199
|
-
return {
|
|
200
|
-
status: false,
|
|
201
|
-
output: err.message
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
let ciphertexts = {
|
|
206
|
-
address: account_address,
|
|
207
|
-
data: ciphertext_data
|
|
208
|
-
};
|
|
209
|
-
let message = {
|
|
210
|
-
salt: password,
|
|
211
|
-
...ciphertexts
|
|
212
|
-
};
|
|
213
|
-
let signature = CryptoJS.SHA256(JSON.stringify(message)).toString();
|
|
214
|
-
|
|
215
|
-
let account = {
|
|
216
|
-
signature,
|
|
217
|
-
account_type: "PK",
|
|
218
|
-
tag: "",
|
|
219
|
-
ciphertexts
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (!generate_account_label) {
|
|
223
|
-
this.account_passwords[account_label] = password;
|
|
224
|
-
this.account_labels.push(account_label);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return {
|
|
228
|
-
status: true,
|
|
229
|
-
output: account
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
public generatePPAccount(account_label: string, pp: string, password: string) {
|
|
234
|
-
if (this.checkAccountLabelIsExist(account_label)) {
|
|
235
|
-
return {
|
|
236
|
-
status: false,
|
|
237
|
-
output: "Account labels already exist"
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
let pp_ciphertext_data = encryptMessage(pp, password);
|
|
242
|
-
let message = {
|
|
243
|
-
slat: password,
|
|
244
|
-
data: pp_ciphertext_data
|
|
245
|
-
}
|
|
246
|
-
let signature = CryptoJS.SHA256(JSON.stringify(message)).toString();
|
|
247
|
-
let evm_account_data = this.getSubAccount("evm", pp, 0);
|
|
248
|
-
if (evm_account_data.status === false) {
|
|
249
|
-
return {
|
|
250
|
-
status: false,
|
|
251
|
-
output: evm_account_data.output
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
let solana_account_data = this.getSubAccount("solana", pp, 0);
|
|
256
|
-
if (solana_account_data.status === false) {
|
|
257
|
-
return {
|
|
258
|
-
status: false,
|
|
259
|
-
output: solana_account_data.output
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
let account = {
|
|
264
|
-
signature,
|
|
265
|
-
account_type: "PP",
|
|
266
|
-
pp_ciphertexts: pp_ciphertext_data,
|
|
267
|
-
tag: "",
|
|
268
|
-
data: [{
|
|
269
|
-
ciphertexts: {
|
|
270
|
-
evm: {
|
|
271
|
-
address: evm_account_data.output.address,
|
|
272
|
-
data: encryptMessage(evm_account_data.output.pk, password)
|
|
273
|
-
},
|
|
274
|
-
solana: {
|
|
275
|
-
address: solana_account_data.output.address,
|
|
276
|
-
data: encryptMessage(solana_account_data.output.pk, password)
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}]
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
this.account_passwords[account_label] = password;
|
|
283
|
-
this.account_labels.push(account_label);
|
|
284
|
-
return {
|
|
285
|
-
status: true,
|
|
286
|
-
output: account
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
public generateSubAccount(account_label: string, account_index: number) {
|
|
291
|
-
if (!this.checkAccountLabelIsExist(account_label)) {
|
|
292
|
-
return {
|
|
293
|
-
status: false,
|
|
294
|
-
output: "Account labels not exist"
|
|
295
|
-
}
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
let json_data_path = path.join(this.setting_path, `accounts/${account_label}.json`);
|
|
299
|
-
let account_label_data = getJsonParams(json_data_path);
|
|
300
|
-
let pp_ciphertexts = account_label_data.pp_ciphertexts;
|
|
301
|
-
|
|
302
|
-
let pp = decryptMessage(pp_ciphertexts, this.account_passwords[account_label]);
|
|
303
|
-
|
|
304
|
-
let evm_account_data = this.getSubAccount("evm", pp, account_index);
|
|
305
|
-
if (evm_account_data.status === false) {
|
|
306
|
-
return {
|
|
307
|
-
status: false,
|
|
308
|
-
output: evm_account_data.output
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
let solana_account_data = this.getSubAccount("solana", pp, account_index);
|
|
313
|
-
if (solana_account_data.status === false) {
|
|
314
|
-
return {
|
|
315
|
-
status: false,
|
|
316
|
-
output: solana_account_data.output
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
let sub_account = {
|
|
321
|
-
evm: {
|
|
322
|
-
address: evm_account_data.output.address,
|
|
323
|
-
data: encryptMessage(evm_account_data.output.pk, this.account_passwords[account_label])
|
|
324
|
-
},
|
|
325
|
-
solana: {
|
|
326
|
-
address: solana_account_data.output.address,
|
|
327
|
-
data: encryptMessage(solana_account_data.output.pk, this.account_passwords[account_label])
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
return {
|
|
332
|
-
status: true,
|
|
333
|
-
output: sub_account
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
public resetPassword(account_label: string, new_password: string) {
|
|
338
|
-
if (!this.checkAccountLabelIsExist(account_label)) {
|
|
339
|
-
return {
|
|
340
|
-
status: false,
|
|
341
|
-
output: "Account labels not exist"
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
if (!this.checkPassword(account_label, this.account_passwords[account_label])) {
|
|
346
|
-
return {
|
|
347
|
-
status: false,
|
|
348
|
-
output: "account passwords is not correct"
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
let json_data_path = path.join(this.setting_path, `accounts/${account_label}.json`);
|
|
353
|
-
let account_label_data = getJsonParams(json_data_path);
|
|
354
|
-
|
|
355
|
-
if (account_label_data.account_type === "PK") {
|
|
356
|
-
let account_data_list = account_label_data.data;
|
|
357
|
-
|
|
358
|
-
for (let i = 0; i < account_data_list.length; i++) {
|
|
359
|
-
let old_ciphertexts_data = account_data_list[i].ciphertexts.data;
|
|
360
|
-
let pk = decryptMessage(old_ciphertexts_data, this.account_passwords[account_label]);
|
|
361
|
-
account_data_list[i].ciphertexts.data = encryptMessage(pk, new_password);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
let message = {
|
|
365
|
-
salt: new_password,
|
|
366
|
-
...account_label_data.data[0].ciphertexts
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
account_label_data.signature = CryptoJS.SHA256(JSON.stringify(message)).toString();
|
|
370
|
-
setJsonParams(account_label_data, json_data_path);
|
|
371
|
-
delete this.account_passwords[account_label];
|
|
372
|
-
|
|
373
|
-
return {
|
|
374
|
-
status: true,
|
|
375
|
-
output: "Password reset successfully"
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
let pp_ciphertext_data = decryptMessage(account_label_data.pp_ciphertexts, this.account_passwords[account_label]);
|
|
380
|
-
account_label_data.pp_ciphertexts = encryptMessage(pp_ciphertext_data, new_password);
|
|
381
|
-
let message = {
|
|
382
|
-
slat: new_password,
|
|
383
|
-
data: account_label_data.pp_ciphertexts
|
|
384
|
-
};
|
|
385
|
-
account_label_data.signature = CryptoJS.SHA256(JSON.stringify(message)).toString();
|
|
386
|
-
|
|
387
|
-
let accounts = account_label_data.data;
|
|
388
|
-
for (let i = 0; i < accounts.length; i++) {
|
|
389
|
-
let ppk = decryptMessage(accounts[i].ciphertexts.evm.data, this.account_passwords[account_label]);
|
|
390
|
-
accounts[i].ciphertexts.evm.data = encryptMessage(ppk, new_password);
|
|
391
|
-
let ppp = decryptMessage(accounts[i].ciphertexts.solana.data, this.account_passwords[account_label]);
|
|
392
|
-
accounts[i].ciphertexts.solana.data = encryptMessage(ppp, new_password);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
setJsonParams(account_label_data, json_data_path);
|
|
396
|
-
delete this.account_passwords[account_label];
|
|
397
|
-
|
|
398
|
-
return {
|
|
399
|
-
status: true,
|
|
400
|
-
output: "Password reset successfully"
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
public signTransaction(account_address: string, transaction: any, rpc_url: string) {
|
|
405
|
-
account_address = this.getAccountChecksumAddress(account_address);
|
|
406
|
-
let account_is_exist = this.checkAccountIsExist(account_address);
|
|
407
|
-
if (!account_is_exist) {
|
|
408
|
-
return {
|
|
409
|
-
status: false,
|
|
410
|
-
output: "Account is not exist"
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
if (this.getAccountChainType(account_address) === "unknown") {
|
|
415
|
-
return {
|
|
416
|
-
status: false,
|
|
417
|
-
output: "Chain type unknown"
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
if (this.getAccountChainType(account_address) === "evm") {
|
|
421
|
-
return this.signEvmTransaction(transaction, rpc_url);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
return this.signSolanaTransaction(account_address, rpc_url, transaction);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
public signTransactionOffline(account_address: string, transaction: any, chainId: number) {
|
|
428
|
-
if (!("chainId" in transaction)) {
|
|
429
|
-
transaction.chainId = chainId;
|
|
430
|
-
}
|
|
431
|
-
const private_key = this.showPrivateKey(account_address);
|
|
432
|
-
const current_web3 = new Web3(Web3.givenProvider);
|
|
433
|
-
let excute_result = excutePromiseFunction(current_web3.eth.accounts.signTransaction.bind(current_web3.eth.accounts), [transaction, private_key]);
|
|
434
|
-
return excute_result;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
public sendSignedTransaction(account_address: string, signed_transaction: any, rpc_url: string) {
|
|
438
|
-
account_address = this.getAccountChecksumAddress(account_address);
|
|
439
|
-
let account_is_exist = this.checkAccountIsExist(account_address);
|
|
440
|
-
if (!account_is_exist) {
|
|
441
|
-
return {
|
|
442
|
-
status: false,
|
|
443
|
-
output: "Account is not exist"
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
if (this.getAccountChainType(account_address) === "unknown") {
|
|
448
|
-
return {
|
|
449
|
-
status: false,
|
|
450
|
-
output: "Chain type unknown"
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
if (this.getAccountChainType(account_address) === "evm") {
|
|
454
|
-
return this.sendEvmTransaction(signed_transaction, rpc_url);
|
|
455
|
-
}
|
|
456
|
-
return this.sendSolanaTransaction(signed_transaction, rpc_url);
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
public signMessage(account_address: string, message: string) {
|
|
460
|
-
account_address = this.getAccountChecksumAddress(account_address);
|
|
461
|
-
let account_is_exist = this.checkAccountIsExist(account_address);
|
|
462
|
-
if (!account_is_exist) {
|
|
463
|
-
return {
|
|
464
|
-
status: false,
|
|
465
|
-
output: "Account is not exist"
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
if (this.getAccountChainType(account_address) === "unknown") {
|
|
470
|
-
return {
|
|
471
|
-
status: false,
|
|
472
|
-
output: "Chain type unknown"
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
if (this.getAccountChainType(account_address) === "evm") {
|
|
476
|
-
return {
|
|
477
|
-
status: true,
|
|
478
|
-
output: this.signEvmMessage(message, account_address)
|
|
479
|
-
};
|
|
480
|
-
}
|
|
481
|
-
return {
|
|
482
|
-
status: true,
|
|
483
|
-
output: this.signSolanaMessage(message, account_address)
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
public async simulateTransaction(account_address: string, rpc_url: string, transaction: any) {
|
|
488
|
-
const connection = new Connection(rpc_url);
|
|
489
|
-
const private_key = this.showPrivateKey(account_address);
|
|
490
|
-
|
|
491
|
-
const signer = Keypair.fromSecretKey(bs58.decode(private_key));
|
|
492
|
-
const simulate_transaction_result = await excutePromiseFunction(connection.simulateTransaction.bind(connection), [transaction, [signer]]);
|
|
493
|
-
return simulate_transaction_result;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
private async signEvmTransaction(tx_params: any, rpc_url: string): Promise<Result> {
|
|
497
|
-
if (!this.account_passwords) {
|
|
498
|
-
return {
|
|
499
|
-
status: false,
|
|
500
|
-
output: "Please set password first"
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
let account = tx_params.from;
|
|
505
|
-
if (!tx_params.gas) {
|
|
506
|
-
let evm_gas_util = new EvmGasUtil(rpc_url);
|
|
507
|
-
let result = await evm_gas_util.getEvmGasLimit(tx_params, rpc_url);
|
|
508
|
-
if (!result.status) {
|
|
509
|
-
return result;
|
|
510
|
-
}
|
|
511
|
-
tx_params.gas = result.output;
|
|
512
|
-
}
|
|
513
|
-
if (!tx_params.gasPrice) {
|
|
514
|
-
let evm_gas_util = new EvmGasUtil(rpc_url);
|
|
515
|
-
let result = await evm_gas_util.getEvmGasPrice();
|
|
516
|
-
if (!result.status) {
|
|
517
|
-
return result;
|
|
518
|
-
}
|
|
519
|
-
tx_params.gasPrice = result.output;
|
|
520
|
-
}
|
|
521
|
-
const private_key = this.showPrivateKey(account);
|
|
522
|
-
const current_web3 = new Web3(rpc_url);
|
|
523
|
-
let excute_result = await excutePromiseFunction(current_web3.eth.accounts.signTransaction.bind(current_web3.eth.accounts), [tx_params, private_key]);
|
|
524
|
-
return excute_result;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
private async sendEvmTransaction(signed_transaction: any, rpc_url: string) {
|
|
528
|
-
const current_web3 = new Web3(rpc_url);
|
|
529
|
-
let excute_result = await excutePromiseFunction(current_web3.eth.sendSignedTransaction.bind(current_web3.eth), [signed_transaction]);
|
|
530
|
-
return excute_result;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
private async signSolanaTransaction(account_address: string, rpc_url: string, transaction: any) {
|
|
534
|
-
const private_key = this.showPrivateKey(account_address);
|
|
535
|
-
const owner = Keypair.fromSecretKey(bs58.decode(private_key));
|
|
536
|
-
const wallet = new Wallet(owner);
|
|
537
|
-
if (!("recentBlockhash" in transaction) || !transaction.recentBlockhash) {
|
|
538
|
-
const connection = new Connection(rpc_url);
|
|
539
|
-
let current_blockhash_result = await excutePromiseFunction(connection.getLatestBlockhash.bind(connection), []);
|
|
540
|
-
if (!current_blockhash_result.status) {
|
|
541
|
-
return {
|
|
542
|
-
status: false,
|
|
543
|
-
output: "Failed to get latest blockhash"
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
transaction.recentBlockhash = current_blockhash_result.output.blockhash;
|
|
547
|
-
}
|
|
548
|
-
transaction.feePayer = wallet.publicKey;
|
|
549
|
-
let excute_result = await excutePromiseFunction(wallet.signTransaction.bind(wallet), [transaction]);
|
|
550
|
-
return excute_result;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
private async sendSolanaTransaction(signed_transaction: any, rpc_url: string) {
|
|
554
|
-
const connection = new Connection(rpc_url);
|
|
555
|
-
let excute_result = await excutePromiseFunction(connection.sendRawTransaction.bind(connection), [signed_transaction.serialize()]);
|
|
556
|
-
return excute_result;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
private signEvmMessage(message: any, account_address: string) {
|
|
560
|
-
const private_key = this.showPrivateKey(account_address);
|
|
561
|
-
const signedData = web3.eth.accounts.sign(message, private_key);
|
|
562
|
-
return signedData.signature;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
private signSolanaMessage(message: any, account_address: string) {
|
|
566
|
-
const private_key = this.showPrivateKey(account_address);
|
|
567
|
-
const signature = nacl.sign.detached(
|
|
568
|
-
hexToUint8Array(message),
|
|
569
|
-
bs58.decode(private_key)
|
|
570
|
-
);
|
|
571
|
-
return bs58.encode(signature);
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
public checkIsDisableAddress(disabled_slots: any, account_index: number) {
|
|
575
|
-
if (!disabled_slots || !this.disable_address) {
|
|
576
|
-
return false;
|
|
577
|
-
}
|
|
578
|
-
let disabled_slots_len = disabled_slots.length;
|
|
579
|
-
for (let i = 0; i < disabled_slots_len; i++) {
|
|
580
|
-
let from = disabled_slots[i].from;
|
|
581
|
-
let to = disabled_slots[i].to;
|
|
582
|
-
if (account_index >= from && account_index <= to) {
|
|
583
|
-
return true;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
return false;
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
private reload() {
|
|
590
|
-
this.account_labels = getAccountLabels(this.setting_path, this.account_labels);
|
|
591
|
-
if (!checkAccountLabelsExistence(this.setting_path, this.account_labels)) {
|
|
592
|
-
throw new Error("Account labels not exist");
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
let new_account_ciphertexts: any = {};
|
|
596
|
-
let account_labels_size = this.account_labels.length;
|
|
597
|
-
for (let i = 0; i < account_labels_size; i++) {
|
|
598
|
-
let account_path = path.join(this.setting_path, `accounts/${this.account_labels[i]}.json`);
|
|
599
|
-
if (!fs.existsSync(account_path)) {
|
|
600
|
-
continue;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
let account_data: any = JSON.parse(fs.readFileSync(account_path, 'utf8'));
|
|
604
|
-
if (account_data.account_type === "PK") {
|
|
605
|
-
let data = account_data.data;
|
|
606
|
-
if (!data) {
|
|
607
|
-
continue;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
let data_len = data.length;
|
|
611
|
-
for (let j = 0; j < data_len; j++) {
|
|
612
|
-
new_account_ciphertexts[data[j].ciphertexts.address] = {
|
|
613
|
-
account_label: this.account_labels[i],
|
|
614
|
-
data: data[j].ciphertexts.data
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
continue;
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
let account_data_len = account_data.data.length;
|
|
621
|
-
let disabled_slots = account_data.disabled_slots;
|
|
622
|
-
|
|
623
|
-
for (let j = 0; j < account_data_len; j++) {
|
|
624
|
-
if (this.checkIsDisableAddress(disabled_slots, j)) {
|
|
625
|
-
continue;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
new_account_ciphertexts[account_data.data[j].ciphertexts.evm.address] = {
|
|
629
|
-
account_label: this.account_labels[i],
|
|
630
|
-
data: account_data.data[j].ciphertexts.evm.data
|
|
631
|
-
};
|
|
632
|
-
new_account_ciphertexts[account_data.data[j].ciphertexts.solana.address] = {
|
|
633
|
-
account_label: this.account_labels[i],
|
|
634
|
-
data: account_data.data[j].ciphertexts.solana.data
|
|
635
|
-
};
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
this.account_ciphertexts = new_account_ciphertexts;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
private getAccountChecksumAddress(account_address: string) {
|
|
643
|
-
let account_type = this.getAccountChainType(account_address);
|
|
644
|
-
if (account_type === "evm") {
|
|
645
|
-
account_address = web3.utils.toChecksumAddress(account_address);
|
|
646
|
-
}
|
|
647
|
-
return account_address;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
private getAccountAddressByPrivateKey(private_key: string, chain_id: string) {
|
|
651
|
-
let network_type = this.getNetworkTypeByChainId(chain_id);
|
|
652
|
-
|
|
653
|
-
if (network_type === "evm") {
|
|
654
|
-
return web3.eth.accounts.privateKeyToAccount(private_key).address;
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
return Keypair.fromSecretKey(bs58.decode(private_key)).publicKey.toBase58();
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
private getNetworkTypeByChainId(chain_id: string) {
|
|
661
|
-
if (chain_id === "901" || chain_id === "902" || chain_id === "903") {
|
|
662
|
-
return "solana";
|
|
663
|
-
}
|
|
664
|
-
return "evm";
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
private getSubAccount(chain_type: string, pp: string, account_index: number): {
|
|
668
|
-
status: boolean,
|
|
669
|
-
output: any
|
|
670
|
-
} {
|
|
671
|
-
if (!checkMnemonic(pp)) {
|
|
672
|
-
return {
|
|
673
|
-
status: false,
|
|
674
|
-
output: "Please set correct mnemonic"
|
|
675
|
-
}
|
|
676
|
-
};
|
|
677
|
-
|
|
678
|
-
if (chain_type === "solana") {
|
|
679
|
-
const seed = bip39.mnemonicToSeedSync(pp);
|
|
680
|
-
let hdWallet = solanaHdKey.fromMasterSeed(seed);
|
|
681
|
-
let keypair = Keypair.fromSeed(hdWallet.derive(`m/44'/501'/${account_index}'/0'`).privateKey);
|
|
682
|
-
return {
|
|
683
|
-
status: true,
|
|
684
|
-
output: {
|
|
685
|
-
address: keypair.publicKey.toBase58(),
|
|
686
|
-
pk: bs58.encode(keypair.secretKey),
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
if (chain_type === "evm") {
|
|
692
|
-
const seed = bip39.mnemonicToSeedSync(pp);
|
|
693
|
-
const hdWallet = evmHdKey.fromMasterSeed(seed);
|
|
694
|
-
const hdRoot = hdWallet.derivePath("m/44'/60'/0'/0");
|
|
695
|
-
const child = hdRoot.deriveChild(account_index);
|
|
696
|
-
const wallet: any = child.getWallet();
|
|
697
|
-
|
|
698
|
-
return {
|
|
699
|
-
status: true,
|
|
700
|
-
output: {
|
|
701
|
-
address: web3.utils.toChecksumAddress(wallet.getAddressString()),
|
|
702
|
-
pk: wallet.getPrivateKeyString()
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
return {
|
|
708
|
-
status: false,
|
|
709
|
-
output: "Unknown chain type"
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
private getAccountSignature() {
|
|
714
|
-
let account_labels_size = this.account_labels.length;
|
|
715
|
-
|
|
716
|
-
// 使用增量哈希计算,避免大数据量问题
|
|
717
|
-
let hash = CryptoJS.algo.MD5.create();
|
|
718
|
-
|
|
719
|
-
for (let i = 0; i < account_labels_size; i++) {
|
|
720
|
-
let account_path = path.join(this.setting_path, `accounts/${this.account_labels[i]}.json`);
|
|
721
|
-
|
|
722
|
-
// 使用流式读取处理大文件
|
|
723
|
-
const chunkSize = 64 * 1024; // 64KB chunks
|
|
724
|
-
const fd = fs.openSync(account_path, 'r');
|
|
725
|
-
const buffer = Buffer.alloc(chunkSize);
|
|
726
|
-
let position = 0;
|
|
727
|
-
|
|
728
|
-
try {
|
|
729
|
-
while (true) {
|
|
730
|
-
const bytesRead = fs.readSync(fd, buffer, 0, chunkSize, position);
|
|
731
|
-
if (bytesRead === 0) break;
|
|
732
|
-
|
|
733
|
-
// 更新哈希,只处理实际读取的字节
|
|
734
|
-
const chunk = buffer.subarray(0, bytesRead).toString('utf8');
|
|
735
|
-
hash.update(chunk);
|
|
736
|
-
position += bytesRead;
|
|
737
|
-
}
|
|
738
|
-
} finally {
|
|
739
|
-
fs.closeSync(fd);
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
// 添加分隔符确保不同文件组合产生不同哈希
|
|
743
|
-
hash.update('|SEPARATOR|');
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
const account_signatures = hash.finalize().toString();
|
|
747
|
-
return account_signatures;
|
|
748
|
-
}
|
|
749
|
-
}
|