Skip to content

Source Adapters

Griffen Fargo edited this page May 10, 2026 · 4 revisions

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.

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 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

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

Supported 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 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

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

Supported 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,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

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

Supported 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_Asset

Usage

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

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

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

# 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)

Clone this wiki locally