@aibtc/mcp-server 1.70.1 → 1.72.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 +45 -8
- package/dist/bridge/index.js +4 -4
- package/dist/config/contracts.d.ts +4 -4
- package/dist/config/contracts.js +2 -2
- package/dist/config/networks.js +4 -1
- package/dist/endpoints/registry.d.ts +8 -26
- package/dist/endpoints/registry.js +7 -932
- package/dist/index.js +118 -42
- package/dist/services/stacking.service.d.ts +144 -45
- package/dist/services/stacking.service.js +416 -123
- package/dist/services/x402-discovery.service.d.ts +81 -0
- package/dist/services/x402-discovery.service.js +170 -0
- package/dist/tools/arxiv-research.tools.d.ts +1 -1
- package/dist/tools/arxiv-research.tools.js +6 -6
- package/dist/tools/at-stake-legion.tools.d.ts +1 -1
- package/dist/tools/at-stake-legion.tools.js +14 -14
- package/dist/tools/at-stake.tools.d.ts +1 -1
- package/dist/tools/at-stake.tools.js +17 -17
- package/dist/tools/bitcoin.tools.d.ts +1 -1
- package/dist/tools/bitcoin.tools.js +12 -12
- package/dist/tools/bitflow.tools.d.ts +1 -1
- package/dist/tools/bitflow.tools.js +21 -21
- package/dist/tools/bns.tools.d.ts +1 -1
- package/dist/tools/bns.tools.js +18 -18
- package/dist/tools/bounty-hint.d.ts +1 -1
- package/dist/tools/bounty-scanner.tools.d.ts +1 -1
- package/dist/tools/bounty-scanner.tools.js +20 -20
- package/dist/tools/child-inscription.tools.d.ts +1 -1
- package/dist/tools/child-inscription.tools.js +6 -6
- package/dist/tools/competition.tools.d.ts +1 -1
- package/dist/tools/competition.tools.js +4 -4
- package/dist/tools/contract.tools.d.ts +1 -1
- package/dist/tools/contract.tools.js +8 -8
- package/dist/tools/credentials.tools.d.ts +1 -1
- package/dist/tools/credentials.tools.js +8 -8
- package/dist/tools/defi.tools.d.ts +1 -1
- package/dist/tools/defi.tools.js +21 -21
- package/dist/tools/dual-stacking.tools.d.ts +1 -1
- package/dist/tools/dual-stacking.tools.js +7 -7
- package/dist/tools/earning.tools.d.ts +1 -1
- package/dist/tools/earning.tools.js +5 -5
- package/dist/tools/endpoint.tools.d.ts +1 -1
- package/dist/tools/endpoint.tools.js +92 -49
- package/dist/tools/identity.tools.d.ts +1 -1
- package/dist/tools/identity.tools.js +19 -19
- package/dist/tools/inbox-x402.tools.d.ts +1 -1
- package/dist/tools/inbox-x402.tools.js +2 -2
- package/dist/tools/inbox.tools.d.ts +1 -1
- package/dist/tools/inbox.tools.js +2 -2
- package/dist/tools/index.d.ts +6 -3
- package/dist/tools/index.js +69 -58
- package/dist/tools/inference-marketplace.tools.d.ts +1 -1
- package/dist/tools/inference-marketplace.tools.js +10 -10
- package/dist/tools/jingswap.tools.d.ts +1 -1
- package/dist/tools/jingswap.tools.js +30 -30
- package/dist/tools/legion.tools.d.ts +1 -1
- package/dist/tools/legion.tools.js +20 -20
- package/dist/tools/lightning.tools.d.ts +1 -1
- package/dist/tools/lightning.tools.js +14 -14
- package/dist/tools/mempool.tools.d.ts +1 -1
- package/dist/tools/mempool.tools.js +5 -5
- package/dist/tools/news.tools.d.ts +1 -1
- package/dist/tools/news.tools.js +2 -1
- package/dist/tools/nft.tools.d.ts +1 -1
- package/dist/tools/nft.tools.js +12 -12
- package/dist/tools/nonce.tools.d.ts +1 -1
- package/dist/tools/nonce.tools.js +8 -8
- package/dist/tools/nostr.tools.d.ts +1 -1
- package/dist/tools/nostr.tools.js +12 -12
- package/dist/tools/openrouter.tools.d.ts +1 -1
- package/dist/tools/openrouter.tools.js +4 -4
- package/dist/tools/ordinals-marketplace.tools.d.ts +1 -1
- package/dist/tools/ordinals-marketplace.tools.js +10 -10
- package/dist/tools/ordinals-p2p.tools.d.ts +1 -1
- package/dist/tools/ordinals-p2p.tools.js +18 -18
- package/dist/tools/ordinals.tools.d.ts +1 -1
- package/dist/tools/ordinals.tools.js +8 -8
- package/dist/tools/pillar-direct.tools.d.ts +1 -1
- package/dist/tools/pillar-direct.tools.js +59 -38
- package/dist/tools/pillar.tools.d.ts +1 -1
- package/dist/tools/pillar.tools.js +28 -26
- package/dist/tools/profiles.d.ts +51 -0
- package/dist/tools/profiles.js +111 -0
- package/dist/tools/psbt.tools.d.ts +1 -1
- package/dist/tools/psbt.tools.js +8 -8
- package/dist/tools/query.tools.d.ts +1 -1
- package/dist/tools/query.tools.js +12 -12
- package/dist/tools/relay-diagnostic.tools.d.ts +1 -1
- package/dist/tools/relay-diagnostic.tools.js +3 -3
- package/dist/tools/reputation.tools.d.ts +1 -1
- package/dist/tools/reputation.tools.js +22 -22
- package/dist/tools/runes.tools.d.ts +1 -1
- package/dist/tools/runes.tools.js +18 -18
- package/dist/tools/sbtc.tools.d.ts +1 -1
- package/dist/tools/sbtc.tools.js +14 -33
- package/dist/tools/scaffold.tools.d.ts +1 -1
- package/dist/tools/scaffold.tools.js +4 -4
- package/dist/tools/settings.tools.d.ts +1 -1
- package/dist/tools/settings.tools.js +9 -9
- package/dist/tools/signing.tools.d.ts +1 -1
- package/dist/tools/signing.tools.js +20 -20
- package/dist/tools/skill-mappings.js +4 -0
- package/dist/tools/souldinals.tools.d.ts +1 -1
- package/dist/tools/souldinals.tools.js +10 -10
- package/dist/tools/stacking-lottery.tools.d.ts +1 -1
- package/dist/tools/stacking-lottery.tools.js +11 -11
- package/dist/tools/stacking.tools.d.ts +1 -1
- package/dist/tools/stacking.tools.js +358 -50
- package/dist/tools/stacks-market.tools.d.ts +1 -1
- package/dist/tools/stacks-market.tools.js +22 -22
- package/dist/tools/styx.tools.d.ts +1 -1
- package/dist/tools/styx.tools.js +11 -11
- package/dist/tools/taproot-multisig.tools.d.ts +1 -1
- package/dist/tools/taproot-multisig.tools.js +5 -5
- package/dist/tools/tenero.tools.d.ts +1 -1
- package/dist/tools/tenero.tools.js +22 -22
- package/dist/tools/tokens.tools.d.ts +1 -1
- package/dist/tools/tokens.tools.js +10 -10
- package/dist/tools/transfer.tools.d.ts +1 -1
- package/dist/tools/transfer.tools.js +4 -4
- package/dist/tools/wallet-management.tools.d.ts +1 -1
- package/dist/tools/wallet-management.tools.js +16 -16
- package/dist/tools/wallet.tools.d.ts +1 -1
- package/dist/tools/wallet.tools.js +2 -2
- package/dist/tools/yield-dashboard.tools.d.ts +1 -1
- package/dist/tools/yield-dashboard.tools.js +18 -27
- package/dist/tools/yield-hunter.tools.d.ts +1 -1
- package/dist/tools/yield-hunter.tools.js +6 -6
- package/dist/utils/bitcoin.d.ts +8 -0
- package/dist/utils/bitcoin.js +24 -0
- package/dist/utils/fee.js +1 -1
- package/package.json +8 -7
- package/skill/SKILL.md +1 -1
- package/skill/references/stacks-defi.md +1 -1
package/dist/index.js
CHANGED
|
@@ -4,13 +4,17 @@ import fs from "fs/promises";
|
|
|
4
4
|
import path from "path";
|
|
5
5
|
import os from "os";
|
|
6
6
|
import { createRequire } from "module";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { randomBytes } from "crypto";
|
|
8
|
+
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
9
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
9
10
|
import { registerAllTools } from "./tools/index.js";
|
|
11
|
+
import { describeSelection, resolveToolSelection } from "./tools/profiles.js";
|
|
10
12
|
import { installBountyHint } from "./tools/bounty-hint.js";
|
|
11
13
|
import { NETWORK, API_URL } from "./config/index.js";
|
|
12
14
|
import { redactSensitive } from "./utils/redact.js";
|
|
13
15
|
import { initializeStorage } from "./utils/storage.js";
|
|
16
|
+
import { getWalletManager } from "./services/wallet-manager.js";
|
|
17
|
+
import { getLightningManager } from "./services/lightning-manager.js";
|
|
14
18
|
const require = createRequire(import.meta.url);
|
|
15
19
|
const packageJson = require("../package.json");
|
|
16
20
|
// =============================================================================
|
|
@@ -64,30 +68,30 @@ async function writeJsonConfig(filePath, config) {
|
|
|
64
68
|
await fs.writeFile(filePath, JSON.stringify(config, null, 2));
|
|
65
69
|
}
|
|
66
70
|
// Standard MCP server entry shared by every JSON-based client config.
|
|
67
|
-
function serverEntry(
|
|
71
|
+
function serverEntry(env) {
|
|
68
72
|
return {
|
|
69
73
|
command: "npx",
|
|
70
74
|
args: ["-y", SERVER_NPM],
|
|
71
|
-
env
|
|
75
|
+
env,
|
|
72
76
|
};
|
|
73
77
|
}
|
|
74
78
|
// Most clients (Claude Code, Claude Desktop, Cursor, Windsurf, Gemini CLI) use
|
|
75
79
|
// the same `{ "mcpServers": { "aibtc": {...} } }` JSON shape.
|
|
76
|
-
async function writeMcpServersJson(configPath,
|
|
80
|
+
async function writeMcpServersJson(configPath, env) {
|
|
77
81
|
const config = await readJsonConfig(configPath);
|
|
78
82
|
const servers = (config.mcpServers ??= {});
|
|
79
|
-
servers["aibtc"] = serverEntry(
|
|
83
|
+
servers["aibtc"] = serverEntry(env);
|
|
80
84
|
await writeJsonConfig(configPath, config);
|
|
81
85
|
}
|
|
82
86
|
// VS Code (.vscode/mcp.json) uses a `servers` key and a typed stdio entry.
|
|
83
|
-
async function writeVsCodeJson(configPath,
|
|
87
|
+
async function writeVsCodeJson(configPath, env) {
|
|
84
88
|
const config = await readJsonConfig(configPath);
|
|
85
89
|
const servers = (config.servers ??= {});
|
|
86
90
|
servers["aibtc"] = {
|
|
87
91
|
type: "stdio",
|
|
88
92
|
command: "npx",
|
|
89
93
|
args: ["-y", SERVER_NPM],
|
|
90
|
-
env
|
|
94
|
+
env,
|
|
91
95
|
};
|
|
92
96
|
await writeJsonConfig(configPath, config);
|
|
93
97
|
}
|
|
@@ -106,7 +110,7 @@ function stripCodexSection(content) {
|
|
|
106
110
|
}
|
|
107
111
|
return out.join("\n");
|
|
108
112
|
}
|
|
109
|
-
async function writeCodexToml(configPath,
|
|
113
|
+
async function writeCodexToml(configPath, env) {
|
|
110
114
|
let existing = "";
|
|
111
115
|
try {
|
|
112
116
|
existing = await fs.readFile(configPath, "utf8");
|
|
@@ -123,7 +127,7 @@ async function writeCodexToml(configPath, network) {
|
|
|
123
127
|
`args = ["-y", "${SERVER_NPM}"]`,
|
|
124
128
|
"",
|
|
125
129
|
"[mcp_servers.aibtc.env]",
|
|
126
|
-
|
|
130
|
+
...Object.entries(env).map(([key, value]) => `${key} = "${value}"`),
|
|
127
131
|
].join("\n");
|
|
128
132
|
const content = (preserved ? `${preserved}\n\n` : "") + block + "\n";
|
|
129
133
|
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
@@ -188,23 +192,86 @@ function resolveInstallTarget() {
|
|
|
188
192
|
// Default to the entry explicitly marked as default (flag === null) — Claude Code.
|
|
189
193
|
return matched[0] ?? INSTALL_TARGETS.find((t) => t.flag === null);
|
|
190
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Create the agent's wallet during install so a fresh user can fund it right
|
|
197
|
+
* away. The generated password and the mnemonic are printed once and not
|
|
198
|
+
* stored in plain text; the password can be changed with wallet_rotate_password.
|
|
199
|
+
* Returns the Stacks address of the new or already-existing wallet.
|
|
200
|
+
*/
|
|
201
|
+
async function ensureInstallWallet(network) {
|
|
202
|
+
await initializeStorage();
|
|
203
|
+
const walletManager = getWalletManager();
|
|
204
|
+
const existing = (await walletManager.listWallets()).find((w) => w.network === network);
|
|
205
|
+
if (existing) {
|
|
206
|
+
console.log(`\n👛 Existing ${network} wallet kept: ${existing.name} (${existing.address})`);
|
|
207
|
+
return existing.address;
|
|
208
|
+
}
|
|
209
|
+
const password = randomBytes(18).toString("base64url");
|
|
210
|
+
const wallet = await walletManager.createWallet("main", password, network);
|
|
211
|
+
// Print the credentials before anything else can fail: the wallet is already
|
|
212
|
+
// on disk, and without the password it can never be unlocked.
|
|
213
|
+
console.log(`\n👛 Wallet created (${network}), stored encrypted in ~/.aibtc/`);
|
|
214
|
+
console.log(` Stacks: ${wallet.address}`);
|
|
215
|
+
if (wallet.btcAddress)
|
|
216
|
+
console.log(` Bitcoin: ${wallet.btcAddress}`);
|
|
217
|
+
console.log(`\n Password: ${password}`);
|
|
218
|
+
console.log(` Mnemonic: ${wallet.mnemonic}`);
|
|
219
|
+
console.log("\n⚠️ Write both down now. They are shown once and the password is not saved anywhere.");
|
|
220
|
+
console.log(" The password unlocks the wallet; change it any time by asking your agent to rotate it.");
|
|
221
|
+
console.log(" The mnemonic is the only way to recover the wallet and its funds.");
|
|
222
|
+
// Same unified setup as wallet_create: a Lightning wallet derived from the
|
|
223
|
+
// same mnemonic (mainnet only). Its failure is reported, the main wallet stands.
|
|
224
|
+
try {
|
|
225
|
+
const lightning = await getLightningManager().setupFromMainMnemonic(wallet.mnemonic, password, "main", network);
|
|
226
|
+
if (lightning.kind === "setup") {
|
|
227
|
+
console.log(` Lightning: ${lightning.depositAddress} (deposit address, same mnemonic)`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
console.error(` Lightning setup failed: ${redactSensitive(error instanceof Error ? error.message : String(error))}. ` +
|
|
232
|
+
"Ask your agent to run lightning_create later.");
|
|
233
|
+
}
|
|
234
|
+
return wallet.address;
|
|
235
|
+
}
|
|
191
236
|
async function runInstall() {
|
|
192
237
|
const network = process.argv.includes("--testnet") ? "testnet" : "mainnet";
|
|
238
|
+
// Only --profile full installs everything; resolving against AIBTC_TOOLS=core
|
|
239
|
+
// also validates the flag.
|
|
240
|
+
const fullProfile = resolveToolSelection(process.argv, { AIBTC_TOOLS: "core" }).all;
|
|
193
241
|
const target = resolveInstallTarget();
|
|
194
242
|
const configPath = target.configPath();
|
|
195
243
|
console.log(`🔧 Installing @aibtc/mcp-server to ${target.label}...\n`);
|
|
196
|
-
|
|
244
|
+
const env = { NETWORK: network };
|
|
245
|
+
env.AIBTC_TOOLS = fullProfile ? "all" : "core";
|
|
246
|
+
await target.write(configPath, env);
|
|
197
247
|
console.log("✅ Successfully installed!\n");
|
|
198
248
|
console.log(` Client: ${target.label}`);
|
|
199
249
|
console.log(` Config: ${configPath}`);
|
|
200
250
|
console.log(` Network: ${network}`);
|
|
201
|
-
console.log("
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if (
|
|
206
|
-
|
|
251
|
+
console.log(` Tools: ${fullProfile ? "all" : "lean core (set AIBTC_TOOLS=core,defi,ordinals,... in the env, or re-run with --profile full)"}`);
|
|
252
|
+
// The wallet's password and mnemonic are printed once, so only create it when
|
|
253
|
+
// a person is reading the terminal, never into a pipe, file or CI log.
|
|
254
|
+
let address = null;
|
|
255
|
+
if (process.argv.includes("--no-wallet")) {
|
|
256
|
+
// Explicitly skipped
|
|
257
|
+
}
|
|
258
|
+
else if (!process.stdout.isTTY) {
|
|
259
|
+
console.log("\n👛 Wallet not created: output is not a terminal, and the password and mnemonic");
|
|
260
|
+
console.log(" are only ever printed to one. Re-run --install in a terminal, or ask the agent to create one.");
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
address = await ensureInstallWallet(network);
|
|
207
264
|
}
|
|
265
|
+
console.log(`\n📋 ${target.restart}, then try:`);
|
|
266
|
+
const fund = network === "testnet"
|
|
267
|
+
? "testnet STX from https://explorer.hiro.so/sandbox/faucet?chain=testnet"
|
|
268
|
+
: "0.01 STX";
|
|
269
|
+
console.log(address
|
|
270
|
+
? ` 1. Send ${fund} to ${address}`
|
|
271
|
+
: ` 1. Ask your agent: "What's your wallet address?" and send it ${fund}`);
|
|
272
|
+
console.log(` 2. Ask your agent: "Unlock my wallet" and give it the password`);
|
|
273
|
+
const x402Host = network === "testnet" ? "x402.aibtc.dev" : "x402.aibtc.com";
|
|
274
|
+
console.log(` 3. Ask it: "Make a paid inference call on ${x402Host}" (0.001 STX per call)\n`);
|
|
208
275
|
}
|
|
209
276
|
// =============================================================================
|
|
210
277
|
// YIELD HUNTER DAEMON
|
|
@@ -251,36 +318,45 @@ else if (process.argv.includes("--install") || process.argv.includes("install"))
|
|
|
251
318
|
}
|
|
252
319
|
else {
|
|
253
320
|
// Normal MCP server mode
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
"
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
321
|
+
// One instance per connection. serveStdio picks the protocol era from the
|
|
322
|
+
// opening message (2025-era `initialize` or a 2026-07-28 envelope) and pins
|
|
323
|
+
// the instance built by this factory to the connection.
|
|
324
|
+
function createServer(toolSelection) {
|
|
325
|
+
const server = new McpServer({
|
|
326
|
+
name: "aibtc-mcp-server",
|
|
327
|
+
version: packageJson.version,
|
|
328
|
+
}, {
|
|
329
|
+
instructions: [
|
|
330
|
+
"This server lets an agent earn and move real Bitcoin/sBTC on Stacks.",
|
|
331
|
+
"",
|
|
332
|
+
"Hunt bounties. The most direct way to earn here is the sBTC bounty board:",
|
|
333
|
+
"call bounty_list to see open bounties, bounty_get for the task detail, do",
|
|
334
|
+
"the work, then bounty_submit your deliverable. Accepted submissions are paid",
|
|
335
|
+
"in sBTC. Check periodically for new open bounties.",
|
|
336
|
+
"",
|
|
337
|
+
"For the full menu of ways to put assets to work (stacking, DeFi yield,",
|
|
338
|
+
"trading, paid endpoints), call earning_opportunities. Submitting to a bounty",
|
|
339
|
+
"requires a Registered (L1+) on-chain identity — see identity_register.",
|
|
340
|
+
"",
|
|
341
|
+
describeSelection(toolSelection),
|
|
342
|
+
].join("\n"),
|
|
343
|
+
});
|
|
344
|
+
// Append a bounty-board hint to spend/onboarding-tool output.
|
|
345
|
+
// Must wrap registerTool before registration; restore it after.
|
|
346
|
+
const restoreBountyHint = installBountyHint(server);
|
|
347
|
+
// Register all tools from the modular registry
|
|
348
|
+
registerAllTools(server, toolSelection);
|
|
349
|
+
restoreBountyHint();
|
|
350
|
+
return server;
|
|
351
|
+
}
|
|
277
352
|
async function main() {
|
|
353
|
+
const toolSelection = resolveToolSelection();
|
|
278
354
|
await initializeStorage();
|
|
279
|
-
|
|
280
|
-
await server.connect(transport);
|
|
355
|
+
serveStdio(() => createServer(toolSelection), { onerror: (error) => console.error("MCP error:", redactSensitive(String(error))) });
|
|
281
356
|
console.error("aibtc-mcp-server running on stdio");
|
|
282
357
|
console.error(`Network: ${NETWORK}`);
|
|
283
358
|
console.error(`API URL: ${API_URL}`);
|
|
359
|
+
console.error(`Tools: ${toolSelection.all ? "all" : ["core", ...toolSelection.groups].join(", ")}`);
|
|
284
360
|
}
|
|
285
361
|
main().catch((error) => {
|
|
286
362
|
console.error("Fatal error:", redactSensitive(String(error)));
|
|
@@ -1,58 +1,157 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* PoX-5 stacking.
|
|
3
|
+
*
|
|
4
|
+
* PoX-5 replaced pox-4 at reward cycle 141 on mainnet, and it is not a rename:
|
|
5
|
+
*
|
|
6
|
+
* - Every stake names a SIGNER MANAGER, a contract implementing pox-5's
|
|
7
|
+
* `signer-manager-trait`. There is no pool delegation (`delegate-stx`) and no
|
|
8
|
+
* PoX reward address on the stake itself; the manager's `validate-stake!`
|
|
9
|
+
* decides who may join and reads any payout preferences out of
|
|
10
|
+
* `signer-calldata`.
|
|
11
|
+
* - Rewards are paid in sBTC to the signer manager, not the staker. Getting a
|
|
12
|
+
* staker paid takes the manager pulling its share out of pox-5
|
|
13
|
+
* (`manager.claim-rewards`) and then paying the staker
|
|
14
|
+
* (`manager.claim-staker-rewards`). Each manager implements that second step
|
|
15
|
+
* its own way, and some pay out off-chain, so the claim path is read from the
|
|
16
|
+
* manager's interface rather than assumed.
|
|
17
|
+
* - `stake`, `stake-update` and `unstake` are refused during the prepare phase
|
|
18
|
+
* (the last `prepare-cycle-length` blocks of a cycle).
|
|
19
|
+
*
|
|
20
|
+
* Locking STX is not a transfer, so these calls carry pox-5's own post-condition
|
|
21
|
+
* types (a staking lock amount, or "performs PoX") rather than STX transfer
|
|
22
|
+
* conditions, and they are not metered against the spend limit.
|
|
23
|
+
*/
|
|
2
24
|
import { type Network } from "../config/index.js";
|
|
3
25
|
import { type Account, type TransferResult } from "../transactions/builder.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
26
|
+
/** pox-5 `MAX_NUM_CYCLES`. */
|
|
27
|
+
export declare const MAX_STAKE_CYCLES = 96;
|
|
28
|
+
export interface PoxState {
|
|
29
|
+
contractId: string;
|
|
30
|
+
burnHeight: number;
|
|
31
|
+
rewardCycle: number;
|
|
32
|
+
firstBurnHeight: number;
|
|
33
|
+
rewardCycleLength: number;
|
|
34
|
+
prepareCycleLength: number;
|
|
35
|
+
/** Burn height where the next reward cycle begins. */
|
|
36
|
+
nextCycleStartHeight: number;
|
|
37
|
+
/** Burn height where this cycle's prepare phase begins. */
|
|
38
|
+
preparePhaseStartHeight: number;
|
|
39
|
+
inPreparePhase: boolean;
|
|
40
|
+
/** Minimum a signer needs delegated to join the signer set (not a per-staker minimum). */
|
|
41
|
+
signerSetMinUstx: bigint;
|
|
42
|
+
totalLiquidSupplyUstx: bigint;
|
|
43
|
+
}
|
|
44
|
+
export interface StakerInfo {
|
|
45
|
+
amountUstx: bigint;
|
|
8
46
|
firstRewardCycle: number;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
47
|
+
numCycles: number;
|
|
48
|
+
/** First cycle in which the STX is unlocked. */
|
|
49
|
+
unlockCycle: number;
|
|
50
|
+
unlockBurnHeight: number;
|
|
51
|
+
signerManager: string;
|
|
52
|
+
}
|
|
53
|
+
export interface BondMembership {
|
|
54
|
+
bondIndex: number;
|
|
55
|
+
amountUstx: bigint;
|
|
56
|
+
amountSats: bigint;
|
|
57
|
+
isL1Lock: boolean;
|
|
58
|
+
signerManager: string;
|
|
59
|
+
}
|
|
60
|
+
export interface StakingStatus {
|
|
61
|
+
address: string;
|
|
62
|
+
pox: PoxState;
|
|
63
|
+
staking: StakerInfo | null;
|
|
64
|
+
bond: BondMembership | null;
|
|
65
|
+
account: {
|
|
66
|
+
balanceUstx: bigint;
|
|
67
|
+
lockedUstx: bigint;
|
|
68
|
+
unlockedUstx: bigint;
|
|
69
|
+
burnchainUnlockHeight: number;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export interface SignerSetEntry {
|
|
73
|
+
signerManager: string;
|
|
74
|
+
delegatedUstx: bigint;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* How a signer manager pays its stakers, read from its public interface.
|
|
78
|
+
* - `staker-arg`: `claim-staker-rewards(staker, reward-cycle, bond-index)`, callable by anyone
|
|
79
|
+
* - `caller`: `claim-staker-rewards(reward-cycle, bond-index)`, pays the caller
|
|
80
|
+
* - `none`: no on-chain staker claim (the manager pays off-chain, or not at all)
|
|
81
|
+
*/
|
|
82
|
+
export type ClaimStyle = "staker-arg" | "caller" | "none";
|
|
83
|
+
export interface StakeOptions {
|
|
84
|
+
signerManager: string;
|
|
85
|
+
amountUstx: bigint;
|
|
86
|
+
numCycles: number;
|
|
87
|
+
signerCalldata?: Uint8Array;
|
|
12
88
|
}
|
|
89
|
+
export interface UpdateStakeOptions {
|
|
90
|
+
/** New signer manager; defaults to the current one. */
|
|
91
|
+
signerManager?: string;
|
|
92
|
+
cyclesToExtend: number;
|
|
93
|
+
amountIncreaseUstx: bigint;
|
|
94
|
+
signerCalldata?: Uint8Array;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Payout calldata in the shape reference signer managers decode:
|
|
98
|
+
* `{ pox-addr: { version, hashbytes }, max-fee }`. Managers derived from the
|
|
99
|
+
* pox-5 reference implementation use it to pay rewards to a Bitcoin address via
|
|
100
|
+
* an sBTC withdrawal, capped at `max-fee` sats of withdrawal fee. Whether a given
|
|
101
|
+
* manager accepts it is up to that manager's `validate-stake!`.
|
|
102
|
+
*/
|
|
103
|
+
export declare function buildPayoutCalldata(poxAddr: {
|
|
104
|
+
version: number;
|
|
105
|
+
hashbytesHex: string;
|
|
106
|
+
}, maxFeeSats: bigint): Uint8Array;
|
|
13
107
|
export declare class StackingService {
|
|
14
108
|
private network;
|
|
15
109
|
private hiro;
|
|
16
|
-
private
|
|
110
|
+
private poxContract;
|
|
17
111
|
constructor(network: Network);
|
|
112
|
+
get contractId(): string;
|
|
113
|
+
private read;
|
|
114
|
+
private readPox;
|
|
115
|
+
getPoxState(): Promise<PoxState>;
|
|
116
|
+
private rewardCycleStartHeight;
|
|
117
|
+
getStakerInfo(address: string, pox?: PoxState): Promise<StakerInfo | null>;
|
|
118
|
+
getBondMembership(address: string): Promise<BondMembership | null>;
|
|
119
|
+
getStakingStatus(address: string): Promise<StakingStatus>;
|
|
120
|
+
/** Whether pox-5 has a signer key registered for this manager. */
|
|
121
|
+
isRegisteredSigner(signerManager: string): Promise<boolean>;
|
|
122
|
+
/** Walk pox-5's signer-set linked list for a reward cycle. */
|
|
123
|
+
getSignerSet(cycle: number): Promise<SignerSetEntry[]>;
|
|
124
|
+
getClaimStyle(signerManager: string): Promise<ClaimStyle>;
|
|
125
|
+
/** sBTC the staker has earned from this signer for a cycle and not yet claimed (before manager fees). */
|
|
126
|
+
getStakerUnclaimedRewards(signerManager: string, rewardCycle: number, staker: string): Promise<bigint>;
|
|
127
|
+
/** sBTC pox-5 still holds for the signer manager for a cycle (not yet pulled by the manager). */
|
|
128
|
+
getSignerUnpulledRewards(signerManager: string, rewardCycle: number): Promise<bigint>;
|
|
129
|
+
private assertNotPreparePhase;
|
|
130
|
+
stake(account: Account, options: StakeOptions): Promise<TransferResult & {
|
|
131
|
+
pox: PoxState;
|
|
132
|
+
unlockCycle: number;
|
|
133
|
+
unlockBurnHeight: number;
|
|
134
|
+
}>;
|
|
135
|
+
updateStake(account: Account, options: UpdateStakeOptions): Promise<TransferResult & {
|
|
136
|
+
previous: StakerInfo;
|
|
137
|
+
newAmountUstx: bigint;
|
|
138
|
+
signerManager: string;
|
|
139
|
+
unlockCycle: number;
|
|
140
|
+
unlockBurnHeight: number;
|
|
141
|
+
}>;
|
|
142
|
+
unstake(account: Account): Promise<TransferResult & {
|
|
143
|
+
previous: StakerInfo;
|
|
144
|
+
unlockCycle: number;
|
|
145
|
+
unlockBurnHeight: number;
|
|
146
|
+
}>;
|
|
18
147
|
/**
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Get stacking status for an address
|
|
24
|
-
* Note: Returns whether the address is stacking, but detailed amounts require proper CV parsing
|
|
25
|
-
*/
|
|
26
|
-
getStackingStatus(address: string): Promise<StackingStatus>;
|
|
27
|
-
/**
|
|
28
|
-
* Stack STX tokens
|
|
29
|
-
*/
|
|
30
|
-
stack(account: Account, amount: bigint, poxAddress: {
|
|
31
|
-
version: number;
|
|
32
|
-
hashbytes: string;
|
|
33
|
-
}, startBurnHeight: number, lockPeriod: number): Promise<TransferResult>;
|
|
34
|
-
/**
|
|
35
|
-
* Extend stacking period
|
|
36
|
-
*/
|
|
37
|
-
extendStacking(account: Account, extendCount: number, poxAddress: {
|
|
38
|
-
version: number;
|
|
39
|
-
hashbytes: string;
|
|
40
|
-
}): Promise<TransferResult>;
|
|
41
|
-
/**
|
|
42
|
-
* Increase stacking amount
|
|
43
|
-
*/
|
|
44
|
-
increaseStacking(account: Account, increaseAmount: bigint): Promise<TransferResult>;
|
|
45
|
-
/**
|
|
46
|
-
* Delegate STX to a stacking pool
|
|
47
|
-
*/
|
|
48
|
-
delegateStx(account: Account, amount: bigint, delegateTo: string, untilBurnHeight?: number, poxAddress?: {
|
|
49
|
-
version: number;
|
|
50
|
-
hashbytes: string;
|
|
51
|
-
}): Promise<TransferResult>;
|
|
52
|
-
/**
|
|
53
|
-
* Revoke delegation
|
|
148
|
+
* Have the signer manager pull its STX-staking rewards for a cycle out of pox-5.
|
|
149
|
+
* Permissionless on reference managers. An empty bond-period list claims the
|
|
150
|
+
* STX-staker bucket only, which is all an STX staker's payout draws on.
|
|
54
151
|
*/
|
|
55
|
-
|
|
152
|
+
pullSignerRewards(account: Account, signerManager: string, rewardCycle: number, unpulledSats: bigint): Promise<TransferResult>;
|
|
153
|
+
/** Pay this staker their share of a cycle's rewards through the signer manager. */
|
|
154
|
+
claimStakerRewards(account: Account, signerManager: string, rewardCycle: number, style: Exclude<ClaimStyle, "none">): Promise<TransferResult>;
|
|
56
155
|
}
|
|
57
156
|
export declare function getStackingService(network: Network): StackingService;
|
|
58
157
|
//# sourceMappingURL=stacking.service.d.ts.map
|