Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/functions integration #11

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
9b37c67
add functions-toolkit and update hardhat version
koteld Oct 16, 2023
07772c5
refactor keepersRegistry.ts
koteld Oct 16, 2023
b24217f
add skipLibCheck to tsconfig.json for compatibility
koteld Oct 16, 2023
6037253
add functionsRouter class and externally callable methods
koteld Oct 16, 2023
febef3c
add functionsUtils class and externally callable methods
koteld Oct 16, 2023
d5a69c4
add utils to create/delete Gist
koteld Oct 16, 2023
06edf12
add Function Routers to registry; remove Function Oracles
koteld Oct 19, 2023
b586305
refactor functionsUtils: add DecodedResult type
koteld Oct 19, 2023
4bb2064
update inquirers with Function Routers
koteld Oct 19, 2023
dbefc25
update types and enums with Function Routers
koteld Oct 19, 2023
dbf09ba
update subtasks wih Functions Routers
koteld Oct 19, 2023
27c8888
update plugin registry tasks with Function Routers
koteld Oct 19, 2023
1ec8973
add tasks for Function Routers and utils
koteld Oct 19, 2023
87f21ed
set consumer address optional for createSubscription method
koteld Oct 19, 2023
8a0fbe7
Function Router -> Functions Router for consistency
koteld Oct 19, 2023
0a89fcd
add initialization method for FunctionsResponseListener
koteld Oct 21, 2023
9312b7a
add FunctionsRouterSubtasks to subtasks
koteld Oct 21, 2023
1f98265
add subtasks for Functions
koteld Oct 21, 2023
7ea9af7
add Functions to Hardhat Extended class
koteld Oct 21, 2023
e3be890
add Functions task
koteld Oct 21, 2023
fd38fd3
update Functions Router actions
koteld Oct 21, 2023
8986e23
modify timeoutRequests task for convenience
koteld Oct 22, 2023
539b438
expose create/delete Gist as tasks
koteld Oct 23, 2023
7746ed8
add subtasks to creat/delete Gist to subtasks enum
koteld Oct 23, 2023
e17601b
add wrapper for Functions Secrets Manager
koteld Oct 23, 2023
b9cf9b4
update subtasks definitions
koteld Oct 23, 2023
9680ac1
add Functions Secrets Manager to Hardhat Extended class
koteld Oct 23, 2023
c36a1b9
bump @chainlink/contracts version to 0.8.0
koteld Oct 25, 2023
90d3a39
update ChainlinkDirectRequestConsumer dependencies on @chainlink/cont…
koteld Oct 25, 2023
24ff856
update fixture contracts dependencies on @chainlink/contracts
koteld Oct 25, 2023
107f010
update arbitrum goerli fixture RPC endpoint
koteld Oct 25, 2023
9a5df39
refactor keepersRegistrar module
koteld Oct 25, 2023
1e3e6b8
refactor functionsRouter.ts
koteld Oct 25, 2023
88d6d3b
bump functions-toolkit version
koteld Oct 30, 2023
9034ee2
update Functions Routers plugin registry
koteld Oct 30, 2023
b872693
update Functions Router module: add overrides, fix typings, add stati…
koteld Oct 30, 2023
cbacdf3
add Functions Consumer module to sandbox
koteld Oct 30, 2023
c7caa16
add Functions Simulations module to sandbox
koteld Oct 30, 2023
cb272fc
update shared types
koteld Oct 30, 2023
251ec7a
add necessary shared enums
koteld Oct 30, 2023
d7610c0
update constants: add default Functions simulations parameters
koteld Oct 30, 2023
4a063db
update Functions Router HRE tasks
koteld Oct 30, 2023
5ab6649
add Functions Consumer and Functions Simulations HRE tasks
koteld Oct 30, 2023
a98c5c5
add Functions Consumer contract and update hardhat max solidity version
koteld Oct 30, 2023
628e74d
add Functions Consumer and Functions Simulations to hardhat extended …
koteld Oct 30, 2023
11e0bb6
add Functions Consumer and Functions Simulations to subtasks
koteld Oct 30, 2023
10594a7
code refactoring
koteld Oct 30, 2023
aa3e463
sandbox:node - code refactoring, add get VRF keys method
koteld Oct 30, 2023
1695979
update inquirers
koteld Oct 30, 2023
e4faad6
add tests for Functions Consumer and Functions Simulations, update fi…
koteld Oct 30, 2023
29bb3cd
add scripts to run Functions Consumer and Functions Simulations tests
koteld Oct 30, 2023
43c6845
bump package version
koteld Oct 30, 2023
fca1977
update README and DOCUMENTATION
koteld Oct 30, 2023
7cd601d
code refactoring and minor fixes
koteld Oct 30, 2023
5155fb6
functions -> functionsRouter in README
koteld Oct 30, 2023
f6e0514
README: move "Available Services" section
koteld Nov 3, 2023
8267ba0
update Functions Service plugin name + refactoring
koteld Nov 3, 2023
06df0b7
add suggested description for Functions Simulations
koteld Nov 3, 2023
a7a3ed6
remove customization for Functions request simulation
koteld Nov 3, 2023
1f0fb4a
rename Functions Service in the documentation
koteld Nov 3, 2023
55f78ef
change donIdHex -> donIdBytes32 in functions routers registry
koteld Nov 3, 2023
7720424
update README + code refactoring
koteld Nov 3, 2023
363d8c9
change encryptedSecretsUploadEndpoints -> gatewayUrls in Functions Ro…
koteld Nov 3, 2023
4c14376
update DOCUMENTATION.md - fix "stop response listener" section
koteld Nov 3, 2023
aeebf9b
remove exposing functions consumer as a service
koteld Jan 10, 2024
d0e50e8
code refactoring: rename variables
koteld Jan 10, 2024
38bc11e
update documentation
koteld Jan 10, 2024
fd2e690
run functions simulations as purely a deno-runtime execution
koteld Jan 10, 2024
9f1057e
update README.md
koteld Jan 12, 2024
c545b1d
rename: drConsumer -> directRequestConsumer
koteld Jan 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,20 +224,7 @@ It is useful for debugging and for checking whether the source code you supply t
> **Note**
Install [Deno](https://deno.com/) and add it to PATH, run ```deno --version``` to verify installation. Instructions: [https://deno.com/#installation](https://deno.com/#installation).

Before you run Functions request simulations, you can configure it.
To achieve this, additional parameters have been included in the `chainlink` group of `hardhat.config.ts`:
```ts
module.exports = {
chainlink: {
functions_simulation: {
port, // Ganache local blockchain port, default: "8546"
}
},
...
}
```

Once these parameters are specified, Functions requests simulations could be performed following the [sandbox documentation](SANDBOX.md#service-alias-functionssimulation).
Functions' requests simulations could be performed following the [sandbox documentation](SANDBOX.md#service-alias-functionssimulation).

### Local testing
> **Note**
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
"test:vrfCoordinator": "mocha --exit 'test/vrfCoordinator.test.ts'",
"test:automationRegistrar": "mocha --exit 'test/automationRegistrar.test.ts'",
"test:automationRegistry": "mocha --exit 'test/automationRegistry.test.ts'",
"test:functionsRouter": "mocha --exit 'test/functionsRouter.test.ts'",
"test:functions": "mocha --exit 'test/functionsRouter.test.ts'",
"test:functionsSimulation": "mocha --exit 'test/functionsSimulation.test.ts'",
"test": "yarn test:prepare && yarn test:dataFeed && yarn test:dataFeedProxy && yarn test:ensFeedsResolver && yarn test:feedRegistry && yarn test:l2FeedUptimeSequencer && yarn test:vrfCoordinator && yarn test:automationRegistrar && yarn test:automationRegistry && yarn test:functionsRouter",
"test": "yarn test:prepare && yarn test:dataFeed && yarn test:dataFeedProxy && yarn test:ensFeedsResolver && yarn test:feedRegistry && yarn test:l2FeedUptimeSequencer && yarn test:vrfCoordinator && yarn test:automationRegistrar && yarn test:automationRegistry && yarn test:functions",
"copyArtifacts": "copyfiles -a -f ./node_modules/@chainlink/contracts/abi/**/* chainlink-artifacts",
"removeArtifacts": "rm -rf chainlink-artifacts",
"compile": "hardhat compile",
Expand Down
44 changes: 18 additions & 26 deletions src/HardhatChainlink.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
import { DecodedResult } from "@chainlink/functions-toolkit/dist/decodeResult";
import {
CodeLanguage,
FunctionsResponse,
GatewayResponse,
Location,
RequestCommitment,
ReturnType,
ThresholdPublicKey,
} from "@chainlink/functions-toolkit/dist/types";
import * as functionsToolkit from "@chainlink/functions-toolkit";
import "@nomiclabs/hardhat-ethers";
import { BigNumber, BigNumberish, BytesLike } from "ethers";
import { HardhatRuntimeEnvironment } from "hardhat/types";
Expand Down Expand Up @@ -1184,7 +1175,7 @@ class Functions {

public timeoutRequests(
functionsRouterAddress: string,
requestCommitments: RequestCommitment[],
requestCommitments: functionsToolkit.RequestCommitment[],
overrides?: Overrides
): Promise<{ transactionHash: string }> {
return functions.timeoutRequests(
Expand Down Expand Up @@ -1220,7 +1211,7 @@ class Functions {
functionsRouterAddress: string,
requestId: string,
timeout?: number
): Promise<FunctionsResponse> {
): Promise<functionsToolkit.FunctionsResponse> {
return functions.listenForResponse(
this.hre,
functionsRouterAddress,
Expand All @@ -1235,7 +1226,7 @@ class Functions {
timeout?: number,
confirmations?: number,
checkInterval?: number
): Promise<FunctionsResponse> {
): Promise<functionsToolkit.FunctionsResponse> {
return functions.listenForResponseFromTransaction(
this.hre,
functionsRouterAddress,
Expand All @@ -1249,7 +1240,7 @@ class Functions {
public listenForResponses(
functionsRouterAddress: string,
subscriptionId: string,
callback: (functionsResponse: FunctionsResponse) => any
callback: (functionsResponse: functionsToolkit.FunctionsResponse) => any
): Promise<void> {
return functions.listenForResponses(
this.hre,
Expand All @@ -1274,7 +1265,7 @@ class Functions {
functionsRouterAddress: string,
donId: string
): Promise<{
thresholdPublicKey: ThresholdPublicKey;
thresholdPublicKey: functionsToolkit.ThresholdPublicKey;
donPublicKey: string;
}> {
return functions.fetchKeys(this.hre, functionsRouterAddress, donId);
Expand Down Expand Up @@ -1348,7 +1339,7 @@ class Functions {
donId: string,
gatewayUrls: string[]
): Promise<{
result: GatewayResponse;
result: functionsToolkit.GatewayResponse;
error?: string;
}> {
return functions.listDONHostedEncryptedSecrets(
Expand Down Expand Up @@ -1382,7 +1373,7 @@ class Functions {
toBlock?: number | "latest",
pastBlocksToSearch?: number,
overrides?: Overrides
): Promise<RequestCommitment> {
): Promise<functionsToolkit.RequestCommitment> {
return functions.fetchRequestCommitment(
this.hre,
functionsRouterAddress,
Expand Down Expand Up @@ -1440,10 +1431,10 @@ class Utils {
}

public async buildFunctionsRequestCBOR(
codeLocation: Location,
codeLanguage: CodeLanguage,
codeLocation: functionsToolkit.Location,
codeLanguage: functionsToolkit.CodeLanguage,
source: string,
secretsLocation?: Location,
secretsLocation?: functionsToolkit.Location,
encryptedSecretsReference?: string,
args?: string[],
bytesArgs?: string[]
Expand All @@ -1461,8 +1452,8 @@ class Utils {

public async decodeHexString(
resultHexstring: string,
expectedReturnType: ReturnType
): Promise<DecodedResult> {
expectedReturnType: functionsToolkit.ReturnType
): Promise<functionsToolkit.DecodedResult> {
return utils.decodeHexString(resultHexstring, expectedReturnType);
}
}
Expand Down Expand Up @@ -1633,12 +1624,13 @@ class FunctionsSimulation {

public async simulateRequest(
source: string,
args?: string[],
bytesArgs?: string[]
): Promise<DecodedResult> {
secrets: Record<string, string> | {},
args: string[] | [],
bytesArgs: string[] | []
): Promise<functionsToolkit.SimulationResult> {
return functionsSimulations.simulateRequest(
this.hre,
source,
secrets,
args,
bytesArgs
);
Expand Down
9 changes: 1 addition & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ export interface ChainlinkUserConfig {
pg_password?: string;
pg_db?: string;
};
functions_simulation: {
port?: number;
};
}

// Add our types to the Hardhat config
Expand All @@ -45,8 +42,7 @@ declare module "hardhat/types/config" {

extendConfig(
(config: HardhatConfig, userConfig: Readonly<HardhatUserConfig>) => {
const { confirmations, node, functions_simulation } =
userConfig.chainlink ?? {};
const { confirmations, node } = userConfig.chainlink ?? {};
config.chainlink = {
confirmations: confirmations || 1,
node: {
Expand All @@ -61,9 +57,6 @@ extendConfig(
pg_password: node?.pg_password,
pg_db: node?.pg_db,
},
functions_simulation: {
port: functions_simulation?.port,
},
};
}
);
Expand Down
86 changes: 7 additions & 79 deletions src/sandbox/functionsSimulations/index.ts
Original file line number Diff line number Diff line change
@@ -1,87 +1,15 @@
import * as functionsToolkit from "@chainlink/functions-toolkit";
danielgruesso marked this conversation as resolved.
Show resolved Hide resolved
import { DecodedResult } from "@chainlink/functions-toolkit/dist/decodeResult";
import { ReturnType } from "@chainlink/functions-toolkit/dist/types";
import { HardhatRuntimeEnvironment } from "hardhat/types";

import { DEFAULT_PORT } from "../../shared/constants";
import * as functionsConsumer from "../functionsConsumer";

export const simulateRequest = async (
hre: HardhatRuntimeEnvironment,
source: string,
args?: string[],
bytesArgs?: string[]
): Promise<DecodedResult> => {
const simulationDeployment =
await functionsToolkit.startLocalFunctionsTestnet(
undefined,
{},
hre.config.chainlink.functions_simulation?.port || DEFAULT_PORT
);

const provider = new hre.ethers.providers.JsonRpcProvider(
`http://localhost:${
hre.config.chainlink.functions_simulation?.port || DEFAULT_PORT
}/`
);
const admin = new hre.ethers.Wallet(
simulationDeployment.adminWallet.privateKey,
provider
);
const functionsConsumerAddress = await functionsConsumer.deploy(
hre,
simulationDeployment.functionsRouterContract.address,
simulationDeployment.donId,
{
signer: admin,
provider,
}
);

const subscriptionManager =
await hre.chainlink.functions.initializeSubscriptionManager(
simulationDeployment.functionsRouterContract.address,
simulationDeployment.linkTokenContract.address,
{
signer: admin,
provider,
}
);

const responseListener =
await hre.chainlink.functions.initializeResponseListener(
simulationDeployment.functionsRouterContract.address,
{
signer: admin,
provider,
}
);

const { subscriptionId } = await subscriptionManager.createSubscription(
functionsConsumerAddress
);

const juelsAmount = hre.ethers.utils.parseUnits("100", "ether");
await subscriptionManager.fundSubscription(juelsAmount, subscriptionId);

const { transactionHash } = await functionsConsumer.sendRequest(
hre,
functionsConsumerAddress,
subscriptionId,
secrets: Record<string, string>,
args: string[],
bytesArgs: string[]
): Promise<functionsToolkit.SimulationResult> => {
return functionsToolkit.simulateScript({
source,
"0xabcd",
functionsToolkit.Location.Remote,
secrets,
args,
bytesArgs,
100_000
);

const receipt = await provider.getTransactionReceipt(transactionHash);
const requestId = receipt.logs[0].topics[1];
const response = await responseListener.listenForResponse(requestId);

return hre.chainlink.utils.decodeHexString(
response.responseBytesHexstring,
ReturnType.string
);
});
};
8 changes: 5 additions & 3 deletions src/tasks/sandbox/functionsSimulation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ import * as functionsSimulations from "../../../sandbox/functionsSimulations";

export const simulateRequest: ActionType<{
source: string;
secrets?: string;
args?: string;
bytesArgs?: string;
}> = async (taskArgs, hre): Promise<string> => {
const secrets = taskArgs.secrets ? JSON.parse(taskArgs.secrets) : {};
const args = taskArgs.args
? taskArgs.args.split(",").map((value) => value.trim())
: [];
const bytesArgs = taskArgs.bytesArgs
? taskArgs.bytesArgs.split(",").map((value) => value.trim())
: [];
const decodedResult = await functionsSimulations.simulateRequest(
hre,
const simulationResult = await functionsSimulations.simulateRequest(
taskArgs.source,
secrets,
args,
bytesArgs
);
return decodedResult.toString();
return JSON.stringify(simulationResult);
};
6 changes: 1 addition & 5 deletions test/fixture-projects/hardhat/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ import { HardhatUserConfig } from "hardhat/types";
import "../../../src/index";

const config: HardhatUserConfig = {
chainlink: {
functions_simulation: {
secrets: { test: "hello world" },
},
},
chainlink: {},
};

export default config;
26 changes: 19 additions & 7 deletions test/functionsSimulation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,50 +17,62 @@ describe("Test chainlink:sandbox:functionsSimulation module [SKIP FOR GITHUB ACT
const result =
danielgruesso marked this conversation as resolved.
Show resolved Hide resolved
await this.hre.chainlink.sandbox.functionsSimulation.simulateRequest(
'return Functions.encodeString(secrets.test + " " + args[0] + " " + args[1] + bytesArgs[0] + bytesArgs[1])',
{ test: "hello" },
["hello", "world"],
["0x1234", "0x5678"]
);

expect(result).to.eq("hello world hello world0x12340x5678");
expect(result.capturedTerminalOutput).to.eq("");
expect(result.responseBytesHexstring).to.eq(
"0x68656c6c6f2068656c6c6f20776f726c64307831323334307835363738"
);
});
});

describe("Run methods as hre subtasks", function () {
it("Run functions simulation", async function () {
if (isGithubActions) this.skip();

const result = await this.hre.run(
const resultJSON = await this.hre.run(
`${PACKAGE_NAME}:${Task.functionsSimulation}:${FunctionsSimulationSubtask.simulateRequest}`,
{
source:
'return Functions.encodeString(secrets.test + " " + args[0] + " " + args[1] + bytesArgs[0] + bytesArgs[1])',
secrets: '{"test":"hello"}',
args: "hello, world",
bytesArgs: "0x1234, 0x5678",
}
);

expect(result).to.eq("hello world hello world0x12340x5678");
const result = JSON.parse(resultJSON);
expect(result.capturedTerminalOutput).to.eq("");
expect(result.responseBytesHexstring).to.eq(
"0x68656c6c6f2068656c6c6f20776f726c64307831323334307835363738"
);
});
});

describe("Run methods as subtasks of a hre task", function () {
it("Run functions simulation", async function () {
if (isGithubActions) this.skip();

const result = await this.hre.run(
const resultJSON = await this.hre.run(
`${PACKAGE_NAME}:${Task.functionsSimulation}`,
{
subtask: FunctionsSimulationSubtask.simulateRequest,
args: JSON.stringify({
source:
'return Functions.encodeString(secrets.test + " " + args[0] + " " + args[1] + bytesArgs[0] + bytesArgs[1])',
secrets: '{"test":"hello"}',
args: "hello, world",
bytesArgs: "0x1234, 0x5678",
}),
}
);

expect(result).to.eq("hello world hello world0x12340x5678");
const result = JSON.parse(resultJSON);
expect(result.capturedTerminalOutput).to.eq("");
expect(result.responseBytesHexstring).to.eq(
"0x68656c6c6f2068656c6c6f20776f726c64307831323334307835363738"
);
});
});
});