@tomo-inc/wallet-utils 0.0.2

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 ADDED
@@ -0,0 +1,3 @@
1
+ # @tomo-inc/wallet-utils
2
+
3
+ ## 0.0.1
package/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # @tomo-inc/wallet-utils
2
+
3
+ ## Plan
4
+
5
+ 1. string: uuid, encrypt
6
+ 2. number: transform, format
7
+ 3. date
8
+ 4. email
9
+ 5. password
10
+ 6. seed phrase
11
+ 7. address
12
+ 8. cache: broswer, chrome
13
+ 9. sign message validator
14
+ 10. message
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@tomo-inc/wallet-utils",
3
+ "version": "0.0.2",
4
+ "author": "tomo.inc",
5
+ "license": "MIT",
6
+ "private": false,
7
+ "type": "module",
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ }
17
+ },
18
+ "dependencies": {
19
+ "uuid": "13.0.0"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^20.0.0",
23
+ "tsup": "^8.0.0",
24
+ "typescript": "^5.0.0",
25
+ "vitest": "^3.2.4"
26
+ },
27
+ "scripts": {
28
+ "build": "tsup"
29
+ }
30
+ }
package/project.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "wallet-utils",
3
+ "sourceRoot": "packages/wallet-utils/src",
4
+ "projectType": "library",
5
+ "targets": {
6
+ "build": {
7
+ "executor": "nx:run-commands",
8
+ "outputs": ["{projectRoot}/dist"],
9
+ "options": {
10
+ "command": "tsup src/index.ts --format esm,cjs --dts --treeshake",
11
+ "cwd": "packages/wallet-utils"
12
+ }
13
+ },
14
+ "dev": {
15
+ "executor": "nx:run-commands",
16
+ "options": {
17
+ "command": "tsup src/index.ts --format esm,cjs --watch --dts",
18
+ "cwd": "packages/wallet-utils"
19
+ }
20
+ },
21
+ "lint": {
22
+ "executor": "nx:run-commands",
23
+ "options": {
24
+ "command": "eslint src/**/*.ts",
25
+ "cwd": "packages/wallet-utils"
26
+ }
27
+ },
28
+ "lint:fix": {
29
+ "executor": "nx:run-commands",
30
+ "options": {
31
+ "command": "eslint src/**/*.ts --fix",
32
+ "cwd": "packages/wallet-utils"
33
+ }
34
+ },
35
+ "format": {
36
+ "executor": "nx:run-commands",
37
+ "options": {
38
+ "command": "prettier --write \"src/**/*.{ts,tsx}\"",
39
+ "cwd": "packages/wallet-utils"
40
+ }
41
+ },
42
+ "test": {
43
+ "executor": "nx:run-commands",
44
+ "outputs": ["{projectRoot}/coverage"],
45
+ "options": {
46
+ "command": "vitest run",
47
+ "cwd": "packages/wallet-utils"
48
+ }
49
+ },
50
+ "test:watch": {
51
+ "executor": "nx:run-commands",
52
+ "options": {
53
+ "command": "vitest",
54
+ "cwd": "packages/wallet-utils"
55
+ }
56
+ }
57
+ },
58
+ "tags": ["npm:public", "scope:wallet-utils", "type:library"]
59
+ }
package/src/broswer.ts ADDED
@@ -0,0 +1,38 @@
1
+ export const getBrowserName = (): string => {
2
+ if (typeof window === "undefined") {
3
+ return "";
4
+ }
5
+
6
+ const userAgent = window.navigator.userAgent;
7
+
8
+ // Safari (must be checked before Chrome as Chrome also includes Safari in userAgent)
9
+ if (userAgent.includes("Safari/") && !userAgent.includes("Chrome/")) {
10
+ return "Safari";
11
+ }
12
+
13
+ if (userAgent.includes("Edg/")) {
14
+ return "Edge";
15
+ }
16
+
17
+ if (userAgent.includes("Firefox/")) {
18
+ return "Firefox";
19
+ }
20
+
21
+ // Chrome (check after other Chromium-based browsers)
22
+ if (userAgent.includes("Chrome/")) {
23
+ return "Chrome";
24
+ }
25
+
26
+ const brave = (window.navigator as any)?.brave;
27
+ if (brave?.isBrave?.()) {
28
+ return "Brave";
29
+ }
30
+
31
+ // Opera
32
+ if (userAgent.includes("Opera/") || userAgent.includes("OPR/")) {
33
+ return "Opera";
34
+ }
35
+
36
+ // Default fallback
37
+ return "";
38
+ };
package/src/cache.ts ADDED
@@ -0,0 +1,120 @@
1
+ /*
2
+ 1: JSON.stringfy --> set --> get --> JSON.parse
3
+ 2: data format well return as set`s
4
+ 3: undefined in array will be null after stringfy+parse
5
+ 4: NS --> namespace
6
+ */
7
+
8
+ //key += account id
9
+ let keyNS = "tomo-";
10
+
11
+ function get(key: string) {
12
+ /*
13
+ legal data: "" [] {} null flase true
14
+
15
+ illegal: undefined
16
+ 1: key not set
17
+ 2: key is cleared
18
+ 3: key removed
19
+ 4: wrong data format
20
+ */
21
+ // Check if we're in a browser environment
22
+ if (typeof window === "undefined") {
23
+ return null;
24
+ }
25
+
26
+ const tempKey = keyNS + key;
27
+ if (!isKeyExist(tempKey)) {
28
+ return null;
29
+ }
30
+ // maybe keyNS could avoid conflict
31
+ let val: { data: any; type: string } | null = null;
32
+ try {
33
+ const data: any = window.localStorage.getItem(tempKey) || window.sessionStorage.getItem(tempKey);
34
+ val = JSON.parse(data);
35
+ } catch (err) {
36
+ console.error(err);
37
+ }
38
+ // val format check
39
+ if (
40
+ val !== null &&
41
+ Object.prototype.hasOwnProperty.call(val, "type") &&
42
+ Object.prototype.hasOwnProperty.call(val, "data")
43
+ ) {
44
+ return val["data"];
45
+ }
46
+ return null;
47
+ }
48
+ // isPersistent
49
+ function set(key: string, val: any, isTemp: boolean) {
50
+ // Check if we're in a browser environment
51
+ if (typeof window === "undefined") {
52
+ return false;
53
+ }
54
+
55
+ let store;
56
+ if (isTemp) {
57
+ store = window.sessionStorage;
58
+ } else {
59
+ store = window.localStorage;
60
+ }
61
+
62
+ const data = JSON.stringify({
63
+ data: val,
64
+ time: new Date().getTime(), //for manage by time limit
65
+ type: typeof val,
66
+ });
67
+ try {
68
+ store.setItem(keyNS + key, data);
69
+ return true;
70
+ } catch (err: any) {
71
+ if (err?.name?.toUpperCase().indexOf("QUOTA") >= 0) {
72
+ window.localStorage.clear();
73
+ store.setItem(keyNS + key, data);
74
+ }
75
+ }
76
+ return false;
77
+ }
78
+
79
+ function remove(key: string) {
80
+ // Check if we're in a browser environment
81
+ if (typeof window === "undefined") {
82
+ return;
83
+ }
84
+
85
+ const tempKey = keyNS + key;
86
+ window.localStorage.removeItem(tempKey);
87
+ window.sessionStorage.removeItem(tempKey);
88
+ }
89
+
90
+ function clear() {
91
+ // Check if we're in a browser environment
92
+ if (typeof window === "undefined") {
93
+ return;
94
+ }
95
+
96
+ window?.localStorage?.clear();
97
+ window?.sessionStorage?.clear();
98
+ }
99
+
100
+ function isKeyExist(key: string) {
101
+ // Check if we're in a browser environment
102
+ if (typeof window === "undefined") {
103
+ return false;
104
+ }
105
+
106
+ // do not depend on value cause of "",0
107
+ return (
108
+ Object.prototype.hasOwnProperty.call(window.localStorage, key) ||
109
+ Object.prototype.hasOwnProperty.call(window.sessionStorage, key)
110
+ );
111
+ }
112
+
113
+ function setKeyNS(NS: string) {
114
+ const isString = typeof NS === "string";
115
+ if (isString && NS !== "") {
116
+ keyNS = NS;
117
+ }
118
+ }
119
+
120
+ export { clear, get, remove, set, setKeyNS };
package/src/email.ts ADDED
@@ -0,0 +1,26 @@
1
+ export const maskEmail = (email: string) => {
2
+ if (!email) {
3
+ return;
4
+ }
5
+ const parts = email.split("@");
6
+
7
+ if (parts.length === 2) {
8
+ let username = parts[0];
9
+ const domain = parts[1];
10
+
11
+ if (username.length >= 4) {
12
+ username = username.slice(0, -3) + "***";
13
+ } else {
14
+ username = username + "*".repeat(4 - username.length);
15
+ }
16
+
17
+ const maskedEmail = `${username}@${domain}`;
18
+ return maskedEmail;
19
+ } else {
20
+ return null;
21
+ }
22
+ };
23
+
24
+ export const isEmail = (email: string) => {
25
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
26
+ };
@@ -0,0 +1,79 @@
1
+ export enum ChainTypes {
2
+ BTC = "btc",
3
+ DOGE = "doge",
4
+ EVM = "evm",
5
+ SOL = "sol",
6
+ SUI = "sui",
7
+ TON = "ton",
8
+ TRON = "tron",
9
+ COSMOS = "cosmos",
10
+ APTOS = "aptos",
11
+ }
12
+
13
+ interface ChainTypeConfig {
14
+ chainId?: string;
15
+ chainIndex?: number;
16
+ support: boolean;
17
+ gasFee: number;
18
+ dust: number;
19
+ reserve?: number;
20
+ }
21
+
22
+ export const SupportedChainTypes: Record<ChainTypes, ChainTypeConfig> = {
23
+ [ChainTypes.DOGE]: {
24
+ chainId: "3",
25
+ chainIndex: 300,
26
+ support: true,
27
+ gasFee: 0.5,
28
+ dust: 0.0001,
29
+ },
30
+ [ChainTypes.EVM]: {
31
+ chainId: "1",
32
+ chainIndex: 100,
33
+ support: true,
34
+ gasFee: 0.00001,
35
+ dust: 0,
36
+ },
37
+ [ChainTypes.SOL]: {
38
+ chainId: "501",
39
+ chainIndex: 50100,
40
+ support: true,
41
+ gasFee: 0.0001,
42
+ dust: 0,
43
+ reserve: 0.0009, // Available balance = Total balance - Reserve balance (for rent exemption)
44
+ },
45
+ [ChainTypes.TRON]: {
46
+ chainId: "19484",
47
+ chainIndex: 1948400,
48
+ support: true,
49
+ gasFee: 0.5,
50
+ dust: 0,
51
+ },
52
+ [ChainTypes.BTC]: {
53
+ chainId: "0", //livenet
54
+ chainIndex: 0,
55
+ support: false,
56
+ gasFee: 0.00001,
57
+ dust: 0.0001,
58
+ },
59
+ [ChainTypes.SUI]: {
60
+ support: false,
61
+ gasFee: 0,
62
+ dust: 0,
63
+ },
64
+ [ChainTypes.TON]: {
65
+ support: false,
66
+ gasFee: 0,
67
+ dust: 0,
68
+ },
69
+ [ChainTypes.COSMOS]: {
70
+ support: false,
71
+ gasFee: 0,
72
+ dust: 0,
73
+ },
74
+ [ChainTypes.APTOS]: {
75
+ support: false,
76
+ gasFee: 0,
77
+ dust: 0,
78
+ },
79
+ };
package/src/index.ts ADDED
@@ -0,0 +1,34 @@
1
+ import * as cache from "./cache";
2
+ export { cache };
3
+
4
+ export * from "./broswer";
5
+ export * from "./email";
6
+ export * from "./global-config";
7
+ export * from "./password";
8
+ export * from "./string";
9
+
10
+ export type TomoStage = "prod" | "pre" | "dev";
11
+ export type CubeStage = "gamma" | "prod";
12
+ export const CubeStages = {
13
+ prod: "prod",
14
+ pre: "prod",
15
+ dev: "gamma",
16
+ };
17
+
18
+ export const CubeOrgIds = {
19
+ prod: "Org#49944bce-9daf-423f-a982-269f6d0d301b",
20
+ pre: "Org#71c13f6d-b992-4660-874d-2ae0fadc789f",
21
+ dev: "Org#3d07a75a-1188-4bd0-acfa-671a198b83eb",
22
+ };
23
+
24
+ export const RelayOrigins = {
25
+ prod: "https://social-relay.tomo.inc",
26
+ pre: "https://social-relay.tomo.inc",
27
+ dev: "https://social-relay-dev.tomo.inc",
28
+ };
29
+
30
+ export const TomoApiDomains = {
31
+ prod: "https://wallet-pro.tomo.inc",
32
+ pre: "https://wallet-pre-wlfi.tomo.inc",
33
+ dev: "https://wallet-test.tomo.inc",
34
+ };
@@ -0,0 +1,6 @@
1
+ export const validatePassword = (password: string) => {
2
+ const lengthValid = password.length >= 8 && password.length <= 32;
3
+ const hasLetter = /[a-zA-Z]/.test(password);
4
+ const hasNumber = /[0-9]/.test(password);
5
+ return lengthValid && hasLetter && hasNumber;
6
+ };
package/src/string.ts ADDED
@@ -0,0 +1,88 @@
1
+ export function stripHexPrefix(str: string) {
2
+ if (typeof str !== "string") {
3
+ return str;
4
+ }
5
+ return str.startsWith("0x") ? str.slice(2) : str;
6
+ }
7
+
8
+ export function compareString(a: string, b: string) {
9
+ return a.toLowerCase() === b.toLowerCase();
10
+ }
11
+
12
+ export function subs(temp: string, data: any, regexp?: RegExp) {
13
+ if (!(Object.prototype.toString.call(data) === "[object Array]")) data = [data];
14
+ const ret = [];
15
+ for (let i = 0, j = data.length; i < j; i++) {
16
+ ret.push(replaceAction(data[i]));
17
+ }
18
+ return ret.join("");
19
+ function replaceAction(object: any) {
20
+ return temp.replace(regexp || /\\?\{([^}]+)\}/g, function (match, name) {
21
+ if (match.charAt(0) == "\\") return match.slice(1);
22
+ return object[name] != undefined ? object[name] : "";
23
+ });
24
+ }
25
+ }
26
+
27
+ export function getExplorerUrl(chainIndex: number, data: { txId: string }) {
28
+ const linkTpls = {
29
+ "0": "",
30
+ "100": "https://etherscan.io/tx/{txId}",
31
+ "300": "https://dogechain.info/tx/{txId}",
32
+ "400": "",
33
+ "1000": "https://optimistic.etherscan.io/tx/{txId}",
34
+ "5600": "https://bscscan.com/tx/{txId}",
35
+ "12600": "https://explorer.movementnetwork.xyz/txn/{txId}?network=mainnet",
36
+ "13700": "https://polygonscan.com/tx/{txId}",
37
+ "20400": "https://opbnb.bscscan.com/tx/{txId}",
38
+ "22300": "https://explorer.bsquared.network/tx/{txId}",
39
+ "22700": "https://promscan.io/tx/{txId}",
40
+ "32400": "https://mainnet.era.zksync.io/tx/{txId}",
41
+ "48000": "https://worldchain-mainnet.explorer.alchemy.com/tx/{txId}",
42
+ "50100": "https://solscan.io/tx/{txId}",
43
+ "78400": "",
44
+ "110000": "",
45
+ "132900": "https://seitrace.com/tx/{txId}",
46
+ "151400": "https://mainnet.storyscan.xyz/tx/{txId}",
47
+ "162500": "https://explorer.gravity.xyz/tx/{txId}",
48
+ "264900": "https://mainnet-explorer.ailayer.xyz/tx/{txId}",
49
+ "420000": "https://scan.merlinchain.io/tx/{txId}",
50
+ "554500": "https://scan.duckchain.io/tx/{txId}",
51
+ "833300": "https://mainnet-rpc.b3.fun/http/tx/{txId}",
52
+ "845300": "https://base.blockscout.com/tx/{txId}",
53
+ "1948400": "https://tronscan.org/#/transaction/{txId}",
54
+ "4216100": "https://arbiscan.io/tx/{txId}",
55
+ "4311400": "https://snowtrace.io/tx/{txId}",
56
+ "4776300": "https://neotube.io/transaction/{txId}",
57
+ "5914400": "https://lineascan.build/tx/{txId}",
58
+ "6080800": "https://rpc.gobob.xyz/tx/{txId}",
59
+ "8009400": "https://berascan.com/tx/{txId}",
60
+ "8145700": "https://blastscan.io/tx/{txId}",
61
+ "20090100": "https://rpc.bitlayer.org/tx/{txId}",
62
+ "53435200": "https://scrollscan.com/tx/{txId}",
63
+ "221122420": "https://blockscout.devnet.doge.xyz/tx/{txId}",
64
+ "2100000000": "https://maizenet-explorer.usecorn.com/tx/{txId}",
65
+ };
66
+
67
+ const key = chainIndex.toString() as keyof typeof linkTpls;
68
+ const linkTpl: string = linkTpls[key] || "";
69
+ if (linkTpl === "") {
70
+ throw new Error(`chainIndex ${chainIndex} tpl not found`);
71
+ }
72
+ return subs(linkTpl, data);
73
+ }
74
+
75
+ export function calcCtrLength(str: string) {
76
+ let length = 0;
77
+ str = str.trim();
78
+ for (let i = 0; i < str.length; i++) {
79
+ const code = str.charCodeAt(i);
80
+ //chianese character: \u4e00-\u9fa5
81
+ if (code >= 0x4e00 && code <= 0x9fa5) {
82
+ length += 2;
83
+ } else {
84
+ length += 1;
85
+ }
86
+ }
87
+ return { len: length, originLen: str.length };
88
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "lib": ["ES2020", "DOM"],
6
+ "moduleResolution": "node",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "declaration": true,
12
+ "baseUrl": "./src"
13
+ },
14
+ "include": ["src"]
15
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from "tsup";
2
+
3
+ export default defineConfig({
4
+ entry: ["src/index.ts"],
5
+ format: ["esm", "cjs"],
6
+ dts: true,
7
+ treeshake: true,
8
+ clean: true,
9
+ platform: "browser",
10
+ outExtension({ format }) {
11
+ return {
12
+ js: format === "esm" ? ".js" : ".cjs",
13
+ };
14
+ },
15
+ });