Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 32 additions & 18 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,27 +1,41 @@
# The network passphrase and RPC url are used to connect to the network
# ─────────────────────────────────────────────────────────────────────────────
# Ye Olde Guestbook — environment variables
#
# Values prefixed `PUBLIC_` are inlined into the client bundle by Vite. Values
# prefixed `PRIVATE_` stay server-side and are only readable from SvelteKit
# server routes (i.e. Cloudflare Pages Functions in production).
# ─────────────────────────────────────────────────────────────────────────────

# Stellar network targeted by the app.
PUBLIC_STELLAR_NETWORK_PASSPHRASE="Test SDF Network ; September 2015"
PUBLIC_STELLAR_RPC_URL="https://soroban-testnet.stellar.org"

# The network name and account here are used by the initialization script, which
# runs some commands from the Stellar CLI
# Used by the initialization script (`pnpm setup`) to drive the Stellar CLI.
PUBLIC_STELLAR_NETWORK=testnet
PUBLIC_STELLAR_ACCOUNT=alice

# This Wasm hash will determine the executable code that will be deployed each
# time a user creates a smart wallet. This Wasm hash doesn't need to be changed,
# and can be copy/pasted into any smart wallet dapp.
PUBLIC_WALLET_WASM_HASH=ecd990f0b45ca6817149b6175f79b32efb442f35731985a084131e8265c4cd90

# Launchtube and mercury URLs for submitting transactions and indexing smart
# wallet creations, respectively
PUBLIC_LAUNCHTUBE_URL="https://testnet.launchtube.xyz"
# ── Smart Account Kit ────────────────────────────────────────────────────────
#
# Wasm hash + WebAuthn verifier from the shared OpenZeppelin Smart Account
# deployment on Testnet. These are stable and safe to copy between apps.
# See https://github.com/kalepail/smart-account-kit for the latest values.
PUBLIC_ACCOUNT_WASM_HASH=a12e8fa9621efd20315753bd4007d974390e31fbcb4a7ddc4dd0a0dec728bf2e
PUBLIC_WEBAUTHN_VERIFIER_ADDRESS=CBSHV66WG7UV6FQVUTB67P3DZUEJ2KJ5X6JKQH5MFRAAFNFJUAJVXJYV

# Launchtube credentials. Grab one for Testnet at
# https://testnet.launchtube.xyz/gen
PRIVATE_LAUNCHTUBE_JWT="generate-one-from-https://testnet.launchtube.xyz/gen"
# ── OpenZeppelin Relayer (Channels plugin) ───────────────────────────────────
#
# The relayer submits smart-account transactions for users so they don't have
# to fund their own fees. Generate a Testnet API key at
# https://channels.openzeppelin.com/testnet/gen
#
# NOTE: kept on the server side so the key never reaches the browser. The
# client hits our same-origin /api/relay proxy instead.
PRIVATE_RELAYER_BASE_URL="https://channels.openzeppelin.com/testnet"
PRIVATE_RELAYER_API_KEY="paste-your-channels-testnet-api-key-here"

# Fund an account on Testnet using Friendbot, and put the public and secret keys
# here. This account will give your guestbook users a mini-airdrop of Testnet
# XLM during the signup process.
PUBLIC_FUNDER_PUBLIC_KEY=G...ENERALLYPUBLIC # really just here for reference
# ── Funder account ───────────────────────────────────────────────────────────
#
# A classic G-account loaded with Testnet XLM via Friendbot. The /api/fund
# endpoint uses it to drop 25 XLM into a freshly-deployed smart wallet so the
# user can transact immediately.
PRIVATE_FUNDER_SECRET_KEY=S...ECRETKEY
126 changes: 90 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,121 @@
# Ye Olde Guestbook <!-- omit from toc -->

A passkey powered dapp that acts like a smart contract version of the [internet
A passkey-powered dapp that acts like a smart-contract version of the [internet
guestbooks](https://en.wikipedia.org/wiki/Guestbook) from the olden days!

> **Fork notice.** This is an updated fork of
> [ElliotFriend/ye-olde-guestbook](https://github.com/ElliotFriend/ye-olde-guestbook).
> The original used `passkey-kit` and Launchtube, both of which are now legacy
> (Launchtube is archived and its hosted service is offline). This fork is
> rebuilt on:
>
> - [Smart Account Kit](https://github.com/kalepail/smart-account-kit) — the
> successor SDK to `passkey-kit`.
> - [OpenZeppelin Smart Account](https://docs.openzeppelin.com/stellar-contracts/accounts/smart-account) —
> the audited smart account contracts it deploys.
> - [OpenZeppelin Relayer (Stellar Channels)](https://docs.openzeppelin.com/relayer/1.4.x/guides/stellar-channels-guide) —
> replaces Launchtube for fee-sponsored submissions.

## Table of Contents <!-- omit from toc -->

- [Give it a Spin](#give-it-a-spin)
- [Passkeys](#passkeys)
- [Anatomy of the Repository](#anatomy-of-the-repository)
- [Smart Contract](#smart-contract)
- [Frontend](#frontend)
- [Relayer Proxy](#relayer-proxy)
- [Running Locally](#running-locally)
- [Deploying to Cloudflare Pages](#deploying-to-cloudflare-pages)
- [More Info](#more-info)

## Give it a Spin

![guestbook screenshot](screenshot.png)

You can get to a Testnet version of the dapp here:

- [ye-olde-guestbook.vercel.app](https://ye-olde-guestbook.vercel.app)

## Passkeys

We utilize Tyler's **amazing**
[passkey-kit](https://github.com/kalepail/passkey-kit) to interact with users
and authenticate with their passkeys. This makes it possible for users to get
on-chain without _any_ of the usual obstacles that can stand in their way.
Users sign transactions with a device passkey (Touch ID, Face ID, or a hardware
key) via WebAuthn. No seed phrases, no browser extensions — the private key
never leaves the authenticator, and the smart account contract verifies the
`secp256r1` signature on-chain.

> Seriously. You have **GOT** to start thinking about passkeys.
Smart Account Kit handles the WebAuthn ceremony, deploys an OpenZeppelin Smart
Account per user on first signup, and stores the credential metadata in
IndexedDB so the session survives page reloads.

## Anatomy of the Repository

### Smart Contract

The [Stellar smart
contract](https://developers.stellar.org/docs/build#smart-contracts) that powers
this dapp is located in the `/contracts/ye_olde_guestbook` directory. It's
simple enough that you can probably get a pretty solid understanding, just by
browsing through the source code.

This smart contract is also used to generate "bindings" that can be imported and
used in the frontend code. The bindings are located in the
`/packages/ye_olde_guestbook` directory. They're auto-generated each time the
`initialize.js` script is run (you can use `npm run init` for this), so the
generated bindings are always going to be up-to-date with the deployed smart
contract.
The [Stellar smart contract](https://developers.stellar.org/docs/build#smart-contracts)
powering the guestbook lives in `contracts/ye_olde_guestbook`. The `initialize.js`
script (invoked with `pnpm run setup`) builds it, deploys it, and regenerates
the TypeScript bindings in `packages/ye_olde_guestbook`.

### Frontend

The frontend files are found in the `/src` directory. It's a
[SvelteKit](https://kit.svelte.dev/) app. There are server-only API routes
located in the `/src/routes/api` directory. Components and utilities are
included in the `/src/lib` directory.
The frontend is a [SvelteKit](https://kit.svelte.dev/) app under `src/`.

- `src/lib/passkeyClient.ts` wires up Smart Account Kit and exposes the
`account`, `native`, and `send()` helpers the UI reaches for.
- `src/lib/server/relayer.ts` holds the server-side `ChannelsClient` and the
API key for the OpenZeppelin Relayer.
- `src/routes/api/relay/+server.ts` proxies transaction submissions to the
relayer so the API key never reaches the browser.
- `src/routes/api/fund/[address]/+server.ts` drops 25 XLM on a freshly-deployed
wallet using a server-held funder keypair.

### Relayer Proxy

OpenZeppelin's hosted relayer doesn't accept calls from browser origins with
the API key embedded client-side. To keep the key off the wire we run the
`/api/relay` route as a same-origin Cloudflare Pages Function: the client
POSTs its XDR to `/api/relay`, the function forwards to
`https://channels.openzeppelin.com/testnet/<KEY>`, and the hash comes back.

## Running Locally

```bash
pnpm install
cp .env.example .env # fill in values — see comments in the file
pnpm run setup # build + deploy the guestbook contract
pnpm run dev
```

You'll need:

- A Testnet OpenZeppelin Channels API key
([generate one here](https://channels.openzeppelin.com/testnet/gen)).
- A funded Testnet G-account for the funder role
([Friendbot](https://friendbot.stellar.org)).
- A modern browser with a registered passkey authenticator.

## Deploying to Cloudflare Pages

With `@sveltejs/adapter-cloudflare` the whole app — static assets _and_ the
`/api/*` functions — deploys as a single Pages project. The short version:

```bash
pnpm run build
npx wrangler pages deploy .svelte-kit/cloudflare
```

Then set the four private env vars in the Pages project settings
(`PRIVATE_RELAYER_BASE_URL`, `PRIVATE_RELAYER_API_KEY`,
`PRIVATE_FUNDER_SECRET_KEY`, and the `PUBLIC_*` values) via
`wrangler pages secret put` or the Cloudflare dashboard.

## More Info

- Source Code: <https://github.com/elliotfriend/ye-olde-guestbook>
- Testnet Dapp: <https://ye-olde-guestbook.vercel.app>
- Developer Documentation:
<https://developers.stellar.org/docs/build/apps/smart-wallets>
- Passkey-kit: <https://github.com/kalepail/passkey-kit>
- Superpeach: <https://github.com/kalepail/superpeach>
- Launchtube: <https://github.com/kalepail/launchtube>
- Mercury Data Indexer: <https://www.mercurydata.app>
- [Join us on Discord](https://discord.gg/stellardev), and ask questions in the
`#passkeys` channel
- Original source:
<https://github.com/ElliotFriend/ye-olde-guestbook>
- Smart Account Kit:
<https://github.com/kalepail/smart-account-kit>
- OpenZeppelin Smart Account docs:
<https://docs.openzeppelin.com/stellar-contracts/accounts/smart-account>
- OpenZeppelin Relayer — Stellar Channels guide:
<https://docs.openzeppelin.com/relayer/1.4.x/guides/stellar-channels-guide>
- Developer documentation:
<https://developers.stellar.org/docs/build/guides/contract-accounts/smart-wallets>
- [Join us on Discord](https://discord.gg/stellardev) and ask questions in the
`#passkeys` channel.
7 changes: 2 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,17 @@
"format": "prettier --write ."
},
"dependencies": {
"@floating-ui/dom": "^1.7.1",
"@lucide/svelte": "^0.562.0",
"@stellar/stellar-sdk": "^14.4.2",
"@tailwindcss/vite": "^4.1.18",
"buffer": "^6.0.3",
"passkey-kit": "^0.11.3"
"smart-account-kit": "^0.2.10"
},
"devDependencies": {
"@eslint/compat": "^1.4.0",
"@eslint/js": "^9.39.1",
"@skeletonlabs/skeleton": "^4.8.0",
"@skeletonlabs/skeleton-svelte": "^4.8.0",
"@sveltejs/adapter-auto": "^7.0.0",
"@sveltejs/adapter-cloudflare": "^7.2.8",
"@sveltejs/kit": "^2.43.5",
"@sveltejs/vite-plugin-svelte": "^6.2.1",
"@tailwindcss/forms": "^0.5.10",
Expand All @@ -35,7 +33,6 @@
"@types/node": "^22",
"@typescript-eslint/eslint-plugin": "^8.33.1",
"@typescript-eslint/parser": "^8.33.1",
"base64url": "^3.0.1",
"dotenv": "^17.2.2",
"eslint": "^9.39.1",
"eslint-config-prettier": "^10.1.8",
Expand Down
Loading