I am trying to explore private data collection and I have written the chaincode in javascript. I am passing the proper collections file while instantiating the chaincode and while invoking the chaincode I am adding the transient data in request payload which looks like this :
const proposal_request = {
chaincodeId: chaincodeId,
fcn: functionName,
args: args,
chainId: channelCode,
txId: tx_id,
transientMap : { "private" : "test data"}
};
My chaincode file looks like this :
const shim = require('fabric-shim');
const util = require('util');
var PrivateDataChaincode = class {
// Initialize the chaincode
async Init(stub) {
console.log('<================> ::Private Data Chaincode Instantion:: <=================>');
return shim.success();
}
async Invoke(stub) {
console.log('<================> ::Private Data Chaincode Invocation:: <=================>');
let ret = stub.getFunctionAndParameters();
console.info(ret);
let method = this[ret.fcn];
console.info('methodName');
console.info(method);
if (!method) {
console.error('No method of name:' + ret.fcn + ' found');
return shim.error('No method of name:' + ret.fcn + ' found. \n UNKNOWN FUNCTION INVOCATION: ' + ret.fcn);
}
console.info('\nCalling method : ' + ret.fcn);
try {
let payload = await method(stub, ret.params);
return shim.success(payload);
} catch (err) {
console.log(err);
return shim.error(err);
}
}
async createPrivateDataInCollection(stub, args) {
if (args.length != 2) {
throw new Error('Incorrect number of arguments. Expecting 2');
}
// arg[0] has the collection name
// arg[1] has the key
console.info("============= START : Create Private data ===========");
// get the transient map
let transientData = stub.getTransient();
await stub.putPrivateData(args[0], args[1], transientData.map.private.value);
console.info('============= END : Create private data ===========');
}
async queryPrivateDataInCollection(stub, args) {
console.info('============= START : Query private Data ===========');
// arg[0] has the collection name
// arg[1] has the key
// query private data with argument
let allResults = await stub.getPrivateData(args[0], args[1]);
if (!allResults) {
throw shim.error("Can't get data from state");
}
console.log(allResults);
return allResults;
}
};
shim.start(new PrivateDataChaincode());
I am storing data using the createPrivateDataInCollection method and fetching the data using queryPrivateDataInCollection. The private data is getting stored correctly when I cross checked in the couch DB. The problem I am facing is that I am getting a blank response when I am querying the private data using queryPrivateDataInCollection method on some occasions. Sometimes I am able to see the data, while sometimes I am getting a blank response. Am I missing something important?
Related
I am working on a program that gets a list of workitems in the committed state from Azure DevOps for a specific area path and iteration path. My code is based on an example found at the following link: https://learn.microsoft.com/en-us/azure/devops/integrate/quickstarts/work-item-quickstart?view=azure-devops
The issue I am running into is when QueryByWiqlAsync() is called, the program terminates and there are no errors for why it terminated. Below is the code in question. I tried calling QueryByWiqlAsync() with and without the ConfigureAwait(false) and that did not seem to make a difference. Any suggestions on what to try or what to fix are appreciated.
static async void GetWorkItemsToTaskFromADO(string tfs_project, string accessToken)
{
var credentials = new VssBasicCredential(string.Empty, accessToken);
var wiql = new Wiql()
{
Query = #"Select [Id] From WorkItems WHERE [System.TeamProject] = 'SampleADOProject' AND [System.AreaPath] = 'Sample\ADO\AreaPath' AND [System.IterationPath] = 'Sample\ADO\IterationPath' AND [System.State] = 'Committed'"
};
using (var httpClient = new WorkItemTrackingHttpClient(new Uri(tfs_project), credentials))
{
try
{
var result = await httpClient.QueryByWiqlAsync(wiql).ConfigureAwait(false);
var ids = result.WorkItems.Select(item => item.Id).ToArray();
var fields = new[] { "System.Id", "System.Title", "System.State" };
var workItems = await httpClient.GetWorkItemsAsync(ids, fields, result.AsOf).ConfigureAwait(false);
// output results to test what came back...
foreach (var workItem in workItems)
{
Console.WriteLine(
"{0}\t{1}\t{2}",
workItem.Id,
workItem.Fields["System.Title"],
workItem.Fields["System.State"]
);
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
Console.Read();
}
}
}
I have build a Web-Application with the MEAN (MongoDB, Express, Angular, NodeJS) Stack and want to make multiple Subscriptions to my Backend while the second subscription needs the result data of the first subscription.
I already tried to implement multiple solutions by other people in my code with e.g. flatMap/mergeMap or with resolving promises but nothing worked for me. I know the showed code with nested subscriptions is not the right way how it works. However, my HTML code can show the first object in the transactions and account md-array.
transaction.service.ts:
export class TransactionsService {
private accounts: Account[] = [];
private account: Account;
private accountsUpdated = new Subject<{accounts: Account[]}>();
private transactions: Transaction[] = [];
private transactionsUpdated = new Subject<{transactions: Transaction[]}>();
private apiUrl = 'http://localhost:3000/api/accounts';
private apiUrlBS = 'http://localhost:3000/api/accounts/bs_demo';
constructor(private http: HttpClient, private router: Router, private as:AuthService) {}
//Check how many bank account token are in our database
checkQuantity(userid:string) {
return this.http.post(this.apiUrl + "/checkquantity", {userid});
}
//Get account data of bankaccount with index (if there are more than one bank account integrated)
getAccounts(userid: string, index: number) {
//DataSchema for the http request
const data = {userid, index};
//Making a HTTP Request to our Backend with sending out userid and the index of the bankaccount we want
return this.http.post<{message: string; accounts: any}>(this.apiUrl + "/get", data)
//Store bankaccounts and subaccounts in local storage
.subscribe(transformedAccountData => {
this.accounts = transformedAccountData.accounts;
this.accountsUpdated.next({accounts: [...this.accounts]});
})
, error => {
console.log('There was an error getting data');
this.clearToken();
return Observable.throw(error);
}
}
//Get transaction data of account with index of chosen bankaccount and the iban (if there is a subaccount)
getTransactions(transactionsPerPage: number, currentPage: number, iban: string, index:number, userid: string) {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json');
//Making a HTTP Request to our Backend with sending out iban of account, index of bakaccount and our userid
return this.http.post<{transactions: any}>(this.apiUrl + "/transactions", {iban, index, userid})
//Store transactions data of accounts and subaccounts in local storage
.subscribe(transformedTransactionData => {
this.transactions = transformedTransactionData.transactions;
this.transactionsUpdated.next({transactions: [...this.transactions]
});
}), error => {
console.log('There was an error getting data');
return Observable.throw(error);
};
}
//Listener for list-transactions.component.ts
getAccountsUpdateListener() {
return this.accountsUpdated.asObservable();
}
//Listener for list-transactions.component.ts
getTransactionsUpdateListener() {
return this.transactionsUpdated.asObservable();
}
list-transactions.component.ts:
export class ListTransactionsComponent implements OnInit {
accounts : Account[][];
transactions: Transaction[][];
totalAccounts = 0;
userlength;
isLoading = true;
tokenerror = false;
//Not interesting at this time
totalTransactions = 0;
transactionsPerPage = 2;
currentPage = 1;
pageSizeOptions = [1, 2, 5, 10];
//counter for our arrays because using the i and j variables does cause errors
countul = 0;
countacc = 0;
constructor(
public transactionsService: TransactionsService,
private as: AuthService,
private router:Router,
private changeDetectorRefs: ChangeDetectorRef)
{
this.accounts = [];
this.transactions = [];
}
//Load accounts and transactions of user
ngOnInit() {
//make loading spinner spinning
this.isLoading = true;
//check quantity of how many external bank account token we have stored in our database
this.transactionsService.checkQuantity(this.as.getUserId()).subscribe(accountData => {
this.userlength = accountData['length'];
var countul = 0;
var countacc = 0;
//check whether the request was successfull or we have surely one token in our databse
if(this.userlength === undefined || this.userlength === 0) {
this.tokenerror = true;
this.isLoading = false;
}
else {
for(var i = 0; i < this.userlength; i++) {
try {
//fetch transactions data of the account with index "countul" to our local storage
this.transactionsService.getAccounts(this.as.getUserId(), countul);
//Sort the account data of our specific accounts into our local array
this.transactionsService.getAccountsUpdateListener().subscribe((pageData: {accounts: Account[], accountsCount: number}) => {
this.totalTransactions = pageData.accountsCount;
var cache = new Array<Account>();
cache = pageData.accounts;
this.accounts[countul] = cache;
this.isLoading = false;
console.log(countul);
for(var j = 0; j < this.accounts[countul].length; j++) {
//fetch transactions data of the useraccount with index "countul" and subaccount with index "countacc" to our local storage
this.transactionsService.getTransactions(this.transactionsPerPage, this.currentPage, this.accounts[countul][countacc].iban, countul, this.as.getUserId());
//Printing some things to the console for testing purpose
console.log("countacc: "+countacc);
console.log(this.accounts[countul][countacc].iban);
//Sort the transaction data of our specific accounts into our local array
this.transactionsService.getTransactionsUpdateListener()
.subscribe((pageData2: {transactions: Transaction[], transactionCount: number}) => {
//Saving data in local array
this.totalTransactions = pageData2.transactionCount;
var cache2 = new Array<Transaction>();
cache2 = pageData2.transactions;
this.transactions[countacc] = cache2;
//Stop loading spinner
this.isLoading = false;
console.log("Transactions of account " +countacc + ": "+this.transactions[countacc]);
//Go to the transactions of the a possible subaccount
countacc++;
});
}
//Go to the next bankaccount
countul++;
});
//Stopping the code execution for some time
setTimeout(()=>{}, 2000);
}
catch (TypeError) {
//If Token of bankaccount is invalid, delete it
this.atTokenError();
}
}
}
});
}
The problem by executing this code is that my code is writing not only the first index of the array but also the second while the for-loop is just running one time trough. The following is shown in the console:
0
list-transactions.component.ts:160 **iban here**
list-transactions.component.ts:163 countacc: 0
list-transactions.component.ts:164 **iban here**
list-transactions.component.ts:178 Trans of acc 0: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
I hided the actual iban here. May anyone explain me what is the better solution for the nested subscriptions with nested dependecies?
#Niklas it looks like there's a lot going on here. Would you be able to elaborate/comment on the code or make a Stackblitz? Some more clarification on what's happening would help me help you more effectively. One thing that could help you is that it's cleaner to push your multiple child subscriptions into a subscriptions array (e.g. subscriptions.add(thisObservable.subscribe(foo => bar)) which will make unsubscribing subscriptions.unsubscribe() much easier.
Docs I am following: https://firebase.google.com/docs/firestore/query-data/query-cursors
I have code like below;
async List(query: any): Promise<Array<any>> {
let collectionQuery = super.GetCollectionReference();
if (query.VideoChannelId) {
collectionQuery = collectionQuery.where(
"VideoChannel.Id",
"==",
query.VideoChannelId
);
}
let startAfterDoc: any = "";
if (query.StartAfter) {
startAfterDoc = await super.GetDocumentReference(query.StartAfter);
}
collectionQuery = collectionQuery
.orderBy(query.OrderBy, "desc")
.startAfter(startAfterDoc)
.limit(query.Limit);
let items = await super.List(collectionQuery);
return items;
}
And utility methods:
GetDocumentReference(id: string): any {
return this.GetCollectionReference().doc(id);
}
async GetDocumentSnapshot(id: string): Promise<any> {
return await this.GetDocumentReference(id).get();
}
GetCollectionReference(): any {
return this.db.collection(this.CollectionName);
}
Regardless what ever value I pass for query.StartAfter it always returns top document in the collection.
I am pretty sure document exists with id query.StartAfter.
If I use GetDocumentSnapshot instead of GetCollectionReference, then I am getting parse error at firebase API.
Indexes has been added for query.OrderBy (CreateDate) and Id fields.
What possibly I would be missing here?
In the following sample program (using MassTransit, Azure ServiceBus), I am able to send messages to the queue, but my Receive Endpoint/Consumer does not seems to get the message. What am I doing wrong here? (Simple publish and a handler example given in this link(http://masstransit-project.com/MassTransit/quickstart.html) works fine!)
static async Task MainAsync(string[] args)
{
var bus = Bus.Factory.CreateUsingAzureServiceBus(cfg =>
{
var serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", "{sb}", "{sb-name}");
var host = cfg.Host(serviceUri, h =>
{
h.OperationTimeout = TimeSpan.FromSeconds(5);
h.TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(
"RootManageSharedAccessKey",
"{key}");
h.TransportType = TransportType.NetMessaging;
});
cfg.ReceiveEndpoint(host, "test_queue", ep =>
{
ep.Consumer<SayHelloCommandConsumer>();
});
});
bus.Start();
await SendAHello(bus);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
bus.Stop();
}
private static async Task SendAHello(IBusControl bus)
{
var sendToUri = new Uri("queue-end-point-address");
var endPoint = await bus.GetSendEndpoint(sendToUri);
await endPoint.Send<ISayHello>( new
{
Message = "Hello there !"
});
}
}
public class SayHelloCommandConsumer : IConsumer<ISayHello>
{
public Task Consume(ConsumeContext<ISayHello> context)
{
var command = context.Message;
return Console.Out.WriteLineAsync($"Recieved a message {command}");
}
}
public interface ISayHello
{
string Message { get; set; }
}
}
The queue address looked suspect, and it seems like you've corrected it.
I have small test smart contract, which is deployed to my test network. And I want to use a server to call the function in the contract. Here is the code:
payontime.sol
pragma solidity ^0.4.0;
contract payontime{
address public remitter;
address private remittee;
uint value;
bool public start;
/*Only owner can use these function*/
modifier onlyOwner(){
if(msg.sender != remitter) throw;
_;
}
/*Initialize the owner*/
function payontime(address receiver) payable{
remitter = msg.sender;
value = msg.value;
remittee = receiver;
start = true;
if(!remittee.send(value)){
throw;
}
}
function wakeUp() public returns (string){
return "success" ;
}
function getContractAddr() public returns(address){
return this;
}
/*Get the remittee*/
function getRemitee() public returns(address){
return remittee;
}
}
I use truffle serve and a webpage to new the contract.
app.js
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'
import payontime_artifacts from '../../build/contracts/payontime.json'
var payontime = contract(payontime_artifacts);
window.App = {
sendCoin : function(){
var sender = web3.eth.accounts[0];
var receiver = document.getElementById('receiver').value;
var amount = parseInt(document.getElementById('amount').value);
web3.eth.getBalance(receiver,function(error,result){
if(!error){
consol.log("Before transfer: " + result );
}else{
console.log("Error: " + error);
}
});
var newContract = payontime.new(receiver,{from:sender, value:amount}).then(
function(myPay){
console.log(myPay.getContractAddr.call());
}).then(
function(){
web3.eth.getBalance(receiver,function(error,result){
if(!error){
console.log("After transfer: " + result );
}else{
console.log("Error: " + error);
}
});
});
}
}
window.addEventListener('load', function() {
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
// Use Mist/MetaMask's provider
window.web3 = new Web3(web3.currentProvider);
} else {
console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
payontime.setProvider(web3.currentProvider);
});
app.js logs the address 0x1d379f2ab48ad20319e9f81cb45af415aa6f2966 , and I want to use this address to call the wakeUp() in the payontime.sol through another application index.js.
const Web3 = require('web3');
/* Connect to ethereum node */
const etherUrl = "http://localhost:8545";
const abi = [{"constant":false,"inputs":[],"name":"wakeUp","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"getContractAddr","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"remitter","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"start","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"getRemitee","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[{"name":"receiver","type":"address"}],"payable":true,"type":"constructor"}];
let web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider(etherUrl));
/*Call the function which already deployed on ethereum network
Notice: ABI have to modifeid when the smart contract code change*/
var contractInstance = web3.eth.contract(abi).at('0x1d379f2ab48ad20319e9f81cb45af415aa6f2966');
var reply = "false";
reply = contractInstance.wakeUp.call(function(error,result){
if(error){
console.log("Error");
throw error;
}else{
return result;
}
});
console.log(reply);
But there is an error message:
BigNumber Error: new BigNumber() not a base 16 number
I found it might be caused by not fully synced. I think it have some problem when I call the function in a deployed contract. So how can I call a deployed contract from web.js?
contractInstance.wakeUp.call is calling the function as constant, but the function is not defined as constant:
function wakeUp() public returns (string){
return "success" ;
}
has to be:
function wakeUp() public constant returns (string){
return "success" ;
}
If your Solidity function doesn't change the blockchain state and is just reading data, you should define it as constant.
As well as putting your console log within the call back, you can fix the big number error with:
console.log(result.toNumber());