ptokens-pbtc
Version:
repo holding the code for interacting with pBTC
352 lines (346 loc) • 18.4 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var _defineProperty = _interopDefault(require('@babel/runtime/helpers/defineProperty'));
var _asyncToGenerator = _interopDefault(require('@babel/runtime/helpers/asyncToGenerator'));
var _classCallCheck = _interopDefault(require('@babel/runtime/helpers/classCallCheck'));
var _createClass = _interopDefault(require('@babel/runtime/helpers/createClass'));
var _inherits = _interopDefault(require('@babel/runtime/helpers/inherits'));
var _possibleConstructorReturn = _interopDefault(require('@babel/runtime/helpers/possibleConstructorReturn'));
var _getPrototypeOf = _interopDefault(require('@babel/runtime/helpers/getPrototypeOf'));
var _regeneratorRuntime = _interopDefault(require('@babel/runtime/regenerator'));
var Web3 = _interopDefault(require('web3'));
var Web3PromiEvent = _interopDefault(require('web3-core-promievent'));
var ptokensNodeSelector = require('ptokens-node-selector');
var ptokensUtils = require('ptokens-utils');
var ptokensDepositAddress = require('ptokens-deposit-address');
var Web3Utils = _interopDefault(require('web3-utils'));
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
var MINIMUM_BTC_REDEEMABLE = 0.00005;
var pBTC = function (_NodeSelector) {
_inherits(pBTC, _NodeSelector);
var _super = _createSuper(pBTC);
function pBTC(_configs) {
var _this;
_classCallCheck(this, pBTC);
var _helpers$parseParams = ptokensUtils.helpers.parseParams(_configs, _configs.nativeBlockchain || ptokensUtils.constants.blockchains.Bitcoin),
hostBlockchain = _helpers$parseParams.hostBlockchain,
hostNetwork = _helpers$parseParams.hostNetwork,
nativeBlockchain = _helpers$parseParams.nativeBlockchain,
nativeNetwork = _helpers$parseParams.nativeNetwork;
_this = _super.call(this, {
pToken: _configs.pToken || ptokensUtils.constants.pTokens.pBTC,
hostBlockchain: hostBlockchain,
hostNetwork: hostNetwork,
nativeBlockchain: nativeBlockchain,
nativeNetwork: nativeNetwork,
defaultNode: _configs.defaultNode
});
var ethPrivateKey = _configs.ethPrivateKey,
ethProvider = _configs.ethProvider,
eosPrivateKey = _configs.eosPrivateKey,
eosRpc = _configs.eosRpc,
eosSignatureProvider = _configs.eosSignatureProvider,
algoProvider = _configs.algoProvider,
algoClient = _configs.algoClient;
if ((ethProvider || ethPrivateKey) && (eosSignatureProvider || eosPrivateKey)) throw new Error('Bad Initialization. Impossible to use both ETH and EOS');
if (ethProvider) _this.hostApi = new Web3(ethProvider);
if (ethPrivateKey) {
var account = _this.hostApi.eth.accounts.privateKeyToAccount(ptokensUtils.eth.addHexPrefix(ethPrivateKey));
_this.hostApi.eth.defaultAccount = account.address;
_this.hostPrivateKey = ptokensUtils.eth.addHexPrefix(ethPrivateKey);
} else {
_this.hostPrivateKey = null;
}
if (eosSignatureProvider) {
_this.hostApi = ptokensUtils.eos.getApi(null, eosRpc, eosSignatureProvider);
} else if (eosPrivateKey && eosRpc) {
_this.hostApi = ptokensUtils.eos.getApi(eosPrivateKey, eosRpc, null);
_this.hostPrivateKey = eosPrivateKey;
} else if (!eosSignatureProvider && !eosPrivateKey && eosRpc) {
_this.hostApi = ptokensUtils.eos.getApi(null, eosRpc, null);
}
if (algoProvider) _this.hostApi = algoProvider;
if (algoClient) _this.algoClient = algoClient;
_this.contractAddress = null;
_this.decimals = null;
return _this;
}
_createClass(pBTC, [{
key: "getDepositAddress",
value: function () {
var _getDepositAddress = _asyncToGenerator( _regeneratorRuntime.mark(function _callee(_hostAddress) {
var _isValidAddress;
var isValidAddress, selectedNode, depositAddress;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
isValidAddress = (_isValidAddress = {}, _defineProperty(_isValidAddress, ptokensUtils.constants.blockchains.Ethereum, function (_address) {
return Web3Utils.isAddress(_address);
}), _defineProperty(_isValidAddress, ptokensUtils.constants.blockchains.BinanceSmartChain, function (_address) {
return Web3Utils.isAddress(_address);
}), _defineProperty(_isValidAddress, ptokensUtils.constants.blockchains.Xdai, function (_address) {
return Web3Utils.isAddress(_address);
}), _defineProperty(_isValidAddress, ptokensUtils.constants.blockchains.Polygon, function (_address) {
return Web3Utils.isAddress(_address);
}), _defineProperty(_isValidAddress, ptokensUtils.constants.blockchains.Arbitrum, function (_address) {
return Web3Utils.isAddress(_address);
}), _defineProperty(_isValidAddress, ptokensUtils.constants.blockchains.Eosio, function (_address) {
return ptokensUtils.eos.isValidAccountName(_address);
}), _defineProperty(_isValidAddress, ptokensUtils.constants.blockchains.Telos, function (_address) {
return ptokensUtils.eos.isValidAccountName(_address);
}), _defineProperty(_isValidAddress, ptokensUtils.constants.blockchains.Algorand, function (_address) {
return ptokensUtils.algo.isValidAddress(_address);
}), _defineProperty(_isValidAddress, ptokensUtils.constants.blockchains.Libre, function (_address) {
return ptokensUtils.eos.isValidAccountName(_address);
}), _isValidAddress);
if (isValidAddress[this.hostBlockchain](_hostAddress)) {
_context.next = 3;
break;
}
throw new Error('Invalid host account');
case 3:
if (!this.selectedNode) {
_context.next = 7;
break;
}
_context.t0 = this.selectedNode;
_context.next = 10;
break;
case 7:
_context.next = 9;
return this.select();
case 9:
_context.t0 = _context.sent;
case 10:
selectedNode = _context.t0;
if (selectedNode) {
_context.next = 13;
break;
}
throw new Error('No node selected. Impossible to generate a deposit Address.');
case 13:
depositAddress = new ptokensDepositAddress.DepositAddress({
node: selectedNode,
nativeBlockchain: this.nativeBlockchain,
nativeNetwork: this.nativeNetwork,
hostBlockchain: this.hostBlockchain,
hostNetwork: this.hostNetwork,
hostApi: this.hostApi
});
_context.next = 16;
return depositAddress.generate(_hostAddress);
case 16:
return _context.abrupt("return", depositAddress);
case 17:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
function getDepositAddress(_x) {
return _getDepositAddress.apply(this, arguments);
}
return getDepositAddress;
}()
}, {
key: "redeem",
value: function redeem(_amount, _btcAddress) {
var _this2 = this;
var _options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var promiEvent = Web3PromiEvent();
var start = function () {
var _ref = _asyncToGenerator( _regeneratorRuntime.mark(function _callee2() {
var gas, gasPrice, blocksBehind, expireSeconds, permission, actor, from, swapInfo, redeemFromEvmCompatible, redeemFromEosio, redeemFromAlgorand, destinationChainId, hostTxHash, hostTxReceipt, eosTxReceipt, _hostTxReceipt, broadcastedBtcTxReport, broadcastedBtcTxReceipt;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_context2.prev = 0;
gas = _options.gas, gasPrice = _options.gasPrice, blocksBehind = _options.blocksBehind, expireSeconds = _options.expireSeconds, permission = _options.permission, actor = _options.actor, from = _options.from, swapInfo = _options.swapInfo;
_context2.next = 4;
return _this2._loadData();
case 4:
if (!(_amount < MINIMUM_BTC_REDEEMABLE)) {
_context2.next = 7;
break;
}
promiEvent.reject("Impossible to burn less than ".concat(MINIMUM_BTC_REDEEMABLE, " pBTC"));
return _context2.abrupt("return");
case 7:
if (!(_this2.pToken === ptokensUtils.constants.pTokens.pBTC)) {
_context2.next = 11;
break;
}
if (ptokensUtils.btc.isValidAddress(_btcAddress)) {
_context2.next = 11;
break;
}
promiEvent.reject('Invalid Bitcoin address');
return _context2.abrupt("return");
case 11:
if (_this2.selectedNode) {
_context2.next = 14;
break;
}
_context2.next = 14;
return _this2.select();
case 14:
redeemFromEvmCompatible = ptokensUtils.redeemFrom.redeemFromEvmCompatible, redeemFromEosio = ptokensUtils.redeemFrom.redeemFromEosio, redeemFromAlgorand = ptokensUtils.redeemFrom.redeemFromAlgorand;
destinationChainId = _this2.version === 'v2' ? ptokensUtils.constants.chainIds[_this2.nativeBlockchain][_this2.nativeNetwork] : null;
hostTxHash = null;
if (!(_this2.hostBlockchain === ptokensUtils.constants.blockchains.Ethereum || _this2.hostBlockchain === ptokensUtils.constants.blockchains.BinanceSmartChain || _this2.hostBlockchain === ptokensUtils.constants.blockchains.Xdai || _this2.hostBlockchain === ptokensUtils.constants.blockchains.Polygon || _this2.hostBlockchain === ptokensUtils.constants.blockchains.Arbitrum)) {
_context2.next = 24;
break;
}
_context2.next = 20;
return redeemFromEvmCompatible(_this2.hostApi, {
privateKey: _this2.hostPrivateKey,
gas: gas,
gasPrice: gasPrice,
contractAddress: _this2.contractAddress,
value: 0
}, _this2.version === 'v1' ? [_amount, _btcAddress] : [_amount, _btcAddress, destinationChainId], promiEvent, 'hostTxBroadcasted', _this2.version || 'v1');
case 20:
hostTxReceipt = _context2.sent;
if (_this2.hostBlockchain === ptokensUtils.constants.blockchains.Ethereum) promiEvent.eventEmitter.emit('onEthTxConfirmed', hostTxReceipt);
promiEvent.eventEmitter.emit('hostTxConfirmed', hostTxReceipt);
hostTxHash = hostTxReceipt.transactionHash;
case 24:
if (!(_this2.hostBlockchain === ptokensUtils.constants.blockchains.Eosio || _this2.hostBlockchain === ptokensUtils.constants.blockchains.Telos || _this2.hostBlockchain === ptokensUtils.constants.blockchains.Libre)) {
_context2.next = 31;
break;
}
_context2.next = 27;
return redeemFromEosio(_this2.hostApi, _amount, _btcAddress, _this2.version === 'v2' ? 9 : 8, _this2.contractAddress, ptokensUtils.constants.pTokens.pBTC, {
blocksBehind: blocksBehind,
expireSeconds: expireSeconds,
permission: permission,
actor: actor,
version: _this2.version,
destinationChainId: destinationChainId
});
case 27:
eosTxReceipt = _context2.sent;
if (_this2.hostBlockchain === ptokensUtils.constants.blockchains.Eosio) {
promiEvent.eventEmitter.emit('onEosTxConfirmed', eosTxReceipt);
}
promiEvent.eventEmitter.emit('hostTxConfirmed', eosTxReceipt);
hostTxHash = eosTxReceipt.transaction_id;
case 31:
if (!(_this2.hostBlockchain === ptokensUtils.constants.blockchains.Algorand)) {
_context2.next = 37;
break;
}
_context2.next = 34;
return redeemFromAlgorand({
provider: _this2.hostApi,
client: _this2.algoClient,
amount: _amount,
to: _this2.hostIdentity,
assetIndex: _this2.contractAddress,
nativeAccount: _btcAddress,
from: from,
destinationChainId: destinationChainId,
eventEmitter: promiEvent.eventEmitter,
swapInfo: swapInfo
});
case 34:
_hostTxReceipt = _context2.sent;
promiEvent.eventEmitter.emit('hostTxConfirmed', _hostTxReceipt);
hostTxHash = _hostTxReceipt.txID().toString();
case 37:
_context2.next = 39;
return _this2.selectedNode.monitorIncomingTransaction(hostTxHash, promiEvent.eventEmitter);
case 39:
broadcastedBtcTxReport = _context2.sent;
_context2.next = 42;
return ptokensUtils.btc.waitForTransactionConfirmation(_this2.nativeNetwork, broadcastedBtcTxReport.broadcast_tx_hash, 5000);
case 42:
broadcastedBtcTxReceipt = _context2.sent;
promiEvent.eventEmitter.emit('onBtcTxConfirmed', broadcastedBtcTxReceipt);
promiEvent.eventEmitter.emit('nativeTxConfirmed', broadcastedBtcTxReceipt);
promiEvent.resolve({
amount: _amount,
hostTx: hostTxHash,
nativeTx: broadcastedBtcTxReport.broadcast_tx_hash,
to: _btcAddress
});
_context2.next = 51;
break;
case 48:
_context2.prev = 48;
_context2.t0 = _context2["catch"](0);
promiEvent.reject(_context2.t0);
case 51:
case "end":
return _context2.stop();
}
}
}, _callee2, null, [[0, 48]]);
}));
return function start() {
return _ref.apply(this, arguments);
};
}();
start();
return promiEvent.eventEmitter;
}
}, {
key: "_loadData",
value: function () {
var _loadData2 = _asyncToGenerator( _regeneratorRuntime.mark(function _callee3() {
var _yield$this$selectedN, host_identity, smart_contract_address, host_smart_contract_address, versions;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_context3.prev = 0;
if (this.contractAddress) {
_context3.next = 15;
break;
}
if (this.selectedNode) {
_context3.next = 5;
break;
}
_context3.next = 5;
return this.select();
case 5:
_context3.next = 7;
return this.selectedNode.getInfo();
case 7:
_yield$this$selectedN = _context3.sent;
host_identity = _yield$this$selectedN.host_identity;
smart_contract_address = _yield$this$selectedN.smart_contract_address;
host_smart_contract_address = _yield$this$selectedN.host_smart_contract_address;
versions = _yield$this$selectedN.versions;
this.contractAddress = smart_contract_address || host_smart_contract_address;
this.version = versions && versions.network ? versions.network : 'v1';
this.hostIdentity = host_identity;
case 15:
_context3.next = 20;
break;
case 17:
_context3.prev = 17;
_context3.t0 = _context3["catch"](0);
throw new Error("Error during getting contract address: ".concat(_context3.t0.message));
case 20:
case "end":
return _context3.stop();
}
}
}, _callee3, this, [[0, 17]]);
}));
function _loadData() {
return _loadData2.apply(this, arguments);
}
return _loadData;
}()
}]);
return pBTC;
}(ptokensNodeSelector.NodeSelector);
exports.pBTC = pBTC;