In short:
- Been trying to access any data from a particular, chosen API url.
- Can view the JSON in browser, but can't call variable in Remix (which should change after SendRequest).
- Tried a wide variety of scenarios (from trying to access different values at the endpoint URL, or trying to access different data types from endpoint, etc), just to validate that I can access data from this URL. I.e. If I can access anything, then I can eventually access the data I want for the Block Magic Hackathon.
- Ideally, what I expect: String variable which was undefined when contract deployed, now has data when called in Remix (and this change should occur after using SendRequest function).
Source of the Error:
In functions.chain.link/polygon-amoy/ 'History' of Recent Fulfillments, the Callback function gives me a Green Tick, but the Computation shows an error:
Error: input into Functions.encodeString is invalid
Here is the API URL I am trying to access:
Note: I'm currently using my API Key in the URL for testing, and will move onto using Secrets in Chainlink Functions after I get this initial testing to fire. Thus this is the URL with the API Key removed:
https://api.sportmonks.com/v3/football/fixtures/date/2024-05-15&includes=scores
Here is my full, current test smart contract, only with the API URL switched out:
pragma solidity 0.8.19;
import {FunctionsClient} from "@chainlink/[email protected]/src/v0.8/functions/v1_0_0/FunctionsClient.sol";
import {ConfirmedOwner} from "@chainlink/[email protected]/src/v0.8/shared/access/ConfirmedOwner.sol";
import {FunctionsRequest} from "@chainlink/[email protected]/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol";
/**
* Request testnet LINK and ETH here: https://faucets.chain.link/
* Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: https://docs.chain.link/resources/link-token-contracts/
*/
/**
* @title GettingStartedFunctionsConsumer
* @notice This is an example contract to show how to make HTTP requests using Chainlink
* @dev This contract uses hardcoded values and should not be used in production.
*/
contract GettingStartedFunctionsConsumer is FunctionsClient, ConfirmedOwner {
using FunctionsRequest for FunctionsRequest.Request;
// State variables to store the last request ID, response, and error
bytes32 public s_lastRequestId;
bytes public s_lastResponse;
bytes public s_lastError;
// Custom error type
error UnexpectedRequestID(bytes32 requestId);
// Event to log responses
event Response(
bytes32 indexed requestId,
string unknownVar,
bytes response,
bytes err
);
// Router address - Hardcoded for Sepolia
// Now hardcoded for Amoy
// Check to get the router address for your supported network https://docs.chain.link/chainlink-functions/supported-networks
address router = 0xC22a79eBA640940ABB6dF0f7982cc119578E11De;
// JavaScript source code
// Fetch character name from the Star Wars API.
// Documentation: https://swapi.info/people
string source =
"const apiResponse = await Functions.makeHttpRequest({"
"url: 'API_URL_WITH_REQUIRED_API_KEY'"
"});"
"if (apiResponse.error) {"
"console.log('There was an error, sorry.');"
"throw new Error('Request failed, sorry.');"
"}"
"let dataPoint1 = apiResponse.data.id;"
"console.log(dataPoint1);"
"return Functions.encodeString(dataPoint1);";
//Callback gas limit
uint32 gasLimit = 300000;
// donID - Hardcoded for Sepolia
// Now hardcoded for Amoy
// Check to get the donID for your supported network https://docs.chain.link/chainlink-functions/supported-networks
bytes32 donID =
0x66756e2d706f6c79676f6e2d616d6f792d310000000000000000000000000000;
// State variable to store the returned character information
string public unknownVar;
/**
* @notice Initializes the contract with the Chainlink router address and sets the contract owner
*/
constructor() FunctionsClient(router) ConfirmedOwner(msg.sender) {}
/**
* @notice Sends an HTTP request for character information
* @param subscriptionId The ID for the Chainlink subscription
* @param args The arguments to pass to the HTTP request
* @return requestId The ID of the request
*/
function sendRequest(
uint64 subscriptionId,
string[] calldata args
) external onlyOwner returns (bytes32 requestId) {
FunctionsRequest.Request memory req;
req.initializeRequestForInlineJavaScript(source); // Initialize the request with JS code
if (args.length > 0) req.setArgs(args); // Set the arguments for the request
// Send the request and store the request ID
s_lastRequestId = _sendRequest(
req.encodeCBOR(),
subscriptionId,
gasLimit,
donID
);
return s_lastRequestId;
}
/**
* @notice Callback function for fulfilling a request
* @param requestId The ID of the request to fulfill
* @param response The HTTP response data
* @param err Any errors from the Functions request
*/
function fulfillRequest(
bytes32 requestId,
bytes memory response,
bytes memory err
) internal override {
if (s_lastRequestId != requestId) {
revert UnexpectedRequestID(requestId); // Check if request IDs match
}
// Update the contract's state variables with the response and any errors
s_lastResponse = response;
unknownVar = string(response);
s_lastError = err;
// Emit an event to log the response
emit Response(requestId, unknownVar, s_lastResponse, s_lastError);
}
}
Thanks for any time and assistance you can provide.
Happy to reply where I can, if further context or clarification is required.
return Functions.encodeString(dataPoint1)---> can you check the value of dataPoint1? is it undefined? i can see you've logged it in the next step, but cant tell if it was valid data. the error indicates that encodeString() is not receiving data of the type expected (i.e string)