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.

소스 정보

저장소
stellar/stellar-dev-skill
최근 소스 활동
2026년 10월 7일 16:55
감지된 SKILL.md 언어
영어
스타
55
포크
64

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
4 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
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, {
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기