Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ jobs:
BASE_RPC: ${{ secrets.BASE_HTTP_PROVIDER }}
BASE_SEPOLIA_RPC: ${{ secrets.BASE_SEPOLIA_HTTP_PROVIDER }}
CELO_RPC: ${{ secrets.CELO_HTTP_PROVIDER }}
AVALANCHE_RPC: ${{ secrets.AVALANCHE_HTTP_PROVIDER }}
ETHERSCAN_KEY: ${{ secrets.ETHERSCAN_KEY }}
runs-on: ubuntu-latest
steps:
Expand Down
1 change: 1 addition & 0 deletions example.env
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ SEPOLIA_RPC=
BASE_RPC=
BASE_SEPOLIA_RPC=
CELO_RPC=
AVALANCHE_RPC=
ETHERSCAN_KEY=

4 changes: 4 additions & 0 deletions modules/haberdasher-labs_passthrough-module_v0.1.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@
{
"chainId": "42220",
"block": "22842477"
},
{
"chainId": "43114",
"block": "64681307"
}
],
"creationArgs": {
Expand Down
173 changes: 173 additions & 0 deletions test/avalancheDeployments.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import {
HatsModulesClient,
solidityToTypescriptType,
} from "@hatsprotocol/modules-sdk";
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { avalanche } from "viem/chains";
import { createAnvil } from "@viem/anvil";
import { bundleModules } from "../bundler";
import type {
PublicClient,
WalletClient,
PrivateKeyAccount,
Address,
} from "viem";
import type { Anvil } from "@viem/anvil";
import type { Module, Registry } from "@hatsprotocol/modules-sdk";
import "dotenv/config";

describe("Avalanche deployments", () => {
let publicClient: PublicClient;
let walletClient: WalletClient;
let hatsModulesClient: HatsModulesClient;
let anvil: Anvil;
let deployerAccount: PrivateKeyAccount;
let instances: Address[] = [];

beforeAll(async () => {
anvil = createAnvil({
forkUrl: process.env.AVALANCHE_RPC,
startTimeout: 20000,
});
await anvil.start();

deployerAccount = privateKeyToAccount(
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
);

// init Viem clients
publicClient = createPublicClient({
chain: avalanche,
transport: http("http://127.0.0.1:8545"),
});
walletClient = createWalletClient({
chain: avalanche,
transport: http("http://127.0.0.1:8545"),
});

const registryModules: Registry = bundleModules() as unknown as Registry;

hatsModulesClient = new HatsModulesClient({
publicClient,
walletClient,
});

await hatsModulesClient.prepare(registryModules);
}, 30000);

afterAll(async () => {
await anvil.stop();
}, 30000);

test("Test create all modules", async () => {
const modules = hatsModulesClient.getModules();

// create new module instance for each module which is deployed on avalanche
for (const [id, module] of Object.entries(modules)) {
console.log(`Testing module: ${module.name}`);
if (module.name === "JokeRace Eligibility") {
continue;
}

// the unlock module has dependencies on other external contracts
if (
module.implementationAddress ===
"0x4c7803041851f7a17Fc6b5Ff5c911FC748160637"
) {
continue;
}

// check if module is deployed on avalanche. If not, then skip
let isOnAvalanche = false;
for (let i = 0; i < module.deployments.length; i++) {
if (module.deployments[i].chainId === "43114") {
isOnAvalanche = true;
break;
}
}
if (!isOnAvalanche) {
continue;
}

const hatId = module.creationArgs.useHatId
? BigInt(
"0x0000000100000000000000000000000000000000000000000000000000000000",
)
: BigInt("0");
const immutableArgs: unknown[] = [];
const mutableArgs: unknown[] = [];

// prepare immutable args
for (let i = 0; i < module.creationArgs.immutable.length; i++) {
let arg: unknown;
const exampleArg = module.creationArgs.immutable[i].example;
const tsType = solidityToTypescriptType(
module.creationArgs.immutable[i].type,
);
if (tsType === "bigint") {
arg = BigInt(exampleArg as string);
} else if (tsType === "bigint[]") {
arg = (exampleArg as Array<string>).map((val) => BigInt(val));
} else {
arg = exampleArg;
}

immutableArgs.push(arg);
}

// prepare mutable args
for (let i = 0; i < module.creationArgs.mutable.length; i++) {
let arg: unknown;
const exampleArg = module.creationArgs.mutable[i].example;
const tsType = solidityToTypescriptType(
module.creationArgs.mutable[i].type,
);
if (tsType === "bigint") {
arg = BigInt(exampleArg as string);
} else if (tsType === "bigint[]") {
arg = (exampleArg as Array<string>).map((val) => BigInt(val));
} else {
arg = exampleArg;
}

mutableArgs.push(arg);
}

// create new module instance
const res = await hatsModulesClient.createNewInstance({
account: deployerAccount,
moduleId: id,
hatId: hatId,
immutableArgs: immutableArgs,
mutableArgs: mutableArgs,
});

instances.push(res.newInstance);

// check correct hat Id in the new instance
const hatIdResult = await publicClient.readContract({
address: res.newInstance as Address,
abi: module.abi,
functionName: "hatId",
args: [],
});
expect(hatIdResult).toBe(hatId);
}
}, 30000);

test("Test module parameters", async () => {
for (let i = 0; i < instances.length; i++) {
let instance = instances[i];

const module = await hatsModulesClient.getModuleByInstance(instance);
const res = await hatsModulesClient.getInstanceParameters(instance);

if (res === undefined || res.length !== module?.parameters.length) {
throw new Error(
`Error: could not read all parameters from the instance of module ${module?.name}`,
);
}
}
}, 30000);
});