web-dc-api 0.0.83 → 0.0.85
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/dc.min.js +2 -2
- package/dist/index.cjs.js +2 -2
- package/dist/index.d.ts +17 -0
- package/dist/index.esm.js +2 -2
- package/lib/common/define.ts +1 -1
- package/lib/dc.ts +1 -1
- package/lib/implements/account/manager.ts +20 -22
- package/lib/implements/aiproxy/client.ts +0 -3
- package/lib/implements/keyvalue/manager.ts +1 -1
- package/lib/modules/keyvalue-module.ts +42 -7
- package/lib/util/utils.ts +8 -8
- package/package.json +2 -2
package/lib/common/define.ts
CHANGED
package/lib/dc.ts
CHANGED
|
@@ -85,7 +85,7 @@ export class DC implements DCContext {
|
|
|
85
85
|
this.dcChain = new ChainUtil();
|
|
86
86
|
this.dcutil = new DcUtil(this.dcChain);
|
|
87
87
|
// //todo 发布注释 remove
|
|
88
|
-
|
|
88
|
+
// this.dcutil.defaultPeerId= "12D3KooWEGzh4AcbJrfZMfQb63wncBUpscMEEyiMemSWzEnjVCPf";
|
|
89
89
|
// //todo remove end
|
|
90
90
|
this.appInfo = options.appInfo || ({} as APPInfo);
|
|
91
91
|
this.accountInfo = {} as AccountInfo;
|
|
@@ -39,10 +39,8 @@ export const Errors = {
|
|
|
39
39
|
export class AccountManager {
|
|
40
40
|
dc: DcUtil;
|
|
41
41
|
chainUtil: ChainUtil | undefined;
|
|
42
|
-
connectedDc: DCConnectInfo = {};
|
|
43
42
|
context: DCContext;
|
|
44
43
|
constructor(context: DCContext) {
|
|
45
|
-
this.connectedDc = context.connectedDc;
|
|
46
44
|
this.dc = context.dcutil;
|
|
47
45
|
this.chainUtil = context.dcChain;
|
|
48
46
|
this.context = context;
|
|
@@ -50,7 +48,7 @@ export class AccountManager {
|
|
|
50
48
|
|
|
51
49
|
// 获取用户备用节点
|
|
52
50
|
getAccountNodeAddr = async (): Promise<[Multiaddr | null, Error | null]> => {
|
|
53
|
-
if (!this.connectedDc.client) {
|
|
51
|
+
if (!this.context.connectedDc.client) {
|
|
54
52
|
console.error("dcClient is null");
|
|
55
53
|
return [null, Errors.ErrNoDcPeerConnected];
|
|
56
54
|
}
|
|
@@ -78,7 +76,7 @@ export class AccountManager {
|
|
|
78
76
|
getUserInfoWithNft = async (
|
|
79
77
|
nftAccount: string
|
|
80
78
|
): Promise<[User | null, Error | null]> => {
|
|
81
|
-
if (!this.connectedDc.client) {
|
|
79
|
+
if (!this.context.connectedDc.client) {
|
|
82
80
|
console.error("dcClient is null");
|
|
83
81
|
return [null, Errors.ErrNoDcPeerConnected];
|
|
84
82
|
}
|
|
@@ -94,7 +92,7 @@ export class AccountManager {
|
|
|
94
92
|
bindAccessPeerToUser = async (
|
|
95
93
|
peerAddr: Multiaddr
|
|
96
94
|
): Promise<[boolean | null, Error | null]> => {
|
|
97
|
-
if (!this.connectedDc.client) {
|
|
95
|
+
if (!this.context.connectedDc.client) {
|
|
98
96
|
console.error("dcClient is null");
|
|
99
97
|
return [false, Errors.ErrNoDcPeerConnected];
|
|
100
98
|
}
|
|
@@ -113,7 +111,7 @@ export class AccountManager {
|
|
|
113
111
|
}
|
|
114
112
|
// 绑定节点
|
|
115
113
|
const blockHeight = await this.chainUtil.getBlockHeight();
|
|
116
|
-
const accountClient = new AccountClient(this.connectedDc.client);
|
|
114
|
+
const accountClient = new AccountClient(this.context.connectedDc.client);
|
|
117
115
|
const bindResult = await accountClient.bindAccessPeerToUser(
|
|
118
116
|
this.context,
|
|
119
117
|
blockHeight ? blockHeight : 0,
|
|
@@ -137,15 +135,15 @@ export class AccountManager {
|
|
|
137
135
|
mnemonic: string
|
|
138
136
|
): Promise<[NFTBindStatus, Error | null]> {
|
|
139
137
|
// 检查节点连接
|
|
140
|
-
if (!this.connectedDc.client) {
|
|
138
|
+
if (!this.context.connectedDc.client) {
|
|
141
139
|
return [NFTBindStatus.DcPeerNotConnected, Errors.ErrNoDcPeerConnected];
|
|
142
140
|
}
|
|
143
|
-
if (!this.connectedDc.nodeAddr) {
|
|
141
|
+
if (!this.context.connectedDc.nodeAddr) {
|
|
144
142
|
return [NFTBindStatus.DcPeerNotConnected, Errors.ErrNodeAddrIsNull];
|
|
145
143
|
}
|
|
146
144
|
|
|
147
145
|
try {
|
|
148
|
-
const connectedPeerIdStr = this.connectedDc.nodeAddr.getPeerId();
|
|
146
|
+
const connectedPeerIdStr = this.context.connectedDc.nodeAddr.getPeerId();
|
|
149
147
|
if (!connectedPeerIdStr) {
|
|
150
148
|
return [NFTBindStatus.DcPeerNotConnected, Errors.ErrNodeAddrIsNull];
|
|
151
149
|
}
|
|
@@ -167,7 +165,7 @@ export class AccountManager {
|
|
|
167
165
|
}
|
|
168
166
|
|
|
169
167
|
// 获取客户端
|
|
170
|
-
const accountClient = new AccountClient(this.connectedDc.client);
|
|
168
|
+
const accountClient = new AccountClient(this.context.connectedDc.client);
|
|
171
169
|
// 调用账户绑定API
|
|
172
170
|
await accountClient.accountBind(req, mnemonic, this.context);
|
|
173
171
|
|
|
@@ -471,7 +469,7 @@ export class AccountManager {
|
|
|
471
469
|
if (!appId) {
|
|
472
470
|
return [null, new AccountError("App ID is required")];
|
|
473
471
|
}
|
|
474
|
-
if (!this.connectedDc.nodeAddr) {
|
|
472
|
+
if (!this.context.connectedDc.nodeAddr) {
|
|
475
473
|
return [null, new AccountError("No connected node")];
|
|
476
474
|
}
|
|
477
475
|
let subPrivateKey: Ed25519PrivKey;
|
|
@@ -494,7 +492,7 @@ export class AccountManager {
|
|
|
494
492
|
return [null, new AccountError("Failed to get blockchain height")];
|
|
495
493
|
}
|
|
496
494
|
// 获取服务器节点ID
|
|
497
|
-
const serverPidStr = this.connectedDc.nodeAddr.getPeerId();
|
|
495
|
+
const serverPidStr = this.context.connectedDc.nodeAddr.getPeerId();
|
|
498
496
|
if (!serverPidStr) {
|
|
499
497
|
return [null, new AccountError("No connected peer ID")];
|
|
500
498
|
}
|
|
@@ -529,11 +527,11 @@ export class AccountManager {
|
|
|
529
527
|
}
|
|
530
528
|
|
|
531
529
|
// 获取token
|
|
532
|
-
if (!this.connectedDc.client) {
|
|
530
|
+
if (!this.context.connectedDc.client) {
|
|
533
531
|
throw [null, Errors.ErrNoAccountPeerConnected];
|
|
534
532
|
}
|
|
535
|
-
if (this.connectedDc.client.token == "") {
|
|
536
|
-
const token = await this.connectedDc.client.GetToken(
|
|
533
|
+
if (this.context.connectedDc.client.token == "") {
|
|
534
|
+
const token = await this.context.connectedDc.client.GetToken(
|
|
537
535
|
this.context.appInfo.appId || "",
|
|
538
536
|
privateKey.publicKey.string(),
|
|
539
537
|
async (payload: Uint8Array): Promise<Uint8Array> => {
|
|
@@ -553,7 +551,7 @@ export class AccountManager {
|
|
|
553
551
|
signature: signature,
|
|
554
552
|
};
|
|
555
553
|
|
|
556
|
-
const client = new AccountClient(this.connectedDc.client);
|
|
554
|
+
const client = new AccountClient(this.context.connectedDc.client);
|
|
557
555
|
// 添加子公钥
|
|
558
556
|
await client.addSubPubkey(req);
|
|
559
557
|
// Wait for app account creation
|
|
@@ -629,10 +627,10 @@ export class AccountManager {
|
|
|
629
627
|
if(!this.context.publicKey){
|
|
630
628
|
throw Errors.ErrAccountPublicKeyIsNull;
|
|
631
629
|
}
|
|
632
|
-
if(!this.connectedDc.client){
|
|
630
|
+
if(!this.context.connectedDc.client){
|
|
633
631
|
throw Errors.ErrNoDcPeerConnected;
|
|
634
632
|
}
|
|
635
|
-
if(!this.connectedDc.nodeAddr){
|
|
633
|
+
if(!this.context.connectedDc.nodeAddr){
|
|
636
634
|
throw Errors.ErrNodeAddrIsNull;
|
|
637
635
|
}
|
|
638
636
|
const dbinfo = threadId + "|" + rk + "|" + sk + "|" + remark;
|
|
@@ -643,8 +641,8 @@ export class AccountManager {
|
|
|
643
641
|
if (blockHeight === undefined) {
|
|
644
642
|
throw new AccountError("Failed to get blockchain height");
|
|
645
643
|
}
|
|
646
|
-
if (this.connectedDc.client.token == "") {
|
|
647
|
-
const token = await this.connectedDc.client.GetToken(
|
|
644
|
+
if (this.context.connectedDc.client.token == "") {
|
|
645
|
+
const token = await this.context.connectedDc.client.GetToken(
|
|
648
646
|
this.context.appInfo.appId || "",
|
|
649
647
|
this.context.publicKey.string(),
|
|
650
648
|
async (payload: Uint8Array): Promise<Uint8Array> => {
|
|
@@ -655,8 +653,8 @@ export class AccountManager {
|
|
|
655
653
|
throw new AccountError("Failed to get token");
|
|
656
654
|
}
|
|
657
655
|
}
|
|
658
|
-
const accountClient = new AccountClient(this.connectedDc.client);
|
|
659
|
-
const serverPidStr = this.connectedDc.nodeAddr.getPeerId() || "";
|
|
656
|
+
const accountClient = new AccountClient(this.context.connectedDc.client);
|
|
657
|
+
const serverPidStr = this.context.connectedDc.nodeAddr.getPeerId() || "";
|
|
660
658
|
const serverPidBytes = new TextEncoder().encode(serverPidStr);
|
|
661
659
|
// 生成签名数据
|
|
662
660
|
const hvalue = uint32ToLittleEndianBytes(blockHeight);
|
|
@@ -267,7 +267,6 @@ export class AIProxyClient {
|
|
|
267
267
|
const onEndCallback = async () => {
|
|
268
268
|
clearTimeoutTimer();
|
|
269
269
|
if (isAborted || checkAborted() || isCompleted) return;
|
|
270
|
-
console.log('*********** onEndCallback ***********1111');
|
|
271
270
|
isCompleted = true;
|
|
272
271
|
if (onStreamResponse) {
|
|
273
272
|
onStreamResponse(AIStreamResponseFlag.CONNECTION_CLOSED, "", "");
|
|
@@ -277,8 +276,6 @@ export class AIProxyClient {
|
|
|
277
276
|
const onErrorCallback = async (error: unknown) => {
|
|
278
277
|
if (isAborted || checkAborted() || isCompleted) return;
|
|
279
278
|
//不要标记完成,和清理定时器,统一由onEndCallback处理
|
|
280
|
-
// isCompleted = true; //
|
|
281
|
-
// clearTimeoutTimer();
|
|
282
279
|
if (onStreamResponse) {
|
|
283
280
|
onStreamResponse(AIStreamResponseFlag.OTHER_ERROR, "", error instanceof Error ? error.message : String(error));
|
|
284
281
|
}
|
|
@@ -79,7 +79,7 @@ export class KeyValueDB {
|
|
|
79
79
|
vaccount?: string
|
|
80
80
|
): Promise<[string | null, Error | null]> {
|
|
81
81
|
if (!writerPubkey) {//没有指定写入者,则获取该key的最新值
|
|
82
|
-
const [values, err] = await this.getWithIndex("
|
|
82
|
+
const [values, err] = await this.getWithIndex("indexkey_keyself_" + key, "", 1, "", Direction.Reverse, 0, vaccount);
|
|
83
83
|
if (err) {
|
|
84
84
|
return [null, err];
|
|
85
85
|
}
|
|
@@ -9,7 +9,7 @@ import { createLogger } from "../util/logger";
|
|
|
9
9
|
import { ThemeAuthInfo, ThemeComment } from "../common/types/types";
|
|
10
10
|
import { Direction } from "../common/define";
|
|
11
11
|
import { ThemePermission } from "../common/constants";
|
|
12
|
-
import {
|
|
12
|
+
import {padPositiveInt20} from "../util/utils";
|
|
13
13
|
const logger = createLogger('KeyValueModule');
|
|
14
14
|
const indexkey_dckv = "indexkey_dckv"; //索引键名,keyvalue设置过程中key本身的索引键
|
|
15
15
|
/**
|
|
@@ -167,7 +167,7 @@ export class KeyValueModule implements DCModule, IKeyValueOperations {
|
|
|
167
167
|
for (const index of indexArray) {
|
|
168
168
|
let indexValue = "";
|
|
169
169
|
if( index.type === "number" ){ //
|
|
170
|
-
indexValue =
|
|
170
|
+
indexValue = padPositiveInt20(index.value);
|
|
171
171
|
}else{
|
|
172
172
|
indexValue = index.value;
|
|
173
173
|
}
|
|
@@ -179,10 +179,6 @@ export class KeyValueModule implements DCModule, IKeyValueOperations {
|
|
|
179
179
|
} catch (error) {
|
|
180
180
|
logger.error(`设置索引,解析失败:`, error);
|
|
181
181
|
}
|
|
182
|
-
//追加时间戳索引,保证每次写入的唯一性
|
|
183
|
-
const timestamp = Date.now();
|
|
184
|
-
const timestampStr = padPositiveInt30(timestamp);
|
|
185
|
-
strIndexs += `dc_timestamp_index:${timestampStr}`;
|
|
186
182
|
const res = await kvdb.set(key, value, strIndexs, vaccount);
|
|
187
183
|
return res;
|
|
188
184
|
} catch (error) {
|
|
@@ -322,7 +318,7 @@ export class KeyValueModule implements DCModule, IKeyValueOperations {
|
|
|
322
318
|
const offset = options.offset? options.offset: 0;
|
|
323
319
|
let indexValueStr = "";
|
|
324
320
|
if( options.type === "number" ){ //
|
|
325
|
-
indexValueStr =
|
|
321
|
+
indexValueStr = padPositiveInt20(indexValue);
|
|
326
322
|
}
|
|
327
323
|
try {
|
|
328
324
|
const res = await kvdb.getWithIndex(indexKey, indexValueStr, limit,seekKey, direction,offset, vaccount);
|
|
@@ -331,6 +327,45 @@ export class KeyValueModule implements DCModule, IKeyValueOperations {
|
|
|
331
327
|
return [null, error instanceof Error ? error : new Error(String(error))];
|
|
332
328
|
}
|
|
333
329
|
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* 按设置时间顺序获取主题的的键值对列表
|
|
333
|
+
* @param kvdb KeyValueDB实例
|
|
334
|
+
* @param limit 返回结果数量限制
|
|
335
|
+
* @param seekKey 查询起始键,用于分页查询
|
|
336
|
+
* @param direction 查询方向
|
|
337
|
+
* @param offset 结果偏移量
|
|
338
|
+
* @param vaccount 可选的虚拟账户
|
|
339
|
+
* @returns [值列表数组生成的json字符串, 错误信息] 数组的每个元素的格式: key:value$$$dckv_extra$$${'dc_timestamp':'%d','dc_opuser':'%s'}
|
|
340
|
+
*/
|
|
341
|
+
async getWithTimeOrder(
|
|
342
|
+
kvdb: KeyValueDB,
|
|
343
|
+
timestamp: number,//毫秒时间戳
|
|
344
|
+
options: { limit?: number; seekKey?: string; direction?: Direction; offset?: number },
|
|
345
|
+
vaccount?: string
|
|
346
|
+
): Promise<[string | null, Error | null]> {
|
|
347
|
+
const err = this.assertInitialized();
|
|
348
|
+
if (err) {
|
|
349
|
+
return [null, err];
|
|
350
|
+
}
|
|
351
|
+
let timestampStr = "";
|
|
352
|
+
if( timestamp > 0 ){
|
|
353
|
+
//把毫秒时间转为微妙时间戳字符串,与DC节点存储的时间戳格式一致
|
|
354
|
+
timestampStr = padPositiveInt20(timestamp * 1000);
|
|
355
|
+
//前面补0,保证长度为20位
|
|
356
|
+
timestampStr = timestampStr.padStart(20, "0");
|
|
357
|
+
}
|
|
358
|
+
const limit = options.limit ? options.limit : 10;
|
|
359
|
+
const seekKey = options.seekKey ? options.seekKey : "";
|
|
360
|
+
const direction = options.direction ? options.direction : Direction.Forward;
|
|
361
|
+
const offset = options.offset ? options.offset : 0;
|
|
362
|
+
try {
|
|
363
|
+
const res = await kvdb.getWithIndex("indexkey_timestamp", timestampStr, limit, seekKey, direction, offset, vaccount);
|
|
364
|
+
return res;
|
|
365
|
+
} catch (error) {
|
|
366
|
+
return [null, error instanceof Error ? error : new Error(String(error))];
|
|
367
|
+
}
|
|
368
|
+
}
|
|
334
369
|
|
|
335
370
|
|
|
336
371
|
/**
|
package/lib/util/utils.ts
CHANGED
|
@@ -236,16 +236,16 @@ function jsonStringify(value: any): string {
|
|
|
236
236
|
|
|
237
237
|
/**
|
|
238
238
|
* 将非负数字字符串(可带小数)格式化:
|
|
239
|
-
* - 仅对整数部分左侧补零至
|
|
239
|
+
* - 仅对整数部分左侧补零至 20 位
|
|
240
240
|
* - 小数部分(若有)原样保留
|
|
241
241
|
* - 不进行数值运算,避免精度问题
|
|
242
242
|
* 例:
|
|
243
|
-
* - "123" -> "
|
|
244
|
-
* - "123.45" -> "
|
|
245
|
-
* - "0.5" -> "
|
|
243
|
+
* - "123" -> "00000000000000000123"
|
|
244
|
+
* - "123.45" -> "00000000000000000123.45"
|
|
245
|
+
* - "0.5" -> "00000000000000000000.5"
|
|
246
246
|
*/
|
|
247
247
|
|
|
248
|
-
function
|
|
248
|
+
function padPositiveInt20(v: string | number): string {
|
|
249
249
|
const s0 = String(v).trim();
|
|
250
250
|
// 仅允许非负数字,支持一处小数点(不允许科学计数法/负号)
|
|
251
251
|
if (!/^\d+(\.\d+)?$/.test(s0)) throw new Error("只接受非负数字(可带小数)");
|
|
@@ -258,9 +258,9 @@ function padPositiveInt30(v: string | number): string {
|
|
|
258
258
|
// 去掉整数部分前导 0
|
|
259
259
|
intPart = intPart.replace(/^0+/, "") || "0";
|
|
260
260
|
|
|
261
|
-
if (intPart.length > 30) throw new Error("整数部分超过
|
|
261
|
+
if (intPart.length > 30) throw new Error("整数部分超过 20 位宽度");
|
|
262
262
|
|
|
263
|
-
const paddedInt = intPart.padStart(
|
|
263
|
+
const paddedInt = intPart.padStart(20, "0");
|
|
264
264
|
return fracPart ? `${paddedInt}.${fracPart}` : paddedInt;
|
|
265
265
|
}
|
|
266
266
|
|
|
@@ -285,5 +285,5 @@ export {
|
|
|
285
285
|
parseUint32,
|
|
286
286
|
hexToAscii,
|
|
287
287
|
jsonStringify,
|
|
288
|
-
|
|
288
|
+
padPositiveInt20
|
|
289
289
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "web-dc-api",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.85",
|
|
4
4
|
"description": "web相关的dcapi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"browser": "dist/dc.min.js",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"datastore-idb": "^3.0.1",
|
|
60
60
|
"datastore-level": "^11.0.1",
|
|
61
61
|
"google-protobuf": "~3.21.2",
|
|
62
|
-
"grpc-libp2p-client": "^0.0.
|
|
62
|
+
"grpc-libp2p-client": "^0.0.19",
|
|
63
63
|
"helia": "5.3.0",
|
|
64
64
|
"interface-ipld-format": "^1.0.1",
|
|
65
65
|
"it-to-buffer": "^4.0.7",
|