1

i have a contract that inherits from ChainlinkClient to send requests to an API, this contract have 3 main functions :

function onTokenTransfer(
    address _sender,
    uint256 _fee,
    bytes calldata _data
) public {
    require(_fee >= fee, "NOT ENOUGH FUNDS");
    bytes memory data = _data[4:];
    uint256 _id = abi.decode(data, (uint256));
    requestVolumeData(_id);
}

function requestVolumeData(uint256 _id) public returns (bytes32 requestId) {
    Chainlink.Request memory req = buildChainlinkRequest(
        jobId,
        address(this),
        this.fulfill.selector
    );

    // do somthing with _id
    req.add(
        "get",
        "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD"
    );
    req.add("path", "RAW,ETH,USD,VOLUME24HOUR"); 
    int256 timesAmount = 10 ** 18;
    req.addInt("times", timesAmount);
    return sendChainlinkRequest(req, fee);
}

function fulfill(
    bytes32 _requestId,
    uint256 _volume
) public recordChainlinkFulfillment(_requestId) {
    emit RequestVolume(_requestId, _volume);
    volume = _volume;
}

When a user calls my contract using link.transferAndCall with an _id, the onTokenTransfer function calls requestVolumeData with the same _id, this function make a request to the node and the node returns the requested data to the fulfill function .

My question is : How can i get the value of the _id used in requestVolumeData in my fulfill function ??

My struct and (id=>struct) mapping :

struct Collab {
    address promoter;
    address client;
    string apiUrl;
    uint256 amount;

}

mapping(uint256 => Collab) public collabById;

1 Answer 1

2

You can store the _id into some state variable like:

uint256 id;

function requestVolumeData(uint256 _id) public returns (bytes32 requestId) {



    Collab memory collab;

    // You can set the values that you are having 

    collab.apiUrl = "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD";
    
    collab.promoter = msg.sender; // Or any other address that goes here

    collab.client = msg.sender; // Or any other address that goes here

    collab.amount = 0; // Setting this 0 for now, you can leave that too because by-default it's 0 only

    id = _id;

    collabById[id] = collab;

    Chainlink.Request memory req = buildChainlinkRequest(
        jobId,
        address(this),
        this.fulfill.selector
    );

    // do somthing with _id
    req.add(
        "get",
        "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD"
    );
    req.add("path", "RAW,ETH,USD,VOLUME24HOUR"); 
    int256 timesAmount = 10 ** 18;
    req.addInt("times", timesAmount);
    return sendChainlinkRequest(req, fee);
}

Then, in the fulfill() function, you can access the latest _id value using the id state variable:

function fulfill(
    bytes32 _requestId,
    uint256 _volume
) public recordChainlinkFulfillment(_requestId) {
    emit RequestVolume(_requestId, _volume);
    volume = _volume;
    // You can set the remaining values of the mapping struct here
    collabById[id].amount = volume;
}
6
  • i have a mapping (id =>Struct), so i want the user to tap his id so i can get the struct of his infos and work on it, thus i have multiple ids i can't store in single variable .
    – noro meb
    Commented Feb 3, 2023 at 11:31
  • 1
    @noromeb, yeah to store the ids in the mapping is possible too. Can you please share that part where you're trying to do that ? Commented Feb 3, 2023 at 11:56
  • 1
    @noromeb, I have updated the answer. Please check if that works for you. Commented Feb 3, 2023 at 12:27
  • 1
    Yes, it works perfectly thank you .
    – noro meb
    Commented Feb 3, 2023 at 12:42
  • 1
    @noromeb, you're welcome. Commented Feb 3, 2023 at 14:37

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.