@aeternity/aepp-sdk
Version:
SDK for the æternity blockchain
285 lines (251 loc) • 9.77 kB
JavaScript
import _typeof from "@babel/runtime-corejs3/helpers/typeof";
import _toConsumableArray from "@babel/runtime-corejs3/helpers/toConsumableArray";
import _slicedToArray from "@babel/runtime-corejs3/helpers/slicedToArray";
import _Object$keys from "@babel/runtime-corejs3/core-js-stable/object/keys";
import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat";
import _Object$assign from "@babel/runtime-corejs3/core-js-stable/object/assign";
import _findInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/find";
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
import _Promise from "@babel/runtime-corejs3/core-js-stable/promise";
/**
* RpcClient module
*
* @module @aeternity/aepp-sdk/es/utils/aepp-wallet-communication/rpc/rpc-client
* @export { RpcClient, RpcClients }
* @example import RpcClient from '@aeternity/aepp-sdk/es/utils/aepp-wallet-communication/rpc/rpc-client'
*/
import stampit from '@stamp/it';
import { METHODS, RPC_STATUS, SUBSCRIPTION_TYPES } from '../schema';
import { sendMessage, message, isValidAccounts } from '../helpers';
/**
* Contain functionality for using RPC conection
* @alias module:@aeternity/aepp-sdk/es/utils/aepp-wallet-communication/rpc/rpc-client
* @function
* @rtype Stamp
* @param {Object} param Init params object
* @param {String} param.name Client name
* @param {Object} param.connection Connection object
* @param {Function[]} param.handlers Arrays with two function for handling messages ([ onMessage: Function, onDisconnect: Function])
* @return {Object}
*/
export default stampit({
init: function init(_ref) {
var _this = this;
var id = _ref.id,
name = _ref.name,
networkId = _ref.networkId,
icons = _ref.icons,
connection = _ref.connection,
_ref$handlers = _slicedToArray(_ref.handlers, 2),
onMessage = _ref$handlers[0],
onDisconnect = _ref$handlers[1];
this.id = id;
this.connection = connection;
this.info = {
name: name,
networkId: networkId,
icons: icons
}; // {
// [msg.id]: { resolve, reject }
// }
this.callbacks = {}; // ['connected', 'current']
this.addressSubscription = []; // {
// connected: { [pub]: {...meta} },
// current: { [pub]: {...meta} }
// }
this.accounts = {};
this.sendMessage = sendMessage(this.connection);
var handleMessage = function handleMessage(msg, origin) {
if (!msg || !msg.jsonrpc || msg.jsonrpc !== '2.0' || !msg.method) {
throw new Error("Received invalid message: ".concat(msg));
}
onMessage(msg, origin);
};
var disconnect = function disconnect(aepp, connection) {
_this.disconnect(true);
typeof onDisconnect === 'function' && onDisconnect(connection, _this);
};
connection.connect(handleMessage, disconnect);
},
propertyDescriptors: {
currentAccount: {
enumerable: true,
configurable: false,
get: function get() {
return this.isHasAccounts() ? _Object$keys(this.accounts.current)[0] : undefined;
}
},
addresses: {
enumerable: true,
configurable: false,
get: function get() {
var _context;
return this.isHasAccounts() ? _concatInstanceProperty(_context = []).call(_context, _toConsumableArray(_Object$keys(this.accounts.current)), _toConsumableArray(_Object$keys(this.accounts.connected))) : [];
}
},
origin: {
enumerable: true,
configurable: false,
get: function get() {
return this.connection;
}
}
},
methods: {
/**
* Update info
* @function updateInfo
* @instance
* @rtype (info: Object) => void
* @param {Object} info Info to update (will be merged with current info object)
* @return {void}
*/
updateInfo: function updateInfo(info) {
_Object$assign(this.info, info);
},
isHasAccounts: function isHasAccounts() {
return _typeof(this.accounts) === 'object' && _typeof(this.accounts.connected) === 'object' && _typeof(this.accounts.current) === 'object';
},
isSubscribed: function isSubscribed() {
return this.addressSubscription.length && this.isHasAccounts();
},
/**
* Check if aepp has access to account
* @function hasAccessToAccount
* @instance
* @rtype (address: String) => Boolean
* @param {String} address Account address
* @return {Boolean} is connected
*/
hasAccessToAccount: function hasAccessToAccount(address) {
var _context2;
return !!address && _findInstanceProperty(_context2 = this.addresses).call(_context2, function (a) {
return a === address;
});
},
/**
* Check if is connected
* @function isConnected
* @instance
* @rtype () => Boolean
* @return {Boolean} is connected
*/
isConnected: function isConnected() {
return this.connection.isConnected() && this.info.status === RPC_STATUS.CONNECTED;
},
/**
* Get selected account
* @function getCurrentAccount
* @instance
* @rtype ({ onAccount } = {}) => String
* @param {Object} options Options
* @return {String}
*/
getCurrentAccount: function getCurrentAccount() {
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
onAccount = _ref2.onAccount;
return onAccount || _Object$keys(this.accounts.current)[0];
},
/**
* Disconnect
* @function disconnect
* @instance
* @rtype () => void
* @return {void}
*/
disconnect: function disconnect() {
var forceConnectionClose = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
this.info.status = RPC_STATUS.DISCONNECTED;
this.addressSubscription = [];
this.accounts = {};
forceConnectionClose || this.connection.disconnect();
},
/**
* Update accounts and sent `update.address` notification to AEPP
* @param {{ current: Object, connected: Object }} accounts Object with current and connected accounts
* @param {{ forceNotification: Boolean }} [options={ forceNotification: false }] Don not sent update notification to AEPP
*/
setAccounts: function setAccounts(accounts) {
var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref3$forceNotificati = _ref3.forceNotification,
forceNotification = _ref3$forceNotificati === void 0 ? false : _ref3$forceNotificati;
if (!isValidAccounts(accounts)) {
throw new Error('Invalid accounts object. Should be object like: `{ connected: {}, selected: {} }`');
}
this.accounts = accounts;
if (!forceNotification) {
// Sent notification about account updates
this.sendMessage(message(METHODS.wallet.updateAddress, this.accounts), true);
}
},
/**
* Update subscription
* @function updateSubscription
* @instance
* @rtype (type: String, value: String) => void
* @param {String} type Subscription type
* @param {String} value Subscription value
* @return {String[]}
*/
updateSubscription: function updateSubscription(type, value) {
var _context3, _context4;
if (type === SUBSCRIPTION_TYPES.subscribe && !_includesInstanceProperty(_context3 = this.addressSubscription).call(_context3, value)) {
this.addressSubscription.push(value);
}
if (type === SUBSCRIPTION_TYPES.unsubscribe && _includesInstanceProperty(_context4 = this.addressSubscription).call(_context4, value)) {
var _context5;
this.addressSubscription = _filterInstanceProperty(_context5 = this.addressSubscription).call(_context5, function (s) {
return s !== value;
});
}
return this.addressSubscription;
},
/**
* Make a request
* @function request
* @instance
* @rtype (name: String, params: Object) => Promise
* @param {String} name Method name
* @param {Object} params Method params
* @return {Promise} Promise which will be resolved after receiving response message
*/
request: function request(name, params) {
var _this2 = this;
var msgId = this.sendMessage(message(name, params));
if (Object.prototype.hasOwnProperty.call(this.callbacks, msgId)) throw new Error('Callback Already exist');
return new _Promise(function (resolve, reject) {
_this2.callbacks[msgId] = {
resolve: resolve,
reject: reject
};
});
},
/**
* Process response message
* @function processResponse
* @instance
* @rtype (msg: Object, transformResult: Function) => void
* @param {Object} msg Message object
* @param {Function=} transformResult Optional parser function for message
* @return {void}
*/
processResponse: function processResponse(_ref4, transformResult) {
var id = _ref4.id,
error = _ref4.error,
result = _ref4.result;
if (!this.callbacks[id]) throw new Error("Can't find callback for this messageId ".concat(id));
if (result) {
var _this$callbacks$id;
(_this$callbacks$id = this.callbacks[id]).resolve.apply(_this$callbacks$id, _toConsumableArray(typeof transformResult === 'function' ? transformResult({
id: id,
result: result
}) : [result]));
} else {
this.callbacks[id].reject(error);
}
delete this.callbacks[id];
}
}
});
//# sourceMappingURL=rpc-client.js.map