diff --git a/api/api.go b/api/api.go index d894469..f5cb51b 100644 --- a/api/api.go +++ b/api/api.go @@ -32,8 +32,9 @@ type TxpoolTransactionsResponse struct { // WalletBalanceResponse is the response type for /wallets/:name/balance. type WalletBalanceResponse struct { - Siacoins types.Currency `json:"siacoins"` - Siafunds uint64 `json:"siafunds"` + Siacoins types.Currency `json:"siacoins"` + ImmatureSiacoins types.Currency `json:"immatureSiacoins"` + Siafunds uint64 `json:"siafunds"` } // WalletOutputsResponse is the response type for /wallets/:name/outputs. diff --git a/api/server.go b/api/server.go index 83321ea..46e770a 100644 --- a/api/server.go +++ b/api/server.go @@ -236,17 +236,23 @@ func (s *server) walletsBalanceHandler(jc jape.Context) { if jc.Check("couldn't load outputs", err) != nil { return } - var sc types.Currency + height := s.cm.TipState().Index.Height + var sc, immature types.Currency var sf uint64 for _, sco := range scos { - sc = sc.Add(sco.SiacoinOutput.Value) + if height >= sco.MaturityHeight { + sc = sc.Add(sco.SiacoinOutput.Value) + } else { + immature = immature.Add(sco.SiacoinOutput.Value) + } } for _, sfo := range sfos { sf += sfo.SiafundOutput.Value } jc.Encode(WalletBalanceResponse{ - Siacoins: sc, - Siafunds: sf, + Siacoins: sc, + ImmatureSiacoins: immature, + Siafunds: sf, }) } diff --git a/cmd/walletd/main.go b/cmd/walletd/main.go index fb03ce8..ec506c4 100644 --- a/cmd/walletd/main.go +++ b/cmd/walletd/main.go @@ -217,7 +217,19 @@ func main() { c := initTestnetClient(apiAddr, network, seed) b, err := c.Wallet("primary").Balance() check("Couldn't get balance:", err) - fmt.Println(b.Siacoins) + out := fmt.Sprint(b.Siacoins) + if !b.ImmatureSiacoins.IsZero() { + out += fmt.Sprintf(" + %v immature", b.ImmatureSiacoins) + } + poolGained, poolLost := testnetTxpoolBalance(c, seed) + if !poolGained.IsZero() || !poolLost.IsZero() { + if poolGained.Cmp(poolLost) >= 0 { + out += fmt.Sprintf(" + %v unconfirmed", poolGained.Sub(poolLost)) + } else { + out += fmt.Sprintf(" - %v unconfirmed", poolLost.Sub(poolGained)) + } + } + fmt.Println(out) case sendCmd: if len(cmd.Args()) != 2 { diff --git a/cmd/walletd/testnet.go b/cmd/walletd/testnet.go index c2bda51..d19e667 100644 --- a/cmd/walletd/testnet.go +++ b/cmd/walletd/testnet.go @@ -316,6 +316,35 @@ func printTestnetEvents(c *api.Client, seed wallet.Seed) { } } +func testnetTxpoolBalance(c *api.Client, seed wallet.Seed) (gained, lost types.Currency) { + ourAddr := types.StandardUnlockHash(seed.PublicKey(0)) + txns, v2txns, err := c.TxpoolTransactions() + check("Couldn't get txpool transactions:", err) + for _, txn := range txns { + if len(txn.SiacoinInputs) == 0 || len(txn.SiacoinOutputs) == 0 { + continue + } + sco := txn.SiacoinOutputs[0] + if txn.SiacoinInputs[0].UnlockConditions.UnlockHash() == ourAddr { + lost = lost.Add(sco.Value) + } else if sco.Address == ourAddr { + gained = gained.Add(sco.Value) + } + } + for _, txn := range v2txns { + if len(txn.SiacoinInputs) == 0 || len(txn.SiacoinOutputs) == 0 { + continue + } + sco := txn.SiacoinOutputs[0] + if txn.SiacoinInputs[0].Parent.SiacoinOutput.Address == ourAddr { + lost = lost.Add(sco.Value) + } else if sco.Address == ourAddr { + gained = gained.Add(sco.Value) + } + } + return +} + func printTestnetTxpool(c *api.Client, seed wallet.Seed) { ourAddr := types.StandardUnlockHash(seed.PublicKey(0)) txns, v2txns, err := c.TxpoolTransactions()