@subly_fi/pay 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SublyFi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,73 +1,110 @@
1
1
  # @subly_fi/pay
2
2
 
3
- Subly client for [x402](https://x402.org)-style HTTP payments funded by
4
- **Kamino vault yield** — your agent pays for paywalled APIs from the yield on
5
- deposited USDC, and the principal is never spent. Non-custodial: it signs
6
- locally with your own Solana key; Subly never holds it.
7
-
8
- Current payments target standard x402 sellers that offer a Solana USDC `exact`
9
- rail with facilitator `extra.feePayer` support.
10
-
11
- Ships one `pay` dispatcher bin with subcommands, all runnable with `npx` (no clone):
12
-
13
- - `pay mcp` — an MCP server (Claude Code, Cursor, any MCP client) exposing
14
- the full lifecycle as tools: `create_subly_setup_link` /
15
- `check_subly_setup` (owner onboarding: the human approves the spending
16
- mandate + first deposit with one Face ID), `deposit_to_subly_vault`,
17
- `get_subly_yield_budget`, `fetch_with_subly_payment`,
18
- `withdraw_from_subly_vault`. Payments above the owner's approval
19
- threshold, deposits, and (when the mandate opts in) withdrawals return an
20
- `approveUrl` to paste into chat; retry with the `approvalId` once the
21
- human approved.
22
- - `pay fetch <url> [maxAmountRawUsdc] [apr_<approvalId>]` — one-shot: pay for
23
- a URL, print the receipt (used by the OpenClaw skill); retry with the
24
- `apr_...` id after an `approval_required` refusal
25
- - `pay deposit <amountRawUsdc> [apr_...]` / `pay withdraw <amountRawUsdc>
26
- [apr_...]` — vault deposit / withdraw with the same owner-approval flow
27
- - `pay setup-link [--initial-deposit <raw>] [--approval-threshold <raw>] ...`
28
- / `pay setup-status <sessionId>` — owner onboarding for CLI/skill harnesses
29
- (same flow as the MCP setup tools)
30
-
31
- ## Wallet
32
-
33
- Subly does not create wallets — bring your own Solana keypair:
3
+ CLI and stdio MCP client for paying compatible x402 APIs with Kamino USDC vault yield on Solana. MIT licensed. Works with your own [Subly relayer](https://github.com/SublyFi/subly-payment-protocol/tree/main/deploy); no Subly account is required.
34
4
 
35
- ```bash
36
- solana-keygen new --no-bip39-passphrase -o ~/.subly/agent.json
37
- export SUBLY_DEMO_AGENT_KEYPAIR_PATH=~/.subly/agent.json
38
- ```
5
+ Version 0.7 is beta software and has not had an external security audit. Vault operations use real mainnet funds. Yield accounting and owner policies depend on your relayer operator. Read the [security model](https://github.com/SublyFi/subly-payment-protocol/blob/main/docs/security-model.md).
6
+
7
+ ## Quick start
39
8
 
40
- Send USDC (Solana mainnet) to the printed address no SOL needed, fees are
41
- sponsored — then deposit (vault minimum is just over 1 USDC: share rounding
42
- refuses exactly 1.000000; deposit self-registers the wallet):
9
+ You need **Node.js 24+**, a Solana agent wallet with mainnet USDC, a trusted relayer URL, and a mainnet RPC endpoint that supports transaction simulation with inner instructions. Your wallet can be a local keypair or a supported custody signer. The owner who approves spending controls can use a passkey or a separate Solana wallet.
43
10
 
44
11
  ```bash
45
- npx -y @subly_fi/pay deposit 1010000 # 1.01 USDC
12
+ npx -y @subly_fi/pay@0.7.0 --help
13
+ export SUBLY_RELAYER_URL=https://your-relayer.example.com
14
+ export SOLANA_RPC_URL=https://your-mainnet-rpc.example.com
15
+ export SUBLY_DEMO_AGENT_KEYPAIR_PATH=/absolute/path/to/agent.json
16
+ npx -y @subly_fi/pay@0.7.0 doctor
17
+ npx -y @subly_fi/pay@0.7.0 vaults
46
18
  ```
47
19
 
48
- ## Use it
20
+ Use an existing dedicated agent wallet, or create one with `solana-keygen new -o agent.json`. Keep its recovery material private and restrict the file to its owner (`chmod 600 agent.json`). Fund its public address with **USDC on Solana mainnet**. Subly does not create or fund wallets. Vault fees require a funded relayer sponsor; the final API payment requires the seller's facilitator fee payer.
49
21
 
50
- ```bash
51
- # Claude Code (no clone):
52
- claude mcp add subly -- npx -y @subly_fi/pay mcp
22
+ 1. Review the selected vault, its curator, fees and liquidity. For a catalogue supplied by your operator, install the reviewed file locally and set `SUBLY_VAULTS_FILE=/absolute/path/vaults.json`. `SUBLY_VAULT_ADDRESS` selects one listed vault for CLI commands. Never install transaction trust anchors merely because a remote response says to.
23
+ 2. Create an owner setup link. This example pre-approves a **1.01 USDC** deposit; the selected vault's minimum can differ:
24
+
25
+ ```bash
26
+ npx -y @subly_fi/pay@0.7.0 setup-link --initial-deposit 1010000
27
+ ```
28
+
29
+ Open the returned `setupUrl`, review the wallet, vault and limits, then approve with your passkey or wallet. Links expire in 10 minutes. Treat setup and approval links as private capabilities. The first person completing an initial setup becomes the owner for that wallet/vault.
30
+ 3. Check completion and deposit promptly; initial deposit approval lasts about 15 minutes:
31
+
32
+ ```bash
33
+ npx -y @subly_fi/pay@0.7.0 setup-status <sessionId>
34
+ npx -y @subly_fi/pay@0.7.0 deposit 1010000
35
+ npx -y @subly_fi/pay@0.7.0 budget
36
+ ```
37
+
38
+ 4. Wait until **spendable yield** covers the price and vault fees. A new deposit does not immediately provide a payment budget. Then request a compatible API:
39
+
40
+ ```bash
41
+ npx -y @subly_fi/pay@0.7.0 fetch https://seller.example.com/paid-resource
42
+ ```
43
+
44
+ 5. Withdraw funds back to the same agent wallet when needed:
45
+
46
+ ```bash
47
+ npx -y @subly_fi/pay@0.7.0 withdraw 1000000
48
+ ```
49
+
50
+ All amounts are raw USDC integers: `1000000` = 1 USDC. `fetch` defaults to a **0.01 USDC cap**, configurable with `SUBLY_MCP_MAX_AMOUNT_RAW_USDC` or `fetch <URL> <capRawUSDC>`. The owner mandate may set stricter limits. `setup-link --help` lists policy options. A withdrawal can include principal and is subject to liquidity, fees and the owner's policy. A revoked mandate also blocks relayer withdrawals.
53
51
 
54
- # One-shot pay (also what the OpenClaw skill calls):
55
- npx -y @subly_fi/pay fetch https://seller.example.com/api/premium
52
+ A subsequent deposit/payment/withdrawal may return `approvalRequired` with an `approveUrl`. After the owner approves, retry the same operation with the returned `apr_...` as a trailing argument. Never automatically retry a transaction reported as submitted or an API payment with an unknown outcome.
53
+
54
+ ## MCP configuration
55
+
56
+ Add this to the MCP configuration of your editor or agent host. Replace all example values with your own absolute paths and endpoints. Pinning the version keeps upgrades explicit.
57
+
58
+ ```json
59
+ {
60
+ "mcpServers": {
61
+ "subly": {
62
+ "command": "npx",
63
+ "args": ["-y", "@subly_fi/pay@0.7.0", "mcp"],
64
+ "env": {
65
+ "SUBLY_RELAYER_URL": "https://your-relayer.example.com",
66
+ "SOLANA_RPC_URL": "https://your-mainnet-rpc.example.com",
67
+ "SUBLY_DEMO_AGENT_KEYPAIR_PATH": "/absolute/path/to/agent.json",
68
+ "SUBLY_MCP_STATE_PATH": "/absolute/path/to/subly-pending.json",
69
+ "SUBLY_MCP_MAX_AMOUNT_RAW_USDC": "10000"
70
+ }
71
+ }
72
+ }
73
+ }
56
74
  ```
57
75
 
58
- ## Environment
59
-
60
- | Var | Required | Default |
61
- |---|---|---|
62
- | `SUBLY_DEMO_AGENT_KEYPAIR_PATH` | yes (or `SUBLY_DEMO_AGENT_KEYPAIR` base58) | — |
63
- | `SUBLY_RELAYER_URL` | no | `https://api.demo.sublyfi.com` |
64
- | `SOLANA_RPC_URL` | no | public mainnet RPC |
65
- | `SUBLY_MCP_MAX_AMOUNT_RAW_USDC` | no | `10000` (0.01 USDC) per-payment cap |
66
-
67
- Requests authenticate with a signature from your wallet key there is no API
68
- token. `SUBLY_FACILITATOR_URL` is still accepted as a legacy fallback for
69
- `SUBLY_RELAYER_URL`. Spending is bounded twice: the client cap, and the
70
- relayer's server-side guard that refuses to realize anything beyond the
71
- spendable yield the deposited principal is never touched by a payment.
72
- (A plain `pay withdraw` is the exit path and may of course move principal
73
- back to your wallet.)
76
+ Tools: `list_subly_vaults`, `select_subly_vault`, `create_subly_setup_link`, `check_subly_setup`, `deposit_to_subly_vault`, `get_subly_yield_budget`, `withdraw_from_subly_vault`, `fetch_with_subly_payment`. Ask the agent to list vaults and follow owner setup before depositing. Each selected vault has its own mandate and accounting; changing selection never moves funds. Stdio stdout is reserved for MCP messages.
77
+
78
+ ## Configuration
79
+
80
+ | Variable | Meaning |
81
+ | --- | --- |
82
+ | `SUBLY_RELAYER_URL` | Chosen operator's HTTPS URL. Set explicitly; the historical demo fallback has no availability promise. |
83
+ | `SOLANA_RPC_URL` | Your trusted mainnet RPC; fallback is the rate-limited public mainnet RPC. Used to verify lookup tables and simulate withdrawals before signing. |
84
+ | `SUBLY_DEMO_AGENT_KEYPAIR_PATH` | Local Solana 64-byte JSON keypair; the historical `DEMO` name also applies in production. |
85
+ | `SUBLY_DEMO_AGENT_KEYPAIR` | Alternative base58 64-byte secret; if set, takes precedence over the file. Avoid putting secrets in shell history. |
86
+ | `SUBLY_SIGNER_PROVIDER` | `local` (default), `circle` or `privy`. |
87
+ | `SUBLY_VAULTS_FILE` | Reviewed local vault catalogue. Without it, the built-in vault is used. |
88
+ | `SUBLY_VAULT_ADDRESS` | Selected catalogue entry (or custom single-vault address with matching share mint/farm settings). |
89
+ | `SUBLY_MCP_MAX_AMOUNT_RAW_USDC` | Client payment cap; default `10000`. |
90
+ | `SUBLY_MCP_STATE_PATH` | Persistent pending-payment file. Default `~/.subly/standard-x402-pending.json`. Use one shared file for all clients paying from the same wallet. |
91
+ | `SUBLY_PAY_METHOD` / `SUBLY_PAY_BODY` | Optional HTTP method and body for CLI `fetch`; MCP accepts these as tool arguments. |
92
+
93
+ For Circle configure `CIRCLE_API_KEY`, `CIRCLE_ENTITY_SECRET`, `CIRCLE_WALLET_ID`. For Privy use `PRIVY_APP_ID`, `PRIVY_APP_SECRET`, `PRIVY_WALLET_ID`, and `PRIVY_AUTHORIZATION_KEY` when required by wallet ownership. Each accepts a `SUBLY_` prefix which takes precedence. See [provider details](https://github.com/SublyFi/subly-payment-protocol/blob/main/docs/agent-wallet-providers.md).
94
+
95
+ Only sellers offering **Solana mainnet USDC `exact`** with `extra.feePayer` are supported. EVM, unsupported tokens and unsponsored rails are refused. A supported seller does not need a Subly integration. Yield realization and x402 payment are separate transactions: if the payment fails after realization, USDC may remain in the agent wallet.
96
+
97
+ ## Recovery and troubleshooting
98
+
99
+ - `doctor` performs read-only configuration, relayer/vault and RPC checks. It never signs or transacts; it does not prove vault safety or available yield.
100
+ - A withdrawal preview failure is a refusal to sign. Check your RPC's simulation support and liquidity; do not disable transaction validation.
101
+ - Preserve the pending-state JSON across restarts and upgrades. An `external_outcome_unknown` record blocks a second payment until you investigate the seller/facilitator outcome.
102
+ - Concurrent clients using the same state file serialize payments with a `.lock` file. After a crash, stop **all** clients using that file before removing only the stale `.lock`. Preserve the JSON. A new file or another machine cannot coordinate with the old one.
103
+ - `submitted` means the transaction may still confirm. Poll the original intent ID / transaction instead of preparing another deposit or withdrawal.
104
+ - Setup passkeys bind to the operator's domain. Use the original domain and device credential; follow the documented recovery delay if access is lost.
105
+
106
+ [Full troubleshooting](https://github.com/SublyFi/subly-payment-protocol/blob/main/docs/troubleshooting.md) · [Support](https://github.com/SublyFi/subly-payment-protocol/blob/main/SUPPORT.md) · [Private security reports](https://github.com/SublyFi/subly-payment-protocol/security/advisories/new)
107
+
108
+ ## Build from source
109
+
110
+ In the repository root: `npm ci`, then `npm ci --prefix packages/pay` and `npm run check --prefix packages/pay`. `npm run test:package` verifies a packed installation from outside the checkout, including the MCP handshake. The published package contains the client only; it does not include the relayer or Kamino server SDK.