diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c2ced08f..50d0b80fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ - [x] `IexecPoco2Delegate.sol` ### Features +- Migrated utility files to TypeScript : (#183) + - `FactoryDeployer.js`, `constants.js`, `odb-tools.js` + - Removed deprecated `scripts/ens/sidechain.js` - Purge Truffle leftovers (#180, #181, #182) - Sunset Jenkins pipeline (#178) - Re-use variable in `IexecPoco2Delegate` in `contribute(...)` function. (#168) diff --git a/docs/ENS-Addresses.md b/docs/ENS-Addresses.md new file mode 100644 index 000000000..e99dcc0ce --- /dev/null +++ b/docs/ENS-Addresses.md @@ -0,0 +1,31 @@ +# ENS Addresses in iExec PoCo + +This document describes the ENS (Ethereum Name Service) addresses used in the iExec Protocol. + +## Domain Structure + +The iExec protocol uses the following ENS domain hierarchy: +- Root domain: `iexec.eth` +- Protocol version domain: `v5.iexec.eth` +- User domain: `users.iexec.eth` +- Resource domains: + - `apps.iexec.eth` + - `datasets.iexec.eth` + - `pools.iexec.eth` + +## Core Protocol Addresses + +The following ENS names are registered for core protocol components: + +- `admin.iexec.eth` - Protocol administrator address +- `rlc.iexec.eth` - RLC token contract address +- `core.v5.iexec.eth` - Core protocol proxy (ERC1538Proxy) + - `0x3eca1B216A7DF1C7689aEb259fFB83ADFB894E7f` +- `apps.v5.iexec.eth` - App registry contract + - `0xB1C52075b276f87b1834919167312221d50c9D16` +- `datasets.v5.iexec.eth` - Dataset registry contract + - `0x799DAa22654128d0C64d5b79eac9283008158730` +- `workerpools.v5.iexec.eth` - Workerpool registry contract + - `0xC76A18c78B7e530A165c5683CB1aB134E21938B4` + +To get more details, see [1_deploy-ens.ts script](../deploy/1_deploy-ens.ts). diff --git a/docs/README.md b/docs/README.md index 335d9efbc..20077ec3d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,3 +24,6 @@ * Nominal TEE [![Nominal TEE](https://tinyurl.com/2zubyfvw)](https://tinyurl.com/2zubyfvw) + +# ENS +Registered ENS names on Bellecour or Mainnet are documented in [./ENS-Addresses.md](./ENS-Addresses.md) \ No newline at end of file diff --git a/scripts/ens/sidechain.js b/scripts/ens/sidechain.js deleted file mode 100644 index f18bcc2a5..000000000 --- a/scripts/ens/sidechain.js +++ /dev/null @@ -1,214 +0,0 @@ -// SPDX-FileCopyrightText: 2020 IEXEC BLOCKCHAIN TECH -// SPDX-License-Identifier: Apache-2.0 - -const { ethers } = require('ethers'); -const { EthersDeployer: FactoryDeployer } = require('../../utils/FactoryDeployer'); -const ENSRegistry = require('@ensdomains/ens/build/contracts/ENSRegistry.json'); -const FIFSRegistrar = require('@ensdomains/ens/build/contracts/FIFSRegistrar.json'); -const ReverseRegistrar = require('@ensdomains/ens/build/contracts/ReverseRegistrar.json'); -const PublicResolver = require('@ensdomains/resolver/build/contracts/PublicResolver.json'); - -(async () => { - const provider = new ethers.getDefaultProvider(process.env.NODE); - const wallet = new ethers.Wallet(process.env.MNEMONIC, provider); - const deployer = new FactoryDeployer(wallet); - - await deployer.deploy(ENSRegistry, { - call: new ethers.utils.Interface(ENSRegistry.abi).encodeFunctionData('setOwner', [ - ethers.constants.HashZero, - wallet.address, - ]), - }); - const ens = new ethers.Contract(ENSRegistry.address, ENSRegistry.abi, wallet); - - await deployer.deploy(PublicResolver, { args: [ens.address] }); - const publicresolver = new ethers.Contract(PublicResolver.address, PublicResolver.abi, wallet); - - await deployer.deploy(ReverseRegistrar, { args: [ens.address, publicresolver.address] }); - const reverseregistrar = new ethers.Contract( - ReverseRegistrar.address, - ReverseRegistrar.abi, - wallet, - ); - - const domains = [ - { - name: 'eth', - }, - { - name: 'iexec.eth', - }, - { - name: 'erlc.iexec.eth', - address: '0x0000000000000000000000000000000000000000', - }, - { - name: 'timelock.iexec.eth', - address: '0x4611B943AA1d656Fc669623b5DA08756A7e288E9', - }, - { - name: 'v5.iexec.eth', - }, - { - name: 'core.v5.iexec.eth', - address: '0x3eca1B216A7DF1C7689aEb259fFB83ADFB894E7f', - setName: true, - }, - { - name: 'apps.v5.iexec.eth', - address: '0xB1C52075b276f87b1834919167312221d50c9D16', - setName: true, - }, - { - name: 'datasets.v5.iexec.eth', - address: '0x799DAa22654128d0C64d5b79eac9283008158730', - setName: true, - }, - { - name: 'workerpools.v5.iexec.eth', - address: '0xC76A18c78B7e530A165c5683CB1aB134E21938B4', - setName: true, - }, - { - name: 'resolver.eth', - address: publicresolver.address, - }, - { - name: 'reverse', - }, - { - name: 'addr.reverse', - owner: reverseregistrar.address, - }, - ]; - - // Register domains - await new Promise((resolve) => { - Promise.all( - domains - .filter((entry) => entry.name) - .map(async (entry) => ({ - ...entry, - owner: entry.owner || wallet.address, - _owner: await ens.owner(ethers.utils.namehash(entry.name)), - })), - ).then((_) => { - _.filter(({ _owner, owner }) => _owner != owner) - .reduce(async (promise, entry) => { - await Promise.resolve(promise); - console.log(`setSubnodeOwner(${entry.name}) → ${entry.owner}`); - const i = entry.name.indexOf('.'); - const label = i == -1 ? entry.name : entry.name.substr(0, i); - const parent = i == -1 ? '' : entry.name.substr(i + 1); - await ( - await ens.setSubnodeOwner( - ethers.utils.namehash(parent), - ethers.utils.id(label), - entry.owner, - ) - ).wait(); - }, Promise.resolve()) - .then(resolve); - }); - }); - - // Set resolver - await new Promise((resolve) => { - Promise.all( - domains - .filter((entry) => entry.resolver || entry.address) - .map(async (entry) => ({ - ...entry, - resolver: entry.resolver || publicresolver.address, - _resolver: await ens.resolver(ethers.utils.namehash(entry.name)), - })), - ).then((_) => { - _.filter(({ _resolver, resolver }) => _resolver != resolver) - .reduce(async (promise, entry) => { - await Promise.resolve(promise); - console.log(`setResolver(${entry.name}) → ${entry.resolver}`); - await ( - await ens.setResolver(ethers.utils.namehash(entry.name), entry.resolver) - ).wait(); - }, Promise.resolve()) - .then(resolve); - }); - }); - - // Set address - await new Promise((resolve) => { - Promise.all( - domains - .filter((entry) => entry.address) - .map(async (entry) => { - try { - const resolverContract = new ethers.Contract( - await ens.resolver(ethers.utils.namehash(entry.name)), - PublicResolver.abi, - wallet, - ); - const address = await resolverContract['addr(bytes32)']( - ethers.utils.namehash(entry.name), - ); - return address == entry.address ? null : { ...entry, resolverContract }; - } catch { - return null; // invalid resolverContract - } - }), - ).then((_) => { - _.filter(Boolean) - .reduce(async (promise, entry) => { - await Promise.resolve(promise); - console.log(`setAddr(${entry.name}) → ${entry.address}`); - await ( - await entry.resolverContract['setAddr(bytes32,address)']( - ethers.utils.namehash(entry.name), - entry.address, - ) - ).wait(); - }, Promise.resolve()) - .then(resolve); - }); - }); - - // Set reverse - await new Promise((resolve) => { - Promise.all( - domains - .filter((entry) => entry.name && entry.address && entry.setName) - .map((entry) => ({ - ...entry, - lookup: `${entry.address.toLowerCase().substr(2)}.addr.reverse`, - })) - .map(async (entry) => { - try { - const reverseResolver = new ethers.Contract( - await ens.resolver(ethers.utils.namehash(entry.lookup)), - PublicResolver.abi, - wallet, - ); - const name = await reverseResolver.name( - ethers.utils.namehash(entry.lookup), - ); - return name == entry.name ? null : entry; - } catch { - return entry; // reverseResolver not set - } - }), - ).then((_) => { - _.filter(Boolean) - .reduce(async (promise, entry) => { - await Promise.resolve(promise); - console.log(`setName(${entry.address}) → ${entry.name}`); - await ( - await new ethers.Contract( - entry.address, - [ethers.utils.FunctionFragment.fromString('setName(address,string)')], - wallet, - ).setName(ens.address, entry.name) - ).wait(); - }, Promise.resolve()) - .then(resolve); - }); - }); -})().catch(console.error); diff --git a/test/000_fullchain-boost.test.ts b/test/000_fullchain-boost.test.ts index 1c5324161..d799392e5 100644 --- a/test/000_fullchain-boost.test.ts +++ b/test/000_fullchain-boost.test.ts @@ -17,7 +17,7 @@ import { TestClient__factory, WorkerpoolInterface__factory, } from '../typechain'; -import constants from '../utils/constants'; +import * as constants from '../utils/constants'; import { OrdersActors, OrdersAssets, diff --git a/test/byContract/IexecPoco/IexecPoco2-claim.test.ts b/test/byContract/IexecPoco/IexecPoco2-claim.test.ts index 0e95fd6d5..3376b4fcb 100644 --- a/test/byContract/IexecPoco/IexecPoco2-claim.test.ts +++ b/test/byContract/IexecPoco/IexecPoco2-claim.test.ts @@ -17,7 +17,7 @@ import { getTaskId, } from '../../../utils/poco-tools'; import { IexecWrapper } from '../../utils/IexecWrapper'; -import constants from './../../../utils/constants'; +import * as constants from './../../../utils/constants'; const categoryTime = 300; const maxDealDuration = 10 * categoryTime; diff --git a/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts b/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts index e8db113b6..5ddc20ef1 100644 --- a/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts +++ b/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts @@ -33,7 +33,7 @@ import { TestClient, TestClient__factory, } from '../../../typechain'; -import constants from '../../../utils/constants'; +import * as constants from '../../../utils/constants'; import { IexecOrders, OrdersActors, diff --git a/utils/FactoryDeployer.js b/utils/FactoryDeployer.js deleted file mode 100644 index b09de2d75..000000000 --- a/utils/FactoryDeployer.js +++ /dev/null @@ -1,137 +0,0 @@ -// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH -// SPDX-License-Identifier: Apache-2.0 - -const { ethers } = require('ethers'); -const FACTORY = - require('../config/config.json').chains.default.asset == 'Token' && - hre.network.name.includes('hardhat') // Required until dev-token chain EIPs are updated - ? require('@amxx/factory/deployments/GenericFactory_shanghai.json') - : require('@amxx/factory/deployments/GenericFactory.json'); - -async function waitTx(txPromise) { - await (await txPromise).wait(); -} - -class EthersDeployer { - // factory: ethers.Contract - // factoryAsPromise: Promise - - constructor(wallet, options = {}) { - this.options = options; - this.factoryAsPromise = new Promise(async (resolve, reject) => { - if ((await wallet.provider.getCode(FACTORY.address)) !== '0x') { - console.debug(`→ Factory is available on this network`); - } else { - try { - console.debug(`→ Factory is not yet deployed on this network`); - await waitTx( - wallet.sendTransaction({ to: FACTORY.deployer, value: FACTORY.cost }), - ); - await waitTx(wallet.provider.sendTransaction(FACTORY.tx)); - console.debug(`→ Factory successfully deployed`); - } catch (e) { - console.debug(`→ Error deploying the factory`); - reject(e); - } - } - this.factory = new ethers.Contract(FACTORY.address, FACTORY.abi, wallet); - resolve(this.factory); - }); - } - - async ready() { - await this.factoryAsPromise; - } - - async deploy(artefact, ...extra) { - await this.ready(); - console.log(`[factoryDeployer] ${artefact.contractName}`); - const constructorABI = artefact.abi.find((e) => e.type == 'constructor'); - const argsCount = constructorABI ? constructorABI.inputs.length : 0; - const args = extra.slice(0, argsCount); - const options = { ...this.options, ...extra[argsCount] }; - var librariesLinkPlaceHolderAndAddress = []; - if (options.libraries) { - librariesLinkPlaceHolderAndAddress = await Promise.all( - options.libraries.map(async (library) => { - const linkPlaceholder = this.getLinkPlaceholder(library, artefact); - if (linkPlaceholder) { - return { - linkPlaceholder: linkPlaceholder, - address: (await library.deployed()).address, - }; - } - }), - ); - } - var coreCode = artefact.bytecode; - librariesLinkPlaceHolderAndAddress - .filter((data) => data != undefined) - .forEach((element) => { - // Replace `__$9d824026d0515d8abd681f0f0f4707f16a$__` - // by address library without 0x prefix - coreCode = coreCode.replaceAll( - element.linkPlaceholder, - element.address.slice(2).toLowerCase(), - ); - }); - - const argsCode = constructorABI - ? ethers.utils.defaultAbiCoder - .encode( - constructorABI.inputs.map((e) => e.type), - args, - ) - .slice(2) - : ''; - const code = coreCode + argsCode; - const salt = options.salt || ethers.constants.HashZero; - const contractAddress = options.call - ? await this.factory.predictAddressWithCall(code, salt, options.call) - : await this.factory.predictAddress(code, salt); - - if ((await this.factory.provider.getCode(contractAddress)) == '0x') { - console.log(`[factory] Preparing to deploy ${artefact.contractName} ...`); - await waitTx( - options.call - ? this.factory.createContractAndCall(code, salt, options.call) - : this.factory.createContract(code, salt), - ); - console.log( - `[factory] ${artefact.contractName} successfully deployed at ${contractAddress}`, - ); - } else { - console.log( - `[factory] ${artefact.contractName} already deployed at ${contractAddress}`, - ); - } - const instance = await artefact.at(contractAddress); - artefact.setAsDeployed(instance); - } - - /** - * Get placeholder to be replaced with library address for a given contract. - * @param libraryArtefact artefact of the library - * @param contractArtefact artefact of the contract to be linked with the library - * @returns the placeholder to be replaced - */ - getLinkPlaceholder(libraryArtefact, contractArtefact) { - const hardhatLibraryArtifact = libraryArtefact._hArtifact; - const hardhatContractArtifact = contractArtefact._hArtifact; - if (hardhatContractArtifact.linkReferences) { - const linkSourceName = - hardhatContractArtifact.linkReferences[hardhatLibraryArtifact.sourceName]; - if (linkSourceName) { - const firstLinkData = linkSourceName[hardhatLibraryArtifact.contractName][0]; - // linkPlaceholder code from: - // https://github.com/NomicFoundation/hardhat/blob/v1.3.3/packages/buidler-truffle5/src/artifacts.ts#L123 - return contractArtefact.bytecode.substr( - firstLinkData.start * 2 + 2, - firstLinkData.length * 2, - ); - } - } - } -} - -module.exports = { EthersDeployer, factoryAddress: FACTORY.address }; diff --git a/utils/FactoryDeployer.ts b/utils/FactoryDeployer.ts new file mode 100644 index 000000000..3f63bee52 --- /dev/null +++ b/utils/FactoryDeployer.ts @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +import factoryJson from '@amxx/factory/deployments/GenericFactory.json'; +import factoryShanghaiJson from '@amxx/factory/deployments/GenericFactory_shanghai.json'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; +import { Contract, ethers } from 'ethers'; +import hre from 'hardhat'; +import config from '../config/config.json'; + +interface FactoryConfig { + address: string; + deployer: string; + cost: string; + tx: string; + abi: any[]; +} + +const factoryConfig: FactoryConfig = + config.chains.default.asset === 'Token' && hre.network.name.includes('hardhat') + ? factoryShanghaiJson + : factoryJson; + +async function waitTx(txPromise: Promise): Promise { + await (await txPromise).wait(); +} + +export class EthersDeployer { + private factory!: Contract; + private factoryAsPromise: Promise; + + constructor(wallet: SignerWithAddress) { + this.factoryAsPromise = new Promise(async (resolve, reject) => { + if ((await wallet.provider!.getCode(factoryConfig.address)) !== '0x') { + console.log(`→ Factory is available on this network`); + } else { + try { + console.log(`→ Factory is not yet deployed on this network`); + await waitTx( + wallet.sendTransaction({ + to: factoryConfig.deployer, + value: factoryConfig.cost, + }), + ); + await waitTx(wallet.provider!.sendTransaction(factoryConfig.tx)); + console.log(`→ Factory successfully deployed`); + } catch (e) { + console.log(`→ Error deploying the factory`); + reject(e); + } + } + this.factory = new ethers.Contract(factoryConfig.address, factoryConfig.abi, wallet); + resolve(this.factory); + }); + } + + async ready(): Promise { + await this.factoryAsPromise; + } +} + +export const factoryAddress = factoryConfig.address; diff --git a/utils/constants.d.ts b/utils/constants.d.ts deleted file mode 100644 index 37441f3b4..000000000 --- a/utils/constants.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-FileCopyrightText: 2023 IEXEC BLOCKCHAIN TECH -// SPDX-License-Identifier: Apache-2.0 - -export declare const NULL: { - ADDRESS: string; - BYTES32: string; - SIGNATURE: string; -}; - -export declare const MULTIADDR_BYTES: string; diff --git a/utils/constants.js b/utils/constants.ts similarity index 63% rename from utils/constants.js rename to utils/constants.ts index 5123a5ebd..763744082 100644 --- a/utils/constants.js +++ b/utils/constants.ts @@ -1,16 +1,13 @@ -// SPDX-FileCopyrightText: 2020 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 -function define(name, value) { - Object.defineProperty(exports, name, { value: value, enumerable: true }); -} - //config -define('EVENT_WAIT_TIMEOUT', 100000); -define('AMOUNT_GAS_PROVIDED', 4500000); -//define("AMOUNT_GAS_PROVIDED", 0xFFFFFFFFFFFFFFFF); +export const EVENT_WAIT_TIMEOUT = 100000; +export const AMOUNT_GAS_PROVIDED = 4500000; +// TODO remove this if not used anymore. +// export const AMOUNT_GAS_PROVIDED = "0xFFFFFFFFFFFFFFFF"; -define('NULL', { +export const NULL = { ADDRESS: '0x0000000000000000000000000000000000000000', BYTES32: '0x0000000000000000000000000000000000000000000000000000000000000000', SIGNATURE: '0x', @@ -25,29 +22,27 @@ define('NULL', { salt: '0x0000000000000000000000000000000000000000000000000000000000000000', sign: '0x', }, -}); +}; // ENUM -define('OrderOperationEnum', { +export const OrderOperationEnum = { SIGN: 0, CLOSE: 1, -}); -define('TaskStatusEnum', { +}; +export const TaskStatusEnum = { UNSET: 0, ACTIVE: 1, REVEALING: 2, COMPLETED: 3, FAILED: 4, -}); -define('ContributionStatusEnum', { +}; +export const ContributionStatusEnum = { UNSET: 0, CONTRIBUTED: 1, PROVED: 2, REJECTED: 3, -}); +}; -define('MULTIADDR', '/ipfs/QmRwwTz9Chq4Y7F7ReKKcx1GV6s3H7egmNGrku9XrwiDa8'); -define( - 'MULTIADDR_BYTES', - '0xa503221220359d55f58a43126d4ba446a35940265eb2dab57ecbc439e7f105c558f8774819', -); +export const MULTIADDR = '/ipfs/QmRwwTz9Chq4Y7F7ReKKcx1GV6s3H7egmNGrku9XrwiDa8'; +export const MULTIADDR_BYTES = + '0xa503221220359d55f58a43126d4ba446a35940265eb2dab57ecbc439e7f105c558f8774819'; diff --git a/utils/createOrders.ts b/utils/createOrders.ts index e33e4e0ea..4a3aea957 100644 --- a/utils/createOrders.ts +++ b/utils/createOrders.ts @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023-2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2023-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 import { TypedDataDomain } from '@ethersproject/abstract-signer'; @@ -6,8 +6,8 @@ import { BigNumber } from '@ethersproject/bignumber'; import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { ethers } from 'hardhat'; import { IexecLibOrders_v5 } from '../typechain'; -import constants, { NULL } from './constants'; -import { utils } from './odb-tools'; +import * as constants from './constants'; +import { hashStruct, signStruct } from './odb-tools'; import { OrderOperationEnum } from './poco-tools'; export interface OrdersAssets { @@ -168,7 +168,7 @@ export function createEmptyDatasetOrder(): IexecLibOrders_v5.DatasetOrderStruct * Create an order operation from an existing order. */ export function createOrderOperation(order: OrderType, operation: OrderOperationEnum) { - return { order, operation: BigNumber.from(operation), sign: NULL.SIGNATURE }; + return { order, operation: BigNumber.from(operation), sign: constants.NULL.SIGNATURE }; } export function buildOrders(matchOrdersArgs: MatchOrdersArgs) { @@ -295,7 +295,7 @@ export async function signOrder( order: Record, signer: SignerWithAddress, ): Promise { - return utils.signStruct(getTypeOf(order), order, domain, signer); + return signStruct(getTypeOf(order), order, domain, signer); } /** @@ -307,7 +307,7 @@ export async function signOrderOperation( orderOperation: OrderOperation, signer: SignerWithAddress, ): Promise { - return utils.signStruct( + return signStruct( getTypeOf(orderOperation.order) + 'Operation', orderOperation, domain, @@ -320,7 +320,7 @@ export async function signOrderOperation( * @returns order hash */ export function hashOrder(domain: TypedDataDomain, order: Record): string { - return utils.hashStruct(getTypeOf(order), order, domain); + return hashStruct(getTypeOf(order), order, domain); } /** diff --git a/utils/odb-tools.js b/utils/odb-tools.ts similarity index 80% rename from utils/odb-tools.js rename to utils/odb-tools.ts index 80423553a..c53c75ff1 100644 --- a/utils/odb-tools.js +++ b/utils/odb-tools.ts @@ -1,9 +1,19 @@ // SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 -const ethers = require('ethers'); +import { TypedDataDomain, TypedDataField, ethers } from 'ethers'; +import hre from 'hardhat'; -const TYPES = { +interface WalletInfo { + privateKey?: string; + address?: string; +} + +interface Types { + [key: string]: Array; +} + +const TYPES: Types = { EIP712Domain: [ { type: 'string', name: 'name' }, { type: 'string', name: 'version' }, @@ -77,9 +87,9 @@ const TYPES = { ], }; -function buildTypes(primaryType) { +function buildTypes(primaryType: string): Types { const OPERATION = 'Operation'; - const types = { + const types: Types = { [primaryType]: TYPES[primaryType], }; @@ -92,7 +102,12 @@ function buildTypes(primaryType) { return types; } -function eth_signTypedData(primaryType, message, domain, wallet) { +async function eth_signTypedData( + primaryType: string, + message: Record, + domain: TypedDataDomain, + wallet: WalletInfo, +): Promise { return new Promise((resolve, reject) => { const typedDataDomain = { name: domain.name, @@ -108,7 +123,12 @@ function eth_signTypedData(primaryType, message, domain, wallet) { const walletInstance = new ethers.Wallet(wallet.privateKey, hre.ethers.provider); signerPromise = Promise.resolve(walletInstance); } else { - signerPromise = hre.ethers.getSigner(wallet.address); + if (wallet.address) { + signerPromise = hre.ethers.getSigner(wallet.address); + } else { + reject(new Error('Wallet address is undefined')); + return; + } } signerPromise @@ -118,15 +138,24 @@ function eth_signTypedData(primaryType, message, domain, wallet) { }); } -function signStruct(primaryType, message, domain, wallet) { +export async function signStruct( + primaryType: string, + message: Record, + domain: TypedDataDomain, + wallet: WalletInfo, +): Promise> { return eth_signTypedData(primaryType, message, domain, wallet).then((sign) => { message.sign = sign; return message; }); } -function hashStruct(primaryType, message, domain) { - let typedDataDomain = { +export function hashStruct( + primaryType: string, + message: Record, + domain: TypedDataDomain, +): string { + const typedDataDomain: TypedDataDomain = { name: domain.name, version: domain.version, chainId: domain.chainId, @@ -138,13 +167,3 @@ function hashStruct(primaryType, message, domain) { return ethers.utils._TypedDataEncoder.hash(typedDataDomain, types, message); } - -/***************************************************************************** - * MODULE * - *****************************************************************************/ -module.exports = { - utils: { - signStruct, - hashStruct, - }, -};