diff --git a/.gitignore b/.gitignore index fb777b06e..dab2a68b5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ dcrwallet vendor *~ .vscode +.idea/ diff --git a/internal/rpchelp/helpdescs_en_US.go b/internal/rpchelp/helpdescs_en_US.go index 2a7a38261..62e8d8975 100644 --- a/internal/rpchelp/helpdescs_en_US.go +++ b/internal/rpchelp/helpdescs_en_US.go @@ -324,6 +324,36 @@ var helpDescsEnUS = map[string]string{ "listsinceblockresult-transactions": "JSON array of objects containing verbose details of the each transaction", "listsinceblockresult-lastblock": "Hash of the latest-synced block to be used in later calls to listsinceblock", + // ListTicketCmd help. + "listtickets--synopsis": "List all ticket details with related spender and state info", + + // ListTicketsResult help. + "listticketsresult-status": "Status of ticket", + "listticketsresult-ticket": "Ticket tx details", + "listticketsresult-spender": "Spender tx details", + + // ListTicketsTransactionSummary + "listticketstransactionsummary-type": "Lists all tickets, including unmined tickets", + "listticketstransactionsummary-hash": "Hash of the transaction", + "listticketstransactionsummary-transaction": "Serialized string of the transaction", + "listticketstransactionsummary-myinputs": "Inputs of tx details", + "listticketstransactionsummary-myoutputs": "Outputs of tx details", + "listticketstransactionsummary-fee": "Total input value minus the total output value for sent transactions", + "listticketstransactionsummary-timestamp": "Timestamp of tx", + + // ListTicketsTransactionSummaryInput + "listticketstransactionsummaryinput-index": "Index of input in list of all tx inputs", + "listticketstransactionsummaryinput-previousaccount": "Input account", + "listticketstransactionsummaryinput-previousamount": "Input amount", + + // ListTicketsTransactionSummaryOutput + "listticketstransactionsummaryoutput-index": "Index of input in list of all tx outputs", + "listticketstransactionsummaryoutput-account": "Output account", + "listticketstransactionsummaryoutput-internal": "Flag if address was create for internal use", + "listticketstransactionsummaryoutput-amount": "Output amount", + "listticketstransactionsummaryoutput-address": "Address receiving amount", + "listticketstransactionsummaryoutput-outputscript": "Pkscript to receive amount", + // ListTransactionsResult help. "listtransactionsresult-account": "DEPRECATED -- Unset", "listtransactionsresult-address": "Payment address for a transaction output", @@ -688,6 +718,7 @@ var helpDescsEnUS = map[string]string{ "purchaseticket-nosplittransaction": "Use ticket purchase change outputs instead of a split transaction", "purchaseticket-comment": "Unused", "purchaseticket-ticketfee": "The transaction fee rate (DCR/kB) to use (overrides fees set by the wallet config or settxfee RPC)", + "purchaseticket-ticketchange": "Currently unused", // SetTicketFeeCmd help. "setticketfee--synopsis": "Modify the fee per kB of the serialized tx size used each time more fee is required for an authored stake transaction.", diff --git a/internal/rpchelp/methods.go b/internal/rpchelp/methods.go index 010b48258..f21e26bd8 100644 --- a/internal/rpchelp/methods.go +++ b/internal/rpchelp/methods.go @@ -67,6 +67,7 @@ var Methods = []struct { {"listreceivedbyaddress", []interface{}{(*[]dcrjson.ListReceivedByAddressResult)(nil)}}, {"listscripts", []interface{}{(*dcrjson.ListScriptsResult)(nil)}}, {"listsinceblock", []interface{}{(*dcrjson.ListSinceBlockResult)(nil)}}, + {"listtickets", []interface{}{(*dcrjson.ListTicketsResult)(nil)}}, {"listtransactions", returnsLTRArray}, {"listunspent", []interface{}{(*dcrjson.ListUnspentResult)(nil)}}, {"lockunspent", returnsBool}, diff --git a/rpc/legacyrpc/methods.go b/rpc/legacyrpc/methods.go index a39b8724a..765715522 100644 --- a/rpc/legacyrpc/methods.go +++ b/rpc/legacyrpc/methods.go @@ -98,6 +98,7 @@ var handlers = map[string]handler{ "listreceivedbyaddress": {fn: listReceivedByAddress}, "listsinceblock": {fn: listSinceBlock}, "listscripts": {fn: listScripts}, + "listtickets": {fn: listTickets}, "listtransactions": {fn: listTransactions}, "listunspent": {fn: listUnspent}, "lockunspent": {fn: lockUnspent}, @@ -1701,6 +1702,30 @@ func listAccounts(s *Server, icmd interface{}) (interface{}, error) { return accountBalances, nil } +// listTickets handles a listtickets request by returning a list +// of tickets containing ticket, spender details and state +func listTickets(s *Server, icmd interface{}) (interface{}, error) { + w, ok := s.walletLoader.LoadedWallet() + if !ok { + return nil, errUnloadedWallet + } + + var chainClient *rpcclient.Client + if n, ok := s.walletLoader.NetworkBackend(); ok { + client, err := chain.RPCClientFromBackend(n) + if err == nil { + chainClient = client + } + } + + tickets, err := w.ListTickets(chainClient) + if err != nil { + return nil, err + } + + return tickets, nil +} + // listLockUnspent handles a listlockunspent request by returning an slice of // all locked outpoints. func listLockUnspent(s *Server, icmd interface{}) (interface{}, error) { diff --git a/rpc/legacyrpc/rpcserverhelp.go b/rpc/legacyrpc/rpcserverhelp.go index 01bd65105..49d39bbd0 100644 --- a/rpc/legacyrpc/rpcserverhelp.go +++ b/rpc/legacyrpc/rpcserverhelp.go @@ -47,6 +47,7 @@ func helpDescsEnUS() map[string]string { "listreceivedbyaddress": "listreceivedbyaddress (minconf=1 includeempty=false includewatchonly=false)\n\nReturns a JSON array of objects listing wallet payment addresses and their total received amounts.\n\nArguments:\n1. minconf (numeric, optional, default=1) Minimum number of block confirmations required before a transaction is considered\n2. includeempty (boolean, optional, default=false) Unused\n3. includewatchonly (boolean, optional, default=false) Unused\n\nResult:\n[{\n \"account\": \"value\", (string) DEPRECATED -- Unset\n \"address\": \"value\", (string) The payment address\n \"amount\": n.nnn, (numeric) Total amount received by the payment address valued in decred\n \"confirmations\": n, (numeric) Number of block confirmations of the most recent transaction relevant to the address\n \"txids\": [\"value\",...], (array of string) Transaction hashes of all transactions involving this address\n \"involvesWatchonly\": true|false, (boolean) Unset\n},...]\n", "listscripts": "listscripts\n\nList all scripts that have been added to wallet\n\nArguments:\nNone\n\nResult:\n{\n \"scripts\": [{ (array of object) A list of the imported scripts\n \"hash160\": \"value\", (string) The script hash\n \"address\": \"value\", (string) The script address\n \"redeemscript\": \"value\", (string) The redeem script\n },...], \n} \n", "listsinceblock": "listsinceblock (\"blockhash\" targetconfirmations=1 includewatchonly=false)\n\nReturns a JSON array of objects listing details of all wallet transactions after some block.\n\nArguments:\n1. blockhash (string, optional) Hash of the parent block of the first block to consider transactions from, or unset to list all transactions\n2. targetconfirmations (numeric, optional, default=1) Minimum number of block confirmations of the last block in the result object. Must be 1 or greater. Note: The transactions array in the result object is not affected by this parameter\n3. includewatchonly (boolean, optional, default=false) Unused\n\nResult:\n{\n \"transactions\": [{ (array of object) JSON array of objects containing verbose details of the each transaction\n \"account\": \"value\", (string) DEPRECATED -- Unset\n \"address\": \"value\", (string) Payment address for a transaction output\n \"amount\": n.nnn, (numeric) The value of the transaction output valued in decred\n \"blockhash\": \"value\", (string) The hash of the block this transaction is mined in, or the empty string if unmined\n \"blockindex\": n, (numeric) Unset\n \"blocktime\": n, (numeric) The Unix time of the block header this transaction is mined in, or 0 if unmined\n \"category\": \"value\", (string) The kind of transaction: \"send\" for sent transactions, \"immature\" for immature coinbase outputs, \"generate\" for mature coinbase outputs, or \"recv\" for all other received outputs. Note: A single output may be included multiple times under different categories\n \"confirmations\": n, (numeric) The number of block confirmations of the transaction\n \"fee\": n.nnn, (numeric) The total input value minus the total output value for sent transactions\n \"generated\": true|false, (boolean) Whether the transaction output is a coinbase output\n \"involveswatchonly\": true|false, (boolean) Unset\n \"time\": n, (numeric) The earliest Unix time this transaction was known to exist\n \"timereceived\": n, (numeric) The earliest Unix time this transaction was known to exist\n \"txid\": \"value\", (string) The hash of the transaction\n \"txtype\": \"value\", (string) The type of tx (regular tx, stake tx)\n \"vout\": n, (numeric) The transaction output index\n \"walletconflicts\": [\"value\",...], (array of string) Unset\n \"comment\": \"value\", (string) Unset\n \"otheraccount\": \"value\", (string) Unset\n },...], \n \"lastblock\": \"value\", (string) Hash of the latest-synced block to be used in later calls to listsinceblock\n} \n", + "listtickets": "listtickets\n\nList all ticket details with related spender and state info\n\nArguments:\nNone\n\nResult:\n{\n \"ticket\": { (object) Ticket tx details\n \"hash\": \"value\", (string) Hash of the transaction\n \"transaction\": \"value\", (string) Serialized string of the transaction\n \"myinputs\": [{ (array of object) Inputs of tx details\n \"index\": n, (numeric) Index of input in list of all tx inputs\n \"previousaccount\": n, (numeric) Input account\n \"previousamount\": n.nnn, (numeric) Input amount\n },...], \n \"myoutputs\": [{ (array of object) Outputs of tx details\n \"index\": n, (numeric) Index of input in list of all tx outputs\n \"account\": n, (numeric) Output account\n \"internal\": true|false, (boolean) Flag if address was create for internal use\n \"amount\": n.nnn, (numeric) Output amount\n \"address\": unknown, (value) Address receiving amount\n \"outputscript\": \"value\", (string) Pkscript to receive amount\n },...], \n \"fee\": n.nnn, (numeric) Total input value minus the total output value for sent transactions\n \"timestamp\": n, (numeric) Timestamp of tx\n \"type\": n, (numeric) Lists all tickets, including unmined tickets\n }, \n \"spender\": { (object) Spender tx details\n \"hash\": \"value\", (string) Hash of the transaction\n \"transaction\": \"value\", (string) Serialized string of the transaction\n \"myinputs\": [{ (array of object) Inputs of tx details\n \"index\": n, (numeric) Index of input in list of all tx inputs\n \"previousaccount\": n, (numeric) Input account\n \"previousamount\": n.nnn, (numeric) Input amount\n },...], \n \"myoutputs\": [{ (array of object) Outputs of tx details\n \"index\": n, (numeric) Index of input in list of all tx outputs\n \"account\": n, (numeric) Output account\n \"internal\": true|false, (boolean) Flag if address was create for internal use\n \"amount\": n.nnn, (numeric) Output amount\n \"address\": unknown, (value) Address receiving amount\n \"outputscript\": \"value\", (string) Pkscript to receive amount\n },...], \n \"fee\": n.nnn, (numeric) Total input value minus the total output value for sent transactions\n \"timestamp\": n, (numeric) Timestamp of tx\n \"type\": n, (numeric) Lists all tickets, including unmined tickets\n }, \n \"status\": \"value\", (string) Status of ticket\n} \n", "listtransactions": "listtransactions (\"account\" count=10 from=0 includewatchonly=false)\n\nReturns a JSON array of objects containing verbose details for wallet transactions.\n\nArguments:\n1. account (string, optional) DEPRECATED -- Unused (must be unset or \"*\")\n2. count (numeric, optional, default=10) Maximum number of transactions to create results from\n3. from (numeric, optional, default=0) Number of transactions to skip before results are created\n4. includewatchonly (boolean, optional, default=false) Unused\n\nResult:\n[{\n \"account\": \"value\", (string) DEPRECATED -- Unset\n \"address\": \"value\", (string) Payment address for a transaction output\n \"amount\": n.nnn, (numeric) The value of the transaction output valued in decred\n \"blockhash\": \"value\", (string) The hash of the block this transaction is mined in, or the empty string if unmined\n \"blockindex\": n, (numeric) Unset\n \"blocktime\": n, (numeric) The Unix time of the block header this transaction is mined in, or 0 if unmined\n \"category\": \"value\", (string) The kind of transaction: \"send\" for sent transactions, \"immature\" for immature coinbase outputs, \"generate\" for mature coinbase outputs, or \"recv\" for all other received outputs. Note: A single output may be included multiple times under different categories\n \"confirmations\": n, (numeric) The number of block confirmations of the transaction\n \"fee\": n.nnn, (numeric) The total input value minus the total output value for sent transactions\n \"generated\": true|false, (boolean) Whether the transaction output is a coinbase output\n \"involveswatchonly\": true|false, (boolean) Unset\n \"time\": n, (numeric) The earliest Unix time this transaction was known to exist\n \"timereceived\": n, (numeric) The earliest Unix time this transaction was known to exist\n \"txid\": \"value\", (string) The hash of the transaction\n \"txtype\": \"value\", (string) The type of tx (regular tx, stake tx)\n \"vout\": n, (numeric) The transaction output index\n \"walletconflicts\": [\"value\",...], (array of string) Unset\n \"comment\": \"value\", (string) Unset\n \"otheraccount\": \"value\", (string) Unset\n},...]\n", "listunspent": "listunspent (minconf=1 maxconf=9999999 [\"address\",...])\n\nReturns a JSON array of objects representing unlocked unspent outputs controlled by wallet keys.\n\nArguments:\n1. minconf (numeric, optional, default=1) Minimum number of block confirmations required before a transaction output is considered\n2. maxconf (numeric, optional, default=9999999) Maximum number of block confirmations required before a transaction output is excluded\n3. addresses (array of string, optional) If set, limits the returned details to unspent outputs received by any of these payment addresses\n\nResult:\n{\n \"txid\": \"value\", (string) The transaction hash of the referenced output\n \"vout\": n, (numeric) The output index of the referenced output\n \"tree\": n, (numeric) The tree the transaction comes from\n \"txtype\": n, (numeric) The type of the transaction\n \"address\": \"value\", (string) The payment address that received the output\n \"account\": \"value\", (string) The account associated with the receiving payment address\n \"scriptPubKey\": \"value\", (string) The output script encoded as a hexadecimal string\n \"redeemScript\": \"value\", (string) Unset\n \"amount\": n.nnn, (numeric) The amount of the output valued in decred\n \"confirmations\": n, (numeric) The number of block confirmations of the transaction\n \"spendable\": true|false, (boolean) Whether the output is entirely controlled by wallet keys/scripts (false for partially controlled multisig outputs or outputs to watch-only addresses)\n} \n", "lockunspent": "lockunspent unlock [{\"amount\":n.nnn,\"txid\":\"value\",\"vout\":n,\"tree\":n},...]\n\nLocks or unlocks an unspent output.\nLocked outputs are not chosen for transaction inputs of authored transactions and are not included in 'listunspent' results.\nLocked outputs are volatile and are not saved across wallet restarts.\nIf unlock is true and no transaction outputs are specified, all locked outputs are marked unlocked.\n\nArguments:\n1. unlock (boolean, required) True to unlock outputs, false to lock\n2. transactions (array of object, required) Transaction outputs to lock or unlock\n[{\n \"amount\": n.nnn, (numeric) The the previous output amount\n \"txid\": \"value\", (string) The transaction hash of the referenced output\n \"vout\": n, (numeric) The output index of the referenced output\n \"tree\": n, (numeric) The tree to generate transaction for\n},...]\n\nResult:\ntrue|false (boolean) The boolean 'true'\n", diff --git a/spv/go.mod b/spv/go.mod index 03c04ad11..e46638227 100644 --- a/spv/go.mod +++ b/spv/go.mod @@ -5,7 +5,7 @@ require ( github.com/decred/dcrd/blockchain/stake v1.0.1 github.com/decred/dcrd/chaincfg/chainhash v1.0.1 github.com/decred/dcrd/dcrutil v1.1.1 - github.com/decred/dcrd/gcs v1.0.1 + github.com/decred/dcrd/gcs v1.0.2 github.com/decred/dcrd/txscript v1.0.1 github.com/decred/dcrd/wire v1.1.0 github.com/decred/dcrwallet/errors v1.0.0 diff --git a/spv/go.sum b/spv/go.sum index d6f337af9..a1e05d4cd 100644 --- a/spv/go.sum +++ b/spv/go.sum @@ -17,6 +17,7 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/blake256 v1.0.0 h1:6gUgI5MHdz9g0TdrgKqXsoDX+Zjxmm1Sc6OsoGru50I= github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= +github.com/dchest/siphash v1.2.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/decred/base58 v1.0.0 h1:BVi1FQCThIjZ0ehG+I99NJ51o0xcc9A/fDKhmJxY6+w= github.com/decred/base58 v1.0.0/go.mod h1:LLY1p5e3g91byL/UO1eiZaYd+uRoVRarybgcoymu9Ks= github.com/decred/dcrd v1.2.1-0.20180801202239-0761de129164 h1:wYjHNfbzWlLpFuqlVVNtXRmqrEETEDv7KWEf7psUWnc= @@ -28,6 +29,7 @@ github.com/decred/dcrd/addrmgr v1.0.2/go.mod h1:gNnmTuf/Xkg8ZX3j5GXbajzPrSdf5bA7 github.com/decred/dcrd/blockchain v1.0.0/go.mod h1:nNMgOz12wlasmEJDCuSuMWYSnjDdmB4l38GKuQ/Yd+8= github.com/decred/dcrd/blockchain v1.0.1 h1:7cviDS26sZ9ZyTFka3aC9C/EChXBslmAvse+4nF5d60= github.com/decred/dcrd/blockchain v1.0.1/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= +github.com/decred/dcrd/blockchain v1.0.2/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= github.com/decred/dcrd/blockchain/stake v1.0.0/go.mod h1:opuzF8UouYyQyRJVF00Rdd7OgWb1WKyy1pyU0QYaxz0= github.com/decred/dcrd/blockchain/stake v1.0.1 h1:IYGsNZRyMUsoFtVAUjd7XIccrIQ4YIqDeNzQJCjyS8A= github.com/decred/dcrd/blockchain/stake v1.0.1/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= @@ -70,6 +72,7 @@ github.com/decred/dcrd/dcrutil v1.1.1/go.mod h1:Jsttr0pEvzPAw+qay1kS1/PsbZYPyhlu github.com/decred/dcrd/gcs v1.0.0/go.mod h1:5uHIPAzn4SdGP2/FhVBK2YdAoKmufds3ZI8yNzojUCM= github.com/decred/dcrd/gcs v1.0.1 h1:MpJXLskT41+JDaD3RLdlSlF2vlu1sxPpZgiRI7FVTWw= github.com/decred/dcrd/gcs v1.0.1/go.mod h1:YwutGzusSdJM79CJtxCo9t7WRCvnkLtWSD19TPo1i9g= +github.com/decred/dcrd/gcs v1.0.2/go.mod h1:eLCvrzUsWro48TlTyrmFcZAZqnllYFz0vEv5VZtufF4= github.com/decred/dcrd/hdkeychain v1.0.0 h1:YZPNvvFYME29nnjLl1c4v+Wusrx4BzUCYdRYmUdRnPI= github.com/decred/dcrd/hdkeychain v1.0.0/go.mod h1:ZLzIMYN4rLNQPdy2I5FYtdYevIKwmUVo1Sz9x909kYc= github.com/decred/dcrd/hdkeychain v1.1.0 h1:6bFdL672dCmtg/JEzb3Jw0dTRO2jLxcA7BK2J+JaoUM= diff --git a/ticketbuyer/go.mod b/ticketbuyer/go.mod index 388b29cdc..ce8a78ad9 100644 --- a/ticketbuyer/go.mod +++ b/ticketbuyer/go.mod @@ -1,7 +1,7 @@ module github.com/decred/dcrwallet/ticketbuyer require ( - github.com/decred/dcrd/blockchain v1.0.1 + github.com/decred/dcrd/blockchain v1.0.2 github.com/decred/dcrd/chaincfg v1.1.1 github.com/decred/dcrd/dcrjson v1.0.0 github.com/decred/dcrd/dcrutil v1.1.1 diff --git a/ticketbuyer/go.sum b/ticketbuyer/go.sum index 29cc4e80b..0679610e5 100644 --- a/ticketbuyer/go.sum +++ b/ticketbuyer/go.sum @@ -14,11 +14,13 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/blake256 v1.0.0 h1:6gUgI5MHdz9g0TdrgKqXsoDX+Zjxmm1Sc6OsoGru50I= github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= +github.com/dchest/siphash v1.2.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/decred/base58 v1.0.0 h1:BVi1FQCThIjZ0ehG+I99NJ51o0xcc9A/fDKhmJxY6+w= github.com/decred/base58 v1.0.0/go.mod h1:LLY1p5e3g91byL/UO1eiZaYd+uRoVRarybgcoymu9Ks= github.com/decred/dcrd/blockchain v1.0.0/go.mod h1:nNMgOz12wlasmEJDCuSuMWYSnjDdmB4l38GKuQ/Yd+8= github.com/decred/dcrd/blockchain v1.0.1 h1:7cviDS26sZ9ZyTFka3aC9C/EChXBslmAvse+4nF5d60= github.com/decred/dcrd/blockchain v1.0.1/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= +github.com/decred/dcrd/blockchain v1.0.2/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= github.com/decred/dcrd/blockchain/stake v1.0.0/go.mod h1:opuzF8UouYyQyRJVF00Rdd7OgWb1WKyy1pyU0QYaxz0= github.com/decred/dcrd/blockchain/stake v1.0.1 h1:IYGsNZRyMUsoFtVAUjd7XIccrIQ4YIqDeNzQJCjyS8A= github.com/decred/dcrd/blockchain/stake v1.0.1/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= @@ -55,6 +57,7 @@ github.com/decred/dcrd/dcrutil v1.1.1/go.mod h1:Jsttr0pEvzPAw+qay1kS1/PsbZYPyhlu github.com/decred/dcrd/gcs v1.0.0/go.mod h1:5uHIPAzn4SdGP2/FhVBK2YdAoKmufds3ZI8yNzojUCM= github.com/decred/dcrd/gcs v1.0.1 h1:MpJXLskT41+JDaD3RLdlSlF2vlu1sxPpZgiRI7FVTWw= github.com/decred/dcrd/gcs v1.0.1/go.mod h1:YwutGzusSdJM79CJtxCo9t7WRCvnkLtWSD19TPo1i9g= +github.com/decred/dcrd/gcs v1.0.2/go.mod h1:eLCvrzUsWro48TlTyrmFcZAZqnllYFz0vEv5VZtufF4= github.com/decred/dcrd/hdkeychain v1.1.0 h1:6bFdL672dCmtg/JEzb3Jw0dTRO2jLxcA7BK2J+JaoUM= github.com/decred/dcrd/hdkeychain v1.1.0/go.mod h1:zyUZtZ3PdnTPHt2XUr1x76b8ZuiM+9aVkP8Rq8Scp1k= github.com/decred/dcrd/mempool v1.0.1 h1:xZOfwGmVbWfKDNztVgsVO/GkMmiZn3MMfDDVE07ZKKs= diff --git a/ticketbuyer/v2/go.sum b/ticketbuyer/v2/go.sum index 29cc4e80b..0679610e5 100644 --- a/ticketbuyer/v2/go.sum +++ b/ticketbuyer/v2/go.sum @@ -14,11 +14,13 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/blake256 v1.0.0 h1:6gUgI5MHdz9g0TdrgKqXsoDX+Zjxmm1Sc6OsoGru50I= github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= +github.com/dchest/siphash v1.2.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/decred/base58 v1.0.0 h1:BVi1FQCThIjZ0ehG+I99NJ51o0xcc9A/fDKhmJxY6+w= github.com/decred/base58 v1.0.0/go.mod h1:LLY1p5e3g91byL/UO1eiZaYd+uRoVRarybgcoymu9Ks= github.com/decred/dcrd/blockchain v1.0.0/go.mod h1:nNMgOz12wlasmEJDCuSuMWYSnjDdmB4l38GKuQ/Yd+8= github.com/decred/dcrd/blockchain v1.0.1 h1:7cviDS26sZ9ZyTFka3aC9C/EChXBslmAvse+4nF5d60= github.com/decred/dcrd/blockchain v1.0.1/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= +github.com/decred/dcrd/blockchain v1.0.2/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= github.com/decred/dcrd/blockchain/stake v1.0.0/go.mod h1:opuzF8UouYyQyRJVF00Rdd7OgWb1WKyy1pyU0QYaxz0= github.com/decred/dcrd/blockchain/stake v1.0.1 h1:IYGsNZRyMUsoFtVAUjd7XIccrIQ4YIqDeNzQJCjyS8A= github.com/decred/dcrd/blockchain/stake v1.0.1/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= @@ -55,6 +57,7 @@ github.com/decred/dcrd/dcrutil v1.1.1/go.mod h1:Jsttr0pEvzPAw+qay1kS1/PsbZYPyhlu github.com/decred/dcrd/gcs v1.0.0/go.mod h1:5uHIPAzn4SdGP2/FhVBK2YdAoKmufds3ZI8yNzojUCM= github.com/decred/dcrd/gcs v1.0.1 h1:MpJXLskT41+JDaD3RLdlSlF2vlu1sxPpZgiRI7FVTWw= github.com/decred/dcrd/gcs v1.0.1/go.mod h1:YwutGzusSdJM79CJtxCo9t7WRCvnkLtWSD19TPo1i9g= +github.com/decred/dcrd/gcs v1.0.2/go.mod h1:eLCvrzUsWro48TlTyrmFcZAZqnllYFz0vEv5VZtufF4= github.com/decred/dcrd/hdkeychain v1.1.0 h1:6bFdL672dCmtg/JEzb3Jw0dTRO2jLxcA7BK2J+JaoUM= github.com/decred/dcrd/hdkeychain v1.1.0/go.mod h1:zyUZtZ3PdnTPHt2XUr1x76b8ZuiM+9aVkP8Rq8Scp1k= github.com/decred/dcrd/mempool v1.0.1 h1:xZOfwGmVbWfKDNztVgsVO/GkMmiZn3MMfDDVE07ZKKs= diff --git a/wallet/notifications.go b/wallet/notifications.go index 7e647474c..44877a602 100644 --- a/wallet/notifications.go +++ b/wallet/notifications.go @@ -219,7 +219,14 @@ func makeTicketSummary(chainClient *dcrrpcclient.Client, dbtx walletdb.ReadTx, w ticketStatus = TicketStatusImmature // Check if ticket age is over TicketExpiry limit and therefore expired } else if ticketExpired(w.chainParams, details.Ticket.Height(), tipHeight) { - ticketStatus = TicketStatusExpired + if chainClient != nil { + ticketStatus = TicketStatusExpired + } else { + ticketStatus = TicketStatusUnspentExpired + } + } else if chainClient == nil { + // Mark ticket as unspent. Possible states are missed, live or expired + ticketStatus = TicketStatusUnspent } } return &TicketSummary{ @@ -455,8 +462,39 @@ const ( TicketStatusMissed // TicketStatusExpired any ticket that has yet to be revoked, and was expired. TicketStatusExpired + // TicketStatusUnspent any ticket that missed, live or expired + TicketStatusUnspent + // TicketStatusUnspentExpired any ticket that missed or expired + TicketStatusUnspentExpired ) +func (t TicketStatus) String() string { + switch t { + case TicketStatusUnknown: + return "UNKNOWN" + case TicketStatusUnmined: + return "UNMINED" + case TicketStatusImmature: + return "IMMATURE" + case TicketStatusLive: + return "LIVE" + case TicketStatusVoted: + return "VOTED" + case TicketStatusRevoked: + return "REVOKED" + case TicketStatusMissed: + return "MISSED" + case TicketStatusExpired: + return "EXPIRED" + case TicketStatusUnspent: + return "UNSPENT" + case TicketStatusUnspentExpired: + return "UNSPENTEXPIRED" + default: + return "" + } +} + // TransactionSummary contains a transaction relevant to the wallet and marks // which inputs and outputs were relevant. type TransactionSummary struct { @@ -510,6 +548,23 @@ func TxTransactionType(tx *wire.MsgTx) TransactionType { } } +func (t TransactionType) String() string { + switch t { + case TransactionTypeRegular: + return "REGULAR" + case TransactionTypeCoinbase: + return "COINBASE" + case TransactionTypeTicketPurchase: + return "TICKETPURCHASE" + case TransactionTypeVote: + return "VOTE" + case TransactionTypeRevocation: + return "REVOCATION" + default: + return "" + } +} + // TransactionSummaryInput describes a transaction input that is relevant to the // wallet. The Index field marks the transaction input index of the transaction // (not included here). The PreviousAccount and PreviousAmount fields describe diff --git a/wallet/wallet.go b/wallet/wallet.go index 3c863db8f..baaff5dba 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -2309,6 +2309,128 @@ func (w *Wallet) ListTransactionDetails(txHash *chainhash.Hash) ([]dcrjson.ListT return txList, nil } +// ListTickets returns the listtickets results +func (w *Wallet) ListTickets(chainClient *dcrrpcclient.Client) ([]*dcrjson.ListTicketsResult, error) { + const op errors.Op = "wallet.ListTickets" + + var tickets []*dcrjson.ListTicketsResult + err := walletdb.View(w.db, func(dbtx walletdb.ReadTx) error { + txmgrNs := dbtx.ReadBucket(wtxmgrNamespaceKey) + + tickets = make([]*dcrjson.ListTicketsResult, 0) + rangeFn := func(details []udb.TxDetails) (bool, error) { + for i := range details { + ticketDetails, err := w.TxStore.TicketDetails(txmgrNs, &details[i]) + if err != nil { + return false, errors.E(op, errors.Errorf("%v while trying to get ticket details for txHash: %v", err, &details[i].Hash)) + } + // Continue if not a ticket + if ticketDetails == nil { + continue + } + ticketSummary := makeTicketSummary(chainClient, dbtx, w, ticketDetails) + ticketInputs := []dcrjson.ListTicketsTransactionSummaryInput{} + ticketOutputs := []dcrjson.ListTicketsTransactionSummaryOutput{} + for _, in := range ticketSummary.Ticket.MyInputs { + accName, err := w.AccountName(in.PreviousAccount) + if err != nil { + return false, errors.E(op, err) + } + + ticketInputs = append(ticketInputs, dcrjson.ListTicketsTransactionSummaryInput{ + Index: in.Index, + PreviousAccount: accName, + PreviousAmount: in.PreviousAmount.ToCoin(), + }) + } + for _, out := range ticketSummary.Ticket.MyOutputs { + accName, err := w.AccountName(out.Account) + if err != nil { + return false, errors.E(op, err) + } + + ticketOutputs = append(ticketOutputs, dcrjson.ListTicketsTransactionSummaryOutput{ + Index: out.Index, + Account: accName, + Internal: out.Internal, + Amount: out.Amount.ToCoin(), + Address: out.Address.EncodeAddress(), + OutputScript: hex.EncodeToString(out.OutputScript), + }) + } + + ticketInfo := &dcrjson.ListTicketsResult{ + Ticket: &dcrjson.ListTicketsTransactionSummary{ + Hash: ticketSummary.Ticket.Hash.String(), + Transaction: hex.EncodeToString(ticketSummary.Ticket.Transaction), + MyInputs: ticketInputs, + MyOutputs: ticketOutputs, + Fee: ticketSummary.Ticket.Fee.ToCoin(), + Timestamp: ticketSummary.Ticket.Timestamp, + Type: ticketSummary.Ticket.Type.String(), + }, + Status: ticketSummary.Status.String(), + } + + if ticketSummary.Spender != nil { + spenderOutputs := []dcrjson.ListTicketsTransactionSummaryOutput{} + spenderInputs := []dcrjson.ListTicketsTransactionSummaryInput{} + for _, in := range ticketSummary.Spender.MyInputs { + accName, err := w.AccountName(in.PreviousAccount) + if err != nil { + return false, errors.E(op, err) + } + + spenderInputs = append(spenderInputs, dcrjson.ListTicketsTransactionSummaryInput{ + Index: in.Index, + PreviousAccount: accName, + PreviousAmount: in.PreviousAmount.ToCoin(), + }) + } + for _, out := range ticketSummary.Spender.MyOutputs { + accName, err := w.AccountName(out.Account) + if err != nil { + return false, errors.E(op, err) + } + + spenderOutputs = append(spenderOutputs, dcrjson.ListTicketsTransactionSummaryOutput{ + Index: out.Index, + Account: accName, + Internal: out.Internal, + Amount: out.Amount.ToCoin(), + Address: out.Address.EncodeAddress(), + OutputScript: hex.EncodeToString(out.OutputScript), + }) + } + ticketInfo.Spender = &dcrjson.ListTicketsTransactionSummary{ + Hash: ticketSummary.Spender.Hash.String(), + Transaction: hex.EncodeToString(ticketSummary.Spender.Transaction), + MyInputs: spenderInputs, + MyOutputs: spenderOutputs, + Fee: ticketSummary.Spender.Fee.ToCoin(), + Timestamp: ticketSummary.Spender.Timestamp, + Type: ticketSummary.Spender.Type.String(), + } + } + tickets = append(tickets, ticketInfo) + } + + if len(tickets) == 0 { + return false, nil + } + + return false, nil + } + + return w.TxStore.RangeTransactions(txmgrNs, 0, -1, rangeFn) + }) + if err != nil { + return nil, errors.E(op, err) + } + + return tickets, nil +} + // BlockIdentifier identifies a block by either a height in the main chain or a // hash. type BlockIdentifier struct {