Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StacksKit

A native Swift implementation of the Stacks.js core, for building Stacks blockchain apps on Apple platforms: key management, transaction construction and signing, Clarity values, stacking (PoX), and the Hiro API — with no JavaScript anywhere.

Every serialization path is verified against golden vectors generated by the Stacks.js test suite, including byte-identical RFC 6979 deterministic signatures.

Coverage

Stacks.js package StacksKit Notes
@stacks/transactions STX transfer, contract call, contract deploy, post conditions, sponsored transactions, full Clarity value codec, txid, origin verification
@stacks/wallet-sdk BIP-39 secret keys, BIP-32 derivation at m/44'/5757'/0'/0/n, accounts, addresses
@stacks/network Mainnet, testnet, devnet, custom API nodes
@stacks/api / node RPC Accounts, balances, nonces, PoX info, fee estimation with fallback, broadcast, read-only calls, transaction status
@stacks/stacking delegate-stx, revoke-delegate-stx, stack-stx, pool operator calls, PoX reward address conversion (base58check + bech32/bech32m)
@stacks/bitcoin-staking ✅ (STX-only) pox-5 stake, stake-update, unstake, get-staker-info, get-earned-staker-rewards, prepare-phase detection. The paired-BTC bond entry points are out of scope
@stacks/encryption Partial SHA-512/256, RIPEMD-160/hash160, HMAC, PBKDF2, secp256k1 recoverable signatures — the pieces transactions and wallets need
@stacks/auth, @stacks/profile, @stacks/storage (Gaia), @stacks/bns, @stacks/cli Legacy web-app concepts, out of scope for iOS. BNS name reads are available through the Hiro API

Multi-sig spending conditions serialize and deserialize; multi-sig signing flows are not yet implemented.

Requirements

  • Swift 6.2, iOS 26 / macOS 26 (matches NetworkingKit's platform floor)
  • NetworkingKit 2.1.1+ for all networking
  • swift-secp256k1 (P256K) for curve operations

Usage

Wallet

import StacksKit

// 24-word secret key, compatible with Xverse and Leather
let mnemonic = try generateSecretKey()

let wallet = try StacksWallet(mnemonic: mnemonic)
let account = try wallet.account(at: 0)
let address = try account.address(on: .mainnet)

Send STX

let transaction = try await makeSTXTokenTransfer(
    recipient: Principal("SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159"),
    amount: 1_000_000, // microSTX
    senderKey: account.privateKey,
    network: .mainnet,
    memo: "thanks"
)
// fee and nonce are fetched automatically when omitted; pass both to build offline

let txid = try await StacksAPIService(network: .mainnet).broadcast(transaction)

Call a contract

let transaction = try await makeContractCall(
    contractAddress: StacksAddress("SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR"),
    contractName: "amm-pool-v2-01",
    functionName: "swap",
    functionArgs: [.uint(100_000), .principal(pool), .none],
    senderKey: account.privateKey,
    network: .mainnet,
    postConditions: [
        .stx(principal: .origin, condition: .lessEqual, amount: 100_000),
    ]
)

Stake STX, earn Bitcoin (pox-5)

let stacking = StackingClient(network: .mainnet)
let info = try await stacking.poxInfo()          // reads the live pox contract id
guard let burnHeight = info.currentBurnchainBlockHeight,
      !info.isInPreparePhase(atBurnHeight: burnHeight) else { return } // stake reverts in the prepare phase

// Bind STX to a signer-manager (the pool). The STX locks at your own address;
// rewards are paid in sBTC on the operator's terms.
let stake = try await stacking.stake(
    signerManager: Principal("SP8HK160YD5GHXP69VGA0TC7AQJ1X4CDW3XVERSE.xverse-signer-manager-3"),
    amountMicroStx: 500_000_000_000,
    numCycles: StackingClient.maxStakeCycles,    // 96 = earn until you unstake
    startBurnHeight: burnHeight,
    senderKey: account.privateKey
)
let txid = try await stacking.broadcast(stake)

// Later: top up, or end the stake at the cycle boundary.
if let position = try await stacking.pox5StakerInfo(for: address) {
    _ = try await stacking.stakeUpdate(signerManager: position.signer, oldSignerManager: position.signer,
                                       amountIncreaseMicroStx: 100_000_000, senderKey: account.privateKey)
    _ = try await stacking.unstake(oldSignerManager: position.signer, senderKey: account.privateKey)
}

The pox-4 delegate-stx family is still available for legacy reads and builders, but mainnet retired delegation with pox-5.

Read on-chain state

let api = StacksAPIService(network: .mainnet)
let balances = try await api.balances(address)
let result = try await api.callReadOnly(
    contract: try info.contract(),                // whatever /v2/pox reports — never hardcode pox-N
    functionName: "get-staker-info",
    functionArgs: [.principal(try Principal(address))]
)

Verification

swift test runs 72 tests covering:

  • NIST vectors for SHA-512/256 and the reference vectors for RIPEMD-160
  • BIP-39 (Trezor vector) and the @stacks/wallet-sdk end-to-end derivation vector
  • c32 / c32check address vectors from the Stacks.js keys tests
  • Byte-for-byte transaction golden vectors from the Stacks.js builder tests: mainnet transfer, testnet transfer, contract call, and sponsored transfer including the placeholder sponsor condition and exact origin signature
  • pox-5 stake / stake-update / unstake and pox-4 delegate-stx golden vectors generated with @stacks/transactions 7.6.0, signatures included
  • Clarity value wire-format vectors and round-trips for every value shape
  • Bitcoin address decoding (BIP-173/BIP-350 vectors) for PoX reward addresses

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages