From 88761f85c4637391dd035fff8680cc919cfa52f7 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Tue, 31 Oct 2023 11:20:29 -0500 Subject: [PATCH 1/3] fix: convert static methods to instance methods --- src/Contacts.ts | 70 ++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/src/Contacts.ts b/src/Contacts.ts index fa368afbf..ea0444864 100644 --- a/src/Contacts.ts +++ b/src/Contacts.ts @@ -34,11 +34,13 @@ export class ConsentListEntry { } export class ConsentList { + client: Client entries: Map - static _identifier: string + private _identifier: string | undefined - constructor() { + constructor(client: Client) { this.entries = new Map() + this.client = client } allow(address: string) { @@ -58,21 +60,25 @@ export class ConsentList { return this.entries.get(entry.key) ?? 'unknown' } - static async getIdentifier(client: Client): Promise { + async getIdentifier(): Promise { if (!this._identifier) { const { identifier } = - await client.keystore.getPrivatePreferencesTopicIdentifier() + await this.client.keystore.getPrivatePreferencesTopicIdentifier() this._identifier = identifier } return this._identifier } - static async load(client: Client, startTime?: Date): Promise { - const consentList = new ConsentList() - const identifier = await this.getIdentifier(client) + async load(startTime?: Date) { + // no startTime, all entries will be fetched + if (!startTime) { + // clear existing entries + this.entries.clear() + } + const identifier = await this.getIdentifier() const contentTopic = buildUserPrivatePreferencesTopic(identifier) - const messages = await client.listEnvelopes( + const messages = await this.client.listEnvelopes( contentTopic, async ({ message }: EnvelopeWithMessage) => message, { @@ -81,7 +87,7 @@ export class ConsentList { ) // decrypt messages - const { responses } = await client.keystore.selfDecrypt({ + const { responses } = await this.client.keystore.selfDecrypt({ requests: messages.map((message) => ({ payload: message })), }) @@ -96,23 +102,23 @@ export class ConsentList { : result }, [] as privatePreferences.PrivatePreferencesAction[]) + // update consent list entries actions.forEach((action) => { action.allow?.walletAddresses.forEach((address) => { - consentList.allow(address) + this.allow(address) }) action.block?.walletAddresses.forEach((address) => { - consentList.block(address) + this.block(address) }) }) - - return consentList } - static async publish(entries: ConsentListEntry[], client: Client) { - const identifier = await this.getIdentifier(client) + async publish(entries: ConsentListEntry[]) { + const identifier = await this.getIdentifier() // encoded actions const actions = entries.reduce((result, entry) => { + // only handle address entries for now if (entry.entryType === 'address') { const action: privatePreferences.PrivatePreferencesAction = { allow: @@ -135,7 +141,7 @@ export class ConsentList { return result }, [] as Uint8Array[]) - const { responses } = await client.keystore.selfEncrypt({ + const { responses } = await this.client.keystore.selfEncrypt({ requests: actions.map((action) => ({ payload: action })), }) @@ -156,7 +162,7 @@ export class ConsentList { timestamp, })) - await client.publishEnvelopes(envelopes) + await this.client.publishEnvelopes(envelopes) } } @@ -165,17 +171,29 @@ export class Contacts { * Addresses that the client has connected to */ addresses: Set - private consentList: ConsentList + /** + * XMTP client + */ client: Client + /** + * The last time the consent list was synced + */ + lastSyncedAt?: Date + private consentList: ConsentList constructor(client: Client) { this.addresses = new Set() - this.consentList = new ConsentList() + this.consentList = new ConsentList(client) this.client = client } - async refreshConsentList(startTime?: Date) { - this.consentList = await ConsentList.load(this.client, startTime) + async loadConsentList(startTime?: Date) { + this.lastSyncedAt = new Date() + await this.consentList.load(startTime) + } + + async refreshConsentList() { + await this.loadConsentList() } isAllowed(address: string) { @@ -191,16 +209,14 @@ export class Contacts { } async allow(addresses: string[]) { - await ConsentList.publish( - addresses.map((address) => this.consentList.allow(address)), - this.client + await this.consentList.publish( + addresses.map((address) => this.consentList.allow(address)) ) } async block(addresses: string[]) { - await ConsentList.publish( - addresses.map((address) => this.consentList.block(address)), - this.client + await this.consentList.publish( + addresses.map((address) => this.consentList.block(address)) ) } } From e86ac72b0521cd5d7ba865a6f213d44909b74e35 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Tue, 31 Oct 2023 12:33:01 -0500 Subject: [PATCH 2/3] fix: update consent list entries after publish --- src/Contacts.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Contacts.ts b/src/Contacts.ts index ea0444864..e7ecdf1b3 100644 --- a/src/Contacts.ts +++ b/src/Contacts.ts @@ -162,7 +162,13 @@ export class ConsentList { timestamp, })) + // publish entries await this.client.publishEnvelopes(envelopes) + + // update local entries after publishing + entries.forEach((entry) => { + this.entries.set(entry.key, entry.permissionType) + }) } } @@ -210,13 +216,17 @@ export class Contacts { async allow(addresses: string[]) { await this.consentList.publish( - addresses.map((address) => this.consentList.allow(address)) + addresses.map((address) => + ConsentListEntry.fromAddress(address, 'allowed') + ) ) } async block(addresses: string[]) { await this.consentList.publish( - addresses.map((address) => this.consentList.block(address)) + addresses.map((address) => + ConsentListEntry.fromAddress(address, 'blocked') + ) ) } } From ff1f8901df6ff4490d667353a19d9595d13d7702 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Tue, 31 Oct 2023 12:45:24 -0500 Subject: [PATCH 3/3] fix: wait for contact allow before return convo --- src/conversations/Conversations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conversations/Conversations.ts b/src/conversations/Conversations.ts index f0320dd13..9c2d1578b 100644 --- a/src/conversations/Conversations.ts +++ b/src/conversations/Conversations.ts @@ -568,7 +568,7 @@ export default class Conversations { ]) // add peer address to allow list - this.client.contacts.allow([peerAddress]) + await this.client.contacts.allow([peerAddress]) return this.conversationReferenceToV2(conversation) }