Source Format Profiles
📑 Source Format Profiles
Section titled “📑 Source Format Profiles”A standard column mapper can easily identify that a CSV header called Fee maps to fee_amount.
However, it structurally cannot know:
- Whether the number in that column represents a fiat EUR valuation or tokens deducted in the native asset.
- Whether a single operation is exported as one row or two separate rows (one for the buy leg, one for the sell leg).
- Whether a row writes the moved quantity into both directional columns simultaneously.
These are facts about the source exchange, not facts about a column name. In Kryptofolio, these exchange-specific conventions are declared as immutable data profiles in packages/core-domain/src/domain/services/sourceProfile/.
🏛️ The SourceFormatProfile Interface
Section titled “🏛️ The SourceFormatProfile Interface”export interface SourceFormatProfile { readonly id: SourceProfileId; readonly label: string; readonly market: DeclaredMarket; // SPOT | FUTURES | UNDECLARED readonly signature: HeaderSignature; // Signature detection prior to mapping readonly feeDenomination: FeeDenomination; // NATIVE | VALUED_IN_FIAT | INCLUDED_IN_TOTAL readonly feeConvention: FeeConvention; // GROSS | NET readonly directionalFill: DirectionalFill; // ONE_SIDED | BOTH_SIDES_WRITTEN readonly columnRoles: ColumnRoles; readonly invariant?: ProfileInvariant; // Self-consistency assertion}🏷️ The Six Declared Profiles
Section titled “🏷️ The Six Declared Profiles”Kryptofolio includes out-of-the-box profiles for major crypto exchanges and wallets:
| Profile ID | Target Platform | Signature Matching Rules | Key Characteristics |
|---|---|---|---|
kraken-spot |
Kraken Spot Ledger | Contains txid, refid, time, type, subtype, aclass |
Two rows per trade; fee denominated in fee asset or valued in EUR. |
kraken-futures |
Kraken Futures | Contains Trade Id, Fill Type, Effective Margin |
Futures margin funding and PnL settlements. |
bit2me-spot |
Bit2Me | Contains Spanish headers (Fecha, Tipo de operación, Operación) |
Writes one movement onto both directional columns (amount_in/out). |
bitvavo-spot |
Bitvavo | Contains Transaction ID, Execution Type, Settled Quantity |
Net/Gross fee adjustments and ISO timestamp format. |
bitunix-spot |
Bitunix | Contains UID, Order No, Trading Pair, Filled Amount |
Dedicated spot order ledger format. |
tangem |
Tangem Hardware Wallet | Contains Tangem app transaction export headers | Cold-storage custody transfer entries with on-chain TX hashes. |
generic |
Generic Fallback | Fallback reached only when no signature matches | Standard neutral CSV mapping. |
🔍 Deterministic Signature Detection
Section titled “🔍 Deterministic Signature Detection”Detection runs on the raw header row before any mapping or data extraction takes place:
import { detectSourceProfile } from '@/domain/services/sourceProfile/detectSourceProfile';
const detected = detectSourceProfile(rawCsvHeaders);// Returns: { status: 'MATCH', profile: krakenSpotProfile }// Or: { status: 'AMBIGUOUS', candidates: [...] }// Or: { status: 'NONE' } -> Generic fallbackSignature Matching Rules:
Section titled “Signature Matching Rules:”- Required Headers: Every header in
signature.requiredmust exist in the file. - Forbidden Headers: None of the headers in
signature.forbiddencan be present (prevents a spot profile from accidentally capturing a futures export from the same exchange). - Ambiguity Guard: If multiple profiles match, detection reports ambiguity rather than picking the first array index. This guarantees that adding a new profile can never silently alter how existing files are resolved.