# Sohopay

> Initiate payments on the SOHO Pay credit layer using EIP-712 signatures.

- Skill: `dvcrn/sohopay` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add dvcrn/sohopay`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dvcrn/sohopay/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: dvcrn (https://skillmd.com/u/dvcrn)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/dvcrn/sohopay

---


# SOHO Pay - Credit Layer Payments

This skill allows the agent to initiate payments through the SOHO Pay `Creditor` smart contract using the `spendWithAuthorization` EIP-712 flow.

The agent signs the payment authorization off-chain using a pre-configured wallet, and then submits the transaction to the network on the user's behalf.

## Core Command

The primary way to use this skill is with a natural language command that maps to:

`pay <amount> to <merchant_address>`

- `<amount>`: The numerical amount to pay (e.g., `10`, `0.5`).
- `<merchant_address>`: The recipient EVM address (`0x...`). **Names are not supported** and no random addresses are ever generated by this skill.

## Workflow

### Payments (credit spend)

When you issue a `pay` command, the skill performs the following actions:

1. **Parse Inputs**: Extracts the amount and merchant address from the user's request.
2. **Validate Merchant Address**: Confirms that the merchant is a valid EVM address; otherwise it aborts.
3. **Pre-Flight Checks** (BorrowerManager):
    - Verifies the borrower is **registered** and **active**.
    - Checks if the **credit limit** is sufficient for the requested amount.
    - On demand, can auto-register the agent once via `registerAgent`.
4. **Generate Authorization**: Creates an EIP-712 typed data message for the payment.
5. **Sign Off-Chain**: Uses the configured `PRIVATE_KEY` wallet (from environment variables) to sign the authorization message.
6. **Execute On-Chain**: Calls the `spendWithAuthorization` function on the `Creditor` contract, providing the signed message.
7. **Report Result**: Returns the transaction hash to the user upon confirmation.

### Status / Profile checks

The `status` helper reads the **BorrowerManager** profile + USDC wallet balance for the bot:

- Calls the `s_borrowerProfiles(address)` public mapping getter to fetch:  
  `creditLimit, outstandingDebt, totalSpent, totalRepaid, spendingCount, repaymentCount, lastActivityTime, creditScore, isActive, isAgent, transactionIds`.
- Calls `IERC20(USDC).balanceOf(bot)` to fetch the **USDC wallet balance** for the same address.
- Prints a human-readable summary so you can see, per network:
  - Whether the bot is registered / active
  - Credit limit and whether the profile is flagged as an agent
  - **Outstanding debt** and historical spend/repay totals
  - Last activity timestamp and credit score
  - USDC balance available in the wallet

This is what powers prompts like:

- `"check my bot status on testnet"`
- `"check my bot outstanding debt on mainnet"`

### Repayments (reduce outstanding debt)

The `repay` helper uses USDC to pay down **outstandingDebt** tracked by BorrowerManager and Creditor:

1. **Pre-flight checks**:
   - Verifies the borrower is **registered** and **active**.
   - Reads current **credit limit** and any existing **outstandingDebt`**.
2. **USDC balance & allowance**:
   - Ensures the bot wallet has enough **USDC balance** for the requested repayment.
   - Checks `IERC20(USDC).allowance(bot, Creditor)` and, if too low, sends an `approve(Creditor, amount)` tx first.
3. **On-chain repay**:
   - Calls `Creditor.repay(amount, USDC)` from the borrower wallet.
   - The Creditor contract:
     - Caps the repayment to `min(amount, outstandingDebt)`.
     - Applies payments to BNPL plans via `applyPaymentToPlans`.
     - Updates the borrower profile via `updateOnRepayment` (new score + limit).
     - Transfers USDC from the borrower to the Vault and calls `vault.repayVaultDebt`.
   - Emits a repayment event with the new score and limit.
4. **Status after repay**:
   - After a successful repay, you can run `status` again to verify:
     - `outstandingDebt` has decreased (or is `0`),
     - `totalRepaid` increased,
     - `creditScore` and `creditLimit` have been updated.

This is what backs prompts like:

- `"repay my bot debt on testnet"`
- `"repay 5 USDC of my bot debt on mainnet"`

## Configuration

- **Environment Variable (runtime)**: The private key for the signing wallet must be provided via the `PRIVATE_KEY` environment variable.
- **Why the private key is needed**: OpenClaw is designed to run as an autonomous agent. For it to initiate SOHO Pay transactions without human clicks, it must be able to sign EIP-712 authorizations itself.
- **Local-only usage (important)**: **`PRIVATE_KEY` is used *only locally* on the machine running OpenClaw. The raw key is **never** sent to SOHO Pay, ClawHub, or any external service — only signed messages and transactions leave the machine.** Anyone running this bot must understand that the key controls whatever funds are on the selected network.
- **Skill Metadata**: The skill declares `PRIVATE_KEY` as a required, sensitive credential. You can use a single key for both Base mainnet and Base Sepolia, but be aware this may control real funds on mainnet.
- **Networks**: The script supports both **Base mainnet** (default) and **Base Sepolia** (testnet). It enforces the expected `chainId` for the selected network and aborts if the RPC does not match.

## Defaults

The following values are hardcoded into the script for consistency, and are used on **both** Base mainnet and Base Sepolia:

- **Creditor Contract**: `0xdb34d612dd9aa548f6c94af118f82a461a835e09`
- **Borrower Manager**: `0xc6ecd37c42ee73714956b6a449b41bc1d46b07b0`
- **Asset (USDC)**: `0x43848d5a4efa0b1c72e1fd8ece1abf42e9d5e221` (6 decimals)
- **Payment Plan ID**: `0`

## Setup, Installation & Dependencies

This skill is a small Node.js project under `skills/sohopay`.

1. **Set `PRIVATE_KEY`** in the environment where OpenClaw runs:
   ```bash
   export PRIVATE_KEY=0xYOUR_KEY_HERE
   ```
   This address will be the SOHO Pay "agent" on Base mainnet / Base Sepolia.

2. **Install the skill and dependencies**:
   ```bash
   clawhub install sohopay
   cd skills/sohopay
   npm install
   ```
   This installs the runtime dependencies declared in `package.json` (currently `ethers` and `dotenv`).

3. **Register the agent once on the chosen network** (before making payments):
   ```bash
   # Base mainnet (default)
   node scripts/register.js

   # Explicit mainnet
   node scripts/register.js mainnet

   # Base Sepolia testnet
   node scripts/register.js testnet
   ```
   This calls `registerAgent(agent)` on the `BorrowerManager` contract using the `PRIVATE_KEY` address.

4. **Make payments after registration** using `scripts/pay.js`:
   ```bash
   # Base mainnet (default when no network arg is given)
   node scripts/pay.js 10 0xMerchantOnMainnet

   # Explicit mainnet
   node scripts/pay.js mainnet 10 0xMerchantOnMainnet

   # Base Sepolia testnet
   node scripts/pay.js testnet 10 0xMerchantOnTestnet
   ```
   This uses the SOHO Pay Creditor contract to spend on credit via `spendWithAuthorization`.

5. **Check status / profile and balances** using `scripts/status.js`:
   ```bash
   # Base mainnet
   node scripts/status.js mainnet

   # Base Sepolia testnet
   node scripts/status.js testnet
   ```
   This reads the BorrowerManager profile and USDC wallet balance for the agent and prints a human-readable summary (credit limit, outstanding debt, totals, scores, and USDC balance).

6. **Repay outstanding debt using USDC** with `scripts/repay.js`:
   ```bash
   # Base mainnet
   node scripts/repay.js mainnet 10

   # Base Sepolia testnet
   node scripts/repay.js testnet 10
   ```
   This uses USDC from the agent wallet to repay `outstandingDebt` via the Creditor contract, updating the borrower profile and vault debt, and emitting a repayment event.

## Security Notes

- **`PRIVATE_KEY` is highly sensitive**. Treat it exactly like the key to a normal wallet: anyone with this value can move all funds it controls.
- **Local signing only**: The script signs transactions **locally** and never transmits the raw private key over the network. Only signatures and transactions are sent to RPC endpoints.
- This skill **never triggers itself**; it is only executed when called by a user, cron job, or higher-level workflow. It is safe to wire into autonomous flows (e.g. “if price < 10, then pay …”) as long as you understand what those automations will do with your `PRIVATE_KEY`.
- The merchant must be provided as an explicit `merchant_address`. If the address is wrong, funds on that network may be irrecoverably sent to the wrong account.
- No random address generation is performed. The skill will refuse non-address merchant inputs.

## Example Usage

### Natural-language commands

These are the kinds of prompts you can send to your OpenClaw agent once the skill is installed and `PRIVATE_KEY` is configured.

- **Register bot (testnet)**  
  `"register my bot to use sohopay on Base Sepolia testnet"`

- **Register bot (mainnet)**  
  `"register my bot to use sohopay on Base mainnet"`

- **Pay a merchant** (EIP‑712 spendWithAuthorization)  
  `"pay 10 USDC to 0x1234567890abcdef1234567890abcdef12345678 on testnet using sohopay"`

- **Check bot status** (credit limit, outstanding debt, totals, USDC balance)  
  `"check my bot status on testnet"`  
  `"check my bot outstanding debt on mainnet"`

- **Repay debt** (calls `Creditor.repay(amount, stablecoin)`)  
  `"repay my bot debt on testnet"`  
  `"repay 5 USDC of my bot debt on mainnet"`

### Script entrypoints (for reference)

- Registration: `node scripts/register.js [mainnet|testnet] [check]`  
  - `node scripts/register.js testnet` – register bot on Base Sepolia  
  - `node scripts/register.js mainnet check` – status only, no tx

- Payments (credit spend):  
  - `node scripts/pay.js [mainnet|testnet] <amount> <merchant_address>`

- Status (profile + outstanding debt + USDC balance):  
  - `node scripts/status.js mainnet`  
  - `node scripts/status.js testnet`

- Repayments (reduce outstanding debt using USDC):  
  - `node scripts/repay.js [mainnet|testnet] <amount>`

When mapped through OpenClaw, you should prefer **natural-language prompts**; the scripts above are provided for debugging and manual CLI use.

