Skip to content

Commit

Permalink
[TX] add utxo functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Bozhytskyi committed Jul 2, 2021
1 parent 8a60c4c commit 09b9773
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 0 deletions.
46 changes: 46 additions & 0 deletions types/v1/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,52 @@ func (t *Tx) determineTransactionDirection(address, from, to string) Direction {
return DirectionOutgoing
}

func (t *Tx) IsUTXO() bool {
return t.Type == TxTransfer && len(t.Outputs) > 0
}

func (t *Tx) GetUTXOValueFor(address string) (Amount, error) {
isTransferOut := false

var totalInputValue uint64
var addressInputValue uint64
for _, input := range t.Inputs {
value, err := strconv.ParseUint(string(input.Value), 10, 64)
if err != nil {
return "0", fmt.Errorf("input value for address %s: %v", input.Address, err)
}

totalInputValue += value

if input.Address == address {
addressInputValue = value
isTransferOut = true
}
}

var addressOutputValue uint64
var totalOutputValue uint64
for _, output := range t.Outputs {
value, err := strconv.ParseUint(string(output.Value), 10, 64)
if err != nil {
return "0", fmt.Errorf("output value for address %s: %v", output.Address, err)
}
totalOutputValue += value
if output.Address == address {
addressOutputValue = value
}
}

var result uint64
if isTransferOut {
result = addressInputValue - (totalInputValue-totalOutputValue)/uint64(len(t.Inputs)) - addressOutputValue
} else {
result = addressOutputValue
}

return Amount(fmt.Sprintf("%d", result)), nil
}

func InferDirection(tx *Tx, addressSet mapset.Set) Direction {
inputSet := mapset.NewSet()
for _, address := range tx.Inputs {
Expand Down
70 changes: 70 additions & 0 deletions types/v1/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,3 +368,73 @@ func TestTx_GetDirection(t *testing.T) {
}

}

func TestUTXOValueByAddress(t *testing.T) {
tests := []struct {
name string
tx Tx
address string
expected Amount
expectedErrAssertion assert.ErrorAssertionFunc
}{
{
name: "transfer_self",
tx: Tx{
Inputs: []TxOutput{{
Address: "addr",
Value: "1000",
}},
Outputs: []TxOutput{{
Address: "addr",
Value: "1000",
}},
},
address: "addr",
expected: "0",
expectedErrAssertion: assert.NoError,
},
{
name: "transfer_in",
tx: Tx{
Outputs: []TxOutput{{
Address: "addr",
Value: "1000",
}},
},
address: "addr",
expected: "1000",
expectedErrAssertion: assert.NoError,
},
{
name: "transfer_out_with_utxo",
tx: Tx{
Inputs: []TxOutput{{
Address: "addr",
Value: "1000",
}},
Outputs: []TxOutput{
{
Address: "addr",
Value: "100",
},
{
Address: "addr1",
Value: "800",
},
},
},
address: "addr",
expected: "800",
expectedErrAssertion: assert.NoError,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result, err := tc.tx.GetUTXOValueFor(tc.address)
tc.expectedErrAssertion(t, err)

assert.Equal(t, tc.expected, result)
})
}
}

0 comments on commit 09b9773

Please sign in to comment.