diff --git a/docs/encyclopedia/fees-surge-pricing-fee-strategies.mdx b/docs/encyclopedia/fees-surge-pricing-fee-strategies.mdx index 8646076af..764e664a9 100644 --- a/docs/encyclopedia/fees-surge-pricing-fee-strategies.mdx +++ b/docs/encyclopedia/fees-surge-pricing-fee-strategies.mdx @@ -2,12 +2,14 @@ title: Fees, Surge Pricing, and Fee Strategies --- +import { CodeExample } from "@site/src/components/CodeExample" + Stellar requires a small fee for all transactions to prevent ledger spam and prioritize transactions during surge pricing. All fees are paid in lumens (XLM). ## Network fees on Stellar The minimum fee for a given transaction equals the number of operations in the transaction multiplied by the base fee for the given ledger. (transaction fee = # of operations * base fee) -**Base fee:** the fee the network charges per operation in a transaction. The base fee is determined using a version of a VCG auction. The base fee is currently 100 stroops per operation. +**Base fee:** the fee the network charges per operation in a transaction. The base fee is determined using a version of a [VCG auction](https://en.wikipedia.org/wiki/Vickrey%E2%80%93Clarke%E2%80%93Groves_auction). The base fee is currently 100 stroops per operation. **Stroop:** the smallest unit of a lumen, one ten-millionth of a lumen (.0000001 XLM). @@ -43,18 +45,67 @@ In general, it is important to track fee costs. If network fees surge beyond wha If you want to match a fee error exactly, you may write something like this: -[insert code] + + +```js +function isFeeError(error) { + return; + error.response !== undefined && + error.status == 400 && + error.extras && + error.extras.result_codes.transaction == sdk.TX_INSUFFICIENT_FEE; +} +``` + + There are more streamlined ways to combine errors, which we use below to demonstrate the (very) specific check. Example: suppose we want a fairly conservative fee-paying strategy- we’re only willing to pay a 10% higher fee than the average transaction paid. -[insert code] + + +```js +// when submitting any transaction, first query fee stats +server.feeStats().then(function (response) { + let avgFee = parseFloat(response.fee_charged.p50); + let tx = base.TransactionBuilder(someAccount, { + fee: (avgFee * 1.10).toFixed(0), // bump & convert to int + networkPassphrase: // ... + }); + // ...build the rest of the tx... + tx.sign(someAccount); + return server.submitTransaction(tx); +}); +``` + + ### Fee-bumps on past transactions Even with a liberal fee-paying policy, your transaction may fail to make it into the ledger due to insufficient funds or untimely surges. Fee-bump transactions can solve this problem. The following snippet shows you how to resubmit a transaction with a higher fee (as long as you have the original transaction envelope): -[insert code] + + +```js +// Let `lastTx` be some transaction that fails submission due to high fees, and +// `lastFee` be the maximum fee (expressed as an int) willing to be paid by +// `account` for `lastTx`. +server.submitTransaction(lastTx).catch(function (error) { + if (isFeeError(error)) { + let bump = sdk.TransactionBuilder.buildFeeBumpTransaction( + account, // account that will PAY the new fee + lastFee * 10, // new fee + lastTx, // the (entire) failing transaction + server.networkPassphrase + ); + bump.sign(someAccount); + return server.submitTransaction(bump); + } + // ...other error conditions... +}).then(...); +``` + + Suppose you submit two distinct transactions with the same source account and sequence number, and the second transaction is a fee-bump transaction. In that case, the second transaction will be included in the transaction queue, replacing the first transaction if and only if the fee bid of the second transaction is at least 10x the fee bid of the first transaction.