hector-rubic-sdk
Version:
Simplify dApp creation
465 lines • 26.2 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Web3Private = void 0;
var erc_20_abi_1 = require("../constants/erc-20-abi");
var bignumber_js_1 = __importDefault(require("bignumber.js"));
var low_gas_error_1 = require("../../../common/errors/blockchain/low-gas.error");
var user_reject_error_1 = require("../../../common/errors/blockchain/user-reject.error");
var transaction_reverted_error_1 = require("../../../common/errors/blockchain/transaction-reverted.error");
var rubic_sdk_error_1 = require("../../../common/errors/rubic-sdk.error");
var failed_to_check_for_transaction_receipt_error_1 = require("../../../common/errors/swap/failed-to-check-for-transaction-receipt.error");
var core_1 = require("../..");
/**
* Class containing methods for executing the functions of contracts and sending transactions in order to change the state of the blockchain.
* To get information from the blockchain use {@link Web3Public}.
*/
var Web3Private = /** @class */ (function () {
/**
* @param walletConnectionConfiguration provider that implements {@link WalletConnectionConfiguration} interface.
* The provider must contain an instance of web3, initialized with ethereum wallet, e.g. Metamask, WalletConnect
*/
function Web3Private(walletConnectionConfiguration) {
this.walletConnectionConfiguration = walletConnectionConfiguration;
this.APPROVE_GAS_LIMIT = 60000;
this.web3 = walletConnectionConfiguration.web3;
}
/**
* @description converts number, string or BigNumber value to integer string
* @param amount value to convert
*/
Web3Private.stringifyAmount = function (amount) {
var bnAmount = new bignumber_js_1.default(amount);
if (!bnAmount.isInteger()) {
throw new rubic_sdk_error_1.RubicSdkError("Value ".concat(amount, " is not integer"));
}
return bnAmount.toFixed(0);
};
Object.defineProperty(Web3Private.prototype, "address", {
/**
* @description current wallet provider address
*/
get: function () {
return this.walletConnectionConfiguration.address;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Web3Private.prototype, "blockchainName", {
/**
* @description current wallet blockchainName
*/
get: function () {
return this.walletConnectionConfiguration.blockchainName;
},
enumerable: false,
configurable: true
});
/**
* @description parse web3 error by its code
* @param err web3 error to parse
*/
Web3Private.parseError = function (err) {
if (err.message.includes('Transaction has been reverted by the EVM')) {
return new transaction_reverted_error_1.TransactionRevertedError();
}
if (err.message.includes('Failed to check for transaction receipt')) {
return new failed_to_check_for_transaction_receipt_error_1.FailedToCheckForTransactionReceiptError();
}
if (err.code === -32603) {
return new low_gas_error_1.LowGasError();
}
if (err.code === 4001) {
return new user_reject_error_1.UserRejectError();
}
try {
var errorMessage = JSON.parse(err.message.slice(24)).message;
if (errorMessage) {
return new Error(errorMessage);
}
}
catch (_a) { }
return err;
};
/**
* @description sends ERC-20 tokens and resolve the promise when the transaction is included in the block
* @param contractAddress address of the smart-contract corresponding to the token
* @param toAddress token receiver address
* @param amount integer tokens amount to send (pre-multiplied by 10 ** decimals)
* @param [options] additional options
* @param [options.onTransactionHash] callback to execute when transaction enters the mempool
* @return transaction receipt
*/
Web3Private.prototype.transferTokens = function (contractAddress, toAddress, amount, options) {
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var contract;
var _this = this;
return __generator(this, function (_a) {
contract = new this.web3.eth.Contract(erc_20_abi_1.ERC20_TOKEN_ABI, contractAddress);
return [2 /*return*/, new Promise(function (resolve, reject) {
contract.methods
.transfer(toAddress, Web3Private.stringifyAmount(amount))
.send(__assign(__assign({ from: _this.address }, (options.gas && { gas: Web3Private.stringifyAmount(options.gas) })), (options.gasPrice && {
gasPrice: Web3Private.stringifyAmount(options.gasPrice)
})))
.on('transactionHash', options.onTransactionHash || (function () { }))
.on('receipt', resolve)
.on('error', function (err) {
console.error("Tokens transfer error. ".concat(err));
reject(Web3Private.parseError(err));
});
})];
});
});
};
/**
* @description sends ERC-20 tokens and resolve the promise without waiting for the transaction to be included in the block
* @param contractAddress address of the smart-contract corresponding to the token
* @param toAddress token receiver address
* @param amount integer tokens amount to send (pre-multiplied by 10 ** decimals)
* @param [options] additional options
* @param [options.onTransactionHash] callback to execute when transaction enters the mempool
* @return transaction hash
*/
Web3Private.prototype.transferTokensWithOnHashResolve = function (contractAddress, toAddress, amount, options) {
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var contract;
var _this = this;
return __generator(this, function (_a) {
contract = new this.web3.eth.Contract(erc_20_abi_1.ERC20_TOKEN_ABI, contractAddress);
return [2 /*return*/, new Promise(function (resolve, reject) {
contract.methods
.transfer(toAddress, Web3Private.stringifyAmount(amount))
.send(__assign(__assign({ from: _this.address }, (options.gas && { gas: Web3Private.stringifyAmount(options.gas) })), (options.gasPrice && {
gasPrice: Web3Private.stringifyAmount(options.gasPrice)
})))
.on('transactionHash', function (hash) { return resolve(hash); })
.on('error', function (err) {
console.error("Tokens transfer error. ".concat(err));
reject(Web3Private.parseError(err));
});
})];
});
});
};
/**
* @description tries to send Eth in transaction and resolve the promise when the transaction is included in the block or rejects the error
* @param toAddress Eth receiver address
* @param value amount in Eth units
* @param [options] additional options
* @param [options.onTransactionHash] callback to execute when transaction enters the mempool
* @param [options.inWei = false] boolean flag for determining the input parameter "value" in Wei
* @param [options.data] data for calling smart contract methods.
* Use this field only if you are receiving data from a third-party api.
* When manually calling contract methods, use executeContractMethod()
* @param [options.gas] transaction gas limit in absolute gas units
* @param [options.gasPrice] price of gas unit in wei
* @return transaction receipt
*/
Web3Private.prototype.trySendTransaction = function (toAddress, value, options) {
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var err_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 3, , 4]);
return [4 /*yield*/, this.web3.eth.call(__assign(__assign(__assign({ from: this.address, to: toAddress, value: Web3Private.stringifyAmount(value) }, (options.gas && { gas: Web3Private.stringifyAmount(options.gas) })), (options.gasPrice && {
gasPrice: Web3Private.stringifyAmount(options.gasPrice)
})), (options.data && { data: options.data })))];
case 1:
_a.sent();
return [4 /*yield*/, this.sendTransaction(toAddress, value, options)];
case 2: return [2 /*return*/, _a.sent()];
case 3:
err_1 = _a.sent();
console.error('Tokens transfer error', err_1);
throw Web3Private.parseError(err_1);
case 4: return [2 /*return*/];
}
});
});
};
/**
* @description sends Eth in transaction and resolve the promise when the transaction is included in the block
* @param toAddress Eth receiver address
* @param value amount in Eth units
* @param [options] additional options
* @param [options.onTransactionHash] callback to execute when transaction enters the mempool
* @param [options.inWei = false] boolean flag for determining the input parameter "value" in Wei
* @param [options.data] data for calling smart contract methods.
* Use this field only if you are receiving data from a third-party api.
* When manually calling contract methods, use executeContractMethod()
* @param [options.gas] transaction gas limit in absolute gas units
* @param [options.gasPrice] price of gas unit in wei
* @return transaction receipt
*/
Web3Private.prototype.sendTransaction = function (toAddress, value, options) {
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) {
_this.web3.eth
.sendTransaction(__assign(__assign(__assign({ from: _this.address, to: toAddress, value: Web3Private.stringifyAmount(value) }, (options.gas && { gas: Web3Private.stringifyAmount(options.gas) })), (options.gasPrice && {
gasPrice: Web3Private.stringifyAmount(options.gasPrice)
})), (options.data && { data: options.data })))
.on('transactionHash', options.onTransactionHash || (function () { }))
.on('receipt', function (receipt) { return resolve(receipt); })
.on('error', function (err) {
console.error("Tokens transfer error. ".concat(err));
reject(Web3Private.parseError(err));
});
})];
});
});
};
/**
* @description sends Eth in transaction and resolve the promise without waiting for the transaction to be included in the block
* @param toAddress Eth receiver address
* @param value amount in Eth units
* @param [options] additional options
* @param [options.inWei = false] boolean flag for determining the input parameter "value" in Wei
* @return transaction hash
*/
Web3Private.prototype.sendTransactionWithOnHashResolve = function (toAddress, value, options) {
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) {
_this.web3.eth
.sendTransaction(__assign(__assign(__assign({ from: _this.address, to: toAddress, value: Web3Private.stringifyAmount(value) }, (options.gas && { gas: Web3Private.stringifyAmount(options.gas) })), (options.gasPrice && {
gasPrice: Web3Private.stringifyAmount(options.gasPrice)
})), (options.data && { data: options.data })))
.on('transactionHash', function (hash) { return resolve(hash); })
.on('error', function (err) {
console.error("Tokens transfer error. ".concat(err));
reject(Web3Private.parseError(err));
});
})];
});
});
};
/**
* @description executes approve method in ERC-20 token contract
* @param tokenAddress address of the smart-contract corresponding to the token
* @param spenderAddress wallet or contract address to approve
* @param value integer value to approve (pre-multiplied by 10 ** decimals)
* @param [options] additional options
* @param [options.onTransactionHash] callback to execute when transaction enters the mempool
* @return approval transaction receipt
*/
Web3Private.prototype.approveTokens = function (tokenAddress, spenderAddress, value, options) {
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var rawValue, contract, gas;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (value === 'infinity') {
rawValue = new bignumber_js_1.default(2).pow(256).minus(1);
}
else {
rawValue = value;
}
contract = new this.web3.eth.Contract(erc_20_abi_1.ERC20_TOKEN_ABI, tokenAddress);
gas = options.gas;
if (!!gas) return [3 /*break*/, 2];
return [4 /*yield*/, contract.methods.approve(spenderAddress, rawValue.toFixed(0)).estimateGas({
from: this.address
})];
case 1:
gas = _a.sent();
_a.label = 2;
case 2: return [2 /*return*/, new Promise(function (resolve, reject) {
contract.methods
.approve(spenderAddress, rawValue.toFixed(0))
.send(__assign(__assign({ from: _this.address }, (gas && { gas: Web3Private.stringifyAmount(gas) })), (options.gasPrice && {
gasPrice: Web3Private.stringifyAmount(options.gasPrice)
})))
.on('transactionHash', options.onTransactionHash || (function () { }))
.on('receipt', resolve)
.on('error', function (err) {
console.error("Tokens approve error. ".concat(err));
reject(Web3Private.parseError(err));
});
})];
}
});
});
};
/**
* @description tries to execute method of smart-contract and resolve the promise when the transaction is included in the block or rejects the error
* @param contractAddress address of smart-contract which method is to be executed
* @param contractAbi abi of smart-contract which method is to be executed
* @param methodName executing method name
* @param methodArguments executing method arguments
* @param [options] additional options
* @param [options.value] amount in Wei amount to be attached to the transaction
* @param [options.gas] gas limit to be attached to the transaction
* @param allowError Check error and decides to execute contact if it needed.
*/
Web3Private.prototype.tryExecuteContractMethod = function (contractAddress, contractAbi, methodName, methodArguments, options, allowError) {
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var contract, gas, err_2;
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
contract = new this.web3.eth.Contract(contractAbi, contractAddress);
_b.label = 1;
case 1:
_b.trys.push([1, 4, , 5]);
return [4 /*yield*/, (_a = contract.methods)[methodName].apply(_a, methodArguments).estimateGas(__assign(__assign(__assign({ from: this.address }, (options.value && { value: Web3Private.stringifyAmount(options.value) })), (options.gas && { gas: Web3Private.stringifyAmount(options.gas) })), (options.gasPrice && {
gasPrice: Web3Private.stringifyAmount(options.gasPrice)
})))];
case 2:
gas = _b.sent();
return [4 /*yield*/, this.executeContractMethod(contractAddress, contractAbi, methodName, methodArguments, __assign(__assign({}, options), { gas: options.gas || core_1.Web3Pure.calculateGasMargin(gas, 1.15) }))];
case 3: return [2 /*return*/, _b.sent()];
case 4:
err_2 = _b.sent();
if (allowError && allowError(err_2)) {
return [2 /*return*/, this.executeContractMethod(contractAddress, contractAbi, methodName, methodArguments, options)];
}
console.error('Method execution error: ', err_2);
throw Web3Private.parseError(err_2);
case 5: return [2 /*return*/];
}
});
});
};
/**
* @description executes method of smart-contract and resolve the promise when the transaction is included in the block
* @param contractAddress address of smart-contract which method is to be executed
* @param contractAbi abi of smart-contract which method is to be executed
* @param methodName executing method name
* @param methodArguments executing method arguments
* @param [options] additional options
* @param [options.onTransactionHash] callback to execute when transaction enters the mempool
* @param [options.value] amount in Wei amount to be attached to the transaction
* @return smart-contract method returned value
*/
Web3Private.prototype.executeContractMethod = function (contractAddress, contractAbi, methodName, methodArguments, options) {
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var contract;
var _this = this;
return __generator(this, function (_a) {
contract = new this.web3.eth.Contract(contractAbi, contractAddress);
return [2 /*return*/, new Promise(function (resolve, reject) {
var _a;
(_a = contract.methods)[methodName].apply(_a, methodArguments).send(__assign(__assign(__assign({ from: _this.address }, (options.value && {
value: Web3Private.stringifyAmount(options.value)
})), (options.gas && {
gas: Web3Private.stringifyAmount(options.gas)
})), (options.gasPrice && {
gasPrice: Web3Private.stringifyAmount(options.gasPrice)
})))
.on('transactionHash', options.onTransactionHash || (function () { }))
.on('receipt', resolve)
.on('error', function (err) {
console.error("Method execution error. ".concat(err));
reject(Web3Private.parseError(err));
});
})];
});
});
};
/**
* @description executes method of smart-contract and resolve the promise without waiting for the transaction to be included in the block
* @param contractAddress address of smart-contract which method is to be executed
* @param contractAbi abi of smart-contract which method is to be executed
* @param methodName executing method name
* @param methodArguments executing method arguments
* @param [options] additional options
* @param [options.onTransactionHash] callback to execute when transaction enters the mempool
* @param [options.value] amount in Wei amount to be attached to the transaction
* @return smart-contract method returned value
*/
Web3Private.prototype.executeContractMethodWithOnHashResolve = function (contractAddress, contractAbi, methodName, methodArguments, options) {
var _this = this;
if (options === void 0) { options = {}; }
var contract = new this.web3.eth.Contract(contractAbi, contractAddress);
return new Promise(function (resolve, reject) {
var _a;
(_a = contract.methods)[methodName].apply(_a, methodArguments).send(__assign(__assign({ from: _this.address }, (options.gas && { gas: Web3Private.stringifyAmount(options.gas) })), (options.gasPrice && {
gasPrice: Web3Private.stringifyAmount(options.gasPrice)
})))
.on('transactionHash', resolve)
.on('error', function (err) {
console.error("Tokens approve error. ".concat(err));
reject(Web3Private.parseError(err));
});
});
};
/**
* @description removes approval for token use
* @param tokenAddress tokenAddress address of the smart-contract corresponding to the token
* @param spenderAddress wallet or contract address to approve
*/
Web3Private.prototype.unApprove = function (tokenAddress, spenderAddress) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, this.approveTokens(tokenAddress, spenderAddress, new bignumber_js_1.default(0))];
});
});
};
return Web3Private;
}());
exports.Web3Private = Web3Private;
//# sourceMappingURL=web3-private.js.map