Skip to content

Latest commit

 

History

37 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hashlock Markets SDK

Official TypeScript and Python SDKs for the Hashlock Markets developer API — non-custodial cross-chain atomic swaps (BTC ↔ EVM / TRON / Solana) over sealed RFQ + HTLC.

📖 Documentation: docs.hashlock.markets — concepts, quickstart, guides and the API reference. For agents: llms.txt (index), llms-full.txt (everything in one file), any page as Markdown by adding .md, and a docs-search MCP server at https://docs.hashlock.markets/mcp.

⚠️ Preview (0.x), pre-launch. The SDK defaults to the production API (api.hashlock.markets), which is not open yet; pass baseUrl to target another deployment. The API surface may still change before the stable 1.0 release, which will accompany launch.

  • Non-custodial. Settlement endpoints return unsigned transactions. You sign with your own key or HSM; the server never holds your keys.
  • Native, no bridge. Real BTC ↔ real EVM/TRON/Solana assets, settled directly via HTLC — no wrapped tokens, no bridge, no custody of principal.
  • One API, two roles. Takers post RFQs; makers quote them; both settle their legs with the same builders. Plus webhooks and a maker WebSocket feed.
Package Language Install
typescript/ TypeScript / JS (Node 18+, browsers, edge) npm i @hashlock-tech/sdk
python/ Python 3.9+ pip install hashlock-sdk
examples/ Quickstarts + Fireblocks/Copper signing reference —

Upgrading to 0.5.0

Solana is a settlement rail here now, and two older shapes were wrong:

  • BtcWitnessBuild is gone. Bitcoin claims and refunds answer with BtcSighashBuild — a PSBT and one sighash per swept input — which is what the API has returned since 13 August. Sign each sighash and pass { psbtBase64, signaturesHex, preimageHex? } back to broadcast('bitcoin', …).
  • TronBuild.family is 'tvm', not 'tron'. A family === 'tron' branch never ran. The chain name in broadcast('tron', …) is unchanged — that route has its own vocabulary.

New: SolanaBuild (sign: 'solana-tx'), broadcast('solana', signedBase64), and feePayTo / feeAmountSats on a Bitcoin funding build — pay both or the leg does not count as funded.

Quick start (TypeScript)

import { HashlockClient, newSecret } from '@hashlock-tech/sdk';

const client = new HashlockClient({ apiKey: process.env.HASHLOCK_API_KEY! }); // hk_test_… / hk_live_…

const assets = await client.assets();
const btc = assets.find((a) => a.symbol === 'BTC')!;
const usdt = assets.find((a) => a.chain === 'ethereum' && a.symbol === 'USDT')!;

// Taker: sell BTC for USDT (funds the long leg → is the initiator).
const rfq = await client.createRfq({
  direction: 'sell_base',
  baseAssetId: btc.id,
  baseAmount: '10000', // sats
  quoteAssetId: usdt.id,
  ttlSeconds: 3600,
});

// …a maker quotes it, both accept (the initiator passes hashlock = sha256(secret)),
// then each side funds/claims its leg with the unsigned-tx builders.
const { hashlock } = await newSecret();

See examples/quickstart.ts for the full lifecycle, and examples/fireblocks for signing the unsigned transactions with a custody provider.

How a swap works

  1. RFQ → quote → accept. A taker posts an RFQ; a maker quotes it (opening a negotiation thread); both accept the terms. The initiator (whoever funds the long-timelock leg) generates a secret locally and submits only hashlock = sha256(secret). When both accept, the swap is created.
  2. Addresses. Each side sets its receive (payout) / refund address per leg (setSwapAddress; pass the leg, 'a' or 'b', when both legs are on one chain). Bitcoin uses the compressed pubkey — the server derives the P2WSH.
  3. Fund. The initiator funds the long leg; the counterparty funds the short leg. Each buildFund call returns an unsigned transaction — you sign and broadcast. Funding is EVM txs, a Bitcoin payment, a Solana transaction or TRON txs; claiming and refunding hand Bitcoin back as PSBT sighashes.
  4. Claim. The initiator claims the short leg with the secret — revealing it on-chain. The counterparty reads the secret and claims the long leg. Atomic: both legs settle, or both refund after their timelocks.

The same sha256(secret) hashlock binds every leg; asymmetric timelocks (long leg ≫ short leg) remove the free-option/griefing risk.

Core surface

  • Auth: API key (Authorization: Bearer hk_… or X-Api-Key), scopes read | taker | maker. Keys expire after 90 days. Create one at /developers, or with no browser by a wallet signature: GET /v1/keys/nonce, then POST /v1/keys (see /v1/docs). A wallet-only account holds one key (a new signed mint replaces it); an account signed up with email, Google or Telegram holds up to 10.
  • Payout addresses: an address that receives money must be a wallet the account signed in with, or proved from a signed-in web session. A proof made with the API key (POST /v1/wallets/<chain>) widens what you can trade but does not count — a leaked key cannot redirect your money.
  • Market: assets(), listRfqs() / rfqs() (cursor-paginated), getRfq(), createRfq(), quoteRfq().
  • Negotiation: getThread(), proposeTerms(), acceptProposal(), acceptTerms().
  • Swaps: listSwaps() / swaps(), getSwap(), setSwapAddress().
  • Settlement (unsigned): buildFund(), buildClaim(), buildRefund(), broadcast().
  • Webhooks: createWebhook(), listWebhooks(), deleteWebhook(), pingWebhook() + verifyWebhook().
  • Maker feed: MakerFeed — stream quotable RFQs and submit quotes over a WebSocket.

Interactive API reference: https://api.hashlock.markets/v1/docs (OpenAPI at /v1/openapi.json).

License

MIT — see LICENSE.