web-dc-api 0.1.5 → 0.1.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/dist/cjs/index.js +1 -1
- package/dist/dc.min.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/index.d.ts +934 -878
- package/package.json +4 -8
- package/dist/cjs/helia-core-B1Xqha7a.js +0 -1
- package/dist/cjs/helia-core-D8Uv1KjQ.js +0 -1
- package/dist/cjs/polkadot-api-7PhQf3ws.js +0 -1
- package/dist/cjs/polkadot-api-CtrJVWuZ.js +0 -1
- package/dist/esm/chunks/helia-core-BxMqyK2Y.js +0 -1
- package/dist/esm/chunks/helia-core-DMXRpcO-.js +0 -1
- package/dist/esm/chunks/polkadot-api-5Y9Bw8VT.js +0 -1
- package/dist/esm/chunks/polkadot-api-D69Ioun_.js +0 -1
- package/lib/common/blowfish/block.ts +0 -259
- package/lib/common/blowfish/cipher.ts +0 -144
- package/lib/common/blowfish/const.ts +0 -195
- package/lib/common/chain.ts +0 -469
- package/lib/common/commonclient.ts +0 -202
- package/lib/common/constants.ts +0 -55
- package/lib/common/dc-key/ed25519.ts +0 -343
- package/lib/common/dc-key/keyManager.ts +0 -424
- package/lib/common/dcapi.ts +0 -98
- package/lib/common/dcutil.ts +0 -627
- package/lib/common/define.ts +0 -70
- package/lib/common/error.ts +0 -67
- package/lib/common/grpc-dc.ts +0 -104
- package/lib/common/module-system.ts +0 -184
- package/lib/common/service-worker.ts +0 -234
- package/lib/common/types/types.ts +0 -344
- package/lib/dc.ts +0 -701
- package/lib/implements/account/client.ts +0 -185
- package/lib/implements/account/manager.ts +0 -683
- package/lib/implements/aiproxy/client.ts +0 -357
- package/lib/implements/aiproxy/manager.ts +0 -670
- package/lib/implements/cache/client.ts +0 -105
- package/lib/implements/cache/manager.ts +0 -127
- package/lib/implements/comment/client.ts +0 -982
- package/lib/implements/comment/manager.ts +0 -1151
- package/lib/implements/dc/client.ts +0 -51
- package/lib/implements/dc/manager.ts +0 -33
- package/lib/implements/file/client.ts +0 -253
- package/lib/implements/file/file-cache-manager.ts +0 -142
- package/lib/implements/file/manager.ts +0 -1240
- package/lib/implements/file/seekableFileStream.ts +0 -344
- package/lib/implements/file/streamwriter.ts +0 -322
- package/lib/implements/keyvalue/client.ts +0 -376
- package/lib/implements/keyvalue/manager.ts +0 -759
- package/lib/implements/message/client.ts +0 -250
- package/lib/implements/message/manager.ts +0 -215
- package/lib/implements/threaddb/cbor/coding.ts +0 -62
- package/lib/implements/threaddb/cbor/event.ts +0 -336
- package/lib/implements/threaddb/cbor/node.ts +0 -542
- package/lib/implements/threaddb/cbor/record.ts +0 -398
- package/lib/implements/threaddb/common/AsyncMutex.ts +0 -24
- package/lib/implements/threaddb/common/addrinfo.ts +0 -135
- package/lib/implements/threaddb/common/dispatcher.ts +0 -81
- package/lib/implements/threaddb/common/idbstore-adapter.ts +0 -260
- package/lib/implements/threaddb/common/json-patcher.ts +0 -204
- package/lib/implements/threaddb/common/key.ts +0 -290
- package/lib/implements/threaddb/common/level-adapter.ts +0 -235
- package/lib/implements/threaddb/common/lineReader.ts +0 -79
- package/lib/implements/threaddb/common/logstore.ts +0 -215
- package/lib/implements/threaddb/common/transformed-datastore.ts +0 -308
- package/lib/implements/threaddb/core/app.ts +0 -206
- package/lib/implements/threaddb/core/core.ts +0 -230
- package/lib/implements/threaddb/core/db.ts +0 -249
- package/lib/implements/threaddb/core/event.ts +0 -54
- package/lib/implements/threaddb/core/head.ts +0 -89
- package/lib/implements/threaddb/core/identity.ts +0 -171
- package/lib/implements/threaddb/core/logstore.ts +0 -137
- package/lib/implements/threaddb/core/options.ts +0 -14
- package/lib/implements/threaddb/core/record.ts +0 -54
- package/lib/implements/threaddb/db/collection.ts +0 -1910
- package/lib/implements/threaddb/db/db.ts +0 -698
- package/lib/implements/threaddb/db/json2Query.ts +0 -192
- package/lib/implements/threaddb/db/query.ts +0 -524
- package/lib/implements/threaddb/dbclient.ts +0 -543
- package/lib/implements/threaddb/dbmanager.ts +0 -1906
- package/lib/implements/threaddb/lsstoreds/addr_book.ts +0 -549
- package/lib/implements/threaddb/lsstoreds/cache.ts +0 -36
- package/lib/implements/threaddb/lsstoreds/cyclic_batch.ts +0 -87
- package/lib/implements/threaddb/lsstoreds/global.ts +0 -151
- package/lib/implements/threaddb/lsstoreds/headbook.ts +0 -373
- package/lib/implements/threaddb/lsstoreds/keybook.ts +0 -297
- package/lib/implements/threaddb/lsstoreds/logstore.ts +0 -29
- package/lib/implements/threaddb/lsstoreds/metadata.ts +0 -223
- package/lib/implements/threaddb/net/define.ts +0 -149
- package/lib/implements/threaddb/net/grpcClient.ts +0 -589
- package/lib/implements/threaddb/net/grpcserver.ts +0 -146
- package/lib/implements/threaddb/net/net.ts +0 -2047
- package/lib/implements/threaddb/pb/lstore.proto +0 -38
- package/lib/implements/threaddb/pb/lstore.ts +0 -393
- package/lib/implements/threaddb/pb/lstore_pb.d.ts +0 -433
- package/lib/implements/threaddb/pb/lstore_pb.js +0 -1085
- package/lib/implements/threaddb/pb/net.proto +0 -194
- package/lib/implements/threaddb/pb/net_pb.d.ts +0 -2349
- package/lib/implements/threaddb/pb/net_pb.js +0 -5525
- package/lib/implements/threaddb/pb/proto-custom-types.ts +0 -212
- package/lib/implements/util/client.ts +0 -72
- package/lib/implements/util/manager.ts +0 -146
- package/lib/implements/wallet/manager.ts +0 -671
- package/lib/index.ts +0 -57
- package/lib/interfaces/DCContext.ts +0 -51
- package/lib/interfaces/aiproxy-interface.ts +0 -145
- package/lib/interfaces/auth-interface.ts +0 -118
- package/lib/interfaces/cache-interface.ts +0 -22
- package/lib/interfaces/client-interface.ts +0 -11
- package/lib/interfaces/comment-interface.ts +0 -167
- package/lib/interfaces/components/news-component.ts +0 -0
- package/lib/interfaces/database-interface.ts +0 -169
- package/lib/interfaces/file-interface.ts +0 -120
- package/lib/interfaces/index.ts +0 -10
- package/lib/interfaces/keyvalue-interface.ts +0 -156
- package/lib/interfaces/message-interface.ts +0 -22
- package/lib/interfaces/util-interface.ts +0 -31
- package/lib/modules/aiproxy-module.ts +0 -246
- package/lib/modules/auth-module.ts +0 -753
- package/lib/modules/cache-module.ts +0 -99
- package/lib/modules/client-module.ts +0 -71
- package/lib/modules/comment-module.ts +0 -429
- package/lib/modules/components/news-components.ts +0 -390
- package/lib/modules/database-module.ts +0 -598
- package/lib/modules/file-module.ts +0 -291
- package/lib/modules/index.ts +0 -13
- package/lib/modules/keyvalue-module.ts +0 -379
- package/lib/modules/message-module.ts +0 -107
- package/lib/modules/util-module.ts +0 -148
- package/lib/polyfills/process-env-browser.ts +0 -1
- package/lib/proto/datasource.ts +0 -93
- package/lib/proto/dcnet.proto +0 -1601
- package/lib/proto/dcnet_proto.d.ts +0 -22857
- package/lib/proto/dcnet_proto.js +0 -55204
- package/lib/proto/dcnet_proto_sparse.js +0 -55166
- package/lib/proto/oidfetch.proto +0 -25
- package/lib/proto/oidfetch_proto.d.ts +0 -585
- package/lib/proto/oidfetch_proto.js +0 -1247
- package/lib/serverless/babel-browser.ts +0 -39
- package/lib/serverless/base_entity.ts +0 -78
- package/lib/serverless/base_repository.ts +0 -414
- package/lib/serverless/browser_schema_extractor.ts +0 -283
- package/lib/serverless/decorator_factory.ts +0 -322
- package/lib/util/BrowserLineReader.ts +0 -73
- package/lib/util/base64.ts +0 -105
- package/lib/util/bcrypt.ts +0 -206
- package/lib/util/curve25519Encryption.ts +0 -418
- package/lib/util/dccrypt.ts +0 -73
- package/lib/util/logger.ts +0 -104
- package/lib/util/utils.ts +0 -289
|
@@ -1,683 +0,0 @@
|
|
|
1
|
-
import type { Multiaddr } from "@multiformats/multiaddr";
|
|
2
|
-
import { ChainUtil } from "../../common/chain";
|
|
3
|
-
import { DcUtil } from "../../common/dcutil";
|
|
4
|
-
import { DCConnectInfo, NFTBindStatus, User } from "../../common/types/types";
|
|
5
|
-
import { AccountClient } from "./client";
|
|
6
|
-
import { sha256, uint32ToLittleEndianBytes } from "../../util/utils";
|
|
7
|
-
import { Ed25519PrivKey, Ed25519PubKey } from "../../common/dc-key/ed25519";
|
|
8
|
-
import { DCContext } from "../../../lib/interfaces/DCContext";
|
|
9
|
-
import { PeerId } from "@libp2p/interface";
|
|
10
|
-
import {
|
|
11
|
-
extractPublicKeyFromPeerId,
|
|
12
|
-
generateSymKeyForPrikey,
|
|
13
|
-
KeyManager,
|
|
14
|
-
} from "../../common/dc-key/keyManager";
|
|
15
|
-
import { SymmetricKey } from "../threaddb/common/key";
|
|
16
|
-
import { peerIdFromString } from "@libp2p/peer-id";
|
|
17
|
-
import { request } from "http";
|
|
18
|
-
|
|
19
|
-
// 错误定义
|
|
20
|
-
export class AccountError extends Error {
|
|
21
|
-
constructor(message: string) {
|
|
22
|
-
super(message);
|
|
23
|
-
this.name = "AccountError";
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
export const Errors = {
|
|
27
|
-
ErrNoDcPeerConnected: new AccountError("no dc peer connected"),
|
|
28
|
-
ErrNodeAddrIsNull: new AccountError("nodeAddr is null"),
|
|
29
|
-
ErrChainUtilIsNull: new AccountError("chainUtil is null"),
|
|
30
|
-
ErrAccountLogin: new AccountError("account login error"),
|
|
31
|
-
ErrNoAccountPeerConnected: new AccountError("no account peer connected"),
|
|
32
|
-
// account privatekey sign is null
|
|
33
|
-
ErrAccountPrivateSignIsNull: new AccountError(
|
|
34
|
-
"account privatekey sign is null"
|
|
35
|
-
),
|
|
36
|
-
// 公钥唯恐
|
|
37
|
-
ErrAccountPublicKeyIsNull: new AccountError("account publickey is null"),
|
|
38
|
-
};
|
|
39
|
-
export class AccountManager {
|
|
40
|
-
dc: DcUtil;
|
|
41
|
-
chainUtil: ChainUtil | undefined;
|
|
42
|
-
context: DCContext;
|
|
43
|
-
constructor(context: DCContext) {
|
|
44
|
-
this.dc = context.dcutil;
|
|
45
|
-
this.chainUtil = context.dcChain;
|
|
46
|
-
this.context = context;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// 获取用户备用节点
|
|
50
|
-
getAccountNodeAddr = async (): Promise<[Multiaddr | null, Error | null]> => {
|
|
51
|
-
if (!this.context.connectedDc.client) {
|
|
52
|
-
console.error("dcClient is null");
|
|
53
|
-
return [null, Errors.ErrNoDcPeerConnected];
|
|
54
|
-
}
|
|
55
|
-
if (!this.chainUtil) {
|
|
56
|
-
console.error("chainUtil is null");
|
|
57
|
-
return [null, Errors.ErrChainUtilIsNull];
|
|
58
|
-
}
|
|
59
|
-
if (!this.context) {
|
|
60
|
-
console.error("context is null");
|
|
61
|
-
return [null, Errors.ErrAccountPrivateSignIsNull];
|
|
62
|
-
}
|
|
63
|
-
const pubkeyRaw = this.context.getPubkeyRaw();
|
|
64
|
-
const peerAddrs = await this.chainUtil.getAccountPeers(pubkeyRaw);
|
|
65
|
-
if (peerAddrs && peerAddrs.length > 0) {
|
|
66
|
-
// 连接备用节点
|
|
67
|
-
const nodeAddr = await this.dc?._connectPeers(peerAddrs);
|
|
68
|
-
console.log("_connectNodeAddrs nodeAddr:", nodeAddr);
|
|
69
|
-
if (nodeAddr) {
|
|
70
|
-
return [nodeAddr, null];
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return [null, Errors.ErrNoAccountPeerConnected];
|
|
74
|
-
};
|
|
75
|
-
// 获取用户信息
|
|
76
|
-
getUserInfoWithNft = async (
|
|
77
|
-
nftAccount: string
|
|
78
|
-
): Promise<[User | null, Error | null]> => {
|
|
79
|
-
if (!this.context.connectedDc.client) {
|
|
80
|
-
console.error("dcClient is null");
|
|
81
|
-
return [null, Errors.ErrNoDcPeerConnected];
|
|
82
|
-
}
|
|
83
|
-
if (!this.chainUtil) {
|
|
84
|
-
console.error("chainUtil is null");
|
|
85
|
-
return [null, Errors.ErrChainUtilIsNull];
|
|
86
|
-
}
|
|
87
|
-
// 从链上获取
|
|
88
|
-
const userInfo = await this.chainUtil.getUserInfoWithNft(nftAccount);
|
|
89
|
-
console.log("userInfo reply:", userInfo);
|
|
90
|
-
return [userInfo, null];
|
|
91
|
-
};
|
|
92
|
-
bindAccessPeerToUser = async (
|
|
93
|
-
peerAddr: Multiaddr
|
|
94
|
-
): Promise<[boolean | null, Error | null]> => {
|
|
95
|
-
if (!this.context.connectedDc.client) {
|
|
96
|
-
console.error("dcClient is null");
|
|
97
|
-
return [false, Errors.ErrNoDcPeerConnected];
|
|
98
|
-
}
|
|
99
|
-
if (!this.chainUtil) {
|
|
100
|
-
console.error("chainUtil is null");
|
|
101
|
-
return [null, Errors.ErrChainUtilIsNull];
|
|
102
|
-
}
|
|
103
|
-
if (!this.context) {
|
|
104
|
-
console.error("context is null");
|
|
105
|
-
return [null, Errors.ErrAccountPrivateSignIsNull];
|
|
106
|
-
}
|
|
107
|
-
const peerId = peerAddr.getPeerId();
|
|
108
|
-
if (!peerId) {
|
|
109
|
-
console.error("peerId is null");
|
|
110
|
-
return [null, Errors.ErrNoAccountPeerConnected];
|
|
111
|
-
}
|
|
112
|
-
// 绑定节点
|
|
113
|
-
const blockHeight = await this.chainUtil.getBlockHeight();
|
|
114
|
-
const accountClient = new AccountClient(this.context.connectedDc.client);
|
|
115
|
-
const bindResult = await accountClient.bindAccessPeerToUser(
|
|
116
|
-
this.context,
|
|
117
|
-
blockHeight ? blockHeight : 0,
|
|
118
|
-
peerId.toString()
|
|
119
|
-
);
|
|
120
|
-
console.log("bindAccessPeerToUser bindResult:", bindResult);
|
|
121
|
-
return [true, null];
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* 将私钥绑定NFT账号(NFT账号+密码+安全码)
|
|
126
|
-
* @param account NFT账号
|
|
127
|
-
* @param password 密码
|
|
128
|
-
* @param seccode 安全码
|
|
129
|
-
* @returns [状态码, 错误信息]
|
|
130
|
-
*/
|
|
131
|
-
async bindNFTAccount(
|
|
132
|
-
account: string,
|
|
133
|
-
password: string,
|
|
134
|
-
seccode: string,
|
|
135
|
-
mnemonic: string
|
|
136
|
-
): Promise<[NFTBindStatus, Error | null]> {
|
|
137
|
-
// 检查节点连接
|
|
138
|
-
if (!this.context.connectedDc.client) {
|
|
139
|
-
return [NFTBindStatus.DcPeerNotConnected, Errors.ErrNoDcPeerConnected];
|
|
140
|
-
}
|
|
141
|
-
if (!this.context.connectedDc.nodeAddr) {
|
|
142
|
-
return [NFTBindStatus.DcPeerNotConnected, Errors.ErrNodeAddrIsNull];
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
const connectedPeerIdStr = this.context.connectedDc.nodeAddr.getPeerId();
|
|
147
|
-
if (!connectedPeerIdStr) {
|
|
148
|
-
return [NFTBindStatus.DcPeerNotConnected, Errors.ErrNodeAddrIsNull];
|
|
149
|
-
}
|
|
150
|
-
const connectedPeerId = peerIdFromString(connectedPeerIdStr);
|
|
151
|
-
// 生成账户请求
|
|
152
|
-
const [req, status] = await this.generateAccountDealRequest(
|
|
153
|
-
account,
|
|
154
|
-
password,
|
|
155
|
-
seccode,
|
|
156
|
-
mnemonic,
|
|
157
|
-
connectedPeerId
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
if (status !== NFTBindStatus.Success) {
|
|
161
|
-
return [
|
|
162
|
-
status,
|
|
163
|
-
new AccountError(`Failed to generate account request: ${status}`),
|
|
164
|
-
];
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// 获取客户端
|
|
168
|
-
const accountClient = new AccountClient(this.context.connectedDc.client);
|
|
169
|
-
// 调用账户绑定API
|
|
170
|
-
await accountClient.accountBind(req, mnemonic, this.context);
|
|
171
|
-
|
|
172
|
-
// 绑定成功
|
|
173
|
-
return [NFTBindStatus.Success, null];
|
|
174
|
-
} catch (error) {
|
|
175
|
-
// 错误处理,匹配各种特定错误类型
|
|
176
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
177
|
-
if (errorMsg.includes("user already binded")) {
|
|
178
|
-
return [
|
|
179
|
-
NFTBindStatus.UserBinded,
|
|
180
|
-
error instanceof Error ? error : new Error(errorMsg),
|
|
181
|
-
];
|
|
182
|
-
} else if (errorMsg.includes("account already binded")) {
|
|
183
|
-
return [
|
|
184
|
-
NFTBindStatus.NftAccountBinded,
|
|
185
|
-
error instanceof Error ? error : new Error(errorMsg),
|
|
186
|
-
];
|
|
187
|
-
} else if (errorMsg.includes("user space expired")) {
|
|
188
|
-
return [
|
|
189
|
-
NFTBindStatus.SpaceExpired,
|
|
190
|
-
error instanceof Error ? error : new Error(errorMsg),
|
|
191
|
-
];
|
|
192
|
-
} else if (errorMsg.includes("no enough user space")) {
|
|
193
|
-
return [
|
|
194
|
-
NFTBindStatus.NoLeftSpace,
|
|
195
|
-
error instanceof Error ? error : new Error(errorMsg),
|
|
196
|
-
];
|
|
197
|
-
} else {
|
|
198
|
-
console.error("NFT账号绑定失败:", error);
|
|
199
|
-
return [
|
|
200
|
-
NFTBindStatus.Error,
|
|
201
|
-
error instanceof Error ? error : new Error(errorMsg),
|
|
202
|
-
];
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* 生成Nft账号处理的请求(包括绑定NFT账号以及修改账号对应的登录信息),
|
|
209
|
-
* 如果登录账号的助记词存在,则使用助记词进行绑定,否则使用私钥进行绑定
|
|
210
|
-
*
|
|
211
|
-
* @param account NFT账号
|
|
212
|
-
* @param password 密码
|
|
213
|
-
* @param seccode 安全码
|
|
214
|
-
* @param serverPid 服务器节点ID
|
|
215
|
-
* @param isParent 是否为父账户
|
|
216
|
-
* @returns [AccountDealRequest对象, 状态码]
|
|
217
|
-
*/
|
|
218
|
-
private async generateAccountDealRequest(
|
|
219
|
-
account: string,
|
|
220
|
-
password: string,
|
|
221
|
-
seccode: string,
|
|
222
|
-
mnemonic: string,
|
|
223
|
-
serverPid: PeerId
|
|
224
|
-
): Promise<
|
|
225
|
-
[
|
|
226
|
-
{
|
|
227
|
-
accounthashencrypt: Uint8Array;
|
|
228
|
-
accountencrypt: Uint8Array;
|
|
229
|
-
prikeyencrypt2: Uint8Array;
|
|
230
|
-
blockheight: number;
|
|
231
|
-
loginkeyrandencrypt: Uint8Array;
|
|
232
|
-
peerid: Uint8Array;
|
|
233
|
-
signature: Uint8Array;
|
|
234
|
-
} | null,
|
|
235
|
-
NFTBindStatus
|
|
236
|
-
]
|
|
237
|
-
> {
|
|
238
|
-
try {
|
|
239
|
-
// 确定要加密的内容(私钥或助记词)
|
|
240
|
-
const needEncryptStr = `mnemonic:${mnemonic}`;
|
|
241
|
-
// 哈希账号
|
|
242
|
-
const accountBytes = new TextEncoder().encode(account);
|
|
243
|
-
const accountHash = await crypto.subtle.digest("SHA-256", accountBytes);
|
|
244
|
-
const accountHashArray = new Uint8Array(accountHash);
|
|
245
|
-
|
|
246
|
-
// 获取节点公钥
|
|
247
|
-
const serverPubkey = await extractPublicKeyFromPeerId(serverPid);
|
|
248
|
-
if (!serverPubkey) {
|
|
249
|
-
return [null, NFTBindStatus.Error];
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// 确定使用的密钥
|
|
253
|
-
// 生成
|
|
254
|
-
const keymanager = new KeyManager();
|
|
255
|
-
const selfPrivkey = await keymanager.getEd25519KeyFromMnemonic(mnemonic, "");
|
|
256
|
-
const selfPubkey = selfPrivkey.publicKey;
|
|
257
|
-
|
|
258
|
-
// 用自身公钥加密账号
|
|
259
|
-
const accountEncrypt = await selfPubkey.encrypt(
|
|
260
|
-
new TextEncoder().encode(account)
|
|
261
|
-
);
|
|
262
|
-
if (!accountEncrypt) {
|
|
263
|
-
return [null, NFTBindStatus.EncryptError];
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// 用服务器公钥加密账号哈希
|
|
267
|
-
const accountHashCrypt = await serverPubkey.encrypt(accountHashArray);
|
|
268
|
-
if (!accountHashCrypt) {
|
|
269
|
-
return [null, NFTBindStatus.EncryptError];
|
|
270
|
-
}
|
|
271
|
-
// 生成对称密钥
|
|
272
|
-
const aeskey = await generateSymKeyForPrikey(account, password);
|
|
273
|
-
if (!aeskey) {
|
|
274
|
-
return [null, NFTBindStatus.EncryptError];
|
|
275
|
-
}
|
|
276
|
-
const encryptKey = SymmetricKey.fromSymKey(aeskey);
|
|
277
|
-
// 用对称密钥加密私钥/助记词
|
|
278
|
-
const prikeyencrypt = await encryptKey.encrypt(
|
|
279
|
-
new TextEncoder().encode(needEncryptStr)
|
|
280
|
-
);
|
|
281
|
-
if (!prikeyencrypt) {
|
|
282
|
-
return [null, NFTBindStatus.EncryptError];
|
|
283
|
-
}
|
|
284
|
-
// 用服务器公钥再次加密
|
|
285
|
-
const prikeyencrypt2 = await serverPubkey.encrypt(prikeyencrypt);
|
|
286
|
-
if (!prikeyencrypt2) {
|
|
287
|
-
return [null, NFTBindStatus.EncryptError];
|
|
288
|
-
}
|
|
289
|
-
// 获取区块链高度
|
|
290
|
-
if (!this.chainUtil) {
|
|
291
|
-
return [null, NFTBindStatus.BlockchainError];
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const blockHeight = await this.chainUtil.getBlockHeight();
|
|
295
|
-
if (blockHeight === undefined) {
|
|
296
|
-
return [null, NFTBindStatus.BlockchainError];
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// 生成随机密钥
|
|
300
|
-
const randKey = new Uint8Array(32);
|
|
301
|
-
crypto.getRandomValues(randKey);
|
|
302
|
-
|
|
303
|
-
// 生成登录密钥
|
|
304
|
-
const passwordBytes = new TextEncoder().encode(password);
|
|
305
|
-
const passwordHashBytes = new Uint8Array(
|
|
306
|
-
await crypto.subtle.digest("SHA-256", passwordBytes.slice(0, 2))
|
|
307
|
-
);
|
|
308
|
-
|
|
309
|
-
// 组合登录密钥种子
|
|
310
|
-
const loginKeySeed = new Uint8Array(
|
|
311
|
-
accountHashArray.length + 2 + new TextEncoder().encode(seccode).length
|
|
312
|
-
);
|
|
313
|
-
loginKeySeed.set(accountHashArray, 0);
|
|
314
|
-
loginKeySeed.set(passwordHashBytes.slice(-2), accountHashArray.length);
|
|
315
|
-
loginKeySeed.set(
|
|
316
|
-
new TextEncoder().encode(seccode),
|
|
317
|
-
accountHashArray.length + 2
|
|
318
|
-
);
|
|
319
|
-
|
|
320
|
-
// 计算登录密钥
|
|
321
|
-
const loginKeyHash = await crypto.subtle.digest("SHA-256", loginKeySeed);
|
|
322
|
-
const loginkey = new Uint8Array(loginKeyHash);
|
|
323
|
-
|
|
324
|
-
// 加密登录密钥和随机密钥
|
|
325
|
-
const loginRandKey = new Uint8Array(loginkey.length + randKey.length);
|
|
326
|
-
loginRandKey.set(loginkey, 0);
|
|
327
|
-
loginRandKey.set(randKey, loginkey.length);
|
|
328
|
-
|
|
329
|
-
const loginkeyRandEncrypt = await serverPubkey.encrypt(loginRandKey);
|
|
330
|
-
if (!loginkeyRandEncrypt) {
|
|
331
|
-
return [null, NFTBindStatus.EncryptError];
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// 准备签名数据
|
|
335
|
-
const serverPidBytes = new TextEncoder().encode(serverPid.toString());
|
|
336
|
-
const prikeyencryptHash = new Uint8Array(
|
|
337
|
-
await crypto.subtle.digest("SHA-256", prikeyencrypt as any)
|
|
338
|
-
);
|
|
339
|
-
|
|
340
|
-
// 区块高度转为小端字节序
|
|
341
|
-
const hvalue = uint32ToLittleEndianBytes(blockHeight);
|
|
342
|
-
|
|
343
|
-
// 组合预签名数据
|
|
344
|
-
const preSign = new Uint8Array(
|
|
345
|
-
accountHashArray.length +
|
|
346
|
-
accountEncrypt.length +
|
|
347
|
-
prikeyencryptHash.length +
|
|
348
|
-
hvalue.length +
|
|
349
|
-
serverPidBytes.length
|
|
350
|
-
);
|
|
351
|
-
console.log("accountHashArray:", accountHashArray);
|
|
352
|
-
console.log("accountEncrypt:", accountEncrypt);
|
|
353
|
-
console.log("prikeyencryptHash:", prikeyencryptHash);
|
|
354
|
-
console.log("hvalue:", hvalue);
|
|
355
|
-
console.log("serverPidBytes:", serverPidBytes);
|
|
356
|
-
|
|
357
|
-
let offset = 0;
|
|
358
|
-
preSign.set(accountHashArray, offset);
|
|
359
|
-
offset += accountHashArray.length;
|
|
360
|
-
preSign.set(accountEncrypt, offset);
|
|
361
|
-
offset += accountEncrypt.length;
|
|
362
|
-
preSign.set(prikeyencryptHash, offset);
|
|
363
|
-
offset += prikeyencryptHash.length;
|
|
364
|
-
preSign.set(hvalue, offset);
|
|
365
|
-
offset += hvalue.length;
|
|
366
|
-
preSign.set(serverPidBytes, offset);
|
|
367
|
-
|
|
368
|
-
// 签名
|
|
369
|
-
let signature: Uint8Array;
|
|
370
|
-
if(selfPrivkey != null){
|
|
371
|
-
signature = selfPrivkey.sign(preSign);
|
|
372
|
-
}else {
|
|
373
|
-
signature = await this.context.sign(preSign);
|
|
374
|
-
}
|
|
375
|
-
if (!signature) {
|
|
376
|
-
return [null, NFTBindStatus.SignError];
|
|
377
|
-
}
|
|
378
|
-
// 创建请求对象
|
|
379
|
-
const req = {
|
|
380
|
-
accounthashencrypt: accountHashCrypt,
|
|
381
|
-
accountencrypt: accountEncrypt,
|
|
382
|
-
prikeyencrypt2: prikeyencrypt2,
|
|
383
|
-
blockheight: blockHeight,
|
|
384
|
-
loginkeyrandencrypt: loginkeyRandEncrypt,
|
|
385
|
-
peerid: serverPidBytes,
|
|
386
|
-
signature: signature,
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
return [req, NFTBindStatus.Success];
|
|
390
|
-
} catch (error) {
|
|
391
|
-
console.error("生成账户请求失败:", error);
|
|
392
|
-
return [null, NFTBindStatus.Error];
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* 检查NFT账号是否成功绑定到用户的公钥
|
|
398
|
-
* @param nftAccount NFT账号
|
|
399
|
-
* @param pubKeyStr 公钥字符串
|
|
400
|
-
* @returns 是否成功绑定
|
|
401
|
-
*/
|
|
402
|
-
async isNftAccountBindSuccess(
|
|
403
|
-
nftAccount: string,
|
|
404
|
-
pubKeyStr: string
|
|
405
|
-
): Promise<boolean> {
|
|
406
|
-
try {
|
|
407
|
-
if (!this.chainUtil || !this.chainUtil.dcchainapi) {
|
|
408
|
-
return false;
|
|
409
|
-
}
|
|
410
|
-
const accountBytes = new TextEncoder().encode(nftAccount);
|
|
411
|
-
const accountHash = await sha256(accountBytes);
|
|
412
|
-
const nftHexAccount = "0x" + Buffer.from(accountHash).toString("hex");
|
|
413
|
-
const walletAccount =
|
|
414
|
-
await (this.chainUtil.dcchainapi?.query as any).dcNode.nftToWalletAccount(
|
|
415
|
-
nftHexAccount
|
|
416
|
-
);
|
|
417
|
-
// 比较公钥
|
|
418
|
-
return (
|
|
419
|
-
walletAccount.toString() ==
|
|
420
|
-
(pubKeyStr.indexOf("0x") === 0 ? pubKeyStr : "0x" + pubKeyStr)
|
|
421
|
-
);
|
|
422
|
-
} catch (error) {
|
|
423
|
-
console.error("检查NFT账号绑定状态失败:", error);
|
|
424
|
-
return false;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* 检查NFT账号是否已经被绑定
|
|
430
|
-
* @param nftAccount NFT账号
|
|
431
|
-
* @returns 是否被其他账号绑定
|
|
432
|
-
*/
|
|
433
|
-
async isNftAccountBinded(nftAccount: string): Promise<boolean> {
|
|
434
|
-
try {
|
|
435
|
-
if (!this.chainUtil || !this.chainUtil.dcchainapi) {
|
|
436
|
-
return false;
|
|
437
|
-
}
|
|
438
|
-
const accountBytes = new TextEncoder().encode(nftAccount);
|
|
439
|
-
const accountHash = await sha256(accountBytes);
|
|
440
|
-
const nftHexAccount = "0x" + Buffer.from(accountHash).toString("hex");
|
|
441
|
-
const walletAccount =
|
|
442
|
-
await (this.chainUtil.dcchainapi?.query as any).dcNode.nftToWalletAccount(
|
|
443
|
-
nftHexAccount
|
|
444
|
-
);
|
|
445
|
-
if (!walletAccount.toString()) {
|
|
446
|
-
return false;
|
|
447
|
-
}
|
|
448
|
-
} catch (error) {
|
|
449
|
-
console.error("检查NFT账号绑定状态失败:", error);
|
|
450
|
-
return false;
|
|
451
|
-
}
|
|
452
|
-
return true;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
/**
|
|
456
|
-
* 创建子账号,只有带有助记词的用户才能创建子账号
|
|
457
|
-
* 子账号创建后,用助记词登陆子账号App,与调用登陆了主账号的App进行授权登陆,是同一个用户
|
|
458
|
-
*
|
|
459
|
-
* @param appId 应用ID
|
|
460
|
-
* @returns [私钥字符串,基于base32编码, 错误]
|
|
461
|
-
*/
|
|
462
|
-
async generateAppAccount(
|
|
463
|
-
appId: string,
|
|
464
|
-
mnemonic: string
|
|
465
|
-
): Promise<[string | null, Error | null]> {
|
|
466
|
-
if (!mnemonic) {
|
|
467
|
-
return [null, new AccountError("Mnemonic is required")];
|
|
468
|
-
}
|
|
469
|
-
if (!appId) {
|
|
470
|
-
return [null, new AccountError("App ID is required")];
|
|
471
|
-
}
|
|
472
|
-
if (!this.context.connectedDc.nodeAddr) {
|
|
473
|
-
return [null, new AccountError("No connected node")];
|
|
474
|
-
}
|
|
475
|
-
let subPrivateKey: Ed25519PrivKey;
|
|
476
|
-
try {
|
|
477
|
-
// 生成有效的应用子账号
|
|
478
|
-
const keymanager = new KeyManager();
|
|
479
|
-
subPrivateKey = await keymanager.getEd25519KeyFromMnemonic(
|
|
480
|
-
mnemonic,
|
|
481
|
-
appId
|
|
482
|
-
);
|
|
483
|
-
// 获取公钥
|
|
484
|
-
const subPubkey = subPrivateKey.publicKey;
|
|
485
|
-
const existFlag = await this.isAppAccountExists(subPubkey.toString());
|
|
486
|
-
if (existFlag) {
|
|
487
|
-
return [subPrivateKey.string(), null];
|
|
488
|
-
}
|
|
489
|
-
// 获取当前区块高度
|
|
490
|
-
const blockHeight = await this.chainUtil?.getBlockHeight();
|
|
491
|
-
if (blockHeight === undefined) {
|
|
492
|
-
return [null, new AccountError("Failed to get blockchain height")];
|
|
493
|
-
}
|
|
494
|
-
// 获取服务器节点ID
|
|
495
|
-
const serverPidStr = this.context.connectedDc.nodeAddr.getPeerId();
|
|
496
|
-
if (!serverPidStr) {
|
|
497
|
-
return [null, new AccountError("No connected peer ID")];
|
|
498
|
-
}
|
|
499
|
-
const serverPidBytes = new TextEncoder().encode(serverPidStr);
|
|
500
|
-
|
|
501
|
-
// 生成签名数据
|
|
502
|
-
const hvalue = uint32ToLittleEndianBytes(blockHeight);
|
|
503
|
-
|
|
504
|
-
// 组合预签名数据: subPubkey + blockHeight + peerid
|
|
505
|
-
const preSign = new Uint8Array(
|
|
506
|
-
subPubkey.raw.length + hvalue.length + serverPidBytes.length
|
|
507
|
-
);
|
|
508
|
-
|
|
509
|
-
let offset = 0;
|
|
510
|
-
preSign.set(subPubkey.raw, offset);
|
|
511
|
-
offset += subPubkey.raw.length;
|
|
512
|
-
preSign.set(hvalue, offset);
|
|
513
|
-
offset += hvalue.length;
|
|
514
|
-
preSign.set(serverPidBytes, offset);
|
|
515
|
-
|
|
516
|
-
// 使用父私钥签名
|
|
517
|
-
const privateKey = await keymanager.getEd25519KeyFromMnemonic(
|
|
518
|
-
mnemonic,
|
|
519
|
-
""
|
|
520
|
-
);
|
|
521
|
-
const signature = privateKey.sign(preSign);
|
|
522
|
-
if (!signature) {
|
|
523
|
-
return [
|
|
524
|
-
null,
|
|
525
|
-
new AccountError("Failed to sign with parent private key"),
|
|
526
|
-
];
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// 获取token
|
|
530
|
-
if (!this.context.connectedDc.client) {
|
|
531
|
-
throw [null, Errors.ErrNoAccountPeerConnected];
|
|
532
|
-
}
|
|
533
|
-
if (this.context.connectedDc.client.token == "") {
|
|
534
|
-
const token = await this.context.connectedDc.client.GetToken(
|
|
535
|
-
this.context.appInfo.appId || "",
|
|
536
|
-
privateKey.publicKey.string(),
|
|
537
|
-
async (payload: Uint8Array): Promise<Uint8Array> => {
|
|
538
|
-
return privateKey.sign(payload);
|
|
539
|
-
}
|
|
540
|
-
);
|
|
541
|
-
if (!token) {
|
|
542
|
-
return [null, new AccountError("Failed to get token")];
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
// 创建请求对象
|
|
547
|
-
const req = {
|
|
548
|
-
subpubkey: subPubkey.raw,
|
|
549
|
-
blockheight: blockHeight,
|
|
550
|
-
peerid: serverPidBytes,
|
|
551
|
-
signature: signature,
|
|
552
|
-
};
|
|
553
|
-
|
|
554
|
-
const client = new AccountClient(this.context.connectedDc.client);
|
|
555
|
-
// 添加子公钥
|
|
556
|
-
await client.addSubPubkey(req);
|
|
557
|
-
// Wait for app account creation
|
|
558
|
-
let waitCount = 0;
|
|
559
|
-
while (true) {
|
|
560
|
-
// Check if app account exists
|
|
561
|
-
try {
|
|
562
|
-
const accountExists = await this.isAppAccountExists(
|
|
563
|
-
subPubkey.toString()
|
|
564
|
-
);
|
|
565
|
-
if (accountExists) {
|
|
566
|
-
break;
|
|
567
|
-
}
|
|
568
|
-
} catch (err) {
|
|
569
|
-
console.warn("Error checking app account status:", err);
|
|
570
|
-
}
|
|
571
|
-
// Sleep for 1 second
|
|
572
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
573
|
-
waitCount++;
|
|
574
|
-
if (waitCount > 30) {
|
|
575
|
-
try {
|
|
576
|
-
const accountExists = await this.isAppAccountExists(
|
|
577
|
-
subPubkey.toString()
|
|
578
|
-
);
|
|
579
|
-
if (accountExists) {
|
|
580
|
-
break;
|
|
581
|
-
}
|
|
582
|
-
} catch (err) {
|
|
583
|
-
// Ignore error on final check
|
|
584
|
-
}
|
|
585
|
-
// Timeout after ~30 seconds
|
|
586
|
-
return [null, new AccountError("Wait app account create timeout")];
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
// 返回编码后的私钥
|
|
590
|
-
return [subPrivateKey.string(), null];
|
|
591
|
-
} catch (error) {
|
|
592
|
-
console.error("Failed to generate app account:", error);
|
|
593
|
-
return [null, error instanceof Error ? error : new Error(String(error))];
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
/**
|
|
598
|
-
* Check if an application account exists
|
|
599
|
-
* @param pubkeyStr The public key string of the account to check
|
|
600
|
-
* @returns True if the account exists, false otherwise
|
|
601
|
-
*/
|
|
602
|
-
private async isAppAccountExists(pubkeyStr: string): Promise<boolean> {
|
|
603
|
-
try {
|
|
604
|
-
const account =
|
|
605
|
-
pubkeyStr.indexOf("0x") === 0 ? pubkeyStr : "0x" + pubkeyStr;
|
|
606
|
-
const user = await this.context.dcChain?.getUserInfoWithAccount(account);
|
|
607
|
-
return !!user;
|
|
608
|
-
} catch (error) {
|
|
609
|
-
return false;
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
/**
|
|
613
|
-
* 获取用户默认数据库
|
|
614
|
-
* @param threadId 数据库ID
|
|
615
|
-
* @param rk 读取密钥,主要用来加解密真正的数据,注意对数据记录进行加密和解密
|
|
616
|
-
* @param sk 服务密钥,主要用来处理传输过程加解密,主要对数据链表头进行加密和解密
|
|
617
|
-
* @param remark 备注信息
|
|
618
|
-
* @returns 用户默认数据库信息
|
|
619
|
-
*/
|
|
620
|
-
async setUserDefaultDB(
|
|
621
|
-
threadId: string,
|
|
622
|
-
rk: string,
|
|
623
|
-
sk: string,
|
|
624
|
-
remark: string,
|
|
625
|
-
vaccount?: string
|
|
626
|
-
): Promise<void> {
|
|
627
|
-
if(!this.context.publicKey){
|
|
628
|
-
throw Errors.ErrAccountPublicKeyIsNull;
|
|
629
|
-
}
|
|
630
|
-
if(!this.context.connectedDc.client){
|
|
631
|
-
throw Errors.ErrNoDcPeerConnected;
|
|
632
|
-
}
|
|
633
|
-
if(!this.context.connectedDc.nodeAddr){
|
|
634
|
-
throw Errors.ErrNodeAddrIsNull;
|
|
635
|
-
}
|
|
636
|
-
const dbinfo = threadId + "|" + rk + "|" + sk + "|" + remark;
|
|
637
|
-
const dbinfocrypto = await this.context.publicKey.encrypt(
|
|
638
|
-
new TextEncoder().encode(dbinfo)
|
|
639
|
-
);
|
|
640
|
-
const blockHeight = await this.chainUtil?.getBlockHeight();
|
|
641
|
-
if (blockHeight === undefined) {
|
|
642
|
-
throw new AccountError("Failed to get blockchain height");
|
|
643
|
-
}
|
|
644
|
-
if (this.context.connectedDc.client.token == "") {
|
|
645
|
-
const token = await this.context.connectedDc.client.GetToken(
|
|
646
|
-
this.context.appInfo.appId || "",
|
|
647
|
-
this.context.publicKey.string(),
|
|
648
|
-
async (payload: Uint8Array): Promise<Uint8Array> => {
|
|
649
|
-
return this.context.sign(payload);
|
|
650
|
-
}
|
|
651
|
-
);
|
|
652
|
-
if (!token) {
|
|
653
|
-
throw new AccountError("Failed to get token");
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
const accountClient = new AccountClient(this.context.connectedDc.client);
|
|
657
|
-
const serverPidStr = this.context.connectedDc.nodeAddr.getPeerId() || "";
|
|
658
|
-
const serverPidBytes = new TextEncoder().encode(serverPidStr);
|
|
659
|
-
// 生成签名数据
|
|
660
|
-
const hvalue = uint32ToLittleEndianBytes(blockHeight);
|
|
661
|
-
// 组合预签名数据: subPubkey + blockHeight + peerid
|
|
662
|
-
const preSign = new Uint8Array(
|
|
663
|
-
dbinfocrypto.length + hvalue.length + serverPidBytes.length
|
|
664
|
-
);
|
|
665
|
-
let offset = 0;
|
|
666
|
-
preSign.set(dbinfocrypto, offset);
|
|
667
|
-
offset += dbinfocrypto.length;
|
|
668
|
-
preSign.set(hvalue, offset);
|
|
669
|
-
offset += hvalue.length;
|
|
670
|
-
preSign.set(serverPidBytes, offset);
|
|
671
|
-
// 使用私钥签名
|
|
672
|
-
const signature = await this.context.sign(preSign);
|
|
673
|
-
|
|
674
|
-
await accountClient.setUserDefaultDB(
|
|
675
|
-
dbinfocrypto,
|
|
676
|
-
blockHeight ? blockHeight : 0,
|
|
677
|
-
serverPidStr,
|
|
678
|
-
signature,
|
|
679
|
-
vaccount
|
|
680
|
-
);
|
|
681
|
-
return;
|
|
682
|
-
}
|
|
683
|
-
}
|