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.
- package/LICENSE +661 -0
- package/README.md +66 -0
- package/_config.yml +1 -0
- package/doc/SDK_CN.md +2003 -0
- package/example/atp10TokenDemo.js +319 -0
- package/example/exchange.js +184 -0
- package/example/offlineSignatureDemo.js +83 -0
- package/example/submitTransactionDemo.js +92 -0
- package/index.d.ts +186 -0
- package/index.js +9 -0
- package/lib/account/index.js +234 -0
- package/lib/blockchain/block.js +380 -0
- package/lib/blockchain/transaction.js +264 -0
- package/lib/common/ctp.js +5 -0
- package/lib/common/operation/accountSetMetadata.js +55 -0
- package/lib/common/operation/accountSetPrivilege.js +90 -0
- package/lib/common/operation/activateAccount.js +58 -0
- package/lib/common/operation/contractCreate.js +72 -0
- package/lib/common/operation/contractInvokeByAsset.js +75 -0
- package/lib/common/operation/contractInvokeByBU.js +53 -0
- package/lib/common/operation/createLog.js +44 -0
- package/lib/common/operation/ctp10TokenApprove.js +59 -0
- package/lib/common/operation/ctp10TokenAssign.js +59 -0
- package/lib/common/operation/ctp10TokenChangeOwner.js +58 -0
- package/lib/common/operation/ctp10TokenIssue.js +78 -0
- package/lib/common/operation/ctp10TokenTransfer.js +59 -0
- package/lib/common/operation/ctp10TokenTransferFrom.js +60 -0
- package/lib/common/operation/issueAsset.js +35 -0
- package/lib/common/operation/payAsset.js +62 -0
- package/lib/common/operation/payCoin.js +44 -0
- package/lib/common/util.js +880 -0
- package/lib/contract/index.js +212 -0
- package/lib/crypto/protobuf/bundle.json +1643 -0
- package/lib/exception/customErrors.js +56 -0
- package/lib/exception/errors.js +240 -0
- package/lib/exception/index.js +8 -0
- package/lib/operation/account.js +193 -0
- package/lib/operation/asset.js +106 -0
- package/lib/operation/bu.js +52 -0
- package/lib/operation/contract.js +184 -0
- package/lib/operation/ctp10Token.js +394 -0
- package/lib/operation/index.js +30 -0
- package/lib/operation/log.js +47 -0
- package/lib/sdk.js +70 -0
- package/lib/token/asset.js +79 -0
- package/lib/token/ctp10Token.js +301 -0
- package/lib/token/index.js +17 -0
- package/lib/util/index.js +86 -0
- package/openchain-sdk-nodejs.iml +9 -0
- package/package.json +39 -0
- package/test/Ctp10Token.test.js +96 -0
- package/test/account.test.js +132 -0
- package/test/accountActivateOperation.test.js +99 -0
- package/test/accountSetMetadata.test.js +102 -0
- package/test/accountSetPrivilege.test.js +66 -0
- package/test/asset.test.js +63 -0
- package/test/assetIssueOperation.test.js +77 -0
- package/test/assetSendOperation.test.js +103 -0
- package/test/blob.test.js +128 -0
- package/test/block.test.js +165 -0
- package/test/buSendOperation.test.js +64 -0
- package/test/contract.test.js +64 -0
- package/test/contractCreateOperation.test.js +41 -0
- package/test/contractCreateTransaction.test.js +116 -0
- package/test/contractInvokeByAssetOperation.test.js +109 -0
- package/test/contractInvokeByBUOperation.test.js +107 -0
- package/test/ctp10TokenApproveOperation.test.js +98 -0
- package/test/ctp10TokenAssignOperation.test.js +99 -0
- package/test/ctp10TokenChangeOwnerOperation.test.js +98 -0
- package/test/ctp10TokenIssueOperation.test.js +40 -0
- package/test/ctp10TokenIssueOperationTransaction.test.js +106 -0
- package/test/ctp10TokenTransferFromOperation.test.js +101 -0
- package/test/ctp10TokenTransferOperation.test.js +98 -0
- package/test/log.transaction.test.js +103 -0
- package/test/transaction.test.js +166 -0
- 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
|
+
}
|