openchain-nodejs-ts-yxl 1.0.1

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 (76) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +66 -0
  3. package/_config.yml +1 -0
  4. package/doc/SDK_CN.md +2003 -0
  5. package/example/atp10TokenDemo.js +319 -0
  6. package/example/exchange.js +184 -0
  7. package/example/offlineSignatureDemo.js +83 -0
  8. package/example/submitTransactionDemo.js +92 -0
  9. package/index.d.ts +186 -0
  10. package/index.js +9 -0
  11. package/lib/account/index.js +234 -0
  12. package/lib/blockchain/block.js +380 -0
  13. package/lib/blockchain/transaction.js +264 -0
  14. package/lib/common/ctp.js +5 -0
  15. package/lib/common/operation/accountSetMetadata.js +55 -0
  16. package/lib/common/operation/accountSetPrivilege.js +90 -0
  17. package/lib/common/operation/activateAccount.js +58 -0
  18. package/lib/common/operation/contractCreate.js +72 -0
  19. package/lib/common/operation/contractInvokeByAsset.js +75 -0
  20. package/lib/common/operation/contractInvokeByBU.js +53 -0
  21. package/lib/common/operation/createLog.js +44 -0
  22. package/lib/common/operation/ctp10TokenApprove.js +59 -0
  23. package/lib/common/operation/ctp10TokenAssign.js +59 -0
  24. package/lib/common/operation/ctp10TokenChangeOwner.js +58 -0
  25. package/lib/common/operation/ctp10TokenIssue.js +78 -0
  26. package/lib/common/operation/ctp10TokenTransfer.js +59 -0
  27. package/lib/common/operation/ctp10TokenTransferFrom.js +60 -0
  28. package/lib/common/operation/issueAsset.js +35 -0
  29. package/lib/common/operation/payAsset.js +62 -0
  30. package/lib/common/operation/payCoin.js +44 -0
  31. package/lib/common/util.js +880 -0
  32. package/lib/contract/index.js +212 -0
  33. package/lib/crypto/protobuf/bundle.json +1643 -0
  34. package/lib/exception/customErrors.js +56 -0
  35. package/lib/exception/errors.js +240 -0
  36. package/lib/exception/index.js +8 -0
  37. package/lib/operation/account.js +193 -0
  38. package/lib/operation/asset.js +106 -0
  39. package/lib/operation/bu.js +52 -0
  40. package/lib/operation/contract.js +184 -0
  41. package/lib/operation/ctp10Token.js +394 -0
  42. package/lib/operation/index.js +30 -0
  43. package/lib/operation/log.js +47 -0
  44. package/lib/sdk.js +70 -0
  45. package/lib/token/asset.js +79 -0
  46. package/lib/token/ctp10Token.js +301 -0
  47. package/lib/token/index.js +17 -0
  48. package/lib/util/index.js +86 -0
  49. package/openchain-sdk-nodejs.iml +9 -0
  50. package/package.json +39 -0
  51. package/test/Ctp10Token.test.js +96 -0
  52. package/test/account.test.js +132 -0
  53. package/test/accountActivateOperation.test.js +99 -0
  54. package/test/accountSetMetadata.test.js +102 -0
  55. package/test/accountSetPrivilege.test.js +66 -0
  56. package/test/asset.test.js +63 -0
  57. package/test/assetIssueOperation.test.js +77 -0
  58. package/test/assetSendOperation.test.js +103 -0
  59. package/test/blob.test.js +128 -0
  60. package/test/block.test.js +165 -0
  61. package/test/buSendOperation.test.js +64 -0
  62. package/test/contract.test.js +64 -0
  63. package/test/contractCreateOperation.test.js +41 -0
  64. package/test/contractCreateTransaction.test.js +116 -0
  65. package/test/contractInvokeByAssetOperation.test.js +109 -0
  66. package/test/contractInvokeByBUOperation.test.js +107 -0
  67. package/test/ctp10TokenApproveOperation.test.js +98 -0
  68. package/test/ctp10TokenAssignOperation.test.js +99 -0
  69. package/test/ctp10TokenChangeOwnerOperation.test.js +98 -0
  70. package/test/ctp10TokenIssueOperation.test.js +40 -0
  71. package/test/ctp10TokenIssueOperationTransaction.test.js +106 -0
  72. package/test/ctp10TokenTransferFromOperation.test.js +101 -0
  73. package/test/ctp10TokenTransferOperation.test.js +98 -0
  74. package/test/log.transaction.test.js +103 -0
  75. package/test/transaction.test.js +166 -0
  76. package/test/util.test.js +93 -0
@@ -0,0 +1,880 @@
1
+ 'use strict';
2
+
3
+ const request = require('request-promise');
4
+ const is = require('is-type-of');
5
+ const long = require('long');
6
+ const JSONbig = require('json-bigint');
7
+ // const bigNumberToString = require('bignumber-to-string')
8
+ const BigNumber = require('bignumber.js');
9
+ const protobuf = require("protobufjs");
10
+ const tou8 = require('buffer-to-uint8array');
11
+ const humps = require('humps');
12
+ const { keypair, signature } = require('yxchain-encryption-nodejs');
13
+ const errors = require('../exception');
14
+
15
+
16
+ const proto = exports;
17
+
18
+
19
+ /**
20
+ * GET/POST request
21
+ *
22
+ * @param {String} method
23
+ * @param {String} path
24
+ * @param {Object} data
25
+ * @return {Object}
26
+ */
27
+ proto._request = function* (method, path, data = {}) {
28
+ try {
29
+ const protocol = this.options.secure ? 'https://' : 'http://';
30
+ const uri = `${protocol}${this.options.host}/${path}`;
31
+
32
+ if (!is.string(method) || this._isEmptyString(method)) {
33
+ throw new Error('method must be a non-empty string');
34
+ }
35
+
36
+ if (!is.string(path) || this._isEmptyString(path)) {
37
+ throw new Error('path must be a non-empty string');
38
+ }
39
+
40
+ const methods = [ 'get', 'post' ];
41
+
42
+ if (!methods.includes(method.toLowerCase())) {
43
+ throw new Error(`${method} http method is not supported`);
44
+ }
45
+
46
+ const options = {
47
+ method,
48
+ uri,
49
+ timeout: this.options.timeout,
50
+ };
51
+
52
+ if (method === 'get') {
53
+ options.qs = data;
54
+ }
55
+
56
+ if (method === 'post') {
57
+ options.body = data;
58
+ }
59
+ const result = yield request(options);
60
+ const obj = JSONbig.parse(result);
61
+ const error_code = obj.error_code;
62
+ const final = this._bigNumberToString(obj);
63
+ final.error_code = error_code;
64
+ return final;
65
+ } catch (err) {
66
+ throw err;
67
+ }
68
+ };
69
+
70
+ proto._response = function(obj) {
71
+ const data = {
72
+ errorCode: obj.error_code || 0,
73
+ errorDesc: obj.error_desc || 'Success',
74
+ };
75
+
76
+ if (is.object(obj) && obj.error_code) {
77
+ if (obj.error_code === 0) {
78
+ data.result = obj.result || {};
79
+ } else {
80
+ data.errorDesc = obj.error_desc || '';
81
+ data.result = {};
82
+ }
83
+ } else {
84
+ data.result = obj;
85
+ }
86
+
87
+ return JSONbig.stringify(data);
88
+ };
89
+
90
+ proto._getBlockNumber = function* () {
91
+ try {
92
+ const data = yield this._request('get', 'getLedger');
93
+ if (data && data.error_code === 0) {
94
+ const seq = data.result.header.seq;
95
+ return this._responseData({
96
+ header: {
97
+ blockNumber: seq,
98
+ },
99
+ });
100
+ } else {
101
+ return this._responseError(errors.INTERNAL_ERROR);
102
+ }
103
+ } catch (err) {
104
+ throw err;
105
+ }
106
+ };
107
+
108
+ proto._isEmptyString = function(str) {
109
+ if (!is.string(str)) {
110
+ throw new Error('str must be a string');
111
+ }
112
+ return (str.trim().length === 0);
113
+ };
114
+
115
+ proto._postData = function(blob, signature) {
116
+ const data = {
117
+ items: [
118
+ {
119
+ transaction_blob: blob,
120
+ signatures: signature
121
+ },
122
+ ],
123
+ };
124
+ return JSONbig.stringify(data);
125
+ };
126
+
127
+ proto._isBigNumber = function (object) {
128
+ return object instanceof BigNumber ||
129
+ (object && object.constructor && object.constructor.name === 'BigNumber');
130
+ };
131
+
132
+ proto._toBigNumber = function(number) {
133
+ number = number || 0;
134
+ //
135
+ if (this._isBigNumber(number)) {
136
+ return number;
137
+ }
138
+ return new BigNumber(number);
139
+ };
140
+
141
+ proto._stringFromBigNumber = function(number) {
142
+ return this._toBigNumber(number).toString(10);
143
+ };
144
+
145
+ proto._verifyValue = function(str) {
146
+ const reg = /^[1-9]\d*$/;
147
+ return (
148
+ is.string(str) &&
149
+ reg.test(str) &&
150
+ long.fromValue(str).greaterThan(0) &&
151
+ long.fromValue(str).lessThanOrEqual(long.MAX_VALUE)
152
+ );
153
+ };
154
+
155
+ proto._isAvailableValue = function(str, from=-1, to=long.MAX_VALUE) {
156
+ const reg = /^(0|([1-9]\d*))$/
157
+ return (
158
+ is.string(str) &&
159
+ reg.test(str) &&
160
+ long.fromValue(str).greaterThan(from) &&
161
+ long.fromValue(str).lessThanOrEqual(to)
162
+ );
163
+ };
164
+
165
+ proto._checkParams = function (obj) {
166
+ for (let prop in obj) {
167
+ if (obj.hasOwnProperty(prop)) {
168
+ let value = obj[prop];
169
+ if (!is.undefined(value)) {
170
+ if (!this._verifyValue(value)) {
171
+ throw new Error(errors.INVALID_FORMAT_OF_ARG.msg);
172
+ }
173
+ }
174
+ }
175
+ }
176
+ };
177
+
178
+ proto._getDefaultValue = function* () {
179
+ try {
180
+ let ledgerInfo = yield this._request('get', 'getLedger', {
181
+ with_fee: true,
182
+ });
183
+ const gasPrice = long.fromValue(ledgerInfo.result.fees.gas_price);
184
+ const feeLimit = long.fromValue(1000).mul(gasPrice);
185
+ return {
186
+ gasPrice,
187
+ feeLimit,
188
+ }
189
+ } catch (err) {
190
+ throw err;
191
+ }
192
+ };
193
+
194
+ proto._responseData = function(data) {
195
+ const errorCode = 0;
196
+ const errorDesc = '';
197
+
198
+ return {
199
+ errorCode,
200
+ errorDesc,
201
+ result: data,
202
+ }
203
+ };
204
+
205
+ proto._responseError = function(message) {
206
+ if (!message) {
207
+ throw new Error('require message');
208
+ }
209
+ const errorCode = message.CODE;
210
+
211
+ return {
212
+ errorCode,
213
+ errorDesc: message.MSG,
214
+ };
215
+ };
216
+
217
+ proto._submitTransaction = function* (data) {
218
+ try {
219
+ const res = yield this._request('post', 'submitTransaction', data);
220
+ const results = res.results;
221
+ if (Array.isArray(results) && results.length > 0) {
222
+ const info = results[0];
223
+
224
+ if (info.error_code === '0') {
225
+ return this._responseData({
226
+ hash: info.hash,
227
+ });
228
+ }
229
+
230
+ return {
231
+ errorCode: info.error_code,
232
+ errorDesc: info.error_desc,
233
+ };
234
+ }
235
+
236
+ } catch (err) {
237
+ throw err;
238
+ }
239
+
240
+ };
241
+
242
+ proto._buildOperation = function(type, data) {
243
+ try {
244
+ return require(`./operation/${type}`)(data);
245
+ } catch (err) {
246
+ console.log(err);
247
+ throw new Error('Operation cannot be resolved');
248
+ }
249
+ };
250
+
251
+ proto._decodeOperation = function(hexString) {
252
+ const root = protobuf.Root.fromJSON(require('../crypto/protobuf/bundle.json'));
253
+ const operation = root.lookupType('protocol.Operation');
254
+ const msgBuffer = Buffer.from(hexString, 'hex');
255
+ return operation.decode(msgBuffer);
256
+ };
257
+
258
+ proto._buildBlob = function(args) {
259
+ try {
260
+ let { sourceAddress, gasPrice, feeLimit, nonce, ceilLedgerSeq, operations, metadata } = args;
261
+
262
+ const operationList = [];
263
+
264
+ operations.forEach(item => {
265
+ const type = item.type;
266
+ const argsData = item.data;
267
+
268
+ const operationItem = this._buildOperation(type, argsData);
269
+ operationList.push(operationItem);
270
+ });
271
+
272
+ const root = protobuf.Root.fromJSON(require('../crypto/protobuf/bundle.json'));
273
+ const tx = root.lookupType('protocol.Transaction');
274
+
275
+ ceilLedgerSeq = ceilLedgerSeq ? long.fromValue(ceilLedgerSeq) : undefined;
276
+
277
+ const payload = {
278
+ sourceAddress,
279
+ gasPrice: long.fromValue(gasPrice),
280
+ feeLimit: long.fromValue(feeLimit),
281
+ nonce: long.fromValue(nonce),
282
+ ceilLedgerSeq,
283
+ operations: operationList
284
+ };
285
+
286
+ if (this.options.chainId > 0) {
287
+ payload.chainId = this.options.chainId
288
+ }
289
+
290
+ if (metadata) {
291
+ payload.metadata = tou8(Buffer.from(metadata));
292
+ }
293
+
294
+ const errMsg = tx.verify(payload);
295
+
296
+ if (errMsg) {
297
+ throw Error(errMsg);
298
+ }
299
+
300
+ const message = tx.create(payload);
301
+ const bufferData = tx.encode(message).finish();
302
+
303
+ return {
304
+ transactionBlob: bufferData.toString('hex'),
305
+ }
306
+ } catch (err) {
307
+ throw err;
308
+ }
309
+ };
310
+
311
+ proto._signBlob = function({ privateKeys, blob } = args) {
312
+ try {
313
+ const buffer = Buffer.from(blob, 'hex');
314
+ const uint8ArrayData = tou8(buffer);
315
+ const signatureArr = [];
316
+ privateKeys.forEach(privateKey => {
317
+ signatureArr.push({
318
+ signData: signature.sign(uint8ArrayData, privateKey),
319
+ publicKey: keypair.getEncPublicKey(privateKey),
320
+ });
321
+ });
322
+ // return signatureArr;
323
+ return {
324
+ signatures: signatureArr,
325
+ };
326
+ } catch (err) {
327
+ throw err;
328
+ }
329
+ };
330
+
331
+ proto._submit = function* (args) {
332
+ const { blob, signature} = args;
333
+ const postData = this._postData(blob, signature);
334
+ return yield this._submitTransaction(postData);
335
+ };
336
+
337
+
338
+ proto._isHexString = function(str) {
339
+ if ((str === '' || !is.string(str))) {
340
+ return false;
341
+ }
342
+ const hexString = Buffer.from(str, 'hex').toString('hex');
343
+ return (hexString === str);
344
+ };
345
+
346
+ proto._isString = function(str) {
347
+ if (!is.string(str) ||
348
+ str.trim().length === 0 ||
349
+ str.length > 1024) {
350
+ return false;
351
+ }
352
+ return true;
353
+ };
354
+
355
+ proto._isTopic = function(str) {
356
+ if (!is.string(str) ||
357
+ str.trim().length === 0 ||
358
+ str.length > 128) {
359
+ return false;
360
+ }
361
+ return true;
362
+ };
363
+
364
+ proto._isSignature = function(arr) {
365
+ let tag = true;
366
+ if (!is.array(arr) || arr.length === 0) {
367
+ tag = false;
368
+ return tag;
369
+ }
370
+
371
+ arr.some(item => {
372
+ if (!is.object(item)) {
373
+ tag = false;
374
+ return true;
375
+ }
376
+
377
+ if (!item.signData || !item.publicKey) {
378
+ tag = false;
379
+ return true;
380
+ }
381
+
382
+ if (!this._isHexString(item.signData)) {
383
+ tag = false;
384
+ return true;
385
+ }
386
+
387
+ if (!keypair.checkEncPublicKey(item.publicKey)) {
388
+ tag = false;
389
+ return true;
390
+ }
391
+ });
392
+
393
+ return tag;
394
+ };
395
+
396
+ proto._isOperation = function(arr) {
397
+ let tag = true;
398
+ if (!is.array(arr) || arr.length === 0) {
399
+ tag = false;
400
+ return tag;
401
+ }
402
+
403
+ arr.some(item => {
404
+ if (!is.object(item)) {
405
+ tag = false;
406
+ return true;
407
+ }
408
+ if (!item.type || !item.data) {
409
+ tag = false;
410
+ return true;
411
+ }
412
+ });
413
+
414
+ return tag;
415
+ };
416
+
417
+
418
+ proto._isPrivateKeys = function(arr) {
419
+ let tag = true;
420
+ if (!is.array(arr) || arr.length === 0) {
421
+ tag = false;
422
+ return tag;
423
+ }
424
+
425
+ arr.some(item => {
426
+ if (!keypair.checkEncPrivateKey(item)) {
427
+ tag = false;
428
+ return true;
429
+ }
430
+ });
431
+
432
+ return tag;
433
+ };
434
+
435
+
436
+ /**
437
+ *
438
+ * @param obj
439
+ * @param schema
440
+ * @returns {boolean}
441
+ * @private
442
+ *
443
+ * eg:
444
+ schema: {
445
+ required: false,
446
+ string: true,
447
+ address: true,
448
+ numeric: true,
449
+ }
450
+ */
451
+ proto._validate = function(obj, schema) {
452
+ let tag = true;
453
+ let msg = '';
454
+
455
+ if (!is.object(obj) || !is.object(schema)) {
456
+ tag = false;
457
+ msg = 'INVALID_NUMBER_OF_ARG';
458
+ return {
459
+ tag,
460
+ msg,
461
+ };
462
+ }
463
+
464
+ Object.keys(schema).some(item => {
465
+
466
+ // required is true
467
+ if (schema[item].required && is.undefined(obj[item])) {
468
+ obj[item] = '';
469
+ }
470
+
471
+ // numeric is true
472
+ if (!is.undefined(obj[item]) &&
473
+ schema[item].numeric &&
474
+ !this._verifyValue(obj[item])) {
475
+ tag = false;
476
+
477
+ switch(item) {
478
+ case 'amount':
479
+ msg = 'INVALID_BU_AMOUNT_ERROR';
480
+ break;
481
+ case 'buAmount':
482
+ msg = 'INVALID_BU_AMOUNT_ERROR';
483
+ break;
484
+ case 'assetAmount':
485
+ msg = 'INVALID_ASSET_AMOUNT_ERROR';
486
+ break;
487
+ case 'gasPrice':
488
+ msg = 'INVALID_GASPRICE_ERROR';
489
+ break;
490
+ case 'feeLimit':
491
+ msg = 'INVALID_FEELIMIT_ERROR';
492
+ break;
493
+ case 'ceilLedgerSeq':
494
+ msg = 'INVALID_CEILLEDGERSEQ_ERROR';
495
+ break;
496
+ case 'nonce':
497
+ msg = 'INVALID_NONCE_ERROR';
498
+ break;
499
+ case 'initBalance':
500
+ msg = 'INVALID_INITBALANCE_ERROR';
501
+ break;
502
+ case 'signtureNumber':
503
+ msg = 'INVALID_SIGNATURENUMBER_ERROR';
504
+ break;
505
+ case 'totalSupply':
506
+ msg = 'INVALID_TOKEN_TOTALSUPPLY_ERROR';
507
+ break;
508
+ case 'tokenAmount':
509
+ msg = 'INVALID_TOKEN_AMOUNT_ERROR';
510
+ break;
511
+ default:
512
+ msg = 'INVALID_ARGUMENTS';
513
+ }
514
+
515
+ return true;
516
+ }
517
+
518
+ // privateKeys is true
519
+ if (!is.undefined(obj[item]) &&
520
+ schema[item].privateKeys &&
521
+ !this._isPrivateKeys(obj[item])) {
522
+ tag = false;
523
+ msg = `PRIVATEKEY_ONE_ERROR`;
524
+ return true;
525
+ }
526
+
527
+ // address is true
528
+ if (!is.undefined(obj[item]) &&
529
+ schema[item].address &&
530
+ !keypair.checkAddress(obj[item])) {
531
+ tag = false;
532
+
533
+ switch(item) {
534
+ case 'sourceAddress':
535
+ msg = 'INVALID_SOURCEADDRESS_ERROR';
536
+ break;
537
+ case 'destAddress':
538
+ msg = 'INVALID_DESTADDRESS_ERROR';
539
+ break;
540
+ case 'issuer':
541
+ msg = 'INVALID_ISSUER_ADDRESS_ERROR';
542
+ break;
543
+ case 'address':
544
+ msg = 'INVALID_ADDRESS_ERROR';
545
+ break;
546
+ case 'contractAddress':
547
+ msg = 'INVALID_CONTRACTADDRESS_ERROR';
548
+ break;
549
+ case 'fromAddress':
550
+ msg = 'INVALID_FROMADDRESS_ERROR';
551
+ break;
552
+ case 'spender':
553
+ msg = 'INVALID_SPENDER_ERROR';
554
+ break;
555
+ case 'tokenOwner':
556
+ msg = 'INVALID_TOKENOWNER_ERRPR';
557
+ break;
558
+ default:
559
+ msg = 'INVALID_ARGUMENTS';
560
+ }
561
+
562
+ return true;
563
+ }
564
+
565
+ // operations is true
566
+ if (!is.undefined(obj[item]) &&
567
+ schema[item].operations &&
568
+ !this._isOperation(obj[item])) {
569
+ tag = false;
570
+ msg = 'INVALID_OPERATIONS';
571
+ return true;
572
+ }
573
+
574
+ // signatures is true
575
+ if (!is.undefined(obj[item]) &&
576
+ schema[item].signatures &&
577
+ !this._isSignature(obj[item])) {
578
+ tag = false;
579
+ msg = 'INVALID_SIGNATURE_ERROR';
580
+ return true;
581
+ }
582
+
583
+ // hex is true
584
+ if (!is.undefined(obj[item]) &&
585
+ schema[item].hex &&
586
+ !this._isHexString(obj[item])) {
587
+ tag = false;
588
+
589
+ switch(item) {
590
+ case 'metadata':
591
+ msg = 'METADATA_NOT_HEX_STRING_ERROR';
592
+ break;
593
+ case 'blob':
594
+ msg = 'INVALID_BLOB_ERROR';
595
+ break;
596
+ default:
597
+ msg = 'METADATA_NOT_HEX_STRING_ERROR';
598
+ }
599
+
600
+ return true;
601
+ }
602
+
603
+ // string is true
604
+ if (!is.undefined(obj[item]) &&
605
+ schema[item].string &&
606
+ !this._isString(obj[item])) {
607
+ tag = false;
608
+
609
+ switch(item) {
610
+ case 'code':
611
+ msg = 'INVALID_ASSET_CODE_ERROR';
612
+ break;
613
+ case 'issuer':
614
+ msg = 'INVALID_ISSUER_ADDRESS_ERROR';
615
+ break;
616
+ case 'data':
617
+ msg = 'INVALID_LOG_DATA_ERROR';
618
+ break;
619
+ case 'metadata':
620
+ msg = 'INVALID_METADATA_ERROR';
621
+ break;
622
+ case 'payload':
623
+ msg = 'PAYLOAD_EMPTY_ERROR';
624
+ break;
625
+ case 'input':
626
+ msg = 'INVALID_INPUT_ERROR';
627
+ break;
628
+ case 'name':
629
+ msg = 'INVALID_TOKEN_NAME_ERROR';
630
+ break;
631
+ case 'symbol':
632
+ msg = 'INVALID_TOKEN_SYMBOL_ERROR';
633
+ break;
634
+ case 'key':
635
+ msg = 'INVALID_DATAKEY_ERROR';
636
+ break;
637
+ default:
638
+ msg = 'INVALID_ARGUMENTS';
639
+ }
640
+
641
+ return true;
642
+ }
643
+
644
+ // topic is true
645
+ if (!is.undefined(obj[item]) &&
646
+ schema[item].topic &&
647
+ !this._isTopic(obj[item])) {
648
+ tag = false;
649
+ msg = 'INVALID_LOG_TOPIC_ERROR';
650
+ return true;
651
+ }
652
+
653
+ // boolean is true
654
+ if (!is.undefined(obj[item]) &&
655
+ schema[item].boolean &&
656
+ (typeof obj[item] !== 'boolean')) {
657
+ tag = false;
658
+
659
+ switch(item) {
660
+ case 'deleteFlag':
661
+ msg = 'INVALID_DELETEFLAG_ERROR';
662
+ break;
663
+ default:
664
+ msg = 'INVALID_ARGUMENTS';
665
+ }
666
+
667
+ return true;
668
+ }
669
+
670
+ });
671
+
672
+ return {
673
+ tag,
674
+ msg,
675
+ };
676
+ };
677
+
678
+ proto._bufToHex = function(buf) {
679
+ const utf8Str = buf.toString('utf8');
680
+ return Buffer.from(utf8Str, 'utf8').toString('hex');
681
+ };
682
+
683
+ proto._bigNumberToString = function(obj, base) {
684
+ // setup base
685
+ base = base || 10;
686
+
687
+ // check if obj is type object, not an array and does not have BN properties
688
+ if (typeof obj === 'object' && obj !== null && !Array.isArray(obj) && !('lessThan' in obj)) {
689
+ // move through plain object
690
+ Object.keys(obj).forEach(function (key) {
691
+ // recurively converty item
692
+ obj[key] = proto._bigNumberToString(obj[key], base);
693
+ })
694
+ }
695
+
696
+ // obj is an array
697
+ if (Array.isArray(obj)) {
698
+ // convert items in array
699
+ obj = obj.map(function (item) {
700
+ // convert item to a string if bignumber
701
+ return proto._bigNumberToString(item, base);
702
+ })
703
+ }
704
+
705
+ // if obj is number, convert to string
706
+ if (typeof obj === 'number') return obj + '';
707
+
708
+ // if not an object bypass
709
+ if (typeof obj !== 'object' || obj === null) return obj;
710
+
711
+ // if the object to does not have BigNumber properties, bypass
712
+ if (!('toString' in obj) || !('lessThan' in obj)) return obj;
713
+
714
+ // if object has bignumber properties, convert to string with base
715
+ return obj.toString(base);
716
+ };
717
+
718
+
719
+ proto._longToInt = function(obj) {
720
+ // check if obj is type object, not an array and does not have long properties
721
+ if (typeof obj === 'object' && obj !== null && !Array.isArray(obj) && !('low' in obj)) {
722
+ // move through plain object
723
+ Object.keys(obj).forEach(function (key) {
724
+ // recurively converty item
725
+ obj[key] = proto._longToInt(obj[key]);
726
+ })
727
+ }
728
+
729
+ // obj is an array
730
+ if (Array.isArray(obj)) {
731
+ // convert items in array
732
+ obj = obj.map(function (item) {
733
+ // convert item to an int if long
734
+ return proto._longToInt(item);
735
+ })
736
+ }
737
+
738
+ // if not an object bypass
739
+ if (typeof obj !== 'object' || obj === null) return obj;
740
+
741
+ // if the object to does not have long properties, bypass
742
+ if (!('low' in obj)) return obj;
743
+
744
+ // if object has long properties, convert to int
745
+ return long.fromValue(obj).toNumber();
746
+ };
747
+
748
+ proto._isContractAddress = function* (address) {
749
+ const data = yield this._request('get', 'getAccount', {
750
+ address,
751
+ });
752
+
753
+ if (data.error_code !== 0) {
754
+ return this._responseError(errors.ACCOUNT_NOT_EXIST);
755
+ }
756
+
757
+ const result = data.result;
758
+
759
+ if (result.contract) {
760
+ return true;
761
+ }
762
+
763
+ return false;
764
+ };
765
+
766
+ proto._isAvailableToken = function* (contractAddress) {
767
+ if (!keypair.checkAddress(contractAddress)) {
768
+ return this._responseError(errors.INVALID_CONTRACTADDRESS_ERROR);
769
+ }
770
+
771
+ const isContractAddress = yield this._isContractAddress(contractAddress);
772
+ if (!isContractAddress) {
773
+ return this._responseError(errors.CONTRACTADDRESS_NOT_CONTRACTACCOUNT_ERROR);
774
+ }
775
+
776
+ let data = yield this._request('get', 'getAccount', {
777
+ address: contractAddress,
778
+ });
779
+
780
+
781
+ if (data.error_code !== 0) {
782
+ return this._responseData({
783
+ isValid: false,
784
+ });
785
+ }
786
+
787
+ data = data.result;
788
+ const contract = data.contract.metadatas;
789
+ const metadatas = data.metadatas;
790
+ let key = '';
791
+ let value = '';
792
+ if (metadatas && is.array(metadatas)) {
793
+
794
+ metadatas.some(item => {
795
+ if (item.key === 'global_attribute') {
796
+ key = 'global_attribute';
797
+ value = item.value;
798
+ return true;
799
+ }
800
+ });
801
+
802
+ if (key !== 'global_attribute') {
803
+ return this._responseData({
804
+ isValid: false,
805
+ });
806
+ }
807
+
808
+ const info = JSON.parse(value);
809
+
810
+ if ('1.0' !== info.ctp) {
811
+ return this._responseData({
812
+ isValid: false,
813
+ });
814
+ }
815
+
816
+ if (!info.symbol || info.symbol < 0 || info.symbol > 8) {
817
+ return this._responseData({
818
+ isValid: false,
819
+ });
820
+ }
821
+
822
+ const schema = {
823
+ balance: {
824
+ required: true,
825
+ numeric: true,
826
+ },
827
+ name: {
828
+ required: true,
829
+ string: true,
830
+ },
831
+ symbol: {
832
+ required: true,
833
+ string: true,
834
+ },
835
+ totalSupply: {
836
+ required: true,
837
+ numeric: true,
838
+ },
839
+ contractOwner: {
840
+ required: true,
841
+ address: true,
842
+ },
843
+ };
844
+
845
+ if (!this._validate(info, schema).tag) {
846
+ return this._responseData({
847
+ isValid: false,
848
+ });
849
+ }
850
+
851
+ return this._responseData({
852
+ isValid: true,
853
+ });
854
+
855
+ } else {
856
+ return this._responseData({
857
+ isValid: false,
858
+ });
859
+ }
860
+ };
861
+
862
+ proto._isAvailableVersion = function(str) {
863
+ const reg = /^\d+(\.\d+)?$/;
864
+ return (
865
+ is.string(str) &&
866
+ reg.test(str) &&
867
+ long.fromValue(str).greaterThanOrEqual(0) &&
868
+ long.fromValue(str).lessThanOrEqual(long.MAX_VALUE)
869
+ );
870
+ };
871
+
872
+ proto._isAvailableBu = function (str) {
873
+ const reg = /^(([1-9]\d*)+|0)(\.\d{1,8})?$/;
874
+ return (
875
+ is.string(str) &&
876
+ reg.test(str) &&
877
+ long.fromValue(str).greaterThanOrEqual(0) &&
878
+ long.fromValue(str).lessThanOrEqual(long.MAX_VALUE.divide(Math.pow(10, 8)))
879
+ );
880
+ }