UNPKG

chainscript

Version:
373 lines (279 loc) 10.5 kB
'use strict'; exports.__esModule = true; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _superagent = require('superagent'); var _superagent2 = _interopRequireDefault(_superagent); var _objectPath = require('object-path'); var _objectPath2 = _interopRequireDefault(_objectPath); var _bitcore = require('bitcore'); var _bitcoreMessage = require('bitcore-message'); var _bitcoreMessage2 = _interopRequireDefault(_bitcoreMessage); var _utilsClone = require('./utils/clone'); var _utilsClone2 = _interopRequireDefault(_utilsClone); var _utilsDeepEquals = require('./utils/deepEquals'); var _utilsDeepEquals2 = _interopRequireDefault(_utilsDeepEquals); var _utilsPromisify = require('./utils/promisify'); var _utilsPromisify2 = _interopRequireDefault(_utilsPromisify); var Chainscript = (function () { _createClass(Chainscript, null, [{ key: 'EXECUTE_URL', value: 'http://agent.chainscript.io/execute', enumerable: true }, { key: 'SNAPSHOTS_URL', value: 'https://chainscript.firebaseio.com/snapshots/', /** * Loads a script from an existing uuid * * @param {string} uuid The uuid of the script * @param {bool} [immutable=false] Whether to create an immutable instance * @returns {Promise} A promise that resolves with a new Chainscript */ enumerable: true }, { key: 'load', value: function value(uuid) { var immutable = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var req = _superagent2['default'].get(Chainscript.SNAPSHOTS_URL + uuid.replace(/:/g, '-') + '.json').set('Accept', 'application/json'); return _utilsPromisify2['default'](req.end.bind(req))().then(function (res) { if (!res.ok) { throw new Error(res.text); } if (!res.body) { throw new Error('Not found'); } return new Chainscript(_utilsClone2['default'](res.body), immutable); }); }, /** * Construct a new chainscript. * * @param {Object | string} [script={}] The initial script * @param {bool} [immutable=false] Whether to create an immutable instance */ enumerable: true }]); function Chainscript() { var script = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var immutable = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; _classCallCheck(this, Chainscript); // Clone the script for safety this.script = _utilsClone2['default'](script); this.immutable = immutable; if (!immutable) { this.initial = _utilsClone2['default'](script); } } /** * Returns the script as JSON. * * @returns {Object} JSON representation of the script */ Chainscript.prototype.toJSON = function toJSON() { // Clone the script for safety return _utilsClone2['default'](this.script); }; /** * Clones the script. * * @returns {Chainscript} A clone of the script */ Chainscript.prototype.clone = function clone() { var copy = new Chainscript(this.script, this.immutable); if (!this.immutable) { copy.initial = _utilsClone2['default'](this.initial); } return copy; }; /** * Run the script. * * @returns {Promise} A promise that resolves with a new Chainscript */ Chainscript.prototype.run = function run() { var _this = this; if (!this.immutable) { var initialContent = _objectPath2['default'].get(this.initial, 'body.content'); var currentContent = _objectPath2['default'].get(this.script, 'body.content'); if (!_utilsDeepEquals2['default'](initialContent, currentContent)) { this.script.body = this.script.body || {}; this.script.body.content = initialContent; this.delta(currentContent, true); } } var req = _superagent2['default'].post(Chainscript.EXECUTE_URL).send(this.script).set('Accept', 'application/json'); return _utilsPromisify2['default'](req.end.bind(req))().then(function (res) { if (!res.ok) { throw new Error(res.text); } if (!res.body) { throw new Error('Not found'); } if (_this.immutable) { return new Chainscript(res.body, true); } _this.script = res.body; _this.initial = _utilsClone2['default'](_this.script); return _this; }); }; /** * Returns the value at specified path. */ Chainscript.prototype.get = function get(path) { var value = _objectPath2['default'].get(this.script, path); if (typeof value === 'undefined') { return undefined; } if (this.immutable) { return _utilsClone2['default'](value); } return value; }; /** * Sets the value at specified path. * * @param {string} path The path of the key to set * @param {any} value The value * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.set = function set(path, value) { var script = undefined; if (this.immutable) { script = _utilsClone2['default'](this.script); } else { script = this.script; } _objectPath2['default'].set(script, path, value); if (this.immutable) { return new Chainscript(script, true); } return this; }; /** * Adds a snapshot command * * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.snapshot = function snapshot() { return this.set('x_chainscript.snapshots_enabled', true).addCommand({ snapshot: {} }); }; /** * Adds an update command * * @param {Object} updates An object with updates to apply * @param {bool} [first=false] Whether to put the command first * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.update = function update(updates) { var first = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; return this.addCommand({ update: updates }, first); }; /** * Adds a notarize command * * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.notarize = function notarize() { return this.addCommand({ notarize: {} }); }; /** * Adds a send email command * * @param {string} to Destination email address * @param {string} [subject] Subject * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.email = function email(to, subject) { if (subject) { return this.addCommand({ send_email: { to: to, subject: subject } }); } return this.addCommand({ send_email: { to: to } }); }; /** * Adds an update command to change the content at specified path. * * @param {function} fn A function that changes the content * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.change = function change(fn) { var next = _utilsClone2['default'](this.get('body.content')); fn(next); return this.delta(next); }; /** * Adds an update command to change the content to the given content. * * @param {Object} next The new content * @param {bool} [first=false] Whether to put the command first * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.delta = function delta(next) { var first = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var prev = this.get('body.content'); if (typeof prev === 'object' && prev && typeof next === 'object' && next) { Object.keys(prev).forEach(function (s) { if (typeof next[s] === 'undefined') { next[s] = null; } else if (_utilsDeepEquals2['default'](prev[s], next[s])) { delete next[s]; } }); } return this.update(next, first); }; /** * Adds a sign content command. * * @param {string} wif A private key in WIF format * @returns {Chainscript} A new instance of Chainscript */ Chainscript.prototype.sign = function sign(wif) { var _sign_content; var digest = _objectPath2['default'].get(this.script, 'body.x_meta.content_digest'); if (typeof digest === 'undefined') { throw new Error('Content has no digest'); } var privateKey = _bitcore.PrivateKey.fromWIF(wif); var address = privateKey.toPublicKey().toAddress().toString(); var message = new _bitcoreMessage2['default'](digest); var signature = message.sign(privateKey); return this.addCommand({ sign_content: (_sign_content = {}, _sign_content[address] = { digest: digest, signature: signature }, _sign_content) }); }; Chainscript.prototype.getNumCommands = function getNumCommands() { if (typeof this.script.execute === 'undefined') { return 0; } return Object.keys(this.script.execute).length; }; Chainscript.prototype.addCommand = function addCommand(command) { var first = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var index = first ? 0 : this.getNumCommands(); var script = undefined; if (this.immutable) { script = _utilsClone2['default'](this.script); } else { script = this.script; } script.execute = script.execute || {}; if (first) { (function () { var tmp = {}; Object.keys(script.execute).forEach(function (s) { tmp[parseInt(s, 10) + 1] = script.execute[s]; }); script.execute = tmp; })(); } script.execute[index] = command; if (this.immutable) { return new Chainscript(script, true); } return this; }; return Chainscript; })(); exports['default'] = Chainscript; module.exports = exports['default'];