diff --git a/docs/build/apps/dapp-frontend.mdx b/docs/build/apps/dapp-frontend.mdx index a9b15c54f..a5b6d1de4 100644 --- a/docs/build/apps/dapp-frontend.mdx +++ b/docs/build/apps/dapp-frontend.mdx @@ -68,7 +68,7 @@ We attempt to keep the code in these generated libraries readable, so go ahead a ## Generate an NPM package for the Increment contract -Though we can run `soroban contract bindings typescript` for each of our contracts individually, the [soroban-astro-template](https://github.com/stellar/soroban-astro-template) that we used as our template includes a very handy `initialize.js` script that will handle this for all of the contracts in our `contracts` directory. +Though we can run `soroban contract bindings typescript` for each of our contracts individually, the [soroban-template-astro](https://github.com/stellar/soroban-astro-template) that we used as our template includes a very handy `initialize.js` script that will handle this for all of the contracts in our `contracts` directory. In addition to generating the NPM packages, `initialize.js` will also: @@ -496,4 +496,4 @@ At this point, you've seen a full end-to-end example of building a contract on S - See more complex example contracts in the [Example Contracts](../smart-contracts/example-contracts/README.mdx) section. - Learn more about the [internal architecture and design](../../learn/encyclopedia/contract-development/README.mdx) of Soroban. -- Check out a more full-featured [example app](https://github.com/stellar/soroban-example-dapp), which uses React rather than vanilla JavaScript and Next.js rather than Astro. This app also has a more complex setup & initialization process, with the option of using a [locally-hosted RPC node](../../data/rpc/admin-guide.mdx). +- Learn how to find other templates for use with `--frontend-template`, other than [stellar/soroban-template-astro](https://github.com/stellar/soroban-astro-template), and how to build your own: [Develop contract initialization frontend templates](../guides/dapps/soroban-contract-init-template.mdx) diff --git a/docs/build/guides/dapps/soroban-contract-init-template.mdx b/docs/build/guides/dapps/soroban-contract-init-template.mdx index 53e5a323c..8b54a100c 100644 --- a/docs/build/guides/dapps/soroban-contract-init-template.mdx +++ b/docs/build/guides/dapps/soroban-contract-init-template.mdx @@ -1,442 +1,296 @@ --- -title: Develop contract initialization templates -hide_table_of_contents: true -description: Create frontend templates that can be used to work with Stellar smart contracts in frontend applications +title: Develop contract initialization frontend templates +description: Understand, find, and create your own frontend templates for use with Stellar CLI's `stellar contract init` command --- - Develop Soroban contract Initialization Template + Develop contract initialization frontend templates -This guide will walk you through the process of developing contract templates for working with Stellar smart contracts in frontend applications. This guide will cover the process of creating or developing the templates itself as well as how to work with the template to build, deploy, and generate smart contract bindings for the template. +This guide picks up where [Build a Dapp Frontend](../../apps/dapp-frontend.mdx) left off, taking a deeper look at the `--frontend-template` used there. From there, we'll: -## Prerequisites +1. Search GitHub for other Soroban templates +1. Build our own simple template -Before you begin, ensure you have the following installed: +Building our own template will be a great way to learn how they work. They're not that complicated! -1. [Rust](https://www.rust-lang.org/) and Cargo (for compiling smart contracts) -2. [Node.js](https://nodejs.org/en) and npm (for running JavaScript deployment scripts) -3. [Stellar CLI](../../smart-contracts/getting-started/setup.mdx#install-the-stellar-cli) -4. [React](https://react.dev/learn) +## Search GitHub for other Soroban templates -## Anatomy of contract initialization (init) template +The official template maintained by Stellar Development Foundation (SDF), as used in [Build a Dapp Frontend](../../apps/dapp-frontend.mdx), lives on GitHub at [stellar/soroban-template-astro](https://github.com/stellar/soroban-astro-template). It uses the [Astro](https://astro.build/) web framework. While Astro works with React, Vue, Svelte, and any other UI library, the template opts not to use them, preferring Astro's own templating language, which uses vanilla JavaScript with no UI library. -Stellar smart contracts are written in Rust, but suppose we want our frontend web application to work with these contracts: this is where templates come into the equation. Templates allow us to work with smart contracts in our frontend application. At its core a template consists of a frontend library and a script for interacting with the Stellar CLI. +(You may wonder why it makes this unpopular choice. A fair question! The team wanted to balance actual utility with broad approachability. Not everyone learning Stellar and Soroban is familiar with React, or any other UI library. It also demonstrates that core Soroban libraries all work with any JavaScript project.) -Keep in mind you can use any frontend library to work with Stellar smart contracts. In this guide we'll use React to generate the template but it is worth noting that you can use whichever library you like or no library at all. - -We'll start off by installing the [React library](https://react.dev/) and then we'll walk through creating the initialization script, and finally wrap up by using the template to build, deploy, and generate contract bindings. - -## Creating the frontend - -The following command initializes a new Vite React project and installs the necessary dependencies: +But note that the CLI's `contract init` command was made to work with _any_ frontend template. It need not even live on GitHub! Simply pass another valid git URL to the command, and it will clone that instead of the official repository: ```bash -npm create vite@latest soroban-react-template --template react -cd soroban-react-template -npm install -npm run dev +# the following is NOT a valid git repository, and will not work 😄 +stellar contract init my-new-project --frontend-template https://whatever.cool/project/you/want ``` -## Creating the initialize script +So how can you find other valid frontend templates? -The initialization script is the heart of the contract template. This little but highly crucial script enables us to execute Stellar CLI commands which, in turn, enables us to build, deploy, and generate smart contract bindings. +At some point we may set up a DAO or other voting system to curate a list of high-quality templates, but for now... search GitHub! And GitLab. And any other source code site you know about. -The initialization script can be written in bash script or JavaScript. This guide uses the latter but the same principles are involved when using bash scripts. +In GitHub, in the main search bar, search for `"soroban-template-"`. With the quotes. Here's a direct link to the search results: [github.com/search?q=%22soroban-template-%22](https://github.com/search?q=%22soroban-template-%22) -We start off by creating `initialize.js` files in our frontend project directory. +You can copy this approach for any other source code website, such as GitLab. -```bash -touch initialize.js -``` - -This command will create the `initailze.js` file in your project's directory. Now let's open the file to begin writing the necessary code +How do you know if any of these are any good? Try them. Look at their source code. How many stars do they have? How active are their maintainers? None of these are perfect metrics, which is why a curated registry might be nice in the future. -### Installing the dependencies +If none of them suit, then it might be time to... -The following dependencies will simplify the process of interacting with files and directories which the `initialize.js` file does together with other functionalities. +## Make your own template -1. [glob](https://npmjs.com/package/glob) -2. [dotenv](https:npmjs.com/package/dotenv) +This will be easier than you might imagine. There are a few gotchas, but overall these templates are fairly standard Node projects. -Install the above packages as dev dependencies by running the command below: +### But first, how are these projects organized? -```bash npm2yarn -npm install dotenv glob --dev -``` +When you run `stellar contract init`, it _always_ includes a Rust/Cargo project, with a `Cargo.toml` that defines a workspace, and workspace members located in a `contracts` folder. At a minimum, there's one contract, `contracts/hello_world`, but you can get more by using `--with-example`. -### Writing the initialization code +Separately, you _may_ include a `--frontend-template`. Frontend templates so far have all been Node projects, which have a `package.json` in the root. In the final composite project, the Node project and Rust project live side-by-side, and the frontend template expects the Rust project to be there. It expects a `contracts` folder with one or more subfolders, and it expects a `target` directory with all the Rust build artifacts. -As a general overview, the following script will perform the below tasks: +So keep that in mind. We're making a fairly simple Node project, and telling it about our Soroban stuff, like the `contracts` folder. -1. Create network profiles for contract project -2. Generate and fund account for interaction with the Stellar network -3. Build smart contract .wasm files -4. Deploy smart contract to the Stellar network -5. Generate smart contract Typescript bindings +### 1. Initialize an NPM project -#### Importing the modules +So let's make a simple Node project! Rather than initializing an Astro project, like the official frontend template, let's try something new. The [State of JS survey](https://2022.stateofjs.com/en-US/libraries/front-end-frameworks/#front_end_frameworks_experience_linechart) tells me that something called "Solid" is fairly new and well-loved. [What does it say to do?](https://www.solidjs.com/) -The following modules allow us to work with environment variables, execute Stellar CLI commands, search files and directories, work with paths, and create and delete files, in that order. - -```javascript -import "dotenv/config"; -import { execSync } from "child_process"; -import { globSync } from "glob"; -import path from "path"; -import { writeFileSync, rmSync } from "fs"; +```bash +npx degit solidjs/templates/ts soroban-template-solid +cd soroban-template-solid +npm install +npm run dev ``` -### Creating the wrapper function +Ok, we have a running Solid template! Now let's turn it into a Soroban template! -Instead of calling the `execSync` function and making the error handling process multiple times, we create a wrapper function to encapsulate this function. +### 2. git init -Furthermore, when deploying the contract, the command returns the deployed contract address, which is required when generating contract Typescript bindings. Wrapping the `execSync` function will enable the script to return Stellar CLI command output while handling errors in one go. +Commit early, commit often! You can stop running the dev server (the one you started with `npm run dev` above; stop it with ctrlc, even on a Mac) if you want, or open a new terminal and: -```javascript -const run = (command) => { - try { - const output = execSync(command, { stdio: ["inherit", "pipe", "pipe"] }); - console.log("Here comes the output\n"); - return output.toString(); - } catch (error) { - console.error("Error executing command: \n", error.message); - return null; // or throw error if you want to propagate it - } -}; +```bash +git init +git add . +git commit -m "init from solid ts template" ``` -### Creating network profiles +### 3. Copy in the `initialize.js` script -This code snippet executes a Stellar CLI command to add a network profile. It uses environment variables (process.env.NETWORK, process.env.RPC_URL, process.env.NETWORK_PASSPHRASE) to specify the network details and RPC URL. +The SDF-maintained `soroban-template-astro` has [an `initialize.js` script](https://github.com/stellar/soroban-astro-template/blob/main/initialize.js) in its project root. Copy-paste it into your project. -You can clearly see the benefit of wrapping the `execSync` function as it results in a much cleaner code and short snippet while retaining same functionality. +If you're familiar with Node scripting, you should be able to figure out what it's doing. If not, it's a great way to learn! Tip: start at the bottom, where it does the `generateAccount(); buildAll(); deployAll();` stuff. -```javascript -run( - `stellar network add ${process.env.NETWORK} --rpc-url ${process.env.RPC_URL} --network-passphrase ${process.env.NETWORK_PASSPHRASE}`, -); -``` +That stuff at the end should give you a clue about what this script does. It does stuff that a _Soroban_ app needs. Soroban apps make calls to Soroban. -### Creating account profiles +So this script: -This code generates Stellar key pairs for an account (process.env.ACCOUNT) and funds them accordingly on a specific network (process.env.NETWORK). +1. generates a Soroban/Stellar account +2. builds all contracts +3. deploys all contracts (to a locally-running Soroban network; we'll recap this soon) +4. _binds_ contracts — that is, it creates NPM projects for each deployed contract by running `stellar contract bindings typescript` +5. imports the contracts for straightforward use in the rest of your project -```javascript -run( - `stellar keys generate ${process.env.ACCOUNT} --network ${process.env.NETWORK}`, -); -``` +Remember that it needs to do this all _in a contract-agnostic way_. That is, the `--frontend-template` choice is separate from the `--with-example` choice. The frontend template doesn't know what contracts it might find! But it needs to build, deploy, bind, and import whatever's there. -### Building the contract +So this script does that. -This snippet builds Stellar smart contracts in the project directory. +But it needs a few other things. -```javascript -run("stellar contract build"); -``` +#### A. `devDependencies` -### Deploying the contract - -This code deploys one or more Stellar smart contracts. It uses files found in `target/wasm32-unknown-unknown/release/\*.wasm`, deploys each with specified parameters, and stores contract details (alias and contractId) in contractsObject. - -The code iterates through the smart contract files found in the project directory and deploys all of them. - -```javascript -const files = globSync("target/wasm32-unknown-unknown/release/*.wasm"); -let alias, contractId; -console.log(files); -files.forEach((file) => { - alias = path.basename(file).split(".")[0]; - console.log(`Deploying Contract ${alias}`); - contractId = run( - `stellar contract deploy --network ${process.env.NETWORK} --source ${process.env.ACCOUNT} --wasm ${file} --alias ${alias}`, - ); - //save contractId and alias to contracts Object - contractsObject[alias] = { - alias, - id: contractId, - }; -}); +The script uses a couple NPM packages. Install them: + +```bash +npm install --save-dev dotenv glob ``` -### Generating TypeScript bindings +#### B. `.env` -This snippet generates TypeScript bindings for Stellar smart contracts deployed earlier. It iterates over files and uses `contractsObject` to obtain contract details (`alias` and `contractId`). +The [`dotenv` package](https://www.npmjs.com/package/dotenv) installed above parses environment variables from a `.env` file. The official template includes [a `.env.example`](https://github.com/stellar/soroban-astro-template/blob/main/.env.example). Go ahead and copy it into your own project. To set you up for testing it all out, you can also copy it to a local `.env`. -```javascript -let filename, output_dir; -files.forEach((file) => { - filename = path.basename(file).split(".")[0]; - output_dir = `./packages/${filename}`; - run( - `stellar contract bindings typescript --output-dir ${output_dir} --network ${process.env.NETWORK} --contract-id ${contractsObject[alias]["id"]} --wasm ${file} --overwrite`, - ); -}); +```bash +cp .env.example .env ``` -### Complete initialization script - -The following snippet is the complete aggregated version of the snippets shown earlier. I've added some functionalities like deleting pre-existing contract Wasm files and creating a `contract.json` file, which are all optional steps. - -```javascript -import "dotenv/config"; -import { execSync } from "child_process"; -import { globSync } from "glob"; -import path from "path"; -import { writeFileSync, rmSync } from "fs"; - -//Create An object to hold the Contract IDs and Alias -const contractsObject = {}; - -//Create a wrapper around execSync function to handle errors and makes its return easily available withing the script -const run = (command) => { - try { - const output = execSync(command, { stdio: ["inherit", "pipe", "pipe"] }); - console.log("Here comes the output\n"); - return output.toString(); - } catch (error) { - console.error("Error executing command: \n", error.message); - return null; // or throw error if you want to propagate it - } -}; - -//Configure the network for the project -console.log("Configuring Network"); -run( - `stellar network add ${process.env.NETWORK} --rpc-url ${process.env.RPC_URL} --network-passphrase ${process.env.NETWORK_PASSPHRASE}`, -); - -//Generate and fund the Wallet Profile for the project -run( - `stellar keys generate ${process.env.ACCOUNT} --network ${process.env.NETWORK}`, -); - -//Delete Remove all pre-existing Wasm Files -const existingFiles = globSync("./target/**.wasm"); - -console.log(`Existing Files ${existingFiles}`); - -existingFiles.forEach((filePath, index) => { - try { - console.log( - `Deleting ${path.basename(filePath)} ${index + 1} out of ${ - existingFiles.length - }`, - ); - rmSync(filePath); - } catch (err) { - console.error(`Error while deleting Files \n ${err}`); - } -}); - -//Build Wasm Contract Files -run("stellar contract build"); - -//Deploy Contract Wasm and save the contact Ids and Aliases -const files = globSync("target/wasm32-unknown-unknown/release/*.wasm"); -let alias, contractId; -console.log(files); -files.forEach((file) => { - alias = path.basename(file).split(".")[0]; - console.log(`Deploying Contract ${alias}`); - contractId = run( - `stellar contract deploy --network ${process.env.NETWORK} --source ${process.env.ACCOUNT} --wasm ${file} --alias ${alias}`, - ); - //save contractId and alias to contracts Object - contractsObject[alias] = { - alias, - id: contractId, - }; -}); - -//Create a json File to store the contract name as key and contract id and contract alias contained in an object as value -const contractsJSONPath = "./contracts.json"; -const contractsJSONData = JSON.stringify(contractsObject); - -try { - writeFileSync(contractsJSONPath, contractsJSONData); - console.log(`JSON file has been saved to ${contractsJSONPath}`); -} catch (err) { - console.error("Error writing JSON file: ", err); -} +#### C. `.gitignore` -//Generate Contract Typescript Bindings -let filename, output_dir; -files.forEach((file) => { - filename = path.basename(file).split(".")[0]; - output_dir = `./packages/${filename}`; - run( - `stellar contract bindings typescript --output-dir ${output_dir} --network ${process.env.NETWORK} --contract-id ${contractsObject[alias]["id"]} --wasm ${file} --overwrite`, - ); -}); -``` +You'll want to ignore the `.env` file you created above, as well as some other build artifacts created by the `initialize.js` script. Paste the bottom of [the official template's `.gitignore`](https://github.com/stellar/soroban-astro-template/blob/main/.gitignore) into your template's `.gitignore`: -## Modifying `package.json` file +```gitignore +# environment variables +.env +.env.production -After saving the `initialize.js` script, let's modify our `package.json` file to create a new entry under scripts to run the code to work on the contract files. +# generated contract clients +packages/* +# if you have other workspace packages, add them here +!packages/.gitkeep -Let's also modify the file to create a new workspace in the `package.json` to point to the path where the the TypeScript bindings are generated +# generated contract client imports +src/contracts/* +!src/contracts/util.ts +``` + +#### C. `package.json` -```json -"scripts": { - "setup": "node initialize.js", - }, +Make sure users of your template don't forget to run the `initialize.js` script. Modify the `scripts` section as follows: - "workspace": ["./packages/*"], +```diff +- "start": "vite", +- "dev": "vite", +- "build": "vite build", +- "serve": "vite preview" ++ "init": "node initialize.js", ++ "start": "npm run init && vite", ++ "dev": "npm run init && vite", ++ "build": "npm run init && vite build", ++ "serve": "npm run init && vite preview" ``` -## Running the script +Alternatively, rather than adding the repetitive `npm run init` statements, you could opt to add [a `postinstall` script](https://docs.npmjs.com/cli/v7/using-npm/scripts#life-cycle-operation-order) where you `npm run init`, or just `node initialize.js` in there. -Now that we have a complete script and a frontend, we should try to run the script. However, because the script is dependent on contract files we need to have a contract project ready, otherwise the script will fail and result in an error. To solve this issue we have to either copy the whole project contents and paste them to an existing Stellar contract project directory or upload the template file to a repo then create a new project and setting the 'f' parameter to point to the hosted repository of the template. +You also need to tell NPM to treat this as a workspace. Yes, this project is a Cargo workspace _and_ an NPM workspace! The `bindAll` step of `initialize.js` puts the generated NPM packages in `packages/*`. At the bottom of `package.json`, add: -### Setting up the project +```diff + "dependencies": { + "solid-js": "^1.8.11" +- } ++ }, ++ "workspaces": [ ++ "packages/*" ++ ] +} +``` -A community member has hosted a [public repository of the React template](https://github.com/CaptainPrinz/soroban-react-template) available for use. The following command implements the second option: +Also make sure that this project is set up to allow the `import` statements in the `initialize.js` script. Add this at the top-level: -```bash -stellar contract init hello_contract -f https://github.com/CaptainPrinz/soroban-react-template +```diff + "description": "", ++ "type": "module", + "scripts": { ``` -The snippet above initializes a new Stellar smart contracts project, `hello_contract`, that uses a prebuilt `hello_world` contract and adds the frontend template we deployed to a remote repository. +While you're here, you can also update the `name` (maybe `"soroban-template-solid"`) and `description`. -### Setting the environment variables +#### E. `src/contracts/util.ts` -Our templates offer a great deal of customization via environment variables. These variables need to be set by the user by creating a `.env` file otherwise the process will fail as these variables will be undefined. +In the `.gitignore` above, you may have noticed that this file is explicitly included. Copy it in from [the official template](https://github.com/stellar/soroban-astro-template/blob/main/src/contracts/util.ts). You'll need to create the `src/contracts` folder. -### Starting the script +As you can see, it just makes it easy to `import { rpcUrl, networkPassphrase } from 'util'` in the files generated in the `importAll` step. -On your terminal run the following code: +#### F. README -```bash -npm install -cp .env.example .env # edit .env file as needed -npm run setup -``` - -This runs the `initialize.js` script and first sets the network profile, account identities, builds the contract `.wasm` file, deploys the contracts, and generates the bindings. +You might want to start by copying [the official template's README](https://github.com/stellar/soroban-astro-template/blob/main/README.md) to explain how to `cp .env.example .env`. From there, this might also be a good time to explain anything else that makes your template unique! Why might people want to use it? -If successful, there should be the following changes in the directory: +### 4. `git commit` -1. A new `.soroban` directory, which contains the network profile files, account identity files, and hosted smart contract files in json format -2. A `packages` directory containing the generated TypeScript bindings -3. A `contracts.json` file +Commit changes! -You are now finally able to import these generated bindings in your frontend application, create their clients, and use them to interact with the contracts deployed on the network. +```bash +git add . +git commit -m "add initialize.js script and supporting changes" +``` -## Interacting with the contract bindings +### 5. Try it! -After running the initialization script, there should be new `packages` directory which confirms successful bindings generation. Navigate to the `packages` directory and there should be a package for the deployed contract(s). This package will form the last piece in solving the puzzle of interacting with soroban contracts from frontend appications which will be discussed briefly. +That's it! You have an NPM project with an `initialize.js` script (and its supporting cast). That's all you really need! -To work with the bindings generated, it is recommended the wrap the bindings by creating a new module, instantiating a new client, then finally importing the client and invoking the contract functions. +To try it, soon we will run `stellar contract init .` _in this project_ to add the Cargo stuff and a `contracts` folder. But be careful! You don't want to commit these changes! You can `git restore .` at the end of your testing to get rid of the new files. -While it is not necessary to follow the procedure above, you stand to have a better code structure and a much easier way of fixing the code should anything go wrong. +Let's try it. First, make sure you're running a local Stellar network. Start Docker Desktop or whatever alternative you prefer, then: -However given the simple structure of our contract, we will proceed to integrate it directly in the frontend without creating a wrapper module. +```bash +stellar network container start local +``` -## Setting up the hello world package +Now we can run `contract init`. Let's include one extra contract. Then we'll run the `dev` script (which, remember, will run the `initialize.js` script first): -Navigate to the packages folder to find the hello world package and observe the directory contents. If the directory does not contain a `dist` and `node modules` folder, you must install the dependencies and build the hello world typescript bindings for the package to work in our react app. +```bash +stellar contract init . --with-example increment +npm run dev +``` -To install the dependencies and build the typescript bindings for the package, navigate to the `packages` directory, then enter `hello_world` package directory and run the command below. +After you do this, you may notice lots of new changes in the project. All that Rust, Cargo, and Soroban stuff! ```bash -npm i -npm run build +$ git status --short + +?? .soroban/ +?? Cargo.lock +?? Cargo.toml +?? contracts/ +?? target/ ``` -After running the command above, there should now be a `node modules` and a `dist` directory containing `index.js` and `index.ts` files. These will serve as an entry point to the package when it is eventually imported. +Q: Should you commit this stuff?
A: **_NO!_** -### Using the hello world package in React +Q: Should you _gitignore_ this stuff?
A: **_NO!_** -First we import the following from the package: +The `.soroban` and `target` folders [are gitignored by the core Rust/Cargo template](https://github.com/stellar/stellar-cli/blob/main/cmd/soroban-cli/src/utils/contract-init-template/.gitignore). In projects that specify yours as their `--frontend-template`, that `.gitignore` will be merged with yours. No need to include those lines twice. -1. A `networks` object. -2. A `Client` class. +And projects that use yours will want to commit the `Cargo.*` files and `contracts`, but your _template_ should not include them. That can cause problems with project initialization later. Nor should it gitignore them, because your `.gitignore` will be part of projects started with your template! It would cause problems and confusion, if people didn't realize that some of their most important files were gitignored! -```javascript -import { Client, networks } from "../packages/hello_world"; -``` +Alright. Go ahead and open the app in your browser. Solid runs its dev server on `http://localhost:3000`. Does it load? It should! We didn't actually use the new `src/contracts/*` stuff in the app itself! -Notice how we point to the directory of the package when importing th ebindings by making reference to the packages folder. +### 6. Wait. Should the template actually use the contracts? -Now we instantiate a the `Client` class and pass an object containing the RPC url and a copy of the `networks.testnet` object by using the spread operator. This technically means that the `Client` class takes in an object of the network configuration along with the contract ID but we make it easier by using the `networks` object. +Good question! -```javascript -const helloWorldContract = new Client({ - ...networks.testnet, - rpcUrl: "https://soroban-testnet.stellar.org:443", -}); -``` +You know that the `hello_world` contract will always be there. So you could demonstrate to your users how to import and use it in an app file (like `src/App.tsx`, in the Solid template). But remember: no other contracts are guaranteed to be there! So don't commit any changes that import and use something like `increment`! -By printing the `helloWorldContract` object, you'll find the hello method which coincides with the hello function defined in the smart contract. Calling this method will invoke its equivalent in the smart contract. +Here's a way you could demonstrate how to import and use the `hello_world` contract in the Solid template's `App.tsx`: -Finally, to interact with the contract we run the following code: +```diff ++import greeter from "./contracts/hello_world"; -```javascript -const { result } = await contract.hello({ to: receiver }); + const App: Component = () => { + return ( +
+
++
{ ++ e.preventDefault(); ++ const { result } = await greeter.hello({ ++ to: e.currentTarget.toWhom.value, ++ }); ++ alert(result); ++ }} ++ > ++ ++ ++
``` -### Modifying the App component - -To put it all together, modify the `App.jsx` component in the `src` directory by replacing its content with the code below. - -```javascript -import { Client, networks } from "../packages/hello_world"; -import { useState } from "react"; - -function App() { - const contract = new Client({ - ...networks.testnet, - rpcUrl: "https://soroban-testnet.stellar.org:443", - }); - console.log(contract); - - const [target, setTarget] = useState(""); - let receiver; - - const getResult = async () => { - const { result } = await contract.hello({ to: receiver }); - console.log(result); - setTarget(result); - }; - - const handleSubmit = (e) => { - e.preventDefault(); - getResult(); - }; - - return ( - <> -

Response: {target}

-
- (receiver = e.target.value)} /> - -
- - ); -} +### 7. Make it as complex as you want! -export default App; -``` +This is _your_ template. Go ahead and add helpful dependencies and utility files that you always want, like wallet management or whatever. If you want to add a whole complex stack of UI components, styles, and state-management libraries, go ahead! + +The official template strives for simplicity. For shallowness, even. It's meant as a teaching tool, for people with all different levels of JS and Soroban experience. Yours has no such constraints! It should be useful to _you_. -Now run `npm run dev` to run the project and play with the deployed smart contract from your frontend app. +And templates are cheap to make! If you want to have one `soroban-template-framework-x-basic` for a broader audience, and another `soroban-template-framework-x-opinionated` for your own projects, you can do that! -## Customization +## Wrapping up -With the `initialize.js` script being the heart of the template file, you can go through the file and modify the paths in which files are saved if necessary. +Some things we did in this section: -Also a great deal of customization is enabled by using environment variables, giving flexibility to change network profiles and account identity without limits. +- Searched GitHub for new frontend templates +- Learned that some templates might not be on GitHub +- Saw how frontend templates work and interact with the "backend" template that always comes with `stellar contract init` +- Built our own template by adding an `initialize.js` script to a basic NPM template -## Conclusion +After you're done building your own frontend template, what's next? You choose! You can: -A lot has been covered from creating template files to building, deploying, generating bindings, and interacting with smart contracts. Now go ahead and play with the code and try applying the procedures to other contracts. +- See more complex example contracts in the [Example Contracts](../../smart-contracts/example-contracts/README.mdx) section. +- Learn more about the [internal architecture and design](../../../learn/encyclopedia/contract-development/README.mdx) of Soroban.