├── .babelrc
├── .gitignore
├── .project
├── README.md
├── index.js
├── karma.conf.js
├── package-lock.json
├── package.json
├── src
├── api
│ ├── sdk.js
│ └── serializers.js
├── crypto
│ └── eciesCrypto.js
├── index.js
├── model
│ ├── ProgramCreateDataEncodePacked.js
│ ├── ProgramEncodePacked.js
│ ├── block.js
│ ├── blockheader.js
│ ├── coindata.js
│ ├── contractdata.js
│ ├── signatures.js
│ ├── txs.js
│ └── txsignatures.js
├── test
│ ├── NAINFTTest
│ │ ├── buyToken.js
│ │ ├── createToken.js
│ │ ├── mint.js
│ │ └── sellToken.js
│ ├── NAIPumpTest
│ │ ├── buyToken.js
│ │ ├── createToken.js
│ │ └── sellToken.js
│ ├── NSWAPTest
│ │ ├── Asset_Asset
│ │ │ ├── ReverseSwap
│ │ │ │ └── swapWAssetForExactWAsset.js
│ │ │ ├── addLiquidityWAssetAndWAsset.js
│ │ │ ├── removeLiquidityWAssetWAsset.js
│ │ │ └── swapExactWAssetForWAsset.js
│ │ ├── Asset_Token
│ │ │ ├── ReverseSwap
│ │ │ │ ├── swapTokensForExactWAsset.js
│ │ │ │ └── swapWAssetForExactTokens.js
│ │ │ ├── addLiquidityWAsset.js
│ │ │ ├── removeLiquidityWAsset.js
│ │ │ ├── swapExactTokensForWAsset.js
│ │ │ └── swapExactWAssetForTokens.js
│ │ ├── Nuls_Asset
│ │ │ ├── ReverseSwap
│ │ │ │ ├── swapNulsForExactWAsset.js
│ │ │ │ └── swapWAssetForExactNuls.js
│ │ │ ├── addLiquidityNULSWAsset.js
│ │ │ ├── removeLiquidityNulsWAsset.js
│ │ │ ├── swapExactNulsForWAsset.js
│ │ │ └── swapExactWAssetForNuls.js
│ │ ├── Nuls_Token
│ │ │ ├── ReverseSwap
│ │ │ │ ├── swapNulsForExactTokens.js
│ │ │ │ └── swapTokensForExactNuls.js
│ │ │ ├── addLiquidityNuls.js
│ │ │ ├── removeLiquidityNuls.js
│ │ │ ├── swapExactNulsForTokens.js
│ │ │ └── swapExactTokensForNuls.js
│ │ ├── Token_Token
│ │ │ ├── ReverseSwap
│ │ │ │ └── swapTokensForExactTokens.js
│ │ │ ├── addLiquidity.js
│ │ │ ├── removeLiquidity.js
│ │ │ └── swapExactTokensForTokens.js
│ │ ├── approveTokenToRouter.js
│ │ └── calcPairAddress.js
│ ├── addressByPub.js
│ ├── api
│ │ ├── https.js
│ │ └── util.js
│ ├── coinTrading.js
│ ├── coindata.js
│ ├── contractCall.js
│ ├── contractCallOfAccountTransferTest.js
│ ├── contractCallOfMultyAccounts.js
│ ├── contractCallOfMultyAssetsTest1.js
│ ├── contractCallOfMultyAssetsTest2.js
│ ├── contractCallTest.js
│ ├── contractCallTest2.js
│ ├── contractCreate.js
│ ├── contractCreateTest.js
│ ├── contractDelete.js
│ ├── contractDeleteTest.js
│ ├── contractNRC20TransferTest.js
│ ├── createTrading.js
│ ├── crossChainTransfer.js
│ ├── cryptoTest.js
│ ├── dataOntoChain.js
│ ├── deposit.js
│ ├── deserialize
│ │ ├── test.js
│ │ ├── testCallContractDataHex.js
│ │ └── testHex.js
│ ├── fee.js
│ ├── flash_test.js
│ ├── hash.js
│ ├── importAddress.js
│ ├── newAddress.js
│ ├── newAgent.js
│ ├── registercrosschain.js
│ ├── setAlias.js
│ ├── stopAgent.js
│ ├── take.js
│ ├── testAes.js
│ ├── tradingOrder.js
│ ├── tradingOrderCancel.js
│ ├── transfer.js
│ ├── v1Tov2.js
│ ├── verifyAddress.js
│ ├── verifyProgramEncodePacked.js
│ └── verifySig.js
└── utils
│ ├── bn.js
│ ├── buffer.js
│ ├── bufferreader.js
│ ├── bufferwriter.js
│ ├── hash.js
│ ├── js.js
│ ├── preconditions.js
│ └── utils.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015"
4 | ],
5 | "plugins": []
6 | }
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /node_modules
3 | /lib
4 | .env
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | nuls2-js-sdk
4 |
5 |
6 |
7 |
8 |
9 | com.aptana.ide.core.unifiedBuilder
10 |
11 |
12 |
13 |
14 |
15 | com.aptana.projects.webnature
16 |
17 |
18 |
19 | 1562055552480
20 |
21 | 26
22 |
23 | org.eclipse.ui.ide.multiFilter
24 | 1.0-name-matches-false-false-node_modules
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Install
2 | ```bash
3 | $ npm i nuls-sdk-js
4 | ```
5 |
6 | # Usage
7 | ```js
8 | const nuls = require('./index');
9 |
10 | let chainId = 3; //链ID 1:NULS主网 2:NULS测试网 3以上其他链
11 | let passWord = "";
12 | let prefix = "semo"; //链前缀
13 |
14 | //创建地址
15 | const newAddress = nuls.newAddress(chainId, passWord, prefix);
16 | console.log(newAddress);
17 |
18 | //导入地址
19 | const key ="";
20 | const importAddress = nuls.importByKey(chainId, key, passWord,prefix);
21 | console.log(importAddress);
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./lib/index.js');
2 |
3 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | process.env.CHROME_BIN = "chromium-browser";
2 |
3 | module.exports = function(config) {
4 | config.set({
5 |
6 | // base path that will be used to resolve all patterns (eg. files, exclude)
7 | basePath: "./src/test/",
8 |
9 |
10 | // frameworks to use
11 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
12 | frameworks: ["mocha", "browserify"],
13 |
14 |
15 | // list of files / patterns to load in the browser
16 | files: [
17 | "cryptoTest.js"
18 | ],
19 |
20 |
21 | // preprocess matching files before serving them to the browser
22 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
23 | preprocessors: {
24 | "cryptoTest.js": ["browserify"],
25 | },
26 |
27 |
28 | // list of files to exclude
29 | exclude: [
30 | ],
31 |
32 |
33 | // test results reporter to use
34 | // possible values: "dots", "progress"
35 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
36 | reporters: ["mocha"],
37 |
38 |
39 | // web server port
40 | port: 9879,
41 |
42 |
43 | // enable / disable colors in the output (reporters and logs)
44 | colors: true,
45 |
46 |
47 | // level of logging
48 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
49 | logLevel: config.LOG_DEBUG,
50 |
51 |
52 | // enable / disable watching file and executing tests whenever any file changes
53 | autoWatch: true,
54 |
55 |
56 | // start these browsers
57 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
58 | browsers: ["Chromium"],
59 | customLaunchers: {
60 | Chromium: {
61 | base: "Chrome",
62 | flags: ["--no-sandbox"],
63 | },
64 | },
65 |
66 |
67 |
68 | // Continuous Integration mode
69 | // if true, Karma captures browsers, runs the tests and exits
70 | singleRun: true,
71 | });
72 | };
73 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nuls-sdk-js",
3 | "version": "2.5.0",
4 | "description": "nuls nuls-js nuls-sdk nuls-js-sdk",
5 | "main": "index.js",
6 | "files": [
7 | "lib",
8 | "src"
9 | ],
10 | "scripts": {
11 | "cleanLib": "./node_modules/.bin/rimraf lib",
12 | "bableBuild": "./node_modules/.bin/babel src --out-dir lib",
13 | "prepublish": "npm run cleanLib && npm run bableBuild",
14 | "test": "node ./src/test"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/nuls-io/nuls-v2-js-sdk"
19 | },
20 | "keywords": [
21 | "nuls",
22 | "nuls-js",
23 | "nuls-sdk"
24 | ],
25 | "devDependencies": {
26 | "buffer-equal": "^1.0.0",
27 | "chai": "*",
28 | "jshint": "^2.9.6",
29 | "karma": "*",
30 | "karma-browserify": "^5.3.0",
31 | "karma-chrome-launcher": "^2.2.0",
32 | "karma-cli": "^1.0.1",
33 | "karma-firefox-launcher": "^1.1.0",
34 | "karma-mocha": "^1.3.0",
35 | "karma-mocha-reporter": "^2.2.5",
36 | "mocha": "*",
37 | "watchify": "^3.11.0",
38 | "dotenv": "^16.4.1"
39 | },
40 | "dependencies": {
41 | "acorn": "6.4.1",
42 | "axios": "^0.18.1",
43 | "babel-cli": "^6.26.0",
44 | "babel-plugin-transform-runtime": "^6.23.0",
45 | "babel-preset-es2015": "^6.24.1",
46 | "babel-preset-stage-2": "^6.24.1",
47 | "bignumber.js": "^9.0.0",
48 | "bitcore-lib": "^0.16.0",
49 | "bitcore-mnemonic": "^1.0.1",
50 | "browserify": "16.2.3",
51 | "bs58": "4.0.1",
52 | "buffer": "^5.2.1",
53 | "buffer-from": "^1.1.1",
54 | "crypto-js": "3.1.9-1",
55 | "ecurve": "1.0.6",
56 | "elliptic": "6.5.3",
57 | "es6-promise": "3.0.2",
58 | "jsrsasign": "8.0.19",
59 | "keccak": "^3.0.4",
60 | "nan": "2.11.1",
61 | "randombytes": "2.0.6",
62 | "rimraf": "^2.6.3",
63 | "sha256": "^0.2.0"
64 | },
65 | "optionalDependencies": {
66 | "secp256k1": "3.7.1"
67 | },
68 | "author": "NULS team",
69 | "license": "ISC",
70 | "bugs": {
71 | "url": "https://github.com/nuls-io/nuls-v2-js-sdk"
72 | },
73 | "homepage": "https://github.com/nuls-io/nuls-v2-js-sdk"
74 | }
75 |
--------------------------------------------------------------------------------
/src/api/serializers.js:
--------------------------------------------------------------------------------
1 | const BufferWriter = require("../utils/bufferwriter");
2 | const BN = require("../utils/bn");
3 | let BigInteger = require("bigi");
4 |
5 | /**
6 | * 交易序列化
7 | * @param bufWriter
8 | * @constructor
9 | */
10 | let Serializers = function (bufWriter) {
11 | if (!bufWriter) {
12 | bufWriter = new BufferWriter();
13 | }
14 |
15 | this.writeString = function (value) {
16 | if (!value || value.length === 0) {
17 | bufWriter.write(Buffer.from([0x00]));
18 | return;
19 | }
20 | let buf = Buffer.from(value, "UTF-8");
21 | bufWriter.writeVarintNum(buf.length);
22 | bufWriter.write(buf);
23 | };
24 |
25 | this.writeBytesWithLength = function (value) {
26 | if (!value || value.length === 0) {
27 | bufWriter.write(Buffer.from([0x00]));
28 | return;
29 | }
30 | bufWriter.writeVarintNum(value.length);
31 | bufWriter.write(value);
32 | };
33 |
34 | this.writeBoolean = function (value) {
35 | if (value) {
36 | bufWriter.writeUInt8(1);
37 | } else {
38 | bufWriter.writeUInt8(0);
39 | }
40 | };
41 |
42 | this.getBufWriter = function () {
43 | return bufWriter;
44 | };
45 |
46 | this.writeUInt64LE = function (value) {
47 | bufWriter.writeUInt64LEBN(new BN(value));
48 | };
49 |
50 | this.writeBigInt = function (value) {
51 | let bigInt = BigInteger('' + value);
52 | let buf = bigInt.toByteArray();
53 | if (buf.length > 32) {
54 | throw "data error!";
55 | }
56 | buf = buf.reverse();
57 | let arr2 = new Buffer(32);
58 | for (let i = 0; i < buf.length; i++) {
59 | arr2[i] = buf[i];
60 | }
61 | bufWriter.write(arr2);
62 | };
63 | this.writeDouble = function (value) {
64 | let buffer = new ArrayBuffer(8); // 初始化6个Byte的二进制数据缓冲区
65 | let dataView = new DataView(buffer);
66 | dataView.setFloat64(0, value, true);
67 | let buf = Buffer.alloc(8);
68 | let view = new Uint8Array(buffer);
69 | for (let i = 0; i < 8; i++) {
70 | buf[i] = view[i];
71 | }
72 | bufWriter.write(buf);
73 | };
74 | };
75 |
76 | module.exports = Serializers;
77 |
--------------------------------------------------------------------------------
/src/crypto/eciesCrypto.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var EC = require("elliptic").ec;
4 |
5 | var ec = new EC("secp256k1");
6 | var browserCrypto = global.crypto || global.msCrypto || {};
7 | var subtle = browserCrypto.subtle || browserCrypto.webkitSubtle;
8 |
9 | var nodeCrypto = require('crypto');
10 |
11 | var promise = typeof Promise === "undefined" ?
12 | require("es6-promise").Promise :
13 | Promise;
14 |
15 | var iv = Buffer.from("00000000000000000000000000000000", "hex");
16 |
17 | const EC_GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex');
18 | const ZERO32 = Buffer.alloc(32, 0);
19 |
20 | function assert(condition, message) {
21 | if (!condition) {
22 | throw new Error(message || "Assertion failed");
23 | }
24 | }
25 |
26 | function isScalar(x) {
27 | return Buffer.isBuffer(x) && x.length === 32;
28 | }
29 |
30 | function isValidPrivateKey(privateKey) {
31 | if (!isScalar(privateKey)) {
32 | return false;
33 | }
34 | return privateKey.compare(ZERO32) > 0 && // > 0
35 | privateKey.compare(EC_GROUP_ORDER) < 0; // < G
36 | }
37 |
38 | // Compare two buffers in constant time to prevent timing attacks.
39 | function equalConstTime(b1, b2) {
40 | if (b1.length !== b2.length) {
41 | return false;
42 | }
43 | var res = 0;
44 | for (var i = 0; i < b1.length; i++) {
45 | res |= b1[i] ^ b2[i]; // jshint ignore:line
46 | }
47 | return res === 0;
48 | }
49 |
50 | /* This must check if we're in the browser or
51 | not, since the functions are different and does
52 | not convert using browserify */
53 | function randomBytes(size) {
54 | var arr = new Uint8Array(size);
55 | if (typeof window === 'undefined') {
56 | return Buffer.from(nodeCrypto.randomBytes(size));
57 | } else {
58 | browserCrypto.getRandomValues(arr);
59 | }
60 | return Buffer.from(arr);
61 | }
62 |
63 | function sha512(msg) {
64 | return new promise(function (resolve) {
65 | var hash = nodeCrypto.createHash('sha512');
66 | var result = hash.update(msg).digest();
67 | resolve(new Uint8Array(result));
68 | });
69 | };
70 |
71 | function getAes(op) {
72 | return function (iv, key, data) {
73 | return new promise(function (resolve) {
74 | if (subtle) {
75 | // console.info("dao aes subtle");
76 | var importAlgorithm = {name: "AES-CBC"};
77 | var keyp = subtle.importKey("raw", key, importAlgorithm, false, [op]);
78 | return keyp.then(function (cryptoKey) {
79 | var encAlgorithm = {name: "AES-CBC", iv: iv};
80 | return subtle[op](encAlgorithm, cryptoKey, data);
81 | }).then(function (result) {
82 | resolve(Buffer.from(new Uint8Array(result)));
83 | });
84 | } else {
85 | if (op === 'encrypt') {
86 | var cipher = nodeCrypto.createCipheriv('aes-256-cbc', key, iv);
87 | cipher.update(data);
88 | resolve(cipher.final());
89 | } else if (op === 'decrypt') {
90 | var decipher = nodeCrypto.createDecipheriv('aes-256-cbc', key, iv);
91 | decipher.update(data);
92 | resolve(decipher.final());
93 | }
94 | }
95 | });
96 | };
97 | }
98 |
99 | var aesCbcEncrypt = getAes("encrypt");
100 | var aesCbcDecrypt = getAes("decrypt");
101 |
102 | function hmacSha256Sign(key, msg) {
103 | return new promise(function (resolve) {
104 | var hmac = nodeCrypto.createHmac('sha256', Buffer.from(key));
105 | hmac.update(msg);
106 | var result = hmac.digest();
107 | resolve(result);
108 | });
109 | };
110 |
111 | function hmacSha256Verify(key, msg, sig) {
112 | return new promise(function (resolve) {
113 | var hmac = nodeCrypto.createHmac('sha256', Buffer.from(key));
114 | hmac.update(msg);
115 | var expectedSig = hmac.digest();
116 | resolve(equalConstTime(expectedSig, sig));
117 | });
118 | }
119 |
120 | /**
121 | * Generate a new valid private key. Will use the window.crypto or window.msCrypto as source
122 | * depending on your browser.
123 | * @return {Buffer} A 32-byte private key.
124 | * @function
125 | */
126 | exports.generatePrivate = function () {
127 | var privateKey = randomBytes(32);
128 | while (!isValidPrivateKey(privateKey)) {
129 | privateKey = randomBytes(32);
130 | }
131 | return privateKey;
132 | };
133 |
134 | var getPublic = exports.getPublic = function (privateKey) {
135 | // This function has sync API so we throw an error immediately.
136 | assert(privateKey.length === 32, "Bad private key");
137 | assert(isValidPrivateKey(privateKey), "Bad private key");
138 | // XXX(Kagami): `elliptic.utils.encode` returns array for every
139 | // encoding except `hex`.
140 | return Buffer.from(ec.keyFromPrivate(privateKey).getPublic("arr"));
141 | };
142 |
143 | /**
144 | * Get compressed version of public key.
145 | */
146 | var getPublicCompressed = exports.getPublicCompressed = function (privateKey) { // jshint ignore:line
147 | assert(privateKey.length === 32, "Bad private key");
148 | assert(isValidPrivateKey(privateKey), "Bad private key");
149 | // See https://github.com/wanderer/secp256k1-node/issues/46
150 | let compressed = true;
151 | return Buffer.from(ec.keyFromPrivate(privateKey).getPublic(compressed, "arr"));
152 | };
153 |
154 | // NOTE(Kagami): We don't use promise shim in Browser implementation
155 | // because it's supported natively in new browsers (see
156 | // ) and we can use only new browsers
157 | // because of the WebCryptoAPI (see
158 | // ).
159 | exports.sign = function (privateKey, msg) {
160 | return new promise(function (resolve) {
161 | assert(privateKey.length === 32, "Bad private key");
162 | assert(isValidPrivateKey(privateKey), "Bad private key");
163 | assert(msg.length > 0, "Message should not be empty");
164 | assert(msg.length <= 32, "Message is too long");
165 | resolve(Buffer.from(ec.sign(msg, privateKey, {canonical: true}).toDER()));
166 | });
167 | };
168 |
169 | exports.verify = function (publicKey, msg, sig) {
170 | return new promise(function (resolve, reject) {
171 | assert(publicKey.length === 65 || publicKey.length === 33, "Bad public key");
172 | if (publicKey.length === 65) {
173 | assert(publicKey[0] === 4, "Bad public key");
174 | }
175 | if (publicKey.length === 33) {
176 | assert(publicKey[0] === 2 || publicKey[0] === 3, "Bad public key");
177 | }
178 | assert(msg.length > 0, "Message should not be empty");
179 | assert(msg.length <= 32, "Message is too long");
180 | if (ec.verify(msg, sig, publicKey)) {
181 | resolve(null);
182 | } else {
183 | reject(new Error("Bad signature"));
184 | }
185 | });
186 | };
187 |
188 | var derive = function (privateKeyA, publicKeyB) {
189 | return new promise(function (resolve) {
190 | assert(Buffer.isBuffer(privateKeyA), "Bad private key");
191 | assert(Buffer.isBuffer(publicKeyB), "Bad public key");
192 | assert(privateKeyA.length === 32, "Bad private key");
193 | assert(isValidPrivateKey(privateKeyA), "Bad private key");
194 | assert(publicKeyB.length === 65 || publicKeyB.length === 33, "Bad public key");
195 | if (publicKeyB.length === 65) {
196 | assert(publicKeyB[0] === 4, "Bad public key");
197 | }
198 | if (publicKeyB.length === 33) {
199 | assert(publicKeyB[0] === 2 || publicKeyB[0] === 3, "Bad public key");
200 | }
201 | var keyA = ec.keyFromPrivate(privateKeyA);
202 | var keyB = ec.keyFromPublic(publicKeyB);
203 | var Px = keyA.derive(keyB.getPublic()); // BN instance
204 | resolve(Buffer.from(Px.toArray()));
205 | });
206 | };
207 |
208 | exports.encrypt = async function (publicKeyTo, msg) {
209 | assert(subtle, "WebCryptoAPI is not available");
210 | let ephemPrivateKey = randomBytes(32);
211 | while (!isValidPrivateKey(ephemPrivateKey)) {
212 | ephemPrivateKey = randomBytes(32);
213 | }
214 | let ephemPublicKey = getPublic(ephemPrivateKey);
215 | let Px = await derive(ephemPrivateKey, publicKeyTo);
216 | let hash = await sha512(Px);
217 | let encryptionKey = hash.slice(0, 32);
218 | let macKey = hash.slice(32);
219 | let ciphertext = await aesCbcEncrypt(iv, encryptionKey, msg);
220 | let dataToMac = Buffer.concat([iv, ephemPublicKey, ciphertext]);
221 | let mac = await hmacSha256Sign(macKey, dataToMac);
222 | return Buffer.concat([ephemPublicKey, iv, ciphertext, mac]);
223 | };
224 |
225 | exports.decrypt = async function (privateKey, encrypted) {
226 | assert(subtle, "WebCryptoAPI is not available");
227 | let metaLength = 1 + 64 + 16 + 32;
228 | assert(encrypted.length > metaLength, "Invalid Ciphertext. Data is too small");
229 | assert(encrypted[0] >= 2 && encrypted[0] <= 4, "Not valid ciphertext.");
230 | // deserialise
231 | let ephemPublicKey = encrypted.slice(0, 65);
232 | let cipherTextLength = encrypted.length - metaLength;
233 | let iv = encrypted.slice(65, 65 + 16);
234 | let ciphertext = encrypted.slice(65 + 16, 65 + 16 + cipherTextLength);
235 | let msgMac = encrypted.slice(65 + 16 + cipherTextLength);
236 | let Px = await derive(privateKey, ephemPublicKey);
237 | let hash = await sha512(Px);
238 | let encryptionKey = hash.slice(0, 32);
239 | let macKey = hash.slice(32);
240 | let dataToMac = Buffer.concat([iv, ephemPublicKey, ciphertext]);
241 | let macGood = await hmacSha256Verify(macKey, dataToMac, msgMac);
242 | assert(macGood, "Bad MAC");
243 | let msg = await aesCbcDecrypt(iv, encryptionKey, ciphertext);
244 | return Buffer.from(new Uint8Array(msg));
245 | };
246 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | const sdk = require('./api/sdk');
2 | const txs = require('./model/txs');
3 | const crypto = require("./crypto/eciesCrypto");
4 | const CoinData = require("./model/coindata");
5 | const ContractData = require("./model/contractdata");
6 | const BufferReader = require("./utils/bufferreader");
7 | const TxSignatures = require("./model/signatures");
8 | const Hash = require("./utils/hash");
9 |
10 | module.exports = {
11 |
12 | /**
13 | * 生成地址
14 | * @param chainId
15 | * @param passWord
16 | * @param prefix
17 | * @returns {{}}
18 | */
19 | newAddress(chainId, passWord, prefix) {
20 | let addressInfo = {"prefix": prefix};
21 | if (passWord) {
22 | addressInfo = sdk.newEcKey(passWord);
23 | addressInfo.aesPri = sdk.encrypteByAES(addressInfo.pri, passWord);
24 | addressInfo.pri = null;
25 | } else {
26 | addressInfo = sdk.newEcKey(passWord);
27 | }
28 | addressInfo.address = sdk.getStringAddress(chainId, addressInfo.pri, addressInfo.pub, prefix);
29 | return addressInfo
30 | },
31 |
32 | /**
33 | * 1.0与2.0的私钥或公钥生成地址是否相同
34 | * @param addressV1
35 | * @param addressV2
36 | * @returns {*}
37 | */
38 | addressEquals(addressV1, addressV2) {
39 | return sdk.addressEquals(addressV1, addressV2);
40 | },
41 |
42 | /**
43 | * 根据公钥获取地址
44 | * @param chainId
45 | * @param assetId
46 | * @param pub
47 | * @param prefix
48 | * @returns {*|string}
49 | */
50 | getAddressByPub(chainId, assetId, pub, prefix) {
51 | return sdk.getStringAddressBase(chainId, assetId, '', pub, prefix);
52 | },
53 |
54 | /**
55 | * 验证地址
56 | * @param address
57 | * @returns {*}
58 | */
59 | verifyAddress(address) {
60 | return sdk.verifyAddress(address);
61 | },
62 |
63 | /**
64 | * 导入地址
65 | * @param chainId
66 | * @param pri
67 | * @param passWord
68 | * @param prefix
69 | * @returns {{}}
70 | */
71 | importByKey(chainId, pri, passWord, prefix) {
72 | let addressInfo = {};
73 | const patrn = /^[A-Fa-f0-9]+$/;
74 | if (!patrn.exec(pri)) { //判断私钥是否为16进制
75 | return {success: false, data: 'Bad private key format'}
76 | }
77 | addressInfo.pri = pri;
78 | addressInfo.address = sdk.getStringAddress(chainId, pri, null, prefix);
79 | addressInfo.pub = sdk.getPub(pri);
80 | if (passWord) {
81 | addressInfo.aesPri = sdk.encrypteByAES(addressInfo.pri, passWord);
82 | addressInfo.pri = null;
83 | }
84 | return addressInfo
85 | },
86 |
87 | /**
88 | * 组装交易
89 | * @param inputs
90 | * @param outputs
91 | * @param remark
92 | * @param type
93 | * @param info
94 | * @returns {Array}
95 | */
96 | transactionAssemble(inputs, outputs, remark, type, info) {
97 | let tt = [];
98 | if (type === 2) { //转账交易
99 | tt = new txs.TransferTransaction();
100 | } else if (type === 3) { //设置别名
101 | tt = new txs.AliasTransaction(info.fromAddress, info.alias);
102 | } else if (type === 4) { //创建节点
103 | tt = new txs.CreateAgentTransaction(info);
104 | } else if (type === 5) { //加入共识
105 | tt = new txs.DepositTransaction(info);
106 | } else if (type === 6) { //退出共识
107 | tt = new txs.WithdrawTransaction(info);
108 | } else if (type === 9) { //注销节点
109 | tt = new txs.StopAgentTransaction(info, outputs[0].lockTime - 86400 * 3);
110 | } else if (type === 11) { //注册跨链交易
111 | tt = new txs.RegisterChainAndAssetTransaction(info);
112 | } else if (type === 15) { //创建合约
113 | tt = new txs.CreateContractTransaction(info);
114 | } else if (type === 16) { //调用合约
115 | tt = new txs.CallContractTransaction(info);
116 | } else if (type === 17) { //删除合约
117 | tt = new txs.DeleteContractTransaction(info);
118 | } else if (type === 10) { //跨链转账
119 | tt = new txs.CrossChainTransaction();
120 | } else if (type === 228) { //创建交易对
121 | tt = new txs.CoinTradingTransaction(info);
122 | } else if (type === 229) { //委托挂单
123 | tt = new txs.TradingOrderTransaction(info);
124 | } else if (type === 230) { //取消委托挂单
125 | tt = new txs.CancelTradingOrderTransaction(info);
126 | }
127 | tt.setCoinData(inputs, outputs);
128 | tt.remark = remark;
129 | return tt
130 | },
131 |
132 | /**
133 | * 交易签名
134 | * @param pri
135 | * @param pub
136 | * @param tAssemble
137 | * @returns {boolean}
138 | */
139 | transactionSerialize(pri, pub, tAssemble) {
140 | sdk.signatureTx(tAssemble, pri, pub);
141 | return tAssemble.txSerialize().toString('hex');
142 | },
143 |
144 | /**
145 | * 交易签名
146 | * @param pri
147 | * @param pub
148 | * @param txHex
149 | * @returns signed txHex
150 | */
151 | signTxHex(pri, pub, txHex) {
152 | let tx = new txs.Transaction();
153 | let bufferReader = new BufferReader(Buffer.from(txHex, "hex"), 0);
154 | tx.parse(bufferReader);
155 | sdk.signatureTx(tx, pri, pub);
156 | return tx.txSerialize().toString('hex');
157 | },
158 |
159 | /**
160 | * @disc: App签名,拼接公钥
161 | * @date: 2019-12-03 16:01
162 | * @author: Wave
163 | */
164 | appSplicingPub: function appSplicingPub(signValue, pubHex) {
165 | return sdk.appSplicingPub(signValue, pubHex);
166 | },
167 |
168 | /**
169 | * 交易签名
170 | * @param pri
171 | * @param tAssemble
172 | * @returns {boolean}
173 | */
174 | transactionSignature(pri, tAssemble) {
175 | return sdk.signatureTransaction(tAssemble, pri);
176 | },
177 |
178 | /**
179 | * 解密私钥
180 | * @param aesPri
181 | * @param password
182 | * @returns {*}
183 | */
184 | decrypteOfAES(aesPri, password) {
185 | return sdk.decrypteOfAES(aesPri, password)
186 | },
187 |
188 | /**
189 | * 公钥加密内容
190 | * @param pub
191 | * @param data
192 | * @returns {Promise}
193 | */
194 | async encryptOfECIES(pub, data) {
195 | let bufferData = Buffer.from(data);
196 | let encrypted = await eccrypto.encrypt(pub, bufferData);
197 | return encrypted.toString("hex");
198 | },
199 |
200 | /**
201 | * 私钥解密内容
202 | * @param pri
203 | * @param encrypted
204 | * @returns {Promise}
205 | */
206 | async decryptOfECIES(pri, encrypted) {
207 | let bufferEncrypted = Buffer.from(encrypted, "hex");
208 | let decrypted = await eccrypto.decrypt(pri, bufferData);
209 | return decrypted.toString();
210 | },
211 |
212 | /**
213 | * @disc: hex 解析
214 | * @params: hex
215 | * @date: 2021-04-13 15:57
216 | * @author: Wave
217 | */
218 | hexParsing(hex) {
219 | let tx = new txs.Transaction();
220 | let bufferReader = new BufferReader(Buffer.from(hex, "hex"), 0);
221 | tx.parse(bufferReader);
222 | tx.hash = tx.calcHash();
223 | const coin = new CoinData(new BufferReader(tx.coinData, 0));
224 | const signatures = new TxSignatures(new BufferReader(tx.signatures, 0));
225 | coin.dataReadable();
226 | signatures.dataReadable();
227 | tx.hash = tx.hash.toString('hex');
228 | tx.coinData = coin;
229 | tx.txData = tx.txData.toString('hex');
230 | tx.remark = tx.remark.toString('utf8');
231 | tx.signatures = signatures;
232 | return tx;
233 | },
234 |
235 | contractDataParsing(hex) {
236 | let bufferReader = new BufferReader(Buffer.from(hex, "hex"), 0);
237 | return new ContractData(bufferReader);
238 | },
239 |
240 | programEncodePacked(args) {
241 | return sdk.newProgramEncodePacked(args);
242 | },
243 |
244 | parseProgramEncodePacked(data) {
245 | return sdk.parseProgramEncodePacked(data);
246 | },
247 |
248 | currentTime() {
249 | var times = new Date().valueOf();
250 | return Number(times.toString().substr(0, times.toString().length - 3)); //交易时间
251 | },
252 |
253 | programCreateDataEncodePacked(sender, salt, codeHash) {
254 | return sdk.newProgramCreateDataEncodePacked(sender, salt, codeHash);
255 | },
256 |
257 | hashCode(value) {
258 | let h = 0;
259 | if (value.length > 0) {
260 | for (let i = 0; i < value.length; i++) {
261 | h = 31 * h + value.charCodeAt(i);
262 | h = h | 0; // 保持结果在32位整数范围内
263 | }
264 | }
265 | return h;
266 | },
267 |
268 | getBytesAddress(addressStr) {
269 | return sdk.getBytesAddress(addressStr);
270 | },
271 |
272 | getStringAddressByBytes(buf) {
273 | return sdk.getStringAddressByBytes(buf);
274 | },
275 |
276 | sha256ripemd160(buf) {
277 | return Hash.sha256ripemd160(buf);
278 | }
279 |
280 | };
281 |
--------------------------------------------------------------------------------
/src/model/ProgramCreateDataEncodePacked.js:
--------------------------------------------------------------------------------
1 | const Serializers = require("../api/serializers");
2 |
3 | let ProgramCreateDataEncodePacked = function () {
4 | this.hard = 255;
5 | this.sender = null;
6 | this.salt = null;
7 | this.codeHash = null;
8 |
9 | this.serialize = function () {
10 | let bw = new Serializers();
11 | bw.getBufWriter().writeUInt8(this.hard);
12 | bw.getBufWriter().write(this.sender);
13 | bw.writeBytesWithLength(this.salt);
14 | bw.writeBytesWithLength(this.codeHash);
15 | return bw.getBufWriter().toBuffer();
16 | };
17 |
18 | this.parse = function (bufferReader) {
19 | this.hard = bufferReader.readUInt8();
20 | this.sender = bufferReader.slice(23);
21 | this.salt = bufferReader.readBytesByLength();
22 | this.codeHash = bufferReader.readBytesByLength();
23 | };
24 | };
25 |
26 | module.exports = {
27 | ProgramCreateDataEncodePacked
28 | };
29 |
--------------------------------------------------------------------------------
/src/model/ProgramEncodePacked.js:
--------------------------------------------------------------------------------
1 | const Serializers = require("../api/serializers");
2 |
3 | let ProgramEncodePacked = function () {
4 | this.argsCount = 0;
5 | this.args = null;
6 | this.serialize = function () {
7 | let bw = new Serializers();
8 | bw.getBufWriter().writeUInt8(this.argsCount);
9 | if (this.args && this.args.length > 0) {
10 | for (let i = 0; i < this.args.length; i++) {
11 | bw.writeString(this.args[i]);
12 | }
13 | }
14 | return bw.getBufWriter().toBuffer();
15 | };
16 |
17 | this.parse = function (bufferReader) {
18 | this.argsCount = bufferReader.readUInt8();
19 | this.args = [];
20 | for (let k = 0; k < this.argsCount; k++) {
21 | this.args.push(bufferReader.readBytesByLength().toString());
22 | }
23 | };
24 | };
25 |
26 | module.exports = {
27 | ProgramEncodePacked
28 | };
29 |
--------------------------------------------------------------------------------
/src/model/block.js:
--------------------------------------------------------------------------------
1 | const BlockHeader = require("./blockheader")
2 | const txs = require("./txs")
3 |
4 | var Block = function (bufferReader) {
5 | this.header = new BlockHeader(bufferReader);
6 | this.txList = [];
7 | for (var i = 0; i < this.header.txCount; i++) {
8 | let tx = new txs.Transaction();
9 | tx.parse(bufferReader);
10 | this.txList.push(tx);
11 | }
12 | }
13 | Block.prototype.printInfo = function () {
14 | console.log('header = [');
15 | this.header.printInfo();
16 | console.log(']');
17 | console.log('txList = [');
18 | for(var i=0;i0){
20 | console.log(",")
21 | }
22 | this.txList[i].printInfo();
23 | }
24 | console.log(']');
25 | }
26 |
27 | module.exports = Block;
--------------------------------------------------------------------------------
/src/model/blockheader.js:
--------------------------------------------------------------------------------
1 | const sdk = require("../api/sdk")
2 |
3 | var BlockHeader = function (bufferReader) {
4 | if (!bufferReader) {
5 | return;
6 | }
7 | this.preHash = bufferReader.slice(32);
8 | this.merkleHash = bufferReader.slice(32);
9 | this.createTime = bufferReader.readUInt32LE();
10 | this.height = bufferReader.readUInt32LE();
11 | this.txCount = bufferReader.readUInt32LE();
12 | this.extend = bufferReader.readBytesByLength();
13 | this.publicKey = bufferReader.readBytesByLength()
14 | this.packer = sdk.getStringAddress(1, null, this.publicKey.toString('hex'))
15 | this.signature = bufferReader.readBytesByLength();
16 | }
17 |
18 | BlockHeader.prototype.printInfo = function () {
19 | console.log(' preHash :: ' + this.preHash.toString("hex"));
20 | console.log(' merkleHash:: ' + this.merkleHash.toString("hex"));
21 | console.log(' createTime:: ' + this.createTime + "(" + new Date(this.createTime * 1000).toLocaleString() + ")");
22 | console.log(' height :: ' + this.height);
23 | console.log(' txCount :: ' + this.txCount);
24 | console.log(' extend :: ' + this.extend.toString("hex"));
25 | console.log(' publicKey :: ' + this.publicKey.toString('hex'))
26 | console.log(' packer :: ' + this.packer);
27 | console.log(' signature :: ' + this.signature.toString('hex'));
28 | }
29 |
30 | module.exports = BlockHeader;
--------------------------------------------------------------------------------
/src/model/coindata.js:
--------------------------------------------------------------------------------
1 | const sdk = require("../api/sdk")
2 | var CoinData = function (bufferReader) {
3 | this.fromList = [];
4 | this.toList = [];
5 | var fromCount = bufferReader.readVarInt();
6 | for (var i = 0; i < fromCount; i++) {
7 | this.fromList.push(new CoinFrom(bufferReader));
8 | }
9 | var toCount = bufferReader.readVarInt();
10 | for (var i = 0; i < toCount; i++) {
11 | this.toList.push(new CoinTo(bufferReader));
12 | }
13 | };
14 | var CoinFrom = function (bufferReader) {
15 | this.address = bufferReader.readBytesByLength();
16 | this.assetsChainId = bufferReader.readUInt16LE();
17 | this.assetsId = bufferReader.readUInt16LE();
18 | this.amount = bufferReader.readBigInteger();
19 | this.nonce = bufferReader.readBytesByLength();
20 | this.locked = bufferReader.slice(1);
21 | };
22 | var CoinTo = function (bufferReader) {
23 | this.address = bufferReader.readBytesByLength();
24 | this.assetsChainId = bufferReader.readUInt16LE();
25 | this.assetsId = bufferReader.readUInt16LE();
26 | this.amount = bufferReader.readBigInteger();
27 | this.lockTime = bufferReader.readUInt64LE();
28 | };
29 |
30 | CoinData.prototype.dataReadable = function() {
31 | for (let i = 0; i < this.fromList.length; i++) {
32 | const coinFrom = this.fromList[i];
33 | coinFrom.address = sdk.getStringAddressByBytes(coinFrom.address);
34 | coinFrom.nonce = coinFrom.nonce.toString('hex');
35 | coinFrom.locked = Number(coinFrom.locked.toString('hex'));
36 | }
37 | for (var i = 0; i < this.toList.length; i++) {
38 | const coinTo = this.toList[i];
39 | coinTo.address = sdk.getStringAddressByBytes(coinTo.address);
40 | }
41 | };
42 |
43 | CoinData.prototype.getPrintInfo = function () {
44 | var result = "{\n fromList: [";
45 | for (var i = 0; i < this.fromList.length; i++) {
46 | if (i > 0) {
47 | result += ",";
48 | }
49 | result += this.fromList[i].getPrintInfo();
50 |
51 | }
52 | result += "]\n";
53 | result += " toList : [";
54 | for (var i = 0; i < this.toList.length; i++) {
55 | if (i > 0) {
56 | result += ",";
57 | }
58 | result += this.toList[i].getPrintInfo();
59 | }
60 | result += "]\n }";
61 | return result;
62 | };
63 |
64 | CoinFrom.prototype.getPrintInfo = function () {
65 | var result = "{\n";
66 | result += " address : " + sdk.getStringAddressByBytes(this.address) + ',\n';
67 | result += "assetsChainId : " + this.assetsChainId + '\n';
68 | result += " assetsId : " + this.assetsId + '\n';
69 | result += " amount : " + this.amount + '\n';
70 | result += " nonce : " + this.nonce.toString('hex') + '\n';
71 | result += " locked : " + this.locked + '\n';
72 | result += " }";
73 | return result;
74 | };
75 | CoinTo.prototype.getPrintInfo = function () {
76 | var result = "{\n";
77 | result += " address : " + sdk.getStringAddressByBytes(this.address) + ',\n';
78 | result += "assetsChainId : " + this.assetsChainId + '\n';
79 | result += " assetsId : " + this.assetsId + '\n';
80 | result += " amount : " + this.amount + '\n';
81 | result += " loctTime : " + this.lockTime + '\n';
82 | result += " }";
83 | return result;
84 | };
85 | module.exports = CoinData;
86 |
--------------------------------------------------------------------------------
/src/model/contractdata.js:
--------------------------------------------------------------------------------
1 | const sdk = require("../api/sdk")
2 |
3 | var ContractData = function (bufferReader) {
4 | this.sender = sdk.getStringAddressByBytes(bufferReader.slice(23));
5 | this.contractAddress = sdk.getStringAddressByBytes(bufferReader.slice(23));
6 | this.value = bufferReader.readBigInteger();
7 | this.gasLimit = bufferReader.readUInt64LE();
8 | this.price = bufferReader.readUInt64LE();
9 | this.methodName = bufferReader.readBytesByLength().toString();
10 | try {
11 | this.methodDesc = bufferReader.readBytesByLength().toString();
12 | this.argsCount = bufferReader.readUInt8();
13 | this.args = [];
14 | for (let i = 0; i < this.argsCount; i++) {
15 | let sizePerArg = bufferReader.readUInt8();
16 | if (sizePerArg == 0) {
17 | this.args.push([]);
18 | } else {
19 | let perArg = [];
20 | for (let k = 0; k < sizePerArg; k++) {
21 | perArg.push(bufferReader.readBytesByLength().toString());
22 | }
23 | this.args.push(perArg);
24 | }
25 | }
26 | } catch (e) {
27 | // console.log(e);
28 | }
29 |
30 | };
31 |
32 |
33 | ContractData.prototype.getPrintInfo = function () {
34 | return JSON.stringify(this);
35 | };
36 |
37 | module.exports = ContractData;
38 |
--------------------------------------------------------------------------------
/src/model/signatures.js:
--------------------------------------------------------------------------------
1 | var TxSignatures = function (bufferReader) {
2 | this.list = [];
3 | while (!bufferReader.isFinished()) {
4 | this.list.push(new Item(bufferReader));
5 | }
6 | };
7 | var Item = function (bufferReader) {
8 | var length = bufferReader.readUInt8();
9 | this.publicKey = bufferReader.slice(length);
10 | this.signData = bufferReader.readBytesByLength();
11 | };
12 |
13 | TxSignatures.prototype.dataReadable = function () {
14 | for (let i = 0; i < this.list.length; i++) {
15 | const item = this.list[i];
16 | item.publicKey = item.publicKey.toString('hex');
17 | item.signData = item.signData.toString('hex');
18 | }
19 | };
20 |
21 | TxSignatures.prototype.getPrintInfo = function () {
22 | var result = "[";
23 | for (var i = 0; i < this.list.length; i++) {
24 | if (i > 0) {
25 | result += ",";
26 | }
27 | result += this.list[i].getPrintInfo();
28 | }
29 | result += "]";
30 | return result;
31 | };
32 | Item.prototype.getPrintInfo = function () {
33 | var result = "{\n";
34 | result += " pubkey : " + this.publicKey.toString('hex') + ',\n';
35 | result += " signData : " + this.signData.toString('hex') + '\n';
36 | result += " }";
37 | return result;
38 | };
39 |
40 | module.exports = TxSignatures;
41 |
--------------------------------------------------------------------------------
/src/model/txsignatures.js:
--------------------------------------------------------------------------------
1 | const Serializers = require("../api/serializers");
2 |
3 | let P2PHKSignature = function () {
4 | this.pubkey = null;
5 | this.signData = null;
6 | };
7 |
8 | let TransactionSignatures = function () {
9 | this.signatures = null;
10 | this.serialize = function () {
11 | let bw = new Serializers();
12 | if (this.signatures && this.signatures.length > 0) {
13 | for (let i = 0; i < this.signatures.length; i++) {
14 | let signature = this.signatures[i];
15 | bw.getBufWriter().writeUInt8(signature.pubkey.length);
16 | bw.getBufWriter().write(signature.pubkey);
17 | bw.writeBytesWithLength(signature.signData);
18 | }
19 | }
20 | return bw.getBufWriter().toBuffer();
21 | };
22 |
23 | this.parse = function (bufferReader) {
24 | this.signatures = [];
25 | while (!bufferReader.isFinished()) {
26 | let length = bufferReader.readUInt8();
27 | let sign = new P2PHKSignature();
28 | sign.pubkey = bufferReader.slice(length);
29 | sign.signData = bufferReader.readBytesByLength();
30 | this.signatures.push(sign);
31 | }
32 | };
33 |
34 | this.addSign = function (pubkey, signValue) {
35 | if (!this.signatures || this.signatures == null) {
36 | this.signatures = [];
37 | }
38 | let sign = new P2PHKSignature();
39 | sign.pubkey = pubkey;
40 | sign.signData = signValue;
41 | this.signatures.push(sign);
42 | }
43 | };
44 |
45 | module.exports = {
46 | TransactionSignatures, P2PHKSignature,
47 | };
48 |
--------------------------------------------------------------------------------
/src/test/NAINFTTest/buyToken.js:
--------------------------------------------------------------------------------
1 | const call = require('../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../index");
4 | require('dotenv').config({ path: '../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.lrg;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = 'tNULSeBaN3fGjoJLt5bMVBMjBT9bJHkJwHL2xu';
19 |
20 | let pid = 0;
21 | let tokenAmount = 20;
22 | let payNULS = 24000;// 支付的NULS数量
23 | // buyToken(int pid, int tokenAmount)
24 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
25 | chainId: assetChainId,
26 | sender: fromAddress,
27 | contractAddress: mainContract,
28 | value: new BigNumber(payNULS).shiftedBy(8).toFixed(),
29 | methodName: "buyToken",
30 | methodDesc: "",
31 | args: [
32 | pid, tokenAmount
33 | ]
34 | }, 'call contract...', []);
35 |
36 |
--------------------------------------------------------------------------------
/src/test/NAINFTTest/createToken.js:
--------------------------------------------------------------------------------
1 | const call = require('../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../index");
4 | require('dotenv').config({ path: '../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = 'tNULSeBaN3fGjoJLt5bMVBMjBT9bJHkJwHL2xu';
19 |
20 | const price = 600;// mint一个nft需要的nuls数量
21 | const maxTotalSupply = 100;// 发行总量
22 | const tigerMode = true;// 是否开启老虎机模式
23 | const mintEndingProgress = 6000;// mint阶段比例,万分位
24 | const swapFeeRate = 1000;// 买卖阶段手续费比例,万分位
25 | // 发布token
26 | // String uri, String extendUri, String name, String symbol, String payAsset, BigInteger price, int maxTotalSupply,
27 | // boolean tigerMode, int mintEndingProgress, int swapFeeRate
28 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
29 | chainId: assetChainId,
30 | sender: fromAddress,
31 | contractAddress: mainContract,
32 | value: new BigNumber(10).shiftedBy(8).toFixed(), //
33 | methodName: "createToken",
34 | methodDesc: "",
35 | args: [
36 | 'uritest', 'extendUriTest', 'token1n', 'token1s', '2-1', new BigNumber(price).shiftedBy(8).toFixed(), maxTotalSupply, tigerMode, mintEndingProgress, swapFeeRate
37 | ]
38 | }, 'call contract...', []);
39 |
--------------------------------------------------------------------------------
/src/test/NAINFTTest/mint.js:
--------------------------------------------------------------------------------
1 | const call = require('../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../index");
4 | require('dotenv').config({ path: '../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.l24;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 |
15 | // 资产链ID
16 | const assetChainId = 2;
17 | // 资产ID
18 | const assetId = 1;
19 | const mainContract = 'tNULSeBaN3fGjoJLt5bMVBMjBT9bJHkJwHL2xu';
20 |
21 | let pid = 0;
22 | let mintAmount = 20;
23 | let mintPrice = 600;// mint一个nft需要的nuls数量
24 | // mint token
25 | // int pid, int mintAmount
26 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
27 | chainId: assetChainId,
28 | sender: fromAddress,
29 | contractAddress: mainContract,
30 | value: new BigNumber(mintPrice*mintAmount).shiftedBy(8).toFixed(), //
31 | methodName: "mint",
32 | methodDesc: "",
33 | args: [
34 | pid, mintAmount
35 | ]
36 | }, 'call contract...', []);
37 |
--------------------------------------------------------------------------------
/src/test/NAINFTTest/sellToken.js:
--------------------------------------------------------------------------------
1 | const call = require('../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../index");
4 | require('dotenv').config({ path: '../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.l24;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = 'tNULSeBaN3fGjoJLt5bMVBMjBT9bJHkJwHL2xu';
19 |
20 | let pid = 0;
21 | let tokenIds = [];
22 | for (let i=0;i<10;i++) {
23 | tokenIds.push((i + 0) + "");
24 | }
25 |
26 | // sellToken(int pid, String[] tokenIds)
27 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
28 | chainId: assetChainId,
29 | sender: fromAddress,
30 | contractAddress: mainContract,
31 | value: '0',
32 | methodName: "sellToken",
33 | methodDesc: "",
34 | args: [
35 | pid, tokenIds
36 | ]
37 | }, 'call contract...', []);
38 |
39 |
--------------------------------------------------------------------------------
/src/test/NAIPumpTest/buyToken.js:
--------------------------------------------------------------------------------
1 | const call = require('../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../index");
4 | require('dotenv').config({ path: '../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.l24;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = 'tNULSeBaN26qVMgnxi1AxS1PDfXn2Kpu6YZyud';
19 |
20 | // 期望得到的token数量
21 | let expectAmount = new BigNumber("0").shiftedBy(8).toFixed();
22 | // 接受的滑点损失
23 | let slippage = 0;
24 | // 支付的NULS数量
25 | let payNULS = 50;
26 |
27 | // buyToken( BigInteger expectAmount, int slippage, Address receiver)
28 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
29 | chainId: assetChainId,
30 | sender: fromAddress,
31 | contractAddress: mainContract,
32 | value: new BigNumber(payNULS).shiftedBy(8).toFixed(),
33 | methodName: "buyToken",
34 | methodDesc: "",
35 | args: [
36 | expectAmount, slippage, ''
37 | ]
38 | }, 'call contract...', []);
39 |
40 |
--------------------------------------------------------------------------------
/src/test/NAIPumpTest/createToken.js:
--------------------------------------------------------------------------------
1 | const call = require('../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../index");
4 | require('dotenv').config({ path: '../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = 'tNULSeBaN11T1Y6o9xJf8empYK8acJdykYr7kR';
19 | // 发布token时,项目方支付NULS购买token(可填0)
20 | const buyTokenPay = new BigNumber("50").shiftedBy(8).toFixed();
21 | // 发布token
22 | // String name, String tick, String logoUri, String extendUri
23 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
24 | chainId: assetChainId,
25 | sender: fromAddress,
26 | contractAddress: mainContract,
27 | value: buyTokenPay,
28 | methodName: "createToken",
29 | methodDesc: "",
30 | args: [
31 | 'T2_A6J2_name', 'T2_A6J2', 'uritest', 'extendUriTest'
32 | ]
33 | }, 'call contract...', []);
34 |
--------------------------------------------------------------------------------
/src/test/NAIPumpTest/sellToken.js:
--------------------------------------------------------------------------------
1 | const call = require('../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../index");
4 | require('dotenv').config({ path: '../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = 'tNULSeBaN26qVMgnxi1AxS1PDfXn2Kpu6YZyud';
19 |
20 | // 要卖出的token数量
21 | const amount = new BigNumber("20000000").shiftedBy(8).toFixed();
22 | // 期望得到的NULS数量
23 | const expectReceive = 0;
24 | // 接受的滑点损失
25 | const slippage = 0;
26 |
27 | // sellToken(BigInteger amount, BigInteger expectReceive, int slippage)
28 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
29 | chainId: assetChainId,
30 | sender: fromAddress,
31 | contractAddress: mainContract,
32 | value: '0',
33 | methodName: "sellToken",
34 | methodDesc: "",
35 | args: [
36 | amount, expectReceive, slippage
37 | ]
38 | }, 'call contract...', []);
39 |
40 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Asset_Asset/ReverseSwap/swapWAssetForExactWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../../index");
4 | require('dotenv').config({ path: '../../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.xaf;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | let multyAssets = [
21 | {
22 | value: new BigNumber("2").shiftedBy(18).toFixed(),
23 | assetChainId: 5,
24 | assetId: 74
25 | }
26 | ];
27 |
28 | // Integer chainId, Integer assetId, Integer chainId2, Integer assetId2, BigInteger amountOut, String[] path, Address to, BigInteger deadline, Address ref
29 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
30 | chainId: assetChainId,
31 | sender: fromAddress,
32 | contractAddress: mainContract,
33 | value: 0, //
34 | methodName: "swapWAssetForExactWAsset",
35 | methodDesc: "",
36 | args: [
37 | 5, 74, 5, 1, new BigNumber("50").shiftedBy(8).toFixed(), [process.env.wusdt, process.env.wnvt], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
38 | ]
39 | }, 'swap usdt for nvt', multyAssets);
40 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Asset_Asset/addLiquidityWAssetAndWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.lrg;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // 转入200个USDT
21 | let multyAssets = [
22 | {
23 | value: new BigNumber("300").shiftedBy(18).toFixed(),
24 | assetChainId: 5,
25 | assetId: 74
26 | },
27 | {
28 | value: new BigNumber("20000").shiftedBy(8).toFixed(),
29 | assetChainId: 5,
30 | assetId: 1
31 | }
32 | ];
33 |
34 | // Integer chainId, Integer assetId, Integer chainId2, Integer assetId2, BigInteger amountTokenMin, BigInteger amountETHMin, Address to, BigInteger deadline
35 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
36 | chainId: assetChainId,
37 | sender: fromAddress,
38 | contractAddress: mainContract,
39 | value: 0, //
40 | methodName: "addLiquidityWAssetAndWAsset",
41 | methodDesc: "",
42 | args: [
43 | 5, 74, 5, 1, 0, 0, fromAddress, nuls.currentTime() + 300
44 | ]
45 | }, 'add lp usdt(300) and nvt(20000)', multyAssets);
46 | // pair: tNULSeBaMypw3yptBpGRr35B5NETxsiFHdBfWv
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Asset_Asset/removeLiquidityWAssetWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.lrg;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // Integer chainId, Integer assetId, Integer chainId2, Integer assetId2, BigInteger liquidity, BigInteger amountTokenMin, BigInteger amountETHMin, Address to, BigInteger deadline
21 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: 0, //
26 | methodName: "removeLiquidityWAssetWAsset",
27 | methodDesc: "",
28 | args: [
29 | 5, 74, 5, 1, new BigNumber('12247448713915000').shiftedBy(0).toFixed(), 0, 0, fromAddress, nuls.currentTime() + 300
30 | ]
31 | }, 'remove lp usdt and nvt', []);
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Asset_Asset/swapExactWAssetForWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // 转入1个USDT
21 | let multyAssets = [
22 | {
23 | value: new BigNumber("1").shiftedBy(18).toFixed(),
24 | assetChainId: 5,
25 | assetId: 74
26 | }
27 | ];
28 |
29 | // Integer chainId, Integer assetId, Integer chainId2, Integer assetId2, BigInteger amountOutMin, String[] path, Address to, BigInteger deadline, Address ref
30 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
31 | chainId: assetChainId,
32 | sender: fromAddress,
33 | contractAddress: mainContract,
34 | value: 0, //
35 | methodName: "swapExactWAssetForWAsset",
36 | methodDesc: "",
37 | args: [
38 | 5, 74, 5, 1, 0, [process.env.wusdt, process.env.wnvt], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
39 | ]
40 | }, 'swap usdt for nvt', multyAssets);
41 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Asset_Token/ReverseSwap/swapTokensForExactWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../../index");
4 | require('dotenv').config({ path: '../../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.xaf;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // Integer chainId, Integer assetId, BigInteger amountOut, BigInteger amountInMax, String[] path, Address to, BigInteger deadline, Address ref
21 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: 0, //
26 | methodName: "swapTokensForExactWAsset",
27 | methodDesc: "",
28 | args: [
29 | 5, 74, new BigNumber("1").shiftedBy(18).toFixed(), new BigNumber("70").shiftedBy(18).toFixed(), [process.env.qqq, process.env.wusdt], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
30 | ]
31 | }, 'swap qqq for wusdt', []);
32 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Asset_Token/ReverseSwap/swapWAssetForExactTokens.js:
--------------------------------------------------------------------------------
1 | const call = require('../../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../../index");
4 | require('dotenv').config({ path: '../../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.xaf;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | let multyAssets = [
21 | {
22 | value: new BigNumber("2").shiftedBy(18).toFixed(),
23 | assetChainId: 5,
24 | assetId: 74
25 | }
26 | ];
27 |
28 | // Integer chainId, Integer assetId, BigInteger amountOut, String[] path, Address to, BigInteger deadline, Address ref
29 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
30 | chainId: assetChainId,
31 | sender: fromAddress,
32 | contractAddress: mainContract,
33 | value: 0, //
34 | methodName: "swapWAssetForExactTokens",
35 | methodDesc: "",
36 | args: [
37 | 5, 74, new BigNumber("50").shiftedBy(18).toFixed(), [process.env.wusdt, process.env.qqq], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
38 | ]
39 | }, 'swap usdt for qqq', multyAssets);
40 | // 900.000988390779549621,60000.052887738874063295
41 | // "0.752884336422843860","50.000000000000000000"
42 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Asset_Token/addLiquidityWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.xaf;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // 转入200个USDT
21 | let multyAssets = [
22 | {
23 | value: new BigNumber("300").shiftedBy(18).toFixed(),
24 | assetChainId: 5,
25 | assetId: 74
26 | }
27 | ];
28 |
29 | //Integer chainId, Integer assetId, Address token, BigInteger amountTokenDesired, BigInteger amountTokenMin, BigInteger amountETHMin, Address to, BigInteger deadline
30 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
31 | chainId: assetChainId,
32 | sender: fromAddress,
33 | contractAddress: mainContract,
34 | value: 0, //
35 | methodName: "addLiquidityWAsset",
36 | methodDesc: "",
37 | args: [
38 | 5, 74, process.env.qqq, new BigNumber("20000").shiftedBy(18).toFixed(), 0, 0, fromAddress, nuls.currentTime() + 300
39 | ]
40 | }, 'add lp usdt(300) and qqq(20000)', multyAssets);
41 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Asset_Token/removeLiquidityWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.xaf;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // Integer chainId, Integer assetId, Address token, BigInteger liquidity, BigInteger amountTokenMin, BigInteger amountETHMin, Address to, BigInteger deadline
21 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: 0, //
26 | methodName: "removeLiquidityWAsset",
27 | methodDesc: "",
28 | args: [
29 | 5, 74, process.env.qqq, new BigNumber('3348469228349534293591').shiftedBy(0).toFixed(), 0, 0, fromAddress, nuls.currentTime() + 300
30 | ]
31 | }, 'remove lp usdt and qqq', []);
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Asset_Token/swapExactTokensForWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.xaf;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // Integer chainId, Integer assetId, BigInteger amountIn, BigInteger amountOutMin, String[] path, Address to, BigInteger deadline, Address ref
21 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: 0, //
26 | methodName: "swapExactTokensForWAsset",
27 | methodDesc: "",
28 | args: [
29 | 5, 74, new BigNumber("20").shiftedBy(18).toFixed(), 0, [process.env.qqq, process.env.wusdt], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
30 | ]
31 | }, 'swap qqq for usdt', []);
32 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Asset_Token/swapExactWAssetForTokens.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // 转入1个USDT
21 | let multyAssets = [
22 | {
23 | value: new BigNumber("0.3").shiftedBy(18).toFixed(),
24 | assetChainId: 5,
25 | assetId: 74
26 | }
27 | ];
28 |
29 | // Integer chainId, Integer assetId, BigInteger amountOutMin, String[] path, Address to, BigInteger deadline, Address ref
30 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
31 | chainId: assetChainId,
32 | sender: fromAddress,
33 | contractAddress: mainContract,
34 | value: 0, //
35 | methodName: "swapExactWAssetForTokens",
36 | methodDesc: "",
37 | args: [
38 | 5, 74, 0, [process.env.wusdt, process.env.qqq], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
39 | ]
40 | }, 'swap usdt for qqq', multyAssets);
41 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Asset/ReverseSwap/swapNulsForExactWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../../index");
4 | require('dotenv').config({ path: '../../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // Integer chainId, Integer assetId, BigInteger amountOut, String[] path, Address to, BigInteger deadline, Address ref
21 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: new BigNumber("5").shiftedBy(8).toFixed(), //
26 | methodName: "swapNulsForExactWAsset",
27 | methodDesc: "",
28 | args: [
29 | 5, 1, new BigNumber("5").shiftedBy(8).toFixed(), [process.env.wnuls, process.env.wnvt], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
30 | ]
31 | }, 'swap nuls for nvt', []);
32 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Asset/ReverseSwap/swapWAssetForExactNuls.js:
--------------------------------------------------------------------------------
1 | const call = require('../../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../../index");
4 | require('dotenv').config({ path: '../../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // 转入1个NVT
21 | let multyAssets = [
22 | {
23 | value: new BigNumber("10").shiftedBy(8).toFixed(),
24 | assetChainId: 5,
25 | assetId: 1
26 | }
27 | ];
28 |
29 | // Integer chainId, Integer assetId, BigInteger amountOut, String[] path, Address to, BigInteger deadline, Address ref
30 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
31 | chainId: assetChainId,
32 | sender: fromAddress,
33 | contractAddress: mainContract,
34 | value: 0, //
35 | methodName: "swapWAssetForExactNuls",
36 | methodDesc: "",
37 | args: [
38 | 5, 1, new BigNumber("4").shiftedBy(8).toFixed(), [process.env.wnvt, process.env.wnuls], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
39 | ]
40 | }, 'swap nvt for nuls', multyAssets);
41 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Asset/addLiquidityNULSWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.lrg;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // 转入100个NVT
21 | let multyAssets = [
22 | {
23 | value: new BigNumber("100").shiftedBy(8).toFixed(),
24 | assetChainId: 5,
25 | assetId: 1
26 | }
27 | ];
28 |
29 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
30 | chainId: assetChainId,
31 | sender: fromAddress,
32 | contractAddress: mainContract,
33 | value: new BigNumber("50").shiftedBy(8).toFixed(), //
34 | methodName: "addLiquidityNULSWAsset",
35 | methodDesc: "",
36 | args: [
37 | 5, 1, 0, 0, fromAddress, nuls.currentTime() + 300
38 | ]
39 | }, 'add lp nuls(50) and nvt(100)', multyAssets);
40 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Asset/removeLiquidityNulsWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.lrg;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
21 | chainId: assetChainId,
22 | sender: fromAddress,
23 | contractAddress: mainContract,
24 | value: 0, //
25 | methodName: "removeLiquidityNulsWAsset",
26 | methodDesc: "",
27 | args: [
28 | 5, 1, new BigNumber('3071066811').shiftedBy(0).toFixed(), 0, 0, fromAddress, nuls.currentTime() + 300
29 | ]
30 | }, 'remove lp nuls and nvt', []);
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Asset/swapExactNulsForWAsset.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.lrg;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | //Integer chainId, Integer assetId, BigInteger amountOutMin, String[] path, Address to, BigInteger deadline, Address ref
21 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: new BigNumber("1").shiftedBy(8).toFixed(), //
26 | methodName: "swapExactNulsForWAsset",
27 | methodDesc: "",
28 | args: [
29 | 5, 1, 0, [process.env.wnuls, process.env.wnvt], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
30 | ]
31 | }, 'swap nuls for nvt', []);
32 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Asset/swapExactWAssetForNuls.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // 转入1个NVT
21 | let multyAssets = [
22 | {
23 | value: new BigNumber("1").shiftedBy(8).toFixed(),
24 | assetChainId: 5,
25 | assetId: 1
26 | }
27 | ];
28 |
29 | // Integer chainId, Integer assetId, BigInteger amountOutMin, String[] path, Address to, BigInteger deadline, Address ref
30 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
31 | chainId: assetChainId,
32 | sender: fromAddress,
33 | contractAddress: mainContract,
34 | value: 0, //
35 | methodName: "swapExactWAssetForNuls",
36 | methodDesc: "",
37 | args: [
38 | 5, 1, 0, [process.env.wnvt, process.env.wnuls], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
39 | ]
40 | }, 'swap nvt for nuls', multyAssets);
41 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Token/ReverseSwap/swapNulsForExactTokens.js:
--------------------------------------------------------------------------------
1 | const call = require('../../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../../index");
4 | require('dotenv').config({ path: '../../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // BigInteger amountOut, String[] path, Address to, BigInteger deadline, Address ref
21 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: new BigNumber("1").shiftedBy(8).toFixed(), //
26 | methodName: "swapNulsForExactTokens",
27 | methodDesc: "",
28 | args: [
29 | new BigNumber("5000").shiftedBy(18).toFixed(), [process.env.wnuls, process.env.fark], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
30 | ]
31 | }, 'swap nuls for fark', []);
32 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Token/ReverseSwap/swapTokensForExactNuls.js:
--------------------------------------------------------------------------------
1 | const call = require('../../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../../index");
4 | require('dotenv').config({ path: '../../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // BigInteger amountOut, BigInteger amountInMax, String[] path, Address to, BigInteger deadline, Address ref
21 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: 0, //
26 | methodName: "swapTokensForExactNuls",
27 | methodDesc: "",
28 | args: [
29 | new BigNumber("1").shiftedBy(8).toFixed(), new BigNumber("2000").shiftedBy(18).toFixed(), [process.env.fark, process.env.wnuls], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
30 | ]
31 | }, 'swap fark for nuls', []);
32 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Token/addLiquidityNuls.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
21 | chainId: assetChainId,
22 | sender: fromAddress,
23 | contractAddress: mainContract,
24 | value: new BigNumber(50).shiftedBy(8).toFixed(), //
25 | methodName: "addLiquidityNuls",
26 | methodDesc: "",
27 | args: [
28 | process.env.fark, new BigNumber(100).shiftedBy(18).toFixed(), 0, 0, fromAddress, nuls.currentTime() + 300
29 | ]
30 | }, 'add lp nuls(50) and fark(100)', []);
31 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Token/removeLiquidityNuls.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
21 | chainId: assetChainId,
22 | sender: fromAddress,
23 | contractAddress: mainContract,
24 | value: 0, //
25 | methodName: "removeLiquidityNuls",
26 | methodDesc: "",
27 | args: [
28 | process.env.fark, new BigNumber('353553390592773').shiftedBy(0).toFixed(), 0, 0, fromAddress, nuls.currentTime() + 300
29 | ]
30 | }, 'remove lp nuls and fark', []);
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Token/swapExactNulsForTokens.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | async function swapNulsForFark() {
21 | await call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: new BigNumber(100).shiftedBy(8).toFixed(), //
26 | methodName: "swapExactNulsForTokens",
27 | methodDesc: "",
28 | args: [
29 | 0, [process.env.wnuls, process.env.fark], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
30 | ]
31 | }, 'swap nuls(1) for fark', []);
32 | }
33 |
34 |
35 | async function swapNulsForCCC() {
36 | await call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
37 | chainId: assetChainId,
38 | sender: fromAddress,
39 | contractAddress: mainContract,
40 | value: new BigNumber(1).shiftedBy(8).toFixed(), //
41 | methodName: "swapExactNulsForTokens",
42 | methodDesc: "",
43 | args: [
44 | 0, [process.env.wnuls, process.env.fark, process.env.ccc], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
45 | ]
46 | }, 'swap nuls for ccc: nuls to fark to ccc', []);
47 | }
48 |
49 | swapNulsForFark();
50 | // swapNulsForCCC();
51 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Nuls_Token/swapExactTokensForNuls.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | async function swapFarkForNuls() {
21 | await call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: 0, //
26 | methodName: "swapExactTokensForNuls",
27 | methodDesc: "",
28 | args: [
29 | new BigNumber(10000).shiftedBy(18).toFixed(), 0, [process.env.fark, process.env.wnuls], process.env.lrgAddr, nuls.currentTime() + 300, process.env.lrgAddr
30 | ]
31 | }, 'swap fark for nuls', []);
32 | }
33 |
34 | async function swapCCCForNuls() {
35 | await call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
36 | chainId: assetChainId,
37 | sender: fromAddress,
38 | contractAddress: mainContract,
39 | value: 0, //
40 | methodName: "swapExactTokensForNuls",
41 | methodDesc: "",
42 | args: [
43 | new BigNumber(1).shiftedBy(8).toFixed(), 0, [process.env.ccc, process.env.fark, process.env.wnuls], fromAddress, nuls.currentTime() + 300, process.env.burnAddr
44 | ]
45 | }, 'swap ccc for nuls: ccc to fark to nuls', []);
46 | }
47 |
48 | swapFarkForNuls();
49 | // swapCCCForNuls();
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Token_Token/ReverseSwap/swapTokensForExactTokens.js:
--------------------------------------------------------------------------------
1 | const call = require('../../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../../index");
4 | require('dotenv').config({ path: '../../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.xaf;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // BigInteger amountOut, BigInteger amountInMax, String[] path, Address to, BigInteger deadline, Address ref
21 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: 0, //
26 | methodName: "swapTokensForExactTokens",
27 | methodDesc: "",
28 | args: [
29 | new BigNumber("0.5").shiftedBy(18).toFixed(), new BigNumber("50").shiftedBy(18).toFixed(), [process.env.fark, process.env.qqq], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
30 | ]
31 | }, 'swap fark for qqq', []);
32 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Token_Token/addLiquidity.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.xaf;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | //Address tokenA, Address tokenB, BigInteger amountADesired, BigInteger amountBDesired, BigInteger amountAMin, BigInteger amountBMin, Address to, BigInteger deadline
21 | async function addFarkAndQQQ() {
22 | await call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
23 | chainId: assetChainId,
24 | sender: fromAddress,
25 | contractAddress: mainContract,
26 | value: 0, //
27 | methodName: "addLiquidity",
28 | methodDesc: "",
29 | args: [
30 | process.env.fark, process.env.qqq, new BigNumber("500").shiftedBy(18).toFixed(), new BigNumber("10000").shiftedBy(18).toFixed(), 0, 0, fromAddress, nuls.currentTime() + 300
31 | ]
32 | }, 'add lp fark(500) and qqq(10000)', []);
33 | }
34 |
35 | async function addFarkAndCcc() {
36 | await call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
37 | chainId: assetChainId,
38 | sender: fromAddress,
39 | contractAddress: mainContract,
40 | value: 0, //
41 | methodName: "addLiquidity",
42 | methodDesc: "",
43 | args: [
44 | process.env.fark, process.env.ccc, new BigNumber("50").shiftedBy(18).toFixed(), new BigNumber("100").shiftedBy(8).toFixed(), 0, 0, fromAddress, nuls.currentTime() + 300
45 | ]
46 | }, 'add lp fark(50) and ccc(100)', []);
47 | }
48 |
49 | // addFarkAndQQQ();
50 | addFarkAndCcc();
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Token_Token/removeLiquidity.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // Address tokenA, Address tokenB, BigInteger liquidity, BigInteger amountAMin, BigInteger amountBMin, Address to, BigInteger deadline
21 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
22 | chainId: assetChainId,
23 | sender: fromAddress,
24 | contractAddress: mainContract,
25 | value: 0, //
26 | methodName: "removeLiquidity",
27 | methodDesc: "",
28 | args: [
29 | process.env.fark, process.env.ccc, new BigNumber('353553390592773').shiftedBy(0).toFixed(), 0, 0, fromAddress, nuls.currentTime() + 300
30 | ]
31 | }, 'remove lp fark and ccc', []);
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/test/NSWAPTest/Token_Token/swapExactTokensForTokens.js:
--------------------------------------------------------------------------------
1 | const call = require('../../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../../index");
4 | require('dotenv').config({ path: '../../../test/.env'});
5 |
6 | // 用户私钥
7 | const pri = process.env.asd;
8 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
9 | // 用户公钥
10 | const pub = importAddress.pub;
11 | // 用户地址
12 | const fromAddress = importAddress.address;
13 | console.log('fromAddress', fromAddress);
14 | // 资产链ID
15 | const assetChainId = 2;
16 | // 资产ID
17 | const assetId = 1;
18 | const mainContract = process.env.router;
19 |
20 | // BigInteger amountIn, BigInteger amountOutMin, String[] path, Address to, BigInteger deadline, Address ref
21 | async function swapFarkForCCC() {
22 | await call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
23 | chainId: assetChainId,
24 | sender: fromAddress,
25 | contractAddress: mainContract,
26 | value: 0, //
27 | methodName: "swapExactTokensForTokens",
28 | methodDesc: "",
29 | args: [
30 | new BigNumber("1").shiftedBy(18).toFixed(), 0, [process.env.fark, process.env.ccc], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
31 | ]
32 | }, 'swap fark for ccc', []);
33 | }
34 |
35 | async function swapCCCForFark() {
36 | await call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
37 | chainId: assetChainId,
38 | sender: fromAddress,
39 | contractAddress: mainContract,
40 | value: 0, //
41 | methodName: "swapExactTokensForTokens",
42 | methodDesc: "",
43 | args: [
44 | new BigNumber("1").shiftedBy(8).toFixed(), 0, [process.env.ccc, process.env.fark], fromAddress, nuls.currentTime() + 300, 'tNULSeBaN5nddf9WkQgRr3RNwARgryndv2Bzs6'
45 | ]
46 | }, 'swap ccc for fark', []);
47 | }
48 |
49 | swapCCCForFark();
--------------------------------------------------------------------------------
/src/test/NSWAPTest/approveTokenToRouter.js:
--------------------------------------------------------------------------------
1 | const call = require('../contractCall.js');
2 | const BigNumber = require("bignumber.js");
3 | const nuls = require("../../index");
4 | require('dotenv').config({ path: '../../test/.env'});
5 |
6 | async function approve(pri, mainContract, to) {
7 | const importAddress = nuls.importByKey(2, pri, '', "tNULS");
8 | // 用户公钥
9 | const pub = importAddress.pub;
10 | // 用户地址
11 | const fromAddress = importAddress.address;
12 | console.log('fromAddress', fromAddress);
13 | // 资产链ID
14 | const assetChainId = 2;
15 | // 资产ID
16 | const assetId = 1;
17 |
18 | await call.callContract(pri, pub, fromAddress, assetChainId, assetId, {
19 | chainId: assetChainId,
20 | sender: fromAddress,
21 | contractAddress: mainContract,
22 | value: 0, //
23 | methodName: "approve",
24 | methodDesc: "",
25 | args: [
26 | to, new BigNumber(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff).toFixed()
27 | ]
28 | }, 'call contract...', []);
29 | }
30 |
31 | async function approveList() {
32 | const router = process.env.router;
33 | await approve(process.env.asd, process.env.fark, router);// FARK
34 | console.log('asd fark done.');
35 | await approve(process.env.xaf, process.env.fark, router);// FARK
36 | console.log('xaf fark done.');
37 | await approve(process.env.asd, process.env.ddd, router);// DDD
38 | console.log('asd ddd done.');
39 | await approve(process.env.xaf, process.env.ddd, router);// DDD
40 | console.log('xaf ddd done.');
41 | await approve(process.env.asd, process.env.ccc, router);// CCC
42 | console.log('asd ccc done.');
43 | await approve(process.env.xaf, process.env.ccc, router);// CCC
44 | console.log('xaf ccc done.');
45 | await approve(process.env.asd, process.env.qqq, router);// QQQ
46 | console.log('asd qqq done.');
47 | await approve(process.env.xaf, process.env.qqq, router);// QQQ
48 | console.log('xaf qqq done.');
49 | // await approve(process.env.lrg, 'tNULSeBaMxs25kpN94U9uXArQ7QCGLsmPurRqt', router);// Pair.LPAddress
50 | }
51 |
52 | approveList();
--------------------------------------------------------------------------------
/src/test/NSWAPTest/calcPairAddress.js:
--------------------------------------------------------------------------------
1 |
2 | const nuls = require("../../index");
3 | const keccak = require('keccak');
4 |
5 | const factory = 'tNULSeBaMzYWiaCcZPu3kD2nJ52jMzMvbNzgVn';
6 | const pairCodeHash = '39a7640b54538bafd656a732db46decbed89389cf6207b168dda6f925d60c590';
7 | const tokenA = 'tNULSeBaMy1Rk3KaHcvXYTGNoNpr8ckAzkKWfS';
8 | const tokenB = 'tNULSeBaN8Ps39De43Gik5GfQ6h4GYsHGmwNcP';
9 |
10 | const wAssetFactory = 'tNULSeBaNCULzexmzet8TbRu6uFnzZarwAX4yb';
11 | const wAssetCodeHash = '8ecce50a65f33c0c8d7ae30d4f7c0b04608ac9825a1db7f1eb6cb7e204e3776f';
12 |
13 | function calcDeployedAddress(chainId, sender, salt, codeHash) {
14 | const saltBuf = Buffer.from(nuls.programEncodePacked(salt), 'hex');
15 | const createData = nuls.programCreateDataEncodePacked(nuls.getBytesAddress(sender), saltBuf, Buffer.from(codeHash, 'hex'));
16 | const hash160 = nuls.sha256ripemd160(keccak('keccak256').update(Buffer.from(createData, 'hex')).digest());
17 | const chainIdBuffer = Buffer.concat([Buffer.from([0xFF & chainId >> 0]), Buffer.from([0xFF & chainId >> 8])]);
18 | const addrBuffer = Buffer.concat([chainIdBuffer, Buffer.from([2]), hash160]);
19 | return nuls.getStringAddressByBytes(addrBuffer);
20 | }
21 |
22 | function calcPairAddress(chainId, _tokenA, _tokenB) {
23 |
24 | // TokenA cannot be equal to TokenB
25 | if (_tokenA == _tokenB) {
26 | throw "IDENTICAL_ADDRESSES";
27 | }
28 | // Find the correct order of the tokens
29 | let token0;
30 | let token1;
31 | if (nuls.hashCode(tokenA) < nuls.hashCode(tokenB)) {
32 | token0 = _tokenA;
33 | token1 = _tokenB;
34 | } else {
35 | token0 = _tokenB;
36 | token1 = _tokenA;
37 | }
38 | return calcDeployedAddress(chainId, factory, ['pair', token0, token1], pairCodeHash);
39 | }
40 |
41 | function calcWAssetAddress(chainId, assetChainId, assetId) {
42 | return calcDeployedAddress(chainId, wAssetFactory, ['wasset', 'w' + assetChainId, 'w' + assetId], wAssetCodeHash)
43 | }
44 |
45 | console.log(calcPairAddress(2, tokenA, tokenB));
46 | console.log(calcWAssetAddress(2, 5, 1));
47 | console.log(calcWAssetAddress(2, 5, 74));
--------------------------------------------------------------------------------
/src/test/addressByPub.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 |
3 | /**
4 | * @disc: 根据公钥获取地址
5 | * @date: 2019-10-18 10:27
6 | * @author: Wave
7 | */
8 |
9 | let addressInfo = {
10 | pub: '02458d425e75a95688571c4cc074289a34d27c74cd284d6be316a775b363a205c3',
11 | address: 'tNULSeBaMiv3V2KMKbkHL8ZRgQRkP6CYUG2hia',
12 | };
13 | let address = nuls.getAddressByPub(2, 1, addressInfo.pub, 'tNULS');
14 | console.log(address);
15 | console.log(address === addressInfo.address);
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/test/api/https.js:
--------------------------------------------------------------------------------
1 | const axios = require('axios');
2 | const API_CHAIN_ID = 2;
3 | axios.defaults.timeout = 8000;
4 | // axios.defaults.baseURL = 'http://127.0.0.1:18004/api';
5 | // axios.defaults.baseURL = 'http://localhost:18003/';
6 | axios.defaults.baseURL = 'https://beta.public1.nuls.io/';
7 | // axios.defaults.baseURL = 'https://beta.api.nuls.io/jsonrpc';
8 | // axios.defaults.baseURL = 'http://127.0.0.1:18004/jsonrpc';
9 | axios.defaults.headers.post['Content-Type'] = 'application/json';
10 |
11 | /**
12 | * 封装post请求
13 | * Encapsulation post method
14 | * @param url
15 | * @param methodName
16 | * @param data
17 | * @returns {Promise}
18 | */
19 | module.exports = {
20 | post(url, methodName, data = []) {
21 | return new Promise((resolve, reject) => {
22 | data.unshift(API_CHAIN_ID);
23 | const params = {"jsonrpc": "2.0", "method": methodName, "params": data, "id": 5898};
24 | axios.post(url, params)
25 | .then(response => {
26 | resolve(response.data)
27 | }, err => {
28 | reject(err)
29 | })
30 | })
31 | },
32 |
33 | postComplete(url, methodName, data = []) {
34 | return new Promise((resolve, reject) => {
35 | const params = {"jsonrpc": "2.0", "method": methodName, "params": data, "id": 5899};
36 | axios.post(url, params)
37 | .then(response => {
38 | resolve(response.data)
39 | }, err => {
40 | reject(err)
41 | })
42 | })
43 | }
44 | };
45 |
--------------------------------------------------------------------------------
/src/test/coinTrading.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const sdk = require('../api/sdk')
3 | const {getBalance, countFee, inputsOrOutputs, validateTx, broadcastTx} = require('./api/util');
4 |
5 | /**
6 | * @disc: 创建交易对 dome
7 | * @params:
8 | * @date: 2019-12-9 10:38
9 | * @author: vivi
10 | */
11 |
12 | let pri = '4100e2f88c3dba08e5000ed3e8da1ae4f1e0041b856c09d35a26fb399550f530';
13 | let pub = '020e19418ed26700b0dba720dcc95483cb4adb1b5f8a103818dab17d5b05231854';
14 | let fromAddress = "tNULSeBaMu38g1vnJsSZUCwTDU9GsE5TVNUtpD";
15 | //创建交易对收款地址
16 | let toAddress = 'tNULSeBaMqywZjfSrKNQKBfuQtVxAHBQ8rB2Zn';
17 | //创建交易对需要金额
18 | let amount = 2000000000000;
19 | let remark = 'create coinTrading....';
20 | let txType = 28;
21 |
22 | let coinTradingInfo = {
23 | quoteAssetChainId: 2, //计价货币chainId
24 | quoteAssetId: 1, //计价货币assetId
25 | quoteMinDecimal: 5, //计价货币交易允许最小小数位
26 | quoteMinSize: 1000000, //计价货币允许最小交易量
27 | baseAssetChainId: 2, //交易货币chainId
28 | baseAssetId: 2, //交易货币assetId
29 | baseMinDecimal: 5, //交易货币交易允许最小小数位
30 | baseMinSize: 1000000, //交易货币允许最小交易量
31 | };
32 |
33 | let transferInfo = {
34 | fromAddress: fromAddress,
35 | toAddress: toAddress,
36 | assetsChainId: 2,
37 | assetsId: 1,
38 | amount: amount,
39 | remark: remark,
40 | fee: 1000000
41 | };
42 |
43 | //调用设置别名
44 | coinTrading(transferInfo, coinTradingInfo);
45 |
46 | /**
47 | * 设置别名
48 | * @param pri
49 | * @param pub
50 | * @param fromAddress
51 | * @param toAddress
52 | * @param assetsChainId
53 | * @param assetsId
54 | * @param amount
55 | * @param remark
56 | * @returns {Promise}
57 | */
58 | async function coinTrading(transferInfo, coinTradingInfo) {
59 | //账户转出资产余额
60 | //console.log(transferInfo);
61 | const balanceInfo = await getBalance(transferInfo.assetsChainId, transferInfo.assetsChainId, transferInfo.assetsId, transferInfo.fromAddress);
62 |
63 | let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, txType);
64 |
65 | //交易组装
66 | let tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, txType, coinTradingInfo);
67 | console.log(tAssemble);
68 | //获取hash
69 | let hash = await tAssemble.getHash();
70 | console.log(hash);
71 | //交易签名
72 | let txSignature = await sdk.getSignData(hash.toString('hex'), pri);
73 | console.log(txSignature);
74 | //通过拼接签名、公钥获取HEX
75 | let signData = await sdk.appSplicingPub(txSignature.signValue, pub);
76 | tAssemble.signatures = signData;
77 | let txhex = tAssemble.txSerialize().toString("hex");
78 | console.log(txhex.toString('hex'));
79 |
80 | /*let getHex = await sdk.appSplicingPub(txSignature);
81 | console.log(getHex);
82 |
83 | let txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
84 | console.log(txhex);*/
85 | // let result = await validateTx(txhex.toString('hex'));
86 | // console.log(result);
87 | // if (result) {
88 | // console.log(result.data.value);
89 | // let results = await broadcastTx(txhex);
90 | // if (results && result.data.value) {
91 | // console.log("交易完成")
92 | // } else {
93 | // console.log("广播交易失败")
94 | // }
95 | // } else {
96 | // console.log("验证交易失败")
97 | // }
98 | }
99 |
100 |
101 |
--------------------------------------------------------------------------------
/src/test/coindata.js:
--------------------------------------------------------------------------------
1 | const tx = require('../model/txs');
2 | let inputs = [];
3 | inputs.push({
4 | address: 'LINcjJR16WwP7a7irS3T4p1td7QAd2MSUEqk',
5 | assetsChainId: 8,
6 | assetsId: 1,
7 | amount: 3300000000,
8 | locked: 0,
9 | nonce: '9673f2fdd28de29f'
10 | });
11 | inputs.push({
12 | address: 'LINcjJR16WwP7a7irS3T4p1td7QAd2MSUEqk',
13 | assetsChainId: 2,
14 | assetsId: 1,
15 | amount: 1000000,
16 | locked: 0,
17 | nonce: '9673f2fdd28de29f'
18 | });
19 | let outputs = [];
20 | outputs.push({
21 | address: 'tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG',
22 | assetsChainId: 8,
23 | assetsId: 1,
24 | amount: 3300000000,
25 | lockTime: 0
26 | });
27 | let temp = new tx.CrossChainTransaction();
28 | temp.setCoinData(inputs, outputs);
29 | console.log(temp.coinData.toString('hex'));
30 |
--------------------------------------------------------------------------------
/src/test/contractCall.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const utils = require('../utils/utils');
3 | const sdk = require('../api/sdk');
4 | const BigNumber = require('bignumber.js');
5 | const {getBalance, countFee, inputsOrOutputsOfContractCall, getContractMethodArgsTypes, validateContractCall, imputedContractCallGas, validateTx, broadcastTx} = require('./api/util');
6 |
7 | module.exports = {
8 | /**
9 | * 调用合约
10 | * @param pri
11 | * @param pub
12 | * @param fromAddress
13 | * @param assetsChainId
14 | * @param assetsId
15 | * @param contractCall
16 | * @returns {Promise}
17 | */
18 | async callContract(pri, pub, fromAddress, assetsChainId, assetsId, contractCall, remark, multyAssets, nulsValueToOthers, payAccount) {
19 | let chainId = contractCall.chainId;
20 | const balanceInfo = await getBalance(chainId, assetsChainId, assetsId, fromAddress);
21 | let contractAddress = contractCall.contractAddress;
22 | let value = Number(contractCall.value);
23 | let newValue = new BigNumber(contractCall.value);
24 | const contractCallTxData = await this.makeCallData(chainId, fromAddress, value, contractAddress, contractCall.methodName, contractCall.methodDesc, contractCall.args, multyAssets);
25 | let gasLimit = new BigNumber(contractCallTxData.gasLimit);
26 | let gasFee = Number(gasLimit.times(contractCallTxData.price));
27 | let amount = Number(newValue.plus(gasFee));
28 | let transferInfo = {
29 | fromAddress: fromAddress,
30 | assetsChainId: assetsChainId,
31 | assetsId: assetsId,
32 | amount: amount,
33 | fee: 200000
34 | };
35 | if (value > 0) {
36 | transferInfo.toAddress = contractAddress;
37 | transferInfo.value = contractCall.value;
38 | }
39 | // let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 16);
40 | if (multyAssets) {
41 | let length = multyAssets.length;
42 | for (var i = 0; i < length; i++) {
43 | let multyAsset = multyAssets[i];
44 | let _balanceInfo = await getBalance(chainId, multyAsset.assetChainId, multyAsset.assetId, fromAddress);
45 | if (_balanceInfo.balance < Number(multyAsset.value)) {
46 | throw "Your balance of " + multyAsset.assetChainId + "-" + multyAsset.assetId + " is not enough.";
47 | }
48 | multyAssets[i].nonce = _balanceInfo.nonce;
49 | }
50 | }
51 |
52 | let inOrOutputs = await inputsOrOutputsOfContractCall(transferInfo, balanceInfo, contractCall, multyAssets, nulsValueToOthers);
53 | if (!inOrOutputs.success) {
54 | throw inOrOutputs.data;
55 | }
56 | if (payAccount) {
57 | const balanceInfoOfPayAccount = await getBalance(chainId, assetsChainId, assetsId, payAccount);
58 | let inputs = inOrOutputs.data.inputs;
59 | let from = inputs[inputs.length - 1];
60 | inputs.push({
61 | address: from.address,
62 | assetsChainId: from.assetsChainId,
63 | assetsId: from.assetsId,
64 | amount: '0',
65 | locked: 0,
66 | nonce: from.nonce
67 | });
68 | from.address = payAccount;
69 | from.nonce = balanceInfoOfPayAccount.nonce;
70 | }
71 | let tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 16, contractCallTxData);
72 | let txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
73 |
74 | // console.log(txhex);
75 | if (payAccount) {
76 | console.log("请追加账户["+payAccount+"]的签名");
77 | return;
78 | }
79 | let result = await validateTx(txhex);
80 | console.log('validateTx', result);
81 | if (result.success) {
82 | let results = await broadcastTx(txhex);
83 | if (results && results.value) {
84 | console.log("交易完成")
85 | } else {
86 | console.log("广播交易失败\n", results)
87 | }
88 | } else {
89 | console.log("验证交易失败")
90 | }
91 | },
92 |
93 | /**
94 | * 预估调用合约的gas
95 | * @param chainId
96 | * @param sender
97 | * @param value
98 | * @param contractAddress
99 | * @param methodName
100 | * @param methodDesc
101 | * @param args
102 | * @returns {Promise<*>}
103 | */
104 | async imputedCallGas(chainId, sender, value, contractAddress, methodName, methodDesc, args, multyAssets) {
105 | let multyAssetArray;
106 | if (multyAssets) {
107 | let length = multyAssets.length;
108 | multyAssetArray = new Array(length);
109 | for (var i = 0; i < length; i++) {
110 | let multyAsset = multyAssets[i];
111 | multyAssetArray[i] = [multyAsset.value, multyAsset.assetChainId, multyAsset.assetId];
112 | }
113 | }
114 | let gasResult = await imputedContractCallGas(sender, value, contractAddress, methodName, methodDesc, args, multyAssetArray);
115 | if (!gasResult.success) {
116 | throw 'imputedCallGas: ' + JSON.stringify(gasResult);
117 | }
118 | return gasResult.data;
119 | },
120 |
121 | /**
122 | * 组装创建合约交易的txData
123 | * @param chainId
124 | * @param sender
125 | * @param value
126 | * @param contractAddress
127 | * @param methodName
128 | * @param methodDesc
129 | * @param args
130 | * @returns {Promise<{}>}
131 | */
132 | async makeCallData(chainId, sender, value, contractAddress, methodName, methodDesc, args, multyAssets) {
133 | let contractCall = {};
134 | contractCall.chainId = chainId;
135 | contractCall.sender = sender;
136 | contractCall.contractAddress = contractAddress;
137 | contractCall.value = value;
138 |
139 | let callGasInfo = await this.imputedCallGas(chainId, sender, value, contractAddress, methodName, methodDesc, args, multyAssets);
140 | contractCall.gasLimit = Number(callGasInfo.gasLimit);
141 | contractCall.price = sdk.CONTRACT_MINIMUM_PRICE;
142 | contractCall.methodName = methodName;
143 | contractCall.methodDesc = methodDesc;
144 | // let argsTypesResult = await getContractMethodArgsTypes(contractAddress, methodName, methodDesc);
145 | // let contractConstructorArgsTypes;
146 | // if (argsTypesResult.success) {
147 | // contractConstructorArgsTypes = argsTypesResult.data;
148 | // } else {
149 | // console.log("获取参数数组失败\n", argsTypesResult.data);
150 | // throw "query data failed";
151 | // }
152 | contractCall.args = utils.twoDimensionalArray(args, callGasInfo.argsType);
153 | return contractCall;
154 | }
155 |
156 | }
157 |
--------------------------------------------------------------------------------
/src/test/contractCallOfAccountTransferTest.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * 调用合约的同时, 支持向其他账户转账,示例为token跨链转账
4 | */
5 |
6 | const call = require('./contractCall.js');
7 | const BigNumber = require('bignumber.js');
8 | const TEN = new BigNumber('10');
9 | // 用户私钥
10 | let pri = '8c6715620151478cdd4ee8c95b688f2c2112a21a266f060973fa776be3f0ebd7';
11 | // 用户公钥
12 | let pub = '02d0b400dfd6dd9ecdf81a068e8311c3cd4f873162389901d793d41e2043128635';
13 | // 用户地址
14 | let fromAddress = "tNULSeBaMuU6sq72mptyghDXDWQXKJ5QUaWhGj";
15 | // 链主资产链ID
16 | let assetChainId = 2;
17 | // 链主资产ID
18 | let assetId = 1;
19 | // 转入地址
20 | let toAddress = "TNVTdTSPVcqUCdfVYWwrbuRtZ1oM6GpSgsgF5";
21 | // NRC20合约地址
22 | let nrc20ContractAddress = "tNULSeBaMzRzrsGToWnL4BeCMnHyMNBayDNrH3";
23 | // 转移的token数量
24 | let tokenNumber = new BigNumber('2');
25 | // token decimals
26 | let decimals = 18;
27 | // 要转入的NULS数量,如果没有请填入0,如转入200个NULS,则填入20000000000,此处填入的值要乘以10的8次幂,如200个NULS,则`value = 200 * (10 ^ 8)`
28 | let nulsAmount = 10000000;
29 | // 交易备注
30 | let remark = 'nrc20 token cross transfer...';
31 |
32 | let contractCall = {
33 | chainId: assetChainId,
34 | sender: fromAddress,
35 | contractAddress: nrc20ContractAddress,
36 | value: nulsAmount, //
37 | methodName: "transferCrossChain",
38 | methodDesc: "",
39 | args: [toAddress, tokenNumber.shiftedBy(decimals)]
40 | };
41 | // 向 tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG 转入2个NULS
42 | let nulsValueToOthers = [
43 | {
44 | value: "200000000",
45 | address: "tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG"
46 | }
47 | ];
48 | //调用合约
49 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, contractCall, remark, null, nulsValueToOthers);
50 |
--------------------------------------------------------------------------------
/src/test/contractCallOfMultyAccounts.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * 调用合约的同时, 支持向其他账户转账,示例为token跨链转账
4 | */
5 |
6 | const call = require('./contractCall.js');
7 | const BigNumber = require('bignumber.js');
8 | const TEN = new BigNumber('10');
9 | // 手续费支出地址
10 | let payAccount = 'tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG';
11 | // 用户私钥
12 | let pri = '8c6715620151478cdd4ee8c95b688f2c2112a21a266f060973fa776be3f0ebd7';
13 | // 用户公钥
14 | let pub = '02d0b400dfd6dd9ecdf81a068e8311c3cd4f873162389901d793d41e2043128635';
15 | // 用户地址
16 | let fromAddress = "tNULSeBaMuU6sq72mptyghDXDWQXKJ5QUaWhGj";
17 | // 链主资产链ID
18 | let assetChainId = 2;
19 | // 链主资产ID
20 | let assetId = 1;
21 | // 转入地址
22 | let toAddress = "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD";
23 | // NRC20合约地址
24 | let nrc20ContractAddress = "tNULSeBaMzRzrsGToWnL4BeCMnHyMNBayDNrH3";
25 | // 转移的token数量
26 | let tokenNumber = new BigNumber('2');
27 | // token decimals
28 | let decimals = 18;
29 | // 要转入的NULS数量,如果没有请填入0,如转入200个NULS,则填入20000000000,此处填入的值要乘以10的8次幂,如200个NULS,则`value = 200 * (10 ^ 8)`
30 | let nulsAmount = 0;
31 | // 交易备注
32 | let remark = 'nrc20 token cross transfer...';
33 |
34 | let contractCall = {
35 | chainId: assetChainId,
36 | sender: fromAddress,
37 | contractAddress: nrc20ContractAddress,
38 | value: nulsAmount, //
39 | methodName: "transfer",
40 | methodDesc: "",
41 | args: [toAddress, tokenNumber.shiftedBy(decimals)]
42 | };
43 | //调用合约
44 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, contractCall, remark, null, null, payAccount);
45 |
--------------------------------------------------------------------------------
/src/test/contractCallOfMultyAssetsTest1.js:
--------------------------------------------------------------------------------
1 |
2 | const call = require('./contractCall.js');
3 |
4 | /**
5 | * 调用合约转入多资产, 举例资产数据 5-1(NVT)
6 | */
7 | // 用户私钥
8 | let pri = '477059f40708313626cccd26f276646e4466032cabceccbf571a7c46f954eb75';
9 | // 用户公钥
10 | let pub = '0318f683066b45e7a5225779061512e270044cc40a45c924afcf78bb7587758ca0';
11 | // 用户地址
12 | let fromAddress = "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD";
13 | // 业务合约地址
14 | let busContractAddress = "tNULSeBaN7pquou8YXJZmPbkna37j7rJRUe5fV";
15 | // 要转入的NULS数量,如果没有请填入0,如转入200个NULS,则填入20000000000,此处填入的值要乘以10的8次幂,如200个NULS,则`value = 200 * (10 ^ 8)`
16 | let nulsAmount = 0;
17 | // 资产链ID
18 | let assetChainId = 2;
19 | // 资产ID
20 | let assetId = 1;
21 | // 交易备注
22 | let remark = 'call contract...';
23 |
24 | let contractCall = {
25 | chainId: assetChainId,
26 | sender: fromAddress,
27 | contractAddress: busContractAddress,
28 | value: nulsAmount, //
29 | methodName: "_payableMultyAsset",
30 | methodDesc: "",
31 | args: []
32 | };
33 | // 转入0.2个NVT
34 | let multyAssets = [
35 | {
36 | value: "200000000000000000",
37 | assetChainId: 5,
38 | assetId: 74
39 | }
40 | ];
41 | //调用合约
42 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, contractCall, remark, multyAssets);
43 |
--------------------------------------------------------------------------------
/src/test/contractCallOfMultyAssetsTest2.js:
--------------------------------------------------------------------------------
1 |
2 | const call = require('./contractCall.js');
3 |
4 | /**
5 | * 调用合约同时转入NULS和NVT, 举例数据: NULS 其他资产 5-1(NVT)
6 | * 转入6.6NULS和0.02NVT
7 | */
8 | // 用户私钥
9 | let pri = '9ce21dad67e0f0af2599b41b515a7f7018059418bab892a7b68f283d489abc4b';
10 | // 用户公钥
11 | let pub = '03958b790c331954ed367d37bac901de5c2f06ac8368b37d7bd6cd5ae143c1d7e3';
12 | // 用户地址
13 | let fromAddress = "tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG";
14 | // 业务合约地址
15 | let busContractAddress = "tNULSeBaMw6y39H3akxv2QofFf5KNR3pUr1Ltf";
16 | // 要转入的NULS数量,如果没有请填入0,如转入200个NULS,则填入20000000000,此处填入的值要乘以10的8次幂,如200个NULS,则`value = 200 * (10 ^ 8)`
17 | let nulsAmount = 660000000;
18 | // 资产链ID
19 | let assetChainId = 2;
20 | // 资产ID
21 | let assetId = 1;
22 | // 交易备注
23 | let remark = 'call contract...';
24 |
25 | let contractCall = {
26 | chainId: assetChainId,
27 | sender: fromAddress,
28 | contractAddress: busContractAddress,
29 | value: nulsAmount, //
30 | methodName: "receiveAllAssets",
31 | methodDesc: "",
32 | args: []
33 | };
34 | // 转入0.02个NVT
35 | let multyAssets = [
36 | {
37 | value: "2000000",
38 | assetChainId: 5,
39 | assetId: 1
40 | }
41 | ];
42 | //调用合约
43 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, contractCall, remark, multyAssets);
44 |
--------------------------------------------------------------------------------
/src/test/contractCallTest.js:
--------------------------------------------------------------------------------
1 |
2 | const call = require('./contractCall.js');
3 |
4 | /**
5 | * @disc: 调用合约dome - token授权
6 | * @date: 2019-10-18 10:28
7 | * @author: Wave
8 | */
9 | // 用户私钥
10 | let pri = '';
11 | // 用户公钥
12 | let pub = '02cb7d76b7e91d60fa3c10298b414e5fe711aed8011b583e366b918d27fc262d73';
13 | // 用户地址
14 | let fromAddress = "tNULSeBaMshNPEnuqiDhMdSA4iNs6LMgjY6tcL";
15 | // 业务合约地址
16 | let busContractAddress = "tNULSeBaMyCzpjWfk4Y4EfGaQq9z72C12GLRpy";
17 | // 要转入的NULS数量,如果没有请填入0,如转入200个NULS,则填入20000000000,此处填入的值要乘以10的8次幂,如200个NULS,则`value = 200 * (10 ^ 8)`
18 | let nulsAmount = 10000;
19 | // 资产链ID
20 | let assetChainId = 2;
21 | // 资产ID
22 | let assetId = 1;
23 | // 交易备注
24 | let remark = 'call contract...';
25 |
26 | let contractCall = {
27 | chainId: assetChainId,
28 | sender: fromAddress,
29 | contractAddress: busContractAddress,
30 | value: nulsAmount, //
31 | methodName: "_payable",
32 | methodDesc: "",
33 | args: []
34 | };
35 | //调用合约
36 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, contractCall, remark);
37 |
--------------------------------------------------------------------------------
/src/test/contractCallTest2.js:
--------------------------------------------------------------------------------
1 |
2 | const call = require('./contractCall.js');
3 |
4 | /**
5 | * @disc: 调用合约dome - 向合约转入8.88个nuls
6 | * @date: 2019-10-18 10:28
7 | * @author: Wave
8 | */
9 | // 用户私钥
10 | let pri = 'ddddb7cb859a467fbe05d5034735de9e62ad06db6557b64d7c139b6db856b200';
11 | // 用户公钥
12 | let pub = '02cb7d76b7e91d60fa3c10298b414e5fe711aed8011b583e366b918d27fc262d73';
13 | // 用户地址
14 | let fromAddress = "tNULSeBaMshNPEnuqiDhMdSA4iNs6LMgjY6tcL";
15 | // 业务合约地址
16 | let busContractAddress = "tNULSeBaMxjeNfiicypEUtttpBC1NdFsmDcCGS";
17 | // 要转入的NULS数量,如果没有请填入0,如转入200个NULS,则填入20000000000,此处填入的值要乘以10的8次幂,如200个NULS,则`value = 200 * (10 ^ 8)`
18 | let nulsAmount = 888000000;
19 | // 资产链ID
20 | let assetChainId = 2;
21 | // 资产ID
22 | let assetId = 1;
23 | // 交易备注
24 | let remark = 'call contract...';
25 |
26 | let contractCall = {
27 | chainId: assetChainId,
28 | sender: fromAddress,
29 | contractAddress: busContractAddress,
30 | value: nulsAmount, //
31 | methodName: "_payable",
32 | methodDesc: "",
33 | args: []
34 | };
35 | //调用合约
36 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, contractCall, remark);
37 |
--------------------------------------------------------------------------------
/src/test/contractCreate.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const utils = require('../utils/utils');
3 | const sdk = require('../api/sdk');
4 | const {getBalance, countFee, inputsOrOutputs, getContractConstructor, validateContractCreate, imputedContractCreateGas, validateTx, broadcastTx} = require('./api/util');
5 |
6 | module.exports = {
7 |
8 | /**
9 | * 创建合约
10 | * @param pri
11 | * @param pub
12 | * @param createAddress
13 | * @param assetsChainId
14 | * @param assetsId
15 | * @returns {Promise}
16 | */
17 | async createContract(pri, pub, createAddress, assetsChainId, assetsId, contractCreate, remark) {
18 | //1、通过接口获取合约的参数 args
19 | let hex = contractCreate.contractCode;
20 | const constructor = await getContractConstructor(hex);
21 | console.log(constructor.data.constructor.args);
22 | //2、给每个参数复制 获取contractCreateTxData
23 | let newArgs = contractCreate.args;
24 | const contractCreateTxData = await this.makeCreateData(contractCreate.chainId, createAddress, contractCreate.alias, hex, newArgs);
25 | //3、序列化
26 |
27 | let chainId = contractCreate.chainId;
28 | const balanceInfo = await getBalance(chainId, assetsChainId, assetsId, createAddress);
29 | let amount = contractCreateTxData.gasLimit * contractCreateTxData.price;
30 | let transferInfo = {
31 | fromAddress: createAddress,
32 | assetsChainId: assetsChainId,
33 | assetsId: assetsId,
34 | amount: amount,
35 | fee: 100000
36 | };
37 |
38 | let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 15);
39 | let tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 15, contractCreateTxData);
40 | let txhex;
41 | //获取手续费
42 | let newFee = countFee(tAssemble, 1);
43 | //手续费大于0.001的时候重新组装交易及签名
44 | if (transferInfo.fee !== newFee) {
45 | transferInfo.fee = newFee;
46 | inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 15);
47 | tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 15, contractCreateTxData);
48 | txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
49 | } else {
50 | txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
51 | }
52 | console.log(txhex);
53 | //4、验证交易
54 | let result = await validateTx(txhex);
55 | if (result) {
56 | //5、广播交易
57 | let results = await broadcastTx(txhex);
58 | console.log(results);
59 | if (results && results.value) {
60 | console.log("交易完成, 合约地址: " + contractCreateTxData.contractAddress)
61 | } else {
62 | console.log("广播交易失败")
63 | }
64 | } else {
65 | console.log("验证交易失败")
66 | }
67 | },
68 |
69 | /**
70 | * 组装构造函数的参数类型
71 | * @param constructor
72 | * @returns {Promise}
73 | */
74 | async makeContractConstructorArgsTypes(constructor) {
75 | let args = constructor.data.constructor.args;
76 | let length = args.length;
77 | let contractConstructorArgsTypes = new Array(length);
78 | let arg;
79 | for (let i = 0; i < length; i++) {
80 | arg = args[i];
81 | contractConstructorArgsTypes[i] = arg.type;
82 | }
83 | return contractConstructorArgsTypes;
84 | },
85 |
86 | /**
87 | * 预估创建合约的gas
88 | * @param sender
89 | * @param contractCode
90 | * @param args
91 | * @returns {Promise<*>}
92 | */
93 | async imputedCreateGas(sender, contractCode, args) {
94 | let result = await validateContractCreate(sender, sdk.CONTRACT_MAX_GASLIMIT, sdk.CONTRACT_MINIMUM_PRICE, contractCode, args);
95 | if (result.success) {
96 | return await imputedContractCreateGas(sender, contractCode, args);
97 | } else {
98 | console.log("创建合约验证失败")
99 | }
100 | },
101 |
102 | /**
103 | * 组装创建合约交易的txData
104 | * @param chainId
105 | * @param sender
106 | * @param contractCode
107 | * @param args
108 | * @param alias
109 | * @returns {Promise<{}>}
110 | */
111 | async makeCreateData(chainId, sender, alias, contractCode, args) {
112 | let contractCreate = {};
113 | contractCreate.chainId = chainId;
114 | contractCreate.sender = sender;
115 | contractCreate.alias = alias;
116 | contractCreate.gasLimit = await this.imputedCreateGas(sender, contractCode, args);
117 | contractCreate.price = sdk.CONTRACT_MINIMUM_PRICE;
118 | contractCreate.contractCode = contractCode;
119 |
120 | let constructor = await getContractConstructor(contractCode);
121 | let contractConstructorArgsTypes = await this.makeContractConstructorArgsTypes(constructor);
122 | contractCreate.args = await utils.twoDimensionalArray(args, contractConstructorArgsTypes);
123 | contractCreate.contractAddress = sdk.getStringContractAddress(chainId);
124 | return contractCreate;
125 | }
126 |
127 | }
--------------------------------------------------------------------------------
/src/test/contractCreateTest.js:
--------------------------------------------------------------------------------
1 |
2 | const create = require('./contractCreate.js');
3 |
4 | /**
5 | * @disc: 创建合约 dome
6 | * @date: 2019-10-18 10:29
7 | * @author: Wave
8 | */
9 | let pri = '76b7beaa98db863fb680def099af872978209ed9422b7acab8ab57ad95ab218b';
10 | let pub = '02ec9e957823cd30d809f44830442562ca5bf42530251247b35d9209690f39be67';
11 | let fromAddress = "tNULSeBaMqywZjfSrKNQKBfuQtVxAHBQ8rB2Zn";
12 | let alias = "test_alias";
13 | // 资产链ID
14 | let assetChainId = 2;
15 | // 资产ID
16 | let assetId = 1;
17 | let remark = 'new contract...';
18 |
19 | let contractCreate = {
20 | chainId: assetChainId,
21 | sender: fromAddress,
22 | alias: alias,
23 | contractCode: '504b03040a0000080000aa7b564e00000000000000000000000003000400696f2ffeca0000504b03040a0000080000aa7b564e00000000000000000000000008000000696f2f6e756c732f504b03040a0000080000aa7b564e00000000000000000000000011000000696f2f6e756c732f636f6e74726163742f504b03040a0000080000aa7b564e00000000000000000000000017000000696f2f6e756c732f636f6e74726163742f746f6b656e2f504b0304140008080800aa7b564e00000000000000000000000028000000696f2f6e756c732f636f6e74726163742f746f6b656e2f53696d706c65546f6b656e2e636c617373b558f97754e5197eeecc90990c972d9090059209a498cc9291a58a8152020d35ca5602b1605bbd99b9492ecc12670922b46ead4babd56aeb5ad1565bd4aa2c020169d59ed353cfe93fd17f84d3d3e7fdee9d3b37612639d5d31ff2ddf77ecbfb3eeff67c77f2afff7cf639804df87b23a23825c323329c96e14c1831fcb411cdf859108f86119497281e93e171997e22cce149197e1ec62ff0d462acc2d3413c13c672fc2a8ce7f0bcccfc3a8817827831cc53bf91e125195e96e5df8af4bb205e09a3430e44f19a0cafcbf086a87d5386df87f096cc9c9597b7457a27843fc8f38f21bc2b7ade0be24f41fc39887341bcaf219033b2a686a6bdc78d692399317213c99152c1ca4d6cd3d0503c951dcb673484d266caca1a99a2066d58c3e252be646446ca535399531a5aeca359a33499dc654d0ce74ae68459e0f1d098417d2993a796d97bca252b93dc674c71b171c49ac819a57281c68766af6edf6be593b972a6984ce573a582912a258be913c9c174ba60168bdb6a9bdb419d412393c99f34d31a4a5f43e337342f0056f5f6d58a6360773e6d4a10ac9cb9bf9c1d330b878db18c8a7a3e6564468d8225efce64a0346931643db7c228e54f98b9e488959de26691a9bbed503957b2b2e6a855b4787c3097636e4a563e47151b6a7b62b87b92a39679924afcbd7d4c6b6b05fdada96cd86ee5acd20e0d3b7a6f75b0decc5c35c37da31a968822cbc80c66f304ae61dd6cfc078d02ebb164166639125dd09143e64365ab60a6a5b2541548e16938dcbb4032e75dad1b8e45f99339b3a0a173fef3acc8e294994bcb565d1d19ac14e8a269235336a5796655c0a9a94a152c192919a9132c47f56eb302b5d048ae386e16f614f2590d47be917bb5bdeb3bc6121c57ea7da53cc3e974f181710d772c60af6ec0828e129242c5030d772e84be2ebea0313555c84f53dd722b972a9846d11c543306c92a6ca4d3667ad48eef7232d79cf565c5f29832e66e0ae53315510ebb49fabf84973d1032ec2d1babe2260f2ed77eb868565f96550e559739b3ab12d7af19cc5109a6bdc583c0d5ba283569a64e90657aeb9f4fd659ab7fa24115ffc68a40df63f3eaf0528b9cf7678b131a06ff27bbb5358547f2e542cadc6349cb2df7306bbf6cd7d18fa48edb65d8884d3a36638b8e217ca0e3436cd1b0a27a6fdc6d1427d9ac3abe8d3b74dc25c35f64f347f858c727381fc4051d177149c7a7b84c42abc3edca76cf61a74586a64da1c82573def5e11ca96477c62816cda2e0213d5cd17115333aaee13a0fccbacf782dd58a888e49983a72c8e83821c367b8a1c382b910ba4a2755d0cd7ad79116adf7e05e1d79301e7fc5df747c8ef31a3a8673c5f2f8b895b2b82fe274703aa254cbe6691d5fe0bc8ea36087270e4f9a11551d916cb9588a8c999109f6312f864869d2c845f2850819dfc8f078e4f67e394e289db32c389413c98fdb36fac5c52f79e32c7cafb216aae57260ecb899a2f6b535fb6bb7f3a261cd7c5153772c0b2e706ce8d001be1c1edacf712a7f527a6bb82e6f86b2e54cc9529f59fdf55ab0ded9d69a78f749eb34149d5b29c22b7f812bcc3f55a6735bbdf7be1d916db7cef4dd3aa5a1bda68123ac4e524ec0cc5a54df5587bd544dd93d3f6172df861a306a1a0d16ec0f025ae83d26e71b53f9ec9451607ee761337e04f9c9868c7b85097943f71eabc51de8e637750c3ec49140039a842af8e3a049d8423d49187cfa8433d493c400d2b492b7f2ef2ecffb003fd699616ca3bc9d3349be697c2e8a5e8676416df90ec70635b9163b38eaf6067c173bf91c745677f1a911422d45beb98ad62fa8682376d750e4ff688ea2be05156dc6f76a280acc45945c50d110f6388afecd1d8bf834a3335476090d571088de40f0e80c4257d05815c3d1d81568d1f815f8a2cd812bf0471397b0b8397015fa552c915397d1780d4b05d0752cf3e3be1b587e54736666b0e21a9a2eba40fbb158fd060c30658bb11a2d6865296cc606a639c6246f645a0799d6434c729a491687b6d8401d8744ea57711049cac5a7a4ef739f5f491b95febb29b705b86d58797eeb4892e50189c51754212692441c8e5dc74a1fbec4aafd89af1064602e24e2ce54f340a02df015429c1449c21f505e75f2f72a887529313611650bc3bd8ec9bf8d798b33e4552f92ae1749ecc53e276dfb29f978ba1b07e8bf9f6797e0204f04f00327a1f6da56ae1de2cc52f86ea22588919b680ee2f0ac248bdf4b7c737c3d825127ef670823c0674f34c6142566d0128d715c1d8d736c95d4c54492ac05aa85daa2c0df8b46825e46b0cd84bc8e80c4b1a8adcf75ac07f7398ef5e087ca31910eaaf408b895fe9ae9e0bde5a4e3491e914cf6c4fe8960e01c02fe6b68932aaba4a6795fdc4ecdbeb8e4c0ef817884d11a453b2174d2f83aea1488115b9f07a21dfb7684713f81f9545417c31fdaa9dd446bad90063517e98ff0632798166d8ae6ae2863199728c6e24e143921f29c3836a9583d80101e64120d92d1980760970bb04b454e53d24105b0665a7fe22279d041d21e750cb7df404705c49ad92096aa9d134ce624bbcff200687701b4ab9ad494340f80075c00136c0151d15d01b0b602404d5c45671d1c59e2c8d1cdbc0747b78ba3dbc5d14d1febe2305c1c978943623c142586ae8aedfdf1c45544ce62859a60e53040e7a057b0b6cc83d5efe9f022a35c22ee32ab6d9a55f4302faf47d8e7a73d8d30e4621f72b10f31cd5b5487df89946a04a9b746e9e21e165ba896533ef914a42c4e3de1907584f545740381685b40bc4bc8108bb705e85d375daaf2acdd0d8fb2d01ea3d5c7b1923abad85955268ab83823187770469846bb61234ec3865821f72826f2c907af83e78c83a7d38327d1b46e06eb2b687a66a1b1cbfe296a7b1a2bf00ccbfe590f924e1749a78ba4d345d2e922697191582e927f7045740cd8b1f0f2b74dd66dce453610508b6dce1dd51688276c49507a59fc39ea7b5efe958836bc40067991fcfc126fa2973d88075cc4032ee20117f1808378156fb5e3e4f32a8bdb335b3923f90f816493248bf3147f42381e9de6aa448ba1bc8a6fed8fc69b36cce0b68a7b8db10423de5d85ee4df72b64ac577975bcc680bf4ee86f78ca72bd0b793d5b6e9ff30563b776031372bf82ec931f340e90a203a4cb01928837f54a862b207ae682b0b3fc16d59d65cdbdcd78bee301e025b7ec1c726b60ac2b00f8b3c701708c6f12cfd5bc075648d3b285dfacde0817dde60cab6def320aef29832df631d7e06a654653415f045fd34e4dd979c8b133e5dc371dd19804597843cabab62ddbc973d4f33eed7e407afcd0435c1daecd0e14944d918aee1543eb2d8ef59263dd74acb7d6f0327e0d7d73ddfc98ee7ce231d9ea9a6c75dc14a9acbe8be6383ced96984f79b1a68ec38959666d8f2f52d12542f894fe5cf6a4758d6b7e8debf11ac7639104887fb6ef2755c53c8c5f2ae53e2c278b3e4b36ece0f35534fe17504b0708ec308779cb09000028180000504b0304140008080800aa7b564e00000000000000000000000022000000696f2f6e756c732f636f6e74726163742f746f6b656e2f546f6b656e2e636c617373a552d14e1341143d03b5cb16aa28a8a0284a08697970131ff481a76a24694282a19507dfa6bb431d989da933b325fc9a0f7e801f65bc534ba5b6a5896eb23b3be79e7bcebd33f7c7cf6fdf01bcc64e84e711b623bc60a8367a3d6bfa5c7de80bed19569a5a0bfb5e71e7848bf092186dcbb53b1376c828699e0b86f55afde89cf779a2b8ee262d6fa5ee1e306c9e14dacb5c9c4a273b4a34b4369e7b69b463d83b9226d18572496ab4b73cf589cb2e123ee224a7525c9248d95de51da318963291ca9c2b4a5eacd59b0ccb9ea8aa55f47aea8a61e3ba869cfb2fc93bd96d6a2fbac29244dce154582a8ecf18ded4a61b37b2cc0ae70e668aec8c37f3915b6add0b3bd6d5fedcae4ec4d7425a9191e2921f1e26c3db39554d2faafe99eee85ae4d09a9ce1d33ca17fb489f86034e8ae63ae94b90cc7c9d0fe2fb799475d6999c2a6e2502af2a8b4cd85d0af0295616b42d0876832e030acfe19c2e3ceb9486942f76fcbd8fd6be06f278fcd7e99816101e1894b749788695fa15d99d66580b0952958157727b07b589dc0eee301a9dfc0b0466f144cd70784877844ff01ac2efc0647a1c7d81886d6166f864684cdd9b94ff0748aef388d085b83ef33dca135141a7c4ad46e488a10ff02504b070868fe421cca0100005e040000504b0304140008080800aa7b564e00000000000000000000000030000000696f2f6e756c732f636f6e74726163742f746f6b656e2f546f6b656e24417070726f76616c4576656e742e636c6173738d565b6f1b4514fec6bbde75b69bbb49d224b46929e05b6a2ee19a4b73218140d2943835b4406163af926d9cdd74771d90a0129540ea033c801020242e2f252f790089b80824c45390f82ffc03049c995dbb89e3243cf8ccd93367e67cdf7c6746fef39f5f7e03f018ae6988e34213148c7333c1cd248f4da998d63083e735bcc0cd0c66b937abe2450d2770218697f838c7cd7c0c176358e0ee256e5e56b1a822c71075deb64d97e1d49ce564ed72c9cb161cdb778d829ff58a6bd98962d1353d6f9841f5364cbbc853a39b46a96c3274cd5d37368decbae1af6627ad9559db37574c97529511cbb6fc3186cb89a3773d66b6e1f6c93c833ce5140940eb9c659b17cbebcba6bb642c9728d231e7148c52de702dfe1d06657fd5f2189a2736365c87b04f6f9ab6cfa0cfdac47caa64789e49d39983607c67cdb4b34bdc9edbb798389e5d2cdbbeb56ee62dcfa22a970cd758377dd39db06dc7377ccbb169cf546382462d27bb68de285bae59a41d632ba6bf10883190481e2747ccab659f39e694f98969b479ae2aa0e6edf9e065f381a03d54f6104979b930eb64e2706114a2639488f97d6152c9b057b20bcbd7cd823f9cbccac01c2ed28129219241a234e77ca3b0366f6c08eda8c1a9f4aae1ad06824b89e42c152156e5122533fa88f94ece772d7b85215e852f760ea2b4b39673ca6ec19cb1782f6842cdf33c4d471f967474a15b470f3727d1abe332f22a5e21e9fe7f37a87855c7237854c5151d4fe16986ee7a189365ab244e3bbe6fe5bbe2f28deab88ad7b8799d006606c28b364ae43203e2ae898c37740c6384a1adfef4187a1bea1ff6391d5a3e9059f43a43e7be7312413aa6fea308379aded362c4ab514b9054c60627c330983828cd41b5c2631aaecbaff6cf11f9fd89a9c3a771869ecc38a82b2121c215a78735c2451723e94ea346f37de8a7effbe9ab44a34c633c75172c95de412495d981941adc81fca358758a6c17a2646f50a68b267868818f4e94719aa2a9603d06f000203c5e97098f578e088fd796708efc4e89261f2467bf7d080f93e590b234f2e5d1d44f88fc50c3a088e03ba2a61e248435191248868bc7289b575404977b0c34117d8fd6dc143b74055935d44a889a2e444320523d90f71b0249370622d503f980d67c7808909e104806830d80c8f5406e3704725e2c3a0044ae07f211adf9f810205c335e98ae7cb8d75f9423d1782b95fe1e51793bbd8b965405d134fdee202a6da77f8732cf75dba58ea22143bf0ad4afd0ba45375ec4298b9f679020514cda9b205513e45db4f381627205b12db472ef0fa8f21664699b404882462f01053e818a4fe9e43e23989f13e52ff026be14b40602c0355ab7e89fc6e3824e1143148be009d1a0badac2fe46bf8a2715d6adb0b836cea9d32b1752ff393cc6e9805d734a306be26046da4ef7ad069c78580ac36f55e37210271a5a10efbb07bf43dc9eafe9367d43cdf32da6f0dd1e35a643d89d04fa193c4b5038d84128ede3ec5fbae511824b30c947e84718cbefffa445f49c862caed1b6bc51867ec5892b77a1773457484141a5b5a32df025eeb7073e616e6dbb594147059df58d77674fe30d8540231815760c67c3a746c173f42c35fd07504b0708ea7bbc798f040000e6090000504b0304140008080800aa7b564e00000000000000000000000030000000696f2f6e756c732f636f6e74726163742f746f6b656e2f546f6b656e245472616e736665724576656e742e636c6173738d56df531b5514fe6e76b31bb60be19740015b5aab8624b06ad156c36f84160da5051a0bd5da25d9c296b08bbb1b5e1c1ffa6ff8aebcf0a033923a3ae3f88433fe2ffe078e7aeedd854212c0879c7bf6dc73eef9cef9cebd933ffff9e53700efe189864e4c3441c12417535c4c73db8c8a590d73b8a3e12e177398e7dabc8a4f345cc244029ff235cfc54202f71258e4ea7d2e1ea85852b1cc203ff3dc6d862b79db359c4ad9378aae1378663130fcd29631552a7996efe7186281cb10df35cb158ba12bffdcdc358d6d33d834a6ed8d7927b0362c8fbc9451dbb183718687a9f30fbc60b7e1f18305823be3960840326f3bd6bdcaf6bae5ad98eb65b2b4e7dda2592e989ecdbf23a31c6cda3e43f38a673afe33cb9bddb59c80419f771ccb9b299bbe6fd176b61e4ce06e598eb1c2e58d53c154e3f5a58a13d8db56c1f66dca72dff4cc6d2bb0bc29c7710333b05d87ce4c372ed03cf63196acaf2ab66795e84475c30ae6040d03a9c18b8850fd23e76b17f498f72b4e47af70e6fc704dd0772124b187729d4163c23ff6ba9c3a9b0c854a30cb54ed6b9153d974368cc5f5e75631c80dae3130971353b72588318988e6e5c02c6e2d983b822f1a674abd69fa9b21c9526a709e92502d95323933fa4804ee72e0d9ce0643e7117c717268a593b565b7e215ad399bf3af090687b99b8e3eace8e842b78e1e2e2ea357c74314547c4674fdff0950f148c73b7857c5aa8e5bb8cdd05d0b63ba62974b96c7d0712af26b7ed5c674ace131179f132bd981c01da3b2b203e26689cd2f74e430cad05adb3786de867c47534ded2a84048bc9a6eca73a248cd4a0fef34a6db47d62a4a8eb8d8681483277762ca7c43094aa27a59ea7a841b91affa3c939c7bf3f3573f636aed1d3d8099a47488871aee9018d71bac54a8cd3aad17e1ffae9fb75fa2ad32ad3da997e0996ce1c2096ce1e404a0f1d40fe51445d21d98538c92c790ea109c36881810e1a82ab644d87f118c01b80d0785e26349e3926349e5bc20dd293120986374fc8b7f036490ec7a09587c6d33f21f6c3717e45186f8a7c7ae810e5634861300a1e276f9e4d1175bc42af09eb2d8ab92d4ee80abd8e112b1162ba060d8148b540720d81641a03916a814c50cce419407a2220596a743d10b916c84c4320c322a80e885c0be40ec5dc3d0308e78b27a68b1e9df517f970ea5ea433df232eef670ed192ae229ea1df77884bfb99dfa12c70de0e699a68c9d2af0af55b24f7a065859dbc783f4307896cd24907e9c8413e441b5fc8265791d843926b7f4095f7204bfb04421265f41250200f150bd4b94582f9804a5ec2975816650d84808fcb7a41ff266e8a724a18215b0cef8be1d4d516f637fa557ca0b06e85756a93bc747adba2d27f8eda381b56d79c1695357130a3ad57fb36c39ab8598acc4f8fec7268a732b4d0def70a7ebbb8398fe826add2f0ac119b8f4fb0311bc1ee20d01fe22382c2c10e41699b64ffd20d8f115c82493a223dc658e1f42705d1531a55f1848ee58332f22b2eadbe84dede5c25064529c9f6d65097b8de16ea8439d9fa4d15ed5574d40eded313833712018d614cc8715c8f9e19051fd393d4f41f504b0708826261e37e040000ca090000504b01020a000a0000080000aa7b564e000000000000000000000000030004000000000000000000000000000000696f2ffeca0000504b01020a000a0000080000aa7b564e000000000000000000000000080000000000000000000000000025000000696f2f6e756c732f504b01020a000a0000080000aa7b564e00000000000000000000000011000000000000000000000000004b000000696f2f6e756c732f636f6e74726163742f504b01020a000a0000080000aa7b564e00000000000000000000000017000000000000000000000000007a000000696f2f6e756c732f636f6e74726163742f746f6b656e2f504b01021400140008080800aa7b564eec308779cb090000281800002800000000000000000000000000af000000696f2f6e756c732f636f6e74726163742f746f6b656e2f53696d706c65546f6b656e2e636c617373504b01021400140008080800aa7b564e68fe421cca0100005e0400002200000000000000000000000000d00a0000696f2f6e756c732f636f6e74726163742f746f6b656e2f546f6b656e2e636c617373504b01021400140008080800aa7b564eea7bbc798f040000e60900003000000000000000000000000000ea0c0000696f2f6e756c732f636f6e74726163742f746f6b656e2f546f6b656e24417070726f76616c4576656e742e636c617373504b01021400140008080800aa7b564e826261e37e040000ca0900003000000000000000000000000000d7110000696f2f6e756c732f636f6e74726163742f746f6b656e2f546f6b656e245472616e736665724576656e742e636c617373504b0506000000000800080051020000b31600000000',
24 | args: ['waves', 'waves', 100000000, 8]
25 | };
26 |
27 | create.createContract(pri, pub, fromAddress, assetChainId, assetId, contractCreate, remark);
--------------------------------------------------------------------------------
/src/test/contractDelete.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const {getBalance, inputsOrOutputs, validateContractDelete, validateTx, broadcastTx} = require('./api/util');
3 |
4 | module.exports = {
5 | /**
6 | * 调用删除合约
7 | * @param pri
8 | * @param pub
9 | * @param fromAddress
10 | * @param assetsChainId
11 | * @param assetsId
12 | * @param contractDelete
13 | * @returns {Promise}
14 | */
15 | async deleteContract(pri, pub, fromAddress, assetsChainId, assetsId, contractDelete, remark) {
16 | let chainId = contractDelete.chainId;
17 | const balanceInfo = await getBalance(chainId, assetsChainId, assetsId, fromAddress);
18 | let amount = 0;
19 | let transferInfo = {
20 | fromAddress: fromAddress,
21 | assetsChainId: assetsChainId,
22 | assetsId: assetsId,
23 | amount: amount,
24 | fee: 100000
25 | };
26 |
27 | const contractDeleteTxData = await this.makeDeleteData(contractDelete.chainId, contractDelete.sender, contractDelete.contractAddress);
28 |
29 | let deleteValidateResult = await validateContractDelete(assetsChainId, contractDeleteTxData.sender, contractDeleteTxData.contractAddress);
30 | if (!deleteValidateResult) {
31 | console.log("验证删除合约失败");
32 | return;
33 | }
34 | let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 17);
35 | let tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 17, contractDeleteTxData);
36 | let txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
37 | let result = await validateTx(txhex);
38 | console.log(result);
39 | if (result) {
40 | let results = await broadcastTx(txhex);
41 | if (results && results.value) {
42 | console.log("交易完成")
43 | } else {
44 | console.log("广播交易失败")
45 | }
46 | } else {
47 | console.log("验证交易失败")
48 | }
49 | },
50 |
51 | /**
52 | * 组装创建合约交易的txData
53 | * @param chainId
54 | * @param sender
55 | * @param contractAddress
56 | * @returns {Promise<{}>}
57 | */
58 | async makeDeleteData(chainId, sender, contractAddress) {
59 | let contractDelete = {};
60 | contractDelete.chainId = chainId;
61 | contractDelete.sender = sender;
62 | contractDelete.contractAddress = contractAddress;
63 | return contractDelete;
64 | }
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/src/test/contractDeleteTest.js:
--------------------------------------------------------------------------------
1 |
2 | const deleted = require('./contractDelete.js');
3 |
4 | /**
5 | * @disc: 删除合约 dome
6 | * @date: 2019-10-18 10:31
7 | * @author: Wave
8 | */
9 | let pri = '76b7beaa98db863fb680def099af872978209ed9422b7acab8ab57ad95ab218b';
10 | let pub = '02ec9e957823cd30d809f44830442562ca5bf42530251247b35d9209690f39be67';
11 | let fromAddress = "tNULSeBaMqywZjfSrKNQKBfuQtVxAHBQ8rB2Zn";
12 | // 业务合约地址
13 | let busContractAddress = "tNULSeBaNA3RADUR6CJCzxdPSevKJKDM4ULAqz";
14 | // 资产链ID
15 | let assetChainId = 2;
16 | // 资产ID
17 | let assetId = 1;
18 | let remark = 'delete contract...';
19 |
20 | let contractDelete = {
21 | chainId: assetChainId,
22 | sender: fromAddress,
23 | contractAddress: busContractAddress
24 | };
25 |
26 | //合约删除
27 | deleted.deleteContract(pri, pub, fromAddress, assetChainId, assetId, contractDelete, remark);
28 |
29 |
--------------------------------------------------------------------------------
/src/test/contractNRC20TransferTest.js:
--------------------------------------------------------------------------------
1 |
2 | const call = require('./contractCall.js');
3 | const BigNumber = require('bignumber.js');
4 | const TEN = new BigNumber('10');
5 | /**
6 | * @disc: NRC20 token transfer dome
7 | * @date: 2019-10-18 10:28
8 | * @author: Wave
9 | */
10 | // 用户私钥
11 | let pri = 'ddddb7cb859a467fbe05d5034735de9e62ad06db6557b64d7c139b6db856b200';
12 | // 用户公钥
13 | let pub = '02cb7d76b7e91d60fa3c10298b414e5fe711aed8011b583e366b918d27fc262d73';
14 | // 用户地址
15 | let fromAddress = "tNULSeBaMshNPEnuqiDhMdSA4iNs6LMgjY6tcL";
16 | // 链主资产链ID
17 | let assetChainId = 2;
18 | // 链主资产ID
19 | let assetId = 1;
20 | // 转入地址
21 | let toAddress = "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD";
22 | // NRC20合约地址
23 | let nrc20ContractAddress = "tNULSeBaN2vEicPEn15febEuvqM29X4wRZ5eGG";
24 | // 转移的token数量
25 | let tokenNumber = new BigNumber('100');
26 | // token decimals
27 | let decimals = 2;
28 | // 交易备注
29 | let remark = 'nrc20 token transfer...';
30 |
31 | let contractCall = {
32 | chainId: assetChainId,
33 | sender: fromAddress,
34 | contractAddress: nrc20ContractAddress,
35 | value: 0, //
36 | methodName: "transfer",
37 | methodDesc: "",
38 | args: [toAddress, tokenNumber.multipliedBy(TEN.pow(decimals))]
39 | };
40 | //调用合约
41 | call.callContract(pri, pub, fromAddress, assetChainId, assetId, contractCall, remark);
42 |
--------------------------------------------------------------------------------
/src/test/createTrading.js:
--------------------------------------------------------------------------------
1 | const txs = require('../model/txs');
2 | const sdk = require('../api/sdk');
3 |
4 | // 以NVT/NULS举例
5 |
6 |
7 | var addressHex = "TNVTdTSPVcqUCdfVYWwrbuRtZ1oM6GpSgsgF5";
8 |
9 | let coinTrading = {}
10 |
11 | coinTrading.address = sdk.getBytesAddress(addressHex)
12 | coinTrading.quoteAssetChainId = 5;
13 | coinTrading.quoteAssetId = 1;
14 | coinTrading.scaleQuoteDecimal = 6;
15 | coinTrading.baseAssetChainId = 2;
16 | coinTrading.baseAssetId = 1;
17 | coinTrading.scaleBaseDecimal = 6;
18 | coinTrading.minBaseAmount = 10000000;
19 | coinTrading.minQuoteAmount = 10000000;
20 |
21 | let tx = new txs.CoinTradingTransaction(coinTrading);
22 | console.log(tx.txData.toString("hex"))
--------------------------------------------------------------------------------
/src/test/crossChainTransfer.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
const txs = require('../model/txs');
const Serializers = require("../api/serializers");
const {isMainNet, countCtxFee, getBalance, broadcastTx, sendCrossTx} = require('./api/util');
/**
* @disc: 跨链交易 dome
* @date: 2019-10-18 10:32
* @author: Wave
*/
/*let pri = '9ce21dad67e0f0af2599b41b515a7f7018059418bab892a7b68f283d489abc4b';//tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG
let pub = '03958b790c331954ed367d37bac901de5c2f06ac8368b37d7bd6cd5ae143c1d7e3';
let fromAddress = "tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG";
let toAddress = '8CPcA7kaXSHbWb3GHP7bd5hRLFu8RZv57rY9w';*/
let pri = "94bb1af12b9099d9c28c436e5613661253a7b3f45a4c2534a0f08a996518bb37";//8CPcA7kaXSHbWb3GHP7bd5hRLFu8RZv57rY9w
let pub = '0398d4c2f8fa788a5f314bd40da588fa0991f2b4fdf7dbf25abce5ecc8cf129d00';
let fromAddress = "LINcjJR3SA4Ui6z5kcGmYm459z7JGQPxuxRC";
let toAddress = 'tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG';
let amount = 8800000000;
let remark = '跨链交易测试....';
let transferInfo = {
fromAddress: fromAddress,
toAddress: toAddress,
assetsChainId: 8,
assetsId: 1,
amount: amount,
remark: remark,
fee: 1000000
};
//调用
transferTransaction(pri, pub, 2, transferInfo);
/**
* 转账交易
* @param pri
* @param pub
* @param chainId
* @param transferInfo
* @returns {Promise}
*/
async function transferTransaction(pri, pub, chainId, transferInfo) {
//账户转出资产余额
//console.log(transferInfo);
const balanceInfo = await getBalance(8, transferInfo.assetsChainId, transferInfo.assetsId, transferInfo.fromAddress);
let inputs = [];
let outputs = [{
address: transferInfo.toAddress ? transferInfo.toAddress : transferInfo.fromAddress,
assetsChainId: transferInfo.assetsChainId,
assetsId: transferInfo.assetsId,
amount: transferInfo.amount,
lockTime: 0
}];
let mainNetBalanceInfo = await getBalance(8, 2, 1, transferInfo.fromAddress);
let localBalanceInfo;
//如果不是主网需要收取NULS手续费
if (!isMainNet(chainId)) {
if (mainNetBalanceInfo.balance < transferInfo.fee) {
console.log("余额不足");
return;
}
}
//如果转出资产为本链主资产,则直接将手续费加到转出金额上
if (chainId === transferInfo.assetsChainId && transferInfo.assetsId === 1) {
let newAmount = transferInfo.amount + transferInfo.fee;
if (balanceInfo.balance < transferInfo.amount + transferInfo.fee) {
console.log("余额不足");
return;
}
//转出的本链资产 = 转出资产amount + 本链手续费
inputs.push({
address: transferInfo.fromAddress,
assetsChainId: transferInfo.assetsChainId,
assetsId: transferInfo.assetsId,
amount: newAmount,
locked: 0,
nonce: balanceInfo.nonce
});
//如果不是主网需收取主网NULS手续费
if (!isMainNet(chainId)) {
inputs.push({
address: transferInfo.fromAddress,
assetsChainId: 2,
assetsId: 1,
amount: transferInfo.fee,
locked: 0,
nonce: mainNetBalanceInfo.nonce
});
}
} else {
localBalanceInfo = await getBalance(8, chainId, 1, transferInfo.fromAddress);
if (localBalanceInfo.balance < transferInfo.fee) {
console.log("该账户本链主资产不足够支付手续费!");
return;
}
//如果转出的是NULS,则需要把NULS手续费添加到转出金额上
if (transferInfo.assetsChainId === 2 && transferInfo.assetsId === 1) {
let newAmount = transferInfo.amount + transferInfo.fee;
if (mainNetBalanceInfo.balance < newAmount) {
console.log("余额不足");
return;
}
inputs.push({
address: transferInfo.fromAddress,
assetsChainId: transferInfo.assetsChainId,
assetsId: transferInfo.assetsId,
amount: newAmount,
locked: 0,
nonce: mainNetBalanceInfo.nonce
});
} else {
inputs.push({
address: transferInfo.fromAddress,
assetsChainId: transferInfo.assetsChainId,
assetsId: transferInfo.assetsId,
amount: transferInfo.amount,
locked: 0,
nonce: balanceInfo.nonce
});
inputs.push({
address: transferInfo.fromAddress,
assetsChainId: 2,
assetsId: 1,
amount: transferInfo.fee,
locked: 0,
nonce: mainNetBalanceInfo.nonce
});
}
//本链主资产手续费
if (!isMainNet(chainId)) {
inputs.push({
address: transferInfo.fromAddress,
assetsChainId: chainId,
assetsId: 1,
amount: transferInfo.fee,
locked: 0,
nonce: localBalanceInfo.nonce
});
}
}
let tAssemble = await nuls.transactionAssemble(inputs, outputs, transferInfo.remark, 10);//交易组装
let ctxSign = "";//本链协议交易签名
let mainCtxSign = "";//主网协议交易签名
let bw = new Serializers();
let mainCtx = new txs.CrossChainTransaction();
let pubHex = Buffer.from(pub, 'hex');
let newFee = 0;
if (isMainNet(chainId)) {
newFee = countCtxFee(tAssemble, 1)
} else {
newFee = countCtxFee(tAssemble, 2);
mainCtx.time = tAssemble.time;
mainCtx.remark = tAssemble.remark;
let mainNetInputs = [];
if (transferInfo.assetsChainId === 2 && transferInfo.assetsId === 1) {
mainNetInputs.push({
address: transferInfo.fromAddress,
assetsChainId: transferInfo.assetsChainId,
assetsId: transferInfo.assetsId,
amount: transferInfo.amount + newFee,
locked: 0,
nonce: mainNetBalanceInfo.nonce
});
} else {
mainNetInputs = [{
address: transferInfo.fromAddress,
assetsChainId: transferInfo.assetsChainId,
assetsId: transferInfo.assetsId,
amount: transferInfo.amount,
locked: 0,
nonce: balanceInfo.nonce
}, {
address: transferInfo.fromAddress,
assetsChainId: 2,
assetsId: 1,
amount: newFee,
locked: 0,
nonce: mainNetBalanceInfo.nonce
}];
}
mainCtx.setCoinData(mainNetInputs, outputs);
}
//如果手续费发生改变,重新组装CoinData
if (transferInfo.fee !== newFee) {
if (chainId === transferInfo.assetsChainId && transferInfo.assetsId === 1) {
if (balanceInfo.balance < transferInfo.amount + newFee) {
console.log("余额不足");
return;
}
inputs[0].amount = transferInfo.amount + newFee;
if (!isMainNet(chainId)) {
inputs[1].amount = newFee;
}
} else {
if (localBalanceInfo.balance < transferInfo.fee) {
console.log("该账户本链主资产不足够支付手续费!");
return;
}
if (transferInfo.assetsChainId === 2 && transferInfo.assetsId === 1) {
if (mainNetBalanceInfo.balance < transferInfo.amount + newFee) {
console.log("余额不足");
return;
}
inputs[0].amount = transferInfo.amount + newFee;
inputs[1].amount = newFee;
} else {
inputs[1].amount = newFee;
inputs[2].amount = newFee;
}
}
tAssemble = await nuls.transactionAssemble(inputs, outputs, transferInfo.remark, 10);
ctxSign = nuls.transactionSignature(pri, tAssemble);
} else {
ctxSign = nuls.transactionSignature(pri, tAssemble);
}
bw.writeBytesWithLength(pubHex);
bw.writeBytesWithLength(ctxSign);
if (!isMainNet(chainId)) {
mainCtx.txData = tAssemble.getHash();
mainCtxSign = nuls.transactionSignature(pri, mainCtx);
bw.writeBytesWithLength(pubHex);
bw.writeBytesWithLength(mainCtxSign);
}
tAssemble.signatures = bw.getBufWriter().toBuffer();
let txHex = tAssemble.txSerialize().toString('hex');
let result = await sendCrossTx(txHex);
console.log(result);
if (result.success) {
console.log(result.data.value);
let results = await broadcastTx(txHex);
if (results && results.value) {
console.log("交易完成")
} else {
console.log("广播交易失败")
}
} else {
console.log("验证交易失败:" + result.error)
}
}
--------------------------------------------------------------------------------
/src/test/cryptoTest.js:
--------------------------------------------------------------------------------
1 | let expect = require('chai').expect;
2 | let eccrypto = require("../crypto/eciesCrypto");
3 |
4 | let userPrivateKey = Buffer.from("1523eb8a85e8bb6641f8ae53c429811ede7ea588c4b8933fed796c667c203c06", "hex");
5 | let userPublicKey = eccrypto.getPublic(userPrivateKey);
6 |
7 | describe("crypto", function () {
8 |
9 | it("whole encrypt success", async function () {
10 | let data = "Information:Modules \"nuls-base\", \"nuls-core-rockdb\", \"nuls-core-rpc\", \"nuls-base-api-provider\", \"nuls-base-protocol-update\" and 我们认为NFT的使用案例由个人拥有和交易,以及托运给第三方经纪人/钱包/拍卖商(“运营商”)。NFT可以代表对数字或实物资rebuilt due to project configuration/dependencies changes";
11 | let bufferData = Buffer.from(data);
12 | let encrypted = await eccrypto.encrypt(userPublicKey, bufferData);
13 | console.info("encryptd data: ", encrypted.toString("hex"));
14 | });
15 |
16 | it("whole decrypt success", async function () {
17 | let encrypted = Buffer.from("0451aa0e455d20a2ddeb9c4671b55738e980a615001b5c4b5bb83db94442375745a2e5eb26a6bb8f45aec6e19c617b3135f14384979ae4cf315ff352ead873534e000000000000000000000000000000008f1333c6b62b88af2f5f5bcad6712e3aa36eab3d2f01bcc9cceabd2fb1a1c353be94ae3fe5c7dd5b5c091c8228d61f39d8f252b67de04c55167e6369267b707bd805348b1d77307e523917cf94d1500bff50926169461dbfdce0a5740b7e92d187c0e2aefc45947220a69dbfb585eed565b51c477c0ae1e5a58e38902fc1fc058a481061a6c7916ebceee078f2328b1b37e4d96da8f6cae6d64ce3eb1ab58b261dcd81af4a8d488ec7267e502b97dd6de408fc12cc7bd9b70de9f20146b9122e0b817b934bfc90aa08d660705954e7e7d80f40a8fd2a8b4cdec4e6e229376b5f51f2c5f5f6c81d7b22ee5aebc0c350571ef179e46356dc9ceaaa34b65a762d934241d258a63ed9f9d98e01cd8c9a879dba2a0d2d5f147fabb5f398b975f56515ad1587655fcc592ad806e8b3abb5d00839b4ff76ff3cf5264a2beb9d4cb13382b22a3fe99700ca86ec97ab07c7e4682931bdd53669361fa62e0400e39ebc57ecafd44334de8e509cee5a2dca60ff8399f9a5511a4496ad0100f6acc2e0b85fc44c30065b7be1fd4cca58fad17caf3b4d1168fa4347ff6adf1c18169c83a8fdddfd07db26b792bca0ad990b02b42d644a3deb192afc586d87a3ead311077a5de95dc249f81133b749a548d3aeca51f06166c14d6a860061f214b18e55fa9d51e6ed00c9b2fa3272b280c1d892927bc6b1", "hex");
18 | let decryptd = await eccrypto.decrypt(userPrivateKey, encrypted);
19 | console.info("decryptd data :", decryptd.toString());
20 | });
21 |
22 | });
23 |
--------------------------------------------------------------------------------
/src/test/dataOntoChain.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const {getNulsBalance, countFee, inputsOrOutputs, validateTx, broadcastTx} = require('./api/util');
3 | const sdk = require('../api/sdk');
4 |
5 | let address = 'tNULSeBaMuG5b4KuWuSg8rvNPttqWThhFsH3ns';
6 | let pri = "642d33a2fe29e40c6e5ee8aafd16da9699e1b9fbba45de7bb879831bed2cbd59";
7 | //上链数据:NULS主网创世块hash
8 | let data = '8221e980cc9707b4fcf05ac79e70b8ac75f00550bb7da9292e6d6432a716ea88';
9 |
10 | //调用
11 | transferTransaction(pri, address, data);
12 |
13 | /**
14 | * 基于转账交易的数据上链交易示例
15 | * @param pri
16 | * @param address
17 | * @param data
18 | * @returns {Promise}
19 | */
20 | async function transferTransaction(pri, address, data) {
21 | let remark = '测试数据上链';
22 | //获取余额和nonce
23 | const balanceInfo = await getNulsBalance(address);
24 |
25 | let pub = sdk.getPub(pri);
26 |
27 | let transferInfo = {
28 | fromAddress: address,
29 | assetsChainId: 2,
30 | assetsId: 1,
31 | amount: 0,
32 | fee: 100000
33 | };
34 | let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 2);
35 | let tAssemble = [];//交易组装
36 | let txhex = "";//交易签名
37 | if (inOrOutputs.success) {
38 | tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 2);
39 | //获取手续费
40 | let newFee = countFee(tAssemble, 1);
41 | //手续费大于0.001的时候重新组装交易及签名
42 | if (transferInfo.fee !== newFee) {
43 | transferInfo.fee = newFee;
44 | inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 2);
45 | tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 2);
46 | txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
47 | } else {
48 | txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
49 | }
50 | } else {
51 | console.log(inOrOutputs.data)
52 | }
53 | console.log(txhex);
54 | let result = await validateTx(txhex);
55 | if (result.success) {
56 | console.log(result.data.value);
57 | let results = await broadcastTx(txhex);
58 | if (results && results.value) {
59 | console.log("交易完成")
60 | } else {
61 | console.log("广播交易失败")
62 | }
63 | } else {
64 | console.log("验证交易失败:" + result.error.message)
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/test/deposit.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const {getNulsBalance, countFee, inputsOrOutputs, validateTx, broadcastTx} = require('./api/util');
3 |
4 | /**
5 | * @disc: 加入共识dome
6 | * @date: 2019-10-18 10:34
7 | * @author: Wave
8 | */
9 |
10 | let pri = '411fa90f7161a20f4624a4f00167fac6d5afd97a7e6815f60e66106c559564a1';
11 | let pub = '031c810153d633a5167ec629af771296bad4f26eacfe4034c978afee12b6c4fd44';
12 | let fromAddress = "tNULSeBaMuBCG7NkSyufjE76CVbPQMrZ5Q1v3s";
13 | let amount = 210000000000;
14 | let remark = 'deposit ....';
15 |
16 | let deposit = {
17 | address: fromAddress,
18 | agentHash: 'd8b31649b8d2ccac2fd258787583017f98fc1e1be579298aae650cb9698845c9',
19 | deposit: 2010000000000
20 | };
21 | //调用加入共识
22 | doit(pri, pub, fromAddress, 2, 1, amount, deposit);
23 |
24 | async function doit(pri, pub, fromAddress, assetsChainId, assetsId, amount, deposit) {
25 | const balanceInfo = await getNulsBalance(fromAddress);
26 | let transferInfo = {
27 | fromAddress: fromAddress,
28 | assetsChainId: assetsChainId,
29 | assetsId: assetsId,
30 | amount: amount,
31 | fee: 100000
32 | };
33 | let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 5);
34 | let tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 5, deposit);
35 | let txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
36 | //console.log(txhex);
37 | let result = await validateTx(txhex);
38 | if (result) {
39 | console.log(result.data.value);
40 | let results = await broadcastTx(txhex);
41 | if (results && result.data.value) {
42 | console.log("交易完成")
43 | } else {
44 | console.log("广播交易失败")
45 | }
46 | } else {
47 | console.log("验证交易失败")
48 | }
49 | }
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/test/deserialize/test.js:
--------------------------------------------------------------------------------
1 | const Serializers = require("../../api/serializers");
2 | const Block = require("../../model/block")
3 | const BufferReader = require("../../utils/bufferreader")
4 |
5 | //共识奖励+转账,1453110
6 | const blockhex = "4ab91a7d320b0b07b29536ec58c076ea7d3169d2c8592662f179f358c70036144ba5e7c1af3c19aa1b3c09ec8190b8b28d8baf789382a378f1f3109642e103622a0b585e362c1600020000005c5c3f00006f00580a585e150004000400500a00208632672517e468d1acdc6e59dd3e757138b8dbc908afb7f7c3daba90759d40c06c608a936d45b943dd821c393be73a53ce88585ccf18f93e8e1924dbd6f1ec9e30b0acafec2d78d32102f28feeaa3cd5b3d0ccde3389debbbc1268db317703750f756eaead92b3c23af546304402201339330f5adaab7163fa284456f07361cf2c29e8de2b5ee4bd9b360f1c6c577a02204aba70760fc5e4de2460bb6bdb1017f5a5e1116571c6cfbae17889760f51c90a01002a0b585e00008a000217010001474a63f8b2f0a999741c4fd162d430e17733f33b01000100a9e8810b00000000000000000000000000000000000000000000000000000000000000000000000017010001940c5646e9b680142d4452ec91ea7a0eeebe05d7010001007f580a00000000000000000000000000000000000000000000000000000000000000000000000000000200230b585e1262696e616e6365207769746864726177616c008c01170100013ba3e3c56062266262514c74fafb01852af99fec01000100e0b562910200000000000000000000000000000000000000000000000000000008dc1890d6baa257ad000117010001a9fa55a587f415bde2cc50469af2ee873322d5fa01000100402f61910200000000000000000000000000000000000000000000000000000000000000000000006921037af860c03801a7453c55fd2a7fe90c5081ac66db79b7a92139f320d4d60fc0bb463044022020731fb06b6452ae6ce67efe5334159f9008fcaa037e717f040774f7e8b4b75502205432dda224c6104aebde56875eec5ba1646eaaeae63f7482dce579c3ec13d79b";
7 |
8 |
9 | let reader = new BufferReader(Buffer.from(blockhex, "hex"), 0);
10 |
11 | let block = new Block(reader);
12 |
13 | block.printInfo();
14 |
15 |
16 | console.log('---------------------------------------------------------------------')
17 | console.log('Cursor::::' + reader.getCursor())
18 | console.log('Total::::' + reader.getBuffer().length)
19 |
20 |
21 | let bw = new Serializers();
22 | bw.getBufWriter().writeVarintNum(65536)
23 | var val = bw.getBufWriter().toBuffer().toString("hex")
24 | console.log(val)
25 | console.log(bw.getBufWriter().toBuffer())
--------------------------------------------------------------------------------
/src/test/deserialize/testCallContractDataHex.js:
--------------------------------------------------------------------------------
1 | const nuls = require("./../../index");
2 |
3 | const hex = "010001707cb4da76399b3406babc98060e524295ddf7e3010002b9387225c04b17daedc4abec193965559fad75d10000000000000000000000000000000000000000000000000000000000000000ab510000000000001900000000000000087472616e73666572000201254e554c53643648676a534c4759456339455a566673566f72654e7862375a7037484d616e7801083434303030303030";
4 | let hexInfo = nuls.contractDataParsing(hex);
5 | console.log(hexInfo.sender);
6 | console.log(JSON.stringify(hexInfo));
7 |
--------------------------------------------------------------------------------
/src/test/deserialize/testHex.js:
--------------------------------------------------------------------------------
1 | const nuls = require("./../../index");
2 |
3 | // const txHex = "02004e1175600433333433008c0117020001f88d93a52edc7437da5e2977d27681f0fb1e6bab02000100a029e31100000000000000000000000000000000000000000000000000000000089159a7cf6f535de8000117020001ad3482b405ca6ba6aee19b3c7db9f4a016b457770200010000a3e11100000000000000000000000000000000000000000000000000000000000000000000000000";
4 | const txHex = "0200211a7d6609636f696e2074657374008c0117020001f7ec6473df12e751d64cf20a8baa7edd50810f8102000100201d9a00000000000000000000000000000000000000000000000000000000000810c7c56b356608c7000117020001d24ac8859ded42e24659f3a953f009c908f1093e02000100809698000000000000000000000000000000000000000000000000000000000000000000000000006a2103958b790c331954ed367d37bac901de5c2f06ac8368b37d7bd6cd5ae143c1d7e3473045022008864c9df4d34fb95493348d06cecb86656055efd497f371b1cdbd146593fc21022100d941780b1bad9a54172e5a6926873ec819069efc3ed086fa45091f2293b50631";
5 | let tx = nuls.hexParsing(txHex);
6 | console.log(tx)
7 | console.log(JSON.stringify(tx))
8 |
9 |
--------------------------------------------------------------------------------
/src/test/fee.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @disc: 使用方式:先组装交易,然后获取手续费,再把手续费增加到from中,然后对交易进行签名,请确认交易地址有足够的余额。
3 | * signatrueCount 签名数量、默认为1
4 | * @date: 2019-10-18 10:35
5 | * @author: Wave
6 | **/
7 | export function countFee(tx, signatrueCount) {
8 | let txSize = tx.txSerialize().length;//后面花些时间把tx.size()方法实现后,可以用size()
9 | txSize += signatrueCount * 110;
10 | return 100000 * (txSize / 1024);
11 | }
12 |
13 | let a = {
14 | "chainId": 1,
15 | "assetId": 1,
16 | "mainChainId": 1,
17 | "mainAssetId": 1,
18 | "language": "zh-CHS",
19 | "encoding": "UTF-8",
20 | "keystoreFolder": "/keystore/backup",
21 | "dataPath":"/data",
22 | "blackHolePublicKey":"000000000000000000000000000000000000000000000000000000000000000000",
23 | "addressPrefix":"NULS"
24 | };
25 |
--------------------------------------------------------------------------------
/src/test/flash_test.js:
--------------------------------------------------------------------------------
1 | const BufferReader = require("../utils/bufferreader");
2 | const txs = require("../model/txs");
3 | const txsignatures = require("../model/txsignatures");
4 | const nuls = require('../index');
5 | const sdk = require("../api/sdk");
6 |
7 | //todo 入参
8 | let txHex = "";
9 | //todo 入参
10 | let prikeyHex = "";
11 | // 解析交易
12 | let bufferReader = new BufferReader(Buffer.from(txHex, "hex"), 0);
13 | // 反序列回交易对象
14 | let tx = new txs.Transaction();
15 | tx.parse(bufferReader);
16 | // 初始化签名对象
17 | let txSignData = new txsignatures.TransactionSignatures();
18 | // 反序列化签名对象
19 | let reader = new BufferReader(tx.signatures, 0);
20 | txSignData.parse(reader);
21 | // 打印已签名地址
22 | let address = nuls.getAddressByPub(5, 1, txSignData.signatures[0].pubkey, 'TNVT');
23 | console.log(address);
24 | //获取本账户公钥
25 | let pub = sdk.getPub(prikeyHex);
26 | // 签名
27 | let sigHex = sdk.signature(tx.getHash().toString("hex"), prikeyHex);
28 | let signValue = Buffer.from(sigHex, 'hex');
29 | // 追加签名到对象中
30 | txSignData.addSign(Buffer.from(pub, "hex"), signValue);
31 | // 追加签名到交易中
32 | tx.signatures = txSignData.serialize();
33 | //计算交易hash
34 | tx.calcHash();
35 | console.log(tx.getHash().toString("hex"));
36 | // console.log(pub)
37 | // console.log(signValue)
38 | // 结果
39 | console.log(tx.txSerialize().toString("hex"));
40 |
--------------------------------------------------------------------------------
/src/test/hash.js:
--------------------------------------------------------------------------------
1 | const sdk = require('../api/sdk');
2 |
3 | let data = "0200b67f2d5d0672656d61726b008c01170200012a9af4ee49f4cb1ee84eafd42aec41bc04b28f7b02000100402a8648170000000000000000000000000000000000000000000000000000000800000000000000000001170200012a9af4ee49f4cb1ee84eafd42aec41bc04b28f7b0200010000e87648170000000000000000000000000000000000000000000000000000000000000000000000";
4 |
5 |
6 | let result = sdk.getSha256Hex(data);
7 |
8 | console.log(sdk.getSha256Hex(result));
9 |
10 |
11 | //验证签名是否正确
12 |
13 |
14 | let hashHex = "89f44d63bd3323f7830993418fa62442f7d1c445a775dc6b4e317ef889b7ddd1";
15 | let signVal = "304502202670fd33a3df9200760fbec71bbdfa46f3e0dab21de1eb6c6a67958c18da9d29022100ab75ea2f44cea563370d8ce0a00e3f68d3c033db06edca755a2e9dc35653c653";
16 | let pub = "033fb58fdd16e7c23b31a3f7fb3bdd41942e2db53092e7dd183c8fef8dafff1082";
17 |
18 | let result1 = sdk.verifySign(hashHex, signVal, pub);
19 | console.log(result1)
20 |
21 |
22 | hashHex = "5ea8974bc3ad29a9af9035be47d3e6a4a5b505935658ff4234c60d795313b524";
23 | signVal = "304502206eacf2bcea9baafed12a50b9017f4be1a6bdbfd6842ed7c86d57d5ac7a47ea29022100f4d31b3d4c78af110f0f481bedea44614642cf33d87325c8bc6342f4642127eb";
24 | pub = "026f74d026c89f6f87ed88c7eeba6380bde58b8711f5481e6d99c63b110091663f";
25 |
26 | result1 = sdk.verifySign(hashHex, signVal, pub);
27 | console.log(result1)
--------------------------------------------------------------------------------
/src/test/importAddress.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 |
3 | /**
4 | * @disc: 导入地址 dome
5 | * @date: 2019-10-18 10:36
6 | * @author: Wave
7 | */
8 |
9 | let passWord = '';
10 | const key = "00db591ead0fd6a43dbff1d8e996288572f92563117c81548d4e3428a5fa503af2";
11 | try {
12 | const importAddress = nuls.importByKey(2, key, passWord, "tNULS");
13 | console.log(importAddress);
14 | console.log(importAddress.address === 'tNULSeBaMuBCG7NkSyufjE76CVbPQMrZ5Q1v3s');
15 | } catch (err) {
16 | console.log(err);
17 | }
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/test/newAddress.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 |
3 | /**
4 | * @disc: 创建地址 dome
5 | * @date: 2019-10-18 10:36
6 | * @author: Wave
7 | */
8 |
9 | let passWord = '';//密码为空 私钥会返回
10 | const newAddress = nuls.newAddress(100, passWord, 'XXX');
11 | console.log(newAddress);
12 |
13 | //验证地址
14 | let result = nuls.verifyAddress(newAddress.address);
15 | console.log(result);
16 |
17 | //1.0与2.0私钥或公钥生成的地址是否相同
18 | /*let rest = nuls.addressEquals("TTarYnUfsftmm7DrStandCEdd4SNiELS", "tNULSeBaMoG1oaW1JZnh6Ly65Ttp6raeTFBfCG");
19 | console.log(rest);*/
20 |
--------------------------------------------------------------------------------
/src/test/newAgent.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const {getNulsBalance, countFee, inputsOrOutputs, validateTx, broadcastTx} = require('./api/util');
3 |
4 | /**
5 | * @disc: 创建节点 dome
6 | * @date: 2019-10-18 10:37
7 | * @author: Wave
8 | */
9 |
10 | let pri = '411fa90f7161a20f4624a4f00167fac6d5afd97a7e6815f60e66106c559564a1';
11 | let pub = '031c810153d633a5167ec629af771296bad4f26eacfe4034c978afee12b6c4fd44';
12 | let fromAddress = "tNULSeBaMuBCG7NkSyufjE76CVbPQMrZ5Q1v3s";
13 | let amount = 2000100000000;
14 | let remark = 'new agent...';
15 |
16 | let agent = {
17 | agentAddress: fromAddress,
18 | packingAddress: "tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG",
19 | rewardAddress: fromAddress,
20 | commissionRate: 12,
21 | deposit: 2000100000000
22 | };
23 |
24 | //调用新建节点
25 | newAgent(pri, pub, fromAddress, 2, 1, amount, agent);
26 |
27 | /**
28 | * 新建节点
29 | * @param pri
30 | * @param pub
31 | * @param fromAddress
32 | * @param assetsChainId
33 | * @param assetsId
34 | * @param amount
35 | * @param agent
36 | * @returns {Promise<*>}
37 | */
38 | async function newAgent(pri, pub, fromAddress, assetsChainId, assetsId, amount, agent) {
39 | const balanceInfo = await getNulsBalance(fromAddress);
40 | let transferInfo = {
41 | fromAddress: fromAddress,
42 | assetsChainId: assetsChainId,
43 | assetsId: assetsId,
44 | amount: amount,
45 | fee: 100000
46 | };
47 | let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 4);
48 | let tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 4, agent);
49 | let txhex = await nuls.transactionSerialize(pri, pub,tAssemble);
50 | //console.log(txhex);
51 | let result = await validateTx(txhex);
52 | if (result) {
53 | console.log(result.data.value);
54 | let results = await broadcastTx(txhex);
55 | if (results && result.data.value) {
56 | console.log("交易完成")
57 | } else {
58 | console.log("广播交易失败")
59 | }
60 | } else {
61 | console.log("验证交易失败")
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/src/test/registercrosschain.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const sdk = require('../api/sdk');
3 | const {getNulsBalance, countFee, validateTx, broadcastTx, mutiInputsOrOutputs} = require('./api/util');
4 |
5 | /**
6 | * @disc:注册跨链交易
7 | * @date: 2019-10-17 15:50
8 | * @author: Wave
9 | */
10 |
11 | let chain = {
12 | chainId: 99,
13 | addressType: "1",//1 使用NULS框架构建的链 生态内,2生态外"
14 | chainName: "test1",
15 | addressPrefix: "XXXX",
16 | magicNumber: 10066,
17 | supportInflowAsset: true,
18 | verifierList: ["XXXcA7kaeQMPaiRNPpQSEP8S8tNXDFeC5vnEy", "XXXcA7kaiK3YhCdSxfXaaffHupBDPjm3veiEE", "XXXcA7kaYY2QrRFX7Le9YdwtzQ9JvtRUU37bx"],
19 | minAvailableNodeNum: 3,
20 | maxSignatureCount: 200,
21 | signatureBFTRatio: 66
22 | };
23 | let asset = {
24 | assetId: 1,
25 | symbol: "XXX",
26 | assetName: "XXX",
27 | initNumber: 10000000000000,
28 | decimalPlaces: 8
29 | };
30 |
31 | let fromAddress = "tNULSeBaMpVdwtAD2k33tiCbEsPXhpV3E6Zvgp";
32 | let pri = '4776e429194e9a1c0669a962df4b9f46745a19b2b6fa04e02304ce3ad54ad791';
33 |
34 | //注册跨链交易
35 | registerChainAndAsset(pri, fromAddress, chain, asset);
36 |
37 | async function registerChainAndAsset(pri, address, chainInfo, assetInfo) {
38 | const balanceInfo = await getNulsBalance(address);
39 | if (!balanceInfo.nonce) {
40 | console.log("get balance failed!");
41 | return;
42 | }
43 | let pub = sdk.getPub(pri);
44 | //跨链交易消耗3000nuls=1600转账+800锁定+600销毁
45 | let transferInfo = {
46 | assetsChainId: 2,
47 | assetsId: 1,
48 | fee: 100000,
49 | from: {
50 | fromAddress: address,
51 | amount: 300000000000
52 | },
53 | to: [
54 | {toAddress: "tNULSeBaMpQTyMygD2DLtW8pPBxHRqjjZqfyMh", amount: 160000000000},
55 | {toAddress: address, amount: 80000000000, lockTime: -1},
56 | {
57 | toAddress: sdk.getStringAddress(2, null, "000000000000000000000000000000000000000000000000000000000000000000", "tNULS"),
58 | amount: 60000000000
59 | }
60 | ]
61 | };
62 | let inOrOutputs = await mutiInputsOrOutputs(transferInfo, balanceInfo, 11);
63 | let tAssemble = [];//交易组装
64 | let txhex = "";//交易签名
65 | if (inOrOutputs.success) {
66 | let txData = {
67 | address: address,
68 | chainInfo: chainInfo,
69 | assetInfo: assetInfo
70 | };
71 | tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, '', 11, txData);
72 | //获取手续费
73 | let newFee = countFee(tAssemble, 1);
74 | //手续费大于0.001的时候重新组装交易及签名
75 | if (transferInfo.fee !== newFee) {
76 | transferInfo.fee = newFee;
77 | inOrOutputs = await mutiInputsOrOutputs(transferInfo, balanceInfo, 11);
78 | tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, '', 11, txData);
79 | txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
80 | } else {
81 | txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
82 | }
83 | console.log(inOrOutputs.data.inputs);
84 | console.log(inOrOutputs.data.outputs);
85 | } else {
86 | console.log(inOrOutputs.data);
87 | return;
88 | }
89 | console.log(txhex);
90 | let result = await validateTx(txhex);
91 | console.log(result);
92 | if (result.success) {
93 | console.log(result.data.value);
94 | let results = await broadcastTx(txhex);
95 | if (results && results.value) {
96 | console.log("交易完成")
97 | } else {
98 | console.log("广播交易失败")
99 | }
100 | } else {
101 | console.log("验证交易失败:" + result.error)
102 | }
103 | }
104 |
105 |
106 |
--------------------------------------------------------------------------------
/src/test/setAlias.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const sdk = require('../api/sdk')
3 | const {getNulsBalance, countFee, inputsOrOutputs, validateTx, broadcastTx} = require('./api/util');
4 |
5 | /**
6 | * @disc: 设置别名 dome
7 | * @params:
8 | * @date: 2019-10-18 10:38
9 | * @author: Wave
10 | */
11 |
12 | let pri = '4100e2f88c3dba08e5000ed3e8da1ae4f1e0041b856c09d35a26fb399550f530';
13 | let pub = '020e19418ed26700b0dba720dcc95483cb4adb1b5f8a103818dab17d5b05231854';
14 | let fromAddress = "tNULSeBaMu38g1vnJsSZUCwTDU9GsE5TVNUtpD";
15 | //黑洞地址
16 | let toAddress = 'tNULSeBaMhZnRteniCy3UZqPjTbnWKBPHX1a5d';
17 | let amount = 100000000;
18 | let remark = 'set alias....';
19 |
20 | //调用设置别名
21 | setAlias(pri, pub, fromAddress, toAddress, 2, 1, amount, remark);
22 |
23 | /**
24 | * 设置别名
25 | * @param pri
26 | * @param pub
27 | * @param fromAddress
28 | * @param toAddress
29 | * @param assetsChainId
30 | * @param assetsId
31 | * @param amount
32 | * @param remark
33 | * @returns {Promise}
34 | */
35 | async function setAlias(pri, pub, fromAddress, toAddress, assetsChainId, assetsId, amount, remark) {
36 | const balanceInfo = await getNulsBalance(fromAddress);
37 | let transferInfo = {
38 | fromAddress: fromAddress,
39 | toAddress: toAddress,
40 | assetsChainId: assetsChainId,
41 | assetsId: assetsId,
42 | amount: amount,
43 | fee: 100000
44 | };
45 | let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 3);
46 | let aliasInfo = {
47 | fromAddress: fromAddress,
48 | alias: 'wave'
49 | };
50 | //交易组装
51 | let tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 3, aliasInfo);
52 | console.log(tAssemble);
53 | //获取hash
54 | let hash = await tAssemble.getHash();
55 | console.log(hash);
56 | //交易签名
57 | let txSignature = await sdk.getSignData(hash.toString('hex'), pri);
58 | console.log(txSignature);
59 | //通过拼接签名、公钥获取HEX
60 | let signData = await sdk.appSplicingPub(txSignature.signValue, pub);
61 | tAssemble.signatures = signData;
62 | let txhex = tAssemble.txSerialize().toString("hex");
63 | console.log(txhex.toString('hex'));
64 |
65 | /*let getHex = await sdk.appSplicingPub(txSignature);
66 | console.log(getHex);
67 |
68 | let txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
69 | console.log(txhex);*/
70 | let result = await validateTx(txhex.toString('hex'));
71 | console.log(result);
72 | if (result) {
73 | console.log(result.data.value);
74 | let results = await broadcastTx(txhex);
75 | if (results && result.data.value) {
76 | console.log("交易完成")
77 | } else {
78 | console.log("广播交易失败")
79 | }
80 | } else {
81 | console.log("验证交易失败")
82 | }
83 | }
84 |
85 |
86 |
--------------------------------------------------------------------------------
/src/test/stopAgent.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const {getNulsBalance, countFee, inputsOrOutputs, validateTx, broadcastTx, agentDeposistList} = require('./api/util');
3 |
4 | /**
5 | * @disc: 注销节点 dome
6 | * @date: 2019-10-18 10:38
7 | * @author: Wave
8 | */
9 |
10 | let pri = '777e333556edb17564ea45f84dce0f5fbea884123924575213c7a30cb3c9375410';
11 | let pub = '027d8d404b0aaa834491999a0212ef7e432da69c6462857566f80a2c81e259e7b2';
12 | let fromAddress = "NULSd6HgfzPGhFsZX16hHgneY25YKs6v6LvmX";
13 | let amount = 2000000000000;
14 | let remark = 'stop agent....';
15 |
16 | //调用注销节点
17 | stopAgent(pri, pub, fromAddress, 1, 1, amount, '7018c41307132d3e4709c3f50bae235e6f028a267b291930520bdb25f9d24195');
18 |
19 | /**
20 | * 注销节点
21 | * @param pri
22 | * @param pub
23 | * @param fromAddress
24 | * @param assetsChainId
25 | * @param assetsId
26 | * @param amount
27 | * @param agentHash
28 | * @returns {Promise}
29 | */
30 | async function stopAgent(pri, pub, fromAddress, assetsChainId, assetsId, amount, agentHash) {
31 | const balanceInfo = await getNulsBalance(fromAddress);
32 | //console.log(balanceInfo);
33 | let transferInfo = {
34 | fromAddress: fromAddress,
35 | assetsChainId: assetsChainId,
36 | assetsId: assetsId,
37 | amount: amount,
38 | fee: 100000,
39 | depositHash: agentHash,
40 | };
41 | let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 9);
42 | //console.log(inOrOutputs);
43 | let newInputs = inOrOutputs.data.inputs;
44 | //console.log(newInputs);
45 | let newOutputs = [];
46 | //console.log(newOutputs);
47 | const depositList = await agentDeposistList(agentHash);
48 | //console.log(depositList);
49 | //console.log(depositList);
50 | for (let itme of depositList.list) {
51 | newInputs.push({
52 | address: itme.address,
53 | assetsChainId: assetsChainId,
54 | assetsId: assetsId,
55 | amount: itme.amount,
56 | locked: -1,
57 | nonce: itme.txHash.substring(agentHash.length - 16)//这里是hash的最后16个字符
58 | });
59 | newOutputs.push({
60 | address: itme.address, assetsChainId: assetsChainId,
61 | assetsId: assetsId, amount: itme.amount, lockTime: 0
62 | });
63 | }
64 | let addressArr = [];
65 | let newOutputss = [];
66 | newOutputs.forEach(function (item) {
67 | let i;
68 | if ((i = addressArr.indexOf(item.address)) > -1) {
69 | //console.log(result, i);
70 | newOutputss[i].amount = Number(newOutputss[i].amount) + Number(item.amount);
71 | } else {
72 | addressArr.push(item.address);
73 | newOutputss.push({
74 | address: item.address,
75 | amount: item.amount,
76 | assetsChainId: item.assetsChainId,
77 | assetsId: item.assetsId,
78 | lockTime: item.lockTime,
79 | })
80 | }
81 | });
82 | newOutputss.unshift(inOrOutputs.data.outputs[0]);
83 |
84 | //console.log(newInputs);
85 | //console.log(newOutputss);
86 |
87 | let tAssemble = await nuls.transactionAssemble(newInputs, newOutputss, remark, 9, agentHash);
88 | //console.log(tAssemble);
89 | let txhex = '';
90 | //获取手续费
91 | let newFee = countFee(tAssemble, 1);
92 | //手续费大于0.001的时候重新组装交易及签名
93 | if (transferInfo.fee !== newFee) {
94 | transferInfo.fee = newFee;
95 | inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 9);
96 | newInputs = inOrOutputs.data.inputs;
97 | newOutputs = inOrOutputs.data.outputs;
98 | for (let itme of depositList.list) {
99 | newInputs.push({
100 | address: itme.address,
101 | assetsChainId: assetsChainId,
102 | assetsId: assetsId,
103 | amount: itme.amount,
104 | locked: -1,
105 | nonce: itme.txHash.substring(agentHash.length - 16)//这里是hash的最后16个字符
106 | });
107 | newOutputs.push({
108 | address: itme.address, assetsChainId: assetsChainId,
109 | assetsId: assetsId, amount: itme.amount, lockTime: 0
110 | });
111 | }
112 | tAssemble = await nuls.transactionAssemble(newInputs, newOutputs, remark, 9, agentHash);
113 | txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
114 | } else {
115 | txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
116 | }
117 | //console.log(txhex);
118 | let result = await validateTx(txhex);
119 | //console.log(result);
120 | if (result) {
121 | let results = await broadcastTx(txhex);
122 | //console.log(results);
123 | if (results && result.value) {
124 | console.log("交易完成")
125 | } else {
126 | console.log("广播交易失败")
127 | }
128 | } else {
129 | console.log("验证交易失败")
130 | }
131 | }
132 |
133 |
134 |
--------------------------------------------------------------------------------
/src/test/take.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const {getNulsBalance, inputsOrOutputs, validateTx, broadcastTx} = require('./api/util');
3 |
4 | /**
5 | * @disc: 退出共识 dome
6 | * @date: 2019-10-18 10:39
7 | * @author: Wave
8 | */
9 |
10 | let pri = '94d344417d6faa55e3017709dd6b837bac2bc1769e3a4b516ac9a981465ac03c';
11 | let pub = '02403cb49ac24ff9555b073ce981e28bed5e81438b2c715a14d06bd248ea1d0091';
12 | let fromAddress = "tNULSeBaMfwpGBmn8xuKABPWUbdtsM2cMoinnn";
13 | let amount = 210000000000;
14 | let remark = 'niels test alias....';
15 |
16 | //退出共识
17 | take(pri, pub, fromAddress, 2, 1, amount, 'f556c7d05dd30c1080759e88e5934ff8981df2bf0dabd287dfee63b490bece50');
18 |
19 | /**
20 | * 退出共识
21 | * @param pri
22 | * @param pub
23 | * @param fromAddress
24 | * @param assetsChainId
25 | * @param assetsId
26 | * @param amount
27 | * @param depositHash
28 | * @returns {Promise}
29 | */
30 | async function take(pri, pub, fromAddress, assetsChainId, assetsId, amount, depositHash) {
31 | const balanceInfo = await getNulsBalance(fromAddress);
32 | let transferInfo = {
33 | fromAddress: fromAddress,
34 | assetsChainId: assetsChainId,
35 | assetsId: assetsId,
36 | amount: amount,
37 | fee: 100000,
38 | depositHash: depositHash
39 | };
40 | let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 6);
41 | let tAssemble = await nuls.transactionAssemble(inOrOutputs.inputs, inOrOutputs.outputs, remark, 6, depositHash);
42 | let txhex = await nuls.transactionSerialize(pri, pub,tAssemble);
43 | //console.log(txhex);
44 | let result = await validateTx(txhex);
45 | if (result) {
46 | console.log(result.value);
47 | let results = await broadcastTx(txhex);
48 | if (results && result.value) {
49 | console.log("交易完成")
50 | } else {
51 | console.log("广播交易失败")
52 | }
53 | } else {
54 | console.log("验证交易失败")
55 | }
56 | }
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/test/testAes.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const sdk = require('../api/sdk');
3 |
4 |
5 | const prikeyhex = "x";
6 |
7 |
8 |
9 | // let result = nuls.decrypteOfAES(prikeyhex,"jian1021!@#$")
10 |
11 |
12 | // console.log(result)
13 |
14 |
15 | console.log(nuls.getAddressByPub(9,1,"x","NERVE"))
16 |
--------------------------------------------------------------------------------
/src/test/tradingOrder.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const sdk = require('../api/sdk')
3 | const {getBalance, countFee, inputsOrOutputs, validateTx, broadcastTx} = require('./api/util');
4 |
5 | /**
6 | * @disc: 创建交易对 dome
7 | * @params:
8 | * @date: 2019-12-9 10:38
9 | * @author: vivi
10 | */
11 |
12 | let pri = '4100e2f88c3dba08e5000ed3e8da1ae4f1e0041b856c09d35a26fb399550f530';
13 | let pub = '020e19418ed26700b0dba720dcc95483cb4adb1b5f8a103818dab17d5b05231854';
14 | let address = "tNULSeBaMu38g1vnJsSZUCwTDU9GsE5TVNUtpD";
15 | let remark = 'create tradingOrder....';
16 | let txType = 29;
17 | let fee = 100000; //手续费
18 |
19 | let defaultAsset = { //本链默认资产,用于生成手续费
20 | assetsChainId: 2,
21 | assetsId: 1
22 | };
23 |
24 | let tradingOrderInfo = {
25 | tradingHash: '2560584b3b33df9676f86230846e666fd645696129799d77ee043269f614862c', //交易对hash
26 | address: address, //挂单委托人
27 | orderType: 1, //委托挂单类型 1:买单,2:卖单
28 | assetsChainId: 2,
29 | assetsId: 1,
30 | amount: 10000000000, //挂单金额
31 | price: 10000000, //单价
32 | feeAddress: config.feeAddress,
33 | feeScale: config.feeScale
34 | };
35 |
36 | //调用委托挂单
37 | tradingOrder(tradingOrderInfo);
38 |
39 | /**
40 | * 委托挂单
41 | * @param pri
42 | * @param pub
43 | * @param fromAddress
44 | * @param toAddress
45 | * @param assetsChainId
46 | * @param assetsId
47 | * @param amount
48 | * @param remark
49 | * @returns {Promise}
50 | */
51 | async function tradingOrder(tradingOrderInfo) {
52 | let inOrOutputs = await createCoinData(tradingOrderInfo);
53 |
54 | //交易组装
55 | let tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, txType, tradingOrderInfo);
56 | console.log(tAssemble);
57 | //获取hash
58 | let hash = await tAssemble.getHash();
59 | console.log(hash);
60 | //交易签名
61 | let txSignature = await sdk.getSignData(hash.toString('hex'), pri);
62 | console.log(txSignature);
63 | //通过拼接签名、公钥获取HEX
64 | let signData = await sdk.appSplicingPub(txSignature.signValue, pub);
65 | tAssemble.signatures = signData;
66 | let txhex = tAssemble.txSerialize().toString("hex");
67 | console.log(txhex.toString('hex'));
68 | }
69 |
70 | async function createCoinData(tradingOrderInfo) {
71 | const balanceInfo = await getBalance(defaultAsset.assetsChainId, tradingOrderInfo.assetsChainId, tradingOrderInfo.assetsId, tradingOrderInfo.address);
72 | let inputs = [], outputs = [];
73 | let input = {
74 | address: tradingOrderInfo.address,
75 | assetsChainId: tradingOrderInfo.assetsChainId,
76 | assetsId: tradingOrderInfo.assetsId,
77 | amount: tradingOrderInfo.amount,
78 | locked: 0,
79 | nonce: balanceInfo.nonce
80 | };
81 | //判断用户的挂单委托资产是否是本链的默认资产
82 | if (tradingOrderInfo.assetsChainId === defaultAsset.assetsChainId && tradingOrderInfo.assetsId === defaultAsset.assetsId) {
83 | //如果是,生成input的时候,将委托金额和手续费一起收
84 | input.amount += fee;
85 | inputs.push(input);
86 | } else {
87 | //如果不是要额外收取手续费
88 | inputs.push(input);
89 | const balanceInfo = await getBalance(defaultAsset.assetsChainId, defaultAsset.assetsChainId, defaultAsset.assetsId, tradingOrderInfo.address);
90 | inputs.push({
91 | address: tradingOrderInfo.address,
92 | assetsChainId: tradingOrderInfo.assetsChainId,
93 | assetsId: tradingOrderInfo.assetsId,
94 | amount: fee,
95 | locked: 0,
96 | nonce: balanceInfo.nonce
97 | });
98 | }
99 |
100 | outputs.push({
101 | address: tradingOrderInfo.address,
102 | assetsChainId: tradingOrderInfo.assetsChainId,
103 | assetsId: tradingOrderInfo.assetsId,
104 | amount: tradingOrderInfo.amount,
105 | lockTime: -2
106 | });
107 | return {success: true, data: {inputs: inputs, outputs: outputs}};
108 | }
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/src/test/tradingOrderCancel.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const sdk = require('../api/sdk');
3 |
4 | /**
5 | * @disc: 撤销委托挂单 dome
6 | * @date: 2019-12-9 10:38
7 | * @author: vivi
8 | */
9 |
10 | let pri = '9ce21dad67e0f0af2599b41b515a7f7018059418bab892a7b68f283d489abc4b';
11 | let pub = '03958b790c331954ed367d37bac901de5c2f06ac8368b37d7bd6cd5ae143c1d7e3';
12 | let address = "tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG";
13 | let remark = 'cancel tradingOrder....';
14 | let txType = 30;
15 | let fee = 100000; //手续费
16 | //本链默认资产,用于生成手续费
17 | let defaultAsset = {assetsChainId: 2, assetsId: 1};
18 |
19 | //正常情况,这个数据是通过查询orderHash的nonce值接口查询到
20 | let tradingOrderInfo = {
21 | orderHash: 'f4ef24c225cc2af33902a3f7d147760d21407039ee98ec6dd74303f969171a5d', //委托挂单hash
22 | address: address, //撤销挂单委托人
23 | orderType: 1, //委托挂单类型 1:买单,2:卖单
24 | nonce: "69db314e5fd02b6b",//通过解决接口查询nonce
25 | leftAmount: 88700391787 //撤销金额
26 |
27 | };
28 |
29 | //正常情况,这个数据是通过交易对详情接口查询出来的
30 | let coinTrading = {
31 | baseAssetChainId: 2,
32 | baseAssetId: 2,
33 | quoteAssetChainId: 2,
34 | quoteAssetId: 1
35 | };
36 |
37 | //调用委托挂单
38 | tradingOrderCancel(tradingOrderInfo);
39 |
40 | /**
41 | * 委托挂单
42 | * @param tradingOrderInfo
43 | * @returns {Promise}
44 | */
45 | async function tradingOrderCancel(tradingOrderInfo) {
46 | let inOrOutputs = await createCoinData(tradingOrderInfo, coinTrading);
47 | //交易组装
48 | let tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, txType, tradingOrderInfo);
49 | console.log(tAssemble);
50 | //获取hash
51 | let hash = await tAssemble.getHash();
52 | console.log(hash);
53 | //交易签名
54 | let txSignature = await sdk.getSignData(hash.toString('hex'), pri);
55 | console.log(txSignature);
56 | //通过拼接签名、公钥获取HEX
57 | let signData = await sdk.appSplicingPub(txSignature.signValue, pub);
58 | tAssemble.signatures = signData;
59 | let txhex = tAssemble.txSerialize().toString("hex");
60 | console.log(txhex.toString('hex'));
61 | }
62 |
63 | async function createCoinData(tradingOrderInfo, coinTrading) {
64 | let inputs = [], outputs = [];
65 | //首先通过订单信息组装解锁from
66 | let orderInput = {
67 | address: tradingOrderInfo.address,
68 | assetsChainId: coinTrading.baseAssetChainId,
69 | assetsId: coinTrading.baseAssetId,
70 | amount: tradingOrderInfo.leftAmount,
71 | locked: -1,
72 | nonce: tradingOrderInfo.nonce
73 | };
74 | if (tradingOrderInfo.type === 1) {
75 | orderInput.assetsChainId = coinTrading.quoteAssetChainId;
76 | orderInput.assetsId = coinTrading.quoteAssetId;
77 | }
78 | inputs.push(orderInput);
79 |
80 | //如果手续费不足,需要添加手续费
81 | if (orderInput.assetsChainId !== defaultAsset.assetsChainId || orderInput.assetsId !== defaultAsset.assetsId || orderInput.amount < fee) {
82 | //通过获取用户当前余额组装手续费from
83 | // const balanceInfo = await getBalance(defaultAsset.assetsChainId, defaultAsset.assetsChainId, defaultAsset.assetsId, tradingOrderInfo.address);
84 | inputs.push({
85 | address: tradingOrderInfo.address,
86 | assetsChainId: defaultAsset.assetsChainId,
87 | assetsId: defaultAsset.assetsId,
88 | amount: fee,
89 | locked: 0,
90 | nonce: "85e00519bbb5f5d8"
91 | });
92 | }
93 |
94 | //组装to
95 | if (orderInput.assetsChainId !== defaultAsset.assetsChainId || orderInput.assetsId !== defaultAsset.assetsId || orderInput.amount < fee) {
96 | outputs.push({
97 | address: tradingOrderInfo.address,
98 | assetsChainId: orderInput.assetsChainId,
99 | assetsId: orderInput.assetsId,
100 | amount: orderInput.amount,
101 | lockTime: 0
102 | });
103 | } else {
104 | outputs.push({
105 | address: tradingOrderInfo.address,
106 | assetsChainId: orderInput.assetsChainId,
107 | assetsId: orderInput.assetsId,
108 | amount: orderInput.amount - fee,
109 | lockTime: 0
110 | });
111 | }
112 |
113 | return {success: true, data: {inputs: inputs, outputs: outputs}};
114 | }
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/src/test/transfer.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 | const txs = require('../model/txs');
3 | const BufferReader = require("../utils/bufferreader");
4 | const {getNulsBalance, countFee, inputsOrOutputs, validateTx, broadcastTx} = require('./api/util');
5 |
6 | /**
7 | * @disc: 转账 dome
8 | * @date: 2019-10-18 10:40
9 | * @author: Wave
10 | */
11 |
12 | let pri = 'x';
13 | let pub = '03958b790c331954ed367d37bac901de5c2f06ac8368b37d7bd6cd5ae143c1d7e3';
14 | let fromAddress = "tNULSeBaMvEtDfvZuukDf2mVyfGo3DdiN8KLRG";
15 | let toAddress = 'tNULSeBaMsvfuGcosTR5dedtk8ksdfarrQWz3X';
16 | let amount = 10000000;
17 | let remark = 'coin test';
18 | //调用
19 | // transferTransaction(pri, pub, fromAddress, toAddress, 2, 1, amount, remark);
20 |
21 | /**
22 | * 转账交易
23 | * @param pri
24 | * @param pub
25 | * @param fromAddress
26 | * @param toAddress
27 | * @param assetsChainId
28 | * @param assetsId
29 | * @param amount
30 | * @param remark
31 | * @returns {Promise}
32 | */
33 | async function transferTransaction(pri, pub, fromAddress, toAddress, assetsChainId, assetsId, amount, remark) {
34 | const balanceInfo = await getNulsBalance(fromAddress);
35 |
36 | let transferInfo = {
37 | fromAddress: fromAddress,
38 | toAddress: toAddress,
39 | assetsChainId: assetsChainId,
40 | assetsId: assetsId,
41 | amount: amount,
42 | fee: 100000
43 | };
44 | let inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 2);
45 | let tAssemble = [];//交易组装
46 | let txhex = "";//交易签名
47 | if (inOrOutputs.success) {
48 | tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 2);
49 | //获取手续费
50 | let newFee = countFee(tAssemble, 1);
51 | //手续费大于0.001的时候重新组装交易及签名
52 | if (transferInfo.fee !== newFee) {
53 | transferInfo.fee = newFee;
54 | inOrOutputs = await inputsOrOutputs(transferInfo, balanceInfo, 2);
55 | tAssemble = await nuls.transactionAssemble(inOrOutputs.data.inputs, inOrOutputs.data.outputs, remark, 2);
56 | txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
57 | } else {
58 | txhex = await nuls.transactionSerialize(pri, pub, tAssemble);
59 | }
60 | } else {
61 | console.log(inOrOutputs.data)
62 | }
63 | console.log(txhex);
64 | let result = await validateTx(txhex);
65 | if (result.success) {
66 | console.log(result.data.value);
67 | let results = await broadcastTx(txhex);
68 | if (results && results.value) {
69 | console.log("交易完成")
70 | } else {
71 | console.log("广播交易失败")
72 | }
73 | } else {
74 | console.log("验证交易失败:" + result.error)
75 | }
76 | }
77 |
78 | let hex = "02005fd2a96700008c0117020001f7ec6473df12e751d64cf20a8baa7edd50810f8102000100a0b33201000000000000000000000000000000000000000000000000000000000811f5e4619e0a12c2000117020001c712dcb7ad82a943470a9a23fae87c50068e465602000100002d310100000000000000000000000000000000000000000000000000000000000000000000000000";
79 | // let tx = new txs.Transaction();
80 | // let bufferReader = new BufferReader(Buffer.from(hex, "hex"), 0);
81 | // tx.parse(bufferReader);
82 |
83 | // let signedTx = nuls.transactionSerialize(pri, pub, tx);
84 | // console.log(signedTx);
85 | console.log(nuls.signTxHex(pri, pub, hex));
86 |
87 |
--------------------------------------------------------------------------------
/src/test/v1Tov2.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../api/sdk');
2 |
3 | /**
4 | * @disc: 验证V1.0与V2.0地址是否相同 dome
5 | * @date: 2019-10-18 10:40
6 | * @author: Wave
7 | */
8 |
9 | let addressV2 = nuls.addressV1ToV2("TTarKL8DjsoXmn2EAYTnzC5KK8oxNULS",1);
10 | console.log(addressV2);
11 | addressV2 = nuls.addressV1ToV2("Nsdwnd4auFisFJKU6iDvBxTdPkeg8qkB",1);
12 | console.log(addressV2);
13 |
--------------------------------------------------------------------------------
/src/test/verifyAddress.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 |
3 | /**
4 | * @disc: 地址验证 dome
5 | * @date: 2019-10-18 10:41
6 | * @author: Wave
7 | */
8 |
9 | let address = 'NULSd6Hgam8YajetEDnCoJBdEFkMNP41PfH7y';
10 | console.log(nuls.verifyAddress(address));
11 |
--------------------------------------------------------------------------------
/src/test/verifyProgramEncodePacked.js:
--------------------------------------------------------------------------------
1 | const nuls = require('../index');
2 |
3 | var txKey = "b03858bb-c265-4e2d-b383-df7a4c4a87d5";
4 | var sender = "tNULSeBaMoixxbUovqmzPyJ2AwYFAX2evKbuy9";
5 | var nulsAmount = "20000000";
6 | var tokenAmount = "0";
7 | var assetKey = "";
8 | var receiver = "tNULSeBaMnrs6JKrCy6TQdzYJZkMZJDng7QAsD";
9 |
10 | function testEncode() {
11 | let args = [txKey, sender, nulsAmount, tokenAmount, assetKey, receiver];
12 | let result = nuls.programEncodePacked(args);
13 | console.log('result', result);
14 | }
15 |
16 | function testDecode() {
17 | let args = [txKey, sender, nulsAmount, tokenAmount, assetKey, receiver];
18 | let result = nuls.programEncodePacked(args);
19 | let parseResult = nuls.parseProgramEncodePacked(result);
20 | console.log('parseResult', parseResult);
21 | }
22 | testEncode();
23 |
24 | const Signature = require('elliptic/lib/elliptic/ec/signature');
25 | const signature = {
26 | r: 'bb09696750985b79948be8ec8f975aa2078ff74dbae1eb3a8dd3ec5673d68856',
27 | s: '502696adf22e6143aac3b3c9fd0c49c6a2210aaa3f8143c9b10b90194477d88d'
28 | };
29 |
30 | // 创建 Signature 对象
31 | const sigObj = new Signature(signature);
32 |
33 | // 转换为 DER 格式
34 | const derSignature = sigObj.toDER();
35 |
36 | // 输出 DER 格式化的签名
37 | console.log('DER-formatted signature:', Buffer.from(derSignature).toString('hex'));
38 |
39 |
--------------------------------------------------------------------------------
/src/test/verifySig.js:
--------------------------------------------------------------------------------
1 | const sdk = require('../api/sdk');
2 | var secp256k1 = require("secp256k1");
3 | var rs = require('jsrsasign/lib/jsrsasign.js');
4 |
5 | //验证签名是否正确
6 |
7 | let account = {
8 | pri:
9 | '5968bbe187f97d78ea93413b083acbecdba1db61e3beb3f0c5e10238fe2dbf5f',
10 | pub:
11 | '04b0358da1571511fb24d078746db64de1c90ec64db9840142b5680201ca80d747970eb8d4e9c2c6e1611704a441e002feddc7074ca5b630ef22259a9d7cc862b0',
12 | address: 'XXXcA7kaimujixnBjjya8BLkPuKPijSv5yxpJ'
13 | }
14 | ;
15 |
16 | // 30440220
17 | // hello
18 | let hashHex = dataToHex("hello");
19 |
20 | let signVal = sdk.signature(hashHex, account.pri);
21 |
22 | let publickey = secp256k1.publicKeyConvert(Buffer.from(account.pub, "hex"), false);
23 |
24 | let result1 = sdk.verifySign(hashHex, signVal, publickey.toString('hex'));
25 |
26 | console.log(Buffer.from(hashHex, "hex").toString("hex") == '');
27 | console.log(Buffer.from(hashHex, "hex").toString("hex") === hashHex);
28 | console.log(Buffer.from(hashHex, "hex").toString("hex"));
29 | console.log(Buffer.from(hashHex, "utf8").toString("hex"));
30 | console.log(signVal);
31 | console.log(result1);
32 | console.log(account.pri.length);
33 |
34 | function dataToHex(data) {
35 | let _data = Buffer.from(data, "hex").toString("hex");
36 | let isHex = _data != '' && _data === data;
37 | if (isHex) {
38 | return data;
39 | }
40 | return Buffer.from(data, "utf8").toString("hex");
41 | }
42 | console.log('sdk.verifySign', sdk.verifySign(
43 | hashHex,
44 | '304502200dfed1d5b45e706b2c7edbca9e19a3c681e41c83b293511a0846541c670dabb9022100fa597d4ad69a9f7ba1b2026e6e6fe2657019448ec6bc964da93d5eec1190259d',
45 | '0347ede10670ddbbfea359242673169528d184f8ef2e586c15d686aa49dddc555f'));
46 |
47 |
48 | function dataToHex1(data) {
49 | try {
50 | return Buffer.from(data, "hex").toString("hex");
51 | } catch (e) {
52 | return Buffer.from(data, "utf8").toString("hex");
53 | }
54 | }
55 |
56 | function dataToHex2(data) {
57 | try {
58 | let _data = Buffer.from(data, "hex").toString("hex");
59 | let isHex = _data != '' && _data === data;
60 | if (isHex) {
61 | return data;
62 | }
63 | return Buffer.from(data, "utf8").toString("hex");
64 | } catch (e) {
65 | return Buffer.from(data, "utf8").toString("hex");
66 | }
67 | }
68 |
69 | console.log(dataToHex("30440220"));
70 | console.log(dataToHex("hi"));
71 | console.log('sdk.verifySign', sdk.verifySign(
72 | hashHex,
73 | '3045022100d624826b02c5d01203b93847315e3a68026217d3c1af49f2676762a81d3da2e1022008aafb78b79e4f28197e890add5248db2dee06057fd96485030514efbc27911a',
74 | '0347ede10670ddbbfea359242673169528d184f8ef2e586c15d686aa49dddc555f'));
75 |
76 | var testSig = function () {
77 | let hash = '63a1802f22fd9b7bd9663317649f57af2dd7a2f1deee82e4d6028d62cdbd57b5';
78 | let pri = '00db591ead0fd6a43dbff1d8e996288572f92563117c81548d4e3428a5fa503af2';
79 |
80 | let signVal = sdk.signature(hashHex, pri);
81 | let pub = sdk.getPub(pri);
82 |
83 | let result = {
84 | "pubkey": pub,
85 | "signData": signVal
86 | };
87 | console.log(result);
88 | }
89 | // testSig();
90 |
--------------------------------------------------------------------------------
/src/utils/bn.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var BN = require('bn.js');
4 | var $ = require('./preconditions');
5 | var _ = require('lodash');
6 |
7 | var reversebuf = function(buf) {
8 | var buf2 = Buffer.alloc(buf.length);
9 | for (var i = 0; i < buf.length; i++) {
10 | buf2[i] = buf[buf.length - 1 - i];
11 | }
12 | return buf2;
13 | };
14 |
15 | BN.Zero = new BN(0);
16 | BN.One = new BN(1);
17 | BN.Minus1 = new BN(-1);
18 |
19 | BN.fromNumber = function(n) {
20 | $.checkArgument(_.isNumber(n));
21 | return new BN(n);
22 | };
23 |
24 | BN.fromString = function(str, base) {
25 | $.checkArgument(_.isString(str));
26 | return new BN(str, base);
27 | };
28 |
29 | BN.fromBuffer = function(buf, opts) {
30 | if (typeof opts !== 'undefined' && opts.endian === 'little') {
31 | buf = reversebuf(buf);
32 | }
33 | var hex = buf.toString('hex');
34 | var bn = new BN(hex, 16);
35 | return bn;
36 | };
37 |
38 | /**
39 | * Instantiate a BigNumber from a "signed magnitude buffer"
40 | * (a buffer where the most significant bit represents the sign (0 = positive, -1 = negative))
41 | */
42 | BN.fromSM = function(buf, opts) {
43 | var ret;
44 | if (buf.length === 0) {
45 | return BN.fromBuffer(Buffer.from([0]));
46 | }
47 |
48 | var endian = 'big';
49 | if (opts) {
50 | endian = opts.endian;
51 | }
52 | if (endian === 'little') {
53 | buf = reversebuf(buf);
54 | }
55 |
56 | if (buf[0] & 0x80) {
57 | buf[0] = buf[0] & 0x7f;
58 | ret = BN.fromBuffer(buf);
59 | ret.neg().copy(ret);
60 | } else {
61 | ret = BN.fromBuffer(buf);
62 | }
63 | return ret;
64 | };
65 |
66 |
67 | BN.prototype.toNumber = function() {
68 | return parseInt(this.toString(10), 10);
69 | };
70 |
71 | BN.prototype.toBuffer = function(opts) {
72 | var buf, hex;
73 | if (opts && opts.size) {
74 | hex = this.toString(16, 2);
75 | var natlen = hex.length / 2;
76 | buf = Buffer.from(hex, 'hex');
77 |
78 | if (natlen === opts.size) {
79 | buf = buf;
80 | } else if (natlen > opts.size) {
81 | buf = BN.trim(buf, natlen);
82 | } else if (natlen < opts.size) {
83 | buf = BN.pad(buf, natlen, opts.size);
84 | }
85 | } else {
86 | hex = this.toString(16, 2);
87 | buf = Buffer.from(hex, 'hex');
88 | }
89 |
90 | if (typeof opts !== 'undefined' && opts.endian === 'little') {
91 | buf = reversebuf(buf);
92 | }
93 |
94 | return buf;
95 | };
96 |
97 | BN.prototype.toSMBigEndian = function() {
98 | var buf;
99 | if (this.cmp(BN.Zero) === -1) {
100 | buf = this.neg().toBuffer();
101 | if (buf[0] & 0x80) {
102 | buf = Buffer.concat([Buffer.from([0x80]), buf]);
103 | } else {
104 | buf[0] = buf[0] | 0x80;
105 | }
106 | } else {
107 | buf = this.toBuffer();
108 | if (buf[0] & 0x80) {
109 | buf = Buffer.concat([Buffer.from([0x00]), buf]);
110 | }
111 | }
112 |
113 | if (buf.length === 1 & buf[0] === 0) {
114 | buf = Buffer.from([]);
115 | }
116 | return buf;
117 | };
118 |
119 | BN.prototype.toSM = function(opts) {
120 | var endian = opts ? opts.endian : 'big';
121 | var buf = this.toSMBigEndian();
122 |
123 | if (endian === 'little') {
124 | buf = reversebuf(buf);
125 | }
126 | return buf;
127 | };
128 |
129 | /**
130 | * Create a BN from a "ScriptNum":
131 | * This is analogous to the constructor for CScriptNum in bitcoind. Many ops in
132 | * bitcoind's script interpreter use CScriptNum, which is not really a proper
133 | * bignum. Instead, an error is thrown if trying to input a number bigger than
134 | * 4 bytes. We copy that behavior here. A third argument, `size`, is provided to
135 | * extend the hard limit of 4 bytes, as some usages require more than 4 bytes.
136 | */
137 | BN.fromScriptNumBuffer = function(buf, fRequireMinimal, size) {
138 | var nMaxNumSize = size || 4;
139 | $.checkArgument(buf.length <= nMaxNumSize, new Error('script number overflow'));
140 | if (fRequireMinimal && buf.length > 0) {
141 | // Check that the number is encoded with the minimum possible
142 | // number of bytes.
143 | //
144 | // If the most-significant-byte - excluding the sign bit - is zero
145 | // then we're not minimal. Note how this test also rejects the
146 | // negative-zero encoding, 0x80.
147 | if ((buf[buf.length - 1] & 0x7f) === 0) {
148 | // One exception: if there's more than one byte and the most
149 | // significant bit of the second-most-significant-byte is set
150 | // it would conflict with the sign bit. An example of this case
151 | // is +-255, which encode to 0xff00 and 0xff80 respectively.
152 | // (big-endian).
153 | if (buf.length <= 1 || (buf[buf.length - 2] & 0x80) === 0) {
154 | throw new Error('non-minimally encoded script number');
155 | }
156 | }
157 | }
158 | return BN.fromSM(buf, {
159 | endian: 'little'
160 | });
161 | };
162 |
163 | /**
164 | * The corollary to the above, with the notable exception that we do not throw
165 | * an error if the output is larger than four bytes. (Which can happen if
166 | * performing a numerical operation that results in an overflow to more than 4
167 | * bytes).
168 | */
169 | BN.prototype.toScriptNumBuffer = function() {
170 | return this.toSM({
171 | endian: 'little'
172 | });
173 | };
174 |
175 | BN.trim = function(buf, natlen) {
176 | return buf.slice(natlen - buf.length, buf.length);
177 | };
178 |
179 | BN.pad = function(buf, natlen, size) {
180 | var rbuf = Buffer.alloc(size);
181 | for (var i = 0; i < buf.length; i++) {
182 | rbuf[rbuf.length - 1 - i] = buf[buf.length - 1 - i];
183 | }
184 | for (i = 0; i < size - natlen; i++) {
185 | rbuf[i] = 0;
186 | }
187 | return rbuf;
188 | };
189 |
190 | module.exports = BN;
191 |
--------------------------------------------------------------------------------
/src/utils/buffer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var buffer = require('buffer');
4 | var assert = require('assert');
5 |
6 | var js = require('./js');
7 | var $ = require('./preconditions');
8 |
9 | function equals(a, b) {
10 | if (a.length !== b.length) {
11 | return false;
12 | }
13 | var length = a.length;
14 | for (var i = 0; i < length; i++) {
15 | if (a[i] !== b[i]) {
16 | return false;
17 | }
18 | }
19 | return true;
20 | }
21 |
22 | module.exports = {
23 | /**
24 | * Fill a buffer with a value.
25 | *
26 | * @param {Buffer} buffer
27 | * @param {number} value
28 | * @return {Buffer}
29 | */
30 | fill: function fill(buffer, value) {
31 | $.checkArgumentType(buffer, 'Buffer', 'buffer');
32 | $.checkArgumentType(value, 'number', 'value');
33 | var length = buffer.length;
34 | for (var i = 0; i < length; i++) {
35 | buffer[i] = value;
36 | }
37 | return buffer;
38 | },
39 |
40 | /**
41 | * Return a copy of a buffer
42 | *
43 | * @param {Buffer} original
44 | * @return {Buffer}
45 | */
46 | copy: function(original) {
47 | var buffer = Buffer.alloc(original.length);
48 | original.copy(buffer);
49 | return buffer;
50 | },
51 |
52 | /**
53 | * Returns true if the given argument is an instance of a buffer. Tests for
54 | * both node's Buffer and Uint8Array
55 | *
56 | * @param {*} arg
57 | * @return {boolean}
58 | */
59 | isBuffer: function isBuffer(arg) {
60 | return buffer.Buffer.isBuffer(arg) || arg instanceof Uint8Array;
61 | },
62 |
63 | /**
64 | * Returns a zero-filled byte array
65 | *
66 | * @param {number} bytes
67 | * @return {Buffer}
68 | */
69 | emptyBuffer: function emptyBuffer(bytes) {
70 | $.checkArgumentType(bytes, 'number', 'bytes');
71 | var result = new buffer.Buffer(bytes);
72 | for (var i = 0; i < bytes; i++) {
73 | result.write('\0', i);
74 | }
75 | return result;
76 | },
77 |
78 | /**
79 | * Concatenates a buffer
80 | *
81 | * Shortcut for buffer.Buffer.concat
82 | */
83 | concat: buffer.Buffer.concat,
84 |
85 | equals: equals,
86 | equal: equals,
87 |
88 | /**
89 | * Transforms a number from 0 to 255 into a Buffer of size 1 with that value
90 | *
91 | * @param {number} integer
92 | * @return {Buffer}
93 | */
94 | integerAsSingleByteBuffer: function integerAsSingleByteBuffer(integer) {
95 | $.checkArgumentType(integer, 'number', 'integer');
96 | return new buffer.Buffer([integer & 0xff]);
97 | },
98 |
99 | /**
100 | * Transform a 4-byte integer into a Buffer of length 4.
101 | *
102 | * @param {number} integer
103 | * @return {Buffer}
104 | */
105 | integerAsBuffer: function integerAsBuffer(integer) {
106 | $.checkArgumentType(integer, 'number', 'integer');
107 | var bytes = [];
108 | bytes.push((integer >> 24) & 0xff);
109 | bytes.push((integer >> 16) & 0xff);
110 | bytes.push((integer >> 8) & 0xff);
111 | bytes.push(integer & 0xff);
112 | return Buffer.from(bytes);
113 | },
114 |
115 | /**
116 | * Transform the first 4 values of a Buffer into a number, in little endian encoding
117 | *
118 | * @param {Buffer} buffer
119 | * @return {number}
120 | */
121 | integerFromBuffer: function integerFromBuffer(buffer) {
122 | $.checkArgumentType(buffer, 'Buffer', 'buffer');
123 | return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
124 | },
125 |
126 | /**
127 | * Transforms the first byte of an array into a number ranging from -128 to 127
128 | * @param {Buffer} buffer
129 | * @return {number}
130 | */
131 | integerFromSingleByteBuffer: function integerFromBuffer(buffer) {
132 | $.checkArgumentType(buffer, 'Buffer', 'buffer');
133 | return buffer[0];
134 | },
135 |
136 | /**
137 | * Transforms a buffer into a string with a number in hexa representation
138 | *
139 | * Shorthand for buffer.toString('hex')
140 | *
141 | * @param {Buffer} buffer
142 | * @return {string}
143 | */
144 | // bufferToHex: function bufferToHex(buffer) {
145 | // $.checkArgumentType(buffer, 'Buffer', 'buffer');
146 | // return buffer.toString('hex');
147 | // },
148 |
149 | /**
150 | * Reverse a buffer
151 | * @param {Buffer} param
152 | * @return {Buffer}
153 | */
154 | reverse: function reverse(param) {
155 | var ret = new buffer.Buffer(param.length);
156 | for (var i = 0; i < param.length; i++) {
157 | ret[i] = param[param.length - i - 1];
158 | }
159 | return ret;
160 | },
161 |
162 | /**
163 | * Transforms an hexa encoded string into a Buffer with binary values
164 | *
165 | * Shorthand for Buffer(string, 'hex')
166 | *
167 | * @param {string} string
168 | * @return {Buffer}
169 | */
170 | hexToBuffer: function hexToBuffer(string) {
171 | assert(js.isHexa(string));
172 | return new buffer.Buffer(string, 'hex');
173 | },
174 |
175 | bufferToHex: function bufferToHex(buf) {
176 | return buf.reduce((r,d)=>{
177 | let hex = d.toString(16);
178 | if(hex.length === 1){
179 | hex = "0" + hex;
180 | }
181 | return r + hex;
182 | },"")
183 | }
184 | };
185 |
186 | module.exports.NULL_HASH = module.exports.fill(Buffer.alloc(32), 0);
187 | module.exports.EMPTY_BUFFER = Buffer.alloc(0);
188 |
--------------------------------------------------------------------------------
/src/utils/bufferreader.js:
--------------------------------------------------------------------------------
1 | let BigInteger = require("bigi");
2 |
3 | var BufferReader = function (buffer, cursor) {
4 | this.buf = buffer;
5 | this.cursor = cursor;
6 |
7 | }
8 |
9 | BufferReader.prototype.getCursor = function () {
10 | return this.cursor;
11 | };
12 | BufferReader.prototype.getBuffer = function () {
13 | return this.buf;
14 | };
15 |
16 | BufferReader.prototype.slice = function (length) {
17 | var result = this.buf.slice(this.cursor, this.cursor + length);
18 | this.cursor += length;
19 | return result;
20 | };
21 |
22 | BufferReader.prototype.readUInt64LE = function () {
23 | var bytes = this.slice(8);
24 | return (bytes[0] & 0xff) |
25 | ((bytes[1] & 0xff) << 8) |
26 | ((bytes[2] & 0xff) << 16) |
27 | ((bytes[3] & 0xff) << 24) |
28 | ((bytes[4] & 0xff) << 32) |
29 | ((bytes[5] & 0xff) << 40) |
30 | ((bytes[6] & 0xff) << 48) |
31 | ((bytes[7] & 0xff) << 56);
32 | };
33 | BufferReader.prototype.readUInt32LE = function () {
34 | var result = this.buf.readUInt32LE(this.cursor);
35 | this.cursor += 4;
36 | return result;
37 | };
38 | BufferReader.prototype.readUInt16LE = function () {
39 | var result = this.buf.readUInt16LE(this.cursor);
40 | this.cursor += 2;
41 | return result;
42 | };
43 | BufferReader.prototype.readUInt8 = function () {
44 | var result = this.buf.readUInt8(this.cursor);
45 | this.cursor += 1;
46 | return result;
47 | };
48 | BufferReader.prototype.readBytesByLength = function () {
49 | var length = this.readVarInt();
50 | var result = this.slice(length);
51 | return result;
52 | };
53 | BufferReader.prototype.isFinished = function () {
54 | return this.buf.length == this.cursor;
55 | };
56 | BufferReader.prototype.readBoolean = function () {
57 | result = this.buf.readUInt8();
58 | this.cursor += 1;
59 | return result != 0;
60 | };
61 | BufferReader.prototype.readBigInteger = function () {
62 | var bytes = this.slice(32);
63 | var value = new BigInteger(bytes.reverse());
64 | return value.toString();
65 | };
66 |
67 | BufferReader.prototype.readVarInt = function () {
68 | var first = 0xFF & this.buf.readInt8(this.cursor);
69 | var result = first;
70 | if (first < 253) {
71 | this.cursor += 1;
72 | } else if (first == 253) {
73 | result = this.buf.readInt16LE(this.cursor + 1)
74 | this.cursor += 3;
75 | } else if (first == 254) {
76 | result = this.buf.readUInt32LE(this.cursor + 1)
77 | this.cursor += 5;
78 | } else {
79 | result = this.buf.readUInt64LE(this.cursor + 1)
80 | this.cursor += 9;
81 | }
82 | return result;
83 | };
84 |
85 |
86 | module.exports = BufferReader;
--------------------------------------------------------------------------------
/src/utils/bufferwriter.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var bufferUtil = require('./buffer');
4 | var assert = require('assert');
5 |
6 | var BufferWriter = function BufferWriter(obj) {
7 | if (!(this instanceof BufferWriter))
8 | return new BufferWriter(obj);
9 | this.bufLen = 0;
10 | if (obj)
11 | this.set(obj);
12 | else
13 | this.bufs = [];
14 | };
15 |
16 | BufferWriter.prototype.set = function(obj) {
17 | this.bufs = obj.bufs || this.bufs || [];
18 | this.bufLen = this.bufs.reduce(function(prev, buf){ return prev + buf.length; }, 0);
19 | return this;
20 | };
21 |
22 | BufferWriter.prototype.toBuffer = function() {
23 | return this.concat();
24 | };
25 |
26 | BufferWriter.prototype.concat = function() {
27 | return Buffer.concat(this.bufs, this.bufLen);
28 | };
29 |
30 | BufferWriter.prototype.write = function(buf) {
31 | assert(bufferUtil.isBuffer(buf));
32 | this.bufs.push(buf);
33 | this.bufLen += buf.length;
34 | return this;
35 | };
36 |
37 | BufferWriter.prototype.writeReverse = function(buf) {
38 | assert(bufferUtil.isBuffer(buf));
39 | this.bufs.push(bufferUtil.reverse(buf));
40 | this.bufLen += buf.length;
41 | return this;
42 | };
43 |
44 | BufferWriter.prototype.writeUInt8 = function(n) {
45 | var buf = Buffer.alloc(1);
46 | buf.writeUInt8(n, 0);
47 | this.write(buf);
48 | return this;
49 | };
50 |
51 | BufferWriter.prototype.writeUInt16BE = function(n) {
52 | var buf = Buffer.alloc(2);
53 | buf.writeUInt16BE(n, 0);
54 | this.write(buf);
55 | return this;
56 | };
57 |
58 | BufferWriter.prototype.writeUInt16LE = function(n) {
59 | var buf = Buffer.alloc(2);
60 | buf.writeUInt16LE(n, 0);
61 | this.write(buf);
62 | return this;
63 | };
64 |
65 | BufferWriter.prototype.writeUInt32BE = function(n) {
66 | var buf = Buffer.alloc(4);
67 | buf.writeUInt32BE(n, 0);
68 | this.write(buf);
69 | return this;
70 | };
71 |
72 | BufferWriter.prototype.writeInt32LE = function(n) {
73 | var buf = Buffer.alloc(4);
74 | buf.writeInt32LE(n, 0);
75 | this.write(buf);
76 | return this;
77 | };
78 |
79 | BufferWriter.prototype.writeUInt32LE = function(n) {
80 | var buf = Buffer.alloc(4);
81 | buf.writeUInt32LE(n, 0);
82 | this.write(buf);
83 | return this;
84 | };
85 |
86 | BufferWriter.prototype.writeUInt64BEBN = function(bn) {
87 | var buf = bn.toBuffer({size: 8});
88 | this.write(buf);
89 | return this;
90 | };
91 |
92 | BufferWriter.prototype.writeUInt64LEBN = function(bn) {
93 | var buf = bn.toBuffer({size: 8});
94 | this.writeReverse(buf);
95 | return this;
96 | };
97 |
98 | BufferWriter.prototype.writeVarintNum = function(n) {
99 | var buf = BufferWriter.varintBufNum(n);
100 | this.write(buf);
101 | return this;
102 | };
103 |
104 | BufferWriter.prototype.writeVarintBN = function(bn) {
105 | var buf = BufferWriter.varintBufBN(bn);
106 | this.write(buf);
107 | return this;
108 | };
109 |
110 | BufferWriter.varintBufNum = function(n) {
111 | var buf = undefined;
112 | if (n < 253) {
113 | buf = Buffer.alloc(1);
114 | buf.writeUInt8(n, 0);
115 | } else if (n < 0x10000) {
116 | buf = Buffer.alloc(1 + 2);
117 | buf.writeUInt8(253, 0);
118 | buf.writeUInt16LE(n, 1);
119 | } else if (n < 0x100000000) {
120 | buf = Buffer.alloc(1 + 4);
121 | buf.writeUInt8(254, 0);
122 | buf.writeUInt32LE(n, 1);
123 | } else {
124 | buf = Buffer.alloc(1 + 8);
125 | buf.writeUInt8(255, 0);
126 | buf.writeInt32LE(n & -1, 1);
127 | buf.writeUInt32LE(Math.floor(n / 0x100000000), 5);
128 | }
129 | return buf;
130 | };
131 |
132 | BufferWriter.varintBufBN = function(bn) {
133 | var buf = undefined;
134 | var n = bn.toNumber();
135 | if (n < 253) {
136 | buf = Buffer.alloc(1);
137 | buf.writeUInt8(n, 0);
138 | } else if (n < 0x10000) {
139 | buf = Buffer.alloc(1 + 2);
140 | buf.writeUInt8(253, 0);
141 | buf.writeUInt16LE(n, 1);
142 | } else if (n < 0x100000000) {
143 | buf = Buffer.alloc(1 + 4);
144 | buf.writeUInt8(254, 0);
145 | buf.writeUInt32LE(n, 1);
146 | } else {
147 | var bw = new BufferWriter();
148 | bw.writeUInt8(255);
149 | bw.writeUInt64LEBN(bn);
150 | var buf = bw.concat();
151 | }
152 | return buf;
153 | };
154 |
155 | module.exports = BufferWriter;
156 |
--------------------------------------------------------------------------------
/src/utils/hash.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var crypto = require('crypto');
4 | var BufferUtil = require('./buffer');
5 | var $ = require('./preconditions');
6 |
7 | var Hash = module.exports;
8 |
9 | Hash.sha1 = function(buf) {
10 | $.checkArgument(BufferUtil.isBuffer(buf));
11 | return crypto.createHash('sha1').update(buf).digest();
12 | };
13 |
14 | Hash.sha1.blocksize = 512;
15 |
16 | Hash.sha256 = function(buf) {
17 | $.checkArgument(BufferUtil.isBuffer(buf));
18 | return crypto.createHash('sha256').update(buf).digest();
19 | };
20 |
21 | Hash.sha256.blocksize = 512;
22 |
23 | Hash.sha256sha256 = function(buf) {
24 | $.checkArgument(BufferUtil.isBuffer(buf));
25 | return Hash.sha256(Hash.sha256(buf));
26 | };
27 |
28 | Hash.ripemd160 = function(buf) {
29 | $.checkArgument(BufferUtil.isBuffer(buf));
30 | return crypto.createHash('ripemd160').update(buf).digest();
31 | };
32 |
33 | Hash.sha256ripemd160 = function(buf) {
34 | $.checkArgument(BufferUtil.isBuffer(buf));
35 | return Hash.ripemd160(Hash.sha256(buf));
36 | };
37 |
38 | Hash.sha512 = function(buf) {
39 | $.checkArgument(BufferUtil.isBuffer(buf));
40 | return crypto.createHash('sha512').update(buf).digest();
41 | };
42 |
43 | Hash.sha512.blocksize = 1024;
44 |
45 | Hash.hmac = function(hashf, data, key) {
46 | //http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
47 | //http://tools.ietf.org/html/rfc4868#section-2
48 | $.checkArgument(BufferUtil.isBuffer(data));
49 | $.checkArgument(BufferUtil.isBuffer(key));
50 | $.checkArgument(hashf.blocksize);
51 |
52 | var blocksize = hashf.blocksize / 8;
53 |
54 | if (key.length > blocksize) {
55 | key = hashf(key);
56 | } else if (key < blocksize) {
57 | var fill = Buffer.alloc(blocksize);
58 | fill.fill(0);
59 | key.copy(fill);
60 | key = fill;
61 | }
62 |
63 | var o_key = Buffer.alloc(blocksize);
64 | o_key.fill(0x5c);
65 |
66 | var i_key = Buffer.alloc(blocksize);
67 | i_key.fill(0x36);
68 |
69 | var o_key_pad = Buffer.alloc(blocksize);
70 | var i_key_pad = Buffer.alloc(blocksize);
71 | for (var i = 0; i < blocksize; i++) {
72 | o_key_pad[i] = o_key[i] ^ key[i];
73 | i_key_pad[i] = i_key[i] ^ key[i];
74 | }
75 |
76 | return hashf(Buffer.concat([o_key_pad, hashf(Buffer.concat([i_key_pad, data]))]));
77 | };
78 |
79 | Hash.sha256hmac = function(data, key) {
80 | return Hash.hmac(Hash.sha256, data, key);
81 | };
82 |
83 | Hash.sha512hmac = function(data, key) {
84 | return Hash.hmac(Hash.sha512, data, key);
85 | };
86 |
--------------------------------------------------------------------------------
/src/utils/js.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _ = require('lodash');
4 |
5 | /**
6 | * Determines whether a string contains only hexadecimal values
7 | *
8 | * @name JSUtil.isHexa
9 | * @param {string} value
10 | * @return {boolean} true if the string is the hexa representation of a number
11 | */
12 | var isHexa = function isHexa(value) {
13 | if (!_.isString(value)) {
14 | return false;
15 | }
16 | return /^[0-9a-fA-F]+$/.test(value);
17 | };
18 |
19 | /**
20 | * @namespace JSUtil
21 | */
22 | module.exports = {
23 | /**
24 | * Test if an argument is a valid JSON object. If it is, returns a truthy
25 | * value (the json object decoded), so no double JSON.parse call is necessary
26 | *
27 | * @param {string} arg
28 | * @return {Object|boolean} false if the argument is not a JSON string.
29 | */
30 | isValidJSON: function isValidJSON(arg) {
31 | var parsed;
32 | if (!_.isString(arg)) {
33 | return false;
34 | }
35 | try {
36 | parsed = JSON.parse(arg);
37 | } catch (e) {
38 | return false;
39 | }
40 | if (typeof(parsed) === 'object') {
41 | return true;
42 | }
43 | return false;
44 | },
45 | isHexa: isHexa,
46 | isHexaString: isHexa,
47 |
48 | /**
49 | * Clone an array
50 | */
51 | cloneArray: function(array) {
52 | return [].concat(array);
53 | },
54 |
55 | /**
56 | * Define immutable properties on a target object
57 | *
58 | * @param {Object} target - An object to be extended
59 | * @param {Object} values - An object of properties
60 | * @return {Object} The target object
61 | */
62 | defineImmutable: function defineImmutable(target, values) {
63 | Object.keys(values).forEach(function(key){
64 | Object.defineProperty(target, key, {
65 | configurable: false,
66 | enumerable: true,
67 | value: values[key]
68 | });
69 | });
70 | return target;
71 | },
72 | /**
73 | * Checks that a value is a natural number, a positive integer or zero.
74 | *
75 | * @param {*} value
76 | * @return {Boolean}
77 | */
78 | isNaturalNumber: function isNaturalNumber(value) {
79 | return typeof value === 'number' &&
80 | isFinite(value) &&
81 | Math.floor(value) === value &&
82 | value >= 0;
83 | }
84 | };
85 |
--------------------------------------------------------------------------------
/src/utils/preconditions.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // var errors = require('../errors');
4 | var _ = require('lodash');
5 |
6 | module.exports = {
7 | checkState: function(condition, message) {
8 | if (!condition) {
9 | throw new errors.InvalidState(message);
10 | }
11 | },
12 | checkArgument: function(condition, argumentName, message, docsPath) {
13 | if (!condition) {
14 | throw new errors.InvalidArgument(argumentName, message, docsPath);
15 | }
16 | },
17 | checkArgumentType: function(argument, type, argumentName) {
18 | argumentName = argumentName || '(unknown name)';
19 | if (_.isString(type)) {
20 | if (type === 'Buffer') {
21 | var buffer = require('buffer'); // './buffer' fails on cordova & RN
22 | if (!buffer.Buffer.isBuffer(argument)) {
23 | throw new errors.InvalidArgumentType(argument, type, argumentName);
24 | }
25 | } else if (typeof argument !== type) {
26 | throw new errors.InvalidArgumentType(argument, type, argumentName);
27 | }
28 | } else {
29 | if (!(argument instanceof type)) {
30 | throw new errors.InvalidArgumentType(argument, type.name, argumentName);
31 | }
32 | }
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/src/utils/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function valueOfstring(obj) {
4 | return obj === null ? null : obj.toString();
5 | }
6 |
7 | function isBlank(str) {
8 | return null === str || str.trim().length === 0;
9 | }
10 |
11 | module.exports = {
12 | stringToByte(str) {
13 | let bytes = [];
14 | let len, c;
15 | len = str.length;
16 | for (let i = 0; i < len; i++) {
17 | c = str.charCodeAt(i);
18 | if (c >= 0x010000 && c <= 0x10FFFF) {
19 | bytes.push(((c >> 18) & 0x07) | 0xF0);
20 | bytes.push(((c >> 12) & 0x3F) | 0x80);
21 | bytes.push(((c >> 6) & 0x3F) | 0x80);
22 | bytes.push((c & 0x3F) | 0x80);
23 | } else if (c >= 0x000800 && c <= 0x00FFFF) {
24 | bytes.push(((c >> 12) & 0x0F) | 0xE0);
25 | bytes.push(((c >> 6) & 0x3F) | 0x80);
26 | bytes.push((c & 0x3F) | 0x80);
27 | } else if (c >= 0x000080 && c <= 0x0007FF) {
28 | bytes.push(((c >> 6) & 0x1F) | 0xC0);
29 | bytes.push((c & 0x3F) | 0x80);
30 | } else {
31 | bytes.push(c & 0xFF);
32 | }
33 | }
34 | return bytes;
35 | },
36 |
37 | twoDimensionalArray: function twoDimensionalArray(args, types) {
38 | if (args.length === 0) {
39 | return null;
40 | } else if (args.length !== types.length) {
41 | throw "args number error";
42 | } else {
43 | let length = args.length;
44 | let two = new Array(length);
45 | let arg = void 0;
46 | for (let i = 0; i < length; i++) {
47 | arg = args[i];
48 | if (arg == null) {
49 | two[i] = [];
50 | continue;
51 | }
52 | if (typeof arg === 'string') {
53 | let argStr = arg;
54 | // 非String类型参数,若传参是空字符串,则赋值为空一维数组,避免数字类型转化异常 -> 空字符串转化为数字
55 | if (types != null && isBlank(argStr) && 'String' !== types[i]) {
56 | two[i] = [];
57 | } else if (types != null && !isBlank(argStr) && types[i].indexOf('[]') >= 0) {
58 | let arrayArg = eval(argStr);
59 | if (Array.isArray(arrayArg)) {
60 | let len = arrayArg.length;
61 | let result = new Array(len);
62 | for (let k = 0; k < len; k++) {
63 | result[k] = valueOfstring(arrayArg[k]);
64 | }
65 | two[i] = result;
66 | } else {
67 | throw "array arg error";
68 | }
69 | } else {
70 | two[i] = [argStr];
71 | }
72 | } else if (Array.isArray(arg)) {
73 | let len = arg.length;
74 | let result = new Array(len);
75 | for (let k = 0; k < len; k++) {
76 | result[k] = valueOfstring(arg[k]);
77 | }
78 | two[i] = result;
79 | } else {
80 | two[i] = [valueOfstring(arg)];
81 | }
82 | }
83 | return two;
84 | }
85 | }
86 | };
87 |
88 |
89 |
--------------------------------------------------------------------------------