github.com/d4mr/t2z/sdks/go. It uses UniFFI bindings to the Rust core.
Installation
Since the Go SDK requires the nativelibt2z_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
# 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
| Function | Description |
|---|---|
ProposeTransaction | Create a PCZT from inputs and payments |
VerifyBeforeSigning | Verify PCZT matches original request |
Signing
| Function | Description |
|---|---|
GetSighash | Get sighash for external signing |
AppendSignature | Add a pre-computed signature |
SignTransparentInput | Sign with in-memory private key |
Proving & Finalization
| Function | Description |
|---|---|
ProveTransaction | Generate Orchard ZK proofs |
FinalizeAndExtract | Extract final transaction bytes |
FinalizeAndExtractHex | Extract as hex string |
CombinePczts | Combine multiple PCZTs |
Utilities
| Function | Description |
|---|---|
PrebuildProvingKey | Pre-build proving key at startup |
IsProvingKeyReady | Check if proving key is cached |
Version | Get 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
| TypeScript | Go |
|---|---|
WasmTransparentInput | UniffiTransparentInput |
WasmPayment | UniffiPayment |
WasmPczt | *UniffiPczt |
bigint | uint64 |
string (hex) | string (hex) |
null | nil / 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

