NexaFlow Docs

Protocol Overview & Primitives

NexaFlow operates as a decentralized, non-custodial continuous compensation routing engine. Employers deploy USDC payroll contracts and seed them with reserves. Smart contract logic calculates worker balances per-second based on time elapsed since last withdrawal.

📊 Wage Accrual Rule: Claimable Balance = elapsed_seconds × flow_rate_per_sec (subject to escrow limits).

Arc Chain Native USDC Gas

NexaFlow is deployed on the **Arc Chain**, a stablecoin-first L2 network. On Arc, transaction gas fees are paid directly in USDC instead of volatile native utility assets (like ETH, SOL, or MATIC). This guarantees predictable, rock-solid processing fees (averaging ~0.01 USDC per transfer) and enables gas sponsorship capabilities for remote workers.

USDC Native Gas assetZero utility-token friction~0.01 USDC average cost

Smart Contract Registry

Contract NameNetwork TargetHex Registry address
StreamingPayroll
Arc Testnet
0xC8f71FCDD3bDeaC7601f0DE727b165b4c10aBD2c
MicroBenefitsVault
Arc Testnet
0xe6Cc45e2270929281aCbF499424D0F8dca9D5184
USDC ERC-20 Gas
Arc Testnet
0x3600000000000000000000000000000000000000

Integration API Code Snippets

Query Stream Claimable Wages (viem / typescript)
import { createPublicClient, http, formatUnits } from 'viem';
import { arcTestnet } from 'viem/chains';

const STREAMING_PAYROLL_ADDRESS = '0x4300000000000000000000000000000000000000';
const STREAMING_PAYROLL_ABI = [
  {
    inputs: [{ name: "streamId", type: "bytes32" }],
    name: "getClaimableAmount",
    outputs: [{ name: "", type: "uint256" }],
    stateMutability: "view",
    type: "function"
  }
];

const client = createPublicClient({
  chain: arcTestnet,
  transport: http('https://rpc.testnet.arc.network')
});

async function checkClaimable(streamId: `0x${string}`) {
  const claimableWei = await client.readContract({
    address: STREAMING_PAYROLL_ADDRESS,
    abi: STREAMING_PAYROLL_ABI,
    functionName: 'getClaimableAmount',
    args: [streamId]
  });
  
  // Note: USDC token balances on Arc are represented in 6 decimal places.
  return formatUnits(claimableWei, 6);
}
Creating a Payroll Stream (viem / typescript)
import { createWalletClient, custom, parseUnits } from 'viem';
import { arcTestnet } from 'viem/chains';

const STREAMING_PAYROLL_ADDRESS = '0x4300000000000000000000000000000000000000';
const USDC_TOKEN_ADDRESS = '0x3600000000000000000000000000000000000000';

async function deployNewStream(employeeAddress: string, flowRatePerSec: number, totalCapAmount: number) {
  const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });
  
  const walletClient = createWalletClient({
    account,
    chain: arcTestnet,
    transport: custom(window.ethereum)
  });

  const flowRateWei = parseUnits(flowRatePerSec.toString(), 6);
  const totalCapWei = parseUnits(totalCapAmount.toString(), 6);

  // 1. Approve USDC first
  // 2. Call createStream(employeeAddress, flowRateWei, totalCapWei)
  const txHash = await walletClient.writeContract({
    address: STREAMING_PAYROLL_ADDRESS,
    abi: [
      {
        inputs: [
          { name: "employee", type: "address" },
          { name: "flowRate", type: "uint256" },
          { name: "totalCap", type: "uint256" }
        ],
        name: "createStream",
        outputs: [{ name: "streamId", type: "bytes32" }],
        stateMutability: "nonpayable",
        type: "function"
      }
    ],
    functionName: 'createStream',
    args: [employeeAddress, flowRateWei, totalCapWei]
  });

  return txHash;
}