Skip to content

Instantly share code, notes, and snippets.

@kmjones1979
Created November 25, 2024 15:22
Show Gist options
  • Save kmjones1979/ddfda6b33cfd58ef1222d948e04a68e9 to your computer and use it in GitHub Desktop.
Save kmjones1979/ddfda6b33cfd58ef1222d948e04a68e9 to your computer and use it in GitHub Desktop.

Revisions

  1. kmjones1979 created this gist Nov 25, 2024.
    98 changes: 98 additions & 0 deletions FunctionsConsumer.sol
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,98 @@
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.28;

    import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
    import {FunctionsClient} from "./@chainlink/contracts/src/v0.8/functions/dev/1_0_0/FunctionsClient.sol";
    import {ConfirmedOwner} from "./@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol";
    import {FunctionsRequest} from "./@chainlink/contracts/src/v0.8/functions/dev/1_0_0/libraries/FunctionsRequest.sol";

    contract FunctionsConsumerExample is FunctionsClient, ConfirmedOwner, ERC721 {
    using FunctionsRequest for FunctionsRequest.Request;

    bytes32 public s_lastRequestId;
    bytes public s_lastResponse;
    bytes public s_lastError;

    uint256 public tokenId;
    mapping(address => bool) public accountMinted;

    error UnexpectedRequestID(bytes32 requestId);

    event Response(bytes32 indexed requestId, bytes response, bytes err);

    constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) ERC721("Credentials", "CRED") {}

    /**
    * @notice Send a simple request
    * @param source JavaScript source code
    * @param encryptedSecretsUrls Encrypted URLs where to fetch user secrets
    * @param donHostedSecretsSlotID Don hosted secrets slotId
    * @param donHostedSecretsVersion Don hosted secrets version
    * @param args List of arguments accessible from within the source code
    * @param bytesArgs Array of bytes arguments, represented as hex strings
    * @param subscriptionId Billing ID
    */
    function sendRequest(
    string memory source,
    bytes memory encryptedSecretsUrls,
    uint8 donHostedSecretsSlotID,
    uint64 donHostedSecretsVersion,
    string[] memory args,
    bytes[] memory bytesArgs,
    uint64 subscriptionId,
    uint32 gasLimit,
    bytes32 donID
    ) external onlyOwner returns (bytes32 requestId) {
    FunctionsRequest.Request memory req;
    req.initializeRequestForInlineJavaScript(source);
    if (encryptedSecretsUrls.length > 0) req.addSecretsReference(encryptedSecretsUrls);
    else if (donHostedSecretsVersion > 0) {
    req.addDONHostedSecrets(donHostedSecretsSlotID, donHostedSecretsVersion);
    }
    if (args.length > 0) req.setArgs(args);
    if (bytesArgs.length > 0) req.setBytesArgs(bytesArgs);
    s_lastRequestId = _sendRequest(req.encodeCBOR(), subscriptionId, gasLimit, donID);
    return s_lastRequestId;
    }

    /**
    * @notice Send a pre-encoded CBOR request
    * @param request CBOR-encoded request data
    * @param subscriptionId Billing ID
    * @param gasLimit The maximum amount of gas the request can consume
    * @param donID ID of the job to be invoked
    * @return requestId The ID of the sent request
    */
    function sendRequestCBOR(
    bytes memory request,
    uint64 subscriptionId,
    uint32 gasLimit,
    bytes32 donID
    ) external onlyOwner returns (bytes32 requestId) {
    s_lastRequestId = _sendRequest(request, subscriptionId, gasLimit, donID);
    return s_lastRequestId;
    }

    /**
    * @notice Store latest result/error
    * @param requestId The request ID, returned by sendRequest()
    * @param response Aggregated response from the user code
    * @param err Aggregated error from the user code or from the execution pipeline
    * Either response or error parameter will be set, but never both
    */
    function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override {
    if (s_lastRequestId != requestId) {
    revert UnexpectedRequestID(requestId);
    }
    s_lastResponse = response;
    s_lastError = err;
    emit Response(requestId, s_lastResponse, s_lastError);
    }

    function _mintCredentials(address _account) internal {
    require(!accountMinted[_account], "already minted");
    _mint(_account, tokenId);
    accountMinted[_account] = true;
    tokenId++;
    }
    }