taxapi

package
v0.0.0-...-b543e46 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 1, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package taxapi serves taxable-event queries + exports (CSV for the major tax platforms, plus a basic IRS 8949) over the data the tax indexer writes, enriched with USD pricing + denom resolution from the wasm-indexer oracle.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func UpsertBalanceSnapshot

func UpsertBalanceSnapshot(db *gorm.DB, s *BalanceSnapshot) error

UpsertBalanceSnapshot writes (or replaces) the snapshot for an address+date.

func Write8949CSV

func Write8949CSV(out io.Writer, rows []Form8949Row) error

Write8949CSV writes the 8949 rows, short-term first then long-term, matching the Part I / Part II split.

func WriteCSV

func WriteCSV(out io.Writer, format string, rows []Row) error

WriteCSV writes rows in the requested platform format.

Types

type BalanceSnapshot

type BalanceSnapshot struct {
	ID      uint
	Address string    `gorm:"index:idx_bal_addr_date,priority:1,unique"`
	Date    time.Time `gorm:"index:idx_bal_addr_date,priority:2,unique"`
	Liquid  float64   // spendable bank balance
	Staked  float64   // bonded delegations
	Reward  float64   // unclaimed staking rewards
	Height  int64
}

BalanceSnapshot is a point-in-time (daily) record of an address's ATOM holdings, captured live from the node so historical lookups don't need a node. Amounts are in ATOM (already divided by 1e6). One row per (address, date). (Ported from the legacy cosmos-tax-cli so the SDK can fully replace it.)

func GetBalanceSnapshotAsOf

func GetBalanceSnapshotAsOf(db *gorm.DB, address string, asOf time.Time) (BalanceSnapshot, bool)

GetBalanceSnapshotAsOf returns the most recent snapshot at or before asOf (the holdings "as of" that date), or the latest if asOf is zero. False if none.

func GetBalanceSnapshotHistory

func GetBalanceSnapshotHistory(db *gorm.DB, address string) []BalanceSnapshot

GetBalanceSnapshotHistory returns all snapshots for an address ordered by date.

type CoverageReport

type CoverageReport struct {
	Start            string        `json:"start"`
	End              string        `json:"end"`
	TotalMessages    int64         `json:"total_messages"`
	ClassifiedMsgs   int64         `json:"classified_messages"`
	CoveragePercent  float64       `json:"coverage_percent"`
	SupportedTypes   int           `json:"supported_types_seen"`
	UnsupportedTypes int           `json:"unsupported_types_seen"`
	Rows             []CoverageRow `json:"rows"`
	// Gaps are types that appeared on chain but the parser does not handle —
	// the explicit "here is what we are NOT yet reporting" list.
	Gaps []CoverageRow `json:"gaps"`
}

CoverageReport is the reconciliation summary an enterprise user needs to trust that every taxable event has been accounted for: it lists every message type seen on chain in the range, how many we classified, and which types are gaps (seen but unsupported, e.g. CosmWasm MsgExecuteContract).

type CoverageRow

type CoverageRow struct {
	MessageType  string `json:"message_type"`
	Total        int64  `json:"total"`        // messages of this type in range
	Classified   int64  `json:"classified"`   // of those, how many produced a taxable event
	Supported    bool   `json:"supported"`    // is this type handled by the parser at all
	Unclassified int64  `json:"unclassified"` // Total - Classified
}

CoverageRow is per-message-type coverage over a block range.

type DenomMeta

type DenomMeta struct {
	Symbol   string
	Decimals int
}

DenomMeta is the symbol + decimals for a base denom, from the oracle's /denoms endpoint (chain-registry + scraped IBC traces).

type Form990T

type Form990T struct {
	StakingIncomeUSD  string `json:"staking_income_usd"` // gross UBTI
	SpecificDeduction string `json:"specific_deduction"`
	TaxableUBTI       string `json:"taxable_ubti_usd"`
	EstimatedTaxUSD   string `json:"estimated_tax_usd"`
	FilingRequired    bool   `json:"filing_required"` // gross UBTI >= $1,000
	Note              string `json:"note"`
}

Form990T is the UBIT summary for an entity's staking income.

type Form8949Row

type Form8949Row struct {
	Description  string // e.g. "1.5 ATOM"
	DateAcquired string // MM/DD/YYYY or "Various"
	DateSold     string // MM/DD/YYYY
	Proceeds     decimal.Decimal
	CostBasis    decimal.Decimal
	GainLoss     decimal.Decimal
	LongTerm     bool
}

Form8949Row is one disposal line for IRS Form 8949 (Sales and Other Dispositions of Capital Assets).

func Build8949

func Build8949(rows []Row) []Form8949Row

Build8949 runs a per-asset FIFO over the priced rows and emits one 8949 line per disposal lot consumed. NOTE: this is a basic engine — cost basis for units acquired before the queried window is unknown (treated as 0 / "Various"); accurate basis needs full acquisition history (archive-node indexing).

NFT marketplace sales (Category "nft_sale") are treated as dispositions of the non-fungible asset itself, NOT of the ATOM that changed hands: a buy (in) establishes the NFT's USD cost basis, a sell (out) is a capital disposal with proceeds = the sale's USD value. (The ATOM leg of an NFT trade is a separate, second-order disposal not yet modeled; the headline NFT gain/loss is.)

type Oracle

type Oracle struct {
	// contains filtered or unexported fields
}

Oracle is a thin client for the wasm-indexer price/denom API.

func NewOracle

func NewOracle(base string) *Oracle

func (*Oracle) Denoms

func (o *Oracle) Denoms(chain string) map[string]DenomMeta

Denoms returns the chain's denom->meta map, cached for 1h.

func (*Oracle) PriceAt

func (o *Oracle) PriceAt(chain, denom, date string) (float64, bool)

PriceAt returns the USD price for a denom on (or most recently before) a date (YYYY-MM-DD). found=false when the oracle has no price.

type Row

type Row struct {
	Time      time.Time
	Category  string // transfer | reward | commission | ibc_in | ibc_out | fee
	Direction string // in | out
	Symbol    string
	Denom     string
	Amount    decimal.Decimal // display units (for nft_sale: the sale price in Denom)
	PriceUSD  decimal.Decimal // per unit at the event date (0 if unknown)
	ValueUSD  decimal.Decimal // Amount * PriceUSD
	From      string
	To        string
	TxHash    string
	Asset     string // non-fungible asset id "<collection>/<token_id>" for nft_sale
	IsIBC     bool   // true when Denom is an IBC trace path (Symbol is the resolved base)
}

Row is a normalized, priced taxable event from the queried address's point of view (Direction = in|out). Platform exporters map this to their columns.

type ScheduleD

type ScheduleD struct {
	ShortTermProceeds  decimal.Decimal `json:"short_term_proceeds"`
	ShortTermCostBasis decimal.Decimal `json:"short_term_cost_basis"`
	ShortTermGainLoss  decimal.Decimal `json:"short_term_gain_loss"` // Schedule D line 7
	LongTermProceeds   decimal.Decimal `json:"long_term_proceeds"`
	LongTermCostBasis  decimal.Decimal `json:"long_term_cost_basis"`
	LongTermGainLoss   decimal.Decimal `json:"long_term_gain_loss"` // Schedule D line 15
	NetGainLoss        decimal.Decimal `json:"net_gain_loss"`       // Schedule D line 16
}

ScheduleD is the capital-gains summary that the 8949 totals flow into on IRS Schedule D (Form 1040). Short-term and long-term are taxed differently, so they stay separate; Net is line 16 (overall capital gain or loss).

func BuildScheduleD

func BuildScheduleD(rows []Form8949Row) ScheduleD

BuildScheduleD rolls up 8949 lines into the Schedule D short/long-term totals.

type Server

type Server struct {
	// contains filtered or unexported fields
}

func NewServer

func NewServer(db *gorm.DB, oracle *Oracle) *Server

func (*Server) Handler

func (s *Server) Handler() http.Handler

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL