Collecting crypto tax reports is a process where every transaction can become a source of error. A trader with a portfolio of 2000+ deals on five exchanges spends weeks on manual reconciliation, and the risk of misclassifying an event (e.g., swap vs staking) can lead to overpaying taxes or penalties. In the US, the average fine for incorrect reporting is about $2000 per Form 8949. We automate collection, classification, and calculation, turning months of manual work into hours of system operation. The system processes up to 5000 transactions per second — 20 times faster than manual entry. Additionally, the system accounts for legislative changes in different countries and updates rules automatically.
Why automation beats manual calculation?
Crypto events come in various types: sale, exchange, interest income, mining, staking, hard fork. Each is treated differently depending on the country. For example, in Germany, staking income up to €256 per year is tax-exempt, but only if it's "other income". In the US, a crypto-to-crypto swap is a taxable event, while in the UK it's a capital gain. Manually tracking all nuances is nearly impossible. According to IRS Notice, cryptocurrency is recognized as property, so each realization is a taxable event.
What tax events does the system recognize?
| Event Type | US | UK | Germany |
|---|---|---|---|
| swap | capital_gain | capital_gain | capital_gain (exempt after 1 year) |
| staking_reward | ordinary_income | miscellaneous_income | other_income (up to €256/year) |
| airdrop | ordinary_income (if tradable) | capital_gain (not income) | – |
The code below shows the configuration for different jurisdictions — easily extensible by adding a new object.
const TAX_TREATMENT: Record<string, Record<string, TaxTreatment>> = {
US: {
swap: { type: "capital_gain", description: "Crypto-to-crypto swap is taxable disposal" },
staking_reward: { type: "ordinary_income", description: "Taxable when received (FMV)" },
mining_reward: { type: "ordinary_income" },
airdrop: { type: "ordinary_income", description: "If can be freely traded" },
hard_fork: { type: "ordinary_income" },
nft_sale: { type: "capital_gain" },
defi_liquidity: { type: "complex", description: "Depends on structure" },
},
UK: {
swap: { type: "capital_gain" },
staking_reward: { type: "miscellaneous_income" },
mining_reward: { type: "trading_income_or_miscellaneous" },
airdrop: { type: "capital_gain", description: "Not income unless received for service" },
},
DE: {
swap: { type: "capital_gain", exemptAfterHolding: 365 },
staking_reward: { type: "other_income", exemptAmount: 256 },
mining_reward: { type: "business_income" },
},
};
How does the system calculate tax liability?
We built an engine in TypeScript that sequentially processes events, determines cost basis, and applies progressive rates. Here's a simplified implementation:
class TaxCalculationEngine {
async calculateTaxYear(
userId: string,
taxYear: number,
jurisdiction: string,
method: CostBasisMethod
): Promise<TaxYearSummary> {
const events = await this.db.getTaxEvents(userId, taxYear);
const jurisdictionRules = TAX_TREATMENT[jurisdiction];
let shortTermGains = 0;
let longTermGains = 0;
let ordinaryIncome = 0;
const processedEvents: ProcessedTaxEvent[] = [];
for (const event of events) {
const treatment = jurisdictionRules[event.type];
if (!treatment) continue;
if (treatment.type === "capital_gain") {
const { costBasis, isLongTerm } = await this.getCostBasis(
userId, event, method, jurisdiction
);
const gain = event.proceedsUSD - costBasis;
if (treatment.exemptAfterHolding && isLongTerm) {
processedEvents.push({ ...event, gain, tax: 0, reason: "exempt_long_term" });
continue;
}
if (isLongTerm) longTermGains += gain;
else shortTermGains += gain;
processedEvents.push({ ...event, costBasis, gain, isLongTerm });
} else if (treatment.type === "ordinary_income" || treatment.type === "miscellaneous_income") {
const income = event.usdValueAtReceipt;
ordinaryIncome += income;
processedEvents.push({ ...event, income });
}
}
const taxLiability = this.applyTaxRates(
jurisdiction, taxYear, shortTermGains, longTermGains, ordinaryIncome
);
return {
taxYear,
jurisdiction,
method,
shortTermGains,
longTermGains,
ordinaryIncome,
taxLiability,
events: processedEvents,
};
}
private applyTaxRates(
jurisdiction: string,
year: number,
shortTerm: number,
longTerm: number,
income: number
): TaxLiability {
const rates = TAX_RATES[jurisdiction][year];
switch (jurisdiction) {
case "US":
return {
shortTermTax: shortTerm > 0 ? shortTerm * rates.shortTermRate : 0,
longTermTax: longTerm > 0 ? this.calculateLTCGTax(longTerm, rates) : 0,
incomeTax: income * rates.ordinaryRate,
};
case "DE":
const capitalGains = shortTerm + longTerm;
return {
capitalGainsTax: capitalGains > 0 ? capitalGains * 0.25 * 1.055 : 0,
incomeTax: income * rates.incomeRate,
};
default:
return { estimatedTax: (shortTerm + longTerm + income) * 0.2 };
}
}
}
How to optimize taxes with the system?
The system offers tax-loss harvesting — selling assets at a loss to offset gains. In the code below, we find losses over $100 and estimate savings:
async function identifyTaxLossHarvestingOpportunities(
userId: string,
currentYear: number
): Promise<HarvestingOpportunity[]> {
const currentGains = await calculateYTDGains(userId, currentYear);
const openPositions = await getOpenPositions(userId);
const opportunities: HarvestingOpportunity[] = [];
for (const position of openPositions) {
const currentValue = await getCurrentValue(position);
const unrealizedLoss = currentValue - position.costBasis;
if (unrealizedLoss < -100) {
opportunities.push({
asset: position.asset,
amount: position.amount,
costBasis: position.costBasis,
currentValue,
potentialLoss: unrealizedLoss,
taxSavings: Math.abs(unrealizedLoss) * getEffectiveTaxRate(userId),
washSaleRisk: await checkWashSaleRule(userId, position.asset),
});
}
}
return opportunities.sort((a, b) => b.taxSavings - a.taxSavings);
}
This approach can reduce the tax burden by 15–30% annually (based on our projects). Compared to manual calculation, automation speeds up processing by 10 times and nearly eliminates errors from misclassification. For more on tax-loss harvesting, see Wikipedia.
Real-world case: a trader with 5000 transactions on Coinbase and Binance. After integrating exchange APIs, the system processed all events in 2 minutes, automatically classified 98%, the remaining 2% required manual review. Cost basis calculated with FIFO method, final tax reduced by 22% thanks to tax-loss harvesting. PDF report generated in 1 second.
Our work process
- Analysis — collect all crypto events, exchanges, wallets, legal requirements. Determine priority jurisdictions.
- Design — choose architecture: monolith or microservices. Design ER diagram, API, admin interface.
- Implementation — develop modules for classification, cost basis, calculation, optimization. Use TypeScript, PostgreSQL, Redis, Tenderly for on-chain testing.
- Testing — unit and integration tests on real data. Compare with manual calculation on 1000+ transactions.
- Deployment and training — deploy in your cloud or on-premise. Hand over documentation and train your team.
What is included in the turnkey solution?
| Component | Description |
|---|---|
| Event classification module | Recognizes 12+ transaction types |
| Cost basis engine | Supports FIFO, LIFO, identified lots |
| Jurisdiction configurator | JSON file with rules for US, UK, DE, AU |
| Dashboard interface | Filters, CSV/PDF export, charts |
| API for integration | REST/GraphQL, webhooks |
| Documentation | Architecture description, extension instructions |
| 3 months support | Consultation on configuration updates |
What stack and timeline?
We use Node.js + TypeScript, PostgreSQL, Redis, Tenderly for testing. The system is easily deployed in Docker/K8s. Development time: 3 to 5 weeks depending on the number of jurisdictions and integrations. We provide an estimate within 2 days after receiving the brief.
Experience: 5 years developing financial solutions for blockchain, over 20 successful projects. We guarantee confidentiality and compliance with security standards.
Order a preliminary assessment of your project — we'll share details and prepare a commercial proposal. Get a consultation for your project today.







