Skip to main content

dapp

Stellar dApp / frontend development. Covers the JavaScript stellar-sdk (browser + Node.js), Freighter wallet, Stellar Wallets Kit (multi-wallet), Wallet Standard, smart accounts with passkeys, transaction building / signing / submission, smart contract invocation from the client, simulation, and error handling. Use when building a React/Next.js/Node.js app that talks to Stellar — classic operations or smart contracts. Blux is also an option.

Quellinformationen

Repository
stellar/stellar-dev-skill
Letzte Quellaktivität
7. Oktober 2026 um 16:55
Erkannte Sprache von SKILL.md
Englisch
Sterne
55
Forks
64

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
4 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
dapp
description
Stellar dApp / frontend development. Covers the JavaScript stellar-sdk (browser + Node.js), Freighter wallet, Stellar Wallets Kit (multi-wallet), Wallet Standard, smart accounts with passkeys, transaction building / signing / submission, smart contract invocation from the client, simulation, and error handling. Use when building a React/Next.js/Node.js app that talks to Stellar — classic operations or smart contracts. Blux is also an option.
user-invocable
true
argument-hint
[dapp task]
# Stellar dApp / Frontend Client-side development with `@stellar/stellar-sdk`, wallet connection, signing, and submitting transactions. Covers both classic Stellar operations and smart contract invocation from the browser or Node.js. ## When to use this skill - Connecting Freighter or other wallets via Stellar Wallets Kit - Building, simulating, signing, and submitting transactions - Invoking Stellar smart contracts from a frontend - Implementing smart accounts with passkeys - Handling network passphrases (Mainnet / Testnet / local) ## Related skills - Writing the contract being invoked → `../smart-contracts/SKILL.md` - Issuing assets and managing trustlines → `../assets/SKILL.md` - Querying chain state via RPC / Horizon → `../data/SKILL.md` - Building paid APIs or agent payment clients → `../agentic-payments/SKILL.md` - SEPs the wallet/anchor flows depend on → `../standards/SKILL.md` --- ## Goals - Single SDK instance for the app (RPC/Horizon + transaction building) - Freighter wallet integration (or multi-wallet via Stellar Wallets Kit) - Clean separation of client/server in Next.js - Transaction sending with proper confirmation handling ## Read the file that matches the task This file covers SDK setup, wallet connection, and transaction build/sign/submit. The deep dives live alongside it: | Task | File | |------|------| | SDK setup and env config | [SDK Initialization](#sdk-initialization) (below) | | Wallet integrations (Freighter, Wallets Kit) | [Wallet Integration](#wallet-integration) (below) | | Tx build/send patterns | [Transaction Building](#transaction-building), [Transaction Submission](#transaction-submission) (below) | | Connect-wallet button, payment form, Next.js App Router wiring | [react.md](react.md) | | Account balances, contract reads (`queryContract`), raw ledger entries | [data-fetching.md](data-fetching.md) | | Passkey smart wallets (Smart Account Kit), gasless tx via OpenZeppelin Relayer | [smart-accounts.md](smart-accounts.md) | | Production UX checklist | [Transaction UX Checklist](#transaction-ux-checklist) (below) | ## Recommended Dependencies > **Requires Node.js 22+.** As of SDK v16, Node 22 is the minimum (older Node produces an `EBADENGINE` warning). v16 also folded `@stellar/stellar-base` into `@stellar/stellar-sdk`, is ESM-first, and uses native `fetch` instead of axios. If you still import `@stellar/stellar-base` directly, switch the import to `@stellar/stellar-sdk` and uninstall the base package (keeping both breaks `instanceof` checks). See the [migration guide](https://stellar.github.io/js-stellar-sdk/guides/00-migration). ```bash npm install @stellar/stellar-sdk @stellar/freighter-api # Or for multi-wallet support — Wallets Kit v2 is distributed on JSR, not npm: npx jsr add @creit-tech/stellar-wallets-kit ``` > **Sourcing:** SDK mechanics below (init, transaction building, contract invocation, submission, data fetching, error handling) track the official [JS SDK docs](https://stellar.github.io/js-stellar-sdk/) (which also publish [`llms.txt`](https://stellar.github.io/js-stellar-sdk/llms.txt) / [`llms-full.txt`](https://stellar.github.io/js-stellar-sdk/llms-full.txt) bundles for agents). Wallet integrations (Freighter, Stellar Wallets Kit), passkey smart accounts, and the OpenZeppelin relayer are separate packages, not part of the JS SDK — verify those against their own upstream docs. ## SDK Initialization > For the full API reference (RPC methods, Horizon endpoints, migration guide), see the [data skill](../data/SKILL.md). ### Basic Setup ```typescript import * as StellarSdk from "@stellar/stellar-sdk"; // For Testnet const testnetServer = new StellarSdk.Horizon.Server("https://horizon-testnet.stellar.org"); const testnetRpc = new StellarSdk.rpc.Server("https://soroban-testnet.stellar.org"); const testnetNetworkPassphrase = StellarSdk.Networks.TESTNET; // For Mainnet const mainnetServer = new StellarSdk.Horizon.Server("https://horizon.stellar.org"); const mainnetRpcUrl = process.env.NEXT_PUBLIC_STELLAR_MAINNET_RPC_URL; if (!mainnetRpcUrl) throw new Error("Missing NEXT_PUBLIC_STELLAR_MAINNET_RPC_URL"); const mainnetRpc = new StellarSdk.rpc.Server(mainnetRpcUrl); // set from your chosen RPC provider const mainnetNetworkPassphrase = StellarSdk.Networks.PUBLIC; ``` ### Environment Configuration > Use a provider-specific mainnet RPC URL (see: https://developers.stellar.org/docs/data/apis/rpc/providers). ```typescript // lib/stellar.ts import * as StellarSdk from "@stellar/stellar-sdk"; const NETWORK = process.env.NEXT_PUBLIC_STELLAR_NETWORK || "testnet"; const requireEnv = (name: string): string => { const value = process.env[name]; if (!value) throw new Error(`Missing required env var: ${name}`); return value; }; function getConfig(network: string) { switch (network) { case "testnet": return { horizonUrl: "https://horizon-testnet.stellar.org", rpcUrl: "https://soroban-testnet.stellar.org", networkPassphrase: StellarSdk.Networks.TESTNET, friendbotUrl: "https://friendbot.stellar.org" as string | null, }; case "mainnet": return { horizonUrl: "https://horizon.stellar.org", // Resolved lazily so testnet runs don't require the mainnet env var rpcUrl: requireEnv("NEXT_PUBLIC_STELLAR_MAINNET_RPC_URL"), networkPassphrase: StellarSdk.Networks.PUBLIC, friendbotUrl: null, }; default: throw new Error(`Unknown network: ${network}`); } } export const config = getConfig(NETWORK); export const horizon = new StellarSdk.Horizon.Server(config.horizonUrl); export const rpc = new StellarSdk.rpc.Server(config.rpcUrl); ``` ## Wallet Integration ### Freighter (Primary Browser Wallet) ```typescript // hooks/useFreighter.ts import { useState, useEffect, useCallback } from "react"; import { isConnected, getAddress, requestAccess, signTransaction, getNetwork, } from "@stellar/freighter-api"; export function useFreighter() { const [connected, setConnected] = useState(false); const [address, setAddress] = useState<string | null>(null); const [network, setNetwork] = useState<string | null>(null); useEffect(() => { checkConnection(); }, []); const checkConnection = async () => { const { isConnected: installed, error } = await isConnected(); if (error || !installed) return; // getAddress returns address: "" until the app has been granted access, // so a non-empty address means we're already authorized. const { address: addr, error: addressError } = await getAddress(); if (addressError || !addr) return; const { network: net, error: networkError } = await getNetwork(); if (networkError) return; setConnected(true); setAddress(addr); setNetwork(net); }; const connect = useCallback(async () => { const { isConnected: installed, error } = await isConnected(); if (error || !installed) { throw new Error("Freighter extension not installed"); } // requestAccess prompts the user and returns the granted address. const { address: addr, error: accessError } = await requestAccess(); if (accessError) throw new Error(accessError.message); const { network: net, error: networkError } = await getNetwork(); if (networkError) throw new Error(networkError.message); setConnected(true); setAddress(addr); setNetwork(net); return addr; }, []); const disconnect = useCallback(() => { setConnected(false); setAddress(null); setNetwork(null); }, []); const sign = useCallback( async (xdr: string, networkPassphrase: string) => { if (!connected) throw new Error("Wallet not connected"); const { signedTxXdr, error } = await signTransaction(xdr, { networkPassphrase, }); if (error) throw new Error(error.message); return signedTxXdr; }, [connected] ); return { connected, address, network, connect, disconnect, sign }; } ``` ### Stellar Wallets Kit (Multi-Wallet) ```typescript // hooks/useStellarWallet.ts import { useState, useCallback } from "react"; import { StellarWalletsKit, Networks } from "@creit-tech/stellar-wallets-kit"; import { defaultModules } from "@creit-tech/stellar-wallets-kit/modules/utils"; // v2 is a static singleton: init once at module load, then call static methods — // there is no instance to construct or pass around. // defaultModules() loads every wallet that needs no extra setup; modules with // prerequisites (WalletConnect, Ledger, Trezor) must be imported and added explicitly. StellarWalletsKit.init({ modules: defaultModules(), network: Networks.TESTNET, }); export function useStellarWallet() { const [address, setAddress] = useState<string | null>(null); const connect = useCallback(async () => { // authModal() opens the wallet picker, sets the chosen module active, // and returns the address — one call replaces v1's openModal callback dance. const { address } = await StellarWalletsKit.authModal(); setAddress(address); }, []); const disconnect = useCallback(async () => { await StellarWalletsKit.disconnect(); setAddress(null); }, []); const sign = useCallback(async (xdr: string) => { const { signedTxXdr } = await StellarWalletsKit.signTransaction(xdr); return signedTxXdr; }, []); return { address, connect, disconnect, sign }; } ``` > **Migrating from v1?** (noted July 2026) v1 lived on npm under the dotted scope `@creit.tech/stellar-wallets-kit`, with `new StellarWalletsKit({...})`, `allowAllModules()`, and `openModal({ onWalletSelected })`. v2 moved to JSR under `@creit-tech/stellar-wallets-kit`, made the kit fully static, replaced `allowAllModules()` with `defaultModules()`, and folded wallet selection + address fetch into `authModal()`. npm parity is maintained for now, but the maintainers say npm updates will eventually stop — install from JSR. Pre-selecting a wallet (`setWallet(FREIGHTER_ID)`) still works; the ID constants now live in per-wallet module subpaths like `@creit-tech/stellar-wallets-kit/modules/freighter`. You can also use [Blux](https://blux.cc) for wallet integration and contract calls. See [react.md](react.md) and [data-fetching.md](data-fetching.md) for examples. ## Transaction Building ### Basic Payment ```typescript import * as StellarSdk from "@stellar/stellar-sdk"; import { horizon, config } from "@/lib/stellar"; export async function buildPaymentTx( sourceAddress: string, destinationAddress: string, amount: string, asset: StellarSdk.Asset = StellarSdk.Asset.native() ) { const account = await horizon.loadAccount(sourceAddress); const transaction = new StellarSdk.TransactionBuilder(account, { fee: StellarSdk.BASE_FEE, networkPassphrase: config.networkPassphrase, }) .addOperation( StellarSdk.Operation.payment({ destination: destinationAddress, asset: asset, amount: amount, }) ) .setTimeout(180) .build(); return transaction.toXDR(); } ``` ### Smart Contract Invocation (`contract.Client`) The canonical way to call a Stellar smart contract from JS is the `contract.Client`, not hand-built `Contract.call` + `assembleTransaction`. The client reads the contract's interface from the network, so each method is callable by name and returns an `AssembledTransaction`. You get a native JS result and don't build ScVals by hand. ```typescript import { contract } from "@stellar/stellar-sdk"; import { config } from "@/lib/stellar"; // Describe just the methods you call. `Client.from<T>()` uses this to type // the returned client, so calls are checked and autocompleted — no codegen. // For a contract with many methods, generate this interface from its spec // with the SDK's binding CLI instead of writing it by hand. interface CounterContract { increment: ( options?: contract.MethodOptions, ) => Promise<contract.AssembledTransaction<number>>; } // `signTransaction` comes from the wallet (e.g. Freighter/Wallets Kit in the // browser). `contract.basicNodeSigner(keypair, networkPassphrase)` is the // Node equivalent for scripts and tests. export async function getCounterClient( contractId: string, publicKey: string, signTransaction: contract.ClientOptions["signTransaction"], ) { return contract.Client.from<CounterContract>({ contractId, rpcUrl: config.rpcUrl, networkPassphrase: config.networkPassphrase, publicKey, signTransaction, }); } // Preview (free simulation) then sign + send to apply on-chain. export async function increment(client: contract.Client & CounterContract) { const tx = await client.increment(); console.log("preview:", tx.result); // predicted return value, no signature const sent = await tx.signAndSend(); // submits and polls to completion return sent.result; } ``` `AssembledTransaction` also supports fine-grained control (`{ fee, simulate, timeoutInSeconds }` as a second arg) and multi-party auth via `tx.needsNonInvokerSigningBy()` / `tx.signAuthEntries()`. See [Invoke a Contract](https://stellar.github.io/js-stellar-sdk/guides/06-invoke-a-contract) and [Authorize a Contract Call](https://stellar.github.io/js-stellar-sdk/guides/07-contract-auth). <details> <summary><b>Advanced: low-level invocation without a client</b></summary> Use this only when you need direct control over the transaction (e.g. batching a contract call with classic operations). Otherwise prefer `contract.Client` above. ```typescript import * as StellarSdk from "@stellar/stellar-sdk"; import { rpc, config } from "@/lib/stellar"; export async function invokeContract( sourceAddress: string, contractId: string, method: string, args: StellarSdk.xdr.ScVal[] ) { const account = await rpc.getAccount(sourceAddress); const contract = new StellarSdk.Contract(contractId); const transaction = new StellarSdk.TransactionBuilder(account, {
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen