Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: consent proofs #599

Merged
merged 8 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 41 additions & 17 deletions src/Contacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,15 @@ export class Contacts {
timestampMs: number,
peerAddress: string
): Promise<boolean> {
alexrisch marked this conversation as resolved.
Show resolved Hide resolved
if (!signature || !timestampMs) {
return false
}
if (timestampMs > Date.now()) {
return false
}
if (timestampMs < Date.now() - 1000 * 60 * 60 * 24 * 30) {
return false
}
rygine marked this conversation as resolved.
Show resolved Hide resolved
const signatureData = splitSignature(signature)
const message = WalletSigner.consentProofRequestText(
peerAddress,
Expand All @@ -271,20 +280,28 @@ export class Contacts {
return publicKey?.getEthereumAddress() === this.client.address
}
rygine marked this conversation as resolved.
Show resolved Hide resolved

private async handleConsentProof(
consentProof: invitation.ConsentProofPayload,
peerAddress: string
): Promise<void> {
const { signature, timestamp } = consentProof
const isValid = await this.validateConsentSignature(
signature as `0x${string}`,
Number(timestamp),
peerAddress
private async handleConsentProofs(
consentProofs: {
consentProof: invitation.ConsentProofPayload
peerAddress: string
}[]
) {
const validConsentProofAddresses: string[] = []
const validationResults = await Promise.allSettled(
consentProofs.map((proofItem) => {
return this.validateConsentSignature(
proofItem.consentProof.signature as `0x${string}`,
Number(proofItem.consentProof.timestamp),
proofItem.peerAddress
)
})
)
if (!isValid) {
return
}
await this.client.contacts.allow([peerAddress])
validationResults.forEach((result, index) => {
if (result.status === 'fulfilled' && result.value) {
validConsentProofAddresses.push(consentProofs[index].peerAddress)
}
})
alexrisch marked this conversation as resolved.
Show resolved Hide resolved
this.client.contacts.allow(validConsentProofAddresses)
}

async loadConsentList(startTime?: Date) {
Expand All @@ -293,17 +310,24 @@ export class Contacts {
const entries = await this.consentList.load(startTime ?? lastRun)
try {
const conversations = await this.client.conversations.list()
const consentProofs: {
consentProof: invitation.ConsentProofPayload
peerAddress: string
}[] = []
conversations.forEach((conversation) => {
if (
conversation.consentProof &&
this.consentState(conversation.peerAddress) === 'unknown'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. It'll always have the current value from the network because this.consentList.load(...) mutates this.consentList as it goes, right?

) {
this.handleConsentProof(
conversation.consentProof,
conversation.peerAddress
)
consentProofs.push({
consentProof: conversation.consentProof,
peerAddress: conversation.peerAddress,
})
}
alexrisch marked this conversation as resolved.
Show resolved Hide resolved
})
if (consentProofs.length) {
this.handleConsentProofs(consentProofs)
}
} catch (err) {
console.log(err)
}
Expand Down
7 changes: 0 additions & 7 deletions test/Contacts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,6 @@ describe('Contacts', () => {
expect(convo).toBeTruthy()
const isApproved = await convo?.isAllowed
expect(isApproved).toBe(true)
await alix.close()
await bo.close()
})

it('consent proof yields to network consent', async () => {
Expand All @@ -237,7 +235,6 @@ describe('Contacts', () => {
env: 'local',
})
alix1.contacts.deny([bo.address])
await alix1.close()
const alix2 = await Client.create(wallet, {
env: 'local',
})
Expand All @@ -264,8 +261,6 @@ describe('Contacts', () => {
await alix2.contacts.refreshConsentList()
const isDenied = await alix2.contacts.isDenied(bo.address)
expect(isDenied).toBeTruthy()
await alix2.close()
await bo.close()
})

it('consent proof correctly validates', async () => {
Expand Down Expand Up @@ -299,8 +294,6 @@ describe('Contacts', () => {
await alix.contacts.refreshConsentList()
const isAllowed = await alix.contacts.isAllowed(bo.address)
expect(isAllowed).toBeFalsy()
await alix.close()
await bo.close()
})
})
})
Loading