UNPKG

@aeternity/aepp-sdk

Version:
358 lines (324 loc) 13.4 kB
import _T from "ramda/src/T"; import _lte from "ramda/src/lte"; import _always from "ramda/src/always"; import _lt from "ramda/src/lt"; import _cond from "ramda/src/cond"; import _slicedToArray from "@babel/runtime-corejs3/helpers/slicedToArray"; import _toConsumableArray from "@babel/runtime-corejs3/helpers/toConsumableArray"; import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat"; import _padStartInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/pad-start"; import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes"; import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice"; import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map"; import _Object$assign from "@babel/runtime-corejs3/core-js-stable/object/assign"; import _endsWithInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/ends-with"; import _findInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/find"; import BigNumber from 'bignumber.js'; import { assertedType, decodeBase58Check, decodeBase64Check, encodeBase58Check, encodeBase64Check, hash, salt } from '../../utils/crypto'; import { toBytes } from '../../utils/bytes'; import { ID_TAG_PREFIX, PREFIX_ID_TAG, NAME_BID_RANGES, NAME_BID_MAX_LENGTH, NAME_FEE, NAME_FEE_BID_INCREMENT, NAME_BID_TIMEOUTS, NAME_ID_KEY } from './schema'; import { ceil } from '../../utils/bignumber'; /** * JavaScript-based Transaction builder helper function's * @module @aeternity/aepp-sdk/es/tx/builder/helpers * @export TxBuilderHelper * @example import { TxBuilderHelper } from '@aeternity/aepp-sdk' */ export var createSalt = salt; var base64Types = ['tx', 'st', 'ss', 'pi', 'ov', 'or', 'cb', 'cs', 'ba']; /** * Build a contract public key * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {string} ownerId The public key of the owner account * @param {number} nonce the nonce of the transaction * @return {string} Contract public key */ export function buildContractId(ownerId, nonce) { var _context; var ownerIdAndNonce = Buffer.from(_concatInstanceProperty(_context = []).call(_context, _toConsumableArray(decode(ownerId, 'ak')), _toConsumableArray(toBytes(nonce)))); var b2bHash = hash(ownerIdAndNonce); return encode(b2bHash, 'ct'); } /** * Build hash * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {String} prefix Transaction hash prefix * @param {Buffer} data Rlp encoded transaction buffer * @param {Object} options * @param {Boolean} options.raw * @return {String} Transaction hash */ export function buildHash(prefix, data) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return options.raw ? hash(data) : encode(hash(data), prefix); } /** * Build a oracle query id * @function * @function* @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {String} senderId The public key of the sender account * @param {Number} nonce the nonce of the transaction * @param {Number} oracleId The oracle public key * @return {string} Contract public key */ export function oracleQueryId(senderId, nonce, oracleId) { var _context2; function _int32(val) { var nonceBE = toBytes(val, true); return _concatInstanceProperty(Buffer).call(Buffer, [Buffer.alloc(32 - nonceBE.length), nonceBE]); } var b2bHash = hash(Buffer.from(_concatInstanceProperty(_context2 = []).call(_context2, _toConsumableArray(decode(senderId, 'ak')), _toConsumableArray(_int32(nonce)), _toConsumableArray(decode(oracleId, 'ok'))))); return encode(b2bHash, 'oq'); } /** * Format the salt into a 64-byte hex string * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {number} salt * @return {string} Zero-padded hex string of salt */ export function formatSalt(salt) { var _context3; return Buffer.from(_padStartInstanceProperty(_context3 = salt.toString(16)).call(_context3, 64, '0'), 'hex'); } /** * Encode a domain name * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {String} name Name to encode * @return {String} `nm_` prefixed encoded domain name */ export function produceNameId(name) { ensureNameValid(name); return encode(hash(name.toLowerCase()), 'nm'); } /** * Generate the commitment hash by hashing the formatted salt and * name, base 58 encoding the result and prepending 'cm_' * * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @function commitmentHash * @category async * @rtype (name: String, salt?: String) => hash: Promise[String] * @param {String} name - Name to be registered * @param {Number} salt Random salt * @return {String} Commitment hash */ export function commitmentHash(name) { var salt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : createSalt(); ensureNameValid(name); return "cm_".concat(encodeBase58Check(hash(_concatInstanceProperty(Buffer).call(Buffer, [Buffer.from(name.toLowerCase()), formatSalt(salt)])))); } /** * Decode data using the default encoding/decoding algorithm * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {string} data An encoded and prefixed string (ex tx_..., sg_..., ak_....) * @param {string} type Prefix of Transaction * @return {Buffer} Buffer of decoded Base58check or Base64check data */ export function decode(data) { var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; if (!type) type = data.split('_')[0]; return _includesInstanceProperty(base64Types).call(base64Types, type) ? decodeBase64Check(assertedType(data, type)) : decodeBase58Check(assertedType(data, type)); } /** * Encode data using the default encoding/decoding algorithm * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {Buffer|String} data An decoded data * @param {string} type Prefix of Transaction * @return {String} Encoded string Base58check or Base64check data */ export function encode(data, type) { var _context4; return _concatInstanceProperty(_context4 = "".concat(type, "_")).call(_context4, _includesInstanceProperty(base64Types).call(base64Types, type) ? encodeBase64Check(data) : encodeBase58Check(data)); } /** * Utility function to create and _id type * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {string} hashId Encoded hash * @return {Buffer} Buffer Buffer with ID tag and decoded HASh */ export function writeId(hashId) { var _context5; var prefix = _sliceInstanceProperty(hashId).call(hashId, 0, 2); var idTag = PREFIX_ID_TAG[prefix]; if (!idTag) throw new Error("Id tag for prefix ".concat(prefix, " not found.")); return Buffer.from(_concatInstanceProperty(_context5 = []).call(_context5, _toConsumableArray(toBytes(idTag)), _toConsumableArray(decode(hashId, prefix)))); } /** * Utility function to read and _id type * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {Buffer} buf Data * @return {String} Encoided hash string with prefix */ export function readId(buf) { var tag = buf.readUIntBE(0, 1); var prefix = ID_TAG_PREFIX[tag]; if (!prefix) throw new Error("Prefix for id-tag ".concat(tag, " not found.")); return encode(_sliceInstanceProperty(buf).call(buf, 1, buf.length), prefix); } /** * Utility function to convert int to bytes * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {Number|String|BigNumber} val Value * @return {Buffer} Buffer Buffer from number(BigEndian) */ export function writeInt(val) { return toBytes(val, true); } /** * Utility function to convert bytes to int * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {Buffer} buf Value * @return {String} Buffer Buffer from number(BigEndian) */ export function readInt() { var buf = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Buffer.from([]); return BigNumber(buf.toString('hex'), 16).toString(10); } /** * Helper function to build pointers for name update TX * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {Array} pointers - Array of pointers ([ { key: 'account_pubkey', id: 'ak_32klj5j23k23j5423l434l2j3423'} ]) * @return {Array} Serialized pointers array */ export function buildPointers(pointers) { return _mapInstanceProperty(pointers).call(pointers, function (p) { return [toBytes(p.key), writeId(p.id)]; }); } /** * Helper function to read pointers from name update TX * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {Array} pointers - Array of pointers ([ { key: 'account_pubkey', id: 'ak_32klj5j23k23j5423l434l2j3423'} ]) * @return {Array} Deserialize pointer array */ export function readPointers(pointers) { return _mapInstanceProperty(pointers).call(pointers, function (_ref) { var _ref2 = _slicedToArray(_ref, 2), key = _ref2[0], id = _ref2[1]; return _Object$assign({ key: key.toString(), id: readId(id) }); }); } /** * Ensure that name is valid * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {string} name * @return void * @throws Error */ export function ensureNameValid(name) { if (!name || typeof name !== 'string') throw new Error('Name must be a string'); if (!_endsWithInstanceProperty(name).call(name, '.chain')) throw new Error("Name should end with .chain: ".concat(name)); } /** * Is name valid * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {string} name * @return Boolean */ export function isNameValid(name) { try { ensureNameValid(name); return true; } catch (error) { return false; } } /** * What kind of a hash is this? If it begins with 'ak_' it is an * account key, if with 'ok_' it's an oracle key. * * @param s - the hash. * returns the type, or throws an exception if type not found. */ export function classify(s) { if (!s.match(/^[a-z]{2}_.+/)) { throw new Error('Not a valid hash'); } var klass = s.substr(0, 2); if (klass in NAME_ID_KEY) { return NAME_ID_KEY[klass]; } else { throw new Error("Unknown class ".concat(klass)); } } /** * Validate name pointers array * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {String[]} pointers Pointers array. Allowed values is: account(ak_), oracle(ok_), contract(ct_), channel(ch_) * @return {Boolean} */ export function validatePointers() { var pointers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; return !_findInstanceProperty(pointers).call(pointers, function (p) { var _context6; return !p || typeof p !== 'string' || !_includesInstanceProperty(_context6 = ['ak', 'ok', 'ct', 'ch']).call(_context6, p.split('_')[0]); }); } /** * Get the minimum name fee for a domain * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {String} domain the domain name to get the fee for * @return {String} the minimum fee for the domain auction */ export function getMinimumNameFee(domain) { var nameLength = domain.replace('.chain', '').length; return NAME_BID_RANGES[nameLength >= NAME_BID_MAX_LENGTH ? NAME_BID_MAX_LENGTH : nameLength]; } /** * Compute bid fee for AENS auction * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {String} domain the domain name to get the fee for * @param {Number|String} startFee Auction start fee * @param {Number} [increment=0.5] Bid multiplier(In percentage, must be between 0 and 1) * @return {String} Bid fee */ export function computeBidFee(domain) { var startFee = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : NAME_FEE; var increment = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : NAME_FEE_BID_INCREMENT; if (!(Number(increment) === increment && increment % 1 !== 0)) throw new Error("Increment must be float. Current increment ".concat(increment)); if (increment < NAME_FEE_BID_INCREMENT) throw new Error("minimum increment percentage is ".concat(NAME_FEE_BID_INCREMENT)); return ceil(BigNumber(BigNumber(startFee).eq(NAME_FEE) ? getMinimumNameFee(domain) : startFee).times(BigNumber(NAME_FEE_BID_INCREMENT).plus(1))); } /** * Compute auction end height * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {String} domain the domain name to get the fee for * @param {Number|String} claimHeight Auction starting height * @return {String} Auction end height */ export function computeAuctionEndBlock(domain, claimHeight) { return _cond([[_lt(5), _always(NAME_BID_TIMEOUTS[4].plus(claimHeight))], [_lt(9), _always(NAME_BID_TIMEOUTS[8].plus(claimHeight))], [_lte(NAME_BID_MAX_LENGTH), _always(NAME_BID_TIMEOUTS[12].plus(claimHeight))], [_T, _always(BigNumber(claimHeight))]])(domain.replace('.chain', '').length).toString(10); } /** * Is name accept going to auction * @function * @alias module:@aeternity/aepp-sdk/es/tx/builder/helpers * @param {String} name Transaction abiVersion * @return {Boolean} */ export function isAuctionName(name) { return name.replace('.chain', '').length < 13; } //# sourceMappingURL=helpers.js.map