SDK & Developer Tools

Everything you need to integrate Halo Protocol into your application. Connect wallets, call contracts, and build on decentralized credit.

Core Packages

@stacks/connect

v8.x

Wallet integration for Leather and Xverse. Handles authentication, transaction signing, and message signing in the browser. Required for all user-facing interactions.

@stacks/transactions

v7.x

Build, sign, and broadcast Stacks transactions. Call smart contract functions, construct post-conditions, and read on-chain state. Server-side and client-side compatible.

@stacks/network

v7.x

Network configuration for testnet and mainnet. Use networkFromName() to get the correct API endpoints and chain ID for your target environment.

Getting Started

1. Install Dependencies

npm install @stacks/connect @stacks/transactions @stacks/network

2. Configure Network

Set up the Stacks network for your target environment. The v7 SDK uses factory functions instead of class constructors.

import { networkFromName } from "@stacks/network";

// For testnet development
const network = networkFromName("testnet");

// For mainnet production
// const network = networkFromName("mainnet");

// Deployer address (set via environment variable)
const DEPLOYER = process.env.NEXT_PUBLIC_DEPLOYER_ADDRESS;

3. Set Environment Variables

# .env.local
NEXT_PUBLIC_DEPLOYER_ADDRESS=ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM
NEXT_PUBLIC_STACKS_NETWORK=testnet

Wallet Connection

Use @stacks/connect to prompt users to connect their Leather or Xverse wallet. The component must use "use client" and dynamic imports to avoid SSR errors.

"use client";

import { showConnect } from "@stacks/connect";

function ConnectWallet() {
  const handleConnect = () => {
    showConnect({
      appDetails: {
        name: "Halo Protocol",
        icon: "/logo.png",
      },
      onFinish: (data) => {
        const address = data.userSession
          .loadUserData()
          .profile.stxAddress.testnet;
        console.log("Connected:", address);
      },
      onCancel: () => {
        console.log("User cancelled");
      },
    });
  };

  return (
    <button onClick={handleConnect}>
      Connect Wallet
    </button>
  );
}

Important: SSR Compatibility

@stacks/connect requires browser APIs and will crash during server-side rendering. Always use "use client" at the top of wallet components. For Next.js dynamic imports, use dynamic(() => import("..."), { ssr: false }).

Smart Contract Interactions

Read-Only Contract Calls

Read on-chain state without broadcasting a transaction. The v7 SDK uses fetchCallReadOnlyFunction (the old callReadOnlyFunction was removed).

import {
  fetchCallReadOnlyFunction,
  cvToJSON,
  principalCV,
} from "@stacks/transactions";
import { networkFromName } from "@stacks/network";

async function getCreditScore(address: string) {
  const network = networkFromName("testnet");
  const DEPLOYER = process.env.NEXT_PUBLIC_DEPLOYER_ADDRESS!;

  const result = await fetchCallReadOnlyFunction({
    network,
    contractAddress: DEPLOYER,
    contractName: "halo-credit",
    functionName: "get-credit-score",
    functionArgs: [principalCV(address)],
    senderAddress: address,
  });

  const json = cvToJSON(result);
  return json.value?.score?.value ?? 300;
}

Write Transactions (Contract Calls)

Broadcast state-changing transactions to the blockchain. The v7 SDK removed AnchorMode—simply omit it from the options object.

import { openContractCall } from "@stacks/connect";
import { uintCV, stringUtf8CV } from "@stacks/transactions";

async function joinCircle(circleId: number) {
  const DEPLOYER = process.env.NEXT_PUBLIC_DEPLOYER_ADDRESS!;

  await openContractCall({
    contractAddress: DEPLOYER,
    contractName: "halo-circle",
    functionName: "join-circle",
    functionArgs: [uintCV(circleId)],
    onFinish: (data) => {
      console.log("TX broadcast:", data.txId);
    },
    onCancel: () => {
      console.log("User rejected transaction");
    },
  });
}

Post-Conditions

Post-conditions protect users by ensuring a transaction only succeeds if specified conditions are met. The v7 SDK uses the fluent Pc builder (the old makeStandardSTXPostCondition was removed).

import { Pc } from "@stacks/transactions";
import { openContractCall } from "@stacks/connect";

async function contributeToCircle(
  circleId: number,
  amount: number,
  senderAddress: string,
) {
  const DEPLOYER = process.env.NEXT_PUBLIC_DEPLOYER_ADDRESS!;

  // Ensure the user sends exactly the contribution amount
  const postConditions = [
    Pc.principal(senderAddress)
      .willSendEq(amount)
      .ustx(),
  ];

  await openContractCall({
    contractAddress: DEPLOYER,
    contractName: "halo-circle",
    functionName: "contribute",
    functionArgs: [uintCV(circleId)],
    postConditions,
    onFinish: (data) => {
      console.log("Contribution TX:", data.txId);
    },
  });
}

Contract Reference

Key public functions available on the Halo Protocol contracts. All contracts are deployed by the deployer address and use Clarity 3 (Epoch 3.0).

halo-identity

WRITE
register-identity (name)

Register a new on-chain identity with a display name.

READ
get-identity (principal)

Look up an identity by Stacks address.

halo-credit

WRITE
record-payment (user, circle-id, amount, on-time)

Record a circle contribution. Authorized via contract-caller. Updates credit score components.

READ
get-credit-score (principal)

Retrieve the composite credit score (300-850) for a user.

halo-circle

WRITE
create-circle (name, contribution, total-members, token-type)

Create a new lending circle with specified parameters.

WRITE
join-circle (circle-id)

Join an existing circle that is still in formation.

WRITE
contribute (circle-id)

Make a contribution for the current round. Transfers tokens to the vault.

READ
get-circle (circle-id)

Retrieve circle details including status, members, and current round.

halo-sbtc-staking

WRITE
stake (amount)

Stake sBTC for yield and credit score boost.

WRITE
unstake (amount)

Withdraw staked sBTC with accrued yield.

Common Pitfalls

v7 Breaking Changes

@stacks/transactions v7 removed several APIs. callReadOnlyFunction is replaced by fetchCallReadOnlyFunction. makeStandardSTXPostCondition is replaced by the Pc fluent builder. AnchorMode is removed entirely.

Network Constructor Removal

@stacks/network v7 removed class constructors like new StacksTestnet(). Use networkFromName("testnet") instead.

Clarity Map Field Names

Clarity uses kebab-case for map field names (e.g., total-members). In JavaScript, access these with bracket notation: result["total-members"].

Credit Contract Authorization

The halo-credit contract's record-payment function uses contract-caller for authorization, not tx-sender. Only the authorized circle contract can record payments.