From 83176ca04f3be445c3d1dabe4384456b6dc554fa Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Thu, 22 May 2025 12:53:51 +0200 Subject: [PATCH 01/11] change interface on getNAMEContract functions to take public and optional wallet clients --- packages/actions/src/client.ts | 16 +++++++- packages/actions/src/contracts/accounts.ts | 16 ++++---- packages/actions/src/contracts/celo-erc20.ts | 17 ++++---- packages/actions/src/contracts/election.ts | 13 ++++--- .../actions/src/contracts/epoch-manager.ts | 20 +++++----- packages/actions/src/contracts/erc20.ts | 11 +++--- .../src/contracts/feecurrency-directory.ts | 13 ++++--- packages/actions/src/contracts/governance.ts | 24 ++++++------ packages/actions/src/contracts/locked-celo.ts | 13 ++++--- .../actions/src/contracts/release-celo.ts | 11 +++--- packages/actions/src/contracts/validators.ts | 13 ++++--- .../stake/elected-rpc-nodes.ts | 11 +++--- .../multicontract-interactions/stake/vote.ts | 6 +-- packages/cli/src/commands/election/current.ts | 3 +- packages/cli/src/commands/election/vote.ts | 2 +- .../commands/epochs/send-validator-payment.ts | 2 +- packages/cli/src/commands/epochs/status.ts | 4 +- packages/cli/src/commands/governance/vote.ts | 2 +- packages/cli/src/commands/network/info.ts | 5 +-- .../commands/releasecelo/transfer-dollars.ts | 2 +- packages/cli/src/commands/transfer/celo.ts | 5 +-- packages/cli/src/commands/transfer/erc20.ts | 7 ++-- packages/cli/src/commands/validator/list.ts | 3 +- .../src/commands/validatorgroup/rpc-urls.ts | 7 ++-- packages/cli/src/packages-to-be/account.ts | 10 ++--- .../cli/src/packages-to-be/getEpochInfo.ts | 6 +-- packages/cli/src/packages-to-be/governance.ts | 11 +++--- packages/cli/src/packages-to-be/validators.ts | 23 ++++++----- packages/cli/src/transfer-stable-base.ts | 6 +-- packages/cli/src/utils/checks.ts | 39 +++++-------------- 30 files changed, 157 insertions(+), 164 deletions(-) diff --git a/packages/actions/src/client.ts b/packages/actions/src/client.ts index 9d419e238..ac136bbf2 100644 --- a/packages/actions/src/client.ts +++ b/packages/actions/src/client.ts @@ -1,4 +1,10 @@ -import type { Account, Client, PublicClient, Transport, WalletClient } from 'viem' +import { + type Account, + type Client, + type PublicClient, + type Transport, + type WalletClient, +} from 'viem' import type { celo, celoAlfajores } from 'viem/chains' import type { celoBaklava } from './chains' @@ -9,3 +15,11 @@ export type CeloClient = Client export type PublicCeloClient = PublicClient export type WalletCeloClient = WalletClient + +export type Clients< + P extends PublicCeloClient | PublicClient = PublicCeloClient, + W extends WalletCeloClient | WalletClient = WalletCeloClient +> = { + public: P + wallet?: W +} diff --git a/packages/actions/src/contracts/accounts.ts b/packages/actions/src/contracts/accounts.ts index a031458a9..e2f53e16f 100644 --- a/packages/actions/src/contracts/accounts.ts +++ b/packages/actions/src/contracts/accounts.ts @@ -1,20 +1,18 @@ import { accountsABI } from '@celo/abis' -import { Address, Client, getContract, GetContractReturnType, PublicClient } from 'viem' - +import { Address, getContract, GetContractReturnType, PublicClient } from 'viem' +import { Clients } from '../client' import { resolveAddress } from './registry' -export type AccountsContract = GetContractReturnType< +export type AccountsContract = GetContractReturnType< typeof accountsABI, - T + C > -export async function getAccountsContract( - client: T -): Promise> { +export async function getAccountsContract(clients: Clients): Promise> { return getContract({ - address: await resolveAddress(client, 'Accounts'), + address: await resolveAddress(clients.public, 'Accounts'), abi: accountsABI, - client, + client: clients, }) } diff --git a/packages/actions/src/contracts/celo-erc20.ts b/packages/actions/src/contracts/celo-erc20.ts index b1df29d46..6216b65a8 100644 --- a/packages/actions/src/contracts/celo-erc20.ts +++ b/packages/actions/src/contracts/celo-erc20.ts @@ -1,17 +1,16 @@ import { goldTokenABI } from '@celo/abis' -import { Client, getContract, GetContractReturnType, PublicClient } from 'viem' +import { getContract, GetContractReturnType } from 'viem' +import { Clients } from '../client' import { resolveAddress } from './registry' -export async function getCeloERC20Contract( - client: T +export type CeloERC20 = GetContractReturnType + +export async function getCeloERC20Contract( + clients: T ): Promise> { return getContract({ - address: await resolveAddress(client, 'GoldToken'), + address: await resolveAddress(clients.public, 'GoldToken'), abi: goldTokenABI, - client, + client: clients, }) } -export type CeloERC20 = GetContractReturnType< - typeof goldTokenABI, - T -> diff --git a/packages/actions/src/contracts/election.ts b/packages/actions/src/contracts/election.ts index 0f4489b3e..d29663d09 100644 --- a/packages/actions/src/contracts/election.ts +++ b/packages/actions/src/contracts/election.ts @@ -1,18 +1,19 @@ import { electionABI } from '@celo/abis' -import { Client, getContract, GetContractReturnType, PublicClient } from 'viem' +import { getContract, GetContractReturnType } from 'viem' +import { Clients } from '../client' import { resolveAddress } from './registry' -export type ElectionContract = GetContractReturnType< +export type ElectionContract = GetContractReturnType< typeof electionABI, T > -export async function getElectionContract( - client: T +export async function getElectionContract( + clients: T ): Promise> { return getContract({ - address: await resolveAddress(client, 'Election'), + address: await resolveAddress(clients.public, 'Election'), abi: electionABI, - client, + client: clients, }) } diff --git a/packages/actions/src/contracts/epoch-manager.ts b/packages/actions/src/contracts/epoch-manager.ts index 54d9bb64c..7f36e9cbd 100644 --- a/packages/actions/src/contracts/epoch-manager.ts +++ b/packages/actions/src/contracts/epoch-manager.ts @@ -1,17 +1,19 @@ import { epochManagerABI } from '@celo/abis' -import { Client, getContract, GetContractReturnType, PublicClient } from 'viem' +import { getContract, GetContractReturnType } from 'viem' +import { Clients } from '../client' import { resolveAddress } from './registry' -export async function getEpochManagerContract( - client: T +export type EpochManager = GetContractReturnType< + typeof epochManagerABI, + T +> + +export async function getEpochManagerContract( + clients: T ): Promise> { return getContract({ - address: await resolveAddress(client, 'EpochManager'), + address: await resolveAddress(clients.public, 'EpochManager'), abi: epochManagerABI, - client, + client: clients, }) } -export type EpochManager = GetContractReturnType< - typeof epochManagerABI, - T -> diff --git a/packages/actions/src/contracts/erc20.ts b/packages/actions/src/contracts/erc20.ts index 78000d179..432e8b96e 100644 --- a/packages/actions/src/contracts/erc20.ts +++ b/packages/actions/src/contracts/erc20.ts @@ -1,13 +1,14 @@ -import { Address, Client, erc20Abi, getContract, GetContractReturnType, PublicClient } from 'viem' +import { erc20Abi, getContract, type Address, type GetContractReturnType } from 'viem' +import { Clients } from '../client' -export async function getERC20Contract( - client: T, +export async function getERC20Contract( + clients: T, address: Address ): Promise> { return getContract({ address, abi: erc20Abi, - client, + client: clients, }) } -export type ERC20 = GetContractReturnType +export type ERC20 = GetContractReturnType diff --git a/packages/actions/src/contracts/feecurrency-directory.ts b/packages/actions/src/contracts/feecurrency-directory.ts index 3d82cdf06..a96246e56 100644 --- a/packages/actions/src/contracts/feecurrency-directory.ts +++ b/packages/actions/src/contracts/feecurrency-directory.ts @@ -1,17 +1,18 @@ import { feeCurrencyDirectoryABI } from '@celo/abis' -import { Client, getContract, GetContractReturnType, PublicClient } from 'viem' +import { getContract, GetContractReturnType } from 'viem' +import { Clients } from '../client' import { resolveAddress } from './registry' -export async function getFeeCurrencyDirectoryContract( - client: T +export async function getFeeCurrencyDirectoryContract( + clients: T ): Promise> { return getContract({ - address: await resolveAddress(client, 'FeeCurrencyDirectory'), + address: await resolveAddress(clients.public, 'FeeCurrencyDirectory'), abi: feeCurrencyDirectoryABI, - client, + client: clients, }) } -export type FeeCurrencyDirectory = GetContractReturnType< +export type FeeCurrencyDirectory = GetContractReturnType< typeof feeCurrencyDirectoryABI, T > diff --git a/packages/actions/src/contracts/governance.ts b/packages/actions/src/contracts/governance.ts index 5ead35eec..9dbdfd981 100644 --- a/packages/actions/src/contracts/governance.ts +++ b/packages/actions/src/contracts/governance.ts @@ -1,11 +1,11 @@ import { governanceABI } from '@celo/abis' import { zip } from '@celo/base' import { voteProposal, VoteProposalTypes } from '@celo/core' -import { Client, getContract, GetContractReturnType, PublicClient } from 'viem' -import { WalletCeloClient } from '../client' +import { getContract, GetContractReturnType } from 'viem' +import { Clients, PublicCeloClient } from '../client' import { resolveAddress } from './registry' -export type GovernanceContract = GetContractReturnType< +export type GovernanceContract = GetContractReturnType< typeof governanceABI, T > @@ -24,22 +24,22 @@ export interface UpvoteRecord { upvotes: bigint } -export async function getGovernanceContract( - client: T +export async function getGovernanceContract( + clients: T ): Promise> { return getContract({ - address: await resolveAddress(client, 'Governance'), + address: await resolveAddress(clients.public, 'Governance'), abi: governanceABI, - client, + client: clients, }) } -export async function vote( - client: T, +export async function vote = Required>( + clients: C, proposalId: bigint, voteValue: VoteProposalTypes ) { - const contract = await getGovernanceContract(client) + const contract = await getGovernanceContract(clients) return voteProposal( { vote: async (proposalID, proposalIndex, voteValue) => { @@ -56,7 +56,7 @@ export async function vote( ) } -export const getQueue = async (client: PublicClient) => { +export const getQueue = async (client: PublicCeloClient) => { const queue = await client.readContract({ address: await resolveAddress(client, 'Governance'), abi: governanceABI, @@ -74,7 +74,7 @@ export const getQueue = async (client: PublicClient) => { } export const getProposalStage = async ( - client: PublicClient, + client: PublicCeloClient, proposalId: bigint ): Promise => { const queue = await getQueue(client) diff --git a/packages/actions/src/contracts/locked-celo.ts b/packages/actions/src/contracts/locked-celo.ts index b88b27083..2219ab13d 100644 --- a/packages/actions/src/contracts/locked-celo.ts +++ b/packages/actions/src/contracts/locked-celo.ts @@ -1,17 +1,18 @@ import { lockedGoldABI } from '@celo/abis' -import { Client, getContract, GetContractReturnType, PublicClient } from 'viem' +import { getContract, GetContractReturnType } from 'viem' +import { Clients } from '../client' import { resolveAddress } from './registry' -export async function getLockedCeloContract( - client: T +export async function getLockedCeloContract( + clients: T ): Promise> { return getContract({ - address: await resolveAddress(client, 'LockedGold'), + address: await resolveAddress(clients.public, 'LockedGold'), abi: lockedGoldABI, - client, + client: clients, }) } -export type LockedCeloContract = GetContractReturnType< +export type LockedCeloContract = GetContractReturnType< typeof lockedGoldABI, T > diff --git a/packages/actions/src/contracts/release-celo.ts b/packages/actions/src/contracts/release-celo.ts index ffad6d420..89a0899ce 100644 --- a/packages/actions/src/contracts/release-celo.ts +++ b/packages/actions/src/contracts/release-celo.ts @@ -1,17 +1,18 @@ import { releaseGoldABI } from '@celo/abis' -import { Address, Client, getContract, GetContractReturnType, PublicClient } from 'viem' +import { Address, getContract, GetContractReturnType } from 'viem' +import { Clients } from '../client' -export async function getReleaseCeloContract( - client: T, +export async function getReleaseCeloContract( + clients: T, address: Address ): Promise> { return getContract({ address, abi: releaseGoldABI, - client, + client: clients, }) } -export type ReleaseCeloContract = GetContractReturnType< +export type ReleaseCeloContract = GetContractReturnType< typeof releaseGoldABI, T > diff --git a/packages/actions/src/contracts/validators.ts b/packages/actions/src/contracts/validators.ts index 63fff4ebe..4e4750b71 100644 --- a/packages/actions/src/contracts/validators.ts +++ b/packages/actions/src/contracts/validators.ts @@ -1,17 +1,18 @@ import { validatorsABI } from '@celo/abis' -import { Client, getContract, GetContractReturnType, PublicClient } from 'viem' +import { getContract, GetContractReturnType } from 'viem' +import { Clients } from '../client' import { resolveAddress } from './registry' -export async function getValidatorsContract( - client: T +export async function getValidatorsContract( + clients: T ): Promise> { return getContract({ - address: await resolveAddress(client, 'Validators'), + address: await resolveAddress(clients.public, 'Validators'), abi: validatorsABI, - client, + client: clients, }) } -export type ValidatorsContract = GetContractReturnType< +export type ValidatorsContract = GetContractReturnType< typeof validatorsABI, T > diff --git a/packages/actions/src/multicontract-interactions/stake/elected-rpc-nodes.ts b/packages/actions/src/multicontract-interactions/stake/elected-rpc-nodes.ts index 455430427..9330c4def 100644 --- a/packages/actions/src/multicontract-interactions/stake/elected-rpc-nodes.ts +++ b/packages/actions/src/multicontract-interactions/stake/elected-rpc-nodes.ts @@ -1,5 +1,6 @@ import { eqAddress, NULL_ADDRESS } from '@celo/base' -import { Address, PublicClient } from 'viem' +import { Address } from 'viem' +import { PublicCeloClient } from '../../client' import { AccountsContract, getAccountsContract } from '../../contracts/accounts' import { getEpochManagerContract } from '../../contracts/epoch-manager' import { getValidatorsContract, ValidatorsContract } from '../../contracts/validators' @@ -31,13 +32,13 @@ export interface ElectedRpcNode extends UnnamedRpcNode { * @returns A promise that resolves to an array of elected validator objects, each decorated with additional metadata. */ export async function getElectedRpcNodes( - client: PublicClient, + client: PublicCeloClient, options: { showChanges?: boolean } = {} ) { const [validators, epochManager, accountsContract] = await Promise.all([ - getValidatorsContract(client), - getEpochManagerContract(client), - getAccountsContract(client), + getValidatorsContract({ public: client }), + getEpochManagerContract({ public: client }), + getAccountsContract({ public: client }), ]) const electedSigners = await epochManager.read.getElectedSigners() diff --git a/packages/actions/src/multicontract-interactions/stake/vote.ts b/packages/actions/src/multicontract-interactions/stake/vote.ts index ea75ff66d..7df00d9c9 100644 --- a/packages/actions/src/multicontract-interactions/stake/vote.ts +++ b/packages/actions/src/multicontract-interactions/stake/vote.ts @@ -1,6 +1,6 @@ import { vote as coreVote, VoteAdapter } from '@celo/core' import { Address, Hex } from 'viem' -import { WalletCeloClient } from '../../client' +import { Clients } from '../../client' import { getElectionContract } from '../../contracts/election' /** @@ -16,11 +16,11 @@ import { getElectionContract } from '../../contracts/election' * @returns A promise that resolves to a Hex string representing the transaction hash. */ export async function vote( - client: WalletCeloClient, + clients: Required, validatorGroup: Address, value: bigint ): Promise { - const election = await getElectionContract(client) + const election = await getElectionContract(clients) const adapter: VoteAdapter = { vote: async (validatorGroup, value, lesser, greater) => { const { request } = await election.simulate.vote([validatorGroup, value, lesser, greater]) diff --git a/packages/cli/src/commands/election/current.ts b/packages/cli/src/commands/election/current.ts index 90346154b..fc4663883 100644 --- a/packages/cli/src/commands/election/current.ts +++ b/packages/cli/src/commands/election/current.ts @@ -1,7 +1,6 @@ import { Flags, ux } from '@oclif/core' import { ElectedRpcNode, getElectedRpcNodes } from '@celo/actions/staking' -import { PublicClient } from 'viem' import { BaseCommand } from '../../base' export const valSetRpcNodeTable: ux.Table.table.Columns<{ address: string }> = { @@ -35,7 +34,7 @@ export default class ElectionCurrent extends BaseCommand { } async run() { - const client = (await this.getPublicClient()) as PublicClient + const client = await this.getPublicClient() const res = await this.parse(ElectionCurrent) ux.action.start('Fetching currently Elected Community Rpc Nodes') const validatorList = await getElectedRpcNodes(client, { diff --git a/packages/cli/src/commands/election/vote.ts b/packages/cli/src/commands/election/vote.ts index 219380563..1438c7ff8 100644 --- a/packages/cli/src/commands/election/vote.ts +++ b/packages/cli/src/commands/election/vote.ts @@ -36,7 +36,7 @@ export default class ElectionVote extends BaseCommand { .hasEnoughNonvotingLockedCelo(value) .runChecks() - const pendingTxHash = vote(walletClient, res.flags.for, value) + const pendingTxHash = vote({ public: publicClient, wallet: walletClient }, res.flags.for, value) await displayViemTx('Electon -> Vote', pendingTxHash, publicClient, { abi: electionABI, displayEventName: 'ValidatorGroupVoteCast', diff --git a/packages/cli/src/commands/epochs/send-validator-payment.ts b/packages/cli/src/commands/epochs/send-validator-payment.ts index 471b9b856..4c1e04aac 100644 --- a/packages/cli/src/commands/epochs/send-validator-payment.ts +++ b/packages/cli/src/commands/epochs/send-validator-payment.ts @@ -31,7 +31,7 @@ export default class SendValidatorPayment extends BaseCommand { const wallet = await this.getWalletClient() const res = await this.parse(SendValidatorPayment) - const epochManagerContract = await getEpochManagerContract(wallet) + const epochManagerContract = await getEpochManagerContract({ wallet, public: client }) await newCheckBuilder(this).isValidator(res.flags.for).runChecks() diff --git a/packages/cli/src/commands/epochs/status.ts b/packages/cli/src/commands/epochs/status.ts index 4f712903a..a29884942 100644 --- a/packages/cli/src/commands/epochs/status.ts +++ b/packages/cli/src/commands/epochs/status.ts @@ -1,5 +1,5 @@ import { ux } from '@oclif/core' -import { BaseError, PublicClient } from 'viem' +import { BaseError } from 'viem' import { BaseCommand } from '../../base' import { getEpochInfo } from '../../packages-to-be/getEpochInfo' export default class EpochStatus extends BaseCommand { @@ -28,7 +28,7 @@ export default class EpochStatus extends BaseCommand { isOnEpochProcess, isIndividualProcessing, isTimeForNextEpoch, - ] = await getEpochInfo(client as unknown as PublicClient) + ] = await getEpochInfo(client) ux.action.stop('Done\n') // if currentEpoch is a tuple, destructure it otherwise it would be an error message diff --git a/packages/cli/src/commands/governance/vote.ts b/packages/cli/src/commands/governance/vote.ts index 92a47a1d5..57313e303 100644 --- a/packages/cli/src/commands/governance/vote.ts +++ b/packages/cli/src/commands/governance/vote.ts @@ -38,7 +38,7 @@ export default class Vote extends BaseCommand { const publicClient = await this.getPublicClient() // do not wait this. it will be awiated in the displayViemTx - const pendingVote = vote(walletClient, id, voteValue) + const pendingVote = vote({ public: publicClient, wallet: walletClient }, id, voteValue) await displayViemTx('Governance -> vote', pendingVote, publicClient, { abi: governanceABI, displayEventName: 'ProposalVoted', diff --git a/packages/cli/src/commands/network/info.ts b/packages/cli/src/commands/network/info.ts index b0041544b..7f37f0544 100644 --- a/packages/cli/src/commands/network/info.ts +++ b/packages/cli/src/commands/network/info.ts @@ -1,6 +1,5 @@ import { getEpochManagerContract } from '@celo/actions/contracts/epoch-manager' import { Flags } from '@oclif/core' -import { PublicClient } from 'viem' import { BaseCommand } from '../../base' import { printValueMapRecursive } from '../../utils/cli' import { ViewCommmandFlags } from '../../utils/flags' @@ -19,14 +18,14 @@ export default class Info extends BaseCommand { } async run() { - const client = (await this.getPublicClient()) as PublicClient + const client = await this.getPublicClient() const res = await this.parse(Info) let latestEpochNumber: bigint let epochSize: bigint const blockNumber = await client.getBlockNumber() - const epochManagerContract = await getEpochManagerContract(client) + const epochManagerContract = await getEpochManagerContract({ public: client }) latestEpochNumber = await epochManagerContract.read.getCurrentEpochNumber() epochSize = await epochManagerContract.read.epochDuration() diff --git a/packages/cli/src/commands/releasecelo/transfer-dollars.ts b/packages/cli/src/commands/releasecelo/transfer-dollars.ts index 0744650ae..094434d0d 100644 --- a/packages/cli/src/commands/releasecelo/transfer-dollars.ts +++ b/packages/cli/src/commands/releasecelo/transfer-dollars.ts @@ -30,7 +30,7 @@ export default class TransferDollars extends ReleaseGoldBaseCommand { const { flags } = await this.parse(TransferDollars) const client = await this.getPublicClient() const wallet = await this.getWalletClient() - const releaseCeloContract = await getReleaseCeloContract(wallet, flags.contract) + const releaseCeloContract = await getReleaseCeloContract({public: client, wallet}, flags.contract) const isRevoked = await releaseCeloContract.read.isRevoked() diff --git a/packages/cli/src/commands/transfer/celo.ts b/packages/cli/src/commands/transfer/celo.ts index eb220286f..0eee4be0a 100644 --- a/packages/cli/src/commands/transfer/celo.ts +++ b/packages/cli/src/commands/transfer/celo.ts @@ -2,7 +2,6 @@ import { getGasPriceOnCelo } from '@celo/actions' import { getCeloERC20Contract } from '@celo/actions/contracts/celo-erc20' import { getERC20Contract } from '@celo/actions/contracts/erc20' import { Flags } from '@oclif/core' -import { PublicClient, publicActions } from 'viem' import { CeloTransactionRequest } from 'viem/celo' import { BaseCommand } from '../../base' import { newCheckBuilder } from '../../utils/checks' @@ -39,7 +38,7 @@ export default class TransferCelo extends BaseCommand { const value = res.flags.value const feeCurrency = res.flags.gasCurrency - const celoERC20Contract = await getCeloERC20Contract(wallet.extend(publicActions)) + const celoERC20Contract = await getCeloERC20Contract({ public: client, wallet }) const transferParams = (feeCurrency ? { feeCurrency } : {}) as Pick< CeloTransactionRequest, @@ -63,7 +62,7 @@ export default class TransferCelo extends BaseCommand { : client.estimateGas({ to, value }), getGasPriceOnCelo(client, feeCurrency), (feeCurrency - ? await getERC20Contract(client as PublicClient, feeCurrency) + ? await getERC20Contract({ public: client }, feeCurrency) : celoERC20Contract ).read.balanceOf([from]), ]) diff --git a/packages/cli/src/commands/transfer/erc20.ts b/packages/cli/src/commands/transfer/erc20.ts index 1b873c5c9..ae700dcd4 100644 --- a/packages/cli/src/commands/transfer/erc20.ts +++ b/packages/cli/src/commands/transfer/erc20.ts @@ -1,7 +1,6 @@ import { getGasPriceOnCelo } from '@celo/actions' import { getCeloERC20Contract } from '@celo/actions/contracts/celo-erc20' import { getERC20Contract } from '@celo/actions/contracts/erc20' -import { PublicClient } from 'viem' import { CeloTransactionRequest } from 'viem/celo' import { BaseCommand } from '../../base' import { newCheckBuilder } from '../../utils/checks' @@ -49,7 +48,7 @@ export default class TransferErc20 extends BaseCommand { const value = res.flags.value const feeCurrency = res.flags.gasCurrency - const erc20Contract = await getERC20Contract(wallet, res.flags.erc20Address) + const erc20Contract = await getERC20Contract({ public: client, wallet }, res.flags.erc20Address) const transferParams = (feeCurrency ? { feeCurrency } : {}) as Pick< CeloTransactionRequest, 'gas' | 'feeCurrency' | 'maxFeePerGas' @@ -80,8 +79,8 @@ export default class TransferErc20 extends BaseCommand { erc20Contract.estimateGas.transfer([to, value], transferParams), getGasPriceOnCelo(client, feeCurrency), (feeCurrency - ? await getERC20Contract(client as PublicClient, feeCurrency) - : await getCeloERC20Contract(client as PublicClient) + ? await getERC20Contract({ public: client }, feeCurrency) + : await getCeloERC20Contract({ public: client }) ).read.balanceOf([from]), ]) diff --git a/packages/cli/src/commands/validator/list.ts b/packages/cli/src/commands/validator/list.ts index 73e18a8fd..a56091072 100644 --- a/packages/cli/src/commands/validator/list.ts +++ b/packages/cli/src/commands/validator/list.ts @@ -1,7 +1,6 @@ import { Validator } from '@celo/contractkit/lib/wrappers/Validators' import { ux } from '@oclif/core' -import { PublicClient } from 'viem' import { BaseCommand } from '../../base' import { getRegisteredValidators } from '../../packages-to-be/validators' import { ViewCommmandFlags } from '../../utils/flags' @@ -32,7 +31,7 @@ export default class ValidatorList extends BaseCommand { ux.action.start('Fetching Registered Community Rpc Nodes') - const validatorList = await getRegisteredValidators(client as PublicClient) + const validatorList = await getRegisteredValidators(client) ux.action.stop() ux.table( diff --git a/packages/cli/src/commands/validatorgroup/rpc-urls.ts b/packages/cli/src/commands/validatorgroup/rpc-urls.ts index 79d9357fc..1acfbdd99 100644 --- a/packages/cli/src/commands/validatorgroup/rpc-urls.ts +++ b/packages/cli/src/commands/validatorgroup/rpc-urls.ts @@ -4,7 +4,6 @@ import { concurrentMap, StrongAddress } from '@celo/base' import { ClaimTypes, IdentityMetadataWrapper } from '@celo/metadata-claims' import { AccountMetadataSignerGetters } from '@celo/metadata-claims/lib/types' import { Flags, ux } from '@oclif/core' -import { PublicClient } from 'viem' import { BaseCommand } from '../../base' import { getMetadataURLs, getNames } from '../../packages-to-be/account' import { @@ -42,7 +41,7 @@ export default class RpcUrls extends BaseCommand { const res = await this.parse(RpcUrls) - const client = (await this.getPublicClient()) as PublicClient + const client = await this.getPublicClient() let validatorAddresses: StrongAddress[] = [] @@ -50,7 +49,7 @@ export default class RpcUrls extends BaseCommand { if (res.flags.all) { validatorAddresses = await getRegisteredValidatorsAddresses(client) } else { - const epochManager = await getEpochManagerContract(client) + const epochManager = await getEpochManagerContract({ public: client }) validatorAddresses = (await epochManager.read.getElectedAccounts()) as StrongAddress[] } @@ -74,7 +73,7 @@ export default class RpcUrls extends BaseCommand { ux.action.stop() ux.action.start(`Fetching Group Metadata`) - const accountsConract = await getAccountsContract(client) + const accountsConract = await getAccountsContract({ public: client }) // Fetch the name for each group const validatorGroupNames = await getNames(client, [ ...new Set(validatorToGroup.values()), diff --git a/packages/cli/src/packages-to-be/account.ts b/packages/cli/src/packages-to-be/account.ts index 8d993a8a8..4af735120 100644 --- a/packages/cli/src/packages-to-be/account.ts +++ b/packages/cli/src/packages-to-be/account.ts @@ -1,5 +1,5 @@ import { lockedGoldABI } from '@celo/abis' -import { resolveAddress } from '@celo/actions' +import { PublicCeloClient, resolveAddress } from '@celo/actions' import { getAccountsContract } from '@celo/actions/contracts/accounts' import { StrongAddress } from '@celo/base' import { Address, erc20Abi, PublicClient } from 'viem' @@ -71,8 +71,8 @@ export const getTotalBalance = async ( } } -export async function getMetadataURLs(client: PublicClient, addresses: Address[]) { - const contract = await getAccountsContract(client) +export async function getMetadataURLs(client: PublicCeloClient, addresses: Address[]) { + const contract = await getAccountsContract({ public: client }) const urlResults = await Promise.allSettled( addresses.map(async (address) => { @@ -85,8 +85,8 @@ export async function getMetadataURLs(client: PublicClient, addresses: Address[] return new Map(filtered) } -export async function getNames(client: PublicClient, addresses: Address[]) { - const contract = await getAccountsContract(client) +export async function getNames(client: PublicCeloClient, addresses: Address[]) { + const contract = await getAccountsContract({ public: client }) const nameResults = await Promise.allSettled( addresses.map(async (address) => { diff --git a/packages/cli/src/packages-to-be/getEpochInfo.ts b/packages/cli/src/packages-to-be/getEpochInfo.ts index 0008f7a14..c3a378d8f 100644 --- a/packages/cli/src/packages-to-be/getEpochInfo.ts +++ b/packages/cli/src/packages-to-be/getEpochInfo.ts @@ -1,8 +1,8 @@ +import { PublicCeloClient } from '@celo/actions' import { getEpochManagerContract } from '@celo/actions/contracts/epoch-manager' -import { PublicClient } from 'viem' -export async function getEpochInfo(client: PublicClient) { - const epochManager = await getEpochManagerContract(client) +export async function getEpochInfo(client: PublicCeloClient) { + const epochManager = await getEpochManagerContract({ public: client }) const results = await Promise.allSettled([ epochManager.read.getCurrentEpoch(), diff --git a/packages/cli/src/packages-to-be/governance.ts b/packages/cli/src/packages-to-be/governance.ts index da40a9b8b..69a190385 100644 --- a/packages/cli/src/packages-to-be/governance.ts +++ b/packages/cli/src/packages-to-be/governance.ts @@ -1,9 +1,8 @@ import { governanceABI } from '@celo/abis' -import { resolveAddress } from '@celo/actions' +import { PublicCeloClient, resolveAddress } from '@celo/actions' import { getProposalStage, ProposalStage } from '@celo/actions/contracts/governance' import { bufferToHex, StrongAddress } from '@celo/base' import BigNumber from 'bignumber.js' -import { PublicClient } from 'viem' import { bigintToBigNumber } from './utils' type DequeuedStageDurations = Pick< @@ -20,7 +19,7 @@ export interface ProposalMetadata { } export const getHotfixRecord = async ( - client: PublicClient, + client: PublicCeloClient, hash: Buffer ): Promise => { const address = await resolveAddress(client, 'Governance') @@ -45,7 +44,7 @@ type StageDurations = { } export const getProposalSchedule = async ( - client: PublicClient, + client: PublicCeloClient, proposalId: bigint ): Promise>> => { const meta = await getProposalMetadata(client, proposalId) @@ -79,7 +78,7 @@ export const getProposalSchedule = async ( } export const getProposalMetadata = async ( - client: PublicClient, + client: PublicCeloClient, proposalId: bigint ): Promise => { const proposal = await client.readContract({ @@ -98,7 +97,7 @@ export const getProposalMetadata = async ( } } -export const stageDurations = async (client: PublicClient): Promise => { +export const stageDurations = async (client: PublicCeloClient): Promise => { const durations = await client.readContract({ address: await resolveAddress(client, 'Governance'), abi: governanceABI, diff --git a/packages/cli/src/packages-to-be/validators.ts b/packages/cli/src/packages-to-be/validators.ts index 4f118ea43..b384e2ed2 100644 --- a/packages/cli/src/packages-to-be/validators.ts +++ b/packages/cli/src/packages-to-be/validators.ts @@ -1,10 +1,9 @@ import { accountsABI, lockedGoldABI, validatorsABI } from '@celo/abis' -import { resolveAddress } from '@celo/actions' +import { PublicCeloClient, resolveAddress } from '@celo/actions' import { getValidatorsContract } from '@celo/actions/contracts/validators' import { Address, concurrentMap, ensureLeading0x, eqAddress, StrongAddress } from '@celo/base' import { fromFixed } from '@celo/utils/lib/fixidity' import BigNumber from 'bignumber.js' -import { PublicClient } from 'viem' import { bigintToBigNumber } from './utils' export interface Validator { @@ -34,7 +33,7 @@ export interface MembershipHistoryExtraData { tail: number } -export const getValidatorLockedGoldRequirements = async (client: PublicClient) => { +export const getValidatorLockedGoldRequirements = async (client: PublicCeloClient) => { const requirements = await client.readContract({ address: await resolveAddress(client, 'Validators'), abi: validatorsABI, @@ -48,7 +47,7 @@ export const getValidatorLockedGoldRequirements = async (client: PublicClient) = } export const meetsValidatorBalanceRequirements = async ( - client: PublicClient, + client: PublicCeloClient, address: StrongAddress ) => { const accountTotalLockedGold = await client.readContract({ @@ -67,7 +66,7 @@ export const meetsValidatorBalanceRequirements = async ( } export const meetsValidatorGroupBalanceRequirements = async ( - client: PublicClient, + client: PublicCeloClient, address: StrongAddress ) => { const accountTotalLockedGold = await client.readContract({ @@ -90,10 +89,10 @@ export const meetsValidatorGroupBalanceRequirements = async ( @returns the group the given address is affiliated with */ export async function getValidatorsGroup( - client: PublicClient, + client: PublicCeloClient, validatorAddress: StrongAddress ): Promise { - const contract = await getValidatorsContract(client) + const contract = await getValidatorsContract({ public: client }) return contract.read.getValidatorsGroup([validatorAddress]) } @@ -102,7 +101,7 @@ export async function getValidatorsGroup( @returns group info including name, commission, affiliates + members and slash data. */ export const getValidatorGroup = async ( - client: PublicClient, + client: PublicCeloClient, address: Address, getAffiliates: boolean = true, blockNumber?: number @@ -145,7 +144,7 @@ export const getValidatorGroup = async ( } export const getRegisteredValidators = async ( - client: PublicClient, + client: PublicCeloClient, blockNumber?: number ): Promise => { const vgAddresses = await getRegisteredValidatorsAddresses(client, blockNumber) @@ -154,7 +153,7 @@ export const getRegisteredValidators = async ( } export const getRegisteredValidatorsAddresses = async ( - client: PublicClient, + client: PublicCeloClient, blockNumber?: number ): Promise => { return (await client.readContract({ @@ -166,7 +165,7 @@ export const getRegisteredValidatorsAddresses = async ( } export const getValidator = async ( - client: PublicClient, + client: PublicCeloClient, address: Address, blockNumber?: number ): Promise => { @@ -197,7 +196,7 @@ export const getValidator = async ( } export const getValidatorMembershipHistoryExtraData = async ( - client: PublicClient, + client: PublicCeloClient, validator: StrongAddress ): Promise => { const history = await client.readContract({ diff --git a/packages/cli/src/transfer-stable-base.ts b/packages/cli/src/transfer-stable-base.ts index 21d0e3e09..84e432a12 100644 --- a/packages/cli/src/transfer-stable-base.ts +++ b/packages/cli/src/transfer-stable-base.ts @@ -2,7 +2,7 @@ import { getGasPriceOnCelo } from '@celo/actions' import { getCeloERC20Contract } from '@celo/actions/contracts/celo-erc20' import { getERC20Contract } from '@celo/actions/contracts/erc20' import { Flags } from '@oclif/core' -import { isAddressEqual, publicActions, PublicClient } from 'viem' +import { isAddressEqual, publicActions } from 'viem' import { CeloTransactionRequest } from 'viem/celo' import { BaseCommand } from './base' import { @@ -69,7 +69,7 @@ export abstract class TransferStableBase extends BaseCommand { } catch { failWith(`The ${stableToken} token was not deployed yet`) } - const celoContract = await getCeloERC20Contract(wallet.extend(publicActions)) + const celoContract = await getCeloERC20Contract({ public: client, wallet }) const transferParams = (feeCurrency ? { feeCurrency } : {}) as Pick< CeloTransactionRequest, @@ -99,7 +99,7 @@ export abstract class TransferStableBase extends BaseCommand { (feeCurrency ? feeInSameStableTokenAsTransfer ? stableTokenContract - : await getERC20Contract(client as PublicClient, feeCurrency) + : await getERC20Contract({ public: client }, feeCurrency) : celoContract ).read.balanceOf([from]), stableTokenContract.read.balanceOf([from]), diff --git a/packages/cli/src/utils/checks.ts b/packages/cli/src/utils/checks.ts index 2c26f0ad1..04dd18377 100644 --- a/packages/cli/src/utils/checks.ts +++ b/packages/cli/src/utils/checks.ts @@ -22,15 +22,7 @@ import { HotfixRecord, ProposalStage } from '@celo/contractkit/lib/wrappers/Gove import BigNumber from 'bignumber.js' import chalk from 'chalk' import { fetch } from 'cross-fetch' -import { - erc20Abi, - formatEther, - formatUnits, - getAddress, - isAddressEqual, - PublicClient, - WalletClient, -} from 'viem' +import { erc20Abi, formatEther, formatUnits, getAddress, isAddressEqual, WalletClient } from 'viem' import { BaseCommand } from '../base' import { getHotfixRecord, getProposalSchedule } from '../packages-to-be/governance' import { StableToken, StableTokens } from '../packages-to-be/stable-tokens' @@ -76,10 +68,10 @@ class CheckBuilder { "'The wallet address has been sanctioned by the U.S. Department of the Treasury.''All U.S. persons are prohibited from accessing, receiving, accepting, or facilitating any property 'and interests in property (including use of any technology, software or software patch(es)) of these'designated digital wallet addresses. These prohibitions include the making of any contribution or''provision of funds, goods, or services by, to, or for the benefit of any blocked person and the ''receipt of any contribution or provision of funds, goods, or services from any such person and ' 'all designated digital asset wallets.'" constructor(private command: BaseCommand, private signer?: StrongAddress) {} - private async getClient(): Promise { + private async getClient() { // In this case we're not using any Celo-specific client features, so it can be // safely casted to PublicClient - return this.command.getPublicClient() as Promise + return this.command.getPublicClient() } private async getWalletClient(): Promise { @@ -112,9 +104,7 @@ class CheckBuilder { ) => A ): () => Promise> { return async () => { - const validatorsContract = (await getValidatorsContract( - await this.getClient() - )) as ValidatorsContract + const validatorsContract = await getValidatorsContract({ public: await this.getClient() }) if (this.signer) { try { @@ -144,12 +134,8 @@ class CheckBuilder { ) => A ): () => Promise> { return async () => { - const lockedCeloContract = (await getLockedCeloContract( - await this.getClient() - )) as LockedCeloContract - const validatorsContract = (await getValidatorsContract( - await this.getClient() - )) as ValidatorsContract + const lockedCeloContract = await getLockedCeloContract({ public: await this.getClient() }) + const validatorsContract = await getValidatorsContract({ public: await this.getClient() }) if (this.signer) { try { @@ -165,9 +151,7 @@ class CheckBuilder { private withAccounts(f: (accounts: AccountsContract) => A): () => Promise> { return async () => { - const accountsContract = (await getAccountsContract( - await this.getClient() - )) as AccountsContract + const accountsContract = await getAccountsContract({ public: await this.getClient() }) return f(accountsContract) as Resolve } @@ -175,9 +159,7 @@ class CheckBuilder { private withGovernance(f: (governance: GovernanceContract) => A): () => Promise> { return async () => { - const governanceContract = (await getGovernanceContract( - await this.getClient() - )) as GovernanceContract + const governanceContract = await getGovernanceContract({ public: await this.getClient() }) return f(governanceContract) as Resolve } @@ -187,9 +169,8 @@ class CheckBuilder { f: (feeCurrencyDirectory: FeeCurrencyDirectory) => A ): () => Promise> { return async () => { - const feeCurrencyDirectoryContract = (await getFeeCurrencyDirectoryContract( - await this.getClient() - )) as FeeCurrencyDirectory + const client = await this.getClient() + const feeCurrencyDirectoryContract = await getFeeCurrencyDirectoryContract({ public: client }) return f(feeCurrencyDirectoryContract) as Resolve } From 96c4af469d398dcd576c177a4eb4cf46b681fc15 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Thu, 22 May 2025 13:12:54 +0200 Subject: [PATCH 02/11] fix type --- packages/actions/src/contracts/accounts.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/actions/src/contracts/accounts.ts b/packages/actions/src/contracts/accounts.ts index e2f53e16f..167e89325 100644 --- a/packages/actions/src/contracts/accounts.ts +++ b/packages/actions/src/contracts/accounts.ts @@ -1,6 +1,6 @@ import { accountsABI } from '@celo/abis' -import { Address, getContract, GetContractReturnType, PublicClient } from 'viem' -import { Clients } from '../client' +import { Address, getContract, GetContractReturnType } from 'viem' +import { Clients, PublicCeloClient } from '../client' import { resolveAddress } from './registry' export type AccountsContract = GetContractReturnType< @@ -18,7 +18,10 @@ export async function getAccountsContract(clients: Clients): Promise => { +export const signerToAccount = async ( + client: PublicCeloClient, + signer: Address +): Promise
=> { return await client.readContract({ address: await resolveAddress(client, 'Accounts'), abi: accountsABI, From c8bb2826b23f3c806342cc14edf555deda82268a Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Thu, 22 May 2025 17:28:46 +0200 Subject: [PATCH 03/11] fix tests, turns out that public clients need accounts too sometimes (when looking up info about self) --- packages/actions/package.json | 2 +- packages/actions/src/client.ts | 2 +- .../actions/src/contracts/governance.test.ts | 20 +++++++++++-------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/actions/package.json b/packages/actions/package.json index d99dc8770..9a3f44f20 100644 --- a/packages/actions/package.json +++ b/packages/actions/package.json @@ -49,7 +49,7 @@ "postbuild": "node ../../scripts/post-build.mjs", "clean": "yarn --top-level run tsc -b . --clean && yarn --top-level run rimraf dist", "docs": "yarn --top-level run typedoc", - "test": "yarn run vitest --run --passWithNoTests", + "test": "yarn run vitest --run --retry=1", "check-size": "size-limit", "test:watch": "yarn run vitest --watch", "test:changes": "yarn run vitest --run --changed", diff --git a/packages/actions/src/client.ts b/packages/actions/src/client.ts index ac136bbf2..2382ff25e 100644 --- a/packages/actions/src/client.ts +++ b/packages/actions/src/client.ts @@ -12,7 +12,7 @@ type CeloChain = typeof celo | typeof celoAlfajores | typeof celoBaklava export type CeloClient = Client -export type PublicCeloClient = PublicClient +export type PublicCeloClient = PublicClient export type WalletCeloClient = WalletClient diff --git a/packages/actions/src/contracts/governance.test.ts b/packages/actions/src/contracts/governance.test.ts index cbdedba96..111b0eb25 100644 --- a/packages/actions/src/contracts/governance.test.ts +++ b/packages/actions/src/contracts/governance.test.ts @@ -2,7 +2,7 @@ import { viem_testWithAnvil } from '@celo/dev-utils/viem/anvil-test' import { createWalletClient, http } from 'viem' import { celo } from 'viem/chains' import { expect, it } from 'vitest' -import { WalletCeloClient } from '../client' +import { PublicCeloClient, WalletCeloClient } from '../client' import { vote } from './governance' const TIMEOUT = 10_000 @@ -16,14 +16,18 @@ const forkUrl = celo.rpcUrls.default.http[0] viem_testWithAnvil( 'vote', async (client) => { - let walletClient: WalletCeloClient + let clients: { public: PublicCeloClient; wallet: WalletCeloClient } beforeEach(async () => { - client.impersonateAccount({ address: voter }) - walletClient = createWalletClient({ + await client.impersonateAccount({ address: voter }) + const walletClient = createWalletClient({ account: voter, chain: client.chain, transport: http(client.chain.rpcUrls.default.http[0]), }) + clients = { + public: client, + wallet: walletClient, + } }) afterEach(async () => { await client.stopImpersonatingAccount({ address: voter }) @@ -35,7 +39,7 @@ viem_testWithAnvil( async () => { // This will throw if proposalId is not in the dequeue // In a real test, ensure proposalId is valid and in the dequeue - await expect(vote(walletClient, proposalId, 'Yes')).resolves.toMatch(txHashRegex) + await expect(vote(clients, proposalId, 'Yes')).resolves.toMatch(txHashRegex) }, TIMEOUT ) @@ -43,7 +47,7 @@ viem_testWithAnvil( it( 'votes No on a proposal', async () => { - await expect(vote(walletClient, proposalId, 'No')).resolves.toMatch(txHashRegex) + await expect(vote(clients, proposalId, 'No')).resolves.toMatch(txHashRegex) }, TIMEOUT ) @@ -51,7 +55,7 @@ viem_testWithAnvil( it( 'votes Abstain on a proposal', async () => { - await expect(vote(walletClient, proposalId, 'Abstain')).resolves.toMatch(txHashRegex) + await expect(vote(clients, proposalId, 'Abstain')).resolves.toMatch(txHashRegex) }, TIMEOUT ) @@ -61,7 +65,7 @@ viem_testWithAnvil( async () => { const invalidProposalId = 999999n await expect( - vote(walletClient, invalidProposalId, 'Yes') + vote(clients, invalidProposalId, 'Yes') ).rejects.toThrowErrorMatchingInlineSnapshot( `[Error: ID 999999 not found in array 36,47,72,32,33,37,38,44,46,45,52,51,58,59,65,64,112,70,73,78,75,74,84,79,81,82,95,87,94,110,90,92,93,97,98,104,100,106,113,108,109,114,126,125,122,124,129,153,146,154,141,152,149,148,155,156,192,184,166,173,186,185,196,230,203,0,207,0,224,206]` ) From e6b35d4f84e5ea078a90d7c86e138ea8d65778de Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Thu, 22 May 2025 18:09:30 +0200 Subject: [PATCH 04/11] lint --- packages/actions/typedoc.json | 16 ++++++---------- .../src/commands/releasecelo/transfer-dollars.ts | 5 ++++- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/actions/typedoc.json b/packages/actions/typedoc.json index 34f5f6b22..4568337a0 100644 --- a/packages/actions/typedoc.json +++ b/packages/actions/typedoc.json @@ -1,8 +1,6 @@ { "$schema": "https://typedoc.org/schema.json", - "exclude": [ - "**/*+(test).ts" - ], + "exclude": ["**/*+(test).ts"], "excludePrivate": true, "excludeProtected": true, "hideGenerator": true, @@ -13,17 +11,15 @@ "entryPoints": [ "./src/index.ts", "./src/contracts/*.ts", - "./src/multicontract-interactions/**/index.ts", + "./src/multicontract-interactions/**/index.ts" ], - "githubPages": false, + "githubPages": false, "excludeExternals": true, - "excludeNotDocumented":true, + "excludeNotDocumented": true, "excludeInternal": true, "excludeReferences": true, "includeVersion": true, "disableSources": true, - "plugin": [ - "typedoc-plugin-markdown" - ], + "plugin": ["typedoc-plugin-markdown"], "entryPointStrategy": "resolve" -} \ No newline at end of file +} diff --git a/packages/cli/src/commands/releasecelo/transfer-dollars.ts b/packages/cli/src/commands/releasecelo/transfer-dollars.ts index 094434d0d..d3a9c11ac 100644 --- a/packages/cli/src/commands/releasecelo/transfer-dollars.ts +++ b/packages/cli/src/commands/releasecelo/transfer-dollars.ts @@ -30,7 +30,10 @@ export default class TransferDollars extends ReleaseGoldBaseCommand { const { flags } = await this.parse(TransferDollars) const client = await this.getPublicClient() const wallet = await this.getWalletClient() - const releaseCeloContract = await getReleaseCeloContract({public: client, wallet}, flags.contract) + const releaseCeloContract = await getReleaseCeloContract( + { public: client, wallet }, + flags.contract + ) const isRevoked = await releaseCeloContract.read.isRevoked() From 79be5e4a611f1628a2d4bdbab2ea644dfa494935 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Thu, 22 May 2025 18:14:26 +0200 Subject: [PATCH 05/11] revert --- packages/cli/src/commands/config/get.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/commands/config/get.test.ts b/packages/cli/src/commands/config/get.test.ts index 779d365e9..9c742f7b3 100644 --- a/packages/cli/src/commands/config/get.test.ts +++ b/packages/cli/src/commands/config/get.test.ts @@ -14,8 +14,8 @@ describe('config:get cmd', () => { await testLocally(Get, []) expect(stripAnsiCodesAndTxHashes(logMock.mock.calls[0][0].replace(/:\d+/, ':PORT'))) .toMatchInlineSnapshot(` - "node: http://localhost:PORT - derivationPath: m/44'/60'/0' + "node: http://127.0.0.1:PORT + derivationPath: m/44'/52752'/0' telemetry: true" `) }) From a793c89ad321fab68e2c46840aeafbdaa719a485 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Thu, 22 May 2025 18:21:35 +0200 Subject: [PATCH 06/11] Revert "revert" This reverts commit 8f9fecd86f5b242bdd9bb74e4501e7eb84ea761f. --- packages/cli/src/commands/config/get.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/commands/config/get.test.ts b/packages/cli/src/commands/config/get.test.ts index 9c742f7b3..9a5f65875 100644 --- a/packages/cli/src/commands/config/get.test.ts +++ b/packages/cli/src/commands/config/get.test.ts @@ -14,7 +14,7 @@ describe('config:get cmd', () => { await testLocally(Get, []) expect(stripAnsiCodesAndTxHashes(logMock.mock.calls[0][0].replace(/:\d+/, ':PORT'))) .toMatchInlineSnapshot(` - "node: http://127.0.0.1:PORT + "node: http://localhost:PORT derivationPath: m/44'/52752'/0' telemetry: true" `) From 0f313046f918b58b82c2ff185384ea3425ccffb6 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Fri, 23 May 2025 11:38:24 +0200 Subject: [PATCH 07/11] fix vote sim (must pass account) --- packages/actions/src/client.ts | 2 +- .../actions/src/contracts/governance.test.ts | 18 +++++++----------- packages/actions/src/contracts/governance.ts | 4 +++- packages/dev-utils/src/viem/anvil-test.ts | 6 +++--- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/packages/actions/src/client.ts b/packages/actions/src/client.ts index 2382ff25e..ac136bbf2 100644 --- a/packages/actions/src/client.ts +++ b/packages/actions/src/client.ts @@ -12,7 +12,7 @@ type CeloChain = typeof celo | typeof celoAlfajores | typeof celoBaklava export type CeloClient = Client -export type PublicCeloClient = PublicClient +export type PublicCeloClient = PublicClient export type WalletCeloClient = WalletClient diff --git a/packages/actions/src/contracts/governance.test.ts b/packages/actions/src/contracts/governance.test.ts index 111b0eb25..6294f6151 100644 --- a/packages/actions/src/contracts/governance.test.ts +++ b/packages/actions/src/contracts/governance.test.ts @@ -1,5 +1,5 @@ import { viem_testWithAnvil } from '@celo/dev-utils/viem/anvil-test' -import { createWalletClient, http } from 'viem' +import { createPublicClient, createWalletClient, http } from 'viem' import { celo } from 'viem/chains' import { expect, it } from 'vitest' import { PublicCeloClient, WalletCeloClient } from '../client' @@ -25,7 +25,10 @@ viem_testWithAnvil( transport: http(client.chain.rpcUrls.default.http[0]), }) clients = { - public: client, + public: createPublicClient({ + chain: client.chain, + transport: http(client.chain.rpcUrls.default.http[0]), + }), wallet: walletClient, } }) @@ -35,25 +38,18 @@ viem_testWithAnvil( const txHashRegex = /^0x([A-Fa-f0-9]{64})$/ it( - 'votes Yes on a proposal', + 'votes Yes/No on a proposal', async () => { // This will throw if proposalId is not in the dequeue // In a real test, ensure proposalId is valid and in the dequeue await expect(vote(clients, proposalId, 'Yes')).resolves.toMatch(txHashRegex) - }, - TIMEOUT - ) - - it( - 'votes No on a proposal', - async () => { await expect(vote(clients, proposalId, 'No')).resolves.toMatch(txHashRegex) }, TIMEOUT ) it( - 'votes Abstain on a proposal', + 'votes Abstain a proposal', async () => { await expect(vote(clients, proposalId, 'Abstain')).resolves.toMatch(txHashRegex) }, diff --git a/packages/actions/src/contracts/governance.ts b/packages/actions/src/contracts/governance.ts index 9dbdfd981..91ead0f06 100644 --- a/packages/actions/src/contracts/governance.ts +++ b/packages/actions/src/contracts/governance.ts @@ -43,7 +43,9 @@ export async function vote = Required>( return voteProposal( { vote: async (proposalID, proposalIndex, voteValue) => { - const { request } = await contract.simulate.vote([proposalID, proposalIndex, voteValue]) + const { request } = await contract.simulate.vote([proposalID, proposalIndex, voteValue], { + account: clients.wallet.account.address, + }) return contract.write.vote(request.args) }, getDequeue: async () => { diff --git a/packages/dev-utils/src/viem/anvil-test.ts b/packages/dev-utils/src/viem/anvil-test.ts index 19274b720..e0e9e78bc 100644 --- a/packages/dev-utils/src/viem/anvil-test.ts +++ b/packages/dev-utils/src/viem/anvil-test.ts @@ -46,11 +46,11 @@ function createInstance(opts?: { chainId?: number; forkUrl?: string; forkBlockNu balance: TEST_BALANCE, gasPrice: TEST_GAS_PRICE, gasLimit: TEST_GAS_LIMIT, - blockBaseFeePerGas: 0, - stopTimeout: 1000, + blockBaseFeePerGas: 25000000000, + stopTimeout: 3000, chainId: opts?.chainId, ...(forkUrl - ? { forkUrl, forkBlockNumber } + ? { forkUrl, forkBlockNumber, forkHeader: { 'User-Agent': 'anvil/devtooling' } } : { loadState: require.resolve('@celo/devchain-anvil/devchain.json') }), } From 13d4c6114b06c4f50c199056e684b24c08cca0b9 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Fri, 23 May 2025 14:34:39 +0200 Subject: [PATCH 08/11] dev ex --- packages/cli/package.json | 3 ++- packages/cli/src/transfer-stable-base.ts | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 24b1e7718..bdbcb6d3f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -35,7 +35,8 @@ "prepack": "yarn run build && oclif readme", "homebrew": "node ./homebrew/scripts/prepare.mjs", "test": "TZ=UTC NODE_OPTIONS='--experimental-vm-modules' yarn jest --maxWorkers 50% --silent --forceExit", - "test-ci": "TZ=UTC NODE_OPTIONS='--experimental-vm-modules' yarn jest --workerIdleMemoryLimit=0.1 --forceExit --ci", + "test-ci": "yarn test-ci-base || yarn test-ci-base --onlyFailures", + "test-ci-base": "TZ=UTC NODE_OPTIONS='--experimental-vm-modules' yarn jest --workerIdleMemoryLimit=0.1 --forceExit --ci", "cs": "yarn --top-level run cs" }, "dependencies": { diff --git a/packages/cli/src/transfer-stable-base.ts b/packages/cli/src/transfer-stable-base.ts index 84e432a12..763963be3 100644 --- a/packages/cli/src/transfer-stable-base.ts +++ b/packages/cli/src/transfer-stable-base.ts @@ -89,13 +89,16 @@ export abstract class TransferStableBase extends BaseCommand { feeCurrency && isAddressEqual(feeCurrency, stableTokenContract.address) const [gas, gasPrice, balanceOfTokenForGas, balanceOfTokenToSend] = await Promise.all([ + // gas estimation res.flags.comment ? stableTokenContract.estimateGas.transferWithComment( [to, value, res.flags.comment], transferParams ) : stableTokenContract.estimateGas.transfer([to, value], transferParams), + // fee estimation getGasPriceOnCelo(client, feeCurrency), + // balanceOfTokenForGas (feeCurrency ? feeInSameStableTokenAsTransfer ? stableTokenContract From 5898d64d941f5496f70371279fb876f0e5c05ac4 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Fri, 23 May 2025 16:15:00 +0200 Subject: [PATCH 09/11] yes no --- packages/actions/src/contracts/governance.test.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/actions/src/contracts/governance.test.ts b/packages/actions/src/contracts/governance.test.ts index 6294f6151..aae6296b9 100644 --- a/packages/actions/src/contracts/governance.test.ts +++ b/packages/actions/src/contracts/governance.test.ts @@ -38,11 +38,15 @@ viem_testWithAnvil( const txHashRegex = /^0x([A-Fa-f0-9]{64})$/ it( - 'votes Yes/No on a proposal', + 'votes Yes on a proposal', async () => { - // This will throw if proposalId is not in the dequeue - // In a real test, ensure proposalId is valid and in the dequeue await expect(vote(clients, proposalId, 'Yes')).resolves.toMatch(txHashRegex) + }, + TIMEOUT + ) + it( + 'votes No on a proposal', + async () => { await expect(vote(clients, proposalId, 'No')).resolves.toMatch(txHashRegex) }, TIMEOUT From 66efb48ca30c15c38d278cb04fdcdf3f6ada8d6b Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Fri, 23 May 2025 18:04:54 +0200 Subject: [PATCH 10/11] spelling and voting --- .changeset/curly-toes-pump.md | 2 +- .changeset/fresh-months-share.md | 2 +- .changeset/old-cougars-look.md | 2 +- packages/actions/src/multicontract-interactions/stake/vote.ts | 4 +++- packages/core/src/governing/vote.ts | 3 ++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.changeset/curly-toes-pump.md b/.changeset/curly-toes-pump.md index e0ee07376..0bb6c7bf3 100644 --- a/.changeset/curly-toes-pump.md +++ b/.changeset/curly-toes-pump.md @@ -2,4 +2,4 @@ '@celo/celocli': major --- -Now defaults to using "m/44'/60'/0'" as base derivation path for account:new and any command using --useLedger. use celocli config:set --derivationPath celoLegacy for old behavior. +Now defaults to using "m/44'/60'/0'" as base derivation path for account:new and any command using --useLedger. use celocli `config:set --derivationPath celoLegacy` for old behavior. diff --git a/.changeset/fresh-months-share.md b/.changeset/fresh-months-share.md index 1d28eb9e5..e34b28f45 100644 --- a/.changeset/fresh-months-share.md +++ b/.changeset/fresh-months-share.md @@ -2,4 +2,4 @@ '@celo/celocli': major --- -Remove node:accounts commmand (use account:list) +Remove node:accounts command (use account:list) diff --git a/.changeset/old-cougars-look.md b/.changeset/old-cougars-look.md index a61326d52..aa3340738 100644 --- a/.changeset/old-cougars-look.md +++ b/.changeset/old-cougars-look.md @@ -2,5 +2,5 @@ '@celo/celocli': patch --- -Deprecate useAKV flag with intent to remove. This was for connecting to AzureKeyVault for storing key to sign trnsactions. We hope to streamline and remove this functionality. +Deprecate useAKV flag with intent to remove. This was for connecting to AzureKeyVault for storing key to sign transactions. We hope to streamline and remove this functionality. diff --git a/packages/actions/src/multicontract-interactions/stake/vote.ts b/packages/actions/src/multicontract-interactions/stake/vote.ts index 7df00d9c9..626706625 100644 --- a/packages/actions/src/multicontract-interactions/stake/vote.ts +++ b/packages/actions/src/multicontract-interactions/stake/vote.ts @@ -23,7 +23,9 @@ export async function vote( const election = await getElectionContract(clients) const adapter: VoteAdapter = { vote: async (validatorGroup, value, lesser, greater) => { - const { request } = await election.simulate.vote([validatorGroup, value, lesser, greater]) + const { request } = await election.simulate.vote([validatorGroup, value, lesser, greater], { + account: clients.wallet.account.address, + }) const gasLimit = await election.estimateGas.vote(request.args) return election.write.vote(request.args, { gas: gasLimit }) }, diff --git a/packages/core/src/governing/vote.ts b/packages/core/src/governing/vote.ts index 8d1f2b1bb..841933d1d 100644 --- a/packages/core/src/governing/vote.ts +++ b/packages/core/src/governing/vote.ts @@ -26,7 +26,8 @@ export type VoteProposalAdapter = { * const adapter: VoteProposalAdapter = * { * vote: async (proposalID, proposalIndex, voteValue) => { - * const { request } = await contract.simulate.vote([proposalID, proposalIndex, voteValue]) + * const { request } = await contract.simulate.vote([proposalID, proposalIndex, voteValue], { + * account: client.wallet.account.address}) * const gasLimit = await contract.estimateGas.vote(request.args) * return contract.write.vote(request.args, { gas: gasLimit }) * }, From 6d1700f427fbb2260e8c20d698feddb61f47aa00 Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Fri, 23 May 2025 20:31:49 +0200 Subject: [PATCH 11/11] test with node 22 --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yaml | 2 +- .github/workflows/upload-celocli-executables.yml | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b84a8f06d..336dd163b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,14 +52,14 @@ jobs: steps: - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' - name: 'enable corepack for yarn' run: sudo corepack enable yarn - uses: actions/checkout@v4 # must call twice because of chicken and egg problem with yarn and node - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: 'yarn' - name: Restore node cache uses: actions/cache@v4 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index af4ffb1ac..f1ad939d8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -42,7 +42,7 @@ jobs: # must call twice because of chicken and egg problem with yarn and node - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: 'yarn' - name: Install Dependencies shell: bash diff --git a/.github/workflows/upload-celocli-executables.yml b/.github/workflows/upload-celocli-executables.yml index 5934c44cf..2708b408f 100644 --- a/.github/workflows/upload-celocli-executables.yml +++ b/.github/workflows/upload-celocli-executables.yml @@ -41,7 +41,7 @@ jobs: # must call twice because of chicken and egg problem with yarn and node - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: 'yarn' - name: Install Dependencies @@ -121,7 +121,7 @@ jobs: # must call twice because of chicken and egg problem with yarn and node - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: 'yarn' - name: Install Dependencies shell: bash @@ -194,7 +194,7 @@ jobs: # must call twice because of chicken and egg problem with yarn and node - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' cache: 'yarn' - name: Install Dependencies shell: bash