Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ This solution provides a simple starting point for a tool to export on-chain Alg

* [CoinTracker](https://www.cointracker.io/)
* [Koinly](https://koinly.io/)
* [TokenTax](https://tokentax.co/)

CoinTracker has an excellent tax guide if you'd lke more details on the subject: https://www.cointracker.io/blog/crypto-tax-guide

Koinly is an excellent choice as well. There are pros/cons to all of these sites and with varying fees & features. They're worth a look.

TokenTax is another simple and easy to use option, but comes at a cost. The report generated from this tool tracks "Deposits", "Withdrawals" and "Staking" income. Combined with
data one's other wallets/exchanges, TokenTax can show captial gains as well as income received from Algorand staking.

[TOC]

# Requirements
Expand Down Expand Up @@ -535,4 +539,4 @@ Index server to connect to (default "localhost:8980")

Refer back to [Example use](#example-use) for examples of how the program is used.

Enjoy!
Enjoy!
74 changes: 74 additions & 0 deletions exporter/tokentax.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package exporter

import (
"fmt"
"io"
"os"
)

/*
NOTHING HERE IS TAX ADVICE NOR SHOULD BE INTERPRETED AS SUCH.

This TokenTax exporter makes a key classification / assumption:

All transactions are either a Withdrawal, Deposit or Staking reward.
Since we can only see Algo-in / Algo-out, we classify "Algo-in" as a deposit, "Algo-out"
as a withdrawal. Staking rewards are "Staking". If an "Algo-out" transaction is to
a wallet that isn't yours, it'll likely show up in your Tax reporting software
and will likely need to be reclassified from "Withdrawal" -> "Spend". (AGAIN THIS IS NOT
TAX ADVICE NOT SHOULD BE INTERPRETED AS SUCH.)
*/

type TokenTaxExporter struct {
}

func (t TokenTaxExporter) Name() string {
return "tokentax"
}

func (t *TokenTaxExporter) WriteHeader(writer io.Writer) {
header := "Type,BuyAmount,BuyCurrency,SellAmount,SellCurrency,FeeAmount,FeeCurrency,Exchange,Group,Comment,Date"
fmt.Fprintln(writer, header)
}

func (t *TokenTaxExporter) WriteRecord(writer io.Writer, record ExportRecord) {

var transactionType, buyAmt, sellAmt string
if record.reward {
transactionType = "Staking"
buyAmt = algoFmt(record.recvQty)
} else {
// If we have a Buy and Sell Amt, this is a "Trade".
// This program isn't meant to track trades. Since we're just
// tracking down transactions between wallets for tax purposes.
// If you're buying and selling, you're likely using an exchange,
// these exchanges can wire into TokenTax (in this case).
if record.recvQty != 0 && record.sentQty != 0 {
msg := "Detected Buy and Sell qtys, this is likely a trade. This program doesn't support trades right now"
fmt.Println(msg)
os.Exit(1)
} else if record.recvQty != 0 {
transactionType = "Deposit"
buyAmt = algoFmt(record.recvQty)
} else if record.sentQty != 0 {
transactionType = "Withdrawal"
sellAmt = algoFmt(record.sentQty)
}
}
fmt.Fprintf(writer, "%s,", transactionType)
if transactionType == "Deposit" || transactionType == "Staking" {
fmt.Fprintf(writer, "%s,ALGO,,,,,,,,", buyAmt)
} else if transactionType == "Withdrawal" {
fmt.Fprintf(writer, ",,%s,ALGO,,,,,,", sellAmt)
}
// Finally, the date
fmt.Fprintf(writer, "%s UTC\n", record.blockTime.UTC().Format("01/02/2006 15:04"))
}

func NewTokenTaxExporter() Interface {
return &TokenTaxExporter{}
}

func init() {
registerFormat("tokentax", NewTokenTaxExporter)
}
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
github.com/algorand/go-algorand-sdk v1.4.2 h1:xF+Q1ZjuFrRVwzGZ0MQJT22S4CWN65tWYNLef3A9Og4=
github.com/algorand/go-algorand-sdk v1.4.2/go.mod h1:atJEKcxcwxgK7E0N1NfKCUyRUWTpt13vpBry+V+uP1Q=
github.com/algorand/go-algorand-sdk v1.5.1 h1:5THZvMOlfAc+HHRhbV/V89LJC4k0EzhK1mn3oizSt+c=
github.com/algorand/go-algorand-sdk v1.5.1/go.mod h1:U12d8fTN/CyKPR1HObrt51ITxb6OgXxpGCH743Ds2GQ=
github.com/algorand/go-codec v1.1.7 h1:6nvCh2nfgnfkaoVHKQyk2wxyl2GQBAlI7IkbqbB/e4s=
github.com/algorand/go-codec v1.1.7/go.mod h1:pVLQYhIVCsx9D3iy4W4Qqi0SKhx6IVhMwOvj/agFL4g=
github.com/algorand/go-codec/codec v1.1.7 h1:EFOyWf5duxbh2ru+AW1YDgmZ+MRVgqklELSqTArgp3M=
Expand All @@ -10,6 +12,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down