From 2610e445c7ddd859438571f343e89eed7536f4a5 Mon Sep 17 00:00:00 2001 From: Chad Ostrowski <221614+chadoh@users.noreply.github.com> Date: Wed, 11 Dec 2024 13:58:44 -0500 Subject: [PATCH] fix: update frontend tutorial to latest libs And just make sure it works, in general. It was pretty broken. Relies on these fixes: - https://github.com/stellar/soroban-template-astro/pull/13 - https://github.com/stellar/soroban-template-astro/pull/14 And can be cleaned up once this is merged: - https://github.com/Creit-Tech/Stellar-Wallets-Kit/pull/49 --- docs/build/apps/dapp-frontend.mdx | 166 +++++++++++++++++++----------- 1 file changed, 107 insertions(+), 59 deletions(-) diff --git a/docs/build/apps/dapp-frontend.mdx b/docs/build/apps/dapp-frontend.mdx index 6ffd509a0..23773d3ed 100644 --- a/docs/build/apps/dapp-frontend.mdx +++ b/docs/build/apps/dapp-frontend.mdx @@ -228,52 +228,87 @@ import { allowAllModules, FREIGHTER_ID, StellarWalletsKit, - WalletNetwork, } from "@creit.tech/stellar-wallets-kit"; -const kit: StellarWalletsKit = new StellarWalletsKit({ +const SELECTED_WALLET_ID = "selectedWalletId"; + +function getSelectedWalletId() { + return localStorage.getItem(SELECTED_WALLET_ID); +} + +// TODO: stop exporting all of `kit` pending merge & release of: +// https://github.com/Creit-Tech/Stellar-Wallets-Kit/pull/49 +export const kit: StellarWalletsKit = new StellarWalletsKit({ modules: allowAllModules(), - network: WalletNetwork.TESTNET, - selectedWalletId: FREIGHTER_ID, + network: import.meta.env.PUBLIC_STELLAR_NETWORK_PASSPHRASE, + // StellarWalletsKit forces you to specify a wallet, even if the user didn't + // select one yet, so we default to Freighter. + // We'll work around this later in `getPublicKey`. + selectedWalletId: getSelectedWalletId() ?? FREIGHTER_ID, }); -const connectionState: { publicKey: string | undefined } = { - publicKey: undefined, -}; +export async function getPublicKey() { + if (!getSelectedWalletId()) return null; + const { address } = await kit.getAddress(); + return address; +} -function loadedPublicKey(): string | undefined { - return connectionState.publicKey; +export async function setWallet(walletId: string) { + localStorage.setItem(SELECTED_WALLET_ID, walletId); + kit.setWallet(walletId); } -function setPublicKey(data: string): void { - connectionState.publicKey = data; +export async function disconnect(callback?: () => Promise) { + localStorage.removeItem(SELECTED_WALLET_ID); + kit.disconnect(); + if (callback) await callback(); } -export { kit, loadedPublicKey, setPublicKey }; +export async function connect(callback?: () => Promise) { + await kit.openModal({ + onWalletSelected: async (option) => { + try { + await setWallet(option.id); + if (callback) await callback(); + } catch (e) { + console.error(e); + } + return option.id; + }, + }); +} ``` -In the code above, we created an instance of the kit and two simple functions that will take care of "setting" and "loading" the public key of the user. This lets us use the user's public key elsewhere in our code. The kit is started with Freighter as the default wallet, and the Testnet network as the default network. You can learn more about how the kit works in [the StellarWalletsKit documentation](https://stellarwalletskit.dev/) +In the code above, we instantiate the kit with desired settings and export it. We also wrap some kit functions and add custom functionality, such as augmenting the kit by allowing it to remember which wallet options was selected between page refreshes (that's the `localStorage` bit). The kit requires a `selectedWalletId` even before the user selects one, so we also work around this limitation, as the code comment explains. You can learn more about how the kit works in [the StellarWalletsKit documentation](https://stellarwalletskit.dev/) -Now we're going to add a "Connect" button to the page which will open the kit's built in modal, and prompt the user to use their preferred wallet. Once the user picks their preferred wallet and grants permission to accept requests from the website, we will fetch the public key and the "Connect" button will be replaced with a message saying, "Signed in as [their public key]". +Now we're going to add a "Connect" button to the page which will open the kit's built-in modal, and prompt the user to use their preferred wallet. Once the user picks their preferred wallet and grants permission to accept requests from the website, we will fetch the public key and the "Connect" button will be replaced with a message saying, "Signed in as [their public key]". Now let's add a new component to the `src/components` directory called `ConnectWallet.astro` with the following content: ```html title="src/components/ConnectWallet.astro"
-
- -
+   +
+ +
``` @@ -325,7 +370,7 @@ And all the `script` declarations get bundled together and included intelligentl You can read more about this in [Astro's page about client-side scripts](https://docs.astro.build/en/guides/client-side-scripts/). -The code itself here is pretty self-explanatory. We import the wallets kit from the file we created before. Then, when the user clicks on the button, we launch the built-in modal do display to the user connection options. Once the user picks their preferred wallet, we set it as the wallets kit's default wallet before requesting and saving the address. +The code itself here is pretty self-explanatory. We import `kit` from the file we created before. Then, when the user clicks on the sign-in button, we call the `connect` function we created in our `stellar-wallets-kit.ts` file above. This will launch the built-in StellarWalletsKit modal, which allows the user to pick from the wallet options we configured (we configured all of them, with `allowAllModules`). We pass our own `setLoggedIn` function as the callback, which will be called in the `onWalletSelected` function in `stellar-wallets-kit.ts`. We end by updating the UI, based on whether the user is currently connected or not. Now we can import the component in the frontmatter of `pages/index.astro`: @@ -341,7 +386,7 @@ Now we can import the component in the frontmatter of `pages/index.astro`: And add it right below the `

`: ```diff title="pages/index.astro" -

{greeting}

+

{greeting}

+ ``` @@ -366,13 +411,15 @@ Current value: ???
``` This should be somewhat familiar by now. We have a `script` that, thanks to Astro's build system, can `import` modules directly. We use `document.querySelector` to find the elements defined above. And we add a `click` handler to the button, which calls `increment` and updates the value on the page. It also sets the button to `disabled` and adds a `loading` class while the call is in progress to prevent the user from clicking it again and visually communicate that something is happening. For people using screen readers, the loading state is communicated with the [visually-hidden](https://www.a11yproject.com/posts/how-to-hide-content/) span, which will be announced to them thanks to the `aria` tags we saw before. -The biggest difference from the call to `greeter.hello` is that this transaction gets executed in two steps. The initial call to `increment` constructs a Soroban transaction and then makes an RPC call to _simulate_ it. For read-only calls like `hello`, this is all you need, so you can get the `result` right away. For write calls like `increment`, you then need to `signAndSend` before the transaction actually gets included in the ledger. +The biggest difference from the call to `greeter.hello` is that this transaction gets executed in two steps. The initial call to `increment` constructs a Soroban transaction and then makes an RPC call to _simulate_ it. For read-only calls like `hello`, this is all you need, so you can get the `result` right away. For write calls like `increment`, you then need to `signAndSend` before the transaction actually gets included in the ledger. You also need to make sure you set a valid `publicKey` and a `signTransaction` method. :::info