Architecture

Source Adapters

Edit on GitHub

Source adapters live in packages/sources/. Each adapter has one job: produce RawEvent[] from its source. Adapters do not classify intent — that's the classifier's job.

Coinbase API Adapter

Location: packages/sources/src/coinbase/

Syncs Coinbase data through Coinbase App APIs. daybook uses the Track APIs for accounts and transaction history, and the Advanced Trade fills endpoint to enrich matched Advanced Trade activity with fill price and fee details.

Coinbase maintains the API setup, key type, permissions, and endpoint documentation. See Coinbase API Setup for daybook usage and links to Coinbase's official docs.

Usage

bash
daybook sync --source coinbase --from 2024-01-01
daybook sync --source coinbase

Behavior

  • Uses deterministic IDs with coinbase:api:* prefixes.
  • Groups duplicate v2 transaction IDs across Coinbase accounts to avoid double-counting multi-account legs.
  • Enriches matched Advanced Trade transactions with v3 fill data.
  • Stores a local sync watermark after successful API syncs.
  • Supports --from for bounded first syncs or explicit resync windows.

Coinbase CSV Adapter

Location: packages/sources/src/coinbase/

Parses Coinbase "All Transactions" CSV exports. Handles all 13 transaction types including Buy, Sell, Convert, Send, Receive, staking income, and internal moves.

Key Features

  • Notes parsing — extracts structured data from the free-form Notes column (Convert second leg, Send destination address, Advanced Trade details)
  • Pair merging — groups Retail Staking Transfer and Retail Eth2 Deprecation rows by (timestamp, abs(quantity)) into single internal_move events
  • Deterministic IDscoinbase:{rowId} for singles, composite IDs for pairs

Usage

bash
daybook sync --source coinbase --file ~/Downloads/Coinbase-All-Transactions.csv

Supported Transaction Types

TypeRawEvent TypeNotes
BuytradeTwo legs (fiat out, crypto in) + fee
SelltradeTwo legs (crypto out, fiat in) + fee
ConverttradeSecond leg parsed from Notes column
Sendcrypto_outDestination address parsed from Notes
Receivecrypto_inSource often unknown
Staking IncomeincomeSingle positive leg
Reward IncomeincomeSingle positive leg
Inflation RewardincomeSingle positive leg
Depositfiat_depositUSD only
Withdrawalfiat_withdrawalUSD only
Retail Staking Transferinternal_movePaired by timestamp + amount
Retail Eth2 Deprecationinternal_movePaired by timestamp + amount
Advanced Trade BuytradeLike Buy with different note format

Kraken CSV Adapter

Location: packages/sources/src/kraken/

Parses Kraken "Export Ledger" CSV files. Kraken uses a true double-entry ledger where trades are represented as two rows sharing a refid.

Key Features

  • Trade pairing — groups rows by refid, pairs of exactly 2 trade rows become one trade event
  • Asset normalization — maps Kraken's internal names to canonical symbols (XXBT→BTC, XETH→ETH, ZUSD→USD, ZEUR→EUR, ETH2→ETH, etc.)
  • Fee handling — non-zero fees produce a separate AssetLeg with feeFlag: true
  • Deterministic IDskraken:{refid} for trades, kraken:{txid} for singles
  • Idempotent — same CSV parsed twice produces identical event IDs

Usage

bash
daybook sync --source kraken --file ~/Downloads/kraken-ledger.csv

Supported Row Types

Kraken TypeRawEvent TypeNotes
tradetradePaired by refid (2 rows → 1 event)
depositcrypto_inSingle positive leg
withdrawalcrypto_outSingle negative leg
stakingincomeSingle positive leg
Unknown typesunknownWarning emitted

Asset Normalization

Kraken uses non-standard asset names. The adapter normalizes them:

Krakendaybook
XXBTBTC
XETHETH
XLTCLTC
XXRPXRP
ZUSDUSD
ZEUREUR
ZGBPGBP
ETH2, ETH2.SETH

Assets not in the map pass through unchanged.

Binance CSV Adapter

Location: packages/sources/src/binance/

Parses Binance ledger-style CSV exports. Binance global and Binance.US are explicit source profiles so their formats can evolve independently.

Binance Ledger Format

--source binance accepts exports with:

csv
User_ID,UTC_Time,Account,Operation,Coin,Change,Remark

Key Features

  • Trade grouping — rows sharing timestamp, account, and remark are grouped into a single trade event when they include both positive and negative trade legs
  • Fee grouping — fee rows in the same group are attached as feeFlag legs
  • Income detection — staking, earn, interest, airdrop, cashback, referral, and reward operations become income
  • Fiat/stablecoin distinction — USD/EUR/etc. are fiat, while USDC and USDT remain crypto assets
  • Deterministic IDs — grouped rows are hashed from stable row content; duplicate IDs are suffixed deterministically

Usage

bash
daybook sync --source binance --file ~/Downloads/binance-ledger.csv

Supported Ledger Operations

Operation shapeRawEvent TypeNotes
Buy/Sell/Trade/Convert rows grouped by remarktradePositive and negative principal legs become one event
Fee/Commissionfee_only or fee legGrouped into trade when present with matching trade rows
Depositcrypto_in or fiat_depositDepends on asset
Withdrawalcrypto_out or fiat_withdrawalDepends on asset
Reward/Earn/Staking/Interest/AirdropincomePositive crypto leg

Binance.US CSV Adapter

Location: packages/sources/src/binance/

Parses Binance.US tax-report style CSV exports with primary/base/quote/fee asset columns.

Binance.US Tax-Report Format

--source binance-us accepts rows such as:

csv
Time,Category,Operation,Order_ID,Transaction_ID,Primary_Asset,Realized_Amount_For_Primary_Asset,Quote_Asset,Realized_Amount_For_Quote_Asset,Fee_Asset,Realized_Amount_For_Fee_Asset

Usage

bash
daybook sync --source binance-us --file ~/Downloads/binance-us-tax.csv

Behavior

  • Primary/base/quote/fee asset columns become signed AssetLeg records.
  • Fee asset columns are always negative fee legs.
  • Rows with both positive and negative principal legs become trade.
  • Single positive reward-like rows become income; other single positive crypto rows become crypto_in.

Generic CSV Adapter

Location: packages/sources/src/generic-csv/

Parses common universal/manual crypto ledger CSV files used by tax tools. This is the fallback when a source-specific adapter does not exist yet.

Preferred Format

csv
Date,Type,Sent Amount,Sent Currency,Received Amount,Received Currency,Fee Amount,Fee Currency,Net Worth Amount,Net Worth Currency,Description,TxHash

Aliases such as Timestamp, Label, Tag, Sent Quantity, Received Quantity, Buy Amount, Sell Amount, Transaction ID, and Fee are also accepted.

Usage

bash
daybook sync --source csv --file ~/Downloads/universal-ledger.csv

Behavior

  • Sent and received columns become signed trade or transfer legs.
  • Fee columns become negative feeFlag legs.
  • Reward/staking/airdrop/mining/interest labels become income.
  • Fiat currencies such as USD/EUR/GBP become fiat events.
  • Stablecoins such as USDC and USDT stay as crypto assets.

EVM Adapter

Location: packages/sources/src/evm/

Fetches on-chain transfers for EVM wallets (Ethereum, Polygon) via provider interfaces.

Providers

Alchemy (primary)

Location: packages/sources/src/evm/providers/alchemy.ts

Uses alchemy.core.getAssetTransfers to fetch all transfer types in a single paginated call:

  • External transfers (ETH sends/receives)
  • Internal transfers (contract-to-contract)
  • ERC-20 token transfers
  • ERC-721 / ERC-1155 NFT transfers

Uses rawContract.value (hex) + rawContract.decimal (hex) for precise amounts — never the SDK's value: number field which loses precision above 2^53.

Etherscan (failed transactions)

Location: packages/sources/src/evm/providers/etherscan.ts

Fetches the normal transaction list from Etherscan's txlist endpoint. Only emits transfers for failed transactions (isError === '1'), capturing gas costs that Alchemy doesn't report.

  • Gas cost computed as gasUsed × gasPrice / 1e18 using decimal.js
  • Provider ID: etherscan-failed:{txHash}
  • Auto-paginates until all results retrieved
  • Exponential backoff on rate limits (429)

Block Resolver

Location: packages/sources/src/evm/block-resolver.ts

Resolves --from values to block numbers:

  • Numeric strings pass through as BigInt
  • ISO 8601 dates are resolved to the nearest block via binary search using Alchemy's getBlock

Usage

bash
# Full sync
daybook sync --source eth
daybook sync --source polygon

# Incremental sync
daybook sync --source eth --from 2024-01-01
daybook sync --source polygon --from 50000000

# Include failed transaction gas
daybook sync --source eth --include-failed-gas

Adapter Behavior

The adapter (packages/sources/src/evm/adapter.ts) translates RawTransfer objects from any provider into RawEvent objects:

  • category: native/erc20 with from = usercrypto_out (negative leg)
  • category: native/erc20 with to = usercrypto_in (positive leg)
  • category: erc721/erc1155nft_event (with contractAddress and tokenId preserved on the AssetLeg)
  • If tokenId is missing from the provider, defaults to 'unknown' with a note on the raw event
  • asset field uses token symbol when available, falls back to contract address
  • Bidirectional dedup by providerId (self-transfers appear in both directions)