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

Migrate from ethers-v5 to viem #271

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all 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
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"ethers": "^5.4.1",
"joi": "^17.7.0",
"qs": "^6.10.1",
"semver": "^7.5.2"
"semver": "^7.5.2",
"viem": "^1.6.7"
},
"devDependencies": {
"@babel/core": "^7.18.10",
Expand Down Expand Up @@ -88,7 +89,7 @@
"typechain": "^7.0.0",
"typedoc": "^0.22.11",
"typedoc-plugin-missing-exports": "^0.22.6",
"typescript": "^4.7.0"
"typescript": "^5.0.4"
},
"files": [
"build/main",
Expand Down
9 changes: 6 additions & 3 deletions src/agents/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ const CONTRACTS: { readonly [key in ChainId]: Contracts } = {
[ChainId.MAINNET]: MAINNET,
};

export const getContract = (
chainId: number,
contract: keyof Contracts
export const getContractOrFail = (
contract: keyof Contracts,
chainId?: number
): ChecksumAddress => {
if (!chainId) {
throw new Error('No chainId provided');
}
if (!Object.values(ChainId).includes(chainId)) {
throw new Error(`No contracts found for chainId: ${chainId}`);
}
Expand Down
61 changes: 31 additions & 30 deletions src/agents/coordinator.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { SessionStaticKey } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
import { PublicClient, WalletClient } from 'viem';

import {
Coordinator,
Coordinator__factory,
} from '../../types/ethers-contracts';
import { Coordinator__factory } from '../../types/ethers-contracts';
import { BLS12381 } from '../../types/ethers-contracts/Coordinator';
import { ChecksumAddress } from '../types';
import { fromHexString } from '../utils';
import { publicClientToProvider, walletClientToSigner } from '../viem';

import { DEFAULT_WAIT_N_CONFIRMATIONS, getContract } from './contracts';
import { DEFAULT_WAIT_N_CONFIRMATIONS, getContractOrFail } from './contracts';

export interface CoordinatorRitual {
initiator: string;
Expand Down Expand Up @@ -39,10 +37,10 @@ export enum DkgRitualState {

export class DkgCoordinatorAgent {
public static async getParticipants(
provider: ethers.providers.Provider,
publicClient: PublicClient,
ritualId: number
): Promise<DkgParticipant[]> {
const Coordinator = await this.connectReadOnly(provider);
const Coordinator = await this.connectReadOnly(publicClient);
const participants = await Coordinator.getParticipants(ritualId);

return participants.map((participant) => {
Expand All @@ -57,10 +55,10 @@ export class DkgCoordinatorAgent {
}

public static async initializeRitual(
provider: ethers.providers.Web3Provider,
walletClient: WalletClient,
providers: ChecksumAddress[]
): Promise<number> {
const Coordinator = await this.connectReadWrite(provider);
const Coordinator = await this.connectReadWrite(walletClient);
const tx = await Coordinator.initiateRitual(providers);
const txReceipt = await tx.wait(DEFAULT_WAIT_N_CONFIRMATIONS);
const [ritualStartEvent] = txReceipt.events ?? [];
Expand All @@ -71,23 +69,23 @@ export class DkgCoordinatorAgent {
}

public static async getRitual(
provider: ethers.providers.Provider,
publicClient: PublicClient,
ritualId: number
): Promise<CoordinatorRitual> {
const Coordinator = await this.connectReadOnly(provider);
const Coordinator = await this.connectReadOnly(publicClient);
return Coordinator.rituals(ritualId);
}

public static async getRitualState(
provider: ethers.providers.Web3Provider,
publicClient: PublicClient,
ritualId: number
): Promise<DkgRitualState> {
const Coordinator = await this.connectReadOnly(provider);
const Coordinator = await this.connectReadOnly(publicClient);
return await Coordinator.getRitualState(ritualId);
}

public static async onRitualEndEvent(
provider: ethers.providers.Web3Provider,
provider: PublicClient,
ritualId: number,
callback: (successful: boolean) => void
): Promise<void> {
Expand All @@ -104,22 +102,25 @@ export class DkgCoordinatorAgent {
});
}

private static async connectReadOnly(provider: ethers.providers.Provider) {
return await this.connect(provider);
}

private static async connectReadWrite(
web3Provider: ethers.providers.Web3Provider
) {
return await this.connect(web3Provider, web3Provider.getSigner());
private static async connectReadOnly(publicClient: PublicClient) {
const contractAddress = getContractOrFail(
'COORDINATOR',
publicClient.chain?.id
);
return Coordinator__factory.connect(
contractAddress,
publicClientToProvider(publicClient)
);
}

private static async connect(
provider: ethers.providers.Provider,
signer?: ethers.providers.JsonRpcSigner
): Promise<Coordinator> {
const network = await provider.getNetwork();
const contractAddress = getContract(network.chainId, 'COORDINATOR');
return Coordinator__factory.connect(contractAddress, signer ?? provider);
private static async connectReadWrite(walletClient: WalletClient) {
const contractAddress = getContractOrFail(
'COORDINATOR',
walletClient.chain?.id
);
return Coordinator__factory.connect(
contractAddress,
walletClientToSigner(walletClient)
);
}
}
55 changes: 23 additions & 32 deletions src/agents/subscription-manager.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
import {
BigNumber,
ContractTransaction,
ethers,
utils as ethersUtils,
} from 'ethers';
import { BigNumber, ContractTransaction, utils as ethersUtils } from 'ethers';
import { PublicClient, WalletClient } from 'viem';

import {
SubscriptionManager,
SubscriptionManager__factory,
} from '../../types/ethers-contracts';
import { SubscriptionManager__factory } from '../../types/ethers-contracts';
import { ChecksumAddress } from '../types';
import { publicClientToProvider, walletClientToSigner } from '../viem';

import { DEFAULT_WAIT_N_CONFIRMATIONS, getContract } from './contracts';
import { DEFAULT_WAIT_N_CONFIRMATIONS, getContractOrFail } from './contracts';

export class PreSubscriptionManagerAgent {
public static async createPolicy(
web3Provider: ethers.providers.Web3Provider,
walletClient: WalletClient,
valueInWei: BigNumber,
policyId: Uint8Array,
size: number,
startTimestamp: number,
endTimestamp: number,
ownerAddress: ChecksumAddress
): Promise<ContractTransaction> {
const SubscriptionManager = await this.connectReadWrite(web3Provider);
const SubscriptionManager = await this.connectReadWrite(walletClient);
const overrides = {
value: valueInWei.toString(),
};
Expand All @@ -48,41 +42,38 @@ export class PreSubscriptionManagerAgent {
}

public static async getPolicyCost(
provider: ethers.providers.Provider,
publicClient: PublicClient,
size: number,
startTimestamp: number,
endTimestamp: number
): Promise<BigNumber> {
const SubscriptionManager = await this.connectReadOnly(provider);
const SubscriptionManager = await this.connectReadOnly(publicClient);
return await SubscriptionManager.getPolicyCost(
size,
startTimestamp,
endTimestamp
);
}

private static async connectReadOnly(provider: ethers.providers.Provider) {
return await this.connect(provider);
}

private static async connectReadWrite(
web3Provider: ethers.providers.Web3Provider
) {
return await this.connect(web3Provider, web3Provider.getSigner());
private static async connectReadOnly(publicClient: PublicClient) {
const contractAddress = getContractOrFail(
'COORDINATOR',
publicClient.chain?.id
);
return SubscriptionManager__factory.connect(
contractAddress,
publicClientToProvider(publicClient)
);
}

private static async connect(
provider: ethers.providers.Provider,
signer?: ethers.providers.JsonRpcSigner
): Promise<SubscriptionManager> {
const network = await provider.getNetwork();
const contractAddress = getContract(
network.chainId,
'SUBSCRIPTION_MANAGER'
private static async connectReadWrite(walletClient: WalletClient) {
const contractAddress = getContractOrFail(
'COORDINATOR',
walletClient.chain?.id
);
return SubscriptionManager__factory.connect(
contractAddress,
signer ?? provider
walletClientToSigner(walletClient)
);
}
}
27 changes: 15 additions & 12 deletions src/characters/alice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
Signer,
VerifiedKeyFrag,
} from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
import { PublicClient, WalletClient } from 'viem';
import { getBlock, getBlockNumber } from 'viem/actions';

import { Keyring } from '../keyring';
import {
Expand All @@ -15,6 +16,7 @@ import {
} from '../policies/policy';
import { PorterClient } from '../porter';
import { ChecksumAddress } from '../types';
import { toPublicClient } from '../viem';

import { RemoteBob } from './bob';

Expand Down Expand Up @@ -42,7 +44,7 @@ export class Alice {
}

public async grant(
web3Provider: ethers.providers.Web3Provider,
walletClient: WalletClient,
porterUri: string,
policyParameters: BlockchainPolicyParameters,
includeUrsulas?: readonly ChecksumAddress[],
Expand All @@ -54,12 +56,12 @@ export class Alice {
excludeUrsulas,
includeUrsulas
);
const policy = await this.createPolicy(web3Provider, policyParameters);
return await policy.enact(web3Provider, ursulas);
const policy = await this.createPolicy(walletClient, policyParameters);
return await policy.enact(walletClient, ursulas);
}

public async generatePreEnactedPolicy(
web3Provider: ethers.providers.Web3Provider,
walletClient: WalletClient,
porterUri: string,
policyParameters: BlockchainPolicyParameters,
includeUrsulas?: readonly ChecksumAddress[],
Expand All @@ -71,7 +73,7 @@ export class Alice {
excludeUrsulas,
includeUrsulas
);
const policy = await this.createPolicy(web3Provider, policyParameters);
const policy = await this.createPolicy(walletClient, policyParameters);
return await policy.generatePreEnactedPolicy(ursulas);
}

Expand All @@ -94,11 +96,12 @@ export class Alice {
}

private async createPolicy(
web3Provider: ethers.providers.Web3Provider,
walletClient: WalletClient,
rawParameters: BlockchainPolicyParameters
): Promise<BlockchainPolicy> {
const publicClient = toPublicClient(walletClient);
const { bob, label, threshold, shares, startDate, endDate } =
await this.validatePolicyParameters(web3Provider, rawParameters);
await this.validatePolicyParameters(publicClient, rawParameters);
const { delegatingKey, verifiedKFrags } = this.generateKFrags(
bob,
label,
Expand All @@ -119,7 +122,7 @@ export class Alice {
}

private async validatePolicyParameters(
web3Provider: ethers.providers.Web3Provider,
publicClient: PublicClient,
rawParams: BlockchainPolicyParameters
): Promise<BlockchainPolicyParameters> {
const startDate = rawParams.startDate ?? new Date();
Expand All @@ -141,9 +144,9 @@ export class Alice {
);
}

const blockNumber = await web3Provider.getBlockNumber();
const block = await web3Provider.getBlock(blockNumber);
const blockTime = new Date(block.timestamp * 1000);
const blockNumber = await getBlockNumber(publicClient);
const block = await getBlock(publicClient, { blockNumber });
const blockTime = new Date(Number(block.timestamp) * 1000);
if (endDate < blockTime) {
throw new Error(
`End date must be in the future, ${endDate} is earlier than block time ${blockTime}).`
Expand Down
14 changes: 8 additions & 6 deletions src/characters/cbd-recipient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import {
SessionStaticSecret,
ThresholdDecryptionRequest,
} from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
import { WalletClient } from 'viem';

import { DkgCoordinatorAgent, DkgParticipant } from '../agents/coordinator';
import { ConditionExpression } from '../conditions';
import { DkgRitual } from '../dkg';
import { PorterClient } from '../porter';
import { fromJSON, toJSON } from '../utils';
import { toPublicClient } from '../viem';

export type ThresholdDecrypterJSON = {
porterUri: string;
Expand All @@ -44,12 +45,12 @@ export class ThresholdDecrypter {

// Retrieve and decrypt ciphertext using provider and condition expression
public async retrieveAndDecrypt(
provider: ethers.providers.Web3Provider,
walletClient: WalletClient,
conditionExpr: ConditionExpression,
ciphertext: Ciphertext
): Promise<Uint8Array> {
const decryptionShares = await this.retrieve(
provider,
walletClient,
conditionExpr,
ciphertext
);
Expand All @@ -64,15 +65,16 @@ export class ThresholdDecrypter {

// Retrieve decryption shares
public async retrieve(
provider: ethers.providers.Web3Provider,
walletClient: WalletClient,
conditionExpr: ConditionExpression,
ciphertext: Ciphertext
): Promise<DecryptionShareSimple[]> {
const publicClient = toPublicClient(walletClient);
const dkgParticipants = await DkgCoordinatorAgent.getParticipants(
provider,
publicClient,
this.ritualId
);
const contextStr = await conditionExpr.buildContext(provider).toJson();
const contextStr = await conditionExpr.buildContext(walletClient).toJson();
const { sharedSecrets, encryptedRequests } = this.makeDecryptionRequests(
this.ritualId,
ciphertext,
Expand Down
Loading
Loading