I'm working on a smart contract that allows users to pay for monthly subscriptions like Netflix, Amazon, etc…
I created a function fetchMysubscription within my smart contract that allows each user to fetch his subscription. It works just fine when I tested it on a remix IDE.
But when I called the function inside a function on the front end (React) so each user can fetch his subscription. The only subscription that appears is the owner of the contract subscription with his address and other information but when I tried to create another subscription with another address the subscription of the owner persisted.
Solidity:
struct Subscription {
address payable subscriber;
uint start;
uint nextPayment;
bool activated;
}
/* nested mapping from address to id to Subscription */
mapping(address => mapping(uint => Subscription)) private AllSubscriptions;
// /* User can fetch it own Loan */
function fetchMysubscription(uint256 planId) external view returns(
address subscriber,
uint start,
uint nextPayment,
bool activated
) {
Subscription storage currentSubscription = AllSubscriptions[msg.sender][planId];
if(currentSubscription.subscriber == msg.sender) {
return (
currentSubscription.subscriber,
currentSubscription.start,
currentSubscription.nextPayment,
currentSubscription.activated
);
}
}
React:
// /*Fetch Subscription */
async function fetchSubscription() {
const data = await blockchain.smartContract.methods.fetchMySubscription("0").call();
const status = (data.activated).toString();
let startDay = (moment.unix(data.start)).toString();
let nextPayment = (moment.unix(data.nextPayment)).toString();
let item = {
subscriber : data.subscriber,
start: startDay,
nextPayment: nextPayment,
activated: status
}
setSubscriptionData(item); // state of array
}
What I'm missing?
Best Answer
You shouldn't use
msg.sender
within a view function, since there's no transaction (msg) being sent. Read about the difference between a call and a transaction.To correctly fetch an account's subscription, you'll have to add an
address user
parameter to your call, which the caller will provide.Other improvements -
currentSubscription.subscriber == user
since you have a mapping that fetches the correct account in the first place.