@midnight-ntwrk/wallet-sdk-facade 5.0.0-beta.3 → 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.
package/README.md CHANGED
@@ -71,7 +71,7 @@ const configuration = {
71
71
  provers: {
72
72
  // Below `forks.v9`: a proof server built against ledger-v8.
73
73
  v8: { kind: 'server', url: new URL('http://localhost:6301') },
74
- // From `forks.v9`: proving in this process, with the published circuits.
74
+ // From `forks.v9`: proving in this process, with ledger-v9's published key material.
75
75
  v9: { kind: 'wasm' },
76
76
  },
77
77
  };
@@ -84,8 +84,9 @@ below the boundary the wallet never authors for; a transaction stamped there the
84
84
  One shorthand remains: `provingServerUrl: url` is one proof server under every key, read only when `provers` is absent.
85
85
  The SDK drives it with each ledger version on its own side of `forks.v9`, so the same URL frames its requests correctly
86
86
  on both. A proof server, though, is built against one ledger version: no published image serves both, so a chain with
87
- history below the boundary wants `provers` with a server per side. The in-process prover works on bytes and does serve
88
- both, under both keys.
87
+ history below the boundary wants `provers` with a server per side. The in-process prover serves both: under each key it
88
+ proves with that ledger version's own key material (ledger-v8's circuits are generation 9, ledger-v9's generation 10),
89
+ read from `https://srs.midnight.network/` and checked against the hashes the ledger release declares.
89
90
 
90
91
  ### Observing Combined State
91
92
 
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ import type { DefaultUnshieldedConfiguration, SignSegment, UnshieldedWalletAPI }
8
8
  import { type UnshieldedWalletState } from '@midnight-ntwrk/wallet-sdk-unshielded-wallet';
9
9
  import { Clock } from '@midnight-ntwrk/wallet-sdk-utilities';
10
10
  import { type DateTime, Option, Schema } from 'effect';
11
- import { type AnyTx, type FinalizedTx, ProtocolVersion, TransactionHistoryStorage, type UnboundTx, type UnprovenTx } from '@midnight-ntwrk/wallet-sdk-abstractions';
11
+ import { type AnyTx, type FinalizedTx, ProtocolVersion, TransactionHistoryStorage, type UnboundTx, type UnprovenTx, WalletTransaction } from '@midnight-ntwrk/wallet-sdk-abstractions';
12
12
  import * as ledgerV8 from '@midnight-ntwrk/ledger-v8';
13
13
  import { type WalletSeeds } from '@midnight-ntwrk/wallet-sdk-hd';
14
14
  import { type Observable } from 'rxjs';
@@ -589,6 +589,37 @@ export declare class WalletFacade {
589
589
  private seal;
590
590
  /** The ledger primitives the facade signs with on its current side of the boundary. */
591
591
  private authoring;
592
+ /**
593
+ * Reads a transaction from bytes that name no protocol version, at the version the facade is acting at.
594
+ *
595
+ * @remarks
596
+ * For bytes that reach the wallet from outside the SDK — a dApp connector's serialized transaction above all, whose
597
+ * contract carries no version alongside them. The bytes cannot say which ledger version wrote them, so this answers
598
+ * with the only version the facade could act at anyway, and reads them with that version's ledger. Bytes the other
599
+ * ledger version wrote are refused here rather than misread, because the markers a stage names are part of what the
600
+ * ledger checks as it reads.
601
+ *
602
+ * The version is the facade's rather than the caller's, which is the point: a caller that reads
603
+ * {@link FacadeState.activeProtocolVersion} and seals a handle itself is answering the same question a moment
604
+ * earlier, with a crossing able to land in between. It is still only the version at the moment of the call — a
605
+ * crossing can land before the handle is used, and {@link ProtocolVersionMismatchError} from the operation that uses
606
+ * it is what says so.
607
+ * @example
608
+ * Balancing a transaction a dApp connector handed over as hex:
609
+ *
610
+ * ```typescript
611
+ * const handle = facade.adoptTransaction(Buffer.from(txHex, 'hex'), 'Unbound');
612
+ * const recipe = await facade.balanceUnboundTransaction(handle, { ttl });
613
+ * ```;
614
+ *
615
+ * @param bytes The transaction's own serialization, as the ledger version that wrote it produced it.
616
+ * @param stage How far along the building of the transaction these bytes are, which decides the markers they are read
617
+ * with.
618
+ * @returns The sealed handle, stamped with the protocol version the facade is acting at.
619
+ * @throws {@link WireFormatError} When the bytes are not a transaction of that version at that stage — which is what
620
+ * a transaction authored on the other side of a protocol boundary looks like from here.
621
+ */
622
+ adoptTransaction<TStage extends WalletTransaction.Stage>(bytes: Uint8Array, stage: TStage): WalletTransaction<TStage>;
592
623
  private defaultTtl;
593
624
  /**
594
625
  * Checks whether a transaction is structurally well-formed before passing it to a balance or submit method.
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import { Clock } from '@midnight-ntwrk/wallet-sdk-utilities';
20
20
  import { FetchTermsAndConditions as FetchTermsAndConditionsQuery } from '@midnight-ntwrk/wallet-sdk-indexer-client';
21
21
  import { QueryRunner } from '@midnight-ntwrk/wallet-sdk-indexer-client/effect';
22
22
  import { Array as Arr, Either, Option, pipe, Schema } from 'effect';
23
- import { ProtocolVersion, TransactionHistoryStorage, WalletTransaction, } from '@midnight-ntwrk/wallet-sdk-abstractions';
23
+ import { ProtocolVersion, TransactionHistoryStorage, WalletTransaction, WireFormatError, } from '@midnight-ntwrk/wallet-sdk-abstractions';
24
24
  import * as ledgerV8 from '@midnight-ntwrk/ledger-v8';
25
25
  import * as Signatures from '@midnight-ntwrk/wallet-sdk-capabilities/signatures';
26
26
  import { BehaviorSubject, combineLatest, concatMap, distinctUntilChanged, firstValueFrom, map, tap, } from 'rxjs';
@@ -114,11 +114,21 @@ const v9Authoring = {
114
114
  sampleSigningKey: () => ledgerV9.sampleSigningKey(),
115
115
  signatureVerifyingKey: (signingKey) => ledgerV9.signatureVerifyingKey(signingKey),
116
116
  signData: (signingKey, data) => ledgerV9.signData(signingKey, data),
117
+ deserializers: {
118
+ Unproven: (bytes) => ledgerV9.Transaction.deserialize('signature', 'pre-proof', 'pre-binding', bytes),
119
+ Unbound: (bytes) => ledgerV9.Transaction.deserialize('signature', 'proof', 'pre-binding', bytes),
120
+ Finalized: (bytes) => ledgerV9.Transaction.deserialize('signature', 'proof', 'binding', bytes),
121
+ },
117
122
  };
118
123
  const v8Authoring = {
119
124
  sampleSigningKey: () => ledgerV8.sampleSigningKey(),
120
125
  signatureVerifyingKey: (signingKey) => Signatures.liftSignatureVerifyingKey(ledgerV8.signatureVerifyingKey(signingKey)),
121
126
  signData: (signingKey, data) => Signatures.liftSignature(ledgerV8.signData(signingKey, data)),
127
+ deserializers: {
128
+ Unproven: (bytes) => ledgerV8.Transaction.deserialize('signature', 'pre-proof', 'pre-binding', bytes),
129
+ Unbound: (bytes) => ledgerV8.Transaction.deserialize('signature', 'proof', 'pre-binding', bytes),
130
+ Finalized: (bytes) => ledgerV8.Transaction.deserialize('signature', 'proof', 'binding', bytes),
131
+ },
122
132
  };
123
133
  const TokenKindsToBalance = new (class {
124
134
  allTokenKinds = ['shielded', 'unshielded', 'dust'];
@@ -541,6 +551,48 @@ export class WalletFacade {
541
551
  authoring() {
542
552
  return this.currentVersion() < this.#forkVersion ? v8Authoring : v9Authoring;
543
553
  }
554
+ /**
555
+ * Reads a transaction from bytes that name no protocol version, at the version the facade is acting at.
556
+ *
557
+ * @remarks
558
+ * For bytes that reach the wallet from outside the SDK — a dApp connector's serialized transaction above all, whose
559
+ * contract carries no version alongside them. The bytes cannot say which ledger version wrote them, so this answers
560
+ * with the only version the facade could act at anyway, and reads them with that version's ledger. Bytes the other
561
+ * ledger version wrote are refused here rather than misread, because the markers a stage names are part of what the
562
+ * ledger checks as it reads.
563
+ *
564
+ * The version is the facade's rather than the caller's, which is the point: a caller that reads
565
+ * {@link FacadeState.activeProtocolVersion} and seals a handle itself is answering the same question a moment
566
+ * earlier, with a crossing able to land in between. It is still only the version at the moment of the call — a
567
+ * crossing can land before the handle is used, and {@link ProtocolVersionMismatchError} from the operation that uses
568
+ * it is what says so.
569
+ * @example
570
+ * Balancing a transaction a dApp connector handed over as hex:
571
+ *
572
+ * ```typescript
573
+ * const handle = facade.adoptTransaction(Buffer.from(txHex, 'hex'), 'Unbound');
574
+ * const recipe = await facade.balanceUnboundTransaction(handle, { ttl });
575
+ * ```;
576
+ *
577
+ * @param bytes The transaction's own serialization, as the ledger version that wrote it produced it.
578
+ * @param stage How far along the building of the transaction these bytes are, which decides the markers they are read
579
+ * with.
580
+ * @returns The sealed handle, stamped with the protocol version the facade is acting at.
581
+ * @throws {@link WireFormatError} When the bytes are not a transaction of that version at that stage — which is what
582
+ * a transaction authored on the other side of a protocol boundary looks like from here.
583
+ */
584
+ adoptTransaction(bytes, stage) {
585
+ const protocolVersion = this.currentVersion();
586
+ return Either.getOrThrowWith(Either.try({
587
+ try: () => this.authoring().deserializers[stage](bytes),
588
+ catch: (cause) => new WireFormatError({
589
+ message: `These bytes are not a transaction of protocol version ${protocolVersion} at stage ${stage} — that is ` +
590
+ `the version this wallet is acting at, and a transaction built for another one has to be built again ` +
591
+ `for it.`,
592
+ cause,
593
+ }),
594
+ }).pipe(Either.map((transaction) => WalletTransaction.adopt(stage, transaction, protocolVersion))), (error) => error);
595
+ }
544
596
  defaultTtl() {
545
597
  return new Date(this.clock.now().getTime() + DEFAULT_TTL_MS);
546
598
  }
@@ -1051,11 +1103,12 @@ export class WalletFacade {
1051
1103
  if (!hasShieldedPart && !hasUnshieldedPart) {
1052
1104
  throw Error('At least one shielded or unshielded swap is required.');
1053
1105
  }
1054
- const shieldedTx = hasShieldedPart && shieldedInputs !== undefined
1055
- ? await this.shielded.initSwap(shieldedInputs, shieldedOutputs)
1106
+ // Build each leg if the swap involves that token kind, even when it has outputs but no inputs.
1107
+ const shieldedTx = hasShieldedPart
1108
+ ? await this.shielded.initSwap(shieldedInputs ?? {}, shieldedOutputs)
1056
1109
  : undefined;
1057
- const unshieldedTx = hasUnshieldedPart && unshieldedInputs !== undefined
1058
- ? await this.unshielded.initSwap(unshieldedInputs, unshieldedOutputs, ttl)
1110
+ const unshieldedTx = hasUnshieldedPart
1111
+ ? await this.unshielded.initSwap(unshieldedInputs ?? {}, unshieldedOutputs, ttl)
1059
1112
  : undefined;
1060
1113
  const combinedTx = this.mergeUnprovenTransactions(shieldedTx, unshieldedTx);
1061
1114
  if (!combinedTx) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midnight-ntwrk/wallet-sdk-facade",
3
- "version": "5.0.0-beta.3",
3
+ "version": "5.0.0-beta.4",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -26,19 +26,19 @@
26
26
  }
27
27
  },
28
28
  "dependencies": {
29
- "@midnightntwrk/ledger-v9": "1.0.0-rc.4",
30
- "@midnight-ntwrk/wallet-sdk-abstractions": "3.0.0-beta.1",
31
- "@midnight-ntwrk/wallet-sdk-address-format": "4.0.0-beta.3",
32
- "@midnight-ntwrk/wallet-sdk-capabilities": "4.0.0-beta.3",
33
- "@midnight-ntwrk/wallet-sdk-dust-wallet": "5.0.0-beta.3",
29
+ "@midnightntwrk/ledger-v9": "1.0.0-rc.5",
30
+ "@midnight-ntwrk/wallet-sdk-abstractions": "3.0.0-beta.2",
31
+ "@midnight-ntwrk/wallet-sdk-address-format": "4.0.0-beta.4",
32
+ "@midnight-ntwrk/wallet-sdk-capabilities": "4.0.0-beta.4",
33
+ "@midnight-ntwrk/wallet-sdk-dust-wallet": "5.0.0-beta.4",
34
34
  "@midnight-ntwrk/wallet-sdk-indexer-client": "2.0.0-beta.2",
35
- "@midnight-ntwrk/wallet-sdk-shielded": "4.0.0-beta.3",
36
- "@midnight-ntwrk/wallet-sdk-unshielded-wallet": "4.0.0-beta.3",
35
+ "@midnight-ntwrk/wallet-sdk-shielded": "4.0.0-beta.4",
36
+ "@midnight-ntwrk/wallet-sdk-unshielded-wallet": "4.0.0-beta.4",
37
37
  "effect": "^3.19.19",
38
38
  "rxjs": "^7.8.2"
39
39
  },
40
40
  "devDependencies": {
41
- "@midnight-ntwrk/wallet-sdk-hd": "^3.1.0-beta.2",
41
+ "@midnight-ntwrk/wallet-sdk-hd": "^3.1.0-beta.3",
42
42
  "@midnight-ntwrk/wallet-sdk-utilities": "^1.2.2-beta.0"
43
43
  },
44
44
  "scripts": {