node_modules
dist
+testCompiled
+.idea/
\ No newline at end of file
{
"name": "bytom-sdk",
- "version": "1.0.0",
+ "version": "1.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"dev": true,
"optional": true
},
+ "assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true
+ },
"async-each": {
"version": "1.0.1",
"resolved": "http://registry.npm.taobao.org/async-each/download/async-each-1.0.1.tgz",
"repeat-element": "1.1.2"
}
},
+ "browser-stdout": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
+ "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
+ "dev": true
+ },
"btoa": {
"version": "1.2.1",
"resolved": "http://registry.npm.taobao.org/btoa/download/btoa-1.2.1.tgz",
"underscore-contrib": "0.3.0"
}
},
+ "chai": {
+ "version": "3.5.0",
+ "resolved": "http://registry.npmjs.org/chai/-/chai-3.5.0.tgz",
+ "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=",
+ "dev": true,
+ "requires": {
+ "assertion-error": "1.1.0",
+ "deep-eql": "0.1.3",
+ "type-detect": "1.0.0"
+ }
+ },
+ "chai-as-promised": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-6.0.0.tgz",
+ "integrity": "sha1-GgKkM6byTa+sY7nJb6FoTbGqjaY=",
+ "dev": true,
+ "requires": {
+ "check-error": "1.0.2"
+ }
+ },
"chalk": {
"version": "1.1.3",
"resolved": "http://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz",
"supports-color": "2.0.0"
}
},
+ "check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
+ "dev": true
+ },
"chokidar": {
"version": "1.7.0",
"resolved": "http://registry.npm.taobao.org/chokidar/download/chokidar-1.7.0.tgz",
"ms": "2.0.0"
}
},
+ "deep-eql": {
+ "version": "0.1.3",
+ "resolved": "http://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
+ "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=",
+ "dev": true,
+ "requires": {
+ "type-detect": "0.1.1"
+ },
+ "dependencies": {
+ "type-detect": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz",
+ "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=",
+ "dev": true
+ }
+ }
+ },
"detect-indent": {
"version": "4.0.0",
"resolved": "http://registry.npm.taobao.org/detect-indent/download/detect-indent-4.0.0.tgz",
"repeating": "2.0.1"
}
},
+ "diff": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
+ "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=",
+ "dev": true
+ },
"dom-serializer": {
"version": "0.1.0",
"resolved": "http://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.1.0.tgz",
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
"dev": true
},
+ "graceful-readlink": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
+ "dev": true
+ },
+ "growl": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
+ "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
+ "dev": true
+ },
"has-ansi": {
"version": "2.0.0",
"resolved": "http://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
+ "he": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
+ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+ "dev": true
+ },
"home-or-tmp": {
"version": "2.0.0",
"resolved": "http://registry.npm.taobao.org/home-or-tmp/download/home-or-tmp-2.0.0.tgz",
"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
"dev": true
},
+ "json3": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
+ "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
+ "dev": true
+ },
"json5": {
"version": "0.5.1",
"resolved": "http://registry.npm.taobao.org/json5/download/json5-0.5.1.tgz",
"integrity": "sha1-G3eTz3JZ6jj7NmHU04syYK+K5Oc=",
"dev": true
},
+ "lodash._baseassign": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
+ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=",
+ "dev": true,
+ "requires": {
+ "lodash._basecopy": "3.0.1",
+ "lodash.keys": "3.1.2"
+ }
+ },
+ "lodash._basecopy": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
+ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
+ "dev": true
+ },
+ "lodash._basecreate": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz",
+ "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=",
+ "dev": true
+ },
+ "lodash._getnative": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+ "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
+ "dev": true
+ },
+ "lodash._isiterateecall": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
+ "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
+ "dev": true
+ },
"lodash.clonedeep": {
"version": "4.5.0",
"resolved": "http://registry.npm.taobao.org/lodash.clonedeep/download/lodash.clonedeep-4.5.0.tgz",
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
"dev": true
},
+ "lodash.create": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz",
+ "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=",
+ "dev": true,
+ "requires": {
+ "lodash._baseassign": "3.2.0",
+ "lodash._basecreate": "3.0.3",
+ "lodash._isiterateecall": "3.0.9"
+ }
+ },
"lodash.escaperegexp": {
"version": "4.1.2",
"resolved": "http://registry.npm.taobao.org/lodash.escaperegexp/download/lodash.escaperegexp-4.1.2.tgz",
"integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=",
"dev": true
},
+ "lodash.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
+ "dev": true
+ },
+ "lodash.isarray": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
+ "dev": true
+ },
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "http://registry.npm.taobao.org/lodash.isplainobject/download/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=",
"dev": true
},
+ "lodash.keys": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
+ "dev": true,
+ "requires": {
+ "lodash._getnative": "3.9.1",
+ "lodash.isarguments": "3.1.0",
+ "lodash.isarray": "3.0.4"
+ }
+ },
"lodash.mergewith": {
"version": "4.6.1",
"resolved": "http://registry.npm.taobao.org/lodash.mergewith/download/lodash.mergewith-4.6.1.tgz",
"minimist": "0.0.8"
}
},
+ "mocha": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz",
+ "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==",
+ "dev": true,
+ "requires": {
+ "browser-stdout": "1.3.0",
+ "commander": "2.9.0",
+ "debug": "2.6.8",
+ "diff": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "glob": "7.1.1",
+ "growl": "1.9.2",
+ "he": "1.1.1",
+ "json3": "3.3.2",
+ "lodash.create": "3.1.1",
+ "mkdirp": "0.5.1",
+ "supports-color": "3.1.2"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.9.0",
+ "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
+ "dev": true,
+ "requires": {
+ "graceful-readlink": "1.0.1"
+ }
+ },
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
+ "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
+ "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=",
+ "dev": true,
+ "requires": {
+ "has-flag": "1.0.0"
+ }
+ }
+ }
+ },
"moment": {
"version": "2.22.1",
"resolved": "http://registry.npm.taobao.org/moment/download/moment-2.22.1.tgz",
"integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
"dev": true
},
+ "type-detect": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz",
+ "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=",
+ "dev": true
+ },
"underscore": {
"version": "1.8.3",
"resolved": "http://registry.npm.taobao.org/underscore/download/underscore-1.8.3.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
},
+ "uuid": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz",
+ "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=",
+ "dev": true
+ },
"v8flags": {
"version": "2.1.1",
"resolved": "http://registry.npm.taobao.org/v8flags/download/v8flags-2.1.1.tgz",
"main": "dist/index.js",
"repository": {
"type": "git",
- "url": "https://github.com/Bytom/node-sdk.git"
+ "url": "https://github.com/Bytom/bytom-node-sdk.git"
},
"license": "Apache-2.0",
"engines": {
"scripts": {
"docs": "jsdoc -c jsdoc.conf.json",
"build": "babel src --out-dir dist",
+ "test": "mocha testCompiled",
+ "pretest": "npm run build && babel test --out-dir testCompiled",
"prepublish": "npm run build"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"ink-docstrap": "^1.3.2",
- "jsdoc": "^3.5.5"
+ "jsdoc": "^3.5.5",
+ "mocha": "^3.2.0",
+ "uuid": "~3.0.0",
+ "chai": "^3.5.0",
+ "chai-as-promised": "^6.0.0"
},
"dependencies": {
"axios": "^0.18.0",
import balancesApi from './api/balances'
import unspentOutputsAPI from './api/unspentOutputs'
import accessTokensApi from './api/accessTokens'
+import configAPI from './api/config'
+import blockAPI from './api/block'
class Client {
constructor(baseUrl, token) {
this.balances = new balancesApi(this.connection)
this.unspentOutputs = new unspentOutputsAPI(this.connection)
this.accessTokens = new accessTokensApi(this.connection)
+ this.status = new configAPI(this.connection)
+ this.block = new blockAPI(this.connection)
}
}
import axios from 'axios'
import btoa from 'btoa'
+const errors = require('./errors')
class Connection {
constructor(baseUrl, token = '') {
return axios.request(config).then(resp => {
if (resp.data.status === 'fail') {
- throw resp.data.msg
+ throw errors.formatErrMsg(resp.data)
} else if (resp.data.status === 'success') {
return resp.data.data
}
return resp.data
})
+ .catch(error=>{
+ throw error
+ })
}
}
--- /dev/null
+const lib = {
+ create: function(type, message, props = {}) {
+ let err
+ if (props.body) {
+ err = lib.newBatchError(props.body, props.requestId)
+ } else {
+ err = new Error(message)
+ }
+
+ err = Object.assign(err, props, {
+ bytomClientError: true,
+ type: type,
+ })
+ return err
+ },
+
+ isbytomError: function(err) {
+ return err && !!err.bytomClientError
+ },
+
+ isBatchError: function (v) {
+ return v && v.code && !v.stack
+ },
+
+ newBatchError: function (body, requestId = false) {
+ let err = new Error(lib.formatErrMsg(body, requestId))
+ err.code = body.code
+ err.bytomMessage = body.msg
+ err.detail = body.error_detail
+ return err
+ },
+
+ formatErrMsg: function(body) {
+ let tokens = []
+
+ if (typeof body.code === 'string' && body.code.length > 0) {
+ tokens.push('Code: ' + body.code)
+ }
+
+ tokens.push('Message: ' + body.msg)
+
+ if (typeof body.error_detail === 'string' && body.error_detail.length > 0) {
+ tokens.push('Detail: ' + body.error_detail)
+ }
+
+ return tokens.join(' ')
+ },
+
+ types: {
+ FETCH: 'FETCH',
+ CONNECTIVITY: 'CONNECTIVITY',
+ JSON: 'JSON',
+ UNAUTHORIZED: 'UNAUTHORIZED',
+ NOT_FOUND: 'NOT_FOUND',
+ BAD_REQUEST: 'BAD_REQUEST',
+ SERVER_ERROR: 'SERVER_ERROR',
+ }
+}
+
+module.exports = lib
--- /dev/null
+/* eslint-env mocha */
+
+const bytom = require('../dist/index.js')
+const uuid = require('uuid')
+const chai = require('chai')
+const chaiAsPromised = require('chai-as-promised')
+
+chai.use(chaiAsPromised)
+const expect = chai.expect
+
+const url = 'http://localhost:9888'
+const accessToken = ''
+
+const client = new bytom.Client(url, accessToken)
+
+function createToken() {
+ return client.accessTokens.create({
+ id: `token-${uuid.v4()}`
+ })
+}
+
+describe('Access token', () => {
+
+ it('creation successful', () => {
+ return client.accessTokens.create({
+ id: `another-${uuid.v4()}`
+ }).then(resp => expect(resp.token).not.to.be.empty)
+ })
+
+ it('creation rejected due to duplicate ID', () => {
+ return createToken()
+ .then((token) => expect(client.accessTokens.create({
+ id: token.id
+ })).to.be.rejectedWith('BTM000'))
+ })
+
+ it('returned in list after creation', () => {
+ let tokenId
+ return createToken()
+ .then((token) => {
+ tokenId = token.id
+ return client.accessTokens.list()
+ })
+ .then(resp => expect(resp.map(item => item.id)).to.contain(tokenId))
+ })
+
+ it('deletion successful', () => {
+ return createToken()
+ .then((token) => client.accessTokens.delete(token.id))
+ .then(resp => expect(resp).to.be.empty)
+ })
+
+ it('deletion rejected due to missing ID', () => {
+ return createToken()
+ .then(() => expect(client.accessTokens.delete())
+ .to.be.rejectedWith('BTM000'))
+ })
+
+ it('removed from list after deletion', () => {
+ let tokenId
+ return createToken()
+ .then((token) => {
+ tokenId = token.id
+ return client.accessTokens.delete(tokenId)
+ })
+ .then(() => client.accessTokens.list())
+ .then(resp => expect(resp.map(item => item.id)).to.not.contain(tokenId))
+ })
+
+})
\ No newline at end of file
+/* eslint-env mocha */
+
+const bytom = require('../dist/index.js')
+const uuid = require('uuid')
+const chai = require('chai')
+const chaiAsPromised = require('chai-as-promised')
+
+chai.use(chaiAsPromised)
+const expect = chai.expect
+
+const url = 'http://localhost:9888'
+const accessToken = ''
+
+const client = new bytom.Client(url, accessToken)
+
+const xAccountAlias = `x-${uuid.v4()}`
+const yAccountAlias = `y-${uuid.v4()}`
+
+let mockHsmKey
+
+describe('Account', () => {
+
+ before('set up API objects', () => {
+
+ // Key and account creation
+ return client.keys.listAll()
+ .then(keys => { mockHsmKey = keys[0] })
+ .then(() => {
+ return client.accounts.create({alias: xAccountAlias, root_xpubs: [mockHsmKey.xpub], quorum: 1 })
+ })
+ .then(() => {
+ return client.accounts.create({alias: yAccountAlias, root_xpubs: [mockHsmKey.xpub], quorum: 1})
+ })
+ })
+
+ describe('Single account creation', () => {
+
+ it('successful', () => {
+ return client.accounts.create({alias: `alice-${uuid.v4()}`, root_xpubs: [mockHsmKey.xpub], quorum: 1})
+ .then(resp => expect(resp.id).not.to.be.empty)
+ })
+
+ it('rejected due to missing key fields', () => {
+ return expect(client.accounts.create({alias: 'david'})).to.be.rejectedWith('BTM202')
+ })
+ })
+
+ describe('Single account alias update', () => {
+
+ it('successful', () => {
+ const newAlias = `alice-${uuid.v4()}`
+ return client.accounts.updateAlias({
+ account_alias: xAccountAlias,
+ new_alias: newAlias
+ })
+ .then(() => {
+ return client.accounts.list({
+ alias: newAlias
+ })
+ })
+ .then(resp => expect(resp[0].alias).to.include(newAlias))
+ })
+
+ it('rejected due to missing ID/Alias', () => {
+ return expect(
+ client.accounts.updateAlias({
+ // ID/Alias intentionally omitted
+ new_alias: 'new'
+ })
+ ).to.be.rejectedWith('BTM709')
+ })
+ })
+
+
+ describe('Delete Account', () => {
+
+ it('successful', () => {
+ const alias = `alice-${uuid.v4()}`
+ return client.accounts.create({alias: alias, root_xpubs: [mockHsmKey.xpub], quorum: 1})
+ .then(() =>{
+ return client.accounts.delete({
+ account_alias: alias
+ })
+ })
+ .then(resp => expect(resp).to.be.empty)
+ })
+ })
+
+ describe('Account Receiver', () => {
+
+ it('created Account Reciever', () => {
+ return client.accounts.create({alias: xAccountAlias, root_xpubs: [mockHsmKey.xpub], quorum: 1})
+ .then(() =>{
+ return client.accounts.createReceiver({account_alias: xAccountAlias})
+ })
+ .then(resp => expect(resp.address).to.not.be.empty)
+ })
+
+ it('list Account Reciever by alias', () => {
+ let address
+ const alias = `connie-${uuid.v4()}`
+
+ return client.accounts.create({alias: alias, root_xpubs: [mockHsmKey.xpub], quorum: 1})
+ .then(() =>{
+ return client.accounts.createReceiver({account_alias: alias})
+ })
+ .then((resp) =>{
+ address = resp.address
+ return client.accounts.listAddresses({
+ account_alias: alias
+ })
+ })
+ .then(resp =>
+ expect(resp.map(item => item.address)).to.include(address)
+ )
+ })
+
+ it('list Account Reciever by Id', () => {
+ let address, id
+ const alias = `connie-${uuid.v4()}`
+
+ return client.accounts.create({alias: alias, root_xpubs: [mockHsmKey.xpub], quorum: 1})
+ .then((resp) =>{
+ id = resp.id
+ return client.accounts.createReceiver({account_id: id})
+ })
+ .then((resp) =>{
+ address = resp.address
+ return client.accounts.listAddresses({
+ account_id: id
+ })
+ })
+ .then(resp =>
+ expect(resp.map(item => item.address)).to.include(address)
+ )
+ })
+
+ })
+
+ describe('list All Account', () => {
+ it('success example', () => {
+ let created
+
+ return client.accounts.create({
+ alias: `bob-${uuid.v4()}`,
+ root_xpubs: [mockHsmKey.xpub],
+ quorum: 1
+ }).then(account =>
+ created = account.id
+ ).then(() =>
+ client.accounts.listAll()
+ ).then((resp) =>
+ expect(resp.map(item => item.id)).to.include(created)
+ )
+ })
+ })
+
+})
\ No newline at end of file
--- /dev/null
+/* eslint-env mocha */
+
+const bytom = require('../dist/index.js')
+const uuid = require('uuid')
+const chai = require('chai')
+const assert = require('assert')
+const chaiAsPromised = require('chai-as-promised')
+
+chai.use(chaiAsPromised)
+const expect = chai.expect
+
+const url = 'http://localhost:9888'
+const accessToken = ''
+
+const client = new bytom.Client(url, accessToken)
+
+const xAssetAlias = `x-${uuid.v4()}`
+const yAssetAlias = `y-${uuid.v4()}`
+
+let mockHsmKey, xAssetId, yAssetId
+
+describe('Asset', () => {
+
+ before('set up API objects', () => {
+
+ // Key and asset creation
+ return client.keys.listAll()
+ .then(keys => { mockHsmKey = keys[0] })
+ .then(() => {
+ return client.assets.create(
+ {
+ alias: xAssetAlias,
+ definition: {
+ decimals: 8,
+ description: {},
+ name: "TESTASSET1",
+ symbol: "TESTASSET1"
+ },
+ root_xpubs: [mockHsmKey.xpub],
+ quorum: 1}
+ )
+ .then((resp)=>{
+ xAssetId = resp.id
+ })
+ })
+ .then(() => {
+ return client.assets.create({
+ alias: yAssetAlias,
+ definition: {
+ decimals: 8,
+ description: {},
+ name: "TESTASSET2",
+ symbol: "TESTASSET2"
+ },
+ root_xpubs: [mockHsmKey.xpub],
+ quorum: 1})
+ .then((resp)=>{
+ yAssetId = resp.id
+ })
+ })
+ })
+
+ describe('Single asset creation', () => {
+
+ it('successful', () => {
+ return client.assets.create({
+ alias: `asset-${uuid.v4()}`,
+ definition: {
+ decimals: 8,
+ description: {},
+ name: `TESTASSET-${uuid.v4()}`,
+ symbol: `TESTASSET-${uuid.v4()}`
+ },
+ root_xpubs: [mockHsmKey.xpub],
+ quorum: 1})
+ .then(resp => expect(resp.id).not.to.be.empty)
+ })
+
+ it('rejected due to missing key fields', () => {
+ return expect(client.assets.create({alias: 'asset'})).to.be.rejectedWith('BTM202')
+ })
+ })
+
+
+ describe('Single asset alias update', () => {
+
+ it('successful', () => {
+ const alias = `asset-${uuid.v4()}`
+ return client.assets.updateAlias({
+ id: xAssetId,
+ alias: alias
+ })
+ .then(() => {
+ return client.assets.list(xAssetId)
+ })
+ .then(page => {
+ assert.deepEqual(page.alias, alias.toUpperCase())
+ })
+ })
+
+ it('rejected due to missing ID/Alias', () => {
+ return expect(
+ client.assets.updateAlias({
+ // ID/Alias intentionally omitted
+ alias: `asset-${uuid.v4()}`,
+ })
+ ).to.be.rejectedWith('BTM000')
+ })
+ })
+
+ describe('listAll', () => {
+ it('success example', () => {
+ return client.assets.listAll()
+ .then((resp) => {
+ expect(resp.map(item => item.alias)).to.be.an('array').that.include(yAssetAlias.toUpperCase())
+ })
+ })
+
+ it('list success', () => {
+ return client.assets.list(xAssetId)
+ .then(page => {
+ assert.deepEqual(page.id, xAssetId)
+ })
+ })
+ })
+})
\ No newline at end of file
--- /dev/null
+/* eslint-env mocha */
+
+const chai = require('chai')
+const chaiAsPromised = require('chai-as-promised')
+chai.use(chaiAsPromised)
+const expect = chai.expect
+
+const {
+ client
+} = require('./testHelpers')
+
+describe('Balance', () => {
+
+ describe('list by specific account', () => {
+ it('simple example', () =>
+ client.balances.list({
+ account_alias: 'default',
+ }).then(items =>
+ expect(items[0].amount).not.to.be.empty
+ )
+ )
+ })
+
+ describe('listAll', () => {
+ it('simple example', () => {
+ return client.balances.listAll().then((resp) => {
+ expect(resp.find(b => b.account_alias == 'default').amount).not.to.be.empty
+ })
+ })
+ })
+
+})
\ No newline at end of file
--- /dev/null
+/* eslint-env mocha */
+
+const chai = require('chai')
+const chaiAsPromised = require('chai-as-promised')
+chai.use(chaiAsPromised)
+const expect = chai.expect
+
+const {
+ client
+} = require('./testHelpers')
+
+describe('Block', () => {
+
+ describe('block count', () => {
+ it('simple example', () =>
+ client.block.getBlockCount()
+ .then(items =>
+ expect(items.block_count).not.to.be.empty
+ )
+ )
+ })
+
+ describe('block hash', () => {
+ it('simple example', () => {
+ return client.block.getBlockHash()
+ .then((resp) => {
+ expect(resp.block_hash).not.to.be.empty
+ })
+ })
+ })
+
+ describe('get Block', () => {
+ it('simple example', () => {
+ let blockHash
+ return client.block.getBlockHash()
+ .then((resp) => {
+ blockHash = resp.block_hash
+ return client.block.getBlock({block_hash: resp.block_hash})
+ })
+ .then((resp) =>
+ expect(resp.hash).to.equal(blockHash)
+ )
+ })
+ })
+
+ describe('get Block Header', () => {
+ it('simple example', () => {
+ let blockHash
+ return client.block.getBlockHash()
+ .then((resp) => {
+ blockHash = resp.block_hash
+ return client.block.getBlockHeader({block_hash: resp.block_hash})
+ })
+ .then((resp) =>
+ expect(resp.block_header).not.to.be.empty
+ )
+ })
+ })
+
+ describe('get Difficulty', () => {
+ it('simple example', () => {
+ let blockHash
+ return client.block.getBlockHash()
+ .then((resp) => {
+ blockHash = resp.block_hash
+ return client.block.getDifficulty({block_hash: resp.block_hash})
+ })
+ .then((resp) =>
+ expect(resp.hash).to.equal(blockHash)
+ )
+ })
+ })
+
+ describe('get Hash Rate', () => {
+ it('simple example', () => {
+ let blockHash
+ return client.block.getBlockHash()
+ .then((resp) => {
+ blockHash = resp.block_hash
+ return client.block.getHashRate({block_hash: resp.block_hash})
+ })
+ .then((resp) =>
+ expect(resp.hash).to.equal(blockHash)
+ )
+ })
+ })
+})
\ No newline at end of file
--- /dev/null
+/* eslint-env mocha */
+
+const chai = require('chai')
+const chaiAsPromised = require('chai-as-promised')
+chai.use(chaiAsPromised)
+const expect = chai.expect
+
+const {
+ client
+} = require('./testHelpers')
+
+describe('Core Status', () => {
+
+ describe('gasRate', () => {
+ it('simple example', () =>
+ client.status.gasRate()
+ .then(items =>
+ expect(items.gas_rate).not.to.be.empty
+ )
+ )
+ })
+
+ describe('netInfo', () => {
+ it('simple example', () => {
+ return client.status.netInfo()
+ .then((resp) => {
+ expect(resp).not.to.be.empty
+ })
+ })
+ })
+
+})
\ No newline at end of file
--- /dev/null
+/* eslint-env mocha */
+
+const bytom = require('../dist/index.js')
+const uuid = require('uuid')
+const chai = require('chai')
+const chaiAsPromised = require('chai-as-promised')
+
+chai.use(chaiAsPromised)
+const expect = chai.expect
+
+const url = 'http://localhost:9888'
+const accessToken = ''
+
+const client = new bytom.Client(url, accessToken)
+
+const keyAlias = `key-${uuid.v4()}`
+const password = '12345'
+
+let keyXpub
+
+before('set up API objects', () => {
+
+ // Key creation
+ return client.keys.create({
+ alias: keyAlias,
+ password: password,
+ })
+ .then((resp)=>{
+ keyXpub = resp.xpub
+ })
+})
+
+describe('key', () => {
+
+ it('successfully creates key', () => {
+ return client.keys.create({
+ alias: `key-${uuid.v4()}`,
+ password: password,
+ })
+ .then((resp) => expect(resp).not.to.be.empty)
+ })
+
+ it('rejects key creation due to duplicate alias', () => {
+ return expect(client.keys.create({ alias: keyAlias, password: password })).to.be.rejectedWith('BTM800')
+ })
+
+ it('returns key in list after key creation, listAll', () => {
+ let keyAlias
+ return client.keys.create({ alias: `key-${uuid.v4()}` , password: password })
+ .then((key) => {
+ keyAlias = key.alias
+ return client.keys.listAll()
+ })
+ .then(resp => {
+ return expect(resp.map(item => item.alias)).to.contain(keyAlias)
+ })
+ })
+
+ describe('password', () => {
+ it('successfully check correct password', () => {
+ return client.keys.checkPassword({
+ xpub: keyXpub,
+ password:password
+ })
+ .then((resp) => {
+ expect(resp.check_result).to.be.true
+ })
+ })
+
+ it('successfully check password wrong', () => {
+ return client.keys.checkPassword({
+ xpub: keyXpub,
+ password:'random'
+ })
+ .then((resp) => {
+ expect(resp.check_result).to.be.false
+ })
+ })
+
+ it('successfully reset password', () => {
+ const newPassword = '11111'
+ return client.keys.resetPassword({
+ xpub: keyXpub,
+ old_password: password,
+ new_password: newPassword
+ })
+ .then((resp) => {
+ expect(resp.changed).to.be.true
+ })
+ })
+
+
+
+ })
+
+})
\ No newline at end of file
--- /dev/null
+const bytom = require('../dist/index.js')
+const uuid = require('uuid')
+const url = 'http://localhost:9888'
+const accessToken = ''
+
+const client = new bytom.Client(url, accessToken)
+
+const balanceByAssetAlias = (balances) => {
+ let res = {}
+ return Promise.resolve(balances)
+ .then((balance) => {
+ balance.forEach((item) => {
+ res[item.sumBy.assetAlias] = item.amount
+ })
+ return res
+ })
+}
+
+const createAccount = (account = 'account') => {
+ return client.keys.listAll()
+ .then((keys) => {
+ return client.accounts.create({
+ alias: `${account}-${uuid.v4()}`,
+ root_xpubs: [keys[0].xpub],
+ quorum: 1
+ })
+ })
+}
+
+const createAccountReciever = (accountAlias = 'account') => {
+ return client.accounts.createReceiver({
+ account_alias: accountAlias
+ })
+}
+
+const createAsset = (asset = 'asset') => {
+ return client.keys.listAll()
+ .then((keys) => {
+ return client.assets.create({
+ alias: `${asset}-${uuid.v4()}`,
+ definition: {
+ decimals: 8,
+ description: {},
+ name: `${asset}-${uuid.v4()}`,
+ symbol: `${asset}-${uuid.v4()}`
+ },
+ root_xpubs: [keys[0].xpub],
+ quorum: 1
+ })
+ })
+}
+
+const buildSignSubmit = (buildFunc, optClient, password) => {
+ const c = optClient || client
+ return c.transactions.build(buildFunc)
+ .then(tpl => c.transactions.sign({
+ transaction: tpl,
+ password
+ }))
+ .then(tpl => c.transactions.submit(tpl.transaction.raw_transaction))
+}
+
+module.exports = {
+ // balanceByAssetAlias,
+ client,
+ createAccount,
+ createAsset,
+ createAccountReciever,
+ buildSignSubmit,
+}
\ No newline at end of file
--- /dev/null
+
+/* eslint-env mocha */
+
+const assert = require('assert')
+const chai = require('chai')
+const chaiAsPromised = require('chai-as-promised')
+
+chai.use(chaiAsPromised)
+const expect = chai.expect
+
+const { balanceByAssetAlias, client, createAccount, createAsset, createAccountReciever } = require('./testHelpers')
+
+const btmAlias = 'BTM'
+
+describe('Transaction', () => {
+ describe('Transfer btm', () => {
+ let aliceAlias, bobAlias, aliceAddress, bobAddress, txId
+
+ before(() => {
+ return Promise.all([
+ createAccount('alice'),
+ createAccount('bob')
+ ])
+ .then((objects) => {
+ aliceAlias = objects[0].alias
+ bobAlias = objects[1].alias
+ return Promise.all([
+ createAccountReciever(aliceAlias),
+ createAccountReciever(bobAlias)
+ ])
+ })
+ .then((objects) => {
+ aliceAddress = objects[0].address
+ bobAddress = objects[1].address
+ })
+ .then(() => client.transactions.build(builder => {
+ builder.spendFromAccount({
+ account_alias: 'default',
+ asset_alias: btmAlias,
+ amount: 310000000
+ })
+ builder.controlWithAddress({
+ address: aliceAddress,
+ asset_alias: btmAlias,
+ amount: 100000000
+ })
+ builder.controlWithAddress({
+ address: bobAddress,
+ asset_alias: btmAlias,
+ amount: 200000000
+ })
+ }))
+ .then((issuance) =>{
+ return client.transactions.sign({transaction: issuance, password: '12345'})})
+ .then((signed) => {
+ return client.transactions.submit(signed.transaction.raw_transaction)
+ })
+ .then((tx) => txId= tx.tx_id)
+ })
+
+ it('transfer 1 BTM to alice', () => {
+ return client.transactions.list({id: txId, unconfirmed:true})
+ .then((resp) => {
+ expect(resp[0].outputs.map(item => item.account_alias)).include(aliceAlias)
+ })
+ })
+
+ it('transfer 1 BTM to bob', () => {
+ return client.transactions.list({id: txId, unconfirmed:true})
+ .then((resp) => {
+ expect(resp[0].outputs.map(item => item.account_alias)).include(bobAlias)
+ })
+ })
+ })
+
+ describe('Issuance', () => {
+ let goldAlias, silverAlias, aliceAlias, bobAlias,
+ aliceAddress, bobAddress, txId
+
+ before(() => {
+ return Promise.all([
+ createAsset('gold'),
+ createAsset('silver'),
+ createAccount('alice'),
+ createAccount('bob')
+ ])
+ .then((objects) => {
+ goldAlias = objects[0].alias
+ silverAlias = objects[1].alias
+ aliceAlias = objects[2].alias
+ bobAlias = objects[3].alias
+ return Promise.all([
+ createAccountReciever(aliceAlias),
+ createAccountReciever(bobAlias)
+ ])
+ })
+ .then((objects) => {
+ aliceAddress = objects[0].address
+ bobAddress = objects[1].address
+ })
+ .then(() => client.transactions.build(builder => {
+ builder.spendFromAccount({
+ account_alias: 'default',
+ asset_alias: btmAlias,
+ amount: 10000000
+ })
+ builder.issue({
+ asset_alias: goldAlias,
+ amount: 1000000
+ })
+ builder.issue({
+ asset_alias: silverAlias,
+ amount: 2000000
+ })
+ builder.controlWithAddress({
+ address: aliceAddress,
+ asset_alias: goldAlias,
+ amount: 1000000
+ })
+ builder.controlWithAddress({
+ address: bobAddress,
+ asset_alias: silverAlias,
+ amount: 2000000
+ })
+ }))
+ .then((issuance) => client.transactions.sign({transaction: issuance, password: '12345'}))
+ .then((signed) => client.transactions.submit(signed.transaction.raw_transaction))
+ .then((tx) => txId= tx.tx_id)
+ })
+
+ it('issues 100 units of gold to alice', () => {
+ return client.transactions.list({id: txId, unconfirmed:true})
+ .then((resp) => {
+ expect(resp[0].outputs.map(item => item.account_alias)).include(aliceAlias)
+ })
+ })
+
+ it('issues 200 units of silver to bob', () => {
+ return client.transactions.list({id: txId, unconfirmed:true})
+ .then((resp) => {
+ expect(resp[0].outputs.map(item => item.account_alias)).include(bobAlias)
+ })
+ })
+ })
+
+
+
+ describe('listAll', () => {
+ it('success example', () => {
+ let created, accountAlias
+
+ return createAccount().then((account) => {
+ accountAlias = account.alias
+ return createAccountReciever(accountAlias)
+ }
+ ).then((resp) =>
+ client.transactions.build(builder => {
+ builder.spendFromAccount({
+ account_alias: 'default',
+ asset_alias: btmAlias,
+ amount: 100000000
+ })
+ builder.controlWithAddress({
+ address: resp.address,
+ asset_alias: btmAlias,
+ amount: 90000000
+ })
+ })
+ ).then(txtpl =>
+ client.transactions.sign({
+ transaction: txtpl,
+ password: '12345'
+ })
+ ).then(signed =>
+ client.transactions.submit(signed.transaction.raw_transaction)
+ ).then(tx =>
+ created = tx.tx_id
+ ).then(() =>
+ client.transactions.listAll()
+ ).then(resp =>{
+ expect(resp.map(item => item.tx_id)).to.include(created)
+ }
+ )
+ })
+ })
+
+ describe('Builder function errors', () => {
+ it('rejects via promise', () =>
+ expect(
+ client.transactions.build(() => {
+ throw new Error("test error")
+ })
+ ).to.be.rejectedWith("test error")
+ )
+ })
+
+})
\ No newline at end of file
--- /dev/null
+/* eslint-env mocha */
+
+const chai = require('chai')
+const chaiAsPromised = require('chai-as-promised')
+chai.use(chaiAsPromised)
+const expect = chai.expect
+
+const {
+ client,
+} = require('./testHelpers')
+
+describe('Unspent output', () => {
+
+ describe('listAll', () => {
+ it('simple example', () => {
+ return client.unspentOutputs.listAll().then((resp) => {
+ expect(resp).not.to.be.empty
+ })
+ })
+ })
+
+})
\ No newline at end of file