Skip to content

ACCUM creator fees: Bankr readings, claim evidence and reconciliation - #92

Merged
danbuildss merged 1 commit into
mainfrom
claude/brave-pasteur-mayw5k
Sep 27, 2026
Merged

danbuildss merged 1 commit into
mainfrom
claude/brave-pasteur-mayw5k

Conversation

@danbuildss

Copy link
Copy Markdown
Owner

What changed

ACCUM PR 2 of 3: fee accounting. The Telegram answers and the on-demand machine report come in PR 3.

  • Migration 025 (additive):
    • fee_sources: token, pool id, fee contract, fee asset and wallet, scoped to one user.
    • fee_source_readings: what Bankr reported, hourly, including failed reads.
    • fee_claim_checks: the receipt evidence for each BNKR transfer into the fee wallet.
    • classifications.fee_source_id
    • No new label.
  • Bankr public reader (src/fees/bankr.ts):
    • No key and a 10-second timeout.
    • Clear failures: "Bankr did not answer within 10 seconds", "Bankr answered with HTTP 503", and so on.
    • It reads the fee side of the pool, which is the numeraire (BNKR).
  • Readings (src/fees/sources.ts): the worker reads Bankr hourly.
    • A failed read keeps the last good reading, and its time, visible.
    • If Bankr ever reports a different pool, fee contract, fee token or wallet, the readings stop until an admin checks it. The mismatched numbers are never used.
  • Claim evidence (src/fees/claims.ts): each cycle, before classification, every BNKR transfer into the fee wallet is checked against its receipt.
    • claim → revenue tied to the source. The transfer came from the fee contract, or the fee contract logged this pool in the same transaction, and nothing ties it to another pool.
    • unclear → unknown. The fee contract is involved, but the evidence doesn't tie the transfer to this pool alone.
    • unrelated → labeled as usual.
  • Waiting for evidence: until its receipt is read, the transfer waits unlabeled, and the model never labels it.
  • What is never changed:
    • The operator's own labels.
    • Swaps, internal transfers and gas; the transaction's shape still decides first.
  • Two tokens named ACCUM pay the same wallet through the same fee contract (0x70ae… and 0x0b3c…). With several sources, a transfer only counts when the transaction names exactly one of their pools. A transfer from the shared fee contract that names no pool stays unknown.
  • Status (feeSourceStatus):
    • Bankr's reported claimable and claimed amounts, and whether that reading is stale.
    • The change in claimable between readings. It is not called "earned", because a claim lowers it.
    • The claims verified on-chain, from exact integer amounts.
    • Reconciliation: Bankr's claimed amount and count against the chain, with any mismatch shown.
  • node dist/scripts/fee-source.js add 0xWallet 0xToken | status, for the admin on the server.

Not in this PR:

  • Volume, lifetime WETH and the fee split. Bankr reports 0 for lifetime/daily WETH, and the on-chain recipient weights conflict with its "95%".
  • Staking and rewards.
  • Any claiming or moving of funds.

Why

This is the approved ACCUM experiment: Luca accounts for the $ACCUM → Bankr creator fees (BNKR) → Luca wallet loop. It follows the three approved refinements:

  1. Specific fee provenance. Unknown is better than false revenue.
  2. Reported vs verified kept apart, with mismatches shown. There is no hardcoded generated = claimed + claimable.
  3. Honest wording: ACCUM is not a supported token. Only BNKR fee activity is booked.

How it was verified

  • npm run lint and npm run typecheck pass
  • LUCA_INTEGRATION=1 npx vitest run passes: 55 files, 527 tests
  • New or changed behaviour has a test
    • tests/fees/bankr.test.ts:
      • Parses Bankr's real Sep 27 ACCUM response and reads the fee side.
      • Rejects unrecognised or negative data.
      • Checks the timeout and HTTP error wording.
    • tests/fees/claims.test.ts covers every verdict:
      • paid by the fee contract
      • routed through another contract, with this pool logged
      • another pool present
      • no pool named
      • fee contract not involved
      • a failed transaction
      • the two-ACCUM cases
    • tests/integration/fee-sources.test.ts:
      • Adding a source; refusing an unverifiable one (untracked wallet, fees paid to another wallet, fee asset not tracked, Bankr down).
      • Hourly readings; a failed read keeps the last good one; a changed pool stops the readings.
      • The claimable window.
      • A claim waits unlabeled until checked, with no model call, then becomes revenue with provenance.
      • Mismatch, then match once Bankr catches up.
      • Unclear stays unknown; BNKR from anyone else is labeled as usual.
      • A model's label is replaced; the operator's own label is untouched.
      • An unreadable receipt is retried next cycle.
      • Two sources on one wallet.
      • Another operator tracking the same wallet gets nothing from this source.
  • Live smoke test against Bankr's real API on a local database: add stored pool 0xf50f…ea37eb, fee contract 0x9982…fdbb, BNKR; status showed claimable 2,742,866.01 BNKR, 0 claimed and a match.
  • Migration 025 applied twice without error.

Checklist

  • Luca stays read-only and every financial query stays scoped to one operator. It only reads Bankr's public API and transaction receipts. Every source, check and status query is scoped to the source's user_id.
  • Schema changes are a new, additive migration (025)
  • No secrets, keys or personal wallet details added. No Bankr key; the addresses in tests are public on-chain addresses from the approved plan.

Deploy:

  1. Code: cd /opt/luca && git pull && npm ci && bun run build
  2. Apply migration 025 with the usual node one-shot, before restarting.
  3. Restart luca-api luca-worker luca-telegram.
  4. Add the source once: node dist/scripts/fee-source.js add 0xb54081ff3f6a90a5a1057d8a5537f7f14e376fdb 0x70aEb20cD233e044bB7676C34105712132F49Ba3

🤖 Generated with Claude Code

https://claude.ai/code/session_01KqcPsn2HCGWiE2FTmHKYEQ


Generated by Claude Code

A fee source (migration 025) ties a token's creator fees to one of the operator's
wallets, with the pool, fee contract and fee asset Bankr reported when it was added.

- Bankr's public data (no key) is read hourly and kept as "reported by Bankr",
  including failed reads, so Luca can say when it last heard from Bankr and why the
  latest read failed. If Bankr ever reports a different pool, fee contract, fee
  token or wallet, the readings stop until an admin checks it.
- Each BNKR transfer into the fee wallet is checked against its receipt before it is
  labeled. It becomes revenue tied to the source only when it comes from the fee
  contract, or the fee contract recorded this pool, and nothing ties it to another
  pool. When the fee contract is involved but the evidence is not enough it stays
  unknown. Anything else is labeled as usual. Until its receipt is read, the
  transfer waits unlabeled; the model never labels it.
- Two tokens named ACCUM pay the same wallet through the same fee contract: with
  several sources, only a transaction naming exactly one of their pools counts.
- Status: reported claimable/claimed, the change in claimable between readings (not
  called "earned"), verified on-chain claims from exact integer amounts, and
  whether Bankr's claimed figure matches the chain (a mismatch is shown, not hidden).
- node dist/scripts/fee-source.js add|status for the admin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqcPsn2HCGWiE2FTmHKYEQ
@vercel

vercel Bot commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
luca Ready Ready Preview Sep 27, 2026 5:07pm UTC

Request Review

@danbuildss
danbuildss merged commit 10dff30 into main Sep 27, 2026
6 checks passed

This branch was successfully deployed

1 active deployment
Preview — 78bb529f Deployed Sep 27, 2026 by vercel[bot]
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