Skip to content

Commit

Permalink
Merge pull request #146 from OriginTrail/bugfix/ensure-blockchain-info
Browse files Browse the repository at this point in the history
Updated ensureBlockchainInfo logic, added gasLimitMultiplier option
  • Loading branch information
u-hubar authored Sep 10, 2024
2 parents 459eaee + adca2aa commit 10a8039
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 63 deletions.
1 change: 1 addition & 0 deletions constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ const DEFAULT_PARAMETERS = {
HANDLE_NOT_MINED_ERROR: false,
SIMULATE_TXS: false,
FORCE_REPLACE_TXS: false,
GAS_LIMIT_MULTIPLIER: 1,
};

const DEFAULT_GAS_PRICE = {
Expand Down
126 changes: 64 additions & 62 deletions services/blockchain-service/blockchain-service-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,37 @@ class BlockchainServiceBase {
// overridden by subclasses
}

async ensureBlockchainInfo(blockchain) {
if (!this[blockchain.name]) {
this[blockchain.name] = {
contracts: { [blockchain.hubContract]: {} },
contractAddresses: {
[blockchain.hubContract]: {
Hub: blockchain.hubContract,
},
},
};

const web3Instance = await this.getWeb3Instance(blockchain);
this[blockchain.name].contracts[blockchain.hubContract].Hub =
new web3Instance.eth.Contract(this.abis.Hub, blockchain.hubContract, { from: blockchain.publicKey });

}
}

async getWeb3Instance(blockchain) {
if (!this[blockchain.name].web3) {
const blockchainOptions = {
transactionPollingTimeout: blockchain.transactionPollingTimeout,
};
await this.initializeWeb3(blockchain.name, blockchain.rpc, blockchainOptions);
}

return this[blockchain.name].web3;
}

async getNetworkGasPrice(blockchain) {
await this.ensureBlockchainInfo(blockchain);
const web3Instance = await this.getWeb3Instance(blockchain);

try {
Expand Down Expand Up @@ -99,7 +129,9 @@ class BlockchainServiceBase {
}

async callContractFunction(contractName, functionName, args, blockchain) {
await this.ensureBlockchainInfo(blockchain);
let contractInstance = await this.getContractInstance(contractName, blockchain);

try {
return await contractInstance.methods[functionName](...args).call();
} catch (error) {
Expand All @@ -124,41 +156,32 @@ class BlockchainServiceBase {
}

async prepareTransaction(contractInstance, functionName, args, blockchain) {
await this.ensureBlockchainInfo(blockchain);
const web3Instance = await this.getWeb3Instance(blockchain);
const publicKey = await this.getPublicKey(blockchain);
const encodedABI = await contractInstance.methods[functionName](...args).encodeABI();

if (blockchain.simulateTxs) {
await this[blockchain.name].web3.eth.call({
to: contractInstance.options.address,
data: encodedABI,
from: publicKey,
});
}

let gasLimit = Number(
await contractInstance.methods[functionName](...args).estimateGas({
from: publicKey,
})
);

if (blockchain.name.startsWith('base')) {
gasLimit *= 1.2;
}
gasLimit = Math.round(gasLimit * blockchain.gasLimitMultiplier);

let gasPrice;
if (blockchain.previousTxGasPrice && blockchain.retryTx) {
// Increase previous tx gas price by 20%
gasPrice = Math.round(blockchain.previousTxGasPrice * 1.2);
} else if (blockchain.forceReplaceTxs) {
// Get the current transaction count (nonce) of the wallet, including pending transactions
const currentNonce = await this[blockchain.name].web3.eth.getTransactionCount(publicKey, 'pending');
const currentNonce = await web3Instance.eth.getTransactionCount(publicKey, 'pending');

// Get the transaction count of the wallet excluding pending transactions
const confirmedNonce = await this[blockchain.name].web3.eth.getTransactionCount(publicKey, 'latest');
const confirmedNonce = await web3Instance.eth.getTransactionCount(publicKey, 'latest');

// If there are any pending transactions
if (currentNonce > confirmedNonce) {
const pendingBlock = await this[blockchain.name].web3.eth.getBlock('pending', true);
const pendingBlock = await web3Instance.eth.getBlock('pending', true);

// Search for pending tx in the pending block
const pendingTx = Object.values(pendingBlock.transactions).find(
Expand All @@ -178,6 +201,16 @@ class BlockchainServiceBase {
gasPrice = blockchain.gasPrice || (await this.getNetworkGasPrice(blockchain));
}

if (blockchain.simulateTxs) {
await web3Instance.eth.call({
to: contractInstance.options.address,
data: encodedABI,
from: publicKey,
gasPrice,
gas: gasLimit,
});
}

return {
from: publicKey,
to: contractInstance.options.address,
Expand All @@ -187,41 +220,8 @@ class BlockchainServiceBase {
};
}

ensureBlockchainInfo(blockchain) {
if (!this[blockchain.name]) {
this[blockchain.name] = {
contracts: { [blockchain.hubContract]: {} },
contractAddresses: {
[blockchain.hubContract]: {
Hub: blockchain.hubContract,
},
},
};
}
}

async getWeb3Instance(blockchain) {
this.ensureBlockchainInfo(blockchain);
if (!this[blockchain.name].web3) {
const blockchainOptions = {
transactionPollingTimeout: blockchain.transactionPollingTimeout,
};
await this.initializeWeb3(blockchain.name, blockchain.rpc, blockchainOptions);
}

return this[blockchain.name].web3;
}

async getContractAddress(contractName, blockchain, force = false) {
this.ensureBlockchainInfo(blockchain);
if (!this[blockchain.name].contracts[blockchain.hubContract]) {
this[blockchain.name].contracts[blockchain.hubContract] = {};
}
if (!this[blockchain.name].contracts[blockchain.hubContract].Hub) {
const web3Instance = await this.getWeb3Instance(blockchain);
this[blockchain.name].contracts[blockchain.hubContract].Hub =
new web3Instance.eth.Contract(this.abis.Hub, blockchain.hubContract, { from: blockchain.publicKey });
}
await this.ensureBlockchainInfo(blockchain);

if (
force ||
Expand All @@ -241,13 +241,9 @@ class BlockchainServiceBase {
}

async updateContractInstance(contractName, blockchain, force = false) {
this.ensureBlockchainInfo(blockchain);
if (
force ||
!this[blockchain.name].contractAddresses[blockchain.hubContract][contractName]
) {
this[blockchain.name].contractAddresses[blockchain.hubContract][contractName] = await this.getContractAddress(contractName, blockchain, force);
}
await this.ensureBlockchainInfo(blockchain);
await this.getContractAddress(contractName, blockchain, force);

if (force || !this[blockchain.name].contracts[blockchain.hubContract][contractName]) {
const web3Instance = await this.getWeb3Instance(blockchain);
this[blockchain.name].contracts[blockchain.hubContract][contractName] =
Expand All @@ -259,6 +255,11 @@ class BlockchainServiceBase {
}
}

async getContractInstance(contractName, blockchain) {
await this.updateContractInstance(contractName, blockchain);
return this[blockchain.name].contracts[blockchain.hubContract][contractName];
}

async increaseServiceAgreementV1Allowance(sender, serviceAgreementV1Address, tokenAmount, blockchain) {
const allowance = await this.callContractFunction(
'Token',
Expand Down Expand Up @@ -289,11 +290,6 @@ class BlockchainServiceBase {
}
}

async getContractInstance(contractName, blockchain) {
await this.updateContractInstance(contractName, blockchain);
return this[blockchain.name].contracts[blockchain.hubContract][contractName];
}

// Knowledge assets operations

async createAsset(requestData, paranetKaContract, paranetTokenId, blockchain, stepHooks = emptyHooks) {
Expand Down Expand Up @@ -710,11 +706,13 @@ class BlockchainServiceBase {
}

async setIncentivesPool(contractAddress, blockchain){
const web3Instance = await this.getWeb3Instance(blockchain);
await this.ensureBlockchainInfo(blockchain);

// eslint-disable-next-line dot-notation
if (this[blockchain.name].contractAddresses[blockchain.hubContract]['ParanetNeuroIncentivesPool'] !== contractAddress) {
// eslint-disable-next-line dot-notation
this[blockchain.name].contractAddresses[blockchain.hubContract]['ParanetNeuroIncentivesPool'] = contractAddress;
const web3Instance = await this.getWeb3Instance(blockchain);
// eslint-disable-next-line dot-notation
this[blockchain.name].contracts[blockchain.hubContract]['ParanetNeuroIncentivesPool'] =
await new web3Instance.eth.Contract(
Expand Down Expand Up @@ -873,6 +871,7 @@ class BlockchainServiceBase {
// Blockchain operations

async getChainId(blockchain) {
await this.ensureBlockchainInfo(blockchain);
const web3Instance = await this.getWeb3Instance(blockchain);

return web3Instance.eth.getChainId();
Expand All @@ -886,6 +885,7 @@ class BlockchainServiceBase {
}

async getGasPrice(blockchain) {
await this.ensureBlockchainInfo(blockchain);
const web3Instance = await this.getWeb3Instance(blockchain);
try {
let gasPrice;
Expand Down Expand Up @@ -922,6 +922,7 @@ class BlockchainServiceBase {
}

async getWalletBalances(blockchain) {
await this.ensureBlockchainInfo(blockchain);
const web3Instance = await this.getWeb3Instance(blockchain);
const publicKey = await this.getPublicKey(blockchain);

Expand All @@ -940,6 +941,7 @@ class BlockchainServiceBase {
}

async getLatestBlock(blockchain) {
await this.ensureBlockchainInfo(blockchain);
const web3 = await this.getWeb3Instance(blockchain);
const blockNumber = await web3.eth.getBlockNumber();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class BrowserBlockchainService extends BlockchainServiceBase {
}

async decodeEventLogs(receipt, eventName, blockchain) {
await this.ensureBlockchainInfo(blockchain);
const web3Instance = await this.getWeb3Instance(blockchain);
let result;
const { hash, inputs } = this.events[eventName];
Expand All @@ -56,6 +57,7 @@ class BrowserBlockchainService extends BlockchainServiceBase {
}

async executeContractFunction(contractName, functionName, args, blockchain) {
await this.ensureBlockchainInfo(blockchain);
let contractInstance = await this.getContractInstance(contractName, blockchain);
let tx;

Expand All @@ -75,8 +77,9 @@ class BrowserBlockchainService extends BlockchainServiceBase {
if (!status) {
await this.updateContractInstance(contractName, blockchain, true);
contractInstance = await this.getContractInstance(contractName, blockchain);
const web3Instance = await this.getWeb3Instance(blockchain);

await this[blockchain.name].web3.eth.call({
await web3Instance.eth.call({
to: contractInstance.options.address,
data: tx.data,
from: tx.from,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class NodeBlockchainService extends BlockchainServiceBase {
}

async decodeEventLogs(receipt, eventName, blockchain) {
await this.ensureBlockchainInfo(blockchain);
const web3Instance = await this.getWeb3Instance(blockchain);
let result;
const { hash, inputs } = this.events[eventName];
Expand All @@ -55,6 +56,7 @@ class NodeBlockchainService extends BlockchainServiceBase {
}

async executeContractFunction(contractName, functionName, args, blockchain) {
await this.ensureBlockchainInfo(blockchain);
const web3Instance = await this.getWeb3Instance(blockchain);
let contractInstance = await this.getContractInstance(contractName, blockchain);

Expand Down
5 changes: 5 additions & 0 deletions services/input-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ class InputService {
options.blockchain?.handleNotMinedError ??
this.config.blockchain?.handleNotMinedError ??
DEFAULT_PARAMETERS.HANDLE_NOT_MINED_ERROR;
const gasLimitMultiplier =
options.blockchain?.gasLimitMultiplier ??
this.config.blockchain?.gasLimitMultiplier ??
DEFAULT_PARAMETERS.GAS_LIMIT_MULTIPLIER;
const gasPrice =
options.blockchain?.gasPrice ?? this.config.blockchain?.gasPrice ?? undefined;
const transactionPollingTimeout =
Expand All @@ -161,6 +165,7 @@ class InputService {
hubContract,
publicKey,
privateKey,
gasLimitMultiplier,
gasPrice,
transactionPollingTimeout,
handleNotMinedError,
Expand Down

0 comments on commit 10a8039

Please sign in to comment.