From 838939bdc8b671123414da13633038abe68c4acb Mon Sep 17 00:00:00 2001 From: Aaron DeRuvo Date: Wed, 25 Sep 2024 15:01:43 +0200 Subject: [PATCH] instead of a viem client instance just use a sign function more generic. --- .vscode/launch.json | 2 - README.md | 8 +- apps/combiner/test/end-to-end/pnp.test.ts | 20 +- apps/combiner/test/end-to-end/resources.ts | 4 +- apps/combiner/test/integration/pnp.test.ts | 65 +++--- apps/monitor/src/query.ts | 4 +- .../signer/src/common/{web3 => }/contracts.ts | 5 +- .../src/pnp/services/account-service.ts | 2 +- apps/signer/test/integration/pnp.test.ts | 34 ++- docs/examples/viem.ts | 4 +- docs/privacy.md | 4 +- kitUsage.ts | 25 --- .../src/{celoViemKit.ts => contracts.ts} | 0 packages/common/src/index.ts | 2 +- packages/common/src/test/utils.ts | 23 +- packages/common/src/utils/authentication.ts | 2 +- .../common/test/utils/authentication.test.ts | 196 +++++++++--------- packages/identity/src/odis/query.ts | 8 +- .../src/offchain-data-wrapper.test.ts | 1 + 19 files changed, 194 insertions(+), 215 deletions(-) rename apps/signer/src/common/{web3 => }/contracts.ts (90%) delete mode 100644 kitUsage.ts rename packages/common/src/{celoViemKit.ts => contracts.ts} (100%) diff --git a/.vscode/launch.json b/.vscode/launch.json index 5b8d973c6..fde443c3f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -41,9 +41,7 @@ "--inspect-brk", "${workspaceRoot}/node_modules/.bin/jest", "--rootDir", - "${workspaceFolder}/packages/contractkit", "--runInBand", - "${workspaceFolder}/packages/contractkit/src/**/*.test.ts", ], "console": "integratedTerminal", "internalConsoleOptions": "neverOpen", diff --git a/README.md b/README.md index 125b18df0..feeb44d14 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ We've made a mini-series to explain you: ## 🧑‍💻 Quickstart -The following steps use the Celo [ContractKit](https://docs.celo.org/developer/contractkit) to quickly set you up to play around with the protocol. If you would like to use a different library instead, please refer to the [example scripts](examples/). +The following steps use the [Viem](https://viem.sh) to quickly set you up to play around with the protocol. If you would like to use a different library instead, please refer to the [example scripts](examples/). 1. Add the [`@celo/identity`](https://www.npmjs.com/package/@celo/identity) package into your project. @@ -80,7 +80,7 @@ The following steps use the Celo [ContractKit](https://docs.celo.org/developer/c // authSigner provides information needed to authenticate with ODIS const authSigner: AuthSigner = { authenticationMethod: OdisUtils.Query.AuthenticationMethod.WALLET_KEY, - contractKit: kit, + sign191: ({message, account}) => viemClient.signMessage({message, account}), }; // serviceContext provides the ODIS endpoint and public key const serviceContext = OdisUtils.Query.getServiceContext( @@ -153,7 +153,7 @@ The following steps use the Celo [ContractKit](https://docs.celo.org/developer/c | Type | | :-------------------------------------------------------------------------------------------: | -| [ContractKit](docs/examples/contractKit.ts) | +| [Viem](docs/examples/viem.ts) | | [EthersJS (v5)](docs/examples/ethers.ts) | | [web3.js](docs/examples/web3.ts) | | [NextJS based web app (Phone Number)](https://github.com/celo-org/emisianto) | @@ -162,7 +162,7 @@ The following steps use the Celo [ContractKit](https://docs.celo.org/developer/c | [NextJS based web app (Twitter)](https://github.com/celo-org/SocialConnect-Twitter) | | [Server side NextJS (Twitter)](https://github.com/celo-org/SocialConnect-Twitter-Server-Side) | - diff --git a/apps/combiner/test/end-to-end/pnp.test.ts b/apps/combiner/test/end-to-end/pnp.test.ts index a6ae7a3d6..2d21aa19b 100644 --- a/apps/combiner/test/end-to-end/pnp.test.ts +++ b/apps/combiner/test/end-to-end/pnp.test.ts @@ -5,13 +5,13 @@ import { PnpClientQuotaStatus } from '@celo/identity/lib/odis/quota' import { CombinerEndpoint, getAccountsContract, + getCUSDContract, getOdisPaymentsContract, PnpQuotaRequest, PnpQuotaResponseSchema, SignMessageRequest, SignMessageResponseSchema, } from '@celo/phone-number-privacy-common' -import { getCUSDContract } from '@celo/phone-number-privacy-common/src/celoViemKit' import { config as signerConfig } from '@celo/phone-number-privacy-signer/src/config' import { normalizeAddressWith0x } from '@celo/utils/lib/address' import threshold_bls from 'blind-threshold-bls' @@ -24,6 +24,7 @@ import { ACCOUNT_ADDRESS, ACCOUNT_ADDRESS_NO_QUOTA, BLINDED_PHONE_NUMBER, + client, dekAuthSigner, deks, getTestContextName, @@ -47,7 +48,7 @@ const expectedVersion = getCombinerVersion() describe(`Running against service deployed at ${combinerUrl} w/ blockchain provider ${fullNodeUrl}`, () => { beforeAll(async () => { - const accountsContract = getAccountsContract(walletAuthSigner.client) + const accountsContract = getAccountsContract(client) const dekPublicKey = normalizeAddressWith0x(deks[0].publicKey) as Hex if ((await accountsContract.read.getDataEncryptionKey([ACCOUNT_ADDRESS])) !== dekPublicKey) { await accountsContract.write.setAccountDataEncryptionKey([dekPublicKey], { @@ -136,7 +137,7 @@ describe(`Running against service deployed at ${combinerUrl} w/ blockchain provi CombinerEndpoint.PNP_QUOTA, PnpQuotaResponseSchema, { - Authorization: await walletAuthSigner.client.signMessage({ + Authorization: await walletAuthSigner.sign191({ message: JSON.stringify(req), account: privateKeyToAccount(PRIVATE_KEY_NO_QUOTA), }), @@ -164,7 +165,6 @@ describe(`Running against service deployed at ${combinerUrl} w/ blockchain provi const amountInWei = BigInt( signerConfig.quota.queryPriceInCUSD.times(1e18).times(numQueriesToReplenish).toString(), ) - const client = walletAuthSigner.client const stableToken = getCUSDContract(client) const odisPayments = getOdisPaymentsContract(client) @@ -172,11 +172,11 @@ describe(`Running against service deployed at ${combinerUrl} w/ blockchain provi await stableToken.write.approve([odisPayments.address, amountInWei], { account: sender, - chain: walletAuthSigner.client.chain, + chain: client.chain, }) await odisPayments.write.payInCUSD([ACCOUNT_ADDRESS, amountInWei], { account: sender, - chain: walletAuthSigner.client.chain, + chain: client.chain, }) // wait for cache to expire and then query to refresh await sleep(5 * 1000) @@ -443,10 +443,10 @@ describe(`Running against service deployed at ${combinerUrl} w/ blockchain provi CombinerEndpoint.PNP_SIGN, SignMessageResponseSchema, { - Authorization: await walletAuthSigner.client.signMessage( - JSON.stringify(req), - ACCOUNT_ADDRESS_NO_QUOTA, - ), + Authorization: await client.signMessage({ + message: JSON.stringify(req), + account: ACCOUNT_ADDRESS_NO_QUOTA, + }), }, ), ).rejects.toThrow(ErrorMessages.ODIS_AUTH_ERROR) diff --git a/apps/combiner/test/end-to-end/resources.ts b/apps/combiner/test/end-to-end/resources.ts index 50144cab9..d36586d2b 100644 --- a/apps/combiner/test/end-to-end/resources.ts +++ b/apps/combiner/test/end-to-end/resources.ts @@ -56,7 +56,7 @@ export const CONTACT_PHONE_NUMBERS = [CONTACT_PHONE_NUMBER] /** * RESOURCES AND UTILS */ -const client = createWalletClient({ +export const client = createWalletClient({ transport: http(DEFAULT_FORNO_URL), chain: celo, account: privateKeyToAccount(PRIVATE_KEY_NO_QUOTA), @@ -94,5 +94,5 @@ export const dekAuthSigner = (index: number): EncryptionKeySigner => { export const walletAuthSigner: WalletKeySigner = { authenticationMethod: AuthenticationMethod.WALLET_KEY, - client, + sign191: (args) => client.signMessage(args), } diff --git a/apps/combiner/test/integration/pnp.test.ts b/apps/combiner/test/integration/pnp.test.ts index c5aaadd94..500e2ff28 100644 --- a/apps/combiner/test/integration/pnp.test.ts +++ b/apps/combiner/test/integration/pnp.test.ts @@ -1,4 +1,3 @@ -import { newKit } from '@celo/contractkit' import { AuthenticationMethod, CombinerEndpoint, @@ -37,6 +36,8 @@ import { Server } from 'http' import { Server as HttpsServer } from 'https' import { Knex } from 'knex' import request from 'supertest' +import { createWalletClient, http } from 'viem' +import { celoAlfajores } from 'viem/chains' import config, { getCombinerVersion } from '../../src/config' import { startCombiner } from '../../src/server' import { getBlindedPhoneNumber, serverClose } from '../utils' @@ -160,6 +161,7 @@ const mockContractKit = createMockContractKit({ [ContractRetrieval.getOdisPayments]: createMockOdisPayments(mockOdisPaymentsTotalPaidCUSD), }) +// TODO replace this mock with mock of viemCeloKit stuff // Mock newKit as opposed to the CK constructor // Returns an object of type ContractKit that can be passed into the signers + combiner jest.mock('@celo/contractkit', () => ({ @@ -192,7 +194,10 @@ describe('pnpService', () => { const message = Buffer.from('test message', 'utf8') // In current setup, the same mocked kit is used for the combiner and signers - const mockKit = newKit('dummyKit') + const mockClient = createWalletClient({ + chain: celoAlfajores, + transport: http(), + }) const sendPnpSignRequest = async ( req: SignMessageRequest, @@ -284,7 +289,7 @@ describe('pnpService', () => { [`${DefaultKeyName.PHONE_NUMBER_PRIVACY}-3`, PNP_THRESHOLD_DEV_PK_SHARE_3_V3], ]), ) - app = startCombiner(combinerConfig, mockKit) + app = startCombiner(combinerConfig, mockClient) }) beforeEach(async () => { @@ -314,9 +319,9 @@ describe('pnpService', () => { describe('when signers are operating correctly', () => { beforeEach(async () => { - signer1 = startSigner(signerConfig, signerDB1, keyProvider1, mockKit).listen(3001) - signer2 = startSigner(signerConfig, signerDB2, keyProvider2, mockKit).listen(3002) - signer3 = startSigner(signerConfig, signerDB3, keyProvider3, mockKit).listen(3003) + signer1 = startSigner(signerConfig, signerDB1, keyProvider1, mockClient).listen(3001) + signer2 = startSigner(signerConfig, signerDB2, keyProvider2, mockClient).listen(3002) + signer3 = startSigner(signerConfig, signerDB3, keyProvider3, mockClient).listen(3003) }) describe(`${CombinerEndpoint.PNP_QUOTA}`, () => { @@ -580,7 +585,7 @@ describe('pnpService', () => { JSON.stringify(combinerConfig), ) configWithApiDisabled.phoneNumberPrivacy.enabled = false - const appWithApiDisabled = startCombiner(configWithApiDisabled, mockKit) + const appWithApiDisabled = startCombiner(configWithApiDisabled, mockClient) const req = { account: ACCOUNT_ADDRESS1, } @@ -871,7 +876,7 @@ describe('pnpService', () => { JSON.stringify(combinerConfig), ) configWithApiDisabled.phoneNumberPrivacy.enabled = false - const appWithApiDisabled = startCombiner(configWithApiDisabled, mockKit) + const appWithApiDisabled = startCombiner(configWithApiDisabled, mockClient) const authorization = getPnpRequestAuthorization(req, PRIVATE_KEY1) const res = await sendPnpSignRequest(req, authorization, appWithApiDisabled) @@ -898,7 +903,7 @@ describe('pnpService', () => { ) const appWithFailOpenDisabled = startCombiner( combinerConfigWithFailOpenDisabled, - mockKit, + mockClient, ) const res = await sendPnpSignRequest(req, authorization, appWithFailOpenDisabled) @@ -927,9 +932,9 @@ describe('pnpService', () => { const badKeyProvider1 = new MockKeyProvider( new Map([[`${DefaultKeyName.PHONE_NUMBER_PRIVACY}-1`, badBlsShare1]]), ) - signer1 = startSigner(signerConfig, signerDB1, badKeyProvider1, mockKit).listen(3001) - signer2 = startSigner(signerConfig, signerDB2, keyProvider2, mockKit).listen(3002) - signer3 = startSigner(signerConfig, signerDB3, keyProvider3, mockKit).listen(3003) + signer1 = startSigner(signerConfig, signerDB1, badKeyProvider1, mockClient).listen(3001) + signer2 = startSigner(signerConfig, signerDB2, keyProvider2, mockClient).listen(3002) + signer3 = startSigner(signerConfig, signerDB3, keyProvider3, mockClient).listen(3003) }) describe(`${CombinerEndpoint.PNP_SIGN}`, () => { @@ -972,9 +977,9 @@ describe('pnpService', () => { new Map([[`${DefaultKeyName.PHONE_NUMBER_PRIVACY}-1`, badBlsShare2]]), ) - signer1 = startSigner(signerConfig, signerDB1, keyProvider1, mockKit).listen(3001) - signer2 = startSigner(signerConfig, signerDB2, badKeyProvider1, mockKit).listen(3002) - signer3 = startSigner(signerConfig, signerDB3, badKeyProvider2, mockKit).listen(3003) + signer1 = startSigner(signerConfig, signerDB1, keyProvider1, mockClient).listen(3001) + signer2 = startSigner(signerConfig, signerDB2, badKeyProvider1, mockClient).listen(3002) + signer3 = startSigner(signerConfig, signerDB3, badKeyProvider2, mockClient).listen(3003) }) describe(`${CombinerEndpoint.PNP_SIGN}`, () => { @@ -997,11 +1002,11 @@ describe('pnpService', () => { beforeEach(async () => { const configWithApiDisabled: SignerConfig = JSON.parse(JSON.stringify(signerConfig)) configWithApiDisabled.api.phoneNumberPrivacy.enabled = false - signer1 = startSigner(signerConfig, signerDB1, keyProvider1, mockKit).listen(3001) - signer2 = startSigner(configWithApiDisabled, signerDB2, keyProvider2, mockKit).listen( + signer1 = startSigner(signerConfig, signerDB1, keyProvider1, mockClient).listen(3001) + signer2 = startSigner(configWithApiDisabled, signerDB2, keyProvider2, mockClient).listen( 3002, ) - signer3 = startSigner(configWithApiDisabled, signerDB3, keyProvider3, mockKit).listen( + signer3 = startSigner(configWithApiDisabled, signerDB3, keyProvider3, mockClient).listen( 3003, ) }) @@ -1042,9 +1047,9 @@ describe('pnpService', () => { beforeEach(async () => { const configWithApiDisabled: SignerConfig = JSON.parse(JSON.stringify(signerConfig)) configWithApiDisabled.api.phoneNumberPrivacy.enabled = false - signer1 = startSigner(signerConfig, signerDB1, keyProvider1, mockKit).listen(3001) - signer2 = startSigner(signerConfig, signerDB2, keyProvider2, mockKit).listen(3002) - signer3 = startSigner(configWithApiDisabled, signerDB3, keyProvider3, mockKit).listen( + signer1 = startSigner(signerConfig, signerDB1, keyProvider1, mockClient).listen(3001) + signer2 = startSigner(signerConfig, signerDB2, keyProvider2, mockClient).listen(3002) + signer3 = startSigner(configWithApiDisabled, signerDB3, keyProvider3, mockClient).listen( 3003, ) }) @@ -1094,13 +1099,13 @@ describe('pnpService', () => { const configWithShortTimeout: SignerConfig = JSON.parse(JSON.stringify(signerConfig)) configWithShortTimeout.timeout = testTimeoutMS // Test this with all signers timing out to decrease possibility of race conditions - signer1 = startSigner(configWithShortTimeout, signerDB1, keyProvider1, mockKit).listen( + signer1 = startSigner(configWithShortTimeout, signerDB1, keyProvider1, mockClient).listen( 3001, ) - signer2 = startSigner(configWithShortTimeout, signerDB2, keyProvider2, mockKit).listen( + signer2 = startSigner(configWithShortTimeout, signerDB2, keyProvider2, mockClient).listen( 3002, ) - signer3 = startSigner(configWithShortTimeout, signerDB3, keyProvider3, mockKit).listen( + signer3 = startSigner(configWithShortTimeout, signerDB3, keyProvider3, mockClient).listen( 3003, ) }) @@ -1223,7 +1228,7 @@ describe('pnpService', () => { ], ]), ) - app = startCombiner(combinerConfigLargerN, mockKit) + app = startCombiner(combinerConfigLargerN, mockClient) }) let req: SignMessageRequest @@ -1235,11 +1240,11 @@ describe('pnpService', () => { signerDB4 = await initSignerDatabase(signerConfig, signerMigrationsPath) signerDB5 = await initSignerDatabase(signerConfig, signerMigrationsPath) - signer1 = startSigner(signerConfig, signerDB1, keyProvider1, mockKit).listen(3001) - signer2 = startSigner(signerConfig, signerDB2, keyProvider2, mockKit).listen(3002) - signer3 = startSigner(signerConfig, signerDB3, keyProvider3, mockKit).listen(3003) - signer4 = startSigner(signerConfig, signerDB4, keyProvider4, mockKit).listen(3004) - signer5 = startSigner(signerConfig, signerDB5, keyProvider5, mockKit).listen(3005) + signer1 = startSigner(signerConfig, signerDB1, keyProvider1, mockClient).listen(3001) + signer2 = startSigner(signerConfig, signerDB2, keyProvider2, mockClient).listen(3002) + signer3 = startSigner(signerConfig, signerDB3, keyProvider3, mockClient).listen(3003) + signer4 = startSigner(signerConfig, signerDB4, keyProvider4, mockClient).listen(3004) + signer5 = startSigner(signerConfig, signerDB5, keyProvider5, mockClient).listen(3005) userSeed = new Uint8Array(32) for (let i = 0; i < userSeed.length - 1; i++) { diff --git a/apps/monitor/src/query.ts b/apps/monitor/src/query.ts index 62c9cdd77..3b388bb44 100644 --- a/apps/monitor/src/query.ts +++ b/apps/monitor/src/query.ts @@ -107,7 +107,7 @@ export const queryOdisForQuota = async ( }) const authSigner: AuthSigner = { authenticationMethod: OdisUtils.Query.AuthenticationMethod.WALLET_KEY, - client, + sign191: ({ message, account }) => client.signMessage({ message, account }), } const abortController = new AbortController() @@ -188,7 +188,7 @@ async function getAuthSignerAndAccount( authSigner = { authenticationMethod: OdisUtils.Query.AuthenticationMethod.WALLET_KEY, - client, + sign191: client.signMessage, } phoneNumber = defaultPhoneNumber.value() } diff --git a/apps/signer/src/common/web3/contracts.ts b/apps/signer/src/common/contracts.ts similarity index 90% rename from apps/signer/src/common/web3/contracts.ts rename to apps/signer/src/common/contracts.ts index a092d03e8..25fc13146 100644 --- a/apps/signer/src/common/web3/contracts.ts +++ b/apps/signer/src/common/contracts.ts @@ -3,8 +3,8 @@ import { getDataEncryptionKey, getOdisPaymentsContract } from '@celo/phone-numbe import { BigNumber } from 'bignumber.js' import Logger from 'bunyan' import { Address, Client, Hex } 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 getOnChainOdisPayments( client: Client, @@ -16,7 +16,6 @@ export async function getOnChainOdisPayments( retryAsyncWithBackOffAndTimeout( async () => { const paid = await getOdisPaymentsContract(client).read.totalPaidCUSD([account]) - // might replace bigNumber with big int but not yet return new BigNumber(paid.toString(10)) }, config.fullNodeRetryCount, diff --git a/apps/signer/src/pnp/services/account-service.ts b/apps/signer/src/pnp/services/account-service.ts index 1f2ab8502..9f72133de 100644 --- a/apps/signer/src/pnp/services/account-service.ts +++ b/apps/signer/src/pnp/services/account-service.ts @@ -3,9 +3,9 @@ import BigNumber from 'bignumber.js' import Logger from 'bunyan' import { LRUCache } from 'lru-cache' import { Address, WalletClient } from 'viem' +import { getDEK, getOnChainOdisPayments } from '../../common/contracts' import { OdisError, wrapError } from '../../common/error' import { traceAsyncFunction } from '../../common/tracing-utils' -import { getDEK, getOnChainOdisPayments } from '../../common/web3/contracts' import { config } from '../../config' export interface PnpAccount { diff --git a/apps/signer/test/integration/pnp.test.ts b/apps/signer/test/integration/pnp.test.ts index ae8dfd121..c73bd3ef8 100644 --- a/apps/signer/test/integration/pnp.test.ts +++ b/apps/signer/test/integration/pnp.test.ts @@ -1,4 +1,3 @@ -import { newKit } from '@celo/contractkit' import { AuthenticationMethod, ErrorMessage, @@ -17,6 +16,8 @@ import { BLINDED_PHONE_NUMBER } from '@celo/phone-number-privacy-common/lib/test import BigNumber from 'bignumber.js' import { Knex } from 'knex' import request from 'supertest' +import { createWalletClient, http } from 'viem' +import { celoAlfajores } from 'viem/chains' import { initDatabase } from '../../src/common/database/database' import { countAndThrowDBError } from '../../src/common/database/utils' import { @@ -92,7 +93,11 @@ describe('pnp', () => { beforeEach(async () => { // Create a new in-memory database for each test. db = await initDatabase(_config) - app = startSigner(_config, db, keyProvider, newKit('dummyKit')) + const client = createWalletClient({ + chain: celoAlfajores, + transport: http(), + }) + app = startSigner(_config, db, keyProvider, client) mockOdisPaymentsTotalPaidCUSD.mockReset() mockGetDataEncryptionKey.mockReset().mockReturnValue(DEK_PUBLIC_KEY) mockGetWalletAddress.mockReset().mockReturnValue(mockAccount) @@ -320,7 +325,10 @@ describe('pnp', () => { configWithApiDisabled, db, keyProvider, - newKit('dummyKit'), + createWalletClient({ + chain: celoAlfajores, + transport: http(), + }), ) const req = getPnpQuotaRequest(ACCOUNT_ADDRESS1) @@ -398,7 +406,10 @@ describe('pnp', () => { configWithShortTimeout, db, keyProvider, - newKit('dummyKit'), + createWalletClient({ + chain: celoAlfajores, + transport: http(), + }), ) const req = getPnpQuotaRequest(ACCOUNT_ADDRESS1) const authorization = getPnpRequestAuthorization(req, PRIVATE_KEY1) @@ -804,7 +815,10 @@ describe('pnp', () => { configWithApiDisabled, db, keyProvider, - newKit('dummyKit'), + createWalletClient({ + chain: celoAlfajores, + transport: http(), + }), ) const req = getPnpSignRequest( @@ -892,7 +906,10 @@ describe('pnp', () => { configWithShortTimeout, db, keyProvider, - newKit('dummyKit'), + createWalletClient({ + chain: celoAlfajores, + transport: http(), + }), ) const req = getPnpSignRequest( @@ -934,7 +951,10 @@ describe('pnp', () => { configWithFailOpenDisabled, db, keyProvider, - newKit('dummyKit'), + createWalletClient({ + chain: celoAlfajores, + transport: http(), + }), ) const authorization = getPnpRequestAuthorization(req, PRIVATE_KEY1) diff --git a/docs/examples/viem.ts b/docs/examples/viem.ts index bde9fc41f..becfb4e82 100644 --- a/docs/examples/viem.ts +++ b/docs/examples/viem.ts @@ -45,7 +45,9 @@ class ASv2 { this.serviceContext = OdisUtils.Query.getServiceContext(OdisContextName.ALFAJORES) this.authSigner = { authenticationMethod: OdisUtils.Query.AuthenticationMethod.WALLET_KEY, - client: this.walletClient, + sign191: (args) => { + return this.walletClient.signMessage(args) + }, } } diff --git a/docs/privacy.md b/docs/privacy.md index d4aea461d..1dcd016de 100644 --- a/docs/privacy.md +++ b/docs/privacy.md @@ -207,12 +207,12 @@ if (remainingQuota < 1) { There are two authentication methods for your `AuthSigner` when interacting with ODIS: -1. **`WalletKeySigner`**: uses a wallet key by passing in a contractkit instance with the account unlocked: +1. **`WalletKeySigner`**: just needs to be capable of signing a eip191 message. Viem and Ethers both have a signMessage function that can be used ```typescript const authSigner: AuthSigner = { authenticationMethod: OdisUtils.Query.AuthenticationMethod.WALLET_KEY, - contractKit, + sign191: , }; ``` diff --git a/kitUsage.ts b/kitUsage.ts deleted file mode 100644 index 3bb9d82c7..000000000 --- a/kitUsage.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { newKit, newKitWithApiKey } from '@celo/contractkit' - -const kit = newKit('mainnet') -// offchain data wrapper -const accounts = await kit.contracts.getAccounts() -accounts.getMetadataURL(address) -// import { ClaimTypes } from '@celo/contractkit/lib/identity/claims/types' -import { IdentityMetadataWrapper } from '@celo/contractkit/lib/identity/metadata' -IdentityMetadataWrapper.fetchFromURL - -/// packages/common/src/utils/contracts.ts -newKitWithApiKey -// newKit with the HttpProviderOptions - -/// packages/common/src/utils/authentication.ts -const accountWrapper = await kit.contracts.getAccounts() -accountWrapper.getDataEncryptionKey(address) - -// apps/signer/src/common/web3/contracts.ts -kit.contracts.getOdisPayments().totalPaidCUSD - -// apps/monitor/src/query.ts -contractKit.connection.addAccount(privateKey) - -accounts.generateProofOfKeyPossessionLocally diff --git a/packages/common/src/celoViemKit.ts b/packages/common/src/contracts.ts similarity index 100% rename from packages/common/src/celoViemKit.ts rename to packages/common/src/contracts.ts diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index d06684d4a..fa47f75b8 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1,4 +1,4 @@ -export { getAccountsContract, getOdisPaymentsContract } from './celoViemKit' +export { getAccountsContract, getCUSDContract, getOdisPaymentsContract } from './contracts' export * from './domains' export * from './interfaces' export { ErrorMessage, WarningMessage } from './interfaces/errors' diff --git a/packages/common/src/test/utils.ts b/packages/common/src/test/utils.ts index cf258cbce..ce406c31e 100644 --- a/packages/common/src/test/utils.ts +++ b/packages/common/src/test/utils.ts @@ -1,7 +1,6 @@ import { privateKeyToAddress } from '@celo/utils/lib/address' -import { serializeSignature, Signature, signMessage } from '@celo/utils/lib/signatureUtils' +import { serializeSignature, signMessage } from '@celo/utils/lib/signatureUtils' import BigNumber from 'bignumber.js' -import { Address, Hex } from 'viem' import { AuthenticationMethod, PhoneNumberPrivacyRequest, @@ -92,26 +91,6 @@ export function createMockWeb3(txCount: number, blockNumber: number) { } } -// Seems unused. -export async function _registerWalletAddress( - accountAddress: Address, - walletAddress: Address, - walletAddressPk: Hex, - contractKit: any, -) { - const accounts = await contractKit.contracts.getAccounts() - // this is not a contract method but rather a local function must port - // there is a method on the contract generateProofOfKeyPossession i wonder if it will work - const pop = await accounts.generateProofOfKeyPossessionLocally( - accountAddress, - walletAddress, - walletAddressPk, - ) - await accounts - .setWalletAddress(walletAddress, pop as Signature) - .sendAndWaitForReceipt({ from: accountAddress } as any) -} - export function getPnpQuotaRequest( account: string, authenticationMethod?: string, diff --git a/packages/common/src/utils/authentication.ts b/packages/common/src/utils/authentication.ts index a9ebc24f4..2a077bd5e 100644 --- a/packages/common/src/utils/authentication.ts +++ b/packages/common/src/utils/authentication.ts @@ -7,7 +7,7 @@ import crypto from 'crypto' import { Request } from 'express' import { Address, Client, Hex, isAddress } from 'viem' import { fetchEnv, rootLogger } from '..' -import { getAccountsContract } from '../celoViemKit' +import { getAccountsContract } from '../contracts' import { AuthenticationMethod, ErrorMessage, diff --git a/packages/common/test/utils/authentication.test.ts b/packages/common/test/utils/authentication.test.ts index 33254e65a..d9d4f9d0d 100644 --- a/packages/common/test/utils/authentication.test.ts +++ b/packages/common/test/utils/authentication.test.ts @@ -1,8 +1,8 @@ import { hexToBuffer } from '@celo/base' -import { ContractKit } from '@celo/contractkit' import Logger from 'bunyan' import { Request } from 'express' -import { Client, createTestClient } from 'viem' +import { Client, createClient, http } from 'viem' +import { celoAlfajores } from 'viem/chains' import { ErrorMessage, ErrorType } from '../../src/interfaces/errors' import { AuthenticationMethod } from '../../src/interfaces/requests' import * as auth from '../../src/utils/authentication' @@ -14,6 +14,8 @@ describe('Authentication test suite', () => { level: 'warn', }) + const client = createClient({ transport: http(), chain: celoAlfajores }) + describe('authenticateUser utility', () => { it("Should fail authentication with missing 'Authorization' header", async () => { const sampleRequest: Request = { @@ -84,8 +86,6 @@ describe('Authentication test suite', () => { // }, // } as ContractKit - const client = createTestClient({}) - const dekFetcher = newDEKFetcher(client, logger) const warnings: ErrorType[] = [] @@ -104,18 +104,18 @@ describe('Authentication test suite', () => { authenticationMethod: AuthenticationMethod.ENCRYPTION_KEY, }, } as Request - const mockContractKit = { - contracts: { - getAccounts: async () => { - return Promise.resolve({ - getDataEncryptionKey: async (_: string) => { - return 'notAValidKeyEncryption' - }, - }) - }, - }, - } as ContractKit - const dekFetcher = newDEKFetcher(mockContractKit, logger) + // const mockContractKit = { + // contracts: { + // getAccounts: async () => { + // return Promise.resolve({ + // getDataEncryptionKey: async (_: string) => { + // return 'notAValidKeyEncryption' + // }, + // }) + // }, + // }, + // } as ContractKit + const dekFetcher = newDEKFetcher(client, logger) const warnings: ErrorType[] = [] @@ -136,25 +136,25 @@ describe('Authentication test suite', () => { get: (name: string) => (name === 'Authorization' ? sig : ''), body, } as Request - const mockContractKit = { - contracts: { - getAccounts: async () => { - return Promise.resolve({ - getDataEncryptionKey: async (_: string) => { - // NOTE: elliptic is disabled elsewhere in this library to prevent - // accidental signing of truncated messages. - const EC = require('elliptic').ec - const ec = new EC('secp256k1') - const key = ec.keyFromPrivate(hexToBuffer(rawKey)) - return key.getPublic(true, 'hex') - }, - }) - }, - }, - } as ContractKit + // const mockContractKit = { + // contracts: { + // getAccounts: async () => { + // return Promise.resolve({ + // getDataEncryptionKey: async (_: string) => { + // // NOTE: elliptic is disabled elsewhere in this library to prevent + // // accidental signing of truncated messages. + // const EC = require('elliptic').ec + // const ec = new EC('secp256k1') + // const key = ec.keyFromPrivate(hexToBuffer(rawKey)) + // return key.getPublic(true, 'hex') + // }, + // }) + // }, + // }, + // } as ContractKit const warnings: ErrorType[] = [] - const dekFetcher = newDEKFetcher(mockContractKit, logger) + const dekFetcher = newDEKFetcher(client, logger) const success = await auth.authenticateUser(sampleRequest, logger, dekFetcher, warnings) @@ -181,26 +181,26 @@ describe('Authentication test suite', () => { get: (name: string) => (name === 'Authorization' ? sig : ''), body, } as Request - const mockContractKit = { - contracts: { - getAccounts: async () => { - return Promise.resolve({ - getDataEncryptionKey: async (_: string) => { - // NOTE: elliptic is disabled elsewhere in this library to prevent - // accidental signing of truncated messages. - const EC = require('elliptic').ec - const ec = new EC('secp256k1') - const key = ec.keyFromPrivate(hexToBuffer(rawKey)) - return key.getPublic(true, 'hex') - }, - }) - }, - }, - } as ContractKit + // const mockContractKit = { + // contracts: { + // getAccounts: async () => { + // return Promise.resolve({ + // getDataEncryptionKey: async (_: string) => { + // // NOTE: elliptic is disabled elsewhere in this library to prevent + // // accidental signing of truncated messages. + // const EC = require('elliptic').ec + // const ec = new EC('secp256k1') + // const key = ec.keyFromPrivate(hexToBuffer(rawKey)) + // return key.getPublic(true, 'hex') + // }, + // }) + // }, + // }, + // } as ContractKit const warnings: ErrorType[] = [] - const dekFetcher = newDEKFetcher(mockContractKit, logger) + const dekFetcher = newDEKFetcher(client, logger) const success = await auth.authenticateUser(sampleRequest, logger, dekFetcher, warnings) @@ -221,27 +221,27 @@ describe('Authentication test suite', () => { body, } as Request - const mockContractKit = { - contracts: { - getAccounts: async () => { - return Promise.resolve({ - getDataEncryptionKey: async (_: string) => { - // NOTE: elliptic is disabled elsewhere in this library to prevent - // accidental signing of truncated messages. - const EC = require('elliptic').ec - const ec = new EC('secp256k1') - // Send back a manipulated key. - const key = ec.keyFromPrivate(hexToBuffer('a' + rawKey.slice(1))) - return key.getPublic(true, 'hex') - }, - }) - }, - }, - } as ContractKit + // const mockContractKit = { + // contracts: { + // getAccounts: async () => { + // return Promise.resolve({ + // getDataEncryptionKey: async (_: string) => { + // // NOTE: elliptic is disabled elsewhere in this library to prevent + // // accidental signing of truncated messages. + // const EC = require('elliptic').ec + // const ec = new EC('secp256k1') + // // Send back a manipulated key. + // const key = ec.keyFromPrivate(hexToBuffer('a' + rawKey.slice(1))) + // return key.getPublic(true, 'hex') + // }, + // }) + // }, + // }, + // } as ContractKit const warnings: ErrorType[] = [] - const dekFetcher = newDEKFetcher(mockContractKit, logger) + const dekFetcher = newDEKFetcher(client, logger) const success = await auth.authenticateUser(sampleRequest, logger, dekFetcher, warnings) @@ -263,27 +263,27 @@ describe('Authentication test suite', () => { body, } as Request - const mockContractKit = { - contracts: { - getAccounts: async () => { - return Promise.resolve({ - getDataEncryptionKey: async (_: string) => { - // NOTE: elliptic is disabled elsewhere in this library to prevent - // accidental signing of truncated messages. - const EC = require('elliptic').ec - const ec = new EC('secp256k1') - // Send back a manipulated key. - const key = ec.keyFromPrivate(hexToBuffer(rawKey)) - return key.getPublic(true, 'hex') - }, - }) - }, - }, - } as ContractKit + // const mockContractKit = { + // contracts: { + // getAccounts: async () => { + // return Promise.resolve({ + // getDataEncryptionKey: async (_: string) => { + // // NOTE: elliptic is disabled elsewhere in this library to prevent + // // accidental signing of truncated messages. + // const EC = require('elliptic').ec + // const ec = new EC('secp256k1') + // // Send back a manipulated key. + // const key = ec.keyFromPrivate(hexToBuffer(rawKey)) + // return key.getPublic(true, 'hex') + // }, + // }) + // }, + // }, + // } as ContractKit const warnings: ErrorType[] = [] - const dekFetcher = newDEKFetcher(mockContractKit, logger) + const dekFetcher = newDEKFetcher(client, logger) const success = await auth.authenticateUser(sampleRequest, logger, dekFetcher, warnings) @@ -308,18 +308,18 @@ describe('Authentication test suite', () => { get: (name: string) => (name === 'Authorization' ? sig : ''), body, } as Request - const mockContractKit = { - contracts: { - getAccounts: async () => { - return Promise.resolve({ - getDataEncryptionKey: async (_: string) => { - return key.getPublic(true, 'hex') - }, - }) - }, - }, - } as ContractKit - const dekFetcher = newDEKFetcher(mockContractKit, logger) + // const mockContractKit = { + // contracts: { + // getAccounts: async () => { + // return Promise.resolve({ + // getDataEncryptionKey: async (_: string) => { + // return key.getPublic(true, 'hex') + // }, + // }) + // }, + // }, + // } as ContractKit + const dekFetcher = newDEKFetcher(client, logger) const warnings: ErrorType[] = [] diff --git a/packages/identity/src/odis/query.ts b/packages/identity/src/odis/query.ts index cb7fb992e..2feccd9a8 100644 --- a/packages/identity/src/odis/query.ts +++ b/packages/identity/src/odis/query.ts @@ -16,18 +16,18 @@ import fetch from 'cross-fetch' import debugFactory from 'debug' import { isLeft } from 'fp-ts/lib/Either' import * as t from 'io-ts' -import { isAddress, WalletClient } from 'viem' +import { Address, Hex, isAddress, SignableMessage } from 'viem' const debug = debugFactory('kit:odis:query') export interface WalletKeySigner { authenticationMethod: AuthenticationMethod.WALLET_KEY - client: WalletClient + sign191: ({ message, account }: { message: SignableMessage; account: Address }) => Promise } export interface EncryptionKeySigner { authenticationMethod: AuthenticationMethod.ENCRYPTION_KEY - rawKey: string + rawKey: Hex } // Support signing with the DEK or with the @@ -135,7 +135,7 @@ export async function getOdisPnpRequestAuth( if (!isAddress(body.account)) { throw new Error('body.account is not a valid Address') } - return signer.client.signMessage({ message: bodyString, account: body.account }) + return signer.sign191({ message: bodyString, account: body.account }) } throw new Error('AuthenticationMethod not supported') } diff --git a/packages/identity/src/offchain-data-wrapper.test.ts b/packages/identity/src/offchain-data-wrapper.test.ts index 2fcbaab41..508aafadd 100644 --- a/packages/identity/src/offchain-data-wrapper.test.ts +++ b/packages/identity/src/offchain-data-wrapper.test.ts @@ -37,6 +37,7 @@ interface RegisteredAccount { } testWithGanache('Offchain Data', (web3) => { + // @ts-expect-error slightly different web3 defs const kit = newKitFromWeb3(web3, new LocalWallet()) const writerPrivate = ACCOUNT_PRIVATE_KEYS[0]