# Communication Protocols

The Valu API ecosystem implements multiple communication protocols to ensure secure, efficient, and reliable data exchange between mobile applications, backend services, and external APIs.

# Mobile App to Valu API Communication

# Authentication Protocol

sequenceDiagram
    participant App as Mobile App
    participant API as Valu API
    participant DB as Database
    
    Note over App: User enters/generates seed
    App->>App: Generate bearer token from seed
    
    rect rgb(240, 248, 255)
        Note over App,API: Initial Authentication
        App->>API: POST /sessions/auth/key
        Note right of App: {secretKey: bearerToken, network: "VRSC|VRSCTEST"}
        
        API->>DB: SELECT * FROM users WHERE password = ?
        alt User not found
            API->>DB: INSERT new user with UUID
            Note right of API: Generate new API key
        else User exists
            Note right of API: Use existing API key
        end
        
        DB-->>API: User record with API key
        API-->>App: {authenticatedAs: userId, apiKey: key, success: true}
    end
    
    App->>App: Store credentials & setup request interceptors
    
    rect rgb(248, 255, 248)
        Note over App,API: Subsequent API Calls
        App->>API: Signed API Request
        Note right of App: Headers: x-api-signature, x-api-key, x-payload-digest-alg
        API->>API: Verify signature & authenticate
        API-->>App: Protected response
    end

# Request Signing Implementation

Mobile App Request Interceptor:

authenticate(valuToken, apiKey) {
  this.authInterceptor = this.service.interceptors.request.use(
    (config) => {
      // Add timestamp to prevent replay attacks
      config.url = config.url.includes("timestamp")
        ? config.url
        : config.url + `?timestamp=${Date.now()}`;

      // Sign based on HTTP method
      if (config.method === "get") {
        config.headers["x-api-signature"] = ValuService.signUrlString(
          axios.getUri(config),
          valuToken
        );
      } else {
        let uri = axios.getUri(config);
        if (uri.substr(0, 4) !== "http") {
          uri = config.baseURL.replace(/\/+$/, "") + uri;
        }
        
        // Sign URL + JSON body for POST/PUT requests
        config.headers["x-api-signature"] = ValuService.signUrlString(
          config.data == null ? uri : uri + JSON.stringify(config.data),
          valuToken
        );
      }
      
      config.headers["x-payload-digest-alg"] = "sha256";
      config.headers["x-api-key"] = apiKey;
      return config;
    }
  );
}

# Bearer Token Generation

flowchart TD
    Seed["User Seed (BIP39 Mnemonic)"] --> Convert["mnemonicToSeed()"]
    Convert --> Hash1["SHA-256 Hash"]
    
    ServiceID["VALU_SERVICE_ID (Canonical Buffer)"] --> Hash1
    Hash1 --> Hash2["RIPEMD-160 Hash"]
    Hash2 --> Token["Bearer Token (40 character hex)"]
    
    classDef input fill:#e1f5fe
    classDef process fill:#f3e5f5
    classDef output fill:#e8f5e8
    
    class Seed,ServiceID input
    class Convert,Hash1,Hash2 process
    class Token output

Implementation:

static bearerFromSeed = async (seed) => {
  var ripemd160 = crypto.createHash("ripemd160");
  var sha256 = crypto.createHash("sha256");

  const VALU_SERVICE_CANONICAL = Buffer.from(VALU_SERVICE_ID, "utf8");

  const sha256Hash = sha256
    .update(await mnemonicToSeed(seed))
    .update(VALU_SERVICE_CANONICAL)
    .digest();

  return ripemd160.update(sha256Hash).digest().toString("hex");
};

# External API Integrations

# Sumsub KYC Communication

sequenceDiagram
    participant VA as Valu API
    participant SB as Sumsub API
    
    rect rgb(255, 248, 240)
        Note over VA,SB: Request Preparation
        VA->>VA: Generate Unix timestamp
        VA->>VA: Create signature payload
        Note right of VA: timestamp + method + url + body
        VA->>VA: HMAC-SHA256 signature
    end
    
    rect rgb(240, 255, 248)
        Note over VA,SB: Authenticated Request
        VA->>SB: HTTP Request with headers
        Note right of VA: X-App-Token, X-App-Access-Sig, X-App-Access-Ts
        SB->>SB: Verify timestamp (±10 minutes)
        SB->>SB: Recreate signature & compare
        SB-->>VA: KYC operation response
    end

Sumsub Authentication Builder:

const getSigBuilder = (apiToken, secretKey) => config => {
  const timestamp = Math.floor(Date.now() / 1000)
  const signature = crypto.createHmac('sha256', secretKey)

  // Build signature payload
  signature.update(`${timestamp}${_.toUpper(config.method)}${config.url}`)
  
  if (config.data instanceof FormData) {
    signature.update(config.data.getBuffer())
  } else if (config.data) {
    signature.update(JSON.stringify(config.data))
  }

  // Set authentication headers
  config.headers['X-App-Token'] = apiToken
  config.headers['X-App-Access-Sig'] = signature.digest('hex')
  config.headers['X-App-Access-Ts'] = timestamp

  return config
}

# Paybis Payment Integration

sequenceDiagram
    participant VA as Valu API
    participant PB as Paybis API
    
    rect rgb(255, 240, 245)
        Note over VA,PB: RSA Signature Process
        VA->>VA: Serialize request body to JSON
        VA->>VA: SHA-512 hash of JSON string
        VA->>VA: RSA-PSS sign with private key
        Note right of VA: PKCS1_PSS_PADDING + SALTLEN_DIGEST
        VA->>VA: Base64 encode signature
    end
    
    rect rgb(240, 248, 255)
        Note over VA,PB: Payment Request
        VA->>PB: POST with X-Request-Signature header
        Note right of VA: Authorization: Bearer token
        PB->>PB: Verify RSA signature
        PB->>PB: Process payment operation
        PB-->>VA: Payment response
    end

RSA Signature Implementation:

const getSigBuilder = (privateKey) => config => {
  if (!config.data) return config
  
  // Hash the request body
  const hash = crypto.createHash('sha512');
  const hashedData = hash.update(JSON.stringify(config.data), 'utf-8').digest('hex');
  
  // Create RSA-PSS signature
  const signature = crypto.sign("sha512", Buffer.from(hashedData), {
    key: privateKey,
    padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
    saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST,
  })
  
  config.headers['X-Request-Signature'] = signature.toString('base64')
  return config
}

# Stripe Payment Processing

flowchart LR
    VA[Valu API] --> Auth[Bearer Token Auth]
    Auth --> Request[HTTPS Request]
    Request --> Stripe[Stripe API]
    Stripe --> Response[JSON Response]
    
    subgraph "Request Flow"
        Headers[Authorization Header<br/>Content-Type: application/json]
        TLS[TLS 1.3 Encryption]
        Webhook[Webhook Verification<br/>Stripe-Signature]
    end
    
    Auth --> Headers
    Request --> TLS
    Response --> Webhook

Stripe Authentication:

const getStripeQuote = async (countryCode) => {
  const convertedCountryCode = getCountryCodeAndCurrency(countryCode);
  const url = new URL('https://api.stripe.com/v1/crypto/onramp_quotes');
  
  url.searchParams.append('source_amount', 1000);
  url.searchParams.append('destination_currencies[]', "usdc");
  url.searchParams.append('destination_networks[]', 'ethereum');
  url.searchParams.append('source_currency', convertedCountryCode.currency.toLowerCase());

  const response = await fetch(url, {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${process.env.STRIPE_SK}`,
      'Content-Type': 'application/json'
    }
  });
  
  return response.json();
}

# Blockchain Communication Protocols

# Verus Blockchain RPC

sequenceDiagram
    participant VA as Valu API
    participant VD as Verus Daemon
    
    rect rgb(248, 255, 248)
        Note over VA,VD: RPC Authentication
        VA->>VD: HTTP Basic Auth Request
        Note right of VA: Username: REMOTE_USER<br/>Password: REMOTE_PASS
        VD->>VD: Validate credentials
    end
    
    rect rgb(240, 248, 255)
        Note over VA,VD: RPC Commands
        VA->>VD: JSON-RPC 2.0 Request
        Note right of VA: {"method": "getinfo", "params": [], "id": 1}
        VD->>VD: Execute blockchain operation
        VD-->>VA: JSON-RPC Response
        Note left of VD: {"result": {...}, "error": null, "id": 1}
    end

Verus RPC Configuration:

// Environment configuration
const VERUS_CONFIG = {
  protocol: process.env.REMOTE_PROTOCOL || "http",
  host: process.env.REMOTE_HOST,
  port: process.env.REMOTE_PORT,
  username: process.env.REMOTE_USER,
  password: process.env.REMOTE_PASS
};

const rpcCall = async (method, params = []) => {
  const request = {
    jsonrpc: "2.0",
    method: method,
    params: params,
    id: Math.floor(Math.random() * 1000000)
  };
  
  const response = await axios.post(
    `${VERUS_CONFIG.protocol}://${VERUS_CONFIG.host}:${VERUS_CONFIG.port}`,
    request,
    {
      auth: {
        username: VERUS_CONFIG.username,
        password: VERUS_CONFIG.password
      }
    }
  );
  
  return response.data.result;
};

# Polygon Blockchain Integration

sequenceDiagram
    participant VA as Valu API
    participant PP as Polygon Provider
    participant PC as Polygon Contract
    
    rect rgb(255, 248, 240)
        Note over VA,PP: Provider Connection
        VA->>PP: Connect to RPC endpoint
        Note right of VA: https://rpc-amoy.polygon.technology/
        PP-->>VA: Connection established
    end
    
    rect rgb(248, 255, 248)
        Note over VA,PC: Transaction Flow
        VA->>VA: Create wallet instance with private key
        VA->>PC: Contract.transfer(address, amount)
        PC->>PP: Submit transaction to network
        PP->>PP: Mine transaction in block
        PP-->>VA: Transaction hash & receipt
    end

Polygon Transaction Implementation:

const { JsonRpcProvider, Wallet, parseUnits, Contract } = require("ethers");

// Initialize provider and wallet
const provider = new JsonRpcProvider("https://rpc-amoy.polygon.technology/");
const wallet = new Wallet(process.env.POLYGON_AMOY_PRIVATE_KEY, provider);

async function payUSDC(toAddress, amount) {
  try {
    // Validate recipient address
    if (!isAddress(toAddress)) {
      throw new Error("Invalid recipient address");
    }
    
    // Setup USDC contract
    const usdcContractAddress = process.env.USDC_AMOY_CONTRACT_ADDRESS;
    const usdcAbi = ["function transfer(address to, uint256 amount) public returns (bool)"];
    const usdcContract = new Contract(usdcContractAddress, usdcAbi, wallet);
    
    // Convert amount to proper decimals (USDC uses 6 decimals)
    const amountInSmallestUnit = parseUnits(amount, 6);
    
    // Execute transaction
    const transactionResponse = await usdcContract.transfer(toAddress, amountInSmallestUnit);
    console.log("Transaction sent:", transactionResponse.hash);
    
    // Wait for confirmation
    await transactionResponse.wait();
    console.log("Transaction confirmed:", transactionResponse.hash);
    
    return transactionResponse.hash;
  } catch (error) {
    console.error("Error sending USDC payment:", error);
    throw error;
  }
}

# Database Communication

# SQL Server Connection Protocol

flowchart TD
    subgraph "Connection Pool"
        Pool[MySQL Connection Pool<br/>Max: 100 connections]
        Pool --> Conn1[Connection 1<br/>Active]
        Pool --> Conn2[Connection 2<br/>Idle]
        Pool --> ConnN[Connection N<br/>Available]
    end
    
    subgraph "Query Processing"
        Query[SQL Query] --> Prepare[Prepared Statement]
        Prepare --> Execute[Execute with Parameters]
        Execute --> Result[Result Set]
    end
    
    subgraph "Security"
        SSL[SSL/TLS Encryption]
        Auth[Database Authentication]
        Audit[Query Auditing]
    end
    
    Pool --> Query
    Query --> SSL
    SSL --> Auth
    Auth --> Audit

Database Configuration:

const mysql = require('mysql2/promise');

const pool = mysql.createPool({
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  waitForConnections: true,
  connectionLimit: 100,
  queueLimit: 0,
  ssl: {
    rejectUnauthorized: false // Configure based on SSL setup
  },
  acquireTimeout: 60000,
  timeout: 60000
});

// User creation with parameterized queries
exports.setNewUserforPOL = async (api_key, password, status, network) => {
  const userId = uuidv4();
  
  // Insert new user
  const result = await pool.query(
    'INSERT INTO users (id, status, password, api_key, network) VALUES (?, ?, ?, ?, ?)',
    [userId, status, password, api_key, network]
  );

  // Retrieve created user
  const userResult = await pool.query(
    'SELECT * FROM users WHERE id = ?',
    [userId]
  );

  return userResult[0];
};

# Inter-Service Communication Patterns

# Synchronous vs Asynchronous Communication

graph TB
    subgraph "Synchronous (Real-time)"
        S1[User Authentication] --> S2[KYC Verification]
        S3[Payment Processing] --> S4[Blockchain Transactions]
    end
    
    subgraph "Asynchronous (Event-driven)"
        A1[Webhook Processing] --> Queue[Message Queue]
        Queue --> A2[Background Jobs]
        A2 --> A3[Notification Delivery]
    end
    
    subgraph "Hybrid Patterns"
        H1[Initial Request] --> H2[Immediate Response]
        H2 --> H3[Background Processing]
        H3 --> H4[Callback/Webhook]
    end

# Error Handling & Retry Logic

sequenceDiagram
    participant Client
    participant API as Valu API
    participant Service as External Service
    
    Client->>API: Request
    API->>Service: Service Call
    
    alt Success
        Service-->>API: Success Response
        API-->>Client: Success
    else Temporary Error
        Service-->>API: 5xx Error
        API->>API: Wait (exponential backoff)
        API->>Service: Retry Request
        Service-->>API: Success Response
        API-->>Client: Success
    else Permanent Error
        Service-->>API: 4xx Error
        API-->>Client: Error Response
    else Timeout
        Service-->>API: Timeout
        API->>API: Log & Alert
        API-->>Client: Service Unavailable
    end

Retry Implementation:

const retryWithBackoff = async (fn, maxRetries = 3, baseDelay = 1000) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (attempt === maxRetries) {
        throw error;
      }
      
      // Check if error is retryable
      if (error.response && error.response.status < 500) {
        throw error; // Don't retry client errors
      }
      
      // Exponential backoff with jitter
      const delay = baseDelay * Math.pow(2, attempt - 1) + Math.random() * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
};

Version Header Implementation:

// Client specifies API version
config.headers['API-Version'] = '2.0';

// Server handles version routing
app.use('/api/v1', v1Router);
app.use('/api/v2', v2Router);
app.use('/api/v3', v3Router);

// Default to latest stable version
app.use('/api', v2Router);

This comprehensive communication protocol documentation ensures secure, efficient, and scalable interactions across the entire Valu ecosystem.