11import { type InitialAccountData , generateSchnorrAccounts } from '@aztec/accounts/testing' ;
22import type { FieldLike } from '@aztec/aztec.js/abi' ;
33import { NO_FROM } from '@aztec/aztec.js/account' ;
4- import type { AztecAddress } from '@aztec/aztec.js/addresses' ;
4+ import type { AztecAddress , CompleteAddress } from '@aztec/aztec.js/addresses' ;
55import type { AztecNode } from '@aztec/aztec.js/node' ;
6+ import type { AccountManager } from '@aztec/aztec.js/wallet' ;
67import { BlockNumber } from '@aztec/foundation/branded-types' ;
78import { type DeliveryEvent , OnchainDeliveryTestContract } from '@aztec/noir-test-contracts.js/OnchainDeliveryTest' ;
8- import type { PXECreationOptions } from '@aztec/pxe/server ' ;
9+ import type { CustomRequest , ResolveCustomRequest , ResolveTaggingSecretStrategy } from '@aztec/pxe/config ' ;
910import type { AztecNodeDebug } from '@aztec/stdlib/interfaces/client' ;
1011
1112import { jest } from '@jest/globals' ;
@@ -14,9 +15,13 @@ import { AUTOMINE_E2E_OPTS } from '../../fixtures/fixtures.js';
1415import { ensureHandshakeRegistryPublished , setup , setupPXEAndGetWallet } from '../../fixtures/setup.js' ;
1516import { TestWallet } from '../../test-wallet/test_wallet.js' ;
1617
17- // The wallet hook that selects a message's tagging-secret source. Derived from the exported PXE options
18- // rather than importing the hook type, which `@aztec/pxe/server` does not re-export.
19- export type SenderHook = NonNullable < NonNullable < PXECreationOptions [ 'hooks' ] > [ 'resolveTaggingSecretStrategy' ] > ;
18+ // Builds the hook serving custom requests issued during the sender's simulations. Installed on the sender PXE at
19+ // creation but built only once the recipient exists, since serving typically needs the recipient's wallet and keys.
20+ export type CustomRequestResponder = (
21+ recipient : TestWallet ,
22+ recipientAccount : InitialAccountData ,
23+ recipientCompleteAddress : CompleteAddress ,
24+ ) => ResolveCustomRequest ;
2025
2126export type Mode = 'constrained' | 'unconstrained' ;
2227
@@ -40,19 +45,22 @@ export function buildMessageDeliveryTest(opts: {
4045 strategy : string ;
4146 mode : DeliveryMode ;
4247 // Required: every cell states its source explicitly rather than leaning on the PXE default (covered by unit tests).
43- senderHook : SenderHook ;
48+ senderHook : ResolveTaggingSecretStrategy ;
4449 // Recipient-side setup the source requires (e.g. registering a raw arbitrary secret); runs once after deployment.
4550 recipientRegistration ?: (
4651 recipient : TestWallet ,
4752 recipientAddress : AztecAddress ,
4853 sender : AztecAddress ,
4954 ) => Promise < void > ;
55+ // Serves the custom requests issued during the sender's simulations (e.g. the registry's interactive-handshake
56+ // signature request).
57+ customRequestResponder ?: CustomRequestResponder ;
5058 // Extra `it()`s to register in this cell's suite, e.g. assertions against state a custom `senderHook` recorded.
5159 // Called inside the same `describe`, after the two baseline assertions below, so it shares their `beforeAll`
5260 // instead of depending on Jest's cross-`describe` execution order.
5361 additionalTests ?: ( ) => void ;
5462} ) {
55- const { strategy, mode, senderHook, recipientRegistration, additionalTests } = opts ;
63+ const { strategy, mode, senderHook, recipientRegistration, customRequestResponder , additionalTests } = opts ;
5664 const description = `${ strategy } x ${ formatMode ( mode ) } ` ;
5765
5866 describe ( description , ( ) => {
@@ -84,11 +92,14 @@ export function buildMessageDeliveryTest(opts: {
8492 ? contractSender . methods . emit_note ( recipient , value )
8593 : contractSender . methods . emit_note_unconstrained ( recipient , value ) ;
8694
95+ let additionallyFundedAccounts : InitialAccountData [ ] ;
96+ let recipientAccount : AccountManager | undefined ;
97+ let customRequestCount = 0 ;
98+
8799 beforeAll ( async ( ) => {
88100 // The sender PXE holds the sender and carries this cell's tagging-secret-strategy hook. The recipient is funded
89101 // at genesis here but created and deployed on the isolated recipient PXE below, so it carries no sender state
90102 // from other cells.
91- let additionallyFundedAccounts : InitialAccountData [ ] ;
92103 ( {
93104 aztecNode,
94105 additionallyFundedAccounts,
@@ -98,7 +109,26 @@ export function buildMessageDeliveryTest(opts: {
98109 } = await setup ( 1 , {
99110 ...AUTOMINE_E2E_OPTS ,
100111 additionallyFundedAccounts : await generateSchnorrAccounts ( 1 , 'schnorr' ) ,
101- pxeCreationOptions : { hooks : { resolveTaggingSecretStrategy : senderHook } } ,
112+ pxeCreationOptions : {
113+ hooks : {
114+ resolveTaggingSecretStrategy : senderHook ,
115+ resolveCustomRequest : async ( request : CustomRequest ) => {
116+ if ( ! customRequestResponder ) {
117+ throw new Error ( 'A custom request arrived but this test cell has no customRequestResponder configured' ) ;
118+ }
119+ if ( ! recipientAccount ) {
120+ throw new Error ( 'A custom request arrived before the recipient wallet was created' ) ;
121+ }
122+ customRequestCount ++ ;
123+ const respond = customRequestResponder (
124+ walletRecipient ,
125+ additionallyFundedAccounts [ 0 ] ,
126+ await recipientAccount . getCompleteAddress ( ) ,
127+ ) ;
128+ return respond ( request ) ;
129+ } ,
130+ } ,
131+ } ,
102132 } ) ) ;
103133
104134 ( { wallet : walletRecipient , teardown : teardownRecipient } = await setupPXEAndGetWallet (
@@ -108,7 +138,7 @@ export function buildMessageDeliveryTest(opts: {
108138 undefined ,
109139 'pxe-recipient' ,
110140 ) ) ;
111- const recipientAccount = await walletRecipient . createSchnorrAccount (
141+ recipientAccount = await walletRecipient . createSchnorrAccount (
112142 additionallyFundedAccounts [ 0 ] . secret ,
113143 additionallyFundedAccounts [ 0 ] . salt ,
114144 additionallyFundedAccounts [ 0 ] . signingKey ,
@@ -172,6 +202,12 @@ export function buildMessageDeliveryTest(opts: {
172202 expect ( readNotes ) . toEqual ( noteValues ) ;
173203 } ) ;
174204
205+ if ( customRequestResponder ) {
206+ it ( 'the custom request hook fires exactly once, on the send that bootstraps the tagging secret' , ( ) => {
207+ expect ( customRequestCount ) . toBe ( 1 ) ;
208+ } ) ;
209+ }
210+
175211 additionalTests ?.( ) ;
176212 } ) ;
177213}
0 commit comments