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/package.json
CHANGED
|
@@ -1,58 +1,104 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wative-core",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
|
|
3
|
+
"version": "2.2.0",
|
|
4
|
+
"description": "Hyperscale crypto wallet management library — multi-workspace, multi-chain, originally designed for on-chain market makers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.node.cjs",
|
|
7
|
+
"module": "./dist/index.node.js",
|
|
8
|
+
"types": "./dist/index.node.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"browser": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"node": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.node.d.ts",
|
|
18
|
+
"default": "./dist/index.node.js"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"types": "./dist/index.node.d.cts",
|
|
22
|
+
"default": "./dist/index.node.cjs"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"default": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"./node": {
|
|
31
|
+
"import": {
|
|
32
|
+
"types": "./dist/node/index.d.ts",
|
|
33
|
+
"default": "./dist/node/index.js"
|
|
34
|
+
},
|
|
35
|
+
"require": {
|
|
36
|
+
"types": "./dist/node/index.d.cts",
|
|
37
|
+
"default": "./dist/node/index.cjs"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"./artifacts/evm": {
|
|
41
|
+
"import": {
|
|
42
|
+
"types": "./dist/artifacts/evm/index.d.ts",
|
|
43
|
+
"default": "./dist/artifacts/evm/index.js"
|
|
44
|
+
},
|
|
45
|
+
"require": {
|
|
46
|
+
"types": "./dist/artifacts/evm/index.d.cts",
|
|
47
|
+
"default": "./dist/artifacts/evm/index.cjs"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"./artifacts/svm": {
|
|
51
|
+
"import": {
|
|
52
|
+
"types": "./dist/artifacts/svm/index.d.ts",
|
|
53
|
+
"default": "./dist/artifacts/svm/index.js"
|
|
54
|
+
},
|
|
55
|
+
"require": {
|
|
56
|
+
"types": "./dist/artifacts/svm/index.d.cts",
|
|
57
|
+
"default": "./dist/artifacts/svm/index.cjs"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"./package.json": "./package.json"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=22.12"
|
|
12
64
|
},
|
|
13
65
|
"repository": {
|
|
14
66
|
"type": "git",
|
|
15
|
-
"url": ""
|
|
67
|
+
"url": "git+https://github.com/braady/wative-core.git"
|
|
16
68
|
},
|
|
17
69
|
"bugs": {
|
|
18
|
-
"url": "https://github.com"
|
|
70
|
+
"url": "https://github.com/braady/wative-core/issues"
|
|
19
71
|
},
|
|
20
|
-
"homepage": "https://github.com",
|
|
72
|
+
"homepage": "https://github.com/braady/wative-core#readme",
|
|
21
73
|
"keywords": [
|
|
74
|
+
"wallet",
|
|
22
75
|
"keystore",
|
|
23
|
-
"
|
|
76
|
+
"ethereum",
|
|
77
|
+
"evm",
|
|
78
|
+
"solana",
|
|
79
|
+
"svm",
|
|
80
|
+
"crypto",
|
|
81
|
+
"hd-wallet",
|
|
82
|
+
"multi-account"
|
|
24
83
|
],
|
|
25
|
-
"author": "",
|
|
26
|
-
"license": "
|
|
84
|
+
"author": "Brady <brady.c@hedgue.com>",
|
|
85
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
27
86
|
"files": [
|
|
28
|
-
"
|
|
29
|
-
"
|
|
87
|
+
"dist/",
|
|
88
|
+
"CHANGELOG.md",
|
|
89
|
+
"tests/"
|
|
30
90
|
],
|
|
31
91
|
"dependencies": {
|
|
32
92
|
"@coral-xyz/anchor": "0.30.1",
|
|
33
|
-
"@
|
|
34
|
-
"
|
|
35
|
-
"
|
|
93
|
+
"@noble/ciphers": "^2.2.0",
|
|
94
|
+
"@noble/curves": "^1.9.7",
|
|
95
|
+
"@noble/hashes": "^1.8.0",
|
|
96
|
+
"@scure/bip39": "^2.2.0",
|
|
97
|
+
"@solana/web3.js": "1.98.4",
|
|
98
|
+
"bs58": "5.0.0",
|
|
99
|
+
"ethers": "6.17.0",
|
|
36
100
|
"micro-ed25519-hdkey": "0.1.2",
|
|
37
|
-
"rpc-websockets": "7.10.0",
|
|
38
101
|
"tslib": "2.6.2",
|
|
39
|
-
"tweetnacl": "1.0.3"
|
|
40
|
-
"web3": "1.7.3",
|
|
41
|
-
"web3-core": "4.3.2"
|
|
42
|
-
},
|
|
43
|
-
"devDependencies": {
|
|
44
|
-
"@babel/plugin-transform-modules-commonjs": "7.24.1",
|
|
45
|
-
"@rollup/plugin-commonjs": "21.0.1",
|
|
46
|
-
"rollup": "2.79.1",
|
|
47
|
-
"rollup-plugin-terser": "7.0.2",
|
|
48
|
-
"rollup-plugin-typescript2": "0.31.2",
|
|
49
|
-
"typescript": "4.9.5",
|
|
50
|
-
"jest": "27.5.1",
|
|
51
|
-
"@types/node": "24.2.0",
|
|
52
|
-
"@types/bs58": "4.0.4",
|
|
53
|
-
"@types/crypto-js": "4.2.2"
|
|
54
|
-
},
|
|
55
|
-
"optionalDependencies": {
|
|
56
|
-
"nodejs-threadpool": "1.0.1"
|
|
102
|
+
"tweetnacl": "1.0.3"
|
|
57
103
|
}
|
|
58
104
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// 01 — Quick start. Open a workspace, create an HD account, derive wallets,
|
|
2
|
+
// lock down. The shortest end-to-end demo.
|
|
3
|
+
|
|
4
|
+
const test = require("node:test");
|
|
5
|
+
const assert = require("node:assert");
|
|
6
|
+
const { mkdtempSync } = require("node:fs");
|
|
7
|
+
const { tmpdir } = require("node:os");
|
|
8
|
+
const { join } = require("node:path");
|
|
9
|
+
|
|
10
|
+
const { Workspace } = require("wative-core");
|
|
11
|
+
|
|
12
|
+
test("quick start — open, create HD account, derive wallets, lock", async () => {
|
|
13
|
+
const root = mkdtempSync(join(tmpdir(), "wative-quickstart-"));
|
|
14
|
+
const password = "your-workspace-password";
|
|
15
|
+
|
|
16
|
+
const ws = await Workspace.open({ path: root, password });
|
|
17
|
+
assert.strictEqual(ws.locked, false);
|
|
18
|
+
|
|
19
|
+
const account = await ws.accounts.create(
|
|
20
|
+
"Trading Desk",
|
|
21
|
+
password,
|
|
22
|
+
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
|
23
|
+
);
|
|
24
|
+
assert.strictEqual(account.wallets.length, 1);
|
|
25
|
+
|
|
26
|
+
await account.deriveWallets(4);
|
|
27
|
+
assert.strictEqual(account.wallets.length, 5);
|
|
28
|
+
|
|
29
|
+
const wallet = account.wallets[0];
|
|
30
|
+
const evm = wallet.addresses.find((a) => a.vm === "evm");
|
|
31
|
+
const svm = wallet.addresses.find((a) => a.vm === "svm");
|
|
32
|
+
assert.ok(evm && evm.publicKey.startsWith("0x"));
|
|
33
|
+
assert.ok(svm && svm.publicKey.length >= 32);
|
|
34
|
+
|
|
35
|
+
await ws.lock();
|
|
36
|
+
assert.strictEqual(ws.locked, true);
|
|
37
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// 02 — HD account flows. derive / slice wallets, dump mnemonic, reset password,
|
|
2
|
+
// reopen a locked workspace.
|
|
3
|
+
|
|
4
|
+
const test = require("node:test");
|
|
5
|
+
const assert = require("node:assert");
|
|
6
|
+
const { mkdtempSync } = require("node:fs");
|
|
7
|
+
const { tmpdir } = require("node:os");
|
|
8
|
+
const { join } = require("node:path");
|
|
9
|
+
|
|
10
|
+
const { Workspace } = require("wative-core");
|
|
11
|
+
|
|
12
|
+
const MNEMONIC =
|
|
13
|
+
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
|
|
14
|
+
|
|
15
|
+
test("HD account — derive, slice, dump mnemonic", async () => {
|
|
16
|
+
const root = mkdtempSync(join(tmpdir(), "wative-hd-"));
|
|
17
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
18
|
+
|
|
19
|
+
const acc = await ws.accounts.create("Desk", "wsp-pwd", MNEMONIC);
|
|
20
|
+
await acc.deriveWallets(10);
|
|
21
|
+
assert.strictEqual(acc.wallets.length, 11);
|
|
22
|
+
|
|
23
|
+
await acc.sliceWallets(6);
|
|
24
|
+
assert.strictEqual(acc.wallets.length, 6);
|
|
25
|
+
|
|
26
|
+
assert.strictEqual(acc.dumpMnemonic(), MNEMONIC);
|
|
27
|
+
|
|
28
|
+
await ws.lock();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("HD account — own password + resetPassword", async () => {
|
|
32
|
+
const root = mkdtempSync(join(tmpdir(), "wative-hd-pwd-"));
|
|
33
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
34
|
+
|
|
35
|
+
const sub = await ws.accounts.create("SubAccount", "sub-pwd", MNEMONIC, undefined, {
|
|
36
|
+
hasOwnPassword: true,
|
|
37
|
+
});
|
|
38
|
+
assert.strictEqual(sub.locked, false);
|
|
39
|
+
|
|
40
|
+
sub.lock();
|
|
41
|
+
assert.strictEqual(sub.locked, true);
|
|
42
|
+
|
|
43
|
+
await assert.rejects(sub.tryUnlock("wrong"), (err) => err.code === "BAD_PASSWORD");
|
|
44
|
+
await sub.tryUnlock("sub-pwd");
|
|
45
|
+
|
|
46
|
+
await sub.resetPassword("sub-pwd", "new-sub-pwd");
|
|
47
|
+
sub.lock();
|
|
48
|
+
await assert.rejects(sub.tryUnlock("sub-pwd"), (err) => err.code === "BAD_PASSWORD");
|
|
49
|
+
await sub.tryUnlock("new-sub-pwd");
|
|
50
|
+
|
|
51
|
+
await ws.lock();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("HD account — round-trip across lock + reopen", async () => {
|
|
55
|
+
const root = mkdtempSync(join(tmpdir(), "wative-hd-reopen-"));
|
|
56
|
+
let ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
57
|
+
|
|
58
|
+
const acc = await ws.accounts.create("Persistent", "wsp-pwd", MNEMONIC);
|
|
59
|
+
await acc.deriveWallets(2);
|
|
60
|
+
const firstAddr = acc.wallets[0].addresses[0].publicKey;
|
|
61
|
+
|
|
62
|
+
await ws.lock();
|
|
63
|
+
|
|
64
|
+
ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
65
|
+
const reopened = ws.accounts.bySlug(acc.slug);
|
|
66
|
+
assert.ok(reopened);
|
|
67
|
+
assert.strictEqual(reopened.wallets.length, 3);
|
|
68
|
+
assert.strictEqual(reopened.wallets[0].addresses[0].publicKey, firstAddr);
|
|
69
|
+
|
|
70
|
+
await ws.lock();
|
|
71
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// 03 — PK account flows. Heterogeneous private keys, one wallet per import.
|
|
2
|
+
|
|
3
|
+
const test = require("node:test");
|
|
4
|
+
const assert = require("node:assert");
|
|
5
|
+
const { mkdtempSync } = require("node:fs");
|
|
6
|
+
const { tmpdir } = require("node:os");
|
|
7
|
+
const { join } = require("node:path");
|
|
8
|
+
|
|
9
|
+
const { Workspace } = require("wative-core");
|
|
10
|
+
|
|
11
|
+
const EVM_PK = "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d";
|
|
12
|
+
const SVM_PK = "xtGWcHvQsr5ue8zG2F5fm31bW8vyn597Y92gUWaZZg3S1Z6FeJMATL8KU3xJMGbLfALnokcct9y5wYtCRrwNXZW";
|
|
13
|
+
|
|
14
|
+
test("PK account — create from EVM key + import a Solana key", async () => {
|
|
15
|
+
const root = mkdtempSync(join(tmpdir(), "wative-pk-"));
|
|
16
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
17
|
+
|
|
18
|
+
const acc = await ws.accounts.create(
|
|
19
|
+
"External Hot Wallet",
|
|
20
|
+
"wsp-pwd",
|
|
21
|
+
EVM_PK,
|
|
22
|
+
undefined,
|
|
23
|
+
{ kind: "PK" },
|
|
24
|
+
);
|
|
25
|
+
assert.strictEqual(acc.organizationType, "PK");
|
|
26
|
+
assert.strictEqual(acc.wallets.length, 1);
|
|
27
|
+
assert.strictEqual(acc.wallets[0].addresses[0].vm, "evm");
|
|
28
|
+
|
|
29
|
+
await acc.importPrivateKey(SVM_PK, "svm");
|
|
30
|
+
assert.strictEqual(acc.wallets.length, 2);
|
|
31
|
+
assert.strictEqual(acc.wallets[1].addresses[0].vm, "svm");
|
|
32
|
+
|
|
33
|
+
await ws.lock();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("PK account — duplicate import is rejected", async () => {
|
|
37
|
+
const root = mkdtempSync(join(tmpdir(), "wative-pk-dup-"));
|
|
38
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
39
|
+
|
|
40
|
+
const acc = await ws.accounts.create("HotWallet", "wsp-pwd", EVM_PK, undefined, { kind: "PK" });
|
|
41
|
+
await assert.rejects(acc.importPrivateKey(EVM_PK, "evm"), (err) => err.code === "PARAMETER_ERROR");
|
|
42
|
+
|
|
43
|
+
await ws.lock();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("PK account — drop a wallet (account keeps at least one)", async () => {
|
|
47
|
+
const root = mkdtempSync(join(tmpdir(), "wative-pk-drop-"));
|
|
48
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
49
|
+
|
|
50
|
+
const acc = await ws.accounts.create("HotWallet", "wsp-pwd", EVM_PK, undefined, { kind: "PK" });
|
|
51
|
+
await acc.importPrivateKey(SVM_PK, "svm");
|
|
52
|
+
|
|
53
|
+
await acc.wallets.drop(acc.wallets[1]);
|
|
54
|
+
assert.strictEqual(acc.wallets.length, 1);
|
|
55
|
+
|
|
56
|
+
await assert.rejects(acc.wallets.drop(acc.wallets[0]), (err) => err.code === "UNSUPPORTED_OP");
|
|
57
|
+
|
|
58
|
+
await ws.lock();
|
|
59
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// 04 — Network management. Pre-loaded networks, add custom networks,
|
|
2
|
+
// override an existing network's RPC URL, drop user networks.
|
|
3
|
+
|
|
4
|
+
const test = require("node:test");
|
|
5
|
+
const assert = require("node:assert");
|
|
6
|
+
const { mkdtempSync } = require("node:fs");
|
|
7
|
+
const { tmpdir } = require("node:os");
|
|
8
|
+
const { join } = require("node:path");
|
|
9
|
+
|
|
10
|
+
const { Workspace, Network } = require("wative-core");
|
|
11
|
+
|
|
12
|
+
test("network — 10 pre-loaded networks ship at workspace open", async () => {
|
|
13
|
+
const root = mkdtempSync(join(tmpdir(), "wative-net-builtin-"));
|
|
14
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
15
|
+
|
|
16
|
+
const slugs = ws.networks.map((n) => n.slug).sort();
|
|
17
|
+
assert.deepStrictEqual(slugs, [
|
|
18
|
+
"arbitrum", "arbitrum-sepolia", "base", "bnbchain", "ethereum", "optimism",
|
|
19
|
+
"sepolia", "solana", "solana-devnet", "solana-testnet",
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
assert.strictEqual(Network.ArbitrumSepolia.chainId, 421614);
|
|
23
|
+
assert.strictEqual(Network.Ethereum.chainId, 1);
|
|
24
|
+
assert.strictEqual(Network.Solana.vm, "svm");
|
|
25
|
+
assert.strictEqual(ws.networks.bySlug("ethereum").chainId, 1);
|
|
26
|
+
assert.strictEqual(ws.networks.bySlug("arbitrum-sepolia").vm, "evm");
|
|
27
|
+
assert.strictEqual(ws.networks.byChainId(8453).slug, "base");
|
|
28
|
+
|
|
29
|
+
await ws.lock();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("network — add a brand-new user network", async () => {
|
|
33
|
+
const root = mkdtempSync(join(tmpdir(), "wative-net-add-"));
|
|
34
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
35
|
+
|
|
36
|
+
const monad = new Network({
|
|
37
|
+
slug: "monad-testnet",
|
|
38
|
+
name: "Monad Testnet",
|
|
39
|
+
chainId: 10143,
|
|
40
|
+
rpcUrl: "https://testnet-rpc.monad.xyz",
|
|
41
|
+
nativeCurrency: { name: "Monad", symbol: "MON", decimals: 18 },
|
|
42
|
+
vm: "evm",
|
|
43
|
+
});
|
|
44
|
+
await ws.networks.add(monad);
|
|
45
|
+
|
|
46
|
+
assert.strictEqual(ws.networks.length, 11);
|
|
47
|
+
assert.strictEqual(ws.networks.bySlug("monad-testnet").chainId, 10143);
|
|
48
|
+
await assert.rejects(ws.networks.add(monad), (err) => err.code === "PARAMETER_ERROR");
|
|
49
|
+
|
|
50
|
+
await ws.lock();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("network — override a pre-loaded RPC URL via update()", async () => {
|
|
54
|
+
const root = mkdtempSync(join(tmpdir(), "wative-net-override-"));
|
|
55
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
56
|
+
|
|
57
|
+
const eth = ws.networks.bySlug("ethereum");
|
|
58
|
+
const customEth = new Network({
|
|
59
|
+
...eth,
|
|
60
|
+
rpcUrl: "https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY",
|
|
61
|
+
});
|
|
62
|
+
await ws.networks.update(customEth);
|
|
63
|
+
|
|
64
|
+
assert.strictEqual(
|
|
65
|
+
ws.networks.bySlug("ethereum").rpcUrl,
|
|
66
|
+
"https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY",
|
|
67
|
+
);
|
|
68
|
+
assert.strictEqual(ws.networks.length, 10);
|
|
69
|
+
|
|
70
|
+
await ws.lock();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("network — drop user network; pre-loaded networks reject drop", async () => {
|
|
74
|
+
const root = mkdtempSync(join(tmpdir(), "wative-net-drop-"));
|
|
75
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
76
|
+
|
|
77
|
+
const custom = new Network({
|
|
78
|
+
slug: "my-net",
|
|
79
|
+
name: "My Net",
|
|
80
|
+
chainId: 99999,
|
|
81
|
+
rpcUrl: "https://rpc.example",
|
|
82
|
+
nativeCurrency: { name: "Foo", symbol: "FOO", decimals: 18 },
|
|
83
|
+
vm: "evm",
|
|
84
|
+
});
|
|
85
|
+
await ws.networks.add(custom);
|
|
86
|
+
|
|
87
|
+
await ws.networks.drop(custom);
|
|
88
|
+
assert.strictEqual(ws.networks.bySlug("my-net"), null);
|
|
89
|
+
|
|
90
|
+
const eth = ws.networks.bySlug("ethereum");
|
|
91
|
+
await assert.rejects(ws.networks.drop(eth), (err) => err.code === "UNSUPPORTED_OP");
|
|
92
|
+
|
|
93
|
+
await ws.lock();
|
|
94
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// 05 — Asset management. Pre-loaded tokens, add custom tokens,
|
|
2
|
+
// drop user tokens, search via filter.
|
|
3
|
+
|
|
4
|
+
const test = require("node:test");
|
|
5
|
+
const assert = require("node:assert");
|
|
6
|
+
const { mkdtempSync } = require("node:fs");
|
|
7
|
+
const { tmpdir } = require("node:os");
|
|
8
|
+
const { join } = require("node:path");
|
|
9
|
+
|
|
10
|
+
const { Workspace, Network, Asset } = require("wative-core");
|
|
11
|
+
|
|
12
|
+
test("asset — pre-loaded tokens per network", async () => {
|
|
13
|
+
const root = mkdtempSync(join(tmpdir(), "wative-asset-builtin-"));
|
|
14
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
15
|
+
|
|
16
|
+
const ethAssets = await ws.assets(Network.Ethereum);
|
|
17
|
+
assert.deepStrictEqual(ethAssets.map((a) => a.symbol).sort(), ["ETH", "USDC", "USDT", "WETH"]);
|
|
18
|
+
|
|
19
|
+
const solAssets = await ws.assets(Network.Solana);
|
|
20
|
+
assert.deepStrictEqual(solAssets.map((a) => a.symbol).sort(), ["SOL", "USDC", "USDT", "WSOL"]);
|
|
21
|
+
|
|
22
|
+
const sepoliaAssets = await ws.assets("sepolia");
|
|
23
|
+
assert.strictEqual(sepoliaAssets.length, 1);
|
|
24
|
+
|
|
25
|
+
const arbSepoliaAssets = await ws.assets("arbitrum-sepolia");
|
|
26
|
+
const arbSepoliaUsdc = arbSepoliaAssets.find((a) => a.symbol === "USDC");
|
|
27
|
+
assert.ok(arbSepoliaUsdc);
|
|
28
|
+
assert.strictEqual(arbSepoliaUsdc.decimals, 6);
|
|
29
|
+
assert.strictEqual(arbSepoliaUsdc.contractAddress, "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d");
|
|
30
|
+
assert.strictEqual(arbSepoliaUsdc.native, false);
|
|
31
|
+
|
|
32
|
+
await ws.lock();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("asset — add a custom user token", async () => {
|
|
36
|
+
const root = mkdtempSync(join(tmpdir(), "wative-asset-add-"));
|
|
37
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
38
|
+
|
|
39
|
+
const pepe = new Asset({
|
|
40
|
+
id: 200,
|
|
41
|
+
symbol: "PEPE",
|
|
42
|
+
name: "Pepe",
|
|
43
|
+
decimals: 18,
|
|
44
|
+
contractAddress: "0x6982508145454Ce325dDbE47a25d4ec3d2311933",
|
|
45
|
+
network: Network.Ethereum,
|
|
46
|
+
});
|
|
47
|
+
await ws.addAsset(pepe);
|
|
48
|
+
|
|
49
|
+
const ethAssets = await ws.assets(Network.Ethereum);
|
|
50
|
+
assert.strictEqual(ethAssets.length, 5);
|
|
51
|
+
assert.ok(ethAssets.some((a) => a.id === 200 && a.symbol === "PEPE"));
|
|
52
|
+
|
|
53
|
+
await ws.lock();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("asset — id and address collisions are rejected", async () => {
|
|
57
|
+
const root = mkdtempSync(join(tmpdir(), "wative-asset-collide-"));
|
|
58
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
59
|
+
|
|
60
|
+
const dupId = new Asset({
|
|
61
|
+
id: 1,
|
|
62
|
+
symbol: "FAKE",
|
|
63
|
+
name: "Fake",
|
|
64
|
+
decimals: 18,
|
|
65
|
+
contractAddress: "0x1234567890123456789012345678901234567890",
|
|
66
|
+
network: Network.Ethereum,
|
|
67
|
+
});
|
|
68
|
+
await assert.rejects(ws.addAsset(dupId), (err) => err.code === "PARAMETER_ERROR");
|
|
69
|
+
|
|
70
|
+
const dupAddr = new Asset({
|
|
71
|
+
id: 201,
|
|
72
|
+
symbol: "USDC2",
|
|
73
|
+
name: "Other USDC",
|
|
74
|
+
decimals: 6,
|
|
75
|
+
contractAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
76
|
+
network: Network.Ethereum,
|
|
77
|
+
});
|
|
78
|
+
await assert.rejects(ws.addAsset(dupAddr), (err) => err.code === "PARAMETER_ERROR");
|
|
79
|
+
|
|
80
|
+
await ws.lock();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("asset — drop user token; pre-loaded tokens reject drop", async () => {
|
|
84
|
+
const root = mkdtempSync(join(tmpdir(), "wative-asset-drop-"));
|
|
85
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
86
|
+
|
|
87
|
+
const my = new Asset({
|
|
88
|
+
id: 300,
|
|
89
|
+
symbol: "MINE",
|
|
90
|
+
name: "Mine",
|
|
91
|
+
decimals: 18,
|
|
92
|
+
contractAddress: "0x1111111111111111111111111111111111111111",
|
|
93
|
+
network: Network.Ethereum,
|
|
94
|
+
});
|
|
95
|
+
await ws.addAsset(my);
|
|
96
|
+
await ws.dropAsset(300);
|
|
97
|
+
|
|
98
|
+
const ethAssets = await ws.assets(Network.Ethereum);
|
|
99
|
+
assert.ok(!ethAssets.some((a) => a.id === 300));
|
|
100
|
+
|
|
101
|
+
await assert.rejects(ws.dropAsset(1), (err) => err.code === "UNSUPPORTED_OP");
|
|
102
|
+
|
|
103
|
+
await ws.lock();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("asset — workspace.filter('Asset', q) finds by symbol or contract address", async () => {
|
|
107
|
+
const root = mkdtempSync(join(tmpdir(), "wative-asset-filter-"));
|
|
108
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
109
|
+
|
|
110
|
+
const bySymbol = await ws.filter("USDC", "Asset");
|
|
111
|
+
assert.ok(bySymbol && bySymbol.symbol === "USDC");
|
|
112
|
+
|
|
113
|
+
const byAddr = await ws.filter("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "Asset");
|
|
114
|
+
assert.ok(byAddr && byAddr.symbol === "USDC");
|
|
115
|
+
|
|
116
|
+
await ws.lock();
|
|
117
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// 06 — Address signing. Sign personal messages and build transactions
|
|
2
|
+
// fully offline.
|
|
3
|
+
|
|
4
|
+
const test = require("node:test");
|
|
5
|
+
const assert = require("node:assert");
|
|
6
|
+
const { mkdtempSync } = require("node:fs");
|
|
7
|
+
const { tmpdir } = require("node:os");
|
|
8
|
+
const { join } = require("node:path");
|
|
9
|
+
|
|
10
|
+
const { Workspace, Network } = require("wative-core");
|
|
11
|
+
|
|
12
|
+
const MNEMONIC =
|
|
13
|
+
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
|
|
14
|
+
|
|
15
|
+
test("address — signMessage on EVM and SVM", async () => {
|
|
16
|
+
const root = mkdtempSync(join(tmpdir(), "wative-sign-msg-"));
|
|
17
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
18
|
+
|
|
19
|
+
const acc = await ws.accounts.create("Desk", "wsp-pwd", MNEMONIC);
|
|
20
|
+
const evm = acc.wallets[0].addresses.find((a) => a.vm === "evm");
|
|
21
|
+
const svm = acc.wallets[0].addresses.find((a) => a.vm === "svm");
|
|
22
|
+
|
|
23
|
+
const evmSig = evm.signMessage("hello");
|
|
24
|
+
const svmSig = svm.signMessage("hello");
|
|
25
|
+
|
|
26
|
+
assert.ok(typeof evmSig === "string" && evmSig.startsWith("0x"));
|
|
27
|
+
assert.ok(typeof svmSig === "string" && svmSig.length > 0);
|
|
28
|
+
assert.notStrictEqual(evmSig, svmSig);
|
|
29
|
+
|
|
30
|
+
await ws.lock();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("address — buildTransaction convenience helper (offline)", async () => {
|
|
34
|
+
const root = mkdtempSync(join(tmpdir(), "wative-build-tx-"));
|
|
35
|
+
const ws = await Workspace.open({ path: root, password: "wsp-pwd" });
|
|
36
|
+
|
|
37
|
+
const acc = await ws.accounts.create("Desk", "wsp-pwd", MNEMONIC);
|
|
38
|
+
const evm = acc.wallets[0].addresses.find((a) => a.vm === "evm");
|
|
39
|
+
|
|
40
|
+
const tx = await evm.buildTransaction({
|
|
41
|
+
to: "0x1234567890123456789012345678901234567890",
|
|
42
|
+
value: 1_000_000_000_000_000n,
|
|
43
|
+
chainId: 1,
|
|
44
|
+
nonce: 0,
|
|
45
|
+
gasLimit: 21000n,
|
|
46
|
+
maxFeePerGas: 50_000_000_000n,
|
|
47
|
+
maxPriorityFeePerGas: 1_000_000_000n,
|
|
48
|
+
type: 2,
|
|
49
|
+
network: Network.Ethereum,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
assert.strictEqual(tx.from.toLowerCase(), evm.publicKey.toLowerCase());
|
|
53
|
+
|
|
54
|
+
await ws.lock();
|
|
55
|
+
});
|