import { SpaceUser } from '@spacehq/users' ; import { tryParsePublicKey } from '@spacehq/utils' ; import { Users , UserAuth , UserMessage , PrivateKey , MailboxEvent } from '@textile/hub' ; import { grpc } from '@improbable-eng/grpc-web' ; import ee from 'event-emitter' ; export interface MailboxConfig { textileHubAddress ? : string ; usersInit ? : ( auth : UserAuth ) => Users ; } export interface DecryptedUserMessage extends UserMessage { decryptedBody : Uint8Array ; } const DefaultTextileHubAddress = 'https://webapi.hub.textile.io' ; example export class Mailbox { private listener ? : grpc . Request ; private emitters : ee . Emitter [ ] ; private constructor ( private readonly user , private readonly config = { } ) { this . config . textileHubAddress = config . textileHubAddress ?? DefaultTextileHubAddress ; this . emitters = [ ] ; } example public static async createMailbox ( user , config = { } , parser ) { const mb = new Mailbox ( user , config ) ; const mid = await mb . getUsersClient ( ) . setupMailbox ( ) ; const callback = ( reply ? , err ? ) => { if ( ! reply || ! reply . message ) return ; mb . emitters . forEach ( async ( emitter ) => { if ( reply . message ) { const dec = await mb . messageDecoder ( mb . user , reply . message ) ; const parsed = await parser ( dec ) ; emitter . emit ( 'data' , { notification : parsed } ) ; } } ) ; } ; mb . listener = await mb . getUsersClient ( ) . watchInbox ( mid , callback ) ; return mb ; } public subscribe ( emitter ) { this . emitters . push ( emitter ) ; } example public async listInboxMessages ( seek ? , limit ? ) { const res = await this . getUsersClient ( ) . listInboxMessages ( { seek , limit , } ) ; const inbox = [ ] ; for ( const msg of res ) { const decryptedMsg = await this . messageDecoder ( this . user , msg ) ; inbox . push ( decryptedMsg ) ; } return inbox ; } example public async sendMessage ( to , body ) { const toKey = tryParsePublicKey ( to ) ; const res = await this . getUsersClient ( ) . sendMessage ( this . user . identity , toKey , body ) ; return res ; } param id public async deleteMessage ( id ) { await this . getUsersClient ( ) . deleteInboxMessage ( id ) ; } private getUserAuth ( ) { if ( this . user . storageAuth === undefined ) { throw new Error ( 'Authentication Error' ) ; } return this . user . storageAuth ; } private getUsersClient ( ) { return this . initUsers ( this . getUserAuth ( ) ) ; } private initUsers ( userAuth ) { if ( this . config ?. usersInit ) { return this . config . usersInit ( userAuth ) ; } return Users . withUserAuth ( userAuth , { host : this . config ?. textileHubAddress } ) ; } /**
     * Decrypts a user's inbox messages using their PrivateKey
     */ messageDecoder = async ( user , message ) : Promise < DecryptedUserMessage > => { const identity = new PrivateKey ( user . identity . privKey . slice ( 0 , 32 ) ) ; const decryptedBody = await identity . decrypt ( message . body ) ; return { decryptedBody , ... message } ; } ; }