Розробка системи обліку стейкінг-нагород для податків

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка системи обліку стейкінг-нагород для податків
Середній
~3-5 днів
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1285
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    902
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1122
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    859

Система обліку стейкинг-нагород для податків

Стейкинг-нагороди — одне з найспірніших питань крипто-оподаткування. У США IRS (Rev. Rul. 2023-14) офіційно підтвердив: стейкинг-нагороди — звичайний дохід при отриманні за справедливою ринковою вартістю. У Німеччині — інша трактовка. Система повинна враховувати юрисдикційні відмінності.

Типи стейкингу та їхня податкова трактовка

const STAKING_TAX_TREATMENT: Record<string, StakingTaxRule> = {
  NATIVE_STAKING: {
    // ETH 2.0, SOL, ADA — прямий стейкинг в мережі
    US: { type: "ordinary_income", timing: "on_receipt" },
    DE: { type: "other_income", timing: "on_receipt", annualExempt: 256 },
    UK: { type: "miscellaneous_income", timing: "on_receipt" },
  },
  LIQUID_STAKING: {
    // stETH, rETH, mSOL — отримуєш liquid токен
    // Спірно: чи є отримання stETH opodatkovia?
    US: { type: "unknown", note: "IRS не висловився явно" },
    DE: { type: "non_taxable", note: "своп розглядається як продовження" },
  },
  REBASING: {
    // stETH rebasing — баланс збільшується, не окремі транзакції нагород
    US: { type: "ordinary_income", timing: "on_receipt", challenge: "hard_to_track" },
  },
  VALIDATOR_REWARDS: {
    // Оператори ETH validator — у деяких трактуваннях business income
    US: { type: "business_income_or_ordinary_income" },
  },
};

Відстеження стейкинг-нагород

class StakingRewardTracker {
  // Ethereum стейкинг через Lido
  async trackLidoRewards(walletAddress: string, since: Date): Promise<StakingReward[]> {
    // stETH використовує rebasing — баланс оновлюється щодня
    // Потрібні snapshots на кожний rebase
    
    const rebaseEvents = await this.getLidoRebaseEvents(since);
    const rewards: StakingReward[] = [];
    
    let previousBalance = await this.getStETHBalance(walletAddress, since);
    
    for (const rebase of rebaseEvents) {
      const newBalance = await this.getStETHBalance(walletAddress, rebase.timestamp);
      const rewardAmount = newBalance - previousBalance;
      
      if (rewardAmount > 0) {
        const ethPrice = await this.priceService.getHistoricalPrice("stETH", rebase.timestamp);
        
        rewards.push({
          timestamp: rebase.timestamp,
          protocol: "Lido",
          asset: "stETH",
          amount: rewardAmount,
          usdValue: rewardAmount * ethPrice,
          rewardType: "REBASING",
          costBasis: rewardAmount * ethPrice, // cost basis = FMV при отриманні
        });
      }
      
      previousBalance = newBalance;
    }
    
    return rewards;
  }
  
  // Ethereum 2.0 validator нагороди
  async trackETH2ValidatorRewards(validatorIndex: number, since: Date): Promise<StakingReward[]> {
    const beaconChainData = await fetch(
      `https://beaconcha.in/api/v1/validator/${validatorIndex}/incomedetail?limit=100`
    ).then(r => r.json());
    
    return beaconChainData.data
      .filter((r: any) => new Date(r.epoch_timestamp) >= since)
      .map(async (r: any) => {
        const timestamp = new Date(r.epoch_timestamp);
        const ethPrice = await this.priceService.getHistoricalPrice("ETH", timestamp);
        const rewardETH = r.income.attestation_source_reward / 1e9; // gwei → ETH
        
        return {
          timestamp,
          protocol: "Ethereum 2.0 Validator",
          asset: "ETH",
          amount: rewardETH,
          usdValue: rewardETH * ethPrice,
          validatorIndex,
          epoch: r.epoch,
        };
      });
  }
  
  // Solana стейкинг нагороди
  async trackSolanaRewards(walletAddress: string, since: Date): Promise<StakingReward[]> {
    // Використовуємо Solana RPC getInflationReward
    const connection = new Connection(SOLANA_RPC);
    
    const rewardHistory = await connection.getInflationReward(
      [walletAddress],
      { epoch: await this.getEpochSince(since) }
    );
    
    return rewardHistory.map(r => ({
      timestamp: epochToTimestamp(r.epoch),
      protocol: "Solana Staking",
      asset: "SOL",
      amount: r.amount / 1e9, // lamports → SOL
      usdValue: (r.amount / 1e9) * solPriceAtEpoch,
    }));
  }
}

Зведена звітність по стейкингу

async function generateStakingTaxReport(
  userId: string,
  taxYear: number,
  jurisdiction: string
): Promise<StakingTaxReport> {
  const rewards = await db.getStakingRewards(userId, taxYear);
  
  // Групуємо за протоколом та місяцем
  const byProtocol = groupBy(rewards, r => r.protocol);
  const monthly = groupByMonth(rewards);
  
  const totalIncome = rewards.reduce((sum, r) => sum + r.usdValue, 0);
  
  // Для Німеччини: перевіряємо Freigrenze €256
  const taxableAmount = jurisdiction === "DE"
    ? Math.max(0, totalIncome - 256)
    : totalIncome;
  
  return {
    taxYear,
    jurisdiction,
    totalRewardsUSD: totalIncome,
    taxableAmountUSD: taxableAmount,
    byProtocol: Object.entries(byProtocol).map(([protocol, rewards]) => ({
      protocol,
      totalRewards: rewards.reduce((sum, r) => sum + r.amount, 0),
      totalUSD: rewards.reduce((sum, r) => sum + r.usdValue, 0),
    })),
    monthlyBreakdown: monthly,
    rewards: rewards.map(r => ({
      ...r,
      costBasisForFutureDisposal: r.usdValue, // cost basis = значення доходу
    })),
  };
}

Особливість: cost basis при майбутньому продажу

Важливий момент: стейкинг-нагорода отримана та включена в звичайний дохід створює cost basis для майбутнього продажу. Система повинна створити tax lot:

// При обліку стейкинг-нагороди — створюємо lot
await db.createTaxLot({
  userId,
  asset: reward.asset,
  amount: reward.amount,
  costPerUnitUSD: reward.usdValue / reward.amount,
  totalCostUSD: reward.usdValue,
  acquiredAt: reward.timestamp,
  source: "staking_reward",
  acquisitionType: "INCOME", // розрізняємо від звичайної покупки
});

Система обліку стейкинг-нагород з підтримкою Lido, ETH2 validator, Solana, Cosmos — 3-4 тижні розробки.