Comments (5)
That is correct. The return type in your example should be List<ListTransactionsResponse>
and not ListTransactionsResponse
, as demonstrated in this test client call.
from bitcoinlib.
The error I reported WAS FROM running the test client! I then modified the call as part of finding out the root cause, but the error is not a type case error, but as described, a deserialization error - which also occur in the unmodified CoinService code, at least for me.
As mentioned, the error occurs because the JSON response cannot be deserialized - not because I try to capture the returned value in a ListTransactionsResponse .
I do not think you tried to run CoinService.ListTransactions, did you? If so - and if you encountered no error, your JSON.Net version must be different than mine, which cannot deserialize the returned JSON string.
The RPC call and the JSON response is captured fine, but Deserilization using your original CoinService code fails.
I investigated the root cause.
Running against the blockchain.info RPC access at https://rpc.blockchain.info:443.
The JSON text string returned from the RPC in my case was:
{"result":{"lastblock":"00000000000000000ee4d0f4d086b0324e750d19fae10003c55ba875652c1ca4","transactions":[{"amount":0.0008,"blockhash":"00000000000000000020a6a6280401444ab61a9d4f35d436a50567935fcbf495","address":"16NxBNBcrxRgzHRGsJiW9fmg7HLoNvUZ3n","fee":0.0001,"txid":"e649d9333f20f7f5a9549809e2784b254cb8d79d9b6f7c0be1814eea4ad4b282","label":"BTCSFFB0W5DY","time":1424387709,"category":"receive","confirmations":-163,"blockindex":781976,"account":"BTCSFFB0W5DY"},{"amount":-0.0019,"blockhash":"00000000000000000020a6a6280401444ab61a9d4f35d436a50567935fcbf495","address":"16NxBNBcrxRgzHRGsJiW9fmg7HLoNvUZ3n","fee":0.0001,"txid":"e649d9333f20f7f5a9549809e2784b254cb8d79d9b6f7c0be1814eea4ad4b282","label":"BTCSFFB0W5DY","time":1424387709,"category":"send","confirmations":-163,"blockindex":781976,"account":"BTCSFFB0W5DY"},{"amount":0.0019,"blockhash":"00000000000000000014506cec64981fdc49178011a1510b1f00995c9d62a95d","address":"16NxBNBcrxRgzHRGsJiW9fmg7HLoNvUZ3n","fee":0.0001,"txid":"7685a8e832d468f224a7b5414b7ce9037a7955132237983acaf4ee842a5d5741","label":"BTCSFFB0W5DY","time":1424276225,"category":"receive","confirmations":-377,"blockindex":779874,"account":"BTCSFFB0W5DY"},{"amount":-0.003,"blockhash":"00000000000000000014506cec64981fdc49178011a1510b1f00995c9d62a95d","address":"16NxBNBcrxRgzHRGsJiW9fmg7HLoNvUZ3n","fee":0.0001,"txid":"7685a8e832d468f224a7b5414b7ce9037a7955132237983acaf4ee842a5d5741","label":"BTCSFFB0W5DY","time":1424276225,"category":"send","confirmations":-377,"blockindex":779874,"account":"BTCSFFB0W5DY"},{"amount":0.003,"blockhash":"00000000000000000477417305b03d8033a0c9fbf949be5ca60dbf0c6abf5fef","address":"16NxBNBcrxRgzHRGsJiW9fmg7HLoNvUZ3n","fee":0.00001,"txid":"e92bfc63cb15f030b557be38aa59025f23bc1f50e16f1b5a2072249bc8c6a778","label":"BTCSFFB0W5DY","time":1424273720,"category":"receive","confirmations":-383,"blockindex":773756,"account":"BTCSFFB0W5DY"}]},"id":"1","jsonrpc":"2.0","error":null}
This is being attempted deserialized in :
private T MakeRequest(RpcMethods rpcMethod, Int16 timedOutRequestsCount, params object[] parameters)
However - here the error occus at:
JsonRpcResponse rpcResponse = JsonConvert.DeserializeObject<JsonRpcResponse>(json);
My Newtonsoft JSON.Net dll (v. 6.0.0) seems unable to handle the response, due in part to the issue described here: http://michaelcummings.net/mathoms/using-a-custom-jsonconverter-to-fix-bad-json-results/
But likely also because the returned JSON has a "lastblock" element, one level lower than the transactions themselves.
FIX:
First step is to rewrite ListTransactionsResponse, to include the lastblock element, then a list of nested transactions (original code assumed JSON return was just the list of transactions):
public class ListTransactionsResponse
{
public string lastblock;
public List transactions;
}
public class ListTransactionsResponseEx
{
public String Account { get; set; }
public String Label { get; set; }
public String Address { get; set; }
public String Category { get; set; }
public Decimal Amount { get; set; }
public Decimal Fee { get; set; }
public Int32 Confirmations { get; set; }
public String BlockHash { get; set; }
public String BlockIndex { get; set; }
public Double BlockTime { get; set; }
public String TxId { get; set; }
public List<String> WalletConflicts { get; set; }
public Double Time { get; set; }
public Double TimeReceived { get; set; }
public String Comment { get; set; }
public String OtherAccount { get; set; }
}
However - the Deserialization will still fail,, as Newtonsoft cannot handle the (actually valid) JSON text response. This can be fixed by adding square brackets around the "result" element in the JSON text string:
UGLY FIX:
if (rpcMethod.ToString() == "listtransactions")
{
json = json.Replace("result":{", "result":[{");
json = json.Replace("]},"id":", "]}],"id":");
}
JsonRpcResponse rpcResponse = JsonConvert.DeserializeObject<JsonRpcResponse>(json);
While this creates an array of results in rpcResponse.Result, at least it works. One then has to access rpcResponse.Result[0] to get to the result data.
TRUE FIX:
Extend JSON.Net's deserialization pipeline as described here: http://michaelcummings.net/mathoms/using-a-custom-jsonconverter-to-fix-bad-json-results/
A few of the other functions in the CoinService fail as well when run up against rpc.blockchain.info (using JSON.Net 6.0) - but are also fixable. So -all in all a very useful piece of code, which certainly got me started :-) Thank you!
from bitcoinlib.
Thanks for your input.
OK, mystery solved: you are getting this deserialization error because blockchain.info
's listtransactions
response is different than the reference client
's.
Bitcoin-core
's response is:
Result:
[
{
"account":"accountname", (string) The account name associated with the transaction.
It will be "" for the default account.
"address":"bitcoinaddress", (string) The bitcoin address of the transaction. Not present for
move transactions (category = move).
"category":"send|receive|move", (string) The transaction category. 'move' is a local (off blockchain)
transaction between accounts, and not associated with an address,
transaction id or block. 'send' and 'receive' transactions are
associated with an address, transaction id and block details
"amount": x.xxx, (numeric) The amount in btc. This is negative for the 'send' category, and for the
'move' category for moves outbound. It is positive for the 'receive' category,
and for the 'move' category for inbound funds.
"vout" : n, (numeric) the vout value
"fee": x.xxx, (numeric) The amount of the fee in btc. This is negative and only available for the
'send' category of transactions.
"confirmations": n, (numeric) The number of confirmations for the transaction. Available for 'send' and
'receive' category of transactions.
"blockhash": "hashvalue", (string) The block hash containing the transaction. Available for 'send' and 'receive'
category of transactions.
"blockindex": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'
category of transactions.
"txid": "transactionid", (string) The transaction id. Available for 'send' and 'receive' category of transactions.
"time": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).
"timereceived": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available
for 'send' and 'receive' category of transactions.
"comment": "...", (string) If a comment is associated with the transaction.
"otheraccount": "accountname", (string) For the 'move' category of transactions, the account the funds came
from (for receiving funds, positive amounts), or went to (for sending funds,
negative amounts).
}
]
while blockchain.info
's response is:
{
"lastblock" : "00000000000009133d70c6282279bfc5fadfea07e27543445a199fe6ef84b51b",
"transactions" : [
{
"fee" : 0.01000000,
"amount" : 1,
"blockindex" : 171984,
"category" : "receive",
"confirmations" : 0,
"address" : "1A8JiWcwvpY7tAopUkSnGuEYHmzGYfZPiq",
"txid" : "90992bc8ebff9774cfc91738863602010dab9ab2f5b0841cc4922786a2029725",
"block" : 1323486876,
"blockhash" : "00000000000003438e8c67500f34dd32bb1bf0d251a5c230c407641961c85b41",
"account" : "My Wallet"
}
]
}
The assumption that this library is blockchain.info
-compatible was based upon the feedback from this issue, however based on your feedback it turns that it isn't and since blockchain.info
decided to diverge from bitcoin-core
's RPC API responses we have to think of other ways to extend this library against blockchain.info
's implementation, which should not however interfere with the default (bitcoin-core
) implementation. Thoughts?
from bitcoinlib.
Damn - it is extremely inconvinient that Blockchain does not stay true to the Core's implementation. Because it does allow for lightweight applications, not to have to download and maintain the blockchain - and run the core client.
Reading through the previous thread, I have some feedback:
We have also not received an API-key from Blockchain.info, although we actually do have a website (https://www.bitcoinsuisse.ch/en/index/). Actually, we didnt get as much as a reply from them. However, the RCP does not require an API key (nowhere to put it in the calls), only the webservices do.
The Blockchain RPC is however extremely responsive and fast, one does not need a core client + blockchain etc. so it is highly recommendable for ligltweight apps.
The responses are indeed somewhat different as you discovered. I think the only workaround for this is to generate entirely seperate response classes for when using blockchain.info - and to implement a "blockchain.info mode" to set when creating the CoinService instance. As 80 % of the responses are the same, this would not be too big a task. And it would certainly add value to the CoinService library
One annoying thing is that the listtransactions-response from blockchain does not contain the "OtherAccount" field, and one thus miss this information in the transactions. I made a workaround where I call GetTransaction on new transactions before storing in DB, then loop through the response to find the "otheraddress".
var txDetails = CoinService.GetTransaction(transaction.TxId);
foreach (var detailline in txDetails.Details)
{
if(detailline.Address != transaction.Address)
transaction.OtherAccount = detailline.Address;
}
return transaction;
Unlike mentioned in the previous thread, I had no issue with the 2nd password functions (send) or similar. All there seem to work smooth.
A rework of CoinService against blockchain.info would certainly trigger a BTC-donation from my side, because then I do not have to do it, and the feature would then be available to the whole community through github. If you would consider such an undertaking, let me know (niklas.nikolajsen(at)bitcoinsuisse.ch).
from bitcoinlib.
There is no obvious way to get this library working with Blockchain.info
's RPC API from the moment they decided to diverge from bitcoin-core
's RPC API specification and their developer support is for from satisfactory.
from bitcoinlib.
Related Issues (20)
- Add createwallet HOT 1
- It produces errors with bitcoin core 0.17.1 HOT 4
- Add documentation comments to methods showing which units are returned HOT 1
- GetBlockResponse does not contain weight
- bitcoinlib support .net core? HOT 1
- NetworkHashPS exceeds Int64.Max resulting in overflow HOT 1
- GetRawMemPool(true) throws exception HOT 4
- Is this repo still maintained? HOT 6
- GetBlockTemplate no longer works HOT 4
- Add support for secure (.cookie) auth
- IsWalletEncrypted returns false positive
- Getting - Dummy value must be set to "" - after some of the method calls HOT 6
- Various 'Wallet' RPC Calls Require URL with '/wallet/<wallet-name>' appended HOT 1
- DecodeRawTransaction does not populate addresses
- GetAccount method returns empty string HOT 2
- ListSinceBlock passing wrong parameter by default HOT 4
- How to create transactions that carry messages in OP_RETURN HOT 2
- Getblocktemplate does not provide txid, only hash HOT 3
- No support for new label system HOT 4
- Exception while DumpWallet method HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bitcoinlib.