diff --git a/docs/build/apps/dapp-frontend.mdx b/docs/build/apps/dapp-frontend.mdx index bc11c378a..a58e33c5a 100644 --- a/docs/build/apps/dapp-frontend.mdx +++ b/docs/build/apps/dapp-frontend.mdx @@ -1,561 +1,536 @@ --- sidebar_position: 70 -sidebar_label: Build a Dapp Frontend +sidebar_label: Develop a Contract with Frontend Templates title: "Build a dapp Frontend: Connect Wallets, Handle Transactions & More" description: "Learn how to build a dapp frontend that connects to smart contracts. Explore best practices for integrating wallets, handling transactions, and interacting with the Stellar network." --- -# Build a Dapp Frontend +# Develop a Contract with Frontend Templates -This is a continuation of the [Getting Started tutorial](../smart-contracts/getting-started/README.mdx), where you should have deployed two smart contracts to the public network. In this section, we'll create a web app that interacts with the contracts via RPC calls. +This guide picks up where [Build a Dapp Frontend](https://developers.stellar.org/docs/build/apps/dapp-frontend) left off. From there, we'll: -Let's get started. +1. Search GitHub for other Soroban templates +2. Build our own simple template -## Initialize a frontend toolchain +Building our own template will be a great way to learn how they work. They're not that complicated! -You can build a Soroban app with any frontend toolchain or integrate it into any existing full-stack app. For this tutorial, we're going to use [Astro](https://astro.build/). Astro works with React, Vue, Svelte, any other UI library, or no UI library at all. In this tutorial, we're not using a UI library. The Soroban-specific parts of this tutorial will be similar no matter what frontend toolchain you use. +## Search GitHub for other Soroban templates -If you're new to frontend, don't worry. We won't go too deep. But it will be useful for you to see and experience the frontend development process used by Soroban apps. We'll cover the relevant bits of JavaScript and Astro, but teaching all of frontend development and Astro is beyond the scope of this tutorial. +The official template maintained by Stellar Development Foundation (SDF), as used in [Build a Dapp Frontend](https://developers.stellar.org/docs/build/apps/dapp-frontend), lives on GitHub at [stellar/soroban-template-astro](https://github.com/stellar/soroban-astro-template). It uses the [Astro web framework](https://astro.build/). 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. -Let's get started. +(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.) -You're going to need [Node.js](https://nodejs.org/en/download/package-manager/) v18.14.1 or greater. If you haven't yet, install it now. - -We want to create an Astro project with the contracts from the previous lesson. To do this, we can clone a template. You can find Soroban templates on GitHub by [searching for repositories that start with "soroban-template-"](https://github.com/search?q=%22soroban-template-%22&type=repositories). For this tutorial, we'll use [stellar/soroban-template-astro](https://github.com/stellar/soroban-template-astro). We'll also use a tool called [degit](https://github.com/Rich-Harris/degit) to clone the template without its git history. This will allow us to set it up as our own git project. - -Since you have `node` and its package manager `npm` installed, you also have `npx`. - -We're going to create a new project directory with this template to make things easier in this tutorial, so make sure you're no longer in your `soroban-hello-world` directory and then run: - -```sh -npx degit stellar/soroban-template-astro first-soroban-app -cd first-soroban-app -git init -git add . -git commit -m "first commit: initialize from stellar/soroban-template-astro" -``` - -This project has the following directory structure, which we'll go over in more detail below. +To use other templates, we will clone them from their repositories, and then copy these files into the root of the existing `soroban-hello-world directory`: ```bash -├── contracts -│ ├── hello_world -│ └── increment -├── CONTRIBUTING.md -├── Cargo.toml -├── Cargo.lock -├── initialize.js -├── package-lock.json -├── package.json -├── packages -├── public -├── src -│ ├── components -│ │ └── Card.astro -│ ├── env.d.ts -│ ├── layouts -│ │ └── Layout.astro -│ └── pages -│ └── index.astro -└── tsconfig.json -``` -The `contracts` are the same ones you walked through in the previous steps of the tutorial. Since we already deployed these contracts with aliases, we can reuse the generated contract ID files by copying them from the `soroban-hello-world/.stellar` directory into this project: +# For example, you could clone this repository +git clone https://github.com/stellar/soroban-examples -```sh -cp -R ../soroban-hello-world/.stellar/ .stellar ``` -## Generate an NPM package for the Hello World contract +Now copy files into the root of `soroban-hello-world`. -Before we open the new frontend files, let's generate an NPM package for the Hello World contract. This is our suggested way to interact with contracts from frontends. These generated libraries work with any JavaScript project (not a specific UI like React), and make it easy to work with some of the trickiest bits of Soroban, like encoding [XDR](../../learn/fundamentals/contract-development/types/fully-typed-contracts.mdx). +So how can you find other valid frontend templates? -This is going to use the CLI command `stellar contract bindings typescript`: +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](http://github.com/search?q=%22soroban-template-%22) -```bash -stellar contract bindings typescript \ - --network testnet \ - --contract-id hello_world \ - --output-dir packages/hello_world -``` +You can copy this approach for any other source code website, such as GitLab. -:::tip +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. -Notice that we were able to use the contract alias, `hello_world`, in place of the contract id! +If none of them suit, then it might be time to... -::: +## Make your own template -This project is set up as an NPM Workspace, and so the `hello_world` client library was generated in the `packages` directory at `packages/hello_world`. +Let’s make our own template! In this example template, we use SolidJS as the JavaScript framework, but other frameworks can be used with minor modifications. The template is using the `hello world` example smart contract, and is a part of the template initialization; bindings for the `hello world` smart contract are created. -We attempt to keep the code in these generated libraries readable, so go ahead and look around. Open up the new `packages/hello_world` directory in your editor. If you've built or contributed to Node projects, it will all look familiar. You'll see a `package.json` file, a `src` directory, a `tsconfig.json`, and even a README. +This example template is very simple, most of the work goes into creating the `initialize.js` file, which is used to take care of creating a user account, building and deploying the smart contract, and creating the smart contract TypeScript bindings. -## Generate an NPM package for the Increment contract +### 1. Initialize a SolidJS project -Though we can run `stellar contract bindings typescript` for each of our contracts individually, the [soroban-template-astro](https://github.com/stellar/soroban-astro-template) project 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. +```bash -In addition to generating the NPM packages, `initialize.js` will also: +npx degit solidjs/templates/ts soroban-template-solid +cd soroban-template-solid +npm install +npm run dev -- Generate and fund our Stellar account -- Build all of the contracts in the `contracts` dir -- Deploy our contracts -- Create handy contract clients for each contract +``` -We have already taken care of the first three bullet points in earlier steps of this tutorial, so those tasks will be noops when we run `initialize.js`. +The basic SolidJS is now running on localhost port 3000. -### Configure initialize.js +#### Dependencies -We need to make sure that `initialize.js` has all of the environment variables it needs before we do anything else. Copy the `.env.example` file over to `.env`. The environment variables set in `.env` are used by the `initialize.js` script. +Most of the needed dependencies are already included by the SolidJS template, we just need to add three more: ```bash -cp .env.example .env -``` -Let's take a look at the contents of the `.env` file: +npm install dotenv glob util ``` -# Prefix with "PUBLIC_" to make available in Astro frontend files -PUBLIC_STELLAR_NETWORK_PASSPHRASE="Standalone Network ; February 2017" -PUBLIC_STELLAR_RPC_URL="http://localhost:8000/soroban/rpc" -STELLAR_ACCOUNT="me" -STELLAR_NETWORK="standalone" -``` +The `dotenv` package is needed for reading the environment variables, `glob` is used to find files in the project based on a pattern, and `util` contains a function that can be used to execute system commands asynchronously. -This `.env` file defaults to connecting to a locally running network, but we want to configure our project to communicate with Testnet, since that is where we deployed our contracts. To do that, let's update the `.env` file to look like this: +#### Smart contract -```diff -# Prefix with "PUBLIC_" to make available in Astro frontend files --PUBLIC_STELLAR_NETWORK_PASSPHRASE="Standalone Network ; February 2017" -+PUBLIC_STELLAR_NETWORK_PASSPHRASE="Test SDF Network ; September 2015" --PUBLIC_STELLAR_RPC_URL="http://localhost:8000/soroban/rpc" -+PUBLIC_STELLAR_RPC_URL="https://soroban-testnet.stellar.org:443" +Since we are going to interact with the smart contract from the `initialize.js` script, let’s copy the smart contract code to the root of the SolidJS template directory. Since the `initialize.js` script is calling Stellar CLI commands, it will only work if the smart contract code is in the same directory as the script. --STELLAR_ACCOUNT="me" -+STELLAR_ACCOUNT="alice" --STELLAR_NETWORK="standalone" -+STELLAR_NETWORK="testnet" -``` +The root directory should look like this: + +```text -:::info +├── contracts +│ └── hello_world +│ ├── src +│ │ └── lib.rs +│ └── Cargo.toml +│ └── Makefile +├── node_modules +├── packages +├── src +│ ├── App.tsx +│ └── index.tsx +├── .env +├── index.html +├── tsconfig.json +├── vite.config.ts +├── initialize.js +├── package.json +└── Cargo.toml -This `.env` file is used in the `initialize.js` script. When using the CLI, we can still use the network configuration we set up in the [Setup](../smart-contracts/getting-started/setup.mdx) step, or by passing the `--rpc-url` and `--network-passphrase` flags. +``` -::: +### 2. Environment variables -### Run `initialize.js` +The SolidJS code itself doesn’t need environment variables for this simple example, but since we are going to add smart contract bindings, it makes sense to store information about the network and the user in an .env file instead of hard coding those values. -First let's install the Javascript dependencies: +These are the variables needed: ```bash -npm install -``` -And then let's run `initialize.js`: +STELLAR_NETWORK="testnet" +STELLAR_NETWORK_PASSPHRASE="Test SDF Network ; September 2015" +STELLAR_RPC_URL="https://soroban-testnet.stellar.org" +STELLAR_ACCOUNT="my-user-name" -```bash -npm run init ``` -As mentioned above, this script attempts to build and deploy our contracts, which we have already done. The script is smart enough to check if a step has already been taken care of, and is a no-op in that case, so it is safe to run more than once. +The variables used here are for deploying the contract to testnet and creating the contract bindings for testnet. The user name can be any name, but let’s say you use alice, and have previously created the user `alice` with the Stellar CLI, creating a new account named `alice` will fail. -### Call the contract from the frontend +### 3. Initialize.js -Now let's open up `src/pages/index.astro` and take a look at how the frontend code integrates with the NPM package we created for our contracts. +The goal is to have a script that will handle everything smart contract-related, from creating a user account to deploying the smart contract and providing a TypeScript binding for easy smart contract calls from frontend code. The file `initialize.js` contains that script, and the functionality of it will be broken down in the following sections. -Here we can see that we're importing our generated `helloWorld` client from `../contracts/hello_world`. We're then invoking the `hello` method and adding the result to the page. +#### Definitions -```ts title="src/pages/index.astro" ---- -import Layout from "../layouts/Layout.astro"; -import Card from "../components/Card.astro"; -import helloWorld from "../contracts/hello_world"; -const { result } = await helloWorld.hello({ to: "you" }); -const greeting = result.join(" "); ---- +Before diving into the functions in the `initialize.js` script, a few constants and variables are defined. The most noteworthy here is `execAsync()`, which will let us execute CLI commands and wait for the command responses. - ... +```javascript +// Get directory names +const __filename = fileURLToPath(import.meta.url); +const dirname = path.dirname(__filename); -