0

I have noticed something very strange...

I have a smart contract with two functions. I am able to interact with all of them (In Remix, Web3 Provider Environment, pragma solidity ^0.8.2) perfectly well. However, when I try calling the same functions via my Dapp (HTML GUI), I am ONLY able to interact with ONE of my functions, and NOT with the other.

Please help me understand what is going on.

Find below a snippet of my solidity functions:

    struct CryptoGift {
    address from;
    address to;
    uint256 tokenId;
    string  tokenName;
    string  messageToRecipient;
    uint256 createdAt;
    uint256 firstReminderAt;
    uint256 transferDate;
}
  
CryptoGift[] private allGifts;
mapping(address => CryptoGift[]) private myGifts;

function viewAllGifts() public view returns ( CryptoGift[] memory ) {   
    return allGifts;   
}

function viewMyGifts() public view returns ( CryptoGift[] memory ) {        
    return myGifts[msg.sender];
}

In Remix, using ENVIRONENT: Web3 Provider ACCOUNT: 0xb35abE6Cbf39AF6b547dB36C4645140F1d807413, both functions viewAllGifts and viewMyGifts work perfectly as illustrated below:

illustrating that both functions work in the Remix environment

However, in my HTML file, the viewAllGifts works perfectly while the viewMyGifts doesn't work.

Find below a snippet from my viewMyGifts function in javascript:

contractMethods.viewMyGifts().call( ({}), (error, result)=> {
    console.log("Your in viewMyGifts"); 
    console.log("ethAddress: " +ethAddress);
    console.log("Result: " +result);
    console.log("Error: " +error);
  if(!error){ }
  else{}
});

The above code yeilds:

Your in viewMyGifts
ethAddress: 0xb35abe6cbf39af6b547db36c4645140f1d807413
Result: 
Error: null 

While...

contractMethods.viewAllGifts().call( ({}), (error, result)=> {
    console.log("Your in viewAllGifts"); 
    console.log("ethAddress: " +ethAddress);
    console.log("Result: " +result);
    console.log("Error: " +error);
  if(!error){ }
     else{}
 });



Your in viewAllGifts
ethAddress: 0xb35abe6cbf39af6b547db36c4645140f1d807413
Result: 0xb35abE6Cbf39AF6b547dB36C4645140F1d807413,0x22Eb94E0DD34B70B9E718595D71bF5CF3065b1c4,100,BOO,I love you Boo 0,0,1652339951,1652339981,1652340011,0xb35abE6Cbf39AF6b547dB36C4645140F1d807413,0x22Eb94E0DD34B70B9E718595D71bF5CF3065b1c4,101,BOO,I love you Boo 1,0,1652339957,1652339987,1652340017,0xb35abE6Cbf39AF6b547dB36C4645140F1d807413,0x22Eb94E0DD34B70B9E718595D71bF5CF3065b1c4,102,BOO,I love you Boo 2,0,1652339962,1652339992,1652340022,0xb35abE6Cbf39AF6b547dB36C4645140F1d807413,0x22Eb94E0DD34B70B9E718595D71bF5CF3065b1c4,103,BOO,I love you Boo 3,0,1652339967,1652339997,1652340027
app.js:36 Error: null

Your help is appreciated!

2 Answers 2

1

That's because you're using msg.sender in a view function.

This variable is used for transactions, but on read-only functions it's possible that msg.sender will be empty.

Change your function to -

function viewMyGifts(address account) public view returns ( CryptoGift[] memory ) {        
    return myGifts[account];
}
5
  • Thanks for the response. In response to your answer, you can use msg.sender in view/ read-only functions, the reason I am using it is merely to filter the results to reflect transactions that belong to the wallet holder /msg.sender, whereas the viewAllGifts() reflected the entire list of transactions that were unfiltered. Furthermore, if the wallet holder /msg.sender doesn't own any transactions then it should rightfully be empty
    – SirBT
    Commented May 13, 2022 at 8:46
  • Msg.sender is empty in view functions since they’re called without firing a transaction, hence no sending wallet. No need for private key, so no wallet. Does this answer your question?
    – Kof
    Commented May 13, 2022 at 14:55
  • On the contrary, msg.sender is NOT empty in view functions. Try out my solution, it actually works!
    – SirBT
    Commented May 14, 2022 at 2:32
  • 1
    That's because you're using hardhat / truffle... it will be empty when you deploy to production and call the method externally. msg.sender is not empty only if you (in hardhat) attach a wallet to the contract, but since it's not mandatory for the call, msg.sender should not be used on view functions. As mentioned in my answer, it's possible that msg.sender will be empty.
    – Kof
    Commented May 14, 2022 at 7:00
  • 1
    I appreciate your valuable contribution, as I had no idea it works differently in production. I will definitely update my code to reflect your solution.
    – SirBT
    Commented May 16, 2022 at 6:22
0

I feel kind of stupid X-D because the solution was so simple...

The solution, since it's an asynchronous method, was (yes you guessed it) to simply wrap the function in an Async/await as illustrated in the code below.

async function generateTheviewMyGiftsTiles (){
  await contractMethods.viewAllGifts().call( ({}), (error, result)=> {
    console.log("Your in viewAllGifts"); 
    console.log("ethAddress: " +ethAddress);
    console.log("Result: " +result);
    console.log("Error: " +error);

    if(!error){ }
    else{}
  });
}

The code above now yields the desired results.

The reason I wasn't getting any yields in the original code was merely because the compiler would call the contractMethods.viewAllGifts().call() function, but wouldnt wait for a any results and merely continue on to the next function. While wrapping the contractMethods.viewAllGifts().call() in an async/await forces the compiler to wait for the results of contractMethods.viewAllGifts().call() before continuing on to the next function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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