Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
stellar avatar

Assets

  • 252 installs
  • 50 repo stars
  • Updated August 4, 2026
  • stellar/stellar-dev-skill

assets is a Stellar developer skill that documents classic asset issuance, trustlines, and SAC bridging so developers can integrate Stellar tokens into applications.

About

assets is a stellar-dev-skill module that teaches how to issue and manage Stellar classic assets, configure trustlines and issuer flags, and expose assets to smart contracts through the Stellar Asset Contract. Reach for it when you are tokenizing real-world assets, shipping stablecoins, or wiring regulated freeze and clawback flows in TypeScript against Horizon. It defaults to classic assets unless custom contract token logic is required.

  • Classic Stellar assets vs SEP-41 contract tokens with SAC bridge guidance
  • Issuer, distributor, changeTrust, and authorization flag examples
  • Regulated-asset patterns: auth required, revocable, clawback
  • Links to sibling stellar-dev-skill modules for dapp, data, and standards

Assets by the numbers

  • 252 all-time installs (skills.sh)
  • +37 installs in the week ending Jul 27, 2026 (Skillselion tracking)
  • Ranked #77 of 479 Web3 & Blockchain skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/stellar/stellar-dev-skill --skill assets

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs252
repo stars50
Last updatedAugust 4, 2026
Repositorystellar/stellar-dev-skill

How do you issue a Stellar asset, manage trustlines and compliance flags, and make that asset usable from smart contracts?

Guides issuing Stellar classic assets, trustlines, issuer flags, regulated flows, and bridging tokens to smart contracts via the Stellar Asset Contract.

Who is it for?

Developers building on Stellar who need classic issuance, trustline setup, or SAC interop with Horizon and stellar-sdk.

Skip if: Teams that only need custom SEP-41 token contracts without classic asset mechanics; use the smart-contracts skill instead.

When should I use this skill?

You are implementing issuance, trustlines, regulated controls, or SAC bridging described in the assets SKILL.md.

What you get

Correct Stellar SDK transaction patterns, flag configuration, and SAC integration steps aligned with Stellar asset best practices.

Files

SKILL.mdMarkdownGitHub ↗

Stellar Assets, Trustlines, and SAC

Stellar's native token mechanism: classic asset issuance, trustlines, and the Stellar Asset Contract (SAC) bridge that makes classic assets usable from Soroban. Default to classic assets over custom Soroban tokens unless you need custom logic.

When to use this skill

  • Issuing a new asset (stablecoin, security token, utility token)
  • Setting up trustlines from a client or contract
  • Managing issuer flags (auth required, auth revocable, clawback)
  • Bridging a classic asset into a Soroban contract via SAC
  • Building regulated-asset flows (compliance, KYC, freeze)

Related skills

  • Custom token contracts (when classic isn't enough) → ../soroban/SKILL.md
  • UI flows for trustline creation and asset display → ../dapp/SKILL.md
  • Looking up balances and trustline state → ../data/SKILL.md
  • Token-related SEPs (SEP-41, SEP-7, etc.) → ../standards/SKILL.md

---

Overview

Stellar has two token mechanisms:

1. Stellar Assets (Classic): Built-in, highly efficient, full ecosystem support 2. Soroban Tokens: Custom contracts with flexible logic

Recommendation: Prefer Stellar Assets unless you need custom token logic.

Stellar Assets (Classic)

Asset Types

TypeDescription
Native (XLM)Stellar's native currency, no trustline needed
CreditIssued by an account, requires trustline
Liquidity Pool SharesRepresent LP positions

Asset Identifiers

import * as StellarSdk from "@stellar/stellar-sdk";

// Native XLM
const xlm = StellarSdk.Asset.native();

// Credit asset (code + issuer)
const usdc = new StellarSdk.Asset(
  "USDC",
  "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"
);

// Asset code rules:
// - 1-4 chars: alphanumeric (credit_alphanum4)
// - 5-12 chars: alphanumeric (credit_alphanum12)

Issuing Assets

Create Issuing Account

import * as StellarSdk from "@stellar/stellar-sdk";

const server = new StellarSdk.Horizon.Server("https://horizon-testnet.stellar.org");

// 1. Create issuing account (should be separate from distribution)
const issuerKeypair = StellarSdk.Keypair.random();
const distributorKeypair = StellarSdk.Keypair.random();

// 2. Fund accounts (testnet)
await fetch(`https://friendbot.stellar.org?addr=${issuerKeypair.publicKey()}`);
await fetch(`https://friendbot.stellar.org?addr=${distributorKeypair.publicKey()}`);

Issue Asset

const asset = new StellarSdk.Asset("MYTOKEN", issuerKeypair.publicKey());

// 1. Distributor creates trustline to issuer
const distributorAccount = await server.loadAccount(distributorKeypair.publicKey());

const trustlineTx = new StellarSdk.TransactionBuilder(distributorAccount, {
  fee: StellarSdk.BASE_FEE,
  networkPassphrase: StellarSdk.Networks.TESTNET,
})
  .addOperation(
    StellarSdk.Operation.changeTrust({
      asset: asset,
      limit: "1000000", // Max amount to hold
    })
  )
  .setTimeout(180)
  .build();

trustlineTx.sign(distributorKeypair);
await server.submitTransaction(trustlineTx);

// 2. Issuer sends tokens to distributor
const issuerAccount = await server.loadAccount(issuerKeypair.publicKey());

const issueTx = new StellarSdk.TransactionBuilder(issuerAccount, {
  fee: StellarSdk.BASE_FEE,
  networkPassphrase: StellarSdk.Networks.TESTNET,
})
  .addOperation(
    StellarSdk.Operation.payment({
      destination: distributorKeypair.publicKey(),
      asset: asset,
      amount: "1000000",
    })
  )
  .setTimeout(180)
  .build();

issueTx.sign(issuerKeypair);
await server.submitTransaction(issueTx);

Lock Issuing Account

For fixed-supply tokens, lock the issuer:

const lockTx = new StellarSdk.TransactionBuilder(issuerAccount, {
  fee: StellarSdk.BASE_FEE,
  networkPassphrase: StellarSdk.Networks.TESTNET,
})
  .addOperation(
    StellarSdk.Operation.setOptions({
      masterWeight: 0, // Disable master key
    })
  )
  .setTimeout(180)
  .build();

lockTx.sign(issuerKeypair);
await server.submitTransaction(lockTx);
// Issuer can never issue more tokens

Asset Flags

Configure issuer account flags for compliance:

const setFlagsTx = new StellarSdk.TransactionBuilder(issuerAccount, {
  fee: StellarSdk.BASE_FEE,
  networkPassphrase: StellarSdk.Networks.TESTNET,
})
  .addOperation(
    StellarSdk.Operation.setOptions({
      setFlags:
        StellarSdk.AuthRequiredFlag |    // Trustlines require approval
        StellarSdk.AuthRevocableFlag |   // Can freeze trustlines
        StellarSdk.AuthClawbackEnabledFlag, // Can clawback tokens
    })
  )
  .setTimeout(180)
  .build();

Flag Descriptions

FlagEffect
AUTH_REQUIREDUsers must get approval before receiving tokens
AUTH_REVOCABLEIssuer can freeze user balances
AUTH_IMMUTABLEFlags cannot be changed (permanent)
AUTH_CLAWBACK_ENABLEDIssuer can clawback tokens from accounts

Authorize Trustline

// When AUTH_REQUIRED is set, approve trustlines:
const authorizeTx = new StellarSdk.TransactionBuilder(issuerAccount, {
  fee: StellarSdk.BASE_FEE,
  networkPassphrase: StellarSdk.Networks.TESTNET,
})
  .addOperation(
    StellarSdk.Operation.setTrustLineFlags({
      trustor: userPublicKey,
      asset: asset,
      flags: {
        authorized: true,
        // authorizedToMaintainLiabilities: true, // Partial auth
      },
    })
  )
  .setTimeout(180)
  .build();

Clawback Tokens

// Requires AUTH_CLAWBACK_ENABLED flag
const clawbackTx = new StellarSdk.TransactionBuilder(issuerAccount, {
  fee: StellarSdk.BASE_FEE,
  networkPassphrase: StellarSdk.Networks.TESTNET,
})
  .addOperation(
    StellarSdk.Operation.clawback({
      asset: asset,
      from: targetAccountId,
      amount: "100",
    })
  )
  .setTimeout(180)
  .build();

Trustlines

Create Trustline

const changeTrustTx = new StellarSdk.TransactionBuilder(userAccount, {
  fee: StellarSdk.BASE_FEE,
  networkPassphrase: StellarSdk.Networks.TESTNET,
})
  .addOperation(
    StellarSdk.Operation.changeTrust({
      asset: asset,
      limit: "10000", // 0 to remove trustline
    })
  )
  .setTimeout(180)
  .build();

Check Trustline Status

const account = await server.loadAccount(userPublicKey);
const trustline = account.balances.find(
  (b) =>
    b.asset_type !== "native" &&
    b.asset_code === "USDC" &&
    b.asset_issuer === usdcIssuer
);

if (trustline) {
  console.log("Balance:", trustline.balance);
  console.log("Limit:", trustline.limit);
  console.log("Authorized:", trustline.is_authorized);
}

Stellar Asset Contract (SAC)

SAC provides Soroban interface for Stellar Assets, enabling smart contract interactions.

Deploy SAC for Existing Asset

# Get the SAC address for an asset
stellar contract asset deploy \
  --asset USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN \
  --source alice \
  --network testnet

SAC Address Derivation

import * as StellarSdk from "@stellar/stellar-sdk";

const asset = new StellarSdk.Asset("USDC", issuerPublicKey);
const contractId = asset.contractId(StellarSdk.Networks.TESTNET);
// Returns the deterministic SAC contract address

Using SAC in Soroban Contracts

use soroban_sdk::{token::Client as TokenClient, Address, Env};

pub fn transfer_asset(
    env: Env,
    from: Address,
    to: Address,
    asset_contract: Address,
    amount: i128,
) {
    from.require_auth();

    // Use standard token interface
    let token = TokenClient::new(&env, &asset_contract);
    token.transfer(&from, &to, &amount);
}

SAC vs Custom Token Interface

SAC implements the standard Soroban token interface:

  • balance(id: Address) -> i128
  • transfer(from: Address, to: Address, amount: i128)
  • approve(from: Address, spender: Address, amount: i128, expiration_ledger: u32)
  • allowance(from: Address, spender: Address) -> i128
  • decimals() -> u32
  • name() -> String
  • symbol() -> Symbol

When to Use What

Use Stellar Assets When:

  • Standard fungible token (currency, stablecoin)
  • Need full ecosystem support (wallets, exchanges)
  • Regulatory compliance features (freeze, clawback)
  • Performance critical (classic operations are cheaper)
  • DEX integration via order book

Use Soroban Custom Tokens When:

  • Complex transfer logic (royalties, fees, restrictions)
  • Custom authorization schemes
  • Non-standard token behaviors
  • Integration with custom DeFi contracts
  • NFTs or semi-fungible tokens

Use SAC When:

  • Need Stellar Asset in Soroban contract
  • Building DeFi protocols with existing assets
  • Bridge between classic and smart contract operations

Querying Assets

Get Account Balances

const account = await server.loadAccount(publicKey);

for (const balance of account.balances) {
  if (balance.asset_type === "native") {
    console.log("XLM:", balance.balance);
  } else {
    console.log(`${balance.asset_code}:`, balance.balance);
  }
}

Find Assets

// Search for assets by code
const assets = await server
  .assets()
  .forCode("USDC")
  .call();

// Get specific asset details
const assetDetails = await server
  .assets()
  .forCode("USDC")
  .forIssuer(issuerPublicKey)
  .call();

Get Asset Statistics

const stats = await server
  .assets()
  .forCode("USDC")
  .forIssuer(issuerPublicKey)
  .call();

// stats includes:
// - amount: total issued
// - num_accounts: trustline count
// - flags: issuer flags

SEP Standards for Assets

SEP-0001 (stellar.toml)

Publish asset metadata in your domain's /.well-known/stellar.toml:

[[CURRENCIES]]
code = "MYTOKEN"
issuer = "GABC..."
display_decimals = 2
name = "My Token"
desc = "A description of my token"
image = "https://example.com/token-logo.png"

SEP-0010 (Web Authentication)

Authenticate users with their Stellar accounts:

// Server generates challenge
// Client signs with wallet
// Server verifies signature

SEP-0024 (Hosted Deposit/Withdrawal)

For fiat on/off ramps:

// Interactive flow for deposits/withdrawals
// Anchor handles KYC and fiat transfer

SEP-0045 (Web Auth for Contract Accounts)

Extends SEP-10 to support Soroban contract accounts (C... addresses) for web authentication. Required for smart wallet / passkey-based anchor integrations. See SEP-0045.

SEP-0050 (Non-Fungible Tokens)

Standard contract interface for NFTs on Soroban. Reference implementations available in OpenZeppelin Stellar Contracts with Base, Consecutive, and Enumerable variants. See SEP-0050.

Best Practices

Asset Issuance

  • Use separate issuing and distribution accounts
  • Lock issuer after initial distribution for fixed supply
  • Publish stellar.toml with asset metadata
  • Consider multisig for issuer account

Trustline Management

  • Check trustline exists before sending payments
  • Handle trustline creation in onboarding flow
  • Respect trustline limits
  • Monitor for frozen/deauthorized status

Security

  • Validate asset issuer, not just code
  • Be cautious of assets with clawback enabled
  • Verify stellar.toml from authoritative source
  • Use well-known asset lists for common tokens

Related skills

FAQ

When should I prefer classic assets over contract tokens?

The skill recommends classic Stellar assets unless you need custom token logic that classic issuance cannot provide.

What is SAC used for?

The Stellar Asset Contract bridges classic assets so smart contracts can interact with them as SEP-41-style tokens.

Which related skills should I open next?

smart-contracts for custom tokens, dapp for UI trustline flows, data for balances, and standards for SEP references.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.