UNPKG

@colony/purser-software

Version:

A javascript library to interact with a software Ethereum wallet, based on the ethers.js library

249 lines (226 loc) 9.25 kB
import _regeneratorRuntime from "@babel/runtime/regenerator"; import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator"; import { bigNumberify, verifyMessage as verifyEthersMessage } from 'ethers/utils'; import { transactionObjectValidator, messageVerificationObjectValidator, messageOrDataValidator } from '@colony/purser-core/helpers'; import { addressNormalizer, hexSequenceNormalizer } from '@colony/purser-core/normalizers'; import { addressValidator } from '@colony/purser-core/validators'; import { objectToErrorString } from '@colony/purser-core/utils'; import { staticMethods as messages } from './messages'; /** * Sign a transaction object and return the serialized signature (as a hex string) * * @method signTransaction * * @param {bigNumber} gasPrice gas price for the transaction in WEI (as an instance of bigNumber), defaults to 9000000000 (9 GWEI) * @param {bigNumber} gasLimit gas limit for the transaction (as an instance of bigNumber), defaults to 21000 * @param {number} chainId the id of the chain for which this transaction is intended * @param {number} nonce the nonce to use for the transaction (as a number) * @param {string} to the address to which to the transaction is sent * @param {bigNumber} value the value of the transaction in WEI (as an instance of bigNumber), defaults to 1 * @param {string} inputData data appended to the transaction (as a `hex` string) * @param {function} callback Ethers method to call with the validated transaction object * * All the above params are sent in as props of an {TransactionObjectType} object. * * @return {Promise<string>} the hex signature string */ export var signTransaction = /*#__PURE__*/ function () { var _ref = _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee() { var _ref2, callback, transactionObject, _transactionObjectVal, gasPrice, gasLimit, chainId, nonce, to, value, inputData, signedTransaction, _args = arguments; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _ref2 = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}, callback = _ref2.callback, transactionObject = _objectWithoutProperties(_ref2, ["callback"]); _transactionObjectVal = transactionObjectValidator(transactionObject), gasPrice = _transactionObjectVal.gasPrice, gasLimit = _transactionObjectVal.gasLimit, chainId = _transactionObjectVal.chainId, nonce = _transactionObjectVal.nonce, to = _transactionObjectVal.to, value = _transactionObjectVal.value, inputData = _transactionObjectVal.inputData; _context.prev = 2; _context.next = 5; return callback(Object.assign({}, { /* * Ethers needs it's own "proprietary" version of bignumber to work. */ gasPrice: bigNumberify(gasPrice.toString()), /* * Ethers needs it's own "proprietary" version of bignumber to work. */ gasLimit: bigNumberify(gasLimit.toString()), chainId: chainId, nonce: nonce, /* * Ethers needs it's own "proprietary" version of bignumber to work. */ value: bigNumberify(value.toString()), data: hexSequenceNormalizer(inputData) }, /* * Only send (and normalize) the destination address if one was * provided in the initial transaction object. */ to ? { to: addressNormalizer(to) } : {})); case 5: signedTransaction = _context.sent; return _context.abrupt("return", hexSequenceNormalizer(signedTransaction)); case 9: _context.prev = 9; _context.t0 = _context["catch"](2); throw new Error("".concat(messages.cannotSign, " ").concat(objectToErrorString({ gasPrice: gasPrice, gasLimit: gasLimit, chainId: chainId, nonce: nonce, to: to, value: value, inputData: inputData }), " Error: ").concat(_context.t0.message)); case 12: case "end": return _context.stop(); } } }, _callee, this, [[2, 9]]); })); return function signTransaction() { return _ref.apply(this, arguments); }; }(); /** * Sign a message and return the signature. Useful for verifying identities. * * @method signMessage * * @param {string} message the message you want to sign * @param {string} messageData the message you want to sign * @param {function} callback Ethers method to call with the validated message string * * All the above params are sent in as props of an {object}. Note that only one * of message or messageData can be set (enforced in class). * * @return {Promise<string>} The signed message `hex` string (wrapped inside a `Promise`) */ export var signMessage = /*#__PURE__*/ function () { var _ref3 = _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee2() { var _ref4, message, messageData, callback, toSign, messageSignature, _args2 = arguments; return _regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _ref4 = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : {}, message = _ref4.message, messageData = _ref4.messageData, callback = _ref4.callback; /* * Validate input value */ toSign = messageOrDataValidator({ message: message, messageData: messageData }); _context2.prev = 2; _context2.next = 5; return callback(toSign); case 5: messageSignature = _context2.sent; return _context2.abrupt("return", hexSequenceNormalizer(messageSignature)); case 9: _context2.prev = 9; _context2.t0 = _context2["catch"](2); throw new Error("".concat(messages.cannotSignMessage, ": ").concat(message, " Error: ").concat(_context2.t0.message)); case 12: case "end": return _context2.stop(); } } }, _callee2, this, [[2, 9]]); })); return function signMessage() { return _ref3.apply(this, arguments); }; }(); /** * Verify a signed message. Useful for verifying identity. (In conjunction with `signMessage`) * * @method verifyMessage * * @param {string} address The wallet address to verify the signature against * @param {string} message The message to verify if it was signed correctly * @param {string} signature The message signature as a `hex` string (you usually get this via `signMessage`) * * All the above params are sent in as props of an {MessageVerificationObjectType} object. * * @return {Promise<boolean>} A boolean to indicate if the message/signature pair are valid (wrapped inside a `Promise`) */ export var verifyMessage = /*#__PURE__*/ function () { var _ref5 = _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee3() { var _ref6, address, signatureMessage, _messageVerificationO, message, signature, recoveredAddress, _args3 = arguments; return _regeneratorRuntime.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: _ref6 = _args3.length > 0 && _args3[0] !== undefined ? _args3[0] : {}, address = _ref6.address, signatureMessage = _objectWithoutProperties(_ref6, ["address"]); /* * Validate the address locally */ addressValidator(address); /* * Validate the rest of the pros using the core helper */ _messageVerificationO = messageVerificationObjectValidator(signatureMessage), message = _messageVerificationO.message, signature = _messageVerificationO.signature; _context3.prev = 3; recoveredAddress = verifyEthersMessage(message, signature); /* * Validate the recovered address */ addressValidator(recoveredAddress); return _context3.abrupt("return", address === recoveredAddress); case 9: _context3.prev = 9; _context3.t0 = _context3["catch"](3); throw new Error("".concat(messages.cannotVerifySignature, " ").concat(objectToErrorString(signatureMessage), " Error: ").concat(_context3.t0.message)); case 12: case "end": return _context3.stop(); } } }, _callee3, this, [[3, 9]]); })); return function verifyMessage() { return _ref5.apply(this, arguments); }; }();