create-mn-app 0.3.8 → 0.3.10

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.
@@ -1,214 +1,268 @@
1
- import "dotenv/config";
2
- import { WalletBuilder } from "@midnight-ntwrk/wallet";
3
- import { deployContract } from "@midnight-ntwrk/midnight-js-contracts";
4
- import { httpClientProofProvider } from "@midnight-ntwrk/midnight-js-http-client-proof-provider";
5
- import { indexerPublicDataProvider } from "@midnight-ntwrk/midnight-js-indexer-public-data-provider";
6
- import { NodeZkConfigProvider } from "@midnight-ntwrk/midnight-js-node-zk-config-provider";
7
- import { levelPrivateStateProvider } from "@midnight-ntwrk/midnight-js-level-private-state-provider";
8
- import {
9
- getZswapNetworkId,
10
- getLedgerNetworkId,
11
- } from "@midnight-ntwrk/midnight-js-network-id";
12
- import { createBalancedTx } from "@midnight-ntwrk/midnight-js-types";
13
- import { nativeToken, Transaction } from "@midnight-ntwrk/ledger";
14
- import { Transaction as ZswapTransaction } from "@midnight-ntwrk/zswap";
15
- import { WebSocket } from "ws";
16
- import * as fs from "fs";
17
- import * as path from "path";
18
- import * as Rx from "rxjs";
19
- import { type Wallet } from "@midnight-ntwrk/wallet-api";
20
- import chalk from "chalk";
21
- import { MidnightProviders } from "./providers/midnight-providers.js";
22
- import { EnvironmentManager } from "./utils/environment.js";
23
-
24
- // Fix WebSocket for Node.js environment
25
- // @ts-ignore
1
+ /**
2
+ * Deploy {{projectName}} contract to Midnight Preprod network
3
+ */
4
+ import { createInterface } from 'node:readline/promises';
5
+ import { stdin, stdout } from 'node:process';
6
+ import * as fs from 'node:fs';
7
+ import * as path from 'node:path';
8
+ import { fileURLToPath, pathToFileURL } from 'node:url';
9
+ import { WebSocket } from 'ws';
10
+ import * as Rx from 'rxjs';
11
+ import { Buffer } from 'buffer';
12
+
13
+ // Midnight SDK imports
14
+ import { deployContract } from '@midnight-ntwrk/midnight-js-contracts';
15
+ import { httpClientProofProvider } from '@midnight-ntwrk/midnight-js-http-client-proof-provider';
16
+ import { indexerPublicDataProvider } from '@midnight-ntwrk/midnight-js-indexer-public-data-provider';
17
+ import { levelPrivateStateProvider } from '@midnight-ntwrk/midnight-js-level-private-state-provider';
18
+ import { NodeZkConfigProvider } from '@midnight-ntwrk/midnight-js-node-zk-config-provider';
19
+ import { setNetworkId, getNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
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';
23
+ import { WalletFacade } from '@midnight-ntwrk/wallet-sdk-facade';
24
+ import { DustWallet } from '@midnight-ntwrk/wallet-sdk-dust-wallet';
25
+ import { HDWallet, Roles, generateRandomSeed } from '@midnight-ntwrk/wallet-sdk-hd';
26
+ import { ShieldedWallet } from '@midnight-ntwrk/wallet-sdk-shielded';
27
+ import { createKeystore, InMemoryTransactionHistoryStorage, PublicKey, UnshieldedWallet } from '@midnight-ntwrk/wallet-sdk-unshielded-wallet';
28
+ import { CompiledContract } from '@midnight-ntwrk/compact-js';
29
+
30
+ // Enable WebSocket for GraphQL subscriptions
31
+ // @ts-expect-error Required for wallet sync
26
32
  globalThis.WebSocket = WebSocket;
27
33
 
28
- // Initialize network from environment config
29
- const networkConfig = EnvironmentManager.initializeNetwork();
30
-
31
- const waitForFunds = (wallet: Wallet) =>
32
- Rx.firstValueFrom(
33
- wallet.state().pipe(
34
- Rx.tap((state) => {
35
- if (state.syncProgress) {
36
- console.log(
37
- `Sync progress: synced=${state.syncProgress.synced}, sourceGap=${state.syncProgress.lag.sourceGap}, applyGap=${state.syncProgress.lag.applyGap}`
38
- );
39
- }
40
- }),
41
- Rx.filter((state) => state.syncProgress?.synced === true),
42
- Rx.map((s) => s.balances[nativeToken()] ?? 0n),
43
- Rx.filter((balance) => balance > 0n),
44
- Rx.tap((balance) => console.log(`Wallet funded with balance: ${balance}`))
45
- )
46
- );
34
+ // Set network to preprod
35
+ setNetworkId('preprod');
47
36
 
48
- async function main() {
49
- console.log();
50
- console.log(chalk.blue.bold("━".repeat(60)));
51
- console.log(chalk.blue.bold("šŸŒ™ {{projectName}} Deployment"));
52
- console.log(chalk.blue.bold("━".repeat(60)));
53
- console.log();
37
+ // Preprod network configuration
38
+ const CONFIG = {
39
+ indexer: 'https://indexer.preprod.midnight.network/api/v3/graphql',
40
+ indexerWS: 'wss://indexer.preprod.midnight.network/api/v3/graphql/ws',
41
+ node: 'https://rpc.preprod.midnight.network',
42
+ proofServer: 'http://127.0.0.1:6300',
43
+ faucetUrl: 'https://faucet.preprod.midnight.network/',
44
+ };
54
45
 
55
- try {
56
- // Validate environment
57
- EnvironmentManager.validateEnvironment();
46
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
47
+ const zkConfigPath = path.resolve(__dirname, '..', 'contracts', 'managed', 'hello-world');
48
+
49
+ // Load compiled contract
50
+ const contractPath = path.join(zkConfigPath, 'contract', 'index.js');
58
51
 
59
- const contractName = process.env.CONTRACT_NAME || "hello-world";
52
+ // Check if contract is compiled
53
+ if (!fs.existsSync(contractPath)) {
54
+ console.error('\nāŒ Contract not compiled! Run: npm run compile\n');
55
+ process.exit(1);
56
+ }
57
+
58
+ const HelloWorld = await import(pathToFileURL(contractPath).href);
59
+
60
+ const compiledContract = CompiledContract.make('hello-world', HelloWorld.Contract).pipe(
61
+ CompiledContract.withVacantWitnesses,
62
+ CompiledContract.withCompiledFileAssets(zkConfigPath),
63
+ );
60
64
 
61
- // Check if contract is compiled
62
- if (!EnvironmentManager.checkContractCompiled(contractName)) {
63
- console.error("āŒ Contract not compiled! Run: npm run compile");
64
- process.exit(1);
65
+ // ─── Wallet Functions ──────────────────────────────────────────────────────────
66
+
67
+ function deriveKeys(seed: string) {
68
+ const hdWallet = HDWallet.fromSeed(Buffer.from(seed, 'hex'));
69
+ if (hdWallet.type !== 'seedOk') throw new Error('Invalid seed');
70
+ const result = hdWallet.hdWallet.selectAccount(0).selectRoles([Roles.Zswap, Roles.NightExternal, Roles.Dust]).deriveKeysAt(0);
71
+ if (result.type !== 'keysDerived') throw new Error('Key derivation failed');
72
+ hdWallet.hdWallet.clear();
73
+ return result.keys;
74
+ }
75
+
76
+ async function createWallet(seed: string) {
77
+ const keys = deriveKeys(seed);
78
+ const networkId = getNetworkId();
79
+ const shieldedSecretKeys = ledger.ZswapSecretKeys.fromSeed(keys[Roles.Zswap]);
80
+ const dustSecretKey = ledger.DustSecretKey.fromSeed(keys[Roles.Dust]);
81
+ const unshieldedKeystore = createKeystore(keys[Roles.NightExternal], networkId);
82
+
83
+ const walletConfig = {
84
+ networkId,
85
+ indexerClientConnection: { indexerHttpUrl: CONFIG.indexer, indexerWsUrl: CONFIG.indexerWS },
86
+ provingServerUrl: new URL(CONFIG.proofServer),
87
+ relayURL: new URL(CONFIG.node.replace(/^http/, 'ws')),
88
+ };
89
+
90
+ const shieldedWallet = ShieldedWallet(walletConfig).startWithSecretKeys(shieldedSecretKeys);
91
+ const unshieldedWallet = UnshieldedWallet({
92
+ networkId,
93
+ indexerClientConnection: walletConfig.indexerClientConnection,
94
+ txHistoryStorage: new InMemoryTransactionHistoryStorage(),
95
+ }).startWithPublicKey(PublicKey.fromKeyStore(unshieldedKeystore));
96
+ const dustWallet = DustWallet({
97
+ ...walletConfig,
98
+ costParameters: { additionalFeeOverhead: 300_000_000_000_000n, feeBlocksMargin: 5 },
99
+ }).startWithSecretKey(dustSecretKey, ledger.LedgerParameters.initialParameters().dust);
100
+
101
+ const wallet = new WalletFacade(shieldedWallet, unshieldedWallet, dustWallet);
102
+ await wallet.start(shieldedSecretKeys, dustSecretKey);
103
+
104
+ return { wallet, shieldedSecretKeys, dustSecretKey, unshieldedKeystore };
105
+ }
106
+
107
+ // Workaround for wallet SDK signRecipe bug
108
+ function signTransactionIntents(tx: { intents?: Map<number, any> }, signFn: (payload: Uint8Array) => ledger.Signature, proofMarker: 'proof' | 'pre-proof'): void {
109
+ if (!tx.intents || tx.intents.size === 0) return;
110
+ for (const segment of tx.intents.keys()) {
111
+ const intent = tx.intents.get(segment);
112
+ if (!intent) continue;
113
+ const cloned = ledger.Intent.deserialize<ledger.SignatureEnabled, ledger.Proofish, ledger.PreBinding>('signature', proofMarker, 'pre-binding', intent.serialize());
114
+ const sigData = cloned.signatureData(segment);
115
+ const signature = signFn(sigData);
116
+ if (cloned.fallibleUnshieldedOffer) {
117
+ const sigs = cloned.fallibleUnshieldedOffer.inputs.map((_: any, i: number) => cloned.fallibleUnshieldedOffer!.signatures.at(i) ?? signature);
118
+ cloned.fallibleUnshieldedOffer = cloned.fallibleUnshieldedOffer.addSignatures(sigs);
65
119
  }
120
+ if (cloned.guaranteedUnshieldedOffer) {
121
+ const sigs = cloned.guaranteedUnshieldedOffer.inputs.map((_: any, i: number) => cloned.guaranteedUnshieldedOffer!.signatures.at(i) ?? signature);
122
+ cloned.guaranteedUnshieldedOffer = cloned.guaranteedUnshieldedOffer.addSignatures(sigs);
123
+ }
124
+ tx.intents.set(segment, cloned);
125
+ }
126
+ }
127
+
128
+ async function createProviders(walletCtx: ReturnType<typeof createWallet> extends Promise<infer T> ? T : never) {
129
+ const state = await Rx.firstValueFrom(walletCtx.wallet.state().pipe(Rx.filter((s) => s.isSynced)));
130
+
131
+ const walletProvider = {
132
+ getCoinPublicKey: () => state.shielded.coinPublicKey.toHexString(),
133
+ getEncryptionPublicKey: () => state.shielded.encryptionPublicKey.toHexString(),
134
+ async balanceTx(tx: any, ttl?: Date) {
135
+ const recipe = await walletCtx.wallet.balanceUnboundTransaction(
136
+ tx,
137
+ { shieldedSecretKeys: walletCtx.shieldedSecretKeys, dustSecretKey: walletCtx.dustSecretKey },
138
+ { ttl: ttl ?? new Date(Date.now() + 30 * 60 * 1000) },
139
+ );
140
+ const signFn = (payload: Uint8Array) => walletCtx.unshieldedKeystore.signData(payload);
141
+ signTransactionIntents(recipe.baseTransaction, signFn, 'proof');
142
+ if (recipe.balancingTransaction) signTransactionIntents(recipe.balancingTransaction, signFn, 'pre-proof');
143
+ return walletCtx.wallet.finalizeRecipe(recipe);
144
+ },
145
+ submitTx: (tx: any) => walletCtx.wallet.submitTransaction(tx) as any,
146
+ };
147
+
148
+ const zkConfigProvider = new NodeZkConfigProvider(zkConfigPath);
149
+
150
+ return {
151
+ privateStateProvider: levelPrivateStateProvider({ privateStateStoreName: 'hello-world-state', walletProvider }),
152
+ publicDataProvider: indexerPublicDataProvider(CONFIG.indexer, CONFIG.indexerWS),
153
+ zkConfigProvider,
154
+ proofProvider: httpClientProofProvider(CONFIG.proofServer, zkConfigProvider),
155
+ walletProvider,
156
+ midnightProvider: walletProvider,
157
+ };
158
+ }
66
159
 
67
- const walletSeed = process.env.WALLET_SEED!;
160
+ // ─── Main Deploy Script ────────────────────────────────────────────────────────
68
161
 
69
- // Build wallet from seed
70
- console.log("Building wallet...");
71
- const wallet = await WalletBuilder.buildFromSeed(
72
- networkConfig.indexer,
73
- networkConfig.indexerWS,
74
- networkConfig.proofServer,
75
- networkConfig.node,
76
- walletSeed,
77
- getZswapNetworkId(),
78
- "info"
79
- );
162
+ async function main() {
163
+ console.log('\n╔══════════════════════════════════════════════════════════════╗');
164
+ console.log('ā•‘ Deploy {{projectName}} to Midnight Preprod ā•‘');
165
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
80
166
 
81
- wallet.start();
82
- const state = await Rx.firstValueFrom(wallet.state());
167
+ const rl = createInterface({ input: stdin, output: stdout });
83
168
 
84
- console.log(chalk.cyan.bold("šŸ“ Wallet Address:"));
85
- console.log(chalk.white(` ${state.address}`));
86
- console.log();
169
+ try {
170
+ // 1. Wallet setup
171
+ console.log('─── Step 1: Wallet Setup ───────────────────────────────────────\n');
172
+ const choice = await rl.question(' [1] Create new wallet\n [2] Restore from seed\n > ');
87
173
 
88
- let balance = state.balances[nativeToken()] || 0n;
174
+ const seed = choice.trim() === '2'
175
+ ? await rl.question('\n Enter your 64-character seed: ')
176
+ : toHex(Buffer.from(generateRandomSeed()));
177
+
178
+ if (choice.trim() !== '2') {
179
+ console.log(`\n āš ļø SAVE THIS SEED (you'll need it later):\n ${seed}\n`);
180
+ }
89
181
 
182
+ console.log(' Creating wallet...');
183
+ const walletCtx = await createWallet(seed.trim());
184
+
185
+ console.log(' Syncing with network...');
186
+ const state = await Rx.firstValueFrom(walletCtx.wallet.state().pipe(Rx.throttleTime(5000), Rx.filter((s) => s.isSynced)));
187
+ const address = walletCtx.unshieldedKeystore.getBech32Address();
188
+ const balance = state.unshielded.balances[unshieldedToken().raw] ?? 0n;
189
+
190
+ console.log(`\n Wallet Address: ${address}`);
191
+ console.log(` Balance: ${balance.toLocaleString()} tNight\n`);
192
+
193
+ // 2. Fund wallet if needed
90
194
  if (balance === 0n) {
91
- console.log(chalk.yellow.bold("šŸ’° Balance: ") + chalk.red.bold("0 DUST"));
92
- console.log();
93
- console.log(chalk.red.bold("āŒ Wallet needs funding to deploy contracts."));
94
- console.log();
95
- console.log(chalk.magenta.bold("━".repeat(60)));
96
- console.log(chalk.magenta.bold("šŸ“ How to Get Test Tokens:"));
97
- console.log(chalk.magenta.bold("━".repeat(60)));
98
- console.log();
99
- console.log(chalk.white(" 1. ") + chalk.cyan("Visit: ") + chalk.underline(networkConfig.faucetUrl));
100
- console.log(chalk.white(" 2. ") + chalk.cyan("Paste your wallet address (shown above)"));
101
- console.log(chalk.white(" 3. ") + chalk.cyan("Request tokens from the faucet"));
102
- console.log();
103
- console.log(chalk.gray("━".repeat(60)));
104
- console.log(chalk.gray("ā±ļø Faucet transactions can take 2-5 minutes to process."));
105
- console.log(chalk.gray("━".repeat(60)));
106
- console.log();
107
- console.log(chalk.yellow.bold("šŸ’” Options while waiting:"));
108
- console.log(chalk.white(" • ") + chalk.cyan("Let this script wait (it will auto-detect when funds arrive)"));
109
- console.log(chalk.white(" • ") + chalk.cyan("OR press ") + chalk.yellow("Ctrl+C") + chalk.cyan(" to stop, then check balance with:"));
110
- console.log(chalk.yellow.bold(" npm run check-balance"));
111
- console.log(chalk.white(" • ") + chalk.cyan("Once funded, run: ") + chalk.yellow.bold("npm run deploy"));
112
- console.log();
113
- console.log(chalk.blue("ā³ Waiting to receive tokens..."));
114
- balance = await waitForFunds(wallet);
195
+ console.log('─── Step 2: Fund Your Wallet ───────────────────────────────────\n');
196
+ console.log(` Visit: ${CONFIG.faucetUrl}`);
197
+ console.log(` Address: ${address}\n`);
198
+ console.log(' Waiting for funds...');
199
+
200
+ await Rx.firstValueFrom(
201
+ walletCtx.wallet.state().pipe(
202
+ Rx.throttleTime(10000),
203
+ Rx.filter((s) => s.isSynced),
204
+ Rx.map((s) => s.unshielded.balances[unshieldedToken().raw] ?? 0n),
205
+ Rx.filter((b) => b > 0n),
206
+ ),
207
+ );
208
+ console.log(' Funds received!\n');
115
209
  }
116
210
 
117
- console.log(chalk.yellow.bold("šŸ’° Balance: ") + chalk.green.bold(`${balance} DUST`));
118
- console.log();
119
-
120
- // Load compiled contract files
121
- console.log(chalk.gray("šŸ“¦ Loading contract..."));
122
- const contractPath = path.join(process.cwd(), "contracts");
123
- const contractModulePath = path.join(
124
- contractPath,
125
- "managed",
126
- contractName,
127
- "contract",
128
- "index.cjs"
129
- );
130
-
131
- const HelloWorldModule = await import(contractModulePath);
132
- const contractInstance = new HelloWorldModule.Contract({});
133
-
134
- // Create wallet provider for transactions
135
- const walletState = await Rx.firstValueFrom(wallet.state());
136
-
137
- const walletProvider = {
138
- coinPublicKey: walletState.coinPublicKey,
139
- encryptionPublicKey: walletState.encryptionPublicKey,
140
- balanceTx(tx: any, newCoins: any) {
141
- return wallet
142
- .balanceTransaction(
143
- ZswapTransaction.deserialize(
144
- tx.serialize(getLedgerNetworkId()),
145
- getZswapNetworkId()
146
- ),
147
- newCoins
148
- )
149
- .then((tx) => wallet.proveTransaction(tx))
150
- .then((zswapTx) =>
151
- Transaction.deserialize(
152
- zswapTx.serialize(getZswapNetworkId()),
153
- getLedgerNetworkId()
154
- )
155
- )
156
- .then(createBalancedTx);
157
- },
158
- submitTx(tx: any) {
159
- return wallet.submitTransaction(tx);
160
- },
161
- };
211
+ // 3. Register for DUST
212
+ console.log('─── Step 3: DUST Token Setup ───────────────────────────────────\n');
213
+ const dustState = await Rx.firstValueFrom(walletCtx.wallet.state().pipe(Rx.filter((s) => s.isSynced)));
162
214
 
163
- // Configure all required providers
164
- console.log("Setting up providers...");
165
- const providers = MidnightProviders.create({
166
- contractName,
167
- walletProvider,
168
- networkConfig,
169
- });
215
+ if (dustState.dust.walletBalance(new Date()) === 0n) {
216
+ const nightUtxos = dustState.unshielded.availableCoins.filter((c: any) => !c.meta?.registeredForDustGeneration);
217
+ if (nightUtxos.length > 0) {
218
+ console.log(' Registering for DUST generation...');
219
+ const recipe = await walletCtx.wallet.registerNightUtxosForDustGeneration(
220
+ nightUtxos,
221
+ walletCtx.unshieldedKeystore.getPublicKey(),
222
+ (payload) => walletCtx.unshieldedKeystore.signData(payload),
223
+ );
224
+ await walletCtx.wallet.submitTransaction(await walletCtx.wallet.finalizeRecipe(recipe));
225
+ }
226
+
227
+ console.log(' Waiting for DUST tokens...');
228
+ await Rx.firstValueFrom(
229
+ walletCtx.wallet.state().pipe(Rx.throttleTime(5000), Rx.filter((s) => s.isSynced), Rx.filter((s) => s.dust.walletBalance(new Date()) > 0n)),
230
+ );
231
+ }
232
+ console.log(' DUST tokens ready!\n');
170
233
 
171
- // Deploy contract to blockchain
172
- console.log(chalk.blue("šŸš€ Deploying contract (30-60 seconds)..."));
173
- console.log();
234
+ // 4. Deploy contract
235
+ console.log('─── Step 4: Deploy Contract ────────────────────────────────────\n');
236
+ console.log(' Setting up providers...');
237
+ const providers = await createProviders(walletCtx);
174
238
 
239
+ console.log(' Deploying contract (this may take 30-60 seconds)...\n');
175
240
  const deployed = await deployContract(providers, {
176
- contract: contractInstance,
177
- privateStateId: "helloWorldState",
241
+ compiledContract,
242
+ privateStateId: 'helloWorldState',
178
243
  initialPrivateState: {},
179
244
  });
180
245
 
181
246
  const contractAddress = deployed.deployTxData.public.contractAddress;
247
+ console.log(' āœ… Contract deployed successfully!\n');
248
+ console.log(` Contract Address: ${contractAddress}\n`);
182
249
 
183
- // Save deployment information
184
- console.log();
185
- console.log(chalk.green.bold("━".repeat(60)));
186
- console.log(chalk.green.bold("šŸŽ‰ CONTRACT DEPLOYED SUCCESSFULLY!"));
187
- console.log(chalk.green.bold("━".repeat(60)));
188
- console.log();
189
- console.log(chalk.cyan.bold("šŸ“ Contract Address:"));
190
- console.log(chalk.white(` ${contractAddress}`));
191
- console.log();
192
-
193
- const info = {
250
+ // 5. Save deployment info
251
+ const deploymentInfo = {
194
252
  contractAddress,
253
+ seed,
254
+ network: 'preprod',
195
255
  deployedAt: new Date().toISOString(),
196
- network: networkConfig.name,
197
- contractName,
198
256
  };
199
257
 
200
- fs.writeFileSync("deployment.json", JSON.stringify(info, null, 2));
201
- console.log(chalk.gray("āœ… Saved to deployment.json"));
202
- console.log();
203
-
204
- // Close wallet connection
205
- await wallet.close();
206
- } catch (error) {
207
- console.log();
208
- console.log(chalk.red.bold("āŒ Deployment Failed:"));
209
- console.error(chalk.red(error instanceof Error ? error.message : String(error)));
210
- console.log();
211
- process.exit(1);
258
+ fs.writeFileSync('deployment.json', JSON.stringify(deploymentInfo, null, 2));
259
+ console.log(' Saved to deployment.json\n');
260
+
261
+ await walletCtx.wallet.stop();
262
+ console.log('─── Deployment Complete! ───────────────────────────────────────\n');
263
+ console.log(' Next: Run `npm run cli` to interact with your contract.\n');
264
+ } finally {
265
+ rl.close();
212
266
  }
213
267
  }
214
268
 
File without changes
@@ -1,7 +0,0 @@
1
- {
2
- "watch": ["contracts/**/*.compact", "src/**/*.ts"],
3
- "ext": "compact,ts",
4
- "ignore": ["contracts/managed/**", "dist/**", "node_modules/**"],
5
- "exec": "npm run compile && npm run build",
6
- "delay": "1000"
7
- }
@@ -1,127 +0,0 @@
1
- #!/usr/bin/env node
2
- import { execSync } from "child_process";
3
- import fs from "fs";
4
- import chalk from "chalk";
5
-
6
- interface HealthCheck {
7
- name: string;
8
- check: () => Promise<boolean>;
9
- message: string;
10
- error?: string;
11
- }
12
-
13
- const checks: HealthCheck[] = [
14
- {
15
- name: "Node.js Version",
16
- message: "Checking Node.js version (>= 22.0.0)...",
17
- check: async () => {
18
- const version = process.version;
19
- const major = parseInt(version.slice(1).split(".")[0]);
20
- return major >= 22;
21
- },
22
- error: "Node.js 22 or higher is required. Please upgrade Node.js.",
23
- },
24
- {
25
- name: "Docker",
26
- message: "Checking Docker availability...",
27
- check: async () => {
28
- try {
29
- execSync("docker --version", { stdio: "ignore" });
30
- return true;
31
- } catch {
32
- return false;
33
- }
34
- },
35
- error: "Docker is not installed or not running. Install Docker to use the proof server.",
36
- },
37
- {
38
- name: "Environment File",
39
- message: "Checking .env configuration...",
40
- check: async () => {
41
- return fs.existsSync(".env");
42
- },
43
- error: ".env file not found. Run 'npm run setup' first.",
44
- },
45
- {
46
- name: "Wallet Seed",
47
- message: "Checking wallet configuration...",
48
- check: async () => {
49
- if (!fs.existsSync(".env")) return false;
50
- const envContent = fs.readFileSync(".env", "utf-8");
51
- return envContent.includes("WALLET_SEED=");
52
- },
53
- error: "WALLET_SEED not found in .env. Run 'npm run setup' to generate a wallet.",
54
- },
55
- {
56
- name: "Dependencies",
57
- message: "Checking node_modules...",
58
- check: async () => {
59
- return fs.existsSync("node_modules");
60
- },
61
- error: "Dependencies not installed. Run 'npm install' first.",
62
- },
63
- {
64
- name: "Contract Compilation",
65
- message: "Checking compiled contracts...",
66
- check: async () => {
67
- return fs.existsSync("dist") || fs.existsSync("build");
68
- },
69
- error: "Project not built. Run 'npm run compile' and 'npm run build'.",
70
- },
71
- ];
72
-
73
- async function runHealthCheck() {
74
- console.log(chalk.blue.bold("\nšŸ„ Midnight App Health Check\n"));
75
-
76
- let passed = 0;
77
- let failed = 0;
78
-
79
- for (const check of checks) {
80
- process.stdout.write(chalk.gray(`ā³ ${check.message} `));
81
-
82
- try {
83
- const result = await check.check();
84
-
85
- if (result) {
86
- console.log(chalk.green("āœ“ Passed"));
87
- passed++;
88
- } else {
89
- console.log(chalk.red("āœ— Failed"));
90
- if (check.error) {
91
- console.log(chalk.yellow(` ${check.error}`));
92
- }
93
- failed++;
94
- }
95
- } catch (error) {
96
- console.log(chalk.red("āœ— Error"));
97
- console.log(chalk.yellow(` ${check.error || "Unknown error"}`));
98
- failed++;
99
- }
100
- }
101
-
102
- console.log();
103
- console.log(chalk.bold("━".repeat(60)));
104
- console.log(
105
- chalk.bold(
106
- `Results: ${chalk.green(`${passed} passed`)} | ${chalk.red(`${failed} failed`)}`
107
- )
108
- );
109
- console.log(chalk.bold("━".repeat(60)));
110
-
111
- if (failed === 0) {
112
- console.log(chalk.green.bold("\nāœ“ All checks passed! Your environment is ready.\n"));
113
- process.exit(0);
114
- } else {
115
- console.log(
116
- chalk.yellow.bold(
117
- "\n⚠ Some checks failed. Please fix the issues above before continuing.\n"
118
- )
119
- );
120
- process.exit(1);
121
- }
122
- }
123
-
124
- runHealthCheck().catch((error) => {
125
- console.error(chalk.red("\nāœ— Health check failed:"), error.message);
126
- process.exit(1);
127
- });
@@ -1,50 +0,0 @@
1
- import path from "path";
2
- import { levelPrivateStateProvider } from "@midnight-ntwrk/midnight-js-level-private-state-provider";
3
- import { indexerPublicDataProvider } from "@midnight-ntwrk/midnight-js-indexer-public-data-provider";
4
- import { NodeZkConfigProvider } from "@midnight-ntwrk/midnight-js-node-zk-config-provider";
5
- import { httpClientProofProvider } from "@midnight-ntwrk/midnight-js-http-client-proof-provider";
6
-
7
- import { NetworkId } from "@midnight-ntwrk/midnight-js-network-id";
8
-
9
- export interface NetworkConfig {
10
- indexer: string;
11
- indexerWS: string;
12
- node: string;
13
- proofServer: string;
14
- name: string;
15
- faucetUrl: string;
16
- networkId: NetworkId;
17
- }
18
-
19
- export interface ProviderConfig {
20
- contractName: string;
21
- walletProvider: any;
22
- networkConfig: NetworkConfig;
23
- privateStateStoreName?: string;
24
- }
25
-
26
- export class MidnightProviders {
27
- static create(config: ProviderConfig) {
28
- const contractPath = path.join(process.cwd(), "contracts");
29
- const zkConfigPath = path.join(
30
- contractPath,
31
- "managed",
32
- config.contractName
33
- );
34
-
35
- return {
36
- privateStateProvider: levelPrivateStateProvider({
37
- privateStateStoreName:
38
- config.privateStateStoreName || `${config.contractName}-state`,
39
- }),
40
- publicDataProvider: indexerPublicDataProvider(
41
- config.networkConfig.indexer,
42
- config.networkConfig.indexerWS
43
- ),
44
- zkConfigProvider: new NodeZkConfigProvider(zkConfigPath),
45
- proofProvider: httpClientProofProvider(config.networkConfig.proofServer),
46
- walletProvider: config.walletProvider,
47
- midnightProvider: config.walletProvider,
48
- };
49
- }
50
- }