Skip to content

Commit 9337925

Browse files
fix: improve transaction cost estimation for pay modal (#5548)
1 parent 8aa454c commit 9337925

File tree

4 files changed

+41
-68
lines changed

4 files changed

+41
-68
lines changed

.changeset/ten-rockets-stare.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Fix tx cost estimation for pay transaction modal

packages/thirdweb/src/react/core/hooks/transaction/useSendTransaction.ts

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { type UseMutationResult, useMutation } from "@tanstack/react-query";
22
import type { Chain } from "../../../../chains/types.js";
3-
import { getGasPrice } from "../../../../gas/get-gas-price.js";
43
import type { BuyWithCryptoStatus } from "../../../../pay/buyWithCrypto/getStatus.js";
54
import type { BuyWithFiatStatus } from "../../../../pay/buyWithFiat/getStatus.js";
65
import type { FiatProvider } from "../../../../pay/utils/commonTypes.js";
7-
import { estimateGasCost } from "../../../../transaction/actions/estimate-gas-cost.js";
86
import type { GaslessOptions } from "../../../../transaction/actions/gasless/types.js";
97
import { sendTransaction } from "../../../../transaction/actions/send-transaction.js";
108
import type { WaitForReceiptOptions } from "../../../../transaction/actions/wait-for-tx-receipt.js";
119
import type { PreparedTransaction } from "../../../../transaction/prepare-transaction.js";
10+
import { getTransactionGasCost } from "../../../../transaction/utils.js";
1211
import { resolvePromisedValue } from "../../../../utils/promise/resolve-promised-value.js";
1312
import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
1413
import { getTokenBalance } from "../../../../wallets/utils/getTokenBalance.js";
@@ -215,7 +214,7 @@ export function useSendTransactionCore(args: {
215214
tokenAddress: _erc20Value.tokenAddress,
216215
})
217216
: undefined,
218-
getTotalTxCostForBuy(tx, account.address),
217+
getTransactionGasCost(tx, account.address),
219218
]);
220219

221220
const gasSponsored = hasSponsoredTransactionsEnabled(wallet);
@@ -248,39 +247,3 @@ export function useSendTransactionCore(args: {
248247
},
249248
});
250249
}
251-
252-
async function getTotalTxCostForBuy(tx: PreparedTransaction, from?: string) {
253-
try {
254-
const gasCost = await estimateGasCost({
255-
transaction: tx,
256-
from,
257-
});
258-
259-
const bufferCost = gasCost.wei / 10n;
260-
261-
// Note: get tx.value AFTER estimateGasCost
262-
const txValue = await resolvePromisedValue(tx.value);
263-
264-
// add 10% extra gas cost to the estimate to ensure user buys enough to cover the tx cost
265-
return gasCost.wei + bufferCost + (txValue || 0n);
266-
} catch {
267-
if (from) {
268-
// try again without passing from
269-
return await getTotalTxCostForBuy(tx);
270-
}
271-
// fallback if both fail, use the tx value + 2M * gas price
272-
const value = await resolvePromisedValue(tx.value);
273-
274-
const gasPrice = await getGasPrice({
275-
client: tx.client,
276-
chain: tx.chain,
277-
});
278-
279-
const buffer = 2_000_000n * gasPrice;
280-
281-
if (!value) {
282-
return 0n + buffer;
283-
}
284-
return value + buffer;
285-
}
286-
}

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/main/useBuyTxStates.ts

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ import { getChainMetadata } from "../../../../../../../chains/utils.js";
44
import { NATIVE_TOKEN_ADDRESS } from "../../../../../../../constants/addresses.js";
55
import { getContract } from "../../../../../../../contract/contract.js";
66
import { getCurrencyMetadata } from "../../../../../../../extensions/erc20/read/getCurrencyMetadata.js";
7-
import { getGasPrice } from "../../../../../../../gas/get-gas-price.js";
87
import { encode } from "../../../../../../../transaction/actions/encode.js";
9-
import { estimateGasCost } from "../../../../../../../transaction/actions/estimate-gas-cost.js";
108
import type { PreparedTransaction } from "../../../../../../../transaction/prepare-transaction.js";
9+
import { getTransactionGasCost } from "../../../../../../../transaction/utils.js";
1110
import type { Hex } from "../../../../../../../utils/encoding/hex.js";
1211
import { resolvePromisedValue } from "../../../../../../../utils/promise/resolve-promised-value.js";
1312
import type { Account } from "../../../../../../../wallets/interfaces/wallet.js";
@@ -138,30 +137,3 @@ export function useTransactionCostAndData(args: {
138137
},
139138
});
140139
}
141-
142-
async function getTransactionGasCost(tx: PreparedTransaction, from?: string) {
143-
try {
144-
const gasCost = await estimateGasCost({
145-
transaction: tx,
146-
from,
147-
});
148-
149-
const bufferCost = gasCost.wei / 10n;
150-
151-
// Note: get tx.value AFTER estimateGasCost
152-
// add 10% extra gas cost to the estimate to ensure user buys enough to cover the tx cost
153-
return gasCost.wei + bufferCost;
154-
} catch {
155-
if (from) {
156-
// try again without passing from
157-
return await getTransactionGasCost(tx);
158-
}
159-
// fallback if both fail, use the tx value + 2M * gas price
160-
const gasPrice = await getGasPrice({
161-
client: tx.client,
162-
chain: tx.chain,
163-
});
164-
165-
return 2_000_000n * gasPrice;
166-
}
167-
}

packages/thirdweb/src/transaction/utils.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import type { AbiFunction } from "abitype";
2+
import { getGasPrice } from "../gas/get-gas-price.js";
3+
import { estimateGasCost } from "./actions/estimate-gas-cost.js";
4+
import type { PreparedTransaction } from "./prepare-transaction.js";
25

36
/**
47
* @internal
@@ -11,3 +14,33 @@ export function isAbiFunction(item: unknown): item is AbiFunction {
1114
item.type === "function"
1215
);
1316
}
17+
18+
export async function getTransactionGasCost(
19+
tx: PreparedTransaction,
20+
from?: string,
21+
) {
22+
try {
23+
const gasCost = await estimateGasCost({
24+
transaction: tx,
25+
from,
26+
});
27+
28+
const bufferCost = gasCost.wei / 10n;
29+
30+
// Note: get tx.value AFTER estimateGasCost
31+
// add 10% extra gas cost to the estimate to ensure user buys enough to cover the tx cost
32+
return gasCost.wei + bufferCost;
33+
} catch {
34+
if (from) {
35+
// try again without passing from
36+
return await getTransactionGasCost(tx);
37+
}
38+
// fallback if both fail, use the tx value + 1M * gas price
39+
const gasPrice = await getGasPrice({
40+
client: tx.client,
41+
chain: tx.chain,
42+
});
43+
44+
return 1_000_000n * gasPrice;
45+
}
46+
}

0 commit comments

Comments
 (0)