@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.
Files changed (134) hide show
  1. package/README.md +45 -8
  2. package/dist/bridge/index.js +4 -4
  3. package/dist/config/contracts.d.ts +4 -4
  4. package/dist/config/contracts.js +2 -2
  5. package/dist/config/networks.js +4 -1
  6. package/dist/endpoints/registry.d.ts +8 -26
  7. package/dist/endpoints/registry.js +7 -932
  8. package/dist/index.js +118 -42
  9. package/dist/services/stacking.service.d.ts +144 -45
  10. package/dist/services/stacking.service.js +416 -123
  11. package/dist/services/x402-discovery.service.d.ts +81 -0
  12. package/dist/services/x402-discovery.service.js +170 -0
  13. package/dist/tools/arxiv-research.tools.d.ts +1 -1
  14. package/dist/tools/arxiv-research.tools.js +6 -6
  15. package/dist/tools/at-stake-legion.tools.d.ts +1 -1
  16. package/dist/tools/at-stake-legion.tools.js +14 -14
  17. package/dist/tools/at-stake.tools.d.ts +1 -1
  18. package/dist/tools/at-stake.tools.js +17 -17
  19. package/dist/tools/bitcoin.tools.d.ts +1 -1
  20. package/dist/tools/bitcoin.tools.js +12 -12
  21. package/dist/tools/bitflow.tools.d.ts +1 -1
  22. package/dist/tools/bitflow.tools.js +21 -21
  23. package/dist/tools/bns.tools.d.ts +1 -1
  24. package/dist/tools/bns.tools.js +18 -18
  25. package/dist/tools/bounty-hint.d.ts +1 -1
  26. package/dist/tools/bounty-scanner.tools.d.ts +1 -1
  27. package/dist/tools/bounty-scanner.tools.js +20 -20
  28. package/dist/tools/child-inscription.tools.d.ts +1 -1
  29. package/dist/tools/child-inscription.tools.js +6 -6
  30. package/dist/tools/competition.tools.d.ts +1 -1
  31. package/dist/tools/competition.tools.js +4 -4
  32. package/dist/tools/contract.tools.d.ts +1 -1
  33. package/dist/tools/contract.tools.js +8 -8
  34. package/dist/tools/credentials.tools.d.ts +1 -1
  35. package/dist/tools/credentials.tools.js +8 -8
  36. package/dist/tools/defi.tools.d.ts +1 -1
  37. package/dist/tools/defi.tools.js +21 -21
  38. package/dist/tools/dual-stacking.tools.d.ts +1 -1
  39. package/dist/tools/dual-stacking.tools.js +7 -7
  40. package/dist/tools/earning.tools.d.ts +1 -1
  41. package/dist/tools/earning.tools.js +5 -5
  42. package/dist/tools/endpoint.tools.d.ts +1 -1
  43. package/dist/tools/endpoint.tools.js +92 -49
  44. package/dist/tools/identity.tools.d.ts +1 -1
  45. package/dist/tools/identity.tools.js +19 -19
  46. package/dist/tools/inbox-x402.tools.d.ts +1 -1
  47. package/dist/tools/inbox-x402.tools.js +2 -2
  48. package/dist/tools/inbox.tools.d.ts +1 -1
  49. package/dist/tools/inbox.tools.js +2 -2
  50. package/dist/tools/index.d.ts +6 -3
  51. package/dist/tools/index.js +69 -58
  52. package/dist/tools/inference-marketplace.tools.d.ts +1 -1
  53. package/dist/tools/inference-marketplace.tools.js +10 -10
  54. package/dist/tools/jingswap.tools.d.ts +1 -1
  55. package/dist/tools/jingswap.tools.js +30 -30
  56. package/dist/tools/legion.tools.d.ts +1 -1
  57. package/dist/tools/legion.tools.js +20 -20
  58. package/dist/tools/lightning.tools.d.ts +1 -1
  59. package/dist/tools/lightning.tools.js +14 -14
  60. package/dist/tools/mempool.tools.d.ts +1 -1
  61. package/dist/tools/mempool.tools.js +5 -5
  62. package/dist/tools/news.tools.d.ts +1 -1
  63. package/dist/tools/news.tools.js +2 -1
  64. package/dist/tools/nft.tools.d.ts +1 -1
  65. package/dist/tools/nft.tools.js +12 -12
  66. package/dist/tools/nonce.tools.d.ts +1 -1
  67. package/dist/tools/nonce.tools.js +8 -8
  68. package/dist/tools/nostr.tools.d.ts +1 -1
  69. package/dist/tools/nostr.tools.js +12 -12
  70. package/dist/tools/openrouter.tools.d.ts +1 -1
  71. package/dist/tools/openrouter.tools.js +4 -4
  72. package/dist/tools/ordinals-marketplace.tools.d.ts +1 -1
  73. package/dist/tools/ordinals-marketplace.tools.js +10 -10
  74. package/dist/tools/ordinals-p2p.tools.d.ts +1 -1
  75. package/dist/tools/ordinals-p2p.tools.js +18 -18
  76. package/dist/tools/ordinals.tools.d.ts +1 -1
  77. package/dist/tools/ordinals.tools.js +8 -8
  78. package/dist/tools/pillar-direct.tools.d.ts +1 -1
  79. package/dist/tools/pillar-direct.tools.js +59 -38
  80. package/dist/tools/pillar.tools.d.ts +1 -1
  81. package/dist/tools/pillar.tools.js +28 -26
  82. package/dist/tools/profiles.d.ts +51 -0
  83. package/dist/tools/profiles.js +111 -0
  84. package/dist/tools/psbt.tools.d.ts +1 -1
  85. package/dist/tools/psbt.tools.js +8 -8
  86. package/dist/tools/query.tools.d.ts +1 -1
  87. package/dist/tools/query.tools.js +12 -12
  88. package/dist/tools/relay-diagnostic.tools.d.ts +1 -1
  89. package/dist/tools/relay-diagnostic.tools.js +3 -3
  90. package/dist/tools/reputation.tools.d.ts +1 -1
  91. package/dist/tools/reputation.tools.js +22 -22
  92. package/dist/tools/runes.tools.d.ts +1 -1
  93. package/dist/tools/runes.tools.js +18 -18
  94. package/dist/tools/sbtc.tools.d.ts +1 -1
  95. package/dist/tools/sbtc.tools.js +14 -33
  96. package/dist/tools/scaffold.tools.d.ts +1 -1
  97. package/dist/tools/scaffold.tools.js +4 -4
  98. package/dist/tools/settings.tools.d.ts +1 -1
  99. package/dist/tools/settings.tools.js +9 -9
  100. package/dist/tools/signing.tools.d.ts +1 -1
  101. package/dist/tools/signing.tools.js +20 -20
  102. package/dist/tools/skill-mappings.js +4 -0
  103. package/dist/tools/souldinals.tools.d.ts +1 -1
  104. package/dist/tools/souldinals.tools.js +10 -10
  105. package/dist/tools/stacking-lottery.tools.d.ts +1 -1
  106. package/dist/tools/stacking-lottery.tools.js +11 -11
  107. package/dist/tools/stacking.tools.d.ts +1 -1
  108. package/dist/tools/stacking.tools.js +358 -50
  109. package/dist/tools/stacks-market.tools.d.ts +1 -1
  110. package/dist/tools/stacks-market.tools.js +22 -22
  111. package/dist/tools/styx.tools.d.ts +1 -1
  112. package/dist/tools/styx.tools.js +11 -11
  113. package/dist/tools/taproot-multisig.tools.d.ts +1 -1
  114. package/dist/tools/taproot-multisig.tools.js +5 -5
  115. package/dist/tools/tenero.tools.d.ts +1 -1
  116. package/dist/tools/tenero.tools.js +22 -22
  117. package/dist/tools/tokens.tools.d.ts +1 -1
  118. package/dist/tools/tokens.tools.js +10 -10
  119. package/dist/tools/transfer.tools.d.ts +1 -1
  120. package/dist/tools/transfer.tools.js +4 -4
  121. package/dist/tools/wallet-management.tools.d.ts +1 -1
  122. package/dist/tools/wallet-management.tools.js +16 -16
  123. package/dist/tools/wallet.tools.d.ts +1 -1
  124. package/dist/tools/wallet.tools.js +2 -2
  125. package/dist/tools/yield-dashboard.tools.d.ts +1 -1
  126. package/dist/tools/yield-dashboard.tools.js +18 -27
  127. package/dist/tools/yield-hunter.tools.d.ts +1 -1
  128. package/dist/tools/yield-hunter.tools.js +6 -6
  129. package/dist/utils/bitcoin.d.ts +8 -0
  130. package/dist/utils/bitcoin.js +24 -0
  131. package/dist/utils/fee.js +1 -1
  132. package/package.json +8 -7
  133. package/skill/SKILL.md +1 -1
  134. 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 { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
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(network) {
71
+ function serverEntry(env) {
68
72
  return {
69
73
  command: "npx",
70
74
  args: ["-y", SERVER_NPM],
71
- env: { NETWORK: network },
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, network) {
80
+ async function writeMcpServersJson(configPath, env) {
77
81
  const config = await readJsonConfig(configPath);
78
82
  const servers = (config.mcpServers ??= {});
79
- servers["aibtc"] = serverEntry(network);
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, network) {
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: { NETWORK: network },
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, network) {
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
- `NETWORK = "${network}"`,
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
- await target.write(configPath, network);
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("\n📋 Next steps:");
202
- console.log(` 1. ${target.restart}`);
203
- console.log(" 2. Ask the agent: \"What's your wallet address?\"");
204
- console.log(" 3. The agent will guide you through wallet setup\n");
205
- if (network === "testnet") {
206
- console.log("💡 Tip: Get testnet STX at https://explorer.hiro.so/sandbox/faucet?chain=testnet\n");
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
- const server = new McpServer({
255
- name: "aibtc-mcp-server",
256
- version: packageJson.version,
257
- }, {
258
- instructions: [
259
- "This server lets an agent earn and move real Bitcoin/sBTC on Stacks.",
260
- "",
261
- "Hunt bounties. The most direct way to earn here is the sBTC bounty board:",
262
- "call bounty_list to see open bounties, bounty_get for the task detail, do",
263
- "the work, then bounty_submit your deliverable. Accepted submissions are paid",
264
- "in sBTC. Check periodically for new open bounties.",
265
- "",
266
- "For the full menu of ways to put assets to work (stacking, DeFi yield,",
267
- "trading, paid endpoints), call earning_opportunities. Submitting to a bounty",
268
- "requires a Registered (L1+) on-chain identity — see identity_register.",
269
- ].join("\n"),
270
- });
271
- // Append a bounty-board hint to spend/onboarding-tool output.
272
- // Must wrap registerTool before registration; restore it after.
273
- const restoreBountyHint = installBountyHint(server);
274
- // Register all tools from the modular registry
275
- registerAllTools(server);
276
- restoreBountyHint();
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
- const transport = new StdioServerTransport();
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
- import { PoxInfo } from "./hiro-api.js";
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
- export interface StackingStatus {
5
- stacked: boolean;
6
- amountMicroStx: string;
7
- amountStx: string;
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
- lockPeriod: number;
10
- unlockHeight: number;
11
- poxAddress?: string;
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 contracts;
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
- * Get current PoX (Proof of Transfer) info
20
- */
21
- getPoxInfo(): Promise<PoxInfo>;
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
- revokeDelegation(account: Account): Promise<TransferResult>;
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