@midnight-ntwrk/wallet-sdk-facade 3.0.0-rc.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # @midnight-ntwrk/wallet-sdk-facade
2
2
 
3
+ > **Note:** It is recommended to use the [`@midnight-ntwrk/wallet-sdk`](../wallet-sdk/README.md) barrel package, which
4
+ > re-exports this and all other wallet SDK packages through a single dependency.
5
+
3
6
  Unified facade for the Midnight Wallet SDK that combines all wallet types into a single API.
4
7
 
5
8
  ## Installation
package/dist/index.d.ts CHANGED
@@ -6,9 +6,72 @@ import { type AnyTransaction, type CoinsAndBalances as DustCoinsAndBalances } fr
6
6
  import { type DefaultShieldedConfiguration, type ShieldedWalletAPI, type ShieldedWalletState } from '@midnight-ntwrk/wallet-sdk-shielded';
7
7
  import type { DefaultUnshieldedConfiguration, UnshieldedWalletAPI } from '@midnight-ntwrk/wallet-sdk-unshielded-wallet';
8
8
  import { type UnshieldedWalletState } from '@midnight-ntwrk/wallet-sdk-unshielded-wallet';
9
+ import { Schema } from 'effect';
10
+ import { TransactionHistoryStorage } from '@midnight-ntwrk/wallet-sdk-abstractions';
9
11
  import { type Observable } from 'rxjs';
10
- import { DefaultPendingTransactionsServiceConfiguration, PendingTransactions, PendingTransactionsService } from '@midnight-ntwrk/wallet-sdk-capabilities';
11
- import { DustAddress, ShieldedAddress, UnshieldedAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
12
+ import { type DefaultPendingTransactionsServiceConfiguration, PendingTransactions, type PendingTransactionsService } from '@midnight-ntwrk/wallet-sdk-capabilities';
13
+ import { type DustAddress, type ShieldedAddress, type UnshieldedAddress } from '@midnight-ntwrk/wallet-sdk-address-format';
14
+ /**
15
+ * Full entry schema for transaction history — common fields + all wallet sections. Pass this to
16
+ * `InMemoryTransactionHistoryStorage` to enable serialize/restore.
17
+ */
18
+ export declare const WalletEntrySchema: Schema.Struct<{
19
+ shielded: Schema.optional<Schema.Struct<{
20
+ receivedCoins: Schema.Array$<Schema.Struct<{
21
+ type: typeof Schema.String;
22
+ nonce: typeof Schema.String;
23
+ value: typeof Schema.BigInt;
24
+ mtIndex: typeof Schema.BigInt;
25
+ }>>;
26
+ spentCoins: Schema.Array$<Schema.Struct<{
27
+ type: typeof Schema.String;
28
+ nonce: typeof Schema.String;
29
+ value: typeof Schema.BigInt;
30
+ mtIndex: typeof Schema.BigInt;
31
+ }>>;
32
+ }>>;
33
+ unshielded: Schema.optional<Schema.Struct<{
34
+ id: typeof Schema.Number;
35
+ createdUtxos: Schema.Array$<Schema.Struct<{
36
+ value: Schema.Schema<bigint, string, never>;
37
+ owner: typeof Schema.String;
38
+ tokenType: typeof Schema.String;
39
+ intentHash: typeof Schema.String;
40
+ outputIndex: typeof Schema.Number;
41
+ }>>;
42
+ spentUtxos: Schema.Array$<Schema.Struct<{
43
+ value: Schema.Schema<bigint, string, never>;
44
+ owner: typeof Schema.String;
45
+ tokenType: typeof Schema.String;
46
+ intentHash: typeof Schema.String;
47
+ outputIndex: typeof Schema.Number;
48
+ }>>;
49
+ }>>;
50
+ dust: Schema.optional<Schema.Struct<{
51
+ receivedUtxos: Schema.Array$<Schema.Struct<{
52
+ initialValue: typeof Schema.BigInt;
53
+ nonce: typeof Schema.BigInt;
54
+ seq: typeof Schema.Number;
55
+ backingNight: typeof Schema.String;
56
+ mtIndex: typeof Schema.BigInt;
57
+ }>>;
58
+ spentUtxos: Schema.Array$<Schema.Struct<{
59
+ initialValue: typeof Schema.BigInt;
60
+ nonce: typeof Schema.BigInt;
61
+ seq: typeof Schema.Number;
62
+ backingNight: typeof Schema.String;
63
+ mtIndex: typeof Schema.BigInt;
64
+ }>>;
65
+ }>>;
66
+ hash: typeof Schema.String;
67
+ protocolVersion: typeof Schema.Number;
68
+ status: Schema.Literal<["SUCCESS", "FAILURE", "PARTIAL_SUCCESS"]>;
69
+ identifiers: Schema.optional<Schema.Array$<typeof Schema.String>>;
70
+ timestamp: Schema.optional<typeof Schema.Date>;
71
+ fees: Schema.optional<Schema.NullOr<typeof Schema.BigInt>>;
72
+ }>;
73
+ export type WalletEntry = Schema.Schema.Type<typeof WalletEntrySchema>;
74
+ export declare const mergeWalletEntries: (existing: WalletEntry, incoming: WalletEntry) => WalletEntry;
12
75
  type TokenKind = 'dust' | 'shielded' | 'unshielded';
13
76
  type TokenKindsToBalance = 'all' | TokenKind[];
14
77
  declare const TokenKindsToBalance: {
@@ -74,8 +137,17 @@ export declare class FacadeState {
74
137
  constructor(shielded: ShieldedWalletState, unshielded: UnshieldedWalletState, dust: DustWalletState, pending: PendingTransactions.PendingTransactions<ledger.FinalizedTransaction>);
75
138
  }
76
139
  /**
77
- * The Terms and Conditions returned by the indexer, containing a URL for display
78
- * and a SHA-256 hash for content verification.
140
+ * A clock abstraction for obtaining the current time. By default, the facade uses the system clock. For testing with a
141
+ * simulator, inject a custom clock (e.g., one backed by the simulator's time).
142
+ */
143
+ export type Clock = {
144
+ readonly now: () => Date;
145
+ };
146
+ /** Default clock using real system time. */
147
+ export declare const systemClock: Clock;
148
+ /**
149
+ * The Terms and Conditions returned by the indexer, containing a URL for display and a SHA-256 hash for content
150
+ * verification.
79
151
  */
80
152
  export type TermsAndConditions = {
81
153
  /** The hex-encoded SHA-256 hash of the Terms and Conditions document. */
@@ -84,9 +156,9 @@ export type TermsAndConditions = {
84
156
  url: string;
85
157
  };
86
158
  /**
87
- * Minimal configuration required for {@link WalletFacade.fetchTermsAndConditions}.
88
- * Accepts the shared `indexerClientConnection` sub-object found on all wallet configurations,
89
- * so callers can pass the full wallet configuration directly without any adaptation.
159
+ * Minimal configuration required for {@link WalletFacade.fetchTermsAndConditions}. Accepts the shared
160
+ * `indexerClientConnection` sub-object found on all wallet configurations, so callers can pass the full wallet
161
+ * configuration directly without any adaptation.
90
162
  */
91
163
  export type FetchTermsAndConditionsConfiguration = {
92
164
  indexerClientConnection: {
@@ -98,6 +170,8 @@ export type DefaultConfiguration = DefaultUnshieldedConfiguration & DefaultShiel
98
170
  type MaybePromise<T> = T | Promise<T>;
99
171
  export type InitParams<TConfig extends DefaultConfiguration> = {
100
172
  configuration: TConfig;
173
+ /** Optional factory for the clock abstraction. Defaults to system clock (`() => new Date()`). */
174
+ clock?: (config: TConfig) => MaybePromise<Clock>;
101
175
  submissionService?: (config: TConfig) => MaybePromise<SubmissionService<ledger.FinalizedTransaction>>;
102
176
  pendingTransactionsService?: (config: TConfig) => MaybePromise<PendingTransactionsService<ledger.FinalizedTransaction>>;
103
177
  provingService?: (config: TConfig) => MaybePromise<ProvingService<UnboundTransaction>>;
@@ -113,18 +187,17 @@ export declare class WalletFacade {
113
187
  /**
114
188
  * Fetches the current Terms and Conditions from the network indexer.
115
189
  *
116
- * This is a static, pre-initialization utility — no wallet instance is required.
117
- * Wallet builders should call this before or independently of wallet initialization
118
- * to display the current T&C to end users and obtain the hash for content verification.
190
+ * This is a static, pre-initialization utility — no wallet instance is required. Wallet builders should call this
191
+ * before or independently of wallet initialization to display the current T&C to end users and obtain the hash for
192
+ * content verification.
119
193
  *
120
- * The returned `hash` is the hex-encoded SHA-256 hash of the document at `url`.
121
- * Wallet builders are responsible for fetching and rendering the document content
122
- * via `url` in whatever manner suits their application.
194
+ * The returned `hash` is the hex-encoded SHA-256 hash of the document at `url`. Wallet builders are responsible for
195
+ * fetching and rendering the document content via `url` in whatever manner suits their application.
123
196
  *
124
- * @param configuration - An object with an `indexerClientConnection.indexerHttpUrl`.
125
- * Any wallet configuration that satisfies {@link FetchTermsAndConditionsConfiguration} can be passed directly.
126
- * @returns A promise resolving to the current {@link TermsAndConditions}, or rejecting if
127
- * no Terms and Conditions have been set on the network yet.
197
+ * @param configuration - An object with an `indexerClientConnection.indexerHttpUrl`. Any wallet configuration that
198
+ * satisfies {@link FetchTermsAndConditionsConfiguration} can be passed directly.
199
+ * @returns A promise resolving to the current {@link TermsAndConditions}, or rejecting if no Terms and Conditions have
200
+ * been set on the network yet.
128
201
  */
129
202
  static fetchTermsAndConditions(configuration: FetchTermsAndConditionsConfiguration): Promise<TermsAndConditions>;
130
203
  static init<TConfig extends DefaultConfiguration>(initParams: InitParams<TConfig>): Promise<WalletFacade>;
@@ -134,6 +207,7 @@ export declare class WalletFacade {
134
207
  readonly submissionService: SubmissionService<ledger.FinalizedTransaction>;
135
208
  readonly pendingTransactionsService: PendingTransactionsService<ledger.FinalizedTransaction>;
136
209
  readonly provingService: ProvingService<UnboundTransaction>;
210
+ readonly clock: Clock;
137
211
  private constructor();
138
212
  private defaultTtl;
139
213
  private mergeUnprovenTransactions;
@@ -183,8 +257,10 @@ export declare class WalletFacade {
183
257
  }): Promise<UnprovenTransactionRecipe>;
184
258
  /**
185
259
  * Provides estimate of the fee of issuing registration transaction with provided UTxOs
260
+ *
186
261
  * @param nightUtxos - Night UTxOs to use for the registration
187
- * @returns And object informing about fee at the moment, as well as estimation of dust generation of the UTxO(s), that would be used for paying the fee. These include data that allows to compute when the fee could be paid
262
+ * @returns And object informing about fee at the moment, as well as estimation of dust generation of the UTxO(s),
263
+ * that would be used for paying the fee. These include data that allows to compute when the fee could be paid
188
264
  */
189
265
  estimateRegistration(nightUtxos: readonly UtxoWithMeta[]): Promise<{
190
266
  fee: bigint;
@@ -203,5 +279,7 @@ export declare class WalletFacade {
203
279
  revertTransaction(tx: AnyTransaction): Promise<void>;
204
280
  start(shieldedSecretKeys: ledger.ZswapSecretKeys, dustSecretKey: ledger.DustSecretKey): Promise<void>;
205
281
  stop(): Promise<void>;
282
+ queryTxHistoryByHash(hash: TransactionHistoryStorage.TransactionHash): Promise<WalletEntry | undefined>;
283
+ getAllFromTxHistory(): Promise<WalletEntry[]>;
206
284
  }
207
285
  export {};
package/dist/index.js CHANGED
@@ -13,12 +13,40 @@
13
13
  import * as ledger from '@midnight-ntwrk/ledger-v8';
14
14
  import { makeDefaultSubmissionService, } from '@midnight-ntwrk/wallet-sdk-capabilities';
15
15
  import { makeDefaultProvingService, } from '@midnight-ntwrk/wallet-sdk-capabilities/proving';
16
+ import { ShieldedSectionSchema, mergeShieldedSections, } from '@midnight-ntwrk/wallet-sdk-shielded';
17
+ import { UnshieldedSectionSchema } from '@midnight-ntwrk/wallet-sdk-unshielded-wallet';
18
+ import { DustSectionSchema, mergeDustSections } from '@midnight-ntwrk/wallet-sdk-dust-wallet';
16
19
  import { FetchTermsAndConditions as FetchTermsAndConditionsQuery } from '@midnight-ntwrk/wallet-sdk-indexer-client';
17
20
  import { QueryRunner } from '@midnight-ntwrk/wallet-sdk-indexer-client/effect';
18
- import { Array as Arr, pipe } from 'effect';
21
+ import { Array as Arr, pipe, Schema } from 'effect';
22
+ import { TransactionHistoryStorage } from '@midnight-ntwrk/wallet-sdk-abstractions';
19
23
  import { combineLatest, map, firstValueFrom, concatMap } from 'rxjs';
20
24
  import { PendingTransactions, PendingTransactionsServiceImpl, } from '@midnight-ntwrk/wallet-sdk-capabilities';
21
25
  import { finalizedTransactionTrait } from './transaction.js';
26
+ /**
27
+ * Full entry schema for transaction history — common fields + all wallet sections. Pass this to
28
+ * `InMemoryTransactionHistoryStorage` to enable serialize/restore.
29
+ */
30
+ export const WalletEntrySchema = Schema.Struct({
31
+ ...TransactionHistoryStorage.TransactionHistoryCommonSchema.fields,
32
+ shielded: Schema.optional(ShieldedSectionSchema),
33
+ unshielded: Schema.optional(UnshieldedSectionSchema),
34
+ dust: Schema.optional(DustSectionSchema),
35
+ });
36
+ export const mergeWalletEntries = (existing, incoming) => ({
37
+ ...existing,
38
+ ...incoming,
39
+ ...(existing.shielded !== undefined && incoming.shielded !== undefined
40
+ ? { shielded: mergeShieldedSections(existing.shielded, incoming.shielded) }
41
+ : {}),
42
+ ...(existing.unshielded !== undefined && incoming.unshielded !== undefined
43
+ ? { unshielded: { ...existing.unshielded, ...incoming.unshielded } }
44
+ : {}),
45
+ ...(existing.dust !== undefined && incoming.dust !== undefined
46
+ ? { dust: mergeDustSections(existing.dust, incoming.dust) }
47
+ : {}),
48
+ });
49
+ const isWalletEntry = Schema.is(WalletEntrySchema);
22
50
  const TokenKindsToBalance = new (class {
23
51
  allTokenKinds = ['shielded', 'unshielded', 'dust'];
24
52
  toFlags = (tokenKinds) => {
@@ -70,6 +98,8 @@ export class FacadeState {
70
98
  }
71
99
  }
72
100
  const DEFAULT_TTL_MS = 60 * 60 * 1000; // 1 hour
101
+ /** Default clock using real system time. */
102
+ export const systemClock = { now: () => new Date() };
73
103
  export class WalletFacade {
74
104
  static makeDefaultSubmissionService(config) {
75
105
  return makeDefaultSubmissionService(config);
@@ -93,18 +123,17 @@ export class WalletFacade {
93
123
  /**
94
124
  * Fetches the current Terms and Conditions from the network indexer.
95
125
  *
96
- * This is a static, pre-initialization utility — no wallet instance is required.
97
- * Wallet builders should call this before or independently of wallet initialization
98
- * to display the current T&C to end users and obtain the hash for content verification.
126
+ * This is a static, pre-initialization utility — no wallet instance is required. Wallet builders should call this
127
+ * before or independently of wallet initialization to display the current T&C to end users and obtain the hash for
128
+ * content verification.
99
129
  *
100
- * The returned `hash` is the hex-encoded SHA-256 hash of the document at `url`.
101
- * Wallet builders are responsible for fetching and rendering the document content
102
- * via `url` in whatever manner suits their application.
130
+ * The returned `hash` is the hex-encoded SHA-256 hash of the document at `url`. Wallet builders are responsible for
131
+ * fetching and rendering the document content via `url` in whatever manner suits their application.
103
132
  *
104
- * @param configuration - An object with an `indexerClientConnection.indexerHttpUrl`.
105
- * Any wallet configuration that satisfies {@link FetchTermsAndConditionsConfiguration} can be passed directly.
106
- * @returns A promise resolving to the current {@link TermsAndConditions}, or rejecting if
107
- * no Terms and Conditions have been set on the network yet.
133
+ * @param configuration - An object with an `indexerClientConnection.indexerHttpUrl`. Any wallet configuration that
134
+ * satisfies {@link FetchTermsAndConditionsConfiguration} can be passed directly.
135
+ * @returns A promise resolving to the current {@link TermsAndConditions}, or rejecting if no Terms and Conditions have
136
+ * been set on the network yet.
108
137
  */
109
138
  static async fetchTermsAndConditions(configuration) {
110
139
  const result = await QueryRunner.runPromise(FetchTermsAndConditionsQuery, {}, {
@@ -129,7 +158,8 @@ export class WalletFacade {
129
158
  const shielded = await Promise.resolve(initParams.shielded(initParams.configuration));
130
159
  const unshielded = await Promise.resolve(initParams.unshielded(initParams.configuration));
131
160
  const dust = await Promise.resolve(initParams.dust(initParams.configuration));
132
- return new WalletFacade(shielded, unshielded, dust, submissionService, pendingTransactionsService, provingService);
161
+ const clock = await Promise.resolve(initParams.clock ? initParams.clock(initParams.configuration) : systemClock);
162
+ return new WalletFacade(shielded, unshielded, dust, submissionService, pendingTransactionsService, provingService, initParams.configuration.txHistoryStorage, clock);
133
163
  }
134
164
  shielded;
135
165
  unshielded;
@@ -137,21 +167,25 @@ export class WalletFacade {
137
167
  submissionService;
138
168
  pendingTransactionsService;
139
169
  provingService;
170
+ #txHistoryStorage;
171
+ clock;
140
172
  #pendingSubscription;
141
- constructor(shieldedWallet, unshieldedWallet, dustWallet, submissionService, pendingTransactionsService, provingService) {
173
+ constructor(shieldedWallet, unshieldedWallet, dustWallet, submissionService, pendingTransactionsService, provingService, txHistoryStorage, clock = systemClock) {
142
174
  this.shielded = shieldedWallet;
143
175
  this.unshielded = unshieldedWallet;
144
176
  this.dust = dustWallet;
145
177
  this.submissionService = submissionService;
146
178
  this.pendingTransactionsService = pendingTransactionsService;
147
179
  this.provingService = provingService;
180
+ this.#txHistoryStorage = txHistoryStorage;
181
+ this.clock = clock;
148
182
  this.#pendingSubscription = this.pendingTransactionsService
149
183
  .state()
150
184
  .pipe(concatMap((pending) => PendingTransactions.allFailed(pending)), concatMap((item) => this.revert(item.tx)))
151
185
  .subscribe();
152
186
  }
153
187
  defaultTtl() {
154
- return new Date(Date.now() + DEFAULT_TTL_MS);
188
+ return new Date(this.clock.now().getTime() + DEFAULT_TTL_MS);
155
189
  }
156
190
  mergeUnprovenTransactions(a, b) {
157
191
  if (a && b)
@@ -397,11 +431,13 @@ export class WalletFacade {
397
431
  }
398
432
  /**
399
433
  * Provides estimate of the fee of issuing registration transaction with provided UTxOs
434
+ *
400
435
  * @param nightUtxos - Night UTxOs to use for the registration
401
- * @returns And object informing about fee at the moment, as well as estimation of dust generation of the UTxO(s), that would be used for paying the fee. These include data that allows to compute when the fee could be paid
436
+ * @returns And object informing about fee at the moment, as well as estimation of dust generation of the UTxO(s),
437
+ * that would be used for paying the fee. These include data that allows to compute when the fee could be paid
402
438
  */
403
439
  async estimateRegistration(nightUtxos) {
404
- const now = new Date();
440
+ const now = this.clock.now();
405
441
  const dustState = await this.dust.waitForSyncedState();
406
442
  const dustGenerationEstimations = pipe(nightUtxos, Arr.map(({ utxo, meta }) => ({
407
443
  ...utxo,
@@ -500,4 +536,12 @@ export class WalletFacade {
500
536
  Promise.resolve(this.#pendingSubscription?.unsubscribe()),
501
537
  ]);
502
538
  }
539
+ async queryTxHistoryByHash(hash) {
540
+ const raw = await this.#txHistoryStorage.get(hash);
541
+ return raw && isWalletEntry(raw) ? raw : undefined;
542
+ }
543
+ async getAllFromTxHistory() {
544
+ const allEntries = await this.#txHistoryStorage.getAll();
545
+ return [...allEntries];
546
+ }
503
547
  }
@@ -1,3 +1,3 @@
1
- import { PendingTransactions } from '@midnight-ntwrk/wallet-sdk-capabilities';
1
+ import { type PendingTransactions } from '@midnight-ntwrk/wallet-sdk-capabilities';
2
2
  import * as ledger from '@midnight-ntwrk/ledger-v8';
3
3
  export declare const finalizedTransactionTrait: PendingTransactions.TransactionTrait<ledger.FinalizedTransaction>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midnight-ntwrk/wallet-sdk-facade",
3
- "version": "3.0.0-rc.0",
3
+ "version": "4.0.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -24,19 +24,19 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "@midnight-ntwrk/ledger-v8": "^8.0.2",
28
- "@midnight-ntwrk/wallet-sdk-address-format": "^3.1.0-rc.0",
29
- "@midnight-ntwrk/wallet-sdk-capabilities": "^3.2.0-rc.0",
30
- "@midnight-ntwrk/wallet-sdk-dust-wallet": "^3.0.0-rc.0",
31
- "@midnight-ntwrk/wallet-sdk-indexer-client": "^1.2.0-rc.0",
32
- "@midnight-ntwrk/wallet-sdk-shielded": "^2.1.0-rc.0",
33
- "@midnight-ntwrk/wallet-sdk-unshielded-wallet": "^2.1.0-rc.0",
27
+ "@midnight-ntwrk/ledger-v8": "^8.0.3",
28
+ "@midnight-ntwrk/wallet-sdk-address-format": "^3.1.1",
29
+ "@midnight-ntwrk/wallet-sdk-capabilities": "^3.3.0",
30
+ "@midnight-ntwrk/wallet-sdk-dust-wallet": "^4.0.0",
31
+ "@midnight-ntwrk/wallet-sdk-indexer-client": "^1.2.1",
32
+ "@midnight-ntwrk/wallet-sdk-shielded": "^3.0.0",
33
+ "@midnight-ntwrk/wallet-sdk-unshielded-wallet": "^3.0.0",
34
34
  "rxjs": "^7.8.2"
35
35
  },
36
36
  "devDependencies": {
37
- "@midnight-ntwrk/wallet-sdk-abstractions": "^2.0.0",
38
- "@midnight-ntwrk/wallet-sdk-hd": "^3.0.1",
39
- "@midnight-ntwrk/wallet-sdk-utilities": "1.1.0-rc.0"
37
+ "@midnight-ntwrk/wallet-sdk-abstractions": "^2.1.0",
38
+ "@midnight-ntwrk/wallet-sdk-hd": "^3.0.2",
39
+ "@midnight-ntwrk/wallet-sdk-utilities": "1.1.1"
40
40
  },
41
41
  "scripts": {
42
42
  "typecheck": "tsc -b ./tsconfig.json --noEmit --force",