@libp2p/peer-store 7.0.2 → 8.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.
Files changed (76) hide show
  1. package/README.md +0 -170
  2. package/dist/index.min.js +12 -12
  3. package/dist/src/errors.d.ts +0 -1
  4. package/dist/src/errors.d.ts.map +1 -1
  5. package/dist/src/errors.js +1 -2
  6. package/dist/src/errors.js.map +1 -1
  7. package/dist/src/index.d.ts +24 -25
  8. package/dist/src/index.d.ts.map +1 -1
  9. package/dist/src/index.js +120 -87
  10. package/dist/src/index.js.map +1 -1
  11. package/dist/src/pb/peer.d.ts +28 -9
  12. package/dist/src/pb/peer.d.ts.map +1 -1
  13. package/dist/src/pb/peer.js +147 -31
  14. package/dist/src/pb/peer.js.map +1 -1
  15. package/dist/src/store.d.ts +18 -28
  16. package/dist/src/store.d.ts.map +1 -1
  17. package/dist/src/store.js +77 -147
  18. package/dist/src/store.js.map +1 -1
  19. package/dist/src/utils/bytes-to-peer.d.ts +4 -0
  20. package/dist/src/utils/bytes-to-peer.d.ts.map +1 -0
  21. package/dist/src/utils/bytes-to-peer.js +33 -0
  22. package/dist/src/utils/bytes-to-peer.js.map +1 -0
  23. package/dist/src/utils/dedupe-addresses.d.ts +6 -0
  24. package/dist/src/utils/dedupe-addresses.d.ts.map +1 -0
  25. package/dist/src/utils/dedupe-addresses.js +41 -0
  26. package/dist/src/utils/dedupe-addresses.js.map +1 -0
  27. package/dist/src/utils/peer-data-to-datastore-peer.d.ts +5 -0
  28. package/dist/src/utils/peer-data-to-datastore-peer.d.ts.map +1 -0
  29. package/dist/src/utils/peer-data-to-datastore-peer.js +92 -0
  30. package/dist/src/utils/peer-data-to-datastore-peer.js.map +1 -0
  31. package/dist/src/utils/peer-id-to-datastore-key.d.ts +5 -0
  32. package/dist/src/utils/peer-id-to-datastore-key.d.ts.map +1 -0
  33. package/dist/src/utils/peer-id-to-datastore-key.js +13 -0
  34. package/dist/src/utils/peer-id-to-datastore-key.js.map +1 -0
  35. package/dist/src/utils/to-peer-pb.d.ts +10 -0
  36. package/dist/src/utils/to-peer-pb.d.ts.map +1 -0
  37. package/dist/src/utils/to-peer-pb.js +182 -0
  38. package/dist/src/utils/to-peer-pb.js.map +1 -0
  39. package/dist/typedoc-urls.json +13 -2
  40. package/package.json +9 -10
  41. package/src/errors.ts +1 -2
  42. package/src/index.ts +133 -97
  43. package/src/pb/peer.proto +10 -7
  44. package/src/pb/peer.ts +187 -37
  45. package/src/store.ts +102 -189
  46. package/src/utils/bytes-to-peer.ts +41 -0
  47. package/src/utils/dedupe-addresses.ts +51 -0
  48. package/src/utils/peer-data-to-datastore-peer.ts +116 -0
  49. package/src/utils/peer-id-to-datastore-key.ts +15 -0
  50. package/src/utils/to-peer-pb.ts +237 -0
  51. package/dist/src/address-book.d.ts +0 -29
  52. package/dist/src/address-book.d.ts.map +0 -1
  53. package/dist/src/address-book.js +0 -304
  54. package/dist/src/address-book.js.map +0 -1
  55. package/dist/src/key-book.d.ts +0 -21
  56. package/dist/src/key-book.d.ts.map +0 -1
  57. package/dist/src/key-book.js +0 -121
  58. package/dist/src/key-book.js.map +0 -1
  59. package/dist/src/metadata-book.d.ts +0 -28
  60. package/dist/src/metadata-book.d.ts.map +0 -1
  61. package/dist/src/metadata-book.js +0 -211
  62. package/dist/src/metadata-book.js.map +0 -1
  63. package/dist/src/pb/tags.d.ts +0 -21
  64. package/dist/src/pb/tags.d.ts.map +0 -1
  65. package/dist/src/pb/tags.js +0 -111
  66. package/dist/src/pb/tags.js.map +0 -1
  67. package/dist/src/proto-book.d.ts +0 -18
  68. package/dist/src/proto-book.d.ts.map +0 -1
  69. package/dist/src/proto-book.js +0 -199
  70. package/dist/src/proto-book.js.map +0 -1
  71. package/src/address-book.ts +0 -367
  72. package/src/key-book.ts +0 -140
  73. package/src/metadata-book.ts +0 -244
  74. package/src/pb/tags.proto +0 -11
  75. package/src/pb/tags.ts +0 -145
  76. package/src/proto-book.ts +0 -234
package/src/index.ts CHANGED
@@ -1,79 +1,80 @@
1
- import { logger } from '@libp2p/logger'
2
- import { EventEmitter } from '@libp2p/interfaces/events'
3
- import { PeerStoreAddressBook } from './address-book.js'
4
- import { PeerStoreKeyBook } from './key-book.js'
5
- import { PeerStoreMetadataBook } from './metadata-book.js'
6
- import { PeerStoreProtoBook } from './proto-book.js'
7
- import { PersistentStore, Store } from './store.js'
8
- import type { PeerStore, AddressBook, KeyBook, MetadataBook, ProtoBook, PeerStoreEvents, PeerStoreInit, Peer, TagOptions } from '@libp2p/interface-peer-store'
1
+ import type { EventEmitter } from '@libp2p/interfaces/events'
2
+ import { PersistentStore, PeerUpdate } from './store.js'
3
+ import type { PeerStore, Peer, PeerData } from '@libp2p/interface-peer-store'
9
4
  import type { PeerId } from '@libp2p/interface-peer-id'
10
- import { CodeError } from '@libp2p/interfaces/errors'
11
- import { Tag, Tags } from './pb/tags.js'
12
5
  import type { Datastore } from 'interface-datastore'
6
+ import type { Multiaddr } from '@multiformats/multiaddr'
7
+ import type { Libp2pEvents } from '@libp2p/interface-libp2p'
8
+ import { logger } from '@libp2p/logger'
9
+ import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record'
13
10
 
14
11
  const log = logger('libp2p:peer-store')
15
12
 
16
13
  export interface PersistentPeerStoreComponents {
17
14
  peerId: PeerId
18
15
  datastore: Datastore
16
+ events: EventEmitter<Libp2pEvents>
17
+ }
18
+
19
+ /**
20
+ * Return true to allow storing the passed multiaddr for the passed peer
21
+ */
22
+ export interface AddressFilter {
23
+ (peerId: PeerId, multiaddr: Multiaddr): Promise<boolean>
24
+ }
25
+
26
+ export interface PersistentPeerStoreInit {
27
+ addressFilter?: AddressFilter
19
28
  }
20
29
 
21
30
  /**
22
31
  * An implementation of PeerStore that stores data in a Datastore
23
32
  */
24
- export class PersistentPeerStore extends EventEmitter<PeerStoreEvents> implements PeerStore {
25
- public addressBook: AddressBook
26
- public keyBook: KeyBook
27
- public metadataBook: MetadataBook
28
- public protoBook: ProtoBook
29
-
30
- private readonly components: PersistentPeerStoreComponents
31
- private readonly store: Store
32
-
33
- constructor (components: PersistentPeerStoreComponents, init: PeerStoreInit = {}) {
34
- super()
35
-
36
- this.components = components
37
- this.store = new PersistentStore(components)
38
- this.addressBook = new PeerStoreAddressBook(this.dispatchEvent.bind(this), this.store, init.addressFilter)
39
- this.keyBook = new PeerStoreKeyBook(this.dispatchEvent.bind(this), this.store)
40
- this.metadataBook = new PeerStoreMetadataBook(this.dispatchEvent.bind(this), this.store)
41
- this.protoBook = new PeerStoreProtoBook(this.dispatchEvent.bind(this), this.store)
33
+ export class PersistentPeerStore implements PeerStore {
34
+ private readonly store: PersistentStore
35
+ private readonly events: EventEmitter<Libp2pEvents>
36
+ private readonly peerId: PeerId
37
+
38
+ constructor (components: PersistentPeerStoreComponents, init: PersistentPeerStoreInit = {}) {
39
+ this.events = components.events
40
+ this.peerId = components.peerId
41
+ this.store = new PersistentStore(components, init)
42
42
  }
43
43
 
44
44
  async forEach (fn: (peer: Peer) => void): Promise<void> {
45
- log.trace('getPeers await read lock')
45
+ log.trace('forEach await read lock')
46
46
  const release = await this.store.lock.readLock()
47
- log.trace('getPeers got read lock')
47
+ log.trace('forEach got read lock')
48
48
 
49
49
  try {
50
50
  for await (const peer of this.store.all()) {
51
- if (peer.id.equals(this.components.peerId)) {
52
- // Skip self peer if present
53
- continue
54
- }
55
-
56
51
  fn(peer)
57
52
  }
58
53
  } finally {
59
- log.trace('getPeers release read lock')
54
+ log.trace('forEach release read lock')
60
55
  release()
61
56
  }
62
57
  }
63
58
 
64
59
  async all (): Promise<Peer[]> {
65
- const output: Peer[] = []
60
+ log.trace('all await read lock')
61
+ const release = await this.store.lock.readLock()
62
+ log.trace('all got read lock')
66
63
 
67
- await this.forEach(peer => {
68
- output.push(peer)
69
- })
64
+ try {
65
+ const output: Peer[] = []
70
66
 
71
- return output
67
+ for await (const peer of this.store.all()) {
68
+ output.push(peer)
69
+ }
70
+
71
+ return output
72
+ } finally {
73
+ log.trace('all release read lock')
74
+ release()
75
+ }
72
76
  }
73
77
 
74
- /**
75
- * Delete the information of the given peer in every book
76
- */
77
78
  async delete (peerId: PeerId): Promise<void> {
78
79
  log.trace('delete await write lock')
79
80
  const release = await this.store.lock.writeLock()
@@ -87,9 +88,19 @@ export class PersistentPeerStore extends EventEmitter<PeerStoreEvents> implement
87
88
  }
88
89
  }
89
90
 
90
- /**
91
- * Get the stored information of a given peer
92
- */
91
+ async has (peerId: PeerId): Promise<boolean> {
92
+ log.trace('has await read lock')
93
+ const release = await this.store.lock.readLock()
94
+ log.trace('has got read lock')
95
+
96
+ try {
97
+ return await this.store.has(peerId)
98
+ } finally {
99
+ log.trace('has release read lock')
100
+ release()
101
+ }
102
+ }
103
+
93
104
  async get (peerId: PeerId): Promise<Peer> {
94
105
  log.trace('get await read lock')
95
106
  const release = await this.store.lock.readLock()
@@ -103,82 +114,107 @@ export class PersistentPeerStore extends EventEmitter<PeerStoreEvents> implement
103
114
  }
104
115
  }
105
116
 
106
- /**
107
- * Returns true if we have a record of the peer
108
- */
109
- async has (peerId: PeerId): Promise<boolean> {
110
- log.trace('has await read lock')
111
- const release = await this.store.lock.readLock()
112
- log.trace('has got read lock')
117
+ async save (id: PeerId, data: PeerData): Promise<Peer> {
118
+ log.trace('save await write lock')
119
+ const release = await this.store.lock.writeLock()
120
+ log.trace('save got write lock')
113
121
 
114
122
  try {
115
- return await this.store.has(peerId)
123
+ const result = await this.store.save(id, data)
124
+
125
+ this.#emitIfUpdated(id, result)
126
+
127
+ return result.peer
116
128
  } finally {
117
- log.trace('has release read lock')
129
+ log.trace('save release write lock')
118
130
  release()
119
131
  }
120
132
  }
121
133
 
122
- async tagPeer (peerId: PeerId, tag: string, options: TagOptions = {}): Promise<void> {
123
- const providedValue = options.value ?? 0
124
- const value = Math.round(providedValue)
125
- const ttl = options.ttl ?? undefined
134
+ async patch (id: PeerId, data: PeerData): Promise<Peer> {
135
+ log.trace('patch await write lock')
136
+ const release = await this.store.lock.writeLock()
137
+ log.trace('patch got write lock')
126
138
 
127
- if (value !== providedValue || value < 0 || value > 100) {
128
- throw new CodeError('Tag value must be between 0-100', 'ERR_TAG_VALUE_OUT_OF_BOUNDS')
129
- }
139
+ try {
140
+ const result = await this.store.patch(id, data)
130
141
 
131
- const buf = await this.metadataBook.getValue(peerId, 'tags')
132
- let tags: Tag[] = []
142
+ this.#emitIfUpdated(id, result)
133
143
 
134
- if (buf != null) {
135
- tags = Tags.decode(buf).tags
144
+ return result.peer
145
+ } finally {
146
+ log.trace('patch release write lock')
147
+ release()
136
148
  }
149
+ }
137
150
 
138
- // do not allow duplicate tags
139
- tags = tags.filter(t => t.name !== tag)
151
+ async merge (id: PeerId, data: PeerData): Promise<Peer> {
152
+ log.trace('merge await write lock')
153
+ const release = await this.store.lock.writeLock()
154
+ log.trace('merge got write lock')
140
155
 
141
- tags.push({
142
- name: tag,
143
- value,
144
- expiry: ttl == null ? undefined : BigInt(Date.now() + ttl)
145
- })
156
+ try {
157
+ const result = await this.store.merge(id, data)
146
158
 
147
- await this.metadataBook.setValue(peerId, 'tags', Tags.encode({ tags }).subarray())
159
+ this.#emitIfUpdated(id, result)
160
+
161
+ return result.peer
162
+ } finally {
163
+ log.trace('merge release write lock')
164
+ release()
165
+ }
148
166
  }
149
167
 
150
- async unTagPeer (peerId: PeerId, tag: string): Promise<void> {
151
- const buf = await this.metadataBook.getValue(peerId, 'tags')
152
- let tags: Tag[] = []
168
+ async consumePeerRecord (buf: Uint8Array, expectedPeer?: PeerId): Promise<boolean> {
169
+ const envelope = await RecordEnvelope.openAndCertify(buf, PeerRecord.DOMAIN)
153
170
 
154
- if (buf != null) {
155
- tags = Tags.decode(buf).tags
171
+ if (expectedPeer?.equals(envelope.peerId) === false) {
172
+ log('envelope peer id was not the expected peer id - expected: %p received: %p', expectedPeer, envelope.peerId)
173
+ return false
156
174
  }
157
175
 
158
- tags = tags.filter(t => t.name !== tag)
176
+ const peerRecord = PeerRecord.createFromProtobuf(envelope.payload)
177
+ let peer: Peer | undefined
159
178
 
160
- await this.metadataBook.setValue(peerId, 'tags', Tags.encode({ tags }).subarray())
161
- }
179
+ try {
180
+ peer = await this.get(envelope.peerId)
181
+ } catch (err: any) {
182
+ if (err.code !== 'ERR_NOT_FOUND') {
183
+ throw err
184
+ }
185
+ }
162
186
 
163
- async getTags (peerId: PeerId): Promise<Array<{ name: string, value: number }>> {
164
- const buf = await this.metadataBook.getValue(peerId, 'tags')
165
- let tags: Tag[] = []
187
+ // ensure seq is greater than, or equal to, the last received
188
+ if (peer?.peerRecordEnvelope != null) {
189
+ const storedEnvelope = await RecordEnvelope.createFromProtobuf(peer.peerRecordEnvelope)
190
+ const storedRecord = PeerRecord.createFromProtobuf(storedEnvelope.payload)
166
191
 
167
- if (buf != null) {
168
- tags = Tags.decode(buf).tags
192
+ if (storedRecord.seqNumber >= peerRecord.seqNumber) {
193
+ log('sequence number was lower or equal to existing sequence number - stored: %d received: %d', storedRecord.seqNumber, peerRecord.seqNumber)
194
+ return false
195
+ }
169
196
  }
170
197
 
171
- const now = BigInt(Date.now())
172
- const unexpiredTags = tags.filter(tag => tag.expiry == null || tag.expiry > now)
198
+ await this.patch(peerRecord.peerId, {
199
+ peerRecordEnvelope: buf,
200
+ addresses: peerRecord.multiaddrs.map(multiaddr => ({
201
+ isCertified: true,
202
+ multiaddr
203
+ }))
204
+ })
173
205
 
174
- if (unexpiredTags.length !== tags.length) {
175
- // remove any expired tags
176
- await this.metadataBook.setValue(peerId, 'tags', Tags.encode({ tags: unexpiredTags }).subarray())
206
+ return true
207
+ }
208
+
209
+ #emitIfUpdated (id: PeerId, result: PeerUpdate): void {
210
+ if (!result.updated) {
211
+ return
177
212
  }
178
213
 
179
- return unexpiredTags.map(t => ({
180
- name: t.name,
181
- value: t.value ?? 0
182
- }))
214
+ if (this.peerId.equals(id)) {
215
+ this.events.safeDispatchEvent('self:peer:update', { detail: result })
216
+ } else {
217
+ this.events.safeDispatchEvent('peer:update', { detail: result })
218
+ }
183
219
  }
184
220
  }
package/src/pb/peer.proto CHANGED
@@ -7,14 +7,17 @@ message Peer {
7
7
  // The protocols the peer supports
8
8
  repeated string protocols = 2;
9
9
 
10
- // Any peer metadata
11
- repeated Metadata metadata = 3;
12
-
13
10
  // The public key of the peer
14
- optional bytes pub_key = 4;
11
+ optional bytes public_key = 4;
15
12
 
16
13
  // The most recently received signed PeerRecord
17
14
  optional bytes peer_record_envelope = 5;
15
+
16
+ // Any peer metadata
17
+ map<string, bytes> metadata = 6;
18
+
19
+ // Any tags the peer has
20
+ map<string, Tag> tags = 7;
18
21
  }
19
22
 
20
23
  // Address represents a single multiaddr
@@ -25,7 +28,7 @@ message Address {
25
28
  optional bool isCertified = 2;
26
29
  }
27
30
 
28
- message Metadata {
29
- string key = 1;
30
- bytes value = 2;
31
+ message Tag {
32
+ uint32 value = 1; // tag value 0-100
33
+ optional uint64 expiry = 2; // ms timestamp after which the tag is no longer valid
31
34
  }
package/src/pb/peer.ts CHANGED
@@ -11,12 +11,148 @@ import type { Uint8ArrayList } from 'uint8arraylist'
11
11
  export interface Peer {
12
12
  addresses: Address[]
13
13
  protocols: string[]
14
- metadata: Metadata[]
15
- pubKey?: Uint8Array
14
+ publicKey?: Uint8Array
16
15
  peerRecordEnvelope?: Uint8Array
16
+ metadata: Map<string, Uint8Array>
17
+ tags: Map<string, Tag>
17
18
  }
18
19
 
19
20
  export namespace Peer {
21
+ export interface Peer$metadataEntry {
22
+ key: string
23
+ value: Uint8Array
24
+ }
25
+
26
+ export namespace Peer$metadataEntry {
27
+ let _codec: Codec<Peer$metadataEntry>
28
+
29
+ export const codec = (): Codec<Peer$metadataEntry> => {
30
+ if (_codec == null) {
31
+ _codec = message<Peer$metadataEntry>((obj, w, opts = {}) => {
32
+ if (opts.lengthDelimited !== false) {
33
+ w.fork()
34
+ }
35
+
36
+ if ((obj.key != null && obj.key !== '')) {
37
+ w.uint32(10)
38
+ w.string(obj.key)
39
+ }
40
+
41
+ if ((obj.value != null && obj.value.byteLength > 0)) {
42
+ w.uint32(18)
43
+ w.bytes(obj.value)
44
+ }
45
+
46
+ if (opts.lengthDelimited !== false) {
47
+ w.ldelim()
48
+ }
49
+ }, (reader, length) => {
50
+ const obj: any = {
51
+ key: '',
52
+ value: new Uint8Array(0)
53
+ }
54
+
55
+ const end = length == null ? reader.len : reader.pos + length
56
+
57
+ while (reader.pos < end) {
58
+ const tag = reader.uint32()
59
+
60
+ switch (tag >>> 3) {
61
+ case 1:
62
+ obj.key = reader.string()
63
+ break
64
+ case 2:
65
+ obj.value = reader.bytes()
66
+ break
67
+ default:
68
+ reader.skipType(tag & 7)
69
+ break
70
+ }
71
+ }
72
+
73
+ return obj
74
+ })
75
+ }
76
+
77
+ return _codec
78
+ }
79
+
80
+ export const encode = (obj: Partial<Peer$metadataEntry>): Uint8Array => {
81
+ return encodeMessage(obj, Peer$metadataEntry.codec())
82
+ }
83
+
84
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Peer$metadataEntry => {
85
+ return decodeMessage(buf, Peer$metadataEntry.codec())
86
+ }
87
+ }
88
+
89
+ export interface Peer$tagsEntry {
90
+ key: string
91
+ value?: Tag
92
+ }
93
+
94
+ export namespace Peer$tagsEntry {
95
+ let _codec: Codec<Peer$tagsEntry>
96
+
97
+ export const codec = (): Codec<Peer$tagsEntry> => {
98
+ if (_codec == null) {
99
+ _codec = message<Peer$tagsEntry>((obj, w, opts = {}) => {
100
+ if (opts.lengthDelimited !== false) {
101
+ w.fork()
102
+ }
103
+
104
+ if ((obj.key != null && obj.key !== '')) {
105
+ w.uint32(10)
106
+ w.string(obj.key)
107
+ }
108
+
109
+ if (obj.value != null) {
110
+ w.uint32(18)
111
+ Tag.codec().encode(obj.value, w)
112
+ }
113
+
114
+ if (opts.lengthDelimited !== false) {
115
+ w.ldelim()
116
+ }
117
+ }, (reader, length) => {
118
+ const obj: any = {
119
+ key: ''
120
+ }
121
+
122
+ const end = length == null ? reader.len : reader.pos + length
123
+
124
+ while (reader.pos < end) {
125
+ const tag = reader.uint32()
126
+
127
+ switch (tag >>> 3) {
128
+ case 1:
129
+ obj.key = reader.string()
130
+ break
131
+ case 2:
132
+ obj.value = Tag.codec().decode(reader, reader.uint32())
133
+ break
134
+ default:
135
+ reader.skipType(tag & 7)
136
+ break
137
+ }
138
+ }
139
+
140
+ return obj
141
+ })
142
+ }
143
+
144
+ return _codec
145
+ }
146
+
147
+ export const encode = (obj: Partial<Peer$tagsEntry>): Uint8Array => {
148
+ return encodeMessage(obj, Peer$tagsEntry.codec())
149
+ }
150
+
151
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Peer$tagsEntry => {
152
+ return decodeMessage(buf, Peer$tagsEntry.codec())
153
+ }
154
+ }
155
+
20
156
  let _codec: Codec<Peer>
21
157
 
22
158
  export const codec = (): Codec<Peer> => {
@@ -40,16 +176,9 @@ export namespace Peer {
40
176
  }
41
177
  }
42
178
 
43
- if (obj.metadata != null) {
44
- for (const value of obj.metadata) {
45
- w.uint32(26)
46
- Metadata.codec().encode(value, w)
47
- }
48
- }
49
-
50
- if (obj.pubKey != null) {
179
+ if (obj.publicKey != null) {
51
180
  w.uint32(34)
52
- w.bytes(obj.pubKey)
181
+ w.bytes(obj.publicKey)
53
182
  }
54
183
 
55
184
  if (obj.peerRecordEnvelope != null) {
@@ -57,6 +186,20 @@ export namespace Peer {
57
186
  w.bytes(obj.peerRecordEnvelope)
58
187
  }
59
188
 
189
+ if (obj.metadata != null && obj.metadata.size !== 0) {
190
+ for (const [key, value] of obj.metadata.entries()) {
191
+ w.uint32(50)
192
+ Peer.Peer$metadataEntry.codec().encode({ key, value }, w)
193
+ }
194
+ }
195
+
196
+ if (obj.tags != null && obj.tags.size !== 0) {
197
+ for (const [key, value] of obj.tags.entries()) {
198
+ w.uint32(58)
199
+ Peer.Peer$tagsEntry.codec().encode({ key, value }, w)
200
+ }
201
+ }
202
+
60
203
  if (opts.lengthDelimited !== false) {
61
204
  w.ldelim()
62
205
  }
@@ -64,7 +207,8 @@ export namespace Peer {
64
207
  const obj: any = {
65
208
  addresses: [],
66
209
  protocols: [],
67
- metadata: []
210
+ metadata: new Map<string, Uint8Array>(),
211
+ tags: new Map<string, undefined>()
68
212
  }
69
213
 
70
214
  const end = length == null ? reader.len : reader.pos + length
@@ -79,15 +223,22 @@ export namespace Peer {
79
223
  case 2:
80
224
  obj.protocols.push(reader.string())
81
225
  break
82
- case 3:
83
- obj.metadata.push(Metadata.codec().decode(reader, reader.uint32()))
84
- break
85
226
  case 4:
86
- obj.pubKey = reader.bytes()
227
+ obj.publicKey = reader.bytes()
87
228
  break
88
229
  case 5:
89
230
  obj.peerRecordEnvelope = reader.bytes()
90
231
  break
232
+ case 6: {
233
+ const entry = Peer.Peer$metadataEntry.codec().decode(reader, reader.uint32())
234
+ obj.metadata.set(entry.key, entry.value)
235
+ break
236
+ }
237
+ case 7: {
238
+ const entry = Peer.Peer$tagsEntry.codec().decode(reader, reader.uint32())
239
+ obj.tags.set(entry.key, entry.value)
240
+ break
241
+ }
91
242
  default:
92
243
  reader.skipType(tag & 7)
93
244
  break
@@ -177,29 +328,29 @@ export namespace Address {
177
328
  }
178
329
  }
179
330
 
180
- export interface Metadata {
181
- key: string
182
- value: Uint8Array
331
+ export interface Tag {
332
+ value: number
333
+ expiry?: bigint
183
334
  }
184
335
 
185
- export namespace Metadata {
186
- let _codec: Codec<Metadata>
336
+ export namespace Tag {
337
+ let _codec: Codec<Tag>
187
338
 
188
- export const codec = (): Codec<Metadata> => {
339
+ export const codec = (): Codec<Tag> => {
189
340
  if (_codec == null) {
190
- _codec = message<Metadata>((obj, w, opts = {}) => {
341
+ _codec = message<Tag>((obj, w, opts = {}) => {
191
342
  if (opts.lengthDelimited !== false) {
192
343
  w.fork()
193
344
  }
194
345
 
195
- if ((obj.key != null && obj.key !== '')) {
196
- w.uint32(10)
197
- w.string(obj.key)
346
+ if ((obj.value != null && obj.value !== 0)) {
347
+ w.uint32(8)
348
+ w.uint32(obj.value)
198
349
  }
199
350
 
200
- if ((obj.value != null && obj.value.byteLength > 0)) {
201
- w.uint32(18)
202
- w.bytes(obj.value)
351
+ if (obj.expiry != null) {
352
+ w.uint32(16)
353
+ w.uint64(obj.expiry)
203
354
  }
204
355
 
205
356
  if (opts.lengthDelimited !== false) {
@@ -207,8 +358,7 @@ export namespace Metadata {
207
358
  }
208
359
  }, (reader, length) => {
209
360
  const obj: any = {
210
- key: '',
211
- value: new Uint8Array(0)
361
+ value: 0
212
362
  }
213
363
 
214
364
  const end = length == null ? reader.len : reader.pos + length
@@ -218,10 +368,10 @@ export namespace Metadata {
218
368
 
219
369
  switch (tag >>> 3) {
220
370
  case 1:
221
- obj.key = reader.string()
371
+ obj.value = reader.uint32()
222
372
  break
223
373
  case 2:
224
- obj.value = reader.bytes()
374
+ obj.expiry = reader.uint64()
225
375
  break
226
376
  default:
227
377
  reader.skipType(tag & 7)
@@ -236,11 +386,11 @@ export namespace Metadata {
236
386
  return _codec
237
387
  }
238
388
 
239
- export const encode = (obj: Partial<Metadata>): Uint8Array => {
240
- return encodeMessage(obj, Metadata.codec())
389
+ export const encode = (obj: Partial<Tag>): Uint8Array => {
390
+ return encodeMessage(obj, Tag.codec())
241
391
  }
242
392
 
243
- export const decode = (buf: Uint8Array | Uint8ArrayList): Metadata => {
244
- return decodeMessage(buf, Metadata.codec())
393
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Tag => {
394
+ return decodeMessage(buf, Tag.codec())
245
395
  }
246
396
  }