UNPKG

@aeternity/aepp-sdk

Version:
1,207 lines (1,101 loc) 41.4 kB
import _Object$keys from "@babel/runtime-corejs3/core-js-stable/object/keys"; import _Object$getOwnPropertySymbols from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols"; import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter"; import _Object$getOwnPropertyDescriptor from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor"; import _forEachInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/for-each"; import _Object$getOwnPropertyDescriptors from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors"; import _Object$defineProperties from "@babel/runtime-corejs3/core-js-stable/object/define-properties"; import _Object$defineProperty from "@babel/runtime-corejs3/core-js-stable/object/define-property"; import _reduce from "ramda/src/reduce"; import _typeof from "@babel/runtime-corejs3/helpers/typeof"; import _asyncToGenerator from "@babel/runtime-corejs3/helpers/asyncToGenerator"; import _defineProperty from "@babel/runtime-corejs3/helpers/defineProperty"; import _slicedToArray from "@babel/runtime-corejs3/helpers/slicedToArray"; import _regeneratorRuntime from "@babel/runtime-corejs3/regenerator"; function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); if (enumerableOnly) symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { var _context10; _forEachInstanceProperty(_context10 = ownKeys(Object(source), true)).call(_context10, function (key) { _defineProperty(target, key, source[key]); }); } else if (_Object$getOwnPropertyDescriptors) { _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)); } else { var _context11; _forEachInstanceProperty(_context11 = ownKeys(Object(source))).call(_context11, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } } return target; } import _reduceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/reduce"; import _Object$entries from "@babel/runtime-corejs3/core-js-stable/object/entries"; import _parseInt from "@babel/runtime-corejs3/core-js-stable/parse-int"; import _Promise from "@babel/runtime-corejs3/core-js-stable/promise"; import _JSON$stringify from "@babel/runtime-corejs3/core-js-stable/json/stringify"; import _setTimeout from "@babel/runtime-corejs3/core-js-stable/set-timeout"; /* * ISC License (ISC) * Copyright (c) 2018 aeternity developers * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /** * Channel module * @module @aeternity/aepp-sdk/es/channel/index * @export Channel * @example import { Channel } from '@aeternity/aepp-sdk' */ import AsyncInit from '../utils/async-init'; import { snakeToPascal } from '../utils/string'; import { buildTx, unpackTx } from '../tx/builder'; import { TX_TYPE } from '../tx/builder/schema'; import * as handlers from './handlers'; import { eventEmitters, status as channelStatus, state as channelState, initialize, enqueueAction, send, channelId, call, disconnect as channelDisconnect, fsmId as channelFsmId } from './internal'; function snakeToPascalObjKeys(obj) { var _context; return _reduceInstanceProperty(_context = _Object$entries(obj)).call(_context, function (result, _ref) { var _ref2 = _slicedToArray(_ref, 2), key = _ref2[0], val = _ref2[1]; return _objectSpread(_objectSpread({}, result), {}, _defineProperty({}, snakeToPascal(key), val)); }, {}); } /** * Register event listener function * * Possible events: * * - "error" * - "onChainTx" * - "ownWithdrawLocked" * - "withdrawLocked" * - "ownDepositLocked" * - "depositLocked" * * @param {String} event - Event name * @param {Function} callback - Callback function */ function on(event, callback) { eventEmitters.get(this).on(event, callback); } /** * Remove event listener function * * @param {String} event - Event name * @param {Function} callback - Callback function */ function off(event, callback) { eventEmitters.get(this).removeListener(event, callback); } /** * Close the connection */ function disconnect() { return channelDisconnect(this); } /** * Get current status * * @return {String} */ function status() { return channelStatus.get(this); } /** * Get current state * * @return {Promise<Object>} */ function state() { return _state.apply(this, arguments); } /** * Get current round * * If round cannot be determined (for example when channel has not been opened) * it will return `null`. * * @return {Number} */ function _state() { _state = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() { return _regeneratorRuntime.wrap(function _callee2$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: _context3.t0 = snakeToPascalObjKeys; _context3.next = 3; return call(this, 'channels.get.offchain_state', {}); case 3: _context3.t1 = _context3.sent; return _context3.abrupt("return", (0, _context3.t0)(_context3.t1)); case 5: case "end": return _context3.stop(); } } }, _callee2, this); })); return _state.apply(this, arguments); } function round() { var state = channelState.get(this); if (!state) { return null; } var _unpackTx$tx$encodedT = unpackTx(channelState.get(this)).tx.encodedTx, txType = _unpackTx$tx$encodedT.txType, tx = _unpackTx$tx$encodedT.tx; switch (txType) { case TX_TYPE.channelCreate: return 1; case TX_TYPE.channelOffChain: case TX_TYPE.channelWithdraw: case TX_TYPE.channelDeposit: return _parseInt(tx.round, 10); default: return null; } } /** * Get channel id * * @return {String} */ function id() { return channelId.get(this); } /** * Get channel's fsm id * * @return {String} */ function fsmId() { return channelFsmId.get(this); } /** * Trigger a transfer update * * The transfer update is moving tokens from one channel account to another. * The update is a change to be applied on top of the latest state. * * Sender and receiver are the channel parties. Both the initiator and responder * can take those roles. Any public key outside of the channel is considered invalid. * * @param {String} from - Sender's public address * @param {String} to - Receiver's public address * @param {Number} amount - Transaction amount * @param {Function} sign - Function which verifies and signs offchain transaction * @param {Array<String>} metadata * @return {Promise<Object>} * @example channel.update( * 'ak_Y1NRjHuoc3CGMYMvCmdHSBpJsMDR6Ra2t5zjhRcbtMeXXLpLH', * 'ak_V6an1xhec1xVaAhLuak7QoEbi6t7w5hEtYWp9bMKaJ19i6A9E', * 10, * async (tx) => await account.signTransaction(tx) * ).then(({ accepted, signedTx }) => * if (accepted) { * console.log('Update has been accepted') * } * ) */ function update(from, to, amount, sign, metadata) { var _this = this; return new _Promise(function (resolve, reject) { enqueueAction(_this, function (channel, state) { return state.handler === handlers.channelOpen; }, function (channel, state) { send(channel, { jsonrpc: '2.0', method: 'channels.update.new', params: { from: from, to: to, amount: amount, meta: metadata } }); return { handler: handlers.awaitingOffChainTx, state: { resolve: resolve, reject: reject, sign: sign } }; }); }); } /** * Get proof of inclusion * * If a certain address of an account or a contract is not found * in the state tree - the response is an error. * * @param {Object} addresses * @param {Array<String>} [addresses.accounts] - List of account addresses to include in poi * @param {Array<String>} [addresses.contracts] - List of contract addresses to include in poi * @return {Promise<String>} * @example channel.poi({ * accounts: [ * 'ak_Y1NRjHuoc3CGMYMvCmdHSBpJsMDR6Ra2t5zjhRcbtMeXXLpLH', * 'ak_V6an1xhec1xVaAhLuak7QoEbi6t7w5hEtYWp9bMKaJ19i6A9E' * ], * contracts: ['ct_2dCUAWYZdrWfACz3a2faJeKVTVrfDYxCQHCqAt5zM15f3u2UfA'] * }).then(poi => console.log(poi)) */ function poi(_x) { return _poi.apply(this, arguments); } /** * Get balances * * The accounts paramcontains a list of addresses to fetch balances of. * Those can be either account balances or a contract ones, encoded as an account addresses. * * If a certain account address had not being found in the state tree - it is simply * skipped in the response. * * @param {Array<String>} accounts - List of addresses to fetch balances from * @return {Promise<Object>} * @example channel.balances([ * 'ak_Y1NRjHuoc3CGMYMvCmdHSBpJsMDR6Ra2t5zjhRcbtMeXXLpLH', * 'ak_V6an1xhec1xVaAhLuak7QoEbi6t7w5hEtYWp9bMKaJ19i6A9E' * 'ct_2dCUAWYZdrWfACz3a2faJeKVTVrfDYxCQHCqAt5zM15f3u2UfA' * ]).then(balances => * console.log(balances['ak_Y1NRjHuoc3CGMYMvCmdHSBpJsMDR6Ra2t5zjhRcbtMeXXLpLH']) * ) */ function _poi() { _poi = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref3) { var accounts, contracts; return _regeneratorRuntime.wrap(function _callee3$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: accounts = _ref3.accounts, contracts = _ref3.contracts; _context4.next = 3; return call(this, 'channels.get.poi', { accounts: accounts, contracts: contracts }); case 3: return _context4.abrupt("return", _context4.sent.poi); case 4: case "end": return _context4.stop(); } } }, _callee3, this); })); return _poi.apply(this, arguments); } function balances(_x2) { return _balances.apply(this, arguments); } /** * Leave channel * * It is possible to leave a channel and then later reestablish the channel * off-chain state and continue operation. When a leave method is called, * the channel fsm passes it on to the peer fsm, reports the current mutually * signed state and then terminates. * * The channel can be reestablished by instantiating another Channel instance * with two extra params: existingChannelId and offchainTx (returned from leave * method as channelId and signedTx respectively). * * @return {Promise<Object>} * @example channel.leave().then(({ channelId, signedTx }) => { * console.log(channelId) * console.log(signedTx) * }) */ function _balances() { _balances = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(accounts) { return _regeneratorRuntime.wrap(function _callee4$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: _context5.t0 = _reduce; _context5.t1 = function (acc, item) { return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, item.account, item.balance)); }; _context5.t2 = {}; _context5.next = 5; return call(this, 'channels.get.balances', { accounts: accounts }); case 5: _context5.t3 = _context5.sent; return _context5.abrupt("return", (0, _context5.t0)(_context5.t1, _context5.t2, _context5.t3)); case 7: case "end": return _context5.stop(); } } }, _callee4, this); })); return _balances.apply(this, arguments); } function leave() { var _this2 = this; return new _Promise(function (resolve, reject) { enqueueAction(_this2, function (channel, state) { return state.handler === handlers.channelOpen; }, function (channel, state) { send(channel, { jsonrpc: '2.0', method: 'channels.leave', params: {} }); return { handler: handlers.awaitingLeave, state: { resolve: resolve, reject: reject } }; }); }); } /** * Trigger mutual close * * At any moment after the channel is opened, a closing procedure can be triggered. * This can be done by either of the parties. The process is similar to the off-chain updates. * * @param {Function} sign - Function which verifies and signs mutual close transaction * @return {Promise<String>} * @example channel.shutdown( * async (tx) => await account.signTransaction(tx) * ).then(tx => console.log('on_chain_tx', tx)) */ function shutdown(sign) { var _this3 = this; return new _Promise(function (resolve, reject) { enqueueAction(_this3, function (channel, state) { return state.handler === handlers.channelOpen; }, function (channel, state) { send(channel, { jsonrpc: '2.0', method: 'channels.shutdown', params: {} }); return { handler: handlers.awaitingShutdownTx, state: { sign: sign, resolve: resolve, reject: reject } }; }); }); } /** * Withdraw tokens from the channel * * After the channel had been opened any of the participants can initiate a withdrawal. * The process closely resembles the update. The most notable difference is that the * transaction has been co-signed: it is channel_withdraw_tx and after the procedure * is finished - it is being posted on-chain. * * Any of the participants can initiate a withdrawal. The only requirements are: * * - Channel is already opened * - No off-chain update/deposit/withdrawal is currently being performed * - Channel is not being closed or in a solo closing state * - The withdrawal amount must be equal to or greater than zero, and cannot exceed * the available balance on the channel (minus the channel_reserve) * * After the other party had signed the withdraw transaction, the transaction is posted * on-chain and onOnChainTx callback is called with on-chain transaction as first argument. * After computing transaction hash it can be tracked on the chain: entering the mempool, * block inclusion and a number of confirmations. * * After the minimum_depth block confirmations onOwnWithdrawLocked callback is called * (without any arguments). * * When the other party had confirmed that the block height needed is reached * onWithdrawLocked callback is called (without any arguments). * * @param {Number} amount - Amount of tokens to withdraw * @param {Function} sign - Function which verifies and signs withdraw transaction * @param {Object} [callbacks] * @param {Function} [callbacks.onOnChainTx] - Called when withdraw transaction has been posted on chain * @param {Function} [callbacks.onOwnWithdrawLocked] * @param {Function} [callbacks.onWithdrawLocked] * @return {Promise<Object>} * @example channel.withdraw( * 100, * async (tx) => await account.signTransaction(tx), * { onOnChainTx: (tx) => console.log('on_chain_tx', tx) } * ).then(({ accepted, signedTx }) => { * if (accepted) { * console.log('Withdrawal has been accepted') * } else { * console.log('Withdrawal has been rejected') * } * }) */ function withdraw(amount, sign) { var _this4 = this; var _ref4 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, onOnChainTx = _ref4.onOnChainTx, onOwnWithdrawLocked = _ref4.onOwnWithdrawLocked, onWithdrawLocked = _ref4.onWithdrawLocked; return new _Promise(function (resolve, reject) { enqueueAction(_this4, function (channel, state) { return state.handler === handlers.channelOpen; }, function (channel, state) { send(channel, { jsonrpc: '2.0', method: 'channels.withdraw', params: { amount: amount } }); return { handler: handlers.awaitingWithdrawTx, state: { sign: sign, resolve: resolve, reject: reject, onOnChainTx: onOnChainTx, onOwnWithdrawLocked: onOwnWithdrawLocked, onWithdrawLocked: onWithdrawLocked } }; }); }); } /** * Deposit tokens into the channel * * After the channel had been opened any of the participants can initiate a deposit. * The process closely resembles the update. The most notable difference is that the * transaction has been co-signed: it is channel_deposit_tx and after the procedure * is finished - it is being posted on-chain. * * Any of the participants can initiate a deposit. The only requirements are: * * - Channel is already opened * - No off-chain update/deposit/withdrawal is currently being performed * - Channel is not being closed or in a solo closing state * - The deposit amount must be equal to or greater than zero, and cannot exceed * the available balance on the channel (minus the channel_reserve) * * After the other party had signed the deposit transaction, the transaction is posted * on-chain and onOnChainTx callback is called with on-chain transaction as first argument. * After computing transaction hash it can be tracked on the chain: entering the mempool, * block inclusion and a number of confirmations. * * After the minimum_depth block confirmations onOwnDepositLocked callback is called * (without any arguments). * * When the other party had confirmed that the block height needed is reached * onDepositLocked callback is called (without any arguments). * * @param {Number} amount - Amount of tokens to deposit * @param {Function} sign - Function which verifies and signs deposit transaction * @param {Object} [callbacks] * @param {Function} [callbacks.onOnChainTx] - Called when deposit transaction has been posted on chain * @param {Function} [callbacks.onOwnDepositLocked] * @param {Function} [callbacks.onDepositLocked] * @return {Promise<Object>} * @example channel.deposit( * 100, * async (tx) => await account.signTransaction(tx), * { onOnChainTx: (tx) => console.log('on_chain_tx', tx) } * ).then(({ accepted, state }) => { * if (accepted) { * console.log('Deposit has been accepted') * console.log('The new state is:', state) * } else { * console.log('Deposit has been rejected') * } * }) */ function deposit(amount, sign) { var _this5 = this; var _ref5 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, onOnChainTx = _ref5.onOnChainTx, onOwnDepositLocked = _ref5.onOwnDepositLocked, onDepositLocked = _ref5.onDepositLocked; return new _Promise(function (resolve, reject) { enqueueAction(_this5, function (channel, state) { return state.handler === handlers.channelOpen; }, function (channel, state) { send(channel, { jsonrpc: '2.0', method: 'channels.deposit', params: { amount: amount } }); return { handler: handlers.awaitingDepositTx, state: { sign: sign, resolve: resolve, reject: reject, onOnChainTx: onOnChainTx, onOwnDepositLocked: onOwnDepositLocked, onDepositLocked: onDepositLocked } }; }); }); } /** * Trigger create contract update * * The create contract update is creating a contract inside the channel's internal state tree. * The update is a change to be applied on top of the latest state. * * That would create a contract with the poster being the owner of it. Poster commits initially * a deposit amount of tokens to the new contract. * * @param {Object} options * @param {String} options.code - Api encoded compiled AEVM byte code * @param {String} options.callData - Api encoded compiled AEVM call data for the code * @param {Number} options.deposit - Initial amount the owner of the contract commits to it * @param {Number} options.vmVersion - Version of the Virtual Machine * @param {Number} options.abiVersion - Version of the Application Binary Interface * @param {Function} sign - Function which verifies and signs create contract transaction * @return {Promise<Object>} * @example channel.createContract({ * code: 'cb_HKtpipK4aCgYb17wZ...', * callData: 'cb_1111111111111111...', * deposit: 10, * vmVersion: 3, * abiVersion: 1 * }).then(({ accepted, signedTx, address }) => { * if (accepted) { * console.log('New contract has been created') * console.log('Contract address:', address) * } else { * console.log('New contract has been rejected') * } * }) */ function createContract(_ref6, sign) { var _this6 = this; var code = _ref6.code, callData = _ref6.callData, deposit = _ref6.deposit, vmVersion = _ref6.vmVersion, abiVersion = _ref6.abiVersion; return new _Promise(function (resolve, reject) { enqueueAction(_this6, function (channel, state) { return state.handler === handlers.channelOpen; }, function (channel, state) { send(channel, { jsonrpc: '2.0', method: 'channels.update.new_contract', params: { code: code, call_data: callData, deposit: deposit, vm_version: vmVersion, abi_version: abiVersion } }); return { handler: handlers.awaitingNewContractTx, state: { sign: sign, resolve: resolve, reject: reject } }; }); }); } /** * Trigger call a contract update * * The call contract update is calling a preexisting contract inside the channel's * internal state tree. The update is a change to be applied on top of the latest state. * * That would call a contract with the poster being the caller of it. Poster commits * an amount of tokens to the contract. * * The call would also create a call object inside the channel state tree. It contains * the result of the contract call. * * It is worth mentioning that the gas is not consumed, because this is an off-chain * contract call. It would be consumed if it were a on-chain one. This could happen * if a call with a similar computation amount is to be forced on-chain. * * @param {Object} options * @param {String} [options.amount] - Amount the caller of the contract commits to it * @param {String} [options.callData] - ABI encoded compiled AEVM call data for the code * @param {Number} [options.contract] - Address of the contract to call * @param {Number} [options.abiVersion] - Version of the ABI * @param {Function} sign - Function which verifies and signs contract call transaction * @return {Promise<Object>} * @example channel.callContract({ * contract: 'ct_9sRA9AVE4BYTAkh5RNfJYmwQe1NZ4MErasQLXZkFWG43TPBqa', * callData: 'cb_1111111111111111...', * amount: 0, * abiVersion: 1 * }).then(({ accepted, signedTx }) => { * if (accepted) { * console.log('Contract called succesfully') * } else { * console.log('Contract call has been rejected') * } * }) */ function callContract(_ref7, sign) { var _this7 = this; var amount = _ref7.amount, callData = _ref7.callData, contract = _ref7.contract, abiVersion = _ref7.abiVersion; return new _Promise(function (resolve, reject) { enqueueAction(_this7, function (channel, state) { return state.handler === handlers.channelOpen; }, function (channel, state) { send(channel, { jsonrpc: '2.0', method: 'channels.update.call_contract', params: { amount: amount, call_data: callData, contract_id: contract, abi_version: abiVersion } }); return { handler: handlers.awaitingCallContractUpdateTx, state: { resolve: resolve, reject: reject, sign: sign } }; }); }); } /** * Trigger a force progress contract call * This call is going on-chain * @param {Object} options * @param {String} [options.amount] - Amount the caller of the contract commits to it * @param {String} [options.callData] - ABI encoded compiled AEVM call data for the code * @param {Number} [options.contract] - Address of the contract to call * @param {Number} [options.abiVersion] - Version of the ABI * @param {Number} [options.gasPrice=1000000000] - Gas price * @param {Number} [options.gas=1000000] - Gas limit * @param {Function} sign - Function which verifies and signs contract force progress transaction * @param {{ onOnChainTxL: Function }} callbacks * @return {Promise<Object>} * @example channel.forceProgress({ * contract: 'ct_9sRA9AVE4BYTAkh5RNfJYmwQe1NZ4MErasQLXZkFWG43TPBqa', * callData: 'cb_1111111111111111...', * amount: 0, * abiVersion: 1, * gasPrice: 1000005554 * }).then(({ accepted, signedTx }) => { * if (accepted) { * console.log('Contract force progress call successful') * } else { * console.log('Contract force progress call has been rejected') * } * }) */ function forceProgress(_ref8, sign) { var _this8 = this; var amount = _ref8.amount, callData = _ref8.callData, contract = _ref8.contract, abiVersion = _ref8.abiVersion, _ref8$gas = _ref8.gas, gas = _ref8$gas === void 0 ? 1000000 : _ref8$gas, _ref8$gasPrice = _ref8.gasPrice, gasPrice = _ref8$gasPrice === void 0 ? 1000000000 : _ref8$gasPrice, nonce = _ref8.nonce; var _ref9 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, onOnChainTx = _ref9.onOnChainTx; return new _Promise(function (resolve, reject) { enqueueAction(_this8, function (channel, state) { return state.handler === handlers.channelOpen; }, function (channel, state) { send(channel, { jsonrpc: '2.0', method: 'channels.force_progress', params: { amount: amount, call_data: callData, contract_id: contract, abi_version: abiVersion, gas_price: gasPrice, gas: gas } }); return { handler: handlers.awaitingCallContractForceProgressUpdate, state: { resolve: resolve, reject: reject, sign: sign, onOnChainTx: onOnChainTx } }; }); }); } /** * Call contract using dry-run * * In order to get the result of a potential contract call, one might need to * dry-run a contract call. It takes the exact same arguments as a call would * and returns the call object. * * The call is executed in the channel's state but it does not impact the state * whatsoever. It uses as an environment the latest channel's state and the current * top of the blockchain as seen by the node. * * @param {Object} options * @param {String} [options.amount] - Amount the caller of the contract commits to it * @param {String} [options.callData] - ABI encoded compiled AEVM call data for the code * @param {Number} [options.contract] - Address of the contract to call * @param {Number} [options.abiVersion] - Version of the ABI * @return {Promise<Object>} * @example channel.callContractStatic({ * contract: 'ct_9sRA9AVE4BYTAkh5RNfJYmwQe1NZ4MErasQLXZkFWG43TPBqa', * callData: 'cb_1111111111111111...', * amount: 0, * abiVersion: 1 * }).then(({ returnValue, gasUsed }) => { * console.log('Returned value:', returnValue) * console.log('Gas used:', gasUsed) * }) */ function callContractStatic(_x3) { return _callContractStatic.apply(this, arguments); } /** * Get contract call result * * The combination of a caller, contract and a round of execution determines the * contract call. Providing an incorrect set of those results in an error response. * * @param {Object} options * @param {String} [options.caller] - Address of contract caller * @param {String} [options.contract] - Address of the contract * @param {Number} [options.round] - Round when contract was called * @return {Promise<Object>} * @example channel.getContractCall({ * caller: 'ak_Y1NRjHuoc3CGMYMvCmdHSBpJsMDR6Ra2t5zjhRcbtMeXXLpLH', * contract: 'ct_9sRA9AVE4BYTAkh5RNfJYmwQe1NZ4MErasQLXZkFWG43TPBqa', * round: 3 * }).then(({ returnType, returnValue }) => { * if (returnType === 'ok') console.log(returnValue) * }) */ function _callContractStatic() { _callContractStatic = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(_ref10) { var amount, callData, contract, abiVersion; return _regeneratorRuntime.wrap(function _callee5$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: amount = _ref10.amount, callData = _ref10.callData, contract = _ref10.contract, abiVersion = _ref10.abiVersion; _context6.t0 = snakeToPascalObjKeys; _context6.next = 4; return call(this, 'channels.dry_run.call_contract', { amount: amount, call_data: callData, contract_id: contract, abi_version: abiVersion }); case 4: _context6.t1 = _context6.sent; return _context6.abrupt("return", (0, _context6.t0)(_context6.t1)); case 6: case "end": return _context6.stop(); } } }, _callee5, this); })); return _callContractStatic.apply(this, arguments); } function getContractCall(_x4) { return _getContractCall.apply(this, arguments); } /** * Get contract latest state * * @param {String} contract - Address of the contract * @return {Promise<Object>} * @example channel.getContractState( * 'ct_9sRA9AVE4BYTAkh5RNfJYmwQe1NZ4MErasQLXZkFWG43TPBqa' * ).then(({ contract }) => { * console.log('deposit:', contract.deposit) * }) */ function _getContractCall() { _getContractCall = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(_ref11) { var caller, contract, round; return _regeneratorRuntime.wrap(function _callee6$(_context7) { while (1) { switch (_context7.prev = _context7.next) { case 0: caller = _ref11.caller, contract = _ref11.contract, round = _ref11.round; _context7.t0 = snakeToPascalObjKeys; _context7.next = 4; return call(this, 'channels.get.contract_call', { caller_id: caller, contract_id: contract, round: round }); case 4: _context7.t1 = _context7.sent; return _context7.abrupt("return", (0, _context7.t0)(_context7.t1)); case 6: case "end": return _context7.stop(); } } }, _callee6, this); })); return _getContractCall.apply(this, arguments); } function getContractState(_x5) { return _getContractState.apply(this, arguments); } /** * Clean up all locally stored contract calls * * Contract calls are kept locally in order for the participant to be able to look them up. * They consume memory and in order for the participant to free it - one can prune all messages. * This cleans up all locally stored contract calls and those will no longer be available for * fetching and inspection. * * @return {Promise} */ function _getContractState() { _getContractState = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7(contract) { var result; return _regeneratorRuntime.wrap(function _callee7$(_context8) { while (1) { switch (_context8.prev = _context8.next) { case 0: _context8.next = 2; return call(this, 'channels.get.contract', { pubkey: contract }); case 2: result = _context8.sent; return _context8.abrupt("return", snakeToPascalObjKeys(_objectSpread(_objectSpread({}, result), {}, { contract: snakeToPascalObjKeys(result.contract) }))); case 4: case "end": return _context8.stop(); } } }, _callee7, this); })); return _getContractState.apply(this, arguments); } function cleanContractCalls() { var _this9 = this; return new _Promise(function (resolve, reject) { enqueueAction(_this9, function (channel, state) { return state.handler === handlers.channelOpen; }, function (channel, state) { send(channel, { jsonrpc: '2.0', method: 'channels.clean_contract_calls', params: {} }); return { handler: handlers.awaitingCallsPruned, state: { resolve: resolve, reject: reject } }; }); }); } /** * Send generic message * * If message is an object it will be serialized into JSON string * before sending. * * If there is ongoing update that has not yet been finished the message * will be sent after that update is finalized. * * @param {String|Object} message * @param {String} recipient - Address of the recipient * @example channel.sendMessage( * 'hello world', * 'ak_Y1NRjHuoc3CGMYMvCmdHSBpJsMDR6Ra2t5zjhRcbtMeXXLpLH' * ) */ function sendMessage(message, recipient) { var _this10 = this; var info = message; if (_typeof(message) === 'object') { info = _JSON$stringify(message); } var doSend = function doSend(channel) { return send(channel, { jsonrpc: '2.0', method: 'channels.message', params: { info: info, to: recipient } }); }; if (this.status() === 'connecting') { var onStatusChanged = function onStatusChanged(status) { if (status !== 'connecting') { // For some reason we can't immediately send a message when connection is // established. Thus we wait 500ms which seems to work. _setTimeout(function () { return doSend(_this10); }, 500); _this10.off('statusChanged', onStatusChanged); } }; this.on('statusChanged', onStatusChanged); } else { doSend(this); } } function reconnect(_x6, _x7) { return _reconnect.apply(this, arguments); } /** * Channel * * @function * @alias module:@aeternity/aepp-sdk/es/channel/index * @rtype Channel * @param {Object} options - Channel params * @param {String} options.url - Channel url (for example: "ws://localhost:3001") * @param {String} options.role - Participant role ("initiator" or "responder") * @param {String} options.initiatorId - Initiator's public key * @param {String} options.responderId - Responder's public key * @param {Number} options.pushAmount - Initial deposit in favour of the responder by the initiator * @param {Number} options.initiatorAmount - Amount of tokens the initiator has committed to the channel * @param {Number} options.responderAmount - Amount of tokens the responder has committed to the channel * @param {Number} options.channelReserve - The minimum amount both peers need to maintain * @param {Number} [options.ttl] - Minimum block height to include the channel_create_tx * @param {String} options.host - Host of the responder's node * @param {Number} options.port - The port of the responders node * @param {Number} options.lockPeriod - Amount of blocks for disputing a solo close * @param {Number} [options.existingChannelId] - Existing channel id (required if reestablishing a channel) * @param {Number} [options.offchainTx] - Offchain transaction (required if reestablishing a channel) * @param {Number} [options.timeoutIdle] - The time waiting for a new event to be initiated (default: 600000) * @param {Number} [options.timeoutFundingCreate] - The time waiting for the initiator to produce the create channel transaction after the noise session had been established (default: 120000) * @param {Number} [options.timeoutFundingSign] - The time frame the other client has to sign an off-chain update after our client had initiated and signed it. This applies only for double signed on-chain intended updates: channel create transaction, deposit, withdrawal and etc. (default: 120000) * @param {Number} [options.timeoutFundingLock] - The time frame the other client has to confirm an on-chain transaction reaching maturity (passing minimum depth) after the local node has detected this. This applies only for double signed on-chain intended updates: channel create transaction, deposit, withdrawal and etc. (default: 360000) * @param {Number} [options.timeoutSign] - The time frame the client has to return a signed off-chain update or to decline it. This applies for all off-chain updates (default: 500000) * @param {Number} [options.timeoutAccept] - The time frame the other client has to react to an event. This applies for all off-chain updates that are not meant to land on-chain, as well as some special cases: opening a noise connection, mutual closing acknowledgement and reestablishing an existing channel (default: 120000) * @param {Number} [options.timeoutInitialized] - the time frame the responder has to accept an incoming noise session. Applicable only for initiator (default: timeout_accept's value) * @param {Number} [options.timeoutAwaitingOpen] - The time frame the initiator has to start an outgoing noise session to the responder's node. Applicable only for responder (default: timeout_idle's value) * @param {Number} [options.debug=false] - Log websocket communication * @param {Function} options.sign - Function which verifies and signs transactions * @return {Promise<Object>} Channel instance * @example Channel({ * url: 'ws://localhost:3001', * role: 'initiator' * initiatorId: 'ak_Y1NRjHuoc3CGMYMvCmdHSBpJsMDR6Ra2t5zjhRcbtMeXXLpLH', * responderId: 'ak_V6an1xhec1xVaAhLuak7QoEbi6t7w5hEtYWp9bMKaJ19i6A9E', * initiatorAmount: 1e18, * responderAmount: 1e18, * pushAmount: 0, * channelReserve: 0, * ttl: 1000, * host: 'localhost', * port: 3002, * lockPeriod: 10, * async sign (tag, tx) => await account.signTransaction(tx) * }) */ function _reconnect() { _reconnect = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8(options, txParams) { var sign; return _regeneratorRuntime.wrap(function _callee8$(_context9) { while (1) { switch (_context9.prev = _context9.next) { case 0: sign = options.sign; _context9.t0 = Channel; _context9.t1 = _objectSpread; _context9.t2 = _objectSpread({}, options); _context9.t3 = {}; _context9.next = 7; return sign('reconnect', buildTx(txParams, TX_TYPE.channelReconnect).tx); case 7: _context9.t4 = _context9.sent; _context9.t5 = { reconnectTx: _context9.t4 }; _context9.t6 = (0, _context9.t1)(_context9.t2, _context9.t3, _context9.t5); return _context9.abrupt("return", (0, _context9.t0)(_context9.t6)); case 11: case "end": return _context9.stop(); } } }, _callee8); })); return _reconnect.apply(this, arguments); } var Channel = AsyncInit.compose({ init: function init(options) { var _this11 = this; return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() { return _regeneratorRuntime.wrap(function _callee$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: initialize(_this11, options); case 1: case "end": return _context2.stop(); } } }, _callee); }))(); }, methods: { on: on, off: off, status: status, state: state, round: round, id: id, fsmId: fsmId, update: update, poi: poi, balances: balances, leave: leave, shutdown: shutdown, sendMessage: sendMessage, withdraw: withdraw, deposit: deposit, createContract: createContract, callContract: callContract, callContractStatic: callContractStatic, getContractCall: getContractCall, getContractState: getContractState, disconnect: disconnect, cleanContractCalls: cleanContractCalls, forceProgress: forceProgress }, statics: { reconnect: reconnect } }); export default Channel; //# sourceMappingURL=index.js.map