Proof of Basis
Demo: all data here is fake and synthetic.
⋮⋮Now
⋮⋮Holdings
⋮⋮In and out
⋮⋮Accounts
AccountTypeCountedOn chainCost basisUnlabeled
⋮⋮Plan a sale

Add a wallet

Your wallets

NameScriptBalanceLast scan

Import CSVs

Uploads are off in the demo, so nobody's real files end up on a public server. Run your own copy to import yours.

Drop CSV exports here or click · platforms are detected
Import with options

Stays on this server. Duplicates skipped.

FileAccountPlatformRowsWarnings

Prices

CSV: date, USD close Used for spends and income that have no price of their own.

Needs a label

Didn't match another account.

What was it?Details

Matched transfers

Wrong match? Unlink it. Both records come back to Review to label or link by hand, and that pair is never matched automatically again.

Proof of Basis is software for organizing your own records, for informational and educational purposes only.

  • Not professional advice. It does not provide tax, legal, accounting or financial advice. Using it does not create a professional-client relationship with anyone.
  • Not a CPA, enrolled agent, law firm or tax preparer. It does not prepare or file tax returns and does not guarantee any tax outcome.
  • Its numbers are estimates. Basis, gains, income, tax estimates, Form 8949 lines, 1099-DA checks and the assistant's answers depend on the records you give it, outside price data and its own rules. They may be incomplete or wrong.
  • You are responsible. You alone are responsible for checking your numbers, knowing current tax law, your filings, and any tax, interest or penalties owed. Tax law is complex and changes often.
  • Talk to a professional. Review your records and tax decisions with a qualified CPA, enrolled agent or tax attorney before you file.
  • No warranty. The software is provided as is, without warranty of any kind. Its authors are not liable for any loss arising from its use.
DateWhatInOutBalanceCounts as

Channels and wallet

AccountPeerBalance

Tax season

    • Drop each PDF and enter its total. Each exchange sends a Form 1099-DA early in the year. The PDF goes into your package, and its total proceeds are checked against your records.

        Import 1099-DA CSV
        • Income by type

          Set a type from the record. Income is reported in different places depending on what it was.

          YearTypeValueUsually reported on

          Gifts, donations and losses

          DateWhatTo / fromBTCValueBasisHeldDeductionTo check

          January 1, 2025: per-wallet split

          Pre-2025 pool split per account. Reassign, then confirm. Until 2024 one pool of basis covered all your accounts. From 2025 each wallet and exchange account keeps its own (Rev. Proc. 2024-28), and the IRS expects a record of how the pool was split as of January 1, 2025. By default the oldest purchases fill accounts in name order; assign a purchase to the account that really holds those coins, then confirm to keep a dated record.

          BoughtOnBTCBasisBelongs to on Jan 1, 2025
        • Form 8949 lines

          IRS box for each sale. C and F before 2025. From 2025: G/J when an exchange's 1099-DA reported basis, H/K when it didn't, I/L for sales no 1099-DA covers. "open" shows the record, to change a label or value.

          BoxSoldAccountBTC(d) Proceeds(e) Basis(f)(g)(h) Gain1099-DA check
        • One zip for the year. A README they read first, the Form 8949 lines (all, and per box), the 1099-DA PDFs with how each was checked, where every coin sold came from, income, gifts and donations, transfers, the January 2025 split, your recorded coin choices, the source files' fingerprints, and any proof you attached.

          Download accountant package

          Off: R- references only, no txids or addresses. Each record goes by a reference (R-…) that this app can look up. Include on-chain IDs only if your tax professional or an audit needs them.

        All years

        YearShort-term gainLong-term gainIncomeLoss carried inLoss deductedCarried outImpact estimate1040 question

        Rough estimate at your Settings rates. Not your return. Uses the rates and filing status in Settings. Net losses are deducted up to the yearly limit and the rest is carried forward.

        Protected purchases

        Sold last. Protect from a record.

        AcquiredAccountBTC

        Disposals

        SoldAcquiredAccountBTCProceedsBasisGainTerm

        Changes

        Display

        Saved in this browser. Whole dollars drop the cents rather than rounding. The bitcoin sign counts sats, written like dollars. Color-blind friendly colors show gains, losses, buys and sales in blue and orange, which people with red-green color blindness can tell apart.

        Your node

        In the demo, the node is simulated: it answers from the demo's own invented history.

        Tax

        Prices

        Only goes online when you press Update. Updating prices is the only time this app contacts anything besides your node. The image already includes daily history up to when it was built.

        Lightning node (optional)

        Create a read-only rune: lightning-cli createrune restrictions='[["method=getinfo","method=bkpr-listincome","method=bkpr-listbalances"]]' Stored here, never shown again and never logged. The app only reads from your node, and only when you sync.

        Security

        Signs out other devices. Forgot it? On the server, run docker compose exec btctax /btctax reset-password and set a new one on the next visit. Over plain http the password isn't encrypted in transit; use HTTPS (a reverse proxy or Tailscale) to reach this app from outside your home.

        Assistant (optional)

        In the demo, the assistant runs on a hosted model. Your own copy uses a model on your own Ollama server.

        Chat using your own Ollama. Pick a tool-capable model. Adds a chat button to every page. Your data goes only to that address, never anywhere else. Models that use tools (for example qwen3:8b or llama3.1:8b) can look things up. If Ollama runs on this same computer, use http://host.docker.internal:11434, since inside Docker "localhost" is the app itself. More memory lets it consider more at once but needs more RAM on the Ollama machine. Chats are saved here, included in backups and removed by Wipe.

        Backup and restore

        Download a backup
        Everything, including xpubs. Keep it encrypted. Settings, wallets and their keys, imports, labels, protected purchases, scans, prices and your Lightning node's history and rune. There's no way to recover a forgotten passphrase.
        Restore from a backup
        Replaces everything; current data saved first.

        Recheck everything

        Rescans and recomputes. Nothing deleted.

        Delete all data

        Deletes all data.

        Before you start