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.
标签
skill
ai