Help us shape the future of Go! Take the 2026 Go Developer Survey

branta

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 28, 2026 License: MIT Imports: 18 Imported by: 0

README

Branta Go SDK

Go SDK for the Branta V2 API — payment destination lookup and registration with zero-knowledge encryption support.

Requirements

  • Go 1.22 or higher

Installation

go get github.com/BrantaOps/branta-go

Integration Guide

If you are an AI agent implementing this SDK, follow the steps below exactly. If you are a developer, use this as a reference for the recommended integration patterns.

1. Ask which side(s) of a payment they are implementing:

  • Send side — the app is paying someone (e.g. a wallet). The user scans or pastes a destination and you verify it belongs to a known platform before funds are sent.
  • Receive side — the app is receiving payment (e.g. a checkout, POS, invoicing platform). You post destinations to Branta so wallets can verify them.
  • Both — some apps do both (e.g. an exchange or self-custodial wallet with invoice generation). Implement each side independently.

If they are on the receive side, ask one follow-up:

  • Platform — single-tenant, one API key.
  • Parent Platform — multi-tenant, manages multiple child platforms. Two variants:
    • Shared key (Recommended) — one API key for all children, no HMAC secret needed; tag the child per-payment with SetChildPlatform(). Default to this unless there's a specific reason for separate per-child keys.
    • Per-client keys — each child has its own API key, and the parent signs every request with an HMAC secret to prove it originated from the parent; scope requests per-call. Use only if each child needs an independent, separately-revocable API key.

2. Follow the matching Quick Start section below.

3. Apply these rules:

General (all types):

  • Always use PrivacyStrict. Never switch to PrivacyLoose unless there is no QR scanner and ZK is impossible.
  • Never call BrantaClient directly — always go through BrantaService.
  • Never show an error or "not verified" message when a lookup returns empty or an error. An empty result means the destination is unknown to Branta, not that it is malicious. Show nothing.
  • For BaseURL: use Production only in production environments. Use Staging everywhere else — including local development, CI, and staging/test environments.

Send side (wallets):

  • Prefer GetPaymentsByQRCode over GetPayments — it handles multi-value ZK QR payloads correctly.
  • Only fall back to GetPayments for copy/paste flows where there is no QR code.
  • If result.Payments is empty or the call returns an error, render nothing.
  • When result.Payments is non-empty, display: the platform logo, the platform name (payment.Platform), and the payment description (payment.Description). Only render description when non-empty. Make the verification card a clickable link to result.VerifyURL — do not display the raw URL.
  • For the platform logo: on dark backgrounds use payment.PlatformLogoURL. On light backgrounds prefer payment.PlatformLogoLightURL when available, falling back to payment.PlatformLogoURL.
  • Optionally display payment.ParentPlatform.LogoURL / payment.ParentPlatform.LogoLightURL as a small secondary badge (e.g. corner icon). This is not required.

Receive side (platforms):

  • Always call .SetZk() on the PaymentBuilder before calling AddPayment. Plain-text destinations are rejected in PrivacyStrict mode.
  • Store the Secret returned by AddPayment alongside the invoice — it is required to reconstruct the verify URL for the wallet.

Receive side (parent platforms — per-client keys), in addition to the platform rules:

  • Set HMACSecret on BrantaClientOptions but leave DefaultAPIKey unset at service construction.
  • Pass per-call BrantaClientOptions with each child's API key to scope requests.

Receive side (parent platforms — shared key), in addition to the platform rules:

  • Set DefaultAPIKey on BrantaClientOptions. Do not set HMACSecret.
  • Call .SetChildPlatform(name, logoURL, logoLightURL) on the builder to tag each payment with the child's branding.

Quick Start

For Wallets

Wallets should use PrivacyStrict. Two flows are supported:

  • Copy/paste: call GetPayments with the pasted text. Plain-text on-chain addresses will not return results in strict mode — they must be ZK-encoded. Hash-ZK destinations (bolt11, ark_address, silent_payment) work as plain text.
  • QR scan: call GetPaymentsByQRCode with the raw QR text. This handles both on-chain (when the QR includes branta_id / branta_secret) and hash-ZK destinations.

Always handle the error and show nothing on not-found — a missing record just means the address was not posted to Branta.

package main

import (
	"context"

	"github.com/BrantaOps/branta-go"
)

func lookup(ctx context.Context, service *branta.BrantaService, input string, isQRCode bool) {
	var (
		result branta.PaymentsResult
		err    error
	)
	if isQRCode {
		result, err = service.GetPaymentsByQRCode(ctx, input, nil)
	} else {
		result, err = service.GetPayments(ctx, input, "", nil)
	}

	if err != nil || len(result.Payments) == 0 {
		// Not found — show nothing. The address may simply not exist in Branta.
		return
	}

	// Render result.Payments and result.VerifyURL
}

func main() {
	service := branta.NewBrantaService(branta.BrantaClientOptions{
		BaseURL: branta.Production,
		Privacy: branta.PrivacyStrict,
	})
	lookup(context.Background(), service, "bitcoin:bc1q...", false)
}

Prefer GetPaymentsByQRCode for QR-driven flows. It handles multi-destination payloads (branta_id / branta_secret fragments) automatically.

Looking up a payment by destination value
// Plain bitcoin address (requires PrivacyLoose or will return ErrPrivacyModeViolation):
result, err := service.GetPayments(ctx, "bc1q...", "", nil)

// ZK-encrypted bitcoin address with secret:
result, err = service.GetPayments(ctx, encryptedAddress, "my-secret", nil)

// BOLT-11 invoice (hash-ZK — works in strict mode):
result, err = service.GetPayments(ctx, "lnbc...", "", nil)
No-QR-Code Flows

When QR scanning is not available, three options exist. Choose one based on how much control you want to give users over privacy:

Option 1 — Keep Strict mode (no code changes)

Only hash-ZK destinations (bolt11, ark_address, silent_payment) will return results. Plain-text on-chain address lookups return ErrPrivacyModeViolation. This is the safest default and requires no additional work.

Option 2 — Opt-in Loose mode (Recommended)

Add a user-facing setting (e.g. "Enable on-chain address verification"). Only switch to PrivacyLoose when the user explicitly opts in — this sends on-chain addresses in plain text, so the choice should be theirs.

var override *branta.BrantaClientOptions
if userOptedIn {
	opts := branta.BrantaClientOptions{BaseURL: branta.Production, Privacy: branta.PrivacyLoose}
	override = &opts
}

result, err := service.GetPayments(ctx, input, "", override)

Option 3 — Always Loose mode

Configure with PrivacyLoose globally. All lookups including plain-text on-chain addresses are sent to Branta. Simplest, but gives users no privacy control.

service := branta.NewBrantaService(branta.BrantaClientOptions{
	BaseURL: branta.Production,
	Privacy: branta.PrivacyLoose,
})

For Platforms

Platforms post payments to Branta so wallets can verify them. Use PrivacyStrict and mark each destination ZK via .SetZk() on the PaymentBuilder.

payment := branta.NewPaymentBuilder().
	AddDestination("bc1q...", branta.BitcoinAddress).SetZk().
	AddDestination("lnbc...", branta.Bolt11).SetZk().
	SetDescription("Donation").
	AddMetadata("email", "donor@example.com").
	Build()

opts := branta.BrantaClientOptions{
	BaseURL:       branta.Production,
	DefaultAPIKey: "your-api-key",
	Privacy:       branta.PrivacyStrict,
}
result, err := service.AddPayment(ctx, payment, &opts)
// result.Payment — the registered payment from the server
// result.Secret — the random encryption key for the bitcoin address
// result.VerifyURL — share this URL to verify the payment

For Parent Platforms

Choose a variant based on how API keys are structured. Only the per-client keys variant signs requests with HMAC — shared key needs none.

Shared key — one API key covers all children (Recommended)

Construct with a single API key; identify the child platform per-payment.

service := branta.NewBrantaService(branta.BrantaClientOptions{
	BaseURL:       branta.Production,
	DefaultAPIKey: "<shared-api-key>",
	Privacy:       branta.PrivacyStrict,
})

payment := branta.NewPaymentBuilder().
	AddDestination("bc1q...", branta.BitcoinAddress).SetZk().
	SetChildPlatform("ChildBrand", "https://example.com/logo.png", "").
	SetTTL(600).
	Build()

result, err := service.AddPayment(ctx, payment, nil)
Per-client keys — each child has its own API key

Construct the service with the shared HMAC secret only; pass each child's API key per-call.

service := branta.NewBrantaService(branta.BrantaClientOptions{
	BaseURL:    branta.Production,
	HMACSecret: "<hmac-secret>",
	Privacy:    branta.PrivacyStrict,
})

payment := branta.NewPaymentBuilder().
	AddDestination("bc1q...", branta.BitcoinAddress).SetZk().
	SetTTL(600).
	Build()

perCall := branta.BrantaClientOptions{
	BaseURL:       branta.Production,
	DefaultAPIKey: "<child-api-key>",
	Privacy:       branta.PrivacyStrict,
}
result, err := service.AddPayment(ctx, payment, &perCall)
Validating an API key
isValid, err := service.IsAPIKeyValid(ctx, &opts)
Per-call option overrides

Every public method accepts an optional *BrantaClientOptions parameter that overrides the service's default options for that call only, field-by-field:

service := branta.NewBrantaService(defaultOptions)
result, err := service.GetPayments(ctx, "lnbc...", "", &overrideOptions)

Privacy

PrivacyMode controls whether plain-text on-chain lookups are allowed.

Value Behavior
PrivacyStrict (default) Only ZK lookups. GetPayments returns ErrPrivacyModeViolation for plain addresses. GetPaymentsByQRCode returns an empty PaymentsResult with a populated VerifyURL. AddPayment returns an error if any destination has IsZk = false.
PrivacyLoose Both plain and ZK lookups are permitted.

ZK destination types

Type Encryption
BitcoinAddress Random secret (UUID) per payment
Bolt11 Deterministic: SHA-256 of lowercase invoice
ArkAddress Deterministic: SHA-256 of lowercase address
SilentPayment Deterministic: SHA-256 of lowercase address

BrantaService

The primary service type. Always use BrantaService — never call BrantaClient directly.

Prefer GetPaymentsByQRCode for integrations. It parses the raw QR text and correctly resolves multiple ZK values in a single scan. GetPayments only handles a single destination value and does not support multi-value ZK lookups.

func (s *BrantaService) GetPaymentsByQRCode(ctx context.Context, qrText string, options *BrantaClientOptions) (PaymentsResult, error)
func (s *BrantaService) GetPayments(ctx context.Context, destinationValue, destinationEncryptionKey string, options *BrantaClientOptions) (PaymentsResult, error)
func (s *BrantaService) AddPayment(ctx context.Context, payment Payment, options *BrantaClientOptions) (AddPaymentResult, error)
func (s *BrantaService) IsAPIKeyValid(ctx context.Context, options *BrantaClientOptions) (bool, error)

PaymentsResult contains the list of matching Payments and the VerifyURL to display to the user — VerifyURL is always returned, even when Payments is empty.

Release

Go modules are versioned by git tags. After merging to main:

git tag v1.0.0
git push origin v1.0.0

pkg.go.dev/github.com/BrantaOps/branta-go indexes the tag automatically. The Go module major version is 1 (import path github.com/BrantaOps/branta-go) per Go module conventions; functionality matches sibling SDKs at 3.2.1.

Development

go test ./...
BRANTA_SKIP_INTEGRATION=1 go test ./...    # skip the live integration suite
go test -run Integration                   # integration tests only (requires network)
go fmt ./...
go vet ./...
go run ./examples/branta_example

Responsible Disclosure

Found critical bugs/vulnerabilities? Please email them to support@branta.pro. Thanks!

Documentation

Overview

Package branta is the Go SDK for the Branta V2 API — payment destination lookup and registration with zero-knowledge encryption support.

Always use BrantaService. Never call BrantaClient directly from consumer code.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrPrivacyModeViolation = fmt.Errorf("PrivacyMode Strict does not permit plain-text lookups for this destination type")

	ErrNonZkDestinationInStrictMode = fmt.Errorf("PrivacyMode Strict requires all destinations to be ZK; one or more destinations have is_zk = false")

	ErrUnauthorized = fmt.Errorf("Unauthorized")

	ErrNoPaymentReturned = fmt.Errorf("No payment returned from server")

	ErrEncryptedDataTooShort = fmt.Errorf("invalid encrypted data: too short")

	ErrNoDestinations = fmt.Errorf("Payment has no destinations")

	ErrTampered = fmt.Errorf("The Bitcoin address in the QR code does not match the address verified by Branta. The QR code may have been tampered with.")
)

Sentinel errors returned by fallible SDK operations.

Note what is deliberately absent: a QR-parse error. No sibling SDK ever raises one — QRParser degrades gracefully rather than erroring.

Decryption failures during a lookup are always swallowed internally and never surface as an error — only AddPayment's HTTP call and the logo-URL domain check are allowed to bubble an error out of BrantaService. The one decrypt-path exception is ErrTampered.

Functions

func Decrypt

func Decrypt(encryptedValue, secret string) (string, error)

Decrypt decrypts a value produced by Encrypt using the matching secret.

A base64 payload shorter than 28 bytes (12 iv + 16 tag minimum) is a distinct ErrEncryptedDataTooShort, checked before any crypto is attempted. Any other failure (e.g. wrong key -> GCM tag mismatch) collapses into a DecryptionError.

func Encrypt

func Encrypt(value, secret string, deterministicNonce bool) (string, error)

Encrypt encrypts value with a key derived from secret.

Wire format MUST match byte-for-byte across every Branta SDK:

  • Key = SHA-256(UTF-8 secret bytes) — 32 bytes, used directly as the AES-256 key.
  • Nonce/IV = 12 bytes. Random (CSPRNG) when deterministicNonce is false. When true: the first 12 bytes of HMAC-SHA256(key = key_data [the SHA-256'd key, NOT the raw secret], message = UTF-8 plaintext value).
  • AES-256-GCM with a 16-byte tag. Wire format: base64_standard(iv || ciphertext || tag).

func IsArk

func IsArk(value string) bool

IsArk reports whether value looks like an Ark address.

func IsBolt11

func IsBolt11(value string) bool

IsBolt11 reports whether value looks like a BOLT-11 invoice.

func IsSilentPayment

func IsSilentPayment(value string) bool

IsSilentPayment reports whether value looks like a silent payment address.

func ToNormalizedHash

func ToNormalizedHash(value string) string

ToNormalizedHash returns SHA-256(lowercase(value)) as 64-char uppercase hex, matching .NET's Convert.ToHexString. This value doubles as the AES secret for hash-ZK destinations, so a case mismatch here silently breaks cross-SDK payment lookups.

func ToURLFragment

func ToURLFragment(keys *orderedKeys) string

ToURLFragment builds a `#k-{zk_id}={key}&k-{zk_id2}={key2}...` URL fragment from resolved decryption keys, iterating in insertion order.

Types

type AESEncryption

type AESEncryption interface {
	Encrypt(value, secret string, deterministicNonce bool) (string, error)
	Decrypt(encryptedValue, secret string) (string, error)
}

AESEncryption is the encrypt/decrypt strategy, injectable for testing.

type AESEncryptionService

type AESEncryptionService struct{}

AESEncryptionService is the production AESEncryption implementation.

func (AESEncryptionService) Decrypt

func (AESEncryptionService) Decrypt(encryptedValue, secret string) (string, error)

func (AESEncryptionService) Encrypt

func (AESEncryptionService) Encrypt(value, secret string, deterministicNonce bool) (string, error)

type AddPaymentResult

type AddPaymentResult struct {
	Payment   Payment
	Secret    string
	VerifyURL string
}

AddPaymentResult is the result of AddPayment.

type BrantaClient

type BrantaClient struct {
	// contains filtered or unexported fields
}

BrantaClient is the production HTTP client.

func NewBrantaClient

func NewBrantaClient(defaultOptions BrantaClientOptions) *BrantaClient

NewBrantaClient constructs a client with the given default options.

func (*BrantaClient) GetPayments

func (c *BrantaClient) GetPayments(ctx context.Context, destinationValue string, options *BrantaClientOptions) ([]Payment, error)

GetPayments looks up payments by destination value. Lookup failures (transport, non-2xx, empty body, malformed JSON) degrade to an empty slice rather than an error. Logo-URL domain mismatches still error.

func (*BrantaClient) IsAPIKeyValid

func (c *BrantaClient) IsAPIKeyValid(ctx context.Context, options *BrantaClientOptions) (bool, error)

IsAPIKeyValid hits the API-key health-check endpoint.

func (*BrantaClient) PostPayment

func (c *BrantaClient) PostPayment(ctx context.Context, payment Payment, options *BrantaClientOptions) (*Payment, error)

PostPayment registers a payment. Unlike GetPayments, failures propagate.

type BrantaClientOptions

type BrantaClientOptions struct {
	BaseURL       BrantaServerBaseURL
	DefaultAPIKey string
	HMACSecret    string
	Privacy       PrivacyMode
}

BrantaClientOptions is per-service configuration, overridable per-call.

func NewBrantaClientOptions

func NewBrantaClientOptions(baseURL BrantaServerBaseURL) BrantaClientOptions

NewBrantaClientOptions returns options for baseURL with PrivacyStrict and no API key or HMAC secret.

func (BrantaClientOptions) GetAPIKey

func (o BrantaClientOptions) GetAPIKey(overrides *BrantaClientOptions) string

GetAPIKey resolves the effective API key, field-by-field: overrides' key wins if non-empty, else falls back to o's key. Empty string means unset.

func (BrantaClientOptions) GetBaseURL

func (o BrantaClientOptions) GetBaseURL(overrides *BrantaClientOptions) string

GetBaseURL resolves the effective base URL: overrides wins if present, else o.

func (BrantaClientOptions) GetHMACSecret

func (o BrantaClientOptions) GetHMACSecret(overrides *BrantaClientOptions) string

GetHMACSecret resolves the effective HMAC secret, field-by-field: overrides' secret wins if non-empty, else falls back to o's secret.

func (BrantaClientOptions) GetPrivacy

func (o BrantaClientOptions) GetPrivacy(overrides *BrantaClientOptions) PrivacyMode

GetPrivacy resolves the effective privacy mode: overrides wins if present, else o.

type BrantaServerBaseURL

type BrantaServerBaseURL int

BrantaServerBaseURL identifies which Branta server environment to talk to.

const (
	Staging BrantaServerBaseURL = iota
	Production
	Localhost
)

func (BrantaServerBaseURL) URL

func (u BrantaServerBaseURL) URL() string

URL returns the base URL for this server environment (no trailing slash).

type BrantaService

type BrantaService struct {
	// contains filtered or unexported fields
}

BrantaService orchestrates zero-knowledge encrypt/decrypt around the raw HTTP calls in BrantaClient.

The single most important behavioral rule: decryption failures (wrong key, mismatched destination, DEK decrypt failure) are always swallowed internally — a destination that fails to decrypt is simply left encrypted (IsEncrypted = true), never surfaced as an error. The one deliberate exception: when a QR code carries both a plaintext on-chain address and branta_id/branta_secret params, a successful decrypt of the ZK Bitcoin-address destination is compared against that plaintext address, and a mismatch propagates ErrTampered.

func NewBrantaService

func NewBrantaService(defaultOptions BrantaClientOptions) *BrantaService

NewBrantaService is the production constructor: real HTTP client, real AES-GCM, real UUID generator.

func NewBrantaServiceWithDeps

func NewBrantaServiceWithDeps(
	defaultOptions BrantaClientOptions,
	client Client,
	aes AESEncryption,
	secretGenerator SecretGenerator,
) *BrantaService

NewBrantaServiceWithDeps is the test/advanced constructor: inject alternate implementations (e.g. mocks).

func (*BrantaService) AddPayment

func (s *BrantaService) AddPayment(ctx context.Context, payment Payment, options *BrantaClientOptions) (AddPaymentResult, error)

AddPayment encrypts ZK destinations and posts the payment.

func (*BrantaService) GetPayments

func (s *BrantaService) GetPayments(ctx context.Context, destinationValue, destinationEncryptionKey string, options *BrantaClientOptions) (PaymentsResult, error)

GetPayments looks up a single destination value.

func (*BrantaService) GetPaymentsByQRCode

func (s *BrantaService) GetPaymentsByQRCode(ctx context.Context, qrText string, options *BrantaClientOptions) (PaymentsResult, error)

GetPaymentsByQRCode parses raw QR text and looks up matching payments.

func (*BrantaService) IsAPIKeyValid

func (s *BrantaService) IsAPIKeyValid(ctx context.Context, options *BrantaClientOptions) (bool, error)

IsAPIKeyValid proxies to the HTTP client health-check.

type Client

type Client interface {
	GetPayments(ctx context.Context, destinationValue string, options *BrantaClientOptions) ([]Payment, error)
	PostPayment(ctx context.Context, payment Payment, options *BrantaClientOptions) (*Payment, error)
	IsAPIKeyValid(ctx context.Context, options *BrantaClientOptions) (bool, error)
}

Client is the raw HTTP layer. Consumers should never call this directly — go through BrantaService.

type DecryptionError

type DecryptionError struct {
	Err error
}

DecryptionError wraps a failed decrypt operation (wrong key, malformed ciphertext, etc). Distinct from ErrEncryptedDataTooShort.

func (*DecryptionError) Error

func (e *DecryptionError) Error() string

func (*DecryptionError) Unwrap

func (e *DecryptionError) Unwrap() error

type Destination

type Destination struct {
	Value        string          `json:"value"`
	IsPrimary    bool            `json:"primary"`
	IsZk         bool            `json:"zk"`
	IsEncrypted  bool            `json:"-"`
	Type         DestinationType `json:"type,omitempty"`
	ZkID         string          `json:"zk_id,omitempty"`
	EncryptedDEK string          `json:"encrypted_dek,omitempty"`
}

Destination is a payment destination exchanged with the Branta API.

Field names on the wire are snake_case (with `primary`/`zk` rather than `is_primary`/`is_zk`) and must match every other Branta SDK exactly. IsEncrypted is client-side-only derived state and is never serialized.

func NewDestination

func NewDestination(value string, destType DestinationType) Destination

NewDestination constructs a destination with the given value and optional type.

type DestinationType

type DestinationType string

DestinationType is the type of a payment destination.

Wire format is snake_case and MUST match every other Branta SDK exactly for cross-SDK interoperability.

const (
	BitcoinAddress DestinationType = "bitcoin_address"
	Bolt11         DestinationType = "bolt11"
	Bolt12         DestinationType = "bolt12"
	LnUrl          DestinationType = "ln_url"
	TetherAddress  DestinationType = "tether_address"
	LnAddress      DestinationType = "ln_address"
	ArkAddress     DestinationType = "ark_address"
	SilentPayment  DestinationType = "silent_payment"
)

func HashZkType

func HashZkType(value string) DestinationType

HashZkType returns the hash-ZK DestinationType for value, or empty if it isn't one of the three hash-ZK types (bolt11, ark, silent payment).

Intentionally returns empty for Bolt12 / LnUrl / LnAddress / TetherAddress — those are valid DestinationTypes but are NOT hash-ZK types in any sibling SDK. Do not "fix" this.

type EncryptionError

type EncryptionError struct {
	Err error
}

EncryptionError wraps a failed encrypt operation.

func (*EncryptionError) Error

func (e *EncryptionError) Error() string

func (*EncryptionError) Unwrap

func (e *EncryptionError) Unwrap() error

type GuidSecretGenerator

type GuidSecretGenerator struct{}

GuidSecretGenerator is the production SecretGenerator: random UUID v4 secrets, non-deterministic nonces.

func (GuidSecretGenerator) DeterministicNonce

func (GuidSecretGenerator) DeterministicNonce() bool

func (GuidSecretGenerator) Generate

func (GuidSecretGenerator) Generate() string

type LogoURLDomainMismatchError

type LogoURLDomainMismatchError struct {
	Field string
}

LogoURLDomainMismatchError is returned when a GET response contains a logo URL whose origin does not match the configured base URL.

func (*LogoURLDomainMismatchError) Error

type Payment

type Payment struct {
	Description               string        `json:"description,omitempty"`
	Destinations              []Destination `json:"destinations"`
	CreatedAt                 string        `json:"created_at,omitempty"`
	TTL                       int           `json:"ttl"`
	Metadata                  string        `json:"metadata,omitempty"`
	Platform                  string        `json:"platform,omitempty"`
	PlatformLogoURL           string        `json:"platform_logo_url,omitempty"`
	PlatformLogoLightURL      string        `json:"platform_logo_light_url,omitempty"`
	ParentPlatform            *Platform     `json:"parent_platform,omitempty"`
	ChildPlatform             *Platform     `json:"child_platform,omitempty"`
	BtcPayServerPluginVersion string        `json:"btc_pay_server_plugin_version,omitempty"`
	IsMetadataDecrypted       bool          `json:"-"`
}

Payment is the wire model for a Branta payment.

ParentPlatform is deserialize-only: set by the server, never sent on a POST. IsMetadataDecrypted is client-side-only and is never serialized.

NOTE: the majority wire name across sibling SDKs (dotnet/js/python/dart/rust) is `btc_pay_server_plugin_version`. branta-kotlin alone uses `btcpay_server_plugin_version` — a pre-existing cross-SDK inconsistency, not something to replicate here.

func (Payment) DefaultValue

func (p Payment) DefaultValue() (string, error)

DefaultValue returns the value of the first destination, or ErrNoDestinations.

func (Payment) MarshalJSON

func (p Payment) MarshalJSON() ([]byte, error)

MarshalJSON omits parent_platform (deserialize-only) and client-side flags.

type PaymentBuilder

type PaymentBuilder struct {
	// contains filtered or unexported fields
}

PaymentBuilder is a fluent builder for constructing a Payment to post.

func NewPaymentBuilder

func NewPaymentBuilder() *PaymentBuilder

NewPaymentBuilder returns an empty builder.

func (*PaymentBuilder) AddDestination

func (b *PaymentBuilder) AddDestination(address string, destType DestinationType) *PaymentBuilder

AddDestination adds a new destination. Call SetZk immediately after to mark it as ZK. An empty destType leaves the destination untyped.

func (*PaymentBuilder) AddMetadata

func (b *PaymentBuilder) AddMetadata(key, value string) *PaymentBuilder

AddMetadata merges key/value into the payment's metadata, which is stored as a JSON-object string (i.e. double-encoded: metadata is itself the serialized form of a {key: value} map).

func (*PaymentBuilder) Build

func (b *PaymentBuilder) Build() Payment

Build returns the constructed Payment.

func (*PaymentBuilder) SetChildPlatform

func (b *PaymentBuilder) SetChildPlatform(name, logoURL, logoLightURL string) *PaymentBuilder

SetChildPlatform tags the payment with child-platform branding.

func (*PaymentBuilder) SetDescription

func (b *PaymentBuilder) SetDescription(description string) *PaymentBuilder

SetDescription sets the payment description.

func (*PaymentBuilder) SetPlatformLogoURL

func (b *PaymentBuilder) SetPlatformLogoURL(platformLogoURL string) *PaymentBuilder

SetPlatformLogoURL sets the platform logo URL.

func (*PaymentBuilder) SetTTL

func (b *PaymentBuilder) SetTTL(ttl int) *PaymentBuilder

SetTTL sets the payment time-to-live in seconds.

func (*PaymentBuilder) SetZk

func (b *PaymentBuilder) SetZk() *PaymentBuilder

SetZk marks the most-recently-added destination as ZK and assigns it a fresh zk_id.

type PaymentsResult

type PaymentsResult struct {
	Payments  []Payment
	VerifyURL string
}

PaymentsResult is the result of GetPayments / GetPaymentsByQRCode.

VerifyURL is always populated, even when Payments is empty.

type Platform

type Platform struct {
	Name         string `json:"name,omitempty"`
	LogoURL      string `json:"logo_url,omitempty"`
	LogoLightURL string `json:"logo_light_url,omitempty"`
}

Platform holds branding for a parent or child platform.

type PrivacyMode

type PrivacyMode int

PrivacyMode controls whether plain-text (non zero-knowledge) lookups and destinations are permitted.

Strict is the default and should be used unless a QR scanner is unavailable and zero-knowledge encryption is therefore impossible.

const (
	// PrivacyStrict forbids plain-text on-chain lookups and non-ZK destinations.
	// Never serialized over the wire.
	PrivacyStrict PrivacyMode = iota
	// PrivacyLoose removes zero-knowledge restrictions.
	PrivacyLoose
)

type QRDestination

type QRDestination struct {
	Value string
	Type  DestinationType
}

QRDestination is a single destination parsed from QR text.

type QRParser

type QRParser struct {
	Destinations            []QRDestination
	OnChainEncryptionText   string
	OnChainEncryptionSecret string
}

QRParser parses raw QR text into one or more payment destinations.

Infallible by design — no sibling SDK ever raises a parse error; unrecognized input just yields a destination with an empty Type.

func NewQRParser

func NewQRParser(qrText string) QRParser

NewQRParser parses qrText.

func (QRParser) Destination

func (p QRParser) Destination() (string, bool)

Destination returns the first destination value, if any.

func (QRParser) DestinationType

func (p QRParser) DestinationType() DestinationType

DestinationType returns the first destination type, if any.

func (QRParser) IsOnChainZk

func (p QRParser) IsOnChainZk() bool

IsOnChainZk is true iff both branta_id and branta_secret query params were present.

type RequestFailedError

type RequestFailedError struct {
	Status int
}

RequestFailedError is returned when a POST (or other mutating call) receives a non-2xx status.

func (*RequestFailedError) Error

func (e *RequestFailedError) Error() string

type SecretGenerator

type SecretGenerator interface {
	Generate() string
	DeterministicNonce() bool
}

SecretGenerator is the secret/nonce generation strategy, injectable for testing.

type UnsupportedZkDestinationTypeError

type UnsupportedZkDestinationTypeError struct {
	Type DestinationType
}

UnsupportedZkDestinationTypeError is returned when AddPayment is asked to encrypt a destination whose type is not a hash-ZK type and is not a Bitcoin address.

func (*UnsupportedZkDestinationTypeError) Error

Directories

Path Synopsis
examples
branta_example command
Command branta_example is an end-to-end usage demo.
Command branta_example is an end-to-end usage demo.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL