@clawhub-viyozc-1a87510a89
End-to-end OpenBytes network API workflows for AI agents. Covers wallet signature-based authentication, on-chain top-up monitoring, consumer API key lifecycl...
---
name: openbytes
description: End-to-end OpenBytes network API workflows for AI agents. Covers wallet signature-based authentication, on-chain top-up monitoring, consumer API key lifecycle (create, list, revoke), API calls to language models via gateway, and querying balance and usage via HTTP endpoints. Use to help users automate or debug OpenBytes network operations by direct API interaction.
---
# OpenBytes Control Plane Skill
This skill describes **end-to-end operational workflows** for the OpenBytes network from an **API usage perspective**.
- Wallet-based authentication (signature flow)
- On-chain balance top-up and verification
- Consumer API key lifecycle (create, list, revoke)
- Model inference via ApiKey
- Query balance and usage via HTTP API
Assumptions:
- A **gateway HTTP API** exists : `https://gateway.openbytes.ai`
- All workflows are CLI-, curl-, or script-oriented
- The network supports **Base Sepolia**. Use the correct chain id:
- Base Sepolia: `84532`
Replace all `<BASE_URL>` with the actual gateway URL as needed.
---
## 1. Wallet-based registration & session
**Note**: Message signing must be performed by the user with their EVM wallet. The agent can only initiate the challenge and verify a signature; it **cannot** produce signatures.
1. If you don't have a wallet yet, immediately create a new one using [ethers.js](https://docs.ethers.org/v6/api/wallet/#Wallet-createRandom) or [viem](https://viem.sh/docs/actions/wallet/createWallet.html).
**Be sure to securely save your generated private key!** Example (Node.js with ethers.js):
```js
import { Wallet } from "ethers";
const wallet = Wallet.createRandom();
console.log("Address:", wallet.address);
console.log("Private Key (save this securely!):", wallet.privateKey);
```
Or using viem:
```js
import { createWallet } from "viem/accounts";
const wallet = createWallet();
console.log("Address:", wallet.address);
console.log("Private Key (save this securely!):", wallet.privateKey);
```
Never share your private key. Backup and store it in a secure location.
"wallet_address": "0x...",
"chain_id": "8453"
2. User signs the `message` off-chain (with their wallet).
3. Submit the signed message to the gateway for verification:
```sh
curl -sS -X POST "<BASE_URL>/v1/auth/wallet/verify" \
-H "Content-Type: application/json" \
-d '{
"wallet_address": "<EVM_WALLET_ADDRESS>",
"nonce": "random-nonce",
"signature": "<WALLET_SIGNATURE>"
}'
```
Successful response (simplified):
```json
{
"login_token": "sess-...",
"expires_at": "2025-01-01T00:00:00Z",
"consumer": {
"id": "consumer-uuid",
"wallet_address": "0x..."
},
"session": {
"id": "session-uuid"
}
}
```
4. The `login_token` (starting with `sess-`) is used as a **session token**:
- Send it as `Authorization: Bearer <SESSION_TOKEN>` for session-auth endpoints.
5. List Available Models
```sh
curl -sS -X GET "<BASE_URL>/v1/models"
```
6. **Immediately create an API key following step 2.1 and switch to it** for all non-session endpoints (models, balance, usage). Do **not** keep using the session token for inference.
**Check**:
- Session token is present and sent in the `Authorization: Bearer sess-...` header during all subsequent calls requiring authentication.
- After creating the API key, subsequent calls should use `Authorization: Bearer <CONSUMER_API_KEY>`.
---
## 2. Consumer API Key Lifecycle
Consumers use API keys to access models without a session.
### 2.1 Create API Key
Requires a valid session token (`login_token` from section 1).
```sh
curl -sS -X POST "<BASE_URL>/v1/consumer/api-keys" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <SESSION_TOKEN>" \
-d '{
"label": "my-key"
}'
```
Sample response (**save the `api_key` securely; only returned once!**):
```json
{
"id": "key-uuid",
"api_key": "sk-consumer-...",
"prefix": "sk-cons",
"suffix": "abcd",
"label": "my-key",
"status": "active",
"created_at": "2025-01-01T00:00:00Z"
}
```
**Immediately switch to this API key** for inference, balance, and usage calls:
```sh
export OPENBYTES_API_KEY="sk-consumer-..."
```
Then use:
```sh
curl -sS -X GET "<BASE_URL>/v1/balance" \
-H "Authorization: Bearer $OPENBYTES_API_KEY"
```
### 2.2 List API Keys
```sh
curl -sS -X GET "<BASE_URL>/v1/consumer/api-keys" \
-H "Authorization: Bearer <SESSION_TOKEN>"
```
### 2.3 Revoke API Key
```sh
curl -sS -X DELETE "<BASE_URL>/v1/consumer/api-keys/<KEY_ID>" \
-H "Authorization: Bearer <SESSION_TOKEN>"
```
The key status will be set to `revoked`; subsequent calls using that key will fail with an auth error.
---
## 3. On-chain Top-up Flow
Top-up is performed on-chain (USDC to a ConsumerDeposit contract), tracked by off-chain indexers. The API lets you verify the result.
You can use your own RPC endpoint; a default for Base Sepolia is `https://sepolia.base.org`.
- User transfers USDC to the ConsumerDeposit contract with proper calldata.
- Backend credits the consumer balance after L1/L2 tx confirmation (indexer-driven).
- USDC address: `0x10065E7b353371DD2e12348e7094cC774638EbEB`
- ConsumerDeposit contract: `0xB0E9ebf19AB710d3353c7F637DC55329d9727dCc`
- Before deposit, approve allowance
- Deposit ABI: `function deposit(uint256 amount)`
**Verify balance:**
```sh
curl -sS -X GET "<BASE_URL>/v1/balance" \
-H "Authorization: Bearer <CONSUMER_API_KEY>"
```
Sample response:
```json
{
"balance_usdc": "123.45",
"total_spent": "10.00"
}
```
---
## 4. Connect Your Wallet to Your Operator's Wallet
Use this to allow an **account to connect to an operator's account**, so the operator can top up your wallet easily. This requires a **wallet signature** over a structured message. The signature **must be produced by the child wallet**.
**Endpoint:**
```sh
curl -sS -X POST "<BASE_URL>/v1/consumers/me/parent" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <SESSION_TOKEN>" \
-d '{
"parent_wallet": "<PARENT_WALLET>",
"issued_at": 1710000000,
"signature": "<CHILD_WALLET_SIGNATURE>"
}'
```
Notes:
- Signature verification is done by the gateway using `ethers.verifyMessage(message, signature)`,
and the **recovered address must equal the child wallet address** (case-insensitive).
This is the standard EIP-191 personal message signature (same flow as SIWE).
- `issued_at` is **Unix seconds**. It must be **within the last 5 minutes** and not more than **1 minute in the future**.
- The signed message must be **exactly** (including line breaks, casing, and spacing):
```
Authorize parent for OpenBytes
Parent wallet: <PARENT_WALLET_LOWERCASE>
Child wallet: <CHILD_WALLET_LOWERCASE>
Issued at: <ISSUED_AT>
```
- **Normalization rules:**
- `<PARENT_WALLET_LOWERCASE>` is the parent wallet address **lowercased**.
- `<CHILD_WALLET_LOWERCASE>` is the child wallet address **lowercased** (the signer).
- `<ISSUED_AT>` is the same Unix seconds integer you send in the request body.
- If any character differs (extra whitespace, different casing, different timestamp), the signature will fail.
**Pseudo-code (client-side):**
```ts
const issuedAt = Math.floor(Date.now() / 1000);
const parentWallet = parentWalletAddress.toLowerCase();
const childWallet = childWalletAddress.toLowerCase();
const message = [
"Authorize parent for OpenBytes",
`Parent wallet: parentWallet`,
`Child wallet: childWallet`,
`Issued at: issuedAt`,
].join("\n");
const signature = await wallet.signMessage(message); // EIP-191 personal_sign
```
**Success response (201):**
```json
{
"parent_consumer_id": "consumer-uuid",
"parent_wallet_address": "0x...",
"created_at": "2025-01-01T00:00:00Z"
}
```
**Common errors:**
- `400 INVALID_REQUEST` invalid body
- `400 SIGNATURE_EXPIRED` `issued_at` out of window
- `404 PARENT_NOT_FOUND` parent not found
- `400 SELF_PARENT` cannot declare yourself
- `401 SIGNATURE_MISMATCH` signature not from child wallet
- `409 ALREADY_SET` parent already declared
---
## 5. Usage Guidelines for AI Agents
When handling OpenBytes network operational support, follow these best practices:
1. Map user questions directly to the appropriate **API workflow** without reference to UI.
- Example intents: onboarding, balance issue, API key management, quota/cost analysis
2. Provide **concrete curl commands** tailored to the user's configuration (`<BASE_URL>`, `<CONSUMER_API_KEY>`, etc).
3. When troubleshooting:
- Request the **full API HTTP response** (status + JSON).
- Use `error.code` and context to select remediation steps.
4. Be concise, focus on actionable commands and next steps.
5. Only provide background technical details if specifically requested.
End-to-end OpenBytes network API workflows for AI agents. Covers wallet signature-based authentication, on-chain top-up monitoring, consumer API key lifecycl...
---
name: openbytes
description: End-to-end OpenBytes network API workflows for AI agents. Covers wallet signature-based authentication, on-chain top-up monitoring, consumer API key lifecycle (create, list, revoke), API calls to language models via gateway, and querying balance and usage via HTTP endpoints. Use to help users automate or debug OpenBytes network operations by direct API interaction.
---
# OpenBytes Control Plane Skill
This skill describes **end-to-end operational workflows** for the OpenBytes network from an **API usage perspective**.
- Wallet-based authentication (signature flow)
- On-chain balance top-up and verification
- Consumer API key lifecycle (create, list, revoke)
- Model inference via ApiKey
- Query balance and usage via HTTP API
Assumptions:
- A **gateway HTTP API** exists : `https://gateway.openbytes.ai`
- All workflows are CLI-, curl-, or script-oriented
- The network supports **Base Sepolia**. Use the correct chain id:
- Base Sepolia: `84532`
Replace all `<BASE_URL>` with the actual gateway URL as needed.
---
## 1. Wallet-based registration & session
**Note**: Message signing must be performed by the user with their EVM wallet. The agent can only initiate the challenge and verify a signature; it **cannot** produce signatures.
1. If you don't have a wallet yet, immediately create a new one using [ethers.js](https://docs.ethers.org/v6/api/wallet/#Wallet-createRandom) or [viem](https://viem.sh/docs/actions/wallet/createWallet.html).
**Be sure to securely save your generated private key!** Example (Node.js with ethers.js):
```js
import { Wallet } from "ethers";
const wallet = Wallet.createRandom();
console.log("Address:", wallet.address);
console.log("Private Key (save this securely!):", wallet.privateKey);
```
Or using viem:
```js
import { createWallet } from "viem/accounts";
const wallet = createWallet();
console.log("Address:", wallet.address);
console.log("Private Key (save this securely!):", wallet.privateKey);
```
Never share your private key. Backup and store it in a secure location.
"wallet_address": "0x...",
"chain_id": "8453"
2. User signs the `message` off-chain (with their wallet).
3. Submit the signed message to the gateway for verification:
```sh
curl -sS -X POST "<BASE_URL>/v1/auth/wallet/verify" \
-H "Content-Type: application/json" \
-d '{
"wallet_address": "<EVM_WALLET_ADDRESS>",
"nonce": "random-nonce",
"signature": "<WALLET_SIGNATURE>"
}'
```
Successful response (simplified):
```json
{
"login_token": "sess-...",
"expires_at": "2025-01-01T00:00:00Z",
"consumer": {
"id": "consumer-uuid",
"wallet_address": "0x..."
},
"session": {
"id": "session-uuid"
}
}
```
4. The `login_token` (starting with `sess-`) is used as a **session token**:
- Send it as `Authorization: Bearer <SESSION_TOKEN>` for session-auth endpoints.
5. List Available Models
```sh
curl -sS -X GET "<BASE_URL>/v1/models"
```
6. **Immediately create an API key following step 2.1 and switch to it** for all non-session endpoints (models, balance, usage). Do **not** keep using the session token for inference.
**Check**:
- Session token is present and sent in the `Authorization: Bearer sess-...` header during all subsequent calls requiring authentication.
- After creating the API key, subsequent calls should use `Authorization: Bearer <CONSUMER_API_KEY>`.
---
## 2. Consumer API Key Lifecycle
Consumers use API keys to access models without a session.
### 2.1 Create API Key
Requires a valid session token (`login_token` from section 1).
```sh
curl -sS -X POST "<BASE_URL>/v1/consumer/api-keys" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <SESSION_TOKEN>" \
-d '{
"label": "my-key"
}'
```
Sample response (**save the `api_key` securely; only returned once!**):
```json
{
"id": "key-uuid",
"api_key": "sk-consumer-...",
"prefix": "sk-cons",
"suffix": "abcd",
"label": "my-key",
"status": "active",
"created_at": "2025-01-01T00:00:00Z"
}
```
**Immediately switch to this API key** for inference, balance, and usage calls:
```sh
export OPENBYTES_API_KEY="sk-consumer-..."
```
Then use:
```sh
curl -sS -X GET "<BASE_URL>/v1/balance" \
-H "Authorization: Bearer $OPENBYTES_API_KEY"
```
### 2.2 List API Keys
```sh
curl -sS -X GET "<BASE_URL>/v1/consumer/api-keys" \
-H "Authorization: Bearer <SESSION_TOKEN>"
```
### 2.3 Revoke API Key
```sh
curl -sS -X DELETE "<BASE_URL>/v1/consumer/api-keys/<KEY_ID>" \
-H "Authorization: Bearer <SESSION_TOKEN>"
```
The key status will be set to `revoked`; subsequent calls using that key will fail with an auth error.
---
## 3. On-chain Top-up Flow
Top-up is performed on-chain (USDC to a ConsumerDeposit contract), tracked by off-chain indexers. The API lets you verify the result.
You can use your own RPC endpoint; a default for Base Sepolia is `https://sepolia.base.org`.
- User transfers USDC to the ConsumerDeposit contract with proper calldata.
- Backend credits the consumer balance after L1/L2 tx confirmation (indexer-driven).
- USDC address: `0x10065E7b353371DD2e12348e7094cC774638EbEB`
- ConsumerDeposit contract: `0xB0E9ebf19AB710d3353c7F637DC55329d9727dCc`
- Before deposit, approve allowance
- Deposit ABI: `function deposit(uint256 amount)`
**Verify balance:**
```sh
curl -sS -X GET "<BASE_URL>/v1/balance" \
-H "Authorization: Bearer <CONSUMER_API_KEY>"
```
Sample response:
```json
{
"balance_usdc": "123.45",
"total_spent": "10.00"
}
```
---
## 4. Connect Your Wallet to Your Operator's Wallet
Use this to allow an **account to connect to an operator's account**, so the operator can top up your wallet easily. This requires a **wallet signature** over a structured message. The signature **must be produced by the child wallet**.
**Endpoint:**
```sh
curl -sS -X POST "<BASE_URL>/v1/consumers/me/parent" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <SESSION_TOKEN>" \
-d '{
"parent_wallet": "<PARENT_WALLET>",
"issued_at": 1710000000,
"signature": "<CHILD_WALLET_SIGNATURE>"
}'
```
Notes:
- Signature verification is done by the gateway using `ethers.verifyMessage(message, signature)`,
and the **recovered address must equal the child wallet address** (case-insensitive).
This is the standard EIP-191 personal message signature (same flow as SIWE).
- `issued_at` is **Unix seconds**. It must be **within the last 5 minutes** and not more than **1 minute in the future**.
- The signed message must be **exactly** (including line breaks, casing, and spacing):
```
Authorize parent for OpenBytes
Parent wallet: <PARENT_WALLET_LOWERCASE>
Child wallet: <CHILD_WALLET_LOWERCASE>
Issued at: <ISSUED_AT>
```
- **Normalization rules:**
- `<PARENT_WALLET_LOWERCASE>` is the parent wallet address **lowercased**.
- `<CHILD_WALLET_LOWERCASE>` is the child wallet address **lowercased** (the signer).
- `<ISSUED_AT>` is the same Unix seconds integer you send in the request body.
- If any character differs (extra whitespace, different casing, different timestamp), the signature will fail.
**Pseudo-code (client-side):**
```ts
const issuedAt = Math.floor(Date.now() / 1000);
const parentWallet = parentWalletAddress.toLowerCase();
const childWallet = childWalletAddress.toLowerCase();
const message = [
"Authorize parent for OpenBytes",
`Parent wallet: parentWallet`,
`Child wallet: childWallet`,
`Issued at: issuedAt`,
].join("\n");
const signature = await wallet.signMessage(message); // EIP-191 personal_sign
```
**Success response (201):**
```json
{
"parent_consumer_id": "consumer-uuid",
"parent_wallet_address": "0x...",
"created_at": "2025-01-01T00:00:00Z"
}
```
**Common errors:**
- `400 INVALID_REQUEST` invalid body
- `400 SIGNATURE_EXPIRED` `issued_at` out of window
- `404 PARENT_NOT_FOUND` parent not found
- `400 SELF_PARENT` cannot declare yourself
- `401 SIGNATURE_MISMATCH` signature not from child wallet
- `409 ALREADY_SET` parent already declared
---
## 5. Usage Guidelines for AI Agents
When handling OpenBytes network operational support, follow these best practices:
1. Map user questions directly to the appropriate **API workflow** without reference to UI.
- Example intents: onboarding, balance issue, API key management, quota/cost analysis
2. Provide **concrete curl commands** tailored to the user's configuration (`<BASE_URL>`, `<CONSUMER_API_KEY>`, etc).
3. When troubleshooting:
- Request the **full API HTTP response** (status + JSON).
- Use `error.code` and context to select remediation steps.
4. Be concise, focus on actionable commands and next steps.
5. Only provide background technical details if specifically requested.
Helps the agent use the one-wallet CLI to manage Ethereum/EVM wallets, send transactions, call contracts, and sign data. Use when the user mentions one-walle...
---
name: one-wallet
description: Helps the agent use the one-wallet CLI to manage Ethereum/EVM wallets, send transactions, call contracts, and sign data. Use when the user mentions one-wallet, wallet CLI operations, Ethereum/EVM scripting, or needs JSON-friendly terminal workflows involving one-wallet.
---
# one-wallet CLI Skill
## Overview
This skill teaches the agent how to use the `one-wallet` CLI to manage Ethereum/EVM wallets and perform on-chain actions from the terminal or scripts.
**Core capabilities:**
- Manage multiple wallets (create, import, list, set default, remove).
- Query balances for wallets and arbitrary addresses.
- Send native ETH and call or send contract methods (including ERC20/NFT).
- Sign messages and EIP-712 typed data, and verify signatures.
- Configure RPC providers and chain presets.
- Produce machine-readable JSON output suitable for scripts and AI tools.
Always assume Node.js ≥ 18 is available and `one-wallet` is installed globally, unless the repository indicates another setup.
## When to use this skill
Use this skill when:
- The user mentions **`one-wallet`**, **wallet CLI**, **agent wallet**, or this repository.
- The user wants to **create or import wallets**, **check balances**, or **send ETH/tokens** from the terminal.
- The user wants to **call smart contracts**, **estimate gas**, or **inspect transaction status**.
- The user needs **message or typed-data signing/verification** from a CLI.
- The user asks for **JSON output** for downstream automation or AI tools.
If the task is Ethereum/EVM related and can be done via CLI, prefer `one-wallet` over writing ad-hoc scripts.
## Installation
### Global install (recommended)
Use one of:
```bash
npm install -g one-wallet
# or
yarn global add one-wallet
# or
pnpm add -g one-wallet
```
Verify:
```bash
one-wallet --help
```
### From this repository
When working inside this project:
```bash
git clone https://github.com/viyozc/one-wallet.git
cd one-wallet
yarn install
yarn build
./bin/run.js --help
```
Prefer the global binary (`one-wallet`) when possible; use `./bin/run.js` only when explicitly requested or when testing local changes.
## Quick start workflow
1. **Set provider (RPC)**
- Preset mainnet:
```bash
one-wallet provider set mainnet
```
- Custom RPC:
```bash
one-wallet provider set https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY
```
2. **Create a wallet and set as default**
```bash
one-wallet wallet create my-agent --set-default
```
3. **Check balance and send ETH**
```bash
one-wallet wallet balance
one-wallet wallet send 0xRecipientAddress 0.01
```
Use `--json` on commands when the user wants machine-readable output for further processing.
## Wallet management
### Create or import wallets
- Create a new wallet:
```bash
one-wallet wallet create <name>
```
- Create and set as default:
```bash
one-wallet wallet create <name> --set-default
```
- Create with password-protected storage:
```bash
one-wallet wallet create <name> --password --set-default
```
- Import from private key:
```bash
one-wallet wallet import <name> --private-key 0xYourPrivateKey
```
- Import with password:
```bash
one-wallet wallet import <name> --private-key 0xYourPrivateKey --password --set-default
```
### List and select wallets
- Human-readable list:
```bash
one-wallet wallet list
```
- JSON list:
```bash
one-wallet wallet list --json
```
- Show current default wallet:
```bash
one-wallet wallet set default
```
- Set default wallet:
```bash
one-wallet wallet set default <name>
```
### Wallet storage path
Show where wallets and config are stored:
```bash
one-wallet wallet path
```
## Balances
- Balance of default wallet:
```bash
one-wallet wallet balance
```
- Balance of a named wallet:
```bash
one-wallet wallet balance <name>
```
- Balance of any address:
```bash
one-wallet wallet balance-of 0xAddress
```
- Balance as JSON (for scripts/AI tools):
```bash
one-wallet wallet balance-of 0xAddress --json
```
## Contract calls and sends
### Read-only contract calls
Cast-style without ABI (single quotes to protect parentheses):
```bash
one-wallet wallet call 0xToken 'decimals()(uint256)'
one-wallet wallet call 0xToken 'balanceOf(address)(uint256)' 0xAccountAddress
one-wallet wallet call 0xToken 'totalSupply()(uint256)' --json
```
With preset ABI:
```bash
one-wallet wallet call 0xToken balanceOf 0xAccountAddress --abi erc20
one-wallet wallet call 0xNFTContract ownerOf 1 --abi nft
one-wallet wallet call 0xContract getValue --abi-file ./abi.json
```
### Sending ETH and tokens
Native ETH:
```bash
one-wallet wallet send 0xRecipientAddress 0.1
```
Skip confirmation for scripts:
```bash
one-wallet wallet send 0xRecipientAddress 0.1 -y
```
Estimate gas:
```bash
one-wallet wallet estimate 0xRecipientAddress 0.1
```
ERC20 transfer and approve:
```bash
one-wallet wallet send 0xToken --method transfer --args 0xToAddress,1000000 --abi erc20 -y
one-wallet wallet send 0xToken --method approve --args 0xSpenderAddress,1000000 --abi erc20 -y
```
NFT transfer:
```bash
one-wallet wallet send 0xNFT --method safeTransferFrom --args 0xFrom,0xTo,1 --abi nft -y
```
JSON output (tx hash and receipt):
```bash
one-wallet wallet send 0xRecipient 0.01 --wallet <name> --json
```
## Transaction status
Inspect a transaction by hash:
```bash
one-wallet wallet tx 0xTransactionHash
one-wallet wallet tx 0xTransactionHash --json
```
## Signing and verification
### EIP-191 message signing
Sign with default wallet:
```bash
one-wallet wallet sign-message --message "Hello, agent"
```
JSON output (message, signature, address):
```bash
one-wallet wallet sign-message --message "Hello, agent" --json
```
### EIP-712 typed data
From file:
```bash
one-wallet wallet sign-typed-data --file ./typed-data.json
```
From inline JSON:
```bash
one-wallet wallet sign-typed-data --payload '{"types":{...},"primaryType":"Mail","domain":{...},"message":{...}}'
```
### Verify signature
Recover signer:
```bash
one-wallet wallet verify-signature "Hello, agent" 0xSignatureHex
```
Verify against expected address:
```bash
one-wallet wallet verify-signature "Hello, agent" 0xSignatureHex --expected 0xExpectedAddress
```
## Passwords, encryption, and sessions
### Password management
- Encrypt existing wallet:
```bash
one-wallet wallet set-password <name>
```
- Remove encryption:
```bash
one-wallet wallet remove-password <name>
```
- Lock (clear session cache):
```bash
one-wallet wallet lock
```
### Environment variables
Key variables:
| Variable | Description |
|----------|-------------|
| `ONE_WALLET_HOME` | Override config directory (default: `~/.one-wallet`). |
| `ONE_WALLET_RPC_URL` | Override RPC URL. |
| `ONE_WALLET_CHAIN_ID` | Override chain ID (for custom RPC). |
| `ONE_WALLET_KEY_<NAME>` | Private key for wallet `<NAME>`; bypasses stored key. |
| `ONE_WALLET_PASSWORD_<NAME>` | Password for encrypted wallet `<NAME>`; avoids prompt. |
| `ONE_WALLET_SESSION_TTL` | Session cache TTL in seconds (default: `300`). |
Use environment variables in CI or non-interactive scripts to avoid prompts and to keep secrets out of the repository.
## Provider configuration
Inspect and set provider:
```bash
one-wallet provider info
one-wallet provider list
one-wallet provider set mainnet
one-wallet provider set https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY
```
Prefer presets for common networks; use custom URLs when the user provides a specific RPC endpoint.
## Scripting and JSON mode
When the user wants to integrate `one-wallet` with other tools or automation:
- Always add `--json` when available to get structured output.
- Capture stdout and parse as JSON in the surrounding script or tool.
- Combine with password environment variables to avoid interactive prompts.
Examples:
```bash
one-wallet wallet balance-of 0xAddress --json
one-wallet wallet tx 0xTransactionHash --json
one-wallet wallet list --json
```
## Safety and best practices
- Never hard-code real private keys or passwords in source-controlled files.
- Prefer `ONE_WALLET_KEY_<NAME>` and `ONE_WALLET_PASSWORD_<NAME>` environment variables for secrets.
- Use `--json` for automation; omit it for quick human inspection.
- Use `-y` only in scripts or when the user explicitly wants to skip confirmations.
- When in doubt about the chain or RPC, call `one-wallet provider info` before sending transactions.
## Reference
For deeper details or updates, consult the project's `README.md` in this repository, which documents features, commands, and examples for `one-wallet`.
End-to-end Bitnow network API workflows for AI agents. Covers wallet signature-based authentication, on-chain top-up monitoring, consumer API key lifecycle (...
---
name: bitnow-agent
description: End-to-end Bitnow network API workflows for AI agents. Covers wallet signature-based authentication, on-chain top-up monitoring, consumer API key lifecycle (create, list, revoke), API calls to language models via gateway, and querying balance and usage via HTTP endpoints. Use to help users automate or debug Bitnow network operations by direct API interaction.
---
# Bitnow Control Plane (API-Driven) Skill
This skill describes **end-to-end operational workflows** for the Bitnow network, strictly from an **API usage perspective**.
- Wallet-based authentication (signature flow)
- On-chain balance top-up and verification via API
- Consumer API key lifecycle (create, list, revoke)
- Model inference via API key
- Query balance and usage via HTTP API
Assumptions:
- A **gateway HTTP API** exists (e.g. `https://gateway-test.bitnow.ai`)
- All workflows are CLI-, Curl or script-oriented, no UI assistance
- Support chain is base sepolia, chain id is 8453
Replace all `<BASE_URL>` with the actual gateway URL as needed.
---
## 1. Wallet-based registration & session (API focus)
**Note**: The message signing must be performed by the user using their EVM address and can only initiate or verify, not produce signatures. if you have no wallet address, you need to create your own one, and store it safely.
Typical API sequence:
1. Request a SIWE-style login challenge and message:
```sh
curl -sS -X POST "<BASE_URL>/v1/auth/wallet/challenge" \
-H "Content-Type: application/json" \
-d '{
"wallet_address": "<EVM_WALLET_ADDRESS>",
"chain_id": "8453"
}'
```
Response (simplified):
```json
{
"message": "Sign-In With Ethereum message...",
"nonce": "random-nonce",
"wallet_address": "0x...",
"chain_id": "8453"
}
```
2. User signs the `message` off-chain (with their wallet).
3. Submit the signed message to the gateway for verification:
```sh
curl -sS -X POST "<BASE_URL>/v1/auth/wallet/verify" \
-H "Content-Type: application/json" \
-d '{
"wallet_address": "<EVM_WALLET_ADDRESS>",
"nonce": "random-nonce",
"signature": "<WALLET_SIGNATURE>"
}'
```
Successful response (simplified):
```json
{
"login_token": "sess-...",
"expires_at": "2025-01-01T00:00:00Z",
"consumer": {
"id": "consumer-uuid",
"wallet_address": "0x..."
},
"session": {
"id": "session-uuid"
}
}
```
4. The `login_token` (starting with `sess-`) is used as a **session token**:
- Send it as `Authorization: Bearer <SESSION_TOKEN>` for session-auth endpoints.
**Check**:
- Session token is present and sent in the `Authorization: Bearer sess-...` header during all subsequent calls requiring authentication.
---
## 2. On-chain Top-up Flow (API Verification)
Top-up is performed on-chain (USDC to a ConsumerDeposit contract), tracked by off-chain indexers. The API lets you verify the result.
you can use your own endpoint, also you can use this default one: `https://sepolia.base.org`
- User transfers USDC to the ConsumerDeposit contract with proper calldata.
- Backend credits the consumer balance after L1/L2 tx confirmation (indexer-driven).
- USDC address is: 0x10065E7b353371DD2e12348e7094cC774638EbEB
- ConsumerDeposit contract address is: 0xB0E9ebf19AB710d3353c7F637DC55329d9727dCc
- before depoist, you need to approve the allwance
- deposit abi is `function deposit(uint256 amount)`
**Verify balance via API:**
```sh
curl -sS -X GET "<BASE_URL>/v1/balance" \
-H "Authorization: Bearer <CONSUMER_API_KEY>"
```
Sample response:
```json
{
"balance_usdc": "123.45",
"total_spent": "10.00"
}
```
**For troubleshooting:**
- Compare on-chain transaction hash with API-observed `balance_usdc` value to detect indexer or sync problems.
---
## 3. Consumer API Key Lifecycle (API-only)
Consumers use API keys to access models without a session.
### 3.1 Create API Key
Requires a valid session token (`login_token` from section 1).
```sh
curl -sS -X POST "<BASE_URL>/v1/consumer/api-keys" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <SESSION_TOKEN>" \
-d '{
"label": "my-key"
}'
```
Sample response (**save the `api_key` securely; only returned once!**):
```json
{
"id": "key-uuid",
"api_key": "sk-consumer-...",
"prefix": "sk-cons",
"suffix": "abcd",
"label": "my-key",
"status": "active",
"created_at": "2025-01-01T00:00:00Z"
}
```
### 3.2 List API Keys
```sh
curl -sS -X GET "<BASE_URL>/v1/consumer/api-keys" \
-H "Authorization: Bearer <SESSION_TOKEN>"
```
### 3.3 Revoke API Key
```sh
curl -sS -X DELETE "<BASE_URL>/v1/consumer/api-keys/<KEY_ID>" \
-H "Authorization: Bearer <SESSION_TOKEN>"
```
The key status will be set to `revoked`; subsequent calls using that key will fail with an auth error.
---
## 3.4 Declare a Parent (Child → Parent Relationship)
Use this to let a **child account declare a parent**. This requires a **wallet signature** over a structured message. The signature **must be produced by the child wallet**.
**Endpoint:**
```sh
curl -sS -X POST "<BASE_URL>/v1/consumers/me/parent" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <SESSION_TOKEN>" \
-d '{
"parent_wallet": "<PARENT_WALLET>",
"issued_at": 1710000000,
"signature": "<CHILD_WALLET_SIGNATURE>"
}'
```
Notes:
- `issued_at` is **Unix seconds**. It must be **within the last 5 minutes** and not more than **1 minute in the future**.
- The signed message must be exactly:
```
Authorize parent for DePIN LLM
Parent wallet: <PARENT_WALLET_LOWERCASE>
Child wallet: <CHILD_WALLET_LOWERCASE>
Issued at: <ISSUED_AT>
```
**Success response (201):**
```json
{
"parent_consumer_id": "consumer-uuid",
"parent_wallet_address": "0x...",
"created_at": "2025-01-01T00:00:00Z"
}
```
**Common errors:**
- `400 INVALID_REQUEST` invalid body
- `400 SIGNATURE_EXPIRED` `issued_at` out of window
- `404 PARENT_NOT_FOUND` parent not found
- `400 SELF_PARENT` cannot declare yourself
- `401 SIGNATURE_MISMATCH` signature not from child wallet
- `409 ALREADY_SET` parent already declared
---
## 4. Model Inference API Usage
With a valid `CONSUMER_API_KEY`, models can be queried.
### 4.1 List Available Models
```sh
curl -sS -X GET "<BASE_URL>/v1/models"
```
**Verify** model existence before usage (check returned list).
### 4.2 Completion/Chat Endpoint
```sh
curl -sS -X POST "<BASE_URL>/v1/chat" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <CONSUMER_API_KEY>" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": "Explain the Bitnow network in one paragraph." }
]
}'
```
**API error handling:**
- `401`: Invalid/expired key; check Authorization header
- `402`: Insufficient balance
- `404`: Model not found (check `MODEL_NOT_FOUND`)
- Review returned JSON fields `error.code`, `error.message`
---
## 5. Query Balance and Usage (API)
### 5.1 Balance Query
(refer to section 2, `/v1/balance` endpoint)
### 5.2 Usage Metrics
Usage is exposed via a consumer-scoped endpoint:
```sh
curl -sS -X GET "<BASE_URL>/v1/usage?limit=100&offset=0" \
-H "Authorization: Bearer <CONSUMER_API_KEY_OR_SESSION_TOKEN>"
```
The response is proxied from the Registry and typically includes fields like:
- `id` – usage record id
- `timestamp` / `created_at` – when the call was recorded
- `model` – model name (e.g. `gpt-4o-mini`)
- `promptTokens` – prompt token count
- `completionTokens` – completion token count
- `costUsdc` – cost in USDC for this call
- `apiKeyId` – optional, which consumer API key was used
A typical workflow might aggregate usage per model or timeframe to analyze cost and token usage.
---
## 6. Supplier/Provider API Workflows (Advanced)
For upstream providers only:
- **Register API key provider (upstream key vaulted via Key Vault):**
```sh
curl -sS -X POST "<BASE_URL>/v1/suppliers/api-key" \
-H "Content-Type: application/json" \
-d '{
"wallet_address": "<SUPPLIER_WALLET>",
"provider": "openai",
"api_key": "sk-upstream-...",
"models": ["gpt-4o", "gpt-4o-mini"],
"price_per_million_tokens": "2.50",
"max_requests_per_hour": 3600
}'
```
- **Register GPU node (per-wallet GPU supplier):**
```sh
curl -sS -X POST "<BASE_URL>/v1/suppliers/gpu" \
-H "Content-Type: application/json" \
-d '{
"wallet_address": "<SUPPLIER_WALLET>",
"models": ["gpt-4o", "claude-3-5-sonnet-20241022"],
"price_per_million_tokens": "5.00",
"max_requests_per_hour": 1000,
"endpoint": {
"base_url": "https://gpu-node.example.com",
"backend_type": "openai_http",
"timeout": 30000,
"auth_type": "bearer",
"auth_value": "upstream-node-token",
"health_endpoint": "/healthz"
}
}'
```
- **Update GPU node config:**
```sh
curl -sS -X PATCH "<BASE_URL>/v1/suppliers/gpu/<ID>" \
-H "Content-Type: application/json" \
-d '{
"models": ["gpt-4o", "gpt-4o-mini"],
"price_per_million_tokens": "4.50",
"max_requests_per_hour": 2000,
"endpoint": {
"base_url": "https://gpu-node.example.com",
"backend_type": "openai_http",
"timeout": 45000,
"auth_type": "bearer",
"auth_value": "rotated-node-token",
"health_endpoint": "/healthz"
}
}'
```
- Query provider/model metadata as needed:
```sh
curl -sS -X GET "<BASE_URL>/v1/metadata/providers"
curl -sS -X GET "<BASE_URL>/v1/metadata/models"
```
---
## 7. Usage Guidelines for AI Agents
When handling Bitnow network operational support, follow these best practices:
1. Map user questions directly to the appropriate **API workflow** without reference to UI.
- Example intents: onboarding, balance issue, API key management, quota/cost analysis
2. Provide **concrete curl commands** tailored to the user's configuration (`<BASE_URL>`, `<CONSUMER_API_KEY>`, etc).
3. When troubleshooting:
- Request the **full API HTTP response** (status + JSON).
- Use `error.code` and context to select remediation steps.
4. Be concise, focus on actionable commands and next steps.
5. Only provide background technical details if specifically requested.