@valve-tech/gas-oracle 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +115 -16
- package/dist/block-position.d.ts +3 -3
- package/dist/block-position.d.ts.map +1 -1
- package/dist/block-position.js +27 -19
- package/dist/block-position.js.map +1 -1
- package/dist/classify-tip.d.ts +33 -0
- package/dist/classify-tip.d.ts.map +1 -0
- package/dist/classify-tip.js +52 -0
- package/dist/classify-tip.js.map +1 -0
- package/dist/inclusion-labels.d.ts +30 -0
- package/dist/inclusion-labels.d.ts.map +1 -0
- package/dist/inclusion-labels.js +35 -0
- package/dist/inclusion-labels.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/math.d.ts +1 -1
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +17 -17
- package/dist/math.js.map +1 -1
- package/dist/oracle.d.ts +2 -2
- package/dist/oracle.d.ts.map +1 -1
- package/dist/oracle.js +7 -6
- package/dist/oracle.js.map +1 -1
- package/dist/presets.d.ts +36 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +27 -0
- package/dist/presets.js.map +1 -0
- package/dist/replacement.d.ts +80 -0
- package/dist/replacement.d.ts.map +1 -0
- package/dist/replacement.js +114 -0
- package/dist/replacement.js.map +1 -0
- package/dist/types.d.ts +49 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +57 -1
- package/dist/types.js.map +1 -1
- package/dist/viem-transport.d.ts +1 -1
- package/dist/viem-transport.d.ts.map +1 -1
- package/dist/viem-transport.js +11 -5
- package/dist/viem-transport.js.map +1 -1
- package/package.json +2 -2
- package/skills/gas-oracle-integration/SKILL.md +105 -12
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ All notable changes to `@valve-tech/gas-oracle` are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [0.8.0] — 2026-05-06
|
|
9
|
+
|
|
10
|
+
Consumes `@valve-tech/chain-source@0.8.0`'s WS-aware `ChainSource` transparently. Adds upstream helpers (replacement / classifyTip / inclusion labels), chain presets (PulseChain), const-namespace exports, and a bigint migration of public numeric fields.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Replacement helpers** (`replacement.ts`): `minimumReplacementFee(current, txType)`, `bumpForReplacement(currentGas, targetGas)`, `recommendBumpTier(snapshot, stuckTx, options?)` with three named strategies (`BumpStrategy.cheapestThatLands` / `oneStepFasterThanRecommended` / `instant`). Outpace correction via optional `stuckTx.identifier` reads `snapshot.mempoolSamples` to find the tip needed to outpace the stuck tx in the live distribution, on top of the EIP-1559 +10% protocol floor (verified against geth/reth/PulseChain go-pulse sources).
|
|
15
|
+
- **`classifyTip(snapshot, tipWei)`** (`classify-tip.ts`): inverse of `tipForBlockPosition`. Returns `{ tier, requiredForNextTier, percentile, rank, gasFromTop }`.
|
|
16
|
+
- **Inclusion labels** (`inclusion-labels.ts`): `defaultInclusionLabels` (Record<TierName, string>) and `inclusionLabel(tier, overrides?)` for locale/branded copy without forking.
|
|
17
|
+
- **Chain presets** (`presets.ts`): `chainPresets.pulsechain` (chainId: 369, priorityModel: PriorityModel.flat) plus `presetForChainId(chainId)` runtime lookup.
|
|
18
|
+
- **Const-namespace exports**: `PriorityModel`, `TierName`, `Trend`, `TxType` are now exported as both values (const namespaces) and types. Use `PriorityModel.flat` instead of `'flat'` etc. `TIER_LADDER` (canonical slow→instant ordering) also exported from `types.ts`.
|
|
19
|
+
- **`mempoolSamples: TipSample[]`** on `GasOracleState`. Producer-local — wire publishers should strip before serializing (same convention as `ring`).
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **`priorityModel` default flips from `'flat'` to `PriorityModel.eip1559`**. Most chains honor the EIP-2718 type byte and the EIP-1559 fee-market; the default is now correct for the majority case. PulseChain (chain 369) becomes the explicit exception — set `priorityModel: PriorityModel.flat` (or use `...chainPresets.pulsechain`).
|
|
24
|
+
- **BigInt migration of public numeric fields**: `MempoolStats.pendingCount`, `MempoolStats.queuedCount`, `BlockPositionQuery.rank`, `BlockPositionQuery.percentile`, `BlockPositionResult.rank`, `CreateGasOracleOptions.pollIntervalMs` are now `bigint`. Identifier-like fields (`chainId`, EIP-2718 type bytes) stay `number`.
|
|
25
|
+
|
|
26
|
+
### Migration notes
|
|
27
|
+
|
|
28
|
+
- Examples that previously omitted `priorityModel` silently get `PriorityModel.eip1559` after upgrade. Verify against your target chain.
|
|
29
|
+
- Math operations on the migrated bigint fields need `n` literals (`0n`, `1n`, etc.) and integer-floor division semantics.
|
|
30
|
+
- `pollIntervalMs: 5000` becomes `pollIntervalMs: 5000n`.
|
|
31
|
+
|
|
8
32
|
## [0.7.0] — 2026-05-06
|
|
9
33
|
|
|
10
34
|
### Changed
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ yarn add @valve-tech/gas-oracle viem
|
|
|
28
28
|
```ts
|
|
29
29
|
import { createPublicClient, http, parseEther } from 'viem'
|
|
30
30
|
import { mainnet } from 'viem/chains'
|
|
31
|
-
import { createGasOracle } from '@valve-tech/gas-oracle'
|
|
31
|
+
import { createGasOracle, PriorityModel } from '@valve-tech/gas-oracle'
|
|
32
32
|
|
|
33
33
|
const client = createPublicClient({ chain: mainnet, transport: http() })
|
|
34
34
|
|
|
@@ -36,7 +36,7 @@ const oracle = createGasOracle({
|
|
|
36
36
|
client,
|
|
37
37
|
chainId: 1,
|
|
38
38
|
priorityFeeDecayCap: parseEther('0.125'), // 12.5%/block, EIP-1559 parity
|
|
39
|
-
priorityModel
|
|
39
|
+
// priorityModel defaults to PriorityModel.eip1559 — explicit only if you need to override
|
|
40
40
|
})
|
|
41
41
|
|
|
42
42
|
oracle.subscribe((state) => {
|
|
@@ -73,7 +73,7 @@ Tier mapping in the gas-weighted percentile distribution:
|
|
|
73
73
|
|
|
74
74
|
`slow` always reads from the full distribution (legacy + 1559) so legacy
|
|
75
75
|
senders can still find the lane they actually live in. Under
|
|
76
|
-
`
|
|
76
|
+
`PriorityModel.eip1559`, the paying-lane tiers (`standard`/`fast`/
|
|
77
77
|
`instant`) draw from type-2+ samples only — legacy spam can't suppress
|
|
78
78
|
them.
|
|
79
79
|
|
|
@@ -95,19 +95,32 @@ priorityFeeDecayCap: null // uncapped — track raw mempool
|
|
|
95
95
|
Validated at construction; out-of-range values throw. Upside is always
|
|
96
96
|
unclamped — real spikes propagate immediately.
|
|
97
97
|
|
|
98
|
-
### `priorityModel`
|
|
98
|
+
### Choosing `priorityModel`
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
EIP-2718 type space:
|
|
100
|
+
The default is `PriorityModel.eip1559` and is correct for every chain whose validators honor the EIP-2718 type byte and the EIP-1559 fee-market shape. **You should only override this if you've verified your target chain's validators are extractive** — that is, they ignore the type byte and maximize fee per gas regardless of tx envelope.
|
|
102
101
|
|
|
103
|
-
|
|
102
|
+
The canonical example is **PulseChain (chain 369)**: extractive validators mean the percentile math has to draw from the full tx distribution (`PriorityModel.flat`) instead of filtering to type-2+ samples. Setting the wrong model here silently under-prices, and your tx stalls.
|
|
103
|
+
|
|
104
|
+
For chains we know about, the `chainPresets` entry-point handles this for you:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { createGasOracle, chainPresets } from '@valve-tech/gas-oracle'
|
|
108
|
+
|
|
109
|
+
const oracle = createGasOracle({
|
|
110
|
+
client,
|
|
111
|
+
...chainPresets.pulsechain, // chainId: 369, priorityModel: PriorityModel.flat
|
|
112
|
+
})
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Mechanics:
|
|
116
|
+
|
|
117
|
+
- `PriorityModel.flat` — every tx contributes equally to the gas-weighted
|
|
104
118
|
distribution. Right for extractive validators (PulseChain, etc.)
|
|
105
119
|
that ignore the type byte and just maximize fee per gas.
|
|
106
|
-
- `
|
|
107
|
-
fast/instant); `slow` still draws from the full
|
|
108
|
-
for chains that honor EIP-1559 ordering
|
|
109
|
-
|
|
110
|
-
Default `'flat'` (most conservative — never under-counts spam).
|
|
120
|
+
- `PriorityModel.eip1559` — type 2+ samples drive the paying-lane tiers
|
|
121
|
+
(standard/fast/instant); `slow` still draws from the full
|
|
122
|
+
distribution. Right for chains that honor EIP-1559 ordering
|
|
123
|
+
(Ethereum, most L2s).
|
|
111
124
|
|
|
112
125
|
### `baseFeeLivenessBlocks`
|
|
113
126
|
|
|
@@ -240,12 +253,12 @@ For callers who need a single fee snapshot without a long-lived
|
|
|
240
253
|
oracle (typical tx-submit flow):
|
|
241
254
|
|
|
242
255
|
```ts
|
|
243
|
-
import { sampleGasFees } from '@valve-tech/gas-oracle'
|
|
256
|
+
import { sampleGasFees, PriorityModel } from '@valve-tech/gas-oracle'
|
|
244
257
|
|
|
245
258
|
const snapshot = await sampleGasFees({
|
|
246
259
|
client,
|
|
247
260
|
chainId: 1,
|
|
248
|
-
priorityModel:
|
|
261
|
+
priorityModel: PriorityModel.eip1559,
|
|
249
262
|
})
|
|
250
263
|
const tip = snapshot?.tiers.fast.maxPriorityFeePerGas
|
|
251
264
|
```
|
|
@@ -309,6 +322,90 @@ the same union `computeTiers` reads. The viem-actions extension
|
|
|
309
322
|
exposes `client.tipForBlockPosition(query)` which assembles this
|
|
310
323
|
distribution for you from the oracle's state.
|
|
311
324
|
|
|
325
|
+
## Replacement workflow
|
|
326
|
+
|
|
327
|
+
When a tx gets stuck and you need to bump it past the EIP-1559 protocol
|
|
328
|
+
replacement floor (and optionally past the live mempool distribution):
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
import {
|
|
332
|
+
createGasOracle,
|
|
333
|
+
recommendBumpTier,
|
|
334
|
+
bumpForReplacement,
|
|
335
|
+
BumpStrategy,
|
|
336
|
+
} from '@valve-tech/gas-oracle'
|
|
337
|
+
|
|
338
|
+
// 1. Pick a tier to bump to:
|
|
339
|
+
const tier = recommendBumpTier(
|
|
340
|
+
state,
|
|
341
|
+
{ priorityTip: stuckTx.maxPriorityFeePerGas, identifier: { hash: stuckTx.hash } },
|
|
342
|
+
{ strategy: BumpStrategy.cheapestThatLands },
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
if (tier === null) {
|
|
346
|
+
// Stuck tx is already paying above the top of the tier ladder, or
|
|
347
|
+
// the snapshot has no tip data. Caller's call: hold, or push instant.
|
|
348
|
+
return
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// 2. Compute the gas object that satisfies both the protocol floor and the target tier:
|
|
352
|
+
const target = state.tiers[tier]
|
|
353
|
+
const gas = bumpForReplacement(
|
|
354
|
+
{ maxFeePerGas: stuckTx.maxFeePerGas, maxPriorityFeePerGas: stuckTx.maxPriorityFeePerGas },
|
|
355
|
+
{ maxFeePerGas: target.maxFeePerGas, maxPriorityFeePerGas: target.maxPriorityFeePerGas },
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
// 3. Send the replacement
|
|
359
|
+
walletClient.sendTransaction({ ...stuckTx, ...gas })
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Tip classification
|
|
363
|
+
|
|
364
|
+
Inverse of `tipForBlockPosition`: given a tip, find where it lands in the
|
|
365
|
+
live distribution and which named tier it falls in.
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
import { classifyTip } from '@valve-tech/gas-oracle'
|
|
369
|
+
|
|
370
|
+
const result = classifyTip(state, myTip)
|
|
371
|
+
// result.tier — TierName | null (null if below slow)
|
|
372
|
+
// result.requiredForNextTier — bigint floor of next tier above (null at instant)
|
|
373
|
+
// result.percentile — bigint 0-100 (0 = top, 100 = bottom)
|
|
374
|
+
// result.rank — bigint 0-indexed from top
|
|
375
|
+
// result.gasFromTop — bigint accumulated gas above this tip
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## UI labels
|
|
379
|
+
|
|
380
|
+
```ts
|
|
381
|
+
import { defaultInclusionLabels, inclusionLabel, TierName } from '@valve-tech/gas-oracle'
|
|
382
|
+
|
|
383
|
+
defaultInclusionLabels[TierName.standard] // 'Next block'
|
|
384
|
+
|
|
385
|
+
// Locale / branded copy via partial overrides — no fork:
|
|
386
|
+
const es = { [TierName.standard]: 'Próximo bloque' }
|
|
387
|
+
inclusionLabel(TierName.standard, es) // 'Próximo bloque'
|
|
388
|
+
inclusionLabel(TierName.slow, es) // falls back to default English
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## Chain presets
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
import { createGasOracle, chainPresets, presetForChainId } from '@valve-tech/gas-oracle'
|
|
395
|
+
|
|
396
|
+
// Static — direct preset access
|
|
397
|
+
createGasOracle({ client, ...chainPresets.pulsechain })
|
|
398
|
+
|
|
399
|
+
// Dynamic — runtime lookup by chainId
|
|
400
|
+
const preset = presetForChainId(chainId)
|
|
401
|
+
createGasOracle({ client, chainId, ...preset })
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
PulseChain (chain 369) is the only entry shipped today. Adding more
|
|
405
|
+
requires verifying the chain's actual validator behavior against
|
|
406
|
+
block-level data; the default (eip1559) is correct for every chain we
|
|
407
|
+
haven't proven otherwise.
|
|
408
|
+
|
|
312
409
|
## viem integration
|
|
313
410
|
|
|
314
411
|
### Subpath: `@valve-tech/gas-oracle/viem-actions`
|
|
@@ -317,12 +414,13 @@ Extension surface for callers who want explicit access to tier shapes:
|
|
|
317
414
|
|
|
318
415
|
```ts
|
|
319
416
|
import { gasOracleActions } from '@valve-tech/gas-oracle/viem-actions'
|
|
417
|
+
import { PriorityModel } from '@valve-tech/gas-oracle'
|
|
320
418
|
|
|
321
419
|
const client = createPublicClient({ chain: mainnet, transport: http() })
|
|
322
420
|
.extend(gasOracleActions({
|
|
323
421
|
chainId: 1,
|
|
324
422
|
priorityFeeDecayCap: parseEther('0.125'),
|
|
325
|
-
priorityModel:
|
|
423
|
+
priorityModel: PriorityModel.eip1559,
|
|
326
424
|
}))
|
|
327
425
|
|
|
328
426
|
await client.getGasTiers() // full snapshot
|
|
@@ -343,11 +441,12 @@ work better* — `useFeeData`, `walletClient.sendTransaction({...})`,
|
|
|
343
441
|
|
|
344
442
|
```ts
|
|
345
443
|
import { withGasOracle } from '@valve-tech/gas-oracle/viem-transport'
|
|
444
|
+
import { PriorityModel } from '@valve-tech/gas-oracle'
|
|
346
445
|
|
|
347
446
|
const transport = withGasOracle(http(rpcUrl), {
|
|
348
447
|
chainId: 1,
|
|
349
448
|
priorityFeeDecayCap: parseEther('0.125'),
|
|
350
|
-
priorityModel:
|
|
449
|
+
priorityModel: PriorityModel.eip1559,
|
|
351
450
|
intercept: {
|
|
352
451
|
eth_gasFeeEstimate: true, // additive (default on)
|
|
353
452
|
eth_maxPriorityFeePerGas: 'fast', // tier required for standard methods
|
package/dist/block-position.d.ts
CHANGED
|
@@ -48,10 +48,10 @@ import type { TxIdentifier } from './mempool.js';
|
|
|
48
48
|
*/
|
|
49
49
|
export type BlockPositionQuery = {
|
|
50
50
|
kind: 'rank';
|
|
51
|
-
rank:
|
|
51
|
+
rank: bigint;
|
|
52
52
|
} | {
|
|
53
53
|
kind: 'percentile';
|
|
54
|
-
percentile:
|
|
54
|
+
percentile: bigint;
|
|
55
55
|
} | {
|
|
56
56
|
kind: 'gasFromTop';
|
|
57
57
|
gas: bigint;
|
|
@@ -79,7 +79,7 @@ export interface BlockPositionResult {
|
|
|
79
79
|
*/
|
|
80
80
|
pivot: TipSample | null;
|
|
81
81
|
/** Approximate rank of the resolved position, 0-indexed from top. */
|
|
82
|
-
rank:
|
|
82
|
+
rank: bigint;
|
|
83
83
|
/** Approximate gas-from-top of the resolved position. */
|
|
84
84
|
gasFromTop: bigint;
|
|
85
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block-position.d.ts","sourceRoot":"","sources":["../src/block-position.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,YAAY,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,YAAY,CAAA;CAAE,CAAA;AAExC,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;IACvB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAA;CACnB;
|
|
1
|
+
{"version":3,"file":"block-position.d.ts","sourceRoot":"","sources":["../src/block-position.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,YAAY,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,YAAY,CAAA;CAAE,CAAA;AAExC,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;IACvB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAA;CACnB;AAoDD;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAC9B,SAAS,SAAS,EAAE,EACpB,OAAO,kBAAkB,KACxB,mBAiEF,CAAA"}
|
package/dist/block-position.js
CHANGED
|
@@ -39,31 +39,33 @@ const matchesIdentifier = (sample, id) => {
|
|
|
39
39
|
/**
|
|
40
40
|
* Walk samples in tip-desc order accumulating gas; return the index
|
|
41
41
|
* (0-based from top) where cumulative gas first crosses `targetGas`.
|
|
42
|
-
* Returns -
|
|
42
|
+
* Returns -1n when the target exceeds the sum of all gas (the position
|
|
43
43
|
* is below the whole distribution).
|
|
44
44
|
*/
|
|
45
45
|
const indexAtGasOffset = (sorted, targetGas) => {
|
|
46
46
|
if (targetGas <= 0n)
|
|
47
|
-
return
|
|
47
|
+
return 0n;
|
|
48
48
|
let cumulative = 0n;
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
const len = BigInt(sorted.length);
|
|
50
|
+
for (let i = 0n; i < len; i += 1n) {
|
|
51
|
+
cumulative += sorted[Number(i)].gas;
|
|
51
52
|
if (cumulative > targetGas)
|
|
52
53
|
return i;
|
|
53
54
|
}
|
|
54
|
-
return -
|
|
55
|
+
return -1n;
|
|
55
56
|
};
|
|
56
57
|
const sumGasUpTo = (sorted, indexExclusive) => {
|
|
57
58
|
let g = 0n;
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
const len = BigInt(sorted.length);
|
|
60
|
+
const upper = indexExclusive < len ? indexExclusive : len;
|
|
61
|
+
for (let i = 0n; i < upper; i += 1n)
|
|
62
|
+
g += sorted[Number(i)].gas;
|
|
61
63
|
return g;
|
|
62
64
|
};
|
|
63
65
|
const empty = () => ({
|
|
64
66
|
requiredTip: 0n,
|
|
65
67
|
pivot: null,
|
|
66
|
-
rank:
|
|
68
|
+
rank: 0n,
|
|
67
69
|
gasFromTop: 0n,
|
|
68
70
|
});
|
|
69
71
|
/**
|
|
@@ -80,6 +82,7 @@ export const tipForBlockPosition = (samples, query) => {
|
|
|
80
82
|
if (samples.length === 0)
|
|
81
83
|
return empty();
|
|
82
84
|
const sorted = sortByTipDesc(samples);
|
|
85
|
+
const len = BigInt(sorted.length);
|
|
83
86
|
let pivotIndex;
|
|
84
87
|
let beatPivot; // true = outbid (tip+1), false = undercut (tip-1)
|
|
85
88
|
switch (query.kind) {
|
|
@@ -89,12 +92,16 @@ export const tipForBlockPosition = (samples, query) => {
|
|
|
89
92
|
break;
|
|
90
93
|
}
|
|
91
94
|
case 'percentile': {
|
|
92
|
-
// 0% = top of block (highest tip); 100% = bottom. Clamp to [
|
|
93
|
-
const pct =
|
|
94
|
-
|
|
95
|
+
// 0% = top of block (highest tip); 100% = bottom. Clamp to [0n, 100n].
|
|
96
|
+
const pct = query.percentile < 0n
|
|
97
|
+
? 0n
|
|
98
|
+
: query.percentile > 100n
|
|
99
|
+
? 100n
|
|
100
|
+
: query.percentile;
|
|
101
|
+
pivotIndex = (len * pct) / 100n;
|
|
95
102
|
// Edge: percentile=100 lands at length, which is "below everything"
|
|
96
|
-
if (pivotIndex >=
|
|
97
|
-
pivotIndex =
|
|
103
|
+
if (pivotIndex >= len)
|
|
104
|
+
pivotIndex = len - 1n;
|
|
98
105
|
beatPivot = true;
|
|
99
106
|
break;
|
|
100
107
|
}
|
|
@@ -105,21 +112,22 @@ export const tipForBlockPosition = (samples, query) => {
|
|
|
105
112
|
}
|
|
106
113
|
case 'aheadOf':
|
|
107
114
|
case 'behind': {
|
|
108
|
-
|
|
115
|
+
const found = sorted.findIndex((s) => matchesIdentifier(s, query.tx));
|
|
116
|
+
pivotIndex = found === -1 ? -1n : BigInt(found);
|
|
109
117
|
beatPivot = query.kind === 'aheadOf';
|
|
110
118
|
break;
|
|
111
119
|
}
|
|
112
120
|
}
|
|
113
|
-
if (pivotIndex <
|
|
121
|
+
if (pivotIndex < 0n || pivotIndex >= len) {
|
|
114
122
|
// Position is below everyone (or pivot not found) — pay nothing in priority
|
|
115
123
|
return {
|
|
116
124
|
requiredTip: 0n,
|
|
117
125
|
pivot: null,
|
|
118
|
-
rank:
|
|
119
|
-
gasFromTop: sumGasUpTo(sorted,
|
|
126
|
+
rank: len,
|
|
127
|
+
gasFromTop: sumGasUpTo(sorted, len),
|
|
120
128
|
};
|
|
121
129
|
}
|
|
122
|
-
const pivot = sorted[pivotIndex];
|
|
130
|
+
const pivot = sorted[Number(pivotIndex)];
|
|
123
131
|
const requiredTip = beatPivot
|
|
124
132
|
? pivot.tip + 1n
|
|
125
133
|
: pivot.tip > 0n
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block-position.js","sourceRoot":"","sources":["../src/block-position.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AA0DH,MAAM,aAAa,GAAG,CAAC,OAAoB,EAAe,EAAE;AAC1D,gEAAgE;AAChE,mEAAmE;AACnE,sDAAsD;AACtD,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAEvD,MAAM,iBAAiB,GAAG,CAAC,MAAiB,EAAE,EAAgB,EAAW,EAAE;IACzE,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC;QACjB,OAAO,CACL,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ;YAC/B,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CACpD,CAAA;IACH,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IAC5E,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE;QAAE,OAAO,KAAK,CAAA;IAC3E,OAAO,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAA;AACrD,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG,CAAC,MAAmB,EAAE,SAAiB,EAAU,EAAE;IAC1E,IAAI,SAAS,IAAI,EAAE;QAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"block-position.js","sourceRoot":"","sources":["../src/block-position.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inverse of `tipForBlockPosition`. Given a tip and a snapshot, find
|
|
3
|
+
* where the tip would land in the live distribution and which named
|
|
4
|
+
* tier it falls in. Pure: no I/O, no oracle dependency, no wall-clock.
|
|
5
|
+
*
|
|
6
|
+
* Useful for "you priced at the Xth percentile" UI affordances and for
|
|
7
|
+
* post-hoc "why is my tx slow" diagnostics.
|
|
8
|
+
*/
|
|
9
|
+
import { TierName, type GasOracleState } from './types.js';
|
|
10
|
+
export interface ClassifyTipResult {
|
|
11
|
+
/**
|
|
12
|
+
* Named tier the tip falls in. `null` when below `TierName.slow`'s
|
|
13
|
+
* `maxPriorityFeePerGas` floor.
|
|
14
|
+
*/
|
|
15
|
+
tier: TierName | null;
|
|
16
|
+
/**
|
|
17
|
+
* `maxPriorityFeePerGas` floor of the next tier above `tier`. `null`
|
|
18
|
+
* when `tier === TierName.instant` (already at top).
|
|
19
|
+
*/
|
|
20
|
+
requiredForNextTier: bigint | null;
|
|
21
|
+
/**
|
|
22
|
+
* Approximate percentile in the live distribution (block ring tips +
|
|
23
|
+
* mempool samples), 0n..100n. `0n` = top of block (highest tip);
|
|
24
|
+
* `100n` = bottom. `0n` when distribution empty.
|
|
25
|
+
*/
|
|
26
|
+
percentile: bigint;
|
|
27
|
+
/** Approximate rank, 0n-indexed from top. `0n` when distribution empty. */
|
|
28
|
+
rank: bigint;
|
|
29
|
+
/** Accumulated gas above this tip's position. `0n` when empty. */
|
|
30
|
+
gasFromTop: bigint;
|
|
31
|
+
}
|
|
32
|
+
export declare const classifyTip: (snapshot: GasOracleState, tipWei: bigint) => ClassifyTipResult;
|
|
33
|
+
//# sourceMappingURL=classify-tip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify-tip.d.ts","sourceRoot":"","sources":["../src/classify-tip.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEL,QAAQ,EACR,KAAK,cAAc,EAEpB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IACrB;;;OAGG;IACH,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAA;IACZ,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAA;CACnB;AA4BD,eAAO,MAAM,WAAW,GACtB,UAAU,cAAc,EACxB,QAAQ,MAAM,KACb,iBA0BF,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inverse of `tipForBlockPosition`. Given a tip and a snapshot, find
|
|
3
|
+
* where the tip would land in the live distribution and which named
|
|
4
|
+
* tier it falls in. Pure: no I/O, no oracle dependency, no wall-clock.
|
|
5
|
+
*
|
|
6
|
+
* Useful for "you priced at the Xth percentile" UI affordances and for
|
|
7
|
+
* post-hoc "why is my tx slow" diagnostics.
|
|
8
|
+
*/
|
|
9
|
+
import { TIER_LADDER, } from './types.js';
|
|
10
|
+
const tierForTip = (tiers, tipWei) => {
|
|
11
|
+
for (let i = TIER_LADDER.length - 1; i >= 0; i -= 1) {
|
|
12
|
+
const tier = TIER_LADDER[i];
|
|
13
|
+
if (tipWei >= tiers[tier].maxPriorityFeePerGas)
|
|
14
|
+
return tier;
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
};
|
|
18
|
+
const requiredForNextTierAbove = (tiers, currentTier) => {
|
|
19
|
+
const currentIndex = currentTier ? TIER_LADDER.indexOf(currentTier) : -1;
|
|
20
|
+
const nextIndex = currentIndex + 1;
|
|
21
|
+
if (nextIndex >= TIER_LADDER.length)
|
|
22
|
+
return null;
|
|
23
|
+
return tiers[TIER_LADDER[nextIndex]].maxPriorityFeePerGas;
|
|
24
|
+
};
|
|
25
|
+
const collectDistribution = (snapshot) => [
|
|
26
|
+
...snapshot.ring.flatMap((block) => block.tips),
|
|
27
|
+
...snapshot.mempoolSamples,
|
|
28
|
+
];
|
|
29
|
+
export const classifyTip = (snapshot, tipWei) => {
|
|
30
|
+
const tier = tierForTip(snapshot.tiers, tipWei);
|
|
31
|
+
const requiredForNextTier = requiredForNextTierAbove(snapshot.tiers, tier);
|
|
32
|
+
const samples = collectDistribution(snapshot);
|
|
33
|
+
if (samples.length === 0) {
|
|
34
|
+
return { tier, requiredForNextTier, percentile: 0n, rank: 0n, gasFromTop: 0n };
|
|
35
|
+
}
|
|
36
|
+
// Sort by tip desc, equal-tip arm folded into descending side
|
|
37
|
+
// (matches block-position.ts convention).
|
|
38
|
+
const sorted = [...samples].sort((a, b) => (a.tip > b.tip ? -1 : 1));
|
|
39
|
+
const firstWeakerIndexNum = sorted.findIndex((s) => s.tip <= tipWei);
|
|
40
|
+
const samplesLen = BigInt(sorted.length);
|
|
41
|
+
const rank = firstWeakerIndexNum === -1
|
|
42
|
+
? samplesLen
|
|
43
|
+
: BigInt(firstWeakerIndexNum);
|
|
44
|
+
// Round-half-away-from-zero percentile, all bigint. samplesLen >= 1n
|
|
45
|
+
// is guaranteed by the early-return on empty samples above.
|
|
46
|
+
const percentile = (rank * 100n + samplesLen / 2n) / samplesLen;
|
|
47
|
+
let gasFromTop = 0n;
|
|
48
|
+
for (let i = 0n; i < rank; i += 1n)
|
|
49
|
+
gasFromTop += sorted[Number(i)].gas;
|
|
50
|
+
return { tier, requiredForNextTier, percentile, rank, gasFromTop };
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=classify-tip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify-tip.js","sourceRoot":"","sources":["../src/classify-tip.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default English UI copy mapping each tier to a user-facing inclusion
|
|
3
|
+
* label, plus a small helper that resolves a tier with optional partial
|
|
4
|
+
* overrides (locale or branded copy without forking the whole map).
|
|
5
|
+
*
|
|
6
|
+
* Conservative phrasing — labels describe relative position in the next
|
|
7
|
+
* block, not hard guarantees. Real inclusion is probabilistic.
|
|
8
|
+
*/
|
|
9
|
+
import { TierName } from './types.js';
|
|
10
|
+
export declare const defaultInclusionLabels: Record<TierName, string>;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve a tier to its inclusion label, falling back to
|
|
13
|
+
* `defaultInclusionLabels` for any tier not present in `overrides`.
|
|
14
|
+
*
|
|
15
|
+
* Locale / branded-copy pattern (no fork required):
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* const es: Partial<Record<TierName, string>> = {
|
|
19
|
+
* [TierName.standard]: 'Próximo bloque',
|
|
20
|
+
* [TierName.fast]: 'Cabeza del próximo bloque',
|
|
21
|
+
* }
|
|
22
|
+
* inclusionLabel(TierName.standard, es) // 'Próximo bloque'
|
|
23
|
+
* inclusionLabel(TierName.slow, es) // falls back to default English
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Consumers can also fully replace the map by spreading:
|
|
27
|
+
* `const myLabels = { ...defaultInclusionLabels, ...partial }`.
|
|
28
|
+
*/
|
|
29
|
+
export declare const inclusionLabel: (tier: TierName, overrides?: Partial<Record<TierName, string>>) => string;
|
|
30
|
+
//# sourceMappingURL=inclusion-labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inclusion-labels.d.ts","sourceRoot":"","sources":["../src/inclusion-labels.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAK3D,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,QAAQ,EACd,YAAY,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,KAC5C,MAA2D,CAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default English UI copy mapping each tier to a user-facing inclusion
|
|
3
|
+
* label, plus a small helper that resolves a tier with optional partial
|
|
4
|
+
* overrides (locale or branded copy without forking the whole map).
|
|
5
|
+
*
|
|
6
|
+
* Conservative phrasing — labels describe relative position in the next
|
|
7
|
+
* block, not hard guarantees. Real inclusion is probabilistic.
|
|
8
|
+
*/
|
|
9
|
+
import { TierName } from './types.js';
|
|
10
|
+
export const defaultInclusionLabels = {
|
|
11
|
+
[TierName.slow]: 'Within a few blocks',
|
|
12
|
+
[TierName.standard]: 'Next block',
|
|
13
|
+
[TierName.fast]: 'Top of next block',
|
|
14
|
+
[TierName.instant]: 'Front of next block',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Resolve a tier to its inclusion label, falling back to
|
|
18
|
+
* `defaultInclusionLabels` for any tier not present in `overrides`.
|
|
19
|
+
*
|
|
20
|
+
* Locale / branded-copy pattern (no fork required):
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* const es: Partial<Record<TierName, string>> = {
|
|
24
|
+
* [TierName.standard]: 'Próximo bloque',
|
|
25
|
+
* [TierName.fast]: 'Cabeza del próximo bloque',
|
|
26
|
+
* }
|
|
27
|
+
* inclusionLabel(TierName.standard, es) // 'Próximo bloque'
|
|
28
|
+
* inclusionLabel(TierName.slow, es) // falls back to default English
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* Consumers can also fully replace the map by spreading:
|
|
32
|
+
* `const myLabels = { ...defaultInclusionLabels, ...partial }`.
|
|
33
|
+
*/
|
|
34
|
+
export const inclusionLabel = (tier, overrides) => overrides?.[tier] ?? defaultInclusionLabels[tier];
|
|
35
|
+
//# sourceMappingURL=inclusion-labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inclusion-labels.js","sourceRoot":"","sources":["../src/inclusion-labels.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,MAAM,CAAC,MAAM,sBAAsB,GAA6B;IAC9D,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,qBAAqB;IACtC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY;IACjC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,mBAAmB;IACpC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB;CAC1C,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,IAAc,EACd,SAA6C,EACrC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,IAAI,sBAAsB,CAAC,IAAI,CAAC,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,9 +16,15 @@ export { createGasOracle, reducePollInputs, sampleGasFees, type CreateGasOracleO
|
|
|
16
16
|
export { effectiveTip, computePercentiles, detectTrend, cappedTip, computeTiers, computeBlobBaseFee, flattenTxPool, gasWeightedPercentiles, sortedTips, DEFAULT_PRIORITY_FEE_DECAY_CAP, DEFAULT_BASE_FEE_LIVENESS_BLOCKS, } from './math.js';
|
|
17
17
|
export { blockToSample, mempoolToSamples, } from './samples.js';
|
|
18
18
|
export { fetchOracleInputs, fetchHeadBlockNumber, type FeeHistoryResult, type BlockResult, type TxPoolContent, type OraclePollInputs, } from './transport.js';
|
|
19
|
-
export type { RawTx, TipPercentiles, TierRecommendation,
|
|
19
|
+
export type { RawTx, TipPercentiles, TierRecommendation, MempoolStats, BlobStats, BlockSample, GasOracleState, TipSample, PollOptions, } from './types.js';
|
|
20
|
+
export { PriorityModel, TierName, TIER_LADDER, Trend, TxType } from './types.js';
|
|
20
21
|
export { normalizeMempool, findByHash, findByAddressNonce, findInMempool, } from './mempool.js';
|
|
21
22
|
export type { NormalizedMempool, TxIdentifier, MempoolBucket, MempoolHit, } from './mempool.js';
|
|
22
23
|
export { tipForBlockPosition } from './block-position.js';
|
|
23
24
|
export type { BlockPositionQuery, BlockPositionResult, } from './block-position.js';
|
|
25
|
+
export { minimumReplacementFee, bumpForReplacement, recommendBumpTier, BumpStrategy, ReplacementBumpPercent, } from './replacement.js';
|
|
26
|
+
export type { RecommendBumpTierOptions, ReplacementGas, } from './replacement.js';
|
|
27
|
+
export { classifyTip, type ClassifyTipResult } from './classify-tip.js';
|
|
28
|
+
export { defaultInclusionLabels, inclusionLabel } from './inclusion-labels.js';
|
|
29
|
+
export { chainPresets, presetForChainId, type ChainPreset, } from './presets.js';
|
|
24
30
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,KAAK,sBAAsB,EAC3B,KAAK,SAAS,GACf,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,SAAS,EACT,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,UAAU,EACV,8BAA8B,EAC9B,gCAAgC,GACjC,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,aAAa,EACb,gBAAgB,GACjB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EACV,KAAK,EACL,cAAc,EACd,kBAAkB,EAClB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,KAAK,sBAAsB,EAC3B,KAAK,SAAS,GACf,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,SAAS,EACT,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,UAAU,EACV,8BAA8B,EAC9B,gCAAgC,GACjC,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,aAAa,EACb,gBAAgB,GACjB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EACV,KAAK,EACL,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,WAAW,EACX,cAAc,EACd,SAAS,EACT,WAAW,GACZ,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGhF,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,aAAa,GACd,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,UAAU,GACX,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACzD,YAAY,EACV,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,sBAAsB,GACvB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,wBAAwB,EACxB,cAAc,GACf,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAGvE,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAG9E,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,KAAK,WAAW,GACjB,MAAM,cAAc,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -16,8 +16,18 @@ export { createGasOracle, reducePollInputs, sampleGasFees, } from './oracle.js';
|
|
|
16
16
|
export { effectiveTip, computePercentiles, detectTrend, cappedTip, computeTiers, computeBlobBaseFee, flattenTxPool, gasWeightedPercentiles, sortedTips, DEFAULT_PRIORITY_FEE_DECAY_CAP, DEFAULT_BASE_FEE_LIVENESS_BLOCKS, } from './math.js';
|
|
17
17
|
export { blockToSample, mempoolToSamples, } from './samples.js';
|
|
18
18
|
export { fetchOracleInputs, fetchHeadBlockNumber, } from './transport.js';
|
|
19
|
+
// Const-namespace pairs (value + type share the identifier — see types.ts).
|
|
20
|
+
export { PriorityModel, TierName, TIER_LADDER, Trend, TxType } from './types.js';
|
|
19
21
|
// Mempool inspection
|
|
20
22
|
export { normalizeMempool, findByHash, findByAddressNonce, findInMempool, } from './mempool.js';
|
|
21
23
|
// Block-position calculations
|
|
22
24
|
export { tipForBlockPosition } from './block-position.js';
|
|
25
|
+
// Replacement helpers (same-nonce EIP-1559)
|
|
26
|
+
export { minimumReplacementFee, bumpForReplacement, recommendBumpTier, BumpStrategy, ReplacementBumpPercent, } from './replacement.js';
|
|
27
|
+
// Tip classification (inverse of tipForBlockPosition)
|
|
28
|
+
export { classifyTip } from './classify-tip.js';
|
|
29
|
+
// Inclusion labels (UI copy with optional locale overrides)
|
|
30
|
+
export { defaultInclusionLabels, inclusionLabel } from './inclusion-labels.js';
|
|
31
|
+
// Chain presets (per-chain config overrides for createGasOracle)
|
|
32
|
+
export { chainPresets, presetForChainId, } from './presets.js';
|
|
23
33
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,GAGd,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,SAAS,EACT,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,UAAU,EACV,8BAA8B,EAC9B,gCAAgC,GACjC,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,aAAa,EACb,gBAAgB,GACjB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,iBAAiB,EACjB,oBAAoB,GAKrB,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,GAGd,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,SAAS,EACT,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,UAAU,EACV,8BAA8B,EAC9B,gCAAgC,GACjC,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,aAAa,EACb,gBAAgB,GACjB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,iBAAiB,EACjB,oBAAoB,GAKrB,MAAM,gBAAgB,CAAA;AAcvB,4EAA4E;AAC5E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAEhF,qBAAqB;AACrB,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,aAAa,GACd,MAAM,cAAc,CAAA;AAQrB,8BAA8B;AAC9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAMzD,4CAA4C;AAC5C,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,sBAAsB,GACvB,MAAM,kBAAkB,CAAA;AAMzB,sDAAsD;AACtD,OAAO,EAAE,WAAW,EAA0B,MAAM,mBAAmB,CAAA;AAEvE,4DAA4D;AAC5D,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAE9E,iEAAiE;AACjE,OAAO,EACL,YAAY,EACZ,gBAAgB,GAEjB,MAAM,cAAc,CAAA"}
|
package/dist/math.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* (legacy txs, EIP-1559 with zero headroom, cold-start cap, post-EIP-4844
|
|
8
8
|
* blob fee) is handled here rather than at higher layers.
|
|
9
9
|
*/
|
|
10
|
-
import
|
|
10
|
+
import { PriorityModel, TierName, Trend, type RawTx, type TierRecommendation, type TipPercentiles, type TipSample } from './types.js';
|
|
11
11
|
/** Default priority-fee decay cap = 12.5% / block (EIP-1559 parity). */
|
|
12
12
|
export declare const DEFAULT_PRIORITY_FEE_DECAY_CAP: bigint;
|
|
13
13
|
/**
|
package/dist/math.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,aAAa,EACb,QAAQ,EACR,KAAK,EAEL,KAAK,KAAK,EACV,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,YAAY,CAAA;AAcnB,wEAAwE;AACxE,eAAO,MAAM,8BAA8B,QAAW,CAAA;AAEtD;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,IAAI,KAAK,EAAE,SAAS,MAAM,KAAG,MAezD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,EAAE,KAAG,cASrD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,KAAK,EAAE,EAAE,SAAS,MAAM,KAAG,MAAM,EAK5B,CAAA;AAErC;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,EAAE,KAAG,KAS/C,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,SAAS,GACpB,QAAQ,MAAM,EACd,gBAAgB,MAAM,EACtB,eAAe,MAAM,GAAG,SAAS,EACjC,0BAA0B,MAAM,GAAG,SAAS,EAC5C,WAAU,MAAM,GAAG,IAAqC,KACvD,MAgBF,CAAA;AAeD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,sBAAsB,GACjC,SAAS,SAAS,EAAE,EACpB,aAAa,MAAM,EAAE,KACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAkCvB,CAAA;AAED,6EAA6E;AAC7E,eAAO,MAAM,gCAAgC,IAAI,CAAA;AAmDjD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO;IAClC,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,cAAc,EAAE,SAAS,EAAE,CAAA;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,KAAK,CAAA;IACnB,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,GAAG,IAAI,CAAA;IAClD,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IACvD,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5C,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B,KAAG;IACF,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAA;IAC3C,aAAa,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;CA4DxC,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAAI,eAAe,MAAM,KAAG,MAY1D,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,KAC7D,KAAK,EAOP,CAAA"}
|