-
Notifications
You must be signed in to change notification settings - Fork 146
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add a tutorial building the guestbook dapp (#1120)
* add ye olde guestbook tutorial * add screenshots * add many links * add a small section with links to the smart-wallets page * First couple sections * editorial * editorial fixes --------- Co-authored-by: Bri <[email protected]>
- Loading branch information
1 parent
6de2e44
commit d4ca6ad
Showing
11 changed files
with
1,598 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--- | ||
title: Build a Passkey Powered Guestbook Dapp | ||
sidebar_position: 57 | ||
--- | ||
|
||
import DocCardList from "@theme/DocCardList"; | ||
|
||
This section walks you through designing and building a decentralized application (dapp) that interacts with a smart contract guestbook, allowing users to read and write public messages. This tutorial also implements a passkey-powered smart wallet for user authentication. | ||
|
||
<DocCardList /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
--- | ||
title: Generate Bindings | ||
sidebar_position: 30 | ||
--- | ||
|
||
Let's turn our attention to how we'll interact with the deployed smart contract. This is where the TypeScript bindings come in! But, I hear you ask: What are TypeScript bindings? | ||
|
||
These bindings are a feature of the Stellar CLI that will generate and produce a fully typed NPM package ready for integration into your frontend. This means you can import and invoke a smart contract as if it were any other nodejs package! You get typed functions for each of your contract's functions, and those will result in a built, simulated, signable, and submittable assembled transaction! | ||
|
||
:::tip | ||
|
||
This can be done with ANY contract that's live on the network! Or, you can use it on contracts you've only compiled locally, too. | ||
|
||
::: | ||
|
||
We'll be generating our contract bindings, and keeping them in the same repository as our frontend code. However, you could do this in a lot of different ways: | ||
|
||
- Your frontend can instantiate a `contract.Client` instance using the [`fromWasmHash` function](https://stellar.github.io/js-stellar-sdk/module-contract.Client.html#.fromWasmHash) of the JavaScript SDK. This can generate bindings on-the-fly as your users browse your application. | ||
- Your deploy process might include a step that builds/deploys/binds a contract package at deploy-time. | ||
- You could even generate and publish a bindings package all by itself. Then `pnpm install <bindings_package_name>` can be done in any dapp that you (or somebody else) might need to interact with that contract. | ||
|
||
### The manual method | ||
|
||
Before you skip ahead! Take a look at this (brief) section. It's _really_ useful to have a full understanding of what steps we're going through in the automated section. This will help you adapt and/or troubleshoot this tutorial for your specific purposes. | ||
|
||
#### Install the compiled contract | ||
|
||
The smart contract code needs to be installed to the network first. This uploads the compiled, binary Wasm file to the blockchain to be instantiated into a contract later on. From inside your project directory: | ||
|
||
```shell | ||
stellar contract install \ | ||
--source S...ECRETKEY \ | ||
--network testnet \ | ||
--wasm ./target/wasm32-unknown-unknown/release/ye_olde_guestbook.wasm | ||
``` | ||
|
||
#### Deploy a contract instance | ||
|
||
This will return a hexadecimal hash corresponding to the uploaded Wasm executable. This hash can then be used in the deploy command to create a new contract instance: | ||
|
||
```shell | ||
stellar contract deploy \ | ||
--source S...ECRETKEY \ | ||
--network testnet \ | ||
--wasm-hash <wasm_hash_from_install_step> | ||
``` | ||
|
||
#### Generate bindings for the deployed contract | ||
|
||
Now we can (again) use the Stellar CLI to generate bindings from the contract we've just deployed. You can also generate these bindings from your local Wasm file using the `--wasm-hash` parameter. The `--overwrite` parameter is used to tell the CLI that it should output the generated bindings package, even if it finds the directory is not empty (i.e., we're re-binding a contract because we've modified the code and redeployed it). | ||
|
||
```shell | ||
stellar contract bindings typescript \ | ||
--source S...ECRETKEY \ | ||
--network testnet \ | ||
--id <contract_address_from_deploy_step> \ | ||
--output-dir ./packages/ye_olde_guestbook \ | ||
--overwrite | ||
``` | ||
|
||
We'll need to build the bindings package, since (in its initial state) the package is mostly TypeScript types and stubs for the various contract functions. | ||
|
||
```shell | ||
cd packages/ye_olde_guestbook | ||
pnpm install | ||
pnpm run build | ||
cd ../.. | ||
``` | ||
|
||
#### Import the bindings package as a project dependency | ||
|
||
With our bindings generated, we can add it to our frontend project. Run this from the root of your project: | ||
|
||
```shell | ||
pnpm add file:./packages/ye_olde_guestbook | ||
``` | ||
|
||
#### Import the bindings client into the SvelteKit project | ||
|
||
:::info | ||
|
||
We're straying just a _bit_ into the Svelte-ish side of things here. The main goal of this step is to get the contract client (which is the "bindings package" we've just generated) into our frontend in a way that makes it usable anywhere we need it. In SvelteKit, we put it into `src/lib/contracts` because that means we can easily access the client by importing from `$lib/contracts/ye_olde_guestbook` whenever and wherever we need it. | ||
|
||
::: | ||
|
||
Now, we'll define the contract client in a way we can easily access it through the rest of our app. | ||
|
||
```js title="src/lib/contracts/ye_olde_guestbook.ts" | ||
import * as Client from "ye_olde_guestbook"; // import the package we just added as a dependency | ||
import { PUBLIC_STELLAR_RPC_URL } from "$env/static/public"; // import the RPC url from the .env file | ||
|
||
// instantiate and export the Client class from the bindings package | ||
export default new Client.Client({ | ||
...Client.networks.testnet, // this includes the contract address and network passphrase | ||
rpcUrl: PUBLIC_STELLAR_RPC_URL, // this is required to invoke the contract through RPC calls | ||
}); | ||
``` | ||
|
||
### The automated way | ||
|
||
That was a lot of steps and a lot of work wasn't it!? The good news is that our starter template (remember that?) comes with an `initialize.js` script that will perform all of those actions for you! This script will go through all the following steps for you: | ||
|
||
- Create and fund a keypair in the CLI | ||
- Install and deploy **all contracts** in the `/contracts` directory | ||
- Generate bindings from the deployed contracts | ||
- Create a `$lib/contracts/<contract_alias>.ts` file for easy import into your frontend code | ||
|
||
You can always customize this script to suit your needs. Check out the [source code here](https://github.com/ElliotFriend/soroban-template-sveltekit-passkeys/blob/main/initialize.js) (which has been documented with comments). Or, you can see the [officially maintained script](https://github.com/stellar/soroban-template-astro/blob/main/initialize.js) in the [`soroban-template-astro` repository](https://github.com/stellar/soroban-template-astro), as well. | ||
|
||
Run the initialization script like so: | ||
|
||
```shell | ||
node initialize.js | ||
``` | ||
|
||
:::info | ||
|
||
For a more comprehensive overview of the process of creating, customizing, and using initialization scripts like this, check out the [frontend template guide](https://developers.stellar.org/docs/build/guides/dapps/soroban-contract-init-template). | ||
|
||
::: | ||
|
||
We've also added a command to the `package.json` scripts, so you can run this initialize script simply by running (from your project's root directory): | ||
|
||
```shell | ||
pnpm run setup | ||
``` | ||
|
||
Right, so we've now created a starter project, written a guestbook smart contract, and generated an NPM package that will help us interact with that contract on the network. Amazing! | ||
|
||
Next up, let's take a look at how our users will connect with and interact with our dapp. It's time for passkeys! (insert air horn noises)📢 |
Oops, something went wrong.