Skip to main content
Available The Go SDK is available at github.com/d4mr/t2z/sdks/go. It uses UniFFI bindings to the Rust core.

Installation

Since the Go SDK requires the native libt2z_uniffi library, you need to build from source:
# Clone the repository
git clone https://github.com/d4mr/t2z
cd t2z/crates

# Build the UniFFI library
cargo build --release -p t2z-uniffi

# macOS: target/release/libt2z_uniffi.dylib
# Linux: target/release/libt2z_uniffi.so
Set the library path:
# macOS
export DYLD_LIBRARY_PATH=/path/to/t2z/crates/target/release:$DYLD_LIBRARY_PATH

# Linux
export LD_LIBRARY_PATH=/path/to/t2z/crates/target/release:$LD_LIBRARY_PATH

Quick Start

package main

import (
    "fmt"
    "log"
    
    t2z "github.com/d4mr/t2z/sdks/go/t2z_uniffi"
)

func main() {
    // 1. Create transparent input
    input := t2z.UniffiTransparentInput{
        Pubkey:       "03abc123...",  // 33-byte compressed pubkey (hex)
        PrevoutTxid:  "ce15f716...",  // 32-byte txid (little-endian hex)
        PrevoutIndex: 0,
        Value:        1_000_000,      // 0.01 ZEC in zatoshis
        ScriptPubkey: "76a914...88ac", // P2PKH script (hex)
        Sequence:     nil,
    }

    // 2. Create payment
    payment := t2z.UniffiPayment{
        Address: "u1recipient...", // Unified address with Orchard
        Amount:  900_000,
        Memo:    nil,
        Label:   nil,
    }

    request := t2z.UniffiTransactionRequest{
        Payments: []t2z.UniffiPayment{payment},
    }

    // 3. Propose transaction
    changeAddr := "u1change..."
    pczt, err := t2z.ProposeTransaction(
        []t2z.UniffiTransparentInput{input},
        request,
        &changeAddr,
        "testnet",
        3720100,
    )
    if err != nil {
        log.Fatal(err)
    }

    // 4. Sign transparent inputs (external signing)
    sighash, err := t2z.GetSighash(pczt, 0)
    if err != nil {
        log.Fatal(err)
    }
    
    // Sign the sighash with your key (ECDSA secp256k1)
    signature := sign(sighash, privateKey) // Your signing logic
    
    pczt, err = t2z.AppendSignature(pczt, 0, pubkeyHex, signature)
    if err != nil {
        log.Fatal(err)
    }

    // 5. Generate Orchard proofs (~10 seconds first time)
    pczt, err = t2z.ProveTransaction(pczt)
    if err != nil {
        log.Fatal(err)
    }

    // 6. Finalize and get raw transaction
    txHex, err := t2z.FinalizeAndExtractHex(pczt)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("Transaction ready:", txHex)
}

API Reference

Transaction Construction

FunctionDescription
ProposeTransactionCreate a PCZT from inputs and payments
VerifyBeforeSigningVerify PCZT matches original request

Signing

FunctionDescription
GetSighashGet sighash for external signing
AppendSignatureAdd a pre-computed signature
SignTransparentInputSign with in-memory private key

Proving & Finalization

FunctionDescription
ProveTransactionGenerate Orchard ZK proofs
FinalizeAndExtractExtract final transaction bytes
FinalizeAndExtractHexExtract as hex string
CombinePcztsCombine multiple PCZTs

Utilities

FunctionDescription
PrebuildProvingKeyPre-build proving key at startup
IsProvingKeyReadyCheck if proving key is cached
VersionGet library version

Types

UniffiTransparentInput

type UniffiTransparentInput struct {
    Pubkey       string   // 33-byte compressed pubkey (hex)
    PrevoutTxid  string   // 32-byte txid (little-endian hex)
    PrevoutIndex uint32   // Output index
    Value        uint64   // Value in zatoshis
    ScriptPubkey string   // P2PKH scriptPubkey (hex)
    Sequence     *uint32  // Optional sequence number
}

UniffiPayment

type UniffiPayment struct {
    Address string   // Unified or transparent address
    Amount  uint64   // Amount in zatoshis
    Memo    *string  // Optional memo (hex-encoded)
    Label   *string  // Optional label
}

UniffiExpectedTxOut

type UniffiExpectedTxOut struct {
    Address string  // Expected address
    Amount  uint64  // Expected amount (0 = wildcard)
}

UniffiPczt

// Create from bytes or hex
pczt, err := t2z.NewUniffiPcztFromBytes(bytes)
pczt, err := t2z.NewUniffiPcztFromHex(hexString)

// Serialize
bytes := pczt.ToBytes()
hexStr := pczt.ToHex()

Error Handling

All functions return Go-style errors:
pczt, err := t2z.ProposeTransaction(inputs, request, &changeAddr, network, expiry)
if err != nil {
    // UniffiError with detailed message
    log.Printf("Failed to propose: %v", err)
    return
}

Performance Tips

Pre-build Proving Key

The first proof generation takes ~10 seconds. Pre-build at startup:
func init() {
    if !t2z.IsProvingKeyReady() {
        log.Println("Building Orchard proving key...")
        t2z.PrebuildProvingKey()
        log.Println("Proving key ready")
    }
}

Type Mappings

TypeScriptGo
WasmTransparentInputUniffiTransparentInput
WasmPaymentUniffiPayment
WasmPczt*UniffiPczt
bigintuint64
string (hex)string (hex)
nullnil / pointer

Building from Source

# Clone the repository
git clone https://github.com/d4mr/t2z
cd t2z/crates

# Build the UniFFI library
cargo build --release -p t2z-uniffi

# Regenerate Go bindings (requires uniffi-bindgen-go)
cargo install uniffi-bindgen-go \
  --git https://github.com/NordSecurity/uniffi-bindgen-go \
  --tag v0.4.0+v0.28.3

uniffi-bindgen-go \
  --library target/release/libt2z_uniffi.dylib \
  --out-dir ../sdks/go