Skip to content

Deploy and Operate an Aspens Market Stack

This guide shows you how to deploy and configure your own Aspens Market Stack (AMS). Follow these steps to set up a crosschain trading infrastructure that enables trading between blockchains.

Table of Contents

  1. Set Up Infrastructure
  2. Deploy Smart Contracts
  3. Deploy the Stack
  4. Configure Blockchain Networks
  5. Configure Tokens
  6. Create Markets
  7. Implement Security and Monitoring
  8. Go Live
  9. Maintain and Update Your Stack
  10. Enable Application Development

1. Set Up Infrastructure

Check Prerequisites

Before beginning, ensure you have:

  • Docker and Docker Compose installed
  • Domain name for your AMS instance
  • Access to blockchain node endpoints (RPC URLs) for each chain you'll support
  • Private key for the AMS deployer wallet (will control the AMS configuration)

Prepare the Environment

# Create a dedicated directory for your AMS deployment
mkdir -p ~/aspens-stack
cd ~/aspens-stack

# Clone the Aspens Market Stack repository
git clone https://github.com/aspensprotocol/markets-stack.git .

# Create configuration directories
mkdir -p config data logs

2. Deploy Smart Contracts

Before deploying the stack, you need to deploy the smart contracts that will power your Aspens Market Stack instance. The deployment process involves deploying a ContractFactory on each supported chain and then creating an AppInstance through the TEE (Trusted Execution Environment).

Contract Deployment Flow

graph TD
    A[ContractFactory Deployed<br>on Multiple Chains] --> B[AppStack Defined,<br>Configured, and<br>Instantiated in TEE]

    subgraph User_Interactions
        C1[gRPC: AddChain base]
        C2[gRPC: AddChain quote]
        C1 --> B
        C2 --> B

        D[gRPC: CreateInstance]
        D --> B
    end

    B -->|Calls| E[ContractFactory SC]
    E -->|Returns AppInstance<br>at 0x... with AppStack<br>as owner| F[AppInstance]

    subgraph Post_Instance_Setup
        G1[gRPC: Add Token<br>to BaseChain]
        G2[gRPC: Add Token<br>to QuoteChain]
        G1 --> F
        G2 --> F

        H[gRPC: Create Markets<br>for Token Pairs]
        H --> F
    end

Deployment Steps

  1. Deploy ContractFactory
  2. Deploy the ContractFactory smart contract on each chain you plan to support
  3. Keep track of the deployed addresses for each chain

  4. Configure AppStack in TEE

  5. Define your AppStack configuration in the TEE
  6. Add base and quote chains using the gRPC interface
  7. Create an instance through the TEE

  8. Create AppInstance

  9. The TEE will interact with the ContractFactory to create your AppInstance
  10. The AppInstance will be deployed at a new address on each chain
  11. Your AppStack will be set as the owner of these instances

  12. Post-Deployment Setup

  13. Add tokens to each chain through the gRPC interface
  14. Create markets for the token pairs you want to support
  15. Configure market parameters and fees

Security Considerations

  • Ensure the TEE is properly configured and secured
  • Keep private keys for contract deployment secure
  • Verify contract addresses and ownership after deployment
  • Monitor contract events for any unexpected behavior

3. Deploy the Stack

Configure the Stack via gRPC

The Aspens Market Stack is configured through a series of gRPC calls. You'll need to use a gRPC client (like grpcurl) to make these calls. Here's the step-by-step process:

1. Add Base Chain

First, add your base chain (e.g., Ethereum):

grpcurl -plaintext -d '{
  "chain": {
    "chainId": "1",
    "name": "Ethereum",
    "rpcUrl": "https://your-ethereum-rpc-endpoint",
    "contractAddress": "0xYourContractFactoryAddress",
    "confirmations": 12
  }
}' localhost:50051 aspens.v1.AdminService/AddChain

2. Add Quote Chain

Next, add your quote chain (e.g., Arbitrum):

grpcurl -plaintext -d '{
  "chain": {
    "chainId": "42161",
    "name": "Arbitrum",
    "rpcUrl": "https://your-arbitrum-endpoint",
    "contractAddress": "0.0.yourContractFactoryAddress",
    "confirmations": 5
  }
}' localhost:50051 aspens.v1.AdminService/AddChain

3. Add Tokens to Base Chain

Add the tokens you want to support on the base chain:

# Add USDT on Ethereum
grpcurl -plaintext -d '{
  "token": {
    "chainId": "1",
    "symbol": "USDT",
    "name": "Tether USD",
    "address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
    "decimals": 6,
    "isNative": false
  }
}' localhost:50051 aspens.v1.AdminService/AddToken

# Add WETH on Ethereum
grpcurl -plaintext -d '{
  "token": {
    "chainId": "1",
    "symbol": "WETH",
    "name": "Wrapped Ether",
    "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    "decimals": 18,
    "isNative": false
  }
}' localhost:50051 aspens.v1.AdminService/AddToken

4. Add Tokens to Quote Chain

Add the corresponding tokens on the quote chain:

# Add USDC on Arbitrum
grpcurl -plaintext -d '{
  "token": {
    "chainId": "42161",
    "symbol": "USDC",
    "name": "USD Coin",
    "address": "0.0.yourUsdcTokenId",
    "decimals": 6,
    "isNative": false
  }
}' localhost:50051 aspens.v1.AdminService/AddToken

# Add ARB on Arbitrum
grpcurl -plaintext -d '{
  "token": {
    "chainId": "42161",
    "symbol": "ARB",
    "name": "Arbitrum",
    "address": "0x912CE59144191C1204E64559FE8253a0e49E6548",
    "decimals": 18,
    "isNative": false
  }
}' localhost:50051 aspens.v1.AdminService/AddToken

5. Create Markets

Create markets for the token pairs you want to support:

# Create USDT/USDC market
grpcurl -plaintext -d '{
  "market": {
    "baseTokenId": "1:USDT",
    "quoteTokenId": "42161:USDC",
    "displayName": "USDT/USDC",
    "description": "Trade USDT on Ethereum for USDC on Arbitrum",
    "minOrderSize": "10",
    "maxOrderSize": "1000000",
    "priceDecimals": 6,
    "quantityDecimals": 2,
    "makerFee": "0.0010",
    "takerFee": "0.0020"
  }
}' localhost:50051 aspens.v1.AdminService/CreateMarket

# Create WETH/ARB market
grpcurl -plaintext -d '{
  "market": {
    "baseTokenId": "1:WETH",
    "quoteTokenId": "42161:ARB",
    "displayName": "WETH/ARB",
    "description": "Trade WETH on Ethereum for ARB on Arbitrum",
    "minOrderSize": "0.01",
    "maxOrderSize": "100",
    "priceDecimals": 8,
    "quantityDecimals": 8,
    "makerFee": "0.0010",
    "takerFee": "0.0020"
  }
}' localhost:50051 aspens.v1.AdminService/CreateMarket

Verify Configuration

After completing the configuration, verify that everything is set up correctly:

# List configured chains
grpcurl -plaintext localhost:50051 aspens.v1.AdminService/ListChains

# List configured tokens
grpcurl -plaintext localhost:50051 aspens.v1.AdminService/ListTokens

# List configured markets
grpcurl -plaintext localhost:50051 aspens.v1.AdminService/ListMarkets

Start the Stack

Once configuration is complete, start the stack services:

# Start all services
docker-compose up -d

# Verify services are running
docker-compose ps

You should see the following services running: - arborter (core service) - journal (trade log database) - frontend (UI service)

4. Configure Blockchain Networks

You must configure the blockchain networks your AMS will interact with through the Admin API.

Add Blockchain Networks

For each blockchain network, make an API call with the network details:

Add Ethereum Mainnet

curl -X POST https://api.your-ams-instance.com/admin/chains \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": 1,
    "name": "Ethereum",
    "symbol": "ETH",
    "rpcUrl": "https://your-ethereum-rpc-endpoint",
    "blockExplorerUrl": "https://etherscan.io",
    "contractAddress": "0xYourAspensContractOnEthereum",
    "gasPrice": {
      "slow": 30,
      "standard": 40,
      "fast": 60
    },
    "confirmations": 12
  }'

Add Arbitrum Mainnet

curl -X POST https://api.your-ams-instance.com/admin/chains \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "42161",
    "name": "Arbitrum",
    "symbol": "ETH",
    "rpcUrl": "https://your-arbitrum-endpoint",
    "blockExplorerUrl": "https://arbiscan.io",
    "contractAddress": "0xYourAspensContractOnArbitrum",
    "gasPrice": {
      "slow": 1000000,
      "standard": 2000000,
      "fast": 5000000
    },
    "confirmations": 5
  }'

Verify Blockchain Configuration

List all configured blockchain networks to verify they were added correctly:

curl -X GET https://api.your-ams-instance.com/config/chains 

5. Configure Tokens

After configuring blockchain networks, add the tokens that will be tradable on your AMS.

Add Tokens

For each token on each blockchain network:

Add USDT on Ethereum

curl -X POST https://api.your-ams-instance.com/admin/tokens \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": 1,
    "symbol": "USDT",
    "name": "Tether USD",
    "address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
    "decimals": 6,
    "isNative": false,
    "iconUrl": "https://assets.example.com/tokens/usdt.png"
  }'

Add USDC on Arbitrum

curl -X POST https://api.your-ams-instance.com/admin/tokens \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "42161",
    "symbol": "USDC",
    "name": "USD Coin",
    "address": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
    "decimals": 6,
    "isNative": false,
    "iconUrl": "https://assets.example.com/tokens/usdc.png"
  }'

Verify Token Configuration

List all configured tokens to verify they were added correctly:

curl -X GET https://api.your-ams-instance.com/admin/tokens 

6. Create Markets

Now that you have configured the networks and tokens, create markets for trading these tokens across chains.

Create a Market

Create a USDT/USDT crosschain Market

curl -X POST https://api.your-ams-instance.com/admin/markets \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "baseTokenId": "ethereum:USDT",
    "quoteTokenId": "arbitrum:USDC",
    "displayName": "USDT:USDC,
    "description": "Trade USDT on Ethereum and USDC on Arbitrum",
    "minOrderSize": "10",
    "maxOrderSize": "1000000",
    "priceDecimals": 6,
    "quantityDecimals": 2,
    "makerFee": "0.0010",
    "takerFee": "0.0020",
    "status": "active"
  }'

Adjust Market Parameters

Modify market parameters such as fees, minimum and maximum order sizes:

curl -X PUT https://api.your-ams-instance.com/admin/markets/ethereum:USDT-arbitrum:USDC \
  -H "Content-Type: application/json" \
  -d '{
    "makerFee": "0.0005",
    "takerFee": "0.0015",
    "minOrderSize": "50",
    "status": "active"
  }'

Verify Market Configuration

List all configured markets to verify they were created correctly:

curl -X GET https://api.your-ams-instance.com/admin/markets 

7. Implement Security and Monitoring

Set Up Monitoring

Configure monitoring to keep track of your AMS performance and security:

# Install monitoring stack (if not included in your docker-compose)
docker-compose -f monitoring-stack.yaml up -d

# Configure Prometheus endpoints in monitoring/prometheus.yml
cat > monitoring/prometheus.yml << 'EOF'
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'aspens-metrics'
    static_configs:
      - targets: ['api-gateway:9090', 'arborter:9090', 'blockchain-watcher:9090']
EOF

# Restart monitoring services
docker-compose -f monitoring-stack.yaml restart

Harden Your Security

Improve the security of your AMS:

  1. Configure a firewall to only allow necessary ports:
# Allow SSH, HTTP, HTTPS, and the AMS API port
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 50051/tcp
sudo ufw enable
  1. Set up SSL certificates with Let's Encrypt:
# Install certbot
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx

# Generate certificates
sudo certbot --nginx -d your-ams-instance.com -d api.yoursite.com

8. Go Live

Complete Pre-Launch Checklist

Before making your AMS available to users, complete these steps:

  1. Fund Owner Wallets: Ensure the owner wallets on each blockchain have enough native tokens for gas fees:
# For Ethereum
# Send at least 1 ETH to your owner address: 0xYourOwnerAddress

# For Arbitrum
# Send at least 0.1 ETH to your owner address: 0xYourOwnerAddressOnArbitrum
  1. Initialize Contracts: Run the initialization command to set up the smart contracts:
curl -X POST https://api.your-ams-instance.com/admin/initialize \
  -H "Authorization: Bearer $TOKEN"
  1. Test Trading: Perform test trades on each market to ensure everything works correctly:
# Follow the steps in the testing script
./scripts/test-trading.sh

Launch Your AMS

After completing all the steps above, prepare for launch:

  1. Update DNS Records: Point your domain to your server's IP address:
your-ams-instance.com.    300    IN    A    your.server.ip.address
api.your-ams-instance.com.    300    IN    A    your.server.ip.address
  1. Announce Launch: Inform users that your AMS is now available for trading.

9. Maintain and Update Your Stack

Perform Regular Maintenance Tasks

Execute these tasks regularly to keep your AMS running smoothly:

  1. Back Up Your Database:
# Daily database backup
docker exec -t postgres pg_dumpall -c -U aspens > ~/aspens-stack/backups/backup_$(date +%Y-%m-%d).sql
  1. Update the Software:
# Pull the latest changes
git pull

# Rebuild and restart containers
docker-compose build
docker-compose up -d
  1. Monitor the Logs:
# Check service logs
docker-compose logs -f --tail=100

Troubleshoot Common Issues

If you encounter issues with your AMS, try these steps:

  1. Fix Unresponsive Services:
# Restart the specific service
docker-compose restart service-name

# Check logs for errors
docker-compose logs service-name
  1. Resolve Database Connection Issues:
# Check database status
docker exec -t postgres pg_isready -U aspens
  1. Solve Blockchain Synchronization Issues:
# Check blockchain-watcher logs
docker-compose logs blockchain-watcher

# Restart the watcher
docker-compose restart blockchain-watcher

10. Enable Application Development

Once your Aspens Market Stack is operational, help developers build applications on top of it.

Create Developer Access

To allow developers to build on your stack:

Provide Documentation to Developers:

Share with developers: - API endpoint information - Links to developer documentation

Access Support and Resources

If you need additional help or have questions: