@midnight-ntwrk/wallet-sdk-dust-wallet 5.0.0-beta.2 → 5.0.0-beta.4

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 (71) hide show
  1. package/README.md +31 -4
  2. package/dist/DustWallet.d.ts +295 -96
  3. package/dist/DustWallet.js +454 -96
  4. package/dist/DustWalletAPI.d.ts +240 -0
  5. package/dist/DustWalletAPI.js +100 -0
  6. package/dist/Restore.d.ts +40 -0
  7. package/dist/Restore.js +63 -0
  8. package/dist/SingleVariantDustWallet.d.ts +25 -0
  9. package/dist/SingleVariantDustWallet.js +221 -0
  10. package/dist/index.d.ts +5 -1
  11. package/dist/index.js +5 -1
  12. package/dist/v1/CoinsAndBalances.js +1 -1
  13. package/dist/v1/CoreWallet.d.ts +28 -1
  14. package/dist/v1/CoreWallet.js +33 -1
  15. package/dist/v1/Keys.d.ts +1 -1
  16. package/dist/v1/Migration.d.ts +111 -0
  17. package/dist/v1/Migration.js +79 -0
  18. package/dist/v1/RunningV1Variant.d.ts +22 -4
  19. package/dist/v1/RunningV1Variant.js +135 -41
  20. package/dist/v1/Serialization.js +1 -1
  21. package/dist/v1/Sync.d.ts +255 -9
  22. package/dist/v1/Sync.js +332 -30
  23. package/dist/v1/Transacting.d.ts +1 -1
  24. package/dist/v1/Transacting.js +5 -4
  25. package/dist/v1/TransactionHistory.d.ts +8 -2
  26. package/dist/v1/TransactionHistory.js +26 -5
  27. package/dist/v1/V1Builder.d.ts +111 -26
  28. package/dist/v1/V1Builder.js +131 -4
  29. package/dist/v1/WalletError.d.ts +26 -1
  30. package/dist/v1/WalletError.js +16 -0
  31. package/dist/v1/index.d.ts +4 -2
  32. package/dist/v1/index.js +5 -2
  33. package/dist/v1/types/Dust.d.ts +1 -1
  34. package/dist/v1/types/ledger.d.ts +1 -1
  35. package/dist/v2/CoinsAndBalances.d.ts +47 -0
  36. package/dist/v2/CoinsAndBalances.js +102 -0
  37. package/dist/v2/CoreWallet.d.ts +63 -0
  38. package/dist/v2/CoreWallet.js +190 -0
  39. package/dist/v2/Keys.d.ts +8 -0
  40. package/dist/v2/Keys.js +11 -0
  41. package/dist/v2/Migration.d.ts +111 -0
  42. package/dist/v2/Migration.js +79 -0
  43. package/dist/v2/RunningV2Variant.d.ts +60 -0
  44. package/dist/v2/RunningV2Variant.js +222 -0
  45. package/dist/v2/Serialization.d.ts +9 -0
  46. package/dist/v2/Serialization.js +75 -0
  47. package/dist/v2/Sync.d.ts +305 -0
  48. package/dist/v2/Sync.js +737 -0
  49. package/dist/v2/SyncSchema.d.ts +649 -0
  50. package/dist/v2/SyncSchema.js +489 -0
  51. package/dist/v2/Transacting.d.ts +97 -0
  52. package/dist/v2/Transacting.js +320 -0
  53. package/dist/v2/TransactionHistory.d.ts +105 -0
  54. package/dist/v2/TransactionHistory.js +144 -0
  55. package/dist/v2/Utils.d.ts +43 -0
  56. package/dist/v2/Utils.js +78 -0
  57. package/dist/v2/V2Builder.d.ts +177 -0
  58. package/dist/v2/V2Builder.js +293 -0
  59. package/dist/v2/WalletError.d.ts +68 -0
  60. package/dist/v2/WalletError.js +39 -0
  61. package/dist/v2/index.d.ts +14 -0
  62. package/dist/v2/index.js +27 -0
  63. package/dist/v2/types/Dust.d.ts +39 -0
  64. package/dist/v2/types/Dust.js +1 -0
  65. package/dist/v2/types/index.d.ts +3 -0
  66. package/dist/v2/types/index.js +15 -0
  67. package/dist/v2/types/ledger.d.ts +4 -0
  68. package/dist/v2/types/ledger.js +1 -0
  69. package/dist/v2/types/transaction.d.ts +4 -0
  70. package/dist/v2/types/transaction.js +1 -0
  71. package/package.json +14 -9
package/README.md CHANGED
@@ -97,17 +97,44 @@ const signedTx = await dustWallet.addDustGenerationSignature(dustGenerationTx, s
97
97
  - `SyncService` - Synchronization service
98
98
  - `Transacting` - Transaction utilities
99
99
  - `CoinsAndBalances` - Coin and balance management
100
+ - V2 (ledger-v9) variant internals via `@midnight-ntwrk/wallet-sdk-dust-wallet/v2`
101
+ - V1 (ledger-v8) variant internals via `@midnight-ntwrk/wallet-sdk-dust-wallet/v1`
100
102
 
101
- ## V1 Builder
103
+ ## V2 Builder
102
104
 
103
- Use the V1 builder pattern for wallet construction:
105
+ Use the V2 builder pattern for wallet construction:
104
106
 
105
107
  ```typescript
106
- import { V1Builder, RunningV1Variant } from '@midnight-ntwrk/wallet-sdk-dust-wallet';
108
+ import { V2Builder, RunningV2Variant } from '@midnight-ntwrk/wallet-sdk-dust-wallet/v2';
107
109
 
108
- // Build a V1 dust wallet variant
110
+ // Build a V2 dust wallet variant
109
111
  ```
110
112
 
113
+ ## Sync: the V1 variant replays events, permanently
114
+
115
+ The two variants do not offer the same synchronisation options, and this is not a temporary gap.
116
+
117
+ `./v2` (ledger-v9) can sync either way: by replaying the indexer's dust ledger events, or through the projections-based
118
+ **eventless fast sync** (`makeEventLessSyncService` / `makeEventLessSyncCapability`).
119
+
120
+ `./v1` (ledger-v8) offers **event replay only** — the same mechanism the shipped 1.x wallet uses in production today. It
121
+ does not export the projection schema types, the `DustProjectionsUpdate` union, or the eventless sync service and
122
+ capability. The reason is the ledger, not the wallet: the eventless path is built on four `DustLocalState` members that
123
+ exist only in ledger-v9, and no published ledger-v8 (checked through 8.1.1, the latest) has any of them —
124
+
125
+ | Member | Used for |
126
+ | ---------------------------------- | ------------------------------------------------------------ |
127
+ | `updateGenerationTreeFromEvidence` | applying generation-tree dtime updates from indexer evidence |
128
+ | `commitmentTreeFirstFree` | placing commitments relative to collapsed-tree updates |
129
+ | `generatingTreeFirstFree` | the same, for the generation tree |
130
+ | `nullifiers` | resolving which dust UTxOs a projection has already spent |
131
+
132
+ There is no v8-compatible implementation of them anywhere, so the path cannot be back-ported. **Decided 2026-08-19: the
133
+ V1 variant keeps event-replay sync permanently; no ledger change is being requested to close this.**
134
+
135
+ Everything else in `./v1` does track the current variant with the ledger swapped — including the sync lock, the one-shot
136
+ `sync` entry point, and typed (non-defect) `blockData` failures.
137
+
111
138
  ## License
112
139
 
113
140
  Apache-2.0
@@ -1,105 +1,304 @@
1
- import { type DustParameters, type DustPublicKey, DustSecretKey, type FinalizedTransaction, type Signature, type SignatureVerifyingKey, type UnprovenTransaction } from '@midnightntwrk/ledger-v9';
2
- import { type ProtocolState, ProtocolVersion, type SyncProgress } from '@midnight-ntwrk/wallet-sdk-abstractions';
3
- import { type DustAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
4
- import { type Variant, type VariantBuilder, type WalletLike } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
5
- import { type Clock } from '@midnight-ntwrk/wallet-sdk-utilities';
6
- import * as rx from 'rxjs';
7
- import { type Balance, type CoinsAndBalancesCapability, type UtxoWithFullDustDetails } from './v1/CoinsAndBalances.js';
8
- import { CoreWallet } from './v1/CoreWallet.js';
9
- import { type KeysCapability } from './v1/Keys.js';
10
- import { type SerializationCapability } from './v1/Serialization.js';
11
- import { type NightUtxoSplitForDustRegistration } from './v1/Transacting.js';
12
- import { type DustFullInfo, type UtxoWithMeta } from './v1/types/Dust.js';
13
- import { type AnyTransaction } from './v1/types/ledger.js';
14
- import { type BaseV1Configuration, type DefaultV1Configuration, type V1Variant } from './v1/V1Builder.js';
15
- import { type BlockData, type WalletSyncUpdate } from './v1/Sync.js';
16
- export type { BlockData } from './v1/Sync.js';
17
- import { type TransactionHistoryService } from './v1/TransactionHistory.js';
18
- export type DustWalletCapabilities<TSerialized = string> = {
19
- serialization: SerializationCapability<CoreWallet, null, TSerialized>;
20
- coinsAndBalances: CoinsAndBalancesCapability<CoreWallet>;
21
- keys: KeysCapability<CoreWallet>;
22
- };
23
- export type DustWalletServices = {
24
- transactionHistory: TransactionHistoryService;
1
+ /**
2
+ * A dust wallet that registers a variant either side of a protocol boundary and follows the chain across it.
3
+ *
4
+ * @remarks
5
+ * One wallet, two ledger versions. Before the boundary the V1 variant reads the chain with the ledger version that
6
+ * produced it; from the boundary the V2 variant does, having been handed identity and a place in the timeline and
7
+ * nothing else — the dust itself is re-discovered from the indexer's replay, which is what
8
+ * `test/forkSimulation.test.ts` proves. Which variant is running is the runtime's business, not the application's:
9
+ * the wallet's public API speaks ledger-v9 throughout, and where the two sides genuinely differ — the key material
10
+ * each variant's synchronization needs — the wallet resolves it per variant from what it retained.
11
+ *
12
+ * `DustWallet(configuration)` at the bottom is how this package ships it. `CustomForkingDustWallet` is the same wallet
13
+ * over builders the caller chooses, and `SingleVariantDustWallet.ts` is the composition that gives up the crossing to
14
+ * run one variant only.
15
+ */
16
+ import * as ledgerV8 from '@midnight-ntwrk/ledger-v8';
17
+ import * as ledgerV9 from '@midnightntwrk/ledger-v9';
18
+ import { ProtocolVersion } from '@midnight-ntwrk/wallet-sdk-abstractions';
19
+ import { type ChainVersionProbe } from '@midnight-ntwrk/wallet-sdk-capabilities/chainVersion';
20
+ import { Variant, type VariantBuilder, type WalletLike } from '@midnight-ntwrk/wallet-sdk-runtime/abstractions';
21
+ import { Either } from 'effect';
22
+ import { type UnsupportedSnapshotVersionError } from './Restore.js';
23
+ import { type DefaultDustConfiguration, type DustWalletAPI } from './DustWalletAPI.js';
24
+ import { type V1Variant } from './v1/index.js';
25
+ import { type WalletSyncUpdate as V1SyncUpdate } from './v1/Sync.js';
26
+ import { Migration, type V2Variant } from './v2/index.js';
27
+ import { type WalletSyncUpdate as V2SyncUpdate } from './v2/SyncSchema.js';
28
+ import { type NetworkId } from './v2/types/index.js';
29
+ import { type WalletError as V1WalletError } from './v1/WalletError.js';
30
+ import { type WalletError } from './v2/WalletError.js';
31
+ /**
32
+ * What restoring a Dust wallet from a snapshot can fail with.
33
+ *
34
+ * @remarks
35
+ * Two failures, and they mean different things. The snapshot may declare a protocol version no registered variant
36
+ * reads, which is a fact about this build of the SDK rather than about the snapshot; or the variant that owns it may
37
+ * be unable to make sense of the bytes, which is a fact about the snapshot. Either is an ordinary thing to meet when
38
+ * restoring something a user supplied, which is why `tryRestore` reports them rather than throwing.
39
+ */
40
+ export type DustRestoreError = UnsupportedSnapshotVersionError | V1WalletError | WalletError;
41
+ /** The V1 variant a forking dust wallet registers: the one that reads the chain before the boundary. */
42
+ export type V1DustVariant<TSyncUpdate> = V1Variant<string, TSyncUpdate, ledgerV8.FinalizedTransaction, ledgerV8.DustSecretKey>;
43
+ /** The V2 variant a forking dust wallet registers: the one the V1 wallet is migrated into. */
44
+ export type V2DustVariant<TSyncUpdate> = V2Variant<string, TSyncUpdate, ledgerV9.FinalizedTransaction, ledgerV9.DustSecretKey, Migration.PreviousLedgerWallet>;
45
+ /** The two variants a forking dust wallet runs, in registration order. */
46
+ export type ForkingDustVariants<TV1SyncUpdate, TV2SyncUpdate> = [
47
+ Variant.VersionedVariant<V1DustVariant<TV1SyncUpdate>>,
48
+ Variant.VersionedVariant<V2DustVariant<TV2SyncUpdate>>
49
+ ];
50
+ /**
51
+ * A variant builder registered together with the configuration it alone is built from.
52
+ *
53
+ * @remarks
54
+ * Per-variant rather than shared, and for dust the hazard is concrete rather than theoretical: both variants declare an
55
+ * optional `dustParameters`, each of its own ledger's `DustParameters`. The two classes are structurally identical,
56
+ * so a wallet-wide intersection accepts either and then hands whichever was supplied to _both_ variants — one of
57
+ * which would be building a `DustLocalState` out of the other module's WASM object. Splitting the configuration is
58
+ * what makes that unrepresentable.
59
+ */
60
+ export type SelfConfiguredDustVariant<TVariant extends Variant.AnyVariant, TConfiguration extends object> = Readonly<{
61
+ builder: VariantBuilder.VariantBuilder<TVariant, TConfiguration>;
62
+ configuration: TConfiguration;
63
+ }>;
64
+ /** What a forking dust wallet needs to know about itself, whatever its variants are built from. */
65
+ export type ForkingDustConfiguration = {
66
+ networkId: NetworkId;
67
+ /** Where each ledger version begins on this chain — see {@link ProtocolVersion.ForkSchedule}. */
68
+ forks: ProtocolVersion.ForkSchedule;
69
+ /**
70
+ * How the wallet asks the chain which protocol version it is on, before it chooses a variant to start at.
71
+ *
72
+ * @remarks
73
+ * Optional, and best-effort where present: a wallet with no probe — or one whose probe does not answer in time —
74
+ * starts on the V1 variant and learns the version from the first event it sees, which is what a wallet with no
75
+ * history has always done. What a probe buys is the two things that guess costs: a hand-over per start on a chain
76
+ * entirely past the boundary, and, on a chain that has shown this wallet no events at all, an epoch that never gets
77
+ * corrected.
78
+ *
79
+ * Nothing about it can make a start fail. A rejection, a timeout, a version no registered variant covers: each leaves
80
+ * the wallet exactly where a wallet that never asked would be.
81
+ */
82
+ chainVersionProbe?: ChainVersionProbe;
25
83
  };
26
- export declare class DustWalletState<TSerialized = string> {
27
- static readonly mapState: <TSerialized_1 = string>(variant: DustWalletCapabilities<TSerialized_1> & DustWalletServices) => (state: ProtocolState.ProtocolState<CoreWallet>) => DustWalletState<TSerialized_1>;
28
- readonly protocolVersion: ProtocolVersion.ProtocolVersion;
29
- readonly state: CoreWallet;
30
- readonly capabilities: DustWalletCapabilities<TSerialized>;
31
- readonly services: DustWalletServices;
32
- get totalCoins(): readonly DustFullInfo[];
33
- get availableCoins(): readonly DustFullInfo[];
34
- get pendingCoins(): readonly DustFullInfo[];
35
- get publicKey(): DustPublicKey;
36
- get address(): DustAddress;
37
- get progress(): SyncProgress.SyncProgress;
38
- constructor(state: ProtocolState.ProtocolState<CoreWallet>, capabilities: DustWalletCapabilities<TSerialized>, services: DustWalletServices);
39
- balance(time: Date): Balance;
40
- estimateDustGeneration(nightUtxos: ReadonlyArray<UtxoWithMeta>, currentTime: Date): ReadonlyArray<UtxoWithFullDustDetails>;
41
- serialize(): TSerialized;
42
- }
43
- export type DustWalletAPI<TStartAux = DustSecretKey, TSerialized = string> = {
44
- readonly state: rx.Observable<DustWalletState<TSerialized>>;
45
- start(secretKey: TStartAux): Promise<void>;
46
- createDustGenerationTransaction(currentTime: Date | undefined, ttl: Date, nightUtxos: Array<UtxoWithMeta>, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined): Promise<UnprovenTransaction>;
47
- splitNightUtxosForDustRegistration(currentTime: Date, nightUtxos: ReadonlyArray<UtxoWithMeta>, isRegistration: boolean): Promise<NightUtxoSplitForDustRegistration>;
48
- attachDustRegistration(transaction: UnprovenTransaction, currentTime: Date, nightVerifyingKey: SignatureVerifyingKey, dustReceiverAddress: DustAddress | undefined, feePayment: bigint): Promise<UnprovenTransaction>;
49
- addDustGenerationSignature(transaction: UnprovenTransaction, signature: Signature): Promise<UnprovenTransaction>;
84
+ /**
85
+ * One ledger version's dust secret key per side of a protocol boundary.
86
+ *
87
+ * @remarks
88
+ * Both sides are required. A caller holding key objects rather than a seed has to hold both, because the two belong to
89
+ * different ledger runtimes and neither can be derived from the other; a product with one side optional would let a
90
+ * wallet be built that cannot read half the chain, which is the shape this replaced.
91
+ */
92
+ export type DustKeysByEpoch = Readonly<{
93
+ /** The ledger-v8's dust secret key. */
94
+ v8: ledgerV8.DustSecretKey;
95
+ /** The ledger-v9's dust secret key. */
96
+ v9: ledgerV9.DustSecretKey;
97
+ }>;
98
+ /**
99
+ * A running dust wallet that spans a protocol boundary.
100
+ *
101
+ * @remarks
102
+ * Its two extra starts are the instance counterparts of the class-level ones, and they are here rather than on
103
+ * {@link DustWalletAPI} because only a wallet with a variant either side of a boundary has anything to do with them: a
104
+ * single-variant wallet speaks one ledger version, and the key `start` takes is always the right one.
105
+ */
106
+ export type ForkingDustWallet<TV1SyncUpdate, TV2SyncUpdate> = DustWalletAPI<ledgerV9.DustSecretKey, string> & WalletLike.WalletLike<ForkingDustVariants<TV1SyncUpdate, TV2SyncUpdate>> & {
50
107
  /**
51
- * Attaches a signature to the DustRegistration in segment 1's `dustActions` only. Unlike
52
- * {@link addDustGenerationSignature}, this does NOT touch the unshielded offers — those should be signed separately
53
- * via the unshielded-wallet signing path. Use this when the caller orchestrates signing across both packages (e.g.
54
- * the facade's `signRecipe`).
108
+ * Starts this wallet from a seed, which answers for the variant either side of the boundary.
109
+ *
110
+ * @remarks
111
+ * The instance counterpart of {@link ForkingDustWalletClass.startWithSeed}, and what a wallet restored from a
112
+ * snapshot written below the boundary is started with. A snapshot carries no key material by design, and the
113
+ * variant it restores onto is the ledger-v8 one, whose synchronization the ledger-v9 key
114
+ * {@link DustWalletAPI.start} takes cannot serve. The class-level start answers for both sides too — but it builds
115
+ * a _fresh_ wallet, which is the opposite of what a caller who has just restored one wants.
116
+ *
117
+ * No dust parameters are asked for, because a restored wallet needs none: they parameterise an _empty_ state, which
118
+ * is what a fresh build has to construct and a restored one already brought back from its snapshot.
119
+ *
120
+ * The seed itself is not kept: both ledger versions' dust keys are derived from it here and retained instead, which
121
+ * is the same capability with a shorter-lived secret.
122
+ * @example
123
+ * ```typescript
124
+ * const wallet = DustWallet(configuration).restore(snapshot);
125
+ * await wallet.startWithSeed(seed);
126
+ * ```;
127
+ *
128
+ * @param seed The seed to derive both ledger versions' dust keys from.
129
+ * @returns Nothing; resolves once synchronization has been started on whichever variant is current.
55
130
  */
56
- addDustRegistrationSignature(transaction: UnprovenTransaction, signature: Signature): Promise<UnprovenTransaction>;
57
- calculateFee(transactions: ReadonlyArray<AnyTransaction>): Promise<bigint>;
58
- estimateFee(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl?: Date, currentTime?: Date): Promise<bigint>;
59
- balanceTransactions(secretKey: DustSecretKey, transactions: ReadonlyArray<AnyTransaction>, ttl: Date, currentTime?: Date): Promise<{
60
- transaction: UnprovenTransaction;
61
- blockData: BlockData;
62
- }>;
63
- serializeState(): Promise<TSerialized>;
64
- waitForSyncedState(allowedGap?: bigint): Promise<DustWalletState<TSerialized>>;
131
+ startWithSeed(seed: Uint8Array): Promise<void>;
65
132
  /**
66
- * Resolves when the dust projected to be generated by the single highest-generation unregistered Night UTxO reaches
67
- * `requiredAmount`. The projection is re-evaluated every second so the wait advances even when the dust state stream
68
- * is quiet. Tracks the same quantity used as `allow_fee_payment` for the registration (the maximum across the UTxOs,
69
- * not their sum, since `splitNightUtxos` puts only one UTxO in the guaranteed slot), so pairing with
70
- * `WalletFacade.estimateRegistration` to pick `requiredAmount` guarantees the subsequent
71
- * `registerNightUtxosForDustGeneration` will pass its fee-coverage guard.
133
+ * Starts this wallet from dust keys of both ledger versions.
134
+ *
135
+ * @remarks
136
+ * The instance counterpart of {@link ForkingDustWalletClass.startWithKeys}, for a caller that will not part with a
137
+ * seed. Both sides are required for the same reason they are there: a `DustSecretKey` belongs to one ledger
138
+ * version's runtime, so a wallet given one side alone could not read the other side of the chain.
139
+ * @example
140
+ * ```typescript
141
+ * const wallet = DustWallet(configuration).restore(snapshot);
142
+ * await wallet.startWithKeys({ v8: v8Key, v9: v9Key });
143
+ * ```;
72
144
  *
73
- * @param nightUtxos - UTxOs to project generation for; same set passed to `registerNightUtxosForDustGeneration`.
74
- * Already-registered UTxOs are ignored. Must be non-empty.
75
- * @param requiredAmount - Threshold to wait for, as a Dust amount. Resolves immediately if `<= 0n`.
76
- * @param clock - Source of current time, read on every tick. Required, and a {@link Clock.Clock} rather than a
77
- * snapshot `Date` like the other methods' `currentTime`: the projection only advances because the time is re-read
78
- * each tick, and callers must inject their own clock so simulator-driven tests respect simulator time.
79
- * @param opts.timeoutMs - Deadline, in ms from subscription, for `requiredAmount` to be reached; rejects if it is
80
- * not. Default `300_000`.
81
- * @returns A promise that resolves once the projected dust reaches `requiredAmount`.
82
- * @throws Error if `nightUtxos` is empty.
83
- * @throws TimeoutError if `requiredAmount` is not reached within `opts.timeoutMs`.
145
+ * @param keys One ledger version's dust secret key per side of the boundary.
146
+ * @returns Nothing; resolves once synchronization has been started on whichever variant is current.
84
147
  */
85
- waitForGeneratedDust(nightUtxos: ReadonlyArray<UtxoWithMeta>, requiredAmount: bigint, clock: Clock.Clock, opts?: {
86
- timeoutMs?: number;
87
- }): Promise<void>;
88
- revertTransaction(transaction: AnyTransaction): Promise<void>;
89
- getAddress(): Promise<DustAddress>;
90
- stop(): Promise<void>;
148
+ startWithKeys(keys: DustKeysByEpoch): Promise<void>;
91
149
  };
92
- export type CustomizedDustWallet<TStartAux = DustSecretKey, TTransaction = FinalizedTransaction, TSyncUpdate = WalletSyncUpdate, TSerialized = string> = DustWalletAPI<TStartAux, TSerialized> & WalletLike.WalletLike<[Variant.VersionedVariant<V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux>>]>;
93
- export type DefaultDustConfiguration = DefaultV1Configuration;
94
- export interface CustomizedDustWalletClass<TStartAux = DustSecretKey, TTransaction = FinalizedTransaction, TSyncUpdate = WalletSyncUpdate, TSerialized = string, TConfig extends BaseV1Configuration = DefaultDustConfiguration> extends WalletLike.BaseWalletClass<[
95
- Variant.VersionedVariant<V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux>>
96
- ]> {
97
- configuration: TConfig;
98
- startWithSeed(seed: Uint8Array, dustParameters: DustParameters): CustomizedDustWallet<TStartAux, TTransaction, TSyncUpdate, TSerialized>;
99
- startWithSecretKey(secretKey: DustSecretKey, dustParameters: DustParameters): CustomizedDustWallet<TStartAux, TTransaction, TSyncUpdate, TSerialized>;
100
- restore(serializedState: TSerialized): CustomizedDustWallet<TStartAux, TTransaction, TSyncUpdate, TSerialized>;
150
+ /** The class a forking dust wallet is started from. */
151
+ export interface ForkingDustWalletClass<TV1SyncUpdate, TV2SyncUpdate, TConfiguration extends ForkingDustConfiguration = ForkingDustConfiguration> extends WalletLike.BaseWalletClass<ForkingDustVariants<TV1SyncUpdate, TV2SyncUpdate>, TConfiguration> {
152
+ /**
153
+ * Builds a wallet from a seed, and remembers the seed.
154
+ *
155
+ * @remarks
156
+ * The only start that can follow the chain the whole way. The seed is the one piece of key material that crosses a
157
+ * protocol boundary — each variant derives its own `DustSecretKey` from it, and the two derive the same dust public
158
+ * key — so a wallet built this way can synchronize on either side of the fork.
159
+ *
160
+ * Asynchronous because choosing where to begin can mean asking the chain: with a
161
+ * {@link ForkingDustConfiguration.chainVersionProbe} configured, the wallet starts at the variant that owns the
162
+ * version the chain reports, which on a chain already past the boundary is the ledger-v9 one from the first moment.
163
+ * Without one, or when the question goes unanswered, it begins on the V1 variant and is handed over when the chain
164
+ * reports a version the V2 variant owns — on a chain that has already forked, the first batch it sees.
165
+ * @param seed The seed to derive both ledger versions' dust keys from.
166
+ * @param dustParameters The ledger-v9's dust parameters, which an empty ledger-v9 state is valued against.
167
+ * @returns A wallet started at the variant the chain is on, or on the V1 variant when the chain was not asked or did
168
+ * not say.
169
+ */
170
+ startWithSeed(seed: Uint8Array, dustParameters?: DustGenerationRates): Promise<ForkingDustWallet<TV1SyncUpdate, TV2SyncUpdate>>;
171
+ /**
172
+ * Builds a wallet from dust keys of both ledger versions.
173
+ *
174
+ * @remarks
175
+ * The escape hatch for a caller that will not hand over a seed. Both sides are required, and that is the whole point:
176
+ * a `DustSecretKey` belongs to one ledger version's runtime — there is nothing to convert, and the dust public keys
177
+ * being identical either side does not help, because reading dust needs the secret — so a wallet given one side
178
+ * alone could not read the other side of the chain. It costs the caller an import of both ledger packages and the
179
+ * same derivation done twice; a seed costs neither.
180
+ * @param keys One ledger version's dust secret key per side of the boundary.
181
+ * @param dustParameters The ledger-v9's dust parameters.
182
+ * @returns A wallet started at the variant the chain is on, or on the V1 variant — where a wallet with no history
183
+ * belongs — when the chain was not asked or did not say.
184
+ */
185
+ startWithKeys(keys: DustKeysByEpoch, dustParameters?: DustGenerationRates): Promise<ForkingDustWallet<TV1SyncUpdate, TV2SyncUpdate>>;
186
+ /**
187
+ * Restores a wallet from a snapshot, into whichever registered variant wrote it.
188
+ *
189
+ * @param serializedState The serialized wallet state.
190
+ * @returns A wallet started from that state, on the variant that owns its protocol version.
191
+ * @throws UnsupportedSnapshotVersionError if the snapshot declares a version no registered variant reads.
192
+ */
193
+ restore(serializedState: string): ForkingDustWallet<TV1SyncUpdate, TV2SyncUpdate>;
194
+ /**
195
+ * Restores a wallet from a snapshot, reporting what it could not read rather than throwing.
196
+ *
197
+ * @remarks
198
+ * Additive alongside {@link restore}, which is unchanged and still the right shape for a snapshot the application has
199
+ * just written itself. This is the shape for one it has not: a snapshot a user supplied, or one written by a build
200
+ * of the SDK that is no longer the one running, where "I cannot read this" is an ordinary answer rather than a bug.
201
+ * The two cannot disagree — `restore` is this, with the reason thrown.
202
+ * @param serializedState The serialized wallet state.
203
+ * @returns A wallet started from that state, or the reason the snapshot could not be read. See
204
+ * {@link DustRestoreError}.
205
+ */
206
+ tryRestore(serializedState: string): Either.Either<ForkingDustWallet<TV1SyncUpdate, TV2SyncUpdate>, DustRestoreError>;
101
207
  }
102
- export type DustWallet = CustomizedDustWallet<DustSecretKey, FinalizedTransaction, WalletSyncUpdate, string>;
103
- export type DustWalletClass = CustomizedDustWalletClass<DustSecretKey, FinalizedTransaction, WalletSyncUpdate, string>;
208
+ /**
209
+ * The same dust parameters, rebuilt by the ledger-v8.
210
+ *
211
+ * @remarks
212
+ * Dust's own departure from shielded, and the one place this wallet has to translate anything. `DustLocalState` is
213
+ * parameterised, so an empty ledger-v8 state cannot be built without a ledger-v8 `DustParameters` — and the
214
+ * application hands over a ledger-v9 one, because that is the ledger version this wallet's public API speaks. What
215
+ * crosses is therefore the three numbers, not the object: they are plain `bigint`s, and the ledger-v8 class takes
216
+ * exactly them.
217
+ * @param parameters The ledger-v9's dust parameters.
218
+ * @returns The same generation and decay rates, as a ledger-v8 `DustParameters`.
219
+ */
220
+ /**
221
+ * The rates dust is generated and decays at, as plain data.
222
+ *
223
+ * @remarks
224
+ * Structurally what both ledger versions' `DustParameters` are — three scalars and nothing else — which is why the
225
+ * ledger classes remain assignable to this and a caller who already holds one can go on passing it. What it removes
226
+ * is the reason to obtain one: three numbers do not need a ledger version to express, and asking for a
227
+ * `LedgerParameters.initialParameters().dust` made an application import a ledger to start a wallet.
228
+ */
229
+ export type DustGenerationRates = Readonly<{
230
+ /** How much dust one Night generates, at the cap. */
231
+ nightDustRatio: bigint;
232
+ /** How fast dust decays once its Night is spent. */
233
+ generationDecayRate: bigint;
234
+ /** How long dust survives after its Night is spent. */
235
+ dustGracePeriodSeconds: bigint;
236
+ }>;
237
+ export declare const asV8DustParameters: (parameters: DustGenerationRates) => ledgerV8.DustParameters;
238
+ /**
239
+ * The same dust rates, as ledger-v9's parameters object.
240
+ *
241
+ * @remarks
242
+ * The mirror of {@link asV8DustParameters}, and needed for the same reason: an empty state of either variant is
243
+ * parameterised, and the rates a caller names are plain numbers rather than either ledger's object. Ordinarily the
244
+ * ledger-v9 side's empty state is the migration's business; a wallet that starts on V2 because the chain said so has
245
+ * no migration to get one from, and builds its own here.
246
+ * @param parameters The rates to express.
247
+ * @returns The same generation and decay rates, as a ledger-v9 `DustParameters`.
248
+ */
249
+ export declare const asV9DustParameters: (parameters: DustGenerationRates) => ledgerV9.DustParameters;
250
+ /**
251
+ * Builds a dust wallet class over a variant either side of a protocol boundary.
252
+ *
253
+ * @remarks
254
+ * The boundary is `configuration.forks.v9` and nothing else: the V1 variant is registered from the minimum supported
255
+ * version and the ledger-v9 one from the fork version, so the version at which the runtime hands over and the version
256
+ * at which each variant stops applying are the same number, taken from one place.
257
+ *
258
+ * Each variant is built from its own configuration, which for dust is load-bearing rather than tidy — see
259
+ * {@link SelfConfiguredDustVariant}.
260
+ * @example
261
+ * ```typescript
262
+ * const Wallet = CustomForkingDustWallet(
263
+ * { forks },
264
+ * { builder: new V1Builder().withDefaults(), configuration: v1Configuration },
265
+ * { builder: new V2Builder().withDefaults().withMigration(...), configuration: v2Configuration },
266
+ * );
267
+ * const wallet = Wallet.startWithSeed(seed, dustParameters);
268
+ * ```;
269
+ *
270
+ * @param configuration What the wallet layer needs: where the boundary lies.
271
+ * @param v1 The variant that reads the chain below the boundary, with the configuration it is built from.
272
+ * @param v2 The variant that reads it from the boundary, with the configuration it is built from.
273
+ * @returns The wallet class.
274
+ */
275
+ export declare function CustomForkingDustWallet<TV1SyncUpdate, TV2SyncUpdate, TV1Config extends object, TV2Config extends object, TConfiguration extends ForkingDustConfiguration = ForkingDustConfiguration>(configuration: TConfiguration, v1: SelfConfiguredDustVariant<V1DustVariant<TV1SyncUpdate>, TV1Config>, v2: SelfConfiguredDustVariant<V2DustVariant<TV2SyncUpdate>, TV2Config>): ForkingDustWalletClass<TV1SyncUpdate, TV2SyncUpdate, TConfiguration>;
276
+ /** A dust wallet built the way this package ships it: one variant either side of the protocol boundary. */
277
+ export type DustWallet = ForkingDustWallet<V1SyncUpdate, V2SyncUpdate>;
278
+ /** The class {@link DustWallet} builds. */
279
+ export type DustWalletClass = ForkingDustWalletClass<V1SyncUpdate, V2SyncUpdate, DefaultDustConfiguration>;
280
+ /**
281
+ * Builds the dust wallet this package ships: the default variant either side of `configuration.forks.v9`.
282
+ *
283
+ * @remarks
284
+ * Both variants read the chain through the indexer's dust event subscription and record transaction history in the same
285
+ * storage. Each is built from the same application configuration, because what they ask for happens to coincide —
286
+ * with one exception the type system cannot police: `dustParameters` names a ledger type, and the two ledgers'
287
+ * `DustParameters` are structurally identical, so it is passed only to the variant it belongs to.
288
+ *
289
+ * **The V1 variant syncs by event replay only.** The projections fast-sync path is a ledger-v9 capability: it needs
290
+ * four `DustLocalState` APIs that no published ledger-v8 has. That is a permanent property of the V1 variant, not a
291
+ * gap to be closed.
292
+ *
293
+ * **Fee-paying operations work on either side of the boundary**: the active variant answers with its own ledger's
294
+ * objects, and every result travels as a handle stamped with the epoch that built it.
295
+ *
296
+ * **The chain is asked where it is before a variant is chosen.** The indexer this wallet already syncs from answers
297
+ * which protocol version the chain is on, so a start on a chain past the boundary begins on V2 rather than handing
298
+ * over immediately. An application that would rather ask something else — a cache, a value it already holds —
299
+ * supplies its own `chainVersionProbe`; one whose chain cannot be reached loses nothing, because the answer is
300
+ * best-effort and its absence is the behaviour this wallet had before.
301
+ * @param configuration What the wallet and both its variants are built from, including where the boundary lies.
302
+ * @returns The wallet class.
303
+ */
104
304
  export declare function DustWallet(configuration: DefaultDustConfiguration): DustWalletClass;
105
- export declare function CustomDustWallet<TConfig extends BaseV1Configuration = DefaultDustConfiguration, TStartAux = DustSecretKey, TTransaction = FinalizedTransaction, TSyncUpdate = WalletSyncUpdate, TSerialized = string>(configuration: TConfig, builder: VariantBuilder.VariantBuilder<V1Variant<TSerialized, TSyncUpdate, TTransaction, TStartAux>, TConfig>): CustomizedDustWalletClass<TStartAux, TTransaction, TSyncUpdate, TSerialized, TConfig>;