@caict/bop-typescript-sdk 1.0.0

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.
Files changed (115) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +5 -0
  4. package/README.md +112 -0
  5. package/package.json +90 -0
  6. package/src/bop/bop-base/README.md +5 -0
  7. package/src/bop/bop-base/base.ts +366 -0
  8. package/src/bop/bop-base/index.ts +83 -0
  9. package/src/bop/bop-base/permit.ts +116 -0
  10. package/src/bop/bop-base/test/base.test.ts +867 -0
  11. package/src/bop/bop-base/test/index.test.ts +69 -0
  12. package/src/bop/bop-base/test/permit.test.ts +125 -0
  13. package/src/bop/bop-base/tsconfig.json +8 -0
  14. package/src/bop/bop-proto/README.md +2 -0
  15. package/src/bop/bop-proto/bop-ws.proto +266 -0
  16. package/src/bop/bop-proto/bop-ws.ts +4447 -0
  17. package/src/bop/bop-proto/bop.proto +898 -0
  18. package/src/bop/bop-proto/bop.ts +12890 -0
  19. package/src/bop/bop-proto/tsconfig.json +8 -0
  20. package/src/bop/bop-ws/index.ts +315 -0
  21. package/src/bop/bop-ws/sample/sample.ts +107 -0
  22. package/src/bop/bop-ws/tsconfig.json +8 -0
  23. package/src/bop/index.ts +14 -0
  24. package/src/bop-sdk/index.ts +22 -0
  25. package/src/bop-sdk/interface/abstract-service/abstract-account.ts +23 -0
  26. package/src/bop-sdk/interface/abstract-service/abstract-chain.ts +9 -0
  27. package/src/bop-sdk/interface/abstract-service/abstract-contract.ts +16 -0
  28. package/src/bop-sdk/interface/abstract-service/abstract-ledger.ts +15 -0
  29. package/src/bop-sdk/interface/abstract-service/abstract-provider.ts +13 -0
  30. package/src/bop-sdk/interface/abstract-service/abstract-signer.ts +133 -0
  31. package/src/bop-sdk/interface/abstract-service/abstract-transaction.ts +86 -0
  32. package/src/bop-sdk/interface/provider-ws.ts +10 -0
  33. package/src/bop-sdk/interface/provider.ts +22 -0
  34. package/src/bop-sdk/interface/service/3rd.ts +54 -0
  35. package/src/bop-sdk/interface/service/account.ts +86 -0
  36. package/src/bop-sdk/interface/service/chain.ts +27 -0
  37. package/src/bop-sdk/interface/service/contract.ts +51 -0
  38. package/src/bop-sdk/interface/service/helper.ts +426 -0
  39. package/src/bop-sdk/interface/service/ledger.ts +75 -0
  40. package/src/bop-sdk/interface/service/offline/check/index.js +138 -0
  41. package/src/bop-sdk/interface/service/offline/common/constant.js +6 -0
  42. package/src/bop-sdk/interface/service/offline/common/snowFlakeUtils.js +192 -0
  43. package/src/bop-sdk/interface/service/offline/common/util.js +511 -0
  44. package/src/bop-sdk/interface/service/offline/exception/customErrors.js +29 -0
  45. package/src/bop-sdk/interface/service/offline/exception/errors.js +90 -0
  46. package/src/bop-sdk/interface/service/offline/exception/index.js +5 -0
  47. package/src/bop-sdk/interface/service/offline/operation/accountCreateOperation.js +28 -0
  48. package/src/bop-sdk/interface/service/offline/operation/accountSetMetadataOperation.js +44 -0
  49. package/src/bop-sdk/interface/service/offline/operation/accountSetPrivilegeOperation.js +49 -0
  50. package/src/bop-sdk/interface/service/offline/operation/contractCreateOperation.js +43 -0
  51. package/src/bop-sdk/interface/service/offline/operation/contractInvokeOperation.js +42 -0
  52. package/src/bop-sdk/interface/service/offline/operation/contractInvokeRequestOperation.js +69 -0
  53. package/src/bop-sdk/interface/service/offline/operation/gasSendOperation.js +29 -0
  54. package/src/bop-sdk/interface/service/offline/operation/gasSendRequestOperation.js +61 -0
  55. package/src/bop-sdk/interface/service/offline/operation/index.js +20 -0
  56. package/src/bop-sdk/interface/service/offline/proto/chain_pb.js +12079 -0
  57. package/src/bop-sdk/interface/service/offline/proto/common_pb.js +2867 -0
  58. package/src/bop-sdk/interface/service/offline/transaction/index.js +988 -0
  59. package/src/bop-sdk/interface/service/offline/transaction/operations.js +188 -0
  60. package/src/bop-sdk/interface/service/offline/validate/account.js +152 -0
  61. package/src/bop-sdk/interface/service/offline/validate/contract.js +101 -0
  62. package/src/bop-sdk/interface/service/offline/validate/index.js +10 -0
  63. package/src/bop-sdk/interface/service/offline/validate/transaction.js +51 -0
  64. package/src/bop-sdk/interface/service/transaction.ts +731 -0
  65. package/src/bop-sdk/interface/signer.ts +46 -0
  66. package/src/bop-sdk/interface/test/3rd.test.ts +1571 -0
  67. package/src/bop-sdk/interface/test/account.test.ts +284 -0
  68. package/src/bop-sdk/interface/test/chain.test.ts +45 -0
  69. package/src/bop-sdk/interface/test/contract.test.ts +283 -0
  70. package/src/bop-sdk/interface/test/ledger.test.ts +166 -0
  71. package/src/bop-sdk/interface/test/provider.test.ts +407 -0
  72. package/src/bop-sdk/interface/test/signer.test.ts +105 -0
  73. package/src/bop-sdk/interface/test/transaction.test.ts +713 -0
  74. package/src/bop-sdk/proto/bop-sdk-common.proto +159 -0
  75. package/src/bop-sdk/proto/bop-sdk-common.ts +829 -0
  76. package/src/bop-sdk/proto/bop-sdk-interface.proto +581 -0
  77. package/src/bop-sdk/proto/bop-sdk-interface.ts +10839 -0
  78. package/src/bop-sdk/proto/bop-sdk-utils.proto +86 -0
  79. package/src/bop-sdk/proto/bop-sdk-utils.ts +1495 -0
  80. package/src/bop-sdk/utils/abi/abi-coder.ts +147 -0
  81. package/src/bop-sdk/utils/abi/address.ts +109 -0
  82. package/src/bop-sdk/utils/abi/bignumber.ts +403 -0
  83. package/src/bop-sdk/utils/abi/bytes.ts +565 -0
  84. package/src/bop-sdk/utils/abi/coders/abstract-coder.ts +239 -0
  85. package/src/bop-sdk/utils/abi/coders/address.ts +58 -0
  86. package/src/bop-sdk/utils/abi/coders/anonymous.ts +25 -0
  87. package/src/bop-sdk/utils/abi/coders/array.ts +275 -0
  88. package/src/bop-sdk/utils/abi/coders/boolean.ts +21 -0
  89. package/src/bop-sdk/utils/abi/coders/bytes.ts +36 -0
  90. package/src/bop-sdk/utils/abi/coders/fixed-bytes.ts +35 -0
  91. package/src/bop-sdk/utils/abi/coders/null.ts +25 -0
  92. package/src/bop-sdk/utils/abi/coders/number.ts +56 -0
  93. package/src/bop-sdk/utils/abi/coders/string.ts +24 -0
  94. package/src/bop-sdk/utils/abi/coders/tuple.ts +73 -0
  95. package/src/bop-sdk/utils/abi/constants/addresses.ts +1 -0
  96. package/src/bop-sdk/utils/abi/constants/bignumbers.ts +30 -0
  97. package/src/bop-sdk/utils/abi/constants/hashes.ts +2 -0
  98. package/src/bop-sdk/utils/abi/constants/index.ts +15 -0
  99. package/src/bop-sdk/utils/abi/constants/strings.ts +2 -0
  100. package/src/bop-sdk/utils/abi/fragments.ts +1243 -0
  101. package/src/bop-sdk/utils/abi/id.ts +6 -0
  102. package/src/bop-sdk/utils/abi/index.ts +46 -0
  103. package/src/bop-sdk/utils/abi/interface.ts +921 -0
  104. package/src/bop-sdk/utils/abi/keccak256.ts +9 -0
  105. package/src/bop-sdk/utils/abi/properties.ts +172 -0
  106. package/src/bop-sdk/utils/abi/strings/bytes32.ts +40 -0
  107. package/src/bop-sdk/utils/abi/strings/idna.ts +258 -0
  108. package/src/bop-sdk/utils/abi/strings/index.ts +28 -0
  109. package/src/bop-sdk/utils/abi/strings/utf8.ts +373 -0
  110. package/src/bop-sdk/utils/encryption-address.ts +501 -0
  111. package/src/bop-sdk/utils/encryption-crypto.ts +427 -0
  112. package/src/bop-sdk/utils/encryption-mnemonics.ts +120 -0
  113. package/src/bop-sdk/utils/index.ts +27 -0
  114. package/src/bop-sdk/utils/logger.ts +480 -0
  115. package/src/index.ts +35 -0
@@ -0,0 +1,366 @@
1
+ import {
2
+ HelloResponse,
3
+ HelloResult,
4
+ GetAccountRequest,
5
+ GetAccountResponse,
6
+ GetAccountBaseRequest,
7
+ GetAccountBaseResponse,
8
+ GetAccountMetadataRequest,
9
+ GetAccountMetadataResponse,
10
+ GetLedgerRequest,
11
+ GetLedgerResponse,
12
+ SubmitTransactionRequest,
13
+ SubmitTransactionResponse,
14
+ GetTransactionHistoryRequest,
15
+ GetTransactionHistoryResponse,
16
+ TestTransactionRequest,
17
+ TestTransactionResponse,
18
+ CallContractRequest,
19
+ CallContractResponse,
20
+ QueryReturn,
21
+ QueryRequest,
22
+ QueryResponse,
23
+ QueryRequest_TxType,
24
+ GetTransactionCacheRequest,
25
+ GetTransactionCacheRequest_PoolType,
26
+ GetTransactionCacheChainResponse,
27
+ GetTransactionCachePlatResponse,
28
+ DiscardRequest,
29
+ DiscardResponse,
30
+ GetTxCacheSizeResponse,
31
+ GetTxCacheSizeResult,
32
+ StatusCodes,
33
+ } from "../bop-proto/bop";
34
+
35
+ import JSONbig from "json-bigint";
36
+
37
+ export class BaseService {
38
+ private readonly apiKey: string;
39
+ private readonly host: string;
40
+ private readonly apiSecret: string;
41
+ private readonly baseUrl: string;
42
+
43
+ private _hasApiSecret: boolean;
44
+
45
+ constructor(host: string, apiKey: string, apiSecret: string) {
46
+ this.host = host;
47
+ this.apiKey = apiKey;
48
+ this.apiSecret = apiSecret;
49
+ this.baseUrl = `${this.host}/base/${this.apiKey}`;
50
+ this._hasApiSecret = !(this.apiSecret === "");
51
+ }
52
+
53
+ private async fetchData(
54
+ endpoint: string,
55
+ params: any,
56
+ method: "GET" | "POST" = "GET",
57
+ timeout: number = 10000, // 默认超时时间为10秒
58
+ ): Promise<any> {
59
+ // 创建一个AbortController实例
60
+ const controller = new AbortController();
61
+ const { signal } = controller;
62
+ // 设置一个超时
63
+ const timeoutId = setTimeout(() => {
64
+ controller.abort();
65
+ throw new Error("Request timed out");
66
+ }, timeout);
67
+ try {
68
+ let url = `${this.baseUrl}/${endpoint}`;
69
+ if (!url.startsWith("http://") && !url.startsWith("https://")) {
70
+ throw new Error("URL must start with 'http://' or 'https://'");
71
+ }
72
+ const headers = {
73
+ "Content-Type": "application/json",
74
+ ...(this._hasApiSecret ? { "api-secret": this.apiSecret } : {}),
75
+ };
76
+ // 对params进行判断,如果是GET请求,则将params转为URL查询字符串并附加到URL上
77
+ let queryString = "";
78
+ if (method === "GET" && params) {
79
+ queryString = new URLSearchParams(params).toString();
80
+ if (queryString) {
81
+ url += `?${queryString}`;
82
+ }
83
+ }
84
+
85
+ // 创建body,仅在POST请求且params存在时创建
86
+ let body: string | null = null;
87
+ if (method === "POST" && params) {
88
+ body = JSON.stringify(params);
89
+ }
90
+
91
+ //console.log(url);
92
+ const response = await fetch(url, {
93
+ method,
94
+ headers,
95
+ body,
96
+ signal, // 将signal传递给fetch
97
+ });
98
+
99
+ if (!response.ok) {
100
+ throw new Error(
101
+ `HTTP error! Status: ${response.status}, Message: ${response.statusText}`,
102
+ );
103
+ }
104
+ const responseText = await response.text();
105
+ const data = JSONbig.parse(responseText);
106
+ clearTimeout(timeoutId); // 请求成功,清除超时计时器
107
+ return data;
108
+ } catch (error) {
109
+ clearTimeout(timeoutId); // 无论请求是否成功,都清除超时计时器
110
+ let errorDesc = "invalid url";
111
+ if (typeof error === "string") {
112
+ errorDesc = error;
113
+ } else if (error instanceof Error) {
114
+ errorDesc = error.message;
115
+ }
116
+
117
+ const obj = {
118
+ error_code: StatusCodes.URL_ERROR,
119
+ error_desc: errorDesc,
120
+ };
121
+ return obj;
122
+ }
123
+ }
124
+
125
+ public async hello(): Promise<HelloResponse> {
126
+ let helloResponse: HelloResponse;
127
+ helloResponse = HelloResponse.fromJSON(await this.fetchData("/hello", {}));
128
+ if (helloResponse.errorCode === 0) {
129
+ helloResponse.errorCode = 0;
130
+ helloResponse.errorDesc = "ok";
131
+ helloResponse.result = HelloResult.fromJSON(
132
+ await this.fetchData("/hello", {}),
133
+ );
134
+ helloResponse.success = true;
135
+ }
136
+
137
+ return helloResponse;
138
+ }
139
+
140
+ public async getAccount(
141
+ params: GetAccountRequest,
142
+ ): Promise<GetAccountResponse> {
143
+ return GetAccountResponse.fromJSON(
144
+ await this.fetchData("/getAccount", params),
145
+ );
146
+ }
147
+
148
+ public async getAccountBase(
149
+ params: GetAccountBaseRequest,
150
+ ): Promise<GetAccountBaseResponse> {
151
+ return GetAccountBaseResponse.fromJSON(
152
+ await this.fetchData("/getAccountBase", params),
153
+ );
154
+ }
155
+
156
+ public async getAccountMetaData(
157
+ params: GetAccountMetadataRequest,
158
+ ): Promise<GetAccountMetadataResponse> {
159
+ return GetAccountMetadataResponse.fromJSON(
160
+ await this.fetchData("/getAccountMetaData", params),
161
+ );
162
+ }
163
+
164
+ public async getLedger(params: GetLedgerRequest): Promise<GetLedgerResponse> {
165
+ interface InternalGetLedgerRequest {
166
+ seq?: number;
167
+ with_validator?: boolean;
168
+ with_leader?: boolean;
169
+ }
170
+
171
+ let request: InternalGetLedgerRequest = {};
172
+
173
+ // 复制并转换 params 中的属性到 request 中
174
+ if (params.seq !== undefined) request.seq = params.seq;
175
+ if (params.withLeader !== undefined)
176
+ request.with_leader = params.withLeader;
177
+ if (params.withValidator !== undefined)
178
+ request.with_validator = params.withValidator;
179
+
180
+ return GetLedgerResponse.fromJSON(
181
+ await this.fetchData("/getLedger", request),
182
+ );
183
+ }
184
+
185
+ public async submitTransaction(
186
+ params: SubmitTransactionRequest,
187
+ ): Promise<SubmitTransactionResponse> {
188
+ console.log(JSON.stringify(SubmitTransactionRequest.toJSON(params)));
189
+
190
+ return SubmitTransactionResponse.fromJSON(
191
+ await this.fetchData(
192
+ "/submitTransaction",
193
+ SubmitTransactionRequest.toJSON(params),
194
+ "POST",
195
+ ),
196
+ );
197
+ }
198
+
199
+ public async getTransactionHistory(
200
+ params: GetTransactionHistoryRequest,
201
+ ): Promise<GetTransactionHistoryResponse> {
202
+ interface InternalGetTransactionHistoryRequest {
203
+ hash?: string | undefined;
204
+ ledger_seq?: number | undefined;
205
+ start?: number | undefined;
206
+ limit?: number | undefined;
207
+ }
208
+
209
+ let request: InternalGetTransactionHistoryRequest = {};
210
+
211
+ if (params.hash !== undefined) request.hash = params.hash;
212
+ if (params.ledgerSeq !== undefined) request.ledger_seq = params.ledgerSeq;
213
+ if (params.start !== undefined) request.start = params.start;
214
+ if (params.limit !== undefined) request.limit = params.limit;
215
+
216
+ return GetTransactionHistoryResponse.fromJSON(
217
+ await this.fetchData("/getTransactionHistory", request),
218
+ );
219
+ }
220
+
221
+ public async testTransaction(
222
+ params: TestTransactionRequest,
223
+ ): Promise<TestTransactionResponse> {
224
+ console.log(JSON.stringify(TestTransactionRequest.toJSON(params)));
225
+ return TestTransactionResponse.fromJSON(
226
+ await this.fetchData(
227
+ "/testTransaction",
228
+ TestTransactionRequest.toJSON(params),
229
+ "POST",
230
+ ),
231
+ );
232
+ }
233
+
234
+ public async callContract(
235
+ params: CallContractRequest,
236
+ ): Promise<CallContractResponse> {
237
+ params.optType = 2; //query
238
+
239
+ function parseCallContractResponse(data: any): CallContractResponse {
240
+ const queryRets: QueryReturn[] = (data.result?.query_rets || []).map(
241
+ (queryRet) => ({
242
+ error: JSON.stringify(queryRet.error), // 将error对象转换为字符串
243
+ result: queryRet.result ? JSON.stringify(queryRet.result) : undefined, // 将result对象转换为字符串(如果存在)
244
+ }),
245
+ );
246
+
247
+ return {
248
+ result: {
249
+ queryRets: queryRets.length > 0 ? queryRets : undefined, // 如果queryRets数组为空,则不设置该字段
250
+ },
251
+ success: data.success,
252
+ errorCode: data.error_code,
253
+ errorDesc: data.error_desc,
254
+ trace: data.trace,
255
+ };
256
+ }
257
+ return parseCallContractResponse(
258
+ await this.fetchData(
259
+ "/callContract",
260
+ CallContractRequest.toJSON(params),
261
+ "POST",
262
+ ),
263
+ );
264
+ }
265
+
266
+ public async query(params: QueryRequest): Promise<QueryResponse> {
267
+ interface InternalQueryRequest {
268
+ bid?: string | undefined;
269
+ hash?: string | undefined;
270
+ tx_id?: string | undefined;
271
+ start_time?: string | undefined;
272
+ end_time?: string | undefined;
273
+ tx_type?: QueryRequest_TxType | undefined;
274
+ page?: number | undefined;
275
+ page_size?: number | undefined;
276
+ ledger_seq?: number | undefined;
277
+ }
278
+
279
+ let request: InternalQueryRequest = {};
280
+ if (params.bid !== undefined) request.bid = params.bid;
281
+ if (params.hash !== undefined) request.hash = params.hash;
282
+ if (params.txId !== undefined) request.tx_id = params.txId;
283
+ if (params.startTime !== undefined) request.start_time = params.startTime;
284
+ if (params.endTime !== undefined) request.end_time = params.endTime;
285
+ if (params.txType !== undefined) request.tx_type = params.txType;
286
+ if (params.page !== undefined) request.page = params.page;
287
+ if (params.pageSize !== undefined) request.page_size = params.pageSize;
288
+ if (params.ledgerSeq !== undefined) request.ledger_seq = params.ledgerSeq;
289
+
290
+ return QueryResponse.fromJSON(await this.fetchData("/query", request));
291
+ }
292
+
293
+ public async getTransactionCachePlat(
294
+ params: GetTransactionCacheRequest,
295
+ ): Promise<GetTransactionCachePlatResponse> {
296
+ interface InternalGetTransactionCacheRequest {
297
+ pool_type?: GetTransactionCacheRequest_PoolType | undefined;
298
+ limit?: number | undefined;
299
+ hash?: string | undefined;
300
+ address?: string | undefined;
301
+ }
302
+
303
+ let request: InternalGetTransactionCacheRequest = {};
304
+ if (params.limit !== undefined) request.limit = params.limit;
305
+ if (params.hash !== undefined) request.hash = params.hash;
306
+ if (params.address !== undefined) request.address = params.address;
307
+ request.pool_type = GetTransactionCacheRequest_PoolType.PLATFORM;
308
+
309
+ return GetTransactionCachePlatResponse.fromJSON(
310
+ await this.fetchData("/getTransactionCache", request),
311
+ );
312
+ }
313
+
314
+ public async getTransactionCacheChain(
315
+ params: GetTransactionCacheRequest,
316
+ ): Promise<GetTransactionCacheChainResponse> {
317
+ interface InternalGetTransactionCacheRequest {
318
+ pool_type?: GetTransactionCacheRequest_PoolType | undefined;
319
+ limit?: number | undefined;
320
+ hash?: string | undefined;
321
+ address?: string | undefined;
322
+ }
323
+
324
+ let request: InternalGetTransactionCacheRequest = {};
325
+ if (params.limit !== undefined) request.limit = params.limit;
326
+ if (params.hash !== undefined) request.hash = params.hash;
327
+ if (params.address !== undefined) request.address = params.address;
328
+ request.pool_type = GetTransactionCacheRequest_PoolType.CHAIN;
329
+ return GetTransactionCacheChainResponse.fromJSON(
330
+ await this.fetchData("/getTransactionCache", request),
331
+ );
332
+ }
333
+
334
+ public async discard(params: DiscardRequest): Promise<DiscardResponse> {
335
+ interface InternalDiscardResponse {
336
+ hash?: string | undefined;
337
+ page?: number | undefined;
338
+ page_size?: number | undefined;
339
+ }
340
+
341
+ let request: InternalDiscardResponse = {};
342
+ if (params.hash !== undefined) request.hash = params.hash;
343
+ if (params.page !== undefined) request.page = params.page;
344
+ if (params.pageSize !== undefined) request.page_size = params.pageSize;
345
+ return DiscardResponse.fromJSON(
346
+ await this.fetchData("/query/discard", request),
347
+ );
348
+ }
349
+
350
+ public async getTxCacheSize(): Promise<GetTxCacheSizeResponse> {
351
+ let getTxCacheSizeResponse: GetTxCacheSizeResponse;
352
+ getTxCacheSizeResponse = GetTxCacheSizeResponse.fromJSON(
353
+ await this.fetchData("/getTxCacheSize", {}),
354
+ );
355
+ if (getTxCacheSizeResponse.errorCode === 0) {
356
+ getTxCacheSizeResponse.errorCode = 0;
357
+ getTxCacheSizeResponse.errorDesc = "ok";
358
+ getTxCacheSizeResponse.result = GetTxCacheSizeResult.fromJSON(
359
+ await this.fetchData("/getTxCacheSize", {}),
360
+ );
361
+ getTxCacheSizeResponse.success = true;
362
+ }
363
+
364
+ return getTxCacheSizeResponse;
365
+ }
366
+ }
@@ -0,0 +1,83 @@
1
+ import { PermitService } from "./permit";
2
+ import { BaseService } from "./base";
3
+
4
+ export class Config {
5
+ constructor(
6
+ public readonly host: string,
7
+ public readonly apiKey: string,
8
+ public readonly apiSecret: string,
9
+ ) {}
10
+ }
11
+
12
+ class ServiceFactory {
13
+ private readonly config: Config;
14
+
15
+ constructor(config: Config) {
16
+ this.config = config;
17
+ }
18
+
19
+ createPermitService(): PermitService {
20
+ return new PermitService(this.config.host);
21
+ }
22
+
23
+ createBaseService(): BaseService {
24
+ return new BaseService(
25
+ this.config.host,
26
+ this.config.apiKey,
27
+ this.config.apiSecret,
28
+ );
29
+ }
30
+ }
31
+
32
+ export class BopInterface {
33
+ private permitService: PermitService;
34
+ private baseService: BaseService;
35
+
36
+ constructor(config: Config) {
37
+ const factory = new ServiceFactory(config);
38
+ this.permitService = factory.createPermitService();
39
+ this.baseService = factory.createBaseService();
40
+ }
41
+
42
+ public getPermitService(): PermitService {
43
+ return this.permitService;
44
+ }
45
+
46
+ public getBaseService(): BaseService {
47
+ return this.baseService;
48
+ }
49
+
50
+ // 调用服务方法
51
+ public callService(methodName: string, ...args: any[]): any {
52
+ const [prefix, functionName] = methodName.split("_", 2);
53
+
54
+ switch (prefix) {
55
+ case "permit":
56
+ return this.callPermitService(functionName, ...args);
57
+ case "base":
58
+ return this.callBaseService(functionName, ...args);
59
+ default:
60
+ throw new Error(`Unknown service prefix: ${prefix}`);
61
+ }
62
+ }
63
+
64
+ // 调用 PermitService 的方法
65
+ private callPermitService(methodName: string, ...args: any[]): any {
66
+ const method = this.permitService[methodName] as Function;
67
+ if (!method) {
68
+ throw new Error(`Method ${methodName} not found in PermitService`);
69
+ }
70
+ const boundMethod = method.bind(this.permitService);
71
+ return boundMethod(...args);
72
+ }
73
+
74
+ // 调用 BaseService 的方法
75
+ private callBaseService(methodName: string, ...args: any[]): any {
76
+ const method = this.baseService[methodName] as Function;
77
+ if (!method) {
78
+ throw new Error(`Method ${methodName} not found in BaseService`);
79
+ }
80
+ const boundMethod = method.bind(this.baseService);
81
+ return boundMethod(...args);
82
+ }
83
+ }
@@ -0,0 +1,116 @@
1
+ import {
2
+ ApplyRequest,
3
+ ApplyResponse,
4
+ ApplyStatusRequest,
5
+ ApplyStatusResponse,
6
+ DetailRequest,
7
+ DetailResponse,
8
+ StatusCodes,
9
+ } from "../bop-proto/bop";
10
+
11
+ import JSONbig from "json-bigint";
12
+
13
+ export class PermitService {
14
+ private readonly host: string;
15
+ private readonly baseUrl: string;
16
+
17
+ private readonly _hasApiSecret: boolean;
18
+
19
+ constructor(host: string) {
20
+ this.host = host;
21
+ this.baseUrl = `${this.host}/permit`;
22
+ this._hasApiSecret = false;
23
+ }
24
+
25
+ private async fetchData(
26
+ endpoint: string,
27
+ params: any,
28
+ method: "GET" | "POST" = "GET",
29
+ timeout: number = 10000, // 默认超时时间为10秒
30
+ ): Promise<any> {
31
+ // 创建一个AbortController实例
32
+ const controller = new AbortController();
33
+ const { signal } = controller;
34
+ // 设置一个超时
35
+ const timeoutId = setTimeout(() => {
36
+ controller.abort();
37
+ throw new Error("Request timed out");
38
+ }, timeout);
39
+ try {
40
+ let url = `${this.baseUrl}/${endpoint}`;
41
+ if (!url.startsWith("http://") && !url.startsWith("https://")) {
42
+ throw new Error("URL must start with 'http://' or 'https://'");
43
+ }
44
+ const headers = {
45
+ "Content-Type": "application/json",
46
+ };
47
+ // 对params进行判断,如果是GET请求,则将params转为URL查询字符串并附加到URL上
48
+ let queryString = "";
49
+ if (method === "GET" && params) {
50
+ queryString = new URLSearchParams(params).toString();
51
+ if (queryString) {
52
+ url += `?${queryString}`;
53
+ }
54
+ }
55
+
56
+ // 创建body,仅在POST请求且params存在时创建
57
+ let body: string | null = null;
58
+ if (method === "POST" && params) {
59
+ body = JSON.stringify(params);
60
+ }
61
+
62
+ //console.log(url);
63
+ const response = await fetch(url, {
64
+ method,
65
+ headers,
66
+ body,
67
+ signal, // 将signal传递给fetch
68
+ });
69
+
70
+ if (!response.ok) {
71
+ throw new Error(
72
+ `HTTP error! Status: ${response.status}, Message: ${response.statusText}`,
73
+ );
74
+ }
75
+
76
+ const responseText = await response.text();
77
+ const data = JSONbig.parse(responseText);
78
+ clearTimeout(timeoutId); // 请求成功,清除超时计时器
79
+ return data;
80
+ } catch (error) {
81
+ clearTimeout(timeoutId); // 无论请求是否成功,都清除超时计时器
82
+ let errorDesc = "invalid url";
83
+ if (typeof error === "string") {
84
+ errorDesc = error;
85
+ } else if (error instanceof Error) {
86
+ errorDesc = error.message;
87
+ }
88
+
89
+ const obj = {
90
+ error_code: StatusCodes.URL_ERROR,
91
+ error_desc: errorDesc,
92
+ };
93
+ return obj;
94
+ }
95
+ }
96
+
97
+ public async apply(params: ApplyRequest): Promise<ApplyResponse> {
98
+ return ApplyResponse.fromJSON(
99
+ await this.fetchData("/data/apply", params, "POST"),
100
+ );
101
+ }
102
+
103
+ public async status(
104
+ params: ApplyStatusRequest,
105
+ ): Promise<ApplyStatusResponse> {
106
+ return ApplyStatusResponse.fromJSON(
107
+ await this.fetchData("/data/query/status", params, "POST"),
108
+ );
109
+ }
110
+
111
+ public async detail(params: DetailRequest): Promise<DetailResponse> {
112
+ return DetailResponse.fromJSON(
113
+ await this.fetchData("/data/query/detail", params, "POST"),
114
+ );
115
+ }
116
+ }