create-mn-app 1.0.0

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 (50) hide show
  1. package/README.md +45 -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 +169 -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 +100 -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 +49 -0
  46. package/templates/hello-world/src/cli.ts.template +194 -0
  47. package/templates/hello-world/src/deploy.ts.template +181 -0
  48. package/templates/hello-world/src/providers/midnight-providers.ts.template +46 -0
  49. package/templates/hello-world/src/utils/environment.ts.template +51 -0
  50. package/templates/hello-world/tsconfig.json.template +20 -0
@@ -0,0 +1,181 @@
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 { MidnightProviders } from "./providers/midnight-providers";
23
+ import { EnvironmentManager } from "./utils/environment";
24
+
25
+ // Fix WebSocket for Node.js environment
26
+ // @ts-ignore
27
+ globalThis.WebSocket = WebSocket;
28
+
29
+ // Configure for Midnight Testnet
30
+ setNetworkId(NetworkId.TestNet);
31
+
32
+ const waitForFunds = (wallet: Wallet) =>
33
+ Rx.firstValueFrom(
34
+ wallet.state().pipe(
35
+ Rx.tap((state) => {
36
+ if (state.syncProgress) {
37
+ console.log(
38
+ `Sync progress: synced=${state.syncProgress.synced}, sourceGap=${state.syncProgress.lag.sourceGap}, applyGap=${state.syncProgress.lag.applyGap}`
39
+ );
40
+ }
41
+ }),
42
+ Rx.filter((state) => state.syncProgress?.synced === true),
43
+ Rx.map((s) => s.balances[nativeToken()] ?? 0n),
44
+ Rx.filter((balance) => balance > 0n),
45
+ Rx.tap((balance) => console.log(`Wallet funded with balance: ${balance}`))
46
+ )
47
+ );
48
+
49
+ async function main() {
50
+ console.log("šŸŒ™ {{projectName}} Deployment\n");
51
+
52
+ try {
53
+ // Validate environment
54
+ EnvironmentManager.validateEnvironment();
55
+
56
+ const networkConfig = EnvironmentManager.getNetworkConfig();
57
+ const contractName = process.env.CONTRACT_NAME || "hello-world";
58
+
59
+ // Check if contract is compiled
60
+ if (!EnvironmentManager.checkContractCompiled(contractName)) {
61
+ console.error("āŒ Contract not compiled! Run: npm run compile");
62
+ process.exit(1);
63
+ }
64
+
65
+ const walletSeed = process.env.WALLET_SEED!;
66
+
67
+ // Build wallet from seed
68
+ console.log("Building wallet...");
69
+ const wallet = await WalletBuilder.buildFromSeed(
70
+ networkConfig.indexer,
71
+ networkConfig.indexerWS,
72
+ networkConfig.proofServer,
73
+ networkConfig.node,
74
+ walletSeed,
75
+ getZswapNetworkId(),
76
+ "info"
77
+ );
78
+
79
+ wallet.start();
80
+ const state = await Rx.firstValueFrom(wallet.state());
81
+
82
+ console.log(`Your wallet address is: ${state.address}`);
83
+
84
+ let balance = state.balances[nativeToken()] || 0n;
85
+
86
+ if (balance === 0n) {
87
+ console.log(`Your wallet balance is: 0`);
88
+ console.log(
89
+ "Visit: https://midnight.network/test-faucet to get some funds."
90
+ );
91
+ console.log(`Waiting to receive tokens...`);
92
+ balance = await waitForFunds(wallet);
93
+ }
94
+
95
+ console.log(`Balance: ${balance}`);
96
+
97
+ // Load compiled contract files
98
+ console.log("Loading contract...");
99
+ const contractPath = path.join(process.cwd(), "contracts");
100
+ const contractModulePath = path.join(
101
+ contractPath,
102
+ "managed",
103
+ contractName,
104
+ "contract",
105
+ "index.cjs"
106
+ );
107
+
108
+ const HelloWorldModule = await import(contractModulePath);
109
+ const contractInstance = new HelloWorldModule.Contract({});
110
+
111
+ // Create wallet provider for transactions
112
+ const walletState = await Rx.firstValueFrom(wallet.state());
113
+
114
+ const walletProvider = {
115
+ coinPublicKey: walletState.coinPublicKey,
116
+ encryptionPublicKey: walletState.encryptionPublicKey,
117
+ balanceTx(tx: any, newCoins: any) {
118
+ return wallet
119
+ .balanceTransaction(
120
+ ZswapTransaction.deserialize(
121
+ tx.serialize(getLedgerNetworkId()),
122
+ getZswapNetworkId()
123
+ ),
124
+ newCoins
125
+ )
126
+ .then((tx) => wallet.proveTransaction(tx))
127
+ .then((zswapTx) =>
128
+ Transaction.deserialize(
129
+ zswapTx.serialize(getZswapNetworkId()),
130
+ getLedgerNetworkId()
131
+ )
132
+ )
133
+ .then(createBalancedTx);
134
+ },
135
+ submitTx(tx: any) {
136
+ return wallet.submitTransaction(tx);
137
+ },
138
+ };
139
+
140
+ // Configure all required providers
141
+ console.log("Setting up providers...");
142
+ const providers = MidnightProviders.create({
143
+ contractName,
144
+ walletProvider,
145
+ networkConfig,
146
+ });
147
+
148
+ // Deploy contract to blockchain
149
+ console.log("Deploying contract (30-60 seconds)...");
150
+
151
+ const deployed = await deployContract(providers, {
152
+ contract: contractInstance,
153
+ privateStateId: "helloWorldState",
154
+ initialPrivateState: {},
155
+ });
156
+
157
+ const contractAddress = deployed.deployTxData.public.contractAddress;
158
+
159
+ // Save deployment information
160
+ console.log("\nšŸŽ‰ DEPLOYED!");
161
+ console.log(`Contract: ${contractAddress}\n`);
162
+
163
+ const info = {
164
+ contractAddress,
165
+ deployedAt: new Date().toISOString(),
166
+ network: networkConfig.name,
167
+ contractName,
168
+ };
169
+
170
+ fs.writeFileSync("deployment.json", JSON.stringify(info, null, 2));
171
+ console.log("āœ… Saved to deployment.json");
172
+
173
+ // Close wallet connection
174
+ await wallet.close();
175
+ } catch (error) {
176
+ console.error("āŒ Failed:", error);
177
+ process.exit(1);
178
+ }
179
+ }
180
+
181
+ 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";
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
+ }