@@ -33,9 +33,11 @@ import type {
3333 GetMessageOptions ,
3434 GetMessagesOptions ,
3535 GetMessagesResult ,
36+ RecoverMessagesOptions ,
3637 SendMessageOptions ,
3738 SubscribeOptions ,
3839} from './messaging-types.js' ;
40+ import type { RecoveryTransport } from './recovery/transport.js' ;
3941import type {
4042 ArchiveGroupOptions ,
4143 CreateGroupOptions ,
@@ -91,6 +93,7 @@ export function messagingGroups<
9193 suinsConfig,
9294 relayer,
9395 attachments,
96+ recovery,
9497} : {
9598 name ?: Name ;
9699 /** Name under which the PermissionedGroupsClient extension is registered (default: 'groups'). */
@@ -105,6 +108,8 @@ export function messagingGroups<
105108 relayer : RelayerConfig ;
106109 /** Attachment support. When omitted, messages cannot include files. */
107110 attachments ?: MessagingGroupsClientOptions < TApproveContext > [ 'attachments' ] ;
111+ /** Optional recovery transport for fetching messages from an alternative storage backend. */
112+ recovery ?: RecoveryTransport ;
108113} ) {
109114 return {
110115 name,
@@ -118,6 +123,7 @@ export function messagingGroups<
118123 encryption,
119124 relayer,
120125 attachments,
126+ recovery,
121127 } ) ;
122128 } ,
123129 } ;
@@ -157,6 +163,7 @@ export class MessagingGroupsClient<TApproveContext = void> {
157163 #packageConfig: MessagingGroupsPackageConfig ;
158164 #client: ClientWithCoreApi ;
159165 #attachments: AttachmentsManager < TApproveContext > | undefined ;
166+ #recovery: RecoveryTransport | undefined ;
160167 readonly #textEncoder = new TextEncoder ( ) ;
161168 readonly #textDecoder = new TextDecoder ( ) ;
162169
@@ -247,6 +254,8 @@ export class MessagingGroupsClient<TApproveContext = void> {
247254 timeout : options . relayer . timeout ,
248255 onError : options . relayer . onError ,
249256 } ) ;
257+
258+ this . #recovery = options . recovery ;
250259 }
251260
252261 // === Private Helpers ===
@@ -523,6 +532,51 @@ export class MessagingGroupsClient<TApproveContext = void> {
523532 this . transport . disconnect ( ) ;
524533 }
525534
535+ // === Recovery ===
536+
537+ /**
538+ * Fetch and decrypt messages from the recovery transport.
539+ *
540+ * Requires a `recovery` transport to be configured at client creation.
541+ * Recovery is read-only and does not require a signer.
542+ *
543+ * @throws {MessagingGroupsClientError } if no recovery transport is configured.
544+ */
545+ async recoverMessages (
546+ options : RecoverMessagesOptions < TApproveContext > ,
547+ ) : Promise < GetMessagesResult > {
548+ if ( ! this . #recovery) {
549+ throw new MessagingGroupsClientError (
550+ 'Recovery transport is not configured. Provide `recovery` when creating the messaging groups client.' ,
551+ ) ;
552+ }
553+
554+ const { groupId, encryptionHistoryId } = this . derive . resolveGroupRef ( options . groupRef ) ;
555+ const approveContext = this . #approveContextSpread( options ) ;
556+
557+ const result = await this . #recovery. recoverMessages ( {
558+ groupId,
559+ afterOrder : options . afterOrder ,
560+ beforeOrder : options . beforeOrder ,
561+ limit : options . limit ,
562+ } ) ;
563+
564+ const settled = await Promise . allSettled (
565+ result . messages . map ( ( raw ) =>
566+ this . #decryptMessage( raw , { groupId, encryptionHistoryId } , approveContext ) ,
567+ ) ,
568+ ) ;
569+
570+ const messages : DecryptedMessage [ ] = [ ] ;
571+ for ( const entry of settled ) {
572+ if ( entry . status === 'fulfilled' ) {
573+ messages . push ( entry . value ) ;
574+ }
575+ }
576+
577+ return { messages, hasNext : result . hasNext } ;
578+ }
579+
526580 // === Private: sealApproveContext ===
527581
528582 /**
@@ -693,7 +747,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
693747 * Returns a tuple of (PermissionedGroup<Messaging>, EncryptionHistory).
694748 * The objects are NOT shared - use createAndShareGroup for shared groups.
695749 */
696- async createGroup ( { signer, transaction, ...callOptions } : CreateGroupOptions & { transaction ?: Transaction } ) {
750+ async createGroup ( {
751+ signer,
752+ transaction,
753+ ...callOptions
754+ } : CreateGroupOptions & { transaction ?: Transaction } ) {
697755 return this . #executeTransaction(
698756 this . tx . createGroup ( { transaction, ...callOptions } ) ,
699757 signer ,
@@ -705,7 +763,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
705763 * Creates a new messaging group and shares both objects.
706764 * The transaction sender automatically becomes the creator with all permissions.
707765 */
708- async createAndShareGroup ( { signer, transaction, ...callOptions } : CreateGroupOptions & { transaction ?: Transaction } ) {
766+ async createAndShareGroup ( {
767+ signer,
768+ transaction,
769+ ...callOptions
770+ } : CreateGroupOptions & { transaction ?: Transaction } ) {
709771 return this . #executeTransaction(
710772 this . tx . createAndShareGroup ( { transaction, ...callOptions } ) ,
711773 signer ,
@@ -717,7 +779,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
717779 * Rotates the encryption key for a group.
718780 * Requires EncryptionKeyRotator permission.
719781 */
720- async rotateEncryptionKey ( { signer, transaction, ...callOptions } : RotateEncryptionKeyOptions & { transaction ?: Transaction } ) {
782+ async rotateEncryptionKey ( {
783+ signer,
784+ transaction,
785+ ...callOptions
786+ } : RotateEncryptionKeyOptions & { transaction ?: Transaction } ) {
721787 return this . #executeTransaction(
722788 this . tx . rotateEncryptionKey ( { transaction, ...callOptions } ) ,
723789 signer ,
@@ -729,7 +795,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
729795 * Atomically removes one or more members and rotates the encryption key.
730796 * Ensures removed members cannot decrypt new messages.
731797 */
732- async removeMembersAndRotateKey ( { signer, transaction, ...callOptions } : RemoveMembersAndRotateKeyOptions & { transaction ?: Transaction } ) {
798+ async removeMembersAndRotateKey ( {
799+ signer,
800+ transaction,
801+ ...callOptions
802+ } : RemoveMembersAndRotateKeyOptions & { transaction ?: Transaction } ) {
733803 return this . #executeTransaction(
734804 this . tx . removeMembersAndRotateKey ( { transaction, ...callOptions } ) ,
735805 signer ,
@@ -740,7 +810,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
740810 /**
741811 * Removes the transaction sender from a messaging group.
742812 */
743- async leave ( { signer, transaction, ...callOptions } : LeaveOptions & { transaction ?: Transaction } ) {
813+ async leave ( {
814+ signer,
815+ transaction,
816+ ...callOptions
817+ } : LeaveOptions & { transaction ?: Transaction } ) {
744818 return this . #executeTransaction(
745819 this . tx . leave ( { transaction, ...callOptions } ) ,
746820 signer ,
@@ -756,7 +830,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
756830 *
757831 * After this call the group is paused and cannot be mutated.
758832 */
759- async archiveGroup ( { signer, transaction, ...callOptions } : ArchiveGroupOptions & { transaction ?: Transaction } ) {
833+ async archiveGroup ( {
834+ signer,
835+ transaction,
836+ ...callOptions
837+ } : ArchiveGroupOptions & { transaction ?: Transaction } ) {
760838 return this . #executeTransaction(
761839 this . tx . archiveGroup ( { transaction, ...callOptions } ) ,
762840 signer ,
@@ -770,7 +848,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
770848 * Sets the group name.
771849 * Requires `MetadataAdmin` permission.
772850 */
773- async setGroupName ( { signer, transaction, ...callOptions } : SetGroupNameOptions & { transaction ?: Transaction } ) {
851+ async setGroupName ( {
852+ signer,
853+ transaction,
854+ ...callOptions
855+ } : SetGroupNameOptions & { transaction ?: Transaction } ) {
774856 return this . #executeTransaction(
775857 this . tx . setGroupName ( { transaction, ...callOptions } ) ,
776858 signer ,
@@ -782,7 +864,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
782864 * Inserts a key-value pair into the group's metadata data map.
783865 * Requires `MetadataAdmin` permission.
784866 */
785- async insertGroupData ( { signer, transaction, ...callOptions } : InsertGroupDataOptions & { transaction ?: Transaction } ) {
867+ async insertGroupData ( {
868+ signer,
869+ transaction,
870+ ...callOptions
871+ } : InsertGroupDataOptions & { transaction ?: Transaction } ) {
786872 return this . #executeTransaction(
787873 this . tx . insertGroupData ( { transaction, ...callOptions } ) ,
788874 signer ,
@@ -794,7 +880,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
794880 * Removes a key-value pair from the group's metadata data map.
795881 * Requires `MetadataAdmin` permission.
796882 */
797- async removeGroupData ( { signer, transaction, ...callOptions } : RemoveGroupDataOptions & { transaction ?: Transaction } ) {
883+ async removeGroupData ( {
884+ signer,
885+ transaction,
886+ ...callOptions
887+ } : RemoveGroupDataOptions & { transaction ?: Transaction } ) {
798888 return this . #executeTransaction(
799889 this . tx . removeGroupData ( { transaction, ...callOptions } ) ,
800890 signer ,
@@ -808,7 +898,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
808898 * Sets a SuiNS reverse lookup on a messaging group.
809899 * Requires `ExtensionPermissionsAdmin` permission on the group.
810900 */
811- async setSuinsReverseLookup ( { signer, transaction, ...callOptions } : SetSuinsReverseLookupOptions & { transaction ?: Transaction } ) {
901+ async setSuinsReverseLookup ( {
902+ signer,
903+ transaction,
904+ ...callOptions
905+ } : SetSuinsReverseLookupOptions & { transaction ?: Transaction } ) {
812906 return this . #executeTransaction(
813907 this . tx . setSuinsReverseLookup ( { transaction, ...callOptions } ) ,
814908 signer ,
@@ -820,7 +914,11 @@ export class MessagingGroupsClient<TApproveContext = void> {
820914 * Unsets a SuiNS reverse lookup on a messaging group.
821915 * Requires `ExtensionPermissionsAdmin` permission on the group.
822916 */
823- async unsetSuinsReverseLookup ( { signer, transaction, ...callOptions } : UnsetSuinsReverseLookupOptions & { transaction ?: Transaction } ) {
917+ async unsetSuinsReverseLookup ( {
918+ signer,
919+ transaction,
920+ ...callOptions
921+ } : UnsetSuinsReverseLookupOptions & { transaction ?: Transaction } ) {
824922 return this . #executeTransaction(
825923 this . tx . unsetSuinsReverseLookup ( { transaction, ...callOptions } ) ,
826924 signer ,
0 commit comments