most-box 0.0.2 → 0.0.6
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 +21 -21
- package/README.md +222 -156
- package/electron/main.js +67 -0
- package/out/404/index.html +15 -0
- package/out/404.html +15 -0
- package/out/__next.__PAGE__.txt +11 -0
- package/out/__next._full.txt +21 -0
- package/out/__next._head.txt +5 -0
- package/out/__next._index.txt +7 -0
- package/out/__next._tree.txt +4 -0
- package/out/_next/static/alUUgRz4oMlw4EtULOYfV/_buildManifest.js +11 -0
- package/out/_next/static/alUUgRz4oMlw4EtULOYfV/_clientMiddlewareManifest.js +1 -0
- package/out/_next/static/alUUgRz4oMlw4EtULOYfV/_ssgManifest.js +1 -0
- package/out/_next/static/chunks/00s106sbq8t9v.js +1 -0
- package/out/_next/static/chunks/0174xh3wfsjm1.js +2 -0
- package/out/_next/static/chunks/01xlw8hd842-c.js +1 -0
- package/out/_next/static/chunks/02ou_44kkb5dz.js +1 -0
- package/out/_next/static/chunks/02pr2b_eos3~h.js +1 -0
- package/out/_next/static/chunks/03~yq9q893hmn.js +1 -0
- package/out/_next/static/chunks/07lsjkarm1p9f.css +1 -0
- package/out/_next/static/chunks/0_-ccbcyh_o30.css +1 -0
- package/out/_next/static/chunks/0_b839~4.q324.js +1 -0
- package/out/_next/static/chunks/0_sna3wdypbzr.js +1 -0
- package/out/_next/static/chunks/0_wia9ofmsi1c.css +2 -0
- package/out/_next/static/chunks/0byj66sc-9o0g.js +1 -0
- package/out/_next/static/chunks/0bzupvr5gt3k9.js +31 -0
- package/out/_next/static/chunks/0d3shmwh5_nmn.js +1 -0
- package/out/_next/static/chunks/0du450zbk4kq_.js +1 -0
- package/out/_next/static/chunks/0e_h0d3ekzks8.css +1 -0
- package/out/_next/static/chunks/0ho~log~~-jwp.css +1 -0
- package/out/_next/static/chunks/0ibjp~7qzxfjv.js +5 -0
- package/out/_next/static/chunks/0imvn_arv36xt.css +1 -0
- package/out/_next/static/chunks/0j9~17180dl8j.js +1 -0
- package/out/_next/static/chunks/0ji.28mehrvdp.js +1 -0
- package/out/_next/static/chunks/0jl~j62iz2uvr.js +1 -0
- package/out/_next/static/chunks/0nct0fubs64d-.js +1 -0
- package/out/_next/static/chunks/0n~dq4kpx9xxx.js +1 -0
- package/out/_next/static/chunks/0pqt~8bl3ukh4.js +4 -0
- package/out/_next/static/chunks/0q7ck9f.90_i9.js +1 -0
- package/out/_next/static/chunks/0qub_r0x_r-e9.css +1 -0
- package/out/_next/static/chunks/0rr4gwjp9z~9a.js +1 -0
- package/out/_next/static/chunks/0ry.po.a~iu4p.js +1 -0
- package/out/_next/static/chunks/0slwj0c46k5cu.js +1 -0
- package/out/_next/static/chunks/0sorqk.oc6b7j.css +1 -0
- package/out/_next/static/chunks/11dalasm30arx.js +1 -0
- package/out/_next/static/chunks/turbopack-0a_g3u0ud~jb8.js +1 -0
- package/out/_not-found/__next._full.txt +20 -0
- package/out/_not-found/__next._head.txt +5 -0
- package/out/_not-found/__next._index.txt +7 -0
- package/out/_not-found/__next._not-found.__PAGE__.txt +9 -0
- package/out/_not-found/__next._not-found.txt +5 -0
- package/out/_not-found/__next._tree.txt +2 -0
- package/out/_not-found/index.html +15 -0
- package/out/_not-found/index.txt +20 -0
- package/out/app/__next._full.txt +20 -0
- package/out/app/__next._head.txt +5 -0
- package/out/app/__next._index.txt +7 -0
- package/out/app/__next._tree.txt +2 -0
- package/out/app/__next.app.__PAGE__.txt +9 -0
- package/out/app/__next.app.txt +5 -0
- package/out/app/index.html +15 -0
- package/out/app/index.txt +20 -0
- package/out/changelog/__next._full.txt +22 -0
- package/out/changelog/__next._head.txt +5 -0
- package/out/changelog/__next._index.txt +7 -0
- package/out/changelog/__next._tree.txt +3 -0
- package/out/changelog/__next.changelog.__PAGE__.txt +10 -0
- package/out/changelog/__next.changelog.txt +5 -0
- package/out/changelog/index.html +15 -0
- package/out/changelog/index.txt +22 -0
- package/out/chat/__next._full.txt +21 -0
- package/out/chat/__next._head.txt +5 -0
- package/out/chat/__next._index.txt +7 -0
- package/out/chat/__next._tree.txt +3 -0
- package/out/chat/__next.chat.__PAGE__.txt +9 -0
- package/out/chat/__next.chat.txt +6 -0
- package/out/chat/index.html +15 -0
- package/out/chat/index.txt +21 -0
- package/out/docs/__next._full.txt +22 -0
- package/out/docs/__next._head.txt +5 -0
- package/out/docs/__next._index.txt +7 -0
- package/out/docs/__next._tree.txt +3 -0
- package/out/docs/__next.docs.__PAGE__.txt +10 -0
- package/out/docs/__next.docs.txt +5 -0
- package/out/docs/getting-started/__next._full.txt +22 -0
- package/out/docs/getting-started/__next._head.txt +5 -0
- package/out/docs/getting-started/__next._index.txt +7 -0
- package/out/docs/getting-started/__next._tree.txt +3 -0
- package/out/docs/getting-started/__next.docs.getting-started.__PAGE__.txt +10 -0
- package/out/docs/getting-started/__next.docs.getting-started.txt +5 -0
- package/out/docs/getting-started/__next.docs.txt +5 -0
- package/out/docs/getting-started/index.html +15 -0
- package/out/docs/getting-started/index.txt +22 -0
- package/out/docs/index.html +15 -0
- package/out/docs/index.txt +22 -0
- package/out/download/__next._full.txt +34 -0
- package/out/download/__next._head.txt +5 -0
- package/out/download/__next._index.txt +7 -0
- package/out/download/__next._tree.txt +4 -0
- package/out/download/__next.download.__PAGE__.txt +16 -0
- package/out/download/__next.download.txt +5 -0
- package/out/download/index.html +15 -0
- package/out/download/index.txt +34 -0
- package/out/favicon.ico +0 -0
- package/out/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/out/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
- package/out/fonts/jetbrains-mono-latin-600-normal.woff2 +0 -0
- package/out/fonts/jetbrains-mono-latin-700-normal.woff2 +0 -0
- package/out/index.html +15 -0
- package/out/index.txt +21 -0
- package/out/lottery/__next._full.txt +21 -0
- package/out/lottery/__next._head.txt +5 -0
- package/out/lottery/__next._index.txt +7 -0
- package/out/lottery/__next._tree.txt +3 -0
- package/out/lottery/__next.lottery.__PAGE__.txt +9 -0
- package/out/lottery/__next.lottery.txt +6 -0
- package/out/lottery/index.html +15 -0
- package/out/lottery/index.txt +21 -0
- package/out/ping/__next._full.txt +21 -0
- package/out/ping/__next._head.txt +5 -0
- package/out/ping/__next._index.txt +7 -0
- package/out/ping/__next._tree.txt +4 -0
- package/out/ping/__next.ping.__PAGE__.txt +10 -0
- package/out/ping/__next.ping.txt +5 -0
- package/out/ping/index.html +15 -0
- package/out/ping/index.txt +21 -0
- package/out/pwa-512x512.png +0 -0
- package/out/web3/__next._full.txt +21 -0
- package/out/web3/__next._head.txt +5 -0
- package/out/web3/__next._index.txt +7 -0
- package/out/web3/__next._tree.txt +3 -0
- package/out/web3/__next.web3.__PAGE__.txt +9 -0
- package/out/web3/__next.web3.txt +6 -0
- package/out/web3/ed25519/__next._full.txt +20 -0
- package/out/web3/ed25519/__next._head.txt +5 -0
- package/out/web3/ed25519/__next._index.txt +7 -0
- package/out/web3/ed25519/__next._tree.txt +3 -0
- package/out/web3/ed25519/__next.web3.ed25519.__PAGE__.txt +6 -0
- package/out/web3/ed25519/__next.web3.ed25519.txt +5 -0
- package/out/web3/ed25519/__next.web3.txt +6 -0
- package/out/web3/ed25519/index.html +1 -0
- package/out/web3/ed25519/index.txt +20 -0
- package/out/web3/index.html +15 -0
- package/out/web3/index.txt +21 -0
- package/out/web3/tools/__next._full.txt +20 -0
- package/out/web3/tools/__next._head.txt +5 -0
- package/out/web3/tools/__next._index.txt +7 -0
- package/out/web3/tools/__next._tree.txt +3 -0
- package/out/web3/tools/__next.web3.tools.__PAGE__.txt +6 -0
- package/out/web3/tools/__next.web3.tools.txt +5 -0
- package/out/web3/tools/__next.web3.txt +6 -0
- package/out/web3/tools/index.html +1 -0
- package/out/web3/tools/index.txt +20 -0
- package/package.json +162 -48
- package/public/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/public/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
- package/public/fonts/jetbrains-mono-latin-600-normal.woff2 +0 -0
- package/public/fonts/jetbrains-mono-latin-700-normal.woff2 +0 -0
- package/public/pwa-512x512.png +0 -0
- package/server/cli.js +3 -0
- package/server/index.js +963 -0
- package/{src → server/src}/config.js +51 -39
- package/{src → server/src}/core/cid.js +157 -146
- package/{src → server/src}/index.js +1950 -1201
- package/server/src/utils/api.js +68 -0
- package/server/src/utils/avatar.js +11 -0
- package/{src → server/src}/utils/errors.js +70 -66
- package/server/src/utils/mostWallet.js +42 -0
- package/server/src/utils/mp.js +117 -0
- package/{src → server/src}/utils/security.js +173 -169
- package/server/src/utils/userIdentity.js +93 -0
- package/build.mjs +0 -40
- package/cli.js +0 -2
- package/public/app.css +0 -1519
- package/public/app.jsx +0 -1543
- package/public/bundle.css +0 -1
- package/public/bundle.js +0 -107
- package/public/error-boundary.jsx +0 -50
- package/public/index.html +0 -16
- package/public/index.jsx +0 -20
- package/server.js +0 -698
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import ky from 'ky'
|
|
2
|
+
|
|
3
|
+
const STORAGE_KEY = 'mostbox_backend_url'
|
|
4
|
+
|
|
5
|
+
function getBackendUrl() {
|
|
6
|
+
if (typeof window === 'undefined') return ''
|
|
7
|
+
return localStorage.getItem(STORAGE_KEY) || ''
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function createApiInstance() {
|
|
11
|
+
const url = getBackendUrl()
|
|
12
|
+
return ky.create({
|
|
13
|
+
prefix: url,
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export let api = createApiInstance()
|
|
18
|
+
|
|
19
|
+
export function setBackendUrl(url) {
|
|
20
|
+
const cleaned = (url || '').trim().replace(/\/+$/, '')
|
|
21
|
+
if (cleaned) {
|
|
22
|
+
localStorage.setItem(STORAGE_KEY, cleaned)
|
|
23
|
+
} else {
|
|
24
|
+
localStorage.removeItem(STORAGE_KEY)
|
|
25
|
+
}
|
|
26
|
+
api = createApiInstance()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getBackendUrlExport() {
|
|
30
|
+
return getBackendUrl()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function checkBackendConnection() {
|
|
34
|
+
const url = getBackendUrl()
|
|
35
|
+
try {
|
|
36
|
+
const res = await fetch(`${url}/api/node-id`, {
|
|
37
|
+
method: 'GET',
|
|
38
|
+
signal: AbortSignal.timeout(3000),
|
|
39
|
+
})
|
|
40
|
+
return res.ok
|
|
41
|
+
} catch {
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function detectSameOriginBackend() {
|
|
47
|
+
try {
|
|
48
|
+
const res = await fetch('/api/node-id', {
|
|
49
|
+
method: 'GET',
|
|
50
|
+
signal: AbortSignal.timeout(2000),
|
|
51
|
+
})
|
|
52
|
+
return res.ok
|
|
53
|
+
} catch {
|
|
54
|
+
return false
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function detectLocalhostBackend() {
|
|
59
|
+
try {
|
|
60
|
+
const res = await fetch('http://localhost:1976/api/node-id', {
|
|
61
|
+
method: 'GET',
|
|
62
|
+
signal: AbortSignal.timeout(2000),
|
|
63
|
+
})
|
|
64
|
+
return res.ok
|
|
65
|
+
} catch {
|
|
66
|
+
return false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createAvatar } from '@dicebear/core'
|
|
2
|
+
import { botttsNeutral } from '@dicebear/collection'
|
|
3
|
+
|
|
4
|
+
export function generateAvatar(address) {
|
|
5
|
+
if (!address) return '/pwa-512x512.png'
|
|
6
|
+
return createAvatar(botttsNeutral, {
|
|
7
|
+
seed: 'most.box@' + address,
|
|
8
|
+
flip: true,
|
|
9
|
+
backgroundType: ['gradientLinear'],
|
|
10
|
+
}).toDataUri()
|
|
11
|
+
}
|
|
@@ -1,66 +1,70 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Custom Error Classes
|
|
3
|
-
* Helps categorize errors for better frontend handling
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export class AppError extends Error {
|
|
7
|
-
constructor(message, code = 'UNKNOWN') {
|
|
8
|
-
super(message)
|
|
9
|
-
this.name = 'AppError'
|
|
10
|
-
this.code = code
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class ValidationError extends AppError {
|
|
15
|
-
constructor(message) {
|
|
16
|
-
super(message, 'VALIDATION_ERROR')
|
|
17
|
-
this.name = 'ValidationError'
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class FileSizeError extends AppError {
|
|
22
|
-
constructor(message, size) {
|
|
23
|
-
super(message, 'FILE_SIZE_ERROR')
|
|
24
|
-
this.name = 'FileSizeError'
|
|
25
|
-
this.size = size
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class PathSecurityError extends AppError {
|
|
30
|
-
constructor(message = 'Path validation failed') {
|
|
31
|
-
super(message, 'PATH_SECURITY_ERROR')
|
|
32
|
-
this.name = 'PathSecurityError'
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export class PeerNotFoundError extends AppError {
|
|
37
|
-
constructor(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Custom Error Classes
|
|
3
|
+
* Helps categorize errors for better frontend handling
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export class AppError extends Error {
|
|
7
|
+
constructor(message, code = 'UNKNOWN') {
|
|
8
|
+
super(message)
|
|
9
|
+
this.name = 'AppError'
|
|
10
|
+
this.code = code
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class ValidationError extends AppError {
|
|
15
|
+
constructor(message) {
|
|
16
|
+
super(message, 'VALIDATION_ERROR')
|
|
17
|
+
this.name = 'ValidationError'
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class FileSizeError extends AppError {
|
|
22
|
+
constructor(message, size) {
|
|
23
|
+
super(message, 'FILE_SIZE_ERROR')
|
|
24
|
+
this.name = 'FileSizeError'
|
|
25
|
+
this.size = size
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class PathSecurityError extends AppError {
|
|
30
|
+
constructor(message = 'Path validation failed') {
|
|
31
|
+
super(message, 'PATH_SECURITY_ERROR')
|
|
32
|
+
this.name = 'PathSecurityError'
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class PeerNotFoundError extends AppError {
|
|
37
|
+
constructor(
|
|
38
|
+
message = 'No peers found. Please ensure the publisher is online.'
|
|
39
|
+
) {
|
|
40
|
+
super(message, 'PEER_NOT_FOUND')
|
|
41
|
+
this.name = 'PeerNotFoundError'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class IntegrityError extends AppError {
|
|
46
|
+
constructor(
|
|
47
|
+
message = 'File integrity check failed. File may be corrupted or tampered.'
|
|
48
|
+
) {
|
|
49
|
+
super(message, 'INTEGRITY_ERROR')
|
|
50
|
+
this.name = 'IntegrityError'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class PermissionError extends AppError {
|
|
55
|
+
constructor(message = 'Permission denied') {
|
|
56
|
+
super(message, 'PERMISSION_ERROR')
|
|
57
|
+
this.name = 'PermissionError'
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export class EngineNotInitializedError extends AppError {
|
|
62
|
+
constructor(message = 'Engine not initialized. Call start() first.') {
|
|
63
|
+
super(message, 'ENGINE_NOT_INITIALIZED')
|
|
64
|
+
this.name = 'EngineNotInitializedError'
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function isErrorWithCode(err, code) {
|
|
69
|
+
return err && err.code === code
|
|
70
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
pbkdf2,
|
|
3
|
+
sha256,
|
|
4
|
+
getBytes,
|
|
5
|
+
Mnemonic,
|
|
6
|
+
HDNodeWallet,
|
|
7
|
+
toUtf8Bytes,
|
|
8
|
+
hexlify,
|
|
9
|
+
} from 'ethers'
|
|
10
|
+
import nacl from 'tweetnacl'
|
|
11
|
+
|
|
12
|
+
const SALT_PREFIX = '/most.box/'
|
|
13
|
+
const PBKDF2_ITERATIONS = 3
|
|
14
|
+
const PBKDF2_KEY_LENGTH = 32
|
|
15
|
+
|
|
16
|
+
export function mostWallet(username, password) {
|
|
17
|
+
const salt = toUtf8Bytes(SALT_PREFIX + username)
|
|
18
|
+
const p = toUtf8Bytes(password)
|
|
19
|
+
const kdf = pbkdf2(p, salt, PBKDF2_ITERATIONS, PBKDF2_KEY_LENGTH, 'sha512')
|
|
20
|
+
const seed = getBytes(sha256(getBytes(kdf)))
|
|
21
|
+
const mnemonic = Mnemonic.entropyToPhrase(seed)
|
|
22
|
+
const account = HDNodeWallet.fromPhrase(mnemonic)
|
|
23
|
+
return {
|
|
24
|
+
username,
|
|
25
|
+
address: account.address,
|
|
26
|
+
danger: hexlify(seed),
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function mostMnemonic(danger) {
|
|
31
|
+
return Mnemonic.entropyToPhrase(getBytes(danger))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function most25519(danger) {
|
|
35
|
+
const x25519KeyPair = nacl.box.keyPair.fromSecretKey(getBytes(danger))
|
|
36
|
+
const ed25519KeyPair = nacl.sign.keyPair.fromSeed(getBytes(danger))
|
|
37
|
+
return {
|
|
38
|
+
public_key: hexlify(x25519KeyPair.publicKey),
|
|
39
|
+
private_key: hexlify(x25519KeyPair.secretKey),
|
|
40
|
+
ed_public_key: hexlify(ed25519KeyPair.publicKey),
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { getBytes, ZeroAddress } from 'ethers'
|
|
2
|
+
import dayjs from 'dayjs'
|
|
3
|
+
import nacl from 'tweetnacl'
|
|
4
|
+
import { generateAvatar } from './avatar.js'
|
|
5
|
+
|
|
6
|
+
const BASE36_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz'
|
|
7
|
+
|
|
8
|
+
// Ed25519 变长整型编码(protobuf varint)
|
|
9
|
+
const encodeVarint = value => {
|
|
10
|
+
const bytes = []
|
|
11
|
+
while (value >= 0x80) {
|
|
12
|
+
bytes.push((value & 0x7f) | 0x80)
|
|
13
|
+
value >>= 7
|
|
14
|
+
}
|
|
15
|
+
bytes.push(value)
|
|
16
|
+
return bytes
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Ed25519 libp2p-protobuf-cleartext 公钥
|
|
20
|
+
const marshalLibp2pPublicKeyEd25519 = publicKey => {
|
|
21
|
+
const header = new Uint8Array([
|
|
22
|
+
0x08,
|
|
23
|
+
0x01,
|
|
24
|
+
0x12,
|
|
25
|
+
...encodeVarint(publicKey.length),
|
|
26
|
+
])
|
|
27
|
+
const out = new Uint8Array(header.length + publicKey.length)
|
|
28
|
+
out.set(header, 0)
|
|
29
|
+
out.set(publicKey, header.length)
|
|
30
|
+
return out
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 通用 BaseX 编码(用于 base36)
|
|
34
|
+
const baseXEncode = (bytes, alphabet) => {
|
|
35
|
+
if (bytes.length === 0) return ''
|
|
36
|
+
const base = alphabet.length
|
|
37
|
+
let zeros = 0
|
|
38
|
+
while (zeros < bytes.length && bytes[zeros] === 0) zeros++
|
|
39
|
+
|
|
40
|
+
const digits = [0]
|
|
41
|
+
for (let i = zeros; i < bytes.length; i++) {
|
|
42
|
+
let carry = bytes[i]
|
|
43
|
+
for (let j = 0; j < digits.length; j++) {
|
|
44
|
+
const val = digits[j] * 256 + carry
|
|
45
|
+
digits[j] = val % base
|
|
46
|
+
carry = Math.floor(val / base)
|
|
47
|
+
}
|
|
48
|
+
while (carry > 0) {
|
|
49
|
+
digits.push(carry % base)
|
|
50
|
+
carry = Math.floor(carry / base)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let result = ''
|
|
55
|
+
for (let i = 0; i < zeros; i++) result += alphabet[0]
|
|
56
|
+
for (let i = digits.length - 1; i >= 0; i--) result += alphabet[digits[i]]
|
|
57
|
+
return result
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const getEdKeyPair = (private_key, ed_public_key) => {
|
|
61
|
+
const public_key = ed_public_key.slice(2)
|
|
62
|
+
const secretKey = new Uint8Array(getBytes(private_key + public_key))
|
|
63
|
+
return nacl.sign.keyPair.fromSecretKey(secretKey)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const getIPNS = (private_key, ed_public_key) => {
|
|
67
|
+
const EdKeyPair = getEdKeyPair(private_key, ed_public_key)
|
|
68
|
+
const pubProto = marshalLibp2pPublicKeyEd25519(EdKeyPair.publicKey)
|
|
69
|
+
const mh = new Uint8Array(2 + pubProto.length)
|
|
70
|
+
mh[0] = 0x00
|
|
71
|
+
mh[1] = 0x24
|
|
72
|
+
mh.set(pubProto, 2)
|
|
73
|
+
const cidHeader = new Uint8Array([0x01, 0x72])
|
|
74
|
+
const cidBytes = new Uint8Array(cidHeader.length + mh.length)
|
|
75
|
+
cidBytes.set(cidHeader, 0)
|
|
76
|
+
cidBytes.set(mh, cidHeader.length)
|
|
77
|
+
return 'k' + baseXEncode(cidBytes, BASE36_ALPHABET)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const formatTime = time => {
|
|
81
|
+
if (!time) return ''
|
|
82
|
+
const date = dayjs(Number(time))
|
|
83
|
+
const hour = date.hour()
|
|
84
|
+
let timeOfDay
|
|
85
|
+
if (hour >= 0 && hour < 3) {
|
|
86
|
+
timeOfDay = '凌晨'
|
|
87
|
+
} else if (hour >= 3 && hour < 6) {
|
|
88
|
+
timeOfDay = '拂晓'
|
|
89
|
+
} else if (hour >= 6 && hour < 9) {
|
|
90
|
+
timeOfDay = '早晨'
|
|
91
|
+
} else if (hour >= 9 && hour < 12) {
|
|
92
|
+
timeOfDay = '上午'
|
|
93
|
+
} else if (hour >= 12 && hour < 15) {
|
|
94
|
+
timeOfDay = '下午'
|
|
95
|
+
} else if (hour >= 15 && hour < 18) {
|
|
96
|
+
timeOfDay = '傍晚'
|
|
97
|
+
} else if (hour >= 18 && hour < 21) {
|
|
98
|
+
timeOfDay = '薄暮'
|
|
99
|
+
} else {
|
|
100
|
+
timeOfDay = '深夜'
|
|
101
|
+
}
|
|
102
|
+
return date.format(`YYYY年M月D日 ${timeOfDay}h点`)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const avatar = generateAvatar
|
|
106
|
+
|
|
107
|
+
export { ZeroAddress }
|
|
108
|
+
|
|
109
|
+
const mp = {
|
|
110
|
+
avatar: generateAvatar,
|
|
111
|
+
formatTime,
|
|
112
|
+
getEdKeyPair,
|
|
113
|
+
getIPNS,
|
|
114
|
+
ZeroAddress,
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export default mp
|