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
|
@@ -18,24 +18,24 @@
|
|
|
18
18
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@midnight-ntwrk/compact-
|
|
22
|
-
"
|
|
23
|
-
"@midnight-ntwrk/
|
|
24
|
-
"@midnight-ntwrk/
|
|
25
|
-
"@midnight-ntwrk/midnight-js-
|
|
26
|
-
"@midnight-ntwrk/midnight-js-
|
|
27
|
-
"@midnight-ntwrk/midnight-js-
|
|
28
|
-
"@midnight-ntwrk/midnight-js-
|
|
29
|
-
"@midnight-ntwrk/midnight-js-network-id": "
|
|
30
|
-
"@midnight-ntwrk/midnight-js-
|
|
31
|
-
"@midnight-ntwrk/midnight-js-
|
|
32
|
-
"@midnight-ntwrk/
|
|
33
|
-
"@midnight-ntwrk/wallet-sdk-
|
|
34
|
-
"@midnight-ntwrk/wallet-sdk-
|
|
35
|
-
"@midnight-ntwrk/wallet-sdk-
|
|
36
|
-
"@midnight-ntwrk/wallet-sdk-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
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-
|
|
12
|
-
import { unshieldedToken } from '@midnight-ntwrk/ledger-
|
|
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
|
-
}
|
|
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
|
-
|
|
104
|
-
|
|
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.
|
|
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-
|
|
21
|
-
import { unshieldedToken } from '@midnight-ntwrk/ledger-
|
|
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
|
-
}
|
|
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
|
|
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
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return walletCtx.wallet.finalizeRecipe(
|
|
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({
|
|
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
|
-
|
|
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
|
|
241
|
+
const currentState = await walletCtx.wallet.waitForSyncedState();
|
|
252
242
|
const currentBalance = currentState.unshielded.balances[unshieldedToken().raw] ?? 0n;
|
|
253
|
-
const dustBalance = currentState.dust.
|
|
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-
|
|
22
|
-
import { unshieldedToken } from '@midnight-ntwrk/ledger-
|
|
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
|
-
}
|
|
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
|
|
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
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return walletCtx.wallet.finalizeRecipe(
|
|
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({
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
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
|
|
401
|
-
const dustBalance = currentState.dust.
|
|
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(' │ │');
|