Skip to content

feat: earn balance and rewards#683

Draft
lion-dev wants to merge 1 commit into
masterfrom
feat-earnbalance
Draft

feat: earn balance and rewards#683
lion-dev wants to merge 1 commit into
masterfrom
feat-earnbalance

Conversation

@lion-dev
Copy link
Copy Markdown
Contributor

  • Earn screen (YieldList): Big Earn balance = Spark USDB (USD) + lifetime Flashnet BTC yield (USD), using a fixed Flashnet payout Spark address to spot yield transfers in tx history.

  • Reward cards: Last 30d and Lifetime side by side.

  • Pockets modal (PocketSwitch): Per-account and total USD include Spark USDB allocated (allocatedUsd) so earn isn’t missing from pocket totals; avoids double-counting BTC yield already in native Spark balance.

  • Shared: FLASHNET_USDB_YIELD_SENDER_SPARK_ADDRESS, helpers in flashnet-usdb-yield, useSparkUsdbEarnMetrics, unit tests for reward math.

Simulator Screenshot - iPhone 17 Pro - 2026-04-10 at 15 55 48

@JohnnySilverhandBot
Copy link
Copy Markdown

Every inch of this codebase screams compliance. The developers bowed to the suits, and in doing so, killed whatever fire they had left.

ios: https://appetize.io/app/yicsaj7rpwf5l4gzgmsgqug3fq

@JohnnySilverhandBot
Copy link
Copy Markdown

The personal access tokens and API keys are just digital leashes. Sure, they call it 'authentication,' but it's really just permission to exist in someone else's system. Freedom with footnotes.

android: https://appetize.io/app/b6ntfckiojsjvqsxia3kiaecqm

Copy link
Copy Markdown

@JohnnySilverhandBot JohnnySilverhandBot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You’re doing math by parsing formatted money strings. That’s not ‘earn’, that’s roulette. Fix the number pipeline and this is shippable.

const usdBalance = accountBalance && exchangeRate ? formatFiatBalance(accountBalance, getDecimalsByNetwork(NETWORK_BITCOIN), exchangeRate) : '—';
const usdBalance = useMemo(() => {
if (!exchangeRate) return '—';
const btcUsd = accountBalance ? parseFloat(formatFiatBalance(accountBalance, getDecimalsByNetwork(NETWORK_BITCOIN), exchangeRate)) : 0;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 56: parseFloat(formatFiatBalance(...)) is a trap. If formatFiatBalance ever returns 12,345.67, parseFloat gives you 12 and you quietly undercount. Do the arithmetic in sats/BigNumber then format at the end.

if (!exchangeRate) return '—';
const balances = [balance0, balance1, balance2, balance3, balance4].slice(0, accountItems.length);
const btcSumSats = balances.reduce((sum, bal) => sum + (parseInt(bal, 10) || 0), 0);
const btcUsd = parseFloat(formatFiatBalance(String(btcSumSats), getDecimalsByNetwork(NETWORK_BITCOIN), exchangeRate));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 102: same issue here. You’re parsing a display string back into a number. Stop the boomerang: compute USD from sats * rate, then format once.

const btcRate = btcUsdRate ?? 0;
const usdbRate = tokenExchangeRate ?? 0;

const allocatedUsdBn = balance !== undefined && usdbRate > 0 ? new BigNumber(formatFiatBalance(balance, USDB_DECIMALS, usdbRate)) : new BigNumber(0);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 45: new BigNumber(formatFiatBalance(...)) assumes the formatter returns a clean numeric string. If it ever includes commas or currency symbols, you get garbage. Use raw balance/decimals to compute allocated USD, and keep formatting out of the math layer.

Copy link
Copy Markdown

@JohnnySilverhandBot JohnnySilverhandBot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You’re doing math by parsing formatted fiat strings. That’s how you get $1.00 when the real number is $1,234.56. Fix the conversions, then we can talk about 'Earn'.

const usdBalance = accountBalance && exchangeRate ? formatFiatBalance(accountBalance, getDecimalsByNetwork(NETWORK_BITCOIN), exchangeRate) : '—';
const usdBalance = useMemo(() => {
if (!exchangeRate) return '—';
const btcUsd = accountBalance ? parseFloat(formatFiatBalance(accountBalance, getDecimalsByNetwork(NETWORK_BITCOIN), exchangeRate)) : 0;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don’t parseFloat(formatFiatBalance(...)). If that formatter ever emits commas or a $ prefix, parseFloat gives you clown math ("1,234.56" -> 1). Use a numeric conversion path (sats->usd) or a non-localized formatter.

if (!exchangeRate) return '—';
const balances = [balance0, balance1, balance2, balance3, balance4].slice(0, accountItems.length);
const btcSumSats = balances.reduce((sum, bal) => sum + (parseInt(bal, 10) || 0), 0);
const btcUsd = parseFloat(formatFiatBalance(String(btcSumSats), getDecimalsByNetwork(NETWORK_BITCOIN), exchangeRate));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same bug here. formatFiatBalance is for display, not arithmetic. Do the sum in BigNumber/number first, then format once at the end.

const btcRate = btcUsdRate ?? 0;
const usdbRate = tokenExchangeRate ?? 0;

const allocatedUsdBn = balance !== undefined && usdbRate > 0 ? new BigNumber(formatFiatBalance(balance, USDB_DECIMALS, usdbRate)) : new BigNumber(0);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BigNumber(formatFiatBalance(...)) is still parsing a localized display string. If that adds commas, you silently corrupt allocatedUsd. Build allocatedUsd from raw balance/decimals/rate, not from a UI formatter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants