libp2r2p 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,40 +44,87 @@ await messenger.tell({
44
44
 
45
45
  ### Deleting Private Broadcasts
46
46
 
47
- High-level private-message sends create one deletion capability for the whole
48
- logical message. The returned object keeps its normal result fields and adds
49
- `deletionPubkey` plus, when the library generated the key, `deletionSeckey`.
50
- All outer kind `3560` chunks for that send carry the public
51
- `['s', deletionPubkey]` tag.
47
+ By default, each high-level private-message send creates one fresh deletion
48
+ keypair for its logical message. Every outer kind `3560` event produced for that
49
+ send, including router chunks, recipient subsets, and nym carriers, carries the
50
+ same public key in its `s` tag. The result always contains `delivery.reports`.
51
+ When libp2r2p generated the keypair, it also contains
52
+ `delivery.deletionSeckey`; the public key can be derived from that secret.
53
+
54
+ This shared `s` value deliberately makes the outer events for one logical send
55
+ linkable to relay operators and other observers. Disable automatic capabilities
56
+ when that tradeoff is not acceptable. The messenger-wide setting defaults to
57
+ `true`, and a channel setting takes precedence:
52
58
 
53
- Pass a pre-generated `deletionPubkey` when the application needs to own and
54
- persist the secret before sending. In that case the result deliberately omits a
55
- secret it was not given:
59
+ ```js
60
+ const messenger = await createPrivateMessenger({
61
+ userSigner,
62
+ autoDeletionCapability: false,
63
+ channels: [{
64
+ signer: privateChannelSigner,
65
+ relays: ['wss://relay.example'],
66
+ autoDeletionCapability: true
67
+ }]
68
+ })
69
+ ```
70
+
71
+ With automatic capabilities disabled and no caller-supplied key, the outer
72
+ events have no `s` tag. They are not deliberately linkable through this
73
+ extension, but cannot later be deleted with it. A caller that already owns a
74
+ deletion key can supply its public key on an individual send; libp2r2p then
75
+ does not generate or return a key. Use a fresh caller-owned key for each
76
+ logical message unless cross-message linkability is intentional:
56
77
 
57
78
  ```js
58
79
  import { generateKeypair } from 'libp2r2p/key'
59
80
 
60
81
  const deletionKey = generateKeypair()
61
- const sent = await messenger.tell({
82
+ await messenger.tell({
62
83
  receiverPubkey,
63
84
  payload: { text: 'remove this later' },
64
85
  deletionPubkey: deletionKey.pubkey
65
86
  })
87
+ ```
88
+
89
+ ```js
90
+ import { finalizeEvent } from 'nostr-tools'
91
+ import { keypairFromSeckey } from 'libp2r2p/key'
92
+ import { relayPool } from 'libp2r2p/relay'
93
+
94
+ const sent = await messenger.tell({
95
+ receiverPubkey,
96
+ payload: { text: 'remove this later' }
97
+ })
66
98
 
67
- // Persist deletionKey.seckey with the application's copy of the message.
68
- console.log(sent.deletionPubkey)
99
+ if (sent.delivery.deletionSeckey) {
100
+ const deletionKey = keypairFromSeckey(sent.delivery.deletionSeckey)
101
+ // Persist this secret with the application's copy of the logical message.
102
+
103
+ const { result: outerEvents } = await relayPool.getEvents({
104
+ kinds: [3560],
105
+ authors: [channelPubkey],
106
+ '#s': [deletionKey.pubkey]
107
+ }, relays)
108
+ for (let offset = 0; offset < outerEvents.length; offset += 100) {
109
+ const deletion = finalizeEvent({
110
+ kind: 5,
111
+ created_at: Math.floor(Date.now() / 1000),
112
+ tags: [['k', '3560'], ...outerEvents.slice(offset, offset + 100).map(event => ['e', event.id])],
113
+ content: ''
114
+ }, deletionKey.secretKey)
115
+ await relayPool.sendEvent(deletion, relays)
116
+ }
117
+ }
69
118
  ```
70
119
 
71
- The `s` tag is public metadata, so it makes the outer chunks for one message
72
- linkable. It is a deletion capability, not the channel key or the sender's
73
- identity. libp2r2p does not automatically delete anything: an application can
74
- later find candidate outer events with a filter such as
75
- `{ kinds: [3560], authors: [channelPubkey], '#s': [deletionPubkey] }`, then
76
- sign a kind `5` deletion event with the matching secret key. Relay support for
77
- this capability is not universal. A relay that supports it SHOULD recognize
78
- only the explicit `k=3560` deletion form; a regular NIP-09 kind `5` event
79
- signed by the outer event's private-channel key MUST NOT delete a kind `3560`
80
- event, whether or not that event carries an `s` tag.
120
+ The `s` tag is public metadata and a deletion capability, not the channel key
121
+ or sender identity. libp2r2p does not delete anything automatically.
122
+
123
+ Relay support for this capability is not universal. A relay that implements it
124
+ should accept only a kind `5` request signed by the matching `s` key with exactly
125
+ one `['k', '3560']` tag, explicit matching `e` targets, and no `a` tags. A
126
+ regular NIP-09 kind `5` request signed by the outer event's private-channel key
127
+ must not delete a kind `3560` event, whether or not that event has an `s` tag.
81
128
 
82
129
  ### Temporary Send Storage
83
130
 
@@ -0,0 +1,193 @@
1
+ // Derived from https://github.com/ticlo/arrow-code/blob/master/src/base93.ts
2
+ // Apache-2.0. JSON-safe alphabet: space is included; double quote and
3
+ // backslash are intentionally excluded.
4
+
5
+ export const BASE93_ALPHABET =
6
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&'()*+,-./:;<=>?@[]^_`{|}~ "
7
+
8
+ const ENCODING_TABLE = (() => {
9
+ const out = new Uint16Array(93)
10
+ for (let i = 0; i < out.length; i++) out[i] = BASE93_ALPHABET.charCodeAt(i)
11
+ return out
12
+ })()
13
+
14
+ const DECODING_TABLE = (() => {
15
+ const out = new Int16Array(128)
16
+ out.fill(-1)
17
+ for (let i = 0; i < BASE93_ALPHABET.length; i++) out[BASE93_ALPHABET.charCodeAt(i)] = i
18
+ return out
19
+ })()
20
+
21
+ function codesToString (codes, length) {
22
+ const chunkLength = 16384
23
+ let result = ''
24
+ for (let i = 0; i < length; i += chunkLength) {
25
+ result += String.fromCharCode.apply(
26
+ null,
27
+ Array.prototype.slice.call(codes, i, Math.min(i + chunkLength, length))
28
+ )
29
+ }
30
+ return result
31
+ }
32
+
33
+ function asBytes (bytes) {
34
+ if (bytes instanceof Uint8Array) return bytes
35
+ if (ArrayBuffer.isView(bytes)) return new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength)
36
+ if (bytes instanceof ArrayBuffer) return new Uint8Array(bytes)
37
+ return Uint8Array.from(bytes)
38
+ }
39
+
40
+ export class Base93Encoder {
41
+ constructor (prefix = '') {
42
+ this.queuedBits = 0
43
+ this.bitCount = 0
44
+ this.parts = prefix ? [String(prefix)] : []
45
+ this.finished = false
46
+ }
47
+
48
+ update (bytes) {
49
+ if (this.finished) throw new Error('Base93 encoder is already finalized.')
50
+ const source = asBytes(bytes)
51
+ const output = new Uint16Array(Math.ceil(source.length * 8 / 6.5) + 4)
52
+ let position = 0
53
+ let queuedBits = this.queuedBits
54
+ let bitCount = this.bitCount
55
+
56
+ for (let i = 0; i < source.length; i++) {
57
+ queuedBits |= source[i] << bitCount
58
+ bitCount += 8
59
+ if (bitCount > 13) {
60
+ let value = queuedBits & 0x1fff
61
+ if (value > 456) {
62
+ queuedBits >>>= 13
63
+ bitCount -= 13
64
+ } else {
65
+ value = queuedBits & 0x3fff
66
+ queuedBits >>>= 14
67
+ bitCount -= 14
68
+ }
69
+ output[position++] = ENCODING_TABLE[value % 93]
70
+ output[position++] = ENCODING_TABLE[Math.floor(value / 93)]
71
+ }
72
+ }
73
+
74
+ this.queuedBits = queuedBits
75
+ this.bitCount = bitCount
76
+ if (position > 0) this.parts.push(codesToString(output, position))
77
+ return this
78
+ }
79
+
80
+ getEncoded () {
81
+ if (!this.finished) {
82
+ if (this.bitCount > 0) {
83
+ const output = new Uint16Array(2)
84
+ let position = 0
85
+ output[position++] = ENCODING_TABLE[this.queuedBits % 93]
86
+ if (this.bitCount > 7 || this.queuedBits > 92) {
87
+ output[position++] = ENCODING_TABLE[Math.floor(this.queuedBits / 93)]
88
+ }
89
+ this.parts.push(codesToString(output, position))
90
+ }
91
+ this.finished = true
92
+ this.queuedBits = 0
93
+ this.bitCount = 0
94
+ }
95
+ return this.parts.join('')
96
+ }
97
+ }
98
+
99
+ export function encode (bytes) {
100
+ return new Base93Encoder().update(bytes).getEncoded()
101
+ }
102
+
103
+ function decodeUnchecked (value) {
104
+ const output = new Uint8Array(Math.ceil(value.length * 7 / 8))
105
+ let queuedBits = 0
106
+ let bitCount = 0
107
+ let first = -1
108
+ let position = 0
109
+
110
+ for (let i = 0; i < value.length; i++) {
111
+ const code = value.charCodeAt(i)
112
+ if (code >= DECODING_TABLE.length || DECODING_TABLE[code] < 0) {
113
+ throw new Error(`Invalid Base93 character at offset ${i}.`)
114
+ }
115
+ const decoded = DECODING_TABLE[code]
116
+ if (first === -1) {
117
+ first = decoded
118
+ continue
119
+ }
120
+
121
+ const pair = first + decoded * 93
122
+ first = -1
123
+ queuedBits |= pair << bitCount
124
+ bitCount += (pair & 0x1fff) > 456 ? 13 : 14
125
+ while (bitCount > 7) {
126
+ output[position++] = queuedBits & 0xff
127
+ queuedBits >>>= 8
128
+ bitCount -= 8
129
+ }
130
+ }
131
+
132
+ if (first !== -1) output[position++] = (queuedBits | (first << bitCount)) & 0xff
133
+ return output.slice(0, position)
134
+ }
135
+
136
+ export function decode (text, offset = 0, length = -1) {
137
+ if (typeof text !== 'string') throw new TypeError('Base93 input must be a string.')
138
+ if (!Number.isSafeInteger(offset) || offset < 0 || offset > text.length) throw new RangeError('Invalid Base93 offset.')
139
+ if (!Number.isSafeInteger(length) || length < -1) throw new RangeError('Invalid Base93 length.')
140
+
141
+ const end = length < 0 ? text.length : Math.min(text.length, offset + length)
142
+ const encoded = text.slice(offset, end)
143
+ const bytes = decodeUnchecked(encoded)
144
+ if (encode(bytes) !== encoded) throw new Error('Non-canonical or truncated Base93 input.')
145
+ return bytes
146
+ }
147
+
148
+ function normalizeSource (source) {
149
+ if (typeof source === 'function') source = source()
150
+ if (typeof source === 'string') return [source]
151
+ if (source?.[Symbol.asyncIterator] || source?.[Symbol.iterator]) return source
152
+ throw new TypeError('Base93 stream source must be iterable.')
153
+ }
154
+
155
+ export class Base93Decoder {
156
+ constructor (source, { mimeType = '', preferTextStreamDecoding = false } = {}) {
157
+ this.source = normalizeSource(source)
158
+ this.asText = preferTextStreamDecoding && mimeType.startsWith('text/')
159
+ }
160
+
161
+ async * decodedValues () {
162
+ const textDecoder = this.asText ? new TextDecoder() : null
163
+ for await (const encoded of this.source) {
164
+ const bytes = decode(encoded)
165
+ const value = textDecoder ? textDecoder.decode(bytes, { stream: true }) : bytes
166
+ if (value.length > 0) yield value
167
+ }
168
+ if (textDecoder) {
169
+ const tail = textDecoder.decode()
170
+ if (tail.length > 0) yield tail
171
+ }
172
+ }
173
+
174
+ getDecoded () {
175
+ const iterator = this.decodedValues()[Symbol.asyncIterator]()
176
+ return new ReadableStream({
177
+ async pull (controller) {
178
+ try {
179
+ const { value, done } = await iterator.next()
180
+ if (done) controller.close()
181
+ else controller.enqueue(value)
182
+ } catch (error) {
183
+ controller.error(error)
184
+ }
185
+ },
186
+ async cancel () {
187
+ await iterator.return?.()
188
+ }
189
+ })
190
+ }
191
+ }
192
+
193
+ export default Base93Decoder
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libp2r2p",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "Peer-to-relay-to-peer",
5
5
  "keywords": [
6
6
  "p2r2p",
@@ -11,6 +11,27 @@
11
11
  "author": "arthurfranca",
12
12
  "type": "module",
13
13
  "sideEffects": false,
14
+ "files": [
15
+ "base16",
16
+ "base64",
17
+ "base93",
18
+ "content-key",
19
+ "double-dh",
20
+ "ecdh",
21
+ "idb",
22
+ "idb-queue",
23
+ "index.js",
24
+ "key",
25
+ "network",
26
+ "nip44-v3",
27
+ "nip46",
28
+ "private-channel",
29
+ "private-message",
30
+ "private-messenger",
31
+ "relay",
32
+ "temporary-storage",
33
+ "web-storage-queue"
34
+ ],
14
35
  "scripts": {
15
36
  "test": "node --test --experimental-test-module-mocks 'tests/**/*.test.js'",
16
37
  "test:only": "node --test --test-only --experimental-test-module-mocks 'tests/**/*.test.js'"
@@ -19,6 +40,7 @@
19
40
  ".": "./index.js",
20
41
  "./base16": "./base16/index.js",
21
42
  "./base64": "./base64/index.js",
43
+ "./base93": "./base93/index.js",
22
44
  "./content-key": "./content-key/index.js",
23
45
  "./content-key/event": "./content-key/event/index.js",
24
46
  "./double-dh": "./double-dh/index.js",
@@ -527,13 +527,13 @@ export async function publish ({ senderSigner, imkcSigner, privateChannelSigner
527
527
  } finally {
528
528
  cleanupEnvelopeRows(context.preparedRows)
529
529
  }
530
- return { results }
530
+ return results
531
531
  }
532
532
 
533
533
  for await (const wrappedEvent of wrapEvents({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers, receiverTag, deletionPubkey: normalizedDeletionPubkey, event, expirationSeconds, temporaryStorageArea, _getIykcProofs })) {
534
534
  results.push(await _publish(wrappedEvent, withRecoveryRelays(relays, recoveryRelays)))
535
535
  }
536
- return { results }
536
+ return results
537
537
  }
538
538
 
539
539
  export async function publishNymEvent ({ nymSigner, privateChannelSigner, privateChannelReaderPubkey, deletionPubkey, event, relays, relayToReceivers, recoveryRelays, expirationSeconds, _publish = sendToRelays }) {
@@ -543,7 +543,7 @@ export async function publishNymEvent ({ nymSigner, privateChannelSigner, privat
543
543
  for await (const wrappedEvent of wrapNymEvents({ nymSigner, privateChannelSigner, privateChannelReaderPubkey, deletionPubkey: normalizedDeletionPubkey, event, expirationSeconds })) {
544
544
  results.push(await _publish(wrappedEvent, publishRelays))
545
545
  }
546
- return { results }
546
+ return results
547
547
  }
548
548
 
549
549
  function readSignerFromMap (signersByPubkey, pubkey) {
@@ -21,22 +21,32 @@ function uniq (values) {
21
21
  return [...new Set((values || []).filter(Boolean))]
22
22
  }
23
23
 
24
- function resolveDeletionCapability (deletionPubkey) {
25
- if (deletionPubkey !== undefined) {
26
- if (typeof deletionPubkey !== 'string' || !HEX_PUBKEY.test(deletionPubkey)) {
27
- throw new Error('INVALID_DELETION_PUBKEY')
28
- }
29
- return { deletionPubkey: deletionPubkey.toLowerCase() }
24
+ function normalizeDeletionPubkey (deletionPubkey) {
25
+ if (deletionPubkey === undefined) return undefined
26
+ if (typeof deletionPubkey !== 'string' || !HEX_PUBKEY.test(deletionPubkey)) {
27
+ throw new Error('INVALID_DELETION_PUBKEY')
30
28
  }
29
+ return deletionPubkey.toLowerCase()
30
+ }
31
+
32
+ function resolveDeletionCapability ({ deletionPubkey, deletionSeckey, autoDeletionCapability = true }) {
33
+ if (deletionSeckey !== undefined) throw new Error('DELETION_SECKEY_NOT_ACCEPTED')
34
+ if (typeof autoDeletionCapability !== 'boolean') throw new Error('AUTO_DELETION_CAPABILITY_BOOLEAN_REQUIRED')
35
+
36
+ const normalizedDeletionPubkey = normalizeDeletionPubkey(deletionPubkey)
37
+ if (normalizedDeletionPubkey) return { deletionPubkey: normalizedDeletionPubkey }
38
+ if (!autoDeletionCapability) return {}
39
+
31
40
  const { pubkey, seckey } = generateKeypair()
32
41
  return { deletionPubkey: pubkey, deletionSeckey: seckey }
33
42
  }
34
43
 
35
- function withDeletionCapability (result, capability) {
44
+ function withDelivery (result, reports, deletionSeckey) {
45
+ const delivery = { reports }
46
+ if (deletionSeckey !== undefined) delivery.deletionSeckey = deletionSeckey
36
47
  return {
37
48
  ...result,
38
- deletionPubkey: capability.deletionPubkey,
39
- ...(capability.deletionSeckey && { deletionSeckey: capability.deletionSeckey })
49
+ delivery
40
50
  }
41
51
  }
42
52
 
@@ -457,8 +467,10 @@ export async function ask ({
457
467
  content,
458
468
  expirationSeconds,
459
469
  temporaryStorageArea,
460
- deletionPubkey,
461
470
  _getIykcProofs,
471
+ deletionPubkey,
472
+ deletionSeckey,
473
+ autoDeletionCapability = true,
462
474
  _publish = privateChannel.publish
463
475
  }) {
464
476
  if (!receiverPubkey) throw new Error('RECEIVER_PUBKEY_REQUIRED')
@@ -474,10 +486,10 @@ export async function ask ({
474
486
  message: message || { code, payload, error, content }
475
487
  })
476
488
  })
477
- const deletionCapability = resolveDeletionCapability(deletionPubkey)
478
- const results = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers: [receiverPubkey], receiverTag: receiverPubkey, deletionPubkey: deletionCapability.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
489
+ const deletion = resolveDeletionCapability({ deletionPubkey, deletionSeckey, autoDeletionCapability })
490
+ const reports = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers: [receiverPubkey], receiverTag: receiverPubkey, deletionPubkey: deletion.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
479
491
 
480
- return withDeletionCapability({ question, results }, deletionCapability)
492
+ return withDelivery({ question }, reports, deletion.deletionSeckey)
481
493
  }
482
494
 
483
495
  export async function reply ({
@@ -497,8 +509,10 @@ export async function reply ({
497
509
  content,
498
510
  expirationSeconds,
499
511
  temporaryStorageArea,
500
- deletionPubkey,
501
512
  _getIykcProofs,
513
+ deletionPubkey,
514
+ deletionSeckey,
515
+ autoDeletionCapability = true,
502
516
  _publish = privateChannel.publish
503
517
  }) {
504
518
  if (!question?.id) throw new Error('QUESTION_REQUIRED')
@@ -511,9 +525,9 @@ export async function reply ({
511
525
  message: message || { code, payload, error, content }
512
526
  })
513
527
  })
514
- const deletionCapability = resolveDeletionCapability(deletionPubkey)
515
- const results = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers: [receiverPubkey], receiverTag: receiverPubkey, deletionPubkey: deletionCapability.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
516
- return withDeletionCapability({ reply: event, results }, deletionCapability)
528
+ const deletion = resolveDeletionCapability({ deletionPubkey, deletionSeckey, autoDeletionCapability })
529
+ const reports = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers: [receiverPubkey], receiverTag: receiverPubkey, deletionPubkey: deletion.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
530
+ return withDelivery({ reply: event }, reports, deletion.deletionSeckey)
517
531
  }
518
532
 
519
533
  export async function tell ({
@@ -532,8 +546,10 @@ export async function tell ({
532
546
  content,
533
547
  expirationSeconds,
534
548
  temporaryStorageArea,
535
- deletionPubkey,
536
549
  _getIykcProofs,
550
+ deletionPubkey,
551
+ deletionSeckey,
552
+ autoDeletionCapability = true,
537
553
  _publish = privateChannel.publish
538
554
  }) {
539
555
  if (!receiverPubkey) throw new Error('RECEIVER_PUBKEY_REQUIRED')
@@ -545,9 +561,9 @@ export async function tell ({
545
561
  message: message || { code, payload, error, content }
546
562
  })
547
563
  })
548
- const deletionCapability = resolveDeletionCapability(deletionPubkey)
549
- const results = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers: [receiverPubkey], receiverTag: receiverPubkey, deletionPubkey: deletionCapability.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
550
- return withDeletionCapability({ tell: event, results }, deletionCapability)
564
+ const deletion = resolveDeletionCapability({ deletionPubkey, deletionSeckey, autoDeletionCapability })
565
+ const reports = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers: [receiverPubkey], receiverTag: receiverPubkey, deletionPubkey: deletion.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
566
+ return withDelivery({ tell: event }, reports, deletion.deletionSeckey)
551
567
  }
552
568
 
553
569
  export async function yell ({
@@ -566,8 +582,10 @@ export async function yell ({
566
582
  content,
567
583
  expirationSeconds,
568
584
  temporaryStorageArea,
569
- deletionPubkey,
570
585
  _getIykcProofs,
586
+ deletionPubkey,
587
+ deletionSeckey,
588
+ autoDeletionCapability = true,
571
589
  _publish = privateChannel.publish
572
590
  }) {
573
591
  const receivers = uniq(receiverPubkeys)
@@ -580,9 +598,9 @@ export async function yell ({
580
598
  message: message || { code, payload, error, content }
581
599
  })
582
600
  })
583
- const deletionCapability = resolveDeletionCapability(deletionPubkey)
584
- const results = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers, receiverTag: '', deletionPubkey: deletionCapability.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
585
- return withDeletionCapability({ yell: event, results }, deletionCapability)
601
+ const deletion = resolveDeletionCapability({ deletionPubkey, deletionSeckey, autoDeletionCapability })
602
+ const reports = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers, receiverTag: '', deletionPubkey: deletion.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
603
+ return withDelivery({ yell: event }, reports, deletion.deletionSeckey)
586
604
  }
587
605
 
588
606
  export async function broadcastRumor ({
@@ -597,16 +615,18 @@ export async function broadcastRumor ({
597
615
  rumor,
598
616
  expirationSeconds,
599
617
  temporaryStorageArea,
600
- deletionPubkey,
601
618
  _getIykcProofs,
619
+ deletionPubkey,
620
+ deletionSeckey,
621
+ autoDeletionCapability = true,
602
622
  _publish = privateChannel.publish
603
623
  }) {
604
624
  const receivers = uniq(receiverPubkeys)
605
625
  if (!receivers.length) throw new Error('NO_RECEIVERS')
606
626
  const { event, wireEvent } = await makeOutgoingRumor({ senderSigner, rumor })
607
- const deletionCapability = resolveDeletionCapability(deletionPubkey)
608
- const results = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers, receiverTag: '', deletionPubkey: deletionCapability.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
609
- return withDeletionCapability({ rumor: event, results }, deletionCapability)
627
+ const deletion = resolveDeletionCapability({ deletionPubkey, deletionSeckey, autoDeletionCapability })
628
+ const reports = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers, receiverTag: '', deletionPubkey: deletion.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
629
+ return withDelivery({ rumor: event }, reports, deletion.deletionSeckey)
610
630
  }
611
631
 
612
632
  export async function broadcastEvent ({
@@ -621,16 +641,18 @@ export async function broadcastEvent ({
621
641
  event,
622
642
  expirationSeconds,
623
643
  temporaryStorageArea,
624
- deletionPubkey,
625
644
  _getIykcProofs,
645
+ deletionPubkey,
646
+ deletionSeckey,
647
+ autoDeletionCapability = true,
626
648
  _publish = privateChannel.publish
627
649
  }) {
628
650
  const receivers = uniq(receiverPubkeys)
629
651
  if (!receivers.length) throw new Error('NO_RECEIVERS')
630
652
  const wireEvent = assertValidSignedEvent({ ...event, tags: cloneTags(event?.tags) })
631
- const deletionCapability = resolveDeletionCapability(deletionPubkey)
632
- const results = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers, receiverTag: '', deletionPubkey: deletionCapability.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
633
- return withDeletionCapability({ event: wireEvent, results }, deletionCapability)
653
+ const deletion = resolveDeletionCapability({ deletionPubkey, deletionSeckey, autoDeletionCapability })
654
+ const reports = await sendPrivateMessage({ senderSigner, imkcSigner, privateChannelSigner, privateChannelReaderPubkey, receivers, receiverTag: '', deletionPubkey: deletion.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, temporaryStorageArea, _getIykcProofs, _publish })
655
+ return withDelivery({ event: wireEvent }, reports, deletion.deletionSeckey)
634
656
  }
635
657
 
636
658
  export async function broadcastNymRumor ({
@@ -643,13 +665,15 @@ export async function broadcastNymRumor ({
643
665
  rumor,
644
666
  expirationSeconds,
645
667
  deletionPubkey,
668
+ deletionSeckey,
669
+ autoDeletionCapability = true,
646
670
  _publish = privateChannel.publishNymEvent
647
671
  }) {
648
672
  if (!nymSigner?.getPublicKey) throw new Error('NYM_SIGNER_REQUIRED')
649
673
  const { event, wireEvent } = await makeOutgoingRumor({ senderSigner: nymSigner, rumor })
650
- const deletionCapability = resolveDeletionCapability(deletionPubkey)
651
- const results = await sendNymMessage({ nymSigner, privateChannelSigner, privateChannelReaderPubkey, deletionPubkey: deletionCapability.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, _publish })
652
- return withDeletionCapability({ rumor: event, results }, deletionCapability)
674
+ const deletion = resolveDeletionCapability({ deletionPubkey, deletionSeckey, autoDeletionCapability })
675
+ const reports = await sendNymMessage({ nymSigner, privateChannelSigner, privateChannelReaderPubkey, deletionPubkey: deletion.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, _publish })
676
+ return withDelivery({ rumor: event }, reports, deletion.deletionSeckey)
653
677
  }
654
678
 
655
679
  export async function broadcastNymEvent ({
@@ -662,11 +686,13 @@ export async function broadcastNymEvent ({
662
686
  event,
663
687
  expirationSeconds,
664
688
  deletionPubkey,
689
+ deletionSeckey,
690
+ autoDeletionCapability = true,
665
691
  _publish = privateChannel.publishNymEvent
666
692
  }) {
667
693
  if (!nymSigner?.getPublicKey) throw new Error('NYM_SIGNER_REQUIRED')
668
694
  const wireEvent = assertValidSignedEvent({ ...event, tags: cloneTags(event?.tags) })
669
- const deletionCapability = resolveDeletionCapability(deletionPubkey)
670
- const results = await sendNymMessage({ nymSigner, privateChannelSigner, privateChannelReaderPubkey, deletionPubkey: deletionCapability.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, _publish })
671
- return withDeletionCapability({ event: wireEvent, results }, deletionCapability)
695
+ const deletion = resolveDeletionCapability({ deletionPubkey, deletionSeckey, autoDeletionCapability })
696
+ const reports = await sendNymMessage({ nymSigner, privateChannelSigner, privateChannelReaderPubkey, deletionPubkey: deletion.deletionPubkey, event: wireEvent, relays, relayToReceivers, recoveryRelays, expirationSeconds, _publish })
697
+ return withDelivery({ event: wireEvent }, reports, deletion.deletionSeckey)
672
698
  }