Skip to content

Commit

Permalink
Merge branch 'main' into fix/balance-loading-placeholders
Browse files Browse the repository at this point in the history
  • Loading branch information
iGroza committed Dec 18, 2024
2 parents d12c218 + c60f919 commit 1ad9713
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 51 deletions.
8 changes: 8 additions & 0 deletions src/models/provider/provider-config.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,12 @@ export class ProviderConfigModel {
AddressUtils.toEth('0x4FEBDDe47Ab9a76200e57eFcC80b212a07b3e6cE')
);
}

get indexerGasEstimateEnabled() {
return this.config?.indexer_gas_estimate_enabled ?? false;
}

toJSON() {
return this.config;
}
}
32 changes: 19 additions & 13 deletions src/models/wallet/wallet.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,24 +408,23 @@ class WalletStore implements RPCObserver {
return balance;
};

const balanceModel = new BalanceModel(
useEmptyFallback
? {
staked: Balance.Empty,
vested: Balance.Empty,
available: Balance.Empty,
total: Balance.Empty,
locked: Balance.Empty,
availableForStake: Balance.Empty,
unlock: new Date(0),
}
: ({} as any),
);
const balanceModel = new BalanceModel({
staked: Balance.Empty,
vested: Balance.Empty,
available: Balance.Empty,
total: Balance.Empty,
locked: Balance.Empty,
availableForStake: Balance.Empty,
unlock: new Date(0),
});

let emptyBalancesCount = 0;

Provider.getAllNetworks().forEach(p => {
const balance = getBalanceData(p);

if (!balance) {
emptyBalancesCount++;
return;
}

Expand All @@ -452,6 +451,13 @@ class WalletStore implements RPCObserver {
);
});

if (
emptyBalancesCount === Provider.getAllNetworks().length &&
!useEmptyFallback
) {
return new BalanceModel({} as any);
}

return balanceModel;
};

Expand Down
21 changes: 21 additions & 0 deletions src/services/indexer/indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
import {createAsyncTask} from '@app/utils';

import {
GasEstimateRequest,
GasEstimateResponce,
IndexerAddressesResponse,
IndexerUpdatesResponse,
ProviderConfig,
Expand Down Expand Up @@ -362,4 +364,23 @@ export class Indexer {
return false;
}
}

async gasEstimate(params: GasEstimateRequest, chainId: number) {
try {
this.checkIndexerAvailability();

const response = await jsonrpcRequest<GasEstimateResponce>(
RemoteConfig.get('proxy_server')!,
'gasEstimate',
[params, chainId],
);

return response ?? {};
} catch (err) {
if (err instanceof JSONRPCError) {
this.captureException(err, 'Indexer:gasEstimate', err.meta);
}
throw err;
}
}
}
15 changes: 15 additions & 0 deletions src/services/indexer/indexer.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export type ProviderConfig = {
explorer_token_id_url: string;
swap_default_token0: string;
swap_default_token1: string;
indexer_gas_estimate_enabled: boolean;
};

export type VerifyContractRequest = {
Expand All @@ -115,3 +116,17 @@ export type VerifyContractResponse = {
is_eip4361: boolean;
contract: IContract | null;
};

export type GasEstimateResponce = {
base_fee: string;
expected_fee: string;
gas_limit: string;
priority_fee: string;
};

export type GasEstimateRequest = {
from: string;
to: string;
value: string;
data?: string;
};
122 changes: 84 additions & 38 deletions src/services/tron-network/tron-network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {Provider, ProviderModel} from '@app/models/provider';

import {Balance} from '../balance';
import {TxEstimationParams} from '../eth-network/types';
import {Indexer} from '../indexer';

type TronSignedTransaction = {
visible: boolean;
Expand Down Expand Up @@ -251,51 +252,67 @@ export class TronNetwork {
{from, to, value = Balance.Empty}: TxEstimationParams,
provider = Provider.selectedProvider,
): Promise<CalculatedFees> {
const tronWeb = new tron.TronWeb({
fullHost: provider.ethRpcEndpoint,
});

try {
logger.log('[estimateFeeSendTRX] Starting fee estimation:', {
from,
to,
value: value.toString(),
const tronWeb = new tron.TronWeb({
fullHost: provider.ethRpcEndpoint,
});
if (provider.config.indexerGasEstimateEnabled) {
try {
const gasEstimateResponse = await Indexer.instance.gasEstimate(
{
from: AddressUtils.toTron(from),
to: AddressUtils.toTron(to),
value: String(
value.toParsedBalanceNumber() * 10 ** provider.decimals,
),
},
Number(provider.ethChainId),
);

return {
gasLimit: Balance.Empty,
maxBaseFee: Balance.Empty,
maxPriorityFee: Balance.Empty,
expectedFee: new Balance(
gasEstimateResponse.expected_fee,
provider.decimals,
provider.denom,
),
};
} catch (err) {
Logger.captureException(err, 'indexer gas estimate failed', {
request: {
from: AddressUtils.toTron(from),
to: AddressUtils.toTron(to),
value: String(
value.toParsedBalanceNumber() * 10 ** provider.decimals,
),
},
chain_id: provider.ethChainId,
});
}
}

// 1. Get account resources and check activation
const accountResources = await this.getAccountBandwidth(from, provider);
logger.log('[estimateFeeSendTRX] Account resources:', accountResources);

// 2. Create transaction to get actual bandwidth consumption
const valueSun = value.toParsedBalanceNumber() * SUN_PER_TRX;
logger.log('[estimateFeeSendTRX] Creating transaction with value:', {
valueTRX: value.toParsedBalanceNumber(),
valueSun,
});

const transaction = await tronWeb.transactionBuilder.sendTrx(
AddressUtils.toTron(to),
valueSun,
AddressUtils.toTron(from),
);

// 3. Calculate total bandwidth consumption
const bandwidthConsumption = this.calculateBandwidthConsumption(
transaction.raw_data_hex,
);
logger.log(
'[estimateFeeSendTRX] Bandwidth consumption:',
bandwidthConsumption,
);
// 5. Calculate required bandwidth fee
let totalFeeInTrx = 0; // fee can be 0 if no bandwidth is consumed
if (bandwidthConsumption > accountResources.totalBandwidth) {
totalFeeInTrx = bandwidthConsumption / BANDWIDTH_PRICE_IN_SUN;
}

// 6. Check account activation and calculate total fee
const accountTo = await tronWeb.trx.getAccount(AddressUtils.toTron(to));

const isAccountActive = !!accountTo.address;

if (!isAccountActive) {
Expand Down Expand Up @@ -327,11 +344,6 @@ export class TronNetwork {
MIN_FEE_TRX,
);

logger.log('[estimateFeeSendTRX] Using fallback fee calculation:', {
standardBandwidthConsumption,
standardFeeInTrx,
});

return {
gasLimit: Balance.Empty,
maxBaseFee: Balance.Empty,
Expand Down Expand Up @@ -384,9 +396,8 @@ export class TronNetwork {

// Calculate fee based on energy required
const energyFee = energyEstimate.energy_required * ENERGY_FEE_RATE;
logger.log('[estimateFeeSendTRC20] Energy fee:', energyFee);
// Get transaction structure for bandwidth estimation
const transaction = await tronWeb.transactionBuilder.triggerSmartContract(
const txWrapper = await tronWeb.transactionBuilder.triggerSmartContract(
contractAddress,
functionSelector,
{
Expand All @@ -396,25 +407,60 @@ export class TronNetwork {
parameter,
fromAddress,
);
logger.log('[estimateFeeSendTRC20] Transaction:', transaction);

if (provider.config.indexerGasEstimateEnabled) {
try {
const gasEstimateResponse = await Indexer.instance.gasEstimate(
{
from: fromAddress,
to: contractAddress,
value: String(
value.toParsedBalanceNumber() * 10 ** provider.decimals,
),
data: txWrapper.transaction.raw_data.contract[0].parameter.value
.data,
},
Number(provider.ethChainId),
);

return {
gasLimit: Balance.Empty,
maxBaseFee: Balance.Empty,
maxPriorityFee: Balance.Empty,
expectedFee: new Balance(
gasEstimateResponse.expected_fee,
provider.decimals,
provider.denom,
),
};
} catch (err) {
Logger.captureException(err, 'indexer gas estimate failed', {
request: {
from: fromAddress,
to: contractAddress,
value: String(
value.toParsedBalanceNumber() * 10 ** provider.decimals,
),
data: txWrapper.transaction.raw_data.contract[0].parameter.value
.data,
},
chain_id: provider.ethChainId,
});
}
}

const accountResources = await this.getAccountBandwidth(from, provider);
logger.log('[estimateFeeSendTRC20] Account resources:', accountResources);
// Calculate bandwidth fee
const bandwidthConsumption = this.calculateBandwidthConsumption(
transaction?.transaction?.raw_data_hex ?? '',
);
logger.log(
'[estimateFeeSendTRC20] Bandwidth consumption:',
bandwidthConsumption,
txWrapper?.transaction?.raw_data_hex ?? '',
);

// 5. Calculate required bandwidth fee
let totalFeeInTrx = energyFee / 10 ** 6;
if (bandwidthConsumption > accountResources.totalBandwidth) {
totalFeeInTrx = bandwidthConsumption / BANDWIDTH_PRICE_IN_SUN;
}
logger.log('[estimateFeeSendTRC20] Total fee in TRX:', totalFeeInTrx);
const accountTo = await tronWeb.trx.getAccount(AddressUtils.toTron(to));
logger.log('[estimateFeeSendTRC20] Account to:', accountTo);
const isAccountActive = !!accountTo.address;
if (!isAccountActive) {
totalFeeInTrx += 1; // Add 1 TRX activation fee
Expand Down

0 comments on commit 1ad9713

Please sign in to comment.