I implemented a crappy version of listtransactions that probably doesn't behave much like the bitcoind version, but it is just as confusing (so at least there's something in common). For each incoming transaction it gives one entry per txOut you own. For each outgoing transaction, it gives one entry for the total output value (i.e. for your own contributions minus change) and one entry for each non-change receiving address (which can be sending or receiving depending on whose/howmany outputs there are). I'm sure people will try to use it and complain. Then I'll fix it to match what they were expecting...
However, I added my own version of listtransactions called "
getledger" and "
getledgersimple". It has
one entry per transaction and is a pure partition of your wallet activity.
For each transaction "getledgersimple" returns:
- "direction" is {'send', 'receive', 'toself'}. To self is any tx for which you own all inputs and outputs.
- "amount" is the total BTC exchanged (inputs - outputs + change + fee)). It is always positive. For example, if I send someone 10 BTC with 0.05 BTC fee and 5 BTC change to myself, "amount is 10". For to-self tx, change address is assumed to the be the address with the higher generation order (since the wallets always generate change addr after recipients are selected)
- "netdiff" is the change in your wallet balance induced by the transaction. For the above transaction, netdiff would be -10.05. If you send money to yourself, netdiff will be the negative of the fee paid. Summing all returned "netdiff" values returned will give you your wallet balance
- "fee" is the fee paid for the transaction. It is always positive, and the caller only has to pay attention to it on outgoing tx if they want (and make it negative). Or they may want to know how much fee was paid to determine how safe an incoming tx is. (returns zero in bitcoind for incoming transactions)
- "txsize" is size in bytes of the tx (included for same reason as fee)
- "firstrecip" is the first "target" of the transaction. For simple transactions this is your own address for incoming tx, or the other person's address for outgoing tx
- "changerecip" is the first address that may reasonably be interpretted as change. Someone sending you money as part of a multi-output tx, this will return the first output address that isn't yours. Or if the transaction is outgoing, it's the first txout with address in your wallet.
For each transaction "getledger" returns the same as the simple one, but with the following additional output. This accommodates users that want to handle more-complex, multi-recipient transactions and kind of just want all the information:
- "senderme": list of all [address,value] pairs on the input side that are part of this wallet
- "senderother" list of all [address,value] pairs on the input side that are not part of this wallet
- "recipme": list of all [address,value] pairs on the output side that are part of this wallet
- "recipother" list of all [address,value] pairs on the output side that are not part of this wallet
mav originally setup the thing to handle watching-only wallets only. I will eventually upgrade it to work on any wallet, and maybe even multiwallet. But for now it's actually starting to have usefulness, and I'll hold off digging into too many more calls until I get some feedback. For now, I want to dig into fixing the instability issues I referred to earlier with blocksplits and simultaneous blocks.
P.S. -- This is all on the armoryd branch, and you must have a armoryd.conf file in your Armory home dir specifying "username:password", then use that in the URL for the connecting client.
Example of simple and nonsimple getledger calls:
getledgersimple$ python armoryd.py --testnet getledgersimple
[
{
"amount": 10.0,
"blockhash": "00000000067a1fb9e9634cf2b39f1728392882475c7fcda32db30724584707b6",
"blocktime": 1357795104,
"changerecip": "mqMK7xSkrNK5auTzHEJBndtxJiRZW6HMHK",
"comment": "",
"direction": "received",
"fee": 0.00050000000000000001,
"firstrecip": "mreAZm1osfLWZTKMcaAaQuUqZW59Ysikr5",
"netdiff": 10.0,
"txid": "e6582b82cf24888a86aee8b819a8e32f34033f2870d399dd0bcc1b9331331370",
"txsize": 292,
"txtime": 1357795104
},
{
"amount": 0.25,
"blockhash": "000000004a769f6db14bdff5374ce3790d756d4f49770a0f2203087133d3ec3a",
"blocktime": 1358106188,
"changerecip": "mzDVubTfVQGfxncSSajjxaRYttXfGJrWdQ",
"comment": "",
"direction": "sent",
"fee": 0.00050000000000000001,
"firstrecip": "n1NWE4QPX7FbxeBQaPhbr6rEwvHR1RjBWT",
"netdiff": -0.2505,
"txid": "747f357c8287da26fcd423e45974e2e1ba367216f0115d15eb2cdd66c4abc767",
"txsize": 258,
"txtime": 1358106188
},
{
"amount": 13.5,
"blockhash": "00000000db486e1907269bdff3fd0b62b1a8c7c51f214e89e57650403922bab9",
"blocktime": 1358113003,
"changerecip": "n1Q3DWs7pH5uvME4o3rDYDTd4ZgiqSPCUx",
"comment": "",
"direction": "toself",
"fee": 0.00050000000000000001,
"firstrecip": "mgdsaZL9WKbKrfxGRw8Rpi9FdRuaMMyyYJ",
"netdiff": -0.00050000000000000001,
"txid": "f53bdc6f3a1b573d2efa892591140caf5c88739c42248efdacfb0fd97da4287b",
"txsize": 618,
"txtime": 1358113003
}
]
getledger {
"amount": 10.0,
"blockhash": "00000000067a1fb9e9634cf2b39f1728392882475c7fcda32db30724584707b6",
"blocktime": 1357795104,
"changerecip": "mqMK7xSkrNK5auTzHEJBndtxJiRZW6HMHK",
"comment": "",
"direction": "received",
"fee": 0.00050000000000000001,
"firstrecip": "mreAZm1osfLWZTKMcaAaQuUqZW59Ysikr5",
"netdiff": 10.0,
"recipme": [
{
"address": "mreAZm1osfLWZTKMcaAaQuUqZW59Ysikr5",
"amount": 10.0
}
],
"recipother": [
{
"address": "mqMK7xSkrNK5auTzHEJBndtxJiRZW6HMHK",
"amount": 14.499499999999999
},
{
"address": "mi6hyHi3zVPx8sgB6wuf6cKkXPswa5NFDf",
"amount": 0.5
}
],
"senderme": [],
"senderother": [
{
"address": "mqy7NzHrcFLu32YK1ow6L4V2YC4PFCChHB",
"amount": 25.0
}
],
"txid": "e6582b82cf24888a86aee8b819a8e32f34033f2870d399dd0bcc1b9331331370",
"txsize": 292,
"txtime": 1357795104
},
{
"amount": 0.25,
"blockhash": "000000004a769f6db14bdff5374ce3790d756d4f49770a0f2203087133d3ec3a",
"blocktime": 1358106188,
"changerecip": "mzDVubTfVQGfxncSSajjxaRYttXfGJrWdQ",
"comment": "",
"direction": "sent",
"fee": 0.00050000000000000001,
"firstrecip": "n1NWE4QPX7FbxeBQaPhbr6rEwvHR1RjBWT",
"netdiff": -0.2505,
"recipme": [
{
"address": "mzDVubTfVQGfxncSSajjxaRYttXfGJrWdQ",
"amount": 9.7494999999999994
}
],
"recipother": [
{
"address": "n1NWE4QPX7FbxeBQaPhbr6rEwvHR1RjBWT",
"amount": 0.25
}
],
"senderme": [
{
"address": "mreAZm1osfLWZTKMcaAaQuUqZW59Ysikr5",
"amount": 10.0
}
],
"senderother": [],
"txid": "747f357c8287da26fcd423e45974e2e1ba367216f0115d15eb2cdd66c4abc767",
"txsize": 258,
"txtime": 1358106188
},
{
"amount": 13.5,
"blockhash": "00000000db486e1907269bdff3fd0b62b1a8c7c51f214e89e57650403922bab9",
"blocktime": 1358113003,
"changerecip": "n1Q3DWs7pH5uvME4o3rDYDTd4ZgiqSPCUx",
"comment": "",
"direction": "toself",
"fee": 0.00050000000000000001,
"firstrecip": "mgdsaZL9WKbKrfxGRw8Rpi9FdRuaMMyyYJ",
"netdiff": -0.00050000000000000001,
"recipme": [
{
"address": "n1Q3DWs7pH5uvME4o3rDYDTd4ZgiqSPCUx",
"amount": 1.7490000000000001
},
{
"address": "mgdsaZL9WKbKrfxGRw8Rpi9FdRuaMMyyYJ",
"amount": 13.5
}
],
"recipother": [],
"senderme": [
{
"address": "mzDVubTfVQGfxncSSajjxaRYttXfGJrWdQ",
"amount": 9.7494999999999994
},
{
"address": "n34NnSRwMTUaHnx4R5ykmcjecoDn8uVXUA",
"amount": 3.25
},
{
"address": "n34NnSRwMTUaHnx4R5ykmcjecoDn8uVXUA",
"amount": 2.25
}
],
"senderother": [],
"txid": "f53bdc6f3a1b573d2efa892591140caf5c88739c42248efdacfb0fd97da4287b",
"txsize": 618,
"txtime": 1358113003
}
]
P.S -- As far as I can tell, the ultra-high-precision values/amounts are due to the python-JSON library display. It's a display issue caused by the fact that someone a long time ago decided the JSON interface should transport floats for amounts, instead of strings or satoshis, and the JSON library just prints the raw floats. Luckily, double-precision values have enough precision that this will never screw up from a simple round() call. But clearly, this is sub-optimal. And since I'm using a built-in json.dumps call in python, I can't really modify the behavior.
I'm thinking I could add a "setamtcoding COIN" or "setamtcoding STRING" to tell the RPC server to always encode values as longs (in Satoshis) or string values with at most 8 decimal places. I could also make the last argument to every RPC call be "COIN" or "STRING" to tell the server what to output for that particular call. But that seems kind of messy.