-
Notifications
You must be signed in to change notification settings - Fork 0
Source Adapters
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.
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.
daybook sync --source coinbase --from 2024-01-01
daybook sync --source coinbase- 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.
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.
- 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
daybook sync --source coinbase --file ~/Downloads/Coinbase-All-Transactions.csv| 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 |
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.
-
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
daybook sync --source kraken --file ~/Downloads/kraken-ledger.csv| 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 |
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.
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.
--source binance accepts exports with:
User_ID,UTC_Time,Account,Operation,Coin,Change,Remark-
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
daybook sync --source binance --file ~/Downloads/binance-ledger.csv| 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 |
Location: packages/sources/src/binance/
Parses Binance.US tax-report style CSV exports with primary/base/quote/fee asset columns.
--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_Assetdaybook sync --source binance-us --file ~/Downloads/binance-us-tax.csv- 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.
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.
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.
daybook sync --source csv --file ~/Downloads/universal-ledger.csv- 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.
Location: packages/sources/src/evm/
Fetches on-chain transfers for EVM wallets (Ethereum, Polygon) via provider interfaces.
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.
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)
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
# 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-gasThe 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)
Getting Started
Usage
Architecture