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
daybook sync --source coinbase --from 2024-01-01
daybook sync --source coinbaseBehavior
- 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
--fromfor 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 TransferandRetail Eth2 Deprecationrows by(timestamp, abs(quantity))into singleinternal_moveevents - Deterministic IDs —
coinbase:{rowId}for singles, composite IDs for pairs
Usage
daybook sync --source coinbase --file ~/Downloads/Coinbase-All-Transactions.csvSupported Transaction Types
| Type | RawEvent Type | Notes |
|---|---|---|
| Buy | trade | Two legs (fiat out, crypto in) + fee |
| Sell | trade | Two legs (crypto out, fiat in) + fee |
| Convert | trade | Second leg parsed from Notes column |
| Send | crypto_out | Destination address parsed from Notes |
| Receive | crypto_in | Source often unknown |
| Staking Income | income | Single positive leg |
| Reward Income | income | Single positive leg |
| Inflation Reward | income | Single positive leg |
| Deposit | fiat_deposit | USD only |
| Withdrawal | fiat_withdrawal | USD only |
| Retail Staking Transfer | internal_move | Paired by timestamp + amount |
| Retail Eth2 Deprecation | internal_move | Paired by timestamp + amount |
| Advanced Trade Buy | trade | Like 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 onetradeevent - 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
AssetLegwithfeeFlag: true - Deterministic IDs —
kraken:{refid}for trades,kraken:{txid}for singles - Idempotent — same CSV parsed twice produces identical event IDs
Usage
daybook sync --source kraken --file ~/Downloads/kraken-ledger.csvSupported Row Types
| Kraken Type | RawEvent Type | Notes |
|---|---|---|
| trade | trade | Paired by refid (2 rows → 1 event) |
| deposit | crypto_in | Single positive leg |
| withdrawal | crypto_out | Single negative leg |
| staking | income | Single positive leg |
| Unknown types | unknown | Warning emitted |
Asset Normalization
Kraken uses non-standard asset names. The adapter normalizes them:
| Kraken | daybook |
|---|---|
| XXBT | BTC |
| XETH | ETH |
| XLTC | LTC |
| XXRP | XRP |
| ZUSD | USD |
| ZEUR | EUR |
| ZGBP | GBP |
| ETH2, ETH2.S | ETH |
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:
User_ID,UTC_Time,Account,Operation,Coin,Change,RemarkKey Features
- Trade grouping — rows sharing timestamp, account, and remark are grouped into a single
tradeevent when they include both positive and negative trade legs - Fee grouping — fee rows in the same group are attached as
feeFlaglegs - 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
daybook sync --source binance --file ~/Downloads/binance-ledger.csvSupported Ledger Operations
| Operation shape | RawEvent Type | Notes |
|---|---|---|
| Buy/Sell/Trade/Convert rows grouped by remark | trade | Positive and negative principal legs become one event |
| Fee/Commission | fee_only or fee leg | Grouped into trade when present with matching trade rows |
| Deposit | crypto_in or fiat_deposit | Depends on asset |
| Withdrawal | crypto_out or fiat_withdrawal | Depends on asset |
| Reward/Earn/Staking/Interest/Airdrop | income | Positive 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:
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_AssetUsage
daybook sync --source binance-us --file ~/Downloads/binance-us-tax.csvBehavior
- Primary/base/quote/fee asset columns become signed
AssetLegrecords. - 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 becomecrypto_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
Date,Type,Sent Amount,Sent Currency,Received Amount,Received Currency,Fee Amount,Fee Currency,Net Worth Amount,Net Worth Currency,Description,TxHashAliases such as Timestamp, Label, Tag, Sent Quantity, Received Quantity, Buy Amount, Sell Amount, Transaction ID, and Fee are also accepted.
Usage
daybook sync --source csv --file ~/Downloads/universal-ledger.csvBehavior
- Sent and received columns become signed trade or transfer legs.
- Fee columns become negative
feeFlaglegs. - 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 / 1e18using 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
# 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-gasAdapter Behavior
The adapter (packages/sources/src/evm/adapter.ts) translates RawTransfer objects from any provider into RawEvent objects:
category: native/erc20withfrom = user→crypto_out(negative leg)category: native/erc20withto = user→crypto_in(positive leg)category: erc721/erc1155→nft_event(withcontractAddressandtokenIdpreserved on theAssetLeg)- If
tokenIdis missing from the provider, defaults to'unknown'with a note on the raw event assetfield uses token symbol when available, falls back to contract address- Bidirectional dedup by
providerId(self-transfers appear in both directions)