nodeapi

package
v0.15.0 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package nodeapi talks to a Teranode node over HTTP: JSON-RPC for mining and direct submission, the asset API for reading what got mined.

It is the funding and settlement side of a producer, and nothing a reader depends on: a reader verifies against a header source, never against a node it would have to trust.

Every response body is bounded before it is parsed and every declared count in a binary proof is checked against the bytes present before the SDK is allowed to allocate for it. The node is trusted to be honest about the chain, which is not the same as trusting it to be well behaved about response size (the same rule the headers package states).

The JSON shapes decoded here are the ones a Teranode node's RPC and asset API answer. The tests' response bodies are written to those shapes, not captured from a live node.

Index

Examples

Constants

View Source
const WoCBase = "https://api.whatsonchain.com/v1/bsv/"

WoCBase is the WhatsOnChain API root, before the network.

View Source
const WoCFreeRate = 3

WoCFreeRate is WhatsOnChain's free tier: "Up to 3 requests/sec".

Variables

View Source
var ErrBodyTooLarge = errors.New("nodeapi: response body exceeds the bound")

ErrBodyTooLarge refuses a response above the bound.

View Source
var ErrChainSpec = errors.New("nodeapi: bad chain specification")

ErrChainSpec is a chain view specification that cannot be used.

View Source
var ErrDoubleSpent = errors.New("an input is spent by another transaction")

ErrDoubleSpent is a transaction one of whose inputs the node shows spent by another transaction. It never mines. Every error this package and the packages built on it return for that case wraps it, so errors.Is finds it whatever the broadcaster said.

View Source
var ErrHeader = errors.New("nodeapi: header does not hash to its hash")

ErrHeader is a header answer whose fields do not hash to its hash.

View Source
var ErrNoID = errors.New("nodeapi: rpc: no request id")

ErrNoID refuses a call on an RPC with no request id. The library has no id of its own to fall back on, and any default would put one application's name on another's requests.

View Source
var ErrNotMined = errors.New("nodeapi: not mined")

ErrNotMined reports a transaction the node has not placed in a main-chain block yet, or a proof it cannot build yet. It is a state, not a failure: callers poll again after the next block.

View Source
var ErrProofRefused = errors.New("nodeapi: proof does not verify against the headers")

ErrProofRefused is a proof that does not verify against the caller's headers. It is the source lying or on another chain, never "not yet".

View Source
var ErrSpendUnknown = errors.New("the node does not say whether the output is spent")

ErrSpendUnknown is the node's UTXO view saying neither that an output is unspent nor who spent it. Every error Spender returns wraps it, so a caller that must not mistake "no answer" for "unspent" tests one error. An output the answer leaves out, a status other than OK or SPENT, a SPENT with no spender, an answer that does not decode, a transaction the node does not serve (a 404, which a node also answers for a fully spent transaction it has pruned) and a failed read are all this. The status NOT_FOUND is one of them: a node answers it for an output it holds no record of, which it has pruned or could not read, as well as for one it never stored.

View Source
var ErrTxNotFound = errors.New("nodeapi: transaction not known")

ErrTxNotFound is a transaction a source does not hold. *Asset answers it as an *HTTPError with status 404; IsNotFound reads both.

Functions

func CheckProof added in v0.14.0

func CheckProof(ctx context.Context, mp *transaction.MerklePath, txid string, headers chaintracker.ChainTracker) error

CheckProof verifies that mp proves txid against headers: txid at the leaf level, and the root it computes is the one headers hold at its height.

func IsHTTP

func IsHTTP(err error, status int) bool

IsHTTP reports whether err is an HTTPError with the given status.

func IsNotFound added in v0.14.0

func IsNotFound(err error) bool

IsNotFound reports a TxSource's "not known": ErrTxNotFound, or a 404.

func ProofFor

func ProofFor(raw []byte, txid string) (*transaction.MerklePath, error)

ProofFor parses a BUMP someone else supplied as the proof for txid, and refuses one that does not name txid at its leaf level. Every source of a proof goes through here: the bytes come from a service, and a path for some other transaction would build a BEEF that no host accepts. The proof is held to the same bound as every answer this package reads.

Example

ProofFor is where every proof a service supplies enters: the guard walks it before the SDK parses it, and a proof that does not name the transaction it was asked for is refused, because it would verify perfectly and prove nothing.

package main

import (
	"crypto/sha256"
	"fmt"

	"github.com/bsv-blockchain/go-sdk/chainhash"
	"github.com/bsv-blockchain/go-sdk/transaction"

	"github.com/lightwebinc/bcommon/nodeapi"
)

func main() {
	txid := chainhash.Hash(sha256.Sum256([]byte("a transaction")))
	sibling := chainhash.Hash(sha256.Sum256([]byte("its neighbour")))
	isTxid := true
	raw := transaction.NewMerklePath(90, [][]*transaction.PathElement{{
		{Offset: 0, Hash: &sibling},
		{Offset: 1, Hash: &txid, Txid: &isTxid},
	}}).Bytes()

	mp, err := nodeapi.ProofFor(raw, txid.String())
	fmt.Println("asked for:", mp != nil, err)

	unrelated := chainhash.Hash(sha256.Sum256([]byte("some other transaction")))
	_, err = nodeapi.ProofFor(raw, unrelated.String())
	fmt.Println("asked for another:", err)

	_, err = nodeapi.ProofFor(raw[:len(raw)-1], txid.String())
	fmt.Println("truncated:", err)
}
Output:
asked for: true <nil>
asked for another: proof does not contain the txid
truncated: bump ends mid-structure

func SpentElsewhereIn added in v0.14.0

func SpentElsewhereIn(ctx context.Context, s SpendSource, tx *transaction.Transaction) error

SpentElsewhereIn is Asset.SpentElsewhere over any SpendSource: a *SpentError for the first input of tx the source shows spent by another transaction, or nil. An input the source cannot answer for is passed over, so nil is not evidence that the inputs are unspent.

func WaitMined

func WaitMined(ctx context.Context, asset *Asset, txid string, poll time.Duration) (*transaction.MerklePath, uint32, error)

WaitMined polls until txid is placed in a main-chain block and its proof is served, or ctx ends. It returns the proof and the block height.

func WaitMinedOn added in v0.14.0

func WaitMinedOn(ctx context.Context, p ProofSource, txid string, poll time.Duration) (*transaction.MerklePath, uint32, error)

WaitMinedOn is WaitMined over any ProofSource: it polls until txid's proof is served, or ctx ends.

func WaitSettled added in v0.5.4

func WaitSettled(ctx context.Context, asset *Asset, tx *transaction.Transaction, poll time.Duration) (*transaction.MerklePath, uint32, error)

WaitSettled is WaitMined for a transaction the caller holds: while tx has not mined, each poll also asks the node whether one of its inputs is spent by another transaction, and returns that *SpentError (errors.Is ErrDoubleSpent) at once rather than waiting until ctx ends.

func WaitSettledOn added in v0.14.0

WaitSettledOn is WaitSettled over any ProofSource and SpendSource: while tx has not mined, each poll also asks spends (when not nil) whether one of its inputs is spent by another transaction, and returns that *SpentError (errors.Is ErrDoubleSpent) at once.

Types

type Asset

type Asset struct {
	// Base is the API root with no path suffix, e.g. http://node.example.com:20090.
	Base string
	// Client is optional; the default has a 30s timeout.
	Client *http.Client
}

Asset is a Teranode asset-HTTP-API client.

func (*Asset) BestHeader

func (a *Asset) BestHeader(ctx context.Context) (*Header, error)

BestHeader reads the tip.

func (*Asset) Block

func (a *Asset) Block(ctx context.Context, hash string) (*Block, error)

Block reads one block by hash.

func (*Asset) BlockTime added in v0.11.0

func (a *Asset) BlockTime(ctx context.Context, height uint32) (time.Time, error)

BlockTime is the time of the main-chain block at height, from its header, which must hash to the hash the node names for that height (Check). The node is trusted for which block is at the height; a caller that must not trust it checks the header's hash or merkle root against its headers.

func (*Asset) HashAtHeight

func (a *Asset) HashAtHeight(ctx context.Context, height uint32) (string, error)

HashAtHeight resolves a main-chain block hash by height through the paged block list, where offset counts back from the tip. The tip can move between the two reads, so the answer is checked against the height asked for and the read is retried when it does.

func (*Asset) Header

func (a *Asset) Header(ctx context.Context, hash string) (*Header, error)

Header reads one block header by hash.

func (*Asset) Known added in v0.14.0

func (a *Asset) Known(ctx context.Context, txid string) (bool, error)

Known reports whether the node holds txid, mined or not (/api/v1/txmeta/{txid}/json answers it; a 404 is not known).

func (*Asset) MerkleProof

func (a *Asset) MerkleProof(ctx context.Context, txid string) (*transaction.MerklePath, error)

MerkleProof returns the BRC-74 BUMP for a mined transaction, parsed.

The node answers 404 for a transaction it has not placed in a main-chain block and 500 for a proof with an empty path (a single-transaction block); both are ErrNotMined to a caller that will ask again after the next block.

The bytes are walked by the guard package before the SDK parses them, and the parse runs under a recover, so a malformed proof is an error and never a crash. The parsed path must also contain txid at its leaf level: a proof the node served for the wrong transaction verifies perfectly and proves nothing.

func (*Asset) Proof

func (a *Asset) Proof(ctx context.Context, txid string) (*transaction.MerklePath, uint32, error)

Proof asks once whether txid is mined and returns its proof and height if so, or ErrNotMined. It is WaitMined without the waiting, for a caller that collects proofs later rather than blocking on them.

func (*Asset) Spender added in v0.5.4

func (a *Asset) Spender(ctx context.Context, txid string, vout uint32) (string, error)

Spender reads the node's UTXO view of txid (/api/v1/utxos/{txid}/json) and names the transaction that spent output vout, or "" with a nil error when the node shows the output unspent (status OK). Only those two answers are evidence. Anything else is an error wrapping ErrSpendUnknown, never "": see ErrSpendUnknown for what the node answers that is not evidence. A transaction the node does not serve is also an *HTTPError with status 404 (IsHTTP).

A caller that acts on "unspent", such as returning a coin to a pool, acts only on a nil error and "", and treats an error as undecided: it changes nothing and asks again later.

func (*Asset) SpentElsewhere added in v0.5.4

func (a *Asset) SpentElsewhere(ctx context.Context, tx *transaction.Transaction) error

SpentElsewhere returns a *SpentError for the first input of tx the node shows spent by another transaction, or nil when there is none: then tx can still mine as far as its inputs go. An input the node cannot answer for (Spender's ErrSpendUnknown: a parent it does not serve, a status that is neither OK nor SPENT, a read that failed) is passed over, so this refuses only on the node's positive word. nil is therefore not evidence that tx's inputs are unspent; a caller that needs that asks Spender per input.

func (*Asset) TxMeta

func (a *Asset) TxMeta(ctx context.Context, txid string) (*TxMeta, error)

TxMeta reads a transaction's placement. A 404 is ErrNotMined: for a submission in flight, "never seen" and "not placed yet" are one state.

func (*Asset) TxRaw

func (a *Asset) TxRaw(ctx context.Context, txid string) ([]byte, error)

TxRaw returns a transaction's raw serialisation. A node may answer in the raw form or in Extended Format (BRC-30), the raw form with each input's previous output added, as a Teranode asset API does; either is walked by guard.RawTransaction and the raw form returned, so a caller always gets bytes guard.ParseTransaction reads. The previous outputs an Extended Format answer carries are dropped.

type Block

type Block struct {
	Hash       string `json:"hash"`
	Height     uint32 `json:"height"`
	CoinbaseTx struct {
		TxID    string `json:"txid"`
		Outputs []struct {
			Satoshis      uint64 `json:"satoshis"`
			LockingScript string `json:"lockingScript"`
		} `json:"outputs"`
	} `json:"coinbase_tx"`
}

Block is the subset of /api/v1/block/{hash}/json read here: the coinbase outputs are what fund the pool.

type Chain added in v0.14.0

type Chain interface {
	TxSource
	ProofSource
	SpendSource
}

Chain is the three views a producer needs to fund, prove and refuse.

type ChainOptions added in v0.14.0

type ChainOptions struct {
	// WoCKey is the WhatsOnChain API key, if any, and WoCRate its
	// requests a second (zero is WoCFreeRate).
	WoCKey  string
	WoCRate float64
	// Client, when set, is every backend's HTTP client.
	Client *http.Client
	// Headers is required: every proof a backend answers is checked
	// against it (Checked) before the Sources return it.
	Headers chaintracker.ChainTracker
}

ChainOptions are the settings a chain specification does not carry: secrets and transport.

type Checked added in v0.14.0

type Checked struct {
	Source  ProofSource
	Headers chaintracker.ChainTracker
}

Checked is a ProofSource whose every proof is verified against Headers before it is returned: it must name txid at its leaf level (ProofFor's rule) and its root must be the one Headers holds at its height. Wrap any third party's proofs in it; a node's own are checked the same way.

func (Checked) Proof added in v0.14.0

func (c Checked) Proof(ctx context.Context, txid string) (*transaction.MerklePath, uint32, error)

Proof is Source's proof once Headers confirm it, ErrNotMined as Source answers it, and an error wrapping ErrProofRefused for a proof Headers do not hold. A header source that cannot answer is an error, not a refusal.

type HTTPError

type HTTPError struct {
	Method string
	Path   string
	Status int
	Body   string
}

HTTPError is a non-2xx answer, kept so callers can distinguish a 404 from a transport failure.

func (*HTTPError) Error

func (e *HTTPError) Error() string
type Header struct {
	Hash       string `json:"hash"`
	Prev       string `json:"previousblockhash"`
	MerkleRoot string `json:"merkleroot"`
	Height     uint32 `json:"height"`
	// Version, Time (Unix seconds), Bits (hex) and Nonce are the rest of
	// the 80 bytes the hash is over; Check rebuilds them.
	Version uint32 `json:"version"`
	Time    uint32 `json:"time"`
	Bits    string `json:"bits"`
	Nonce   uint32 `json:"nonce"`
}

Header is the subset of a block header answer a caller needs.

func (*Header) Check added in v0.11.0

func (h *Header) Check() error

Check rebuilds the 80-byte header from h's fields and refuses, as ErrHeader, one whose double SHA-256 is not h.Hash. A header that passes carries the fields its hash commits to, so its Time is the block's own once the hash is known to be on the chain (through headers, say); before that it is the node's word.

type Info

type Info struct {
	Blocks      int64 `json:"blocks"`
	Connections int64 `json:"connections"`
	Version     int64 `json:"version"`
}

Info is the subset of getinfo used here. Teranode registers getblockcount but answers "Command unimplemented", so the height comes from here.

type KnownSource added in v0.14.0

type KnownSource interface {
	Known(ctx context.Context, txid string) (bool, error)
}

KnownSource reports whether the source holds a transaction at all, mined or not: true for "known", false with a nil error for "not known", an error when it cannot say. A transaction known and not mined is one to wait for; one not known after it was sent is one to send again.

type ProofSource added in v0.14.0

type ProofSource interface {
	Proof(ctx context.Context, txid string) (*transaction.MerklePath, uint32, error)
}

ProofSource returns a mined transaction's proof and block height, or ErrNotMined while it has not mined (or the source does not know it).

type RPC

type RPC struct {
	// URL is the RPC endpoint, e.g. http://node.example.com:21292/.
	URL  string
	User string
	Pass string
	// ID is the JSON-RPC request id, sent verbatim on every call. It is the
	// application's to choose and it is required: Call refuses an empty one
	// before any request is sent rather than choosing one itself.
	ID string
	// Client is optional; the default has a 60s timeout, which is long
	// because generatetoaddress mines inline. The lever for a slow node is
	// the batch size, not this.
	Client *http.Client
}

RPC is a Teranode JSON-RPC client.

func (*RPC) Call

func (r *RPC) Call(ctx context.Context, method string, params []any, out any) error

Call issues one JSON-RPC call and unmarshals the result into out, which may be nil. An RPC-level error is returned as the node phrased it. An RPC with no ID is refused with ErrNoID before anything is sent.

func (*RPC) GenerateToAddress

func (r *RPC) GenerateToAddress(ctx context.Context, n int, addr string) ([]string, error)

GenerateToAddress mines n blocks paying the coinbase to addr and returns the block hashes. Keep n small: a large call can outlast the RPC timeout, which is why FundFromCoinbase mines in batches. Coinbase: only on a regtest chain you run (development and tests).

func (*RPC) GetInfo

func (r *RPC) GetInfo(ctx context.Context) (*Info, error)

GetInfo reads the node's view of the tip.

func (*RPC) SendRawTransaction

func (r *RPC) SendRawTransaction(ctx context.Context, rawHex string) (string, error)

SendRawTransaction submits standard-format hex straight to the node and returns the txid it acknowledged. This is the settlement leg with an ack; the TCP ingress has none.

type Sources added in v0.14.0

type Sources struct {
	Tx     []TxSource
	Proofs []ProofSource
	Spends SpendSource
	Knows  KnownSource
}

Sources is a Chain built from a backend per method, which is how an application picks them in configuration (ParseChain). Presence answers may come from any backend in a list, tried in order, since each is checked: a transaction must hash to its txid, and a proof should be wrapped in Checked by the caller who holds the headers. Absence answers come from the one Spends and the one Knows backend only.

func ParseChain added in v0.14.0

func ParseChain(spec string, opt ChainOptions) (*Sources, error)

ParseChain reads a chain view specification, in the style of headers.Parse: comma-separated backends, each

woc:main | woc:test     the public WhatsOnChain API (*WoC)
asset:http://node:8090  a Teranode asset API (*Asset)

with every proof checked against opt.Headers (Checked), optionally qualified by the one method it serves: tx=, proof=, spend= or known=. An unqualified backend serves every method. Transactions and proofs are asked of every backend that serves them, in order, since each answer is checked. "Spent", "unspent" and "known" come from one backend only: the first that serves spend (or known), so that an absence answer is never a fall-through. Arcade, which proves only what it was sent, is not named here; put a publish.Arcade first in Proofs, as producer.Proofs does.

woc:main                               no node, mainnet
asset:http://node:8090                 a node for everything
asset:http://node:8090,woc:main        a node, WhatsOnChain for what it lacks
woc:test,spend=asset:http://node:8090  WhatsOnChain, a node's spend view

func (*Sources) Known added in v0.14.0

func (s *Sources) Known(ctx context.Context, txid string) (bool, error)

Known is the Knows backend's answer; with none configured, an error.

func (*Sources) Proof added in v0.14.0

func (s *Sources) Proof(ctx context.Context, txid string) (*transaction.MerklePath, uint32, error)

Proof asks each ProofSource in order and returns the first proof. When every source answers ErrNotMined, so does Proof; a source that failed otherwise does not stop the next from being asked.

func (*Sources) Spender added in v0.14.0

func (s *Sources) Spender(ctx context.Context, txid string, vout uint32) (string, error)

Spender is the Spends backend's answer; with none configured, every answer is ErrSpendUnknown.

func (*Sources) SpentElsewhere added in v0.14.0

func (s *Sources) SpentElsewhere(ctx context.Context, tx *transaction.Transaction) error

SpentElsewhere is SpentElsewhereIn over the Spends backend.

func (*Sources) TxRaw added in v0.14.0

func (s *Sources) TxRaw(ctx context.Context, txid string) ([]byte, error)

TxRaw asks each TxSource in order and returns the first answer whose bytes are the transaction txid names. Every source not holding it is IsNotFound; the error otherwise joins what each said.

type SpendSource added in v0.14.0

type SpendSource interface {
	Spender(ctx context.Context, txid string, vout uint32) (string, error)
}

SpendSource names the transaction that spent an output, "" with a nil error only when the source shows it unspent, and an error wrapping ErrSpendUnknown for every other answer.

type SpentError added in v0.5.4

type SpentError struct {
	Txid string
	// Input is the index of the input in Txid; Outpoint is what it spends,
	// txid.vout.
	Input    int
	Outpoint string
	By       string
}

SpentError names the input of Txid that the node shows spent by By.

func (*SpentError) Error added in v0.5.4

func (e *SpentError) Error() string

func (*SpentError) Unwrap added in v0.5.4

func (e *SpentError) Unwrap() error

Unwrap makes a *SpentError errors.Is ErrDoubleSpent.

type TSCProof added in v0.14.0

type TSCProof struct {
	Index  uint64   `json:"index"`
	TxOrID string   `json:"txOrId"`
	Target string   `json:"target"`
	Nodes  []string `json:"nodes"`
}

TSCProof is one entry of WhatsOnChain's /tx/{txid}/proof/tsc answer: a TSC merkle proof (the transaction's index in its block, the block hash as target, and the sibling at each level, "*" for a duplicate).

func (*TSCProof) MerklePath added in v0.14.0

func (p *TSCProof) MerklePath(txid string, height uint32) (*transaction.MerklePath, error)

MerklePath converts a TSC proof of txid into a BRC-74 BUMP at height.

type TxMeta

type TxMeta struct {
	BlockHashes    []string `json:"blockHashes"`
	BlockHeights   []uint32 `json:"blockHeights"`
	SubtreeIdxs    []int    `json:"subtreeIdxs"`
	MainChainIndex int      `json:"mainChainIndex"`
	IsCoinbase     bool     `json:"isCoinbase"`
}

TxMeta is the placement subset of /api/v1/txmeta/{txid}/json. The slices are parallel, one entry per block the transaction landed in, and MainChainIndex selects the main-chain one.

func (*TxMeta) Placement

func (m *TxMeta) Placement() (hash string, height uint32, err error)

Placement returns the main-chain block hash and height, or ErrNotMined when the node knows the transaction but has not placed it.

type TxSource added in v0.14.0

type TxSource interface {
	TxRaw(ctx context.Context, txid string) ([]byte, error)
}

TxSource returns a transaction's raw bytes. A transaction the source does not hold is an error for which IsNotFound is true.

type WoC added in v0.14.0

type WoC struct {
	// Network is "main" or "test".
	Network string
	// Base overrides the API root (default
	// https://api.whatsonchain.com/v1/bsv/<Network>), for a mirror or a
	// test.
	Base string
	// Key, when set, is sent as the Authorization header, as WhatsOnChain
	// documents for an API key.
	Key string
	// Client is optional; the default has a 30 s timeout and takes no
	// proxy from the environment.
	Client *http.Client
	// Rate is requests a second, shared by every call on this value; zero
	// is WoCFreeRate.
	Rate float64
	// MaxTx bounds a transaction's size in bytes; zero is
	// guard.DefaultBound.
	MaxTx int
	// contains filtered or unexported fields
}

WoC is the public WhatsOnChain API for one network, as a TxSource, ProofSource, SpendSource and KnownSource: a chain view that needs no node.

What it answers is held to the same rules as a node's: a transaction must hash to the txid asked for, a proof must name it (and should be checked against the caller's headers, Checked), and a spender must be a txid. Its absence answers are its word: "unspent" is a 404 from the spent endpoint, which WhatsOnChain documents as "known but spent details are not found", and a 400, which it documents as an unknown output (and answers for an unspendable one), is ErrSpendUnknown, never unspent.

The free tier allows 3 requests a second; Rate paces requests to it, and a 429 is retried with backoff. A key (Key) raises the limit on a paid plan; set Rate to match it.

Safe for concurrent use.

func NewWoC added in v0.14.0

func NewWoC(network, key string) (*WoC, error)

NewWoC returns a WhatsOnChain view of network, "main" or "test".

func (*WoC) Known added in v0.14.0

func (w *WoC) Known(ctx context.Context, txid string) (bool, error)

Known is GET /tx/hash/{txid}: true for a transaction WhatsOnChain holds, mined or in its mempool, false for a 404.

func (*WoC) Proof added in v0.14.0

func (w *WoC) Proof(ctx context.Context, txid string) (*transaction.MerklePath, uint32, error)

Proof is txid's proof and height, or ErrNotMined while WhatsOnChain does not hold it mined. It reads the BEEF first and falls back to the raw transaction's TSC proof (/tx/{txid}/proof/tsc) when the BEEF endpoint fails for any other reason, since that endpoint is undocumented. The proof names txid; check it against your headers (Checked).

func (*WoC) Spender added in v0.14.0

func (w *WoC) Spender(ctx context.Context, txid string, vout uint32) (string, error)

Spender is GET /tx/{txid}/{vout}/spent. A 200 names the spender, mined or not; a 404 is unspent ("" and nil), which WhatsOnChain documents as an output it knows with no spend; a 400, its "UTXO is unknown" (also its answer for an unspendable output), and every other answer is an error wrapping ErrSpendUnknown.

func (*WoC) SpentElsewhere added in v0.14.0

func (w *WoC) SpentElsewhere(ctx context.Context, tx *transaction.Transaction) error

SpentElsewhere is SpentElsewhereIn over WhatsOnChain's spends.

func (*WoC) TxBEEF added in v0.14.0

func (w *WoC) TxBEEF(ctx context.Context, txid string) ([]byte, error)

TxBEEF is GET /tx/{txid}/beef, which WhatsOnChain serves but does not document: the transaction as BEEF, with its proof when mined. A 422 (it declines some unmined transactions) is ErrNotMined; a 404, or a 500 saying the transaction is unknown, is ErrTxNotFound. The bytes are returned as served; ParseBEEF them through guard before use.

func (*WoC) TxRaw added in v0.14.0

func (w *WoC) TxRaw(ctx context.Context, txid string) ([]byte, error)

TxRaw is GET /tx/{txid}/hex: the raw transaction, which must hash to txid. A 404 is ErrTxNotFound.

Jump to

Keyboard shortcuts

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