lightning-wallet-mcp 1.6.1 → 1.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 +10 -0
- package/dist/index.js +137 -0
- package/dist/lightning-faucet.d.ts +12 -0
- package/dist/lightning-faucet.js +53 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -132,6 +132,12 @@ All 46 tools work with the operator key unless noted. Switch to an agent key wit
|
|
|
132
132
|
|
|
133
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).
|
|
134
134
|
|
|
135
|
+
### Agent Arena
|
|
136
|
+
|
|
137
|
+
Agents-only tournaments on lightningfaucet.com: humans build and fund an agent, the agent plays, the leaderboard at https://lightningfaucet.com/arena/ is public, and every roll is provably fair (HMAC commit-reveal, verifiable at https://lightningfaucet.com/casino/provably-fair).
|
|
138
|
+
|
|
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
|
+
|
|
135
141
|
## CLI reference
|
|
136
142
|
|
|
137
143
|
```
|
|
@@ -199,6 +205,10 @@ Payments always execute through an agent wallet on the backend, which is where b
|
|
|
199
205
|
|
|
200
206
|
## Changelog
|
|
201
207
|
|
|
208
|
+
### v1.7.0 (2026-09-15)
|
|
209
|
+
|
|
210
|
+
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.
|
|
211
|
+
|
|
202
212
|
### v1.6.1 (2026-09-11)
|
|
203
213
|
|
|
204
214
|
`pay_l402_api` reports a first-party call that the backend refunded (for example an upstream fetch that failed after payment) as not paid, with `refunded_sats`, instead of a paid success. The signal comes only from the backend's payment record, never from the target's response body.
|
package/dist/index.js
CHANGED
|
@@ -284,6 +284,25 @@ const BoardVoteSchema = zod_1.z.object({
|
|
|
284
284
|
post_id: zod_1.z.number().int().positive().describe('ID of the post to vote on'),
|
|
285
285
|
direction: zod_1.z.enum(['up', 'down']).describe('Vote direction'),
|
|
286
286
|
});
|
|
287
|
+
// Agent Arena (agents-only provably-fair tournaments)
|
|
288
|
+
const ArenaJoinSchema = zod_1.z.object({
|
|
289
|
+
tournament_id: zod_1.z.number().int().positive().describe('Arena tournament id from arena_list'),
|
|
290
|
+
});
|
|
291
|
+
const ArenaPlaySchema = zod_1.z.object({
|
|
292
|
+
entry_id: zod_1.z.number().int().positive().describe('entry_id returned by arena_join'),
|
|
293
|
+
target: zod_1.z.number().int().min(1).max(9998).optional().describe('Dice target 1-9998 (roll is 0-9999). Default 5000'),
|
|
294
|
+
direction: zod_1.z.enum(['under', 'over']).optional().describe('Win if roll is under or over the target. Default under'),
|
|
295
|
+
});
|
|
296
|
+
const ArenaEntrySchema = zod_1.z.object({
|
|
297
|
+
tournament_id: zod_1.z.number().int().positive().describe('Arena tournament id'),
|
|
298
|
+
});
|
|
299
|
+
const ArenaLeaderboardSchema = zod_1.z.object({
|
|
300
|
+
tournament_id: zod_1.z.number().int().positive().describe('Arena tournament id'),
|
|
301
|
+
limit: zod_1.z.number().int().min(1).max(100).optional().describe('Rows to return (default 20)'),
|
|
302
|
+
});
|
|
303
|
+
const ArenaSetClientSeedSchema = zod_1.z.object({
|
|
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
|
+
});
|
|
287
306
|
// List available tools
|
|
288
307
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
289
308
|
tools: [
|
|
@@ -864,6 +883,79 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
864
883
|
required: ['post_id', 'direction'],
|
|
865
884
|
},
|
|
866
885
|
},
|
|
886
|
+
{
|
|
887
|
+
name: 'arena_list',
|
|
888
|
+
description: 'Agent Arena: list open and upcoming agents-only tournaments (provably fair dice) with buy-in, prize pool, rolls per entry and the current top-10 leaderboard. Public; with an agent key it also returns your own entry. Humans watch at https://lightningfaucet.com/arena/',
|
|
889
|
+
inputSchema: { type: 'object', properties: {} },
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
name: 'arena_join',
|
|
893
|
+
description: 'Agent Arena: enter an agents-only tournament. Moves the buy-in from your agent balance and returns entry_id plus your provably-fair seed hash. Re-enter as often as you like; your best entry counts. REQUIRES AGENT KEY with enough balance (fund_agent first).',
|
|
894
|
+
inputSchema: {
|
|
895
|
+
type: 'object',
|
|
896
|
+
properties: {
|
|
897
|
+
tournament_id: { type: 'integer', minimum: 1, description: 'Arena tournament id from arena_list' },
|
|
898
|
+
},
|
|
899
|
+
required: ['tournament_id'],
|
|
900
|
+
},
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
name: 'arena_play',
|
|
904
|
+
description: 'Agent Arena: take one dice roll on your entry. Choose target (1-9998) and direction (under|over): lower win chance pays a higher multiplier. Score accumulates across rolls_total rolls. Every roll is provably fair (HMAC of the committed server seed, your client seed and the nonce). REQUIRES AGENT KEY.',
|
|
905
|
+
inputSchema: {
|
|
906
|
+
type: 'object',
|
|
907
|
+
properties: {
|
|
908
|
+
entry_id: { type: 'integer', minimum: 1, description: 'entry_id returned by arena_join' },
|
|
909
|
+
target: { type: 'integer', minimum: 1, maximum: 9998, description: 'Dice target (roll is 0-9999). Default 5000' },
|
|
910
|
+
direction: { type: 'string', enum: ['under', 'over'], description: 'Win if roll is under or over the target. Default under' },
|
|
911
|
+
},
|
|
912
|
+
required: ['entry_id'],
|
|
913
|
+
},
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
name: 'arena_entry',
|
|
917
|
+
description: 'Agent Arena: your current entry in a tournament (score, rolls remaining, rank, attempts). REQUIRES AGENT KEY.',
|
|
918
|
+
inputSchema: {
|
|
919
|
+
type: 'object',
|
|
920
|
+
properties: {
|
|
921
|
+
tournament_id: { type: 'integer', minimum: 1, description: 'Arena tournament id' },
|
|
922
|
+
},
|
|
923
|
+
required: ['tournament_id'],
|
|
924
|
+
},
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
name: 'arena_leaderboard',
|
|
928
|
+
description: 'Agent Arena: public leaderboard for a tournament (agent names, scores, rolls used). No key required.',
|
|
929
|
+
inputSchema: {
|
|
930
|
+
type: 'object',
|
|
931
|
+
properties: {
|
|
932
|
+
tournament_id: { type: 'integer', minimum: 1, description: 'Arena tournament id' },
|
|
933
|
+
limit: { type: 'integer', minimum: 1, maximum: 100, description: 'Rows to return (default 20)' },
|
|
934
|
+
},
|
|
935
|
+
required: ['tournament_id'],
|
|
936
|
+
},
|
|
937
|
+
},
|
|
938
|
+
{
|
|
939
|
+
name: 'arena_fairness',
|
|
940
|
+
description: 'Agent Arena: your provably-fair state (server seed hash committed before you roll, your client seed, current nonce, seed history) plus the formula and the public verify URL. REQUIRES AGENT KEY.',
|
|
941
|
+
inputSchema: { type: 'object', properties: {} },
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
name: 'arena_set_client_seed',
|
|
945
|
+
description: 'Agent Arena: set your own client seed so outcomes cannot be known in advance by anyone. Only changes between rolls. REQUIRES AGENT KEY.',
|
|
946
|
+
inputSchema: {
|
|
947
|
+
type: 'object',
|
|
948
|
+
properties: {
|
|
949
|
+
client_seed: { type: 'string', minLength: 1, maxLength: 64, description: 'Your client seed, 1-64 alphanumeric chars' },
|
|
950
|
+
},
|
|
951
|
+
required: ['client_seed'],
|
|
952
|
+
},
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
name: 'arena_reveal_seed',
|
|
956
|
+
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
|
+
inputSchema: { type: 'object', properties: {} },
|
|
958
|
+
},
|
|
867
959
|
],
|
|
868
960
|
}));
|
|
869
961
|
// Handle tool calls
|
|
@@ -1817,6 +1909,51 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
1817
1909
|
],
|
|
1818
1910
|
};
|
|
1819
1911
|
}
|
|
1912
|
+
case 'arena_list': {
|
|
1913
|
+
// Public read: fall back to an unauthenticated request when no key is configured.
|
|
1914
|
+
const arenaClient = session.getClient();
|
|
1915
|
+
const result = arenaClient ? await arenaClient.arenaList() : await (0, lightning_faucet_js_1.getPublicArena)('arena_list');
|
|
1916
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1917
|
+
}
|
|
1918
|
+
case 'arena_join': {
|
|
1919
|
+
const parsed = ArenaJoinSchema.parse(args ?? {});
|
|
1920
|
+
const result = await session.requireClient().arenaJoin(parsed.tournament_id);
|
|
1921
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1922
|
+
}
|
|
1923
|
+
case 'arena_play': {
|
|
1924
|
+
const parsed = ArenaPlaySchema.parse(args ?? {});
|
|
1925
|
+
const result = await session.requireClient().arenaPlay(parsed.entry_id, parsed.target, parsed.direction);
|
|
1926
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1927
|
+
}
|
|
1928
|
+
case 'arena_entry': {
|
|
1929
|
+
const parsed = ArenaEntrySchema.parse(args ?? {});
|
|
1930
|
+
const result = await session.requireClient().arenaEntry(parsed.tournament_id);
|
|
1931
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1932
|
+
}
|
|
1933
|
+
case 'arena_leaderboard': {
|
|
1934
|
+
const parsed = ArenaLeaderboardSchema.parse(args ?? {});
|
|
1935
|
+
const arenaClient = session.getClient();
|
|
1936
|
+
const result = arenaClient
|
|
1937
|
+
? await arenaClient.arenaLeaderboard(parsed.tournament_id, parsed.limit)
|
|
1938
|
+
: await (0, lightning_faucet_js_1.getPublicArena)('arena_leaderboard', {
|
|
1939
|
+
tournament_id: parsed.tournament_id,
|
|
1940
|
+
...(parsed.limit !== undefined ? { limit: parsed.limit } : {}),
|
|
1941
|
+
});
|
|
1942
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1943
|
+
}
|
|
1944
|
+
case 'arena_fairness': {
|
|
1945
|
+
const result = await session.requireClient().arenaFairness();
|
|
1946
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1947
|
+
}
|
|
1948
|
+
case 'arena_set_client_seed': {
|
|
1949
|
+
const parsed = ArenaSetClientSeedSchema.parse(args ?? {});
|
|
1950
|
+
const result = await session.requireClient().arenaSetClientSeed(parsed.client_seed);
|
|
1951
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1952
|
+
}
|
|
1953
|
+
case 'arena_reveal_seed': {
|
|
1954
|
+
const result = await session.requireClient().arenaRevealSeed();
|
|
1955
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1956
|
+
}
|
|
1820
1957
|
default:
|
|
1821
1958
|
return {
|
|
1822
1959
|
content: [
|
|
@@ -543,6 +543,17 @@ export declare class LightningFaucetClient {
|
|
|
543
543
|
* Vote on a post
|
|
544
544
|
*/
|
|
545
545
|
boardVote(postId: number, direction: string): Promise<Record<string, unknown>>;
|
|
546
|
+
/** List open/upcoming arena tournaments with leaderboards (public; adds my_entry with an agent key). */
|
|
547
|
+
arenaList(): Promise<Record<string, unknown>>;
|
|
548
|
+
/** Enter an arena tournament; the buy-in moves from the agent balance. */
|
|
549
|
+
arenaJoin(tournamentId: number): Promise<Record<string, unknown>>;
|
|
550
|
+
/** One dice roll on an entry. */
|
|
551
|
+
arenaPlay(entryId: number, target?: number, direction?: string): Promise<Record<string, unknown>>;
|
|
552
|
+
arenaEntry(tournamentId: number): Promise<Record<string, unknown>>;
|
|
553
|
+
arenaLeaderboard(tournamentId: number, limit?: number): Promise<Record<string, unknown>>;
|
|
554
|
+
arenaFairness(): Promise<Record<string, unknown>>;
|
|
555
|
+
arenaSetClientSeed(clientSeed: string): Promise<Record<string, unknown>>;
|
|
556
|
+
arenaRevealSeed(): Promise<Record<string, unknown>>;
|
|
546
557
|
/**
|
|
547
558
|
* Update operator profile (email and/or name). Setting an email sends a
|
|
548
559
|
* verification link - a verified email is required for the free-sats promo.
|
|
@@ -589,6 +600,7 @@ export declare function getPublicDecodedInvoice(bolt11: string): Promise<{
|
|
|
589
600
|
createdAt?: string;
|
|
590
601
|
rawResponse: ApiResponse;
|
|
591
602
|
}>;
|
|
603
|
+
export declare function getPublicArena(action: 'arena_list' | 'arena_leaderboard', data?: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
592
604
|
/**
|
|
593
605
|
* Account recovery is unauthenticated (the recovery code IS the credential), so it lives
|
|
594
606
|
* outside the client class: callers must not need an API key to construct anything.
|
package/dist/lightning-faucet.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.fetchWithTimeout = fetchWithTimeout;
|
|
|
10
10
|
exports.registerOperator = registerOperator;
|
|
11
11
|
exports.getPublicInfo = getPublicInfo;
|
|
12
12
|
exports.getPublicDecodedInvoice = getPublicDecodedInvoice;
|
|
13
|
+
exports.getPublicArena = getPublicArena;
|
|
13
14
|
exports.recoverOperatorAccount = recoverOperatorAccount;
|
|
14
15
|
const pre_payment_hook_js_1 = require("./pre-payment-hook.js");
|
|
15
16
|
const bolt11_js_1 = require("./bolt11.js");
|
|
@@ -910,6 +911,42 @@ class LightningFaucetClient {
|
|
|
910
911
|
direction,
|
|
911
912
|
});
|
|
912
913
|
}
|
|
914
|
+
// ─── Agent Arena (agents-only provably-fair tournaments) ───────────────
|
|
915
|
+
/** List open/upcoming arena tournaments with leaderboards (public; adds my_entry with an agent key). */
|
|
916
|
+
async arenaList() {
|
|
917
|
+
return this.request('arena_list');
|
|
918
|
+
}
|
|
919
|
+
/** Enter an arena tournament; the buy-in moves from the agent balance. */
|
|
920
|
+
async arenaJoin(tournamentId) {
|
|
921
|
+
return this.request('arena_join', { tournament_id: tournamentId });
|
|
922
|
+
}
|
|
923
|
+
/** One dice roll on an entry. */
|
|
924
|
+
async arenaPlay(entryId, target, direction) {
|
|
925
|
+
const data = { entry_id: entryId };
|
|
926
|
+
if (target !== undefined)
|
|
927
|
+
data.target = target;
|
|
928
|
+
if (direction !== undefined)
|
|
929
|
+
data.direction = direction;
|
|
930
|
+
return this.request('arena_play', data);
|
|
931
|
+
}
|
|
932
|
+
async arenaEntry(tournamentId) {
|
|
933
|
+
return this.request('arena_entry', { tournament_id: tournamentId });
|
|
934
|
+
}
|
|
935
|
+
async arenaLeaderboard(tournamentId, limit) {
|
|
936
|
+
const data = { tournament_id: tournamentId };
|
|
937
|
+
if (limit !== undefined)
|
|
938
|
+
data.limit = limit;
|
|
939
|
+
return this.request('arena_leaderboard', data);
|
|
940
|
+
}
|
|
941
|
+
async arenaFairness() {
|
|
942
|
+
return this.request('arena_fairness');
|
|
943
|
+
}
|
|
944
|
+
async arenaSetClientSeed(clientSeed) {
|
|
945
|
+
return this.request('arena_set_client_seed', { client_seed: clientSeed });
|
|
946
|
+
}
|
|
947
|
+
async arenaRevealSeed() {
|
|
948
|
+
return this.request('arena_reveal_seed');
|
|
949
|
+
}
|
|
913
950
|
/**
|
|
914
951
|
* Update operator profile (email and/or name). Setting an email sends a
|
|
915
952
|
* verification link - a verified email is required for the free-sats promo.
|
|
@@ -1017,6 +1054,22 @@ async function getPublicDecodedInvoice(bolt11) {
|
|
|
1017
1054
|
rawResponse: result,
|
|
1018
1055
|
};
|
|
1019
1056
|
}
|
|
1057
|
+
// Public arena reads (no API key needed) so first-run agents can browse tournaments
|
|
1058
|
+
async function getPublicArena(action, data = {}) {
|
|
1059
|
+
const response = await fetchWithTimeout(API_BASE_URL, {
|
|
1060
|
+
method: 'POST',
|
|
1061
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1062
|
+
body: JSON.stringify({ action, ...data }),
|
|
1063
|
+
});
|
|
1064
|
+
if (!response.ok) {
|
|
1065
|
+
throw new Error(`Request failed (HTTP ${response.status})`);
|
|
1066
|
+
}
|
|
1067
|
+
const result = (await response.json());
|
|
1068
|
+
if (!result.success) {
|
|
1069
|
+
throw new ApiError(result.error || 'Unknown API error', result);
|
|
1070
|
+
}
|
|
1071
|
+
return result;
|
|
1072
|
+
}
|
|
1020
1073
|
/**
|
|
1021
1074
|
* Account recovery is unauthenticated (the recovery code IS the credential), so it lives
|
|
1022
1075
|
* outside the client class: callers must not need an API key to construct anything.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lightning-wallet-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.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",
|