Skip to content

Commit

Permalink
feat: fhenixsdk/PermitV2 integration (#18)
Browse files Browse the repository at this point in the history
* Add fhenixsdk to hardhat

* Add initializeWithHHSigner to fhenixsdk, start on tests

* Add `fhenixsdk` tests

* Update fhenix.js version

* Improve overloaded class functions

* Update api and naming

* Update ethers version
  • Loading branch information
architect-dev authored Dec 16, 2024
1 parent 47f3239 commit b9eddb8
Show file tree
Hide file tree
Showing 9 changed files with 3,293 additions and 2,528 deletions.
5 changes: 3 additions & 2 deletions packages/fhenix-hardhat-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"README.md"
],
"devDependencies": {
"@nomicfoundation/hardhat-ethers": "^3.0.5",
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.6",
"@types/node": "^16.18.76",
Expand All @@ -48,8 +49,8 @@
"dependencies": {
"axios": "^1.6.5",
"chalk": "^4.1.2",
"ethers": "^6.0.0",
"fhenixjs": "^0.4.1"
"ethers": "^6.10.0",
"fhenixjs": "^0.4.2-alpha.1"
},
"peerDependencies": {
"hardhat": "^2.11.0"
Expand Down
163 changes: 34 additions & 129 deletions packages/fhenix-hardhat-plugin/src/FhenixHardhatRuntimeEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class FhenixHardhatRuntimeEnvironment extends FhenixClient {
public config: FhenixHardhatRuntimeEnvironmentConfig,
) {
const isHardhat = hre?.network?.config?.chainId === 31337;

const superArgs: InstanceParams = {
ignoreErrors: true,
provider: new MockProvider(),
Expand All @@ -50,137 +50,38 @@ export class FhenixHardhatRuntimeEnvironment extends FhenixClient {
this.isHardhat = isHardhat;
}

public async encrypt_uint8(
value: number,
securityZone?: number | undefined,
): Promise<EncryptedUint8> {
if (this.isHardhat) {
const data = bigintToUint8Array(BigInt(value));

return {
data,
securityZone: securityZone || 0,
};
} else {
return super.encrypt_uint8(value, securityZone);
}
}

public async encrypt_uint16(
value: number,
securityZone?: number | undefined,
): Promise<EncryptedUint16> {
if (this.isHardhat) {
const data = bigintToUint8Array(BigInt(value));

return {
data,
securityZone: securityZone || 0,
};
} else {
return super.encrypt_uint16(value, securityZone);
}
}

public async encrypt_uint32(
value: number,
securityZone?: number | undefined,
): Promise<EncryptedUint32> {
if (this.isHardhat) {
const data = bigintToUint8Array(BigInt(value));

return {
data,
securityZone: securityZone || 0,
};
} else {
return super.encrypt_uint32(value, securityZone);
}
}

public async encrypt_uint64(
value: string | bigint,
securityZone?: number | undefined,
): Promise<EncryptedUint64> {
if (this.isHardhat) {
const data = bigintToUint8Array(BigInt(value));

return {
data,
securityZone: securityZone || 0,
};
} else {
return super.encrypt_uint64(value, securityZone);
}
}

public async encrypt_uint128(
value: string | bigint,
securityZone?: number | undefined,
): Promise<EncryptedUint128> {
if (this.isHardhat) {
const data = bigintToUint8Array(BigInt(value));

return {
data,
securityZone: securityZone || 0,
};
} else {
return super.encrypt_uint128(value, securityZone);
}
}

public async encrypt_uint256(
value: string | bigint,
securityZone?: number | undefined,
): Promise<EncryptedUint256> {
if (this.isHardhat) {
const data = bigintToUint8Array(BigInt(value));

return {
data,
securityZone: securityZone || 0,
};
} else {
return super.encrypt_uint256(value, securityZone);
}
}

public async encrypt_bool(
value: boolean,
securityZone?: number | undefined,
): Promise<EncryptedBool> {
if (this.isHardhat) {
if (value) {
const data = bigintToUint8Array(BigInt(1));

return {
data,
securityZone: securityZone || 0,
};
} else {
const data = bigintToUint8Array(BigInt(0));

return {
data,
securityZone: securityZone || 0,
};
private hardhatMockEncryptCurry = <
T extends (value: any, securityZone?: number) => Promise<any>
>(
encryptFunction: T,
) => {
return (async (
value: Parameters<T>[0],
securityZone?: number,
): Promise<ReturnType<T>> => {
if (this.isHardhat) {
return hardhatMockEncrypt(BigInt(value), securityZone) as ReturnType<T>;
}
} else {
return super.encrypt_bool(value, securityZone);
}
}
return encryptFunction(value, securityZone);
}) as T;
};

public encrypt_bool = this.hardhatMockEncryptCurry(super.encrypt_bool);
public encrypt_uint8 = this.hardhatMockEncryptCurry(super.encrypt_uint8);
public encrypt_uint16 = this.hardhatMockEncryptCurry(super.encrypt_uint16);
public encrypt_uint32 = this.hardhatMockEncryptCurry(super.encrypt_uint32);
public encrypt_uint64 = this.hardhatMockEncryptCurry(super.encrypt_uint64);
public encrypt_uint128 = this.hardhatMockEncryptCurry(super.encrypt_uint128);
public encrypt_uint256 = this.hardhatMockEncryptCurry(super.encrypt_uint256);
public encrypt_address = this.hardhatMockEncryptCurry(super.encrypt_address);

public unseal(
contractAddress: string,
ciphertext: string,
account: string,
): bigint {
if (this.isHardhat) {
return uint8ArrayToBigint(ciphertext);
} else {
return super.unseal(contractAddress, ciphertext, account);
}
if (this.isHardhat) return hardhatMockDecrypt(ciphertext);
return super.unseal(contractAddress, ciphertext, account);
}

public async getFunds(address: string) {
Expand Down Expand Up @@ -218,10 +119,9 @@ export class MockProvider {
}
}

function uint8ArrayToBigint(uint8ArrayStr: string): bigint {
const byteArray = new Uint8Array(
uint8ArrayStr.split("").map((c) => c.charCodeAt(0)),
);
function hardhatMockDecrypt(value: string): bigint {
// Convert string into byte array
const byteArray = new Uint8Array(value.split("").map((c) => c.charCodeAt(0)));

let result = BigInt(0);
for (const byteArrayItem of byteArray) {
Expand All @@ -248,3 +148,8 @@ function bigintToUint8Array(bigNum: bigint): Uint8Array {

return byteArray;
}

const hardhatMockEncrypt = (value: bigint, securityZone = 0) => ({
data: bigintToUint8Array(BigInt(value)),
securityZone: securityZone || 0,
});
19 changes: 19 additions & 0 deletions packages/fhenix-hardhat-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
} from "./exposed";
import { FhenixHardhatRuntimeEnvironment } from "./FhenixHardhatRuntimeEnvironment";
import "./type-extensions";
import { fhenixsdk } from "fhenixjs";

// This import is needed to let the TypeScript compiler know that it should include your type
// extensions in your npm package's types file.
Expand All @@ -37,6 +38,24 @@ extendEnvironment((hre) => {

return fhenix;
});

hre.fhenixsdk = lazyObject(() => ({
...fhenixsdk,
initializeWithHHSigner: async ({ signer, ...params }) => {
fhenixsdk.initialize({
provider: {
call: signer.provider.call,
getChainId: async () =>
(await signer.provider.getNetwork()).chainId.toString(),
},
signer: {
signTypedData: signer.signTypedData,
getAddress: signer.getAddress,
},
...params,
});
},
}));
});

extendConfig((config, userConfig) => {
Expand Down
32 changes: 31 additions & 1 deletion packages/fhenix-hardhat-plugin/src/type-extensions.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,43 @@
import { FhenixClient } from "fhenixjs";
import { FhenixClient, fhenixsdk } from "fhenixjs";
import "hardhat/types/config";
import "hardhat/types/runtime";

import { FhenixHardhatRuntimeEnvironment } from "./FhenixHardhatRuntimeEnvironment";
import { InitParams } from "fhenixjs/lib/types/sdk/v2/sdk.store";
import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers";

type PermitV2AccessRequirementsParams =
| {
contracts?: never[];
projects: string[];
}
| {
contracts: string[];
projects?: never[];
};

type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;

type FhenixsdkInitWithHHSignerParams = Expand<
Omit<InitParams, "provider" | "signer" | "contracts" | "projects"> & {
signer: SignerWithAddress;
ignoreErrors?: boolean;
}
> &
PermitV2AccessRequirementsParams;

declare module "hardhat/types/runtime" {
// Fhenix extension to the Hardhat Runtime Environment.
// This new field will be available in tasks' actions, scripts, and tests.
export interface HardhatRuntimeEnvironment {
fhenixjs: FhenixClient & FhenixHardhatRuntimeEnvironment;
fhenixsdk: typeof fhenixsdk & {
/**
* Initialize (or re-initialize) the fhenixsdk with an ethers hardhat SignerWithAddress
*/
initializeWithHHSigner: (
params: FhenixsdkInitWithHHSignerParams,
) => Promise<void>;
};
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// We load the plugin here.
import { HardhatUserConfig } from "hardhat/types";
import "@nomicfoundation/hardhat-ethers";

import "../../../src/index";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// We load the plugin here.
import { HardhatUserConfig } from "hardhat/types";
import "@nomicfoundation/hardhat-ethers";

import "../../../src/index";

Expand All @@ -9,6 +10,15 @@ const config: HardhatUserConfig = {
networks: {
localfhenix: {
url: "http://localhost:8545",
accounts: {
mnemonic:
"demand hotel mass rally sphere tiger measure sick spoon evoke fashion comfort",
path: "m/44'/60'/0'/0",
initialIndex: 0,
count: 20,
accountsBalance: "10000000000000000000",
passphrase: "",
},
},
},
paths: {
Expand Down
Loading

0 comments on commit b9eddb8

Please sign in to comment.