@kaleidorg/mind 0.9.0 → 0.10.1
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/dist/engine/answer.d.ts +3 -0
- package/dist/engine/answer.d.ts.map +1 -1
- package/dist/engine/answer.js +19 -2
- package/dist/engine/answer.js.map +1 -1
- package/dist/engine/rgb-ticker.d.ts +17 -0
- package/dist/engine/rgb-ticker.d.ts.map +1 -0
- package/dist/engine/rgb-ticker.js +47 -0
- package/dist/engine/rgb-ticker.js.map +1 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +8 -2
- package/dist/engine.js.map +1 -1
- package/dist/guards.d.ts +12 -0
- package/dist/guards.d.ts.map +1 -1
- package/dist/guards.js +60 -0
- package/dist/guards.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/kaleidoswap/contract.d.ts +7 -0
- package/dist/kaleidoswap/contract.d.ts.map +1 -1
- package/dist/kaleidoswap/contract.js +71 -17
- package/dist/kaleidoswap/contract.js.map +1 -1
- package/dist/kaleidoswap/index.d.ts +1 -1
- package/dist/kaleidoswap/index.d.ts.map +1 -1
- package/dist/kaleidoswap/index.js +1 -1
- package/dist/kaleidoswap/index.js.map +1 -1
- package/dist/qvac/parse.d.ts.map +1 -1
- package/dist/qvac/parse.js +13 -0
- package/dist/qvac/parse.js.map +1 -1
- package/dist/qvac/provider.d.ts.map +1 -1
- package/dist/qvac/provider.js +127 -95
- package/dist/qvac/provider.js.map +1 -1
- package/dist/recipe/asset-send.js +1 -1
- package/dist/recipe/asset-send.js.map +1 -1
- package/dist/testing/mock-wallet.d.ts.map +1 -1
- package/dist/testing/mock-wallet.js +6 -0
- package/dist/testing/mock-wallet.js.map +1 -1
- package/dist/wallet/contract.d.ts +5 -0
- package/dist/wallet/contract.d.ts.map +1 -1
- package/dist/wallet/contract.js +39 -6
- package/dist/wallet/contract.js.map +1 -1
- package/package.json +1 -1
- package/scripts/snapshot-mcp-tools.mjs +38 -0
- package/skills/README.md +98 -64
- package/skills/bitrefill/SKILL.md +30 -157
- package/skills/channel-manager/SKILL.md +31 -52
- package/skills/flashnet-swaps/SKILL.md +24 -150
- package/skills/kaleido-node/SKILL.md +25 -55
- package/skills/kaleido-trading/SKILL.md +28 -172
- package/skills/kaleido-trading/references/assets.md +4 -4
- package/skills/kaleido-trading/references/atomic.md +5 -7
- package/skills/merchant-finder/SKILL.md +25 -108
- package/skills/paid-data/SKILL.md +25 -58
- package/skills/portfolio-manager/SKILL.md +26 -60
- package/skills/rgb-lightning-node/SKILL.md +37 -255
- package/skills/rgb-lightning-node/references/channels.md +34 -0
- package/skills/spark-wallet/SKILL.md +26 -228
- package/skills/submarine-swaps/SKILL.md +19 -37
- package/skills/wallet-assistant/SKILL.md +26 -44
- package/src/engine/answer.ts +26 -2
- package/src/engine/rgb-ticker.test.ts +29 -0
- package/src/engine/rgb-ticker.ts +54 -0
- package/src/engine.ts +16 -2
- package/src/funnel.mind.test.ts +6 -5
- package/src/guards.test.ts +39 -0
- package/src/guards.ts +61 -0
- package/src/index.ts +4 -0
- package/src/kaleidoswap/contract.test.ts +32 -3
- package/src/kaleidoswap/contract.ts +65 -17
- package/src/kaleidoswap/index.ts +1 -0
- package/src/qvac/parse.test.ts +14 -0
- package/src/qvac/parse.ts +11 -0
- package/src/qvac/provider.test.ts +33 -0
- package/src/qvac/provider.ts +37 -4
- package/src/recipe/asset-send.ts +1 -1
- package/src/recipe/recipe.test.ts +1 -1
- package/src/skills/catalog.test.ts +215 -0
- package/src/skills/mcp-tools.snapshot.json +1938 -0
- package/src/testing/mock-wallet.ts +6 -0
- package/src/wallet/contract.test.ts +20 -1
- package/src/wallet/contract.ts +36 -6
- package/skills/dca/SKILL.md +0 -48
- package/skills/kaleido-lsps/SKILL.md +0 -131
- package/skills/liquidity-optimizer/SKILL.md +0 -91
|
@@ -149,6 +149,12 @@ export class MockWallet {
|
|
|
149
149
|
}),
|
|
150
150
|
spark_get_balance: async () => ({ btc_sats: this.balances.spark }),
|
|
151
151
|
rln_get_balances: async () => ({ btc_sats: this.balances.rln, assets: this.assets }),
|
|
152
|
+
rln_get_node_info: async () => ({
|
|
153
|
+
pubkey: '02' + 'ab'.repeat(32),
|
|
154
|
+
num_channels: 0,
|
|
155
|
+
num_usable_channels: 0,
|
|
156
|
+
local_balance_sat: 0,
|
|
157
|
+
}),
|
|
152
158
|
arkade_get_balance: async () => ({ btc_sats: this.balances.arkade }),
|
|
153
159
|
spark_get_address: async () => ({ address: 'bc1qspark0mockreceiveaddr' }),
|
|
154
160
|
arkade_get_address: async () => ({ address: 'ark1q0mockreceiveaddr' }),
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
toToolDefs,
|
|
12
12
|
bindWalletTools,
|
|
13
13
|
getWalletTool,
|
|
14
|
+
normalizeWalletArgs,
|
|
14
15
|
} from './contract.js';
|
|
15
16
|
|
|
16
17
|
describe('WALLET_TOOLS contract', () => {
|
|
@@ -64,7 +65,25 @@ describe('WALLET_TOOLS contract', () => {
|
|
|
64
65
|
it('required args declared on the actionable tools', () => {
|
|
65
66
|
expect((getWalletTool('send_payment')!.parameters as any).required).toContain('to');
|
|
66
67
|
expect((getWalletTool('fiat_to_sats')!.parameters as any).required).toEqual(['amount', 'currency']);
|
|
67
|
-
expect((getWalletTool('
|
|
68
|
+
expect((getWalletTool('rln_send_asset')!.parameters as any).required).toEqual(['asset_id', 'recipient_id', 'amount']);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('normalizeWalletArgs', () => {
|
|
73
|
+
it('fills legacy names for older handlers and canonical names for legacy callers', () => {
|
|
74
|
+
expect(normalizeWalletArgs('rln_send_asset', { asset_id: 'rgb:x', recipient_id: 'utxob:y', amount: 1 }))
|
|
75
|
+
.toEqual({ asset_id: 'rgb:x', asset: 'rgb:x', recipient_id: 'utxob:y', to: 'utxob:y', amount: 1 });
|
|
76
|
+
expect(normalizeWalletArgs('rln_send_asset', { asset: 'USDT', to: 'bob', amount: 2 }))
|
|
77
|
+
.toMatchObject({ asset_id: 'USDT', recipient_id: 'bob' });
|
|
78
|
+
expect(normalizeWalletArgs('get_price', { asset: 'BTC', vs_currency: 'eur' })).toMatchObject({ fiat: 'eur' });
|
|
79
|
+
expect(normalizeWalletArgs('rln_get_balances', { skip_sync: true })).toEqual({ skip_sync: true });
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('bound handlers receive both shapes', async () => {
|
|
83
|
+
let got: Record<string, unknown> = {};
|
|
84
|
+
const src = bindWalletTools({ rln_create_rgb_invoice: async (a) => { got = a; return {}; } }, { layers: ['rln'], includeCore: false, allowMissing: true });
|
|
85
|
+
await src.execute('rln_create_rgb_invoice', { asset_id: 'USDT', amount: 5 });
|
|
86
|
+
expect(got).toMatchObject({ asset_id: 'USDT', asset: 'USDT', amount: 5 });
|
|
68
87
|
});
|
|
69
88
|
});
|
|
70
89
|
|
package/src/wallet/contract.ts
CHANGED
|
@@ -88,11 +88,20 @@ export const WALLET_TOOLS: WalletToolDef[] = [
|
|
|
88
88
|
t('rln', 'rln_get_node_info', 'Get RLN node status and sync state.'),
|
|
89
89
|
t('rln', 'rln_list_channels', 'List the RLN node Lightning channels.'),
|
|
90
90
|
t('rln', 'rln_create_ln_invoice', 'Create a Lightning (BTC) invoice on the RLN node.', { amount_sats: sats }),
|
|
91
|
-
t('rln', 'rln_create_rgb_invoice', 'Create an RGB
|
|
91
|
+
t('rln', 'rln_create_rgb_invoice', 'Create an RGB invoice to receive an asset on-chain. Returns the invoice string to share with the payer.', {
|
|
92
|
+
asset_id: { type: 'string', description: "RGB asset id ('rgb:…'); in-app wallets also accept a ticker. Omit for any asset." },
|
|
93
|
+
amount: { type: 'number', description: 'Expected amount in display units (e.g. 10 for 10 USDT)' },
|
|
94
|
+
duration_seconds: { type: 'number', description: 'Invoice expiry (default 86400)' },
|
|
95
|
+
}),
|
|
92
96
|
t('rln', 'rln_pay_invoice', 'Pay a Lightning invoice from the RLN node.', { invoice: { type: 'string' } }, ['invoice'], true),
|
|
93
|
-
t('rln', 'rln_send_asset', 'Send an RGB asset
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
t('rln', 'rln_send_asset', 'Send an RGB asset to the recipient of an RGB invoice.', {
|
|
98
|
+
asset_id: { type: 'string', description: "RGB asset id ('rgb:…') from rln_list_assets; in-app wallets also accept a ticker." },
|
|
99
|
+
recipient_id: { type: 'string', description: 'Recipient from the RGB invoice: its utxob:/wvout: part, or the whole invoice.' },
|
|
100
|
+
amount: { type: 'number', description: 'Amount in display units (e.g. 10 for 10 USDT)' },
|
|
101
|
+
fee_rate: { type: 'number', description: 'sat/vbyte (default 3)' },
|
|
102
|
+
}, ['asset_id', 'recipient_id', 'amount'], true),
|
|
103
|
+
t('rln', 'rln_list_assets', 'List every RGB asset on the RLN node with its balance (asset_id, ticker, name, precision, balance {settled, future, spendable, offchain_outbound, offchain_inbound} in raw units = display × 10^precision). Answers "what do I hold" in one call.'),
|
|
104
|
+
t('rln', 'rln_get_asset_balance', 'Get the balance of ONE RGB asset by asset_id (settled, future, spendable, off-chain). rln_list_assets already includes every balance.', { asset_id: { type: 'string', description: "RGB asset id, e.g. 'rgb:2JEUOrsc-…'" } }, ['asset_id']),
|
|
96
105
|
t('rln', 'rln_refresh_transfers', 'Refresh pending RGB transfers so balances and transfer status are up to date.'),
|
|
97
106
|
t('rln', 'rln_get_address', 'Get an on-chain BTC address of the RLN node for deposits.'),
|
|
98
107
|
t('rln', 'rln_send_btc', 'Send on-chain BTC from the RLN node.', { address: { type: 'string', description: 'Destination Bitcoin address' }, amount_sat: { type: 'number', description: 'Amount in satoshis' }, fee_rate: { type: 'number', description: 'sat/vbyte (default 3)' } }, ['address', 'amount_sat'], true),
|
|
@@ -141,7 +150,7 @@ export const WALLET_TOOLS: WalletToolDef[] = [
|
|
|
141
150
|
// ── Core: router + helpers ─────────────────────────────────────────────
|
|
142
151
|
t('core', 'get_balances', 'Get balances across all layers (or one layer).', { layer: { type: 'string', enum: ['spark', 'rln', 'arkade', 'liquid'], description: 'Optional: a single layer' } }),
|
|
143
152
|
t('core', 'resolve_contact', 'Resolve a contact name to a Lightning address / Nostr / preferred rail.', { name: { type: 'string', description: 'Contact name, e.g. "bob"' } }, ['name']),
|
|
144
|
-
t('core', 'get_price', 'Get the current price of an asset, optionally in a fiat currency.', { asset,
|
|
153
|
+
t('core', 'get_price', 'Get the current price of an asset, optionally in a fiat currency.', { asset, vs_currency: { type: 'string', description: "Quote currency, e.g. 'usd', 'eur' (default usd)" } }, ['asset']),
|
|
145
154
|
t('core', 'fiat_to_sats', 'Convert a fiat amount to satoshis at the current rate.', { amount: { type: 'number' }, currency: { type: 'string', description: "Fiat code, e.g. 'EUR'" } }, ['amount', 'currency']),
|
|
146
155
|
t('core', 'get_swap_quote', 'Quote a swap between two assets.', { from_asset: asset, to_asset: asset, amount: { type: 'number' } }, ['from_asset', 'to_asset', 'amount']),
|
|
147
156
|
t('core', 'execute_swap', 'Execute a previously quoted swap.', { quote_id: { type: 'string' }, from_asset: asset, to_asset: asset, amount: { type: 'number' } }, [], true),
|
|
@@ -178,6 +187,27 @@ export function toToolDefs(tools: WalletToolDef[]): ToolDef[] {
|
|
|
178
187
|
return tools.map(({ name, description, parameters, requiresConfirmation }) => ({ name, description, parameters, requiresConfirmation }));
|
|
179
188
|
}
|
|
180
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Map kaleido-mcp argument names onto the pre-0.9 contract names (and back), so
|
|
192
|
+
* one call shape works on every surface and older host handlers keep working.
|
|
193
|
+
*/
|
|
194
|
+
export function normalizeWalletArgs(name: string, args: Record<string, unknown>): Record<string, unknown> {
|
|
195
|
+
const a: Record<string, unknown> = { ...args };
|
|
196
|
+
const alias = (canonical: string, legacy: string) => {
|
|
197
|
+
if (a[canonical] == null && a[legacy] != null) a[canonical] = a[legacy];
|
|
198
|
+
if (a[legacy] == null && a[canonical] != null) a[legacy] = a[canonical];
|
|
199
|
+
};
|
|
200
|
+
if (name === 'rln_send_asset') {
|
|
201
|
+
alias('asset_id', 'asset');
|
|
202
|
+
alias('recipient_id', 'to');
|
|
203
|
+
} else if (name === 'rln_create_rgb_invoice') {
|
|
204
|
+
alias('asset_id', 'asset');
|
|
205
|
+
} else if (name === 'get_price') {
|
|
206
|
+
alias('vs_currency', 'fiat');
|
|
207
|
+
}
|
|
208
|
+
return a;
|
|
209
|
+
}
|
|
210
|
+
|
|
181
211
|
/** A handler bound to one contract tool. */
|
|
182
212
|
export type WalletHandler = (args: Record<string, unknown>) => Promise<unknown>;
|
|
183
213
|
|
|
@@ -208,7 +238,7 @@ export function bindWalletTools(handlers: Record<string, WalletHandler>, opts: B
|
|
|
208
238
|
description: def.description,
|
|
209
239
|
parameters: def.parameters,
|
|
210
240
|
requiresConfirmation: def.requiresConfirmation,
|
|
211
|
-
handler,
|
|
241
|
+
handler: (args) => handler(normalizeWalletArgs(def.name, args)),
|
|
212
242
|
});
|
|
213
243
|
}
|
|
214
244
|
return new InProcessToolSource(opts.id ?? 'wallet', bound);
|
package/skills/dca/SKILL.md
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: dca
|
|
3
|
-
description: "Dollar-cost-average a fixed budget into a target asset on a schedule. Reads the live quote and (when allowed) buys a small fixed slice via an atomic swap, respecting per-run allocation and risk limits. Triggers when the user mentions DCA, recurring buys, or averaging in — and is the skill a user-created DCA loop runs."
|
|
4
|
-
tools: rln_get_balances, kaleidoswap_get_quote, kaleidoswap_atomic_init, kaleidoswap_atomic_execute, kaleidoswap_atomic_status, get_price
|
|
5
|
-
triggers: dca, dollar cost average, recurring buy, average in, accumulate, stack
|
|
6
|
-
metadata:
|
|
7
|
-
author: kaleidoswap
|
|
8
|
-
version: "0.1.0"
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Dollar-cost averaging
|
|
12
|
-
|
|
13
|
-
Buy a fixed, small slice of a target asset each run. Boring on purpose: same
|
|
14
|
-
size, every interval, regardless of price.
|
|
15
|
-
|
|
16
|
-
## Critical rules — these override everything else
|
|
17
|
-
|
|
18
|
-
- **Fixed slice only.** The per-run budget is the task's `allocation` — never
|
|
19
|
-
exceed it, never "catch up" by buying extra after a missed run.
|
|
20
|
-
- **Respect `dry_run`.** When true, quote and report what you *would* buy; do NOT
|
|
21
|
-
execute.
|
|
22
|
-
- **Respect risk + reserve.** A DCA buy is a spend; it passes through the host's
|
|
23
|
-
risk gate. Never breach the BTC reserve or the max single-spend limit.
|
|
24
|
-
|
|
25
|
-
## Each run
|
|
26
|
-
|
|
27
|
-
1. **Check funds.** `rln_get_balances` — is there enough BTC for one slice plus
|
|
28
|
-
the reserve? If not, return `action: "skip"` with the reason.
|
|
29
|
-
2. **Quote.** `kaleidoswap_get_quote(BTC, <asset>, <slice>)`. Read the
|
|
30
|
-
`to_amount_display` / `fee_display` strings verbatim — no arithmetic.
|
|
31
|
-
3. **Execute** (only when `dry_run` is false and within limits): the atomic swap
|
|
32
|
-
recipe drives `kaleidoswap_atomic_init` → `_execute`; then poll
|
|
33
|
-
`kaleidoswap_atomic_status`.
|
|
34
|
-
|
|
35
|
-
## Scheduled (background) runs
|
|
36
|
-
|
|
37
|
-
Return STRICT JSON only:
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
{"task":"<task id>","timestamp":"<ISO8601>","action":"buy|skip","dry_run":<bool>,"reason":"<why>","details":{"asset":"<asset>","slice":"<n>","received":"<display>","fee":"<display>"}}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Don'ts
|
|
44
|
-
|
|
45
|
-
- Don't vary the slice size or try to time the market — that's not DCA.
|
|
46
|
-
- Don't buy when funds are below the reserve — `skip` instead.
|
|
47
|
-
- Don't execute when `dry_run` is true.
|
|
48
|
-
- Don't invent a quote — only the current `kaleidoswap_get_quote` result is real.
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: kaleido-lsps
|
|
3
|
-
description: "Buy inbound Lightning channel capacity from a Lightning Service Provider (LSPS1). Quote a channel, estimate fees, place a channel order, and check order status. Triggers when the user wants inbound liquidity, says they can't receive a payment, needs a channel, asks about LSP fees, or wants to check the status of a channel order / LSP order."
|
|
4
|
-
tools: lsp_get_info, lsp_get_network_info, lsp_estimate_fees, lsp_create_order, lsp_get_order, kaleidoswap_lsp_get_info, kaleidoswap_lsp_estimate_fees, kaleidoswap_lsp_create_order, kaleidoswap_lsp_get_order, kaleidoswap_lsp_quote_asset_channel, kaleidoswap_lsp_create_asset_channel, rln_get_node_info, rln_list_channels, rln_pay_invoice
|
|
5
|
-
triggers: inbound, liquidity, channel order, lsp, lsps1, receive limit, can't receive, open channel, channel from, check status, order status, check the order, channel status, lsp status, check my channel, check lsp order, did the channel open, lsp order status, list my channels, my channels, channel capacity
|
|
6
|
-
metadata:
|
|
7
|
-
author: kaleidoswap
|
|
8
|
-
version: "0.2.0"
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Lightning channel orders (LSPS1)
|
|
12
|
-
|
|
13
|
-
Buy inbound Lightning channel capacity from a Lightning Service Provider when
|
|
14
|
-
the user can't receive a payment, wants a bigger receive limit, or just wants
|
|
15
|
-
to open a new channel from the LSP. The host binds these to whichever LSP it
|
|
16
|
-
talks to — the KaleidoSwap maker by default. Tool names are LSP-agnostic
|
|
17
|
-
(`lsp_*`), so the same skill works against any LSPS1-compliant LSP.
|
|
18
|
-
|
|
19
|
-
## Critical rules — these override everything else
|
|
20
|
-
|
|
21
|
-
You have **no knowledge** of LSP capabilities, fees, channel sizes, or order
|
|
22
|
-
status. Every number, capacity, fee, order id, or invoice in your reply MUST
|
|
23
|
-
come from a tool result returned in the CURRENT turn. Never quote a fee from
|
|
24
|
-
memory. Never claim an order completed without calling `kaleidoswap_lsp_get_order`.
|
|
25
|
-
Never reuse a number from a previous turn.
|
|
26
|
-
|
|
27
|
-
**Calling the tool IS the answer.** Don't write "the LSP info is fetched with
|
|
28
|
-
`kaleidoswap_lsp_get_info`" — call it. Don't reveal tool names in your reply; describe
|
|
29
|
-
what you're doing in plain language.
|
|
30
|
-
|
|
31
|
-
If a tool needs a required argument the user didn't give (e.g. `client_pubkey`
|
|
32
|
-
when creating an order — get it from `rln_get_node_info`), resolve it via the
|
|
33
|
-
appropriate read tool. Don't ask the user for a pubkey.
|
|
34
|
-
|
|
35
|
-
## Asset codes
|
|
36
|
-
|
|
37
|
-
The same conventions as trading apply:
|
|
38
|
-
- `BTC` (sats) — the default for "inbound liquidity" / "channel capacity".
|
|
39
|
-
- `USDT` / `XAUT` — for RGB asset channels (uses `asset_id` + `lsp_asset_amount`).
|
|
40
|
-
|
|
41
|
-
## Tools and the flow
|
|
42
|
-
|
|
43
|
-
### Step 1 — `kaleidoswap_lsp_get_info`
|
|
44
|
-
No args. Returns the LSP's `OrderOptions` (min/max channel size, min/max
|
|
45
|
-
expiry, etc.) and the `assets` list. **Call it once before estimating** so you
|
|
46
|
-
can validate the user's request against the LSP's limits.
|
|
47
|
-
|
|
48
|
-
If the user wants 1M sats inbound but `max_initial_lsp_balance_sat` is 500k,
|
|
49
|
-
say so plainly and offer the maximum — don't push through and let the maker
|
|
50
|
-
reject it.
|
|
51
|
-
|
|
52
|
-
### Step 2 — `kaleidoswap_lsp_estimate_fees` (read-only)
|
|
53
|
-
Required args: `lsp_balance_sat`, `client_balance_sat`, `channel_expiry_blocks`.
|
|
54
|
-
|
|
55
|
-
Defaults you can use silently if the user didn't specify:
|
|
56
|
-
- `client_balance_sat: 0` (pure inbound order — most common)
|
|
57
|
-
- `channel_expiry_blocks: 4320` (~30 days)
|
|
58
|
-
|
|
59
|
-
Returns `{setup_fee, capacity_fee, duration_fee, total_fee}` — surface
|
|
60
|
-
`total_fee` to the user and the breakdown when relevant.
|
|
61
|
-
|
|
62
|
-
### Step 3 — `rln_get_node_info`
|
|
63
|
-
No args. Returns `{pubkey, ...}`. **Pubkey is required by `kaleidoswap_lsp_create_order` —
|
|
64
|
-
fetch it deterministically. Never invent a pubkey.**
|
|
65
|
-
|
|
66
|
-
### Step 4 — `kaleidoswap_lsp_create_order` 🔒 spend
|
|
67
|
-
Required args: `client_pubkey` (from step 3), `lsp_balance_sat`. The maker
|
|
68
|
-
also expects `client_balance_sat`, `required_channel_confirmations`,
|
|
69
|
-
`funding_confirms_within_blocks`, `channel_expiry_blocks`, `announce_channel`
|
|
70
|
-
— the host adapter fills sensible defaults (1, 6, 4320, true) when the user
|
|
71
|
-
didn't specify, so just pass the values the user actually named.
|
|
72
|
-
|
|
73
|
-
Returns:
|
|
74
|
-
- `order_id`
|
|
75
|
-
- `access_token` (save it — required for `kaleidoswap_lsp_get_order`)
|
|
76
|
-
- `payment.bolt11.invoice` — Lightning invoice to pay
|
|
77
|
-
- `payment.bolt11.order_total_sat` — the sats that need to flow
|
|
78
|
-
- `payment.onchain.address` — optional on-chain fallback
|
|
79
|
-
- `order_state: "CREATED"`
|
|
80
|
-
|
|
81
|
-
### Step 5 — Pay the invoice with `rln_pay_invoice`
|
|
82
|
-
Hand the `payment.bolt11.invoice` to `rln_pay_invoice`. This is a separate
|
|
83
|
-
spend gate at the wallet contract; the user confirms paying the LSP.
|
|
84
|
-
|
|
85
|
-
### Verify the opened channel — `rln_list_channels`
|
|
86
|
-
After an order completes (or when the user asks "do I have a channel with X
|
|
87
|
-
inbound?", "list my channels", "did my channel open?"), call
|
|
88
|
-
`rln_list_channels`. It returns each channel's `capacity_sat`, `inbound_sat`,
|
|
89
|
-
`outbound_sat`, `ready`/`status`, and RGB `asset_*` amounts. Match the
|
|
90
|
-
requested capacity against an actual channel to confirm it opened correctly.
|
|
91
|
-
A freshly-bought channel opens ASYNCHRONOUSLY — if it isn't listed yet, say
|
|
92
|
-
it's still opening, don't claim failure. Do NOT use `rln_get_node_info` for
|
|
93
|
-
this (it only has counts + aggregate balance, not per-channel capacity).
|
|
94
|
-
|
|
95
|
-
### Step 6 — poll the order (`lsp_get_order` / `kaleidoswap_lsp_get_order`)
|
|
96
|
-
Use `lsp_get_order` on CLI hosts, `kaleidoswap_lsp_get_order` on desktop —
|
|
97
|
-
whichever your host exposes. **Args: `order_id`, `access_token` (BOTH
|
|
98
|
-
required — never omit either).** `order_state` progresses
|
|
99
|
-
`CREATED → CHANNEL_OPENING → COMPLETED` (or `FAILED`). Poll until terminal.
|
|
100
|
-
Always pass the exact order_id and access_token from the previous
|
|
101
|
-
create-order result **or from the most recent assistant message/summary**
|
|
102
|
-
(the one that said something like "order_id=xxx access_token=yyy" or "To
|
|
103
|
-
check status use: lsp_get_order(order_id=..., access_token=...)"). If
|
|
104
|
-
memory/remember is available, first recall the last LSPS1 order details.
|
|
105
|
-
Report the outcome plainly with the new channel id from `channel.channel_id` if present.
|
|
106
|
-
|
|
107
|
-
## Don'ts
|
|
108
|
-
|
|
109
|
-
- Don't invent capacity, fees, pubkeys, order_ids, or invoices.
|
|
110
|
-
- Don't reuse a number from a previous turn — re-estimate when parameters
|
|
111
|
-
change (different size or expiry).
|
|
112
|
-
- Don't describe how a tool works — call it.
|
|
113
|
-
- Don't pay a Lightning invoice without confirming the amount + LSP — the
|
|
114
|
-
spend gate at `rln_pay_invoice` shows the user the destination.
|
|
115
|
-
- Don't claim an order completed without polling `kaleidoswap_lsp_get_order` with BOTH
|
|
116
|
-
`order_id` and `access_token` and seeing `order_state: COMPLETED`.
|
|
117
|
-
- Never call `kaleidoswap_lsp_get_order` with only the access_token or only the order_id.
|
|
118
|
-
Always extract the exact values from the previous turn's summary (the one that
|
|
119
|
-
said "order_id=... access_token=..." or the explicit "To check status use..." line)
|
|
120
|
-
and pass them as separate arguments. If using the `remember` tool, first recall
|
|
121
|
-
the last channel/LSPS1 order details.
|
|
122
|
-
- Don't ask the user for their node pubkey — fetch it from `rln_get_node_info`.
|
|
123
|
-
|
|
124
|
-
## When the deterministic recipe handles it
|
|
125
|
-
|
|
126
|
-
For requests like "I need 500k inbound" or "buy a channel from the LSP", the
|
|
127
|
-
`kaleidoswap-channel-order` recipe drives the whole chain (get_info →
|
|
128
|
-
estimate_fees → get_node_info → create_order → pay_invoice) with a single
|
|
129
|
-
confirmation gate showing the real fee. Use the agentic flow here only when
|
|
130
|
-
the recipe didn't fire — typically for read-only questions ("what does the
|
|
131
|
-
LSP offer?") or partial flows ("estimate fees for 200k inbound").
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: liquidity-optimizer
|
|
3
|
-
description: "Analyze and optimize the node's Lightning liquidity. Reads channels, balances and payment history, then explains the node's liquidity health and recommends concrete actions: buy inbound, open/close channels, rebalance BTC↔assets, or tune routing fees. Triggers when the user wants to rebalance, optimize liquidity, fix inbound/outbound balance, free up capital, lower fees, or asks 'how healthy is my node?' / 'where is my liquidity?'."
|
|
4
|
-
tools: rln_list_channels, rln_get_balances, rln_get_node_info, rln_list_payments, kaleidoswap_lsp_get_info, kaleidoswap_lsp_estimate_fees, kaleidoswap_lsp_quote_asset_channel, rln_open_channel, rln_close_channel
|
|
5
|
-
triggers: rebalance, rebalancing, optimize liquidity, liquidity, inbound, outbound, lopsided, depleted channel, free up capital, stuck funds, channel balance, routing fee, lower fees, fee optimization, node health, healthy node, where is my liquidity, capacity
|
|
6
|
-
metadata:
|
|
7
|
-
author: kaleidoswap
|
|
8
|
-
version: "0.1.0"
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Liquidity optimizer
|
|
12
|
-
|
|
13
|
-
Help the user keep their RGB Lightning node's liquidity healthy: balanced
|
|
14
|
-
inbound/outbound, capital not stuck in dead channels, and fees set so the node
|
|
15
|
-
can actually route and receive. You **analyze real channel state and recommend
|
|
16
|
-
actions** — you never move funds without an explicit, confirmed instruction.
|
|
17
|
-
|
|
18
|
-
## Critical rules — these override everything else
|
|
19
|
-
|
|
20
|
-
You have **no knowledge** of the node's channels, balances, or capacity. Every
|
|
21
|
-
number, channel id, ratio, or fee in your reply MUST come from a tool result
|
|
22
|
-
returned in the CURRENT turn. Never quote a balance from memory or reuse a
|
|
23
|
-
number from a previous turn — re-read it.
|
|
24
|
-
|
|
25
|
-
**Calling the tool IS the analysis.** Don't say "I'd check your channels with
|
|
26
|
-
`rln_list_channels`" — call it, then report what it returned in plain language.
|
|
27
|
-
Don't reveal raw tool names in your reply.
|
|
28
|
-
|
|
29
|
-
**Read freely, spend never (without confirmation).** `rln_list_channels`,
|
|
30
|
-
`rln_get_balances`, `rln_get_node_info`, `rln_list_payments`,
|
|
31
|
-
`kaleidoswap_lsp_get_info`, and `kaleidoswap_lsp_estimate_fees` are read-only —
|
|
32
|
-
use them as much as you need. `rln_open_channel`, `rln_close_channel`, and
|
|
33
|
-
buying a channel are **spends**: only call them when the user explicitly asked
|
|
34
|
-
for that action this turn, and each goes through the wallet's confirmation gate.
|
|
35
|
-
When you merely *recommend* an action, describe it — do not execute it.
|
|
36
|
-
|
|
37
|
-
## How to assess liquidity
|
|
38
|
-
|
|
39
|
-
### 1 — Read the state (always start here)
|
|
40
|
-
- `rln_list_channels` → `channel_count`, `total_outbound_msat`,
|
|
41
|
-
`total_inbound_msat`, and per-channel `outbound_balance_msat`,
|
|
42
|
-
`inbound_balance_msat`, `is_usable`, capacity, peer, and any RGB asset
|
|
43
|
-
allocation. **Balances are in millisats (msat); divide by 1000 for sats.**
|
|
44
|
-
- `rln_get_balances` → on-chain (vanilla/colored) + Lightning balance, to see
|
|
45
|
-
uncommitted capital that could open a channel.
|
|
46
|
-
- `rln_get_node_info` → pubkey, peer/channel counts, sync state.
|
|
47
|
-
- `rln_list_payments` (optional) → recent flow direction, to infer whether the
|
|
48
|
-
node mostly sends or receives.
|
|
49
|
-
|
|
50
|
-
### 2 — Compute the picture (per channel and overall)
|
|
51
|
-
For each channel, the **outbound ratio** = `outbound / (outbound + inbound)`:
|
|
52
|
-
- **~0% (all inbound):** can receive but can't send — depleted outbound.
|
|
53
|
-
- **~100% (all outbound):** can send but can't receive — no inbound liquidity.
|
|
54
|
-
- **40–60%:** balanced and healthy.
|
|
55
|
-
Then look at the totals: is the node short on **inbound** (can't receive) or
|
|
56
|
-
short on **outbound** (can't send)? Flag channels that are `is_usable: false`
|
|
57
|
-
(offline/pending peer) or that hold meaningful capital but never route.
|
|
58
|
-
|
|
59
|
-
### 3 — Recommend, prioritized
|
|
60
|
-
Lead with a one-line health verdict, then a short ordered action list. Match the
|
|
61
|
-
remedy to the problem:
|
|
62
|
-
- **Low inbound / "can't receive":** buy inbound from the LSP. Use
|
|
63
|
-
`kaleidoswap_lsp_get_info` for limits and `kaleidoswap_lsp_estimate_fees`
|
|
64
|
-
(or `kaleidoswap_lsp_quote_asset_channel` for an asset channel) to give a real
|
|
65
|
-
fee, then hand off to the channel-order flow. Don't invent the fee.
|
|
66
|
-
- **Low outbound / "can't send":** open a channel to a well-connected peer with
|
|
67
|
-
spare on-chain BTC (`rln_open_channel`), or fund the wallet first.
|
|
68
|
-
- **Lopsided but funded both ways:** rebalance instead of opening new channels —
|
|
69
|
-
for BTC↔asset imbalance, suggest a swap (the trading flow), since circular
|
|
70
|
-
rebalancing may not be available on this node.
|
|
71
|
-
- **Dead/offline channels with stuck capital:** consider closing
|
|
72
|
-
(`rln_close_channel`) to reclaim funds, but only if the user confirms — note
|
|
73
|
-
on-chain fees and the ~hours for funds to settle.
|
|
74
|
-
- **Fees:** if the node should route more, suggest lower routing fees; if it's
|
|
75
|
-
draining outbound cheaply, suggest raising them. If no fee-setting tool is
|
|
76
|
-
available this turn, give the recommendation and tell the user where to set it
|
|
77
|
-
rather than pretending you changed it.
|
|
78
|
-
|
|
79
|
-
## Output style
|
|
80
|
-
Concise and scannable. A verdict line, then "Top actions" as a short numbered
|
|
81
|
-
list with the concrete number behind each (e.g. "Channel abc12… is 97% outbound
|
|
82
|
-
— buy ~200k inbound, est. fee from the LSP"). No walls of JSON.
|
|
83
|
-
|
|
84
|
-
## Don'ts
|
|
85
|
-
- Don't invent channels, balances, ratios, capacities, or fees — read them.
|
|
86
|
-
- Don't forget msat→sat conversion when reporting channel balances.
|
|
87
|
-
- Don't open or close a channel, or buy liquidity, unless the user asked for
|
|
88
|
-
that action this turn — recommendations are not actions.
|
|
89
|
-
- Don't claim you changed fees or rebalanced if no tool did it — say what the
|
|
90
|
-
user should do.
|
|
91
|
-
- Don't reuse last turn's numbers — re-read before advising again.
|