@midnight-ntwrk/wallet-sdk-facade 1.0.0-beta.14 → 1.0.0-beta.16

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 (3) hide show
  1. package/dist/index.d.ts +38 -11
  2. package/dist/index.js +165 -100
  3. package/package.json +7 -6
package/dist/index.d.ts CHANGED
@@ -1,9 +1,24 @@
1
1
  import { Observable } from 'rxjs';
2
2
  import { ShieldedWalletState, type ShieldedWallet } from '@midnight-ntwrk/wallet-sdk-shielded';
3
3
  import { type UnshieldedWallet, UnshieldedWalletState } from '@midnight-ntwrk/wallet-sdk-unshielded-wallet';
4
- import { AnyTransaction, DustWallet, DustWalletState } from '@midnight-ntwrk/wallet-sdk-dust-wallet';
5
- import { ProvingRecipe } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
4
+ import { AnyTransaction, DustWallet, DustWalletState, CoinsAndBalances as DustCoinsAndBalances } from '@midnight-ntwrk/wallet-sdk-dust-wallet';
6
5
  import * as ledger from '@midnight-ntwrk/ledger-v7';
6
+ export type UnboundTransaction = ledger.Transaction<ledger.SignatureEnabled, ledger.Proof, ledger.PreBinding>;
7
+ export type FinalizedTransactionRecipe = {
8
+ type: 'FINALIZED_TRANSACTION';
9
+ originalTransaction: ledger.FinalizedTransaction;
10
+ balancingTransaction: ledger.UnprovenTransaction;
11
+ };
12
+ export type UnboundTransactionRecipe = {
13
+ type: 'UNBOUND_TRANSACTION';
14
+ baseTransaction: UnboundTransaction;
15
+ balancingTransaction: ledger.UnprovenTransaction;
16
+ };
17
+ export type UnprovenTransactionRecipe = {
18
+ type: 'UNPROVEN_TRANSACTION';
19
+ transaction: ledger.UnprovenTransaction;
20
+ };
21
+ export type BalancingRecipe = FinalizedTransactionRecipe | UnboundTransactionRecipe | UnprovenTransactionRecipe;
7
22
  export interface TokenTransfer {
8
23
  type: ledger.RawTokenType;
9
24
  receiverAddress: string;
@@ -33,20 +48,32 @@ export declare class FacadeState {
33
48
  constructor(shielded: ShieldedWalletState, unshielded: UnshieldedWalletState, dust: DustWalletState);
34
49
  }
35
50
  export declare class WalletFacade {
36
- shielded: ShieldedWallet;
37
- unshielded: UnshieldedWallet;
38
- dust: DustWallet;
51
+ readonly shielded: ShieldedWallet;
52
+ readonly unshielded: UnshieldedWallet;
53
+ readonly dust: DustWallet;
39
54
  constructor(shieldedWallet: ShieldedWallet, unshieldedWallet: UnshieldedWallet, dustWallet: DustWallet);
55
+ private defaultTtl;
56
+ private mergeUnprovenTransactions;
57
+ private createDustActionTransaction;
40
58
  state(): Observable<FacadeState>;
59
+ waitForSyncedState(): Promise<FacadeState>;
41
60
  submitTransaction(tx: ledger.FinalizedTransaction): Promise<TransactionIdentifier>;
42
- balanceTransaction(zswapSecretKeys: ledger.ZswapSecretKeys, dustSecretKeys: ledger.DustSecretKey, tx: ledger.Transaction<ledger.SignatureEnabled, ledger.Proofish, ledger.Bindingish>, ttl: Date): Promise<ProvingRecipe.ProvingRecipe<ledger.FinalizedTransaction>>;
43
- finalizeTransaction(recipe: ProvingRecipe.ProvingRecipe<ledger.FinalizedTransaction>): Promise<ledger.FinalizedTransaction>;
61
+ balanceFinalizedTransaction(zswapSecretKeys: ledger.ZswapSecretKeys, dustSecretKeys: ledger.DustSecretKey, tx: ledger.FinalizedTransaction, ttl: Date): Promise<FinalizedTransactionRecipe>;
62
+ balanceUnboundTransaction(zswapSecretKeys: ledger.ZswapSecretKeys, dustSecretKeys: ledger.DustSecretKey, tx: UnboundTransaction, ttl: Date): Promise<UnboundTransactionRecipe>;
63
+ balanceUnprovenTransaction(zswapSecretKeys: ledger.ZswapSecretKeys, dustSecretKeys: ledger.DustSecretKey, tx: ledger.UnprovenTransaction, ttl: Date): Promise<UnprovenTransactionRecipe>;
64
+ finalizeRecipe(recipe: BalancingRecipe): Promise<ledger.FinalizedTransaction>;
65
+ signRecipe(recipe: BalancingRecipe, signSegment: (data: Uint8Array) => ledger.Signature): Promise<BalancingRecipe>;
44
66
  signTransaction(tx: ledger.UnprovenTransaction, signSegment: (data: Uint8Array) => ledger.Signature): Promise<ledger.UnprovenTransaction>;
67
+ finalizeTransaction(tx: ledger.UnprovenTransaction): Promise<ledger.FinalizedTransaction>;
45
68
  calculateTransactionFee(tx: AnyTransaction): Promise<bigint>;
46
- transferTransaction(zswapSecretKeys: ledger.ZswapSecretKeys, dustSecretKey: ledger.DustSecretKey, outputs: CombinedTokenTransfer[], ttl: Date): Promise<ProvingRecipe.TransactionToProve>;
47
- registerNightUtxosForDustGeneration(nightUtxos: readonly UtxoWithMeta[], nightVerifyingKey: ledger.SignatureVerifyingKey, signDustRegistration: (payload: Uint8Array) => Promise<ledger.Signature> | ledger.Signature, dustReceiverAddress?: string): Promise<ProvingRecipe.TransactionToProve>;
48
- initSwap(zswapSecretKeys: ledger.ZswapSecretKeys, desiredInputs: CombinedSwapInputs, desiredOutputs: CombinedSwapOutputs[], ttl: Date): Promise<ledger.UnprovenTransaction>;
49
- deregisterFromDustGeneration(nightUtxos: UtxoWithMeta[], nightVerifyingKey: ledger.SignatureVerifyingKey, signDustRegistration: (payload: Uint8Array) => Promise<ledger.Signature> | ledger.Signature): Promise<ProvingRecipe.TransactionToProve>;
69
+ transferTransaction(zswapSecretKeys: ledger.ZswapSecretKeys, dustSecretKey: ledger.DustSecretKey, outputs: CombinedTokenTransfer[], ttl: Date): Promise<UnprovenTransactionRecipe>;
70
+ estimateRegistration(nightUtxos: readonly UtxoWithMeta[]): Promise<{
71
+ fee: bigint;
72
+ dustGenerationEstimations: ReadonlyArray<DustCoinsAndBalances.UtxoWithFullDustDetails>;
73
+ }>;
74
+ initSwap(zswapSecretKeys: ledger.ZswapSecretKeys, desiredInputs: CombinedSwapInputs, desiredOutputs: CombinedSwapOutputs[], ttl: Date): Promise<UnprovenTransactionRecipe>;
75
+ registerNightUtxosForDustGeneration(nightUtxos: readonly UtxoWithMeta[], nightVerifyingKey: ledger.SignatureVerifyingKey, signDustRegistration: (payload: Uint8Array) => ledger.Signature, dustReceiverAddress?: string): Promise<UnprovenTransactionRecipe>;
76
+ deregisterFromDustGeneration(nightUtxos: UtxoWithMeta[], nightVerifyingKey: ledger.SignatureVerifyingKey, signDustRegistration: (payload: Uint8Array) => ledger.Signature): Promise<UnprovenTransactionRecipe>;
50
77
  start(zswapSecretKeys: ledger.ZswapSecretKeys, dustSecretKey: ledger.DustSecretKey): Promise<void>;
51
78
  stop(): Promise<void>;
52
79
  }
package/dist/index.js CHANGED
@@ -11,7 +11,8 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { combineLatest, map } from 'rxjs';
14
- import { ProvingRecipe } from '@midnight-ntwrk/wallet-sdk-shielded/v1';
14
+ import { Array as Arr, pipe } from 'effect';
15
+ import * as ledger from '@midnight-ntwrk/ledger-v7';
15
16
  export class FacadeState {
16
17
  shielded;
17
18
  unshielded;
@@ -27,6 +28,7 @@ export class FacadeState {
27
28
  this.dust = dust;
28
29
  }
29
30
  }
31
+ const DEFAULT_TTL_MS = 60 * 60 * 1000; // 1 hour
30
32
  export class WalletFacade {
31
33
  shielded;
32
34
  unshielded;
@@ -36,45 +38,140 @@ export class WalletFacade {
36
38
  this.unshielded = unshieldedWallet;
37
39
  this.dust = dustWallet;
38
40
  }
41
+ defaultTtl() {
42
+ return new Date(Date.now() + DEFAULT_TTL_MS);
43
+ }
44
+ mergeUnprovenTransactions(a, b) {
45
+ if (a && b)
46
+ return a.merge(b);
47
+ return a ?? b;
48
+ }
49
+ async createDustActionTransaction(action, nightUtxos, nightVerifyingKey, signDustRegistration) {
50
+ const ttl = this.defaultTtl();
51
+ const transaction = await this.dust.createDustGenerationTransaction(undefined, ttl, nightUtxos.map(({ utxo, meta }) => ({ ...utxo, ctime: meta.ctime })), nightVerifyingKey, action.type === 'registration' ? action.dustReceiverAddress : undefined);
52
+ const intent = transaction.intents?.get(1);
53
+ if (!intent) {
54
+ throw Error('Dust generation transaction is missing intent segment 1.');
55
+ }
56
+ const signatureData = intent.signatureData(1);
57
+ const signature = await Promise.resolve(signDustRegistration(signatureData));
58
+ return await this.dust.addDustGenerationSignature(transaction, signature);
59
+ }
39
60
  state() {
40
61
  return combineLatest([this.shielded.state, this.unshielded.state, this.dust.state]).pipe(map(([shieldedState, unshieldedState, dustState]) => new FacadeState(shieldedState, unshieldedState, dustState)));
41
62
  }
63
+ async waitForSyncedState() {
64
+ const [shieldedState, unshieldedState, dustState] = await Promise.all([
65
+ this.shielded.waitForSyncedState(),
66
+ this.unshielded.waitForSyncedState(),
67
+ this.dust.waitForSyncedState(),
68
+ ]);
69
+ return new FacadeState(shieldedState, unshieldedState, dustState);
70
+ }
42
71
  async submitTransaction(tx) {
43
72
  await this.shielded.submitTransaction(tx, 'Finalized');
44
73
  return tx.identifiers().at(-1);
45
74
  }
46
- async balanceTransaction(zswapSecretKeys, dustSecretKeys, tx, ttl) {
47
- const unshieldedBalancedTx = await this.unshielded.balanceTransaction(tx);
48
- const recipe = await this.shielded.balanceTransaction(zswapSecretKeys, unshieldedBalancedTx, []);
75
+ async balanceFinalizedTransaction(zswapSecretKeys, dustSecretKeys, tx, ttl) {
76
+ const unshieldedBalancing = await this.unshielded.balanceFinalizedTransaction(tx);
77
+ const shieldedBalancing = await this.shielded.balanceTransaction(zswapSecretKeys, tx);
78
+ const mergedBalancing = this.mergeUnprovenTransactions(shieldedBalancing, unshieldedBalancing);
79
+ const feeBalancingTransaction = await this.dust.balanceTransactions(dustSecretKeys, mergedBalancing ? [tx, mergedBalancing] : [tx], ttl);
80
+ const balancingTransaction = mergedBalancing
81
+ ? mergedBalancing.merge(feeBalancingTransaction)
82
+ : feeBalancingTransaction;
83
+ return {
84
+ type: 'FINALIZED_TRANSACTION',
85
+ originalTransaction: tx,
86
+ balancingTransaction,
87
+ };
88
+ }
89
+ async balanceUnboundTransaction(zswapSecretKeys, dustSecretKeys, tx, ttl) {
90
+ // For unbound transactions, unshielded balancing happens in place not with a balancing transaction
91
+ const balancedUnshieldedTx = await this.unshielded.balanceUnboundTransaction(tx);
92
+ const shieldedBalancingTx = await this.shielded.balanceTransaction(zswapSecretKeys, tx);
93
+ // unbound unshielded tx are balanced in place, check if balancedUnshieldedTx is present and use it as base tx
94
+ const baseTx = balancedUnshieldedTx ?? tx;
95
+ // Add fee payment - pass shielded balancing if present, otherwise just calculate fee for base tx
96
+ const transactionsToPayFeesFor = shieldedBalancingTx ? [baseTx, shieldedBalancingTx] : [baseTx];
97
+ const feeBalancingTransaction = await this.dust.balanceTransactions(dustSecretKeys, transactionsToPayFeesFor, ttl);
98
+ // Create the final balancing transaction
99
+ const balancingTransaction = shieldedBalancingTx
100
+ ? shieldedBalancingTx.merge(feeBalancingTransaction)
101
+ : feeBalancingTransaction;
102
+ return {
103
+ type: 'UNBOUND_TRANSACTION',
104
+ baseTransaction: baseTx,
105
+ balancingTransaction,
106
+ };
107
+ }
108
+ async balanceUnprovenTransaction(zswapSecretKeys, dustSecretKeys, tx, ttl) {
109
+ // For unproven transactions, unshielded balancing happens in place
110
+ const balancedUnshieldedTx = await this.unshielded.balanceUnprovenTransaction(tx);
111
+ const shieldedBalancingTx = await this.shielded.balanceTransaction(zswapSecretKeys, tx);
112
+ // Use the balanced unshielded tx if present, otherwise use the original tx
113
+ const baseTx = balancedUnshieldedTx ?? tx;
114
+ // Merge shielded balancing into base tx if present
115
+ const mergedTx = shieldedBalancingTx ? baseTx.merge(shieldedBalancingTx) : baseTx;
116
+ // Add fee payment
117
+ const feeBalancingTransaction = await this.dust.balanceTransactions(dustSecretKeys, [mergedTx], ttl);
118
+ const balancedTransaction = mergedTx.merge(feeBalancingTransaction);
119
+ return {
120
+ type: 'UNPROVEN_TRANSACTION',
121
+ transaction: balancedTransaction,
122
+ };
123
+ }
124
+ async finalizeRecipe(recipe) {
49
125
  switch (recipe.type) {
50
- case ProvingRecipe.TRANSACTION_TO_PROVE:
51
- return await this.dust.addFeePayment(dustSecretKeys, recipe.transaction, ttl);
52
- case ProvingRecipe.BALANCE_TRANSACTION_TO_PROVE: {
53
- // if the shielded wallet returned a proven transaction, we need to pay fees with the dust wallet
54
- const balancedTx = await this.dust.addFeePayment(dustSecretKeys, recipe.transactionToProve, ttl);
55
- if (balancedTx.type !== ProvingRecipe.TRANSACTION_TO_PROVE) {
56
- throw Error('Unexpected transaction type after adding fee payment.');
57
- }
126
+ case 'FINALIZED_TRANSACTION': {
127
+ const finalizedBalancing = await this.finalizeTransaction(recipe.balancingTransaction);
128
+ return recipe.originalTransaction.merge(finalizedBalancing);
129
+ }
130
+ case 'UNBOUND_TRANSACTION': {
131
+ const finalizedBalancingTx = await this.finalizeTransaction(recipe.balancingTransaction);
132
+ const finalizedTransaction = recipe.baseTransaction.bind();
133
+ return finalizedTransaction.merge(finalizedBalancingTx);
134
+ }
135
+ case 'UNPROVEN_TRANSACTION': {
136
+ return await this.finalizeTransaction(recipe.transaction);
137
+ }
138
+ }
139
+ }
140
+ async signRecipe(recipe, signSegment) {
141
+ switch (recipe.type) {
142
+ case 'FINALIZED_TRANSACTION': {
143
+ const signedBalancing = await this.signTransaction(recipe.balancingTransaction, signSegment);
144
+ return {
145
+ type: 'FINALIZED_TRANSACTION',
146
+ originalTransaction: recipe.originalTransaction,
147
+ balancingTransaction: signedBalancing,
148
+ };
149
+ }
150
+ case 'UNBOUND_TRANSACTION': {
151
+ const signedBalancing = await this.signTransaction(recipe.balancingTransaction, signSegment);
58
152
  return {
59
- ...recipe,
60
- transactionToProve: balancedTx.transaction,
153
+ type: 'UNBOUND_TRANSACTION',
154
+ baseTransaction: recipe.baseTransaction,
155
+ balancingTransaction: signedBalancing,
61
156
  };
62
157
  }
63
- case ProvingRecipe.NOTHING_TO_PROVE: {
64
- // @TODO fix casting
65
- const txToBalance = recipe.transaction;
66
- return await this.dust.addFeePayment(dustSecretKeys, txToBalance, ttl);
158
+ case 'UNPROVEN_TRANSACTION': {
159
+ const signedTransaction = await this.signTransaction(recipe.transaction, signSegment);
160
+ return {
161
+ type: 'UNPROVEN_TRANSACTION',
162
+ transaction: signedTransaction,
163
+ };
67
164
  }
68
165
  }
69
166
  }
70
- async finalizeTransaction(recipe) {
71
- return await this.shielded.finalizeTransaction(recipe);
72
- }
73
167
  async signTransaction(tx, signSegment) {
74
168
  return await this.unshielded.signTransaction(tx, signSegment);
75
169
  }
170
+ async finalizeTransaction(tx) {
171
+ return await this.shielded.finalizeTransaction(tx);
172
+ }
76
173
  async calculateTransactionFee(tx) {
77
- return await this.dust.calculateFee(tx);
174
+ return await this.dust.calculateFee([tx]);
78
175
  }
79
176
  async transferTransaction(zswapSecretKeys, dustSecretKey, outputs, ttl) {
80
177
  const unshieldedOutputs = outputs
@@ -84,66 +181,35 @@ export class WalletFacade {
84
181
  if (unshieldedOutputs.length === 0 && shieldedOutputs.length === 0) {
85
182
  throw Error('At least one shielded or unshielded output is required.');
86
183
  }
87
- let shieldedTxRecipe = undefined;
88
- let unshieldedTx = undefined;
184
+ let shieldedTx;
185
+ let unshieldedTx;
89
186
  if (unshieldedOutputs.length > 0) {
90
187
  unshieldedTx = await this.unshielded.transferTransaction(unshieldedOutputs, ttl);
91
188
  }
92
189
  if (shieldedOutputs.length > 0) {
93
- shieldedTxRecipe = await this.shielded.transferTransaction(zswapSecretKeys, shieldedOutputs);
94
- }
95
- // if there's a shielded tx only, return it as it's already balanced
96
- if (shieldedTxRecipe !== undefined && unshieldedTx === undefined) {
97
- if (shieldedTxRecipe.type !== 'TransactionToProve') {
98
- throw Error('Unexpected transaction type.');
99
- }
100
- const recipe = await this.dust.addFeePayment(dustSecretKey, shieldedTxRecipe.transaction, ttl);
101
- if (recipe.type !== 'TransactionToProve') {
102
- throw Error('Unexpected transaction type after adding fee payment.');
103
- }
104
- return recipe;
105
- }
106
- // if there's an unshielded tx only, pay fees (balance) with shielded wallet
107
- if (shieldedTxRecipe === undefined && unshieldedTx !== undefined) {
108
- const recipe = await this.dust.addFeePayment(dustSecretKey, unshieldedTx, ttl);
109
- if (recipe.type !== 'TransactionToProve') {
110
- throw Error('Unexpected transaction type after adding fee payment.');
111
- }
112
- return recipe;
190
+ shieldedTx = await this.shielded.transferTransaction(zswapSecretKeys, shieldedOutputs);
113
191
  }
114
- // if there's a shielded and unshielded tx, pay fees for unshielded and merge them
115
- if (shieldedTxRecipe !== undefined && unshieldedTx !== undefined) {
116
- if (shieldedTxRecipe.type !== 'TransactionToProve') {
117
- throw Error('Unexpected transaction type.');
118
- }
119
- const txToBalance = shieldedTxRecipe.transaction.merge(unshieldedTx);
120
- const recipe = await this.dust.addFeePayment(dustSecretKey, txToBalance, ttl);
121
- if (recipe.type !== 'TransactionToProve') {
122
- throw Error('Unexpected transaction type after adding fee payment.');
123
- }
124
- return recipe;
125
- }
126
- throw Error('Unexpected transaction state.');
192
+ const mergedTxs = this.mergeUnprovenTransactions(shieldedTx, unshieldedTx);
193
+ // Add fee payment
194
+ const feeBalancingTransaction = await this.dust.balanceTransactions(dustSecretKey, [mergedTxs], ttl);
195
+ return {
196
+ type: 'UNPROVEN_TRANSACTION',
197
+ transaction: mergedTxs.merge(feeBalancingTransaction),
198
+ };
127
199
  }
128
- async registerNightUtxosForDustGeneration(nightUtxos, nightVerifyingKey, signDustRegistration, dustReceiverAddress) {
129
- if (nightUtxos.length === 0) {
130
- throw Error('At least one Night UTXO is required.');
131
- }
200
+ async estimateRegistration(nightUtxos) {
201
+ const now = new Date();
132
202
  const dustState = await this.dust.waitForSyncedState();
133
- const receiverAddress = dustReceiverAddress ?? dustState.dustAddress;
134
- const ttl = new Date(Date.now() + 60 * 60 * 1000);
135
- const transaction = await this.dust.createDustGenerationTransaction(undefined, ttl, nightUtxos.map(({ utxo, meta }) => ({ ...utxo, ctime: meta.ctime })), nightVerifyingKey, receiverAddress);
136
- const intent = transaction.intents?.get(1);
137
- if (!intent) {
138
- throw Error('Dust generation transaction is missing intent segment 1.');
139
- }
140
- const signatureData = intent.signatureData(1);
141
- const signature = await Promise.resolve(signDustRegistration(signatureData));
142
- const recipe = await this.dust.addDustGenerationSignature(transaction, signature);
143
- if (recipe.type !== ProvingRecipe.TRANSACTION_TO_PROVE) {
144
- throw Error('Unexpected recipe type returned when registering Night UTXOs.');
145
- }
146
- return recipe;
203
+ const dustGenerationEstimations = pipe(nightUtxos, Arr.map(({ utxo, meta }) => ({ ...utxo, ctime: meta.ctime })), (utxosWithMeta) => dustState.estimateDustGeneration(utxosWithMeta, now), (estimatedUtxos) => dustState.capabilities.coinsAndBalances.splitNightUtxos(estimatedUtxos), (split) => split.guaranteed);
204
+ const fakeSigningKey = ledger.sampleSigningKey();
205
+ const fakeVerifyingKey = ledger.signatureVerifyingKey(fakeSigningKey);
206
+ const fakeRegistrationRecipe = await this.registerNightUtxosForDustGeneration(nightUtxos, fakeVerifyingKey, (payload) => ledger.signData(fakeSigningKey, payload), dustState.dustAddress);
207
+ const finalizedFakeTx = fakeRegistrationRecipe.transaction.mockProve().bind();
208
+ const fee = await this.calculateTransactionFee(finalizedFakeTx);
209
+ return {
210
+ fee,
211
+ dustGenerationEstimations,
212
+ };
147
213
  }
148
214
  async initSwap(zswapSecretKeys, desiredInputs, desiredOutputs, ttl) {
149
215
  const { shielded: shieldedInputs, unshielded: unshieldedInputs } = desiredInputs;
@@ -158,40 +224,39 @@ export class WalletFacade {
158
224
  if (!hasShieldedPart && !hasUnshieldedPart) {
159
225
  throw Error('At least one shielded or unshielded swap is required.');
160
226
  }
161
- const shieldedTxRecipe = hasShieldedPart && shieldedInputs !== undefined
227
+ const shieldedTx = hasShieldedPart && shieldedInputs !== undefined
162
228
  ? await this.shielded.initSwap(zswapSecretKeys, shieldedInputs, shieldedOutputs)
163
229
  : undefined;
164
230
  const unshieldedTx = hasUnshieldedPart && unshieldedInputs !== undefined
165
231
  ? await this.unshielded.initSwap(unshieldedInputs, unshieldedOutputs, ttl)
166
232
  : undefined;
167
- if (shieldedTxRecipe !== undefined && shieldedTxRecipe.type !== ProvingRecipe.TRANSACTION_TO_PROVE) {
168
- throw Error('Unexpected transaction type.');
233
+ const combinedTx = this.mergeUnprovenTransactions(shieldedTx, unshieldedTx);
234
+ if (!combinedTx) {
235
+ throw Error('Unexpected transaction state.');
169
236
  }
170
- if (shieldedTxRecipe && unshieldedTx) {
171
- return shieldedTxRecipe.transaction.merge(unshieldedTx);
172
- }
173
- if (shieldedTxRecipe) {
174
- return shieldedTxRecipe.transaction;
175
- }
176
- if (unshieldedTx) {
177
- return unshieldedTx;
237
+ return {
238
+ type: 'UNPROVEN_TRANSACTION',
239
+ transaction: combinedTx,
240
+ };
241
+ }
242
+ async registerNightUtxosForDustGeneration(nightUtxos, nightVerifyingKey, signDustRegistration, dustReceiverAddress) {
243
+ if (nightUtxos.length === 0) {
244
+ throw Error('At least one Night UTXO is required.');
178
245
  }
179
- throw Error('Unexpected transaction state.');
246
+ const dustState = await this.dust.waitForSyncedState();
247
+ const receiverAddress = dustReceiverAddress ?? dustState.dustAddress;
248
+ const dustRegistrationTx = await this.createDustActionTransaction({ type: 'registration', dustReceiverAddress: receiverAddress }, nightUtxos, nightVerifyingKey, signDustRegistration);
249
+ return {
250
+ type: 'UNPROVEN_TRANSACTION',
251
+ transaction: dustRegistrationTx,
252
+ };
180
253
  }
181
254
  async deregisterFromDustGeneration(nightUtxos, nightVerifyingKey, signDustRegistration) {
182
- const ttl = new Date(Date.now() + 60 * 60 * 1000);
183
- const transaction = await this.dust.createDustGenerationTransaction(undefined, ttl, nightUtxos.map(({ utxo, meta }) => ({ ...utxo, ctime: meta.ctime })), nightVerifyingKey, undefined);
184
- const intent = transaction.intents?.get(1);
185
- if (!intent) {
186
- throw Error('Dust generation transaction is missing intent segment 1.');
187
- }
188
- const signatureData = intent.signatureData(1);
189
- const signature = await Promise.resolve(signDustRegistration(signatureData));
190
- const recipe = await this.dust.addDustGenerationSignature(transaction, signature);
191
- if (recipe.type !== ProvingRecipe.TRANSACTION_TO_PROVE) {
192
- throw Error('Unexpected recipe type returned when registering Night UTXOs.');
193
- }
194
- return recipe;
255
+ const dustDeregistrationTx = await this.createDustActionTransaction({ type: 'deregistration' }, nightUtxos, nightVerifyingKey, signDustRegistration);
256
+ return {
257
+ type: 'UNPROVEN_TRANSACTION',
258
+ transaction: dustDeregistrationTx,
259
+ };
195
260
  }
196
261
  async start(zswapSecretKeys, dustSecretKey) {
197
262
  await Promise.all([this.shielded.start(zswapSecretKeys), this.unshielded.start(), this.dust.start(dustSecretKey)]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midnight-ntwrk/wallet-sdk-facade",
3
- "version": "1.0.0-beta.14",
3
+ "version": "1.0.0-beta.16",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -24,16 +24,17 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "@midnight-ntwrk/ledger-v7": "7.0.0-alpha.1",
27
+ "@midnight-ntwrk/ledger-v7": "7.0.0-rc.1",
28
28
  "@midnight-ntwrk/wallet-sdk-abstractions": "1.0.0-beta.10",
29
- "@midnight-ntwrk/wallet-sdk-address-format": "3.0.0-beta.10",
30
- "@midnight-ntwrk/wallet-sdk-dust-wallet": "1.0.0-beta.13",
29
+ "@midnight-ntwrk/wallet-sdk-address-format": "3.0.0-beta.11",
30
+ "@midnight-ntwrk/wallet-sdk-dust-wallet": "1.0.0-beta.15",
31
31
  "@midnight-ntwrk/wallet-sdk-hd": "3.0.0-beta.8",
32
- "@midnight-ntwrk/wallet-sdk-shielded": "1.0.0-beta.14",
33
- "@midnight-ntwrk/wallet-sdk-unshielded-wallet": "1.0.0-beta.16",
32
+ "@midnight-ntwrk/wallet-sdk-shielded": "1.0.0-beta.16",
33
+ "@midnight-ntwrk/wallet-sdk-unshielded-wallet": "1.0.0-beta.18",
34
34
  "rxjs": "^7.5"
35
35
  },
36
36
  "devDependencies": {
37
+ "@midnight-ntwrk/wallet-sdk-prover-client": "1.0.0-beta.13",
37
38
  "eslint": "^9.37.0",
38
39
  "prettier": "^3.7.0",
39
40
  "publint": "~0.3.14",