-
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/
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/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_eventplaceholder - Bidirectional dedup by
providerId(self-transfers appear in both directions)
Getting Started
Usage
Architecture