1

Say I just wanted to get a list of all transactions that involved a specific asset (assuming I would need a query for this?). Should I use the TransactionRegistry or the Historian? What's the difference?

atkayla
  • 8,143
  • 17
  • 72
  • 132

2 Answers2

2

we have a current issue open for Historian to show history of changes/ deltas for a particular asset - https://github.com/hyperledger/composer/issues/991 As a workaround you can do the following - so for sample network trade-network with an asset Commodity (and a transaction class 'Trade') you could create a query eg:

query selectTransaction {description: "choose specific commodity asset"
     statement: SELECT org.acme.biznet.Trade 
       WHERE (commodity == _$commodity ) } 

On the difference:

Historian records all transaction activities (eg. create Asset, create participant, create identity etc etc - and also business network specific custom transactions like 'TransferAsset' or 'PlaceOrder') including (where assets / participants are concerned) what changed.

For the TransactionRegistry itself (ie a particular class - say 'TransferAsset' or 'PlaceOrder') this is stored in the Transaction registry for that class - you may have many Transaction classes in your business network. But nothing in here would be related to other activities, such as system activities, that also recorded in Historian records.

to query - you would do something like this (in a query file for example):

query myTransactions{
description: "return all transactions made (ie system transactions)"
  statement: SELECT org.acme.sample.PlaceOrder
}

ie SELECT org.acme.sample.NAME_OF_TRANSACTION_CLASS

For Historian queries - eg

SELECT org.hyperledger.composer.system.HistorianRecord WHERE (transactionType == 'myTranType'

see more examples here -> https://www.ibm.com/developerworks/cloud/library/cl-create-powerful-blockchain-queries-with-hyperledger-composer/index.html

Paul O'Mahony
  • 6,740
  • 1
  • 10
  • 15
  • Thanks for answering my questions all the time. Great work on Hyperledger Composer, and I'm loving it so far! – atkayla Feb 16 '18 at 15:06
  • @PaulO'Mahony- what if I further want to see the data I received in this transaction? – Varun Mar 22 '18 at 09:35
  • either `return this.httpClient.get('http://localhost:3000/api/Trade?filter=%7B%22include%22%3A%22resolve%22%7D', {withCredentials: true}).toPromise();` (with authentication) or `return this.httpClient.get('http://localhost:3000/api/Trade?filter=%7B%22include%22%3A%22resolve%22%7D').toPromise(); – Paul O'Mahony Mar 23 '18 at 16:10
0

furthermore, to see the transaction data (deltas) for the asset id you're zoning in on - ie available through the transactionInvoked field of the transaction class (eg org.acme.trading.Trade transaction class). you could use REST APIs with loopback filters -eg either (both return a promise below):

return this.httpClient.get('http://localhost:3000/api/Trade?filter=%7B%22include%22%3A%22resolve%22%7D', {withCredentials: true}).toPromise();`

or return this.httpClient.get('http://localhost:3000/api/Trade?filter=%7B%22include%22%3A%22resolve%22%7D').toPromise();

which has the {"include":"resolve"} filter to resolve relationships in the transaction class - each resolved transaction has the transaction deltas. Then you could look for the asset id in question.

Sample unresolved transaction class (below, followed by resolved txn class):

Not resolved:

[ { "$class": "org.acme.mynetwork.Trade", "commodity": "resource:org.acme.mynetwork.Commodity#1", "newOwner": "resource:org.acme.mynetwork.Trader#2", "transactionId": "354dca97fc6ac00aabbd923883e3ec2a3d09b8c75a54a8f536a88b6df31e8a0f", "timestamp": "2018-03-23T12:02:11.228Z" }, { "$class": "org.acme.mynetwork.Trade", "commodity": "resource:org.acme.mynetwork.Commodity#2", "newOwner": "resource:org.acme.mynetwork.Trader#1", "transactionId": "9da43acca718633ac8870e6ea34c3c9f481194e48bcdba42673570177091809f", "timestamp": "2018-03-23T12:02:31.294Z" } ] Resolved with {"include":"resolve"} as a filter: [ { "$class": "org.acme.mynetwork.Trade", "commodity": { "$class": "org.acme.mynetwork.Commodity", "tradingSymbol": "1", "description": "werwer", "mainExchange": "wrrewer", "quantity": 10, "owner": { "$class": "org.acme.mynetwork.Trader", "tradeId": "2", "firstName": "tes2t", "lastName": "test" } }, "newOwner": { "$class": "org.acme.mynetwork.Trader", "tradeId": "2", "firstName": "tes2t", "lastName": "test" }, "transactionId": "354dca97fc6ac00aabbd923883e3ec2a3d09b8c75a54a8f536a88b6df31e8a0f", "timestamp": "2018-03-23T12:02:11.228Z" }, { "$class": "org.acme.mynetwork.Trade", "commodity": { "$class": "org.acme.mynetwork.Commodity", "tradingSymbol": "2", "description": "Ut fugiat.", "mainExchange": "ACE2", "quantity": 10, "owner": { "$class": "org.acme.mynetwork.Trader", "tradeId": "1", "firstName": "test", "lastName": "test" } }, "newOwner": { "$class": "org.acme.mynetwork.Trader", "tradeId": "1", "firstName": "test", "lastName": "test" }, "transactionId": "9da43acca718633ac8870e6ea34c3c9f481194e48bcdba42673570177091809f", "timestamp": "2018-03-23T12:02:31.294Z" } ]

Paul O'Mahony
  • 6,740
  • 1
  • 10
  • 15