From 443922ff440a596e078b84ac4addf409fc7a70b2 Mon Sep 17 00:00:00 2001 From: derekpierre Date: Mon, 19 Aug 2024 12:28:12 -0400 Subject: [PATCH 1/8] Add ability for IStorage to remove items. --- packages/taco-auth/src/storage.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/taco-auth/src/storage.ts b/packages/taco-auth/src/storage.ts index a0d48d511..ef08e367d 100644 --- a/packages/taco-auth/src/storage.ts +++ b/packages/taco-auth/src/storage.ts @@ -4,6 +4,8 @@ interface IStorage { getItem(key: string): string | null; setItem(key: string, value: string): void; + + removeItem(key: string): void; } class BrowserStorage implements IStorage { @@ -14,6 +16,10 @@ class BrowserStorage implements IStorage { public setItem(key: string, value: string): void { localStorage.setItem(key, value); } + + public removeItem(key: string): void { + localStorage.removeItem(key); + } } class NodeStorage implements IStorage { @@ -26,6 +32,10 @@ class NodeStorage implements IStorage { public setItem(key: string, value: string): void { this.storage[key] = value; } + + public removeItem(key: string) { + delete this.storage[key]; + } } export class LocalStorage { @@ -50,4 +60,8 @@ export class LocalStorage { const asJson = JSON.stringify(authSignature); this.storage.setItem(key, asJson); } + + public clear(key: string): void { + this.storage.removeItem(key); + } } From be3af1640cf3d17e0900e1f98269d9def4a050ea Mon Sep 17 00:00:00 2001 From: derekpierre Date: Mon, 19 Aug 2024 12:29:26 -0400 Subject: [PATCH 2/8] Check whether prior auth signature is now expired (2h) before returning; if expired remove from storage and regenerate it. --- .../src/providers/eip4361/eip4361.ts | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/taco-auth/src/providers/eip4361/eip4361.ts b/packages/taco-auth/src/providers/eip4361/eip4361.ts index e5043023a..232c121b0 100644 --- a/packages/taco-auth/src/providers/eip4361/eip4361.ts +++ b/packages/taco-auth/src/providers/eip4361/eip4361.ts @@ -52,7 +52,13 @@ export class EIP4361AuthProvider { // If we have a signature in localStorage, return it const maybeSignature = this.storage.getAuthSignature(storageKey); if (maybeSignature) { - return maybeSignature; + // check whether older than node freshness requirement + if (this.isMessageExpired(maybeSignature.typedData)) { + // clear signature so that it will be recreated and stored + this.storage.clear(storageKey); + } else { + return maybeSignature; + } } // If at this point we didn't return, we need to create a new message @@ -61,6 +67,19 @@ export class EIP4361AuthProvider { return authMessage; } + private isMessageExpired(message: string): boolean { + const siweMessage = new SiweMessage(message); + if (!siweMessage.issuedAt) { + // don't expect to ever happen; but just in case + return false; + } + + const twoHourWindow = new Date(siweMessage.issuedAt); + twoHourWindow.setHours(twoHourWindow.getHours() + 2); + const now = new Date(); + return twoHourWindow < now; + } + private async createSIWEAuthMessage(): Promise { const address = await this.signer.getAddress(); const { domain, uri } = this.providerParams; From 09437cc77c6be7806e8cbef59bc0c76bc47b48fd Mon Sep 17 00:00:00 2001 From: derekpierre Date: Mon, 19 Aug 2024 12:31:01 -0400 Subject: [PATCH 3/8] Add test for EIP4361AuthProvider storage expiry. --- packages/taco-auth/test/auth-provider.test.ts | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/packages/taco-auth/test/auth-provider.test.ts b/packages/taco-auth/test/auth-provider.test.ts index cf927b47b..a2aa4d83a 100644 --- a/packages/taco-auth/test/auth-provider.test.ts +++ b/packages/taco-auth/test/auth-provider.test.ts @@ -5,7 +5,7 @@ import { TEST_SIWE_PARAMS, } from '@nucypher/test-utils'; import { SiweMessage } from 'siwe'; -import { describe, expect, it } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { EIP4361AuthProvider } from '../src/providers'; import { EIP4361TypedDataSchema } from '../src/providers/eip4361/common'; @@ -52,3 +52,50 @@ describe('auth provider', () => { ).toThrow(); }); }); + +describe('auth provider caching', () => { + beforeEach(() => { + // tell vitest we use mocked time + vi.useFakeTimers(); + }); + + afterEach(() => { + // restoring date after each test run + vi.useRealTimers(); + }); + + const provider = fakeProvider(bobSecretKeyBytes); + const signer = fakeSigner(bobSecretKeyBytes); + const eip4361Provider = new EIP4361AuthProvider( + provider, + signer, + TEST_SIWE_PARAMS, + ); + + it('caches auth signature, but regenerates when expired', async () => { + const createAuthSignatureSpy = vi.spyOn( + eip4361Provider, + 'createSIWEAuthMessage', + ); + + const typedSignature = await eip4361Provider.getOrCreateAuthSignature(); + expect(createAuthSignatureSpy).toHaveBeenCalledTimes(1); + + const typedSignatureSecondCall = + await eip4361Provider.getOrCreateAuthSignature(); + // auth signature not expired, so spy is not called a 2nd time + expect(createAuthSignatureSpy).toHaveBeenCalledTimes(1); + expect(typedSignatureSecondCall).toEqual(typedSignature); + + // time travel to 2h:1m in the future; auth signature is now expired + const now = new Date(); + now.setHours(now.getHours() + 2, now.getMinutes() + 1); + vi.setSystemTime(now); + + const typedSignatureThirdCall = + await eip4361Provider.getOrCreateAuthSignature(); + // auth signature is now expired, so spy is called a 2nd time + expect(createAuthSignatureSpy).toHaveBeenCalledTimes(2); + expect(typedSignatureThirdCall).not.toEqual(typedSignature); + }); +}); From 35019f3331cf718e0d4979f4443d1768bd436cca Mon Sep 17 00:00:00 2001 From: derekpierre Date: Mon, 19 Aug 2024 16:16:00 -0400 Subject: [PATCH 4/8] Add test for SingleSignOnEIP4361AuthProvider. --- packages/taco-auth/test/auth-provider.test.ts | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/packages/taco-auth/test/auth-provider.test.ts b/packages/taco-auth/test/auth-provider.test.ts index a2aa4d83a..b9157be0a 100644 --- a/packages/taco-auth/test/auth-provider.test.ts +++ b/packages/taco-auth/test/auth-provider.test.ts @@ -1,18 +1,20 @@ import { bobSecretKeyBytes, fakeProvider, - fakeSigner, TEST_SIWE_PARAMS, } from '@nucypher/test-utils'; import { SiweMessage } from 'siwe'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { EIP4361AuthProvider } from '../src/providers'; +import { + EIP4361AuthProvider, + SingleSignOnEIP4361AuthProvider, +} from '../src/providers'; import { EIP4361TypedDataSchema } from '../src/providers/eip4361/common'; describe('auth provider', () => { const provider = fakeProvider(bobSecretKeyBytes); - const signer = fakeSigner(bobSecretKeyBytes); + const signer = provider.getSigner(); const eip4361Provider = new EIP4361AuthProvider( provider, signer, @@ -65,7 +67,7 @@ describe('auth provider caching', () => { }); const provider = fakeProvider(bobSecretKeyBytes); - const signer = fakeSigner(bobSecretKeyBytes); + const signer = provider.getSigner(); const eip4361Provider = new EIP4361AuthProvider( provider, signer, @@ -99,3 +101,34 @@ describe('auth provider caching', () => { expect(typedSignatureThirdCall).not.toEqual(typedSignature); }); }); + +describe('single sign-on auth provider', async () => { + const provider = fakeProvider(bobSecretKeyBytes); + const signer = provider.getSigner(); + + const eip4361Provider = new EIP4361AuthProvider( + provider, + signer, + TEST_SIWE_PARAMS, + ); + const originalTypedSignature = + await eip4361Provider.getOrCreateAuthSignature(); + + it('use existing SIWE message', async () => { + const originalSiweMessage = originalTypedSignature.typedData; + const originalSiweSignature = originalTypedSignature.signature; + + const singleSignOnProvider = + await SingleSignOnEIP4361AuthProvider.fromExistingSiweInfo( + originalSiweMessage, + originalSiweSignature, + ); + + const typedSignature = + await singleSignOnProvider.getOrCreateAuthSignature(); + expect(typedSignature.typedData).toEqual(originalSiweMessage); + expect(typedSignature.signature).toEqual(originalSiweSignature); + expect(typedSignature.address).toEqual(await signer.getAddress()); + expect(typedSignature.scheme).toEqual('EIP4361'); + }); +}); From 959f40ecf7f14e342f145da649aa817dfaad0c24 Mon Sep 17 00:00:00 2001 From: derekpierre Date: Mon, 19 Aug 2024 16:17:12 -0400 Subject: [PATCH 5/8] Use a legit signer with the fakeProvider() test utility. There is no need to have both fakeSigner() and fakeProvider() utilities. Only fakeProvider() is needed, and the signer can be obtained from the provider. It also better links the provider and signer. --- packages/test-utils/src/utils.ts | 74 ++++++++++++++------------------ 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/packages/test-utils/src/utils.ts b/packages/test-utils/src/utils.ts index a19af1391..147d289d4 100644 --- a/packages/test-utils/src/utils.ts +++ b/packages/test-utils/src/utils.ts @@ -41,6 +41,7 @@ import { EIP4361AuthProvider, SingleSignOnEIP4361AuthProvider, USER_ADDRESS_PARAM_DEFAULT, + USER_ADDRESS_PARAM_EXTERNAL_EIP4361, } from '@nucypher/taco-auth'; import { ethers, providers, Wallet } from 'ethers'; import { expect, SpyInstance, vi } from 'vitest'; @@ -70,66 +71,55 @@ const makeFakeProvider = ( }; }; -export const fakeSigner = ( +export const fakeProvider = ( secretKeyBytes = SecretKey.random().toBEBytes(), blockNumber = 1000, blockTimestamp = 1000, blockHash = '0x0000000000000000000000000000000000000000', -) => { +): ethers.providers.Web3Provider => { const provider = makeFakeProvider(blockNumber, blockTimestamp, blockHash); - return { - ...new Wallet(secretKeyBytes), + const wallet = new Wallet(secretKeyBytes); + const fakeSigner = { + ...wallet, provider: provider, - _signTypedData: () => Promise.resolve('fake-typed-signature'), - signMessage: () => Promise.resolve('fake-signature'), - getAddress: () => - Promise.resolve('0x0000000000000000000000000000000000000000'), + _signTypedData: wallet._signTypedData, + signMessage: wallet.signMessage, + getAddress: wallet.getAddress, } as unknown as ethers.providers.JsonRpcSigner; + + return { + ...provider, + getSigner: () => fakeSigner, + } as unknown as ethers.providers.Web3Provider; }; -export const fakeAuthProviders = async () => { +export const fakeAuthProviders = async ( + signer?: ethers.providers.JsonRpcSigner, +) => { + const signerToUse = signer ? signer : fakeProvider().getSigner(); return { - [USER_ADDRESS_PARAM_DEFAULT]: fakeEIP4351AuthProvider(), - [':userAddressExternalEIP4361']: - await fakeSingleSignOnEIP4361AuthProvider(), + [USER_ADDRESS_PARAM_DEFAULT]: fakeEIP4351AuthProvider(signerToUse), + [USER_ADDRESS_PARAM_EXTERNAL_EIP4361]: + await fakeSingleSignOnEIP4361AuthProvider(signerToUse), }; }; -export const fakeProvider = ( - secretKeyBytes = SecretKey.random().toBEBytes(), - blockNumber = 1000, - blockTimestamp = 1000, - blockHash = '0x0000000000000000000000000000000000000000', -): ethers.providers.Web3Provider => { - const fakeProvider = makeFakeProvider(blockTimestamp, blockNumber, blockHash); - const fakeSignerWithProvider = fakeSigner( - secretKeyBytes, - blockNumber, - blockTimestamp, - ); - return { - ...fakeProvider, - getSigner: () => fakeSignerWithProvider, - } as unknown as ethers.providers.Web3Provider; +const fakeEIP4351AuthProvider = (signer: ethers.providers.JsonRpcSigner) => { + return new EIP4361AuthProvider(signer.provider, signer, TEST_SIWE_PARAMS); }; -const fakeEIP4351AuthProvider = () => { - return new EIP4361AuthProvider( - fakeProvider(), - fakeSigner(), +const fakeSingleSignOnEIP4361AuthProvider = async ( + signer: ethers.providers.JsonRpcSigner, +) => { + const eip4361Provider = new EIP4361AuthProvider( + signer.provider, + signer, TEST_SIWE_PARAMS, ); -}; - -const fakeSingleSignOnEIP4361AuthProvider = async () => { - const message = - 'localhost wants you to sign in with your Ethereum account:\n0x924c255297BF9032583dF6E06a8633dc720aB52D\n\nSign-In With Ethereum Example Statement\n\nURI: http://localhost:3000\nVersion: 1\nChain ID: 1234\nNonce: bTyXgcQxn2htgkjJn\nIssued At: 2024-07-18T16:53:39.093516Z'; - const signature = - '0x22cc163b9c37cf425997b76ebafd44a0d68043d0dc9a1dbf823e78c320924476644f28abcf0974d54b8604eff8a62a51559994537d4b8a85cdee977e02ee98921b'; - + const authSignature = await eip4361Provider.getOrCreateAuthSignature(); return SingleSignOnEIP4361AuthProvider.fromExistingSiweInfo( - message, - signature, + authSignature.typedData, + authSignature.signature, ); }; From c53ea31974ca9b1102483782a5106688a43daf68 Mon Sep 17 00:00:00 2001 From: derekpierre Date: Mon, 19 Aug 2024 16:19:03 -0400 Subject: [PATCH 6/8] Update tests to obtain signer from fakeProvider() instead of using fakeSigner() utility. --- packages/pre/test/acceptance/alice-grants.test.ts | 6 +++--- packages/pre/test/acceptance/delay-enact.test.ts | 3 +-- packages/taco/test/conditions/context.test.ts | 14 +++++--------- packages/taco/test/taco.test.ts | 5 ++--- packages/taco/test/test-utils.ts | 5 +++-- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/packages/pre/test/acceptance/alice-grants.test.ts b/packages/pre/test/acceptance/alice-grants.test.ts index fdf88cbcd..1e1442734 100644 --- a/packages/pre/test/acceptance/alice-grants.test.ts +++ b/packages/pre/test/acceptance/alice-grants.test.ts @@ -10,7 +10,6 @@ import { bytesEqual, fakePorterUri, fakeProvider, - fakeSigner, fakeUrsulas, fromBytes, mockGetUrsulas, @@ -70,9 +69,10 @@ describe('story: alice shares message with bob through policy', () => { startDate, endDate, }; + const provider = fakeProvider(); policy = await alice.grant( - fakeProvider(), - fakeSigner(), + provider, + provider.getSigner(), domains.DEVNET, fakePorterUri, policyParams, diff --git a/packages/pre/test/acceptance/delay-enact.test.ts b/packages/pre/test/acceptance/delay-enact.test.ts index 01cab8949..b88e64343 100644 --- a/packages/pre/test/acceptance/delay-enact.test.ts +++ b/packages/pre/test/acceptance/delay-enact.test.ts @@ -2,7 +2,6 @@ import { bytesEqual, fakePorterUri, fakeProvider, - fakeSigner, fakeUrsulas, mockGetUrsulas, } from '@nucypher/test-utils'; @@ -61,7 +60,7 @@ describe('story: alice creates a policy but someone else enacts it', () => { const enacted = await preEnactedPolicy.enact( provider, - fakeSigner(), + provider.getSigner(), domains.DEVNET, ); expect(enacted.txHash).toBeDefined(); diff --git a/packages/taco/test/conditions/context.test.ts b/packages/taco/test/conditions/context.test.ts index d18758554..e893766a1 100644 --- a/packages/taco/test/conditions/context.test.ts +++ b/packages/taco/test/conditions/context.test.ts @@ -7,11 +7,7 @@ import { USER_ADDRESS_PARAM_DEFAULT, USER_ADDRESS_PARAM_EXTERNAL_EIP4361, } from '@nucypher/taco-auth'; -import { - fakeAuthProviders, - fakeProvider, - fakeSigner, -} from '@nucypher/test-utils'; +import { fakeAuthProviders, fakeProvider } from '@nucypher/test-utils'; import { ethers } from 'ethers'; import { beforeAll, describe, expect, it, vi } from 'vitest'; @@ -308,8 +304,8 @@ describe('context', () => { // TODO: Move to a separate file describe('No authentication provider', () => { - let provider: ethers.providers.Provider; - let signer: ethers.Signer; + let provider: ethers.providers.Web3Provider; + let signer: ethers.providers.JsonRpcSigner; let authProviders: Record; async function testEIP4361AuthSignature( @@ -337,8 +333,8 @@ describe('No authentication provider', () => { beforeAll(async () => { await initialize(); provider = fakeProvider(); - signer = fakeSigner(); - authProviders = await fakeAuthProviders(); + signer = provider.getSigner(); + authProviders = await fakeAuthProviders(signer); }); it('throws an error if there is no auth provider', () => { diff --git a/packages/taco/test/taco.test.ts b/packages/taco/test/taco.test.ts index 589d7a9fa..5f8b59f3d 100644 --- a/packages/taco/test/taco.test.ts +++ b/packages/taco/test/taco.test.ts @@ -10,7 +10,6 @@ import { fakeDkgFlow, fakePorterUri, fakeProvider, - fakeSigner, fakeTDecFlow, mockGetRitualIdFromPublicKey, mockTacoDecrypt, @@ -48,7 +47,7 @@ describe('taco', () => { const mockedDkg = fakeDkgFlow(FerveoVariant.precomputed, 0, 4, 4); const mockedDkgRitual = fakeDkgRitual(mockedDkg); const provider = fakeProvider(aliceSecretKeyBytes); - const signer = fakeSigner(aliceSecretKeyBytes); + const signer = provider.getSigner(); const getFinalizedRitualSpy = mockGetActiveRitual(mockedDkgRitual); const messageKit = await taco.encrypt( @@ -110,7 +109,7 @@ describe('taco', () => { const mockedDkg = fakeDkgFlow(FerveoVariant.precomputed, 0, 4, 4); const mockedDkgRitual = fakeDkgRitual(mockedDkg); const provider = fakeProvider(aliceSecretKeyBytes); - const signer = fakeSigner(aliceSecretKeyBytes); + const signer = provider.getSigner(); const getFinalizedRitualSpy = mockGetActiveRitual(mockedDkgRitual); const customParamKey = ':nftId'; diff --git a/packages/taco/test/test-utils.ts b/packages/taco/test/test-utils.ts index 02de484f3..360585b1b 100644 --- a/packages/taco/test/test-utils.ts +++ b/packages/taco/test/test-utils.ts @@ -27,7 +27,7 @@ import { } from '@nucypher/shared'; import { fakeDkgFlow, - fakeSigner, + fakeProvider, fakeTDecFlow, TEST_CHAIN_ID, TEST_CONTRACT_ADDR, @@ -84,11 +84,12 @@ export const fakeDkgTDecFlowE2E: ( ) => { const ritual = fakeDkgFlow(variant, ritualId, sharesNum, threshold); const dkgPublicKey = ritual.dkg.publicKey(); + const provider = fakeProvider(); const thresholdMessageKit = await encryptMessage( message, dkgPublicKey, conditionExpr, - fakeSigner(), + provider.getSigner(), ); const { decryptionShares } = fakeTDecFlow({ From 61176cad094841abbfe54aead602201de404044d Mon Sep 17 00:00:00 2001 From: derekpierre Date: Mon, 19 Aug 2024 20:44:44 -0400 Subject: [PATCH 7/8] Exclude non-applicable files from code coverage reports. --- vitest.config.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vitest.config.ts b/vitest.config.ts index 658908535..e29e2152f 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -18,7 +18,12 @@ export default defineConfig({ reporter: ['text', 'html', 'lcov', 'clover'], reportsDirectory: 'coverage', include: ['packages/**/*.ts'], - exclude: ['packages/**/*.test.ts'], + exclude: [ + 'packages/**/*.test.ts', + 'packages/taco/examples/*.ts', + 'packages/shared/scripts/*.ts', + 'packages/test-utils/**/*.ts', + ], }, }, }); From 236f2963e68ff116acf55a2c30e0bce67ebe4e0d Mon Sep 17 00:00:00 2001 From: derekpierre Date: Tue, 20 Aug 2024 09:13:20 -0400 Subject: [PATCH 8/8] Remove unnecessary taco api calls; one of which is no longer applicable. --- examples/taco/nodejs/src/index.ts | 13 --------- packages/taco/src/index.ts | 4 +-- packages/taco/src/taco.ts | 45 ------------------------------- 3 files changed, 2 insertions(+), 60 deletions(-) diff --git a/examples/taco/nodejs/src/index.ts b/examples/taco/nodejs/src/index.ts index 37e8974a7..86d806ea6 100644 --- a/examples/taco/nodejs/src/index.ts +++ b/examples/taco/nodejs/src/index.ts @@ -10,7 +10,6 @@ import { encrypt, fromBytes, initialize, - isAuthorized, toBytes, toHexString, } from '@nucypher/taco'; @@ -81,18 +80,6 @@ const encryptToBytes = async (messageString: string) => { encryptorSigner, ); - // Note: Not actually needed but used by CI for checking contract compatibility. - // Calling it after the encryption because we need material from messageKit. - const isEncryptorAuthenticated = await isAuthorized( - provider, - domain, - messageKit, - ritualId, - ); - if (!isEncryptorAuthenticated) { - throw new Error('Not authorized'); - } - return messageKit.toBytes(); }; diff --git a/packages/taco/src/index.ts b/packages/taco/src/index.ts index 20d7ea005..2bc970844 100644 --- a/packages/taco/src/index.ts +++ b/packages/taco/src/index.ts @@ -10,8 +10,8 @@ export { } from '@nucypher/shared'; export * as conditions from './conditions'; -// TODO(#324): Expose registerEncrypters from taco API -export { decrypt, encrypt, encryptWithPublicKey, isAuthorized } from './taco'; + +export { decrypt, encrypt, encryptWithPublicKey } from './taco'; // TODO: Remove this re-export once `@nucypher/taco-auth` is mature and published export { diff --git a/packages/taco/src/taco.ts b/packages/taco/src/taco.ts index fc166bf00..da1fc9ce9 100644 --- a/packages/taco/src/taco.ts +++ b/packages/taco/src/taco.ts @@ -5,12 +5,10 @@ import { ThresholdMessageKit, } from '@nucypher/nucypher-core'; import { - ChecksumAddress, DkgCoordinatorAgent, Domain, fromHexString, getPorterUris, - GlobalAllowListAgent, PorterClient, toBytes, } from '@nucypher/shared'; @@ -160,46 +158,3 @@ export const decrypt = async ( context, ); }; - -/** - * Checks if the encryption from the provided messageKit is authorized for the specified ritual. - * - * @export - * @param {ethers.providers.Provider} provider - Instance of ethers provider which is used to interact with - * your selected network. - * @param {Domain} domain - The domain which was used to encrypt the network. Must match the `ritualId`. - * @param {ThresholdMessageKit} messageKit - The encrypted message kit to be checked. - * @param {number} ritualId - The ID of the DKG Ritual under which the messageKit was supposedly encrypted. - * - * @returns {Promise} Returns a Promise that resolves with the authorization status. - * True if authorized, false otherwise - */ -export const isAuthorized = async ( - provider: ethers.providers.Provider, - domain: Domain, - messageKit: ThresholdMessageKit, - ritualId: number, -): Promise => - DkgCoordinatorAgent.isEncryptionAuthorized( - provider, - domain, - ritualId, - messageKit, - ); - -// TODO is this still valid and actually needed? should we remove this? -export const registerEncrypters = async ( - provider: ethers.providers.Provider, - signer: ethers.Signer, - domain: Domain, - ritualId: number, - encrypters: ChecksumAddress[], -): Promise => { - await GlobalAllowListAgent.registerEncrypters( - provider, - signer, - domain, - ritualId, - encrypters, - ); -};