@@ -37,6 +37,16 @@ export class AccountInboxService extends Context.Tag('AccountInboxService')<
3737 Messages . InboxMessage ,
3838 ResourceNotFoundError | ValidationError | AuthorizationError | DatabaseService . DatabaseError
3939 > ;
40+ readonly createAccountInbox : (
41+ data : Messages . RequestCreateAccountInbox ,
42+ ) => Effect . Effect < AccountInboxResult , ValidationError | AuthorizationError | DatabaseService . DatabaseError > ;
43+ readonly getLatestAccountInboxMessages : ( params : {
44+ inboxId : string ;
45+ since : Date ;
46+ } ) => Effect . Effect < Messages . InboxMessage [ ] , DatabaseService . DatabaseError > ;
47+ readonly listAccountInboxes : ( params : {
48+ accountAddress : string ;
49+ } ) => Effect . Effect < Messages . AccountInbox [ ] , DatabaseService . DatabaseError > ;
4050 }
4151> ( ) { }
4252
@@ -258,9 +268,131 @@ export const layer = Effect.gen(function* () {
258268 return createdMessage ;
259269 } ) ;
260270
271+ const createAccountInbox = Effect . fn ( 'createAccountInbox' ) ( function * ( data : Messages . RequestCreateAccountInbox ) {
272+ const { accountAddress, inboxId, isPublic, authPolicy, encryptionPublicKey, signature } = data ;
273+
274+ // Verify the signature is valid for the corresponding accountAddress
275+ const signer = Inboxes . recoverAccountInboxCreatorKey ( data ) ;
276+ const signerAccount = yield * getAppOrConnectIdentity ( {
277+ accountAddress : data . accountAddress ,
278+ signaturePublicKey : signer ,
279+ } ) . pipe ( Effect . mapError ( ( ) => new AuthorizationError ( { message : 'Invalid signature' } ) ) ) ;
280+
281+ if ( signerAccount . accountAddress !== accountAddress ) {
282+ return yield * Effect . fail ( new AuthorizationError ( { message : 'Invalid signature' } ) ) ;
283+ }
284+
285+ // Create the inbox (will throw an error if it already exists)
286+ const inbox = yield * use ( ( client ) =>
287+ client . accountInbox . create ( {
288+ data : {
289+ id : inboxId ,
290+ isPublic,
291+ authPolicy,
292+ encryptionPublicKey,
293+ signatureHex : signature . hex ,
294+ signatureRecovery : signature . recovery ,
295+ account : { connect : { address : accountAddress } } ,
296+ } ,
297+ } ) ,
298+ ) ;
299+
300+ return {
301+ inboxId : inbox . id ,
302+ accountAddress,
303+ isPublic : inbox . isPublic ,
304+ authPolicy : inbox . authPolicy as Inboxes . InboxSenderAuthPolicy ,
305+ encryptionPublicKey : inbox . encryptionPublicKey ,
306+ signature : {
307+ hex : inbox . signatureHex ,
308+ recovery : inbox . signatureRecovery ,
309+ } ,
310+ } ;
311+ } ) ;
312+
313+ const getLatestAccountInboxMessages = Effect . fn ( 'getLatestAccountInboxMessages' ) ( function * ( {
314+ inboxId,
315+ since,
316+ } : {
317+ inboxId : string ;
318+ since : Date ;
319+ } ) {
320+ const messages = yield * use ( ( client ) =>
321+ client . accountInboxMessage . findMany ( {
322+ where : {
323+ accountInboxId : inboxId ,
324+ createdAt : {
325+ gte : since ,
326+ } ,
327+ } ,
328+ orderBy : {
329+ createdAt : 'asc' ,
330+ } ,
331+ } ) ,
332+ ) ;
333+
334+ return messages . map (
335+ ( msg ) : Messages . InboxMessage => ( {
336+ id : msg . id ,
337+ ciphertext : msg . ciphertext ,
338+ signature :
339+ msg . signatureHex != null && msg . signatureRecovery != null
340+ ? {
341+ hex : msg . signatureHex ,
342+ recovery : msg . signatureRecovery ,
343+ }
344+ : undefined ,
345+ authorAccountAddress : msg . authorAccountAddress ?? undefined ,
346+ createdAt : msg . createdAt ,
347+ } ) ,
348+ ) ;
349+ } ) ;
350+
351+ const listAccountInboxes = Effect . fn ( 'listAccountInboxes' ) ( function * ( {
352+ accountAddress,
353+ } : {
354+ accountAddress : string ;
355+ } ) {
356+ const inboxes = yield * use ( ( client ) =>
357+ client . accountInbox . findMany ( {
358+ where : { accountAddress } ,
359+ select : {
360+ id : true ,
361+ isPublic : true ,
362+ authPolicy : true ,
363+ encryptionPublicKey : true ,
364+ account : {
365+ select : {
366+ address : true ,
367+ } ,
368+ } ,
369+ signatureHex : true ,
370+ signatureRecovery : true ,
371+ } ,
372+ } ) ,
373+ ) ;
374+
375+ return inboxes . map (
376+ ( inbox ) : Messages . AccountInbox => ( {
377+ inboxId : inbox . id ,
378+ accountAddress : inbox . account . address ,
379+ isPublic : inbox . isPublic ,
380+ authPolicy : inbox . authPolicy as Inboxes . InboxSenderAuthPolicy ,
381+ encryptionPublicKey : inbox . encryptionPublicKey ,
382+ signature : {
383+ hex : inbox . signatureHex ,
384+ recovery : inbox . signatureRecovery ,
385+ } ,
386+ } ) ,
387+ ) ;
388+ } ) ;
389+
261390 return {
262391 listPublicAccountInboxes,
263392 getAccountInbox,
264393 postAccountInboxMessage,
394+ createAccountInbox,
395+ getLatestAccountInboxMessages,
396+ listAccountInboxes,
265397 } as const ;
266398} ) . pipe ( Layer . effect ( AccountInboxService ) , Layer . provide ( DatabaseService . layer ) , Layer . provide ( IdentityService . layer ) ) ;
0 commit comments