creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/AIOracleCallbackReceiver.sol": {
        "content": "// SampleContract.sol\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"./interfaces/IAIOracle.sol\";\n\n/// @notice A base contract for writing a AIOracle app\nabstract contract AIOracleCallbackReceiver {\n\n    // Address of the AIOracle contract\n    IAIOracle public immutable aiOracle;\n\n    // Invalid callback source error\n    error UnauthorizedCallbackSource(IAIOracle expected, IAIOracle found);\n\n    /// @notice Initialize the contract, binding it to a specified AIOracle contract\n    constructor(IAIOracle _aiOracle) {\n        aiOracle = _aiOracle;\n    }\n\n    /// @notice Verify this is a callback by the aiOracle contract \n    modifier onlyAIOracleCallback() {\n        IAIOracle foundRelayAddress = IAIOracle(msg.sender);\n        if (foundRelayAddress != aiOracle) {\n            revert UnauthorizedCallbackSource(aiOracle, foundRelayAddress);\n        }\n        _;\n    }\n\n    /**\n     * @dev the callback function in OAO, should add the modifier onlyAIOracleCallback!\n     * @param requestId Id for the request in OAO (unique per request)\n     * @param output AI model's output\n     * @param callbackData user-defined data (The same as when the user call aiOracle.requestCallback)\n     */\n    function aiOracleCallback(uint256 requestId, bytes calldata output, bytes calldata callbackData) external virtual;\n\n    function isFinalized(uint256 requestId) external view returns (bool) {\n        return aiOracle.isFinalized(requestId);\n    }\n}"
      },
      "contracts/interfaces/IAIOracle.sol": {
        "content": "// SampleContract.sol\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface IAIOracle {\n    /// @notice Event emitted upon receiving a callback request through requestCallback.\n    event AICallbackRequest(\n        address indexed account,\n        uint256 indexed requestId,\n        uint256 modelId,\n        bytes input,\n        address callbackContract,\n        uint64 gasLimit,\n        bytes callbackData\n    );\n\n    /// @notice Event emitted when the result is uploaded or update.\n    event AICallbackResult(\n        address indexed account,\n        uint256 indexed requestId,\n        address invoker,\n        bytes output\n    );\n\n    /**\n     * initiate a request in OAO\n     * @param modelId ID for AI model\n     * @param input input for AI model\n     * @param callbackContract address of callback contract\n     * @param gasLimit gas limitation of calling the callback function\n     * @param callbackData optional, user-defined data, will send back to the callback function\n     * @return requestID\n     */\n    function requestCallback(\n        uint256 modelId,\n        bytes memory input,\n        address callbackContract,\n        uint64 gasLimit,\n        bytes memory callbackData\n    ) external payable returns (uint256);\n\n    function estimateFee(uint256 modelId, uint256 gasLimit) external view returns (uint256);\n\n    function isFinalized(uint256 requestId) external view returns (bool);\n}"
      },
      "contracts/SimplePrompt.sol": {
        "content": "// SampleContract.sol\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"./interfaces/IAIOracle.sol\";\nimport \"./AIOracleCallbackReceiver.sol\";\n\n// this contract is for ai.ora.io website\ncontract SimplePrompt is AIOracleCallbackReceiver {\n\n    event promptsUpdated(\n        uint256 requestId,\n        string output,\n        bytes callbackData\n    );\n\n    event promptRequest(\n        uint256 requestId,\n        address sender, \n        uint256 modelId,\n        string prompt\n    );\n\n    struct AIOracleRequest {\n        address sender;\n        uint256 modelId;\n        bytes input;\n        bytes output;\n    }\n\n    address immutable owner;\n\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"Only owner\");\n        _;\n    }\n\n    // requestId => AIOracleRequest\n    mapping(uint256 => AIOracleRequest) public requests;\n\n    // modelId => callback gasLimit\n    mapping(uint256 => uint64) public callbackGasLimit;\n\n    /// @notice Initialize the contract, binding it to a specified AIOracle.\n    constructor(IAIOracle _aiOracle) AIOracleCallbackReceiver(_aiOracle) {\n        owner = msg.sender;\n        callbackGasLimit[50] = 200_000; // SD 500k\n        callbackGasLimit[11] = 1_500_000; // llama\n        callbackGasLimit[9] = 1_500_000; // grok\n    }\n\n    function setCallbackGasLimit(uint256 modelId, uint64 gasLimit) external onlyOwner {\n        callbackGasLimit[modelId] = gasLimit;\n    }\n\n    // the callback function, only the AI Oracle can call this function\n    function aiOracleCallback(uint256 requestId, bytes calldata output, bytes calldata callbackData) external override onlyAIOracleCallback() {\n        emit promptsUpdated(requestId, string(output), callbackData);\n    }\n\n    function estimateFee(uint256 modelId) public view returns (uint256) {\n        return aiOracle.estimateFee(modelId, callbackGasLimit[modelId]);\n    }\n\n    function calculateAIResult(uint256 modelId, string calldata prompt) payable external {\n        bytes memory input = bytes(prompt);\n        // we do not need to set the callbackData in this example\n        uint256 requestId = aiOracle.requestCallback{value: msg.value}(\n            modelId, input, address(this), callbackGasLimit[modelId], \"\"\n        );\n        emit promptRequest(requestId, msg.sender, modelId, prompt);\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 1000
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}