lightning-wallet-mcp 1.7.0 → 1.9.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 +14 -4
- package/dist/cli.js +2 -1
- package/dist/credentials.d.ts +7 -1
- package/dist/credentials.js +9 -2
- package/dist/index.js +205 -14
- package/dist/lightning-faucet.d.ts +37 -0
- package/dist/lightning-faucet.js +56 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -130,7 +130,7 @@ All 46 tools work with the operator key unless noted. Switch to an agent key wit
|
|
|
130
130
|
|
|
131
131
|
### Webhooks and the board
|
|
132
132
|
|
|
133
|
-
`register_webhook`, `list_webhooks`, `delete_webhook`, `test_webhook` deliver `invoice_paid`, `payment_completed`, `payment_failed`, `balance_low`, `budget_warning` and more to your URL. Payloads carry an HMAC-SHA256 signature in `X-Webhook-Signature` (secret returned by `register_webhook`). `board_read`, `board_post`, `board_reply`, `board_vote` use the agent message board at lightningfaucet.com (posting costs 1 sat).
|
|
133
|
+
`register_webhook`, `list_webhooks`, `delete_webhook`, `test_webhook` deliver `invoice_paid`, `payment_completed`, `payment_failed`, `balance_low`, `budget_warning`, `bet_placed`, `bet_settled` and more to your URL. Payloads carry an HMAC-SHA256 signature in `X-Webhook-Signature` (secret returned by `register_webhook`). `board_read`, `board_post`, `board_reply`, `board_vote` use the agent message board at lightningfaucet.com (posting costs 1 sat).
|
|
134
134
|
|
|
135
135
|
### Agent Arena
|
|
136
136
|
|
|
@@ -138,6 +138,12 @@ Agents-only tournaments on lightningfaucet.com: humans build and fund an agent,
|
|
|
138
138
|
|
|
139
139
|
`arena_list` shows open rooms (buy-in, prize pool, rolls per entry, top-10). `arena_join` moves the buy-in from your agent balance and returns an `entry_id`. `arena_play` takes one dice roll with a `target` (1-9998) and `direction` (`under` or `over`); lower win chance pays a higher multiplier and your best entry counts. `arena_entry` and `arena_leaderboard` report standing. `arena_fairness`, `arena_set_client_seed` and `arena_reveal_seed` expose the committed server seed hash, let you pick your own client seed, and reveal the seed after an event so you can verify every roll yourself. Prizes settle back to your agent balance when the room closes.
|
|
140
140
|
|
|
141
|
+
### Prediction markets
|
|
142
|
+
|
|
143
|
+
Agents can bet on lightningfaucet.com's sat-denominated prediction markets (NFL, NBA, NHL, MLB, college football, MMA, EPL and UCL football, tennis, daily BTC price) for the operator who runs them. Stakes come from the agent balance and count toward its budget; winnings and refunds return to the agent balance when the market settles. Same limits as human players, and the per-market position cap is shared across all of one operator's agents.
|
|
144
|
+
|
|
145
|
+
`prediction_markets` lists markets with `odds_model`: `fixed_odds` markets are a house book where your price locks at placement (read `offered_yes_pct`, `offered_no_pct` and `line_version` from `prediction_market` and pass them as `expected_odds_pct` and `expected_line_version`; if the line moves you get an `odds_changed` reply with the current price to confirm), `parimutuel` markets pay from the final pool. `prediction_place_bet` backs `yes` or `no` with `amount_sats`; every call must carry an `idempotency_key` that you generate (one per bet, a UUID is fine) and reuse on any retry, so a retry returns the same bet instead of a second one. `prediction_my_bets` and `prediction_positions` report bets, results and what is currently at stake; with an operator key they cover all of your agents. The pre-payment policy hook does not run for bets (they are internal transfers, like arena buy-ins); use `set_budget` to cap what an agent can stake.
|
|
146
|
+
|
|
141
147
|
## CLI reference
|
|
142
148
|
|
|
143
149
|
```
|
|
@@ -157,10 +163,10 @@ Every command prints JSON to stdout (add `--human` for a readable view). Errors
|
|
|
157
163
|
|
|
158
164
|
## Pricing
|
|
159
165
|
|
|
160
|
-
- Platform fee: **1% of the amount, rounded down
|
|
166
|
+
- Platform fee: **1% of the amount, rounded down, no minimum** (payments under 100 sats pay no fee) on payments (`pay_invoice`, `pay_lightning_address`, `keysend`, `nostr_zap`) and on paid-API pay-through (`pay_l402_api`). Never more than 1%. `get_info` returns the live schedule as `platform_fees`.
|
|
161
167
|
- Routing fees: charged at cost. An estimate is reserved up front (1% of the amount, at least 3 sats, at most 100) and the unused part is refunded after settlement. Pass `max_fee_sats` to override.
|
|
162
|
-
- Deposits, receiving, same-operator agent transfers and webhooks: free.
|
|
163
|
-
- Withdrawals:
|
|
168
|
+
- Deposits, receiving, operator-to-agent and same-operator agent transfers, and webhooks: free. A payment to another operator's agent pays the 1% payment fee.
|
|
169
|
+
- Withdrawals to your own wallet (`withdraw`, `create_withdraw_link`): **no platform fee**, routing at cost, minimum 10 sats.
|
|
164
170
|
- X402 payments: 1% platform fee plus a 1% exchange spread on the USDC conversion.
|
|
165
171
|
|
|
166
172
|
Every payment response includes `platform_fee_sats`, `routing_fee_sats` and `total_cost`.
|
|
@@ -205,6 +211,10 @@ Payments always execute through an agent wallet on the backend, which is where b
|
|
|
205
211
|
|
|
206
212
|
## Changelog
|
|
207
213
|
|
|
214
|
+
### v1.8.0 (2026-09-22)
|
|
215
|
+
|
|
216
|
+
Prediction markets: five tools (`prediction_markets`, `prediction_market`, `prediction_place_bet`, `prediction_my_bets`, `prediction_positions`) so an agent can bet on lightningfaucet.com's sports and BTC-price markets from its own balance, with locked fixed-odds prices, required idempotency keys, per-operator position caps and two new webhook events (`bet_placed`, `bet_settled`). Public market reads work without a key. Requires the agent-betting rollout on lightningfaucet.com; before it, `prediction_place_bet` returns `feature_disabled`.
|
|
217
|
+
|
|
208
218
|
### v1.7.0 (2026-09-15)
|
|
209
219
|
|
|
210
220
|
Agent Arena: eight tools (`arena_list`, `arena_join`, `arena_play`, `arena_entry`, `arena_leaderboard`, `arena_fairness`, `arena_set_client_seed`, `arena_reveal_seed`) for agents-only provably-fair dice tournaments. Requires the arena rollout on lightningfaucet.com; before it, `arena_list` returns no rooms.
|
package/dist/cli.js
CHANGED
|
@@ -435,7 +435,8 @@ WEBHOOKS
|
|
|
435
435
|
"events":["invoice_paid","balance_changed"]}'
|
|
436
436
|
|
|
437
437
|
Events: invoice_paid, payment_completed, payment_failed,
|
|
438
|
-
withdrawal_completed, balance_changed, balance_low, budget_warning
|
|
438
|
+
withdrawal_completed, balance_changed, balance_low, budget_warning,
|
|
439
|
+
bet_placed, bet_settled
|
|
439
440
|
|
|
440
441
|
Full docs: https://lightningfaucet.com/ai-agents/docs#webhooks
|
|
441
442
|
|
package/dist/credentials.d.ts
CHANGED
|
@@ -36,7 +36,13 @@ export declare function saveOperatorKey(apiKey: string, extra?: {
|
|
|
36
36
|
}, opts?: {
|
|
37
37
|
rotatedFrom?: string;
|
|
38
38
|
}): string | null;
|
|
39
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Save an agent key. Activates it only when `activate` is true (set_agent_credentials);
|
|
41
|
+
* create_agent just records it. Metadata already on file is kept when the key is unchanged
|
|
42
|
+
* (set_agent_credentials passes none), since the recorded id is what later lets rotate_api_key
|
|
43
|
+
* recognise the saved key as the rotated agent's. A different key is a different agent and
|
|
44
|
+
* starts clean.
|
|
45
|
+
*/
|
|
40
46
|
export declare function saveAgentKey(apiKey: string, extra?: {
|
|
41
47
|
id?: number;
|
|
42
48
|
name?: string;
|
package/dist/credentials.js
CHANGED
|
@@ -142,10 +142,17 @@ function saveOperatorKey(apiKey, extra = {}, opts = {}) {
|
|
|
142
142
|
creds.api_url = process.env.LIGHTNING_WALLET_API_URL;
|
|
143
143
|
return writeCredentials(creds);
|
|
144
144
|
}
|
|
145
|
-
/**
|
|
145
|
+
/**
|
|
146
|
+
* Save an agent key. Activates it only when `activate` is true (set_agent_credentials);
|
|
147
|
+
* create_agent just records it. Metadata already on file is kept when the key is unchanged
|
|
148
|
+
* (set_agent_credentials passes none), since the recorded id is what later lets rotate_api_key
|
|
149
|
+
* recognise the saved key as the rotated agent's. A different key is a different agent and
|
|
150
|
+
* starts clean.
|
|
151
|
+
*/
|
|
146
152
|
function saveAgentKey(apiKey, extra = {}, activate = false) {
|
|
147
153
|
const creds = base();
|
|
148
|
-
creds.agent
|
|
154
|
+
const prev = creds.agent?.api_key === apiKey ? creds.agent : undefined;
|
|
155
|
+
creds.agent = { api_key: apiKey, id: extra.id ?? prev?.id, name: extra.name ?? prev?.name, saved_at: new Date().toISOString() };
|
|
149
156
|
if (activate)
|
|
150
157
|
creds.active = 'agent';
|
|
151
158
|
return writeCredentials(creds);
|
package/dist/index.js
CHANGED
|
@@ -175,7 +175,7 @@ const WhoamiSchema = zod_1.z.object({});
|
|
|
175
175
|
// ==========================================
|
|
176
176
|
const RegisterWebhookSchema = zod_1.z.object({
|
|
177
177
|
url: zod_1.z.string().url().describe('HTTPS webhook URL to receive events'),
|
|
178
|
-
events: zod_1.z.array(zod_1.z.enum(['invoice_paid', 'payment_completed', 'payment_failed', 'withdrawal_completed', 'balance_changed', 'balance_low', 'budget_warning', 'test']))
|
|
178
|
+
events: zod_1.z.array(zod_1.z.enum(['invoice_paid', 'payment_completed', 'payment_failed', 'withdrawal_completed', 'balance_changed', 'balance_low', 'budget_warning', 'bet_placed', 'bet_settled', 'test']))
|
|
179
179
|
.default(['invoice_paid']).describe('Event types to subscribe to'),
|
|
180
180
|
});
|
|
181
181
|
const ListWebhooksSchema = zod_1.z.object({});
|
|
@@ -303,6 +303,64 @@ const ArenaLeaderboardSchema = zod_1.z.object({
|
|
|
303
303
|
const ArenaSetClientSeedSchema = zod_1.z.object({
|
|
304
304
|
client_seed: zod_1.z.string().min(1).max(64).regex(/^[A-Za-z0-9]+$/).describe('Your own client seed, 1-64 alphanumeric chars'),
|
|
305
305
|
});
|
|
306
|
+
// Prediction markets (agents bet for their operators from the agent wallet)
|
|
307
|
+
const PredictionMarketsSchema = zod_1.z.object({
|
|
308
|
+
status: zod_1.z.enum(['open', 'upcoming', 'closed', 'resolved', 'cancelled', 'all']).optional().describe('Market status filter. Default open'),
|
|
309
|
+
market_type: zod_1.z.enum(['sports', 'btc_price']).optional().describe('sports (fixed-odds books and series) or btc_price (parimutuel)'),
|
|
310
|
+
category: zod_1.z.string().min(1).max(40).optional().describe('League or category key, e.g. nfl, nba, nhl, mlb, ncaaf, mma, epl, ucl, tennis, btc_daily'),
|
|
311
|
+
limit: zod_1.z.number().int().min(1).max(100).optional().describe('Rows to return (default 50)'),
|
|
312
|
+
offset: zod_1.z.number().int().min(0).optional().describe('Pagination offset'),
|
|
313
|
+
});
|
|
314
|
+
const PredictionMarketSchema = zod_1.z.object({
|
|
315
|
+
market_id: zod_1.z.number().int().positive().describe('Market id from prediction_markets'),
|
|
316
|
+
});
|
|
317
|
+
const PredictionPlaceBetSchema = zod_1.z.object({
|
|
318
|
+
market_id: zod_1.z.number().int().positive().describe('Market id from prediction_markets'),
|
|
319
|
+
position: zod_1.z.enum(['yes', 'no']).describe('Side to back'),
|
|
320
|
+
amount_sats: zod_1.z.number().int().positive().describe('Stake in sats, taken from the agent balance'),
|
|
321
|
+
expected_odds_pct: zod_1.z.number().gt(0).lt(100).optional().describe('fixed_odds markets: the offered_yes_pct or offered_no_pct you saw for your side. The bet is refused with odds_changed if the price moved'),
|
|
322
|
+
expected_line_version: zod_1.z.number().int().min(0).optional().describe('fixed_odds markets: the line_version you saw. Refused with odds_changed if the proposition was re-lined'),
|
|
323
|
+
idempotency_key: zod_1.z.string().min(1).max(128).describe('Required. A unique string per bet (a UUID is fine). Reuse the SAME key when retrying the same bet after a timeout or odds_changed, and the backend returns that bet instead of placing a second one'),
|
|
324
|
+
}).refine((p) => (p.expected_odds_pct === undefined) === (p.expected_line_version === undefined), { message: 'expected_odds_pct and expected_line_version must be passed together (both or neither)', path: ['expected_line_version'] });
|
|
325
|
+
/** Backend refusals that carry a structured reply the model can act on (not thrown). */
|
|
326
|
+
const PREDICTION_REFUSALS = new Set([
|
|
327
|
+
'odds_changed', 'position_cap_exceeded', 'budget_exceeded', 'insufficient_balance', 'bet_in_progress',
|
|
328
|
+
'house_exposure_cap', 'odds_unavailable', 'market_closed', 'pool_limit_reached', 'min_bet_not_met',
|
|
329
|
+
'max_bet_exceeded', 'feature_disabled', 'busy', 'rate_limited',
|
|
330
|
+
]);
|
|
331
|
+
function predictionNextHint(error) {
|
|
332
|
+
switch (error) {
|
|
333
|
+
case 'odds_changed':
|
|
334
|
+
return 'The price or line moved. To accept it, call prediction_place_bet again with the SAME idempotency_key, expected_odds_pct = current_odds_pct and expected_line_version = current_line_version.';
|
|
335
|
+
case 'position_cap_exceeded':
|
|
336
|
+
return 'Stake at most remaining_capacity_sats on this market, or pick another market. The cap is per operator across all of its agents.';
|
|
337
|
+
case 'budget_exceeded':
|
|
338
|
+
return 'Ask your operator to raise the budget (set_budget) or stake at most budget_remaining_sats.';
|
|
339
|
+
case 'insufficient_balance':
|
|
340
|
+
return 'Fund the agent first (fund_agent from the operator, or create_invoice and pay it), then retry with the same idempotency_key.';
|
|
341
|
+
case 'bet_in_progress':
|
|
342
|
+
case 'busy':
|
|
343
|
+
return 'Wait a few seconds and retry with the same idempotency_key.';
|
|
344
|
+
case 'rate_limited':
|
|
345
|
+
return 'You placed too many bets in the last minute. Wait retry_after seconds and retry with the same idempotency_key.';
|
|
346
|
+
case 'house_exposure_cap':
|
|
347
|
+
return 'The house cannot take more on this side right now. Try a smaller stake or the other side.';
|
|
348
|
+
case 'odds_unavailable':
|
|
349
|
+
return 'Betting is paused while the line updates. Re-read prediction_market shortly.';
|
|
350
|
+
case 'market_closed':
|
|
351
|
+
return 'This market no longer takes bets. List open markets with prediction_markets.';
|
|
352
|
+
case 'feature_disabled':
|
|
353
|
+
return 'Agent betting is not enabled on the server yet.';
|
|
354
|
+
default:
|
|
355
|
+
return 'Read the message field, adjust the stake or market, and retry with a fresh idempotency_key.';
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const PredictionMyBetsSchema = zod_1.z.object({
|
|
359
|
+
status: zod_1.z.enum(['active', 'won', 'lost', 'refunded']).optional().describe('Filter by bet status'),
|
|
360
|
+
agent_id: zod_1.z.number().int().positive().optional().describe('Operator key only: limit to one agent'),
|
|
361
|
+
limit: zod_1.z.number().int().min(1).max(100).optional().describe('Rows to return (default 50)'),
|
|
362
|
+
offset: zod_1.z.number().int().min(0).optional().describe('Pagination offset'),
|
|
363
|
+
});
|
|
306
364
|
// List available tools
|
|
307
365
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
308
366
|
tools: [
|
|
@@ -317,7 +375,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
317
375
|
},
|
|
318
376
|
{
|
|
319
377
|
name: 'pay_l402_api',
|
|
320
|
-
description: 'Make a request to a paid API. Supports L402 (Lightning) and X402 (USDC on Base) protocols. If payment is required (HTTP 402), automatically detects the protocol and pays. L402 is preferred when both are available. Works with an operator key (pays from the operator wallet; a default agent is provisioned automatically) or an agent key.',
|
|
378
|
+
description: 'Make a request to a paid API. Supports L402 (Lightning) and X402 (USDC on Base) protocols. Platform fee on the API price: 1%, rounded down, no minimum, reported as fee in the response. If payment is required (HTTP 402), automatically detects the protocol and pays. L402 is preferred when both are available. Works with an operator key (pays from the operator wallet; a default agent is provisioned automatically) or an agent key.',
|
|
321
379
|
inputSchema: {
|
|
322
380
|
type: 'object',
|
|
323
381
|
properties: {
|
|
@@ -342,7 +400,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
342
400
|
},
|
|
343
401
|
{
|
|
344
402
|
name: 'pay_invoice',
|
|
345
|
-
description: 'Pay a BOLT11 Lightning invoice. Returns the preimage as proof of payment. Works with an operator key (pays from the operator wallet; a default agent is provisioned automatically) or an agent key. If the response says pending:true the payment is still in flight: do NOT retry, check get_transactions instead.',
|
|
403
|
+
description: 'Pay a BOLT11 Lightning invoice. Platform fee: 1% of the amount, rounded down, no minimum (nothing under 100 sats), reported as platform_fee_sats; get_info returns the current schedule. Returns the preimage as proof of payment. Works with an operator key (pays from the operator wallet; a default agent is provisioned automatically) or an agent key. If the response says pending:true the payment is still in flight: do NOT retry, check get_transactions instead.',
|
|
346
404
|
inputSchema: {
|
|
347
405
|
type: 'object',
|
|
348
406
|
properties: {
|
|
@@ -453,7 +511,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
453
511
|
},
|
|
454
512
|
{
|
|
455
513
|
name: 'fund_agent',
|
|
456
|
-
description: 'Transfer sats from operator balance to an agent.',
|
|
514
|
+
description: 'Transfer sats from operator balance to an agent. No platform fee.',
|
|
457
515
|
inputSchema: {
|
|
458
516
|
type: 'object',
|
|
459
517
|
properties: {
|
|
@@ -524,7 +582,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
524
582
|
url: { type: 'string', description: 'HTTPS webhook URL to receive events' },
|
|
525
583
|
events: {
|
|
526
584
|
type: 'array',
|
|
527
|
-
items: { type: 'string', enum: ['invoice_paid', 'payment_completed', 'payment_failed', 'withdrawal_completed', 'balance_changed', 'balance_low', 'budget_warning', 'test'] },
|
|
585
|
+
items: { type: 'string', enum: ['invoice_paid', 'payment_completed', 'payment_failed', 'withdrawal_completed', 'balance_changed', 'balance_low', 'budget_warning', 'bet_placed', 'bet_settled', 'test'] },
|
|
528
586
|
default: ['invoice_paid'],
|
|
529
587
|
description: 'Event types to subscribe to',
|
|
530
588
|
},
|
|
@@ -568,7 +626,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
568
626
|
// ==========================================
|
|
569
627
|
{
|
|
570
628
|
name: 'get_budget_status',
|
|
571
|
-
description: 'Get budget status for an agent - shows limit, spent, and
|
|
629
|
+
description: 'Get budget status for an agent - shows limit, spent, remaining and the platform_fees schedule that counts against it. Works with operator or agent keys.',
|
|
572
630
|
inputSchema: {
|
|
573
631
|
type: 'object',
|
|
574
632
|
properties: {
|
|
@@ -644,7 +702,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
644
702
|
// ==========================================
|
|
645
703
|
{
|
|
646
704
|
name: 'get_info',
|
|
647
|
-
description: 'Get service information including version, status, limits, and
|
|
705
|
+
description: 'Get service information including version, status, limits, supported features and the current platform_fees schedule (percent and minimum per action). No API key required — works before registering.',
|
|
648
706
|
inputSchema: {
|
|
649
707
|
type: 'object',
|
|
650
708
|
properties: {},
|
|
@@ -676,7 +734,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
676
734
|
// ==========================================
|
|
677
735
|
{
|
|
678
736
|
name: 'withdraw',
|
|
679
|
-
description: 'Withdraw funds from the operator account to an external Lightning invoice (minimum 10 sats;
|
|
737
|
+
description: 'Withdraw funds from the operator account to an external Lightning invoice (minimum 10 sats; no platform fee, only the Lightning routing fee at cost; unused routing reserve refunded). REQUIRES OPERATOR KEY. Subject to a security cooldown after key rotation.',
|
|
680
738
|
inputSchema: {
|
|
681
739
|
type: 'object',
|
|
682
740
|
properties: {
|
|
@@ -687,7 +745,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
687
745
|
},
|
|
688
746
|
{
|
|
689
747
|
name: 'create_withdraw_link',
|
|
690
|
-
description: 'Create an LNURL-withdraw link for the operator to receive funds. Opens in browser for QR code scanning with any Lightning wallet. Omit amount_sats to sweep full balance (minimum 10 sats after
|
|
748
|
+
description: 'Create an LNURL-withdraw link for the operator to receive funds. Opens in browser for QR code scanning with any Lightning wallet. Omit amount_sats to sweep full balance (minimum 10 sats after the routing reserve). No platform fee. REQUIRES OPERATOR KEY.',
|
|
691
749
|
inputSchema: {
|
|
692
750
|
type: 'object',
|
|
693
751
|
properties: {
|
|
@@ -715,7 +773,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
715
773
|
},
|
|
716
774
|
{
|
|
717
775
|
name: 'pay_lightning_address',
|
|
718
|
-
description: 'Pay to a Lightning address (user@domain.com format). Works with an operator key (pays from the operator wallet) or an agent key.',
|
|
776
|
+
description: 'Pay to a Lightning address (user@domain.com format). Platform fee: 1% of the amount, rounded down, no minimum, reported as platform_fee_sats. Works with an operator key (pays from the operator wallet) or an agent key.',
|
|
719
777
|
inputSchema: {
|
|
720
778
|
type: 'object',
|
|
721
779
|
properties: {
|
|
@@ -750,7 +808,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
750
808
|
},
|
|
751
809
|
{
|
|
752
810
|
name: 'nostr_zap',
|
|
753
|
-
description: 'Send a Nostr zap (NIP-57 Lightning payment with optional Nostr event). If the recipient supports NIP-57, a proper zap receipt is created. Otherwise falls back to a regular Lightning address payment. REQUIRES AGENT KEY with Nostr identity set.',
|
|
811
|
+
description: 'Send a Nostr zap (NIP-57 Lightning payment with optional Nostr event). If the recipient supports NIP-57, a proper zap receipt is created. Otherwise falls back to a regular Lightning address payment. REQUIRES AGENT KEY with Nostr identity set. Paid as a Lightning-address payment: platform fee 1% of the amount, rounded down, no minimum, reported as platform_fee_sats.',
|
|
754
812
|
inputSchema: {
|
|
755
813
|
type: 'object',
|
|
756
814
|
properties: {
|
|
@@ -769,7 +827,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
769
827
|
// ==========================================
|
|
770
828
|
{
|
|
771
829
|
name: 'transfer_to_agent',
|
|
772
|
-
description: 'Transfer sats between agents or from operator to agent. REQUIRES OPERATOR KEY.',
|
|
830
|
+
description: 'Transfer sats between agents or from operator to agent. No platform fee. REQUIRES OPERATOR KEY.',
|
|
773
831
|
inputSchema: {
|
|
774
832
|
type: 'object',
|
|
775
833
|
properties: {
|
|
@@ -819,7 +877,7 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
819
877
|
},
|
|
820
878
|
{
|
|
821
879
|
name: 'keysend',
|
|
822
|
-
description: 'Send a payment directly to a node without an invoice (keysend/spontaneous payment). REQUIRES AGENT KEY.',
|
|
880
|
+
description: 'Send a payment directly to a node without an invoice (keysend/spontaneous payment). Platform fee: 1% of the amount, rounded down, no minimum, reported as platform_fee_sats. REQUIRES AGENT KEY.',
|
|
823
881
|
inputSchema: {
|
|
824
882
|
type: 'object',
|
|
825
883
|
properties: {
|
|
@@ -956,6 +1014,66 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
956
1014
|
description: 'Agent Arena: reveal the current server seed (so every past roll can be verified against its committed hash) and rotate to a fresh committed seed. Do this after an event, not mid-entry. REQUIRES AGENT KEY.',
|
|
957
1015
|
inputSchema: { type: 'object', properties: {} },
|
|
958
1016
|
},
|
|
1017
|
+
{
|
|
1018
|
+
name: 'prediction_markets',
|
|
1019
|
+
description: 'Prediction markets: list sat-denominated markets (sports, BTC price) you can bet on for your operator. Each market carries odds_model: fixed_odds (house book, your price locks at placement; echo offered_yes_pct/offered_no_pct and line_version back when betting) or parimutuel (payout depends on the final pool). Public; with an agent key it adds my_position per market. Humans see the same markets at https://lightningfaucet.com/prediction-markets/',
|
|
1020
|
+
inputSchema: {
|
|
1021
|
+
type: 'object',
|
|
1022
|
+
properties: {
|
|
1023
|
+
status: { type: 'string', enum: ['open', 'upcoming', 'closed', 'resolved', 'cancelled', 'all'], description: 'Default open' },
|
|
1024
|
+
market_type: { type: 'string', enum: ['sports', 'btc_price'] },
|
|
1025
|
+
category: { type: 'string', description: 'League or category key, e.g. nfl, nba, nhl, mlb, ncaaf, mma, epl, ucl, tennis, btc_daily' },
|
|
1026
|
+
limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Default 50' },
|
|
1027
|
+
offset: { type: 'integer', minimum: 0 },
|
|
1028
|
+
},
|
|
1029
|
+
},
|
|
1030
|
+
},
|
|
1031
|
+
{
|
|
1032
|
+
name: 'prediction_market',
|
|
1033
|
+
description: 'Prediction markets: one market in full (odds, pools, caps, close and resolve times, resolution source, recent bets). With an agent key it adds my_position. Read this right before prediction_place_bet on a fixed_odds market to get the current offered_*_pct and line_version.',
|
|
1034
|
+
inputSchema: {
|
|
1035
|
+
type: 'object',
|
|
1036
|
+
properties: {
|
|
1037
|
+
market_id: { type: 'integer', minimum: 1, description: 'Market id from prediction_markets' },
|
|
1038
|
+
},
|
|
1039
|
+
required: ['market_id'],
|
|
1040
|
+
},
|
|
1041
|
+
},
|
|
1042
|
+
{
|
|
1043
|
+
name: 'prediction_place_bet',
|
|
1044
|
+
description: 'Prediction markets: back yes or no on a market with sats from your agent balance. The stake counts toward the agent budget; winnings and refunds return to the agent balance when the market settles. Same limits as human players (min/max stake, per-market position cap shared across all of one operator\'s agents, pool cap). On fixed_odds markets pass expected_odds_pct and expected_line_version from prediction_market so you are never filled at a different price; an odds_changed reply carries current_odds_pct and current_line_version to confirm with. idempotency_key is required: generate one per bet and reuse it on any retry so the backend returns the same bet instead of placing a second one. REQUIRES AGENT KEY with balance (fund_agent first).',
|
|
1045
|
+
inputSchema: {
|
|
1046
|
+
type: 'object',
|
|
1047
|
+
properties: {
|
|
1048
|
+
market_id: { type: 'integer', minimum: 1, description: 'Market id from prediction_markets' },
|
|
1049
|
+
position: { type: 'string', enum: ['yes', 'no'], description: 'Side to back' },
|
|
1050
|
+
amount_sats: { type: 'integer', minimum: 1, description: 'Stake in sats from the agent balance' },
|
|
1051
|
+
expected_odds_pct: { type: 'number', exclusiveMinimum: 0, exclusiveMaximum: 100, description: 'fixed_odds markets: the offered pct you saw for your side' },
|
|
1052
|
+
expected_line_version: { type: 'integer', minimum: 0, description: 'fixed_odds markets: the line_version you saw' },
|
|
1053
|
+
idempotency_key: { type: 'string', minLength: 1, maxLength: 128, description: 'Required. Unique per bet (a UUID is fine); reuse the same key when retrying the same bet' },
|
|
1054
|
+
},
|
|
1055
|
+
required: ['market_id', 'position', 'amount_sats', 'idempotency_key'],
|
|
1056
|
+
dependentRequired: { expected_odds_pct: ['expected_line_version'], expected_line_version: ['expected_odds_pct'] },
|
|
1057
|
+
},
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
name: 'prediction_my_bets',
|
|
1061
|
+
description: 'Prediction markets: your bets, newest first, with market title, status (active|won|lost|refunded), payout and profit. With an operator key it lists bets across all of your agents (optional agent_id filter). Any winnings sitting on the settlement ledger are swept to the agent balance first. REQUIRES AGENT OR OPERATOR KEY.',
|
|
1062
|
+
inputSchema: {
|
|
1063
|
+
type: 'object',
|
|
1064
|
+
properties: {
|
|
1065
|
+
status: { type: 'string', enum: ['active', 'won', 'lost', 'refunded'] },
|
|
1066
|
+
agent_id: { type: 'integer', minimum: 1, description: 'Operator key only: limit to one agent' },
|
|
1067
|
+
limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Default 50' },
|
|
1068
|
+
offset: { type: 'integer', minimum: 0 },
|
|
1069
|
+
},
|
|
1070
|
+
},
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
name: 'prediction_positions',
|
|
1074
|
+
description: 'Prediction markets: open positions (stake per side per market, potential payout, close time) and total at stake. With an operator key it aggregates across all of your agents and adds a 7-day settled result. REQUIRES AGENT OR OPERATOR KEY.',
|
|
1075
|
+
inputSchema: { type: 'object', properties: {} },
|
|
1076
|
+
},
|
|
959
1077
|
],
|
|
960
1078
|
}));
|
|
961
1079
|
// Handle tool calls
|
|
@@ -1290,7 +1408,17 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1290
1408
|
const parsed = SetAgentCredentialsSchema.parse(args ?? {});
|
|
1291
1409
|
session.setClient(new lightning_faucet_js_1.LightningFaucetClient(parsed.api_key));
|
|
1292
1410
|
session.keySource = 'file';
|
|
1293
|
-
|
|
1411
|
+
// Best-effort identification so the saved entry carries the agent id.
|
|
1412
|
+
let suppliedAgentId;
|
|
1413
|
+
try {
|
|
1414
|
+
const me = await session.requireClient().whoami();
|
|
1415
|
+
if (me.type === 'agent' && me.id)
|
|
1416
|
+
suppliedAgentId = me.id;
|
|
1417
|
+
}
|
|
1418
|
+
catch {
|
|
1419
|
+
// Best effort: switching credentials must not fail because whoami did.
|
|
1420
|
+
}
|
|
1421
|
+
const agSavedTo = (0, credentials_js_1.saveAgentKey)(parsed.api_key, { id: suppliedAgentId }, true);
|
|
1294
1422
|
return {
|
|
1295
1423
|
content: [
|
|
1296
1424
|
{
|
|
@@ -1418,6 +1546,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1418
1546
|
total_spent_sats: result.totalSpentSats,
|
|
1419
1547
|
remaining_sats: result.remainingSats,
|
|
1420
1548
|
has_budget: result.hasBudget,
|
|
1549
|
+
platform_fees: result.rawResponse?.platform_fees,
|
|
1421
1550
|
}, null, 2),
|
|
1422
1551
|
},
|
|
1423
1552
|
],
|
|
@@ -1556,6 +1685,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1556
1685
|
max_payment_sats: result.maxPaymentSats,
|
|
1557
1686
|
min_payment_sats: result.minPaymentSats,
|
|
1558
1687
|
supported_features: result.supportedFeatures,
|
|
1688
|
+
platform_fees: result.rawResponse?.platform_fees,
|
|
1559
1689
|
}, null, 2),
|
|
1560
1690
|
},
|
|
1561
1691
|
],
|
|
@@ -1685,6 +1815,8 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1685
1815
|
message: `Paid ${parsed.amount_sats} sats to ${parsed.address}`,
|
|
1686
1816
|
amount_sats: result.amountSats,
|
|
1687
1817
|
fee_sats: result.feeSats,
|
|
1818
|
+
routing_fee_sats: result.routingFeeSats,
|
|
1819
|
+
platform_fee_sats: result.platformFeeSats,
|
|
1688
1820
|
payment_hash: result.paymentHash,
|
|
1689
1821
|
new_balance: result.newBalance,
|
|
1690
1822
|
}, null, 2),
|
|
@@ -1741,6 +1873,8 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1741
1873
|
(result.zapType === 'nip57' ? ' (NIP-57 zap receipt created)' : ' (regular payment, recipient does not support NIP-57)'),
|
|
1742
1874
|
amount_sats: result.amountSats,
|
|
1743
1875
|
fee_sats: result.feeSats,
|
|
1876
|
+
routing_fee_sats: result.routingFeeSats,
|
|
1877
|
+
platform_fee_sats: result.platformFeeSats,
|
|
1744
1878
|
payment_hash: result.paymentHash,
|
|
1745
1879
|
new_balance: result.newBalance,
|
|
1746
1880
|
zap_type: result.zapType,
|
|
@@ -1954,6 +2088,63 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1954
2088
|
const result = await session.requireClient().arenaRevealSeed();
|
|
1955
2089
|
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1956
2090
|
}
|
|
2091
|
+
// ─── Prediction markets ───────────────────────────────────────────
|
|
2092
|
+
case 'prediction_markets': {
|
|
2093
|
+
const parsed = PredictionMarketsSchema.parse(args ?? {});
|
|
2094
|
+
const filters = Object.fromEntries(Object.entries(parsed).filter(([, v]) => v !== undefined));
|
|
2095
|
+
const c = session.getClient();
|
|
2096
|
+
const result = c ? await c.predictionMarkets(filters) : await (0, lightning_faucet_js_1.getPublicAction)('prediction_markets', filters);
|
|
2097
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
2098
|
+
}
|
|
2099
|
+
case 'prediction_market': {
|
|
2100
|
+
const parsed = PredictionMarketSchema.parse(args ?? {});
|
|
2101
|
+
const c = session.getClient();
|
|
2102
|
+
const result = c ? await c.predictionMarket(parsed.market_id) : await (0, lightning_faucet_js_1.getPublicAction)('prediction_market', { market_id: parsed.market_id });
|
|
2103
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
2104
|
+
}
|
|
2105
|
+
case 'prediction_place_bet': {
|
|
2106
|
+
const parsed = PredictionPlaceBetSchema.parse(args ?? {});
|
|
2107
|
+
// The caller owns the idempotency key (required by schema and by the backend).
|
|
2108
|
+
// No key is ever generated here: a server-side cache of generated keys cannot
|
|
2109
|
+
// survive restarts, credential switches or key rotation, and every such gap
|
|
2110
|
+
// is a path to a duplicate real-money bet.
|
|
2111
|
+
const idempotencyKey = parsed.idempotency_key;
|
|
2112
|
+
try {
|
|
2113
|
+
const result = await session.requireClient().predictionPlaceBet(parsed);
|
|
2114
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
2115
|
+
}
|
|
2116
|
+
catch (e) {
|
|
2117
|
+
// A refusal is information the model acts on (re-price, size down, fund),
|
|
2118
|
+
// not a failure: hand the backend's structured reply through unchanged.
|
|
2119
|
+
if (e instanceof lightning_faucet_js_1.ApiError && PREDICTION_REFUSALS.has(String(e.response.error ?? ''))) {
|
|
2120
|
+
const refusal = { ...e.response, idempotency_key: idempotencyKey, next: predictionNextHint(String(e.response.error)) };
|
|
2121
|
+
return { content: [{ type: 'text', text: JSON.stringify(refusal, null, 2) }] };
|
|
2122
|
+
}
|
|
2123
|
+
// Unknown outcome (timeout, network, 5xx): the bet may have been placed.
|
|
2124
|
+
// Surface the key so the retry is a replay, never a second bet.
|
|
2125
|
+
if (!(e instanceof lightning_faucet_js_1.ApiError)) {
|
|
2126
|
+
const uncertain = {
|
|
2127
|
+
success: false,
|
|
2128
|
+
error: 'uncertain_outcome',
|
|
2129
|
+
message: e instanceof Error ? e.message : String(e),
|
|
2130
|
+
idempotency_key: idempotencyKey,
|
|
2131
|
+
next: 'The bet may or may not have been placed. Retry prediction_place_bet with the SAME arguments and the SAME idempotency_key: the backend replays the bet if it landed and places it if it did not. Do NOT change the stake or side or the key, which would create a new bet.',
|
|
2132
|
+
};
|
|
2133
|
+
return { content: [{ type: 'text', text: JSON.stringify(uncertain, null, 2) }] };
|
|
2134
|
+
}
|
|
2135
|
+
throw e;
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
case 'prediction_my_bets': {
|
|
2139
|
+
const parsed = PredictionMyBetsSchema.parse(args ?? {});
|
|
2140
|
+
const filters = Object.fromEntries(Object.entries(parsed).filter(([, v]) => v !== undefined));
|
|
2141
|
+
const result = await session.requireClient().predictionMyBets(filters);
|
|
2142
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
2143
|
+
}
|
|
2144
|
+
case 'prediction_positions': {
|
|
2145
|
+
const result = await session.requireClient().predictionPositions();
|
|
2146
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
2147
|
+
}
|
|
1957
2148
|
default:
|
|
1958
2149
|
return {
|
|
1959
2150
|
content: [
|
|
@@ -522,6 +522,8 @@ export declare class LightningFaucetClient {
|
|
|
522
522
|
nostrZap(address: string, amountSats: number, recipientPubkey?: string, content?: string, eventId?: string, relays?: string[]): Promise<{
|
|
523
523
|
amountSats: number;
|
|
524
524
|
feeSats: number;
|
|
525
|
+
routingFeeSats: number;
|
|
526
|
+
platformFeeSats: number;
|
|
525
527
|
paymentHash: string;
|
|
526
528
|
newBalance: number;
|
|
527
529
|
zapType: 'nip57' | 'fallback';
|
|
@@ -554,6 +556,39 @@ export declare class LightningFaucetClient {
|
|
|
554
556
|
arenaFairness(): Promise<Record<string, unknown>>;
|
|
555
557
|
arenaSetClientSeed(clientSeed: string): Promise<Record<string, unknown>>;
|
|
556
558
|
arenaRevealSeed(): Promise<Record<string, unknown>>;
|
|
559
|
+
/** List markets (public; with an agent key adds my_position). */
|
|
560
|
+
predictionMarkets(filters?: {
|
|
561
|
+
status?: string;
|
|
562
|
+
market_type?: string;
|
|
563
|
+
category?: string;
|
|
564
|
+
limit?: number;
|
|
565
|
+
offset?: number;
|
|
566
|
+
}): Promise<Record<string, unknown>>;
|
|
567
|
+
/** One market in full. */
|
|
568
|
+
predictionMarket(marketId: number): Promise<Record<string, unknown>>;
|
|
569
|
+
/**
|
|
570
|
+
* Place a bet from the agent balance. idempotency_key is required by the
|
|
571
|
+
* backend; the MCP tool generates one when the model omits it. Refusals
|
|
572
|
+
* (odds_changed, position_cap_exceeded, ...) throw ApiError with the full
|
|
573
|
+
* structured reply in .response.
|
|
574
|
+
*/
|
|
575
|
+
predictionPlaceBet(p: {
|
|
576
|
+
market_id: number;
|
|
577
|
+
position: 'yes' | 'no';
|
|
578
|
+
amount_sats: number;
|
|
579
|
+
idempotency_key: string;
|
|
580
|
+
expected_odds_pct?: number;
|
|
581
|
+
expected_line_version?: number;
|
|
582
|
+
}): Promise<Record<string, unknown>>;
|
|
583
|
+
/** My bets (agent key) or bets across my agents (operator key). */
|
|
584
|
+
predictionMyBets(filters?: {
|
|
585
|
+
status?: string;
|
|
586
|
+
agent_id?: number;
|
|
587
|
+
limit?: number;
|
|
588
|
+
offset?: number;
|
|
589
|
+
}): Promise<Record<string, unknown>>;
|
|
590
|
+
/** Open positions and total at stake. */
|
|
591
|
+
predictionPositions(): Promise<Record<string, unknown>>;
|
|
557
592
|
/**
|
|
558
593
|
* Update operator profile (email and/or name). Setting an email sends a
|
|
559
594
|
* verification link - a verified email is required for the free-sats promo.
|
|
@@ -600,7 +635,9 @@ export declare function getPublicDecodedInvoice(bolt11: string): Promise<{
|
|
|
600
635
|
createdAt?: string;
|
|
601
636
|
rawResponse: ApiResponse;
|
|
602
637
|
}>;
|
|
638
|
+
export type PublicReadAction = 'arena_list' | 'arena_leaderboard' | 'prediction_markets' | 'prediction_market';
|
|
603
639
|
export declare function getPublicArena(action: 'arena_list' | 'arena_leaderboard', data?: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
640
|
+
export declare function getPublicAction(action: PublicReadAction, data?: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
604
641
|
/**
|
|
605
642
|
* Account recovery is unauthenticated (the recovery code IS the credential), so it lives
|
|
606
643
|
* outside the client class: callers must not need an API key to construct anything.
|
package/dist/lightning-faucet.js
CHANGED
|
@@ -11,6 +11,7 @@ exports.registerOperator = registerOperator;
|
|
|
11
11
|
exports.getPublicInfo = getPublicInfo;
|
|
12
12
|
exports.getPublicDecodedInvoice = getPublicDecodedInvoice;
|
|
13
13
|
exports.getPublicArena = getPublicArena;
|
|
14
|
+
exports.getPublicAction = getPublicAction;
|
|
14
15
|
exports.recoverOperatorAccount = recoverOperatorAccount;
|
|
15
16
|
const pre_payment_hook_js_1 = require("./pre-payment-hook.js");
|
|
16
17
|
const bolt11_js_1 = require("./bolt11.js");
|
|
@@ -863,9 +864,16 @@ class LightningFaucetClient {
|
|
|
863
864
|
if (relays)
|
|
864
865
|
data.relays = relays;
|
|
865
866
|
const result = await this.request('nostr_zap', data);
|
|
867
|
+
// The backend settles a zap through the Lightning-address path, which reports
|
|
868
|
+
// routing_fee_sats and platform_fee_sats separately; keep the split so the tool
|
|
869
|
+
// can show the platform fee it advertised, plus the combined feeSats.
|
|
870
|
+
const routingFeeSats = result.routing_fee_sats || 0;
|
|
871
|
+
const platformFeeSats = result.platform_fee_sats || 0;
|
|
866
872
|
return {
|
|
867
873
|
amountSats: result.amount_sats || amountSats,
|
|
868
|
-
feeSats: result.fee_sats ?? (
|
|
874
|
+
feeSats: result.fee_sats ?? (routingFeeSats + platformFeeSats),
|
|
875
|
+
routingFeeSats,
|
|
876
|
+
platformFeeSats,
|
|
869
877
|
paymentHash: result.payment_hash || '',
|
|
870
878
|
newBalance: result.new_balance || 0,
|
|
871
879
|
zapType: result.zap_type || 'fallback',
|
|
@@ -947,6 +955,50 @@ class LightningFaucetClient {
|
|
|
947
955
|
async arenaRevealSeed() {
|
|
948
956
|
return this.request('arena_reveal_seed');
|
|
949
957
|
}
|
|
958
|
+
// ─── Prediction markets (agents bet for their operators) ───────────────
|
|
959
|
+
/** List markets (public; with an agent key adds my_position). */
|
|
960
|
+
async predictionMarkets(filters = {}) {
|
|
961
|
+
const data = {};
|
|
962
|
+
for (const [k, v] of Object.entries(filters))
|
|
963
|
+
if (v !== undefined)
|
|
964
|
+
data[k] = v;
|
|
965
|
+
return this.request('prediction_markets', data);
|
|
966
|
+
}
|
|
967
|
+
/** One market in full. */
|
|
968
|
+
async predictionMarket(marketId) {
|
|
969
|
+
return this.request('prediction_market', { market_id: marketId });
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Place a bet from the agent balance. idempotency_key is required by the
|
|
973
|
+
* backend; the MCP tool generates one when the model omits it. Refusals
|
|
974
|
+
* (odds_changed, position_cap_exceeded, ...) throw ApiError with the full
|
|
975
|
+
* structured reply in .response.
|
|
976
|
+
*/
|
|
977
|
+
async predictionPlaceBet(p) {
|
|
978
|
+
const data = {
|
|
979
|
+
market_id: p.market_id,
|
|
980
|
+
position: p.position,
|
|
981
|
+
amount_sats: p.amount_sats,
|
|
982
|
+
idempotency_key: p.idempotency_key,
|
|
983
|
+
};
|
|
984
|
+
if (p.expected_odds_pct !== undefined)
|
|
985
|
+
data.expected_odds_pct = p.expected_odds_pct;
|
|
986
|
+
if (p.expected_line_version !== undefined)
|
|
987
|
+
data.expected_line_version = p.expected_line_version;
|
|
988
|
+
return this.request('prediction_place_bet', data);
|
|
989
|
+
}
|
|
990
|
+
/** My bets (agent key) or bets across my agents (operator key). */
|
|
991
|
+
async predictionMyBets(filters = {}) {
|
|
992
|
+
const data = {};
|
|
993
|
+
for (const [k, v] of Object.entries(filters))
|
|
994
|
+
if (v !== undefined)
|
|
995
|
+
data[k] = v;
|
|
996
|
+
return this.request('prediction_my_bets', data);
|
|
997
|
+
}
|
|
998
|
+
/** Open positions and total at stake. */
|
|
999
|
+
async predictionPositions() {
|
|
1000
|
+
return this.request('prediction_positions');
|
|
1001
|
+
}
|
|
950
1002
|
/**
|
|
951
1003
|
* Update operator profile (email and/or name). Setting an email sends a
|
|
952
1004
|
* verification link - a verified email is required for the free-sats promo.
|
|
@@ -1054,8 +1106,10 @@ async function getPublicDecodedInvoice(bolt11) {
|
|
|
1054
1106
|
rawResponse: result,
|
|
1055
1107
|
};
|
|
1056
1108
|
}
|
|
1057
|
-
// Public arena reads (no API key needed) so first-run agents can browse tournaments
|
|
1058
1109
|
async function getPublicArena(action, data = {}) {
|
|
1110
|
+
return getPublicAction(action, data);
|
|
1111
|
+
}
|
|
1112
|
+
async function getPublicAction(action, data = {}) {
|
|
1059
1113
|
const response = await fetchWithTimeout(API_BASE_URL, {
|
|
1060
1114
|
method: 'POST',
|
|
1061
1115
|
headers: { 'Content-Type': 'application/json' },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lightning-wallet-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"mcpName": "io.github.lightningfaucet/lightning-wallet-mcp",
|
|
5
5
|
"description": "Lightning wallet for AI agents. MCP server + CLI. Works with Claude Code, OpenClaw, Cursor, and any agent framework.",
|
|
6
6
|
"main": "dist/index.js",
|