Skip to content

Latest commit

 

History

History
556 lines (409 loc) · 13.2 KB

File metadata and controls

556 lines (409 loc) · 13.2 KB

Stellar Network Integration Guide

Overview

Trustless Work runs on Stellar (Soroban), a blockchain optimized for fast, low-cost financial transactions. Understanding Stellar basics is essential for integrating Trustless Work escrows.


Why Stellar?

Advantages

Fast: 3-5 second finality ✅ Cheap: Transaction fees typically < $0.01 ✅ Built for payments: Native support for multiple assets ✅ Mature: 8+ years of production use ✅ Stablecoin-native: USDC officially issued on Stellar ✅ Smart contracts: Soroban enables programmable escrows

Comparison to Other Chains

Feature Stellar Ethereum Solana
Tx Finality 3-5 sec ~15 sec < 1 sec
Tx Cost < $0.01 $1-50+ $0.001-0.01
Stablecoin Support Native USDC Yes (ERC-20) Yes (SPL)
Smart Contracts Soroban EVM Rust
Best For Payments, escrow DeFi, complex apps High-throughput

Core Concepts

1. Stellar Accounts

Every Stellar account has:

  • Public Key: Starts with G (e.g., GCLIENT123...)
  • Private Key: Starts with S (keep secret!)
  • Minimum Balance: 1 XLM (Stellar's native token)

Escrow Addresses (Smart Contracts):

  • Contract addresses start with C (e.g., CESCROW_ABC123...)
  • These are the Escrow IDs in Trustless Work

2. Trustlines

A trustline is explicit permission to hold a specific asset.

Example: To hold USDC, your account must establish a trustline to the USDC issuer.

USDC Issuer on Stellar:

GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5

Why it matters for Trustless Work:

  • ⚠️ All escrow participants (Approver, Service Provider, Release Signer, Receiver) must have the trustline enabled
  • Without trustline → transactions will fail
  • Trustline setup is a one-time operation per asset

3. Assets on Stellar

Stellar supports multiple assets:

  • Native: XLM (Lumens)
  • Issued Assets: USDC, EURC, custom tokens
  • Format: CODE:ISSUER (e.g., USDC:GBBD47IF...)

Trustless Work typically uses USDC but supports any Stellar-issued token.


Setting Up Stellar Accounts

Create a New Account

import * as StellarSDK from '@stellar/stellar-sdk';

// Generate new keypair
const pair = StellarSDK.Keypair.random();

console.log('Public Key:', pair.publicKey());  // Starts with G
console.log('Private Key:', pair.secret());     // Starts with S (KEEP SECRET!)

⚠️ Security: Never share or commit private keys. Use environment variables or hardware wallets.

Fund Account on Testnet

# Use Stellar's Testnet Friendbot
curl "https://friendbot.stellar.org/?addr=YOUR_PUBLIC_KEY"

Or visit: https://laboratory.stellar.org/#account-creator?network=test

Fund Account on Mainnet

Send XLM from an exchange or another Stellar wallet.

Minimum: 1 XLM to activate account


Trustline Management

Check if Trustline Exists

import * as StellarSDK from '@stellar/stellar-sdk';

const server = new StellarSDK.Server('https://horizon.stellar.org');

async function hasTrustline(accountId: string, assetCode: string, issuer: string) {
  const account = await server.loadAccount(accountId);

  return account.balances.some(balance =>
    balance.asset_code === assetCode &&
    balance.asset_issuer === issuer
  );
}

// Check if account has USDC trustline
const hasUSDC = await hasTrustline(
  'GCLIENT_WALLET...',
  'USDC',
  'GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5'
);

console.log('Has USDC trustline:', hasUSDC);

Add Trustline

async function addUSDCTrustline(secretKey: string) {
  const keypair = StellarSDK.Keypair.fromSecret(secretKey);
  const server = new StellarSDK.Server('https://horizon.stellar.org');
  const account = await server.loadAccount(keypair.publicKey());

  const usdcAsset = new StellarSDK.Asset(
    'USDC',
    'GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5'
  );

  const transaction = new StellarSDK.TransactionBuilder(account, {
    fee: StellarSDK.BASE_FEE,
    networkPassphrase: StellarSDK.Networks.PUBLIC
  })
    .addOperation(StellarSDK.Operation.changeTrust({
      asset: usdcAsset
    }))
    .setTimeout(180)
    .build();

  transaction.sign(keypair);

  const result = await server.submitTransaction(transaction);
  console.log('Trustline added:', result.hash);
  return result;
}

Trustline Limits

By default, trustlines have no limit (can hold unlimited amount).

You can optionally set a maximum:

StellarSDK.Operation.changeTrust({
  asset: usdcAsset,
  limit: '10000' // Max 10,000 USDC
})

Wallets

Recommended: Freighter

Freighter is a browser extension wallet (like MetaMask for Stellar).

Install: https://www.freighter.app/

Integration:

import { isConnected, requestAccess, signTransaction } from '@stellar/freighter-api';

async function connectWallet() {
  if (await isConnected()) {
    const access = await requestAccess();
    if (access.error) {
      console.error('User denied access');
    } else {
      console.log('Connected:', access.address);
      return access.address;
    }
  } else {
    alert('Please install Freighter wallet');
  }
}

async function signWithFreighter(xdr: string) {
  const signed = await signTransaction(xdr, {
    network: 'PUBLIC', // or 'TESTNET'
    networkPassphrase: StellarSDK.Networks.PUBLIC
  });
  return signed.signedTxXdr;
}

Other Wallets

Wallet Type Support
Freighter Browser extension ✅ Best
LOBSTR Mobile app ✅ Good
Albedo Web wallet ✅ Good
Ledger Hardware ✅ Enterprise
Solar Desktop ✅ Power users

Sending USDC

Direct Send (Not Through Escrow)

async function sendUSDC(fromSecret: string, toAddress: string, amount: string) {
  const keypair = StellarSDK.Keypair.fromSecret(fromSecret);
  const server = new StellarSDK.Server('https://horizon.stellar.org');
  const account = await server.loadAccount(keypair.publicKey());

  const usdcAsset = new StellarSDK.Asset(
    'USDC',
    'GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5'
  );

  const transaction = new StellarSDK.TransactionBuilder(account, {
    fee: StellarSDK.BASE_FEE,
    networkPassphrase: StellarSDK.Networks.PUBLIC
  })
    .addOperation(StellarSDK.Operation.payment({
      destination: toAddress,
      asset: usdcAsset,
      amount: amount
    }))
    .setTimeout(180)
    .build();

  transaction.sign(keypair);

  const result = await server.submitTransaction(transaction);
  console.log('Payment sent:', result.hash);
  return result;
}

// Send 100 USDC
await sendUSDC('S...SECRET', 'GDESTINATION...', '100');

Send to Escrow Contract

To fund a Trustless Work escrow:

Option 1: Use Trustless Work API (recommended)

await sdk.escrow.fund(escrowId, {
  amount: 1000,
  depositorAddress: 'GCLIENT_WALLET...'
});

Option 2: Direct Deposit

// Send USDC to the escrow contract address (starts with C)
await sendUSDC('S...SECRET', escrow.contractId, '1000');

Common USDC Addresses

Mainnet (Production)

Asset Code: USDC
Issuer: GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5
Full: USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5

Testnet (Development)

Asset Code: USDC
Issuer: GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5
(Same issuer for testnet testing)

Get Testnet USDC:

  1. Create testnet account
  2. Fund with friendbot (XLM)
  3. Add USDC trustline
  4. Use testnet faucet or request from Trustless Work team

Horizon API

Horizon is Stellar's REST API for querying blockchain data.

Endpoints

Network URL
Mainnet https://horizon.stellar.org
Testnet https://horizon-testnet.stellar.org

Query Account

curl "https://horizon.stellar.org/accounts/GACCOUNT..."

Query Transactions

curl "https://horizon.stellar.org/accounts/GACCOUNT.../transactions?limit=10"

Query Payments

curl "https://horizon.stellar.org/accounts/GACCOUNT.../payments"

JavaScript SDK

const server = new StellarSDK.Server('https://horizon.stellar.org');

// Load account
const account = await server.loadAccount('GACCOUNT...');
console.log('Balances:', account.balances);

// Stream payments (real-time)
server.payments()
  .forAccount('GACCOUNT...')
  .cursor('now')
  .stream({
    onmessage: (payment) => {
      console.log('New payment:', payment);
    }
  });

Stellar Expert

Stellar Expert is a blockchain explorer for Stellar.

URL: https://stellar.expert/explorer/public

Use Cases

  • View account details and balances
  • Inspect transaction history
  • Verify escrow contract deployments
  • Check trustline status
  • Monitor network activity

Example: View escrow contract

https://stellar.expert/explorer/public/contract/CESCROW_ADDRESS

Transaction Fees

Fee Structure

  • Base Fee: 100 stroops (0.00001 XLM)
  • Typical Cost: < $0.01 USD
  • Complex Transactions: May require higher fees (multi-sig, contract calls)

Fee Calculation

Total Fee = Base Fee × Number of Operations

Example: Transaction with 2 operations

Fee = 100 stroops × 2 = 200 stroops = 0.00002 XLM ≈ $0.000002

Setting Fees in SDK

const transaction = new StellarSDK.TransactionBuilder(account, {
  fee: StellarSDK.BASE_FEE, // 100 stroops
  networkPassphrase: StellarSDK.Networks.PUBLIC
})
// ...

Network Passphrases

Network Passphrase identifies which Stellar network you're on.

Network Passphrase
Mainnet Public Global Stellar Network ; September 2015
Testnet Test SDF Network ; September 2015

Use SDK constants:

StellarSDK.Networks.PUBLIC  // Mainnet
StellarSDK.Networks.TESTNET // Testnet

⚠️ Critical: Always use correct passphrase or transactions will fail!


Testing on Testnet

Setup Testnet Environment

const server = new StellarSDK.Server('https://horizon-testnet.stellar.org');
const networkPassphrase = StellarSDK.Networks.TESTNET;

Fund Testnet Account

# Get 10,000 test XLM
curl "https://friendbot.stellar.org/?addr=YOUR_PUBLIC_KEY"

Switch Trustless Work to Testnet

const sdk = new TrustlessWorkSDK({
  apiKey: 'YOUR_API_KEY',
  network: 'testnet' // Use testnet
});

Testnet USDC

Request testnet USDC from:

  • Stellar community faucets
  • Trustless Work team (for development)
  • Issue your own test tokens

Common Issues & Solutions

Issue: "Account not found"

Cause: Account not funded with minimum XLM Solution: Send at least 1 XLM to activate account

Issue: "Trustline required"

Cause: Account doesn't have trustline for asset Solution: Add trustline using changeTrust operation

Issue: "Transaction failed: tx_bad_auth"

Cause: Wrong private key used to sign Solution: Verify you're signing with correct keypair

Issue: "Transaction failed: tx_insufficient_balance"

Cause: Account doesn't have enough asset balance Solution: Fund account with more XLM or USDC

Issue: "Destination account requires memo"

Cause: Sending to exchange that requires memo Solution: Add memo to transaction (not typical for escrows)

Issue: "Can't send to contract address"

Cause: Some exchanges block contract addresses Solution: Use non-custodial wallet (Freighter, LOBSTR)


Security Best Practices

1. Private Key Management

DO:

  • Store in environment variables
  • Use hardware wallets for high-value accounts
  • Encrypt keys at rest
  • Use key derivation for multiple accounts

DON'T:

  • Commit keys to Git
  • Log private keys
  • Share keys via chat/email
  • Store plaintext on servers

2. Transaction Signing

DO:

  • Validate transaction details before signing
  • Use browser wallets for user transactions
  • Implement transaction approval flows
  • Log signed transaction hashes (not contents)

DON'T:

  • Auto-sign without user consent
  • Sign arbitrary transactions
  • Reuse signatures

3. Account Setup

DO:

  • Set up multi-signature for platform accounts
  • Use separate accounts for different roles
  • Monitor account activity
  • Set up transaction limits

4. Testing

DO:

  • Always test on Testnet first
  • Verify all addresses before mainnet deploy
  • Test with small amounts initially
  • Simulate failure scenarios

Next Steps

  1. Set up Testnet:

    • Create account
    • Add USDC trustline
    • Get test tokens
  2. Install Freighter: https://www.freighter.app/

  3. Test Escrow Flow:

    • Create escrow on testnet
    • Fund with test USDC
    • Walk through full lifecycle
  4. Deploy to Mainnet:

    • Verify all addresses
    • Fund with real USDC
    • Monitor with Stellar Expert

Resources