I have a trouble when I want to get query result in my fabric. I have 2 channels, channel 1 stored account data, channel 2 stored some content and their cost. I am in channel 1,I want to query a content's cost in channel2,then "buy" it in channel 1. For example,channel1 have an account A and he has $20,channel2 have a movie cost $9, A wants to query the cost of the movie, then "buy" it, so A only have $11 now. But now I don't know how to get the "$9" from channel2. How can I do it?
Fabric uses channels as a form of isolation.
How ever you can invoke another chaincode using 'InvokeChaincode' API.
// InvokeChaincode locally calls the specified chaincode `Invoke` using the
// same transaction context; that is, chaincode calling chaincode doesn't
// create a new transaction message.
// If the called chaincode is on the same channel, it simply adds the called
// chaincode read set and write set to the calling transaction.
// If the called chaincode is on a different channel,
// only the Response is returned to the calling chaincode; any PutState calls
// from the called chaincode will not have any effect on the ledger; that is,
// the called chaincode on a different channel will not have its read set
// and write set applied to the transaction. Only the calling chaincode's
// read set and write set will be applied to the transaction. Effectively
// the called chaincode on a different channel is a `Query`, which does not
// participate in state validation checks in subsequent commit phase.
// If `channel` is empty, the caller's channel is assumed.
InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response
Source
Related
I am trying to do a Dapp with Nodejs and truffle. I have a solidity contract that works fine and I would like to use the method getTransactionReceipt() from the web3 library to print in console the result, but I dont know how.
The thing is that I have different functions in the nodejs app that call the functions in the solidity contract, and just after I call those contract function and the transaction is finished, I want to print that transaction info, but to use the method getTransactionReceipt() I need the transaction hash, ¿how can I get it?
as per web3.js documentation
web3.eth.getTransaction(transactionHash [, callback])
above line returns a transaction matching the given transaction hash.
also
web3.eth.getTransactionReceipt(hash [, callback])
above line returns the receipt of a transaction by transaction hash.
Note: The receipt is not available for pending transactions and returns null.
I am trying to create a discord bot using node.js. I want the bot to send a welcome message. At the moment I copied the channel_id of the the welcome channel from discord. Though I want to write code to get the id of the welcome channel by its name. (Or if there is another more effective method). Using discord.js v13.
Get the channel from cache by using Guild#channels. That includes a cache property which has all the channels the bot can see in it[1]. Use the find() method on it and compare the name
// remember channel names can only be lowercase and have no spaces
const channel = guild.channels.cache.find(channel => channel.name === "channel-name");
console.log(channel.id)
One drawback here is that multiple channels can have the same name, unlike IDs, which is why people prefer using IDs instead of name or other properties
[1]: All channels are cached by default, so no need to fetch from API
Fetch the channels of the guild and then find in the cache by its name
<Guild>.channels.fetch().then(channels => channels.cache.find(c=> c.name === "channel_name_here"))
Use Guild.channels to get the list of channels in the server, then loop through them using the fetch() method to find a channel with a matching name.
I'm using NodeJs to write the Hyperledger Fabric chaincode v2.x and using const { Contract } = require('fabric-contract-api')
I have 2 sets of chaincode, one to maintain the user and its wallet amount, and 2nd contract has the information about the asset e.g. quantity, price, name, etc.
I wanted to transfer the asset some quantity from user1 to user2 and wanted to deduct money from user1's account and transfer it to user2's account.
How can I call the function of transfer from the user contract inside the asset contract?
Yes, you can call one chain code function in another chain code .
You can find a few more information in the below link:
https://hyperledger.github.io/fabric-chaincode-node/release-2.2/api/fabric-shim.ChaincodeStub.html#invokeChaincode__anchor
As there is nothing like a piece of code to explain how the SDK works, I would like to offer the following which may help. The exchangeAsset is a method signature on the current contract. It receives as parameters, the AssetId and the buyerId.
async exchangeAsset(ctx, assetId, buyerId) {
Further down in this contract method, there is a need to make a cross contract call to the client contract, which contains information on buyers and sellers. First create an array containing the name of the function to call and the number of parameters required e.g.
let values = new Array("readKeyValue", buyerId);
Then make the call using the following
let buyer = await this.crossChannelRead(
ctx,
"client",
[...values],
"channelname"
);
The "client" string is the name of the other contract to call.
The values array is spread and will read as readKeyValue, buyerId, which means use the readKeyValue function and use buyerId as the parameter.
The "channelname" as shown above will actually be the name of the channel where the contract can be found.
As you know there is chance to have multiple transaction in one block , depend on the batch size and orderer configuration.
I need to make only one call to return all transaction inside the block not one by one.
I could retrieve one transaction with queryTransaction by using fabric SDK.
like
let response_payload = await channel.queryTransaction(trxnID, peer);
First Approach: implement a chanincode function and pass the block number which comes from eventHub along the method then inside the chaincode retrieve all transaction Ids and then make a query to find all transaction then stitch all together as result.
Second Approach:
retrieve the block inside with fabric sdk then parse all signed proposal in the payload of the block content.
Third Approach:
retrieve the block inside with fabric sdk then retrieve the transaction ids or keys in the payload and then make a couch db query to retrieve all content .
Which approach do you think is more reasonable if not what is your suggestion?
If you have a your client set up correctly, there should be a
LedgerClient which has a function like
QueryBlock(blockNumber uint64, options ...ledger.RequestOption) (*common.Block, error)
Once you have the block, you can pull the data out of it
block, _ := QueryBlock(37)
data := block.GetData().GetData()
data is a [][]byte, and each entry is one transaction.
I am using cqrs and ddd to build my application.
I have an account entity, a transaction entity and a transactionLine entity. A transaction contains multiple transactionLines. Each transactionLine has an amount and points to an account.
If a user adds a transactionLine in a transaction that already has a transactionLine that points to the same account as the one the new transactionLine, I want to simply add the new transactionLine amount to the existing one, preventing a transaction from having two transactionLines that point to the same account.
Ex :
Before command :
transaction
transactionLine1(amount=100, account=2)
transactionLine2(amount=50, account=1)
Command :
addNewTransaction(amount=25, account=1)
Desired result :
transaction
transactionLine1(amount=100, account=2)
transactionLine2(amount=75, account=1) // Add amount (50+25) instead of two different transactionLines
instead of
transaction
transactionLine1(amount=100, account=2)
transactionLine2(amount=50, account=1)
transactionLine3(amount=25, account=1) // Error, two different transactionLines point to the same account
But I wonder if it is best to handle this in the command or the event handler.
If this case is handled by the command handler
Before command :
transaction
transactionLine1(amount=100, account=2)
transactionLine2(amount=50, account=1)
Command :
addNewTransaction(amount=25, account=1) // Detects the case
Dispatches event
transactionLineAmountChanged(transactionLine=2, amount=75)
AddTransactionLine command is received
Check if a transactionLine exists in the new transactionLine's transaction with the same account
If so, emit a transactionAmountChangedEvt event
Otherwise, emit a transactionAddedEvt event
Corresponding event handler handles the right event
If this case is handled by the event handler
Before command :
transaction
transactionLine1(amount=100, account=2)
transactionLine2(amount=50, account=1)
Command :
addNewTransaction(amount=25, account=1)
Dispatches event
transactionLineAdded(transactionLine=3, amount=25)
Handler // Detects the case
transactionLine2.amount = 75
AddTransactionLine command is received
TransactionLineAdded event is dispatched
TransactionLineAdded is handled
Check if the added transaction's transactionLine points to the same account as an existing transactionLine in this account
If so, just add the amount of the new transactionLine to the existing transactionLine
Otherwise, add a new transactionLine
Neither commands nor events should contain domain logic, only the domain should contain the domain logic. In your domain, aggregate roots represent transaction boundaries (not your transaction entities, but transactions for the logic). Handling logic within commands or events would bypass those boundaries and make your system very brittle.
The right place for that logic is the transaction entity.
So the best way would be
AddTransactionCommand finds the correct transaction entity and calls
Transaction.AddLine(...), which does the logic and publishes events of what happened
TransactionLineAddedEvent or TransactionLineChangedEvent depending on what happened.
Think of commands and events as 'containers', 'dtos' of data that you are going to need in order to hydrate your AggregateRoots or send out to the world (event) for other Bounded Contexts to consume them. That's it. Any other operation that is strictly related to your Domain has no place but your AggregateRoots, Entities and Value Objects.
You can add some 'validation' to your Commands, either by using DataAnnotations or your own implementation of a validate method.
public interface ICommand
{
void Validate();
}
public class ChangeCustomerName : ICommand
{
public string Name {get;set;}
public void Validate()
{
if(Name == "No one")
{
throw new InvalidOperationException("Sorry Aria Stark... we need a name here!");
}
}
}