create-mn-app 0.0.6

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 (51) hide show
  1. package/README.md +239 -0
  2. package/bin/create-midnight-app.js +47 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +35 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/create-app.d.ts +10 -0
  8. package/dist/create-app.d.ts.map +1 -0
  9. package/dist/create-app.js +186 -0
  10. package/dist/create-app.js.map +1 -0
  11. package/dist/installers/package-installer.d.ts +8 -0
  12. package/dist/installers/package-installer.d.ts.map +1 -0
  13. package/dist/installers/package-installer.js +62 -0
  14. package/dist/installers/package-installer.js.map +1 -0
  15. package/dist/installers/proof-server-setup.d.ts +6 -0
  16. package/dist/installers/proof-server-setup.d.ts.map +1 -0
  17. package/dist/installers/proof-server-setup.js +54 -0
  18. package/dist/installers/proof-server-setup.js.map +1 -0
  19. package/dist/installers/wallet-generator.d.ts +4 -0
  20. package/dist/installers/wallet-generator.d.ts.map +1 -0
  21. package/dist/installers/wallet-generator.js +64 -0
  22. package/dist/installers/wallet-generator.js.map +1 -0
  23. package/dist/test.d.ts +2 -0
  24. package/dist/test.d.ts.map +1 -0
  25. package/dist/test.js +53 -0
  26. package/dist/test.js.map +1 -0
  27. package/dist/utils/git-utils.d.ts +6 -0
  28. package/dist/utils/git-utils.d.ts.map +1 -0
  29. package/dist/utils/git-utils.js +51 -0
  30. package/dist/utils/git-utils.js.map +1 -0
  31. package/dist/utils/template-manager.d.ts +7 -0
  32. package/dist/utils/template-manager.d.ts.map +1 -0
  33. package/dist/utils/template-manager.js +61 -0
  34. package/dist/utils/template-manager.js.map +1 -0
  35. package/dist/utils/validation.d.ts +6 -0
  36. package/dist/utils/validation.d.ts.map +1 -0
  37. package/dist/utils/validation.js +32 -0
  38. package/dist/utils/validation.js.map +1 -0
  39. package/package.json +60 -0
  40. package/templates/hello-world/README.md.template +99 -0
  41. package/templates/hello-world/_env.template +0 -0
  42. package/templates/hello-world/_gitignore +52 -0
  43. package/templates/hello-world/contracts/hello-world.compact.template +12 -0
  44. package/templates/hello-world/nodemon.json.template +7 -0
  45. package/templates/hello-world/package.json.template +51 -0
  46. package/templates/hello-world/src/check-balance.ts.template +107 -0
  47. package/templates/hello-world/src/cli.ts.template +194 -0
  48. package/templates/hello-world/src/deploy.ts.template +218 -0
  49. package/templates/hello-world/src/providers/midnight-providers.ts.template +46 -0
  50. package/templates/hello-world/src/utils/environment.ts.template +51 -0
  51. package/templates/hello-world/tsconfig.json.template +20 -0
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "A Midnight Network application created with create-midnight-app",
6
+ "author": "{{author}}",
7
+ "license": "MIT",
8
+ "scripts": {
9
+ "dev": "concurrently \"npm run proof-server\" \"npm run watch\"",
10
+ "watch": "nodemon --config nodemon.json",
11
+ "setup": "npm run compile && npm run build && npm run deploy",
12
+ "compile": "compact compile contracts/hello-world.compact contracts/managed/hello-world",
13
+ "build": "tsc",
14
+ "deploy": "node dist/deploy.js",
15
+ "cli": "node dist/cli.js",
16
+ "check-balance": "npm run build && node dist/check-balance.js",
17
+ "reset": "rm -rf contracts/managed deployment.json dist && npm run compile",
18
+ "validate": "tsc --noEmit && npm run compile",
19
+ "clean": "rm -rf dist contracts/managed deployment.json",
20
+ "proof-server": "docker run -p 6300:6300 midnightnetwork/proof-server -- 'midnight-proof-server --network testnet'",
21
+ "test": "echo \"Error: no test specified\" && exit 1"
22
+ },
23
+ "dependencies": {
24
+ "@midnight-ntwrk/compact-runtime": "^0.8.1",
25
+ "@midnight-ntwrk/ledger": "^4.0.0",
26
+ "@midnight-ntwrk/midnight-js-contracts": "2.0.2",
27
+ "@midnight-ntwrk/midnight-js-http-client-proof-provider": "2.0.2",
28
+ "@midnight-ntwrk/midnight-js-indexer-public-data-provider": "2.0.2",
29
+ "@midnight-ntwrk/midnight-js-level-private-state-provider": "2.0.2",
30
+ "@midnight-ntwrk/midnight-js-node-zk-config-provider": "2.0.2",
31
+ "@midnight-ntwrk/midnight-js-network-id": "2.0.2",
32
+ "@midnight-ntwrk/midnight-js-types": "2.0.2",
33
+ "@midnight-ntwrk/wallet": "5.0.0",
34
+ "@midnight-ntwrk/wallet-api": "5.0.0",
35
+ "@midnight-ntwrk/zswap": "^4.0.0",
36
+ "ws": "^8.18.3",
37
+ "dotenv": "^16.3.1",
38
+ "chalk": "^5.3.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^24.4.0",
42
+ "@types/ws": "^8.5.10",
43
+ "typescript": "^5.9.2",
44
+ "nodemon": "^3.0.1",
45
+ "concurrently": "^8.2.0"
46
+ },
47
+ "engines": {
48
+ "node": ">=18.0.0"
49
+ },
50
+ "keywords": ["midnight", "blockchain", "zero-knowledge", "privacy"]
51
+ }
@@ -0,0 +1,107 @@
1
+ import "dotenv/config";
2
+ import { WalletBuilder } from "@midnight-ntwrk/wallet";
3
+ import {
4
+ NetworkId,
5
+ setNetworkId,
6
+ getZswapNetworkId,
7
+ getLedgerNetworkId,
8
+ } from "@midnight-ntwrk/midnight-js-network-id";
9
+ import { nativeToken } from "@midnight-ntwrk/ledger";
10
+ import { WebSocket } from "ws";
11
+ import * as Rx from "rxjs";
12
+ import chalk from "chalk";
13
+ import { EnvironmentManager } from "./utils/environment.js";
14
+
15
+ // Fix WebSocket for Node.js environment
16
+ // @ts-ignore
17
+ globalThis.WebSocket = WebSocket;
18
+
19
+ // Configure for Midnight Testnet
20
+ setNetworkId(NetworkId.TestNet);
21
+
22
+ async function checkBalance() {
23
+ try {
24
+ console.log();
25
+ console.log(chalk.blue.bold("━".repeat(60)));
26
+ console.log(chalk.blue.bold("🌙 Wallet Balance Checker"));
27
+ console.log(chalk.blue.bold("━".repeat(60)));
28
+ console.log();
29
+
30
+ const seed = process.env.WALLET_SEED;
31
+ if (!seed) {
32
+ throw new Error("WALLET_SEED not found in .env file");
33
+ }
34
+
35
+ console.log(chalk.gray("Building wallet..."));
36
+ console.log();
37
+
38
+ // Get network configuration
39
+ const networkConfig = EnvironmentManager.getNetworkConfig();
40
+
41
+ // Build wallet from seed
42
+ const wallet = await WalletBuilder.buildFromSeed(
43
+ networkConfig.indexer,
44
+ networkConfig.indexerWS,
45
+ networkConfig.proofServer,
46
+ networkConfig.node,
47
+ seed,
48
+ getZswapNetworkId(),
49
+ "info"
50
+ );
51
+
52
+ wallet.start();
53
+
54
+ const state = await Rx.firstValueFrom(wallet.state());
55
+
56
+ console.log(chalk.cyan.bold("📍 Wallet Address:"));
57
+ console.log(chalk.white(` ${state.address}`));
58
+ console.log();
59
+
60
+ const balance = state.balances[nativeToken()] || 0n;
61
+
62
+ if (balance === 0n) {
63
+ console.log(chalk.yellow.bold("💰 Balance: ") + chalk.red.bold("0 DUST"));
64
+ console.log();
65
+ console.log(chalk.red("❌ No funds detected."));
66
+ console.log();
67
+ console.log(chalk.magenta.bold("━".repeat(60)));
68
+ console.log(chalk.magenta.bold("📝 How to Get Test Tokens:"));
69
+ console.log(chalk.magenta.bold("━".repeat(60)));
70
+ console.log();
71
+ console.log(chalk.white(" 1. ") + chalk.cyan("Visit: ") + chalk.underline("https://midnight.network/test-faucet"));
72
+ console.log(chalk.white(" 2. ") + chalk.cyan("Paste your wallet address (shown above)"));
73
+ console.log(chalk.white(" 3. ") + chalk.cyan("Request tokens from the faucet"));
74
+ console.log(chalk.white(" 4. ") + chalk.cyan("Wait 2-5 minutes for processing"));
75
+ console.log(chalk.white(" 5. ") + chalk.cyan("Run ") + chalk.yellow.bold("'npm run check-balance'") + chalk.cyan(" again"));
76
+ console.log();
77
+ console.log(chalk.gray("━".repeat(60)));
78
+ console.log(chalk.gray("💡 Tip: Faucet transactions typically take 2-5 minutes to process."));
79
+ console.log(chalk.gray("━".repeat(60)));
80
+ } else {
81
+ console.log(chalk.yellow.bold("💰 Balance: ") + chalk.green.bold(`${balance} DUST`));
82
+ console.log();
83
+ console.log(chalk.green.bold("✅ Wallet is funded and ready!"));
84
+ console.log();
85
+ console.log(chalk.magenta.bold("━".repeat(60)));
86
+ console.log(chalk.magenta.bold("🚀 Next Step:"));
87
+ console.log(chalk.magenta.bold("━".repeat(60)));
88
+ console.log();
89
+ console.log(chalk.cyan(" Deploy your contract with:"));
90
+ console.log(chalk.yellow.bold(" npm run deploy"));
91
+ console.log();
92
+ console.log(chalk.gray("━".repeat(60)));
93
+ }
94
+
95
+ console.log();
96
+ wallet.close();
97
+ process.exit(0);
98
+ } catch (error) {
99
+ console.log();
100
+ console.log(chalk.red.bold("❌ Error checking balance:"));
101
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
102
+ console.log();
103
+ process.exit(1);
104
+ }
105
+ }
106
+
107
+ checkBalance();
@@ -0,0 +1,194 @@
1
+ import "dotenv/config";
2
+ import * as readline from "readline/promises";
3
+ import { WalletBuilder } from "@midnight-ntwrk/wallet";
4
+ import { findDeployedContract } from "@midnight-ntwrk/midnight-js-contracts";
5
+ import {
6
+ NetworkId,
7
+ setNetworkId,
8
+ getZswapNetworkId,
9
+ getLedgerNetworkId,
10
+ } from "@midnight-ntwrk/midnight-js-network-id";
11
+ import { createBalancedTx } from "@midnight-ntwrk/midnight-js-types";
12
+ import { Transaction } from "@midnight-ntwrk/ledger";
13
+ import { Transaction as ZswapTransaction } from "@midnight-ntwrk/zswap";
14
+ import { WebSocket } from "ws";
15
+ import * as path from "path";
16
+ import * as fs from "fs";
17
+ import * as Rx from "rxjs";
18
+ import { MidnightProviders } from "./providers/midnight-providers.js";
19
+ import { EnvironmentManager } from "./utils/environment.js";
20
+
21
+ // Fix WebSocket for Node.js environment
22
+ // @ts-ignore
23
+ globalThis.WebSocket = WebSocket;
24
+
25
+ // Configure for Midnight Testnet
26
+ setNetworkId(NetworkId.TestNet);
27
+
28
+ async function main() {
29
+ const rl = readline.createInterface({
30
+ input: process.stdin,
31
+ output: process.stdout,
32
+ });
33
+
34
+ console.log("🌙 {{projectName}} CLI\n");
35
+
36
+ try {
37
+ // Validate environment
38
+ EnvironmentManager.validateEnvironment();
39
+
40
+ // Check for deployment file
41
+ if (!fs.existsSync("deployment.json")) {
42
+ console.error("❌ No deployment.json found! Run npm run deploy first.");
43
+ process.exit(1);
44
+ }
45
+
46
+ const deployment = JSON.parse(fs.readFileSync("deployment.json", "utf-8"));
47
+ console.log(`Contract: ${deployment.contractAddress}\n`);
48
+
49
+ const networkConfig = EnvironmentManager.getNetworkConfig();
50
+ const contractName =
51
+ deployment.contractName || process.env.CONTRACT_NAME || "hello-world";
52
+ const walletSeed = process.env.WALLET_SEED!;
53
+
54
+ console.log("Connecting to Midnight network...");
55
+
56
+ // Build wallet
57
+ const wallet = await WalletBuilder.buildFromSeed(
58
+ networkConfig.indexer,
59
+ networkConfig.indexerWS,
60
+ networkConfig.proofServer,
61
+ networkConfig.node,
62
+ walletSeed,
63
+ getZswapNetworkId(),
64
+ "info"
65
+ );
66
+
67
+ wallet.start();
68
+
69
+ // Wait for sync
70
+ await Rx.firstValueFrom(
71
+ wallet.state().pipe(Rx.filter((s) => s.syncProgress?.synced === true))
72
+ );
73
+
74
+ // Load contract
75
+ const contractPath = path.join(process.cwd(), "contracts");
76
+ const contractModulePath = path.join(
77
+ contractPath,
78
+ "managed",
79
+ contractName,
80
+ "contract",
81
+ "index.cjs"
82
+ );
83
+ const HelloWorldModule = await import(contractModulePath);
84
+ const contractInstance = new HelloWorldModule.Contract({});
85
+
86
+ // Create wallet provider
87
+ const walletState = await Rx.firstValueFrom(wallet.state());
88
+
89
+ const walletProvider = {
90
+ coinPublicKey: walletState.coinPublicKey,
91
+ encryptionPublicKey: walletState.encryptionPublicKey,
92
+ balanceTx(tx: any, newCoins: any) {
93
+ return wallet
94
+ .balanceTransaction(
95
+ ZswapTransaction.deserialize(
96
+ tx.serialize(getLedgerNetworkId()),
97
+ getZswapNetworkId()
98
+ ),
99
+ newCoins
100
+ )
101
+ .then((tx) => wallet.proveTransaction(tx))
102
+ .then((zswapTx) =>
103
+ Transaction.deserialize(
104
+ zswapTx.serialize(getZswapNetworkId()),
105
+ getLedgerNetworkId()
106
+ )
107
+ )
108
+ .then(createBalancedTx);
109
+ },
110
+ submitTx(tx: any) {
111
+ return wallet.submitTransaction(tx);
112
+ },
113
+ };
114
+
115
+ // Configure providers
116
+ const providers = MidnightProviders.create({
117
+ contractName,
118
+ walletProvider,
119
+ networkConfig,
120
+ });
121
+
122
+ // Connect to contract
123
+ const deployed: any = await findDeployedContract(providers, {
124
+ contractAddress: deployment.contractAddress,
125
+ contract: contractInstance,
126
+ privateStateId: "helloWorldState",
127
+ initialPrivateState: {},
128
+ });
129
+
130
+ console.log("✅ Connected to contract\n");
131
+
132
+ // Main menu loop
133
+ let running = true;
134
+ while (running) {
135
+ console.log("--- Menu ---");
136
+ console.log("1. Store message");
137
+ console.log("2. Read current message");
138
+ console.log("3. Exit");
139
+
140
+ const choice = await rl.question("\nYour choice: ");
141
+
142
+ switch (choice) {
143
+ case "1":
144
+ console.log("\nStoring custom message...");
145
+ const customMessage = await rl.question("Enter your message: ");
146
+ try {
147
+ const tx = await deployed.callTx.storeMessage(customMessage);
148
+ console.log("✅ Success!");
149
+ console.log(`Message: "${customMessage}"`);
150
+ console.log(`Transaction ID: ${tx.public.txId}`);
151
+ console.log(`Block height: ${tx.public.blockHeight}\n`);
152
+ } catch (error) {
153
+ console.error("❌ Failed to store message:", error);
154
+ }
155
+ break;
156
+
157
+ case "2":
158
+ console.log("\nReading message from blockchain...");
159
+ try {
160
+ const state = await providers.publicDataProvider.queryContractState(
161
+ deployment.contractAddress
162
+ );
163
+ if (state) {
164
+ const ledger = HelloWorldModule.ledger(state.data);
165
+ const message = Buffer.from(ledger.message).toString();
166
+ console.log(`📋 Current message: "${message}"\n`);
167
+ } else {
168
+ console.log("📋 No message found\n");
169
+ }
170
+ } catch (error) {
171
+ console.error("❌ Failed to read message:", error);
172
+ }
173
+ break;
174
+
175
+ case "3":
176
+ running = false;
177
+ console.log("\n👋 Goodbye!");
178
+ break;
179
+
180
+ default:
181
+ console.log("❌ Invalid choice. Please enter 1, 2, or 3.\n");
182
+ }
183
+ }
184
+
185
+ // Clean up
186
+ await wallet.close();
187
+ } catch (error) {
188
+ console.error("\n❌ Error:", error);
189
+ } finally {
190
+ rl.close();
191
+ }
192
+ }
193
+
194
+ main().catch(console.error);
@@ -0,0 +1,218 @@
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
+ NetworkId,
10
+ setNetworkId,
11
+ getZswapNetworkId,
12
+ getLedgerNetworkId,
13
+ } from "@midnight-ntwrk/midnight-js-network-id";
14
+ import { createBalancedTx } from "@midnight-ntwrk/midnight-js-types";
15
+ import { nativeToken, Transaction } from "@midnight-ntwrk/ledger";
16
+ import { Transaction as ZswapTransaction } from "@midnight-ntwrk/zswap";
17
+ import { WebSocket } from "ws";
18
+ import * as fs from "fs";
19
+ import * as path from "path";
20
+ import * as Rx from "rxjs";
21
+ import { type Wallet } from "@midnight-ntwrk/wallet-api";
22
+ import chalk from "chalk";
23
+ import { MidnightProviders } from "./providers/midnight-providers.js";
24
+ import { EnvironmentManager } from "./utils/environment.js";
25
+
26
+ // Fix WebSocket for Node.js environment
27
+ // @ts-ignore
28
+ globalThis.WebSocket = WebSocket;
29
+
30
+ // Configure for Midnight Testnet
31
+ setNetworkId(NetworkId.TestNet);
32
+
33
+ const waitForFunds = (wallet: Wallet) =>
34
+ Rx.firstValueFrom(
35
+ wallet.state().pipe(
36
+ Rx.tap((state) => {
37
+ if (state.syncProgress) {
38
+ console.log(
39
+ `Sync progress: synced=${state.syncProgress.synced}, sourceGap=${state.syncProgress.lag.sourceGap}, applyGap=${state.syncProgress.lag.applyGap}`
40
+ );
41
+ }
42
+ }),
43
+ Rx.filter((state) => state.syncProgress?.synced === true),
44
+ Rx.map((s) => s.balances[nativeToken()] ?? 0n),
45
+ Rx.filter((balance) => balance > 0n),
46
+ Rx.tap((balance) => console.log(`Wallet funded with balance: ${balance}`))
47
+ )
48
+ );
49
+
50
+ async function main() {
51
+ console.log();
52
+ console.log(chalk.blue.bold("━".repeat(60)));
53
+ console.log(chalk.blue.bold("🌙 {{projectName}} Deployment"));
54
+ console.log(chalk.blue.bold("━".repeat(60)));
55
+ console.log();
56
+
57
+ try {
58
+ // Validate environment
59
+ EnvironmentManager.validateEnvironment();
60
+
61
+ const networkConfig = EnvironmentManager.getNetworkConfig();
62
+ const contractName = process.env.CONTRACT_NAME || "hello-world";
63
+
64
+ // Check if contract is compiled
65
+ if (!EnvironmentManager.checkContractCompiled(contractName)) {
66
+ console.error("❌ Contract not compiled! Run: npm run compile");
67
+ process.exit(1);
68
+ }
69
+
70
+ const walletSeed = process.env.WALLET_SEED!;
71
+
72
+ // Build wallet from seed
73
+ console.log("Building wallet...");
74
+ const wallet = await WalletBuilder.buildFromSeed(
75
+ networkConfig.indexer,
76
+ networkConfig.indexerWS,
77
+ networkConfig.proofServer,
78
+ networkConfig.node,
79
+ walletSeed,
80
+ getZswapNetworkId(),
81
+ "info"
82
+ );
83
+
84
+ wallet.start();
85
+ const state = await Rx.firstValueFrom(wallet.state());
86
+
87
+ console.log(chalk.cyan.bold("📍 Wallet Address:"));
88
+ console.log(chalk.white(` ${state.address}`));
89
+ console.log();
90
+
91
+ let balance = state.balances[nativeToken()] || 0n;
92
+
93
+ if (balance === 0n) {
94
+ console.log(chalk.yellow.bold("💰 Balance: ") + chalk.red.bold("0 DUST"));
95
+ console.log();
96
+ console.log(chalk.red.bold("❌ Wallet needs funding to deploy contracts."));
97
+ console.log();
98
+ console.log(chalk.magenta.bold("━".repeat(60)));
99
+ console.log(chalk.magenta.bold("📝 How to Get Test Tokens:"));
100
+ console.log(chalk.magenta.bold("━".repeat(60)));
101
+ console.log();
102
+ console.log(chalk.white(" 1. ") + chalk.cyan("Visit: ") + chalk.underline("https://midnight.network/test-faucet"));
103
+ console.log(chalk.white(" 2. ") + chalk.cyan("Paste your wallet address (shown above)"));
104
+ console.log(chalk.white(" 3. ") + chalk.cyan("Request tokens from the faucet"));
105
+ console.log();
106
+ console.log(chalk.gray("━".repeat(60)));
107
+ console.log(chalk.gray("⏱️ Faucet transactions can take 2-5 minutes to process."));
108
+ console.log(chalk.gray("━".repeat(60)));
109
+ console.log();
110
+ console.log(chalk.yellow.bold("💡 Options while waiting:"));
111
+ console.log(chalk.white(" • ") + chalk.cyan("Let this script wait (it will auto-detect when funds arrive)"));
112
+ console.log(chalk.white(" • ") + chalk.cyan("OR press ") + chalk.yellow("Ctrl+C") + chalk.cyan(" to stop, then check balance with:"));
113
+ console.log(chalk.yellow.bold(" npm run check-balance"));
114
+ console.log(chalk.white(" • ") + chalk.cyan("Once funded, run: ") + chalk.yellow.bold("npm run deploy"));
115
+ console.log();
116
+ console.log(chalk.blue("⏳ Waiting to receive tokens..."));
117
+ balance = await waitForFunds(wallet);
118
+ }
119
+
120
+ console.log(chalk.yellow.bold("💰 Balance: ") + chalk.green.bold(`${balance} DUST`));
121
+ console.log();
122
+
123
+ // Load compiled contract files
124
+ console.log(chalk.gray("📦 Loading contract..."));
125
+ const contractPath = path.join(process.cwd(), "contracts");
126
+ const contractModulePath = path.join(
127
+ contractPath,
128
+ "managed",
129
+ contractName,
130
+ "contract",
131
+ "index.cjs"
132
+ );
133
+
134
+ const HelloWorldModule = await import(contractModulePath);
135
+ const contractInstance = new HelloWorldModule.Contract({});
136
+
137
+ // Create wallet provider for transactions
138
+ const walletState = await Rx.firstValueFrom(wallet.state());
139
+
140
+ const walletProvider = {
141
+ coinPublicKey: walletState.coinPublicKey,
142
+ encryptionPublicKey: walletState.encryptionPublicKey,
143
+ balanceTx(tx: any, newCoins: any) {
144
+ return wallet
145
+ .balanceTransaction(
146
+ ZswapTransaction.deserialize(
147
+ tx.serialize(getLedgerNetworkId()),
148
+ getZswapNetworkId()
149
+ ),
150
+ newCoins
151
+ )
152
+ .then((tx) => wallet.proveTransaction(tx))
153
+ .then((zswapTx) =>
154
+ Transaction.deserialize(
155
+ zswapTx.serialize(getZswapNetworkId()),
156
+ getLedgerNetworkId()
157
+ )
158
+ )
159
+ .then(createBalancedTx);
160
+ },
161
+ submitTx(tx: any) {
162
+ return wallet.submitTransaction(tx);
163
+ },
164
+ };
165
+
166
+ // Configure all required providers
167
+ console.log("Setting up providers...");
168
+ const providers = MidnightProviders.create({
169
+ contractName,
170
+ walletProvider,
171
+ networkConfig,
172
+ });
173
+
174
+ // Deploy contract to blockchain
175
+ console.log(chalk.blue("🚀 Deploying contract (30-60 seconds)..."));
176
+ console.log();
177
+
178
+ const deployed = await deployContract(providers, {
179
+ contract: contractInstance,
180
+ privateStateId: "helloWorldState",
181
+ initialPrivateState: {},
182
+ });
183
+
184
+ const contractAddress = deployed.deployTxData.public.contractAddress;
185
+
186
+ // Save deployment information
187
+ console.log();
188
+ console.log(chalk.green.bold("━".repeat(60)));
189
+ console.log(chalk.green.bold("🎉 CONTRACT DEPLOYED SUCCESSFULLY!"));
190
+ console.log(chalk.green.bold("━".repeat(60)));
191
+ console.log();
192
+ console.log(chalk.cyan.bold("📍 Contract Address:"));
193
+ console.log(chalk.white(` ${contractAddress}`));
194
+ console.log();
195
+
196
+ const info = {
197
+ contractAddress,
198
+ deployedAt: new Date().toISOString(),
199
+ network: networkConfig.name,
200
+ contractName,
201
+ };
202
+
203
+ fs.writeFileSync("deployment.json", JSON.stringify(info, null, 2));
204
+ console.log(chalk.gray("✅ Saved to deployment.json"));
205
+ console.log();
206
+
207
+ // Close wallet connection
208
+ await wallet.close();
209
+ } catch (error) {
210
+ console.log();
211
+ console.log(chalk.red.bold("❌ Deployment Failed:"));
212
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
213
+ console.log();
214
+ process.exit(1);
215
+ }
216
+ }
217
+
218
+ main().catch(console.error);
@@ -0,0 +1,46 @@
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
+ export interface NetworkConfig {
8
+ indexer: string;
9
+ indexerWS: string;
10
+ node: string;
11
+ proofServer: string;
12
+ name: string;
13
+ }
14
+
15
+ export interface ProviderConfig {
16
+ contractName: string;
17
+ walletProvider: any;
18
+ networkConfig: NetworkConfig;
19
+ privateStateStoreName?: string;
20
+ }
21
+
22
+ export class MidnightProviders {
23
+ static create(config: ProviderConfig) {
24
+ const contractPath = path.join(process.cwd(), "contracts");
25
+ const zkConfigPath = path.join(
26
+ contractPath,
27
+ "managed",
28
+ config.contractName
29
+ );
30
+
31
+ return {
32
+ privateStateProvider: levelPrivateStateProvider({
33
+ privateStateStoreName:
34
+ config.privateStateStoreName || `${config.contractName}-state`,
35
+ }),
36
+ publicDataProvider: indexerPublicDataProvider(
37
+ config.networkConfig.indexer,
38
+ config.networkConfig.indexerWS
39
+ ),
40
+ zkConfigProvider: new NodeZkConfigProvider(zkConfigPath),
41
+ proofProvider: httpClientProofProvider(config.networkConfig.proofServer),
42
+ walletProvider: config.walletProvider,
43
+ midnightProvider: config.walletProvider,
44
+ };
45
+ }
46
+ }
@@ -0,0 +1,51 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { NetworkConfig } from "../providers/midnight-providers.js";
4
+
5
+ export class EnvironmentManager {
6
+ static getNetworkConfig(): NetworkConfig {
7
+ const network = process.env.MIDNIGHT_NETWORK || "testnet";
8
+
9
+ const networks = {
10
+ testnet: {
11
+ indexer: "https://indexer.testnet-02.midnight.network/api/v1/graphql",
12
+ indexerWS:
13
+ "wss://indexer.testnet-02.midnight.network/api/v1/graphql/ws",
14
+ node: "https://rpc.testnet-02.midnight.network",
15
+ proofServer: process.env.PROOF_SERVER_URL || "http://127.0.0.1:6300",
16
+ name: "Testnet",
17
+ },
18
+ };
19
+
20
+ return networks[network as keyof typeof networks] || networks.testnet;
21
+ }
22
+
23
+ static validateEnvironment(): void {
24
+ const required = ["WALLET_SEED"];
25
+ const missing = required.filter((key) => !process.env[key]);
26
+
27
+ if (missing.length > 0) {
28
+ throw new Error(
29
+ `Missing required environment variables: ${missing.join(", ")}`
30
+ );
31
+ }
32
+
33
+ const walletSeed = process.env.WALLET_SEED!;
34
+ if (!/^[a-fA-F0-9]{64}$/.test(walletSeed)) {
35
+ throw new Error("WALLET_SEED must be a 64-character hexadecimal string");
36
+ }
37
+ }
38
+
39
+ static checkContractCompiled(contractName: string): boolean {
40
+ const contractPath = path.join(
41
+ process.cwd(),
42
+ "contracts",
43
+ "managed",
44
+ contractName
45
+ );
46
+ const keysPath = path.join(contractPath, "keys");
47
+ const contractModulePath = path.join(contractPath, "contract", "index.cjs");
48
+
49
+ return fs.existsSync(keysPath) && fs.existsSync(contractModulePath);
50
+ }
51
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "allowSyntheticDefaultImports": true,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true
17
+ },
18
+ "include": ["src/**/*"],
19
+ "exclude": ["node_modules", "dist", "contracts/managed"]
20
+ }