Skip to content

eric-stacks/turnkey-stacksjs-sdk

 
 

Repository files navigation

@turnkey/stacks

npm version Apache-2.0

Turnkey signer for Stacks blockchain transactions.

This package provides a class-based signer following the patterns established by @turnkey/solana, @turnkey/ethers, and @turnkey/cosmjs.

Installation

npm install @turnkey/stacks @stacks/transactions

Quick Start

import { TurnkeySigner, broadcastTransaction } from "@turnkey/stacks"
import { Turnkey } from "@turnkey/sdk-server"

// Initialize Turnkey client
const turnkey = new Turnkey({
  apiBaseUrl: "https://api.turnkey.com",
  apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY!,
  apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY!,
  defaultOrganizationId: process.env.TURNKEY_ORGANIZATION_ID!,
})

// Create Stacks signer
const signer = new TurnkeySigner({
  client: turnkey.apiClient(),
  organizationId: process.env.TURNKEY_ORGANIZATION_ID!,
  publicKey: "025afa6566651f6c49d84a482a1af918b25ba7caac0b06d9ab8d79a45b72715aeb",
  network: "testnet",
})

// Get address
const address = signer.getAddress()
console.log(`Address: ${address}`)

// Sign and broadcast transfer
const { transaction } = await signer.signSTXTransfer({
  recipient: "ST2J6ZY7R94P80Z4CGFRHZ3Q16MF0NKHN3FK4R0N",
  amount: 1_000_000n, // 1 STX
})

const txid = await broadcastTransaction(transaction, "testnet")
console.log(`TX: https://explorer.hiro.so/txid/${txid}?chain=testnet`)

API Reference

TurnkeySigner

Class-based signer for Stacks transactions.

Constructor

new TurnkeySigner(config: TurnkeySignerConfig)
Parameter Type Description
config.client TurnkeySignerClient Turnkey client (use turnkey.apiClient() for SDK server)
config.organizationId string Turnkey organization ID
config.publicKey string Compressed secp256k1 public key (66 hex chars)
config.network 'testnet' | 'mainnet' Default network (optional, defaults to 'testnet')

Methods

getAddress(network?): string

Returns the Stacks address for this signer.

const address = signer.getAddress()           // Uses default network
const mainnetAddr = signer.getAddress("mainnet")  // Override network
getPublicKey(): string

Returns the compressed public key.

const pubKey = signer.getPublicKey()
signSTXTransfer(params): Promise<SignedTransactionResult>

Signs an STX token transfer.

const { transaction, senderAddress, nonce, fee } = await signer.signSTXTransfer({
  recipient: "ST2J6ZY...",
  amount: 1_000_000n,    // Required: amount in microSTX
  memo: "Payment",       // Optional: memo string
  nonce: 5n,             // Optional: fetched if not provided
  fee: 200n,             // Optional: defaults to 180n
  network: "testnet",    // Optional: overrides signer default
})

Standalone Functions

getAddressFromPublicKey(publicKey, network?): string

Derives a Stacks address without creating a signer.

import { getAddressFromPublicKey } from "@turnkey/stacks"

const address = getAddressFromPublicKey("025afa...", "testnet")

broadcastTransaction(transaction, network?): Promise<string>

Broadcasts a signed transaction.

import { broadcastTransaction } from "@turnkey/stacks"

const txid = await broadcastTransaction(signedTx, "testnet")

signAndBroadcastSTXTransfer(signer, params): Promise<BroadcastResult>

Signs and broadcasts in one call.

import { signAndBroadcastSTXTransfer } from "@turnkey/stacks"

const { txid, senderAddress, recipient, amount } = await signAndBroadcastSTXTransfer(
  signer,
  { recipient: "ST2J6ZY...", amount: 1_000_000n }
)

Types

TurnkeySignerConfig

interface TurnkeySignerConfig {
  client: TurnkeySignerClient
  organizationId: string
  publicKey: string
  network?: "testnet" | "mainnet"
}

STXTransferParams

interface STXTransferParams {
  recipient: string
  amount: bigint
  nonce?: bigint
  fee?: bigint
  memo?: string
  network?: "testnet" | "mainnet"
}

SignedTransactionResult

interface SignedTransactionResult {
  transaction: StacksTransactionWire
  senderAddress: string
  nonce: bigint
  fee: bigint
}

BroadcastResult

interface BroadcastResult {
  txid: string
  senderAddress: string
  recipient: string
  amount: bigint
}

Client Compatibility

The TurnkeySigner works with multiple Turnkey client types:

With @turnkey/sdk-server

import { Turnkey } from "@turnkey/sdk-server"

const turnkey = new Turnkey({ ... })
const signer = new TurnkeySigner({
  client: turnkey.apiClient(),  // Use apiClient()
  ...
})

With @turnkey/sdk-browser

import { TurnkeyBrowserClient } from "@turnkey/sdk-browser"

const client = new TurnkeyBrowserClient({ ... })
const signer = new TurnkeySigner({
  client: client,  // Use directly
  ...
})

With @turnkey/http (Legacy)

import { TurnkeyClient } from "@turnkey/http"

const client = new TurnkeyClient({ ... }, stamper)
const signer = new TurnkeySigner({
  client: client,  // Use directly
  ...
})

Cryptographic Details

This package uses Turnkey's signRawPayload with HASH_FUNCTION_NO_OP because Stacks' sigHashPreSign already produces the final hash to be signed. Turnkey must sign the bytes directly without re-hashing.

Signature flow:

  1. Build unsigned STX transfer with makeUnsignedSTXTokenTransfer
  2. Generate pre-sign hash with sigHashPreSign
  3. Sign with Turnkey using HASH_FUNCTION_NO_OP
  4. Construct VRS signature (recovery byte + r + s = 65 bytes)
  5. Attach signature to transaction spending condition

License

Apache-2.0

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • TypeScript 93.0%
  • JavaScript 7.0%