diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index a27d6e290..4b65b17cd 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -273,3 +273,18 @@ jobs:
- run: cd packages/midnight-setup && npm publish --access public
env:
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
+
+ publish-meshsdk-midnight-contracts-wizard:
+ needs: [build, check-version]
+ if: needs.check-version.outputs.version-updated == 'true'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ registry-url: https://registry.npmjs.org/
+ - run: npm install && npm run build
+ - run: cd packages/midnight-contracts-wizard && npm publish --access public
+ env:
+ NODE_AUTH_TOKEN: ${{secrets.npm_token}}
diff --git a/README.md b/README.md
index 02ac137cc..7d029f574 100644
--- a/README.md
+++ b/README.md
@@ -85,18 +85,19 @@ graph TD
A collection of packages that provide different functionalities to interact with the Cardano blockchain.
-| | Description | Docs | Playground |
-| ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------- |
-| [@meshsdk/common](https://github.com/MeshJS/mesh/tree/main/packages/mesh-common) | Contains constants, types and interfaces used across the SDK and different serialization libraries | [:page_facing_up:](https://docs.meshjs.dev/common) | |
-| [@meshsdk/contract](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract) | A collection of smart contracts and its transactions | [:page_facing_up:](https://docs.meshjs.dev/contracts) | [:shipit:](https://meshjs.dev/smart-contracts) |
-| [@meshsdk/core](https://github.com/MeshJS/mesh/tree/main/packages/mesh-core) | Exports all the functionalities including wallets, transactions, and providers | | [:shipit:](https://meshjs.dev/) |
-| [@meshsdk/core-csl](https://github.com/MeshJS/mesh/tree/main/packages/mesh-core-csl) | Types and utilities functions between Mesh and cardano-serialization-lib | [:page_facing_up:](https://docs.meshjs.dev/core-csl) | |
-| [@meshsdk/core-cst](https://github.com/MeshJS/mesh/tree/main/packages/mesh-core-cst) | Types and utilities functions between Mesh and cardano-js-sdk | [:page_facing_up:](https://docs.meshjs.dev/core-cst) | |
-| [@meshsdk/provider](https://github.com/MeshJS/mesh/tree/main/packages/mesh-provider) | Blockchain data providers | [:page_facing_up:](https://docs.meshjs.dev/providers) | [:shipit:](https://meshjs.dev/providers) |
-| [@meshsdk/react](https://github.com/MeshJS/mesh/tree/main/packages/mesh-react) | React component library | | [:shipit:](https://meshjs.dev/react) |
-| [@meshsdk/transaction](https://github.com/MeshJS/mesh/tree/main/packages/mesh-transaction) | Transactions to send assets, mint tokens, and interact with smart contracts | [:page_facing_up:](https://docs.meshjs.dev/transactions) | [:shipit:](https://meshjs.dev/apis/transaction) |
-| [@meshsdk/wallet](https://github.com/MeshJS/mesh/tree/main/packages/mesh-wallet) | Wallets to manage assets and interact with the blockchain | [:page_facing_up:](https://docs.meshjs.dev/wallets) | [:shipit:](https://meshjs.dev/apis/wallets) |
-| [@meshsdk/midnight-setup](https://github.com/MeshJS/mesh/tree/main/packages/midnight-setup) | Complete development setup for building Midnight Network dApps | [:page_facing_up:](https://midnight.meshjs.dev/en/packages/midnight_setup) | [:shipit:](https://github.com/MeshJS/midnight-setup) |
+| | Description | Docs | Playground |
+| ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
+| [@meshsdk/common](https://github.com/MeshJS/mesh/tree/main/packages/mesh-common) | Contains constants, types and interfaces used across the SDK and different serialization libraries | [:page_facing_up:](https://docs.meshjs.dev/common) | |
+| [@meshsdk/contract](https://github.com/MeshJS/mesh/tree/main/packages/mesh-contract) | A collection of smart contracts and its transactions | [:page_facing_up:](https://docs.meshjs.dev/contracts) | [:shipit:](https://meshjs.dev/smart-contracts) |
+| [@meshsdk/core](https://github.com/MeshJS/mesh/tree/main/packages/mesh-core) | Exports all the functionalities including wallets, transactions, and providers | | [:shipit:](https://meshjs.dev/) |
+| [@meshsdk/core-csl](https://github.com/MeshJS/mesh/tree/main/packages/mesh-core-csl) | Types and utilities functions between Mesh and cardano-serialization-lib | [:page_facing_up:](https://docs.meshjs.dev/core-csl) | |
+| [@meshsdk/core-cst](https://github.com/MeshJS/mesh/tree/main/packages/mesh-core-cst) | Types and utilities functions between Mesh and cardano-js-sdk | [:page_facing_up:](https://docs.meshjs.dev/core-cst) | |
+| [@meshsdk/provider](https://github.com/MeshJS/mesh/tree/main/packages/mesh-provider) | Blockchain data providers | [:page_facing_up:](https://docs.meshjs.dev/providers) | [:shipit:](https://meshjs.dev/providers) |
+| [@meshsdk/react](https://github.com/MeshJS/mesh/tree/main/packages/mesh-react) | React component library | | [:shipit:](https://meshjs.dev/react) |
+| [@meshsdk/transaction](https://github.com/MeshJS/mesh/tree/main/packages/mesh-transaction) | Transactions to send assets, mint tokens, and interact with smart contracts | [:page_facing_up:](https://docs.meshjs.dev/transactions) | [:shipit:](https://meshjs.dev/apis/transaction) |
+| [@meshsdk/wallet](https://github.com/MeshJS/mesh/tree/main/packages/mesh-wallet) | Wallets to manage assets and interact with the blockchain | [:page_facing_up:](https://docs.meshjs.dev/wallets) | [:shipit:](https://meshjs.dev/apis/wallets) |
+| [@meshsdk/midnight-setup](https://github.com/MeshJS/mesh/tree/main/packages/midnight-setup) | Complete development setup for building Midnight Network dApps | [:page_facing_up:](https://midnight.meshjs.dev/en/packages/midnight_setup) | [:shipit:](https://github.com/MeshJS/midnight-setup) |
+| [@meshsdk/midnight-contracts-wizard](https://github.com/MeshJS/mesh/tree/main/packages/midnight-contracts-wizard) | CLI wizard to create new Midnight contracts projects with pre-built smart contracts | [:page_facing_up:](https://midnight.meshjs.dev/en/packages/midnight_contracts_wizard) | [:shipit:](https://www.npmjs.com/package/@meshsdk/midnight-contracts-wizard) |
### Apps
diff --git a/package-lock.json b/package-lock.json
index 88fefead5..045a39bf5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,6 +19,7 @@
},
"devDependencies": {
"@meshsdk/configs": "*",
+ "@types/fs-extra": "^11.0.4",
"@types/jest": "^29.5.12",
"dotenv": "^16.4.5",
"jest": "^29.7.0",
@@ -12044,6 +12045,36 @@
}
}
},
+ "node_modules/@inquirer/external-editor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz",
+ "integrity": "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==",
+ "license": "MIT",
+ "dependencies": {
+ "chardet": "^2.1.0",
+ "iconv-lite": "^0.7.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inquirer/figures": {
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.14.tgz",
+ "integrity": "sha512-DbFgdt+9/OZYFM+19dbpXOSeAstPy884FPy1KjDu4anWwymZeOYhMY1mdFri172htv6mvc/uvIAAi7b7tvjJBQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@internationalized/date": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.10.0.tgz",
@@ -12840,6 +12871,10 @@
"resolved": "packages/mesh-hydra",
"link": true
},
+ "node_modules/@meshsdk/midnight-contracts-wizard": {
+ "resolved": "packages/midnight-contracts-wizard",
+ "link": true
+ },
"node_modules/@meshsdk/midnight-setup": {
"resolved": "packages/midnight-setup",
"link": true
@@ -16107,6 +16142,17 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/fs-extra": {
+ "version": "11.0.4",
+ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz",
+ "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/jsonfile": "*",
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/got": {
"version": "9.6.12",
"resolved": "https://registry.npmjs.org/@types/got/-/got-9.6.12.tgz",
@@ -16144,6 +16190,17 @@
"integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
"license": "MIT"
},
+ "node_modules/@types/inquirer": {
+ "version": "9.0.9",
+ "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.9.tgz",
+ "integrity": "sha512-/mWx5136gts2Z2e5izdoRCo46lPp5TMs9R15GTSsgg/XnZyxDWVqoVU3R9lWnccKpqwsJLvRoxbCjoJtZB7DSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/through": "*",
+ "rxjs": "^7.2.0"
+ }
+ },
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
@@ -16200,6 +16257,16 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"license": "MIT"
},
+ "node_modules/@types/jsonfile": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz",
+ "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/mdast": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
@@ -16347,6 +16414,16 @@
"minipass": "^4.0.0"
}
},
+ "node_modules/@types/through": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz",
+ "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/tough-cookie": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
@@ -17165,7 +17242,6 @@
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
"integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"type-fest": "^0.21.3"
@@ -17181,7 +17257,6 @@
"version": "0.21.3",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
"integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
- "dev": true,
"license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=10"
@@ -19161,6 +19236,12 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/chardet": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz",
+ "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==",
+ "license": "MIT"
+ },
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
@@ -19366,6 +19447,39 @@
"node": ">=0.8.0"
}
},
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+ "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
+ "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
@@ -19427,6 +19541,15 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
@@ -20324,6 +20447,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/defer-to-connect": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
@@ -23721,6 +23856,22 @@
"node": ">=0.4"
}
},
+ "node_modules/iconv-lite": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz",
+ "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -23887,6 +24038,63 @@
"integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==",
"license": "MIT"
},
+ "node_modules/inquirer": {
+ "version": "9.3.8",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.8.tgz",
+ "integrity": "sha512-pFGGdaHrmRKMh4WoDDSowddgjT1Vkl90atobmTeSmcPGdYiwikch/m/Ef5wRaiamHejtw0cUUMMerzDUXCci2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/external-editor": "^1.0.2",
+ "@inquirer/figures": "^1.0.3",
+ "ansi-escapes": "^4.3.2",
+ "cli-width": "^4.1.0",
+ "mute-stream": "1.0.0",
+ "ora": "^5.4.1",
+ "run-async": "^3.0.0",
+ "rxjs": "^7.8.1",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^6.2.0",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/inquirer/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/inquirer/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inquirer/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/internal-slot": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
@@ -24305,6 +24513,15 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-map": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
@@ -24512,6 +24729,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-weakmap": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
@@ -25571,7 +25800,6 @@
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
@@ -25969,6 +26197,22 @@
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
"license": "MIT"
},
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/long": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
@@ -27125,7 +27369,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -27327,6 +27570,15 @@
"integrity": "sha512-VqO6OSvLrFVAYYjgsr8tyv62/rCQhPgsZUXLTqoFLSgdkgiUYKYeArbt1uWLlEpkjxQe+P0+sHlbPEte1Bi06Q==",
"license": "Apache-2.0 OR MIT"
},
+ "node_modules/mute-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
+ "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
"node_modules/mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
@@ -30486,7 +30738,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"mimic-fn": "^2.1.0"
@@ -30557,6 +30808,29 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/os-browserify": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
@@ -32751,6 +33025,25 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "license": "ISC"
+ },
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
@@ -32827,6 +33120,15 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/run-async": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
+ "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -33011,6 +33313,12 @@
"node": ">=10"
}
},
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
"node_modules/satori": {
"version": "0.12.2",
"resolved": "https://registry.npmjs.org/satori/-/satori-0.12.2.tgz",
@@ -35828,7 +36136,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
@@ -36882,6 +37189,15 @@
"makeerror": "1.0.12"
}
},
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "license": "MIT",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
"node_modules/web-encoding": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz",
@@ -37468,6 +37784,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/yoctocolors-cjs": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz",
+ "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/yoga-wasm-web": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/yoga-wasm-web/-/yoga-wasm-web-0.3.3.tgz",
@@ -37547,7 +37875,7 @@
},
"packages/bitcoin": {
"name": "@meshsdk/bitcoin",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"dependencies": {
"@bitcoin-js/tiny-secp256k1-asmjs": "^2.2.3",
"bip174": "^3.0.0",
@@ -38937,7 +39265,7 @@
},
"packages/mesh-common": {
"name": "@meshsdk/common",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
"bech32": "^2.0.0",
@@ -38955,11 +39283,11 @@
},
"packages/mesh-contract": {
"name": "@meshsdk/contract",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.81",
- "@meshsdk/core": "1.9.0-beta.81"
+ "@meshsdk/common": "1.9.0-beta.83",
+ "@meshsdk/core": "1.9.0-beta.83"
},
"devDependencies": {
"@meshsdk/configs": "*",
@@ -38970,15 +39298,15 @@
},
"packages/mesh-core": {
"name": "@meshsdk/core",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.81",
- "@meshsdk/core-cst": "1.9.0-beta.81",
- "@meshsdk/provider": "1.9.0-beta.81",
- "@meshsdk/react": "1.9.0-beta.81",
- "@meshsdk/transaction": "1.9.0-beta.81",
- "@meshsdk/wallet": "1.9.0-beta.81"
+ "@meshsdk/common": "1.9.0-beta.83",
+ "@meshsdk/core-cst": "1.9.0-beta.83",
+ "@meshsdk/provider": "1.9.0-beta.83",
+ "@meshsdk/react": "1.9.0-beta.83",
+ "@meshsdk/transaction": "1.9.0-beta.83",
+ "@meshsdk/wallet": "1.9.0-beta.83"
},
"devDependencies": {
"@meshsdk/configs": "*",
@@ -38989,10 +39317,10 @@
},
"packages/mesh-core-csl": {
"name": "@meshsdk/core-csl",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.81",
+ "@meshsdk/common": "1.9.0-beta.83",
"@sidan-lab/whisky-js-browser": "^1.0.11",
"@sidan-lab/whisky-js-nodejs": "^1.0.11",
"@types/base32-encoding": "^1.0.2",
@@ -39002,7 +39330,7 @@
},
"devDependencies": {
"@meshsdk/configs": "*",
- "@meshsdk/provider": "1.9.0-beta.81",
+ "@meshsdk/provider": "1.9.0-beta.83",
"@types/json-bigint": "^1.0.4",
"eslint": "^8.57.0",
"ts-jest": "^29.1.4",
@@ -39012,7 +39340,7 @@
},
"packages/mesh-core-cst": {
"name": "@meshsdk/core-cst",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
"@cardano-sdk/core": "^0.45.5",
@@ -39023,7 +39351,7 @@
"@harmoniclabs/pair": "^1.0.0",
"@harmoniclabs/plutus-data": "1.2.4",
"@harmoniclabs/uplc": "1.2.4",
- "@meshsdk/common": "1.9.0-beta.81",
+ "@meshsdk/common": "1.9.0-beta.83",
"@types/base32-encoding": "^1.0.2",
"base32-encoding": "^1.0.0",
"bech32": "^2.0.0",
@@ -39042,11 +39370,11 @@
},
"packages/mesh-hydra": {
"name": "@meshsdk/hydra",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.81",
- "@meshsdk/core": "1.9.0-beta.81",
- "@meshsdk/core-cst": "1.9.0-beta.81",
+ "@meshsdk/common": "1.9.0-beta.83",
+ "@meshsdk/core": "1.9.0-beta.83",
+ "@meshsdk/core-cst": "1.9.0-beta.83",
"axios": "^1.7.2"
},
"devDependencies": {
@@ -39098,12 +39426,12 @@
},
"packages/mesh-provider": {
"name": "@meshsdk/provider",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
- "@meshsdk/bitcoin": "1.9.0-beta.81",
- "@meshsdk/common": "1.9.0-beta.81",
- "@meshsdk/core-cst": "1.9.0-beta.81",
+ "@meshsdk/bitcoin": "1.9.0-beta.83",
+ "@meshsdk/common": "1.9.0-beta.83",
+ "@meshsdk/core-cst": "1.9.0-beta.83",
"@utxorpc/sdk": "^0.6.7",
"@utxorpc/spec": "^0.16.0",
"axios": "^1.7.2",
@@ -39119,14 +39447,14 @@
},
"packages/mesh-react": {
"name": "@meshsdk/react",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
"@fabianbormann/cardano-peer-connect": "^1.2.18",
- "@meshsdk/bitcoin": "1.9.0-beta.81",
- "@meshsdk/common": "1.9.0-beta.81",
- "@meshsdk/transaction": "1.9.0-beta.81",
- "@meshsdk/wallet": "1.9.0-beta.81",
+ "@meshsdk/bitcoin": "1.9.0-beta.83",
+ "@meshsdk/common": "1.9.0-beta.83",
+ "@meshsdk/transaction": "1.9.0-beta.83",
+ "@meshsdk/wallet": "1.9.0-beta.83",
"@meshsdk/web3-sdk": "0.0.50",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
@@ -39164,10 +39492,10 @@
},
"packages/mesh-svelte": {
"name": "@meshsdk/svelte",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
- "@meshsdk/core": "1.9.0-beta.81",
+ "@meshsdk/core": "1.9.0-beta.83",
"bits-ui": "1.0.0-next.65"
},
"devDependencies": {
@@ -39193,14 +39521,14 @@
},
"packages/mesh-transaction": {
"name": "@meshsdk/transaction",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
"@cardano-sdk/core": "^0.45.5",
"@cardano-sdk/input-selection": "^0.13.33",
"@cardano-sdk/util": "^0.15.5",
- "@meshsdk/common": "1.9.0-beta.81",
- "@meshsdk/core-cst": "1.9.0-beta.81",
+ "@meshsdk/common": "1.9.0-beta.83",
+ "@meshsdk/core-cst": "1.9.0-beta.83",
"json-bigint": "^1.0.0"
},
"devDependencies": {
@@ -39213,12 +39541,12 @@
},
"packages/mesh-wallet": {
"name": "@meshsdk/wallet",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.81",
- "@meshsdk/core-cst": "1.9.0-beta.81",
- "@meshsdk/transaction": "1.9.0-beta.81",
+ "@meshsdk/common": "1.9.0-beta.83",
+ "@meshsdk/core-cst": "1.9.0-beta.83",
+ "@meshsdk/transaction": "1.9.0-beta.83",
"@simplewebauthn/browser": "^13.0.0"
},
"devDependencies": {
@@ -39229,9 +39557,144 @@
"typescript": "^5.3.3"
}
},
+ "packages/midnight-contracts-wizard": {
+ "name": "@meshsdk/midnight-contracts-wizard",
+ "version": "1.9.0-beta.84",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.2",
+ "fs-extra": "^11.1.1",
+ "inquirer": "^9.2.12",
+ "ora": "^5.4.1"
+ },
+ "bin": {
+ "midnight-contracts-wizard": "dist/index.js"
+ },
+ "devDependencies": {
+ "@meshsdk/configs": "*",
+ "@types/fs-extra": "^11.0.0",
+ "@types/inquirer": "^9.0.0",
+ "@types/node": "^20.19.23",
+ "eslint": "^8.57.0",
+ "jest": "^29.7.0",
+ "prettier": "^3.0.0",
+ "ts-jest": "^29.1.0",
+ "typescript": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "packages/midnight-contracts-wizard/node_modules/@eslint/js": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "packages/midnight-contracts-wizard/node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "deprecated": "Use @eslint/config-array instead",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "packages/midnight-contracts-wizard/node_modules/@types/node": {
+ "version": "20.19.23",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.23.tgz",
+ "integrity": "sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "packages/midnight-contracts-wizard/node_modules/eslint": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
+ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.0",
+ "@humanwhocodes/config-array": "^0.11.14",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "packages/midnight-contracts-wizard/node_modules/fs-extra": {
+ "version": "11.3.2",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz",
+ "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==",
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
"packages/midnight-setup": {
"name": "@meshsdk/midnight-setup",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
"@midnight-ntwrk/compact-runtime": "^0.8.1",
@@ -39258,7 +39721,7 @@
},
"scripts/mesh-cli": {
"name": "meshjs",
- "version": "1.9.0-beta.81",
+ "version": "1.9.0-beta.83",
"license": "Apache-2.0",
"dependencies": {
"@sidan-lab/cardano-bar": "^0.0.7",
diff --git a/package.json b/package.json
index 3afc72dcf..0c57714df 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
},
"devDependencies": {
"@meshsdk/configs": "*",
+ "@types/fs-extra": "^11.0.4",
"@types/jest": "^29.5.12",
"dotenv": "^16.4.5",
"jest": "^29.7.0",
diff --git a/packages/bitcoin/package.json b/packages/bitcoin/package.json
index b17f38cf6..65b58ef81 100644
--- a/packages/bitcoin/package.json
+++ b/packages/bitcoin/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/bitcoin",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Mesh Bitcoin package",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
diff --git a/packages/mesh-common/package.json b/packages/mesh-common/package.json
index 5ef09fde7..79d986b46 100644
--- a/packages/mesh-common/package.json
+++ b/packages/mesh-common/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/common",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Contains constants, types and interfaces used across the SDK and different serialization libraries",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
diff --git a/packages/mesh-contract/package.json b/packages/mesh-contract/package.json
index 5f597ae49..15eab2c0b 100644
--- a/packages/mesh-contract/package.json
+++ b/packages/mesh-contract/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/contract",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "List of open-source smart contracts, complete with documentation, live demos, and end-to-end source code. https://meshjs.dev/smart-contracts",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -34,8 +34,8 @@
"typescript": "^5.3.3"
},
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.83",
- "@meshsdk/core": "1.9.0-beta.83"
+ "@meshsdk/common": "1.9.0-beta.84",
+ "@meshsdk/core": "1.9.0-beta.84"
},
"prettier": "@meshsdk/configs/prettier",
"publishConfig": {
diff --git a/packages/mesh-core-csl/package.json b/packages/mesh-core-csl/package.json
index ed1d5e5ec..a9cc6f5f9 100644
--- a/packages/mesh-core-csl/package.json
+++ b/packages/mesh-core-csl/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/core-csl",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Types and utilities functions between Mesh and cardano-serialization-lib",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
@@ -31,7 +31,7 @@
},
"devDependencies": {
"@meshsdk/configs": "*",
- "@meshsdk/provider": "1.9.0-beta.83",
+ "@meshsdk/provider": "1.9.0-beta.84",
"@types/json-bigint": "^1.0.4",
"eslint": "^8.57.0",
"ts-jest": "^29.1.4",
@@ -39,7 +39,7 @@
"typescript": "^5.3.3"
},
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.83",
+ "@meshsdk/common": "1.9.0-beta.84",
"@sidan-lab/whisky-js-browser": "^1.0.11",
"@sidan-lab/whisky-js-nodejs": "^1.0.11",
"@types/base32-encoding": "^1.0.2",
diff --git a/packages/mesh-core-cst/package.json b/packages/mesh-core-cst/package.json
index 45403445c..4f21ae98c 100644
--- a/packages/mesh-core-cst/package.json
+++ b/packages/mesh-core-cst/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/core-cst",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Types and utilities functions between Mesh and cardano-js-sdk",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -44,7 +44,7 @@
"@harmoniclabs/plutus-data": "1.2.4",
"@harmoniclabs/uplc": "1.2.4",
"@harmoniclabs/pair": "^1.0.0",
- "@meshsdk/common": "1.9.0-beta.83",
+ "@meshsdk/common": "1.9.0-beta.84",
"@types/base32-encoding": "^1.0.2",
"base32-encoding": "^1.0.0",
"bech32": "^2.0.0",
diff --git a/packages/mesh-core/package.json b/packages/mesh-core/package.json
index cffeceae8..985f82f04 100644
--- a/packages/mesh-core/package.json
+++ b/packages/mesh-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/core",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Mesh SDK Core - https://meshjs.dev/",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -33,12 +33,12 @@
"typescript": "^5.3.3"
},
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.83",
- "@meshsdk/core-cst": "1.9.0-beta.83",
- "@meshsdk/provider": "1.9.0-beta.83",
- "@meshsdk/react": "1.9.0-beta.83",
- "@meshsdk/transaction": "1.9.0-beta.83",
- "@meshsdk/wallet": "1.9.0-beta.83"
+ "@meshsdk/common": "1.9.0-beta.84",
+ "@meshsdk/core-cst": "1.9.0-beta.84",
+ "@meshsdk/provider": "1.9.0-beta.84",
+ "@meshsdk/react": "1.9.0-beta.84",
+ "@meshsdk/transaction": "1.9.0-beta.84",
+ "@meshsdk/wallet": "1.9.0-beta.84"
},
"prettier": "@meshsdk/configs/prettier",
"publishConfig": {
diff --git a/packages/mesh-hydra/package.json b/packages/mesh-hydra/package.json
index 272ceaf80..fc91d9509 100644
--- a/packages/mesh-hydra/package.json
+++ b/packages/mesh-hydra/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/hydra",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Mesh Hydra package",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -27,9 +27,9 @@
"test": "jest"
},
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.83",
- "@meshsdk/core": "1.9.0-beta.83",
- "@meshsdk/core-cst": "1.9.0-beta.83",
+ "@meshsdk/common": "1.9.0-beta.84",
+ "@meshsdk/core": "1.9.0-beta.84",
+ "@meshsdk/core-cst": "1.9.0-beta.84",
"axios": "^1.7.2"
},
"devDependencies": {
diff --git a/packages/mesh-provider/package.json b/packages/mesh-provider/package.json
index 1d4354d21..3751f7a13 100644
--- a/packages/mesh-provider/package.json
+++ b/packages/mesh-provider/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/provider",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Blockchain data providers - https://meshjs.dev/providers",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -35,9 +35,9 @@
"typescript": "^5.3.3"
},
"dependencies": {
- "@meshsdk/bitcoin": "1.9.0-beta.83",
- "@meshsdk/common": "1.9.0-beta.83",
- "@meshsdk/core-cst": "1.9.0-beta.83",
+ "@meshsdk/bitcoin": "1.9.0-beta.84",
+ "@meshsdk/common": "1.9.0-beta.84",
+ "@meshsdk/core-cst": "1.9.0-beta.84",
"@utxorpc/sdk": "^0.6.7",
"@utxorpc/spec": "^0.16.0",
"axios": "^1.7.2",
diff --git a/packages/mesh-react/package.json b/packages/mesh-react/package.json
index 1282b3a53..951b5e361 100644
--- a/packages/mesh-react/package.json
+++ b/packages/mesh-react/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/react",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "React component library - https://meshjs.dev/react",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -30,10 +30,10 @@
},
"dependencies": {
"@fabianbormann/cardano-peer-connect": "^1.2.18",
- "@meshsdk/bitcoin": "1.9.0-beta.83",
- "@meshsdk/common": "1.9.0-beta.83",
- "@meshsdk/transaction": "1.9.0-beta.83",
- "@meshsdk/wallet": "1.9.0-beta.83",
+ "@meshsdk/bitcoin": "1.9.0-beta.84",
+ "@meshsdk/common": "1.9.0-beta.84",
+ "@meshsdk/transaction": "1.9.0-beta.84",
+ "@meshsdk/wallet": "1.9.0-beta.84",
"@meshsdk/web3-sdk": "0.0.50",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
diff --git a/packages/mesh-svelte/package.json b/packages/mesh-svelte/package.json
index 6a440b0d7..8ee23e418 100644
--- a/packages/mesh-svelte/package.json
+++ b/packages/mesh-svelte/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/svelte",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Svelte component library - https://meshjs.dev/svelte",
"type": "module",
"exports": {
@@ -26,7 +26,7 @@
"dev": "vite dev"
},
"dependencies": {
- "@meshsdk/core": "1.9.0-beta.83",
+ "@meshsdk/core": "1.9.0-beta.84",
"bits-ui": "1.0.0-next.65"
},
"devDependencies": {
diff --git a/packages/mesh-transaction/package.json b/packages/mesh-transaction/package.json
index 39ebbfc40..08dba0919 100644
--- a/packages/mesh-transaction/package.json
+++ b/packages/mesh-transaction/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/transaction",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Transactions - https://meshjs.dev/apis/transaction",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -35,8 +35,8 @@
"typescript": "^5.3.3"
},
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.83",
- "@meshsdk/core-cst": "1.9.0-beta.83",
+ "@meshsdk/common": "1.9.0-beta.84",
+ "@meshsdk/core-cst": "1.9.0-beta.84",
"@cardano-sdk/core": "^0.45.5",
"@cardano-sdk/util": "^0.15.5",
"@cardano-sdk/input-selection": "^0.13.33",
diff --git a/packages/mesh-wallet/package.json b/packages/mesh-wallet/package.json
index e52842345..e560a749c 100644
--- a/packages/mesh-wallet/package.json
+++ b/packages/mesh-wallet/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/wallet",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Wallets - https://meshjs.dev/apis/wallets",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
@@ -35,9 +35,9 @@
"typescript": "^5.3.3"
},
"dependencies": {
- "@meshsdk/common": "1.9.0-beta.83",
- "@meshsdk/core-cst": "1.9.0-beta.83",
- "@meshsdk/transaction": "1.9.0-beta.83",
+ "@meshsdk/common": "1.9.0-beta.84",
+ "@meshsdk/core-cst": "1.9.0-beta.84",
+ "@meshsdk/transaction": "1.9.0-beta.84",
"@simplewebauthn/browser": "^13.0.0"
},
"prettier": "@meshsdk/configs/prettier",
diff --git a/packages/midnight-contracts-wizard/.npmignore b/packages/midnight-contracts-wizard/.npmignore
new file mode 100644
index 000000000..38a357538
--- /dev/null
+++ b/packages/midnight-contracts-wizard/.npmignore
@@ -0,0 +1,28 @@
+# Source files
+src/
+contracts/
+
+# Development files
+jest.config.ts
+tsconfig.json
+tsconfig.spec.json
+
+# Test files
+test/
+**/*.test.ts
+**/*.spec.ts
+
+# Documentation
+INSTRUCTIONS.md
+
+# Build artifacts
+coverage/
+.nyc_output/
+
+# IDE files
+.vscode/
+.idea/
+
+# OS files
+.DS_Store
+Thumbs.db
diff --git a/packages/midnight-contracts-wizard/README.md b/packages/midnight-contracts-wizard/README.md
new file mode 100644
index 000000000..32814b95b
--- /dev/null
+++ b/packages/midnight-contracts-wizard/README.md
@@ -0,0 +1,67 @@
+# @meshsdk/midnight-contracts-wizard
+
+A CLI tool to create new Midnight contracts projects with selected smart contracts.
+
+## Installation
+
+```bash
+npm install @meshsdk/midnight-contracts-wizard
+```
+
+## Usage
+
+```bash
+npx @meshsdk/midnight-contracts-wizard
+```
+
+## Features
+
+- **Interactive CLI** - Select which contracts to include
+- **Multiple Contract Types** - Tokenization, Staking, Identity, Oracle, Lending & Borrowing
+- **Complete Setup** - Generates package.json, tsconfig, and build scripts
+- **Ready to Use** - All necessary files for compilation and build
+- **Self-Contained** - All contract templates included, no external dependencies
+
+## Available Contracts
+
+### Tokenization Contract
+
+- Complete project tokenization system with ZK privacy investment (7 ZK circuits)
+
+### Staking Contract
+
+- Privacy-focused staking system with rewards and lock periods (8 ZK circuits)
+
+### Identity Contracts
+
+- Complete identity management system with cryptographic libraries (1 ZK circuit)
+
+### Oracle Contract
+
+- Decentralized oracle system with privacy-preserving data feeds (7 ZK circuits)
+
+### Lending & Borrowing Contract
+
+- Privacy-preserving decentralized lending protocol (7 ZK circuits)
+
+## Generated Project Structure
+
+```
+my-project/
+├── src/
+│ ├── [selected-contracts]/
+│ │ └── *.compact
+│ └── managed/ # Compiled contracts
+├── dist/ # Distribution
+├── package.json
+├── tsconfig.json
+├── tsconfig.build.json
+└── README.md
+```
+
+---
+
+
+
Powered by MeshJS Team
+
Built with ❤️ on Midnight Network
+
diff --git a/packages/midnight-contracts-wizard/contracts/identity/CryptoLibrary.compact b/packages/midnight-contracts-wizard/contracts/identity/CryptoLibrary.compact
new file mode 100644
index 000000000..d6bccb7c6
--- /dev/null
+++ b/packages/midnight-contracts-wizard/contracts/identity/CryptoLibrary.compact
@@ -0,0 +1,244 @@
+pragma language_version >= 0.16.0;
+
+module CryptoLibrary {
+ import CompactStandardLibrary;
+
+ /**
+ * @dev Point to bytes conversion
+ * @notice Converts a curve point to a 32-byte hash representation
+ * @param p The curve point to convert
+ * @return A 32-byte hash of the curve point
+ */
+ circuit curvePointToBytes(p: CurvePoint): Bytes<32> {
+ return persistentHash(p);
+ }
+
+/**
+ * @dev 96-byte structure
+ * @notice Represents a 96-byte value split into three 32-byte segments
+ * @param b0 First 32-byte segment
+ * @param b1 Second 32-byte segment
+ * @param b2 Third 32-byte segment
+ */
+struct Bytes96 {
+ b0: Bytes<32>;
+ b1: Bytes<32>;
+ b2: Bytes<32>;
+}
+
+/**
+ * @dev 64-byte structure
+ * @notice Represents a 64-byte value split into two 32-byte segments
+ * @param b0 First 32-byte segment
+ * @param b1 Second 32-byte segment
+ */
+struct Bytes64 {
+ b0: Bytes<32>;
+ b1: Bytes<32>;
+}
+
+/**
+ * @dev Digital signature structure
+ * @notice Represents a cryptographic signature for credential verification
+ * @param pk Public key curve point of the signer
+ * @param R Random curve point used in signature generation
+ * @param s Scalar field element completing the signature
+ */
+export struct Signature {
+ pk: CurvePoint;
+ R: CurvePoint;
+ s: Field;
+}
+
+/**
+ * @dev Credential subject structure
+ * @notice Represents a credential subject as defined in the W3C Verifiable Credentials Data Model
+ * @see
+ * @param id The subject's identifier (Midnight wallet public key)
+ * @param firstName The subject's first name (hashed to 32 bytes)
+ * @param lastName The subject's last name (hashed to 32 bytes)
+ * @param nationalIdentifier The subject's national identifier (hashed to 32 bytes)
+ * @param birthTimestamp The subject's birth timestamp in Unix time
+ */
+export struct CredentialSubject {
+ id: Bytes<32>;
+ firstName: Bytes<32>;
+ lastName: Bytes<32>;
+ nationalIdentifier: Bytes<32>;
+ birthTimestamp: Uint<64>;
+}
+
+/**
+ * @dev Signed credential subject structure
+ * @notice Represents a credential subject with an issuer's digital signature for verification
+ * @param subject The credential subject data (identity information)
+ * @param signature The issuer's digital signature over the credential subject
+ */
+export struct SignedCredentialSubject {
+ subject: CredentialSubject;
+ signature: Signature;
+}
+
+/**
+ * @dev Subject hash circuit
+ * @notice Computes a persistent hash of a credential subject for canonical representation
+ * @param credentialSubject The credential subject to hash
+ * @return A 32-byte persistent hash of the credential subject
+ */
+export pure circuit subjectHash(credentialSubject: CredentialSubject): Bytes<32> {
+ return persistentHash(credentialSubject);
+}
+
+/**
+ * @dev Derive public key circuit
+ * @notice Derives a public key curve point from a private key using elliptic curve multiplication
+ * @param skBytes The 32-byte private key
+ * @return The corresponding public key as a curve point
+ */
+export pure circuit derivePk(skBytes: Bytes<32>): CurvePoint {
+ const sk: Field = 0; //transientHash>(skBytes);
+ const pk: CurvePoint = ecMulGenerator(sk);
+ return pk;
+}
+
+/**
+ * @dev Sign message circuit (original implementation)
+ * @notice Creates a digital signature over a message using a private key and deterministic nonce
+ * @param msg The 32-byte message to sign
+ * @param skBytes The 32-byte private key
+ * @return A Signature structure containing the public key, random point R, and scalar s
+ */
+/*
+// Original way to sign
+ export pure circuit sign(msg: Bytes<32>, skBytes: Bytes<32>): Signature {
+ // Convert skBytes to Field
+ const sk: Field = transientHash>(skBytes);
+ // Compute public key: pk = sk * B
+ const pk: CurvePoint = ecMulGenerator(sk);
+
+ // Derive nonce k deterministically: k = H(skBytes || msg)
+ const nonceInput: Bytes64 = Bytes64 { b0: skBytes, b1: msg };
+ const k: Field = transientHash(nonceInput); // Hash to scalar
+
+ // Compute R = k * B
+ const R: CurvePoint = ecMulGenerator(k);
+
+ // Compute challenge: c = H(R || pk || msg)
+ const rBytes: Bytes<32> = curvePointToBytes(R);
+ const pkBytes: Bytes<32> = curvePointToBytes(pk);
+ const cBytes: Bytes96 = Bytes96 {
+ b0: rBytes,
+ b1: pkBytes,
+ b2: msg
+ };
+ const c: Field = transientHash(cBytes);
+
+ // Compute signature: s = k + c * sk
+ const s: Field = k + (c * sk);
+
+ return Signature { pk: pk, R: R, s: s };
+}
+*/
+
+/**
+ * @dev Sign message circuit (workaround implementation)
+ * @notice Creates a digital signature using hardcoded field constants as a temporary workaround
+ * @param msg The 32-byte message to sign
+ * @param skBytes The 32-byte private key (currently unused due to workaround)
+ * @return A Signature structure containing the public key, random point R, and scalar s
+ * @custom:warning This is a temporary workaround using constant values. Not suitable for production use.
+ * @custom:issue Awaiting resolution from Midnight team for proper field derivation from bytes
+ */
+// Workaround way to sign using a Field 2 (not resolved by Midnight team yet)
+export pure circuit sign(msg: Bytes<32>, skBytes: Bytes<32>): Signature {
+ // Use a small, valid constant for demonstration
+ const sk: Field = 2; // Instead of deriving from skBytes
+ const pk: CurvePoint = ecMulGenerator(sk);
+
+ // Use another small, valid constant for the nonce
+ const k: Field = 3; // Instead of deriving from hash
+ const R: CurvePoint = ecMulGenerator(k);
+
+ const rBytes: Bytes<32> = curvePointToBytes(R);
+ const pkBytes: Bytes<32> = curvePointToBytes(pk);
+ const cBytes: Bytes96 = Bytes96 {
+ b0: rBytes,
+ b1: pkBytes,
+ b2: msg
+ };
+ const c: Field = transientHash(cBytes);
+
+ const s: Field = k + (c * sk);
+
+ return Signature { pk: pk, R: R, s: s };
+}
+
+/**
+ * @dev Verify signature circuit
+ * @notice Verifies a digital signature by checking the Schnorr signature equation: s*G = R + c*pk
+ * @param msg The 32-byte message that was signed
+ * @param signature The signature structure containing pk, R, and s
+ * @custom:throws Assertion error if signature verification fails
+ */
+// Original way to verify the signature
+export pure circuit verifySignature(msg: Bytes<32>, signature: Signature): [] {
+ const {pk, R, s} = signature;
+ // Compute challenge: c = H(R || pk || msg)
+ const rBytes: Bytes<32> = curvePointToBytes(R);
+ const pkBytes: Bytes<32> = curvePointToBytes(pk);
+ const cBytes: Bytes96 = Bytes96 {
+ b0: rBytes,
+ b1: pkBytes,
+ b2: msg
+ };
+ const c: Field = transientHash(cBytes);
+
+ // Left-hand side: s * B
+ const lhs: CurvePoint = ecMulGenerator(s);
+
+ // Right-hand side: R + c * pk
+ const cPk: CurvePoint = ecMul(pk, c);
+ const rhs: CurvePoint = ecAdd(R, cPk);
+
+ // Enforce verification equation
+ assert(lhs == rhs, "Signature verification failed");
+}
+
+ /**
+ * @dev Verify signature circuit (workaround implementation)
+ * @notice Verifies a digital signature using a hardcoded scalar constant as a temporary workaround
+ * @param msg The 32-byte message that was signed
+ * @param signature The signature structure containing pk, R, and s (s component currently unused)
+ * @custom:warning This is a temporary workaround using a constant value. Not suitable for production use.
+ * @custom:issue Awaiting resolution from Midnight team for proper signature verification
+ * @custom:throws Assertion error if signature verification fails
+ */
+/*
+ // Workaround way to verify the signature (not resolved by Midnight team yet)
+ export pure circuit verifySignature(msg: Bytes<32>, signature: Signature): [] {
+ const {pk, R} = signature;
+ // Use a constant Field value for demonstration
+ const s: Field = 2;
+
+ // Compute challenge: c = H(R || pk || msg)
+ const rBytes: Bytes<32> = curvePointToBytes(R);
+ const pkBytes: Bytes<32> = curvePointToBytes(pk);
+ const cBytes: Bytes96 = Bytes96 {
+ b0: rBytes,
+ b1: pkBytes,
+ b2: msg
+ };
+ const c: Field = transientHash(cBytes);
+
+ // Left-hand side: s * B
+ const lhs: CurvePoint = ecMulGenerator(s);
+
+ // Right-hand side: R + c * pk
+ const cPk: CurvePoint = ecMul(pk, c);
+ const rhs: CurvePoint = ecAdd(R, cPk);
+
+ // Enforce verification equation
+ assert(lhs == rhs, "Signature verification failed");
+ }
+ */
+}
diff --git a/packages/midnight-contracts-wizard/contracts/identity/IdentityLibrary.compact b/packages/midnight-contracts-wizard/contracts/identity/IdentityLibrary.compact
new file mode 100644
index 000000000..2b00446b5
--- /dev/null
+++ b/packages/midnight-contracts-wizard/contracts/identity/IdentityLibrary.compact
@@ -0,0 +1,25 @@
+pragma language_version >= 0.16.0;
+
+import CompactStandardLibrary;
+import "../identity/CryptoLibrary";
+
+/**
+ * @dev Exported types and functions
+ * @notice Makes cryptographic primitives and identity types available to external consumers
+ * - CoinInfo: Coin information structure for token handling
+ * - Signature: Digital signature type for credential verification
+ * - CredentialSubject: Structure representing credential subject data
+ * - SignedCredentialSubject: Credential subject with issuer signature
+ * - sign: Function to create digital signatures
+ * - verifySignature: Function to verify digital signatures
+ * - derivePk: Function to derive public key from private key
+ * - subjectHash: Function to hash credential subject data
+ */
+export { CoinInfo }
+export { Signature }
+export { CredentialSubject }
+export { SignedCredentialSubject }
+export { sign }
+export { verifySignature }
+export { derivePk }
+export { subjectHash }
\ No newline at end of file
diff --git a/packages/midnight-contracts-wizard/contracts/identity/registry.compact b/packages/midnight-contracts-wizard/contracts/identity/registry.compact
new file mode 100644
index 000000000..1c95afd29
--- /dev/null
+++ b/packages/midnight-contracts-wizard/contracts/identity/registry.compact
@@ -0,0 +1,31 @@
+pragma language_version >= 0.16.0;
+
+import CompactStandardLibrary;
+
+/**
+ * @dev Exported types
+ * @notice Makes CurvePoint available to external consumers for signature verification
+ */
+export { CurvePoint }
+
+/**
+ * @dev Wallet public key
+ * @notice Stores the user's Zswap coin public key for receiving payments
+ */
+export ledger walletPublicKey: ZswapCoinPublicKey;
+
+/**
+ * @dev Signing public key
+ * @notice Stores the user's signing public key for credential verification
+ */
+export ledger signingPublicKey: CurvePoint;
+
+/**
+ * @dev Register user circuit
+ * @notice Allows users to register their wallet and signing public keys on-chain
+ * @param signingKey The user's public signing key for credential verification
+ */
+export circuit register(signingKey: CurvePoint): [] {
+ walletPublicKey = ownPublicKey();
+ signingPublicKey = disclose(signingKey);
+}
\ No newline at end of file
diff --git a/packages/midnight-contracts-wizard/contracts/lending-borrowing/lending-borrowing.compact b/packages/midnight-contracts-wizard/contracts/lending-borrowing/lending-borrowing.compact
new file mode 100644
index 000000000..d5331f4a6
--- /dev/null
+++ b/packages/midnight-contracts-wizard/contracts/lending-borrowing/lending-borrowing.compact
@@ -0,0 +1,491 @@
+pragma language_version >= 0.16.0;
+
+import CompactStandardLibrary;
+
+/**
+ * @dev Total borrowed by asset
+ * @notice Maps asset types (coin colors) to the total amount currently borrowed from the lending pool
+ */
+export ledger totalBorrowedByAsset: Map, Uint<128>>;
+
+/**
+ * @dev Total supplied by asset
+ * @notice Maps asset types (coin colors) to the total amount currently supplied to the lending pool
+ */
+export ledger totalSuppliedByAsset: Map, Uint<128>>;
+
+/**
+ * @dev Supply positions registry
+ * @notice Merkle tree storing anonymous supply position commitments for lenders
+ * @custom:privacy Allows lenders to prove their supply positions without revealing identity
+ */
+export ledger supplyPositions: MerkleTree<100, Bytes<32>>;
+
+/**
+ * @dev Collateral positions registry
+ * @notice Merkle tree storing anonymous collateral position commitments for borrowers
+ * @custom:privacy Allows borrowers to prove their collateral positions without revealing identity
+ */
+export ledger collateralPositions: MerkleTree<100, Bytes<32>>;
+
+/**
+ * @dev Lending pool
+ * @notice Maps asset types (coin colors) to their qualified coin information for lending operations
+ * @custom:usage Stores available liquidity that can be borrowed by users
+ */
+export ledger lendingPool: Map, QualifiedCoinInfo>;
+
+/**
+ * @dev Collateral pool
+ * @notice Maps position commitments to their qualified coin information for collateral management
+ * @custom:usage Stores collateral deposited by borrowers to secure their loans
+ */
+export ledger collateralPool: Map, QualifiedCoinInfo>;
+
+/**
+ * @dev Interest rate model
+ * @notice Maps asset types (coin colors) to their current interest rates in basis points
+ * @custom:usage Used to determine borrowing costs and lending yields based on pool utilization
+ */
+export ledger interestRateModel: Map, Uint<64>>;
+
+/**
+ * @dev Current interest rate
+ * @notice Stores the current global interest rate in basis points
+ * @custom:usage Used to calculate interest accrual for supply and borrow positions
+ */
+export ledger interestRate: Uint<64>;
+
+/**
+ * @dev Collateral position structure
+ * @notice Represents a user's collateral position with privacy-preserving commitments
+ * @param userCommitment Anonymous user identifier (commitment hash)
+ * @param collateralCommitment Commitment to the collateral amount (keeps amount private)
+ * @param debtCommitment Commitment to the debt amount (keeps amount private)
+ * @param assetType Type of collateral asset (coin color)
+ * @param timestamp Unix timestamp when the position was created
+ */
+struct CollateralPosition {
+ userCommitment: Bytes<32>;
+ collateralCommitment: Bytes<32>;
+ debtCommitment: Bytes<32>;
+ assetType: Bytes<32>;
+ timestamp: Uint<64>;
+}
+
+/**
+ * @dev Supply position structure
+ * @notice Represents a user's supply position with privacy-preserving commitments
+ * @param userCommitment Anonymous user identifier (commitment hash)
+ * @param supplyCommitment Commitment to the supply amount (keeps amount private)
+ * @param assetType Type of asset supplied (coin color)
+ * @param timestamp Unix timestamp when the position was created
+ */
+struct SupplyPosition {
+ userCommitment: Bytes<32>;
+ supplyCommitment: Bytes<32>;
+ assetType: Bytes<32>;
+ timestamp: Uint<64>;
+}
+
+/**
+ * @dev Verify collateral ownership witness
+ * @notice Proves that the user owns the collateral being deposited
+ * @param amount The collateral amount to verify ownership for
+ * @return Boolean indicating whether the user owns the specified collateral amount
+ */
+witness verifyCollateralOwnership(amount: Uint<128>): Boolean;
+
+/**
+ * @dev Verify health factor witness
+ * @notice Proves that a position maintains the required collateral ratio privately
+ * @param collateralProof The commitment to the collateral position
+ * @param borrowAmount The amount being borrowed or already borrowed
+ * @param price The oracle price for collateral valuation
+ * @return Boolean indicating whether the health factor requirement is met
+ */
+witness verifyHealthFactor(collateralProof: Bytes<32>, borrowAmount: Uint<128>, price: Uint<128>): Boolean;
+
+/**
+ * @dev Verify liquidation eligibility witness
+ * @notice Proves that a position is undercollateralized and eligible for liquidation
+ * @param liquidationProof The proof that the position is undercollateralized
+ * @return Boolean indicating whether the position can be liquidated
+ */
+witness verifyLiquidationEligibility(liquidationProof: Bytes<32>): Boolean;
+
+/**
+ * @dev Calculate liquidation bonus witness
+ * @notice Computes the liquidation bonus (incentive) for liquidators
+ * @param repaymentAmount The amount being repaid by the liquidator
+ * @return The liquidation bonus amount to be awarded to the liquidator
+ */
+witness calculateLiquidationBonus(repaymentAmount: Uint<128>): Uint<128>;
+
+/**
+ * @dev Update or remove position witness
+ * @notice Updates or removes a collateral position after liquidation
+ * @param positionCommitment The commitment to the position being updated or removed
+ * @return Empty tuple (no return value)
+ */
+witness updateOrRemovePosition(positionCommitment: Bytes<32>): [];
+
+/**
+ * @dev Update debt commitment witness
+ * @notice Updates the debt commitment after a repayment or borrowing operation
+ * @param positionCommitment The commitment to the position being updated
+ * @param repaymentAmount The amount being repaid (reduces debt) or borrowed (increases debt)
+ * @return The new debt commitment hash
+ */
+witness updateDebtCommitment(positionCommitment: Bytes<32>, repaymentAmount: Uint<128>): Bytes<32>;
+
+/**
+ * @dev Mark position repaid witness
+ * @notice Marks a position as fully repaid, allowing collateral withdrawal
+ * @param positionCommitment The commitment to the position being marked as repaid
+ * @return Empty tuple (no return value)
+ */
+witness markPositionRepaid(positionCommitment: Bytes<32>): [];
+
+/**
+ * @dev Update collateral commitment witness
+ * @notice Updates the collateral commitment after a withdrawal operation
+ * @param positionCommitment The commitment to the position being updated
+ * @param withdrawAmount The amount being withdrawn from collateral
+ * @return The new collateral commitment hash
+ */
+witness updateCollateralCommitment(positionCommitment: Bytes<32>, withdrawAmount: Uint<128>): Bytes<32>;
+
+/**
+ * @dev Generate user commitment witness
+ * @notice Creates an anonymous user identifier from a secret key
+ * @param secretKey The user's secret key
+ * @return A commitment hash representing the user anonymously
+ */
+witness generateUserCommitment(secretKey: Bytes<32>): Bytes<32>;
+
+/**
+ * @dev Calculate utilization rate witness
+ * @notice Computes the pool utilization rate as (borrowed / supplied) * 10000
+ * @param totalBorrowed Total amount currently borrowed from the pool
+ * @param totalSupplied Total amount currently supplied to the pool
+ * @return The utilization rate in basis points (0-10000)
+ */
+witness calculateUtilizationRate(totalBorrowed: Uint<128>, totalSupplied: Uint<128>): Uint<64>;
+
+/**
+ * @dev Apply interest rate model witness
+ * @notice Calculates the interest rate based on the utilization rate using the protocol's rate model
+ * @param utilizationRate The current pool utilization rate in basis points
+ * @return The calculated interest rate in basis points
+ */
+witness applyInterestRateModel(utilizationRate: Uint<64>): Uint<64>;
+
+/**
+ * @dev Get secret key witness
+ * @notice Provides the caller's secret key for commitment generation and ownership verification
+ * @return The caller's 32-byte secret key
+ */
+witness getSecretKey(): Bytes<32>;
+
+/**
+ * @dev Get randomness witness
+ * @notice Provides random bytes for commitment generation to ensure uniqueness
+ * @return A 32-byte random value for cryptographic commitments
+ */
+witness getRandomness(): Bytes<32>;
+
+/**
+ * @dev Get current time witness
+ * @notice Provides the current timestamp for recording position creation and updates
+ * @return The current Unix timestamp in seconds
+ */
+witness getCurrentTime(): Uint<64>;
+
+/**
+ * @dev Verify position ownership witness
+ * @notice Proves that the caller owns the specified position
+ * @param positionCommitment The commitment to the position being verified
+ * @return Boolean indicating whether the caller owns the position
+ */
+witness verifyPositionOwnership(positionCommitment: Bytes<32>): Boolean;
+
+/**
+ * @dev Verify health factor after withdrawal witness
+ * @notice Proves that a position maintains the required collateral ratio after a withdrawal
+ * @param positionCommitment The commitment to the position being verified
+ * @param withdrawAmount The amount to be withdrawn from collateral
+ * @return Boolean indicating whether the health factor remains sufficient after withdrawal
+ */
+witness verifyHealthFactorAfterWithdrawal(positionCommitment: Bytes<32>, withdrawAmount: Uint<128>): Boolean;
+
+/**
+ * @dev Find collateral position witness
+ * @notice Provides the Merkle tree path for a collateral position's authorization proof
+ * @param positionCommitment The commitment to the collateral position
+ * @return The Merkle tree path proving the position exists in the collateral positions tree
+ */
+witness findCollateralPosition(positionCommitment: Bytes<32>): MerkleTreePath<100, Bytes<32>>;
+
+/**
+ * @dev Find supply position witness
+ * @notice Provides the Merkle tree path for a supply position's authorization proof
+ * @param userCommitment The user's commitment hash
+ * @return The Merkle tree path proving the position exists in the supply positions tree
+ */
+witness findSupplyPosition(userCommitment: Bytes<32>): MerkleTreePath<100, Bytes<32>>;
+
+/**
+ * @dev Reduce debt commitment witness
+ * @notice Updates the debt commitment after a repayment, reducing the debt amount
+ * @param positionCommitment The commitment to the position being updated
+ * @param repaymentAmount The amount being repaid to reduce the debt
+ * @return The new debt commitment hash after reduction
+ */
+witness reduceDebtCommitment(positionCommitment: Bytes<32>, repaymentAmount: Uint<128>): Bytes<32>;
+
+/**
+ * @dev Get private oracle data witness
+ * @notice Provides oracle data privately for zero-knowledge proof generation
+ * @param dataKey The identifier for the oracle data feed
+ * @return The oracle data value (kept private)
+ */
+witness getPrivateOracleData(dataKey: Bytes<32>): Uint<128>;
+
+/**
+ * @dev Get current debt witness
+ * @notice Retrieves the current debt amount for a position
+ * @param positionCommitment The commitment to the position
+ * @return The current debt amount
+ */
+witness getCurrentDebt(positionCommitment: Bytes<32>): Uint<128>;
+
+/**
+ * @dev Deposit collateral circuit
+ * @notice Allows users to deposit collateral anonymously with ZK proof of ownership
+ * @param collateralCoin The coin to deposit as collateral
+ * @param collateralAmount The amount being deposited (kept private)
+ */
+export circuit depositCollateral(
+ collateralCoin: CoinInfo,
+ collateralAmount: Uint<128>
+): [] {
+ // Verify coin ownership and amount privately
+ assert(verifyCollateralOwnership(collateralAmount), "Invalid collateral");
+
+ // Receive the collateral
+ receive(disclose(collateralCoin));
+
+ // Create anonymous position commitment
+ const userCommit = generateUserCommitment(disclose(getSecretKey()));
+ const collateralCommit = persistentCommit>(disclose(collateralAmount), disclose(getRandomness()));
+
+ // Store position anonymously in Merkle tree with explicit disclosure
+ const position = CollateralPosition {
+ userCommitment: userCommit,
+ collateralCommitment: collateralCommit,
+ debtCommitment: persistentCommit>(0 as Uint<128>, disclose(getRandomness())),
+ assetType: disclose(collateralCoin.color),
+ timestamp: disclose(getCurrentTime())
+ };
+
+ collateralPositions.insert(disclose(userCommit));
+}
+
+/**
+ * @dev Borrow circuit
+ * @notice Allows users to borrow against collateral while proving health factor privately
+ * @param borrowAmount The amount to borrow (kept private)
+ * @param collateralProof ZK proof of sufficient collateral
+ * @param priceKey Oracle price feed identifier
+ */
+export circuit borrow(
+ borrowAmount: Uint<128>,
+ collateralProof: Bytes<32>,
+ priceKey: Bytes<32>
+): [] {
+ // Verify user has sufficient collateral using ZK proof
+ const path = disclose(findCollateralPosition(collateralProof));
+ assert(collateralPositions.checkRoot(merkleTreePathRoot<100, Bytes<32>>(path)),
+ "Invalid collateral position");
+
+ // Get oracle price privately
+ const price = getPrivateOracleData(disclose(priceKey));
+
+ // Verify health factor privately
+ assert(verifyHealthFactor(collateralProof, disclose(borrowAmount), price),
+ "Insufficient collateral ratio");
+
+ // Update debt commitment
+ const newDebtCommit = updateDebtCommitment(collateralProof, disclose(borrowAmount));
+
+ // Send borrowed funds to user
+ const sendResult = send(
+ lendingPool.lookup(disclose(priceKey)), // Now returns QualifiedCoinInfo
+ left(ownPublicKey()),
+ disclose(borrowAmount)
+ );
+
+ // Update lending pool balance with change
+ sendResult.change.is_some ?
+ lendingPool.insertCoin(disclose(priceKey), sendResult.change.value, right(kernel.self())) :
+ lendingPool.remove(disclose(priceKey));
+}
+
+/**
+ * @dev Liquidate position circuit
+ * @notice Allows liquidators to liquidate undercollateralized positions with ZK proof
+ * @param positionCommitment The commitment to the position being liquidated
+ * @param liquidationProof ZK proof that position is undercollateralized
+ * @param repaymentCoin Coin to repay the debt
+ */
+export circuit liquidatePosition(
+ positionCommitment: Bytes<32>,
+ liquidationProof: Bytes<32>,
+ repaymentCoin: CoinInfo
+): [] {
+ // Verify position exists
+ const path = disclose(findCollateralPosition(positionCommitment));
+ assert(collateralPositions.checkRoot(merkleTreePathRoot<100, Bytes<32>>(path)),
+ "Position not found");
+
+ // Verify position is undercollateralized using ZK proof
+ assert(verifyLiquidationEligibility(liquidationProof),
+ "Position is not eligible for liquidation");
+
+ // Receive repayment
+ receive(disclose(repaymentCoin));
+
+ // Calculate liquidation bonus (e.g., 5%)
+ const liquidationBonus = calculateLiquidationBonus(disclose(repaymentCoin.value));
+
+ // Transfer collateral to liquidator (with explicit disclosure)
+ const collateralToTransfer = (disclose(repaymentCoin.value) + liquidationBonus) as Uint<128>;
+
+ const sendResult = send(
+ collateralPool.lookup(disclose(positionCommitment)),
+ left(ownPublicKey()),
+ disclose(collateralToTransfer) // Add disclose() here
+ );
+
+ // Update or remove position
+ updateOrRemovePosition(positionCommitment);
+}
+
+/**
+ * @dev Repay debt circuit
+ * @notice Allows users to repay their debt partially or fully
+ * @param positionCommitment The commitment to the user's position
+ * @param repaymentCoin The coin used for repayment
+ * @param repaymentAmount The amount being repaid (kept private)
+ */
+export circuit repayDebt(
+ positionCommitment: Bytes<32>,
+ repaymentCoin: CoinInfo,
+ repaymentAmount: Uint<128>
+): [] {
+ // Verify position ownership
+ const path = disclose(findCollateralPosition(positionCommitment));
+ assert(collateralPositions.checkRoot(merkleTreePathRoot<100, Bytes<32>>(path)),
+ "Position not found");
+
+ // Verify user owns this position
+ assert(verifyPositionOwnership(positionCommitment), "Not position owner");
+
+ // Receive repayment
+ receive(disclose(repaymentCoin));
+
+ // Get current debt amount via witness
+ const currentDebt = getCurrentDebt(positionCommitment);
+
+ // Calculate new debt
+ const newDebt = currentDebt - disclose(repaymentAmount);
+
+ // Update debt commitment
+ const newDebtCommit = persistentCommit>(newDebt, disclose(getRandomness()));
+
+ // If fully repaid, allow collateral withdrawal
+ if (newDebt == 0 as Uint<128>) {
+ // Mark position as repaid, allowing collateral withdrawal
+ markPositionRepaid(positionCommitment);
+ }
+}
+
+/**
+ * @dev Withdraw collateral circuit
+ * @notice Allows users to withdraw collateral while maintaining health factor
+ * @param positionCommitment The commitment to the user's position
+ * @param withdrawAmount The amount to withdraw (kept private)
+ */
+export circuit withdrawCollateral(
+ positionCommitment: Bytes<32>,
+ withdrawAmount: Uint<128>
+): [] {
+ // Verify position ownership
+ assert(verifyPositionOwnership(positionCommitment), "Not position owner");
+
+ // Verify withdrawal maintains health factor
+ assert(verifyHealthFactorAfterWithdrawal(positionCommitment, disclose(withdrawAmount)),
+ "Withdrawal would violate health factor");
+
+ // Send collateral to user
+ const sendResult = send(
+ collateralPool.lookup(disclose(positionCommitment)),
+ left(ownPublicKey()),
+ disclose(withdrawAmount)
+ );
+
+ // Update collateral commitment
+ updateCollateralCommitment(positionCommitment, disclose(withdrawAmount));
+}
+
+/**
+ * @dev Supply to lending pool circuit
+ * @notice Allows users to supply assets to earn interest
+ * @param supplyCoin The coin to supply to the pool
+ * @param supplyAmount The amount being supplied
+ */
+export circuit supplyToPool(
+ supplyCoin: CoinInfo,
+ supplyAmount: Uint<128>
+): [] {
+ // Receive supply
+ receive(disclose(supplyCoin));
+
+ // Create supply position commitment
+ const userCommit = generateUserCommitment(disclose(getSecretKey()));
+ const supplyCommit = persistentCommit>(disclose(supplyAmount), disclose(getRandomness()));
+
+ // Store supply position
+ const supplyPosition = SupplyPosition {
+ userCommitment: userCommit,
+ supplyCommitment: supplyCommit,
+ assetType: disclose(supplyCoin.color),
+ timestamp: disclose(getCurrentTime())
+ };
+
+ supplyPositions.insert(disclose(userCommit));
+
+ // Update total supplied (cast to Uint<128>)
+ const currentTotal = totalSuppliedByAsset.lookup(disclose(supplyCoin.color));
+ totalSuppliedByAsset.insert(disclose(supplyCoin.color), (currentTotal + disclose(supplyAmount)) as Uint<128>);
+}
+
+/**
+ * @dev Calculate interest rate circuit
+ * @notice Computes the current interest rate based on pool utilization
+ * @param assetType The asset type (coin color) to calculate interest rate for
+ * @return The current interest rate in basis points
+ */
+export circuit calculateInterestRate(assetType: Bytes<32>): Uint<64> {
+ const totalBorrowed = totalBorrowedByAsset.lookup(disclose(assetType));
+ const totalSupplied = totalSuppliedByAsset.lookup(disclose(assetType));
+
+ // Calculate utilization rate using witness function
+ const utilizationRate = calculateUtilizationRate(totalBorrowed, totalSupplied);
+
+ // Apply interest rate model
+ const interestRate = applyInterestRateModel(disclose(utilizationRate));
+
+ return disclose(interestRate);
+}
\ No newline at end of file
diff --git a/packages/midnight-contracts-wizard/contracts/oracle/oracle.compact b/packages/midnight-contracts-wizard/contracts/oracle/oracle.compact
new file mode 100644
index 000000000..c84f0bbfa
--- /dev/null
+++ b/packages/midnight-contracts-wizard/contracts/oracle/oracle.compact
@@ -0,0 +1,278 @@
+pragma language_version >= 0.16.0;
+
+import CompactStandardLibrary;
+
+/**
+ * @dev Trusted oracle operator registry
+ * @notice Merkle tree storing authorized oracle operator commitments for privacy-preserving authorization
+ */
+export ledger authorizedOperators: MerkleTree<100, Bytes<32>>;
+
+/**
+ * @dev Oracle address
+ * @notice Stores the address of the trusted oracle for signature verification
+ */
+export ledger oracleAddress: Uint<32>;
+
+/**
+ * @dev Oracle data value
+ * @notice Stores the current value updated by the oracle
+ */
+export ledger dataValue: Uint<64>;
+
+/**
+ * @dev Oracle feeds registry
+ * @notice Maps data keys to their latest oracle data points with metadata
+ */
+export ledger oracleFeeds: Map, OracleDataPoint>;
+
+/**
+ * @dev Authorized auditors registry
+ * @notice Merkle tree storing authorized auditor commitments for compliance and oversight
+ */
+export ledger authorizedAuditors: MerkleTree<100, Bytes<32>>;
+
+/**
+ * @dev Contract owner
+ * @notice Stores the contract owner's public key for administrative functions
+ */
+export ledger owner: Bytes<32>;
+
+/**
+ * @dev Oracle data point structure
+ * @notice Represents a single oracle data submission with value, timestamp, and operator metadata
+ * @param value The oracle data value (e.g., price, rate, or other metric)
+ * @param timestamp Unix timestamp when the data was submitted
+ * @param operator Commitment hash of the operator who submitted the data
+ */
+struct OracleDataPoint {
+ value: Uint<128>;
+ timestamp: Uint<64>;
+ operator: Bytes<32>;
+}
+
+/**
+ * @dev Constructor
+ * @notice Initializes the oracle contract with the trusted oracle address
+ * @param oracle The address of the trusted oracle for signature verification
+ */
+constructor(oracle: Uint<32>) {
+ oracleAddress = disclose(oracle);
+ dataValue = 0; // Initialize with a default value
+}
+
+/**
+ * @dev Verify signature witness
+ * @notice Verifies a digital signature against data and oracle address
+ * @param signature The 64-byte signature to verify
+ * @param data The 32-byte data that was signed
+ * @param oracleAddress The oracle's address for verification
+ * @return Boolean indicating whether the signature is valid
+ */
+witness verifySignature(signature: Bytes<64>, data: Bytes<32>, oracleAddress: Uint<32>): Boolean;
+
+/**
+ * @dev Hash data witness
+ * @notice Computes a hash of the provided value for signature verification
+ * @param newValue The value to hash
+ * @return A 32-byte hash of the input value
+ */
+witness hashData(newValue: Uint<64>): Bytes<32>;
+
+/**
+ * @dev Get private oracle data witness
+ * @notice Provides oracle data privately for zero-knowledge proof generation
+ * @param dataKey The identifier for the data feed
+ * @return The oracle data value (kept private)
+ */
+witness getPrivateOracleData(dataKey: Bytes<32>): Uint<128>;
+
+/**
+ * @dev Validate data freshness witness
+ * @notice Checks if oracle data is recent enough for use
+ * @param dataKey The data feed identifier
+ * @param maxAge Maximum acceptable age in seconds
+ * @return Boolean indicating whether the data is fresh enough
+ */
+witness validateDataFreshness(dataKey: Bytes<32>, maxAge: Uint<64>): Boolean;
+
+/**
+ * @dev Find operator witness
+ * @notice Provides the Merkle tree path for an operator's authorization proof
+ * @param operatorCommitment The operator's commitment hash
+ * @return The Merkle tree path proving the operator is authorized
+ */
+witness findOperator(operatorCommitment: Bytes<32>): MerkleTreePath<100, Bytes<32>>;
+
+/**
+ * @dev Get current time witness
+ * @notice Provides the current timestamp for recording updates and freshness checks
+ * @return The current Unix timestamp in seconds
+ */
+witness getCurrentTime(): Uint<64>;
+
+/**
+ * @dev Find auditor witness
+ * @notice Provides the Merkle tree path for an auditor's authorization proof
+ * @param auditorCommitment The auditor's commitment hash
+ * @return The Merkle tree path proving the auditor is authorized
+ */
+witness findAuditor(auditorCommitment: Bytes<32>): MerkleTreePath<100, Bytes<32>>;
+
+/**
+ * @dev Get secret key witness
+ * @notice Provides the caller's secret key for owner verification
+ * @return The caller's 32-byte secret key
+ */
+witness getSecretKey(): Bytes<32>;
+
+/**
+ * @dev Register oracle operator circuit
+ * @notice Allows the contract owner to register a new authorized oracle operator
+ * @param operatorCommitment Hash commitment of the operator's credentials
+ */
+export circuit registerOperator(operatorCommitment: Bytes<32>): [] {
+ // Verify caller is contract owner
+ const callerPk = persistentHash>(disclose(getSecretKey()));
+ assert(owner == callerPk, "Only owner can register operators");
+
+ authorizedOperators.insert(disclose(operatorCommitment));
+}
+
+/**
+ * @dev Submit oracle data circuit
+ * @notice Allows authorized operators to submit oracle data with cryptographic proof of authorization
+ * @param dataKey Identifier for the data feed (e.g., price pair, metric name)
+ * @param dataValue The oracle data value to store
+ * @param timestamp Unix timestamp when the data was observed
+ * @param operatorProof The operator's commitment hash for authorization verification
+ */
+export circuit submitOracleData(
+ dataKey: Bytes<32>,
+ dataValue: Uint<128>,
+ timestamp: Uint<64>,
+ operatorProof: Bytes<32>
+): [] {
+ // Verify operator is authorized using Merkle proof
+ const path = disclose(findOperator(operatorProof));
+ assert(authorizedOperators.checkRoot(merkleTreePathRoot<100, Bytes<32>>(path)),
+ "Unauthorized oracle operator");
+
+ // Create the OracleDataPoint struct
+ const dataPoint = OracleDataPoint {
+ value: disclose(dataValue),
+ timestamp: disclose(timestamp),
+ operator: disclose(operatorProof)
+ };
+
+ // Insert the complete struct into the map
+ oracleFeeds.insert(disclose(dataKey), dataPoint);
+}
+
+/**
+ * @dev Get oracle data circuit
+ * @notice Retrieves the current oracle data value with freshness validation
+ * @param dataKey The identifier for the data feed to retrieve
+ * @param maxAge Maximum acceptable age in seconds for the data to be considered valid
+ * @return The current oracle data value if it passes freshness checks
+ */
+export circuit getOracleData(dataKey: Bytes<32>, maxAge: Uint<64>): Uint<128> {
+ assert(oracleFeeds.member(disclose(dataKey)), "Oracle data not found");
+
+ const dataPoint = oracleFeeds.lookup(disclose(dataKey));
+
+ // Verify data freshness
+ const currentTime = disclose(getCurrentTime());
+ assert(currentTime - dataPoint.timestamp <= disclose(maxAge), "Oracle data is stale");
+
+ // Return only the value
+ return dataPoint.value;
+}
+
+/**
+ * @dev Verify oracle condition circuit
+ * @notice Proves that oracle data meets a threshold condition without revealing the actual value
+ * @param dataKey The identifier for the data feed to verify
+ * @param threshold The threshold value to compare against
+ * @return Boolean indicating whether the oracle value meets or exceeds the threshold
+ */
+export circuit verifyOracleCondition(
+ dataKey: Bytes<32>,
+ threshold: Uint<128>
+): Boolean {
+ const oracleValue = getPrivateOracleData(disclose(dataKey));
+ return disclose(oracleValue) >= disclose(threshold);
+}
+
+/**
+ * @dev Check collateral ratio circuit
+ * @notice Verifies that collateral value meets the required ratio (150%) without revealing exact amounts
+ * @param collateralAmount The amount of collateral held (kept private)
+ * @param debtAmount The amount of debt owed (kept private)
+ * @param priceKey The identifier for the price feed to use in valuation
+ * @return Boolean indicating whether the collateral ratio requirement is met
+ */
+export circuit checkCollateralRatio(
+ collateralAmount: Uint<128>,
+ debtAmount: Uint<128>,
+ priceKey: Bytes<32>
+): Boolean {
+ const price = getPrivateOracleData(disclose(priceKey));
+
+ // Calculate collateral value and required collateral (150% ratio)
+ const collateralValue = (disclose(collateralAmount) as Field) * (disclose(price) as Field);
+ const requiredCollateral = (disclose(debtAmount) as Field) * (150 as Field);
+
+ return (collateralValue as Uint<128>) >= (requiredCollateral as Uint<128>);
+}
+
+/**
+ * @dev Register auditor circuit
+ * @notice Allows the contract owner to register a new authorized auditor for compliance oversight
+ * @param auditorCommitment Hash commitment of the auditor's credentials
+ */
+export circuit registerAuditor(auditorCommitment: Bytes<32>): [] {
+ // Verify caller is contract owner
+ const callerPk = persistentHash>(disclose(getSecretKey()));
+ assert(owner == callerPk, "Only owner can register auditors");
+
+ authorizedAuditors.insert(disclose(auditorCommitment));
+}
+
+/**
+ * @dev Disclose oracle data to auditor circuit
+ * @notice Allows authorized auditors to access oracle data for compliance and oversight purposes
+ * @param dataKey The identifier for the data feed to disclose
+ * @param auditorKey The auditor's public key or commitment hash
+ * @return The complete oracle data point including value, timestamp, and operator information
+ */
+export circuit discloseToAuditor(
+ dataKey: Bytes<32>,
+ auditorKey: Bytes<32>
+): OracleDataPoint {
+ // Verify auditor is authorized using Merkle proof
+ const path = disclose(findAuditor(disclose(auditorKey)));
+ assert(authorizedAuditors.checkRoot(merkleTreePathRoot<100, Bytes<32>>(path)),
+ "Unauthorized auditor");
+
+ // Verify the data exists
+ assert(oracleFeeds.member(disclose(dataKey)), "Oracle data not found");
+
+ // Retrieve and return the oracle data
+ const dataPoint = oracleFeeds.lookup(disclose(dataKey));
+ return dataPoint;
+}
+
+/**
+ * @dev Update oracle value circuit
+ * @notice Allows a trusted oracle to update the data value with cryptographic signature verification
+ * @param newValue The new oracle data value to store
+ * @param signature The oracle's 64-byte signature over the combined data and value
+ * @param data The 32-byte data context (e.g., data feed identifier) for the update
+ */
+export circuit updateValue(newValue: Uint<64>, signature: Bytes<64>, data: Bytes<32>): [] {
+ // Hash both the data context and new value for signature verification
+ const message = persistentHash<[Bytes<32>, Uint<64>]>([disclose(data), disclose(newValue)]);
+ assert(verifySignature(disclose(signature), message, oracleAddress), "Invalid signature");
+ dataValue = disclose(newValue);
+}
diff --git a/packages/midnight-contracts-wizard/contracts/staking/staking.compact b/packages/midnight-contracts-wizard/contracts/staking/staking.compact
new file mode 100644
index 000000000..ef32d6216
--- /dev/null
+++ b/packages/midnight-contracts-wizard/contracts/staking/staking.compact
@@ -0,0 +1,332 @@
+pragma language_version >= 0.16.0;
+
+import CompactStandardLibrary;
+
+// =======================
+// Enums
+// =======================
+
+/**
+ * @dev Staking status for users
+ * @notice Defines the possible states a user can be in regarding their staking position
+ * - NotStaked: User has no active stake
+ * - Staked: User has an active stake that can be unstaked
+ * - Locked: User's stake is locked and cannot be unstaked until the lock period expires
+ */
+enum StakingStatus {
+ NotStaked,
+ Staked,
+ Locked
+}
+
+// =======================
+// Ledger State (Public)
+// =======================
+
+/**
+ * @dev Total staked supply
+ * @notice Tracks the total amount of tokens currently staked in the contract
+ */
+export ledger totalStakedSupply: Uint<64>;
+
+/**
+ * @dev Lock period
+ * @notice Minimum duration (in time units) that tokens must remain staked
+ */
+export ledger lockPeriod: Uint<64>;
+
+/**
+ * @dev Contract owner
+ * @notice Address of the contract owner who can perform administrative functions
+ */
+export ledger ownerId: Uint<32>;
+
+/**
+ * @dev Transaction counter
+ * @notice Increments with each state-changing operation to prevent replay attacks
+ */
+export ledger nonce: Counter;
+
+/**
+ * @dev Stake start time
+ * @notice Stores the timestamp when staking began (public)
+ */
+export ledger stakeStartTime: Uint<64>;
+
+/**
+ * @dev Reward rate value
+ * @notice Stores the current reward rate for staking calculations
+ */
+export ledger rewardRateValue: Uint<64>;
+
+/**
+ * @dev Staked balances
+ * @notice Maps each user ID to their total staked token amount
+ */
+export ledger stakedBalances: Map, Uint<64>>;
+
+/**
+ * @dev Reward balances
+ * @notice Maps each user ID to their accumulated rewards that can be claimed
+ */
+export ledger rewardBalances: Map, Uint<64>>;
+
+/**
+ * @dev User staking status
+ * @notice Maps each user ID to their current staking status (NotStaked, Staked, or Locked)
+ */
+export ledger userStatus: Map, StakingStatus>;
+
+
+// =======================
+// Witness State (Private)
+// =======================
+
+/**
+ * @dev Private stake start time
+ * @notice Provides the private stake start time for ZK proof generation
+ */
+witness getStakeStartTime(): Uint<64>;
+
+/**
+ * @dev Private reward rate
+ * @notice Provides the private reward rate for ZK proof generation
+ */
+witness getRewardRate(): Uint<64>;
+
+/**
+ * @dev Private balance
+ * @notice Provides the private balance for ZK proof generation
+ */
+witness getBalance(): Uint<64>;
+
+// =======================
+// Constructor
+// =======================
+
+/**
+ * @dev Constructor
+ * @notice Initializes the staking contract with the owner ID, lock period, and reward rate
+ * @param initialOwnerId The address of the contract owner who can perform administrative functions
+ * @param initialLockPeriod The minimum duration (in time units) that tokens must remain staked
+ * @param initialRewardRate The initial reward rate for staking calculations
+ */
+constructor(initialOwnerId: Uint<32>, initialLockPeriod: Uint<64>, initialRewardRate: Uint<64>) {
+ totalStakedSupply = 0;
+ lockPeriod = disclose(initialLockPeriod);
+ ownerId = disclose(initialOwnerId);
+ rewardRateValue = disclose(initialRewardRate);
+}
+
+// =======================
+// Witness Functions (For ZK Proofs)
+// =======================
+
+/**
+ * @dev Private check to ensure lock-up period has passed
+ * @notice Verifies if the lock-up period has passed for a given user
+ * @param stakerId The ID of the staker to check
+ * @param currentTime The current timestamp to compare against
+ * @return Boolean indicating whether the lock-up period has passed
+ */
+witness checkLockPeriod(stakerId: Uint<32>, currentTime: Uint<64>): Boolean;
+
+/**
+ * @dev Private calculation of accrued rewards
+ * @notice Calculates the accrued rewards for a given user based on their stake and time
+ * @param stakerId The ID of the staker
+ * @param currentTime The current timestamp for reward calculation
+ * @return The amount of accrued rewards
+ */
+witness calculateRewards(stakerId: Uint<32>, currentTime: Uint<64>): Uint<64>;
+
+/**
+ * @dev Private verification of sufficient funds for staking
+ * @notice Verifies if the user has sufficient funds to stake the requested amount
+ * @param stakerId The ID of the staker
+ * @param amount The amount to be staked
+ * @return Boolean indicating whether the user has sufficient funds
+ */
+witness verifyStakeAmount(stakerId: Uint<32>, amount: Uint<64>): Boolean;
+
+// =======================
+// Circuits (Transition Functions)
+// =======================
+
+/**
+ * @dev Stake function
+ * @notice Allows a user to stake tokens, which are locked for the configured lock period
+ * @param stakerId The ID of the user staking tokens
+ * @param amount The amount of tokens to stake
+ * @param currentTime The current timestamp for recording the stake start time
+ */
+export circuit stake(
+ stakerId: Uint<32>,
+ amount: Uint<64>,
+ currentTime: Uint<64>
+): [] {
+ // Verify sufficient funds privately
+ const isValid = verifyStakeAmount(disclose(stakerId), disclose(amount));
+ assert(isValid, "Insufficient private token balance");
+
+ // Update staked balance
+ const currentStake = stakedBalances.member(disclose(stakerId))
+ ? stakedBalances.lookup(disclose(stakerId))
+ : 0 as Uint<64>;
+
+ stakedBalances.insert(disclose(stakerId), (currentStake + disclose(amount)) as Uint<64>);
+
+ // Update total supply
+ totalStakedSupply = (totalStakedSupply + disclose(amount)) as Uint<64>;
+
+ // Update stake start time
+ stakeStartTime = disclose(currentTime);
+
+ // Update user status to Locked
+ userStatus.insert(disclose(stakerId), StakingStatus.Locked);
+
+ nonce.increment(1);
+}
+
+/**
+ * @dev Unstake function
+ * @notice Allows a user to unstake tokens after the lock period has passed
+ * @param stakerId The ID of the user unstaking tokens
+ * @param amount The amount of tokens to unstake
+ * @param currentTime The current timestamp for verifying the lock period
+ */
+export circuit unstake(
+ stakerId: Uint<32>,
+ amount: Uint<64>,
+ currentTime: Uint<64>
+): [] {
+ // Check if lock period has passed privately
+ const isLockPeriodPassed = checkLockPeriod(disclose(stakerId), disclose(currentTime));
+ assert(isLockPeriodPassed, "Lock-up period not completed");
+
+ // Check user has sufficient stake
+ assert(stakedBalances.member(disclose(stakerId)), "No staked balance found");
+ const currentStake = stakedBalances.lookup(disclose(stakerId));
+ assert(currentStake >= disclose(amount), "Insufficient staked amount");
+
+ // Update staked balance
+ stakedBalances.insert(disclose(stakerId), (currentStake - disclose(amount)) as Uint<64>);
+
+ // Update total supply
+ totalStakedSupply = (totalStakedSupply - disclose(amount)) as Uint<64>;
+
+ // Update status if balance is zero
+ if ((currentStake - disclose(amount)) == 0 as Uint<64>) {
+ userStatus.insert(disclose(stakerId), StakingStatus.NotStaked);
+ } else {
+ // Re-lock remaining stake
+ stakeStartTime = disclose(currentTime);
+ userStatus.insert(disclose(stakerId), StakingStatus.Locked);
+ }
+
+ nonce.increment(1);
+}
+
+/**
+ * @dev Claim rewards function
+ * @notice Allows a user to claim their accumulated staking rewards
+ * @param stakerId The ID of the user claiming rewards
+ * @param currentTime The current timestamp for reward calculation
+ */
+export circuit claimRewards(
+ stakerId: Uint<32>,
+ currentTime: Uint<64>
+): [] {
+ // Calculate rewards privately
+ const rewardsToClaim = calculateRewards(disclose(stakerId), disclose(currentTime));
+
+ // Assert that rewards are positive
+ assert(rewardsToClaim > 0, "No rewards to claim");
+
+ // Update public reward balance
+ const currentRewards = rewardBalances.member(disclose(stakerId))
+ ? rewardBalances.lookup(disclose(stakerId))
+ : 0 as Uint<64>;
+
+ rewardBalances.insert(disclose(stakerId), (currentRewards + disclose(rewardsToClaim)) as Uint<64>);
+
+ nonce.increment(1);
+}
+
+/**
+ * @dev Update reward rate function
+ * @notice Updates the global reward rate for all stakers (owner only)
+ * @param callerId The ID of the caller (must be the contract owner)
+ * @param newRewardRate The new reward rate to be applied
+ */
+export circuit updateRewardRate(
+ callerId: Uint<32>,
+ newRewardRate: Uint<64>
+): [] {
+ // Access control: Only owner can update the rate
+ assert(ownerId == disclose(callerId), "Only contract owner can update reward rate");
+
+ // Update global reward rate
+ rewardRateValue = disclose(newRewardRate);
+
+ nonce.increment(1);
+}
+
+/**
+ * @dev Update lock period function
+ * @notice Updates the global lock period for all stakers (owner only)
+ * @param callerId The ID of the caller (must be the contract owner)
+ * @param newLockPeriod The new lock period duration (in time units)
+ */
+export circuit updateLockPeriod(
+ callerId: Uint<32>,
+ newLockPeriod: Uint<64>
+): [] {
+ // Access control: Only owner can update the lock period
+ assert(ownerId == disclose(callerId), "Only contract owner can update lock period");
+
+ // Update public lock period
+ lockPeriod = disclose(newLockPeriod);
+
+ nonce.increment(1);
+}
+
+// =======================
+// Query Functions (Publicly readable ledger state)
+// =======================
+
+/**
+ * @dev Query stake function
+ * @notice Returns the total staked amount for a specified user
+ * @param stakerId The ID of the user to query
+ * @return The amount of tokens currently staked by the user, or 0 if no stake exists
+ */
+export circuit queryStake(stakerId: Uint<32>): Uint<64> {
+ return stakedBalances.member(disclose(stakerId))
+ ? stakedBalances.lookup(disclose(stakerId))
+ : 0 as Uint<64>;
+}
+
+/**
+ * @dev Query rewards function
+ * @notice Returns the accumulated rewards for a specified user
+ * @param stakerId The ID of the user to query
+ * @return The amount of rewards accumulated by the user, or 0 if no rewards exist
+ */
+export circuit queryRewards(stakerId: Uint<32>): Uint<64> {
+ return rewardBalances.member(disclose(stakerId))
+ ? rewardBalances.lookup(disclose(stakerId))
+ : 0 as Uint<64>;
+}
+
+/**
+ * @dev Query status function
+ * @notice Returns the current staking status for a specified user
+ * @param stakerId The ID of the user to query
+ * @return The user's staking status (NotStaked, Staked, or Locked), or NotStaked if no status exists
+ */
+export circuit queryStatus(stakerId: Uint<32>): StakingStatus {
+ return userStatus.member(disclose(stakerId))
+ ? userStatus.lookup(disclose(stakerId))
+ : StakingStatus.NotStaked;
+}
diff --git a/packages/midnight-contracts-wizard/contracts/tokenization/TokenizationLibrary.compact b/packages/midnight-contracts-wizard/contracts/tokenization/TokenizationLibrary.compact
new file mode 100644
index 000000000..1dd34a7a5
--- /dev/null
+++ b/packages/midnight-contracts-wizard/contracts/tokenization/TokenizationLibrary.compact
@@ -0,0 +1,23 @@
+module TokenizationLibrary {
+ export {generateOwnersPK, Investor, generateCommit};
+ import CompactStandardLibrary;
+
+ struct Investor {
+ id: Bytes<32>;
+ investment: Uint<32>;
+ coinType: Bytes<32>;
+ };
+
+ circuit generateOwnersPK(address: Bytes<32>, sk: Bytes<32>, rand: Bytes<32>): Bytes<32>{
+ return persistentHash>>([
+ pad(32, "tokenless:user"),
+ persistentHash>>([
+ address, sk, rand,
+ ])
+ ]);
+ }
+ circuit generateCommit(data: Investor, rand: Bytes<32>): Bytes<32>{
+ return persistentCommit(data, rand);
+ }
+
+}
\ No newline at end of file
diff --git a/packages/midnight-contracts-wizard/contracts/tokenization/tokenization.compact b/packages/midnight-contracts-wizard/contracts/tokenization/tokenization.compact
new file mode 100644
index 000000000..ff4c9b974
--- /dev/null
+++ b/packages/midnight-contracts-wizard/contracts/tokenization/tokenization.compact
@@ -0,0 +1,362 @@
+pragma language_version >= 0.16.0;
+
+import CompactStandardLibrary;
+import TokenizationLibrary;
+
+/**
+ * @dev Exported types
+ * @notice Makes custom project types available to external consumers
+ * - Project: Represents a crowdfunding project with its details and state
+ * - ProjectStatus: Enum defining the possible states of a project
+ */
+export {Project, ProjectStatus};
+
+/**
+ * @dev Project status enumeration
+ * @notice Defines the possible states a project can be in during its lifecycle
+ * - Active: Project is currently accepting investments
+ * - Withdrawn: Project has been withdrawn by the creator
+ * - Closed: Project has reached its goal or deadline and is no longer accepting investments
+ */
+enum ProjectStatus {
+ Active,
+ Withdrawn,
+ Closed
+}
+
+/**
+ * @dev Protocol total value locked
+ * @notice Maps coin types to their qualified coin information, tracking all coins deposited into the protocol
+ */
+export ledger protocolTVL: Map, QualifiedCoinInfo>;
+
+/**
+ * @dev Projects registry
+ * @notice Maps project IDs to their project data, storing all projects created on-chain
+ */
+export ledger projects: Map, Project>;
+
+/**
+ * @dev Investor commitments
+ * @notice Merkle tree storing investor commitment hashes anonymously using zero-knowledge proofs
+ */
+export ledger investors: MerkleTree<100, Bytes<32>>;
+
+
+/**
+ * @dev Project structure
+ * @notice Represents a crowdfunding project with all its details and current state
+ * @param id Unique identifier for the project
+ * @param title Project title (opaque string)
+ * @param desc Project description (opaque string)
+ * @param owner Address of the project owner/creator
+ * @param investmentGoal Target funding goal for the project
+ * @param raised Total amount raised so far
+ * @param investors Number of investors who have contributed
+ * @param duration Project duration in time units
+ * @param creationDate Timestamp when the project was created
+ * @param status Current status of the project (Active, Withdrawn, or Closed)
+ * @param coinType Type of coin accepted for investments
+ */
+struct Project {
+ id: Bytes<32>;
+ title: Opaque<"string">;
+ desc: Opaque<"string">;
+ owner: Bytes<32>;
+ investmentGoal: Uint<128>;
+ raised: Uint<128>;
+ investors: Uint<128>;
+ duration: Uint<128>;
+ creationDate: Uint<128>;
+ status: ProjectStatus;
+ coinType: Bytes<32>;
+}
+
+/**
+ * @dev Local secret key witness
+ * @notice Provides the user's private secret key for generating commitments and identifiers
+ * @return The user's 32-byte secret key
+ */
+witness localSecretKey(): Bytes<32>;
+
+/**
+ * @dev Project expiration check witness
+ * @notice Verifies whether a project has expired based on its duration and start date
+ * @param duration The project's duration in time units
+ * @param startDate The timestamp when the project was created
+ * @return Boolean indicating whether the project is still valid (false if expired)
+ */
+witness confirmProjectExpiration(duration: Uint<128>, startDate: Uint<128>): Boolean;
+
+/**
+ * @dev Investor commitment proof witness
+ * @notice Finds the Merkle tree path for an investor's commitment hash to prove their investment anonymously
+ * @param commitment The investor's commitment hash
+ * @return The Merkle tree path proving the commitment exists in the investors tree
+ */
+witness findInvestor(commitment: Bytes<32>): MerkleTreePath<100, Bytes<32>>;
+
+
+// =======================
+// Interaction for project creation and management
+// =======================
+
+/**
+ * @dev Create project circuit
+ * @notice Allows users to create a new crowdfunding project on-chain
+ * @param projectId Unique identifier for the new project
+ * @param investmentGoal Target funding goal for the project
+ * @param duration Project duration in time units
+ * @param coinType Type of coin accepted for investments
+ * @param currentDate Current timestamp for recording the creation date
+ * @param title Project title (opaque string)
+ * @param desc Project description (opaque string)
+ */
+export circuit createProject(
+ projectId: Bytes<32>,
+ investmentGoal: Uint<128>,
+ duration: Uint<128>,
+ coinType: Bytes<32>,
+ currentDate: Uint<128>,
+ title: Opaque<"string">,
+ desc: Opaque<"string">
+): [] {
+ const disclosedId = disclose(projectId);
+ assert (!projects.member(disclosedId), "Project with same ID already exists");
+
+ // Generate a unique hash representing the project owner without revealing their public key
+ const ownersHash = generateOwnersPK(ownPublicKey().bytes, disclose(localSecretKey()), disclosedId);
+
+ const newProject = Project{
+ ...default,
+ title: disclose(title),
+ desc: disclose(desc),
+ status: ProjectStatus.Active,
+ investmentGoal: disclose(investmentGoal),
+ duration: disclose(duration),
+ owner: ownersHash,
+ coinType: disclose(coinType),
+ creationDate: disclose(currentDate)
+ };
+
+ projects.insert(disclosedId, newProject);
+}
+
+/**
+ * @dev Cancel project circuit
+ * @notice Allows the project owner to cancel and remove their project from the on-chain registry
+ * @param projectId The unique identifier of the project to cancel
+ */
+export circuit cancelProject(projectId: Bytes<32>): [] {
+ const disclosedId = disclose(projectId);
+
+ assert (projects.member(disclosedId), "Project with specified ID does not exist");
+ const projectToEnd = projects.lookup(disclosedId);
+ const reconstructedOwnersHash = generateOwnersPK(ownPublicKey().bytes, disclose(localSecretKey()), disclosedId);
+
+ assert (reconstructedOwnersHash == projectToEnd.owner, "Can not end this project: You are not the owner");
+
+ // Remove the project from the on-chain registry
+ projects.remove(disclosedId);
+}
+
+/**
+ * @dev Withdraw project funds circuit
+ * @notice Allows the project owner to withdraw funds after the project reaches its goal or closes
+ * @param projectId The unique identifier of the project to withdraw funds from
+ */
+export circuit withdrawProjectFunds(projectId: Bytes<32>): []{
+ const disclosedId = disclose(projectId);
+ assert (projects.member(disclosedId), "Project with the specified ID does not exist");
+
+ const projectToWithdrawFrom = projects.lookup(disclosedId);
+ const reconstructedOwnersHash = generateOwnersPK(ownPublicKey().bytes, disclose(localSecretKey()), disclosedId);
+
+ assert (reconstructedOwnersHash == projectToWithdrawFrom.owner, "Can not end this project: You are not the owner");
+ assert (projectToWithdrawFrom.raised >= projectToWithdrawFrom.investmentGoal || projectToWithdrawFrom.status == ProjectStatus.Closed, "Project funds is less than the investment goal");
+
+ const sendResult = send(
+ protocolTVL.lookup(projectToWithdrawFrom.coinType),
+ left(ownPublicKey()),
+ projectToWithdrawFrom.investmentGoal
+ );
+
+ sendResult.change.is_some ?
+ protocolTVL.insertCoin(projectToWithdrawFrom.coinType, sendResult.change.value, left(ownPublicKey())) :
+ protocolTVL.remove(projectToWithdrawFrom.coinType);
+
+ // Update the project status to Withdrawn
+ projects.remove(disclosedId);
+
+ const updateProject = Project{
+ ...projectToWithdrawFrom,
+ status: ProjectStatus.Withdrawn
+ };
+
+ projects.insert(disclosedId, updateProject);
+}
+
+/**
+ * @dev End project circuit
+ * @notice Allows the project owner to close their project at any time and return remaining funds
+ * @param projectId The unique identifier of the project to close
+ */
+export circuit endProject(projectId: Bytes<32>): [] {
+ const disclosedId = disclose(projectId);
+
+ assert (projects.member(disclosedId), "Project with specified ID does not exist");
+ const projectToEnd = projects.lookup(disclosedId);
+ const reconstructedOwnersHash = generateOwnersPK(ownPublicKey().bytes, disclose(localSecretKey()), disclosedId);
+
+ assert (reconstructedOwnersHash == projectToEnd.owner, "Can not end this project: You are not the owner");
+
+ if(projectToEnd.raised > 0){
+ // Send raised funds to the project owner before closing
+ const sendResult = send(
+ protocolTVL.lookup(projectToEnd.coinType),
+ left(ownPublicKey()),
+ projectToEnd.raised
+ );
+
+ // Update protocol balance with any remaining change
+ sendResult.change.is_some ?
+ protocolTVL.insertCoin(projectToEnd.coinType, sendResult.change.value, right(kernel.self())) :
+ protocolTVL.remove(projectToEnd.coinType);
+ }
+
+ // Update the project status to Closed
+ projects.insert(disclosedId, Project{
+ ...projectToEnd,
+ status: ProjectStatus.Closed
+ });
+}
+
+/**
+ * @dev Update project circuit
+ * @notice Allows the project owner to update their project's details while it's still active
+ * @param projectId The unique identifier of the project to update
+ * @param title New project title (opaque string)
+ * @param desc New project description (opaque string)
+ * @param investmentGoal New target funding goal for the project
+ * @param duration New project duration in time units
+ */
+export circuit updateProject(
+ projectId: Bytes<32>,
+ title: Opaque<"string">,
+ desc: Opaque<"string">,
+ investmentGoal: Uint<128>,
+ duration: Uint<128>
+ ): []{
+ const disclosedId = disclose(projectId);
+ assert (projects.member(disclosedId), "Project with the specified ID does not exist");
+ const projectToUpdate = projects.lookup(disclosedId);
+ assert (projectToUpdate.status != ProjectStatus.Withdrawn || projectToUpdate.status != ProjectStatus.Closed, "Can not edit project: This project has ended");
+
+ const reconstructedOwnersHash = generateOwnersPK(ownPublicKey().bytes, disclose(localSecretKey()), disclosedId);
+ assert (reconstructedOwnersHash == projectToUpdate.owner, "Can not end this project: You are not the owner");
+
+ const updateProject = Project{
+ ...projectToUpdate,
+ title: disclose(title),
+ desc: disclose(desc),
+ investmentGoal: disclose(investmentGoal),
+ duration: disclose(duration),
+ };
+
+ projects.insert(disclosedId, updateProject);
+}
+
+
+/**
+ * @dev Invest in project circuit
+ * @notice Allows users to invest in an active project by depositing coins anonymously
+ * @param coin The coin information containing the investment amount and type
+ * @param projectId The unique identifier of the project to invest in
+ */
+export circuit investProject(coin: CoinInfo, projectId: Bytes<32>): []{
+ const disclosedCoin = disclose(coin);
+ const disclosedId = disclose(projectId);
+ assert (projects.member(disclosedId), "Project with the specified ID does not exist");
+ const projectToInvest = projects.lookup(disclosedId);
+ assert (projectToInvest.raised < projectToInvest.investmentGoal, "Can not invest in this project: the investment objective of the project has been reached");
+ const isProjectActive = confirmProjectExpiration(projectToInvest.duration, projectToInvest.creationDate);
+ assert (isProjectActive, "Project with specified ID is no longer active");
+ assert (projectToInvest.status != ProjectStatus.Withdrawn || projectToInvest.status != ProjectStatus.Closed, "Can not invest in the project: this project is finished");
+ assert (coin.color == projectToInvest.coinType, "Insufficient funds provided");
+ assert (coin.value <= projectToInvest.investmentGoal, "Amount is greater than investment goal");
+ receive(disclosedCoin);
+
+ const coinToInsert = protocolTVL.member(disclosedCoin.color) ?
+ mergeCoinImmediate(protocolTVL.lookup(disclosedCoin.color), disclosedCoin) :
+ disclosedCoin;
+
+ protocolTVL.insertCoin(
+ disclosedCoin.color,
+ coinToInsert,
+ right(kernel.self())
+ );
+
+ const investor = Investor{
+ id: disclose(localSecretKey()),
+ investment: disclosedCoin.value as Uint<32>,
+ coinType: disclosedCoin.color
+ };
+
+ // Create a zero-knowledge commitment of the investor’s data (amount, currency, secret ID).
+ // This commitment is stored in the investors Merkle Tree
+ const investorCommit = generateCommit(investor, disclosedId);
+ investors.insert(investorCommit);
+
+ const updateProject = Project{
+ ...projectToInvest,
+ investors: (projectToInvest.investors + 1) as Uint<128>,
+ raised: (projectToInvest.raised + disclosedCoin.value) as Uint<128>
+ };
+
+ projects.insert(disclosedId, updateProject);
+}
+
+/**
+ * @dev Request refund circuit
+ * @notice Allows an investor to request a refund from an active project using zero-knowledge proof of their investment
+ * @param projectId The unique identifier of the project to request a refund from
+ * @param refundAmount The amount the investor wishes to withdraw
+ * @param amountDeposited The total amount the investor originally deposited
+ */
+export circuit requestRefund(projectId: Bytes<32>, refundAmount: Uint<32>, amountDeposited: Uint<32>): []{
+ const disclosedId = disclose(projectId);
+
+ assert (projects.member(disclosedId), "Project with the specified ID does not exist");
+ const project = projects.lookup(disclosedId);
+ assert (project.status != ProjectStatus.Withdrawn || project.status != ProjectStatus.Closed, "Can not refund: This project has ended");
+
+ const investor = Investor{
+ id: disclose(localSecretKey()),
+ investment: disclose(amountDeposited),
+ coinType: project.coinType
+ };
+
+ const investorsCommit = generateCommit(investor, disclosedId);
+
+ const path = disclose(findInvestor(investorsCommit));
+
+ // Verify that the commitment exists in the Merkle tree of investors
+ assert(investors.checkRoot(merkleTreePathRoot<100, Bytes<32>>(path)), "You are not a valid investor for this project");
+ assert (refundAmount <= amountDeposited, "Can not withdraw more than deposited amount");
+
+ const sendResult = send(
+ protocolTVL.lookup(project.coinType),
+ left(ownPublicKey()),
+ disclose(refundAmount)
+ );
+sendResult.change.is_some ?
+ protocolTVL.insertCoin(project.coinType, sendResult.change.value, right(kernel.self())) :
+ protocolTVL.remove(project.coinType);
+
+ const updateProject = Project {
+ ...project,
+ raised: (project.raised - disclose(refundAmount)) as Uint<128>
+ };
+
+ projects.insert(disclosedId, updateProject);
+}
\ No newline at end of file
diff --git a/packages/midnight-contracts-wizard/jest.config.ts b/packages/midnight-contracts-wizard/jest.config.ts
new file mode 100644
index 000000000..f642dcb1a
--- /dev/null
+++ b/packages/midnight-contracts-wizard/jest.config.ts
@@ -0,0 +1,13 @@
+import type { Config } from "jest";
+
+const config: Config = {
+ displayName: "midnight-contracts-wizard",
+ preset: "../../jest.preset.js",
+ transform: {
+ "^.+\\.[tj]s$": ["ts-jest", { tsconfig: "/tsconfig.spec.json" }],
+ },
+ moduleFileExtensions: ["ts", "js", "html"],
+ coverageDirectory: "../../coverage/packages/midnight-contracts-wizard",
+};
+
+export default config;
diff --git a/packages/midnight-contracts-wizard/package.json b/packages/midnight-contracts-wizard/package.json
new file mode 100644
index 000000000..5384448e0
--- /dev/null
+++ b/packages/midnight-contracts-wizard/package.json
@@ -0,0 +1,62 @@
+{
+ "name": "@meshsdk/midnight-contracts-wizard",
+ "version": "1.9.0-beta.84",
+ "description": "Create a new Midnight contracts project with selected smart contracts",
+ "main": "dist/index.js",
+ "bin": {
+ "midnight-contracts-wizard": "./dist/index.js"
+ },
+ "scripts": {
+ "build": "tsc",
+ "clean": "rm -rf dist",
+ "format": "prettier --write \"src/**/*.{ts,js,json}\"",
+ "dev": "tsc --watch",
+ "lint": "eslint",
+ "pack": "npm pack",
+ "test": "jest",
+ "start": "node dist/index.js",
+ "install-cli": "node dist/install.js",
+ "prepublishOnly": "npm run build"
+ },
+ "keywords": [
+ "midnight",
+ "contracts",
+ "blockchain",
+ "privacy",
+ "zk",
+ "zero-knowledge",
+ "cli",
+ "generator"
+ ],
+ "author": "MeshJS Team",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.2",
+ "fs-extra": "^11.1.1",
+ "inquirer": "^9.2.12",
+ "ora": "^5.4.1"
+ },
+ "devDependencies": {
+ "@meshsdk/configs": "*",
+ "@types/fs-extra": "^11.0.0",
+ "@types/inquirer": "^9.0.0",
+ "@types/node": "^20.19.23",
+ "eslint": "^8.57.0",
+ "jest": "^29.7.0",
+ "prettier": "^3.0.0",
+ "ts-jest": "^29.1.0",
+ "typescript": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/MeshJS/mesh.git",
+ "directory": "packages/midnight-contracts-wizard"
+ },
+ "bugs": {
+ "url": "https://github.com/MeshJS/mesh/issues"
+ },
+ "homepage": "https://meshjs.dev/"
+}
diff --git a/packages/midnight-contracts-wizard/src/index.ts b/packages/midnight-contracts-wizard/src/index.ts
new file mode 100644
index 000000000..67af80764
--- /dev/null
+++ b/packages/midnight-contracts-wizard/src/index.ts
@@ -0,0 +1,489 @@
+#!/usr/bin/env node
+import path from "path";
+import chalk from "chalk";
+import fs from "fs-extra";
+import inquirer from "inquirer";
+import ora from "ora";
+
+// Contract interface
+interface Contract {
+ name: string;
+ description: string;
+ circuits: number;
+ files: string[];
+}
+
+// Contract templates
+const contracts: Record = {
+ tokenization: {
+ name: "Tokenization Contract",
+ description:
+ "Complete project tokenization system with ZK privacy investment",
+ circuits: 7,
+ files: [
+ "contracts/tokenization/tokenization.compact",
+ "contracts/tokenization/TokenizationLibrary.compact",
+ ],
+ },
+ staking: {
+ name: "Staking Contract",
+ description: "Privacy-focused staking system with rewards and lock periods",
+ circuits: 8,
+ files: ["contracts/staking/staking.compact"],
+ },
+ identity: {
+ name: "Identity Contracts",
+ description:
+ "Complete identity management system with cryptographic libraries",
+ circuits: 1,
+ files: [
+ "contracts/identity/IdentityLibrary.compact",
+ "contracts/identity/registry.compact",
+ "contracts/identity/CryptoLibrary.compact",
+ ],
+ },
+ oracle: {
+ name: "Oracle Contract",
+ description:
+ "Decentralized oracle system with privacy-preserving data feeds",
+ circuits: 7,
+ files: ["contracts/oracle/oracle.compact"],
+ },
+ lendingBorrowing: {
+ name: "Lending & Borrowing Contract",
+ description: "Privacy-preserving decentralized lending protocol",
+ circuits: 7,
+ files: ["contracts/lending-borrowing/lending-borrowing.compact"],
+ },
+};
+
+async function main(): Promise {
+ console.log(chalk.blue.bold("\n✨ Midnight Contracts Wizard\n"));
+ console.log(
+ chalk.gray(
+ "Create a new Midnight contracts project with selected smart contracts\n",
+ ),
+ );
+ console.log(
+ chalk.yellow(
+ "💡 Tip: Use SPACE to select contracts, then ENTER to continue\n",
+ ),
+ );
+
+ // Get project name
+ const { projectName } = await inquirer.prompt<{ projectName: string }>([
+ {
+ type: "input",
+ name: "projectName",
+ message: "What is your project name?",
+ default: "my-midnight-contracts",
+ validate: (input: string) => {
+ if (!input.trim()) {
+ return "Project name is required";
+ }
+ if (!/^[a-z0-9-]+$/.test(input)) {
+ return "Project name must contain only lowercase letters, numbers, and hyphens";
+ }
+ return true;
+ },
+ },
+ ]);
+
+ // Get project directory
+ const { projectDir } = await inquirer.prompt<{ projectDir: string }>([
+ {
+ type: "input",
+ name: "projectDir",
+ message: "Where should we create your project?",
+ default: `./${projectName}`,
+ validate: (input: string) => {
+ if (!input.trim()) {
+ return "Project directory is required";
+ }
+ return true;
+ },
+ },
+ ]);
+
+ // Select contracts
+ const { selectedContracts } = await inquirer.prompt<{
+ selectedContracts: string[];
+ }>([
+ {
+ type: "checkbox",
+ name: "selectedContracts",
+ message: "Which contracts would you like to include?",
+ choices: Object.entries(contracts).map(([key, contract]) => ({
+ name: `${contract.name} (${contract.circuits} ZK circuits)`,
+ short: contract.name,
+ value: key,
+ checked: false,
+ })),
+ validate: (input: string[]) => {
+ if (!input || input.length === 0) {
+ return "Please select at least one contract (use SPACE to select, then ENTER to continue)";
+ }
+ return true;
+ },
+ },
+ ]);
+
+ // Show summary
+ console.log(chalk.green("\n📋 Project Summary:"));
+ console.log(chalk.gray(`Project: ${projectName}`));
+ console.log(chalk.gray(`Directory: ${projectDir}`));
+ console.log(chalk.gray(`Selected contracts: ${selectedContracts.length}`));
+
+ selectedContracts.forEach((key) => {
+ const contract = contracts[key];
+ if (contract) {
+ console.log(
+ chalk.blue(` • ${contract.name} (${contract.circuits} circuits)`),
+ );
+ console.log(chalk.gray(` ${contract.description}`));
+ }
+ });
+
+ const { confirm } = await inquirer.prompt<{ confirm: boolean }>([
+ {
+ type: "confirm",
+ name: "confirm",
+ message: "Create the project with these settings?",
+ default: true,
+ },
+ ]);
+
+ if (!confirm) {
+ console.log(chalk.yellow("Project creation cancelled."));
+ return;
+ }
+
+ // Create project
+ const spinner = ora("Creating project...").start();
+
+ try {
+ await createProject(projectName, projectDir, selectedContracts);
+ spinner.succeed("Project created successfully!");
+
+ console.log(chalk.green("\n🎉 Your Midnight contracts project is ready!"));
+ console.log(chalk.gray("\n📋 Next steps:"));
+ console.log(chalk.blue("1) Navigate to the project folder:"));
+ console.log(chalk.white(` cd ${projectDir}`));
+ console.log(chalk.blue("\n2) Compile your smart contracts:"));
+ const compileCommands = generateCompileCommands(selectedContracts);
+ compileCommands.forEach((command, index) => {
+ console.log(chalk.white(` ${command}`));
+ if (index < compileCommands.length - 1) {
+ console.log(chalk.white(""));
+ }
+ });
+ console.log(
+ chalk.gray("\n💡 Your contracts will be compiled to src/managed/"),
+ );
+ console.log(chalk.gray("💡 Check the README.md for detailed instructions"));
+ } catch (error) {
+ spinner.fail("Failed to create project");
+ console.error(chalk.red("Error:"), (error as Error).message);
+ }
+}
+
+async function createProject(
+ projectName: string,
+ projectDir: string,
+ selectedContracts: string[],
+): Promise {
+ // Create project directory
+ await fs.ensureDir(projectDir);
+
+ // Create package.json
+ const packageJson = {
+ name: projectName,
+ version: "0.1.0",
+ license: "MIT",
+ type: "module",
+ main: "index.js",
+ module: "./dist/index.js",
+ types: "./dist/index.d.ts",
+ packageManager: "yarn@4.9.2",
+ exports: {
+ ".": {
+ default: "./dist/index.js",
+ import: "./dist/index.js",
+ types: "./dist/index.d.ts",
+ require: "./dist/index.js",
+ },
+ },
+ scripts: {
+ compact: generateCompactScript(selectedContracts),
+ build: generateBuildScript(selectedContracts),
+ lint: "eslint src",
+ typecheck: "tsc -p tsconfig.json --noEmit",
+ prepack: "yarn build",
+ },
+ dependencies: {
+ "@midnight-ntwrk/compact-runtime": "^0.8.1",
+ "@midnight-ntwrk/midnight-js-contracts": "2.0.2",
+ "@midnight-ntwrk/midnight-js-types": "2.0.2",
+ },
+ devDependencies: {
+ "@midnight-ntwrk/compact": "^0.8.1",
+ eslint: "^9.27.0",
+ jest: "^29.7.0",
+ typescript: "^5.8.2",
+ },
+ };
+
+ await fs.writeJson(path.join(projectDir, "package.json"), packageJson, {
+ spaces: 2,
+ });
+
+ // Create tsconfig files
+ await createTsConfig(projectDir);
+
+ // Create src directory structure
+ await fs.ensureDir(path.join(projectDir, "src"));
+ await fs.ensureDir(path.join(projectDir, "src/managed"));
+
+ // Copy selected contract files from templates
+ for (const contractKey of selectedContracts) {
+ const contract = contracts[contractKey];
+ if (!contract) continue;
+ for (const filePath of contract.files) {
+ // Get the correct path to contracts directory
+ const currentDir = path.dirname(process.argv[1] || __filename);
+ const sourcePath = path.join(currentDir, "..", filePath);
+ const destPath = path.join(projectDir, filePath);
+
+ if (await fs.pathExists(sourcePath)) {
+ await fs.ensureDir(path.dirname(destPath));
+ await fs.copy(sourcePath, destPath);
+ }
+ }
+ }
+
+ // Create .yarnrc.yml for standalone project
+ const yarnrcContent = `nodeLinker: node-modules
+enableGlobalCache: false
+`;
+ await fs.writeFile(path.join(projectDir, ".yarnrc.yml"), yarnrcContent);
+
+ // Create README
+ await createReadme(projectDir, projectName, selectedContracts);
+
+ // Create .gitignore
+ await createGitignore(projectDir);
+}
+
+function generateCompileCommands(selectedContracts: string[]): string[] {
+ return selectedContracts
+ .map((contractKey) => {
+ const contract = contracts[contractKey];
+ if (!contract) return [];
+ return contract.files.map((file) => {
+ const fileName = path.basename(file, ".compact");
+ return `compact compile ${file} ./src/managed/${fileName}`;
+ });
+ })
+ .flat();
+}
+
+function generateCompactScript(selectedContracts: string[]): string {
+ const commands = generateCompileCommands(selectedContracts);
+ return commands.join(" && ");
+}
+
+function generateBuildScript(selectedContracts: string[]): string {
+ const copyCommands = selectedContracts
+ .map((contractKey) => {
+ const contract = contracts[contractKey];
+ if (!contract) return [];
+ return contract.files.map((file) => {
+ const fileName = path.basename(file, ".compact");
+ return `test -d ./src/managed/${fileName} && cp -R ./src/managed/${fileName} ./dist/managed/`;
+ });
+ })
+ .flat();
+
+ const copySourceFiles = selectedContracts
+ .map((contractKey) => {
+ const contract = contracts[contractKey];
+ if (!contract) return [];
+ return contract.files.map((file) => `cp ${file} dist`);
+ })
+ .flat();
+
+ return `rm -rf dist && find src/managed -type d -empty -delete && tsc --project tsconfig.build.json && mkdir -p dist/managed && ${copyCommands.join(" && ")} && ${copySourceFiles.join(" && ")}`;
+}
+
+async function createTsConfig(projectDir: string): Promise {
+ const tsconfig = {
+ compilerOptions: {
+ target: "ES2022",
+ module: "ESNext",
+ moduleResolution: "node",
+ allowSyntheticDefaultImports: true,
+ esModuleInterop: true,
+ allowJs: true,
+ strict: true,
+ skipLibCheck: true,
+ forceConsistentCasingInFileNames: true,
+ declaration: true,
+ outDir: "./dist",
+ rootDir: "./src",
+ },
+ include: ["src/**/*"],
+ exclude: ["node_modules", "dist"],
+ };
+
+ const tsconfigBuild = {
+ extends: "./tsconfig.json",
+ compilerOptions: {
+ declaration: true,
+ declarationMap: true,
+ sourceMap: true,
+ },
+ exclude: ["**/*.test.ts", "**/*.spec.ts"],
+ };
+
+ await fs.writeJson(path.join(projectDir, "tsconfig.json"), tsconfig, {
+ spaces: 2,
+ });
+ await fs.writeJson(
+ path.join(projectDir, "tsconfig.build.json"),
+ tsconfigBuild,
+ { spaces: 2 },
+ );
+}
+
+async function createReadme(
+ projectDir: string,
+ projectName: string,
+ selectedContracts: string[],
+): Promise {
+ const selectedContractNames = selectedContracts
+ .map((key) => contracts[key])
+ .filter((contract): contract is Contract => contract !== undefined)
+ .map((contract) => contract.name);
+
+ const compileCommands = generateCompileCommands(selectedContracts);
+ const compileCommandsText = compileCommands.join("\n\n");
+
+ const readme = `# Midnight Contracts Wizard
+
+A Midnight contracts project with the following smart contracts:
+
+${selectedContractNames.map((name) => `- ${name}`).join("\n")}
+
+## Quick Start
+
+\`\`\`bash
+# Compile smart contracts (IMPORTANT!)
+${compileCommandsText}
+\`\`\`
+
+## 🔥 Compiling Smart Contracts
+
+**This is the most important step!** Your \`.compact\` files need to be compiled before use:
+
+\`\`\`bash
+# Compile each contract individually:
+${compileCommandsText}
+\`\`\`
+
+### What gets generated after compilation:
+
+\`\`\`
+src/managed/
+├── tokenization/ # Compiled tokenization contract
+│ ├── compiler/ # Compilation artifacts
+│ ├── contract/ # Contract bytecode
+│ ├── keys/ # Cryptographic keys
+│ └── zkir/ # ZK proof system files
+└── TokenizationLibrary/ # Compiled library
+ ├── compiler/
+ ├── contract/
+ ├── keys/
+ └── zkir/
+\`\`\`
+
+## What's Included
+
+- **Smart Contracts**: Ready-to-compile \`.compact\` files in \`contracts/\`
+- **Dependencies**: All necessary Midnight Network packages
+- **Build Scripts**: Automated compilation and build process
+- **TypeScript**: Full TypeScript support with type definitions
+- **Standalone Project**: Includes \`.yarnrc.yml\` for independent operation
+
+## Available Commands
+
+- \`compact compile [source] [output]\` - **Compile individual smart contracts**
+
+## Project Structure
+
+\`\`\`
+${projectName}/
+├── contracts/ # Source contract files (.compact)
+├── src/
+│ ├── managed/ # Compiled contracts (after compact compile)
+│ └── index.ts # Your application code
+└── package.json # Dependencies and scripts
+\`\`\`
+
+---
+
+
+
Powered by MeshJS Team
+
Built with ❤️ on Midnight Network
+
+`;
+
+ await fs.writeFile(path.join(projectDir, "README.md"), readme);
+}
+
+async function createGitignore(projectDir: string): Promise {
+ const gitignoreContent = `# Compiled contracts (generated by compact compile)
+src/managed/
+
+# Node modules
+node_modules/
+
+# Build outputs
+dist/
+build/
+
+# Environment files
+.env
+.env.local
+.env.production
+
+# IDE files
+.vscode/
+.idea/
+*.swp
+*.swo
+
+# OS files
+.DS_Store
+Thumbs.db
+
+# Logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Midnight Network compilation artifacts
+*.prover
+*.verifier
+*.zkir
+`;
+
+ await fs.writeFile(path.join(projectDir, ".gitignore"), gitignoreContent);
+}
+
+// Run the CLI
+if (require.main === module) {
+ main().catch(console.error);
+}
+
+export { main };
diff --git a/packages/midnight-contracts-wizard/src/install.ts b/packages/midnight-contracts-wizard/src/install.ts
new file mode 100644
index 000000000..7233e35dc
--- /dev/null
+++ b/packages/midnight-contracts-wizard/src/install.ts
@@ -0,0 +1,13 @@
+#!/usr/bin/env node
+import fs from "fs";
+import path from "path";
+
+// Make the main script executable
+const indexPath = path.join(__dirname, "index.js");
+fs.chmodSync(indexPath, "755");
+
+console.log("✅ midnight-contracts-wizard CLI is ready!");
+console.log("📦 To publish to npm:");
+console.log(" 1. npm login");
+console.log(" 2. npm publish");
+console.log(" 3. Users can then run: npx @meshsdk/midnight-contracts-wizard");
diff --git a/packages/midnight-contracts-wizard/tsconfig.json b/packages/midnight-contracts-wizard/tsconfig.json
new file mode 100644
index 000000000..131d426d5
--- /dev/null
+++ b/packages/midnight-contracts-wizard/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "outDir": "./dist",
+ "rootDir": "./src",
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true,
+ "module": "CommonJS",
+ "target": "ES2022",
+ "lib": ["ES2022"],
+ "moduleResolution": "node",
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "resolveJsonModule": true,
+ "allowSyntheticDefaultImports": true,
+ "types": ["node"]
+ },
+ "include": ["src/**/*"],
+ "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
+}
diff --git a/packages/midnight-setup/package.json b/packages/midnight-setup/package.json
index 6bbf4fcb2..18a1adc69 100644
--- a/packages/midnight-setup/package.json
+++ b/packages/midnight-setup/package.json
@@ -1,6 +1,6 @@
{
"name": "@meshsdk/midnight-setup",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"description": "Midnight Network integration SDK for MeshSDK - https://meshjs.dev/midnight",
"main": "./dist/index.cjs",
"browser": "./dist/index.js",
diff --git a/scripts/mesh-cli/package.json b/scripts/mesh-cli/package.json
index bef02038f..72bfdde3c 100644
--- a/scripts/mesh-cli/package.json
+++ b/scripts/mesh-cli/package.json
@@ -3,7 +3,7 @@
"description": "A quick and easy way to bootstrap your Web3 app using Mesh.",
"homepage": "https://meshjs.dev",
"author": "MeshJS",
- "version": "1.9.0-beta.83",
+ "version": "1.9.0-beta.84",
"license": "Apache-2.0",
"type": "module",
"main": "./dist/index.cjs",
diff --git a/turbo.json b/turbo.json
index 1010f53c1..5a73adcd3 100644
--- a/turbo.json
+++ b/turbo.json
@@ -3,7 +3,12 @@
"globalDependencies": ["**/.env.*local"],
"tasks": {
"build": {
- "dependsOn": ["^build:mesh", "^build:docs", "^build:apps", "^build:scripts"],
+ "dependsOn": [
+ "^build:mesh",
+ "^build:docs",
+ "^build:apps",
+ "^build:scripts"
+ ],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
},
"build:apps": {