@aeternity/aepp-sdk
Version:
SDK for the æternity blockchain
1,207 lines (1,101 loc) • 41.4 kB
JavaScript
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