diff --git a/.changeset/fair-knives-end.md b/.changeset/fair-knives-end.md new file mode 100644 index 000000000..b4188558a --- /dev/null +++ b/.changeset/fair-knives-end.md @@ -0,0 +1,19 @@ +--- +"@celo/phone-number-privacy-monitor": major +--- + +Replace @celo/contractkit with viem + + +### Breaking Changes + +`queryOdisForQuota` and `queryOdisForSalt` for first param instead of a string url now take an object with rpcURL and chainID. + +```diff +- queryOdisForQuota("https://forno.celo.org",...rest) ++ queryOdisForQuota({rpcURL: "https://forno.celo.org", chainID: 42220},...rest) + + +- queryOdisForSalt("https://forno.celo.org",...rest) ++ queryOdisForSalt({rpcURL: "https://forno.celo.org", chainID: 42220},...rest) +``` \ No newline at end of file diff --git a/.changeset/hot-buckets-begin.md b/.changeset/hot-buckets-begin.md new file mode 100644 index 000000000..972ab0b89 --- /dev/null +++ b/.changeset/hot-buckets-begin.md @@ -0,0 +1,48 @@ +--- +"@celo/phone-number-privacy-combiner": major +--- + +Replace @celo/contractkit with viem + + +### Breaking Changes + +`startCombiner` now takes an optional WalletClient instance from viem instead of a ContractKit instance + +config passed to `startCombiner` has a sub config `blockchain` which has the following changes. + +```diff +{ + ...restOfConfig, + blockchain: { + - provider: "https://forno.celo.org" + + rpcURL: "https://forno.celo.org" + + chainID: 42220 + } +} + +``` +--- + +`lib/common/web3` => `lib/common` + +`getDEK` moved from + +it now takes a WalletClient as its first param instead of a ContractKit. + +third param is now typed to require address starts with 0x + +```diff +- export async function getDEK(kit: ContractKit, logger: Logger, account: string): Promise ++ export async function getDEK(client: Client, logger: Logger, account: Address): Promise +``` + +--- + +lib/pnp/services/account-services` + +`ContractKitAccountServiceOptions` => `ViemAccountServiceOptions` + +`ContractKitAccountService` => `ViemAccountService` + +addressed passed to `getAccount` now MUST start with `0x` in type \ No newline at end of file diff --git a/.changeset/nasty-forks-tell.md b/.changeset/nasty-forks-tell.md new file mode 100644 index 000000000..0f9650d27 --- /dev/null +++ b/.changeset/nasty-forks-tell.md @@ -0,0 +1,13 @@ +--- +"@celo/identity": major +--- + +Contract kit has been replaced with viem as dependency. + +from `lib/odis/query`; WalletKeySigner instead of a contractKit instance now takes a sign191 function + +- This should use EIP191 to sign the message using the private key assosiated with the account + +Most places that were previously typed as string are now 0x-string typed + +ContractKit is now an optional peer dependency. it is only needed if using the offchain-data-wrapper diff --git a/.changeset/shiny-plants-raise.md b/.changeset/shiny-plants-raise.md new file mode 100644 index 000000000..6d085c1f6 --- /dev/null +++ b/.changeset/shiny-plants-raise.md @@ -0,0 +1,66 @@ +--- +"@celo/phone-number-privacy-common": major +--- + +Replace @celo/contractkit with viem + + +### BREAKING CHANGES +Config changes + +`BlockchainConfig` gains a new required `chainID` property + +`provider` which is an overloaded term is renamed to `rpcURL` + +```diff +config: BlockchainConfig = { + - provider: FORNO_URL + + rpcURL: FORNOURL + + chainID: 42220 +} +``` + +`getContractKit` => `getWalletClient` + + +functions replaced in utils/authentication + +`newContractKitFetcher` => `newDEKFetcher` + +```diff +- newContractKitFetcher(contractKit: ContractKit, ...) ++ newDEKFetcher(viemClient: Client, ...) +``` + +functions with with changed signatures + +`getDataEncryptionKey` + +```diff +export async function getDataEncryptionKey( +- address: string, +- contractKit: ContractKit, ++ address: Address, ++ viemClient: Client, + logger: Logger, + fullNodeTimeoutMs: number, + fullNodeRetryCount: number, + fullNodeRetryDelayMs: number, +- ): Promise ++ ): Promise +``` + +functions removed from test/utils + +- `createMockToken` +- `createMockContractKit` +- `createMockConnection` +- `createMockWeb3` +- `replenishQuota` + + +### NEW FUNCTIONS + +`import {getAccountsContract, getOdisPaymentsContract, getCUSDContract } from @celo/phone-number-privacy-common` + +To replace contractKit wrappers for Accounts, OdisPayments, and StableToken, contracts. diff --git a/.changeset/stupid-suns-tickle.md b/.changeset/stupid-suns-tickle.md new file mode 100644 index 000000000..7abb2245d --- /dev/null +++ b/.changeset/stupid-suns-tickle.md @@ -0,0 +1,22 @@ +--- +"@celo/phone-number-privacy-signer": major +--- + +Replace @celo/contractKit with viem + + +If you are just running the service no actual changes required except to use with same major version of combiner and monitor + +### Breaking Changes + + + +`ContractKitAccountService` => `ClientAccountService` + +```diff +- new ContractKitAccountService(logger, contractKit) ++ new ClientAccountService(logger, walletClient) + +``` + +`getAccount` now takes strongly typed 0x string \ No newline at end of file diff --git a/apps/combiner/src/common/web3/contracts.ts b/apps/combiner/src/common/contracts.ts similarity index 90% rename from apps/combiner/src/common/web3/contracts.ts rename to apps/combiner/src/common/contracts.ts index 18db08775..fb3111766 100644 --- a/apps/combiner/src/common/web3/contracts.ts +++ b/apps/combiner/src/common/contracts.ts @@ -1,8 +1,8 @@ import { ErrorMessage, getDataEncryptionKey } from '@celo/phone-number-privacy-common' import Logger from 'bunyan' import { Address, Client } from 'viem' -import config from '../../config' -import { Counters, Histograms, newMeter } from '../metrics' +import config from '../config' +import { Counters, Histograms, newMeter } from './metrics' export async function getDEK(client: Client, logger: Logger, account: Address): Promise { const _meter = newMeter(Histograms.fullNodeLatency, 'getDataEncryptionKey') diff --git a/apps/combiner/src/config.ts b/apps/combiner/src/config.ts index 315418f8f..7421a505d 100644 --- a/apps/combiner/src/config.ts +++ b/apps/combiner/src/config.ts @@ -7,6 +7,7 @@ import { TestUtils, toBool, } from '@celo/phone-number-privacy-common' +import { celoAlfajores } from 'viem/chains' export function getCombinerVersion(): string { return process.env.npm_package_version ?? require('../package.json').version ?? '0.0.0' @@ -80,7 +81,8 @@ if (DEV_MODE) { port: 8081, }, blockchain: { - provider: FORNO_ALFAJORES, + rpcURL: FORNO_ALFAJORES, + chainID: celoAlfajores.id, }, phoneNumberPrivacy: { serviceName: defaultServiceName, diff --git a/apps/combiner/src/pnp/services/account-services.ts b/apps/combiner/src/pnp/services/account-services.ts index 2dc49d20b..63d22f1a4 100644 --- a/apps/combiner/src/pnp/services/account-services.ts +++ b/apps/combiner/src/pnp/services/account-services.ts @@ -2,10 +2,10 @@ import { ErrorMessage } from '@celo/phone-number-privacy-common' import Logger from 'bunyan' import { LRUCache } from 'lru-cache' import { Address, Client } from 'viem' +import { getDEK } from '../../common/contracts' import { OdisError, wrapError } from '../../common/error' import { Counters } from '../../common/metrics' import { traceAsyncFunction } from '../../common/tracing-utils' -import { getDEK } from '../../common/web3/contracts' export interface AccountService { getAccount(address: string): Promise diff --git a/apps/monitor/src/query.ts b/apps/monitor/src/query.ts index 3b388bb44..91fc107e9 100644 --- a/apps/monitor/src/query.ts +++ b/apps/monitor/src/query.ts @@ -20,9 +20,9 @@ import { } from '@celo/utils/lib/address' import { defined } from '@celo/utils/lib/sign-typed-data-utils' import { defineString } from 'firebase-functions/params' -import { Address, createWalletClient, Hex, http } from 'viem' +import { Account, Address, createWalletClient, extractChain, http } from 'viem' import { privateKeyToAccount } from 'viem/accounts' -import { celo } from 'viem/chains' +import { celo, celoAlfajores } from 'viem/chains' import { dekAuthSigner, generateRandomPhoneNumber, PRIVATE_KEY } from './resources' let phoneNumber: string @@ -30,11 +30,16 @@ let phoneNumber: string const defaultPhoneNumber = defineString('PHONE_NUMBER') const newPrivateKey = async () => { const mnemonic = await generateMnemonic(MnemonicStrength.s256_24words) - return (await generateKeys(mnemonic)).privateKey as Hex + return (await generateKeys(mnemonic)).privateKey +} + +type ChainInfo = { + rpcURL: string + chainID: 44787 | 42220 } export const queryOdisForSalt = async ( - blockchainProvider: string, + blockchainProvider: ChainInfo, contextName: OdisContextName, timeoutMs: number = 10000, bypassQuota: boolean = false, @@ -81,10 +86,10 @@ export const queryOdisForSalt = async ( } export const queryOdisForQuota = async ( - blockchainProvider: string, + blockchainProvider: ChainInfo, contextName: OdisContextName, timeoutMs: number = 10000, - privateKey?: Hex, + privateKey?: string, privateKeyPercentage: number = 100, ) => { console.log(`contextName: ${contextName}`) // tslint:disable-line:no-console @@ -96,15 +101,11 @@ export const queryOdisForQuota = async ( privateKey = await newPrivateKey() } - const account = privateKeyToAccount(privateKey as Hex) + const account = privateKeyToAccount(ensureLeading0x(privateKey)) const accountAddress = normalizeAddressWith0x(privateKeyToAddress(privateKey)) - const client = createWalletClient({ - account, - chain: celo, - transport: http(blockchainProvider), - }) + const client = makeClient(blockchainProvider, account) const authSigner: AuthSigner = { authenticationMethod: OdisUtils.Query.AuthenticationMethod.WALLET_KEY, sign191: ({ message, account }) => client.signMessage({ message, account }), @@ -157,7 +158,7 @@ export const queryOdisDomain = async (contextName: OdisContextName) => { } async function getAuthSignerAndAccount( - blockchainProvider: string, + blockchainProvider: ChainInfo, useDEK: boolean, privateKey: string | undefined, privateKeyPercentage: number, @@ -179,12 +180,9 @@ async function getAuthSignerAndAccount( privateKey = await newPrivateKey() } accountAddress = normalizeAddressWith0x(privateKeyToAddress(privateKey)) as Address + const account = privateKeyToAccount(ensureLeading0x(privateKey)) - const client = createWalletClient({ - account: privateKeyToAccount(ensureLeading0x(privateKey)), - chain: celo, - transport: http(blockchainProvider), - }) + const client = makeClient(blockchainProvider, account) authSigner = { authenticationMethod: OdisUtils.Query.AuthenticationMethod.WALLET_KEY, @@ -194,3 +192,11 @@ async function getAuthSignerAndAccount( } return { accountAddress, authSigner, privateKey } } + +function makeClient(chainInfo: ChainInfo, account: Account) { + return createWalletClient({ + account: account, + chain: extractChain({ chains: [celoAlfajores, celo], id: chainInfo.chainID }), + transport: http(chainInfo.rpcURL), + }) +} diff --git a/apps/monitor/src/resources.ts b/apps/monitor/src/resources.ts index 939cb0991..cdd0713da 100644 --- a/apps/monitor/src/resources.ts +++ b/apps/monitor/src/resources.ts @@ -6,7 +6,6 @@ import { privateKeyToAddress, } from '@celo/utils/lib/address' -// why no 0x? export const PRIVATE_KEY = '2c63bf6d60b16c8afa13e1069dbe92fef337c23855fff8b27732b3e9c6e7efd4' export const ACCOUNT_ADDRESS = normalizeAddressWith0x(privateKeyToAddress(PRIVATE_KEY)) // 0x6037800e91eaa703e38bad40c01410bbdf0fea7e diff --git a/packages/common/src/utils/contracts.ts b/packages/common/src/utils/contracts.ts index 576fdafb5..df5848538 100644 --- a/packages/common/src/utils/contracts.ts +++ b/packages/common/src/utils/contracts.ts @@ -4,17 +4,18 @@ import { type HttpTransportConfig, type WalletClient, } from 'viem' -import { celo } from 'viem/chains' +import { celo, celoAlfajores } from 'viem/chains' export interface BlockchainConfig { - provider: string + rpcURL: string + chainID: typeof celo.id | typeof celoAlfajores.id apiKey?: string } export function getWalletClient(config: BlockchainConfig): WalletClient { return createWalletClient({ - chain: celo, - transport: viemHttpTransport(config.provider, configureOptions(config, {})), + chain: config.chainID === celo.id ? celo : celoAlfajores, + transport: viemHttpTransport(config.rpcURL, configureOptions(config, {})), }) } @@ -24,6 +25,7 @@ export function getWalletClientWithAgent(config: BlockchainConfig): WalletClient options.fetchOptions = {} options.fetchOptions.keepalive = true + // TODO // no agent on viem? // options.fetchOptions = { // http: new http.Agent({ keepAlive: true }), @@ -31,8 +33,8 @@ export function getWalletClientWithAgent(config: BlockchainConfig): WalletClient // } return createWalletClient({ - chain: celo, - transport: viemHttpTransport(config.provider, configureOptions(config, options)), + chain: config.chainID === celo.id ? celo : celoAlfajores, + transport: viemHttpTransport(config.rpcURL, configureOptions(config, options)), }) }