cojson 0.18.33 → 0.18.35

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 (93) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +17 -0
  3. package/dist/SyncStateManager.d.ts.map +1 -1
  4. package/dist/SyncStateManager.js +2 -2
  5. package/dist/SyncStateManager.js.map +1 -1
  6. package/dist/coValueContentMessage.d.ts +5 -2
  7. package/dist/coValueContentMessage.d.ts.map +1 -1
  8. package/dist/coValueContentMessage.js +15 -0
  9. package/dist/coValueContentMessage.js.map +1 -1
  10. package/dist/coValueCore/SessionMap.d.ts +4 -3
  11. package/dist/coValueCore/SessionMap.d.ts.map +1 -1
  12. package/dist/coValueCore/SessionMap.js +21 -30
  13. package/dist/coValueCore/SessionMap.js.map +1 -1
  14. package/dist/coValueCore/coValueCore.d.ts +14 -6
  15. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  16. package/dist/coValueCore/coValueCore.js +32 -52
  17. package/dist/coValueCore/coValueCore.js.map +1 -1
  18. package/dist/coValueCore/verifiedState.d.ts +6 -4
  19. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  20. package/dist/coValueCore/verifiedState.js +21 -7
  21. package/dist/coValueCore/verifiedState.js.map +1 -1
  22. package/dist/coValues/group.d.ts.map +1 -1
  23. package/dist/coValues/group.js +20 -15
  24. package/dist/coValues/group.js.map +1 -1
  25. package/dist/knownState.d.ts +9 -1
  26. package/dist/knownState.d.ts.map +1 -1
  27. package/dist/knownState.js +29 -3
  28. package/dist/knownState.js.map +1 -1
  29. package/dist/localNode.d.ts +7 -2
  30. package/dist/localNode.d.ts.map +1 -1
  31. package/dist/localNode.js +10 -15
  32. package/dist/localNode.js.map +1 -1
  33. package/dist/queue/LocalTransactionsSyncQueue.d.ts +10 -9
  34. package/dist/queue/LocalTransactionsSyncQueue.d.ts.map +1 -1
  35. package/dist/queue/LocalTransactionsSyncQueue.js +53 -47
  36. package/dist/queue/LocalTransactionsSyncQueue.js.map +1 -1
  37. package/dist/storage/knownState.js +2 -2
  38. package/dist/storage/knownState.js.map +1 -1
  39. package/dist/sync.d.ts +1 -2
  40. package/dist/sync.d.ts.map +1 -1
  41. package/dist/sync.js +15 -19
  42. package/dist/sync.js.map +1 -1
  43. package/dist/tests/coPlainText.test.js +13 -14
  44. package/dist/tests/coPlainText.test.js.map +1 -1
  45. package/dist/tests/coValueContentMessage.test.js +130 -1
  46. package/dist/tests/coValueContentMessage.test.js.map +1 -1
  47. package/dist/tests/coValueCore.isCompletelyDownloaded.test.js +3 -2
  48. package/dist/tests/coValueCore.isCompletelyDownloaded.test.js.map +1 -1
  49. package/dist/tests/coValueCore.isStreaming.test.js +54 -3
  50. package/dist/tests/coValueCore.isStreaming.test.js.map +1 -1
  51. package/dist/tests/coValueCore.test.js +3 -6
  52. package/dist/tests/coValueCore.test.js.map +1 -1
  53. package/dist/tests/group.childKeyRotation.test.js +9 -9
  54. package/dist/tests/group.childKeyRotation.test.js.map +1 -1
  55. package/dist/tests/knownState.test.js +82 -10
  56. package/dist/tests/knownState.test.js.map +1 -1
  57. package/dist/tests/sync.load.test.js +29 -29
  58. package/dist/tests/sync.mesh.test.js +38 -31
  59. package/dist/tests/sync.mesh.test.js.map +1 -1
  60. package/dist/tests/sync.storage.test.js +24 -23
  61. package/dist/tests/sync.storage.test.js.map +1 -1
  62. package/dist/tests/sync.storageAsync.test.js +24 -23
  63. package/dist/tests/sync.storageAsync.test.js.map +1 -1
  64. package/dist/tests/sync.upload.test.js +58 -58
  65. package/dist/tests/testUtils.d.ts +11 -9
  66. package/dist/tests/testUtils.d.ts.map +1 -1
  67. package/dist/tests/testUtils.js +26 -16
  68. package/dist/tests/testUtils.js.map +1 -1
  69. package/package.json +3 -4
  70. package/src/SyncStateManager.ts +8 -2
  71. package/src/coValueContentMessage.ts +29 -2
  72. package/src/coValueCore/SessionMap.ts +41 -31
  73. package/src/coValueCore/coValueCore.ts +41 -74
  74. package/src/coValueCore/verifiedState.ts +36 -11
  75. package/src/coValues/group.ts +40 -27
  76. package/src/knownState.ts +39 -4
  77. package/src/localNode.ts +16 -21
  78. package/src/queue/LocalTransactionsSyncQueue.ts +77 -93
  79. package/src/storage/knownState.ts +2 -2
  80. package/src/sync.ts +24 -26
  81. package/src/tests/coPlainText.test.ts +13 -14
  82. package/src/tests/coValueContentMessage.test.ts +197 -2
  83. package/src/tests/coValueCore.isCompletelyDownloaded.test.ts +3 -2
  84. package/src/tests/coValueCore.isStreaming.test.ts +84 -2
  85. package/src/tests/coValueCore.test.ts +7 -10
  86. package/src/tests/group.childKeyRotation.test.ts +9 -9
  87. package/src/tests/knownState.test.ts +106 -9
  88. package/src/tests/sync.load.test.ts +29 -29
  89. package/src/tests/sync.mesh.test.ts +38 -31
  90. package/src/tests/sync.storage.test.ts +24 -23
  91. package/src/tests/sync.storageAsync.test.ts +24 -23
  92. package/src/tests/sync.upload.test.ts +58 -58
  93. package/src/tests/testUtils.ts +30 -18
@@ -1,5 +1,4 @@
1
1
  import { UpDownCounter, ValueType, metrics } from "@opentelemetry/api";
2
- import { Result, err, ok } from "neverthrow";
3
2
  import type { PeerState } from "../PeerState.js";
4
3
  import type { RawCoValue } from "../coValue.js";
5
4
  import type { ControlledAccountOrAgent } from "../coValues/account.js";
@@ -201,7 +200,7 @@ export class CoValueCore {
201
200
  }
202
201
  | {
203
202
  type: "errored";
204
- error: TryAddTransactionsError;
203
+ error: unknown;
205
204
  }
206
205
  >();
207
206
 
@@ -474,12 +473,10 @@ export class CoValueCore {
474
473
  new SessionMap(this.id, this.node.crypto, streamingKnownState),
475
474
  );
476
475
 
477
- this.resetKnownStateCache();
478
-
479
476
  return true;
480
477
  }
481
478
 
482
- markErrored(peerId: PeerID, error: TryAddTransactionsError) {
479
+ markErrored(peerId: PeerID, error: unknown) {
483
480
  const previousState = this.loadingState;
484
481
  this.loadingStatuses.set(peerId, { type: "errored", error });
485
482
  this.updateCounter(previousState);
@@ -531,27 +528,18 @@ export class CoValueCore {
531
528
  .then((core) => core.getCurrentContent());
532
529
  }
533
530
 
534
- private _cachedKnownStateWithStreaming?: CoValueKnownState;
535
531
  /**
536
532
  * Returns the known state considering the known state of the streaming source
537
533
  *
538
534
  * Used to correctly manage the content & subscriptions during the content streaming process
539
535
  */
540
536
  knownStateWithStreaming(): CoValueKnownState {
541
- if (this._cachedKnownStateWithStreaming) {
542
- return this._cachedKnownStateWithStreaming;
543
- }
544
-
545
- const knownState = this.verified
546
- ? cloneKnownState(this.verified.knownStateWithStreaming())
547
- : emptyKnownState(this.id);
548
-
549
- this._cachedKnownStateWithStreaming = knownState;
550
-
551
- return knownState;
537
+ return (
538
+ this.verified?.immutableKnownStateWithStreaming() ??
539
+ emptyKnownState(this.id)
540
+ );
552
541
  }
553
542
 
554
- private _cachedKnownState?: CoValueKnownState;
555
543
  /**
556
544
  * Returns the known state of the CoValue
557
545
  *
@@ -560,17 +548,7 @@ export class CoValueCore {
560
548
  * On change the knownState is invalidated and a new object is returned.
561
549
  */
562
550
  knownState(): CoValueKnownState {
563
- if (this._cachedKnownState) {
564
- return this._cachedKnownState;
565
- }
566
-
567
- const knownState = this.verified
568
- ? cloneKnownState(this.verified.knownState())
569
- : emptyKnownState(this.id);
570
-
571
- this._cachedKnownState = knownState;
572
-
573
- return knownState;
551
+ return this.verified?.immutableKnownState() ?? emptyKnownState(this.id);
574
552
  }
575
553
 
576
554
  get meta(): JsonValue {
@@ -612,31 +590,36 @@ export class CoValueCore {
612
590
  newTransactions: Transaction[],
613
591
  newSignature: Signature,
614
592
  skipVerify: boolean = false,
615
- ): Result<true, TryAddTransactionsError> {
616
- let result: Result<SignerID | undefined, TryAddTransactionsError>;
593
+ ) {
594
+ let signerID: SignerID | undefined;
617
595
 
618
- if (skipVerify) {
619
- result = ok(undefined);
620
- } else {
621
- result = this.node
622
- .resolveAccountAgent(
623
- accountOrAgentIDfromSessionID(sessionID),
624
- "Expected to know signer of transaction",
625
- )
626
- .andThen((agent) => {
627
- return ok(this.crypto.getAgentSignerID(agent));
628
- });
629
- }
596
+ if (!skipVerify) {
597
+ const result = this.node.resolveAccountAgent(
598
+ accountOrAgentIDfromSessionID(sessionID),
599
+ "Expected to know signer of transaction",
600
+ );
630
601
 
631
- return result.andThen((signerID) => {
632
- if (!this.verified) {
633
- return err({
634
- type: "TriedToAddTransactionsWithoutVerifiedState",
602
+ if (result.error || !result.value) {
603
+ return {
604
+ type: "ResolveAccountAgentError",
635
605
  id: this.id,
636
- } satisfies TriedToAddTransactionsWithoutVerifiedStateErrpr);
606
+ error: result.error,
607
+ } as const;
637
608
  }
638
609
 
639
- const result = this.verified.tryAddTransactions(
610
+ signerID = this.crypto.getAgentSignerID(result.value);
611
+ }
612
+
613
+ if (!this.verified) {
614
+ return {
615
+ type: "TriedToAddTransactionsWithoutVerifiedState",
616
+ id: this.id,
617
+ error: undefined,
618
+ };
619
+ }
620
+
621
+ try {
622
+ this.verified.tryAddTransactions(
640
623
  sessionID,
641
624
  signerID,
642
625
  newTransactions,
@@ -644,19 +627,11 @@ export class CoValueCore {
644
627
  skipVerify,
645
628
  );
646
629
 
647
- if (result.isOk()) {
648
- this.resetKnownStateCache();
649
- this.processNewTransactions();
650
- this.scheduleNotifyUpdate();
651
- }
652
-
653
- return result;
654
- });
655
- }
656
-
657
- private resetKnownStateCache() {
658
- this._cachedKnownState = undefined;
659
- this._cachedKnownStateWithStreaming = undefined;
630
+ this.processNewTransactions();
631
+ this.scheduleNotifyUpdate();
632
+ } catch (e) {
633
+ return { type: "InvalidSignature", id: this.id, error: e } as const;
634
+ }
660
635
  }
661
636
 
662
637
  private processNewTransactions() {
@@ -769,6 +744,8 @@ export class CoValueCore {
769
744
 
770
745
  let result: { signature: Signature; transaction: Transaction };
771
746
 
747
+ const knownStateBefore = this.knownState();
748
+
772
749
  if (privacy === "private") {
773
750
  const { secret: keySecret, id: keyID } = this.getCurrentReadKey();
774
751
 
@@ -795,7 +772,7 @@ export class CoValueCore {
795
772
  );
796
773
  }
797
774
 
798
- const { transaction, signature } = result;
775
+ const { transaction } = result;
799
776
 
800
777
  // Assign pre-parsed meta and changes to skip the parse/decrypt operation when loading
801
778
  // this transaction in the current content
@@ -803,23 +780,13 @@ export class CoValueCore {
803
780
 
804
781
  this.node.syncManager.recordTransactionsSize([transaction], "local");
805
782
 
806
- const session = this.verified.sessions.get(sessionID);
807
- const txIdx = session ? session.transactions.length - 1 : 0;
808
-
809
- this.resetKnownStateCache();
810
783
  this.processNewTransactions();
811
784
  this.addDependenciesFromNewTransaction(transaction);
812
785
 
813
786
  // force immediate notification because local updates may come from the UI
814
787
  // where we need synchronous updates
815
788
  this.notifyUpdate();
816
- this.node.syncManager.syncLocalTransaction(
817
- this.verified,
818
- transaction,
819
- sessionID,
820
- signature,
821
- txIdx,
822
- );
789
+ this.node.syncManager.syncLocalTransaction(this.verified, knownStateBefore);
823
790
 
824
791
  return true;
825
792
  }
@@ -1,10 +1,10 @@
1
- import { Result, err, ok } from "neverthrow";
2
1
  import { AnyRawCoValue } from "../coValue.js";
3
2
  import {
4
3
  createContentMessage,
5
4
  exceedsRecommendedSize,
6
5
  getTransactionSize,
7
6
  addTransactionToContentMessage,
7
+ knownStateFromContent,
8
8
  } from "../coValueContentMessage.js";
9
9
  import {
10
10
  CryptoProvider,
@@ -20,9 +20,13 @@ import { JsonObject, JsonValue } from "../jsonValue.js";
20
20
  import { PermissionsDef as RulesetDef } from "../permissions.js";
21
21
  import { NewContentMessage } from "../sync.js";
22
22
  import { TryAddTransactionsError } from "./coValueCore.js";
23
- import { SessionLog, SessionMap } from "./SessionMap.js";
23
+ import { SessionMap } from "./SessionMap.js";
24
24
  import { ControlledAccountOrAgent } from "../coValues/account.js";
25
- import { CoValueKnownState, KnownStateSessions } from "../knownState.js";
25
+ import {
26
+ CoValueKnownState,
27
+ getKnownStateToSend,
28
+ KnownStateSessions,
29
+ } from "../knownState.js";
26
30
 
27
31
  export type CoValueHeader = {
28
32
  type: AnyRawCoValue["type"];
@@ -89,16 +93,14 @@ export class VerifiedState {
89
93
  newTransactions: Transaction[],
90
94
  newSignature: Signature,
91
95
  skipVerify: boolean = false,
92
- ): Result<true, TryAddTransactionsError> {
93
- const result = this.sessions.addTransaction(
96
+ ) {
97
+ this.sessions.addTransaction(
94
98
  sessionID,
95
99
  signerID,
96
100
  newTransactions,
97
101
  newSignature,
98
102
  skipVerify,
99
103
  );
100
-
101
- return result;
102
104
  }
103
105
 
104
106
  makeNewTrustingTransaction(
@@ -158,6 +160,9 @@ export class VerifiedState {
158
160
 
159
161
  newContentSince(
160
162
  knownState: CoValueKnownState | undefined,
163
+ opts?: {
164
+ skipExpectContentUntil?: boolean;
165
+ },
161
166
  ): NewContentMessage[] | undefined {
162
167
  let currentPiece: NewContentMessage = createContentMessage(
163
168
  this.id,
@@ -285,10 +290,19 @@ export class VerifiedState {
285
290
  );
286
291
 
287
292
  if (piecesWithContent.length > 1 || this.isStreaming()) {
288
- // Flag that more content is coming
289
- firstPiece.expectContentUntil = {
290
- ...this.knownStateWithStreaming().sessions,
291
- };
293
+ if (!opts?.skipExpectContentUntil) {
294
+ // Flag that more content is coming
295
+ if (knownState) {
296
+ firstPiece.expectContentUntil = getKnownStateToSend(
297
+ this.knownStateWithStreaming().sessions,
298
+ knownState.sessions,
299
+ );
300
+ } else {
301
+ firstPiece.expectContentUntil = {
302
+ ...this.knownStateWithStreaming().sessions,
303
+ };
304
+ }
305
+ }
292
306
  }
293
307
 
294
308
  if (piecesWithContent.length === 0) {
@@ -306,6 +320,17 @@ export class VerifiedState {
306
320
  return this.sessions.knownStateWithStreaming ?? this.knownState();
307
321
  }
308
322
 
323
+ immutableKnownState() {
324
+ return this.sessions.immutableKnownState;
325
+ }
326
+
327
+ immutableKnownStateWithStreaming() {
328
+ return (
329
+ this.sessions.immutableKnownStateWithStreaming ??
330
+ this.immutableKnownState()
331
+ );
332
+ }
333
+
309
334
  isStreaming(): boolean {
310
335
  return Boolean(this.sessions.knownStateWithStreaming);
311
336
  }
@@ -508,12 +508,14 @@ export class RawGroup<
508
508
  memberRole === "writerInvite" ||
509
509
  memberRole === "adminInvite"
510
510
  ) {
511
- const otherMemberAgent = this.core.node
512
- .resolveAccountAgent(
513
- otherMemberKey,
514
- "Expected member agent to be loaded",
515
- )
516
- ._unsafeUnwrap({ withStackTrace: true });
511
+ const otherMemberAgent = this.core.node.resolveAccountAgent(
512
+ otherMemberKey,
513
+ "Expected member agent to be loaded",
514
+ ).value;
515
+
516
+ if (!otherMemberAgent) {
517
+ throw new Error("Expected member agent to be loaded");
518
+ }
517
519
 
518
520
  this.storeKeyRevelationForMember(
519
521
  otherMemberKey,
@@ -689,9 +691,14 @@ export class RawGroup<
689
691
 
690
692
  if (lastReadyKeyEdit?.value) {
691
693
  const revealer = lastReadyKeyEdit.by;
692
- const revealerAgent = core.node
693
- .resolveAccountAgent(revealer, "Expected to know revealer")
694
- ._unsafeUnwrap({ withStackTrace: true });
694
+ const revealerAgent = core.node.resolveAccountAgent(
695
+ revealer,
696
+ "Expected to know revealer",
697
+ ).value;
698
+
699
+ if (!revealerAgent) {
700
+ throw new Error("Expected to know revealer");
701
+ }
695
702
 
696
703
  const secret = this.crypto.unseal(
697
704
  lastReadyKeyEdit.value,
@@ -841,12 +848,14 @@ export class RawGroup<
841
848
  const newReadKey = this.crypto.newRandomKeySecret();
842
849
 
843
850
  for (const readerID of currentlyPermittedReaders) {
844
- const agent = this.core.node
845
- .resolveAccountAgent(
846
- readerID,
847
- "Expected to know currently permitted reader",
848
- )
849
- ._unsafeUnwrap({ withStackTrace: true });
851
+ const agent = this.core.node.resolveAccountAgent(
852
+ readerID,
853
+ "Expected to know currently permitted reader",
854
+ ).value;
855
+
856
+ if (!agent) {
857
+ throw new Error("Expected to know currently permitted reader");
858
+ }
850
859
 
851
860
  this.storeKeyRevelationForMember(
852
861
  readerID,
@@ -861,12 +870,14 @@ export class RawGroup<
861
870
  * and reveal them to the other non-writeOnly members
862
871
  */
863
872
  for (const writeOnlyMemberID of writeOnlyMembers) {
864
- const agent = this.core.node
865
- .resolveAccountAgent(
866
- writeOnlyMemberID,
867
- "Expected to know writeOnly member",
868
- )
869
- ._unsafeUnwrap({ withStackTrace: true });
873
+ const agent = this.core.node.resolveAccountAgent(
874
+ writeOnlyMemberID,
875
+ "Expected to know writeOnly member",
876
+ ).value;
877
+
878
+ if (!agent) {
879
+ throw new Error("Expected to know writeOnly member");
880
+ }
870
881
 
871
882
  const writeOnlyKey = this.crypto.newRandomKeySecret();
872
883
 
@@ -879,12 +890,14 @@ export class RawGroup<
879
890
  this.set(`writeKeyFor_${writeOnlyMemberID}`, writeOnlyKey.id, "trusting");
880
891
 
881
892
  for (const readerID of currentlyPermittedReaders) {
882
- const agent = this.core.node
883
- .resolveAccountAgent(
884
- readerID,
885
- "Expected to know currently permitted reader",
886
- )
887
- ._unsafeUnwrap({ withStackTrace: true });
893
+ const agent = this.core.node.resolveAccountAgent(
894
+ readerID,
895
+ "Expected to know currently permitted reader",
896
+ ).value;
897
+
898
+ if (!agent) {
899
+ throw new Error("Expected to know currently permitted reader");
900
+ }
888
901
 
889
902
  this.storeKeyRevelationForMember(
890
903
  readerID,
package/src/knownState.ts CHANGED
@@ -106,18 +106,53 @@ export function cloneKnownState(knownState: CoValueKnownState) {
106
106
  };
107
107
  }
108
108
 
109
+ /**
110
+ * Checks if all the local sessions have the same counters as in remote.
111
+ */
112
+ export function areCurrentSessionsInSyncWith(
113
+ current: Record<string, number>,
114
+ target: Record<string, number>,
115
+ ) {
116
+ for (const [sessionId, currentCount] of Object.entries(current)) {
117
+ const targetCount = target[sessionId] ?? 0;
118
+ if (currentCount !== targetCount) {
119
+ return false;
120
+ }
121
+ }
122
+
123
+ return true;
124
+ }
125
+
109
126
  /**
110
127
  * Checks if all the local sessions have the same counters as in remote.
111
128
  */
112
129
  export function isKnownStateSubsetOf(
113
- local: Record<string, number>,
114
- remote: Record<string, number>,
130
+ current: Record<string, number>,
131
+ target: Record<string, number>,
115
132
  ) {
116
- for (const sessionId of Object.keys(local)) {
117
- if (local[sessionId] !== remote[sessionId]) {
133
+ for (const [sessionId, currentCount] of Object.entries(current)) {
134
+ const targetCount = target[sessionId] ?? 0;
135
+ if (currentCount > targetCount) {
118
136
  return false;
119
137
  }
120
138
  }
121
139
 
122
140
  return true;
123
141
  }
142
+
143
+ /**
144
+ * Returns the record with the sessions that need to be sent to the target
145
+ */
146
+ export function getKnownStateToSend(
147
+ current: Record<string, number>,
148
+ target: Record<string, number>,
149
+ ) {
150
+ const toSend: Record<string, number> = {};
151
+ for (const [sessionId, currentCount] of Object.entries(current)) {
152
+ const targetCount = target[sessionId] ?? 0;
153
+ if (currentCount > targetCount) {
154
+ toSend[sessionId] = currentCount;
155
+ }
156
+ }
157
+ return toSend;
158
+ }
package/src/localNode.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { Result, err, ok } from "neverthrow";
2
1
  import { GarbageCollector } from "./GarbageCollector.js";
3
2
  import type { CoID } from "./coValue.js";
4
3
  import type { RawCoValue } from "./coValue.js";
@@ -10,7 +9,6 @@ import {
10
9
  import {
11
10
  type CoValueHeader,
12
11
  type CoValueUniqueness,
13
- VerifiedState,
14
12
  } from "./coValueCore/verifiedState.js";
15
13
  import {
16
14
  AccountMeta,
@@ -31,7 +29,7 @@ import {
31
29
  type RawGroup,
32
30
  secretSeedFromInviteSecret,
33
31
  } from "./coValues/group.js";
34
- import { CO_VALUE_LOADING_CONFIG, GARBAGE_COLLECTOR_CONFIG } from "./config.js";
32
+ import { CO_VALUE_LOADING_CONFIG } from "./config.js";
35
33
  import { AgentSecret, CryptoProvider } from "./crypto/crypto.js";
36
34
  import { AgentID, RawCoID, SessionID, isAgentID } from "./ids.js";
37
35
  import { logger } from "./logger.js";
@@ -41,6 +39,7 @@ import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromS
41
39
  import { expectGroup } from "./typeUtils/expectGroup.js";
42
40
  import { canBeBranched } from "./coValueCore/branching.js";
43
41
  import { connectedPeers } from "./streamUtils.js";
42
+ import { emptyKnownState } from "./knownState.js";
44
43
 
45
44
  /** A `LocalNode` represents a local view of a set of loaded `CoValue`s, from the perspective of a particular account (or primitive cryptographic agent).
46
45
 
@@ -380,7 +379,10 @@ export class LocalNode {
380
379
  }
381
380
 
382
381
  this.garbageCollector?.trackCoValueAccess(coValue);
383
- this.syncManager.syncHeader(coValue.verified);
382
+ this.syncManager.syncLocalTransaction(
383
+ coValue.verified,
384
+ emptyKnownState(id),
385
+ );
384
386
 
385
387
  return coValue;
386
388
  }
@@ -686,12 +688,9 @@ export class LocalNode {
686
688
  }
687
689
 
688
690
  /** @internal */
689
- resolveAccountAgent(
690
- id: RawAccountID | AgentID,
691
- expectation?: string,
692
- ): Result<AgentID, ResolveAccountAgentError> {
691
+ resolveAccountAgent(id: RawAccountID | AgentID, expectation?: string) {
693
692
  if (isAgentID(id)) {
694
- return ok(id);
693
+ return { value: id, error: undefined };
695
694
  }
696
695
 
697
696
  let coValue: AvailableCoValueCore;
@@ -699,12 +698,7 @@ export class LocalNode {
699
698
  try {
700
699
  coValue = this.expectCoValueLoaded(id, expectation);
701
700
  } catch (e) {
702
- return err({
703
- type: "ErrorLoadingCoValueCore",
704
- expectation,
705
- id,
706
- error: e,
707
- } satisfies LoadCoValueCoreError);
701
+ return { value: undefined, error: e };
708
702
  }
709
703
 
710
704
  if (
@@ -714,14 +708,15 @@ export class LocalNode {
714
708
  !("type" in coValue.verified.header.meta) ||
715
709
  coValue.verified.header.meta.type !== "account"
716
710
  ) {
717
- return err({
718
- type: "UnexpectedlyNotAccount",
719
- expectation,
720
- id,
721
- } satisfies UnexpectedlyNotAccountError);
711
+ return {
712
+ value: undefined,
713
+ error: new Error(`Unexpectedly not account: ${expectation}`),
714
+ };
722
715
  }
723
716
 
724
- return ok((coValue.getCurrentContent() as RawAccount).currentAgentID());
717
+ const account = coValue.getCurrentContent() as RawAccount;
718
+
719
+ return { value: account.currentAgentID(), error: undefined };
725
720
  }
726
721
 
727
722
  createGroup(