@mybucks.online/core 1.0.2 → 1.0.4
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/README.md +20 -2
- package/index.js +53 -14
- package/package.json +8 -2
- package/test/index.test.js +45 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @mybucks.online/core
|
|
2
2
|
|
|
3
|
-
This is a core part of [mybucks.online](https://mybucks.online) crypto wallet, involving
|
|
3
|
+
This is a core part of [mybucks.online](https://mybucks.online) crypto wallet, involving hash and private key generation, generate and parse transfer-link token.
|
|
4
4
|
|
|
5
5
|
## mybucks.online
|
|
6
6
|
|
|
@@ -33,6 +33,21 @@ const privateKey = getEvmPrivateKey(hash);
|
|
|
33
33
|
console.log("Private key: ", privateKey);
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
### 3. Generate and parse (transfer-link's)token
|
|
37
|
+
```javascript
|
|
38
|
+
import { generateToken } from "@mybucks.online/core";
|
|
39
|
+
const token = generateToken(password, passcode, network);
|
|
40
|
+
|
|
41
|
+
console.log("https://app.mybucks.online?wallet=" + token);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
import { parseToken } from "@mybucks.online/core";
|
|
46
|
+
const [password, passcode, network] = parseToken(token);
|
|
47
|
+
console.log("Account credentials are: ", password, passcode);
|
|
48
|
+
console.log("Network: ", network);
|
|
49
|
+
```
|
|
50
|
+
|
|
36
51
|
## Test
|
|
37
52
|
```bash
|
|
38
53
|
npm run test
|
|
@@ -45,4 +60,7 @@ Find the docs [here](https://docs.mybucks.online).
|
|
|
45
60
|
## Live example
|
|
46
61
|
|
|
47
62
|
- https://github.com/mybucks.online/app
|
|
48
|
-
- https://app.mybucks.online
|
|
63
|
+
- https://app.mybucks.online
|
|
64
|
+
password: **DemoAccount5&**
|
|
65
|
+
passcode: **112324**
|
|
66
|
+
- https://app.mybucks.online/?wallet=VWnsSGRGVtb0FjY291bnQ1JgIxMTIzMjQCb3B0aW1pc20=_wNovT
|
package/index.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Buffer } from "buffer";
|
|
2
|
+
import { ethers } from "ethers";
|
|
3
|
+
import scryptJS from "scrypt-js";
|
|
4
|
+
import { nanoid } from "nanoid";
|
|
4
5
|
|
|
6
|
+
const { scrypt } = scryptJS;
|
|
5
7
|
const abi = new ethers.AbiCoder();
|
|
6
8
|
|
|
7
|
-
/**
|
|
8
|
-
* [CRITICAL] DON'T CHANGE FOREVER!!!
|
|
9
|
-
* Reference:
|
|
10
|
-
* https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#scrypt
|
|
11
|
-
*/
|
|
12
9
|
const HASH_OPTIONS = {
|
|
13
10
|
N: 32768, // CPU/memory cost parameter, 2^15
|
|
14
11
|
r: 8, // block size parameter
|
|
@@ -24,7 +21,7 @@ const HASH_OPTIONS = {
|
|
|
24
21
|
* @param {*} cb a callback function designed to receive the progress updates during the scrypt hashing process.
|
|
25
22
|
* @returns hash result as string format
|
|
26
23
|
*/
|
|
27
|
-
async function generateHash(password, passcode, cb = () => {}) {
|
|
24
|
+
export async function generateHash(password, passcode, cb = () => {}) {
|
|
28
25
|
if (!password || !passcode) {
|
|
29
26
|
return "";
|
|
30
27
|
}
|
|
@@ -52,11 +49,53 @@ async function generateHash(password, passcode, cb = () => {}) {
|
|
|
52
49
|
* @param {*} hash
|
|
53
50
|
* @returns private key as string format
|
|
54
51
|
*/
|
|
55
|
-
function getEvmPrivateKey(hash) {
|
|
52
|
+
export function getEvmPrivateKey(hash) {
|
|
56
53
|
return ethers.keccak256(abi.encode(["string"], [hash]));
|
|
57
54
|
}
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
const URL_DELIMITER = "\u0002";
|
|
57
|
+
const NETWORKS = [
|
|
58
|
+
"ethereum",
|
|
59
|
+
"polygon",
|
|
60
|
+
"arbitrum",
|
|
61
|
+
"optimism",
|
|
62
|
+
"bsc",
|
|
63
|
+
"avalanche",
|
|
64
|
+
"tron",
|
|
65
|
+
];
|
|
66
|
+
/**
|
|
67
|
+
* This function generates a transfer-link by combining credentials and randomly generated padding.
|
|
68
|
+
* The transfer-link introduces a nice feature that enables the transfer of full ownership of a wallet account.
|
|
69
|
+
* @param {*} password
|
|
70
|
+
* @param {*} passcode
|
|
71
|
+
* @param {*} network ethereum | polygon | arbitrum | optimism | bsc | avalanche | tron
|
|
72
|
+
* @returns A string formatted as a transfer-link token, which can be appended to `https://app.mybucks.online?wallet=`
|
|
73
|
+
*/
|
|
74
|
+
export function generateToken(password, passcode, network) {
|
|
75
|
+
if (!password || !passcode || !network) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
if (!NETWORKS.find((n) => n === network)) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const merged = Buffer.from(
|
|
83
|
+
password + URL_DELIMITER + passcode + URL_DELIMITER + network,
|
|
84
|
+
"utf-8"
|
|
85
|
+
);
|
|
86
|
+
const base64Encoded = merged.toString("base64");
|
|
87
|
+
const padding = nanoid(12);
|
|
88
|
+
return padding.slice(0, 6) + base64Encoded + padding.slice(6);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* This function parses a transfer-link token generated by generateToken().
|
|
93
|
+
* @param {*} token
|
|
94
|
+
* @returns an array of strings, including the password, passcode and network.
|
|
95
|
+
*/
|
|
96
|
+
export function parseToken(token) {
|
|
97
|
+
const payload = token.slice(6, token.length - 6);
|
|
98
|
+
const base64Decoded = Buffer.from(payload, "base64").toString("utf-8");
|
|
99
|
+
const [password, passcode, network] = base64Decoded.split(URL_DELIMITER);
|
|
100
|
+
return [password, passcode, network];
|
|
101
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mybucks.online/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Core module for mybucks.online crypto wallet",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"scripts": {
|
|
7
8
|
"test": "node test/index.test.js"
|
|
8
9
|
},
|
|
@@ -19,7 +20,11 @@
|
|
|
19
20
|
"browser-based",
|
|
20
21
|
"ethereum",
|
|
21
22
|
"tron",
|
|
22
|
-
"
|
|
23
|
+
"scrypt",
|
|
24
|
+
"keccak256",
|
|
25
|
+
"key-generation",
|
|
26
|
+
"open-source",
|
|
27
|
+
"mybucks.online"
|
|
23
28
|
],
|
|
24
29
|
"author": "koko37",
|
|
25
30
|
"license": "MIT",
|
|
@@ -30,6 +35,7 @@
|
|
|
30
35
|
"dependencies": {
|
|
31
36
|
"buffer": "^6.0.3",
|
|
32
37
|
"ethers": "^6.13.5",
|
|
38
|
+
"nanoid": "^5.0.9",
|
|
33
39
|
"scrypt-js": "^3.0.1"
|
|
34
40
|
}
|
|
35
41
|
}
|
package/test/index.test.js
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { describe, test } from "node:test";
|
|
3
|
+
import {
|
|
4
|
+
generateHash,
|
|
5
|
+
getEvmPrivateKey,
|
|
6
|
+
generateToken,
|
|
7
|
+
parseToken,
|
|
8
|
+
} from "../index.js";
|
|
4
9
|
|
|
5
10
|
const DEMO_PASSWORD = "DemoAccount5&";
|
|
6
11
|
const DEMO_PASSCODE = "112324";
|
|
12
|
+
const DEMO_NETWORK = "optimism";
|
|
7
13
|
const DEMO_HASH =
|
|
8
14
|
"af9a22d75f8f69d33fe8fc294e8f413219d9c75374dec07fda2e4a66868599609887a10e04981e17356d2c07432fc89c11089172fdf91c0015b9a4beef11e447";
|
|
9
15
|
const DEMO_PRIVATE_KEY =
|
|
10
16
|
"0x71743de900c63ed741263a2a4513c1b1829e80bd9f18d5d3a593e651b914cb3b";
|
|
17
|
+
const DEMO_TOKEN =
|
|
18
|
+
"VWnsSGRGVtb0FjY291bnQ1JgIxMTIzMjQCb3B0aW1pc20=_wNovT";
|
|
11
19
|
|
|
12
20
|
describe("generateHash", () => {
|
|
13
21
|
test("should return empty string if password or passcode is blank", async () => {
|
|
@@ -29,3 +37,37 @@ describe("getEvmPrivateKey", () => {
|
|
|
29
37
|
assert.strictEqual(privateKey, DEMO_PRIVATE_KEY);
|
|
30
38
|
});
|
|
31
39
|
});
|
|
40
|
+
|
|
41
|
+
describe("generateToken", () => {
|
|
42
|
+
test("should return null if password, passcode or network is invalid", async () => {
|
|
43
|
+
assert.strictEqual(generateToken("", "123345", "ethereum"), null);
|
|
44
|
+
assert.strictEqual(generateToken("", "123345"), null);
|
|
45
|
+
assert.strictEqual(generateToken("password", "", "ethereum"), null);
|
|
46
|
+
assert.strictEqual(generateToken("password", "123456", ""), null);
|
|
47
|
+
assert.strictEqual(generateToken("password", "123456", "invalid"), null);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe("parseToken", () => {
|
|
52
|
+
test("should return array of password, passcode, and network", () => {
|
|
53
|
+
const [password, passcode, network] = parseToken(DEMO_TOKEN);
|
|
54
|
+
|
|
55
|
+
assert.strictEqual(password, DEMO_PASSWORD);
|
|
56
|
+
assert.strictEqual(passcode, DEMO_PASSCODE);
|
|
57
|
+
assert.strictEqual(network, DEMO_NETWORK);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("generateToken and parseToken", () => {
|
|
62
|
+
test("should be compatible and return correct result", () => {
|
|
63
|
+
const testPassword = "random^Password9";
|
|
64
|
+
const testPasscode = "909011";
|
|
65
|
+
const testNetwork = "polygon";
|
|
66
|
+
const token = generateToken(testPassword, testPasscode, testNetwork);
|
|
67
|
+
|
|
68
|
+
const [password, passcode, network] = parseToken(token);
|
|
69
|
+
assert.strictEqual(password, testPassword);
|
|
70
|
+
assert.strictEqual(passcode, testPasscode);
|
|
71
|
+
assert.strictEqual(network, testNetwork);
|
|
72
|
+
});
|
|
73
|
+
});
|