@dxos/echo-db 2.33.3-dev.5c4af82a → 2.33.3-dev.63b42961

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 (66) hide show
  1. package/dist/src/echo.js +2 -2
  2. package/dist/src/echo.js.map +1 -1
  3. package/dist/src/halo/halo-party.d.ts.map +1 -1
  4. package/dist/src/halo/halo-party.js +1 -1
  5. package/dist/src/halo/halo-party.js.map +1 -1
  6. package/dist/src/halo/identity.d.ts +5 -4
  7. package/dist/src/halo/identity.d.ts.map +1 -1
  8. package/dist/src/halo/identity.js +9 -9
  9. package/dist/src/halo/identity.js.map +1 -1
  10. package/dist/src/invitations/offline-invitation-claimer.d.ts +2 -2
  11. package/dist/src/invitations/offline-invitation-claimer.d.ts.map +1 -1
  12. package/dist/src/invitations/offline-invitation-claimer.js +2 -2
  13. package/dist/src/invitations/offline-invitation-claimer.js.map +1 -1
  14. package/dist/src/parties/data-party.d.ts.map +1 -1
  15. package/dist/src/parties/data-party.js +1 -1
  16. package/dist/src/parties/data-party.js.map +1 -1
  17. package/dist/src/parties/data-party.test.d.ts +2 -0
  18. package/dist/src/parties/data-party.test.d.ts.map +1 -0
  19. package/dist/src/parties/data-party.test.js +129 -0
  20. package/dist/src/parties/data-party.test.js.map +1 -0
  21. package/dist/src/parties/party-factory.d.ts +2 -2
  22. package/dist/src/parties/party-factory.d.ts.map +1 -1
  23. package/dist/src/parties/party-factory.js +11 -10
  24. package/dist/src/parties/party-factory.js.map +1 -1
  25. package/dist/src/parties/party-manager.d.ts +2 -2
  26. package/dist/src/parties/party-manager.d.ts.map +1 -1
  27. package/dist/src/parties/party-manager.js.map +1 -1
  28. package/dist/src/parties/party-manager.test.js +7 -22
  29. package/dist/src/parties/party-manager.test.js.map +1 -1
  30. package/dist/src/pipeline/metadata-store.d.ts.map +1 -1
  31. package/dist/src/pipeline/metadata-store.js +5 -6
  32. package/dist/src/pipeline/metadata-store.js.map +1 -1
  33. package/dist/src/pipeline/party-core.test.js +1 -1
  34. package/dist/src/pipeline/party-core.test.js.map +1 -1
  35. package/dist/src/pipeline/party-processor.d.ts +0 -5
  36. package/dist/src/pipeline/party-processor.d.ts.map +1 -1
  37. package/dist/src/pipeline/party-processor.js +0 -7
  38. package/dist/src/pipeline/party-processor.js.map +1 -1
  39. package/dist/src/protocol/identity-credentials.d.ts +22 -0
  40. package/dist/src/protocol/identity-credentials.d.ts.map +1 -0
  41. package/dist/src/protocol/identity-credentials.js +50 -0
  42. package/dist/src/protocol/identity-credentials.js.map +1 -0
  43. package/dist/src/protocol/party-protocol-factory.d.ts +3 -4
  44. package/dist/src/protocol/party-protocol-factory.d.ts.map +1 -1
  45. package/dist/src/protocol/party-protocol-factory.js +12 -15
  46. package/dist/src/protocol/party-protocol-factory.js.map +1 -1
  47. package/dist/src/snapshots/snapshot-store.d.ts.map +1 -1
  48. package/dist/src/snapshots/snapshot-store.js +5 -6
  49. package/dist/src/snapshots/snapshot-store.js.map +1 -1
  50. package/dist/tsconfig.tsbuildinfo +1 -1
  51. package/package.json +17 -17
  52. package/src/echo.ts +1 -1
  53. package/src/halo/halo-party.ts +1 -2
  54. package/src/halo/identity.ts +14 -13
  55. package/src/invitations/offline-invitation-claimer.ts +5 -5
  56. package/src/parties/data-party.test.ts +212 -0
  57. package/src/parties/data-party.ts +1 -2
  58. package/src/parties/party-factory.ts +13 -12
  59. package/src/parties/party-manager.test.ts +8 -42
  60. package/src/parties/party-manager.ts +2 -2
  61. package/src/pipeline/metadata-store.ts +5 -6
  62. package/src/pipeline/party-core.test.ts +2 -4
  63. package/src/pipeline/party-processor.ts +0 -13
  64. package/src/protocol/identity-credentials.ts +78 -0
  65. package/src/protocol/party-protocol-factory.ts +13 -17
  66. package/src/snapshots/snapshot-store.ts +5 -6
@@ -9,6 +9,7 @@ import { Filter, KeyChain, KeyRecord, Keyring, KeyType, SignedMessage, Signer }
9
9
  import { failUndefined } from '@dxos/debug';
10
10
 
11
11
  import { CredentialsSigner } from '../protocol/credentials-signer';
12
+ import { IdentityCredentials } from '../protocol/identity-credentials';
12
13
  import { ContactManager } from './contact-manager';
13
14
  import { HaloParty } from './halo-party';
14
15
  import { Preferences } from './preferences';
@@ -20,7 +21,7 @@ const log = debug('dxos:echo-db:identity');
20
21
  *
21
22
  * Acts as a read-only view into IdentityManager.
22
23
  */
23
- export class Identity {
24
+ export class Identity implements IdentityCredentials {
24
25
  private readonly _identityKey: KeyRecord;
25
26
  private readonly _deviceKey: KeyRecord;
26
27
  private readonly _deviceKeyChain: KeyChain;
@@ -42,6 +43,10 @@ export class Identity {
42
43
  return this._keyring;
43
44
  }
44
45
 
46
+ get keyring (): Keyring {
47
+ return this._keyring;
48
+ }
49
+
45
50
  get identityKey (): KeyRecord {
46
51
  return this._identityKey;
47
52
  }
@@ -54,14 +59,6 @@ export class Identity {
54
59
  return this._deviceKeyChain;
55
60
  }
56
61
 
57
- get preferences (): Preferences {
58
- return this._halo.preferences;
59
- }
60
-
61
- get contacts (): ContactManager {
62
- return this._halo.contacts;
63
- }
64
-
65
62
  get displayName (): string | undefined {
66
63
  return this.identityInfo?.signed.payload.displayName;
67
64
  }
@@ -78,6 +75,14 @@ export class Identity {
78
75
  return this._halo.identityGenesis ?? failUndefined();
79
76
  }
80
77
 
78
+ get preferences (): Preferences {
79
+ return this._halo.preferences;
80
+ }
81
+
82
+ get contacts (): ContactManager {
83
+ return this._halo.contacts;
84
+ }
85
+
81
86
  /**
82
87
  * HALO party. Must be open.
83
88
  */
@@ -85,10 +90,6 @@ export class Identity {
85
90
  return this._halo;
86
91
  }
87
92
 
88
- get keyring () {
89
- return this._keyring;
90
- }
91
-
92
93
  createCredentialsSigner (): CredentialsSigner {
93
94
  return new CredentialsSigner(
94
95
  this._keyring,
@@ -24,7 +24,7 @@ import { keyToBuffer, keyToString, PublicKey, randomBytes } from '@dxos/crypto';
24
24
  import { FullyConnectedTopology, NetworkManager } from '@dxos/network-manager';
25
25
 
26
26
  import { InvalidInvitationError } from '../errors';
27
- import { Identity } from '../halo';
27
+ import { CredentialsSigner } from '../protocol';
28
28
  import { greetingProtocolProvider } from './greeting-protocol-provider';
29
29
  import { GreetingState } from './greeting-responder';
30
30
  import { InvitationDescriptor, InvitationDescriptorType } from './invitation-descriptor';
@@ -169,17 +169,17 @@ export class OfflineInvitationClaimer {
169
169
  }
170
170
 
171
171
  // The secretProvider should provide an `Auth` message signed directly by the Identity key.
172
- static createSecretProvider (identity: Identity): SecretProvider {
172
+ static createSecretProvider (credentials: CredentialsSigner): SecretProvider {
173
173
  return async (info?: SecretInfo) => {
174
174
  return Buffer.from(codec.encode(
175
175
  /* The signed portion of the Auth message includes the ID and authNonce provided
176
176
  * by the `info` object. These values will be validated on the other end.
177
177
  */
178
178
  createAuthMessage(
179
- identity.signer,
179
+ credentials.signer,
180
180
  info!.id.value,
181
- identity.identityKey,
182
- identity.deviceKeyChain,
181
+ credentials.getIdentityKey(),
182
+ credentials.getDeviceSigningKeys(),
183
183
  undefined,
184
184
  info!.authNonce.value)
185
185
  ));
@@ -0,0 +1,212 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import expect from 'expect';
6
+ import { it as test } from 'mocha';
7
+
8
+ import { createKeyAdmitMessage, createPartyGenesisMessage, defaultSecretProvider, KeyHint, Keyring, KeyType, codec as haloCodec } from '@dxos/credentials';
9
+ import { PublicKey } from '@dxos/crypto';
10
+ import { codec } from '@dxos/echo-protocol';
11
+ import { FeedStore } from '@dxos/feed-store';
12
+ import { ModelFactory } from '@dxos/model-factory';
13
+ import { NetworkManager } from '@dxos/network-manager';
14
+ import { ObjectModel } from '@dxos/object-model';
15
+ import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
16
+
17
+ import { createDataPartyAdmissionMessages, defaultInvitationAuthenticator, GreetingInitiator } from '../invitations';
18
+ import { MetadataStore, PartyFeedProvider } from '../pipeline';
19
+ import { createAuthenticator, createCredentialsProvider } from '../protocol';
20
+ import { createTestIdentityCredentials, deriveTestDeviceCredentials, IdentityCredentials } from '../protocol/identity-credentials';
21
+ import { SnapshotStore } from '../snapshots';
22
+ import { createRamStorage } from '../util';
23
+ import { DataParty } from './data-party';
24
+
25
+ describe('DataParty', () => {
26
+ const createParty = async (identity: IdentityCredentials, partyKey: PublicKey, hints: KeyHint[]) => {
27
+ const metadataStore = new MetadataStore(createRamStorage());
28
+ const feedStore = new FeedStore(createStorage('', StorageType.RAM), { valueEncoding: codec });
29
+ const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
30
+ const modelFactory = new ModelFactory().registerModel(ObjectModel);
31
+ const networkManager = new NetworkManager();
32
+ const partyFeedProvider = new PartyFeedProvider(metadataStore, identity.keyring, feedStore, partyKey);
33
+
34
+ return new DataParty(
35
+ partyKey,
36
+ modelFactory,
37
+ snapshotStore,
38
+ partyFeedProvider,
39
+ identity.createCredentialsSigner(),
40
+ identity.preferences,
41
+ networkManager,
42
+ hints
43
+ );
44
+ };
45
+
46
+ test('open & close', async () => {
47
+ const keyring = new Keyring();
48
+ const identity = await createTestIdentityCredentials(keyring);
49
+ const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
50
+ const party = await createParty(identity, partyKey.publicKey, []);
51
+
52
+ await party.open();
53
+ await party.close();
54
+ });
55
+
56
+ test('edit data', async () => {
57
+ const keyring = new Keyring();
58
+ const identity = await createTestIdentityCredentials(keyring);
59
+ const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
60
+ const party = await createParty(identity, partyKey.publicKey, []);
61
+ await party.open();
62
+
63
+ const feed = await party.feedProvider.createOrOpenWritableFeed();
64
+ await party.processor.writeHaloMessage(createPartyGenesisMessage(
65
+ keyring,
66
+ partyKey,
67
+ feed.key,
68
+ partyKey
69
+ ));
70
+
71
+ await party.database.createItem({ type: 'test:item' });
72
+
73
+ await party.close();
74
+ });
75
+
76
+ test('authenticates its own credentials', async () => {
77
+ const keyring = new Keyring();
78
+ const identity = await createTestIdentityCredentials(keyring);
79
+ const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
80
+
81
+ const party = await createParty(identity, partyKey.publicKey, []);
82
+ await party.open();
83
+ const feed = await party.feedProvider.createOrOpenWritableFeed();
84
+ await party.processor.writeHaloMessage(createPartyGenesisMessage(
85
+ keyring,
86
+ partyKey,
87
+ feed.key,
88
+ partyKey
89
+ ));
90
+
91
+ const authenticator = createAuthenticator(party.processor, identity.createCredentialsSigner());
92
+ const credentialsProvider = createCredentialsProvider(identity.createCredentialsSigner(), party.key, feed.key);
93
+
94
+ const wrappedCredentials = haloCodec.decode(credentialsProvider.get());
95
+ expect(await authenticator.authenticate(wrappedCredentials.payload)).toEqual(true);
96
+
97
+ await party.close();
98
+ });
99
+
100
+ test('authenticates another device', async () => {
101
+ const keyring = new Keyring();
102
+ const identityA = await createTestIdentityCredentials(keyring);
103
+ const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
104
+
105
+ const party = await createParty(identityA, partyKey.publicKey, []);
106
+ await party.open();
107
+ const feed = await party.feedProvider.createOrOpenWritableFeed();
108
+ await party.processor.writeHaloMessage(createPartyGenesisMessage(
109
+ keyring,
110
+ partyKey,
111
+ feed.key,
112
+ partyKey
113
+ ));
114
+ const authenticator = createAuthenticator(party.processor, identityA.createCredentialsSigner());
115
+
116
+ const identityB = await deriveTestDeviceCredentials(identityA);
117
+ const credentialsProvider = createCredentialsProvider(identityB.createCredentialsSigner(), party.key, feed.key);
118
+
119
+ const wrappedCredentials = haloCodec.decode(credentialsProvider.get());
120
+ expect(await authenticator.authenticate(wrappedCredentials.payload)).toEqual(true);
121
+
122
+ await party.close();
123
+ });
124
+
125
+ test('two instances replicating', async () => {
126
+ const keyring = new Keyring();
127
+ const identityA = await createTestIdentityCredentials(keyring);
128
+ const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
129
+
130
+ const partyA = await createParty(identityA, partyKey.publicKey, []);
131
+ await partyA.open();
132
+ const feedA = await partyA.feedProvider.createOrOpenWritableFeed();
133
+ await partyA.processor.writeHaloMessage(createPartyGenesisMessage(
134
+ keyring,
135
+ partyKey,
136
+ feedA.key,
137
+ partyKey
138
+ ));
139
+ await partyA.processor.writeHaloMessage(createKeyAdmitMessage(
140
+ keyring,
141
+ partyKey.publicKey,
142
+ identityA.identityKey,
143
+ [partyKey]
144
+ ));
145
+
146
+ const identityB = await deriveTestDeviceCredentials(identityA);
147
+ const partyB = await createParty(identityB, partyKey.publicKey, [
148
+ { type: KeyType.FEED, publicKey: feedA.key }
149
+ ]);
150
+ await partyB.open();
151
+
152
+ await partyA.database.createItem({ type: 'test:item-a' });
153
+ await partyB.database.waitForItem({ type: 'test:item-a' });
154
+
155
+ await partyB.database.createItem({ type: 'test:item-b' });
156
+ await partyA.database.waitForItem({ type: 'test:item-b' });
157
+
158
+ await partyA.close();
159
+ await partyB.close();
160
+ });
161
+
162
+ test('invitations', async () => {
163
+ const identityA = await createTestIdentityCredentials(new Keyring());
164
+ const partyKeyA = await identityA.keyring.createKeyRecord({ type: KeyType.PARTY });
165
+
166
+ const partyA = await createParty(identityA, partyKeyA.publicKey, []);
167
+ await partyA.open();
168
+ const feedA = await partyA.feedProvider.createOrOpenWritableFeed();
169
+ await partyA.processor.writeHaloMessage(createPartyGenesisMessage(
170
+ identityA.keyring,
171
+ partyKeyA,
172
+ feedA.key,
173
+ partyKeyA
174
+ ));
175
+ await partyA.processor.writeHaloMessage(createKeyAdmitMessage(
176
+ identityA.keyring,
177
+ partyKeyA.publicKey,
178
+ identityA.identityKey,
179
+ [partyKeyA]
180
+ ));
181
+
182
+ const invitation = await partyA.invitationManager.createInvitation(defaultInvitationAuthenticator);
183
+
184
+ const identityB = await createTestIdentityCredentials(new Keyring());
185
+ const initiator = new GreetingInitiator(
186
+ new NetworkManager(),
187
+ invitation,
188
+ async (partyKey, nonce) => [createDataPartyAdmissionMessages(
189
+ identityB.createCredentialsSigner(),
190
+ partyKey,
191
+ identityB.identityGenesis,
192
+ nonce
193
+ )]
194
+ );
195
+
196
+ await initiator.connect();
197
+ const { partyKey: partyKeyB, hints: hintsB } = await initiator.redeemInvitation(defaultSecretProvider);
198
+ expect(partyKeyB.equals(partyKeyA.publicKey));
199
+ const partyB = await createParty(identityB, partyKeyB, hintsB);
200
+ await partyB.open();
201
+ await initiator.destroy();
202
+
203
+ await partyA.database.createItem({ type: 'test:item-a' });
204
+ await partyB.database.waitForItem({ type: 'test:item-a' });
205
+
206
+ await partyB.database.createItem({ type: 'test:item-b' });
207
+ await partyA.database.waitForItem({ type: 'test:item-b' });
208
+
209
+ await partyA.close();
210
+ await partyB.close();
211
+ });
212
+ });
@@ -175,8 +175,7 @@ export class DataParty {
175
175
  this._networkManager,
176
176
  this._feedProvider,
177
177
  deviceKey.publicKey,
178
- createCredentialsProvider(this._credentialsSigner, this._partyCore.key, writeFeed.key),
179
- this._partyCore.processor.getActiveFeedSet()
178
+ createCredentialsProvider(this._credentialsSigner, this._partyCore.key, writeFeed.key)
180
179
  );
181
180
 
182
181
  await this._protocol.start([
@@ -22,12 +22,12 @@ import { NetworkManager } from '@dxos/network-manager';
22
22
  import { ObjectModel } from '@dxos/object-model';
23
23
 
24
24
  import { IdentityNotInitializedError } from '../errors';
25
- import { IdentityProvider } from '../halo';
26
25
  import {
27
26
  createDataPartyAdmissionMessages,
28
27
  GreetingInitiator, InvitationDescriptor, InvitationDescriptorType, OfflineInvitationClaimer
29
28
  } from '../invitations';
30
29
  import { PartyFeedProvider, PartyOptions } from '../pipeline';
30
+ import { IdentityCredentialsProvider } from '../protocol/identity-credentials';
31
31
  import { SnapshotStore } from '../snapshots';
32
32
  import { DataParty, PARTY_ITEM_TYPE } from './data-party';
33
33
 
@@ -38,7 +38,7 @@ const log = debug('dxos:echo-db:party-factory');
38
38
  */
39
39
  export class PartyFactory {
40
40
  constructor (
41
- private readonly _identityProvider: IdentityProvider,
41
+ private readonly _identityProvider: IdentityCredentialsProvider,
42
42
  private readonly _networkManager: NetworkManager,
43
43
  private readonly _modelFactory: ModelFactory,
44
44
  private readonly _snapshotStore: SnapshotStore,
@@ -64,7 +64,7 @@ export class PartyFactory {
64
64
 
65
65
  // PartyGenesis (self-signed by Party).
66
66
  await party.processor.writeHaloMessage(createPartyGenesisMessage(
67
- identity.signer,
67
+ identity.keyring,
68
68
  partyKey,
69
69
  writableFeed.key,
70
70
  partyKey)
@@ -72,15 +72,16 @@ export class PartyFactory {
72
72
 
73
73
  // KeyAdmit (IdentityGenesis in an Envelope signed by Party).
74
74
  await party.processor.writeHaloMessage(createEnvelopeMessage(
75
- identity.signer,
75
+ identity.keyring,
76
76
  partyKey.publicKey,
77
77
  wrapMessage(identity.identityGenesis),
78
78
  [partyKey])
79
79
  );
80
80
 
81
81
  // FeedAdmit (signed by the Device KeyChain).
82
+ // TODO(dmaretskyi): Is this really needed since a feed is already admitted by party genesis message.
82
83
  await party.processor.writeHaloMessage(createFeedAdmitMessage(
83
- identity.signer,
84
+ identity.keyring,
84
85
  partyKey.publicKey,
85
86
  writableFeed.key,
86
87
  [identity.deviceKeyChain]
@@ -89,7 +90,7 @@ export class PartyFactory {
89
90
  // IdentityInfo in an Envelope signed by the Device KeyChain.
90
91
  if (identity.identityInfo) {
91
92
  await party.processor.writeHaloMessage(createEnvelopeMessage(
92
- identity.signer,
93
+ identity.keyring,
93
94
  partyKey.publicKey,
94
95
  wrapMessage(identity.identityInfo),
95
96
  [identity.deviceKeyChain]
@@ -141,7 +142,7 @@ export class PartyFactory {
141
142
  assert(signingKey, 'No device key or keychain.');
142
143
  // Write the Feed genesis message.
143
144
  await party.processor.writeHaloMessage(createFeedAdmitMessage(
144
- identity.signer,
145
+ identity.keyring,
145
146
  partyKey,
146
147
  feedKeyPair.publicKey,
147
148
  [signingKey]
@@ -224,7 +225,7 @@ export class PartyFactory {
224
225
  const infoMessage = identity.identityInfo;
225
226
  if (infoMessage) {
226
227
  await party.processor.writeHaloMessage(createEnvelopeMessage(
227
- identity.signer,
228
+ identity.keyring,
228
229
  partyKey,
229
230
  wrapMessage(infoMessage),
230
231
  [identity.deviceKeyChain]
@@ -250,7 +251,7 @@ export class PartyFactory {
250
251
 
251
252
  // PartyGenesis (self-signed by Party).
252
253
  await party.processor.writeHaloMessage(createPartyGenesisMessage(
253
- identity.signer,
254
+ identity.keyring,
254
255
  partyKey,
255
256
  writableFeed.key,
256
257
  partyKey)
@@ -258,7 +259,7 @@ export class PartyFactory {
258
259
 
259
260
  // KeyAdmit (IdentityGenesis in an Envelope signed by Party).
260
261
  await party.processor.writeHaloMessage(createEnvelopeMessage(
261
- identity.signer,
262
+ identity.keyring,
262
263
  partyKey.publicKey,
263
264
  wrapMessage(identity.identityGenesis),
264
265
  [partyKey]
@@ -266,7 +267,7 @@ export class PartyFactory {
266
267
 
267
268
  // FeedAdmit (signed by the Device KeyChain).
268
269
  await party.processor.writeHaloMessage(createFeedAdmitMessage(
269
- identity.signer,
270
+ identity.keyring,
270
271
  partyKey.publicKey,
271
272
  writableFeed.key,
272
273
  [identity.deviceKeyChain]
@@ -275,7 +276,7 @@ export class PartyFactory {
275
276
  // IdentityInfo in an Envelope signed by the Device KeyChain.
276
277
  if (identity.identityInfo) {
277
278
  await party.processor.writeHaloMessage(createEnvelopeMessage(
278
- identity.signer,
279
+ identity.keyring,
279
280
  partyKey.publicKey,
280
281
  wrapMessage(identity.identityInfo),
281
282
  [identity.deviceKeyChain]
@@ -33,9 +33,9 @@ import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
33
33
  import { afterTest, testTimeout } from '@dxos/testutils';
34
34
 
35
35
  import { Item } from '../api';
36
- import { HaloFactory, Identity, IdentityManager } from '../halo';
37
36
  import { defaultInvitationAuthenticator, OfflineInvitationClaimer } from '../invitations';
38
37
  import { MetadataStore, PartyFeedProvider } from '../pipeline';
38
+ import { createTestIdentityCredentials } from '../protocol/identity-credentials';
39
39
  import { SnapshotStore } from '../snapshots';
40
40
  import { messageLogger } from '../testing';
41
41
  import { createRamStorage } from '../util';
@@ -58,33 +58,12 @@ const setup = async () => {
58
58
  const keyring = new Keyring();
59
59
  const metadataStore = new MetadataStore(createRamStorage());
60
60
  const feedStore = new FeedStore(createStorage('', StorageType.RAM), { valueEncoding: codec });
61
-
62
- const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
63
-
64
- assert(keyring.keys.length === 1);
65
-
66
61
  const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
67
62
  const modelFactory = new ModelFactory().registerModel(ObjectModel);
68
63
  const networkManager = new NetworkManager();
69
64
  const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey);
70
65
 
71
- const haloFactory = new HaloFactory(
72
- networkManager,
73
- modelFactory,
74
- snapshotStore,
75
- feedProviderFactory,
76
- keyring,
77
- {
78
- writeLogger: messageLogger('<<<'),
79
- readLogger: messageLogger('>>>')
80
- }
81
- );
82
- const haloParty = await haloFactory.createHalo({
83
- identityDisplayName: identityKey.publicKey.humanize()
84
- });
85
- afterTest(() => haloParty.close());
86
- const identity = new Identity(keyring, haloParty);
87
-
66
+ const identity = await createTestIdentityCredentials(keyring);
88
67
  const partyFactory = new PartyFactory(
89
68
  () => identity,
90
69
  networkManager,
@@ -171,33 +150,22 @@ describe('Party manager', () => {
171
150
  test('Create from cold start', async () => {
172
151
  const storage = createStorage('', StorageType.RAM);
173
152
  const feedStore = new FeedStore(storage, { valueEncoding: codec });
174
-
175
153
  const keyring = new Keyring();
176
154
  const metadataStore = new MetadataStore(createRamStorage());
177
-
178
- const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
179
- await keyring.createKeyRecord({ type: KeyType.DEVICE });
180
-
181
155
  const modelFactory = new ModelFactory().registerModel(ObjectModel);
182
156
  const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
183
157
  const networkManager = new NetworkManager();
184
158
  const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey);
159
+
160
+ const identity = await createTestIdentityCredentials(keyring);
185
161
  const partyFactory = new PartyFactory(
186
- () => identityManager.identity,
162
+ () => identity,
187
163
  networkManager,
188
164
  modelFactory,
189
165
  snapshotStore,
190
166
  feedProviderFactory
191
167
  );
192
- const haloFactory: HaloFactory = new HaloFactory(
193
- networkManager,
194
- modelFactory,
195
- snapshotStore,
196
- feedProviderFactory,
197
- keyring
198
- );
199
- const identityManager = new IdentityManager(keyring, haloFactory, metadataStore);
200
- const partyManager = new PartyManager(metadataStore, snapshotStore, () => identityManager.identity, partyFactory);
168
+ const partyManager = new PartyManager(metadataStore, snapshotStore, () => identity, partyFactory);
201
169
 
202
170
  /* TODO(telackey): Injecting "raw" Parties into the feeds behind the scenes seems fishy to me, as it writes the
203
171
  * Party messages in a slightly different way than the code inside PartyFactory does, and so could easily diverge
@@ -221,7 +189,7 @@ describe('Party manager', () => {
221
189
  assert(feedKey);
222
190
 
223
191
  const feedStream = createWritableFeedStream(feed);
224
- feedStream.write({ halo: createPartyGenesisMessage(keyring, partyKey, feedKey.publicKey, identityKey) });
192
+ feedStream.write({ halo: createPartyGenesisMessage(keyring, partyKey, feedKey.publicKey, identity.identityKey) });
225
193
  feedStream.write({
226
194
  echo: checkType<EchoEnvelope>({
227
195
  itemId: 'foo',
@@ -235,8 +203,6 @@ describe('Party manager', () => {
235
203
  }
236
204
 
237
205
  // Open.
238
- await identityManager.createHalo();
239
- afterTest(() => identityManager.close());
240
206
  await partyManager.open();
241
207
  expect(partyManager.parties).toHaveLength(numParties);
242
208
  await partyManager.close();
@@ -450,7 +416,7 @@ describe('Party manager', () => {
450
416
  // Redeem the invitation on B.
451
417
  expect(partyManagerB.parties).toHaveLength(0);
452
418
  const partyB = await partyManagerB.joinParty(invitationDescriptor,
453
- OfflineInvitationClaimer.createSecretProvider(identityB));
419
+ OfflineInvitationClaimer.createSecretProvider(identityB.createCredentialsSigner()));
454
420
  expect(partyB).toBeDefined();
455
421
  log(`Joined ${partyB.key.toHex()}`);
456
422
 
@@ -13,9 +13,9 @@ import { timed } from '@dxos/debug';
13
13
  import { PartyKey, PartySnapshot } from '@dxos/echo-protocol';
14
14
  import { ComplexMap, boolGuard } from '@dxos/util';
15
15
 
16
- import { IdentityProvider } from '../halo';
17
16
  import { InvitationDescriptor } from '../invitations';
18
17
  import { MetadataStore } from '../pipeline';
18
+ import { IdentityCredentialsProvider } from '../protocol/identity-credentials';
19
19
  import { SnapshotStore } from '../snapshots';
20
20
  import { DataParty, PARTY_ITEM_TYPE, PARTY_TITLE_PROPERTY } from './data-party';
21
21
  import { PartyFactory } from './party-factory';
@@ -51,7 +51,7 @@ export class PartyManager {
51
51
  constructor (
52
52
  private readonly _metadataStore: MetadataStore,
53
53
  private readonly _snapshotStore: SnapshotStore,
54
- private readonly _identityProvider: IdentityProvider,
54
+ private readonly _identityProvider: IdentityCredentialsProvider,
55
55
  private readonly _partyFactory: PartyFactory
56
56
  ) {}
57
57
 
@@ -4,7 +4,6 @@
4
4
 
5
5
  import assert from 'assert';
6
6
  import debug from 'debug';
7
- import pify from 'pify';
8
7
 
9
8
  import { PublicKey } from '@dxos/crypto';
10
9
  import { failUndefined } from '@dxos/debug';
@@ -50,12 +49,12 @@ export class MetadataStore {
50
49
  async load (): Promise<void> {
51
50
  const file = this._storage.createOrOpen('EchoMetadata');
52
51
  try {
53
- const { size } = await pify(file.stat.bind(file))();
52
+ const { size } = await file.stat();
54
53
  if (size === 0) {
55
54
  return;
56
55
  }
57
56
 
58
- const data = await pify(file.read.bind(file))(0, size);
57
+ const data = await file.read(0, size);
59
58
  this._metadata = schema.getCodecForType('dxos.echo.metadata.EchoMetadata').decode(data);
60
59
  } catch (err: any) {
61
60
  if (err.code === 'ENOENT') {
@@ -64,7 +63,7 @@ export class MetadataStore {
64
63
  throw err;
65
64
  }
66
65
  } finally {
67
- await pify(file.close.bind(file))();
66
+ await file.close();
68
67
  }
69
68
  }
70
69
 
@@ -80,9 +79,9 @@ export class MetadataStore {
80
79
 
81
80
  try {
82
81
  const encoded = Buffer.from(schema.getCodecForType('dxos.echo.metadata.EchoMetadata').encode(data));
83
- await pify(file.write.bind(file))(0, encoded);
82
+ await file.write(0, encoded);
84
83
  } finally {
85
- await pify(file.close.bind(file))();
84
+ await file.close();
86
85
  }
87
86
  }
88
87
 
@@ -325,12 +325,10 @@ describe('PartyCore', () => {
325
325
 
326
326
  createTestProtocolPair(
327
327
  new ReplicatorProtocolPluginFactory(
328
- peer1.partyFeedProvider,
329
- peer1.party.processor.getActiveFeedSet()
328
+ peer1.partyFeedProvider
330
329
  ).createPlugins().map(r => r.createExtension()),
331
330
  new ReplicatorProtocolPluginFactory(
332
- partyFeedProvider,
333
- peer1.party.processor.getActiveFeedSet()
331
+ partyFeedProvider
334
332
  ).createPlugins().map(r => r.createExtension())
335
333
  );
336
334
 
@@ -20,11 +20,6 @@ import { jsonReplacer } from '@dxos/util';
20
20
 
21
21
  const log = debug('dxos:echo-db:party-processor');
22
22
 
23
- export interface FeedSetProvider {
24
- get(): FeedKey[]
25
- added: Event<FeedKey>
26
- }
27
-
28
23
  /**
29
24
  * TODO(burdon): Wrapper/Bridge between HALO APIs.
30
25
  */
@@ -108,14 +103,6 @@ export class PartyProcessor {
108
103
  return this._state.getAdmittedBy(feedKey);
109
104
  }
110
105
 
111
- // TODO(burdon): Rename xxxProvider.
112
- getActiveFeedSet (): FeedSetProvider {
113
- return {
114
- get: () => this.feedKeys,
115
- added: this.feedAdded
116
- };
117
- }
118
-
119
106
  getOfflineInvitation (invitationID: Buffer) {
120
107
  return this._state.getInvitation(invitationID);
121
108
  }