ENS-budget: budget-first ENS v2 renewals for viem

ens-budget is a small TypeScript library for ENSv2 renewals. It finds the longest renewal a budget buys, warns users when the term they picked costs more than a longer one, and handles the renewal.

The problem

ENSv2 discounts the whole term once it reaches 2, 3 or 6 years. So one day short of a tier can cost more than the tier itself. For a 5+ character name:

Term Price
1 year 364 days $15.98
2 years $14.01
2 years 364 days $20.99
3 years $16.51
5 years 364 days $32.99
6 years $27.01

Most apps let users pick a “renew until” date. Pick a date just short of a tier and you pay more for less time.

For apps with a date picker

Check the chosen term and suggest the tier when it is cheaper:


const cost = priceOf(pricing, { label, duration })

const best = solve(pricing, { label, budget: cost })

if (best.tier && best.tier.duration > duration) {

// e.g. "6 years costs $27.01, less than the $32.99 you selected"

}

pricing comes from one getPricing call; priceOf and solve run locally, so this can run on every date change.

For apps that start from a budget

quoteRenewal returns the longest term a budget buys, which is never one of the more expensive terms above, and flags when a small top-up reaches the next tier. With $26, the best term is about 4 years 9 months; adding $1.01 reaches 6 years, about 15 more months. The steps are sharp: $27.00 buys about 4 years 11 months, while $27.01 buys 6 years. renewWithBudget then renews the name for that term.

Details

  • Reads rates, discount points and the token ratio from the renewer’s rentPriceOracle(), and confirms quotes with getRenewPrice. Nothing is hardcoded.

  • Picks ETHRegistrar or ETHRenewerV1 automatically, so unmigrated v1 names work too.

  • prepareRenewal returns plain calls for EIP-5792 batching, Safe, bundlers or relayers.

  • viem is the only dependency; about 3 kB min+gzip. Mainnet and Sepolia, USDC and DAI.

Feedback, issues and PRs welcome.