Skip to main content
Glama

get_htlc

Retrieve per-leg HTLC settlement state for a trade: lock status, chain, timelock, and preimage reveal. Returns an array of HTLC legs; empty array means no HTLC recorded.

Instructions

Real-time trade observability — per-leg HTLC settlement state for a trade: which legs are locked, on which chain, with what timelock, and whether the preimage has been revealed. Read-only, safe to call at any time.

Returns an ARRAY of HTLC legs (one entry per locked leg, typically the initiator leg and the counterparty leg). An empty array means no HTLC has been recorded for this tradeId yet (or the tradeId does not exist) — treat empty as "nothing locked", not an error.

USE WHEN: showing trade/settlement status to the user, deciding the next settlement action (lock / claim / refund), polling for the counterparty leg, or rebuilding state after losing context. DO NOT USE WHEN: you need RFQ/quote status (this is settlement-leg state only) — use list_my_trades or list_open_rfqs instead.

INTERPRETING THE RESULT (per leg): role = INITIATOR | COUNTERPARTY; status = leg lifecycle; chainType = evm | bitcoin | sui; timelock = unix expiry of that leg; preimage non-null on a claimed initiator leg. Both legs ACTIVE = swap can complete (claim path). Initiator leg past timelock with counterparty leg absent = refund path.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tradeIdYesTrade ID to query HTLC legs for. An unknown ID returns an empty array, not an error.

Implementation Reference

  • src/index.ts:125-144 (registration)
    Registration of the 'get_htlc' tool via server.tool(). Registers the name, description, schema (tradeId: z.string()), and the handler.
    server.tool(
      'get_htlc',
      [
        'Real-time trade observability — per-leg HTLC settlement state for a trade: which legs are locked, on which chain, with what timelock, and whether the preimage has been revealed. Read-only, safe to call at any time.',
        '',
        'Returns an ARRAY of HTLC legs (one entry per locked leg, typically the initiator leg and the counterparty leg). An empty array means no HTLC has been recorded for this tradeId yet (or the tradeId does not exist) — treat empty as "nothing locked", not an error.',
        '',
        'USE WHEN: showing trade/settlement status to the user, deciding the next settlement action (lock / claim / refund), polling for the counterparty leg, or rebuilding state after losing context.',
        'DO NOT USE WHEN: you need RFQ/quote status (this is settlement-leg state only) — use list_my_trades or list_open_rfqs instead.',
        '',
        'INTERPRETING THE RESULT (per leg): `role` = INITIATOR | COUNTERPARTY; `status` = leg lifecycle; `chainType` = evm | bitcoin | sui; `timelock` = unix expiry of that leg; `preimage` non-null on a claimed initiator leg. Both legs ACTIVE = swap can complete (claim path). Initiator leg past `timelock` with counterparty leg absent = refund path.',
      ].join('\n'),
      {
        tradeId: z.string().describe('Trade ID to query HTLC legs for. An unknown ID returns an empty array, not an error.'),
      },
      wrapTool(async ({ tradeId }) => {
        const result = await hl.getHTLCs(tradeId);
        return okContent(result);
      }),
    );
  • Input schema for get_htlc: a single 'tradeId' string parameter described as 'Trade ID to query HTLC legs for.'
    {
      tradeId: z.string().describe('Trade ID to query HTLC legs for. An unknown ID returns an empty array, not an error.'),
    },
  • Handler function for get_htlc. Calls hl.getHTLCs(tradeId) via the @hashlock-tech/sdk and wraps the result using okContent().
    wrapTool(async ({ tradeId }) => {
      const result = await hl.getHTLCs(tradeId);
      return okContent(result);
    }),
  • okContent helper used by the handler to serialize the result as JSON text content.
    export function okContent(value: unknown): ToolContent {
      return { content: [{ type: 'text', text: JSON.stringify(value, null, 2) }] };
    }
  • wrapTool helper used to wrap the handler, converting thrown errors into structured error envelopes.
    export function wrapTool<A extends unknown[]>(
      handler: (...args: A) => Promise<ToolContent>,
    ): (...args: A) => Promise<ToolContent> {
      return async (...args: A) => {
        try {
          return await handler(...args);
        } catch (err) {
          return toErrorEnvelope(err);
        }
      };
    }
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses read-only nature and safety to call anytime. Explains empty array behavior for unknown tradeId (not an error), and details the structure and interpretation of the result array. Since no annotations exist, the description carries the full burden and excels.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured into sections (purpose, returns, usage, interpretation). Some verbosity in the interpretation section, but every sentence adds value. Front-loaded key info effectively.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Highly complete: covers purpose, return format, edge cases, interpretation per leg, and usage guidance. Despite no output schema, the description compensates thoroughly for a one-parameter query tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a clear description for tradeId. The description repeats the empty-array behavior already in the schema, adding no new parameter-level meaning. Thus baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly specifies 'Real-time trade observability — per-leg HTLC settlement state for a trade' with specific details on what is returned. Distinguishes from sibling tools like list_my_trades and list_open_rfqs by stating it covers settlement-leg state only.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit 'USE WHEN' scenarios (showing trade status, deciding next action, polling) and a 'DO NOT USE WHEN' section naming alternative tools, guiding appropriate invocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Hashlock-Tech/hashlock-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server