diff --git a/packages/core/stellar/src/zip-rust.ts b/packages/core/stellar/src/zip-rust.ts index 788e8b58a..b3699b2ff 100644 --- a/packages/core/stellar/src/zip-rust.ts +++ b/packages/core/stellar/src/zip-rust.ts @@ -41,7 +41,7 @@ Continue your development journey with [Stellar CLI](https://github.com/stellar/ - See [Git installation guide](https://github.com/git-guides/install-git). `; -export async function zipRust(c: Contract, opts: GenericOptions) { +export const createRustZipEnvironment = (c: Contract, opts: GenericOptions) => { const zip = new JSZip(); const contractName = contractOptionsToContractName(opts?.kind || 'contract'); @@ -51,7 +51,11 @@ export async function zipRust(c: Contract, opts: GenericOptions) { zip.file(`contracts/${contractName}/src/lib.rs`, createRustLibFile); zip.file(`contracts/${contractName}/Cargo.toml`, printContractCargo(contractName)); zip.file('Cargo.toml', workspaceCargo); - zip.file('README.md', readme); return zip; -} +}; + +const addRustProjectReadme = (zip: JSZip) => zip.file('README.md', readme); + +export const zipRustProject = async (c: Contract, opts: GenericOptions) => + addRustProjectReadme(createRustZipEnvironment(c, opts)); diff --git a/packages/core/stellar/src/zip-scaffold.test.ts b/packages/core/stellar/src/zip-scaffold.test.ts index 39601731d..1f4ff3914 100644 --- a/packages/core/stellar/src/zip-scaffold.test.ts +++ b/packages/core/stellar/src/zip-scaffold.test.ts @@ -1,7 +1,7 @@ import type { TestFn, ExecutionContext } from 'ava'; import _test from 'ava'; -import { zipScaffold } from './zip-scaffold'; +import { zipScaffoldProject } from './zip-scaffold'; import { buildFungible } from './fungible'; import { buildNonFungible } from './non-fungible'; @@ -32,6 +32,7 @@ function assertLayout(t: ExecutionContext, zip: JSZip, opts: GenericOpt const scaffoldContractName = contractOptionsToContractName(opts?.kind || 'contract'); t.deepEqual(sorted, [ + 'Cargo.toml', 'README-WIZARD.md', 'contracts/', `contracts/${scaffoldContractName}/`, @@ -109,7 +110,7 @@ test.afterEach.always(async t => { async function runTest(t: ExecutionContext, c: Contract, opts: GenericOptions) { t.timeout(3_000_000); - const zip = await zipScaffold(c, opts); + const zip = await zipScaffoldProject(c, opts); assertLayout(t, zip, opts); await extractPackage(t, zip); diff --git a/packages/core/stellar/src/zip-scaffold.ts b/packages/core/stellar/src/zip-scaffold.ts index 56a7aeb38..67c2aeb9e 100644 --- a/packages/core/stellar/src/zip-scaffold.ts +++ b/packages/core/stellar/src/zip-scaffold.ts @@ -1,138 +1,14 @@ -import JSZip from 'jszip'; +import type JSZip from 'jszip'; import type { GenericOptions } from './build-generic'; import type { Contract } from './contract'; -import { printContract, removeCreateLevelAttributes } from './print'; -import { compatibleSorobanVersion, contractsVersionTag } from './utils/version'; -import { - addDependenciesWith, - allStellarDependencies, - contractOptionsToContractName, - createRustLibFile, - printContractCargo, - printRustNameTest, -} from './zip-shared'; +import { createRustZipEnvironment } from './zip-rust'; -function getAddressArgs(c: Contract): string[] { - return c.constructorArgs - .filter(constructorArg => constructorArg.type?.toLowerCase() === 'address') - .map(constructorArg => constructorArg.name); -} - -const setupSh = (c: Contract, opts: GenericOptions, scaffoldContractName: string) => { - const environmentsFileUpdate = (setUpContract: Contract, setUpScaffoldContractName: string) => ` -# Update environments.toml: remove original contracts and insert wizard's contract -setup_environment() { - local file="environments.toml" - local temp - temp="$(mktemp)" - - local in_dev_contracts=0 - local skip_entry=0 - local contract_entry_inserted=0 - insert_contract_entry() { - { - printf '%s\\n' "[development.contracts.${setUpScaffoldContractName}_contract]" \\ - "client = true" "" \\ - "# If your contract has a \\\`__constructor\\\`, specify your arguments to it here." \\ - "# These are the same arguments you could pass after the \\\`--\\\` in a call to" \\ - "# \\\`stellar contract deploy\\\`" \\ - "# Only available in \\\`development\\\` and \\\`test\\\` environments" \\ - ${ - setUpContract.constructorArgs.length - ? // Mind the spacing - `"# TODO add appropriate values for for the constructors arguments" \\ - "constructor_args = \\"\\"\\"" \\ - "${setUpContract.constructorArgs.map(constructorArg => `--${constructorArg.name} \\"ADD_${constructorArg.name.toLocaleUpperCase()}_${constructorArg.type?.toLocaleUpperCase() || 'ARGUMENT'}_HERE\\"`).join(' ')}" \\ - "\\"\\"\\"" \\ - ""` - : '""' - } - } >> "$temp" - } - - while IFS= read -r line; do - if [[ $contract_entry_inserted -eq 0 && $line == '[staging.network]' ]]; then - insert_contract_entry - contract_entry_inserted=1 - fi - - if [[ $line =~ ^\\[development\\.contracts\\]$ ]]; then - printf '%s\\n' "$line" >> "$temp" - in_dev_contracts=1 - skip_entry=0 - continue - fi - - if [[ $line =~ ^\\[[^]]+\\]$ ]]; then - if (( in_dev_contracts )) && [[ $line =~ ^\\[development\\.contracts\\..+\\]$ ]]; then - skip_entry=1 - in_dev_contracts=0 - continue - fi - in_dev_contracts=0 - skip_entry=0 - printf '%s\\n' "$line" >> "$temp" - continue - fi - - if (( skip_entry )); then - continue - fi - - if (( in_dev_contracts )); then - if [[ $line =~ ^[[:space:]]*# ]]; then - printf '%s\\n' "$line" >> "$temp" - fi - continue - fi - - printf '%s\\n' "$line" >> "$temp" - done < "$file" - - mv "$temp" "$file" -} -`; - - const updateWorkspaceCargo = `update_cargo() { - cp Cargo.toml Cargo.toml.bak - - cat < deps.tmp -${addDependenciesWith(`{ git = "https://github.com/OpenZeppelin/stellar-contracts", tag = "${contractsVersionTag}" }`, allStellarDependencies)}${addDependenciesWith(`{ version = "${compatibleSorobanVersion}" }`, ['soroban'])} -EOF - - awk ' - BEGIN { - inserted = 0 - deps = "" - while ((getline line < "deps.tmp") > 0) { - deps = deps line "\\n" - } - close("deps.tmp") - } - /^\\[workspace.dependencies\\]/ { - in_deps = 1 - print - if (!inserted) { - printf "%s", deps - inserted = 1 - } - next - } - /^\\[/ { in_deps = 0 } - in_deps { next } - { print } - ' Cargo.toml.bak > Cargo.toml - - rm deps.tmp - rm Cargo.toml.bak -}`; - - return `\ +const setupSh = `\ #!/usr/bin/env bash # # setup.sh -# -# This script is meant to set up a Scaffold project and insert the Wizard's contracts in the project +# +# This script is meant to set up a Scaffold project with the Wizard's contracts check_is_installed() { if ! which "$1" &> /dev/null; then @@ -143,18 +19,7 @@ check_is_installed() { } scaffold() { - tmp_folder="tmp" - stellar scaffold init "$tmp_folder" - - rm -rf "$tmp_folder/contracts" - - local current_directory - current_directory="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)" - - shopt -s dotglob - - cp -a "$current_directory/$tmp_folder"/. "$current_directory"/ - rm -rf "$current_directory/$tmp_folder" + stellar-scaffold upgrade } init_git(){ @@ -163,10 +28,6 @@ init_git(){ git commit -m "openzeppelin: add wizard output" --quiet } -${environmentsFileUpdate(c, scaffoldContractName)} - -${updateWorkspaceCargo} - build_contracts() { cargo build } @@ -196,10 +57,6 @@ then echo "🏗️ Building Scaffold project" scaffold - - setup_environment - - update_cargo build_contracts @@ -212,15 +69,11 @@ else echo "✅ Scaffold project already initialized." fi `; -}; - -const readme = (c: Contract) => { - const hasTodosToResolve = (c: Contract) => getAddressArgs(c).length > 0; - return `\ +const wizardReadme = `\ # Sample Scaffold Project -This project demonstrates a basic Scaffold use case. It comes with a contract generated by [OpenZeppelin Wizard](https://wizard.openzeppelin.com/), a test for that contract, and a script that initiate a Stellar Scaffold project with this contract. [Scaffold Stellar](https://github.com/AhaLabs/scaffold-stellar?tab=readme-ov-file#scaffold-stellar) is a convention-over-configuration toolkit for blockchain and distributed application development on the Stellar network. It provides a seamless development experience through CLI tools, smart contract management, and deployment utilities. +This project demonstrates a basic Scaffold use case. It comes with a contract generated by [OpenZeppelin Wizard](https://wizard.openzeppelin.com/), a test for that contract, and a script that initiates a Stellar Scaffold project with this contract. [Scaffold Stellar](https://github.com/AhaLabs/scaffold-stellar?tab=readme-ov-file#scaffold-stellar) is a convention-over-configuration toolkit for blockchain and distributed application development on the Stellar network. It provides a seamless development experience through CLI tools, smart contract management, and deployment utilities. ## Installing dependencies @@ -235,7 +88,6 @@ This project demonstrates a basic Scaffold use case. It comes with a contract ge \`\`\` bash setup.sh \`\`\` -${hasTodosToResolve(c) ? '\n## Resolve any TODOs \n\nSearch for any TODO comments in the project and resolve them (search for TODO with your code editor).\n' : ''} ## Testing the contract @@ -255,19 +107,13 @@ stellar scaffold watch --build-clients npm run dev \`\`\` `; -}; - -export async function zipScaffold(c: Contract, opts: GenericOptions) { - const zip = new JSZip(); - const scaffoldContractName = contractOptionsToContractName(opts?.kind || 'contract'); - - zip.file(`contracts/${scaffoldContractName}/src/contract.rs`, removeCreateLevelAttributes(printContract(c))); - zip.file(`contracts/${scaffoldContractName}/src/test.rs`, printRustNameTest(c)); - zip.file(`contracts/${scaffoldContractName}/src/lib.rs`, createRustLibFile); - zip.file(`contracts/${scaffoldContractName}/Cargo.toml`, printContractCargo(scaffoldContractName)); - zip.file('setup.sh', setupSh(c, opts, scaffoldContractName)); - zip.file('README-WIZARD.md', readme(c)); +const addScaffoldProjectFiles = (zip: JSZip) => { + zip.file('README-WIZARD.md', wizardReadme); + zip.file('setup.sh', setupSh); return zip; -} +}; + +export const zipScaffoldProject = async (c: Contract, opts: GenericOptions) => + addScaffoldProjectFiles(createRustZipEnvironment(c, opts)); diff --git a/packages/core/stellar/src/zip-shared.ts b/packages/core/stellar/src/zip-shared.ts index 3d4913d7a..7a9e15a35 100644 --- a/packages/core/stellar/src/zip-shared.ts +++ b/packages/core/stellar/src/zip-shared.ts @@ -1,4 +1,5 @@ import type { Contract } from './contract'; +import { contractsVersionTag, compatibleSorobanVersion } from './utils/version'; function pascalToSnakeCase(string: string) { return string @@ -83,3 +84,17 @@ export const createRustLibFile = `#![no_std] mod contract; mod test; `; + +export const workspaceCargo = `[workspace] +resolver = "2" +members = ["contracts/*"] + +[workspace.package] +authors = [] +edition = "2021" +license = "Apache-2.0" +version = "0.0.1" + +[workspace.dependencies] +${addDependenciesWith(`{ git = "https://github.com/OpenZeppelin/stellar-contracts", tag = "${contractsVersionTag}" }`, allStellarDependencies)}${addDependenciesWith(`{ version = "${compatibleSorobanVersion}" }`, ['soroban'])} +`; diff --git a/packages/ui/src/stellar/App.svelte b/packages/ui/src/stellar/App.svelte index 27caf9543..3e4e15b7c 100644 --- a/packages/ui/src/stellar/App.svelte +++ b/packages/ui/src/stellar/App.svelte @@ -82,17 +82,17 @@ const zipScaffoldModule = import('@openzeppelin/wizard-stellar/zip-env-scaffold'); const downloadScaffoldHandler = async () => { - const { zipScaffold } = await zipScaffoldModule; + const { zipScaffoldProject } = await zipScaffoldModule; - await downloadZip(zipScaffold, 'download-scaffold', 'stellar', contract, opts); + await downloadZip(zipScaffoldProject, 'download-scaffold', 'stellar', contract, opts); }; const zipRustModule = import('@openzeppelin/wizard-stellar/zip-env-rust'); const downloadRustHandler = async () => { - const { zipRust } = await zipRustModule; + const { zipRustProject } = await zipRustModule; - await downloadZip(zipRust, 'download-rust-stellar', 'stellar', contract, opts); + await downloadZip(zipRustProject, 'download-rust-stellar', 'stellar', contract, opts); }; export let initialTab: string | undefined = 'Fungible';