Documentación
spare-wallets-kit
Suma Spare a una app que firma con Stellar Wallets Kit: antes de cada firma, la persona ve “¿Sumar US$0,50 para [fundación]?” y decide. No se agrega nada sin un sí explícito. Spare nunca retiene fondos.
Instalar
pnpm add spare-wallets-kit spare-sdk @creit.tech/stellar-wallets-kit @stellar/stellar-sdkGuía rápida
import { StellarWalletsKit } from "@creit.tech/stellar-wallets-kit";
import { Networks } from "@stellar/stellar-sdk";
import { HorizonAccountPort } from "spare-sdk";
import { withSpare } from "spare-wallets-kit";
const spare = withSpare(StellarWalletsKit, {
foundation: { account: "G...", domain: "foundation.org" }, // listed in its stellar.toml
foundationName: "Tellus Cooperative",
mode: { amount: "0.50" }, // or { roundUp: true } for USDC purchases
appId: "my-app", // <= 22 ASCII bytes
maxAmount: "5",
accounts: new HorizonAccountPort("https://horizon.stellar.org"),
networkPassphrase: Networks.PUBLIC,
locale: "es",
});
// Same signature as the kit: use it wherever you called kit.signTransaction.
const { signedTxXdr } = await spare.signTransaction(xdr, { address });¿Necesitas saber si cambió el hash? Usa signWithDonation: devuelve { signedTxXdr, donation, changed, outcome }.
Seguimiento en Soroban
Una transacción Soroban tiene una sola operación, así que la donación es un pago aparte después de que tu llamada resulte bien. Necesita una segunda firma, y el modal lo avisa.
// A Soroban tx holds one operation: the donation is a separate payment after success.
const follow = await spare.offerFollowUp({ successful: true, sourceAccount: address, hash });
if (follow.status === "signed") await submit(follow.signedTxXdr); // submitting is your jobAPI
| Export | Qué hace |
|---|---|
withSpare(kit, options) | Devuelve { signTransaction, signWithDonation, offerFollowUp, lastDonation }. |
createConfirmModal({ locale?, theme? }) | Interfaz de confirmación por defecto (DOM puro, shadow root). Resuelve true solo con el botón principal. |
Opciones
| Opción | Requerida | Descripción |
|---|---|---|
foundation | sí | { account, domain }. Dominio verificado mediante el stellar.toml de SEP-1. |
foundationName | no | Nombre que ve la persona. Por defecto, el dominio. |
mode | sí | { amount: "0.50" } o { roundUp: true } (solo compras en USDC). |
appId | sí | Etiqueta para el memo spare:<appId>. |
maxAmount | sí | Tu tope por donación, en USDC. |
accounts | sí | AccountPort de spare-sdk (por ejemplo HorizonAccountPort). |
fetch | no | Fetch propio para consultar stellar.toml. |
networkPassphrase | no | Se usa para leer el XDR cuando la llamada no lo recibe. Sin ninguno, la transacción se firma sin cambios. |
confirm | no | (prompt: DonationPrompt) => Promise<boolean>. Reemplaza el modal integrado. |
locale / theme | no | "en" | "es"; "light" | "dark" | "auto" para el modal integrado. |
wallet | no | Id de wallet (o función). Por defecto kit.selectedModule.productId. LEDGER muestra la nota “revisa tu Ledger”. |
followUpAmount | no | Monto del seguimiento en Soroban. Por defecto el mode.amount fijo; obligatorio con redondeo. |
Resultados
signWithDonation devuelve { signedTxXdr, donation, changed, outcome, reason? }. outcome es uno de donated, declined, not-offered, passthrough o error. donation es null cuando se firmó la transacción original, y changed es true cuando la transacción firmada no es la que pasaste.
offerFollowUp resuelve a { status: "signed", signedTxXdr, donation } o { status: "skipped", reason }. Enviarla es tu trabajo.
DonationPrompt y confirmación propia
DonationPrompt es { amount, foundationName, foundationDomain, mode: "fixed" | "round-up", wallet: "classic" | "soroban" | "ledger", locale, secondSignature, purchaseTotal?, roundUpTotal? }. purchaseTotal y roundUpTotal vienen directo de donation.purchase / donation.roundedTotal de spare-sdk. Pasa tu propio confirm para reemplazar el modal; devuelve true solo con un sí explícito.
Reglas de paso directo
- Solo se modifican transacciones sin firmar, sin fee-bump, clásicas y de un solo firmante de origen. Agregar una operación cambia el hash y la comisión, así que todo lo demás (parcialmente firmadas, multisig, firmantes extra, fee-bump, Soroban) se firma sin cambios y no se ofrece donación.
- Una revisión fallida en spare-sdk (fundación sin verificar, sin trustline, saldo bajo, sobre el tope) significa que no hay pregunta y se firma la original.
- Si la persona dice que no: se firma el XDR original, byte por byte.
- Cualquier error dentro de Spare (XDR inválido, falla de consulta, caída del confirm) falla cerrado: se firma la original. Los errores de la wallet, por ejemplo cuando la persona rechaza en la wallet, no se tragan.
Modal integrado
role="dialog", aria-modal, título etiquetado, trampa de foco, Esc lo omite, el foco vuelve a quien lo abrió, se respeta prefers-reduced-motion. Muestra “Dominio verificado: <dominio>” bajo el título: el stellar.toml de la fundación lista su cuenta, nada más. El foco empieza en el diálogo, no en un botón, el botón principal ignora la activación durante los primeros 400 ms, y el resto de la página queda inert mientras está abierto. Los estilos viven en un shadow root. Las fuentes (Instrument Sans, Newsreader) no vienen incluidas: cárgalas tú o se usan las del sistema.