├── .gitignore ├── lib ├── base58check │ ├── bs58.js │ ├── index.js │ └── base-x.js ├── constants.js ├── options.js ├── transactions │ ├── delegate.js │ ├── basic.js │ ├── vote.js │ ├── signature.js │ ├── multisignature.js │ ├── transfer.js │ ├── uia.js │ ├── dapp.js │ ├── transaction.js │ └── crypto.js ├── address.js └── time │ ├── slots.js │ └── format.js ├── .travis.yml ├── index.js ├── package.json ├── README.md └── test └── tests.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | node_modules 4 | npm-debug.log 5 | package-lock.json 6 | -------------------------------------------------------------------------------- /lib/base58check/bs58.js: -------------------------------------------------------------------------------- 1 | var basex = require('./base-x.js') 2 | var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' 3 | 4 | module.exports = basex(ALPHABET) -------------------------------------------------------------------------------- /lib/constants.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | fees:{ 3 | send: 10000000, 4 | vote: 10000000, 5 | delegate: 10000000000, 6 | secondsignature: 500000000, 7 | multisignature: 500000000, 8 | dapp: 10000000000 9 | }, 10 | coin: 100000000 11 | } 12 | -------------------------------------------------------------------------------- /lib/options.js: -------------------------------------------------------------------------------- 1 | var optionMap = { 2 | clientDriftSeconds: 5 3 | } 4 | 5 | module.exports = { 6 | set: function (key, val) { 7 | optionMap[key] = val 8 | }, 9 | get: function (key) { 10 | return optionMap[key] 11 | }, 12 | getAll: function () { 13 | return optionMap 14 | } 15 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | language: node_js 4 | env: 5 | - CXX=g++-4.8 6 | node_js: 7 | - "6.0.0" 8 | - "7" 9 | notifications: 10 | recipients: 11 | - sqf1225@foxmail.com 12 | - i@yanyiwu.com 13 | email: 14 | on_success: change 15 | on_failure: always 16 | addons: 17 | apt: 18 | sources: 19 | - ubuntu-toolchain-r-test 20 | packages: 21 | - g++-4.8 22 | -------------------------------------------------------------------------------- /lib/transactions/delegate.js: -------------------------------------------------------------------------------- 1 | var crypto = require("./crypto.js") 2 | var constants = require("../constants.js") 3 | var slots = require("../time/slots.js") 4 | var options = require('../options') 5 | var transaction = require('./transaction') 6 | 7 | function createDelegate(secret, secondSecret) { 8 | return transaction.createTransactionEx({ 9 | type: 10, 10 | fee: 100 * 1e8, 11 | args: [], 12 | secret: secret, 13 | secondSecret: secondSecret 14 | }) 15 | } 16 | 17 | module.exports = { 18 | createDelegate : createDelegate 19 | } 20 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | basic: require("./lib/transactions/basic.js"), 3 | crypto : require("./lib/transactions/crypto.js"), 4 | dapp: require("./lib/transactions/dapp.js"), 5 | transfer: require("./lib/transactions/transfer.js"), 6 | delegate : require("./lib/transactions/delegate.js"), 7 | signature : require("./lib/transactions/signature.js"), 8 | transaction : require("./lib/transactions/transaction.js"), 9 | vote : require("./lib/transactions/vote.js"), 10 | uia: require("./lib/transactions/uia.js"), 11 | options: require("./lib/options.js"), 12 | utils: { 13 | slots: require("./lib/time/slots.js"), 14 | format: require("./lib/time/format.js") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/transactions/basic.js: -------------------------------------------------------------------------------- 1 | var transaction = require('./transaction.js') 2 | 3 | function calculateFee(username){ 4 | let len = username.length 5 | if (len === 2) { 6 | return 200 7 | } else if (len === 3) { 8 | return 100 9 | } else if (len === 4) { 10 | return 80 11 | } else if (len === 5) { 12 | return 40 13 | } else if (len <= 10) { 14 | return 10 15 | } 16 | return 1 17 | } 18 | 19 | function setName(username, secret, secondSecret) { 20 | return transaction.createTransactionEx({ 21 | type: 2, 22 | fee: calculateFee(username) * 1e8, 23 | secret: secret, 24 | secondSecret: secondSecret, 25 | args: [username] 26 | }) 27 | } 28 | 29 | module.exports = { 30 | setName: setName 31 | } 32 | -------------------------------------------------------------------------------- /lib/transactions/vote.js: -------------------------------------------------------------------------------- 1 | var crypto = require("./crypto.js") 2 | var constants = require("../constants.js") 3 | var slots = require("../time/slots.js") 4 | var options = require('../options') 5 | var transaction = require('./transaction') 6 | 7 | function createVote(keyList, secret, secondSecret) { 8 | return transaction.createTransactionEx({ 9 | type: 11, 10 | fee: 0.1 * 1e8, 11 | args: keyList, 12 | secret: secret, 13 | secondSecret: secondSecret 14 | }) 15 | } 16 | 17 | function deleteVote(keyList, secret, secondSecret) { 18 | return transaction.createTransactionEx({ 19 | type: 12, 20 | fee: 0.1 * 1e8, 21 | args: keyList, 22 | secret: secret, 23 | secondSecret: secondSecret 24 | }) 25 | } 26 | 27 | module.exports = { 28 | createVote: createVote, 29 | deleteVote: deleteVote 30 | } 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asch-js", 3 | "version": "1.4.2", 4 | "description": "asch javascript library", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "mocha test", 11 | "build": "browserify build.js -o browserify-asch.js && uglifyjs browserify-asch.js > browserify-asch-min.js" 12 | }, 13 | "keywords": [ 14 | "asch", 15 | "js", 16 | "library" 17 | ], 18 | "author": "sqf1225@foxmail.com", 19 | "license": "ISC", 20 | "dependencies": { 21 | "JSONStream": "=1.3.1", 22 | "browserify-bignum": "=1.3.0-2", 23 | "buffer": "=4.7.0", 24 | "bytebuffer": "=5.0.1", 25 | "fast-sha256": "=1.0.0", 26 | "ripemd160": "=2.0.1", 27 | "through2": "=2.0.3", 28 | "tweetnacl": "=1.0.0" 29 | }, 30 | "devDependencies": { 31 | "browserify": "^13.1.0", 32 | "mocha": "^3.4.2", 33 | "should": "^9.0.2", 34 | "uglify-es": "github:mishoo/UglifyJS2#harmony" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/transactions/signature.js: -------------------------------------------------------------------------------- 1 | var crypto = require("./crypto.js") 2 | var constants = require("../constants.js") 3 | var slots = require("../time/slots.js") 4 | var options = require('../options') 5 | 6 | function newSignature(secondSecret) { 7 | var keys = crypto.getKeys(secondSecret); 8 | 9 | var signature = { 10 | publicKey: keys.publicKey 11 | }; 12 | 13 | return signature; 14 | } 15 | 16 | function createSignature(secret, secondSecret) { 17 | var keys = crypto.getKeys(secret); 18 | 19 | var signature = newSignature(secondSecret); 20 | var transaction = { 21 | type: 1, 22 | amount: 0, 23 | fee: constants.fees.secondsignature, 24 | recipientId: null, 25 | senderPublicKey: keys.publicKey, 26 | timestamp: slots.getTime() - options.get('clientDriftSeconds'), 27 | asset: { 28 | signature: signature 29 | } 30 | }; 31 | 32 | crypto.sign(transaction, keys); 33 | transaction.id = crypto.getId(transaction); 34 | 35 | return transaction; 36 | } 37 | 38 | module.exports = { 39 | createSignature: createSignature 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/AschPlatform/asch-js.png?branch=master)](https://travis-ci.org/AschPlatform/asch-js) 2 | [![Author](https://img.shields.io/badge/author-@AschPlatform-blue.svg?style=flat)](http://github.com/AschPlatform) 3 | [![License](https://img.shields.io/badge/license-MIT-yellow.svg?style=flat)](http://AschPlatform.mit-license.org) 4 | [![NpmDownload Status](http://img.shields.io/npm/dm/asch-js.svg)](https://www.npmjs.org/package/asch-js) 5 | [![NPM Version](https://img.shields.io/npm/v/asch-js.svg?style=flat)](https://www.npmjs.org/package/asch-js) 6 | - - - 7 | 8 | # Asch Javascript Library 9 | 10 | ## Install 11 | 12 | ``` 13 | npm install asch-js 14 | ``` 15 | 16 | ## Import 17 | 18 | CommonJS 19 | 20 | ``` 21 | var AschJS = require('asch-js'); 22 | ``` 23 | 24 | Front end 25 | 26 | ``` 27 | 28 | # or 29 | 30 | 31 | console.log(window.AschJS) 32 | ``` 33 | 34 | 35 | 36 | ## Usage 37 | 38 | Please reference the [asch http interface documents](https://github.com/AschPlatform/asch/blob/master/docs/asch_http_interface.md) 39 | -------------------------------------------------------------------------------- /lib/address.js: -------------------------------------------------------------------------------- 1 | var sha256 = require('fast-sha256') 2 | var RIPEMD160 = require('ripemd160') 3 | var base58check = require('./base58check') 4 | 5 | const NORMAL_PREFIX = 'A' // A 6 | 7 | module.exports = { 8 | isAddress: function (address) { 9 | if (typeof address !== 'string') { 10 | return false 11 | } 12 | if (!/^[0-9]{1,20}$/g.test(address)) { 13 | if (!base58check.decodeUnsafe(address.slice(1))) { 14 | return false 15 | } 16 | if (['A'].indexOf(address[0]) == -1) { 17 | return false 18 | } 19 | } 20 | return true 21 | }, 22 | 23 | isBase58CheckAddress: function (address) { 24 | if (typeof address !== 'string') { 25 | return false 26 | } 27 | if (!base58check.decodeUnsafe(address.slice(1))) { 28 | return false 29 | } 30 | if (['A'].indexOf(address[0]) == -1) { 31 | return false 32 | } 33 | return true 34 | }, 35 | 36 | generateBase58CheckAddress: function (publicKey) { 37 | if (typeof publicKey === 'string') { 38 | publicKey = Buffer.from(publicKey, 'hex') 39 | } 40 | var h1 = sha256.hash(publicKey) 41 | var h2 = new RIPEMD160().update(Buffer.from(h1)).digest() 42 | return NORMAL_PREFIX + base58check.encode(h2) 43 | }, 44 | } -------------------------------------------------------------------------------- /lib/transactions/multisignature.js: -------------------------------------------------------------------------------- 1 | var crypto = require("./crypto.js") 2 | var constants = require("../constants.js") 3 | var slots = require("../time/slots.js") 4 | var options = require('../options') 5 | 6 | function signTransaction(trs, secret) { 7 | var keys = crypto.getKeys(secret); 8 | var signature = crypto.sign(trs, keys); 9 | 10 | return signature; 11 | } 12 | 13 | function createMultisignature(keysgroup, lifetime, min, secret, secondSecret) { 14 | var keys = crypto.getKeys(secret); 15 | 16 | var transaction = { 17 | type: 4, 18 | amount: 0, 19 | fee: constants.fees.multisignature, 20 | recipientId: null, 21 | senderPublicKey: keys.publicKey, 22 | timestamp: slots.getTime() - options.get('clientDriftSeconds'), 23 | asset: { 24 | multisignature: { 25 | min: min, 26 | lifetime: lifetime, 27 | keysgroup: keysgroup 28 | } 29 | } 30 | }; 31 | 32 | crypto.sign(transaction, keys); 33 | 34 | if (secondSecret) { 35 | var secondKeys = crypto.getKeys(secondSecret); 36 | crypto.secondSign(transaction, secondKeys); 37 | } 38 | 39 | transaction.id = crypto.getId(transaction); 40 | return transaction; 41 | } 42 | 43 | module.exports = { 44 | createMultisignature : createMultisignature, 45 | signTransaction: signTransaction 46 | } 47 | -------------------------------------------------------------------------------- /lib/transactions/transfer.js: -------------------------------------------------------------------------------- 1 | var crypto = require("./crypto.js") 2 | var constants = require("../constants.js") 3 | var slots = require("../time/slots.js") 4 | var options = require('../options') 5 | var transaction = require('./transaction') 6 | 7 | function createInTransfer(dappName, currency, amount, secret, secondSecret) { 8 | return transaction.createTransactionEx({ 9 | type: 204, 10 | fee: 0.1 * 1e8, 11 | args: [dappName, currency, amount], 12 | secret, 13 | secondSecret: secondSecret 14 | }) 15 | } 16 | 17 | function createOutTransfer(address, chain, recipient, currency, amount, wid, seq) { 18 | var transaction = { 19 | type: 205, 20 | fee: 10000000, 21 | senderId: address, 22 | timestamp: slots.getTime() - options.get('clientDriftSeconds'), 23 | args: [ 24 | chain, 25 | recipient, 26 | currency, 27 | amount, 28 | wid, 29 | seq 30 | ] 31 | }; 32 | return transaction; 33 | } 34 | 35 | function signOutTransfer(transaction, secret) { 36 | var keys = crypto.getKeys(secret); 37 | var signature = crypto.sign(transaction, keys); 38 | 39 | return keys.publicKey + signature; 40 | } 41 | 42 | module.exports = { 43 | createInTransfer: createInTransfer, 44 | createOutTransfer: createOutTransfer, 45 | signOutTransfer: signOutTransfer 46 | } -------------------------------------------------------------------------------- /lib/base58check/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var sha256 = require('fast-sha256') 4 | var base58 = require('./bs58.js') 5 | 6 | // SHA256(SHA256(buffer)) 7 | function sha256x2(buffer) { 8 | return Buffer.from(sha256.hash(sha256.hash(buffer))) 9 | } 10 | 11 | // Encode a buffer as a base58-check encoded string 12 | function encode(payload) { 13 | var checksum = sha256x2(payload) 14 | return base58.encode(Buffer.concat([ 15 | payload, 16 | checksum 17 | ], payload.length + 4)) 18 | } 19 | 20 | function decodeRaw(buffer) { 21 | var payload = buffer.slice(0, -4) 22 | var checksum = buffer.slice(-4) 23 | var newChecksum = sha256x2(payload) 24 | 25 | if (checksum[0] ^ newChecksum[0] | 26 | checksum[1] ^ newChecksum[1] | 27 | checksum[2] ^ newChecksum[2] | 28 | checksum[3] ^ newChecksum[3]) return 29 | 30 | return payload 31 | } 32 | 33 | // Decode a base58-check encoded string to a buffer, no result if checksum is wrong 34 | function decodeUnsafe(string) { 35 | var buffer = base58.decodeUnsafe(string) 36 | if (!buffer) return 37 | 38 | return decodeRaw(buffer) 39 | } 40 | 41 | function decode(string) { 42 | var buffer = base58.decode(string) 43 | var payload = decodeRaw(buffer) 44 | if (!payload) throw new Error('Invalid checksum') 45 | return payload 46 | } 47 | 48 | module.exports = { 49 | encode: encode, 50 | decode: decode, 51 | decodeUnsafe: decodeUnsafe 52 | } 53 | -------------------------------------------------------------------------------- /lib/time/slots.js: -------------------------------------------------------------------------------- 1 | function getEpochTime(time) { 2 | if (time === undefined) { 3 | time = (new Date()).getTime(); 4 | } 5 | var d = beginEpochTime(); 6 | var t = d.getTime(); 7 | return Math.floor((time - t) / 1000); 8 | } 9 | 10 | function beginEpochTime() { 11 | var d = new Date(Date.UTC(2016, 5, 27, 20, 0, 0, 0)) 12 | 13 | return d; 14 | } 15 | 16 | var interval = 10, 17 | delegates = 101; 18 | 19 | function getTime(time) { 20 | return getEpochTime(time); 21 | } 22 | 23 | function getRealTime(epochTime) { 24 | if (epochTime === undefined) { 25 | epochTime = getTime() 26 | } 27 | var d = beginEpochTime(); 28 | var t = Math.floor(d.getTime() / 1000) * 1000; 29 | return t + epochTime * 1000; 30 | } 31 | 32 | function getSlotNumber(epochTime) { 33 | if (epochTime === undefined) { 34 | epochTime = getTime() 35 | } 36 | 37 | return Math.floor(epochTime / interval); 38 | } 39 | 40 | function getSlotTime(slot) { 41 | return slot * interval; 42 | } 43 | 44 | function getNextSlot() { 45 | var slot = getSlotNumber(); 46 | 47 | return slot + 1; 48 | } 49 | 50 | function getLastSlot(nextSlot) { 51 | return nextSlot + delegates; 52 | } 53 | 54 | module.exports = { 55 | interval: interval, 56 | delegates: delegates, 57 | getTime: getTime, 58 | getRealTime: getRealTime, 59 | getSlotNumber: getSlotNumber, 60 | getSlotTime: getSlotTime, 61 | getNextSlot: getNextSlot, 62 | getLastSlot: getLastSlot, 63 | beginEpochTime: beginEpochTime 64 | } 65 | -------------------------------------------------------------------------------- /lib/transactions/uia.js: -------------------------------------------------------------------------------- 1 | var ByteBuffer = require('bytebuffer') 2 | var crypto = require("./crypto.js") 3 | var constants = require("../constants.js") 4 | var slots = require("../time/slots.js") 5 | var options = require('../options') 6 | var transaction = require('./transaction') 7 | 8 | function createIssuer (name, desc, secret, secondSecret) { 9 | return transaction.createTransactionEx({ 10 | type: 100, 11 | fee: 100 * 1e8, 12 | args: [ name, desc ], 13 | secret: secret, 14 | secondSecret: secondSecret 15 | }) 16 | } 17 | 18 | function createAsset(name, desc, maximum, precision, secret, secondSecret) { 19 | return transaction.createTransactionEx({ 20 | type: 101, 21 | fee: 500 * 1e8, 22 | args: [ name, desc, maximum, precision ], 23 | secret: secret, 24 | secondSecret: secondSecret 25 | }) 26 | } 27 | 28 | 29 | function createIssue(currency, amount, secret, secondSecret) { 30 | return transaction.createTransactionEx({ 31 | type: 102, 32 | fee: 0.1 * 1e8, 33 | args: [ currency, amount ], 34 | secret: secret, 35 | secondSecret: secondSecret 36 | }) 37 | } 38 | 39 | function createTransfer(currency, amount, recipientId, message, secret, secondSecret) { 40 | return transaction.createTransactionEx({ 41 | type: 103, 42 | fee: 0.1 * 1e8, 43 | args: [currency, amount, recipientId], 44 | secret, 45 | secondSecret, 46 | message 47 | }) 48 | } 49 | 50 | module.exports = { 51 | createIssuer: createIssuer, 52 | createAsset: createAsset, 53 | createIssue: createIssue, 54 | createTransfer: createTransfer 55 | } 56 | -------------------------------------------------------------------------------- /lib/transactions/dapp.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | var ByteBuffer = require('bytebuffer') 3 | var crypto = require("./crypto.js") 4 | var constants = require("../constants.js") 5 | var slots = require("../time/slots.js") 6 | var globalOptions = require('../options.js') 7 | var transaction = require('./transaction.js') 8 | 9 | function createDApp(options, secret, secondSecret) { 10 | return transaction.createTransactionEx({ 11 | type: 200, 12 | fee: 100 * 1e8, 13 | secret: secret, 14 | secondSecret: secondSecret, 15 | args: [ 16 | options.name, 17 | options.desc, 18 | options.link, 19 | options.icon, 20 | options.delegates, 21 | options.unlockDelegates 22 | ] 23 | }) 24 | } 25 | 26 | function getDAppTransactionBytes(trs, skipSignature) { 27 | var bb = new ByteBuffer(1, true); 28 | bb.writeInt(trs.timestamp); 29 | bb.writeString(trs.fee) 30 | 31 | var senderPublicKeyBuffer = new Buffer(trs.senderPublicKey, 'hex'); 32 | for (var i = 0; i < senderPublicKeyBuffer.length; i++) { 33 | bb.writeByte(senderPublicKeyBuffer[i]); 34 | } 35 | 36 | bb.writeInt(trs.type) 37 | 38 | assert(Array.isArray(trs.args)) 39 | bb.writeString(JSON.stringify(trs.args)) 40 | 41 | if (!skipSignature && trs.signature) { 42 | var signatureBuffer = new Buffer(trs.signature, 'hex'); 43 | for (var i = 0; i < signatureBuffer.length; i++) { 44 | bb.writeByte(signatureBuffer[i]); 45 | } 46 | } 47 | bb.flip(); 48 | return bb.toBuffer() 49 | } 50 | 51 | function createInnerTransaction(options, secret) { 52 | var keys = crypto.getKeys(secret) 53 | var args = options.args 54 | if (typeof args === 'string') args = JSON.parse(args) 55 | var trs = { 56 | fee: options.fee, 57 | timestamp: slots.getTime() - globalOptions.get('clientDriftSeconds'), 58 | senderPublicKey: keys.publicKey, 59 | type: options.type, 60 | args: args 61 | } 62 | trs.signature = crypto.signBytes(getDAppTransactionBytes(trs), keys) 63 | return trs 64 | } 65 | 66 | module.exports = { 67 | createDApp: createDApp, 68 | createInnerTransaction: createInnerTransaction 69 | } 70 | -------------------------------------------------------------------------------- /lib/time/format.js: -------------------------------------------------------------------------------- 1 | var slots = require('./slots.js'); 2 | 3 | function timeAgo(time) { 4 | var d = slots.beginEpochTime(); 5 | var t = parseInt(d.getTime() / 1000); 6 | 7 | time = new Date((time + t) * 1000); 8 | 9 | var currentTime = new Date().getTime(); 10 | var diffTime = (currentTime - time.getTime()) / 1000; 11 | 12 | if (diffTime < 60) { 13 | return Math.floor(diffTime) + ' sec ago'; 14 | } 15 | if (Math.floor(diffTime / 60) <= 1) { 16 | return Math.floor(diffTime / 60) + ' min ago'; 17 | } 18 | if ((diffTime / 60) < 60) { 19 | return Math.floor(diffTime / 60) + ' mins ago'; 20 | } 21 | if (Math.floor(diffTime / 60 / 60) <= 1) { 22 | return Math.floor(diffTime / 60 / 60) + ' hour ago'; 23 | } 24 | if ((diffTime / 60 / 60) < 24) { 25 | return Math.floor(diffTime / 60 / 60) + ' hours ago'; 26 | } 27 | if (Math.floor(diffTime / 60 / 60 / 24) <= 1) { 28 | return Math.floor(diffTime / 60 / 60 / 24) + ' day ago'; 29 | } 30 | if ((diffTime / 60 / 60 / 24) < 30) { 31 | return Math.floor(diffTime / 60 / 60 / 24) + ' days ago'; 32 | } 33 | if (Math.floor(diffTime / 60 / 60 / 24 / 30) <= 1) { 34 | return Math.floor(diffTime / 60 / 60 / 24 / 30) + ' month ago'; 35 | } 36 | if ((diffTime / 60 / 60 / 24 / 30) < 12) { 37 | return Math.floor(diffTime / 60 / 60 / 24 / 30) + ' months ago'; 38 | } 39 | if (Math.floor((diffTime / 60 / 60 / 24 / 30 / 12)) <= 1) { 40 | return Math.floor(diffTime / 60 / 60 / 24 / 30 / 12) + ' year ago'; 41 | } 42 | 43 | return Math.floor(diffTime / 60 / 60 / 24 / 30 / 12) + ' years ago'; 44 | } 45 | 46 | function fullTimestamp(time) { 47 | var d = slots.beginEpochTime(); 48 | var t = parseInt(d.getTime() / 1000); 49 | 50 | d = new Date((time + t) * 1000); 51 | var month = d.getMonth() + 1; 52 | 53 | if (month < 10) { 54 | month = "0" + month; 55 | } 56 | 57 | var day = d.getDate(); 58 | 59 | if (day < 10) { 60 | day = "0" + day; 61 | } 62 | 63 | var h = d.getHours(); 64 | var m = d.getMinutes(); 65 | var s = d.getSeconds(); 66 | 67 | if (h < 10) { 68 | h = "0" + h; 69 | } 70 | 71 | if (m < 10) { 72 | m = "0" + m; 73 | } 74 | 75 | if (s < 10) { 76 | s = "0" + s; 77 | } 78 | 79 | return d.getFullYear() + "/" + month + "/" + day + " " + h + ":" + m + ":" + s; 80 | } 81 | 82 | module.exports = { 83 | timeAgo: timeAgo, 84 | fullTimestamp: fullTimestamp 85 | } -------------------------------------------------------------------------------- /lib/base58check/base-x.js: -------------------------------------------------------------------------------- 1 | // base-x encoding 2 | // Forked from https://github.com/cryptocoinjs/bs58 3 | // Originally written by Mike Hearn for BitcoinJ 4 | // Copyright (c) 2011 Google Inc 5 | // Ported to JavaScript by Stefan Thomas 6 | // Merged Buffer refactorings from base58-native by Stephen Pair 7 | // Copyright (c) 2013 BitPay Inc 8 | 9 | module.exports = function base (ALPHABET) { 10 | var ALPHABET_MAP = {} 11 | var BASE = ALPHABET.length 12 | var LEADER = ALPHABET.charAt(0) 13 | 14 | // pre-compute lookup table 15 | for (var z = 0; z < ALPHABET.length; z++) { 16 | var x = ALPHABET.charAt(z) 17 | 18 | if (ALPHABET_MAP[x] !== undefined) throw new TypeError(x + ' is ambiguous') 19 | ALPHABET_MAP[x] = z 20 | } 21 | 22 | function encode (source) { 23 | if (source.length === 0) return '' 24 | 25 | var digits = [0] 26 | for (var i = 0; i < source.length; ++i) { 27 | for (var j = 0, carry = source[i]; j < digits.length; ++j) { 28 | carry += digits[j] << 8 29 | digits[j] = carry % BASE 30 | carry = (carry / BASE) | 0 31 | } 32 | 33 | while (carry > 0) { 34 | digits.push(carry % BASE) 35 | carry = (carry / BASE) | 0 36 | } 37 | } 38 | 39 | var string = '' 40 | 41 | // deal with leading zeros 42 | for (var k = 0; source[k] === 0 && k < source.length - 1; ++k) string += ALPHABET[0] 43 | // convert digits to a string 44 | for (var q = digits.length - 1; q >= 0; --q) string += ALPHABET[digits[q]] 45 | 46 | return string 47 | } 48 | 49 | function decodeUnsafe (string) { 50 | if (string.length === 0) return Buffer.allocUnsafe(0) 51 | 52 | var bytes = [0] 53 | for (var i = 0; i < string.length; i++) { 54 | var value = ALPHABET_MAP[string[i]] 55 | if (value === undefined) return 56 | 57 | for (var j = 0, carry = value; j < bytes.length; ++j) { 58 | carry += bytes[j] * BASE 59 | bytes[j] = carry & 0xff 60 | carry >>= 8 61 | } 62 | 63 | while (carry > 0) { 64 | bytes.push(carry & 0xff) 65 | carry >>= 8 66 | } 67 | } 68 | 69 | // deal with leading zeros 70 | for (var k = 0; string[k] === LEADER && k < string.length - 1; ++k) { 71 | bytes.push(0) 72 | } 73 | 74 | return Buffer.from(bytes.reverse()) 75 | } 76 | 77 | function decode (string) { 78 | var buffer = decodeUnsafe(string) 79 | if (buffer) return buffer 80 | 81 | throw new Error('Non-base' + BASE + ' character') 82 | } 83 | 84 | return { 85 | encode: encode, 86 | decodeUnsafe: decodeUnsafe, 87 | decode: decode 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /lib/transactions/transaction.js: -------------------------------------------------------------------------------- 1 | var crypto = require("./crypto.js") 2 | var constants = require("../constants.js") 3 | var slots = require("../time/slots.js") 4 | var options = require('../options') 5 | 6 | function calculateFee(amount) { 7 | var min = constants.fees.send; 8 | var fee = parseFloat((amount * 0.0001).toFixed(0)); 9 | return fee < min ? min : fee; 10 | } 11 | 12 | function createTransaction(recipientId, amount, message, secret, secondSecret) { 13 | return createTransactionEx({ 14 | type: 1, 15 | fee: 0.1 * 1e8, 16 | args: [amount, recipientId], 17 | secret, 18 | secondSecret: secondSecret, 19 | message 20 | }) 21 | } 22 | 23 | function createLock(height, amount, secret, secondSecret) { 24 | return createTransactionEx({ 25 | type: 4, 26 | fee: 0.1 * 1e8, 27 | args: [height, amount], 28 | secret: secret, 29 | secondSecret: secondSecret 30 | }) 31 | } 32 | 33 | function unlock(secret, secondSecret) { 34 | return createTransactionEx({ 35 | type: 5, 36 | fee: 0, 37 | args: [], 38 | secret: secret, 39 | secondSecret: secondSecret 40 | }) 41 | } 42 | 43 | function createTransactionEx(params) { 44 | if (!params.secret) throw new Error('Secret needed') 45 | let keys = crypto.getKeys(params.secret) 46 | let transaction = { 47 | type: params.type, 48 | timestamp: slots.getTime() - options.get('clientDriftSeconds'), 49 | fee: params.fee, 50 | message: params.message, 51 | args: params.args, 52 | senderPublicKey: keys.publicKey, 53 | senderId: crypto.getAddress(keys.publicKey), 54 | signatures: [] 55 | } 56 | transaction.signatures.push(crypto.sign(transaction, keys)) 57 | if (params.secondSecret) { 58 | let secondKeys = crypto.getKeys(params.secondSecret); 59 | transaction.secondSignature = crypto.secondSign(transaction, secondKeys); 60 | } 61 | transaction.id = crypto.getId(transaction) 62 | return transaction 63 | } 64 | 65 | function createMultiSigTransaction(params) { 66 | var transaction = { 67 | type: params.type, 68 | fee: params.fee, 69 | senderId: params.senderId, 70 | requestId: params.requestId, 71 | mode: params.mode, 72 | timestamp: slots.getTime() - options.get('clientDriftSeconds'), 73 | args: params.args 74 | }; 75 | return transaction; 76 | } 77 | 78 | function signMultiSigTransaction(transaction, secret) { 79 | var keys = crypto.getKeys(secret); 80 | var signature = crypto.sign(transaction, keys); 81 | 82 | return keys.publicKey + signature; 83 | } 84 | 85 | module.exports = { 86 | createTransaction: createTransaction, 87 | createTransactionEx: createTransactionEx, 88 | calculateFee: calculateFee, 89 | createLock: createLock, 90 | unlock: unlock, 91 | createMultiSigTransaction: createMultiSigTransaction, 92 | signMultiSigTransaction: signMultiSigTransaction 93 | } 94 | -------------------------------------------------------------------------------- /lib/transactions/crypto.js: -------------------------------------------------------------------------------- 1 | var sha256 = require("fast-sha256"); 2 | var addressHelper = require('../address.js') 3 | 4 | if (typeof Buffer === "undefined") { 5 | Buffer = require("buffer/").Buffer; 6 | } 7 | 8 | var ByteBuffer = require("bytebuffer"); 9 | var bignum = require("browserify-bignum"); 10 | var nacl = require('tweetnacl') 11 | 12 | var fixedPoint = Math.pow(10, 8); 13 | 14 | function getSignatureBytes(signature) { 15 | var bb = new ByteBuffer(32, true); 16 | var publicKeyBuffer = new Buffer(signature.publicKey, "hex"); 17 | 18 | for (var i = 0; i < publicKeyBuffer.length; i++) { 19 | bb.writeByte(publicKeyBuffer[i]); 20 | } 21 | 22 | bb.flip(); 23 | return new Uint8Array(bb.toArrayBuffer()); 24 | } 25 | 26 | function toLocalBuffer(buf) { 27 | if (typeof window !== 'undefined') { 28 | return new Uint8Array(buf.toArrayBuffer()) 29 | } else { 30 | return buf.toBuffer() 31 | } 32 | } 33 | 34 | function sha256Bytes(data) { 35 | return sha256.hash(data) 36 | } 37 | 38 | function sha256Hex(data) { 39 | return Buffer.from(sha256.hash(data)).toString('hex') 40 | } 41 | 42 | function getDAppBytes(dapp) { 43 | try { 44 | var buf = new Buffer([]); 45 | var nameBuf = new Buffer(dapp.name, "utf8"); 46 | buf = Buffer.concat([buf, nameBuf]); 47 | 48 | if (dapp.description) { 49 | var descriptionBuf = new Buffer(dapp.description, "utf8"); 50 | buf = Buffer.concat([buf, descriptionBuf]); 51 | } 52 | 53 | if (dapp.tags) { 54 | var tagsBuf = new Buffer(dapp.tags, "utf8"); 55 | buf = Buffer.concat([buf, tagsBuf]); 56 | } 57 | 58 | if (dapp.link) { 59 | buf = Buffer.concat([buf, new Buffer(dapp.link, "utf8")]); 60 | } 61 | 62 | if (dapp.icon) { 63 | buf = Buffer.concat([buf, new Buffer(dapp.icon, "utf8")]); 64 | } 65 | 66 | var bb = new ByteBuffer(1, true); 67 | bb.writeInt(dapp.type); 68 | bb.writeInt(dapp.category); 69 | bb.writeString(dapp.delegates.join(',')); 70 | bb.writeInt(dapp.unlockDelegates); 71 | bb.flip(); 72 | 73 | buf = Buffer.concat([buf, bb.toBuffer()]); 74 | } catch (e) { 75 | throw Error(e.toString()); 76 | } 77 | 78 | return buf; 79 | } 80 | 81 | function getInTransferBytes(inTransfer) { 82 | try { 83 | var buf = new Buffer([]); 84 | var dappId = new Buffer(inTransfer.dappId, "utf8"); 85 | var currency = new Buffer(inTransfer.currency, "utf8") 86 | buf = Buffer.concat([buf, dappId, currency]); 87 | if (inTransfer.currency !== 'XAS') { 88 | var amount = new Buffer(inTransfer.amount, "utf8") 89 | buf = Buffer.concat([buf, amount]) 90 | } 91 | } catch (e) { 92 | throw Error(e.toString()); 93 | } 94 | 95 | return buf; 96 | } 97 | 98 | function getOutTransferBytes(outTransfer) { 99 | try { 100 | var buf = new Buffer([]); 101 | var dappIdBuf = new Buffer(outTransfer.dappId, 'utf8'); 102 | var transactionIdBuff = new Buffer(outTransfer.transactionId, 'utf8'); 103 | var currencyBuff = new Buffer(outTransfer.currency, 'utf8') 104 | var amountBuff = new Buffer(outTransfer.amount, 'utf8') 105 | buf = Buffer.concat([buf, dappIdBuf, transactionIdBuff, currencyBuff, amountBuff]); 106 | } catch (e) { 107 | throw Error(e.toString()); 108 | } 109 | 110 | return buf; 111 | } 112 | 113 | function getBytes(trs, skipSignature, skipSecondSignature) { 114 | var bb = new ByteBuffer(1, true); 115 | bb.writeInt(trs.type); 116 | bb.writeInt(trs.timestamp); 117 | bb.writeLong(trs.fee); 118 | bb.writeString(trs.senderId) 119 | if (trs.requestorId) { 120 | bb.writeString(trs.requestorId) 121 | } 122 | if (trs.mode) { 123 | bb.writeInt(trs.mode) 124 | } 125 | 126 | if (trs.message) bb.writeString(trs.message); 127 | if (trs.args) { 128 | let args 129 | if (typeof trs.args === 'string') { 130 | args = trs.args 131 | } else if (Array.isArray(trs.args)) { 132 | args = JSON.stringify(trs.args) 133 | } 134 | bb.writeString(args) 135 | } 136 | 137 | if (!skipSignature && trs.signatures) { 138 | for (let signature of trs.signatures) { 139 | var signatureBuffer = new Buffer(signature, 'hex'); 140 | for (var i = 0; i < signatureBuffer.length; i++) { 141 | bb.writeByte(signatureBuffer[i]); 142 | } 143 | } 144 | } 145 | 146 | if (!skipSecondSignature && trs.secondSignature) { 147 | var signSignatureBuffer = new Buffer(trs.secondSignature, 'hex'); 148 | for (var i = 0; i < signSignatureBuffer.length; i++) { 149 | bb.writeByte(signSignatureBuffer[i]); 150 | } 151 | } 152 | 153 | bb.flip(); 154 | return toLocalBuffer(bb); 155 | } 156 | 157 | function getId(transaction) { 158 | return sha256Hex(getBytes(transaction)) 159 | } 160 | function getHash(transaction, skipSignature, skipSecondSignature) { 161 | return sha256Bytes(getBytes(transaction, skipSignature, skipSecondSignature)) 162 | } 163 | 164 | function getFee(transaction) { 165 | switch (transaction.type) { 166 | case 0: // Normal 167 | return 0.1 * fixedPoint; 168 | break; 169 | 170 | case 1: // Signature 171 | return 100 * fixedPoint; 172 | break; 173 | 174 | case 2: // Delegate 175 | return 10000 * fixedPoint; 176 | break; 177 | 178 | case 3: // Vote 179 | return 1 * fixedPoint; 180 | break; 181 | } 182 | } 183 | 184 | function sign(transaction, keys) { 185 | var hash = getHash(transaction, true, true); 186 | var signature = nacl.sign.detached(hash, keys.keypair.secretKey); 187 | 188 | return new Buffer(signature).toString("hex"); 189 | } 190 | 191 | function secondSign(transaction, keys) { 192 | var hash = getHash(transaction, true, true); 193 | var signature = nacl.sign.detached(hash, keys.keypair.secretKey); 194 | return new Buffer(signature).toString("hex") 195 | } 196 | 197 | function signBytes(bytes, keys) { 198 | var hash = sha256Bytes(new Buffer(bytes, 'hex')) 199 | var signature = nacl.sign.detached(hash, keys.keypair.secretKey); 200 | return new Buffer(signature).toString("hex"); 201 | } 202 | 203 | function verify(transaction) { 204 | var remove = 64; 205 | 206 | if (transaction.signSignature) { 207 | remove = 128; 208 | } 209 | 210 | var bytes = getBytes(transaction); 211 | var data2 = new Buffer(bytes.length - remove); 212 | 213 | for (var i = 0; i < data2.length; i++) { 214 | data2[i] = bytes[i]; 215 | } 216 | 217 | var hash = sha256Bytes(data2) 218 | 219 | var signatureBuffer = new Buffer(transaction.signature, "hex"); 220 | var senderPublicKeyBuffer = new Buffer(transaction.senderPublicKey, "hex"); 221 | var res = nacl.sign.detached.verify(hash, signatureBuffer, senderPublicKeyBuffer); 222 | 223 | return res; 224 | } 225 | 226 | function verifySecondSignature(transaction, publicKey) { 227 | var bytes = getBytes(transaction); 228 | var data2 = new Buffer(bytes.length - 64); 229 | 230 | for (var i = 0; i < data2.length; i++) { 231 | data2[i] = bytes[i]; 232 | } 233 | 234 | var hash = sha256Bytes(data2) 235 | 236 | var signSignatureBuffer = new Buffer(transaction.signSignature, "hex"); 237 | var publicKeyBuffer = new Buffer(publicKey, "hex"); 238 | var res = nacl.sign.detached.verify(hash, signSignatureBuffer, publicKeyBuffer); 239 | 240 | return res; 241 | } 242 | 243 | function verifyBytes(bytes, signature, publicKey) { 244 | var hash = sha256Bytes(new Buffer(bytes, 'hex')) 245 | var signatureBuffer = new Buffer(signature, "hex"); 246 | var publicKeyBuffer = new Buffer(publicKey, "hex"); 247 | var res = nacl.sign.detached.verify(hash, signatureBuffer, publicKeyBuffer); 248 | return res 249 | } 250 | 251 | function getKeys(secret) { 252 | var hash = sha256Bytes(new Buffer(secret)) 253 | var keypair = nacl.sign.keyPair.fromSeed(hash); 254 | 255 | return { 256 | keypair, 257 | publicKey: new Buffer(keypair.publicKey).toString("hex"), 258 | privateKey: new Buffer(keypair.secretKey).toString("hex") 259 | } 260 | } 261 | 262 | function getAddress(publicKey) { 263 | return addressHelper.generateBase58CheckAddress(publicKey) 264 | } 265 | 266 | module.exports = { 267 | getBytes: getBytes, 268 | getHash: getHash, 269 | getId: getId, 270 | getFee: getFee, 271 | sign: sign, 272 | secondSign: secondSign, 273 | getKeys: getKeys, 274 | getAddress: getAddress, 275 | verify: verify, 276 | verifySecondSignature: verifySecondSignature, 277 | fixedPoint: fixedPoint, 278 | signBytes: signBytes, 279 | toLocalBuffer: toLocalBuffer, 280 | verifyBytes: verifyBytes, 281 | isAddress: addressHelper.isAddress, 282 | isBase58CheckAddress: addressHelper.isBase58CheckAddress 283 | } 284 | -------------------------------------------------------------------------------- /test/tests.js: -------------------------------------------------------------------------------- 1 | var Buffer = require("buffer/").Buffer; 2 | var crypto_lib = require("crypto-browserify"); 3 | var should = require("should"); 4 | var asch = require("../index.js"); 5 | 6 | describe("Asch JS", function () { 7 | 8 | it("should be ok", function () { 9 | (asch).should.be.ok; 10 | }); 11 | 12 | it("should be object", function () { 13 | (asch).should.be.type("object"); 14 | }); 15 | 16 | it("should have properties", function () { 17 | var properties = ["transaction", "signature", "vote", "delegate", "dapp", "crypto"]; 18 | 19 | properties.forEach(function (property) { 20 | (asch).should.have.property(property); 21 | }); 22 | }); 23 | 24 | describe("crypto.js", function () { 25 | var crypto = asch.crypto; 26 | 27 | it("should be ok", function () { 28 | (crypto).should.be.ok; 29 | }); 30 | 31 | it("should be object", function () { 32 | (crypto).should.be.type("object"); 33 | }); 34 | 35 | it("should has properties", function () { 36 | var properties = ["getBytes", "getHash", "getId", "getFee", "sign", "secondSign", "getKeys", "getAddress", "verify", "verifySecondSignature", "fixedPoint"]; 37 | properties.forEach(function (property) { 38 | (crypto).should.have.property(property); 39 | }); 40 | }); 41 | 42 | describe("#getBytes", function () { 43 | var getBytes = crypto.getBytes; 44 | var bytes = null; 45 | 46 | it("should be ok", function () { 47 | (getBytes).should.be.ok; 48 | }); 49 | 50 | it("should be a function", function () { 51 | (getBytes).should.be.type("function"); 52 | }); 53 | 54 | it("should return Buffer of simply transaction and buffer most be 117 length", function () { 55 | var transaction = { 56 | type: 0, 57 | amount: 1000, 58 | recipientId: "58191285901858109", 59 | timestamp: 141738, 60 | asset: {}, 61 | senderPublicKey: "5d036a858ce89f844491762eb89e2bfbd50a4a0a0da658e4b2628b25b117ae09", 62 | signature: "618a54975212ead93df8c881655c625544bce8ed7ccdfe6f08a42eecfb1adebd051307be5014bb051617baf7815d50f62129e70918190361e5d4dd4796541b0a", 63 | id: "13987348420913138422" 64 | }; 65 | 66 | bytes = getBytes(transaction); 67 | (bytes).should.be.ok; 68 | (bytes).should.be.type("object"); 69 | (bytes.length).should.be.equal(117); 70 | }); 71 | 72 | it("should return Buffer of transaction with second signature and buffer most be 181 length", function () { 73 | var transaction = { 74 | type: 0, 75 | amount: 1000, 76 | recipientId: "58191285901858109", 77 | timestamp: 141738, 78 | asset: {}, 79 | senderPublicKey: "5d036a858ce89f844491762eb89e2bfbd50a4a0a0da658e4b2628b25b117ae09", 80 | signature: "618a54975212ead93df8c881655c625544bce8ed7ccdfe6f08a42eecfb1adebd051307be5014bb051617baf7815d50f62129e70918190361e5d4dd4796541b0a", 81 | signSignature: "618a54975212ead93df8c881655c625544bce8ed7ccdfe6f08a42eecfb1adebd051307be5014bb051617baf7815d50f62129e70918190361e5d4dd4796541b0a", 82 | id: "13987348420913138422" 83 | }; 84 | 85 | bytes = getBytes(transaction); 86 | (bytes).should.be.ok; 87 | (bytes).should.be.type("object"); 88 | (bytes.length).should.be.equal(181); 89 | }); 90 | }); 91 | 92 | describe("#getHash", function () { 93 | var getHash = crypto.getHash; 94 | 95 | it("should be ok", function () { 96 | (getHash).should.be.ok; 97 | }); 98 | 99 | it("should be a function", function () { 100 | (getHash).should.be.type("function"); 101 | }) 102 | 103 | it("should return Buffer and Buffer most be 32 bytes length", function () { 104 | var transaction = { 105 | type: 0, 106 | amount: 1000, 107 | recipientId: "58191285901858109", 108 | timestamp: 141738, 109 | asset: {}, 110 | senderPublicKey: "5d036a858ce89f844491762eb89e2bfbd50a4a0a0da658e4b2628b25b117ae09", 111 | signature: "618a54975212ead93df8c881655c625544bce8ed7ccdfe6f08a42eecfb1adebd051307be5014bb051617baf7815d50f62129e70918190361e5d4dd4796541b0a", 112 | id: "13987348420913138422" 113 | }; 114 | 115 | var result = getHash(transaction); 116 | (result).should.be.ok; 117 | (result).should.be.type("object"); 118 | (result.length).should.be.equal(32); 119 | }); 120 | }); 121 | 122 | describe("#getId", function () { 123 | var getId = crypto.getId; 124 | 125 | it("should be ok", function () { 126 | (getId).should.be.ok; 127 | }); 128 | 129 | it("should be a function", function () { 130 | (getId).should.be.type("function"); 131 | }); 132 | 133 | it("should return string id and be equal to 13987348420913138422", function () { 134 | var transaction = { 135 | type: 0, 136 | amount: 1000, 137 | recipientId: "58191285901858109", 138 | timestamp: 141738, 139 | asset: {}, 140 | senderPublicKey: "5d036a858ce89f844491762eb89e2bfbd50a4a0a0da658e4b2628b25b117ae09", 141 | signature: "618a54975212ead93df8c881655c625544bce8ed7ccdfe6f08a42eecfb1adebd051307be5014bb051617baf7815d50f62129e70918190361e5d4dd4796541b0a" 142 | }; 143 | 144 | var id = getId(transaction); 145 | (id).should.be.type("string").and.equal("f60a26da470b1dc233fd526ed7306c1d84836f9e2ecee82c9ec47319e0910474"); 146 | }); 147 | }); 148 | 149 | describe("#getFee", function () { 150 | var getFee = crypto.getFee; 151 | 152 | it("should be ok", function () { 153 | (getFee).should.be.ok; 154 | }) 155 | 156 | it("should be a function", function () { 157 | (getFee).should.be.type("function"); 158 | }); 159 | 160 | it("should return number", function () { 161 | var fee = getFee({ amount: 100000, type: 0 }); 162 | (fee).should.be.type("number"); 163 | (fee).should.be.not.NaN; 164 | }); 165 | 166 | it("should return 10000000", function () { 167 | var fee = getFee({ amount: 100000, type: 0 }); 168 | (fee).should.be.type("number").and.equal(10000000); 169 | }); 170 | 171 | it("should return 10000000000", function () { 172 | var fee = getFee({ type: 1 }); 173 | (fee).should.be.type("number").and.equal(10000000000); 174 | }); 175 | 176 | it("should be equal 1000000000000", function () { 177 | var fee = getFee({ type: 2 }); 178 | (fee).should.be.type("number").and.equal(1000000000000); 179 | }); 180 | 181 | it("should be equal 100000000", function () { 182 | var fee = getFee({ type: 3 }); 183 | (fee).should.be.type("number").and.equal(100000000); 184 | }); 185 | }); 186 | 187 | describe("fixedPoint", function () { 188 | var fixedPoint = crypto.fixedPoint; 189 | 190 | it("should be ok", function () { 191 | (fixedPoint).should.be.ok; 192 | }) 193 | 194 | it("should be number", function () { 195 | (fixedPoint).should.be.type("number").and.not.NaN; 196 | }); 197 | 198 | it("should be equal 100000000", function () { 199 | (fixedPoint).should.be.equal(100000000); 200 | }); 201 | }); 202 | 203 | describe("#sign", function () { 204 | var sign = crypto.sign; 205 | 206 | it("should be ok", function () { 207 | (sign).should.be.ok; 208 | }); 209 | 210 | it("should be a function", function () { 211 | (sign).should.be.type("function"); 212 | }); 213 | }); 214 | 215 | describe("#secondSign", function () { 216 | var secondSign = crypto.secondSign; 217 | 218 | it("should be ok", function () { 219 | (secondSign).should.be.ok; 220 | }); 221 | 222 | it("should be a function", function () { 223 | (secondSign).should.be.type("function"); 224 | }); 225 | }); 226 | 227 | describe("#getKeys", function () { 228 | var getKeys = crypto.getKeys; 229 | 230 | it("should be ok", function () { 231 | (getKeys).should.be.ok; 232 | }); 233 | 234 | it("should be a function", function () { 235 | (getKeys).should.be.type("function"); 236 | }); 237 | 238 | it("should return two keys in hex", function () { 239 | var keys = getKeys("secret"); 240 | 241 | (keys).should.be.ok; 242 | (keys).should.be.type("object"); 243 | (keys).should.have.property("publicKey"); 244 | (keys).should.have.property("privateKey"); 245 | (keys.publicKey).should.be.type("string").and.match(function () { 246 | try { 247 | new Buffer(keys.publicKey, "hex"); 248 | } catch (e) { 249 | return false; 250 | } 251 | 252 | return true; 253 | }); 254 | (keys.privateKey).should.be.type("string").and.match(function () { 255 | try { 256 | new Buffer(keys.privateKey, "hex"); 257 | } catch (e) { 258 | return false; 259 | } 260 | 261 | return true; 262 | }); 263 | }); 264 | }); 265 | 266 | describe("#getAddress", function () { 267 | var getAddress = crypto.getAddress; 268 | 269 | it("should be ok", function () { 270 | (getAddress).should.be.ok; 271 | }) 272 | 273 | it("should be a function", function () { 274 | (getAddress).should.be.type("function"); 275 | }); 276 | 277 | it("should generate address by publicKey", function () { 278 | var keys = crypto.getKeys("secret"); 279 | var address = getAddress(keys.publicKey); 280 | 281 | (address).should.be.ok; 282 | (address).should.be.type("string"); 283 | (address).should.be.equal("AFkctfgZFkaATGRhGbj72wzJqACvMyzQ1U"); 284 | }); 285 | }); 286 | 287 | describe("#verify", function () { 288 | var verify = crypto.verify; 289 | 290 | it("should be ok", function () { 291 | (verify).should.be.ok; 292 | }) 293 | 294 | it("should be function", function () { 295 | (verify).should.be.type("function"); 296 | }); 297 | }); 298 | 299 | describe("#verifySecondSignature", function () { 300 | var verifySecondSignature = crypto.verifySecondSignature; 301 | 302 | it("should be ok", function () { 303 | (verifySecondSignature).should.be.ok; 304 | }); 305 | 306 | it("should be function", function () { 307 | (verifySecondSignature).should.be.type("function"); 308 | }); 309 | }); 310 | }); 311 | 312 | describe("dapp.js", function () { 313 | var dapp = asch.dapp; 314 | 315 | it("should be object", function () { 316 | (dapp).should.be.type("object"); 317 | }); 318 | 319 | it("should have properties", function () { 320 | (dapp).should.have.property("createDApp"); 321 | }) 322 | 323 | describe("#createDApp", function () { 324 | var createDApp = dapp.createDApp; 325 | var trs = null; 326 | 327 | var options = { 328 | "name": "asch-dapp-cctime", 329 | "link": "https://github.com/AschPlatform/asch-dapp-cctime/archive/master.zip", 330 | "category": 1, 331 | "description": "Decentralized news channel", 332 | "tags": "asch,dapp,demo,cctime", 333 | "icon": "http://o7dyh3w0x.bkt.clouddn.com/hello.png", 334 | "type": 0, 335 | "delegates": [ 336 | "8b1c24a0b9ba9b9ccf5e35d0c848d582a2a22cca54d42de8ac7b2412e7dc63d4", 337 | "aa7dcc3afd151a549e826753b0547c90e61b022adb26938177904a73fc4fee36", 338 | "e29c75979ac834b871ce58dc52a6f604f8f565dea2b8925705883b8c001fe8ce", 339 | "55ad778a8ff0ce4c25cb7a45735c9e55cf1daca110cfddee30e789cb07c8c9f3", 340 | "982076258caab20f06feddc94b95ace89a2862f36fea73fa007916ab97e5946a" 341 | ], 342 | "unlockDelegates": 3 343 | } 344 | 345 | it("should be a function", function () { 346 | (createDApp).should.be.type("function"); 347 | }); 348 | 349 | it("should create dapp without second signature", function () { 350 | trs = createDApp(options, "secret", null); 351 | (trs).should.be.ok; 352 | }); 353 | 354 | it("should create delegate with second signature", function () { 355 | trs = createDApp(options, "secret", "secret 2"); 356 | (trs).should.be.ok; 357 | }); 358 | 359 | describe("returned dapp", function () { 360 | var keys = asch.crypto.getKeys("secret"); 361 | var secondKeys = asch.crypto.getKeys("secret 2"); 362 | 363 | it("should be object", function () { 364 | (trs).should.be.type("object"); 365 | }); 366 | 367 | it("should have id as string", function () { 368 | (trs.id).should.be.type("string"); 369 | }); 370 | 371 | it("should have type as number and equal 9", function () { 372 | (trs.type).should.be.type("number").and.equal(5); 373 | }); 374 | 375 | it("should have amount as number and eqaul 0", function () { 376 | (trs.amount).should.be.type("number").and.equal(0); 377 | }); 378 | 379 | it("should have fee as number and equal 10000000000", function () { 380 | (trs.fee).should.be.type("number").and.equal(10000000000); 381 | }); 382 | 383 | it("should have null recipientId", function () { 384 | trs.should.have.property("recipientId").equal(null); 385 | }); 386 | 387 | it("should have senderPublicKey as hex string", function () { 388 | (trs.senderPublicKey).should.be.type("string").and.match(function () { 389 | try { 390 | new Buffer(trs.senderPublicKey, "hex") 391 | } catch (e) { 392 | return false; 393 | } 394 | 395 | return true; 396 | }) 397 | }); 398 | 399 | it("should have timestamp as number", function () { 400 | (trs.timestamp).should.be.type("number").and.not.NaN; 401 | }); 402 | 403 | it("should have dapp inside asset", function () { 404 | (trs.asset).should.have.property("dapp"); 405 | }); 406 | 407 | describe("dapp asset", function () { 408 | it("should be ok", function () { 409 | (trs.asset.dapp).should.be.ok; 410 | }) 411 | 412 | it("should be object", function () { 413 | (trs.asset.dapp).should.be.type("object"); 414 | }); 415 | 416 | it("should have category property", function () { 417 | (trs.asset.dapp).should.have.property("category").and.equal(options.category); 418 | }); 419 | 420 | it("should have name property", function () { 421 | (trs.asset.dapp).should.have.property("name").and.equal(options.name); 422 | }); 423 | 424 | it("should have tags property", function () { 425 | (trs.asset.dapp).should.have.property("tags").and.equal(options.tags); 426 | }); 427 | 428 | it("should have type property", function () { 429 | (trs.asset.dapp).should.have.property("type").and.equal(options.type); 430 | }); 431 | 432 | it("should have link property", function () { 433 | (trs.asset.dapp).should.have.property("link").and.equal(options.link); 434 | }); 435 | 436 | it("should have icon property", function () { 437 | (trs.asset.dapp).should.have.property("icon").and.equal(options.icon); 438 | }); 439 | }); 440 | 441 | it("should have signature as hex string", function () { 442 | (trs.signature).should.be.type("string").and.match(function () { 443 | try { 444 | new Buffer(trs.signature, "hex") 445 | } catch (e) { 446 | return false; 447 | } 448 | 449 | return true; 450 | }) 451 | }); 452 | 453 | it("should have second signature in hex", function () { 454 | (trs).should.have.property("signSignature").and.type("string").and.match(function () { 455 | try { 456 | new Buffer(trs.signSignature, "hex"); 457 | } catch (e) { 458 | return false; 459 | } 460 | 461 | return true; 462 | }); 463 | }); 464 | 465 | it("should be signed correctly", function () { 466 | var result = asch.crypto.verify(trs); 467 | (result).should.be.ok; 468 | }); 469 | 470 | it("should not be signed correctly now", function () { 471 | trs.amount = 10000; 472 | var result = asch.crypto.verify(trs); 473 | (result).should.be.not.ok; 474 | }); 475 | 476 | it("should be second signed correctly", function () { 477 | trs.amount = 0; 478 | var result = asch.crypto.verifySecondSignature(trs, secondKeys.publicKey); 479 | (result).should.be.ok; 480 | }); 481 | 482 | it("should not be second signed correctly now", function () { 483 | trs.amount = 10000; 484 | var result = asch.crypto.verifySecondSignature(trs, secondKeys.publicKey); 485 | (result).should.be.not.ok; 486 | }); 487 | 488 | it("should be ok to verify bytes", function () { 489 | var data1 = 'a1b2c3d4' 490 | var secret = 'secret1' 491 | var keys = asch.crypto.getKeys(secret) 492 | var signature = asch.crypto.signBytes(data1, keys) 493 | var result = asch.crypto.verifyBytes(data1, signature, keys.publicKey) 494 | result.should.be.ok 495 | 496 | var data2 = new Buffer('a1b2c3d4', 'hex') 497 | signature = asch.crypto.signBytes(data2, keys) 498 | result = asch.crypto.verifyBytes(data2, signature, keys.publicKey) 499 | result.should.be.ok 500 | }) 501 | }); 502 | }); 503 | }); 504 | 505 | describe("delegate.js", function () { 506 | var delegate = asch.delegate; 507 | 508 | it("should be ok", function () { 509 | (delegate).should.be.ok; 510 | }); 511 | 512 | it("should be function", function () { 513 | (delegate).should.be.type("object"); 514 | }); 515 | 516 | it("should have property createDelegate", function () { 517 | (delegate).should.have.property("createDelegate"); 518 | }); 519 | 520 | describe("#createDelegate", function () { 521 | var createDelegate = delegate.createDelegate; 522 | var trs = null; 523 | 524 | it("should be ok", function () { 525 | (createDelegate).should.be.ok; 526 | }); 527 | 528 | it("should be function", function () { 529 | (createDelegate).should.be.type("function"); 530 | }); 531 | 532 | it("should create delegate", function () { 533 | trs = createDelegate("delegate", "secret", "secret 2"); 534 | }); 535 | 536 | describe("returned delegate", function () { 537 | var keys = asch.crypto.getKeys("secret"); 538 | var secondKeys = asch.crypto.getKeys("secret 2"); 539 | 540 | it("should be ok", function () { 541 | (trs).should.be.ok; 542 | }); 543 | 544 | it("should be object", function () { 545 | (trs).should.be.type("object"); 546 | }); 547 | 548 | it("should have recipientId equal null", function () { 549 | (trs).should.have.property("recipientId").and.type("object").and.be.empty; 550 | }) 551 | 552 | it("shoud have amount equal 0", function () { 553 | (trs).should.have.property("amount").and.type("number").and.equal(0); 554 | }) 555 | 556 | it("should have type equal 0", function () { 557 | (trs).should.have.property("type").and.type("number").and.equal(2); 558 | }); 559 | 560 | it("should have timestamp number", function () { 561 | (trs).should.have.property("timestamp").and.type("number"); 562 | }); 563 | 564 | it("should have senderPublicKey in hex", function () { 565 | (trs).should.have.property("senderPublicKey").and.type("string").and.match(function () { 566 | try { 567 | new Buffer(trs.senderPublicKey, "hex"); 568 | } catch (e) { 569 | return false; 570 | } 571 | 572 | return true; 573 | }).and.equal(keys.publicKey); 574 | }); 575 | 576 | it("should have signature in hex", function () { 577 | (trs).should.have.property("signature").and.type("string").and.match(function () { 578 | try { 579 | new Buffer(trs.signature, "hex"); 580 | } catch (e) { 581 | return false; 582 | } 583 | 584 | return true; 585 | }); 586 | }); 587 | 588 | it("should have second signature in hex", function () { 589 | (trs).should.have.property("signSignature").and.type("string").and.match(function () { 590 | try { 591 | new Buffer(trs.signSignature, "hex"); 592 | } catch (e) { 593 | return false; 594 | } 595 | 596 | return true; 597 | }); 598 | }); 599 | 600 | it("should have delegate asset", function () { 601 | (trs).should.have.property("asset").and.type("object"); 602 | (trs.asset).should.have.have.property("delegate"); 603 | }) 604 | 605 | it("should be signed correctly", function () { 606 | var result = asch.crypto.verify(trs, keys.publicKey); 607 | (result).should.be.ok; 608 | }); 609 | 610 | it("should be second signed correctly", function () { 611 | var result = asch.crypto.verifySecondSignature(trs, secondKeys.publicKey); 612 | (result).should.be.ok; 613 | }); 614 | 615 | it("should not be signed correctly now", function () { 616 | trs.amount = 100; 617 | var result = asch.crypto.verify(trs, keys.publicKey); 618 | (result).should.be.not.ok; 619 | }); 620 | 621 | it("should not be second signed correctly now", function () { 622 | trs.amount = 100; 623 | var result = asch.crypto.verify(trs, secondKeys.publicKey); 624 | (result).should.be.not.ok; 625 | }); 626 | 627 | describe("delegate asset", function () { 628 | it("should be ok", function () { 629 | (trs.asset.delegate).should.be.ok; 630 | }); 631 | 632 | it("should be object", function () { 633 | (trs.asset.delegate).should.be.type("object"); 634 | }); 635 | 636 | it("should be have property username", function () { 637 | (trs.asset.delegate).should.have.property("username").and.be.type("string").and.equal("delegate"); 638 | }); 639 | }); 640 | }); 641 | }); 642 | }); 643 | 644 | describe("multisignature.js", function () { 645 | }); 646 | 647 | describe("signature.js", function () { 648 | var signature = asch.signature; 649 | it("should be ok", function () { 650 | (signature).should.be.ok; 651 | }); 652 | 653 | it("should be object", function () { 654 | (signature).should.be.type("object"); 655 | }); 656 | 657 | it("should have properties", function () { 658 | (signature).should.have.property("createSignature"); 659 | }); 660 | 661 | describe("#createSignature", function () { 662 | var createSignature = signature.createSignature; 663 | var sgn = null; 664 | 665 | it("should be function", function () { 666 | (createSignature).should.be.type("function"); 667 | }); 668 | 669 | it("should create signature transaction", function () { 670 | sgn = createSignature("secret", "second secret"); 671 | (sgn).should.be.ok; 672 | (sgn).should.be.type("object"); 673 | }); 674 | 675 | describe("returned signature transaction", function () { 676 | it("should have empty recipientId", function () { 677 | (sgn).should.have.property("recipientId").equal(null); 678 | }); 679 | 680 | it("should have amount equal 0", function () { 681 | (sgn.amount).should.be.type("number").equal(0); 682 | }); 683 | 684 | it("should have asset", function () { 685 | (sgn.asset).should.be.type("object"); 686 | (sgn.asset).should.be.not.empty; 687 | }); 688 | 689 | it("should have signature inside asset", function () { 690 | (sgn.asset).should.have.property("signature"); 691 | }); 692 | 693 | describe("signature asset", function () { 694 | it("should be ok", function () { 695 | (sgn.asset.signature).should.be.ok; 696 | }) 697 | 698 | it("should be object", function () { 699 | (sgn.asset.signature).should.be.type("object"); 700 | }); 701 | 702 | it("should have publicKey property", function () { 703 | (sgn.asset.signature).should.have.property("publicKey"); 704 | }); 705 | 706 | it("should have publicKey in hex", function () { 707 | (sgn.asset.signature.publicKey).should.be.type("string").and.match(function () { 708 | try { 709 | new Buffer(sgn.asset.signature.publicKey); 710 | } catch (e) { 711 | return false; 712 | } 713 | 714 | return true; 715 | }); 716 | }); 717 | 718 | it("should have publicKey in 32 bytes", function () { 719 | var publicKey = new Buffer(sgn.asset.signature.publicKey, "hex"); 720 | (publicKey.length).should.be.equal(32); 721 | }); 722 | }); 723 | }); 724 | }); 725 | }); 726 | 727 | describe("slots.js", function () { 728 | var slots = require("../lib/time/slots.js"); 729 | 730 | it("should be ok", function () { 731 | (slots).should.be.ok; 732 | }); 733 | 734 | it("should be object", function () { 735 | (slots).should.be.type("object"); 736 | }); 737 | 738 | it("should have properties", function () { 739 | var properties = ["interval", "delegates", "getTime", "getRealTime", "getSlotNumber", "getSlotTime", "getNextSlot", "getLastSlot"]; 740 | properties.forEach(function (property) { 741 | (slots).should.have.property(property); 742 | }); 743 | }); 744 | 745 | describe(".interval", function () { 746 | var interval = slots.interval; 747 | 748 | it("should be ok", function () { 749 | (interval).should.be.ok; 750 | }); 751 | 752 | it("should be number and not NaN", function () { 753 | (interval).should.be.type("number").and.not.NaN; 754 | }); 755 | }); 756 | 757 | describe(".delegates", function () { 758 | var delegates = slots.delegates; 759 | 760 | it("should be ok", function () { 761 | (delegates).should.be.ok; 762 | }); 763 | 764 | it("should be number and not NaN", function () { 765 | (delegates).should.be.type("number").and.not.NaN; 766 | }); 767 | }); 768 | 769 | describe("#getTime", function () { 770 | var getTime = slots.getTime; 771 | 772 | it("should be ok", function () { 773 | (getTime).should.be.ok; 774 | }); 775 | 776 | it("should be a function", function () { 777 | (getTime).should.be.type("function"); 778 | }); 779 | 780 | it("should return epoch time as number, equal to 2764800", function () { 781 | var d = 1469822400000; 782 | var time = getTime(d); 783 | (time).should.be.ok; 784 | (time).should.be.type("number").and.equal(2764800); 785 | }); 786 | }); 787 | 788 | describe("#getRealTime", function () { 789 | var getRealTime = slots.getRealTime; 790 | 791 | it("should be ok", function () { 792 | (getRealTime).should.be.ok; 793 | }); 794 | 795 | it("should be a function", function () { 796 | (getRealTime).should.be.type("function"); 797 | }); 798 | 799 | it("should return return real time, convert 196144 to 1467253744000", function () { 800 | var d = 196144; 801 | var real = getRealTime(d); 802 | (real).should.be.ok; 803 | (real).should.be.type("number").and.equal(1467253744000); 804 | }); 805 | }); 806 | 807 | describe("#getSlotNumber", function () { 808 | var getSlotNumber = slots.getSlotNumber; 809 | 810 | it("should be ok", function () { 811 | (getSlotNumber).should.be.ok; 812 | }); 813 | 814 | it("should be a function", function () { 815 | (getSlotNumber).should.be.type("function"); 816 | }); 817 | 818 | it("should return slot number, equal to 19614", function () { 819 | var d = 196144; 820 | var slot = getSlotNumber(d); 821 | (slot).should.be.ok; 822 | (slot).should.be.type("number").and.equal(19614); 823 | }); 824 | }); 825 | 826 | describe("#getSlotTime", function () { 827 | var getSlotTime = slots.getSlotTime; 828 | 829 | it("should be ok", function () { 830 | (getSlotTime).should.be.ok; 831 | }); 832 | 833 | it("should be function", function () { 834 | (getSlotTime).should.be.type("function"); 835 | }); 836 | 837 | it("should return slot time number, equal to ", function () { 838 | var slot = 19614; 839 | var slotTime = getSlotTime(19614); 840 | (slotTime).should.be.ok; 841 | (slotTime).should.be.type("number").and.equal(196140); 842 | }); 843 | }); 844 | 845 | describe("#getNextSlot", function () { 846 | var getNextSlot = slots.getNextSlot; 847 | 848 | it("should be ok", function () { 849 | (getNextSlot).should.be.ok; 850 | }); 851 | 852 | it("should be function", function () { 853 | (getNextSlot).should.be.type("function"); 854 | }); 855 | 856 | it("should return next slot number", function () { 857 | var nextSlot = getNextSlot(); 858 | (nextSlot).should.be.ok; 859 | (nextSlot).should.be.type("number").and.not.NaN; 860 | }); 861 | }); 862 | 863 | describe("#getLastSlot", function () { 864 | var getLastSlot = slots.getLastSlot; 865 | 866 | it("should be ok", function () { 867 | (getLastSlot).should.be.ok; 868 | }); 869 | 870 | it("should be function", function () { 871 | (getLastSlot).should.be.type("function"); 872 | }); 873 | 874 | it("should return last slot number", function () { 875 | var lastSlot = getLastSlot(slots.getNextSlot()); 876 | (lastSlot).should.be.ok; 877 | (lastSlot).should.be.type("number").and.not.NaN; 878 | }); 879 | }); 880 | }); 881 | 882 | describe("transaction.js", function () { 883 | var transaction = asch.transaction; 884 | 885 | it("should be object", function () { 886 | (transaction).should.be.type("object"); 887 | }); 888 | 889 | it("should have properties", function () { 890 | (transaction).should.have.property("createTransaction"); 891 | }) 892 | 893 | describe("#createTransaction", function () { 894 | var createTransaction = transaction.createTransaction; 895 | var trs = null; 896 | 897 | it("should be a function", function () { 898 | (createTransaction).should.be.type("function"); 899 | }); 900 | 901 | it("should create transaction without second signature", function () { 902 | trs = createTransaction("58191285901858109", 1000, "", "secret"); 903 | (trs).should.be.ok; 904 | }); 905 | 906 | describe("returned transaction", function () { 907 | it("should be object", function () { 908 | (trs).should.be.type("object"); 909 | }); 910 | 911 | it("should have id as string", function () { 912 | (trs.id).should.be.type("string"); 913 | }); 914 | 915 | it("should have type as number and eqaul 0", function () { 916 | (trs.type).should.be.type("number").and.equal(0); 917 | }); 918 | 919 | it("should have timestamp as number", function () { 920 | (trs.timestamp).should.be.type("number").and.not.NaN; 921 | }); 922 | 923 | it("should have senderPublicKey as hex string", function () { 924 | (trs.senderPublicKey).should.be.type("string").and.match(function () { 925 | try { 926 | new Buffer(trs.senderPublicKey, "hex") 927 | } catch (e) { 928 | return false; 929 | } 930 | 931 | return true; 932 | }) 933 | }); 934 | 935 | it("should have recipientId as string and to be equal 58191285901858109", function () { 936 | (trs.recipientId).should.be.type("string").and.equal("58191285901858109"); 937 | }); 938 | 939 | it("should have amount as number and eqaul to 1000", function () { 940 | (trs.amount).should.be.type("number").and.equal(1000); 941 | }); 942 | 943 | it("should have empty asset object", function () { 944 | (trs.asset).should.be.type("object").and.empty; 945 | }); 946 | 947 | it("should does not have second signature", function () { 948 | (trs).should.not.have.property("signSignature"); 949 | }); 950 | 951 | it("should have signature as hex string", function () { 952 | (trs.signature).should.be.type("string").and.match(function () { 953 | try { 954 | new Buffer(trs.signature, "hex") 955 | } catch (e) { 956 | return false; 957 | } 958 | 959 | return true; 960 | }) 961 | }); 962 | 963 | it("should be signed correctly", function () { 964 | var result = asch.crypto.verify(trs); 965 | (result).should.be.ok; 966 | }); 967 | 968 | it("should not be signed correctly now", function () { 969 | trs.amount = 10000; 970 | var result = asch.crypto.verify(trs); 971 | (result).should.be.not.ok; 972 | }); 973 | }); 974 | }); 975 | 976 | describe("#createTransaction with second secret", function () { 977 | var createTransaction = transaction.createTransaction; 978 | var trs = null; 979 | var secondSecret = "second secret"; 980 | var keys = asch.crypto.getKeys(secondSecret); 981 | 982 | it("should be a function", function () { 983 | (createTransaction).should.be.type("function"); 984 | }); 985 | 986 | it("should create transaction without second signature", function () { 987 | trs = createTransaction("58191285901858109", 1000, "", "secret", secondSecret); 988 | (trs).should.be.ok; 989 | }); 990 | 991 | describe("returned transaction", function () { 992 | it("should be object", function () { 993 | (trs).should.be.type("object"); 994 | }); 995 | 996 | it("should have id as string", function () { 997 | (trs.id).should.be.type("string"); 998 | }); 999 | 1000 | it("should have type as number and eqaul 0", function () { 1001 | (trs.type).should.be.type("number").and.equal(0); 1002 | }); 1003 | 1004 | it("should have timestamp as number", function () { 1005 | (trs.timestamp).should.be.type("number").and.not.NaN; 1006 | }); 1007 | 1008 | it("should have senderPublicKey as hex string", function () { 1009 | (trs.senderPublicKey).should.be.type("string").and.match(function () { 1010 | try { 1011 | new Buffer(trs.senderPublicKey, "hex") 1012 | } catch (e) { 1013 | return false; 1014 | } 1015 | 1016 | return true; 1017 | }) 1018 | }); 1019 | 1020 | it("should have recipientId as string and to be equal 58191285901858109", function () { 1021 | (trs.recipientId).should.be.type("string").and.equal("58191285901858109"); 1022 | }); 1023 | 1024 | it("should have amount as number and eqaul to 1000", function () { 1025 | (trs.amount).should.be.type("number").and.equal(1000); 1026 | }); 1027 | 1028 | it("should have empty asset object", function () { 1029 | (trs.asset).should.be.type("object").and.empty; 1030 | }); 1031 | 1032 | it("should have second signature", function () { 1033 | (trs).should.have.property("signSignature"); 1034 | }); 1035 | 1036 | it("should have signature as hex string", function () { 1037 | (trs.signature).should.be.type("string").and.match(function () { 1038 | try { 1039 | new Buffer(trs.signature, "hex") 1040 | } catch (e) { 1041 | return false; 1042 | } 1043 | 1044 | return true; 1045 | }) 1046 | }); 1047 | 1048 | it("should have signSignature as hex string", function () { 1049 | (trs.signSignature).should.be.type("string").and.match(function () { 1050 | try { 1051 | new Buffer(trs.signSignature, "hex"); 1052 | } catch (e) { 1053 | return false; 1054 | } 1055 | 1056 | return true; 1057 | }); 1058 | }); 1059 | 1060 | it("should be signed correctly", function () { 1061 | var result = asch.crypto.verify(trs); 1062 | (result).should.be.ok; 1063 | }); 1064 | 1065 | it("should be second signed correctly", function () { 1066 | var result = asch.crypto.verifySecondSignature(trs, keys.publicKey); 1067 | (result).should.be.ok; 1068 | }); 1069 | 1070 | it("should not be signed correctly now", function () { 1071 | trs.amount = 10000; 1072 | var result = asch.crypto.verify(trs); 1073 | (result).should.be.not.ok; 1074 | }); 1075 | 1076 | it("should not be second signed correctly now", function () { 1077 | trs.amount = 10000; 1078 | var result = asch.crypto.verifySecondSignature(trs, keys.publicKey); 1079 | (result).should.be.not.ok; 1080 | }); 1081 | }); 1082 | }); 1083 | }); 1084 | 1085 | describe("transfer.js", function () { 1086 | }); 1087 | 1088 | describe("vote.js", function () { 1089 | var vote = asch.vote; 1090 | 1091 | it("should be ok", function () { 1092 | (vote).should.be.ok; 1093 | }); 1094 | 1095 | it("should be object", function () { 1096 | (vote).should.be.type("object"); 1097 | }); 1098 | 1099 | it("should have createVote property", function () { 1100 | (vote).should.have.property("createVote"); 1101 | }); 1102 | 1103 | describe("#createVote", function () { 1104 | var createVote = vote.createVote, 1105 | vt = null, 1106 | publicKey = asch.crypto.getKeys("secret").publicKey, 1107 | publicKeys = ["+" + publicKey]; 1108 | 1109 | it("should be ok", function () { 1110 | (createVote).should.be.ok; 1111 | }); 1112 | 1113 | it("should be function", function () { 1114 | (createVote).should.be.type("function"); 1115 | }); 1116 | 1117 | it("should create vote", function () { 1118 | vt = createVote(publicKeys, "secret", "second secret"); 1119 | }); 1120 | 1121 | describe("returned vote", function () { 1122 | it("should be ok", function () { 1123 | (vt).should.be.ok; 1124 | }); 1125 | 1126 | it("should be object", function () { 1127 | (vt).should.be.type("object"); 1128 | }); 1129 | 1130 | it("should have recipientId string equal to sender", function () { 1131 | (vt).should.have.property("recipientId").equal(null);; 1132 | }); 1133 | 1134 | it("should have amount number eaul to 0", function () { 1135 | (vt).should.have.property("amount").and.be.type("number").and.equal(0); 1136 | }); 1137 | 1138 | it("should have type number equal to 3", function () { 1139 | (vt).should.have.property("type").and.be.type("number").and.equal(3); 1140 | }); 1141 | 1142 | it("should have timestamp number", function () { 1143 | (vt).should.have.property("timestamp").and.be.type("number"); 1144 | }); 1145 | 1146 | it("should have senderPublicKey hex string equal to sender public key", function () { 1147 | (vt).should.have.property("senderPublicKey").and.be.type("string").and.match(function () { 1148 | try { 1149 | new Buffer(vt.senderPublicKey, "hex"); 1150 | } catch (e) { 1151 | return false; 1152 | } 1153 | 1154 | return true; 1155 | }).and.equal(publicKey); 1156 | }); 1157 | 1158 | it("should have signature hex string", function () { 1159 | (vt).should.have.property("signature").and.be.type("string").and.match(function () { 1160 | try { 1161 | new Buffer(vt.signature, "hex"); 1162 | } catch (e) { 1163 | return false; 1164 | } 1165 | 1166 | return true; 1167 | }); 1168 | }); 1169 | 1170 | it("should have second signature hex string", function () { 1171 | (vt).should.have.property("signSignature").and.be.type("string").and.match(function () { 1172 | try { 1173 | new Buffer(vt.signSignature, "hex"); 1174 | } catch (e) { 1175 | return false; 1176 | } 1177 | 1178 | return true; 1179 | }); 1180 | }); 1181 | 1182 | it("should be signed correctly", function () { 1183 | var result = asch.crypto.verify(vt); 1184 | (result).should.be.ok; 1185 | }); 1186 | 1187 | it("should be second signed correctly", function () { 1188 | var result = asch.crypto.verifySecondSignature(vt, asch.crypto.getKeys("second secret").publicKey); 1189 | (result).should.be.ok; 1190 | }); 1191 | 1192 | it("should not be signed correctly now", function () { 1193 | vt.amount = 100; 1194 | var result = asch.crypto.verify(vt); 1195 | (result).should.be.not.ok; 1196 | }); 1197 | 1198 | it("should not be second signed correctly now", function () { 1199 | vt.amount = 100; 1200 | var result = asch.crypto.verifySecondSignature(vt, asch.crypto.getKeys("second secret").publicKey); 1201 | (result).should.be.not.ok; 1202 | }); 1203 | 1204 | it("should have asset", function () { 1205 | (vt).should.have.property("asset").and.not.empty; 1206 | }); 1207 | 1208 | describe("vote asset", function () { 1209 | it("should be ok", function () { 1210 | (vt.asset.vote).should.have.property("votes").and.be.ok; 1211 | }); 1212 | 1213 | it("should be object", function () { 1214 | (vt.asset.vote.votes).should.be.type("object"); 1215 | }); 1216 | 1217 | it("should be not empty", function () { 1218 | (vt.asset.vote.votes).should.be.not.empty; 1219 | }); 1220 | 1221 | it("should contains one element", function () { 1222 | (vt.asset.vote.votes.length).should.be.equal(1); 1223 | }); 1224 | 1225 | it("should have public keys in hex", function () { 1226 | vt.asset.vote.votes.forEach(function (v) { 1227 | (v).should.be.type("string").startWith("+").and.match(function () { 1228 | try { 1229 | new Buffer(v.substring(1, v.length), "hex"); 1230 | } catch (e) { 1231 | return false; 1232 | } 1233 | 1234 | return true; 1235 | }); 1236 | }); 1237 | }); 1238 | 1239 | it("should be equal to sender public key", function () { 1240 | var v = vt.asset.vote.votes[0]; 1241 | (v.substring(1, v.length)).should.be.equal(publicKey); 1242 | }); 1243 | }) 1244 | }); 1245 | }); 1246 | }); 1247 | 1248 | describe('crypto sha256 and address', function () { 1249 | it('should be equal to the expected address', function () { 1250 | asch.crypto.getAddress('7a91b9bfc0ea185bf3ade9d264da273f7fe19bf71008210b1d7239c82dd3ad20').should.be.equal('AFbYJhiJb3DXzHy5ZP24mKw21M2dCBJCXP') 1251 | var publicKeyBuffer = new Buffer('7a91b9bfc0ea185bf3ade9d264da273f7fe19bf71008210b1d7239c82dd3ad20', 'hex') 1252 | asch.crypto.getAddress(publicKeyBuffer).should.be.equal('AFbYJhiJb3DXzHy5ZP24mKw21M2dCBJCXP') 1253 | }) 1254 | }) 1255 | 1256 | }); 1257 | --------------------------------------------------------------------------------