0

Consider the following basic solidity smart contract

     event BattleResult(string result,uint playerResult, uint enemyResult);
     mapping(address => uint)playerChoice;

     function setChoice(uint _number)public {
         playerChoice[msg.sender] = _number
        }

     function battle(address _target) public {
      playerValue = playerChoice[msg.sender];
      enemyValue = playerChoice[_target];
      if(playerValue > enemyValue){
       emit Battleresult("win",playerValue,enemyValue);
       }
      else if(playerValue < enemyValue){
       emit Battleresult("lose",playerValue,enemyValue);
       }
      else if(playerValue == enemyValue){
       emit Battleresult("draw",playerValue,enemyValue);
       }

}

In this basic example players choose a number and they set up a battle. Don't mind the security measures and the fact that players can check opponent's value before entering a battle.

The problem I have is that when I set up the battle on the frontend, I try to show the player the results (whatever is emited: win, lose or draw). The problem I have is that it is so impossible to filter information just for a specific player and everytime I try to do something I am getting no results in the console.

I tried

SmartcontractInstance.events.BattleResult({}, {fromBlock: 0}, function(error,event){
      console.log(event);
    })
  }

which allows me to get all the past events. However is there a way to get just the result from the specific battle?

For example, should I change my solidity smart contract and for each function add

returns(string,uint,uint)

One thing I tried to do is check the address and see if it matches the sender, then push it into the array and I would simply show the last index (this sounds inefficient but maybe is just my opinion).

let result =[];
    SmartcontractInstance.events.BattleResult({}, {fromBlock: 0}, function(error,event){
      for(let i=0; i<event.length;i++){
        if(event.args.address == account[0]){
          result.push(event.args.address);
        }
      }
    })
console.log(result);  /// i'm getting an empty array unfortunately
1

For example, should I change my solidity smart contract and for each function add

returns(string,uint,uint)

That won't do it. Return values are visible to other contracts but they are not visible externally.

The problem I have is that it is so impossible to filter information just for a specific player

You can filter events but you have to:

  • include the data to filter in the log
  • define it as indexed

E.g. event LogName(address indexed player, ...);

You can then configure an event filter on the observer side.

It's important to keep in mind how clients will rely on the event logs so everything they will need goes in there. Since contracts are immutable, everything any client will ever need.

A good starting point is to include all information that would be necessary to theoretically reconstruct the state history of the contract from logs.

Have a look over here for an example of consuming a log with indexed values. How could return events of specific args?

Hope it helps.

| improve this answer | |
  • 1
    Very helpful. The indexed definition for filtering is what I needed and didn't know it exist. The example you provided is also helpful – Iulian Jan 2 at 17:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.