paytaca-cli 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/README.md +153 -37
- package/dist/ai/autoRefill.d.ts +27 -0
- package/dist/ai/autoRefill.d.ts.map +1 -0
- package/dist/ai/autoRefill.js +75 -0
- package/dist/ai/autoRefill.js.map +1 -0
- package/dist/ai/client.d.ts +73 -0
- package/dist/ai/client.d.ts.map +1 -0
- package/dist/ai/client.js +90 -0
- package/dist/ai/client.js.map +1 -0
- package/dist/ai/config.d.ts +7 -0
- package/dist/ai/config.d.ts.map +1 -0
- package/dist/ai/config.js +16 -0
- package/dist/ai/config.js.map +1 -0
- package/dist/ai/configure.d.ts +61 -0
- package/dist/ai/configure.d.ts.map +1 -0
- package/dist/ai/configure.js +452 -0
- package/dist/ai/configure.js.map +1 -0
- package/dist/ai/credits.d.ts +27 -0
- package/dist/ai/credits.d.ts.map +1 -0
- package/dist/ai/credits.js +99 -0
- package/dist/ai/credits.js.map +1 -0
- package/dist/ai/models.d.ts +13 -0
- package/dist/ai/models.d.ts.map +1 -0
- package/dist/ai/models.js +49 -0
- package/dist/ai/models.js.map +1 -0
- package/dist/ai/oauth.d.ts +45 -0
- package/dist/ai/oauth.d.ts.map +1 -0
- package/dist/ai/oauth.js +137 -0
- package/dist/ai/oauth.js.map +1 -0
- package/dist/ai/purchase.d.ts +30 -0
- package/dist/ai/purchase.d.ts.map +1 -0
- package/dist/ai/purchase.js +456 -0
- package/dist/ai/purchase.js.map +1 -0
- package/dist/commands/address.d.ts.map +1 -1
- package/dist/commands/address.js +88 -36
- package/dist/commands/address.js.map +1 -1
- package/dist/commands/ai.d.ts +9 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +675 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/balance.d.ts.map +1 -1
- package/dist/commands/balance.js +68 -129
- package/dist/commands/balance.js.map +1 -1
- package/dist/commands/history.d.ts.map +1 -1
- package/dist/commands/history.js +38 -78
- package/dist/commands/history.js.map +1 -1
- package/dist/commands/mcp.d.ts +14 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +68 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/pay.js +1 -1
- package/dist/commands/pay.js.map +1 -1
- package/dist/commands/receive.d.ts +1 -8
- package/dist/commands/receive.d.ts.map +1 -1
- package/dist/commands/receive.js +51 -124
- package/dist/commands/receive.js.map +1 -1
- package/dist/commands/send.d.ts +0 -10
- package/dist/commands/send.d.ts.map +1 -1
- package/dist/commands/send.js +40 -50
- package/dist/commands/send.js.map +1 -1
- package/dist/commands/swap.js +1 -1
- package/dist/commands/swap.js.map +1 -1
- package/dist/commands/token.d.ts +1 -9
- package/dist/commands/token.d.ts.map +1 -1
- package/dist/commands/token.js +192 -289
- package/dist/commands/token.js.map +1 -1
- package/dist/core/context.d.ts +30 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +45 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/wallet.d.ts +130 -0
- package/dist/core/wallet.d.ts.map +1 -0
- package/dist/core/wallet.js +276 -0
- package/dist/core/wallet.js.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +8 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +24 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +5 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +473 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/utils/format.d.ts +23 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +62 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/x402.js +1 -1
- package/dist/utils/x402.js.map +1 -1
- package/dist/wallet/index.d.ts +13 -0
- package/dist/wallet/index.d.ts.map +1 -1
- package/dist/wallet/index.js +18 -0
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/keys.d.ts.map +1 -1
- package/dist/wallet/keys.js +2 -0
- package/dist/wallet/keys.js.map +1 -1
- package/package.json +7 -3
- package/dist/commands/wallet.test.d.ts +0 -2
- package/dist/commands/wallet.test.d.ts.map +0 -1
- package/dist/commands/wallet.test.js +0 -68
- package/dist/commands/wallet.test.js.map +0 -1
- package/dist/nostr/chat.test.d.ts +0 -2
- package/dist/nostr/chat.test.d.ts.map +0 -1
- package/dist/nostr/chat.test.js +0 -121
- package/dist/nostr/chat.test.js.map +0 -1
- package/dist/nostr/store.test.d.ts +0 -2
- package/dist/nostr/store.test.d.ts.map +0 -1
- package/dist/nostr/store.test.js +0 -456
- package/dist/nostr/store.test.js.map +0 -1
- package/dist/utils/prices.test.d.ts +0 -5
- package/dist/utils/prices.test.d.ts.map +0 -1
- package/dist/utils/prices.test.js +0 -62
- package/dist/utils/prices.test.js.map +0 -1
- package/dist/utils/x402.test.d.ts +0 -2
- package/dist/utils/x402.test.d.ts.map +0 -1
- package/dist/utils/x402.test.js +0 -216
- package/dist/utils/x402.test.js.map +0 -1
- package/dist/wallet/cauldron/pools.test.d.ts +0 -3
- package/dist/wallet/cauldron/pools.test.d.ts.map +0 -1
- package/dist/wallet/cauldron/pools.test.js +0 -149
- package/dist/wallet/cauldron/pools.test.js.map +0 -1
- package/dist/wallet/cauldron/swap.test.d.ts +0 -2
- package/dist/wallet/cauldron/swap.test.d.ts.map +0 -1
- package/dist/wallet/cauldron/swap.test.js +0 -179
- package/dist/wallet/cauldron/swap.test.js.map +0 -1
- package/skills/README.md +0 -68
- package/skills/paytaca-send/SKILL.md +0 -159
- package/skills/paytaca-wallet/SKILL.md +0 -164
- package/skills/paytaca-x402/SKILL.md +0 -130
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
A command-line interface for the Paytaca [Bitcoin Cash](https://bitcoincash.org) (BCH) wallet. Built with the same core logic as the [Paytaca mobile app](https://github.com/paytaca/paytaca-app), using [watchtower-cash-js](https://github.com/paytaca/watchtower-cash-js) for transaction operations and [libauth](https://github.com/bitauth/libauth) for HD key derivation.
|
|
4
4
|
|
|
5
|
-
Bitcoin Cash is peer-to-peer electronic cash, enabling fast, low-fee transactions for everyday use. Paytaca CLI brings the full capabilities of the Paytaca wallet to the terminal — create wallets, derive addresses, send and receive BCH, manage CashTokens (fungible tokens and NFTs), and view transaction history, all from the command line.
|
|
5
|
+
Bitcoin Cash is peer-to-peer electronic cash, enabling fast, low-fee transactions for everyday use. Paytaca CLI brings the full capabilities of the Paytaca wallet to the terminal — create wallets, derive addresses, send and receive BCH, manage CashTokens (fungible tokens and NFTs), swap tokens on the Cauldron DEX, pay x402 HTTP APIs, chat over Nostr, and view transaction history, all from the command line.
|
|
6
6
|
|
|
7
|
-
Designed to be AI agent-friendly and useful for automation by power users.
|
|
7
|
+
Designed to be AI agent-friendly and useful for automation by power users. It ships an MCP server and a one-step installer for the Paytaca AI provider.
|
|
8
8
|
|
|
9
9
|
## Requirements
|
|
10
10
|
|
|
@@ -29,6 +29,8 @@ After installing, the `paytaca` command is available globally.
|
|
|
29
29
|
|
|
30
30
|
## Commands
|
|
31
31
|
|
|
32
|
+
Most commands accept `--json` for machine-readable output and `--chipnet` to target testnet (see [Network](#network)). Run `paytaca <command> --help` for the full option list.
|
|
33
|
+
|
|
32
34
|
### Wallet
|
|
33
35
|
|
|
34
36
|
```bash
|
|
@@ -111,8 +113,11 @@ paytaca token info <category> # Token metadata, balance,
|
|
|
111
113
|
paytaca token price <category> [amount] # USD price of a token and value of an amount (default: balance)
|
|
112
114
|
paytaca token send <address> <amount> --token <cat> # Send fungible tokens
|
|
113
115
|
paytaca token send-nft <address> --token <cat> --commitment <hex> # Send an NFT
|
|
116
|
+
paytaca token send-nft <address> --token <cat> --commitment '' --capability minting
|
|
114
117
|
```
|
|
115
118
|
|
|
119
|
+
`token send-nft` also accepts `--capability <none|minting|mutable>` (default `none`), and `--txid` / `--vout` to pin a specific NFT UTXO (auto-detected otherwise).
|
|
120
|
+
|
|
116
121
|
### Swap (Cauldron DEX)
|
|
117
122
|
|
|
118
123
|
```bash
|
|
@@ -122,58 +127,118 @@ paytaca swap <tokenId> <amount> --raw # Amount is in raw base units
|
|
|
122
127
|
paytaca swap <tokenId> <amount> --yes # Skip the confirmation prompt
|
|
123
128
|
```
|
|
124
129
|
|
|
125
|
-
The `--action` option is `sell` (token→BCH) or `buy` (BCH→token). Swaps run on mainnet only.
|
|
130
|
+
The `--action` option is `sell` (token→BCH) or `buy` (BCH→token). Swaps run on mainnet only; `--chipnet` is accepted but exits with an error.
|
|
126
131
|
|
|
127
132
|
### x402 Payments
|
|
128
133
|
|
|
129
|
-
The x402 protocol enables HTTP payments via BCH. Some APIs
|
|
134
|
+
The x402 protocol enables HTTP payments via BCH. Some APIs require payment to access.
|
|
130
135
|
|
|
131
136
|
```bash
|
|
132
|
-
paytaca check <url>
|
|
133
|
-
paytaca
|
|
134
|
-
paytaca pay <url>
|
|
135
|
-
paytaca pay <url> --
|
|
136
|
-
paytaca pay <url> --
|
|
137
|
-
paytaca pay <url>
|
|
137
|
+
paytaca check <url> # Check if URL requires payment, shows estimated cost
|
|
138
|
+
paytaca check <url> -X POST -d '{}' # Check a POST endpoint (-X/--method, -H/--header, -d/--body)
|
|
139
|
+
paytaca pay <url> # Make a paid HTTP request (handles 402 automatically)
|
|
140
|
+
paytaca pay <url> --json # JSON output (recommended for AI agents)
|
|
141
|
+
paytaca pay <url> --dry-run # Preview payment without executing
|
|
142
|
+
paytaca pay <url> -X POST -d '{"prompt":"hello"}'
|
|
143
|
+
paytaca pay <url> --max-amount 500 # Cap payment in sats (overrides server max)
|
|
144
|
+
paytaca pay <url> --change-address <addr> # Custom change address
|
|
145
|
+
paytaca pay <url> --payer <value> # Payer identifier (defaults to wallet index 0)
|
|
146
|
+
paytaca pay <url> --confirmed # Skip the confirmation prompt
|
|
138
147
|
```
|
|
139
148
|
|
|
140
149
|
**Example workflow:**
|
|
141
150
|
```bash
|
|
142
|
-
paytaca check https://api.
|
|
151
|
+
paytaca check https://api.example.com/v1/complete --json
|
|
143
152
|
# → {"paymentRequired": true, "estimatedCostSats": "100"}
|
|
144
153
|
|
|
145
|
-
paytaca pay https://api.
|
|
154
|
+
paytaca pay https://api.example.com/v1/complete --method POST --body '{"prompt":"hello"}'
|
|
146
155
|
# → Handles 402 → pays → returns response
|
|
147
156
|
```
|
|
148
157
|
|
|
149
|
-
### AI
|
|
158
|
+
### Paytaca AI
|
|
159
|
+
|
|
160
|
+
Paytaca AI is a pay-as-you-go model gateway paid with BCH or LIFT via x402. Manage it from the CLI:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
paytaca ai configure [harness] # Install MCP + AI provider (opencode is the default)
|
|
164
|
+
paytaca ai api-key create # Create a wallet-bound API key (shown once)
|
|
165
|
+
paytaca ai models # List available models
|
|
166
|
+
paytaca ai plans [model] # Plan pricing, optionally for a single model
|
|
167
|
+
paytaca ai credits [--model <id>] # Remaining time credits per model
|
|
168
|
+
paytaca ai usage # Per-session usage
|
|
169
|
+
paytaca ai balance # BCH + LIFT funds available for purchases
|
|
170
|
+
paytaca ai purchase --model <id> --minutes <n> # Buy a plan
|
|
171
|
+
paytaca ai purchase --model <id> --minutes 60 --lift # Pay with LIFT (discount)
|
|
172
|
+
paytaca ai auto-refill --enable --model <id> --minutes <n> --max-minutes <n>
|
|
173
|
+
paytaca ai auto-refill --status # Inspect; also --disable
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`ai configure` accepts `--backend`, `--path`, `--api-key`, `--chipnet`, and `-y/--yes`. `ai purchase` and `ai auto-refill` accept `--lift` to pay with LIFT tokens at a discount. Add `--json` to any `ai` subcommand for machine-readable output.
|
|
150
177
|
|
|
151
|
-
|
|
178
|
+
### MCP Server
|
|
179
|
+
|
|
180
|
+
Configure an AI harness in one step. This installs the Paytaca MCP server and, for opencode, also the Paytaca AI provider (model catalogue + API key) so the Paytaca AI models are usable immediately:
|
|
152
181
|
|
|
153
182
|
```bash
|
|
154
|
-
#
|
|
155
|
-
|
|
183
|
+
paytaca ai configure opencode # opencode | pi | omp
|
|
184
|
+
```
|
|
156
185
|
|
|
157
|
-
|
|
158
|
-
npx skills add paytaca/paytaca-cli --all
|
|
186
|
+
The command creates a wallet-bound API key against the Paytaca AI backend, writes the provider (base URL, models, key) and MCP server into the harness config, then checks your AI credits and offers to buy a plan when none are active.
|
|
159
187
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
188
|
+
Re-running is idempotent: an existing provider API key is reused. Then run the server over stdio:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
paytaca mcp # mainnet
|
|
192
|
+
paytaca mcp --chipnet # default MCP tools to chipnet (testnet)
|
|
164
193
|
```
|
|
165
194
|
|
|
166
|
-
**
|
|
195
|
+
**Read-only wallets:** if the active wallet cannot sign (no seed phrase in the keychain), `ai configure` asks for an API key instead of creating one. Generate it from your full wallet and hand it over:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
paytaca ai api-key create # full wallet: prints sk-pytc-… once
|
|
199
|
+
paytaca ai configure opencode --api-key sk-pytc-… # read-only wallet
|
|
200
|
+
```
|
|
167
201
|
|
|
168
|
-
|
|
169
|
-
|-------|---------|------------------|
|
|
170
|
-
| `paytaca-x402` | HTTP 402 payment handling | Yes (before payment) |
|
|
171
|
-
| `paytaca-wallet` | Balance, addresses, history, token info | No (read-only) |
|
|
172
|
-
| `paytaca-send` | Send BCH and CashTokens | Yes (before sending) |
|
|
202
|
+
Read-only wallets report credits from the shared wallet hash but can't buy plans — fund credits from the full wallet.
|
|
173
203
|
|
|
174
|
-
**
|
|
204
|
+
**MCP tools:** wallet reads (`get_balance`, `get_transactions`, `get_receiving_address`, `get_tokens`, `send`) plus Paytaca AI (`get_models`, `get_plans`, `get_credits`, `buy_plan`, `auto_refill`, `get_help`).
|
|
175
205
|
|
|
176
|
-
|
|
206
|
+
Spending tools (`send`, `buy_plan`, `auto_refill`) require host-level approval. By default MCP operates on your **main wallet** and can spend real funds.
|
|
207
|
+
|
|
208
|
+
When `get_credits` finds a model with no active session (e.g. after a `402` from the Paytaca AI provider), the result includes a `purchaseHint`. Relay `purchaseHint.message` as-is — it carries the exact copy-paste top-up command (no upsell or follow-up questions needed):
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"modelId": "deepseek/deepseek-v4.1-flash",
|
|
213
|
+
"active": false,
|
|
214
|
+
"purchaseHint": {
|
|
215
|
+
"model": "deepseek/deepseek-v4.1-flash",
|
|
216
|
+
"minutes": 15,
|
|
217
|
+
"command": "paytaca ai purchase --model deepseek/deepseek-v4.1-flash --minutes 15",
|
|
218
|
+
"message": "To keep using DeepSeek V4.1 Flash, top up by running this in a terminal:\n\n paytaca ai purchase --model deepseek/deepseek-v4.1-flash --minutes 15\n\n(Switch models with `paytaca ai plans`.)"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Nostr Chat
|
|
224
|
+
|
|
225
|
+
End-to-end encrypted Nostr chat keyed from the wallet mnemonic (HD path `m/44'/1237'/0'/0/0`; keys are derived in memory and never stored). Conversation metadata (contacts, rooms, messages) is persisted at `~/.paytaca/chat-state.json`.
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
paytaca chat identity # Show your npub and pubkey
|
|
229
|
+
paytaca chat profile # Show display name and published BCH address
|
|
230
|
+
paytaca chat contacts # List saved contacts
|
|
231
|
+
paytaca chat add-contact <npub> [name] # Add a contact
|
|
232
|
+
paytaca chat start <npub> # Start a 1:1 conversation
|
|
233
|
+
paytaca chat list # List conversations
|
|
234
|
+
paytaca chat open <room-id> --tail 20 # Show recent messages (--tail, --json)
|
|
235
|
+
paytaca chat send <room-id> <text> # Send a message
|
|
236
|
+
paytaca chat listen [--contact <npub|name>] # Subscribe to new messages (long-running)
|
|
237
|
+
paytaca chat set-display-name <name> # Publish profile name to relays (NIP-78)
|
|
238
|
+
paytaca chat set-bch-address <address> # Publish a BCH address to relays (NIP-78)
|
|
239
|
+
paytaca chat remove-display-name # Remove published name
|
|
240
|
+
paytaca chat remove-bch-address # Remove published address
|
|
241
|
+
```
|
|
177
242
|
|
|
178
243
|
## Network
|
|
179
244
|
|
|
@@ -195,6 +260,8 @@ Seed phrases are stored in the OS native keychain:
|
|
|
195
260
|
|
|
196
261
|
Powered by [@napi-rs/keyring](https://github.com/Brooooooklyn/keyring-node) (prebuilt Rust binaries, no node-gyp required).
|
|
197
262
|
|
|
263
|
+
Nostr chat keys are **not** persisted — they are re-derived from the wallet mnemonic at runtime via HD path `m/44'/1237'/0'/0/0` and held only in memory for the duration of a session. Non-secret chat metadata (contacts, rooms, messages) is written to `~/.paytaca/chat-state.json` with mode `0600`; no key material is ever written there.
|
|
264
|
+
|
|
198
265
|
## Architecture
|
|
199
266
|
|
|
200
267
|
```
|
|
@@ -210,20 +277,49 @@ src/
|
|
|
210
277
|
swap.ts Cauldron DEX swaps (sell/buy with --action)
|
|
211
278
|
pay.ts x402 BCH payment handler for HTTP requests
|
|
212
279
|
check.ts Check if URL requires x402 payment
|
|
280
|
+
ai.ts Paytaca AI (configure, api-key, models, plans, credits, purchase, auto-refill)
|
|
281
|
+
chat.ts Nostr chat (contacts, conversations, identity, listen)
|
|
282
|
+
mcp.ts `paytaca mcp` stdio entry + per-harness config templates
|
|
283
|
+
core/
|
|
284
|
+
context.ts Wallet context resolution (keychain + network), embed-safe
|
|
285
|
+
wallet.ts Render-agnostic wallet ops shared by CLI and MCP tools
|
|
286
|
+
mcp/
|
|
287
|
+
server.ts MCP server construction and stdio lifecycle
|
|
288
|
+
tools.ts MCP tool registration (wallet reads, send, Paytaca AI)
|
|
213
289
|
wallet/
|
|
214
290
|
index.ts Wallet class, mnemonic gen/import/load
|
|
215
291
|
bch.ts BchWallet (balance, send, history, CashTokens)
|
|
216
292
|
keys.ts LibauthHDWallet (HD key derivation, token addresses)
|
|
217
293
|
x402.ts X402Payer (BCH payment signing and verification)
|
|
294
|
+
cauldron/
|
|
295
|
+
api.ts Cauldron (riften indexer) REST client
|
|
296
|
+
pools.ts Pool conversions and helpers
|
|
297
|
+
swap.ts Swap orchestration: quote estimation and execution
|
|
298
|
+
transact.ts Cauldron trade transaction building
|
|
218
299
|
storage/
|
|
219
300
|
keychain.ts OS keychain wrapper (@napi-rs/keyring)
|
|
220
301
|
utils/
|
|
221
302
|
crypto.ts pubkey -> CashAddress pipeline
|
|
303
|
+
format.ts Shared display/formatting helpers
|
|
222
304
|
network.ts Watchtower URLs, derivation paths
|
|
223
305
|
prices.ts Watchtower asset-prices client (USD per token/BCH)
|
|
224
306
|
x402.ts x402 header parsing, payment requirement selection
|
|
225
307
|
types/
|
|
226
308
|
x402.ts x402 payment types (PaymentRequired, PaymentPayload, etc.)
|
|
309
|
+
ai/
|
|
310
|
+
client.ts Paytaca AI backend client (config, wallet status)
|
|
311
|
+
config.ts Backend URL, LIFT token id, ~/.paytaca paths
|
|
312
|
+
oauth.ts BCH OAuth challenge -> access token -> API key
|
|
313
|
+
models.ts Model catalogue, plan tiers, price/duration helpers
|
|
314
|
+
credits.ts Credit session lookup and summaries
|
|
315
|
+
purchase.ts Plan purchase via x402 (BCH or LIFT)
|
|
316
|
+
autoRefill.ts Auto-refill state and orchestration
|
|
317
|
+
configure.ts Harness setup (MCP + Paytaca AI provider + credits offer)
|
|
318
|
+
nostr/
|
|
319
|
+
keys.ts Nostr key derivation from wallet mnemonic (in memory)
|
|
320
|
+
chat.ts DM event building/signing (NIP-17 style)
|
|
321
|
+
relay.ts Relay connection/subscription service
|
|
322
|
+
store.ts Contact/room/message JSON store (~/.paytaca)
|
|
227
323
|
```
|
|
228
324
|
|
|
229
325
|
## Key Dependencies
|
|
@@ -232,35 +328,55 @@ src/
|
|
|
232
328
|
|---------|---------|
|
|
233
329
|
| `watchtower-cash-js` | UTXO fetching, tx building/signing/broadcasting |
|
|
234
330
|
| `@bitauth/libauth` | HD key derivation (pinned to 2.0.0-alpha.8) |
|
|
331
|
+
| `@cashlab/cauldron` | Cauldron DEX swap building |
|
|
235
332
|
| `@napi-rs/keyring` | OS-native keychain storage |
|
|
333
|
+
| `@modelcontextprotocol/sdk` | MCP server (stdio) |
|
|
236
334
|
| `bip39` | Mnemonic generation and validation |
|
|
335
|
+
| `nostr-tools` | Nostr chat events, keys, and relay transport |
|
|
336
|
+
| `js-sha256` | Hashing for key derivation and payment headers |
|
|
237
337
|
| `commander` | CLI framework |
|
|
238
338
|
| `chalk` | Terminal colors |
|
|
239
339
|
| `qrcode-terminal` | Terminal QR code rendering |
|
|
340
|
+
| `zod` | MCP tool input schemas |
|
|
240
341
|
|
|
241
342
|
## Development
|
|
242
343
|
|
|
243
344
|
```bash
|
|
244
345
|
npm run dev # Watch mode (recompile on change)
|
|
245
|
-
npm run build # One-time build
|
|
346
|
+
npm run build # One-time build (also type-checks)
|
|
347
|
+
npm test # Run the Vitest suite
|
|
246
348
|
npm run clean # Remove dist/
|
|
247
349
|
```
|
|
248
350
|
|
|
351
|
+
There is no lint script; `npm run build` is the type-check. Tests live next to sources as `*.test.ts`.
|
|
352
|
+
|
|
249
353
|
## x402 Server
|
|
250
354
|
|
|
251
|
-
A reference x402 server
|
|
355
|
+
A reference x402 server accepting BCH (the `utxo` scheme) is included for testing:
|
|
252
356
|
|
|
253
357
|
```bash
|
|
254
358
|
cd x402-server
|
|
255
359
|
npm install
|
|
256
|
-
npm run dev # Start dev server on port
|
|
360
|
+
npm run dev # Start dev server on port 3000 (npm start to run once)
|
|
257
361
|
```
|
|
258
362
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
363
|
+
Configuration via environment variables:
|
|
364
|
+
|
|
365
|
+
| Variable | Description | Default |
|
|
366
|
+
|----------|-------------|---------|
|
|
367
|
+
| `PORT` | Server port | `3000` |
|
|
368
|
+
| `BCH_NETWORK` | `mainnet` or `chipnet` | `mainnet` |
|
|
369
|
+
| `RECEIVE_ADDRESS` | BCH address to receive payments | required for real payments |
|
|
370
|
+
|
|
371
|
+
The server exposes:
|
|
372
|
+
|
|
373
|
+
| Endpoint | Cost | Description |
|
|
374
|
+
|----------|------|-------------|
|
|
375
|
+
| `GET /api/quote` | 100 sats | Random inspirational quote |
|
|
376
|
+
| `GET /api/weather` | 50 sats | Fake weather data |
|
|
377
|
+
| `GET /api/status` | 1 sat | Server status |
|
|
262
378
|
|
|
263
|
-
Useful for testing the `paytaca pay` workflow locally.
|
|
379
|
+
Useful for testing the `paytaca check` / `paytaca pay` workflow locally (see `x402-server/README.md` for the header-level protocol details).
|
|
264
380
|
|
|
265
381
|
## License
|
|
266
382
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type PaymentMethod = 'bch' | 'lift';
|
|
2
|
+
export interface AutoRefillState {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
model?: string;
|
|
5
|
+
minutes?: number;
|
|
6
|
+
maxMinutes?: number;
|
|
7
|
+
spentMinutes?: number;
|
|
8
|
+
paymentMethod?: PaymentMethod;
|
|
9
|
+
startedAt?: string;
|
|
10
|
+
lastRefillAt?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function readAutoRefillState(): AutoRefillState | null;
|
|
13
|
+
export declare function writeAutoRefillState(state: AutoRefillState): void;
|
|
14
|
+
export interface ArmAutoRefillOptions {
|
|
15
|
+
model?: string;
|
|
16
|
+
minutes?: number;
|
|
17
|
+
maxMinutes?: number;
|
|
18
|
+
paymentMethod?: PaymentMethod;
|
|
19
|
+
}
|
|
20
|
+
export declare function armAutoRefill(opts: ArmAutoRefillOptions): AutoRefillState;
|
|
21
|
+
export declare function disarmAutoRefill(): AutoRefillState;
|
|
22
|
+
export declare function remainingBudget(state: AutoRefillState | null): number | null;
|
|
23
|
+
export declare function autoRefillCanBuy(state: AutoRefillState | null, model: string, minutes: number): {
|
|
24
|
+
canBuy: boolean;
|
|
25
|
+
reason?: string;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=autoRefill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autoRefill.d.ts","sourceRoot":"","sources":["../../src/ai/autoRefill.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAA;AAE1C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,mBAAmB,IAAI,eAAe,GAAG,IAAI,CAS5D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAKjE;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,aAAa,CAAA;CAC9B;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,eAAe,CAczE;AAED,wBAAgB,gBAAgB,IAAI,eAAe,CAQlD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAG5E;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,eAAe,GAAG,IAAI,EAC7B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAwBtC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { PAYTACA_DIR, AUTO_REFILL_FILE } from './config.js';
|
|
3
|
+
export function readAutoRefillState() {
|
|
4
|
+
try {
|
|
5
|
+
const raw = fs.readFileSync(AUTO_REFILL_FILE, 'utf8');
|
|
6
|
+
const parsed = JSON.parse(raw);
|
|
7
|
+
if (!parsed || typeof parsed !== 'object')
|
|
8
|
+
return null;
|
|
9
|
+
return parsed;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function writeAutoRefillState(state) {
|
|
16
|
+
fs.mkdirSync(PAYTACA_DIR, { recursive: true, mode: 0o700 });
|
|
17
|
+
fs.writeFileSync(AUTO_REFILL_FILE, JSON.stringify(state, null, 2), {
|
|
18
|
+
mode: 0o600,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export function armAutoRefill(opts) {
|
|
22
|
+
const existing = readAutoRefillState();
|
|
23
|
+
const state = {
|
|
24
|
+
enabled: true,
|
|
25
|
+
model: opts.model ?? existing?.model,
|
|
26
|
+
minutes: opts.minutes ?? existing?.minutes,
|
|
27
|
+
maxMinutes: opts.maxMinutes ?? existing?.maxMinutes,
|
|
28
|
+
spentMinutes: existing?.spentMinutes ?? 0,
|
|
29
|
+
paymentMethod: opts.paymentMethod ?? existing?.paymentMethod ?? 'bch',
|
|
30
|
+
startedAt: new Date().toISOString(),
|
|
31
|
+
lastRefillAt: existing?.lastRefillAt,
|
|
32
|
+
};
|
|
33
|
+
writeAutoRefillState(state);
|
|
34
|
+
return state;
|
|
35
|
+
}
|
|
36
|
+
export function disarmAutoRefill() {
|
|
37
|
+
const existing = readAutoRefillState();
|
|
38
|
+
const state = {
|
|
39
|
+
...(existing || {}),
|
|
40
|
+
enabled: false,
|
|
41
|
+
};
|
|
42
|
+
writeAutoRefillState(state);
|
|
43
|
+
return state;
|
|
44
|
+
}
|
|
45
|
+
export function remainingBudget(state) {
|
|
46
|
+
if (!state || state.maxMinutes === undefined)
|
|
47
|
+
return null;
|
|
48
|
+
return Math.max(0, state.maxMinutes - (state.spentMinutes ?? 0));
|
|
49
|
+
}
|
|
50
|
+
export function autoRefillCanBuy(state, model, minutes) {
|
|
51
|
+
if (!state || !state.enabled) {
|
|
52
|
+
return { canBuy: false, reason: 'Auto-refill is not enabled.' };
|
|
53
|
+
}
|
|
54
|
+
if (state.model && state.model !== model) {
|
|
55
|
+
return {
|
|
56
|
+
canBuy: false,
|
|
57
|
+
reason: `Auto-refill is armed for ${state.model}, not ${model}.`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (state.minutes && state.minutes !== minutes) {
|
|
61
|
+
return {
|
|
62
|
+
canBuy: false,
|
|
63
|
+
reason: `Auto-refill is armed for ${state.minutes}-minute plans, not ${minutes}.`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const budget = remainingBudget(state);
|
|
67
|
+
if (budget !== null && budget < minutes) {
|
|
68
|
+
return {
|
|
69
|
+
canBuy: false,
|
|
70
|
+
reason: `Auto-refill budget exhausted (${budget} min left).`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return { canBuy: true };
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=autoRefill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autoRefill.js","sourceRoot":"","sources":["../../src/ai/autoRefill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export interface PriceTier {
|
|
2
|
+
minutes: number;
|
|
3
|
+
price_usd?: number;
|
|
4
|
+
price_php?: number;
|
|
5
|
+
price_sats: number;
|
|
6
|
+
}
|
|
7
|
+
export interface AiModelConfig {
|
|
8
|
+
id: string;
|
|
9
|
+
display_name: string;
|
|
10
|
+
price_tiers: PriceTier[];
|
|
11
|
+
}
|
|
12
|
+
export interface AiConfig {
|
|
13
|
+
models: AiModelConfig[];
|
|
14
|
+
default_model?: string;
|
|
15
|
+
default_duration_minutes?: number;
|
|
16
|
+
context_retention_hours?: number;
|
|
17
|
+
lift_payment_discount_percent?: number;
|
|
18
|
+
proxy_url?: string;
|
|
19
|
+
image_models?: unknown[];
|
|
20
|
+
}
|
|
21
|
+
export interface WalletSession {
|
|
22
|
+
model_id?: string;
|
|
23
|
+
ai_model?: string;
|
|
24
|
+
display_name?: string;
|
|
25
|
+
model_active?: boolean;
|
|
26
|
+
session_active?: boolean;
|
|
27
|
+
time_credits_seconds?: number;
|
|
28
|
+
time_used_seconds?: number;
|
|
29
|
+
time_remaining_seconds?: number;
|
|
30
|
+
token_limit?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface WalletStatus extends WalletSession {
|
|
33
|
+
sessions?: WalletSession[];
|
|
34
|
+
}
|
|
35
|
+
export interface ChatMessage {
|
|
36
|
+
role: 'system' | 'user' | 'assistant' | 'tool';
|
|
37
|
+
content: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ChatResult {
|
|
40
|
+
ok: boolean;
|
|
41
|
+
status: number;
|
|
42
|
+
statusText: string;
|
|
43
|
+
headers: Record<string, string>;
|
|
44
|
+
data: any;
|
|
45
|
+
}
|
|
46
|
+
export declare class AiApiError extends Error {
|
|
47
|
+
status?: number;
|
|
48
|
+
body?: unknown;
|
|
49
|
+
constructor(message: string, status?: number, body?: unknown);
|
|
50
|
+
}
|
|
51
|
+
export interface RequestOptions {
|
|
52
|
+
backendUrl?: string;
|
|
53
|
+
headers?: Record<string, string>;
|
|
54
|
+
timeoutMs?: number;
|
|
55
|
+
signal?: AbortSignal;
|
|
56
|
+
}
|
|
57
|
+
export declare function getConfig(opts?: RequestOptions): Promise<AiConfig>;
|
|
58
|
+
export declare function getWalletStatus(walletHash: string, opts?: RequestOptions & {
|
|
59
|
+
modelId?: string;
|
|
60
|
+
}): Promise<WalletStatus>;
|
|
61
|
+
export interface ChatRequestOptions extends RequestOptions {
|
|
62
|
+
walletHash: string;
|
|
63
|
+
body: {
|
|
64
|
+
model?: string;
|
|
65
|
+
messages: ChatMessage[];
|
|
66
|
+
stream?: boolean;
|
|
67
|
+
temperature?: number;
|
|
68
|
+
max_tokens?: number;
|
|
69
|
+
[key: string]: unknown;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export declare function chatCompletions(opts: ChatRequestOptions): Promise<ChatResult>;
|
|
73
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/ai/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { resolveBackendUrl, apiUrl } from './config.js';
|
|
2
|
+
export class AiApiError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
body;
|
|
5
|
+
constructor(message, status, body) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'AiApiError';
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.body = body;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
async function doFetch(url, init, timeoutMs) {
|
|
13
|
+
const signal = timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined;
|
|
14
|
+
return fetch(url, { ...init, signal });
|
|
15
|
+
}
|
|
16
|
+
async function parseBody(response) {
|
|
17
|
+
const text = await response.text();
|
|
18
|
+
if (!text)
|
|
19
|
+
return null;
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(text);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return text;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function headersToObject(headers) {
|
|
28
|
+
const out = {};
|
|
29
|
+
headers.forEach((value, key) => {
|
|
30
|
+
out[key] = value;
|
|
31
|
+
});
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
export async function getConfig(opts = {}) {
|
|
35
|
+
const base = resolveBackendUrl(opts.backendUrl);
|
|
36
|
+
let response;
|
|
37
|
+
try {
|
|
38
|
+
response = await doFetch(apiUrl(base, '/v1/config'), { method: 'GET', headers: opts.headers }, opts.timeoutMs ?? 15000);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
throw new AiApiError(`Backend unreachable: ${err?.message || err}`);
|
|
42
|
+
}
|
|
43
|
+
const body = await parseBody(response);
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw new AiApiError(`GET /v1/config failed (${response.status} ${response.statusText})`, response.status, body);
|
|
46
|
+
}
|
|
47
|
+
return body;
|
|
48
|
+
}
|
|
49
|
+
export async function getWalletStatus(walletHash, opts = {}) {
|
|
50
|
+
const base = resolveBackendUrl(opts.backendUrl);
|
|
51
|
+
const url = new URL(apiUrl(base, '/v1/wallet/status'));
|
|
52
|
+
if (opts.modelId)
|
|
53
|
+
url.searchParams.set('model_id', opts.modelId);
|
|
54
|
+
let response;
|
|
55
|
+
try {
|
|
56
|
+
response = await doFetch(url.toString(), {
|
|
57
|
+
method: 'GET',
|
|
58
|
+
headers: { 'X-Wallet-Hash': walletHash, ...(opts.headers || {}) },
|
|
59
|
+
}, opts.timeoutMs ?? 15000);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
throw new AiApiError(`Backend unreachable: ${err?.message || err}`);
|
|
63
|
+
}
|
|
64
|
+
const body = await parseBody(response);
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
throw new AiApiError(`GET /v1/wallet/status failed (${response.status} ${response.statusText})`, response.status, body);
|
|
67
|
+
}
|
|
68
|
+
return body;
|
|
69
|
+
}
|
|
70
|
+
export async function chatCompletions(opts) {
|
|
71
|
+
const base = resolveBackendUrl(opts.backendUrl);
|
|
72
|
+
const headers = {
|
|
73
|
+
'Content-Type': 'application/json',
|
|
74
|
+
'X-Wallet-Hash': opts.walletHash,
|
|
75
|
+
...(opts.headers || {}),
|
|
76
|
+
};
|
|
77
|
+
const response = await doFetch(apiUrl(base, '/v1/chat/completions'), {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
headers,
|
|
80
|
+
body: JSON.stringify({ stream: false, ...opts.body }),
|
|
81
|
+
}, opts.timeoutMs ?? 240000);
|
|
82
|
+
return {
|
|
83
|
+
ok: response.ok,
|
|
84
|
+
status: response.status,
|
|
85
|
+
statusText: response.statusText,
|
|
86
|
+
headers: headersToObject(response.headers),
|
|
87
|
+
data: await parseBody(response),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/ai/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const DEFAULT_BACKEND_URL = "https://api.paytaca.ai";
|
|
2
|
+
export declare const LIFT_TOKEN_ID = "5932b2fd4915d6a75d3ec53282cd49118149a2176ee67ed68b1111ff0786f7fc";
|
|
3
|
+
export declare const PAYTACA_DIR: string;
|
|
4
|
+
export declare const AUTO_REFILL_FILE: string;
|
|
5
|
+
export declare function resolveBackendUrl(explicit?: string): string;
|
|
6
|
+
export declare function apiUrl(baseUrl: string, apiPath: string): string;
|
|
7
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/ai/config.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,mBAAmB,2BAA2B,CAAA;AAE3D,eAAO,MAAM,aAAa,qEAC0C,CAAA;AAEpE,eAAO,MAAM,WAAW,QAAsC,CAAA;AAC9D,eAAO,MAAM,gBAAgB,QAA6C,CAAA;AAE1E,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAI/D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
export const DEFAULT_BACKEND_URL = 'https://api.paytaca.ai';
|
|
4
|
+
export const LIFT_TOKEN_ID = '5932b2fd4915d6a75d3ec53282cd49118149a2176ee67ed68b1111ff0786f7fc';
|
|
5
|
+
export const PAYTACA_DIR = path.join(os.homedir(), '.paytaca');
|
|
6
|
+
export const AUTO_REFILL_FILE = path.join(PAYTACA_DIR, 'auto-refill.json');
|
|
7
|
+
export function resolveBackendUrl(explicit) {
|
|
8
|
+
const url = explicit || process.env.PAYTACA_BACKEND_URL || DEFAULT_BACKEND_URL;
|
|
9
|
+
return url.replace(/\/+$/, '');
|
|
10
|
+
}
|
|
11
|
+
export function apiUrl(baseUrl, apiPath) {
|
|
12
|
+
const normalized = baseUrl.replace(/\/+$/, '');
|
|
13
|
+
const suffix = apiPath.startsWith('/') ? apiPath : `/${apiPath}`;
|
|
14
|
+
return `${normalized}${suffix}`;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/ai/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,MAAM,CAAC,MAAM,mBAAmB,GAAG,wBAAwB,CAAA;AAE3D,MAAM,CAAC,MAAM,aAAa,GACxB,kEAAkE,CAAA;AAEpE,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAA;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAA;AAE1E,MAAM,UAAU,iBAAiB,CAAC,QAAiB;IACjD,MAAM,GAAG,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,mBAAmB,CAAA;IAC9E,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;AAChC,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,OAAe,EAAE,OAAe;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAA;IAChE,OAAO,GAAG,UAAU,GAAG,MAAM,EAAE,CAAA;AACjC,CAAC"}
|