@midnightntwrk/wallet-sdk-shielded 4.0.0-beta.2 → 4.0.0-beta.3

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 (60) hide show
  1. package/README.md +11 -6
  2. package/dist/Restore.d.ts +40 -0
  3. package/dist/Restore.js +63 -0
  4. package/dist/ShieldedWallet.d.ts +248 -62
  5. package/dist/ShieldedWallet.js +366 -76
  6. package/dist/ShieldedWalletAPI.d.ts +179 -0
  7. package/dist/ShieldedWalletAPI.js +75 -0
  8. package/dist/SingleVariantShieldedWallet.d.ts +35 -0
  9. package/dist/SingleVariantShieldedWallet.js +240 -0
  10. package/dist/index.d.ts +4 -1
  11. package/dist/index.js +4 -1
  12. package/dist/v1/CoinsAndBalances.d.ts +1 -1
  13. package/dist/v1/CoreWallet.d.ts +48 -1
  14. package/dist/v1/CoreWallet.js +54 -1
  15. package/dist/v1/Migration.d.ts +95 -0
  16. package/dist/v1/Migration.js +82 -0
  17. package/dist/v1/RunningV1Variant.d.ts +1 -1
  18. package/dist/v1/RunningV1Variant.js +37 -8
  19. package/dist/v1/Serialization.js +1 -1
  20. package/dist/v1/Sync.d.ts +132 -9
  21. package/dist/v1/Sync.js +244 -35
  22. package/dist/v1/Transacting.d.ts +1 -1
  23. package/dist/v1/Transacting.js +1 -1
  24. package/dist/v1/TransactionHistory.d.ts +9 -2
  25. package/dist/v1/TransactionHistory.js +26 -5
  26. package/dist/v1/TransactionOps.d.ts +1 -1
  27. package/dist/v1/V1Builder.d.ts +87 -26
  28. package/dist/v1/V1Builder.js +109 -8
  29. package/dist/v1/WalletError.d.ts +1 -1
  30. package/dist/v1/index.d.ts +2 -1
  31. package/dist/v1/index.js +5 -1
  32. package/dist/v2/CoinsAndBalances.d.ts +24 -0
  33. package/dist/v2/CoinsAndBalances.js +41 -0
  34. package/dist/v2/CoreWallet.d.ts +162 -0
  35. package/dist/v2/CoreWallet.js +305 -0
  36. package/dist/v2/Keys.d.ts +8 -0
  37. package/dist/v2/Keys.js +16 -0
  38. package/dist/v2/Migration.d.ts +112 -0
  39. package/dist/v2/Migration.js +96 -0
  40. package/dist/v2/RunningV2Variant.d.ts +40 -0
  41. package/dist/v2/RunningV2Variant.js +127 -0
  42. package/dist/v2/Serialization.d.ts +12 -0
  43. package/dist/v2/Serialization.js +93 -0
  44. package/dist/v2/Sync.d.ts +208 -0
  45. package/dist/v2/Sync.js +436 -0
  46. package/dist/v2/Transacting.d.ts +50 -0
  47. package/dist/v2/Transacting.js +258 -0
  48. package/dist/v2/TransactionHistory.d.ts +100 -0
  49. package/dist/v2/TransactionHistory.js +132 -0
  50. package/dist/v2/TransactionImbalances.d.ts +10 -0
  51. package/dist/v2/TransactionImbalances.js +30 -0
  52. package/dist/v2/TransactionOps.d.ts +17 -0
  53. package/dist/v2/TransactionOps.js +73 -0
  54. package/dist/v2/V2Builder.d.ts +154 -0
  55. package/dist/v2/V2Builder.js +273 -0
  56. package/dist/v2/WalletError.d.ts +74 -0
  57. package/dist/v2/WalletError.js +53 -0
  58. package/dist/v2/index.d.ts +13 -0
  59. package/dist/v2/index.js +26 -0
  60. package/package.json +16 -8
@@ -1,7 +1,8 @@
1
- import * as ledger from '@midnightntwrk/ledger-v9';
1
+ import * as ledger from '@midnight-ntwrk/ledger-v8';
2
2
  import { type Either, type Types } from 'effect';
3
3
  import { type NetworkId } from '@midnightntwrk/wallet-sdk-abstractions';
4
- import { type Variant, type VariantBuilder } from '@midnightntwrk/wallet-sdk-runtime/abstractions';
4
+ import { type Variant, type VariantBuilder, type StartMaterial } from '@midnightntwrk/wallet-sdk-runtime/abstractions';
5
+ import { type StateMigration } from './Migration.js';
5
6
  import { RunningV1Variant, V1Tag } from './RunningV1Variant.js';
6
7
  import { type SerializationCapability } from './Serialization.js';
7
8
  import { type DefaultSyncContext, type DefaultSyncConfiguration, type ChangesResult, type SyncCapability, type SyncService, type WalletSyncUpdate } from './Sync.js';
@@ -10,7 +11,7 @@ import { type WalletError } from './WalletError.js';
10
11
  import { type CoinsAndBalancesCapability } from './CoinsAndBalances.js';
11
12
  import { type KeysCapability } from './Keys.js';
12
13
  import { type CoinSelection } from '@midnightntwrk/wallet-sdk-capabilities';
13
- import { CoreWallet } from './CoreWallet.js';
14
+ import { type CoreWallet } from './CoreWallet.js';
14
15
  import { type DefaultTransactionHistoryConfiguration, type TransactionHistoryService } from './TransactionHistory.js';
15
16
  export type BaseV1Configuration = {
16
17
  networkId: NetworkId.NetworkId;
@@ -19,40 +20,81 @@ export type DefaultV1Configuration = BaseV1Configuration & DefaultSyncConfigurat
19
20
  declare const V1BuilderSymbol: {
20
21
  readonly typeId: unique symbol;
21
22
  };
22
- export type V1Variant<TSerialized, TSyncUpdate, TTransaction, TAuxData> = Variant.Variant<typeof V1Tag, CoreWallet, null, RunningV1Variant<TSerialized, TSyncUpdate, TTransaction, TAuxData>> & {
23
+ export type V1Variant<TSerialized, TSyncUpdate, TTransaction, TAuxData, TPreviousState = null> = Variant.Variant<typeof V1Tag, CoreWallet, TPreviousState, RunningV1Variant<TSerialized, TSyncUpdate, TTransaction, TAuxData>> & {
23
24
  deserializeState: (serialized: TSerialized) => Either.Either<CoreWallet, WalletError>;
24
25
  coinsAndBalances: CoinsAndBalancesCapability<CoreWallet>;
25
26
  keys: KeysCapability<CoreWallet>;
26
27
  serialization: SerializationCapability<CoreWallet, null, TSerialized>;
27
28
  transactionHistory: TransactionHistoryService;
29
+ startAux: StartMaterial.StartAuxCapability<TAuxData>;
28
30
  };
29
31
  export type AnyV1Variant = V1Variant<any, any, any, any>;
30
32
  export type DefaultV1Variant = V1Variant<string, WalletSyncUpdate, ledger.FinalizedTransaction, ledger.ZswapSecretKeys>;
31
33
  export type TransactionOf<T extends AnyV1Variant> = T extends V1Variant<any, any, infer TTransaction, any> ? TTransaction : never;
32
34
  export type AuxDataOf<T extends AnyV1Variant> = T extends V1Variant<any, any, any, infer TAuxData> ? TAuxData : never;
33
35
  export type SerializedStateOf<T extends AnyV1Variant> = T extends V1Variant<infer TSerialized, any, any, any> ? TSerialized : never;
34
- export type DefaultV1Builder = V1Builder<DefaultV1Configuration, RunningV1Variant.Context<string, WalletSyncUpdate, ledger.FinalizedTransaction, ledger.ZswapSecretKeys>, string, WalletSyncUpdate, ledger.FinalizedTransaction, ledger.ZswapSecretKeys>;
35
- export declare class V1Builder<TConfig extends BaseV1Configuration = BaseV1Configuration, TContext extends Partial<RunningV1Variant.AnyContext> = object, TSerialized = never, TSyncUpdate = never, TTransaction = never, TStartAux extends object = object> implements VariantBuilder.VariantBuilder<V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux>, TConfig> {
36
+ export type DefaultV1Builder<TPreviousState = null> = V1Builder<DefaultV1Configuration, RunningV1Variant.Context<string, WalletSyncUpdate, ledger.FinalizedTransaction, ledger.ZswapSecretKeys>, string, WalletSyncUpdate, ledger.FinalizedTransaction, ledger.ZswapSecretKeys, TPreviousState>;
37
+ export declare class V1Builder<TConfig extends BaseV1Configuration = BaseV1Configuration, TContext extends Partial<RunningV1Variant.AnyContext> = object, TSerialized = never, TSyncUpdate = never, TTransaction = never, TStartAux extends object = object, TPreviousState = null> implements VariantBuilder.VariantBuilder<V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>, TConfig> {
36
38
  #private;
37
- constructor(buildState?: V1Builder.PartialBuildState<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>);
38
- withDefaults(): DefaultV1Builder;
39
- withTransactionType<Transaction>(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, Transaction, TStartAux>;
40
- withDefaultTransactionType(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, ledger.FinalizedTransaction, TStartAux>;
41
- withSyncDefaults(): V1Builder<TConfig & DefaultSyncConfiguration, TContext & DefaultSyncContext, TSerialized, WalletSyncUpdate, TTransaction, ledger.ZswapSecretKeys>;
42
- withSync<TSyncConfig, TSyncContext extends Partial<RunningV1Variant.AnyContext>, TSyncUpdate, TStartAux extends object>(syncService: (configuration: TSyncConfig, getContext: () => TSyncContext) => SyncService<CoreWallet, TStartAux, TSyncUpdate>, syncCapability: (configuration: TSyncConfig, getContext: () => TSyncContext) => SyncCapability<CoreWallet, TSyncUpdate, ChangesResult>): V1Builder<TConfig & TSyncConfig, TContext & TSyncContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
43
- withSerializationDefaults(): V1Builder<TConfig, TContext, string, TSyncUpdate, TTransaction, TStartAux>;
44
- withSerialization<TSerializationConfig, TSerializationContext extends Partial<RunningV1Variant.AnyContext>, TSerialized>(serializationCapability: (configuration: TSerializationConfig, getContext: () => TSerializationContext) => SerializationCapability<CoreWallet, null, TSerialized>): V1Builder<TConfig & TSerializationConfig, TContext & TSerializationContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
45
- withTransactingDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, ledger.FinalizedTransaction, TStartAux>): V1Builder<TConfig & DefaultTransactingConfiguration, TContext & DefaultTransactingContext, TSerialized, TSyncUpdate, ledger.FinalizedTransaction, TStartAux>;
46
- withTransacting<TTransactingConfig, TTransactingContext extends Partial<RunningV1Variant.AnyContext>>(transactingCapability: (config: TTransactingConfig, getContext: () => TTransactingContext) => TransactingCapability<ledger.ZswapSecretKeys, CoreWallet, TTransaction>): V1Builder<TConfig & TTransactingConfig, TContext & TTransactingContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
47
- withCoinSelection<TCoinSelectionConfig, TCoinSelectionContext extends Partial<RunningV1Variant.AnyContext>>(coinSelection: (config: TCoinSelectionConfig, getContext: () => TCoinSelectionContext) => CoinSelection<ledger.QualifiedShieldedCoinInfo>): V1Builder<TConfig & TCoinSelectionConfig, TContext & TCoinSelectionContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
48
- withCoinSelectionDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
49
- withCoinsAndBalancesDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
50
- withCoinsAndBalances<TBalancesConfig, TBalancesContext extends Partial<RunningV1Variant.AnyContext>>(coinsAndBalancesCapability: (configuration: TBalancesConfig, getContext: () => TBalancesContext) => CoinsAndBalancesCapability<CoreWallet>): V1Builder<TConfig & TBalancesConfig, TContext & TBalancesContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
51
- withTransactionHistoryDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, ledger.FinalizedTransaction, TStartAux>): V1Builder<TConfig & DefaultTransactionHistoryConfiguration, TContext, TSerialized, TSyncUpdate, ledger.FinalizedTransaction, TStartAux>;
52
- withTransactionHistory<TTransactionHistoryConfig, TTransactionHistoryContext extends Partial<RunningV1Variant.AnyContext>>(transactionHistoryService: (configuration: TTransactionHistoryConfig, getContext: () => TTransactionHistoryContext) => TransactionHistoryService): V1Builder<TConfig & TTransactionHistoryConfig, TContext & TTransactionHistoryContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
53
- withKeysDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
54
- withKeys<TKeysConfig, TKeysContext extends Partial<RunningV1Variant.AnyContext>>(keysCapability: (configuration: TKeysConfig, getContext: () => TKeysContext) => KeysCapability<CoreWallet>): V1Builder<TConfig & TKeysConfig, TContext & TKeysContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>;
55
- build(this: V1Builder<TConfig, RunningV1Variant.Context<TSerialized, TSyncUpdate, TTransaction, TStartAux>, TSerialized, TSyncUpdate, TTransaction, TStartAux>, configuration: TConfig): V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux>;
39
+ constructor(buildState?: V1Builder.PartialBuildState<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>);
40
+ withDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, null>): DefaultV1Builder;
41
+ withTransactionType<Transaction>(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, Transaction, TStartAux, TPreviousState>;
42
+ withDefaultTransactionType(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, ledger.FinalizedTransaction, TStartAux, TPreviousState>;
43
+ withSyncDefaults(): V1Builder<TConfig & DefaultSyncConfiguration, TContext & DefaultSyncContext, TSerialized, WalletSyncUpdate, TTransaction, ledger.ZswapSecretKeys, TPreviousState>;
44
+ withSync<TSyncConfig, TSyncContext extends Partial<RunningV1Variant.AnyContext>, TSyncUpdate, TStartAux extends object>(syncService: (configuration: TSyncConfig, getContext: () => TSyncContext) => SyncService<CoreWallet, TStartAux, TSyncUpdate>, syncCapability: (configuration: TSyncConfig, getContext: () => TSyncContext) => SyncCapability<CoreWallet, TSyncUpdate, ChangesResult>): V1Builder<TConfig & TSyncConfig, TContext & TSyncContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
45
+ withSerializationDefaults(): V1Builder<TConfig, TContext, string, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
46
+ withSerialization<TSerializationConfig, TSerializationContext extends Partial<RunningV1Variant.AnyContext>, TSerialized>(serializationCapability: (configuration: TSerializationConfig, getContext: () => TSerializationContext) => SerializationCapability<CoreWallet, null, TSerialized>): V1Builder<TConfig & TSerializationConfig, TContext & TSerializationContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
47
+ withTransactingDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, ledger.FinalizedTransaction, TStartAux, TPreviousState>): V1Builder<TConfig & DefaultTransactingConfiguration, TContext & DefaultTransactingContext, TSerialized, TSyncUpdate, ledger.FinalizedTransaction, TStartAux, TPreviousState>;
48
+ withTransacting<TTransactingConfig, TTransactingContext extends Partial<RunningV1Variant.AnyContext>>(transactingCapability: (config: TTransactingConfig, getContext: () => TTransactingContext) => TransactingCapability<ledger.ZswapSecretKeys, CoreWallet, TTransaction>): V1Builder<TConfig & TTransactingConfig, TContext & TTransactingContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
49
+ withCoinSelection<TCoinSelectionConfig, TCoinSelectionContext extends Partial<RunningV1Variant.AnyContext>>(coinSelection: (config: TCoinSelectionConfig, getContext: () => TCoinSelectionContext) => CoinSelection<ledger.QualifiedShieldedCoinInfo>): V1Builder<TConfig & TCoinSelectionConfig, TContext & TCoinSelectionContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
50
+ withCoinSelectionDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
51
+ withCoinsAndBalancesDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
52
+ withCoinsAndBalances<TBalancesConfig, TBalancesContext extends Partial<RunningV1Variant.AnyContext>>(coinsAndBalancesCapability: (configuration: TBalancesConfig, getContext: () => TBalancesContext) => CoinsAndBalancesCapability<CoreWallet>): V1Builder<TConfig & TBalancesConfig, TContext & TBalancesContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
53
+ withTransactionHistoryDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, ledger.FinalizedTransaction, TStartAux, TPreviousState>): V1Builder<TConfig & DefaultTransactionHistoryConfiguration, TContext, TSerialized, TSyncUpdate, ledger.FinalizedTransaction, TStartAux, TPreviousState>;
54
+ withTransactionHistory<TTransactionHistoryConfig, TTransactionHistoryContext extends Partial<RunningV1Variant.AnyContext>>(transactionHistoryService: (configuration: TTransactionHistoryConfig, getContext: () => TTransactionHistoryContext) => TransactionHistoryService): V1Builder<TConfig & TTransactionHistoryConfig, TContext & TTransactionHistoryContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
55
+ withKeysDefaults(): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
56
+ /**
57
+ * Uses the default start-aux derivation: this ledger version's Zswap secret keys, derived from the seed.
58
+ *
59
+ * @remarks
60
+ * The seed is the only key material that crosses a protocol boundary, so every variant must be able to produce its
61
+ * own from one. This is that derivation for this ledger version; a builder whose sync service expects something
62
+ * else supplies its own with {@link V1Builder.withStartAux}.
63
+ */
64
+ withStartAuxDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, ledger.ZswapSecretKeys, TPreviousState>): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, ledger.ZswapSecretKeys, TPreviousState>;
65
+ /**
66
+ * Chooses how this variant derives the key material its synchronization is started with from a seed.
67
+ *
68
+ * @param startAux The derivation.
69
+ * @returns A builder that produces a variant able to start sync from a seed alone.
70
+ */
71
+ withStartAux(startAux: StartMaterial.StartAuxCapability<TStartAux>): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
72
+ /**
73
+ * Uses the default migration: an empty wallet built from nothing.
74
+ *
75
+ * @remarks
76
+ * This is what an unconfigured builder already does, so calling it changes no behaviour — it states the choice rather
77
+ * than inheriting it. Registering this variant as the target of a real fork means calling
78
+ * {@link V1Builder.withMigration} with {@link makeCrossLedgerMigration} instead.
79
+ */
80
+ withMigrationDefaults(this: V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, null>): V1Builder<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, null>;
81
+ /**
82
+ * Chooses how this variant produces its first state from the state that preceded it.
83
+ *
84
+ * @remarks
85
+ * The strategy's input type becomes the variant's `TPreviousState`, which is what the runtime type-checks a
86
+ * registration against: a variant declaring it migrates from a ledger-v8 wallet cannot be registered after one that
87
+ * produces something else.
88
+ * @example
89
+ * ```typescript
90
+ * const forkTarget = new V1Builder().withDefaults().withMigration(makeCrossLedgerMigration);
91
+ * ```;
92
+ *
93
+ * @param migration Builds the migration from the configuration and the sibling capabilities.
94
+ */
95
+ withMigration<TMigrationConfig, TPrevious>(migration: (configuration: TMigrationConfig, getContext: () => TContext) => StateMigration<TPrevious>): V1Builder<TConfig & TMigrationConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPrevious>;
96
+ withKeys<TKeysConfig, TKeysContext extends Partial<RunningV1Variant.AnyContext>>(keysCapability: (configuration: TKeysConfig, getContext: () => TKeysContext) => KeysCapability<CoreWallet>): V1Builder<TConfig & TKeysConfig, TContext & TKeysContext, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
97
+ build(this: V1Builder<TConfig, RunningV1Variant.Context<TSerialized, TSyncUpdate, TTransaction, TStartAux>, TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>, configuration: TConfig): V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux, TPreviousState>;
56
98
  }
57
99
  /** @internal */
58
100
  declare namespace V1Builder {
@@ -80,9 +122,28 @@ declare namespace V1Builder {
80
122
  };
81
123
  /** The internal build state of {@link V1Builder}. */
82
124
  type FullBuildState<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux> = Types.Simplify<HasSync<TConfig, TContext, TSyncUpdate, TStartAux> & HasSerialization<TConfig, TContext, TSerialized> & HasTransacting<TConfig, TContext, TTransaction> & HasCoinSelection<TConfig, TContext> & HasCoinsAndBalances<TConfig, TContext> & HasKeys<TConfig, TContext> & HasTransactionHistory<TConfig, TContext>>;
83
- type PartialBuildState<TConfig = object, TContext = object, TSerialized = never, TSyncUpdate = never, TTransaction = never, TStartAux = object> = {
125
+ /**
126
+ * The migration entry, kept out of {@link FullBuildState} on purpose: absent means "empty wallet", which is the
127
+ * behaviour every builder had before migrations were configurable, so a builder that never mentions migration must
128
+ * still be considered complete.
129
+ */
130
+ /**
131
+ * The start-aux entry, kept out of {@link FullBuildState} because it is not one of the context-producing capabilities:
132
+ * it takes neither configuration nor sibling capabilities, only a seed.
133
+ */
134
+ type HasStartAux<TStartAux> = {
135
+ readonly startAux: StartMaterial.StartAuxCapability<TStartAux>;
136
+ };
137
+ type HasMigration<TConfig, TContext, TPreviousState> = {
138
+ readonly migration: (configuration: TConfig, getContext: () => TContext) => StateMigration<TPreviousState>;
139
+ };
140
+ /** The capability half of the build state — everything that does not depend on the previous-state parameter. */
141
+ type CapabilityBuildState<TConfig = object, TContext = object, TSerialized = never, TSyncUpdate = never, TTransaction = never, TStartAux = object> = {
84
142
  [K in keyof FullBuildState<never, never, never, never, never, never>]?: FullBuildState<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux>[K] | undefined;
85
143
  };
144
+ type PartialBuildState<TConfig = object, TContext = object, TSerialized = never, TSyncUpdate = never, TTransaction = never, TStartAux = object, TPreviousState = null> = {
145
+ [K in keyof (FullBuildState<never, never, never, never, never, never> & HasMigration<never, never, never> & HasStartAux<never>)]?: (FullBuildState<TConfig, TContext, TSerialized, TSyncUpdate, TTransaction, TStartAux> & HasMigration<TConfig, TContext, TPreviousState> & HasStartAux<TStartAux>)[K] | undefined;
146
+ };
86
147
  /** Utility interface that manages the type variance of {@link V1Builder}. */
87
148
  interface Variance<R> {
88
149
  readonly [V1BuilderSymbol.typeId]: {
@@ -10,9 +10,10 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
- import * as ledger from '@midnightntwrk/ledger-v9';
13
+ import * as ledger from '@midnight-ntwrk/ledger-v8';
14
14
  import { Effect, Scope } from 'effect';
15
- import { WalletSeed } from '@midnightntwrk/wallet-sdk-abstractions';
15
+ import { WalletRuntimeError, } from '@midnightntwrk/wallet-sdk-runtime/abstractions';
16
+ import { makeEmptyWalletMigration } from './Migration.js';
16
17
  import { RunningV1Variant, V1Tag } from './RunningV1Variant.js';
17
18
  import { makeDefaultV1SerializationCapability } from './Serialization.js';
18
19
  import { makeEventsSyncService, makeEventsSyncCapability, } from './Sync.js';
@@ -20,7 +21,6 @@ import { makeDefaultTransactingCapability, } from './Transacting.js';
20
21
  import { makeDefaultCoinsAndBalancesCapability } from './CoinsAndBalances.js';
21
22
  import { makeDefaultKeysCapability } from './Keys.js';
22
23
  import { chooseCoin } from '@midnightntwrk/wallet-sdk-capabilities';
23
- import { CoreWallet, PublicKeys } from './CoreWallet.js';
24
24
  import { makeDefaultTransactionHistoryService, } from './TransactionHistory.js';
25
25
  const V1BuilderSymbol = {
26
26
  typeId: Symbol('@midnight-ntwrk/wallet#V1Builder'),
@@ -38,6 +38,12 @@ export class V1Builder {
38
38
  .withCoinsAndBalancesDefaults()
39
39
  .withTransactionHistoryDefaults()
40
40
  .withKeysDefaults()
41
+ .withStartAuxDefaults()
42
+ // Type cast required because: the chain accumulates `TContext` as an intersection of the individual
43
+ // `Default*Context` fragments, which is a structurally weaker type than the complete
44
+ // `RunningV1Variant.Context` that `DefaultV1Builder` names — the defaults do produce a full context, but the
45
+ // chain's type cannot express that. Routing through `unknown` because the added `migration` key put the two
46
+ // sides past what TypeScript will accept as directly comparable; the widening itself predates it.
41
47
  .withCoinSelectionDefaults();
42
48
  }
43
49
  withTransactionType() {
@@ -58,6 +64,9 @@ export class V1Builder {
58
64
  ...this.#buildState,
59
65
  syncService,
60
66
  syncCapability,
67
+ // The derivation is typed against the *old* start-aux parameter, so it cannot ride along into a builder whose
68
+ // sync service expects something else — exactly as the migration cannot ride along through `withMigration`.
69
+ startAux: undefined,
61
70
  });
62
71
  }
63
72
  withSerializationDefaults() {
@@ -108,6 +117,63 @@ export class V1Builder {
108
117
  withKeysDefaults() {
109
118
  return this.withKeys(makeDefaultKeysCapability);
110
119
  }
120
+ /**
121
+ * Uses the default start-aux derivation: this ledger version's Zswap secret keys, derived from the seed.
122
+ *
123
+ * @remarks
124
+ * The seed is the only key material that crosses a protocol boundary, so every variant must be able to produce its
125
+ * own from one. This is that derivation for this ledger version; a builder whose sync service expects something
126
+ * else supplies its own with {@link V1Builder.withStartAux}.
127
+ */
128
+ withStartAuxDefaults() {
129
+ return this.withStartAux({ fromSeed: (seed) => ledger.ZswapSecretKeys.fromSeed(seed) });
130
+ }
131
+ /**
132
+ * Chooses how this variant derives the key material its synchronization is started with from a seed.
133
+ *
134
+ * @param startAux The derivation.
135
+ * @returns A builder that produces a variant able to start sync from a seed alone.
136
+ */
137
+ withStartAux(startAux) {
138
+ return new V1Builder({
139
+ ...this.#buildState,
140
+ startAux,
141
+ });
142
+ }
143
+ /**
144
+ * Uses the default migration: an empty wallet built from nothing.
145
+ *
146
+ * @remarks
147
+ * This is what an unconfigured builder already does, so calling it changes no behaviour — it states the choice rather
148
+ * than inheriting it. Registering this variant as the target of a real fork means calling
149
+ * {@link V1Builder.withMigration} with {@link makeCrossLedgerMigration} instead.
150
+ */
151
+ withMigrationDefaults() {
152
+ return this.withMigration((configuration) => makeEmptyWalletMigration(configuration));
153
+ }
154
+ /**
155
+ * Chooses how this variant produces its first state from the state that preceded it.
156
+ *
157
+ * @remarks
158
+ * The strategy's input type becomes the variant's `TPreviousState`, which is what the runtime type-checks a
159
+ * registration against: a variant declaring it migrates from a ledger-v8 wallet cannot be registered after one that
160
+ * produces something else.
161
+ * @example
162
+ * ```typescript
163
+ * const forkTarget = new V1Builder().withDefaults().withMigration(makeCrossLedgerMigration);
164
+ * ```;
165
+ *
166
+ * @param migration Builds the migration from the configuration and the sibling capabilities.
167
+ */
168
+ withMigration(migration) {
169
+ const capabilities = this.#buildState;
170
+ return new V1Builder({
171
+ // Only the capability half crosses: the strategy being replaced is typed against the *old* previous-state
172
+ // parameter, so it cannot ride along even though it is about to be overwritten.
173
+ ...capabilities,
174
+ migration,
175
+ });
176
+ }
111
177
  withKeys(keysCapability) {
112
178
  return new V1Builder({
113
179
  ...this.#buildState,
@@ -116,28 +182,63 @@ export class V1Builder {
116
182
  }
117
183
  build(configuration) {
118
184
  const v1Context = this.#buildContextFromBuildState(configuration);
119
- const { networkId } = configuration;
185
+ const migration = this.#resolveMigration(configuration, () => v1Context);
120
186
  return {
121
187
  __polyTag__: V1Tag,
122
188
  coinsAndBalances: v1Context.coinsAndBalancesCapability,
123
189
  keys: v1Context.keysCapability,
124
190
  serialization: v1Context.serializationCapability,
125
191
  transactionHistory: v1Context.transactionHistoryService,
192
+ startAux: this.#resolveStartAux(),
126
193
  start(context) {
127
194
  return Effect.gen(function* () {
128
195
  const scope = yield* Scope.Scope;
129
196
  return new RunningV1Variant(scope, context, v1Context);
130
197
  });
131
198
  },
132
- migrateState(_previousState) {
133
- const seed = WalletSeed.fromString('0000000000000000000000000000000000000000000000000000000000000001');
134
- return Effect.succeed(CoreWallet.empty(PublicKeys.fromSecretKeys(ledger.ZswapSecretKeys.fromSeed(seed)), networkId));
135
- },
199
+ // An unconfigured builder keeps producing an empty wallet, which is what `startEmpty` has always relied on.
200
+ // Anything else — carrying state within a ledger version, or projecting it across one — is the injected
201
+ // strategy's business, and its failures are reported on the runtime's state stream rather than thrown.
202
+ migrateState: (previousState) => migration.migrate(previousState).pipe(Effect.mapError((error) => new WalletRuntimeError({
203
+ message: 'Failed to migrate shielded wallet state into this variant',
204
+ cause: error,
205
+ }))),
136
206
  deserializeState: (serialized) => {
137
207
  return v1Context.serializationCapability.deserialize(null, serialized);
138
208
  },
139
209
  };
140
210
  }
211
+ /**
212
+ * Resolves the configured migration, or the empty-wallet fallback when none was configured.
213
+ *
214
+ * @remarks
215
+ * The fallback is written as a nullary function on purpose. It ignores whatever preceded it — it builds an empty
216
+ * wallet from nothing — which makes it a valid migration from _any_ previous state, but a `StateMigration<null>`
217
+ * value could only be widened to `StateMigration<TPreviousState>` through a cast. Declaring no parameter says the
218
+ * same thing to the type system without one.
219
+ */
220
+ /**
221
+ * Resolves the configured start-aux derivation.
222
+ *
223
+ * @remarks
224
+ * Unlike the migration there is no sensible fallback: the default derivation produces this ledger version's secret
225
+ * keys, which is only correct for a builder that kept a sync service expecting them. A builder that replaced sync
226
+ * and did not say how to derive its own key material is misconfigured, and is told so at build time rather than
227
+ * silently handed key objects of the wrong shape at the first migration.
228
+ */
229
+ #resolveStartAux() {
230
+ const configured = this.#buildState.startAux;
231
+ if (configured === undefined) {
232
+ throw new Error('Not all components are configured in V1 Builder: startAux');
233
+ }
234
+ return configured;
235
+ }
236
+ #resolveMigration(configuration, getContext) {
237
+ const configured = this.#buildState.migration;
238
+ return configured === undefined
239
+ ? { migrate: () => makeEmptyWalletMigration(configuration).migrate(null) }
240
+ : configured(configuration, getContext);
241
+ }
141
242
  #buildContextFromBuildState(configuration) {
142
243
  if (!isBuildStateFull(this.#buildState)) {
143
244
  throw new Error('Not all components are configured in V1 Builder');
@@ -1,4 +1,4 @@
1
- import type * as ledger from '@midnightntwrk/ledger-v9';
1
+ import type * as ledger from '@midnight-ntwrk/ledger-v8';
2
2
  import { type LedgerOps } from '@midnightntwrk/wallet-sdk-utilities';
3
3
  export declare const WalletError: {
4
4
  other(err: unknown): WalletError;
@@ -3,10 +3,11 @@ export * as Sync from './Sync.js';
3
3
  export * as Transacting from './Transacting.js';
4
4
  export * as TransactionHistory from './TransactionHistory.js';
5
5
  export * as Serialization from './Serialization.js';
6
+ export * as Migration from './Migration.js';
6
7
  export * as CoinsAndBalances from './CoinsAndBalances.js';
7
8
  export * as Keys from './Keys.js';
8
9
  export * from './RunningV1Variant.js';
9
- export * as Simulator from '@midnightntwrk/wallet-sdk-capabilities/simulation';
10
+ export { V8 as Simulator } from '@midnightntwrk/wallet-sdk-capabilities/simulation';
10
11
  export * as WalletError from './WalletError.js';
11
12
  export * from './CoreWallet.js';
12
13
  export * from './TransactionOps.js';
package/dist/v1/index.js CHANGED
@@ -10,15 +10,19 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
+ // The V1 variant: this wallet on `@midnight-ntwrk/ledger-v8`, run below `forks.v9`. Its twin is `../v2`.
13
14
  export * from './V1Builder.js';
14
15
  export * as Sync from './Sync.js';
15
16
  export * as Transacting from './Transacting.js';
16
17
  export * as TransactionHistory from './TransactionHistory.js';
17
18
  export * as Serialization from './Serialization.js';
19
+ export * as Migration from './Migration.js';
18
20
  export * as CoinsAndBalances from './CoinsAndBalances.js';
19
21
  export * as Keys from './Keys.js';
20
22
  export * from './RunningV1Variant.js';
21
- export * as Simulator from '@midnightntwrk/wallet-sdk-capabilities/simulation';
23
+ // The V1 variant re-exports the ledger-v8 simulator twin, not the whole simulation index — the unqualified
24
+ // names there are the ledger-v9 twin's.
25
+ export { V8 as Simulator } from '@midnightntwrk/wallet-sdk-capabilities/simulation';
22
26
  export * as WalletError from './WalletError.js';
23
27
  export * from './CoreWallet.js';
24
28
  export * from './TransactionOps.js';
@@ -0,0 +1,24 @@
1
+ import { type CoreWallet } from './CoreWallet.js';
2
+ import type * as ledger from '@midnightntwrk/ledger-v9';
3
+ export type AvailableCoin = {
4
+ coin: ledger.QualifiedShieldedCoinInfo;
5
+ commitment: ledger.CoinCommitment;
6
+ nullifier: ledger.Nullifier;
7
+ };
8
+ export type PendingCoin = {
9
+ coin: ledger.ShieldedCoinInfo;
10
+ ttl: Date | undefined;
11
+ commitment: ledger.CoinCommitment;
12
+ nullifier: ledger.Nullifier;
13
+ };
14
+ export type Coin = AvailableCoin | PendingCoin;
15
+ export type Balances = Record<ledger.RawTokenType, bigint>;
16
+ export type CoinsAndBalancesCapability<TState> = {
17
+ getAvailableBalances(state: TState): Balances;
18
+ getPendingBalances(state: TState): Balances;
19
+ getTotalBalances(state: TState): Balances;
20
+ getAvailableCoins(state: TState): readonly AvailableCoin[];
21
+ getPendingCoins(state: TState): readonly PendingCoin[];
22
+ getTotalCoins(state: TState): ReadonlyArray<AvailableCoin | PendingCoin>;
23
+ };
24
+ export declare const makeDefaultCoinsAndBalancesCapability: () => CoinsAndBalancesCapability<CoreWallet>;
@@ -0,0 +1,41 @@
1
+ import { pipe, Array, Option } from 'effect';
2
+ import { RecordOps } from '@midnightntwrk/wallet-sdk-utilities';
3
+ const calculateBalances = (coins) => coins.reduce((acc, { coin }) => ({
4
+ ...acc,
5
+ [coin.type]: acc[coin.type] === undefined ? coin.value : acc[coin.type] + coin.value,
6
+ }), {});
7
+ export const makeDefaultCoinsAndBalancesCapability = () => {
8
+ const getAvailableBalances = (state) => {
9
+ const availableCoins = getAvailableCoins(state);
10
+ return calculateBalances(availableCoins);
11
+ };
12
+ const getPendingBalances = (state) => {
13
+ const pendingCoins = getPendingCoins(state);
14
+ return calculateBalances(pendingCoins);
15
+ };
16
+ const getTotalBalances = (state) => {
17
+ const availableBalances = getAvailableBalances(state);
18
+ const pendingBalances = getPendingBalances(state);
19
+ return pipe([availableBalances, pendingBalances], RecordOps.mergeWithAccumulator(0n, (a, b) => a + b));
20
+ };
21
+ // Both joins are total over the crossing window. A wallet that crossed the ledger-version boundary holds its full
22
+ // local state before it holds the hashes for it — computing a commitment or nullifier needs the secret keys the
23
+ // migration deliberately does not have — so a coin without its hash entry is not yet nameable and is left out of
24
+ // the view, rather than assumed present and dereferenced. The window closes on the first sync update, which
25
+ // carries the keys and both resolves the map and releases the spends the state crossed with, so a coin booked for a
26
+ // transaction the boundary stranded is available again by the time it can be named (see CoreWallet.completeCrossing).
27
+ const getAvailableCoins = (state) => {
28
+ const pendingSpends = new Set([...state.state.pendingSpends.values()].map(([coin]) => coin.nonce));
29
+ return pipe([...state.state.coins], Array.filter((coin) => !pendingSpends.has(coin.nonce)), Array.filterMap((coin) => pipe(Option.fromNullable(state.coinHashes[coin.nonce]), Option.map(({ commitment, nullifier }) => ({ coin, commitment, nullifier })))));
30
+ };
31
+ const getPendingCoins = (state) => pipe([...state.state.pendingOutputs.values()], Array.filterMap(([coin, ttl]) => pipe(Option.fromNullable(state.coinHashes[coin.nonce]), Option.map(({ commitment, nullifier }) => ({ coin, ttl, commitment, nullifier })))));
32
+ const getTotalCoins = (state) => [...getAvailableCoins(state), ...getPendingCoins(state)];
33
+ return {
34
+ getAvailableBalances,
35
+ getPendingBalances,
36
+ getTotalBalances,
37
+ getAvailableCoins,
38
+ getPendingCoins,
39
+ getTotalCoins,
40
+ };
41
+ };
@@ -0,0 +1,162 @@
1
+ import * as ledger from '@midnightntwrk/ledger-v9';
2
+ import { ProtocolVersion, SyncProgress } from '@midnightntwrk/wallet-sdk-abstractions';
3
+ import { Either } from 'effect';
4
+ import { type WalletError } from './WalletError.js';
5
+ export type PublicKeys = {
6
+ coinPublicKey: ledger.CoinPublicKey;
7
+ encryptionPublicKey: ledger.EncPublicKey;
8
+ };
9
+ export declare const PublicKeys: {
10
+ fromSecretKeys: (secretKeys: ledger.ZswapSecretKeys) => PublicKeys;
11
+ };
12
+ export type CoinHashesMap = Readonly<Record<ledger.Nonce, {
13
+ nullifier: ledger.Nullifier;
14
+ commitment: ledger.CoinCommitment;
15
+ }>>;
16
+ export declare const CoinHashesMap: {
17
+ empty: {};
18
+ pickAllCoins(state: ledger.ZswapLocalState): readonly ledger.ShieldedCoinInfo[];
19
+ assertValid(map: CoinHashesMap, state: ledger.ZswapLocalState): Either.Either<void, Set<ledger.Nonce>>;
20
+ updateWithCoins(secretKeys: ledger.ZswapSecretKeys, existing: CoinHashesMap, coins: Iterable<ledger.ShieldedCoinInfo>): CoinHashesMap;
21
+ updateWithNewCoins(secretKeys: ledger.ZswapSecretKeys, existing: CoinHashesMap, coins: Iterable<ledger.ShieldedCoinInfo>): CoinHashesMap;
22
+ init(secretKeys: ledger.ZswapSecretKeys, coins: Iterable<ledger.ShieldedCoinInfo>): CoinHashesMap;
23
+ };
24
+ export type CoreWallet = Readonly<{
25
+ state: ledger.ZswapLocalState;
26
+ publicKeys: PublicKeys;
27
+ protocolVersion: ProtocolVersion.ProtocolVersion;
28
+ progress: SyncProgress.SyncProgress;
29
+ networkId: string;
30
+ coinHashes: CoinHashesMap;
31
+ /**
32
+ * This wallet's coin hashes have never been computed, and {@link CoinHashesMap.empty} means "not yet", not "none".
33
+ *
34
+ * @remarks
35
+ * Set by the cross-ledger migration and cleared by the first sync update, which is the first moment secret keys are
36
+ * at hand — see {@link CoreWallet.fromPreviousVersion} and {@link CoreWallet.completeCrossing}. It is also what marks
37
+ * the wallet as freshly crossed, which is how that step knows the reservations in its local state are ones no
38
+ * inclusion can ever clear and releases them exactly once. Stated as a field rather than inferred from "empty map
39
+ * beside a non-empty state" because an empty map is a perfectly good value for a wallet holding nothing, and
40
+ * overloading it would make one shape mean two things. Being a field, it is also what lets a snapshot taken
41
+ * mid-crossing declare itself: {@link CoreWallet.restoreWithCoinHashes} goes on rejecting a snapshot whose hashes do
42
+ * not cover its coins, because only a wallet carrying this marker is permitted the gap. `true` is the only
43
+ * inhabitant, so "pending" and "absent" are the only two states.
44
+ */
45
+ coinHashesPending?: true;
46
+ }>;
47
+ export declare const CoreWallet: {
48
+ init(localState: ledger.ZswapLocalState, secretKeys: ledger.ZswapSecretKeys, networkId: string): CoreWallet;
49
+ empty(publicKeys: PublicKeys, networkId: string): CoreWallet;
50
+ restore(localState: ledger.ZswapLocalState, secretKeys: ledger.ZswapSecretKeys, syncProgress: Omit<SyncProgress.SyncProgressData, "isConnected">, protocolVersion: bigint, networkId: string): CoreWallet;
51
+ restoreWithCoinHashes(publicKeys: PublicKeys, localState: ledger.ZswapLocalState, coinHashes: CoinHashesMap, syncProgress: SyncProgress.SyncProgressData, protocolVersion: bigint, networkId: string): Either.Either<CoreWallet, WalletError>;
52
+ /**
53
+ * Restores a wallet whose coin hashes were never computed — a snapshot taken mid-crossing.
54
+ *
55
+ * @remarks
56
+ * The counterpart of {@link CoreWallet.restoreWithCoinHashes} for the one shape that validation would otherwise
57
+ * refuse: a full local state, carried across the ledger-version boundary as bytes, beside an empty hash map. The
58
+ * hashes are commitments and nullifiers, and computing them needs the secret keys a deserializer does not hold, so
59
+ * the wallet comes back still marked pending and the first sync update fills them in
60
+ * ({@link CoreWallet.resolveCoinHashes}). Total: there is nothing here to reject, which is exactly why it is a
61
+ * separate entry point rather than a flag on the validating one.
62
+ * @param publicKeys The identity the snapshot declared.
63
+ * @param localState The local state the snapshot carried.
64
+ * @param syncProgress Where the snapshot's reading had got to.
65
+ * @param protocolVersion The version the snapshot was written under.
66
+ * @param networkId The network the snapshot claims.
67
+ * @returns A wallet holding that state, its coin hashes still pending.
68
+ */
69
+ restoreWithPendingCoinHashes(publicKeys: PublicKeys, localState: ledger.ZswapLocalState, syncProgress: SyncProgress.SyncProgressData, protocolVersion: bigint, networkId: string): CoreWallet;
70
+ initEmpty(keys: ledger.ZswapSecretKeys, networkId: string): CoreWallet;
71
+ /**
72
+ * Records an observed protocol version on the wallet, never going backwards.
73
+ *
74
+ * @remarks
75
+ * The version is a signal, not a measurement: writing one outside the running variant's activation range is what
76
+ * makes it hand over to the next variant. A source that briefly reports an older version — a reconnect replaying
77
+ * from an earlier cursor, say — must therefore not be able to drag the wallet back below a boundary it has already
78
+ * crossed, which would ask the runtime to migrate backwards. Taking the maximum makes that unrepresentable.
79
+ * @param wallet The wallet to annotate.
80
+ * @param version The protocol version just observed.
81
+ * @returns `wallet` unchanged if it already records `version` or a later one, otherwise a copy recording `version`.
82
+ */
83
+ withProtocolVersion(wallet: CoreWallet, version: ProtocolVersion.ProtocolVersion): CoreWallet;
84
+ /**
85
+ * Adopts a wallet inherited from the previous ledger version: its local state, its identity, and its position.
86
+ *
87
+ * @remarks
88
+ * The state passed in is this ledger version's own object, decoded from the previous version's bytes — the two majors
89
+ * share the `zswap-local-state` codec, so the crossing is a round-trip rather than a reconstruction (see
90
+ * `Migration.makeCrossLedgerMigration`, and the characterization test that pins the codec). So everything the
91
+ * previous wallet's tree held arrives intact: its coins at the Merkle indices the chain gave them, the height it
92
+ * had reached, and the outputs it was still expecting. What also crosses is the public keys, the network, the
93
+ * protocol version that triggered the hand-over (kept so the new variant starts inside its own activation range
94
+ * rather than immediately signalling backwards), and the cursor the previous variant stopped at.
95
+ *
96
+ * **Sync progress is parked at the fork, not rewound**: the previous wallet's cursor crosses unchanged. The indexer
97
+ * numbers ledger-v9 events onwards from whatever id it had reached when the fork happened, never from zero, so
98
+ * resuming from the inherited cursor is what puts this wallet in front of them. Rewinding to zero would park it on
99
+ * a stretch of history that this ledger version's events do not occupy. What does not cross is `isConnected`: no
100
+ * sync is running behind this state yet.
101
+ *
102
+ * The one thing the bytes cannot supply is the coin hashes: commitments and nullifiers are computed from the secret
103
+ * keys, which a migration by design does not hold. They are therefore left empty and marked
104
+ * {@link CoreWallet.coinHashesPending}, for {@link CoreWallet.completeCrossing} to fill in at the first sync update —
105
+ * the first place in this variant where keys and state meet. The same step releases the spends the state crossed
106
+ * with: those transactions belong to the ledger version the chain has left behind and can never be included, so
107
+ * nothing else would ever free the coins they reserved.
108
+ * @param previous The identity and position read off the previous ledger version's wallet, and its decoded state.
109
+ * @returns A wallet of this ledger version holding what its predecessor held, positioned at the fork.
110
+ */
111
+ fromPreviousVersion(previous: {
112
+ readonly state: ledger.ZswapLocalState;
113
+ readonly publicKeys: PublicKeys;
114
+ readonly networkId: string;
115
+ readonly protocolVersion: bigint;
116
+ readonly progress: SyncProgress.SyncProgressData;
117
+ }): CoreWallet;
118
+ /**
119
+ * Finishes a crossing at the first sync update: the reservations released, then the coin hashes computed.
120
+ *
121
+ * @remarks
122
+ * The other half of {@link CoreWallet.fromPreviousVersion}. A migrated wallet arrives holding its whole local state
123
+ * but nothing it needs the secret keys for — no commitments or nullifiers, and no way to un-book the spends it
124
+ * carried — because a migration is by design handed no key material. The first sync update carries it, so this is
125
+ * where both gaps close: {@link releaseStrandedSpends} first, since a released coin is one more coin the hashes have
126
+ * to name, and {@link CoreWallet.resolveCoinHashes} over the state that comes back. Applied at the head of both sync
127
+ * capabilities, before anything else they do, so a batch that turns out to be empty still runs it: a wallet that
128
+ * crossed into a quiet timeline must not be left unable to name or to spend the coins it crossed with.
129
+ *
130
+ * Idempotent and self-clearing: without the marker this is the identity, so it costs a field read on every update
131
+ * thereafter and nothing else. That is also what keeps it away from a reservation made on this side of the
132
+ * boundary, whose transaction is live and whose coins are genuinely spoken for.
133
+ * @param wallet The wallet to complete.
134
+ * @param secretKeys The keys the update arrived with.
135
+ * @returns `wallet` unchanged if it never crossed, otherwise a copy whose coins are nameable and spendable again.
136
+ */
137
+ completeCrossing(wallet: CoreWallet, secretKeys: ledger.ZswapSecretKeys): CoreWallet;
138
+ /**
139
+ * Computes the coin hashes a wallet crossed the ledger-version boundary without.
140
+ *
141
+ * @remarks
142
+ * The hash half of {@link CoreWallet.completeCrossing}, which is what the sync capabilities call: a crossing has a
143
+ * second gap to close beside this one, so a caller finishing one should go through the combined step rather than
144
+ * here. A migrated wallet arrives holding its whole local state but no commitments or nullifiers for it, because
145
+ * deriving those needs the secret keys, and the first sync update is what carries them.
146
+ *
147
+ * Idempotent and self-clearing: without the marker this is the identity.
148
+ * @param wallet The wallet to complete.
149
+ * @param secretKeys The keys the update arrived with.
150
+ * @returns `wallet` unchanged if its hashes were never pending, otherwise a copy holding them.
151
+ */
152
+ resolveCoinHashes(wallet: CoreWallet, secretKeys: ledger.ZswapSecretKeys): CoreWallet;
153
+ applyCollapsedUpdate(wallet: CoreWallet, collapsed: ledger.MerkleTreeCollapsedUpdate): CoreWallet;
154
+ apply<TOffer extends ledger.ZswapOffer<ledger.Proofish>>(wallet: CoreWallet, secretKeys: ledger.ZswapSecretKeys, offer: TOffer): CoreWallet;
155
+ replayEventsWithChanges(wallet: CoreWallet, secretKeys: ledger.ZswapSecretKeys, events: ledger.Event[]): [CoreWallet, ledger.ZswapStateChanges[]];
156
+ updateProgress(wallet: CoreWallet, { appliedIndex, highestRelevantWalletIndex, highestIndex, highestRelevantIndex, isConnected, }: Partial<SyncProgress.SyncProgressData>): CoreWallet;
157
+ addTransaction(wallet: CoreWallet, _tx: ledger.FinalizedTransaction): CoreWallet;
158
+ revertTransaction<TTx extends ledger.Transaction<ledger.Signaturish, ledger.Proofish, ledger.Bindingish>>(wallet: CoreWallet, tx: TTx): CoreWallet;
159
+ updateTxHistory(wallet: CoreWallet, _newTxs: readonly ledger.FinalizedTransaction[]): CoreWallet;
160
+ spendCoins(wallet: CoreWallet, secretKeys: ledger.ZswapSecretKeys, coins: ReadonlyArray<ledger.QualifiedShieldedCoinInfo>, segment: number): [ReadonlyArray<ledger.ZswapOffer<ledger.PreProof>>, CoreWallet];
161
+ watchCoins(wallet: CoreWallet, secretKeys: ledger.ZswapSecretKeys, coins: ReadonlyArray<ledger.ShieldedCoinInfo>): CoreWallet;
162
+ };