Skip to content

StellarFlow-Lab/autofi-reward-router

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

28 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

AutoFi Wallet β€” Automated Developer Reward Off-Ramp

AutoFi is a Soroban-powered middleware that hooks into open-source payout engines (Drips Waves, GitHub bounties). The moment a developer receives an on-chain token reward (USDC, XLM), AutoFi catches it, applies a configurable split rule stored on-chain, and executes an atomic path payment swap into a local fiat anchor stablecoin (NGNX, USDC, GBPT) β€” pushing funds directly into local banking infrastructure.

Live on Drips Network: https://docs.drips.network/wave


Features

  • On-chain Split Rules β€” Developer preferences (% to off-ramp vs. hold) are stored in a Soroban smart contract, not a centralised server.
  • Atomic Path Payments β€” One Stellar operation swaps inbound reward tokens to an anchor stablecoin via the native DEX.
  • Multi-Currency Off-Ramp β€” Supports NGN (NIBSS), USD (ACH), GBP (SEPA) via SEP-6/SEP-24 anchor integrations.
  • Drips Wave Listener β€” Monitors Drips Wave payouts and fires the off-ramp pipeline automatically.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  External Triggers                   β”‚
β”‚  Drips Wave Payout  β”‚  GitHub Bounty  β”‚  Manual Send β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚                   β”‚               β”‚
           β–Ό                   β–Ό               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               dripListener.ts                        β”‚
β”‚  Polls Drips subgraph / webhook  β†’  RewardEvent{}    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
                       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   index.ts                           β”‚
β”‚  1. Read RoutePreferences from Soroban contract      β”‚
β”‚  2. Calculate off-ramp amount  (amount Γ— pct / 100)  β”‚
β”‚  3. Call executePathPayment()                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β–Ό                         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Soroban Contract β”‚     β”‚    pathPayment.ts         β”‚
β”‚  reward_router    β”‚     β”‚  pathPaymentStrictSend    β”‚
β”‚  RoutePreferences β”‚     β”‚  inbound β†’ anchor asset   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                     β”‚
                                     β–Ό
                          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                          β”‚  Stellar Anchor       β”‚
                          β”‚  SEP-6 / SEP-24       β”‚
                          β”‚  NGN / USD / GBP      β”‚
                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Directory Structure

autofi-wallet/
β”œβ”€β”€ .env.example
β”œβ”€β”€ README.md
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ contracts/
β”‚   └── reward_router/
β”‚       β”œβ”€β”€ Cargo.toml
β”‚       └── src/
β”‚           └── lib.rs          # Soroban contract: stores RoutePreferences per user
└── src/
    β”œβ”€β”€ index.ts                # Orchestrator: listens β†’ reads prefs β†’ executes swap
    β”œβ”€β”€ config/
    β”‚   └── anchors.ts          # SEP-6/SEP-24 anchor configs (NGNX, USDC, GBPT)
    β”œβ”€β”€ services/
    β”‚   β”œβ”€β”€ dripListener.ts     # Drips Wave / GitHub bounty event listener
    β”‚   └── pathPayment.ts      # Stellar pathPaymentStrictSend executor
    └── types/
        └── index.ts            # Shared TypeScript interfaces

Getting Started

Prerequisites

  • Node.js v18+
  • Rust + Soroban CLI
  • Stellar Testnet or Mainnet account funded with XLM

Setup

# 1. Install TypeScript dependencies
yarn install

# 2. Copy env config and fill in your keys
cp .env.example .env

# 3. Build the Soroban contract
cd contracts/reward_router
soroban contract build

# 4. Deploy to testnet (get back a contract ID)
soroban contract deploy \
  --wasm target/wasm32-unknown-unknown/release/reward_router.wasm \
  --source <YOUR_SECRET_KEY> \
  --rpc-url https://soroban-testnet.stellar.org \
  --network-passphrase "Test SDF Network ; September 2015"

# 5. Start the listener
cd ../..
yarn start

Code Walkthrough

1. Smart Contract β€” contracts/reward_router/src/lib.rs

Stores each developer's routing preferences on-chain. The set_preferences call requires the user's Stellar auth signature so only the wallet owner can modify their own rules.

#![no_std]
use soroban_sdk::{contract, contractimpl, contracttype, Address, Env, String};

#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RoutePreferences {
    pub off_ramp_pct: u32,
    pub keep_crypto_pct: u32,
    pub anchor_asset_code: String, // "NGNX" | "USDC" | "GBPT"
    pub anchor_issuer: Address,
}

#[contract]
pub struct RewardRouter;

#[contractimpl]
impl RewardRouter {
    pub fn set_preferences(env: Env, user: Address, prefs: RoutePreferences) {
        user.require_auth();
        assert!(
            prefs.off_ramp_pct + prefs.keep_crypto_pct == 100,
            "allocations must sum to 100"
        );
        env.storage().persistent().set(&user, &prefs);
    }

    pub fn get_preferences(env: Env, user: Address) -> RoutePreferences {
        env.storage()
            .persistent()
            .get(&user)
            .expect("no preferences set for this address")
    }
}

2. Path Payment Service β€” src/services/pathPayment.ts

Single function that builds and submits a pathPaymentStrictSend transaction. The empty path: [] lets Horizon's pathfinding engine auto-route through the Stellar DEX.

import { Horizon, Keypair, Operation, TransactionBuilder, Asset, Networks } from '@stellar/stellar-sdk';

const server = new Horizon.Server(process.env.HORIZON_URL || 'https://horizon-testnet.stellar.org');

export async function executePathPayment({ developerKeypair, sendAmount, sendAsset, destAsset, destMin = '0.0000001' }) {
  const account = await server.loadAccount(developerKeypair.publicKey());

  const tx = new TransactionBuilder(account, { fee: '100000', networkPassphrase: Networks.TESTNET })
    .addOperation(Operation.pathPaymentStrictSend({
      sendAsset, sendAmount,
      destination: developerKeypair.publicKey(),
      destAsset, destMin,
      path: [], // Horizon auto-routes via DEX
    }))
    .setTimeout(30)
    .build();

  tx.sign(developerKeypair);
  const result = await server.submitTransaction(tx);
  return result.hash;
}

3. Drips Listener β€” src/services/dripListener.ts

Polls for incoming Drips Wave payouts and emits RewardEvent objects to the handler pipeline. Replace the mock interval with a real Drips subgraph query or webhook.

export async function startDripListener(recipientAddress: string, onReward: RewardHandler, intervalMs = 30_000) {
  setInterval(async () => {
    // TODO: query Drips subgraph for new splits/squeezes targeting recipientAddress
    const event: RewardEvent = { developerPublicKey: recipientAddress, amount: '100.00', assetCode: 'USDC', ... };
    await onReward(event);
  }, intervalMs);
}

4. Orchestrator β€” src/index.ts

Ties the pipeline together: receive event β†’ read on-chain prefs β†’ calculate split β†’ execute swap.

async function handleReward(event: RewardEvent) {
  const prefs = await readContractPreferences(event.developerPublicKey); // TODO: soroban-client call
  const offRampAmount = ((parseFloat(event.amount) * prefs.off_ramp_pct) / 100).toFixed(7);

  const txHash = await executePathPayment({
    developerKeypair: Keypair.fromSecret(process.env.DEV_PRIVATE_KEY!),
    sendAmount: offRampAmount,
    sendAsset: new Asset(event.assetCode, event.assetIssuer),
    destAsset: new Asset(anchor.code, anchor.issuer),
  });

  console.log(`βœ… Off-ramp complete: ${txHash}`);
  // Next: trigger SEP-24 interactive deposit for bank push
}

Environment Variables

Variable Description
STELLAR_NETWORK testnet or mainnet
HORIZON_URL Horizon server endpoint
DEV_PUBLIC_KEY Developer's Stellar public key
DEV_PRIVATE_KEY Developer's Stellar secret key
NGNX_ISSUER NGNX anchor issuer address
GBPT_ISSUER GBPT anchor issuer address
SOROBAN_RPC_URL Soroban RPC endpoint
REWARD_ROUTER_CONTRACT_ID Deployed contract address

Roadmap / Open Issues

These are the remaining ~50% of the project β€” create GitHub issues for each:

  • Soroban client integration β€” Replace mock prefs with live get_preferences call via @stellar/stellar-sdk contract client
  • Drips subgraph query β€” Implement real Drips Wave payout listener using the GraphQL subgraph
  • SEP-24 off-ramp trigger β€” After path payment, call anchor's /transactions/deposit/interactive to initiate bank transfer
  • SEP-6 polling β€” Poll anchor transaction status and emit webhook/notification on completion
  • GitHub bounty listener β€” Parse GitHub webhook events for bounty payouts
  • Slippage protection β€” Dynamically calculate destMin from current DEX orderbook before submitting
  • Multi-account support β€” Handle multiple developer wallets from a single running instance
  • Frontend UI β€” Simple web interface for setting RoutePreferences and viewing transaction history

License

MIT

About

A smart wallet built on Soroban that links directly to GitHub/Drips identity protocols. The moment an ecosystem bounty, grant, or Drips Wave payout hits the wallet, a customizable rule triggers an immediate swap and off-ramp directly into the user's local bank account or mobile money wallet in Naira (NGN), Dollars (USD), or Pounds (G

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors