Skip to content

Commit

Permalink
Adds function test contract (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
kgrofelnik authored Apr 2, 2024
1 parent 7cc5e1d commit df6184e
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 32 deletions.
107 changes: 107 additions & 0 deletions contracts/contracts/Test.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

// Uncomment this line to use console.log
// import "hardhat/console.sol";


interface IOracle {
function createFunctionCall(
uint functionCallbackId,
string memory functionType,
string memory functionInput
) external returns (uint i);

function createKnowledgeBaseQuery(
uint kbQueryCallbackId,
string memory cid,
string memory query,
uint32 num_documents
) external returns (uint i);
}

contract Test {
address private owner;
address public oracleAddress;
string public lastResponse;
string public lastError;
uint private callsCount;

event OracleAddressUpdated(address indexed newOracleAddress);

constructor(
address initialOracleAddress
) {
owner = msg.sender;
oracleAddress = initialOracleAddress;
}

modifier onlyOwner() {
require(msg.sender == owner, "Caller is not owner");
_;
}

modifier onlyOracle() {
require(msg.sender == oracleAddress, "Caller is not oracle");
_;
}

function setOracleAddress(address newOracleAddress) public onlyOwner {
oracleAddress = newOracleAddress;
emit OracleAddressUpdated(newOracleAddress);
}

function callFunction(string memory name, string memory message) public returns (uint i) {
uint currentId = callsCount;
callsCount = currentId + 1;

lastResponse = "";
lastError = "";

IOracle(oracleAddress).createFunctionCall(
currentId,
name,
message
);

return currentId;
}

function queryKnowledgeBase(string memory cid, string memory query) public returns (uint i) {
uint currentId = callsCount;
callsCount = currentId + 1;

lastResponse = "";
lastError = "";

IOracle(oracleAddress).createKnowledgeBaseQuery(
currentId,
cid,
query,
3
);
return currentId;
}

function onOracleFunctionResponse(
uint runId,
string memory response,
string memory errorMessage
) public onlyOracle {
lastResponse = response;
lastError = errorMessage;
}

function onOracleKnowledgeBaseQueryResponse(
uint runId,
string [] memory documents,
string memory errorMessage
) public onlyOracle {
string memory newContent = "";
for (uint i = 0; i < documents.length; i++) {
newContent = string(abi.encodePacked(newContent, documents[i], "\n"));
}
lastResponse = newContent;
lastError = errorMessage;
}
}
3 changes: 2 additions & 1 deletion contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {HardhatUserConfig} from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "./tasks/whitelist";
import "./tasks/deployChatWithRAG";
import "./tasks/deployments";
import "./tasks/functions";

require('dotenv').config()

Expand Down
2 changes: 2 additions & 0 deletions contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"deployAll:localhost": "npx hardhat run scripts/deployAll.ts --network localhost",
"deployAll:galadriel": "npx hardhat run scripts/deployAll.ts --network galadriel",
"deployQuickstart": "npx hardhat run scripts/deployQuickstart.ts --network galadriel",
"deployTest:localhost": "npx hardhat run scripts/deployTest.ts --network localhost",
"deployTest:galadriel": "npx hardhat run scripts/deployTest.ts --network galadriel",
"callQuickstart": "npx hardhat run scripts/callQuickstart.ts --network galadriel"
},
"devDependencies": {
Expand Down
28 changes: 28 additions & 0 deletions contracts/scripts/deployTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {ethers} from "hardhat";


async function main() {
if (!process.env.ORACLE_ADDRESS) {
throw new Error("ORACLE_ADDRESS env variable is not set.");
}
const oracleAddress: string = process.env.ORACLE_ADDRESS;
await deployTest(oracleAddress);
}


async function deployTest(oracleAddress: string) {
const contract = await ethers.deployContract("Test", [oracleAddress], {});

await contract.waitForDeployment();

console.log(
`Test contract deployed to ${contract.target}`
);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
29 changes: 0 additions & 29 deletions contracts/scripts/start_chat.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,3 @@ task("deployChatWithRAG", "Deploys the chat contract with knowledge base")
await contract.waitForDeployment();
console.log(`RAG deployed to: ${contract.target}`);
});


133 changes: 133 additions & 0 deletions contracts/tasks/functions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { task } from "hardhat/config";
import { Contract, TransactionReceipt } from "ethers";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { Func } from "mocha";

interface FunctionResponse {
response: string,
error: string,
}

task("web_search", "Calls the web search function")
.addParam("contractAddress", "The address of the Test contract")
.addParam("query", "The query to ask the contract")
.setAction(async (taskArgs, hre) => {
const contractAddress = taskArgs.contractAddress;
const query = taskArgs.query;

const contract = await getContract("Test", contractAddress, hre);
const response = await queryContractFunction(contract, "web_search", query, hre);
console.log(response)
if (response.error.length > 0) {
process.exit(1);
}
});

task("image_generation", "Calls the image generation function")
.addParam("contractAddress", "The address of the Test contract")
.addParam("query", "The query to ask the contract")
.setAction(async (taskArgs, hre) => {
const contractAddress = taskArgs.contractAddress;
const query = taskArgs.query;

const contract = await getContract("Test", contractAddress, hre);
const response = await queryContractFunction(contract, "image_generation", query, hre);
console.log(response)
if (response.error.length > 0) {
process.exit(1);
}
});

task("code_interpreter", "Calls the code interpreter function")
.addParam("contractAddress", "The address of the Test contract")
.addParam("query", "The query to ask the contract")
.setAction(async (taskArgs, hre) => {
const contractAddress = taskArgs.contractAddress;
const query = taskArgs.query;

const contract = await getContract("Test", contractAddress, hre);
const response = await queryContractFunction(contract, "code_interpreter", query, hre);
console.log(response)
if (response.error.length > 0) {
process.exit(1);
}
});

task("knowledge_base", "Queries a knowledge base")
.addParam("contractAddress", "The address of the Test contract")
.addParam("cid", "The CID of the knowledge base")
.addParam("query", "The query to ask the knowledge base")
.setAction(async (taskArgs, hre) => {
const contractAddress = taskArgs.contractAddress;
const cid = taskArgs.cid;
const query = taskArgs.query;

const contract = await getContract("Test", contractAddress, hre);
const response = await queryContractKnowledgeBase(contract, cid, query, hre);
console.log(response)
if (response.error.length > 0) {
process.exit(1);
}
});

async function getContract(
name: string,
contractAddress: string,
hre: HardhatRuntimeEnvironment
): Promise<Contract> {
const signer = (await hre.ethers.getSigners())[0];
const ContractArtifact = await hre.artifacts.readArtifact(name);
return new hre.ethers.Contract(contractAddress, ContractArtifact.abi, signer);
}

async function queryContractFunction(
contract: Contract,
tool: string,
query: string,
hre: HardhatRuntimeEnvironment
): Promise<FunctionResponse> {
try {
const txResponse = await contract.callFunction(tool, query);
await txResponse.wait();
process.stdout.write("Waiting for response");
let response = await contract.lastResponse();
let error = await contract.lastError();
while (response.length === 0 && error.length === 0) {
await new Promise((resolve) => setTimeout(resolve, 1000));
response = await contract.lastResponse();
error = await contract.lastError();
process.stdout.write(".");
}
console.log("");
return { response: response, error: error };
} catch (error) {
console.error(`Error calling contract function: ${error}`);
}
return { response: "", error: "Failed XX"};
}

async function queryContractKnowledgeBase(
contract: Contract,
cid: string,
query: string,
hre: HardhatRuntimeEnvironment
): Promise<FunctionResponse> {
try {
const txResponse = await contract.queryKnowledgeBase(cid, query);
await txResponse.wait();
process.stdout.write("Waiting for response");
let response = await contract.lastResponse();
let error = await contract.lastError();
while (response.length === 0 && error.length === 0) {
await new Promise((resolve) => setTimeout(resolve, 1000));
response = await contract.lastResponse();
error = await contract.lastError();
process.stdout.write(".");
}
console.log("");
return { response: response, error: error };
} catch (error) {
console.error(`Error calling contract function: ${error}`);
}
return { response: "", error: "Failed XX"};
}

0 comments on commit df6184e

Please sign in to comment.