create-mn-app 0.3.26 → 0.3.28

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-mn-app",
3
- "version": "0.3.26",
3
+ "version": "0.3.28",
4
4
  "description": "Create Midnight Network applications with zero configuration",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -18,24 +18,24 @@
18
18
  "test": "echo \"Error: no test specified\" && exit 1"
19
19
  },
20
20
  "dependencies": {
21
- "@midnight-ntwrk/compact-runtime": "0.14.0",
22
- "@midnight-ntwrk/compact-js": "2.4.0",
23
- "@midnight-ntwrk/ledger-v7": "7.0.0",
24
- "@midnight-ntwrk/midnight-js-contracts": "3.0.0",
25
- "@midnight-ntwrk/midnight-js-http-client-proof-provider": "3.0.0",
26
- "@midnight-ntwrk/midnight-js-indexer-public-data-provider": "3.0.0",
27
- "@midnight-ntwrk/midnight-js-level-private-state-provider": "3.0.0",
28
- "@midnight-ntwrk/midnight-js-node-zk-config-provider": "3.0.0",
29
- "@midnight-ntwrk/midnight-js-network-id": "3.0.0",
30
- "@midnight-ntwrk/midnight-js-types": "3.0.0",
31
- "@midnight-ntwrk/midnight-js-utils": "3.0.0",
32
- "@midnight-ntwrk/wallet-sdk-facade": "1.0.0",
33
- "@midnight-ntwrk/wallet-sdk-hd": "3.0.0",
34
- "@midnight-ntwrk/wallet-sdk-shielded": "1.0.0",
35
- "@midnight-ntwrk/wallet-sdk-unshielded-wallet": "1.0.0",
36
- "@midnight-ntwrk/wallet-sdk-dust-wallet": "1.0.0",
37
- "ws": "^8.19.0",
38
- "rxjs": "^7.8.0"
21
+ "@midnight-ntwrk/compact-js": "2.5.0",
22
+ "rxjs": "^7.8.1",
23
+ "@midnight-ntwrk/compact-runtime": "0.15.0",
24
+ "@midnight-ntwrk/ledger-v8": "8.0.3",
25
+ "@midnight-ntwrk/midnight-js-contracts": "4.0.2",
26
+ "@midnight-ntwrk/midnight-js-http-client-proof-provider": "4.0.2",
27
+ "@midnight-ntwrk/midnight-js-indexer-public-data-provider": "4.0.2",
28
+ "@midnight-ntwrk/midnight-js-level-private-state-provider": "4.0.2",
29
+ "@midnight-ntwrk/midnight-js-network-id": "4.0.2",
30
+ "@midnight-ntwrk/midnight-js-node-zk-config-provider": "4.0.2",
31
+ "@midnight-ntwrk/midnight-js-types": "4.0.2",
32
+ "@midnight-ntwrk/midnight-js-utils": "4.0.2",
33
+ "@midnight-ntwrk/wallet-sdk-dust-wallet": "3.0.0",
34
+ "@midnight-ntwrk/wallet-sdk-facade": "3.0.0",
35
+ "@midnight-ntwrk/wallet-sdk-hd": "3.0.1",
36
+ "@midnight-ntwrk/wallet-sdk-shielded": "2.1.0",
37
+ "@midnight-ntwrk/wallet-sdk-unshielded-wallet": "2.1.0",
38
+ "ws": "^8.19.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/node": "^22.0.0",
@@ -8,8 +8,8 @@ import { Buffer } from 'buffer';
8
8
 
9
9
  // Midnight SDK imports
10
10
  import { setNetworkId, getNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
11
- import * as ledger from '@midnight-ntwrk/ledger-v7';
12
- import { unshieldedToken } from '@midnight-ntwrk/ledger-v7';
11
+ import * as ledger from '@midnight-ntwrk/ledger-v8';
12
+ import { unshieldedToken } from '@midnight-ntwrk/ledger-v8';
13
13
  import { WalletFacade } from '@midnight-ntwrk/wallet-sdk-facade';
14
14
  import { DustWallet } from '@midnight-ntwrk/wallet-sdk-dust-wallet';
15
15
  import { HDWallet, Roles } from '@midnight-ntwrk/wallet-sdk-hd';
@@ -55,20 +55,17 @@ async function createWallet(seed: string) {
55
55
  indexerClientConnection: { indexerHttpUrl: CONFIG.indexer, indexerWsUrl: CONFIG.indexerWS },
56
56
  provingServerUrl: new URL(CONFIG.proofServer),
57
57
  relayURL: new URL(CONFIG.node.replace(/^http/, 'ws')),
58
- };
59
-
60
- const shieldedWallet = ShieldedWallet(walletConfig).startWithSecretKeys(shieldedSecretKeys);
61
- const unshieldedWallet = UnshieldedWallet({
62
- networkId,
63
- indexerClientConnection: walletConfig.indexerClientConnection,
64
58
  txHistoryStorage: new InMemoryTransactionHistoryStorage(),
65
- }).startWithPublicKey(PublicKey.fromKeyStore(unshieldedKeystore));
66
- const dustWallet = DustWallet({
67
- ...walletConfig,
68
59
  costParameters: { additionalFeeOverhead: 300_000_000_000_000n, feeBlocksMargin: 5 },
69
- }).startWithSecretKey(dustSecretKey, ledger.LedgerParameters.initialParameters().dust);
60
+ };
61
+
62
+ const wallet = await WalletFacade.init({
63
+ configuration: walletConfig,
64
+ shielded: async (config) => ShieldedWallet(config).startWithSecretKeys(shieldedSecretKeys),
65
+ unshielded: async (config) => UnshieldedWallet(config).startWithPublicKey(PublicKey.fromKeyStore(unshieldedKeystore)),
66
+ dust: async (config) => DustWallet(config).startWithSecretKey(dustSecretKey, ledger.LedgerParameters.initialParameters().dust),
67
+ });
70
68
 
71
- const wallet = new WalletFacade(shieldedWallet, unshieldedWallet, dustWallet);
72
69
  await wallet.start(shieldedSecretKeys, dustSecretKey);
73
70
 
74
71
  return { wallet, unshieldedKeystore };
@@ -100,13 +97,20 @@ async function main() {
100
97
  const { wallet, unshieldedKeystore } = await createWallet(seed);
101
98
 
102
99
  console.log(' Syncing with network...');
103
- const state = await Rx.firstValueFrom(
104
- wallet.state().pipe(Rx.throttleTime(5000), Rx.filter((s) => s.isSynced)),
105
- );
100
+ console.log(' ℹ This may take several minutes depending on network size.');
101
+ console.log(' RPC disconnection messages during sync are normal and can be safely ignored.\n');
102
+ const syncStart = Date.now();
103
+ const syncInterval = setInterval(() => {
104
+ const elapsed = Math.round((Date.now() - syncStart) / 1000);
105
+ process.stdout.write(`\r ⏳ Still syncing... (${elapsed}s elapsed) `);
106
+ }, 5000);
107
+ const state = await wallet.waitForSyncedState();
108
+ clearInterval(syncInterval);
109
+ process.stdout.write('\r ✓ Synced with network. \n');
106
110
 
107
111
  const address = unshieldedKeystore.getBech32Address();
108
112
  const tNightBalance = state.unshielded.balances[unshieldedToken().raw] ?? 0n;
109
- const dustBalance = state.dust.walletBalance(new Date());
113
+ const dustBalance = state.dust.balance(new Date());
110
114
 
111
115
  console.log('\n─── Wallet Details ─────────────────────────────────────────────\n');
112
116
  console.log(` Address: ${address}`);
@@ -17,8 +17,8 @@ import { indexerPublicDataProvider } from '@midnight-ntwrk/midnight-js-indexer-p
17
17
  import { levelPrivateStateProvider } from '@midnight-ntwrk/midnight-js-level-private-state-provider';
18
18
  import { NodeZkConfigProvider } from '@midnight-ntwrk/midnight-js-node-zk-config-provider';
19
19
  import { setNetworkId, getNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
20
- import * as ledger from '@midnight-ntwrk/ledger-v7';
21
- import { unshieldedToken } from '@midnight-ntwrk/ledger-v7';
20
+ import * as ledger from '@midnight-ntwrk/ledger-v8';
21
+ import { unshieldedToken } from '@midnight-ntwrk/ledger-v8';
22
22
  import { WalletFacade } from '@midnight-ntwrk/wallet-sdk-facade';
23
23
  import { DustWallet } from '@midnight-ntwrk/wallet-sdk-dust-wallet';
24
24
  import { HDWallet, Roles } from '@midnight-ntwrk/wallet-sdk-hd';
@@ -83,48 +83,26 @@ async function createWallet(seed: string) {
83
83
  indexerClientConnection: { indexerHttpUrl: CONFIG.indexer, indexerWsUrl: CONFIG.indexerWS },
84
84
  provingServerUrl: new URL(CONFIG.proofServer),
85
85
  relayURL: new URL(CONFIG.node.replace(/^http/, 'ws')),
86
- };
87
-
88
- const shieldedWallet = ShieldedWallet(walletConfig).startWithSecretKeys(shieldedSecretKeys);
89
- const unshieldedWallet = UnshieldedWallet({
90
- networkId,
91
- indexerClientConnection: walletConfig.indexerClientConnection,
92
86
  txHistoryStorage: new InMemoryTransactionHistoryStorage(),
93
- }).startWithPublicKey(PublicKey.fromKeyStore(unshieldedKeystore));
94
- const dustWallet = DustWallet({
95
- ...walletConfig,
96
87
  costParameters: { additionalFeeOverhead: 300_000_000_000_000n, feeBlocksMargin: 5 },
97
- }).startWithSecretKey(dustSecretKey, ledger.LedgerParameters.initialParameters().dust);
88
+ };
89
+
90
+ const wallet = await WalletFacade.init({
91
+ configuration: walletConfig,
92
+ shielded: async (config) => ShieldedWallet(config).startWithSecretKeys(shieldedSecretKeys),
93
+ unshielded: async (config) => UnshieldedWallet(config).startWithPublicKey(PublicKey.fromKeyStore(unshieldedKeystore)),
94
+ dust: async (config) => DustWallet(config).startWithSecretKey(dustSecretKey, ledger.LedgerParameters.initialParameters().dust),
95
+ });
98
96
 
99
- const wallet = new WalletFacade(shieldedWallet, unshieldedWallet, dustWallet);
100
97
  await wallet.start(shieldedSecretKeys, dustSecretKey);
101
98
 
102
99
  return { wallet, shieldedSecretKeys, dustSecretKey, unshieldedKeystore };
103
100
  }
104
101
 
105
- // Workaround for wallet SDK signRecipe bug
106
- function signTransactionIntents(tx: { intents?: Map<number, any> }, signFn: (payload: Uint8Array) => ledger.Signature, proofMarker: 'proof' | 'pre-proof'): void {
107
- if (!tx.intents || tx.intents.size === 0) return;
108
- for (const segment of tx.intents.keys()) {
109
- const intent = tx.intents.get(segment);
110
- if (!intent) continue;
111
- const cloned = ledger.Intent.deserialize<ledger.SignatureEnabled, ledger.Proofish, ledger.PreBinding>('signature', proofMarker, 'pre-binding', intent.serialize());
112
- const sigData = cloned.signatureData(segment);
113
- const signature = signFn(sigData);
114
- if (cloned.fallibleUnshieldedOffer) {
115
- const sigs = cloned.fallibleUnshieldedOffer.inputs.map((_: any, i: number) => cloned.fallibleUnshieldedOffer!.signatures.at(i) ?? signature);
116
- cloned.fallibleUnshieldedOffer = cloned.fallibleUnshieldedOffer.addSignatures(sigs);
117
- }
118
- if (cloned.guaranteedUnshieldedOffer) {
119
- const sigs = cloned.guaranteedUnshieldedOffer.inputs.map((_: any, i: number) => cloned.guaranteedUnshieldedOffer!.signatures.at(i) ?? signature);
120
- cloned.guaranteedUnshieldedOffer = cloned.guaranteedUnshieldedOffer.addSignatures(sigs);
121
- }
122
- tx.intents.set(segment, cloned);
123
- }
124
- }
125
-
126
102
  async function createProviders(walletCtx: ReturnType<typeof createWallet> extends Promise<infer T> ? T : never) {
127
- const state = await Rx.firstValueFrom(walletCtx.wallet.state().pipe(Rx.filter((s) => s.isSynced)));
103
+ const privateStatePassword = process.env.PRIVATE_STATE_PASSWORD?.trim() || 'development';
104
+
105
+ const state = await walletCtx.wallet.waitForSyncedState();
128
106
 
129
107
  const walletProvider = {
130
108
  getCoinPublicKey: () => state.shielded.coinPublicKey.toHexString(),
@@ -135,18 +113,23 @@ async function createProviders(walletCtx: ReturnType<typeof createWallet> extend
135
113
  { shieldedSecretKeys: walletCtx.shieldedSecretKeys, dustSecretKey: walletCtx.dustSecretKey },
136
114
  { ttl: ttl ?? new Date(Date.now() + 30 * 60 * 1000) },
137
115
  );
138
- const signFn = (payload: Uint8Array) => walletCtx.unshieldedKeystore.signData(payload);
139
- signTransactionIntents(recipe.baseTransaction, signFn, 'proof');
140
- if (recipe.balancingTransaction) signTransactionIntents(recipe.balancingTransaction, signFn, 'pre-proof');
141
- return walletCtx.wallet.finalizeRecipe(recipe);
116
+ const signedRecipe = await walletCtx.wallet.signRecipe(recipe, (payload) =>
117
+ walletCtx.unshieldedKeystore.signData(payload),
118
+ );
119
+ return walletCtx.wallet.finalizeRecipe(signedRecipe);
142
120
  },
143
121
  submitTx: (tx: any) => walletCtx.wallet.submitTransaction(tx) as any,
144
122
  };
145
123
 
146
124
  const zkConfigProvider = new NodeZkConfigProvider(zkConfigPath);
125
+ const accountId = walletCtx.unshieldedKeystore.getBech32Address().toString();
147
126
 
148
127
  return {
149
- privateStateProvider: levelPrivateStateProvider({ privateStateStoreName: 'hello-world-state', walletProvider }),
128
+ privateStateProvider: levelPrivateStateProvider({
129
+ privateStateStoreName: 'hello-world-state',
130
+ accountId,
131
+ privateStoragePasswordProvider: () => privateStatePassword,
132
+ }),
150
133
  publicDataProvider: indexerPublicDataProvider(CONFIG.indexer, CONFIG.indexerWS),
151
134
  zkConfigProvider,
152
135
  proofProvider: httpClientProofProvider(CONFIG.proofServer, zkConfigProvider),
@@ -186,7 +169,16 @@ async function main() {
186
169
  const walletCtx = await createWallet(seed);
187
170
 
188
171
  console.log(' Syncing with network...');
189
- const state = await Rx.firstValueFrom(walletCtx.wallet.state().pipe(Rx.throttleTime(5000), Rx.filter((s) => s.isSynced)));
172
+ console.log(' ℹ This may take several minutes depending on network size.');
173
+ console.log(' RPC disconnection messages during sync are normal and can be safely ignored.\n');
174
+ const syncStart = Date.now();
175
+ const syncInterval = setInterval(() => {
176
+ const elapsed = Math.round((Date.now() - syncStart) / 1000);
177
+ process.stdout.write(`\r ⏳ Still syncing... (${elapsed}s elapsed) `);
178
+ }, 5000);
179
+ const state = await walletCtx.wallet.waitForSyncedState();
180
+ clearInterval(syncInterval);
181
+ process.stdout.write('\r ✓ Synced with network. \n');
190
182
  const balance = state.unshielded.balances[unshieldedToken().raw] ?? 0n;
191
183
  console.log(` Balance: ${balance.toLocaleString()} tNight\n`);
192
184
 
@@ -195,10 +187,8 @@ async function main() {
195
187
  const providers = await createProviders(walletCtx);
196
188
 
197
189
  const deployed: any = await findDeployedContract(providers, {
198
- compiledContract,
190
+ compiledContract: compiledContract as any,
199
191
  contractAddress: deployment.contractAddress,
200
- privateStateId: 'helloWorldState',
201
- initialPrivateState: {},
202
192
  });
203
193
 
204
194
  console.log(' ✅ Connected!\n');
@@ -248,9 +238,9 @@ async function main() {
248
238
 
249
239
  case '3': {
250
240
  console.log('\n Checking balance...');
251
- const currentState = await Rx.firstValueFrom(walletCtx.wallet.state().pipe(Rx.filter((s) => s.isSynced)));
241
+ const currentState = await walletCtx.wallet.waitForSyncedState();
252
242
  const currentBalance = currentState.unshielded.balances[unshieldedToken().raw] ?? 0n;
253
- const dustBalance = currentState.dust.walletBalance(new Date());
243
+ const dustBalance = currentState.dust.balance(new Date());
254
244
  console.log(`\n tNight: ${currentBalance.toLocaleString()}`);
255
245
  console.log(` DUST: ${dustBalance.toLocaleString()}\n`);
256
246
  break;
@@ -18,8 +18,8 @@ import { levelPrivateStateProvider } from '@midnight-ntwrk/midnight-js-level-pri
18
18
  import { NodeZkConfigProvider } from '@midnight-ntwrk/midnight-js-node-zk-config-provider';
19
19
  import { setNetworkId, getNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
20
20
  import { toHex } from '@midnight-ntwrk/midnight-js-utils';
21
- import * as ledger from '@midnight-ntwrk/ledger-v7';
22
- import { unshieldedToken } from '@midnight-ntwrk/ledger-v7';
21
+ import * as ledger from '@midnight-ntwrk/ledger-v8';
22
+ import { unshieldedToken } from '@midnight-ntwrk/ledger-v8';
23
23
  import { WalletFacade } from '@midnight-ntwrk/wallet-sdk-facade';
24
24
  import { DustWallet } from '@midnight-ntwrk/wallet-sdk-dust-wallet';
25
25
  import { HDWallet, Roles, generateRandomSeed } from '@midnight-ntwrk/wallet-sdk-hd';
@@ -114,48 +114,26 @@ async function createWallet(seed: string) {
114
114
  indexerClientConnection: { indexerHttpUrl: CONFIG.indexer, indexerWsUrl: CONFIG.indexerWS },
115
115
  provingServerUrl: new URL(CONFIG.proofServer),
116
116
  relayURL: new URL(CONFIG.node.replace(/^http/, 'ws')),
117
- };
118
-
119
- const shieldedWallet = ShieldedWallet(walletConfig).startWithSecretKeys(shieldedSecretKeys);
120
- const unshieldedWallet = UnshieldedWallet({
121
- networkId,
122
- indexerClientConnection: walletConfig.indexerClientConnection,
123
117
  txHistoryStorage: new InMemoryTransactionHistoryStorage(),
124
- }).startWithPublicKey(PublicKey.fromKeyStore(unshieldedKeystore));
125
- const dustWallet = DustWallet({
126
- ...walletConfig,
127
118
  costParameters: { additionalFeeOverhead: 300_000_000_000_000n, feeBlocksMargin: 5 },
128
- }).startWithSecretKey(dustSecretKey, ledger.LedgerParameters.initialParameters().dust);
119
+ };
120
+
121
+ const wallet = await WalletFacade.init({
122
+ configuration: walletConfig,
123
+ shielded: async (config) => ShieldedWallet(config).startWithSecretKeys(shieldedSecretKeys),
124
+ unshielded: async (config) => UnshieldedWallet(config).startWithPublicKey(PublicKey.fromKeyStore(unshieldedKeystore)),
125
+ dust: async (config) => DustWallet(config).startWithSecretKey(dustSecretKey, ledger.LedgerParameters.initialParameters().dust),
126
+ });
129
127
 
130
- const wallet = new WalletFacade(shieldedWallet, unshieldedWallet, dustWallet);
131
128
  await wallet.start(shieldedSecretKeys, dustSecretKey);
132
129
 
133
130
  return { wallet, shieldedSecretKeys, dustSecretKey, unshieldedKeystore };
134
131
  }
135
132
 
136
- // Workaround for wallet SDK signRecipe bug
137
- function signTransactionIntents(tx: { intents?: Map<number, any> }, signFn: (payload: Uint8Array) => ledger.Signature, proofMarker: 'proof' | 'pre-proof'): void {
138
- if (!tx.intents || tx.intents.size === 0) return;
139
- for (const segment of tx.intents.keys()) {
140
- const intent = tx.intents.get(segment);
141
- if (!intent) continue;
142
- const cloned = ledger.Intent.deserialize<ledger.SignatureEnabled, ledger.Proofish, ledger.PreBinding>('signature', proofMarker, 'pre-binding', intent.serialize());
143
- const sigData = cloned.signatureData(segment);
144
- const signature = signFn(sigData);
145
- if (cloned.fallibleUnshieldedOffer) {
146
- const sigs = cloned.fallibleUnshieldedOffer.inputs.map((_: any, i: number) => cloned.fallibleUnshieldedOffer!.signatures.at(i) ?? signature);
147
- cloned.fallibleUnshieldedOffer = cloned.fallibleUnshieldedOffer.addSignatures(sigs);
148
- }
149
- if (cloned.guaranteedUnshieldedOffer) {
150
- const sigs = cloned.guaranteedUnshieldedOffer.inputs.map((_: any, i: number) => cloned.guaranteedUnshieldedOffer!.signatures.at(i) ?? signature);
151
- cloned.guaranteedUnshieldedOffer = cloned.guaranteedUnshieldedOffer.addSignatures(sigs);
152
- }
153
- tx.intents.set(segment, cloned);
154
- }
155
- }
156
-
157
133
  async function createProviders(walletCtx: ReturnType<typeof createWallet> extends Promise<infer T> ? T : never) {
158
- const state = await Rx.firstValueFrom(walletCtx.wallet.state().pipe(Rx.filter((s) => s.isSynced)));
134
+ const privateStatePassword = process.env.PRIVATE_STATE_PASSWORD?.trim() || 'development';
135
+
136
+ const state = await walletCtx.wallet.waitForSyncedState();
159
137
 
160
138
  const walletProvider = {
161
139
  getCoinPublicKey: () => state.shielded.coinPublicKey.toHexString(),
@@ -166,18 +144,23 @@ async function createProviders(walletCtx: ReturnType<typeof createWallet> extend
166
144
  { shieldedSecretKeys: walletCtx.shieldedSecretKeys, dustSecretKey: walletCtx.dustSecretKey },
167
145
  { ttl: ttl ?? new Date(Date.now() + 30 * 60 * 1000) },
168
146
  );
169
- const signFn = (payload: Uint8Array) => walletCtx.unshieldedKeystore.signData(payload);
170
- signTransactionIntents(recipe.baseTransaction, signFn, 'proof');
171
- if (recipe.balancingTransaction) signTransactionIntents(recipe.balancingTransaction, signFn, 'pre-proof');
172
- return walletCtx.wallet.finalizeRecipe(recipe);
147
+ const signedRecipe = await walletCtx.wallet.signRecipe(recipe, (payload) =>
148
+ walletCtx.unshieldedKeystore.signData(payload),
149
+ );
150
+ return walletCtx.wallet.finalizeRecipe(signedRecipe);
173
151
  },
174
152
  submitTx: (tx: any) => walletCtx.wallet.submitTransaction(tx) as any,
175
153
  };
176
154
 
177
155
  const zkConfigProvider = new NodeZkConfigProvider(zkConfigPath);
156
+ const accountId = walletCtx.unshieldedKeystore.getBech32Address().toString();
178
157
 
179
158
  return {
180
- privateStateProvider: levelPrivateStateProvider({ privateStateStoreName: 'hello-world-state', walletProvider }),
159
+ privateStateProvider: levelPrivateStateProvider({
160
+ privateStateStoreName: 'hello-world-state',
161
+ accountId,
162
+ privateStoragePasswordProvider: () => privateStatePassword,
163
+ }),
181
164
  publicDataProvider: indexerPublicDataProvider(CONFIG.indexer, CONFIG.indexerWS),
182
165
  zkConfigProvider,
183
166
  proofProvider: httpClientProofProvider(CONFIG.proofServer, zkConfigProvider),
@@ -272,7 +255,16 @@ async function main() {
272
255
  const walletCtx = await createWallet(seed.trim());
273
256
 
274
257
  console.log(' Syncing with network...');
275
- const state = await Rx.firstValueFrom(walletCtx.wallet.state().pipe(Rx.throttleTime(5000), Rx.filter((s) => s.isSynced)));
258
+ console.log(' ℹ This may take several minutes depending on network size.');
259
+ console.log(' RPC disconnection messages during sync are normal and can be safely ignored.\n');
260
+ const syncStart = Date.now();
261
+ const syncInterval = setInterval(() => {
262
+ const elapsed = Math.round((Date.now() - syncStart) / 1000);
263
+ process.stdout.write(`\r ⏳ Still syncing... (${elapsed}s elapsed) `);
264
+ }, 5000);
265
+ const state = await walletCtx.wallet.waitForSyncedState();
266
+ clearInterval(syncInterval);
267
+ process.stdout.write('\r ✓ Synced with network. \n');
276
268
  const address = walletCtx.unshieldedKeystore.getBech32Address();
277
269
  const balance = state.unshielded.balances[unshieldedToken().raw] ?? 0n;
278
270
 
@@ -301,7 +293,7 @@ async function main() {
301
293
  console.log('─── Step 3: DUST Token Setup ───────────────────────────────────\n');
302
294
  const dustState = await Rx.firstValueFrom(walletCtx.wallet.state().pipe(Rx.filter((s) => s.isSynced)));
303
295
 
304
- if (dustState.dust.walletBalance(new Date()) === 0n) {
296
+ if (dustState.dust.balance(new Date()) === 0n) {
305
297
  const nightUtxos = dustState.unshielded.availableCoins.filter((c: any) => !c.meta?.registeredForDustGeneration);
306
298
  if (nightUtxos.length > 0) {
307
299
  console.log(' Registering for DUST generation...');
@@ -310,12 +302,13 @@ async function main() {
310
302
  walletCtx.unshieldedKeystore.getPublicKey(),
311
303
  (payload) => walletCtx.unshieldedKeystore.signData(payload),
312
304
  );
313
- await walletCtx.wallet.submitTransaction(await walletCtx.wallet.finalizeRecipe(recipe));
305
+ const signedRecipe = await walletCtx.wallet.signRecipe(recipe, (payload) => walletCtx.unshieldedKeystore.signData(payload));
306
+ await walletCtx.wallet.submitTransaction(await walletCtx.wallet.finalizeRecipe(signedRecipe));
314
307
  }
315
308
 
316
309
  console.log(' Waiting for DUST tokens...');
317
310
  await Rx.firstValueFrom(
318
- walletCtx.wallet.state().pipe(Rx.throttleTime(5000), Rx.filter((s) => s.isSynced), Rx.filter((s) => s.dust.walletBalance(new Date()) > 0n)),
311
+ walletCtx.wallet.state().pipe(Rx.throttleTime(5000), Rx.filter((s) => s.isSynced), Rx.filter((s) => s.dust.balance(new Date()) > 0n)),
319
312
  );
320
313
  }
321
314
  console.log(' DUST tokens ready!\n');
@@ -360,11 +353,10 @@ async function main() {
360
353
 
361
354
  for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
362
355
  try {
363
- deployed = await deployContract(providers, {
364
- compiledContract,
365
- privateStateId: 'helloWorldState',
366
- initialPrivateState: {},
367
- });
356
+ deployed = await deployContract(providers, {
357
+ compiledContract: compiledContract as any,
358
+ args: [],
359
+ });
368
360
  break; // Success - exit retry loop
369
361
  } catch (err: any) {
370
362
  const errMsg = err?.message || err?.toString() || '';
@@ -397,8 +389,8 @@ async function main() {
397
389
  // Check if it's a DUST-related error (must check "Not enough Dust" specifically)
398
390
  if (fullError.includes('Not enough Dust')) {
399
391
  // Get current DUST balance
400
- const currentState = await Rx.firstValueFrom(walletCtx.wallet.state().pipe(Rx.filter((s) => s.isSynced)));
401
- const dustBalance = currentState.dust.walletBalance(new Date());
392
+ const currentState = await walletCtx.wallet.waitForSyncedState();
393
+ const dustBalance = currentState.dust.balance(new Date());
402
394
 
403
395
  if (attempt < MAX_RETRIES) {
404
396
  console.log(` ⏳ DUST balance: ${dustBalance.toLocaleString()} (need more for tx fees)`);
@@ -422,7 +414,7 @@ async function main() {
422
414
  console.log(' │ (DUST accumulates as blocks are produced) │');
423
415
  console.log(' │ │');
424
416
  console.log(' │ [2] Send DUST from existing wallet to this address: │');
425
- console.log(` │ ${address.slice(0, 50)}... │`);
417
+ console.log(` │ ${address.toString().slice(0, 50)}... │`);
426
418
  console.log(' │ │');
427
419
  console.log(' │ [3] Import wallet with DUST (choose option 2 on retry) │');
428
420
  console.log(' │ │');