Skip to content

ElliotFriend/regional-starter-pack

Stellar Regional Starter Pack

A SvelteKit application and portable library for building fiat on/off ramps on the Stellar network. Includes integrations for three anchor providers -- Etherfuse, AlfredPay, and BlindPay -- as well as a composable SEP protocol library for building against any SEP-compliant anchor.

TL;DR: The Most Important Thing

This demo is a fully functional application that you can test out and interact with and (usually) even get some Testnet tokens from the onramp simulations! But, it's also a tool and a resource.

The /src/lib/anchors/ and /src/lib/wallet/ directories are portable, framework-agnostic TypeScript libraries that should work out-of-the-box! Copy them (or just the parts you need) into any TypeScript project, and your project can interact with any of the anchors and the Stellar network. Super easy. Barely an inconvenience!

What's Inside

src/lib/anchors/          <- PORTABLE: Copy into any TypeScript project
  types.ts                <- Shared Anchor interface + common types
  etherfuse/              <- Etherfuse integration (Latin America)
  alfredpay/              <- AlfredPay integration (Mexico)
  blindpay/               <- BlindPay integration (global)
  sep/                    <- SEP protocol implementations
  testanchor/             <- Reference client for testanchor.stellar.org

src/lib/wallet/           <- PORTABLE: Freighter wallet + Stellar helpers

src/lib/server/           <- SvelteKit-specific server code
  anchorFactory.ts        <- Anchor factory (reads $env, instantiates clients)

src/lib/stores/           <- Svelte 5 reactive state (runes)
src/lib/components/       <- On/off ramp UI components
src/lib/config/           <- Anchors, regions, tokens, and payment rail configuration
src/routes/               <- SvelteKit pages and API routes

Quick Start

cp .env.example .env      # Configure API keys
pnpm install              # Install dependencies
pnpm dev                  # Run development server
pnpm check                # Type check
pnpm build                # Build for production

Using the Anchor Library

The /src/lib/anchors/ directory is framework-agnostic and designed to be copied into any TypeScript project. Each anchor client implements a shared Anchor interface, so swapping providers requires no changes to your application logic.

The Anchor Interface

All custom clients implement this interface from types.ts:

interface Anchor {
    readonly name: string;
    readonly displayName: string;
    readonly capabilities: AnchorCapabilities;
    readonly supportedTokens: readonly TokenInfo[];
    readonly supportedCurrencies: readonly string[];
    readonly supportedRails: readonly string[];
    createCustomer(input: CreateCustomerInput): Promise<Customer>;
    getCustomer(customerId: string): Promise<Customer | null>;
    getCustomerByEmail?(email: string, country?: string): Promise<Customer | null>;
    getQuote(input: GetQuoteInput): Promise<Quote>;
    createOnRamp(input: CreateOnRampInput): Promise<OnRampTransaction>;
    getOnRampTransaction(transactionId: string): Promise<OnRampTransaction | null>;
    registerFiatAccount(input: RegisterFiatAccountInput): Promise<RegisteredFiatAccount>;
    getFiatAccounts(customerId: string): Promise<SavedFiatAccount[]>;
    createOffRamp(input: CreateOffRampInput): Promise<OffRampTransaction>;
    getOffRampTransaction(transactionId: string): Promise<OffRampTransaction | null>;
    getKycUrl?(customerId: string, publicKey?: string, bankAccountId?: string): Promise<string>;
    getKycStatus(customerId: string, publicKey?: string): Promise<KycStatus>;
}

Each client declares displayName, supportedTokens (with Stellar issuers), supportedCurrencies, and supportedRails — making the portable library fully self-contained.

Anchor Providers

Provider Region Fiat Currency Token Payment Rail KYC Flow
Etherfuse Mexico MXN CETES SPEI iframe
AlfredPay Mexico MXN USDC SPEI form
BlindPay Global (Mexico demo) MXN USDB SPEI redirect

Each provider has its own directory under /src/lib/anchors/ with a README.md containing detailed setup, usage examples, and flow documentation.

Example: Etherfuse

import { EtherfuseClient } from './anchors/etherfuse';

const anchor = new EtherfuseClient({
    apiKey: 'your-api-key',
    baseUrl: 'https://api.sand.etherfuse.com', // sandbox
});

// 1. Create customer (returns KYC onboarding URL)
const customer = await anchor.createCustomer({
    email: 'user@example.com',
    publicKey: 'GXYZ...',
    country: 'MX',
});

// 2. Get quote (MXN -> CETES)
const quote = await anchor.getQuote({
    fromCurrency: 'MXN',
    toCurrency: 'CETES',
    fromAmount: '1000',
    customerId: customer.id,
    stellarAddress: 'GXYZ...',
});

// 3. Create on-ramp order
const onramp = await anchor.createOnRamp({
    customerId: customer.id,
    quoteId: quote.id,
    stellarAddress: 'GXYZ...',
    fromCurrency: 'MXN',
    toCurrency: 'CETES',
    amount: '1000',
    bankAccountId: customer.bankAccountId!,
});

Example: SEP-Compliant Anchors

For anchors that implement Stellar SEP protocols, use the /sep/ modules directly:

import { sep1, sep10, sep24 } from './anchors/sep';

// 1. Discover anchor endpoints
const toml = await sep1.fetchStellarToml('testanchor.stellar.org');

// 2. Authenticate
const token = await sep10.authenticate(
    {
        authEndpoint: toml.WEB_AUTH_ENDPOINT!,
        serverSigningKey: toml.SIGNING_KEY!,
        networkPassphrase: 'Test SDF Network ; September 2015',
    },
    userPublicKey,
    signerFunction,
);

// 3. Start interactive deposit
const response = await sep24.deposit(toml.TRANSFER_SERVER_SEP0024!, token, {
    asset_code: 'USDC',
    amount: '100',
});

window.open(response.url, '_blank');

Usage Outside SvelteKit

The anchors/ and wallet/ directories have no framework dependencies -- they rely only on @stellar/stellar-sdk (and @stellar/freighter-api for the wallet). Copy the provider directories you need and instantiate clients directly with process.env or your framework's env mechanism:

// Express / Node.js example
import express from 'express';
import { EtherfuseClient } from './lib/anchors/etherfuse';

const anchor = new EtherfuseClient({
    apiKey: process.env.ETHERFUSE_API_KEY!,
    baseUrl: process.env.ETHERFUSE_BASE_URL!,
});

const app = express();
app.use(express.json());

app.post('/api/quotes', async (req, res) => {
    const quote = await anchor.getQuote(req.body);
    res.json(quote);
});

You only need to copy the provider(s) you use plus types.ts. For example, to use just BlindPay, copy anchors/types.ts and anchors/blindpay/. The providers don't reference each other.

If your app runs in the browser, anchor API calls will hit CORS restrictions. Proxy them through your backend the same way this SvelteKit app does with its /api/anchor/[provider]/ routes.


Architecture

Server-Side Anchor Factory

Anchor clients require API keys and should only be instantiated server-side. The factory at src/lib/server/anchorFactory.ts reads environment variables and returns configured client instances:

// In a +server.ts route handler:
import { getAnchor, isValidProvider } from '$lib/server/anchorFactory';

const anchor = getAnchor('etherfuse'); // Returns configured EtherfuseClient

This separation keeps the anchor library (src/lib/anchors/) portable and free of SvelteKit imports.

API Routes

All anchor operations are proxied through SvelteKit API routes at /api/anchor/[provider]/:

/api/anchor/[provider]/customers      - Customer creation and lookup
/api/anchor/[provider]/kyc            - KYC status and iframe URLs
/api/anchor/[provider]/quotes         - Quote generation
/api/anchor/[provider]/onramp         - On-ramp order creation and status
/api/anchor/[provider]/offramp        - Off-ramp order creation and status
/api/anchor/[provider]/fiat-accounts  - Bank account registration
/api/anchor/[provider]/sandbox        - Sandbox-only operations (KYC completion, fiat simulation)
/api/anchor/[provider]/payout-submit  - Payout submission (BlindPay)
/api/anchor/[provider]/blockchain-wallets - Blockchain wallet registration (BlindPay)
/api/anchor/webhooks                  - Webhook handler (AlfredPay)

For the test anchor (SEP flows), separate proxy endpoints handle CORS:

/api/testanchor/sep6   - SEP-6 proxy
/api/testanchor/sep24  - SEP-24 proxy

UI Components

The on-ramp and off-ramp flows are implemented as Svelte components:

  • OnRampFlow.svelte - Fiat to crypto flow (customer -> quote -> payment instructions -> status polling)
  • OffRampFlow.svelte - Crypto to fiat flow (customer -> quote -> bank selection -> signing -> status polling)
  • KycForm.svelte / KycIframe.svelte - KYC collection (form-based or iframe-based depending on provider)
  • QuoteDisplay.svelte - Quote summary with countdown timer
  • WalletConnect.svelte - Freighter wallet connection

Pages

/                       - Home page
/anchors                - Anchor provider listing
/anchors/[provider]     - Provider detail page
/anchors/[provider]/onramp   - On-ramp page
/anchors/[provider]/offramp  - Off-ramp page
/regions                - Region listing
/regions/[region]       - Region detail with available anchors
/testanchor             - SEP flow demo with testanchor.stellar.org

SEP Module Reference

Module Protocol Description
sep1 SEP-1 Stellar.toml discovery
sep10 SEP-10 Web authentication
sep6 SEP-6 Programmatic deposits/withdrawals
sep12 SEP-12 KYC/customer management
sep24 SEP-24 Interactive deposits/withdrawals
sep31 SEP-31 Cross-border payments
sep38 SEP-38 Anchor quotes (RFQ)

SEP modules are framework-agnostic. They accept an optional fetchFn parameter for SSR and depend only on @stellar/stellar-sdk.


Environment Variables

Copy .env.example to .env and fill in your API keys:

# Etherfuse
ETHERFUSE_API_KEY=""
ETHERFUSE_BASE_URL="https://api.sand.etherfuse.com"

# AlfredPay
ALFREDPAY_API_KEY=""
ALFREDPAY_API_SECRET=""
ALFREDPAY_BASE_URL="https://penny-api-restricted-dev.alfredpay.io/api/v1/third-party-service/penny"

# BlindPay
BLINDPAY_API_KEY=""
BLINDPAY_INSTANCE_ID=""
BLINDPAY_BASE_URL="https://api.blindpay.com"

# Webhooks
ALFREDPAY_WEBHOOK_SECRET=""

# Stellar Network
PUBLIC_STELLAR_NETWORK="testnet"
PUBLIC_USDC_ISSUER="GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5"

Tech Stack

  • SvelteKit - Full-stack framework
  • Svelte 5 - UI with runes ($state, $derived, $effect)
  • TypeScript - Type safety throughout
  • Tailwind CSS - Styling
  • @stellar/stellar-sdk - Stellar blockchain interaction
  • @stellar/freighter-api - Wallet connection (Freighter browser extension)

Adding a New Anchor

  1. Create /src/lib/anchors/[anchor-name]/ with client.ts, types.ts, and index.ts
  2. Implement the Anchor interface from ../types.ts — set all relevant AnchorCapabilities flags
  3. Add the provider to src/lib/server/anchorFactory.ts (env vars, factory switch case)
  4. Add the provider to src/lib/constants.ts (PROVIDER object)
  5. Add the provider to src/lib/config/anchors.ts (ANCHORS record with matching capabilities)
  6. Add the provider to src/lib/config/regions.ts (region anchors arrays)
  7. Add API route proxies if needed for CORS
  8. Document in /src/lib/anchors/[anchor-name]/README.md

Claude Code

This repository includes configuration for Claude Code to assist with development. Contributors using Claude Code will automatically pick up the MCP servers and skills described below.

MCP Servers

Configured in .mcp.json and loaded automatically when Claude Code starts a session in this repo.

Server URL Description
Svelte https://mcp.svelte.dev/mcp Official Svelte MCP server. Provides Svelte 5 and SvelteKit documentation, code autofixing, and playground links.
Etherfuse https://docs.etherfuse.com/mcp Etherfuse FX API documentation search. Provides API references, code examples, and integration guides for the Etherfuse anchor.

To enable a new MCP server, add it to .mcp.json:

{
    "mcpServers": {
        "your-server": {
            "type": "http",
            "url": "https://example.com/mcp"
        }
    }
}

Skills

Skills are project-scoped prompt extensions that give Claude Code domain knowledge for specific integrations.

Skill Description
BlindPay Provides BlindPay API documentation covering payins, payouts, receivers, KYC, bank accounts, blockchain wallets, and webhooks. Includes reference docs for all endpoints and guides for development vs production environments.

Skills are stored under .claude/skills/ and activated automatically when Claude Code detects relevant context (e.g., working on BlindPay integration files).

License

Apache-2.0

About

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors