mirror of
https://github.com/bigchaindb/js-bigchaindb-driver.git
synced 2024-11-22 01:36:56 +01:00
commit
0b0ea0a97e
@ -4,7 +4,7 @@ node_js: node
|
||||
install: npm install
|
||||
|
||||
script:
|
||||
- npm run clean
|
||||
- npm test
|
||||
- npm run build
|
||||
|
||||
cache:
|
||||
|
@ -18,11 +18,12 @@
|
||||
"build:cjs": "cross-env BABEL_ENV=cjs babel ./src -d dist/node",
|
||||
"build:dist": "cross-env NODE_ENV=production webpack -p",
|
||||
"clean": "rimraf dist/bundle dist/node",
|
||||
"test": "echo \"Error: no test specified AWWWW YEAHHH\" && exit 1",
|
||||
"test": "npm run lint",
|
||||
"release": "./node_modules/release-it/bin/release.js --src.tagName='v%s' --github.release --npm.publish --non-interactive",
|
||||
"release-minor": "./node_modules/release-it/bin/release.js minor --src.tagName='v%s' --github.release --npm.publish --non-interactive",
|
||||
"release-major": "./node_modules/release-it/bin/release.js major --src.tagName='v%s' --github.release --npm.publish --non-interactive",
|
||||
"postinstall": "npm run build"
|
||||
"postinstall": "npm run build",
|
||||
"precommit": "npm run lint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.22.2",
|
||||
@ -41,6 +42,7 @@
|
||||
"eslint": "^3.14.1",
|
||||
"eslint-config-ascribe": "^3.0.1",
|
||||
"eslint-plugin-import": "^2.2.0",
|
||||
"husky": "^0.13.4",
|
||||
"release-it": "^2.7.3",
|
||||
"rimraf": "^2.5.4",
|
||||
"webpack": "^2.2.1"
|
||||
@ -58,6 +60,7 @@
|
||||
"js-sha3": "^0.5.7",
|
||||
"js-utility-belt": "^1.5.0",
|
||||
"json-stable-stringify": "^1.0.1",
|
||||
"query-string": "^4.3.4",
|
||||
"sprintf-js": "^1.0.3",
|
||||
"tweetnacl": "^1.0.0"
|
||||
},
|
||||
|
@ -1,6 +1,5 @@
|
||||
import base58 from 'bs58';
|
||||
import nacl from 'tweetnacl';
|
||||
import sha3 from 'js-sha3';
|
||||
import base58 from 'bs58'
|
||||
import nacl from 'tweetnacl'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@ -11,8 +10,8 @@ import sha3 from 'js-sha3';
|
||||
* @property {string} privateKey
|
||||
*/
|
||||
export default function Ed25519Keypair(seed) {
|
||||
const keyPair = seed ? nacl.sign.keyPair.fromSeed(seed) : nacl.sign.keyPair();
|
||||
this.publicKey = base58.encode(keyPair.publicKey);
|
||||
const keyPair = seed ? nacl.sign.keyPair.fromSeed(seed) : nacl.sign.keyPair()
|
||||
this.publicKey = base58.encode(keyPair.publicKey)
|
||||
// tweetnacl's generated secret key is the secret key + public key (resulting in a 64-byte buffer)
|
||||
this.privateKey = base58.encode(keyPair.secretKey.slice(0, 32));
|
||||
this.privateKey = base58.encode(keyPair.secretKey.slice(0, 32))
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { Promise } from 'es6-promise';
|
||||
import fetchPonyfill from 'fetch-ponyfill';
|
||||
import { vsprintf } from 'sprintf-js';
|
||||
import { Promise } from 'es6-promise'
|
||||
import fetchPonyfill from 'fetch-ponyfill'
|
||||
import { vsprintf } from 'sprintf-js'
|
||||
|
||||
import formatText from './format_text';
|
||||
import formatText from './format_text'
|
||||
|
||||
import stringifyAsQueryParam from './stringify_as_query_param';
|
||||
import stringifyAsQueryParam from './stringify_as_query_param'
|
||||
|
||||
|
||||
const fetch = fetchPonyfill(Promise);
|
||||
const fetch = fetchPonyfill(Promise)
|
||||
|
||||
|
||||
/**
|
||||
@ -38,35 +38,35 @@ const fetch = fetchPonyfill(Promise);
|
||||
* otherwise rejects with the response
|
||||
*/
|
||||
export default function baseRequest(url, { jsonBody, query, urlTemplateSpec, ...fetchConfig } = {}) {
|
||||
let expandedUrl = url;
|
||||
let expandedUrl = url
|
||||
|
||||
if (urlTemplateSpec != null) {
|
||||
if (Array.isArray(urlTemplateSpec) && urlTemplateSpec.length) {
|
||||
// Use vsprintf for the array call signature
|
||||
expandedUrl = vsprintf(url, urlTemplateSpec);
|
||||
expandedUrl = vsprintf(url, urlTemplateSpec)
|
||||
} else if (urlTemplateSpec &&
|
||||
typeof urlTemplateSpec === 'object' &&
|
||||
Object.keys(urlTemplateSpec).length) {
|
||||
expandedUrl = formatText(url, urlTemplateSpec);
|
||||
expandedUrl = formatText(url, urlTemplateSpec)
|
||||
} else if (process.env.NODE_ENV !== 'production') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('Supplied urlTemplateSpec was not an array or object. Ignoring...');
|
||||
console.warn('Supplied urlTemplateSpec was not an array or object. Ignoring...')
|
||||
}
|
||||
}
|
||||
|
||||
if (query != null) {
|
||||
if (typeof query === 'string') {
|
||||
expandedUrl += query;
|
||||
expandedUrl += query
|
||||
} else if (query && typeof query === 'object') {
|
||||
expandedUrl += stringifyAsQueryParam(query);
|
||||
expandedUrl += stringifyAsQueryParam(query)
|
||||
} else if (process.env.NODE_ENV !== 'production') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('Supplied query was not a string or object. Ignoring...');
|
||||
console.warn('Supplied query was not a string or object. Ignoring...')
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonBody != null) {
|
||||
fetchConfig.body = JSON.stringify(jsonBody);
|
||||
fetchConfig.body = JSON.stringify(jsonBody)
|
||||
}
|
||||
|
||||
return fetch.fetch(expandedUrl, fetchConfig)
|
||||
@ -74,8 +74,8 @@ export default function baseRequest(url, { jsonBody, query, urlTemplateSpec, ...
|
||||
// If status is not a 2xx (based on Response.ok), assume it's an error
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
|
||||
if (!(res && res.ok)) {
|
||||
throw res;
|
||||
throw res
|
||||
}
|
||||
return res;
|
||||
});
|
||||
}
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
import request from '../request';
|
||||
import request from '../request'
|
||||
|
||||
|
||||
export default class Connection {
|
||||
constructor(path, headers) {
|
||||
this.path = path;
|
||||
this.headers = headers;
|
||||
this.path = path
|
||||
this.headers = headers
|
||||
}
|
||||
|
||||
getApiUrls(endpoints) {
|
||||
// TODO: Use camel case
|
||||
return {
|
||||
'blocks': this.path + 'blocks',
|
||||
'blocks_detail': this.path + 'blocks/%(blockId)s',
|
||||
'outputs': this.path + 'outputs',
|
||||
'statuses': this.path + 'statuses',
|
||||
'transactions': this.path + 'transactions',
|
||||
'transactions_detail': this.path + 'transactions/%(txId)s',
|
||||
'search_assets': this.path + 'assets',
|
||||
'votes': this.path + 'votes'
|
||||
}[endpoints];
|
||||
'blocks': `${this.path}blocks`,
|
||||
'blocks_detail': `${this.path}blocks/%(blockId)s`,
|
||||
'outputs': `${this.path}outputs`,
|
||||
'statuses': `${this.path}statuses`,
|
||||
'transactions': `${this.path}transactions`,
|
||||
'transactions_detail': `${this.path}transactions/%(txId)s`,
|
||||
'search_assets': `${this.path}assets`,
|
||||
'votes': `${this.path}votes`
|
||||
}[endpoints]
|
||||
}
|
||||
|
||||
_req(path, options={}) {
|
||||
_req(path, options = {}) {
|
||||
// NOTE: `options.headers` could be undefined, but that's OK.
|
||||
options.headers = Object.assign({}, options.headers, this.headers)
|
||||
return request(path, options)
|
||||
@ -33,22 +33,22 @@ export default class Connection {
|
||||
*/
|
||||
getBlock(blockId) {
|
||||
return this._req(this.getApiUrls('blocks_detail'), {
|
||||
urlTemplateSpec: {
|
||||
blockId
|
||||
}
|
||||
});
|
||||
urlTemplateSpec: {
|
||||
blockId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @param tx_id
|
||||
*/
|
||||
getStatus(tx_id) {
|
||||
getStatus(tx_id) { // eslint-disable-line camelcase
|
||||
return this._req(this.getApiUrls('statuses'), {
|
||||
query: {
|
||||
tx_id
|
||||
}
|
||||
});
|
||||
query: {
|
||||
tx_id
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,10 +57,10 @@ export default class Connection {
|
||||
*/
|
||||
getTransaction(txId) {
|
||||
return this._req(this.getApiUrls('transactions_detail'), {
|
||||
urlTemplateSpec: {
|
||||
txId
|
||||
}
|
||||
});
|
||||
urlTemplateSpec: {
|
||||
txId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,11 +70,11 @@ export default class Connection {
|
||||
*/
|
||||
listBlocks({ tx_id, status }) {
|
||||
return this._req(this.getApiUrls('blocks'), {
|
||||
query: {
|
||||
tx_id,
|
||||
status
|
||||
}
|
||||
});
|
||||
query: {
|
||||
tx_id,
|
||||
status
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,7 +83,7 @@ export default class Connection {
|
||||
* @param unspent
|
||||
* @param onlyJsonResponse
|
||||
*/
|
||||
listOutputs({ public_key, unspent }, onlyJsonResponse=true) {
|
||||
listOutputs({ public_key, unspent }, onlyJsonResponse = true) {
|
||||
return this._req(this.getApiUrls('outputs'), {
|
||||
query: {
|
||||
public_key,
|
||||
@ -110,38 +110,38 @@ export default class Connection {
|
||||
* @public
|
||||
* @param block_id
|
||||
*/
|
||||
listVotes(block_id) {
|
||||
listVotes(block_id) { // eslint-disable-line camelcase
|
||||
return this._req(this.getApiUrls('votes'), {
|
||||
query: {
|
||||
block_id
|
||||
}
|
||||
});
|
||||
query: {
|
||||
block_id
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @param tx_id
|
||||
* @param txId
|
||||
* @return {Promise}
|
||||
*/
|
||||
pollStatusAndFetchTransaction(tx_id) {
|
||||
pollStatusAndFetchTransaction(txId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = setInterval(() => {
|
||||
this.getStatus(tx_id)
|
||||
this.getStatus(txId)
|
||||
.then((res) => {
|
||||
console.log('Fetched transaction status:', res);
|
||||
console.log('Fetched transaction status:', res) // eslint-disable-line no-console
|
||||
if (res.status === 'valid') {
|
||||
clearInterval(timer);
|
||||
this.getTransaction(tx_id)
|
||||
.then((res) => {
|
||||
console.log('Fetched transaction:', res);
|
||||
resolve(res);
|
||||
});
|
||||
clearInterval(timer)
|
||||
this.getTransaction(txId)
|
||||
.then((res_) => {
|
||||
console.log('Fetched transaction:', res_) // eslint-disable-line no-console
|
||||
resolve(res_)
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
clearInterval(timer);
|
||||
reject(err);
|
||||
});
|
||||
clearInterval(timer)
|
||||
reject(err)
|
||||
})
|
||||
}, 500)
|
||||
})
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { sprintf } from 'sprintf-js';
|
||||
import { sprintf } from 'sprintf-js'
|
||||
|
||||
|
||||
// Regexes taken from or inspired by sprintf-js
|
||||
const Regex = {
|
||||
TEMPLATE_LITERAL: /\${([^\)]+?)}/g,
|
||||
TEMPLATE_LITERAL: /\${([^)]+?)}/g,
|
||||
KEY: /^([a-z_][a-z_\d]*)/i,
|
||||
KEY_ACCESS: /^\.([a-z_][a-z_\d]*)/i,
|
||||
INDEX_ACCESS: /^\[(\d+)\]/
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* imported from https://github.com/bigchaindb/js-utility-belt/
|
||||
@ -37,14 +37,14 @@ const Regex = {
|
||||
* => 'Berlin is best known for its Currywurst'
|
||||
*/
|
||||
export default function formatText(s, ...argv) {
|
||||
let expandedFormatStr = s;
|
||||
let expandedFormatStr = s
|
||||
|
||||
// Try to replace formats of the form '${...}' if named replacement fields are used
|
||||
if (s && argv.length === 1 && typeof argv[0] === 'object') {
|
||||
const templateSpecObj = argv[0];
|
||||
const templateSpecObj = argv[0]
|
||||
|
||||
expandedFormatStr = s.replace(Regex.TEMPLATE_LITERAL, (match, replacement) => {
|
||||
let interpolationLeft = replacement;
|
||||
let interpolationLeft = replacement
|
||||
|
||||
/**
|
||||
* Interpolation algorithm inspired by sprintf-js.
|
||||
@ -61,21 +61,21 @@ export default function formatText(s, ...argv) {
|
||||
* And that in the regexes defined, the first matching group always corresponds to the
|
||||
* property matched.
|
||||
*/
|
||||
let value;
|
||||
let curMatch = Regex.KEY.exec(interpolationLeft);
|
||||
let value
|
||||
let curMatch = Regex.KEY.exec(interpolationLeft)
|
||||
if (curMatch !== null) {
|
||||
value = templateSpecObj[curMatch[1]];
|
||||
value = templateSpecObj[curMatch[1]]
|
||||
|
||||
// Assigning in the conditionals here makes the code less bloated
|
||||
/* eslint-disable no-cond-assign */
|
||||
while ((interpolationLeft = interpolationLeft.substring(curMatch[0].length)) &&
|
||||
value != null) {
|
||||
if ((curMatch = Regex.KEY_ACCESS.exec(interpolationLeft))) {
|
||||
value = value[curMatch[1]];
|
||||
value = value[curMatch[1]]
|
||||
} else if ((curMatch = Regex.INDEX_ACCESS.exec(interpolationLeft))) {
|
||||
value = value[curMatch[1]];
|
||||
value = value[curMatch[1]]
|
||||
} else {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
/* eslint-enable no-cond-assign */
|
||||
@ -86,12 +86,12 @@ export default function formatText(s, ...argv) {
|
||||
if (interpolationLeft.length) {
|
||||
throw new SyntaxError(
|
||||
`[formatText] failed to parse named argument key: ${replacement}`
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
return value;
|
||||
});
|
||||
return value
|
||||
})
|
||||
}
|
||||
|
||||
return sprintf(expandedFormatStr, ...argv);
|
||||
}
|
||||
return sprintf(expandedFormatStr, ...argv)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
export Ed25519Keypair from './Ed25519Keypair';
|
||||
export Ed25519Keypair from './Ed25519Keypair'
|
||||
|
||||
export * as Transaction from './transaction';
|
||||
export Connection from './connection';
|
||||
export * as Transaction from './transaction'
|
||||
export Connection from './connection'
|
||||
|
@ -1,43 +1,41 @@
|
||||
import baseRequest from './baseRequest';
|
||||
import sanitize from './sanitize';
|
||||
import baseRequest from './baseRequest'
|
||||
import sanitize from './sanitize'
|
||||
|
||||
|
||||
const DEFAULT_REQUEST_CONFIG = {
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Small wrapper around js-utility-belt's request that provides url resolving,
|
||||
* default settings, and response handling.
|
||||
*/
|
||||
export default function request(url, config = {}, onlyJsonResponse=true) {
|
||||
export default function request(url, config = {}, onlyJsonResponse = true) {
|
||||
// Load default fetch configuration and remove any falsy query parameters
|
||||
const requestConfig = Object.assign({}, DEFAULT_REQUEST_CONFIG, config, {
|
||||
query: config.query && sanitize(config.query)
|
||||
});
|
||||
let apiUrl = url;
|
||||
})
|
||||
const apiUrl = url
|
||||
|
||||
if (requestConfig.jsonBody) {
|
||||
requestConfig.headers = Object.assign({}, requestConfig.headers, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
})
|
||||
}
|
||||
if (!url) {
|
||||
return Promise.reject(new Error('Request was not given a url.'));
|
||||
return Promise.reject(new Error('Request was not given a url.'))
|
||||
}
|
||||
|
||||
return baseRequest(apiUrl, requestConfig)
|
||||
.then((res) => {
|
||||
return onlyJsonResponse ? res.json() :
|
||||
{
|
||||
json: res.json(),
|
||||
url: res.url
|
||||
};
|
||||
.then((res) => onlyJsonResponse ? res.json() : // eslint-disable-line no-confusing-arrow
|
||||
{
|
||||
json: res.json(),
|
||||
url: res.url
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
throw err;
|
||||
});
|
||||
console.error(err)
|
||||
throw err
|
||||
})
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import coreIncludes from 'core-js/library/fn/array/includes';
|
||||
import coreObjectEntries from 'core-js/library/fn/object/entries';
|
||||
import coreIncludes from 'core-js/library/fn/array/includes'
|
||||
import coreObjectEntries from 'core-js/library/fn/object/entries'
|
||||
|
||||
|
||||
/**
|
||||
@ -10,13 +10,13 @@ import coreObjectEntries from 'core-js/library/fn/object/entries';
|
||||
function filterFromObject(obj, filter, { isInclusion = true } = {}) {
|
||||
if (filter && Array.isArray(filter)) {
|
||||
return applyFilterOnObject(obj, isInclusion ? ((_, key) => coreIncludes(filter, key))
|
||||
: ((_, key) => !coreIncludes(filter, key)));
|
||||
: ((_, key) => !coreIncludes(filter, key)))
|
||||
} else if (filter && typeof filter === 'function') {
|
||||
// Flip the filter fn's return if it's for inclusion
|
||||
return applyFilterOnObject(obj, isInclusion ? filter
|
||||
: (...args) => !filter(...args));
|
||||
: (...args) => !filter(...args))
|
||||
} else {
|
||||
throw new Error('The given filter is not an array or function. Exclude aborted');
|
||||
throw new Error('The given filter is not an array or function. Exclude aborted')
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,17 +26,17 @@ function filterFromObject(obj, filter, { isInclusion = true } = {}) {
|
||||
*/
|
||||
function applyFilterOnObject(obj, filterFn) {
|
||||
if (filterFn == null) {
|
||||
return Object.assign({}, obj);
|
||||
return Object.assign({}, obj)
|
||||
}
|
||||
|
||||
const filteredObj = {};
|
||||
const filteredObj = {}
|
||||
coreObjectEntries(obj).forEach(([key, val]) => {
|
||||
if (filterFn(val, key)) {
|
||||
filteredObj[key] = val;
|
||||
filteredObj[key] = val
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
return filteredObj;
|
||||
return filteredObj
|
||||
}
|
||||
|
||||
/**
|
||||
@ -48,7 +48,7 @@ function applyFilterOnObject(obj, filterFn) {
|
||||
* @return {object} The new object
|
||||
*/
|
||||
function selectFromObject(obj, filter) {
|
||||
return filterFromObject(obj, filter);
|
||||
return filterFromObject(obj, filter)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,5 +60,5 @@ function selectFromObject(obj, filter) {
|
||||
* @return {object} Sanitized Javascript object
|
||||
*/
|
||||
export default function sanitize(obj) {
|
||||
return selectFromObject(obj, (val) => !!val);
|
||||
return selectFromObject(obj, (val) => !!val)
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import sha3 from 'js-sha3';
|
||||
import sha3 from 'js-sha3'
|
||||
|
||||
export default function sha256Hash(data) {
|
||||
return sha3.sha3_256
|
||||
.create()
|
||||
.update(data)
|
||||
.hex();
|
||||
.hex()
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import coreObjectEntries from 'core-js/library/fn/object/entries';
|
||||
import decamelize from 'decamelize';
|
||||
import queryString from 'query-string';
|
||||
import coreObjectEntries from 'core-js/library/fn/object/entries'
|
||||
import decamelize from 'decamelize'
|
||||
import queryString from 'query-string'
|
||||
|
||||
|
||||
/**
|
||||
@ -30,13 +30,13 @@ import queryString from 'query-string';
|
||||
*/
|
||||
export default function stringifyAsQueryParam(obj, transform = decamelize) {
|
||||
if (!obj || typeof obj !== 'object' || !Object.keys(obj).length) {
|
||||
return '';
|
||||
return ''
|
||||
}
|
||||
|
||||
const transformedKeysObj = coreObjectEntries(obj).reduce((paramsObj, [key, value]) => {
|
||||
paramsObj[transform(key)] = value;
|
||||
return paramsObj;
|
||||
}, {});
|
||||
paramsObj[transform(key)] = value
|
||||
return paramsObj
|
||||
}, {})
|
||||
|
||||
return `?${queryString.stringify(transformedKeysObj)}`;
|
||||
}
|
||||
return `?${queryString.stringify(transformedKeysObj)}`
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import serializeTransactionIntoCanonicalString from './serializeTransactionIntoCanonicalString';
|
||||
import sha256Hash from '../sha256Hash';
|
||||
import serializeTransactionIntoCanonicalString from './serializeTransactionIntoCanonicalString'
|
||||
import sha256Hash from '../sha256Hash'
|
||||
|
||||
export default function hashTransaction(transaction) {
|
||||
// Safely remove any tx id from the given transaction for hashing
|
||||
const tx = { ...transaction };
|
||||
delete tx.id;
|
||||
const tx = { ...transaction }
|
||||
delete tx.id
|
||||
|
||||
return sha256Hash(serializeTransactionIntoCanonicalString(tx));
|
||||
}
|
||||
return sha256Hash(serializeTransactionIntoCanonicalString(tx))
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
export makeEd25519Condition from './makeEd25519Condition';
|
||||
export makeSha256Condition from './makeSha256Condition';
|
||||
export makeThresholdCondition from './makeThresholdCondition';
|
||||
export makeCreateTransaction from './makeCreateTransaction';
|
||||
export makeOutput from './makeOutput';
|
||||
export makeTransaction from './makeTransaction';
|
||||
export makeTransferTransaction from './makeTransferTransaction';
|
||||
export serializeTransactionIntoCanonicalString from './serializeTransactionIntoCanonicalString';
|
||||
export signTransaction from './signTransaction';
|
||||
export ccJsonLoad from './utils/ccJsonLoad';
|
||||
export ccJsonify from './utils/ccJsonify';
|
||||
export makeEd25519Condition from './makeEd25519Condition'
|
||||
export makeSha256Condition from './makeSha256Condition'
|
||||
export makeThresholdCondition from './makeThresholdCondition'
|
||||
export makeCreateTransaction from './makeCreateTransaction'
|
||||
export makeOutput from './makeOutput'
|
||||
export makeTransaction from './makeTransaction'
|
||||
export makeTransferTransaction from './makeTransferTransaction'
|
||||
export serializeTransactionIntoCanonicalString from './serializeTransactionIntoCanonicalString'
|
||||
export signTransaction from './signTransaction'
|
||||
export ccJsonLoad from './utils/ccJsonLoad'
|
||||
export ccJsonify from './utils/ccJsonify'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import makeInputTemplate from './makeInputTemplate';
|
||||
import makeTransaction from './makeTransaction';
|
||||
import makeInputTemplate from './makeInputTemplate'
|
||||
import makeTransaction from './makeTransaction'
|
||||
|
||||
|
||||
/**
|
||||
@ -24,8 +24,8 @@ import makeTransaction from './makeTransaction';
|
||||
export default function makeCreateTransaction(asset, metadata, outputs, ...issuers) {
|
||||
const assetDefinition = {
|
||||
'data': asset || null,
|
||||
};
|
||||
const inputs = issuers.map((issuer) => makeInputTemplate([issuer]));
|
||||
}
|
||||
const inputs = issuers.map((issuer) => makeInputTemplate([issuer]))
|
||||
|
||||
return makeTransaction('CREATE', assetDefinition, metadata, outputs, inputs);
|
||||
}
|
||||
return makeTransaction('CREATE', assetDefinition, metadata, outputs, inputs)
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Buffer } from 'buffer';
|
||||
import { Buffer } from 'buffer'
|
||||
|
||||
import base58 from 'bs58';
|
||||
import cc from 'five-bells-condition';
|
||||
import base58 from 'bs58'
|
||||
import cc from 'five-bells-condition'
|
||||
|
||||
import ccJsonify from './utils/ccJsonify';
|
||||
import ccJsonify from './utils/ccJsonify'
|
||||
|
||||
|
||||
/**
|
||||
@ -13,15 +13,15 @@ import ccJsonify from './utils/ccJsonify';
|
||||
* @param {boolean} [json=true] If true returns a json object otherwise a crypto-condition type
|
||||
* @returns {object} Ed25519 Condition (that will need to wrapped in an Output)
|
||||
*/
|
||||
export default function makeEd25519Condition(publicKey, json=true) {
|
||||
const publicKeyBuffer = new Buffer(base58.decode(publicKey));
|
||||
export default function makeEd25519Condition(publicKey, json = true) {
|
||||
const publicKeyBuffer = new Buffer(base58.decode(publicKey))
|
||||
|
||||
const ed25519Fulfillment = new cc.Ed25519();
|
||||
ed25519Fulfillment.setPublicKey(publicKeyBuffer);
|
||||
const ed25519Fulfillment = new cc.Ed25519()
|
||||
ed25519Fulfillment.setPublicKey(publicKeyBuffer)
|
||||
|
||||
if (json) {
|
||||
return ccJsonify(ed25519Fulfillment)
|
||||
}
|
||||
|
||||
return ed25519Fulfillment;
|
||||
return ed25519Fulfillment
|
||||
}
|
||||
|
@ -3,5 +3,5 @@ export default function makeInputTemplate(publicKeys = [], fulfills = null, fulf
|
||||
fulfillment,
|
||||
fulfills,
|
||||
'owners_before': publicKeys,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,9 @@
|
||||
*/
|
||||
export default function makeOutput(condition, amount = 1) {
|
||||
return {
|
||||
amount: amount.toString(),
|
||||
'amount': amount.toString(),
|
||||
condition,
|
||||
'public_keys': condition.details.hasOwnProperty('public_key') ?
|
||||
[condition.details.public_key] : [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Buffer } from 'buffer';
|
||||
import { Buffer } from 'buffer'
|
||||
|
||||
import cc from 'five-bells-condition';
|
||||
import cc from 'five-bells-condition'
|
||||
|
||||
import ccJsonify from './utils/ccJsonify';
|
||||
import ccJsonify from './utils/ccJsonify'
|
||||
|
||||
|
||||
/**
|
||||
@ -12,12 +12,12 @@ import ccJsonify from './utils/ccJsonify';
|
||||
* @param {boolean} [json=true] If true returns a json object otherwise a crypto-condition type
|
||||
* @returns {object} Preimage-Sha256 Condition (that will need to wrapped in an Output)
|
||||
*/
|
||||
export default function makeSha256Condition(preimage, json=true) {
|
||||
const sha256Fulfillment = new cc.PreimageSha256();
|
||||
sha256Fulfillment.preimage = new Buffer(preimage);
|
||||
export default function makeSha256Condition(preimage, json = true) {
|
||||
const sha256Fulfillment = new cc.PreimageSha256()
|
||||
sha256Fulfillment.preimage = new Buffer(preimage)
|
||||
|
||||
if (json) {
|
||||
return ccJsonify(sha256Fulfillment)
|
||||
}
|
||||
return sha256Fulfillment;
|
||||
return sha256Fulfillment
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import cc from 'five-bells-condition';
|
||||
import cc from 'five-bells-condition'
|
||||
|
||||
import ccJsonify from './utils/ccJsonify';
|
||||
import ccJsonify from './utils/ccJsonify'
|
||||
|
||||
|
||||
/**
|
||||
@ -11,14 +11,14 @@ import ccJsonify from './utils/ccJsonify';
|
||||
* @param {boolean} [json=true] If true returns a json object otherwise a crypto-condition type
|
||||
* @returns {object} Sha256 Threshold Condition (that will need to wrapped in an Output)
|
||||
*/
|
||||
export default function makeThresholdCondition(threshold, subconditions=[], json=true) {
|
||||
const thresholdCondition = new cc.ThresholdSha256();
|
||||
thresholdCondition.threshold = threshold;
|
||||
export default function makeThresholdCondition(threshold, subconditions = [], json = true) {
|
||||
const thresholdCondition = new cc.ThresholdSha256()
|
||||
thresholdCondition.threshold = threshold
|
||||
|
||||
subconditions.forEach((subcondition) => {
|
||||
// TODO: add support for Condition and URIs
|
||||
thresholdCondition.addSubfulfillment(subcondition);
|
||||
});
|
||||
thresholdCondition.addSubfulfillment(subcondition)
|
||||
})
|
||||
|
||||
if (json) {
|
||||
return ccJsonify(thresholdCondition)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import hashTransaction from './hashTransaction';
|
||||
import hashTransaction from './hashTransaction'
|
||||
|
||||
|
||||
function makeTransactionTemplate() {
|
||||
@ -10,19 +10,19 @@ function makeTransactionTemplate() {
|
||||
'metadata': null,
|
||||
'asset': null,
|
||||
'version': '0.9',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default function makeTransaction(operation, asset, metadata = null, outputs = [], inputs = []) {
|
||||
const tx = makeTransactionTemplate();
|
||||
tx.operation = operation;
|
||||
tx.asset = asset;
|
||||
tx.metadata = metadata;
|
||||
tx.inputs = inputs;
|
||||
tx.outputs = outputs;
|
||||
const tx = makeTransactionTemplate()
|
||||
tx.operation = operation
|
||||
tx.asset = asset
|
||||
tx.metadata = metadata
|
||||
tx.inputs = inputs
|
||||
tx.outputs = outputs
|
||||
|
||||
// Hashing must be done after, as the hash is of the Transaction (up to now)
|
||||
tx.id = hashTransaction(tx);
|
||||
return tx;
|
||||
tx.id = hashTransaction(tx)
|
||||
return tx
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import makeInputTemplate from './makeInputTemplate';
|
||||
import makeTransaction from './makeTransaction';
|
||||
import makeInputTemplate from './makeInputTemplate'
|
||||
import makeTransaction from './makeTransaction'
|
||||
|
||||
|
||||
/**
|
||||
@ -22,21 +22,26 @@ import makeTransaction from './makeTransaction';
|
||||
* @returns {object} Unsigned transaction -- make sure to call signTransaction() on it before
|
||||
* sending it off!
|
||||
*/
|
||||
export default function makeTransferTransaction(unspentTransaction, metadata, outputs, ...fulfilledOutputs) {
|
||||
export default function makeTransferTransaction(
|
||||
unspentTransaction,
|
||||
metadata,
|
||||
outputs,
|
||||
...fulfilledOutputs
|
||||
) {
|
||||
const inputs = fulfilledOutputs.map((outputIndex) => {
|
||||
const fulfilledOutput = unspentTransaction.outputs[outputIndex];
|
||||
const fulfilledOutput = unspentTransaction.outputs[outputIndex]
|
||||
const transactionLink = {
|
||||
'output': outputIndex,
|
||||
'txid': unspentTransaction.id,
|
||||
};
|
||||
}
|
||||
|
||||
return makeInputTemplate(fulfilledOutput.public_keys, transactionLink);
|
||||
});
|
||||
return makeInputTemplate(fulfilledOutput.public_keys, transactionLink)
|
||||
})
|
||||
|
||||
const assetLink = {
|
||||
'id': unspentTransaction.operation === 'CREATE' ? unspentTransaction.id
|
||||
: unspentTransaction.asset.id
|
||||
};
|
||||
}
|
||||
|
||||
return makeTransaction('TRANSFER', assetLink, metadata, outputs, inputs);
|
||||
return makeTransaction('TRANSFER', assetLink, metadata, outputs, inputs)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import stableStringify from 'json-stable-stringify';
|
||||
import clone from 'clone';
|
||||
import stableStringify from 'json-stable-stringify'
|
||||
import clone from 'clone'
|
||||
|
||||
|
||||
/**
|
||||
@ -10,8 +10,8 @@ import clone from 'clone';
|
||||
*/
|
||||
export default function serializeTransactionIntoCanonicalString(transaction) {
|
||||
// BigchainDB signs fulfillments by serializing transactions into a "canonical" format where
|
||||
const tx = clone(transaction);
|
||||
const tx = clone(transaction)
|
||||
// TODO: set fulfillments to null
|
||||
// Sort the keys
|
||||
return stableStringify(tx, (a, b) => (a.key > b.key ? 1 : -1));
|
||||
}
|
||||
return stableStringify(tx, (a, b) => (a.key > b.key ? 1 : -1))
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Buffer } from 'buffer';
|
||||
import base58 from 'bs58';
|
||||
import cc from 'five-bells-condition';
|
||||
import clone from 'clone';
|
||||
import { Buffer } from 'buffer'
|
||||
import base58 from 'bs58'
|
||||
import cc from 'five-bells-condition'
|
||||
import clone from 'clone'
|
||||
|
||||
import serializeTransactionIntoCanonicalString from './serializeTransactionIntoCanonicalString';
|
||||
import serializeTransactionIntoCanonicalString from './serializeTransactionIntoCanonicalString'
|
||||
|
||||
|
||||
/**
|
||||
@ -19,17 +19,17 @@ import serializeTransactionIntoCanonicalString from './serializeTransactionIntoC
|
||||
* @returns {object} The signed version of `transaction`.
|
||||
*/
|
||||
export default function signTransaction(transaction, ...privateKeys) {
|
||||
const signedTx = clone(transaction);
|
||||
const signedTx = clone(transaction)
|
||||
signedTx.inputs.forEach((input, index) => {
|
||||
const privateKey = privateKeys[index];
|
||||
const privateKeyBuffer = new Buffer(base58.decode(privateKey));
|
||||
const serializedTransaction = serializeTransactionIntoCanonicalString(transaction);
|
||||
const ed25519Fulfillment = new cc.Ed25519();
|
||||
ed25519Fulfillment.sign(new Buffer(serializedTransaction), privateKeyBuffer);
|
||||
const fulfillmentUri = ed25519Fulfillment.serializeUri();
|
||||
const privateKey = privateKeys[index]
|
||||
const privateKeyBuffer = new Buffer(base58.decode(privateKey))
|
||||
const serializedTransaction = serializeTransactionIntoCanonicalString(transaction)
|
||||
const ed25519Fulfillment = new cc.Ed25519()
|
||||
ed25519Fulfillment.sign(new Buffer(serializedTransaction), privateKeyBuffer)
|
||||
const fulfillmentUri = ed25519Fulfillment.serializeUri()
|
||||
|
||||
input.fulfillment = fulfillmentUri;
|
||||
});
|
||||
input.fulfillment = fulfillmentUri
|
||||
})
|
||||
|
||||
return signedTx;
|
||||
return signedTx
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import base58 from 'bs58';
|
||||
import cc from 'five-bells-condition';
|
||||
import { Buffer } from 'buffer';
|
||||
import { Buffer } from 'buffer'
|
||||
import base58 from 'bs58'
|
||||
import cc from 'five-bells-condition'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@ -9,41 +9,41 @@ import { Buffer } from 'buffer';
|
||||
* @returns {cc.Condition} Ed25519 Condition (that will need to wrapped in an Output)
|
||||
*/
|
||||
export default function ccJsonLoad(conditionJson) {
|
||||
|
||||
if ('hash' in conditionJson) {
|
||||
let condition = new cc.Condition();
|
||||
condition.type = conditionJson.type_id;
|
||||
condition.bitmask = conditionJson.bitmask;
|
||||
condition.hash = new Buffer(base58.decode(conditionJson.hash));
|
||||
condition.maxFulfillmentLength = parseInt(conditionJson.max_fulfillment_length, 10);
|
||||
const condition = new cc.Condition()
|
||||
condition.type = conditionJson.type_id
|
||||
condition.bitmask = conditionJson.bitmask
|
||||
condition.hash = new Buffer(base58.decode(conditionJson.hash))
|
||||
condition.maxFulfillmentLength = parseInt(conditionJson.max_fulfillment_length, 10)
|
||||
return condition
|
||||
} else {
|
||||
let fulfillment;
|
||||
let fulfillment
|
||||
|
||||
if (conditionJson.type_id === 2) {
|
||||
fulfillment = new cc.ThresholdSha256();
|
||||
fulfillment.threshold = conditionJson.threshold;
|
||||
conditionJson.subfulfillments.forEach((subfulfillment) => {
|
||||
subfulfillment = ccJsonLoad(subfulfillment);
|
||||
if ('getConditionUri' in subfulfillment)
|
||||
fulfillment.addSubfulfillment(subfulfillment);
|
||||
else if ('serializeUri' in subfulfillment)
|
||||
fulfillment = new cc.ThresholdSha256()
|
||||
fulfillment.threshold = conditionJson.threshold
|
||||
conditionJson.subfulfillments.forEach((subfulfillmentJson) => {
|
||||
const subfulfillment = ccJsonLoad(subfulfillmentJson)
|
||||
if ('getConditionUri' in subfulfillment) {
|
||||
fulfillment.addSubfulfillment(subfulfillment)
|
||||
} else if ('serializeUri' in subfulfillment) {
|
||||
fulfillment.addSubcondition(subfulfillment)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (conditionJson.type_id === 0) {
|
||||
fulfillment = new cc.PreimageSha256();
|
||||
fulfillment.preimage = new Buffer(conditionJson.preimage);
|
||||
|
||||
fulfillment = new cc.PreimageSha256()
|
||||
fulfillment.preimage = new Buffer(conditionJson.preimage)
|
||||
}
|
||||
|
||||
if (conditionJson.type_id === 4) {
|
||||
fulfillment = new cc.Ed25519();
|
||||
fulfillment.publicKey = new Buffer(base58.decode(conditionJson.public_key));
|
||||
if (conditionJson.signature)
|
||||
fulfillment.signature = new Buffer(base58.decode(conditionJson.signature));
|
||||
fulfillment = new cc.Ed25519()
|
||||
fulfillment.publicKey = new Buffer(base58.decode(conditionJson.public_key))
|
||||
if (conditionJson.signature) {
|
||||
fulfillment.signature = new Buffer(base58.decode(conditionJson.signature))
|
||||
}
|
||||
}
|
||||
return fulfillment;
|
||||
return fulfillment
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +1,36 @@
|
||||
import base58 from 'bs58';
|
||||
import base58 from 'bs58'
|
||||
|
||||
/**
|
||||
* @public
|
||||
* Serializes a crypto-condition class (Condition or Fulfillment) into a BigchainDB-compatible JSON
|
||||
* @param {cc.Fulfillment} fulfillment base58 encoded Ed25519 public key for the recipient of the Transaction
|
||||
* @param {cc.Fulfillment} fulfillment base58 encoded Ed25519 public key for recipient of the Transaction
|
||||
* @returns {object} Ed25519 Condition (that will need to wrapped in an Output)
|
||||
*/
|
||||
export default function ccJsonify(fulfillment) {
|
||||
let conditionUri
|
||||
|
||||
let conditionUri;
|
||||
if ('getConditionUri' in fulfillment) {
|
||||
conditionUri = fulfillment.getConditionUri()
|
||||
} else if ('serializeUri' in fulfillment) {
|
||||
conditionUri = fulfillment.serializeUri()
|
||||
}
|
||||
|
||||
if ('getConditionUri' in fulfillment)
|
||||
conditionUri = fulfillment.getConditionUri();
|
||||
else if ('serializeUri' in fulfillment)
|
||||
conditionUri = fulfillment.serializeUri();
|
||||
|
||||
let jsonBody = {
|
||||
const jsonBody = {
|
||||
'details': {},
|
||||
'uri': conditionUri,
|
||||
};
|
||||
}
|
||||
|
||||
if (fulfillment.getTypeId() === 0) {
|
||||
jsonBody.details.type_id = 0;
|
||||
jsonBody.details.bitmask = 3;
|
||||
jsonBody.details.type_id = 0
|
||||
jsonBody.details.bitmask = 3
|
||||
|
||||
if ('preimage' in fulfillment) {
|
||||
jsonBody.details.preimage = fulfillment.preimage.toString();
|
||||
jsonBody.details.type = 'fulfillment';
|
||||
jsonBody.details.preimage = fulfillment.preimage.toString()
|
||||
jsonBody.details.type = 'fulfillment'
|
||||
}
|
||||
}
|
||||
|
||||
if (fulfillment.getTypeId() === 2)
|
||||
if (fulfillment.getTypeId() === 2) {
|
||||
return {
|
||||
'details': {
|
||||
'type_id': 2,
|
||||
@ -38,30 +38,31 @@ export default function ccJsonify(fulfillment) {
|
||||
'bitmask': fulfillment.getBitmask(),
|
||||
'threshold': fulfillment.threshold,
|
||||
'subfulfillments': fulfillment.subconditions.map((subcondition) => {
|
||||
const subconditionJson = ccJsonify(subcondition.body);
|
||||
subconditionJson.details.weight = 1;
|
||||
return subconditionJson.details;
|
||||
const subconditionJson = ccJsonify(subcondition.body)
|
||||
subconditionJson.details.weight = 1
|
||||
return subconditionJson.details
|
||||
})
|
||||
},
|
||||
'uri': conditionUri,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (fulfillment.getTypeId() === 4) {
|
||||
jsonBody.details.type_id = 4;
|
||||
jsonBody.details.bitmask = 32;
|
||||
jsonBody.details.type_id = 4
|
||||
jsonBody.details.bitmask = 32
|
||||
|
||||
if ('publicKey' in fulfillment) {
|
||||
jsonBody.details.signature = null;
|
||||
jsonBody.details.public_key = base58.encode(fulfillment.publicKey);
|
||||
jsonBody.details.type = 'fulfillment';
|
||||
jsonBody.details.signature = null
|
||||
jsonBody.details.public_key = base58.encode(fulfillment.publicKey)
|
||||
jsonBody.details.type = 'fulfillment'
|
||||
}
|
||||
}
|
||||
|
||||
if ('hash' in fulfillment) {
|
||||
jsonBody.details.hash = base58.encode(fulfillment.hash);
|
||||
jsonBody.details.max_fulfillment_length = fulfillment.maxFulfillmentLength;
|
||||
jsonBody.details.type = 'condition';
|
||||
jsonBody.details.hash = base58.encode(fulfillment.hash)
|
||||
jsonBody.details.max_fulfillment_length = fulfillment.maxFulfillmentLength
|
||||
jsonBody.details.type = 'condition'
|
||||
}
|
||||
|
||||
return jsonBody;
|
||||
return jsonBody
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
/* eslint-disable strict, no-console, object-shorthand */
|
||||
|
||||
'use strict';
|
||||
'use strict'
|
||||
|
||||
const path = require('path');
|
||||
const path = require('path')
|
||||
|
||||
const webpack = require('webpack');
|
||||
const webpack = require('webpack')
|
||||
|
||||
const PRODUCTION = process.env.NODE_ENV === 'production';
|
||||
const PRODUCTION = process.env.NODE_ENV === 'production'
|
||||
|
||||
const PATHS = {
|
||||
ENTRY: path.resolve(__dirname, './src/index.js'),
|
||||
BUNDLE: path.resolve(__dirname, 'dist/bundle'),
|
||||
NODE_MODULES: path.resolve(__dirname, 'node_modules'),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/** PLUGINS **/
|
||||
const PLUGINS = [
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
];
|
||||
]
|
||||
|
||||
const PROD_PLUGINS = [
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
@ -34,10 +34,10 @@ const PROD_PLUGINS = [
|
||||
debug: false,
|
||||
minimize: true,
|
||||
}),
|
||||
];
|
||||
]
|
||||
|
||||
if (PRODUCTION) {
|
||||
PLUGINS.push(...PROD_PLUGINS);
|
||||
PLUGINS.push(...PROD_PLUGINS)
|
||||
}
|
||||
|
||||
|
||||
@ -75,6 +75,6 @@ const config = {
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = config;
|
||||
module.exports = config
|
||||
|
Loading…
Reference in New Issue
Block a user