Skip to content

Commit 7b00404

Browse files
authored
Merge pull request #384 from bsv-blockchain/feature/certificate-revocation
Feature/certificate revocation
2 parents cbb5b6a + e9e915b commit 7b00404

File tree

7 files changed

+199
-115
lines changed

7 files changed

+199
-115
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. The format
55
## Table of Contents
66

77
- [Unreleased](#unreleased)
8+
- [1.9.5 - 2025-11-13](#195---2025-11-13)
89
- [1.9.3 - 2025-11-11](#193---2025-11-11)
910
- [1.9.2 - 2025-11-11](#192---2025-11-11)
1011
- [1.9.1 - 2025-11-10](#191---2025-11-10)
@@ -177,6 +178,14 @@ All notable changes to this project will be documented in this file. The format
177178

178179
---
179180

181+
### [1.9.5] - 2025-11-13
182+
183+
### Added
184+
185+
- Added support for revoking certificate revelation.
186+
187+
---
188+
180189
### [1.9.3] - 2025-11-11
181190

182191
### Added

docs/reference/identity.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
6161

6262
```ts
6363
export class ContactsManager {
64-
constructor(wallet?: WalletInterface)
64+
constructor(wallet?: WalletInterface, originator?: string)
6565
async getContacts(identityKey?: PubKeyHex, forceRefresh = false, limit = 1000): Promise<Contact[]>
6666
async saveContact(contact: DisplayableIdentity, metadata?: Record<string, any>): Promise<void>
6767
async removeContact(identityKey: string): Promise<void>
@@ -134,20 +134,18 @@ export class IdentityClient {
134134
async publiclyRevealAttributes(certificate: WalletCertificate, fieldsToReveal: CertificateFieldNameUnder50Bytes[]): Promise<BroadcastResponse | BroadcastFailure>
135135
async resolveByIdentityKey(args: DiscoverByIdentityKeyArgs, overrideWithContacts = true): Promise<DisplayableIdentity[]>
136136
async resolveByAttributes(args: DiscoverByAttributesArgs, overrideWithContacts = true): Promise<DisplayableIdentity[]>
137+
async revokeCertificateRevelation(serialNumber: Base64String): Promise<BroadcastResponse | BroadcastFailure>
137138
public async getContacts(identityKey?: PubKeyHex, forceRefresh = false, limit = 1000): Promise<Contact[]>
138139
public async saveContact(contact: DisplayableIdentity, metadata?: Record<string, any>): Promise<void>
139140
public async removeContact(identityKey: PubKeyHex): Promise<void>
140141
static parseIdentity(identityToParse: IdentityCertificate): DisplayableIdentity
141142
}
142143
```
143144

144-
See also: [BroadcastFailure](./transaction.md#interface-broadcastfailure), [BroadcastResponse](./transaction.md#interface-broadcastresponse), [CertificateFieldNameUnder50Bytes](./wallet.md#type-certificatefieldnameunder50bytes), [Contact](./identity.md#type-contact), [DEFAULT_IDENTITY_CLIENT_OPTIONS](./identity.md#variable-default_identity_client_options), [DiscoverByAttributesArgs](./wallet.md#interface-discoverbyattributesargs), [DiscoverByIdentityKeyArgs](./wallet.md#interface-discoverbyidentitykeyargs), [DisplayableIdentity](./identity.md#interface-displayableidentity), [IdentityCertificate](./wallet.md#interface-identitycertificate), [OriginatorDomainNameStringUnder250Bytes](./wallet.md#type-originatordomainnamestringunder250bytes), [PubKeyHex](./wallet.md#type-pubkeyhex), [WalletCertificate](./wallet.md#interface-walletcertificate), [WalletInterface](./wallet.md#interface-walletinterface)
145+
See also: [Base64String](./wallet.md#type-base64string), [BroadcastFailure](./transaction.md#interface-broadcastfailure), [BroadcastResponse](./transaction.md#interface-broadcastresponse), [CertificateFieldNameUnder50Bytes](./wallet.md#type-certificatefieldnameunder50bytes), [Contact](./identity.md#type-contact), [DEFAULT_IDENTITY_CLIENT_OPTIONS](./identity.md#variable-default_identity_client_options), [DiscoverByAttributesArgs](./wallet.md#interface-discoverbyattributesargs), [DiscoverByIdentityKeyArgs](./wallet.md#interface-discoverbyidentitykeyargs), [DisplayableIdentity](./identity.md#interface-displayableidentity), [IdentityCertificate](./wallet.md#interface-identitycertificate), [OriginatorDomainNameStringUnder250Bytes](./wallet.md#type-originatordomainnamestringunder250bytes), [PubKeyHex](./wallet.md#type-pubkeyhex), [WalletCertificate](./wallet.md#interface-walletcertificate), [WalletInterface](./wallet.md#interface-walletinterface)
145146

146147
#### Method getContacts
147148

148-
TODO: Implement once revocation overlay is created
149-
Remove public certificate revelation from overlay services by spending the identity token
150-
151149
Load all records from the contacts basket
152150

153151
```ts
@@ -161,8 +159,6 @@ A promise that resolves with an array of contacts
161159

162160
Argument Details
163161

164-
+ **serialNumber**
165-
+ Unique serial number of the certificate to revoke revelation
166162
+ **identityKey**
167163
+ Optional specific identity key to fetch
168164
+ **forceRefresh**
@@ -267,6 +263,20 @@ Argument Details
267263
+ **overrideWithContacts**
268264
+ Whether to override the results with personal contacts if available.
269265

266+
#### Method revokeCertificateRevelation
267+
268+
Remove public certificate revelation from overlay services by spending the identity token
269+
270+
```ts
271+
async revokeCertificateRevelation(serialNumber: Base64String): Promise<BroadcastResponse | BroadcastFailure>
272+
```
273+
See also: [Base64String](./wallet.md#type-base64string), [BroadcastFailure](./transaction.md#interface-broadcastfailure), [BroadcastResponse](./transaction.md#interface-broadcastresponse)
274+
275+
Argument Details
276+
277+
+ **serialNumber**
278+
+ Unique serial number of the certificate to revoke revelation
279+
270280
#### Method saveContact
271281

272282
Save or update a Metanet contact

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bsv/sdk",
3-
"version": "1.9.4",
3+
"version": "1.9.5",
44
"type": "module",
55
"description": "BSV Blockchain Software Development Kit",
66
"main": "dist/cjs/mod.js",

src/identity/ContactsManager.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ export class ContactsManager {
3232
private readonly wallet: WalletInterface
3333
private readonly cache = new MemoryCache()
3434
private readonly CONTACTS_CACHE_KEY = 'metanet-contacts'
35+
private readonly originator?: string
3536

36-
constructor (wallet?: WalletInterface) {
37+
constructor (wallet?: WalletInterface, originator?: string) {
3738
this.wallet = wallet ?? new WalletClient()
39+
this.originator = originator
3840
}
3941

4042
/**
@@ -68,7 +70,7 @@ export class ContactsManager {
6870
keyID: identityKey,
6971
counterparty: 'self',
7072
data: Utils.toArray(identityKey, 'utf8')
71-
})
73+
}, this.originator)
7274
tags.push(`identityKey ${Utils.toHex(hashedIdentityKey)}`)
7375
}
7476

@@ -79,7 +81,7 @@ export class ContactsManager {
7981
includeCustomInstructions: true,
8082
tags,
8183
limit
82-
})
84+
}, this.originator)
8385

8486
if (outputs.outputs == null || outputs.outputs.length === 0) {
8587
this.cache.setItem(this.CONTACTS_CACHE_KEY, JSON.stringify([]))
@@ -104,7 +106,7 @@ export class ContactsManager {
104106
protocolID: CONTACT_PROTOCOL_ID,
105107
keyID,
106108
counterparty: 'self'
107-
})
109+
}, this.originator)
108110

109111
// Parse the contact data
110112
const contactData: Contact = JSON.parse(Utils.toUTF8(plaintext))
@@ -157,7 +159,7 @@ export class ContactsManager {
157159
keyID: contact.identityKey,
158160
counterparty: 'self',
159161
data: Utils.toArray(contact.identityKey, 'utf8')
160-
})
162+
}, this.originator)
161163

162164
// Check if this contact already exists (to update it)
163165
const outputs = await this.wallet.listOutputs({
@@ -166,7 +168,7 @@ export class ContactsManager {
166168
includeCustomInstructions: true,
167169
tags: [`identityKey ${Utils.toHex(hashedIdentityKey)}`],
168170
limit: 100 // Should only be one contact!
169-
})
171+
}, this.originator)
170172

171173
let existingOutput: any = null
172174
let keyID = Utils.toBase64(Random(32))
@@ -185,7 +187,7 @@ export class ContactsManager {
185187
protocolID: CONTACT_PROTOCOL_ID,
186188
keyID,
187189
counterparty: 'self'
188-
})
190+
}, this.originator)
189191

190192
const storedContact: Contact = JSON.parse(Utils.toUTF8(plaintext))
191193
if (storedContact.identityKey === contact.identityKey) {
@@ -209,7 +211,7 @@ export class ContactsManager {
209211
protocolID: CONTACT_PROTOCOL_ID,
210212
keyID,
211213
counterparty: 'self'
212-
})
214+
}, this.originator)
213215

214216
// Create locking script for the new contact token
215217
const lockingScript = await new PushDrop(this.wallet).lock(
@@ -242,7 +244,7 @@ export class ContactsManager {
242244
customInstructions: JSON.stringify({ keyID })
243245
}],
244246
options: { acceptDelayedBroadcast: false, randomizeOutputs: false } // TODO: Support custom config as needed.
245-
})
247+
}, this.originator)
246248

247249
if (signableTransaction == null) throw new Error('Unable to update contact')
248250

@@ -255,7 +257,7 @@ export class ContactsManager {
255257
const { tx } = await this.wallet.signAction({
256258
reference: signableTransaction.reference,
257259
spends: { 0: { unlockingScript: unlockingScript.toHex() } }
258-
})
260+
}, this.originator)
259261

260262
if (tx == null) throw new Error('Failed to update contact output')
261263
} else {
@@ -271,7 +273,7 @@ export class ContactsManager {
271273
customInstructions: JSON.stringify({ keyID })
272274
}],
273275
options: { acceptDelayedBroadcast: false, randomizeOutputs: false } // TODO: Support custom config as needed.
274-
})
276+
}, this.originator)
275277

276278
if (tx == null) throw new Error('Failed to create contact output')
277279
}
@@ -302,7 +304,7 @@ export class ContactsManager {
302304
keyID: identityKey,
303305
counterparty: 'self',
304306
data: Utils.toArray(identityKey, 'utf8')
305-
})
307+
}, this.originator)
306308
tags.push(`identityKey ${Utils.toHex(hashedIdentityKey)}`)
307309

308310
// Find and spend the contact's output
@@ -312,7 +314,7 @@ export class ContactsManager {
312314
includeCustomInstructions: true,
313315
tags,
314316
limit: 100 // Should only be one contact!
315-
})
317+
}, this.originator)
316318

317319
if (outputs.outputs == null) return
318320

@@ -330,7 +332,7 @@ export class ContactsManager {
330332
protocolID: CONTACT_PROTOCOL_ID,
331333
keyID,
332334
counterparty: 'self'
333-
})
335+
}, this.originator)
334336

335337
const storedContact: Contact = JSON.parse(Utils.toUTF8(plaintext))
336338
if (storedContact.identityKey === identityKey) {
@@ -348,7 +350,7 @@ export class ContactsManager {
348350
}],
349351
outputs: [], // No outputs = deletion
350352
options: { acceptDelayedBroadcast: false, randomizeOutputs: false } // TODO: Support custom config as needed.
351-
})
353+
}, this.originator)
352354

353355
if (signableTransaction == null) throw new Error('Unable to delete contact')
354356

@@ -361,7 +363,7 @@ export class ContactsManager {
361363
const { tx: deleteTx } = await this.wallet.signAction({
362364
reference: signableTransaction.reference,
363365
spends: { 0: { unlockingScript: unlockingScript.toHex() } }
364-
})
366+
}, this.originator)
365367

366368
if (deleteTx == null) throw new Error('Failed to delete contact output')
367369
return

0 commit comments

Comments
 (0)