BSV.Tokens.Factory.Stas3 (bsv_sdk v1.4.0)

Copy Markdown View Source

STAS3 transaction factories.

Pure functions that build complete, signed transactions for STAS 3 token operations: two-tx issuance, base spend, freeze, unfreeze, and swap.

Summary

Functions

Build a generic STAS3 spend transaction.

Build a STAS3 confiscation transaction.

Build a STAS3 freeze transaction.

Build the two-transaction STAS3 issuance flow.

Build a STAS3 merge transaction.

Build a STAS3 redeem transaction.

Build a STAS3 split transaction.

Build a STAS3 swap flow transaction with auto-detected mode.

Build a STAS3 swap-swap transaction.

Build a STAS3 transfer-swap transaction.

Build a STAS3 unfreeze transaction.

Detect whether a swap is transfer-swap or swap-swap based on input locking scripts.

Types

base_config()

@type base_config() :: %{
  token_inputs: [BSV.Tokens.TokenInput.t()],
  fee_txid: binary(),
  fee_vout: non_neg_integer(),
  fee_satoshis: non_neg_integer(),
  fee_locking_script: BSV.Script.t(),
  fee_private_key: BSV.PrivateKey.t(),
  destinations: [BSV.Tokens.Stas3OutputParams.t()],
  spend_type: BSV.Tokens.Stas3SpendType.t(),
  fee_rate: non_neg_integer()
}

issue_config()

@type issue_config() :: %{
  scheme: BSV.Tokens.Scheme.t(),
  funding_txid: binary(),
  funding_vout: non_neg_integer(),
  funding_satoshis: non_neg_integer(),
  funding_locking_script: BSV.Script.t(),
  funding_private_key: BSV.PrivateKey.t() | nil,
  funding_key: BSV.Tokens.SigningKey.t() | nil,
  outputs: [
    %{satoshis: non_neg_integer(), owner_pkh: <<_::160>>, freezable: boolean()}
  ],
  fee_rate: non_neg_integer()
}

Functions

build_stas3_base_tx(config)

@spec build_stas3_base_tx(base_config()) ::
  {:ok, BSV.Transaction.t()} | {:error, term()}

Build a generic STAS3 spend transaction.

build_stas3_confiscate_tx(config)

@spec build_stas3_confiscate_tx(base_config()) ::
  {:ok, BSV.Transaction.t()} | {:error, term()}

Build a STAS3 confiscation transaction.

Confiscates token UTXOs using spending type 3 (confiscation authority path). Frozen inputs CAN be confiscated. The scheme must have confiscation enabled and service fields must include the confiscation authority.

Parameters

  • config - A base_config() map. The spend_type will be overridden to :confiscation.

Returns

  • {:ok, transaction} on success
  • {:error, reason} on validation failure

build_stas3_freeze_tx(config)

@spec build_stas3_freeze_tx(base_config()) ::
  {:ok, BSV.Transaction.t()} | {:error, term()}

Build a STAS3 freeze transaction.

build_stas3_issue_txs(config)

@spec build_stas3_issue_txs(issue_config()) ::
  {:ok, %{contract_tx: BSV.Transaction.t(), issue_tx: BSV.Transaction.t()}}
  | {:error, term()}

Build the two-transaction STAS3 issuance flow.

build_stas3_merge_tx(config)

@spec build_stas3_merge_tx(base_config()) ::
  {:ok, BSV.Transaction.t()} | {:error, term()}

Build a STAS3 merge transaction.

Merges exactly 2 STAS inputs into 1-2 STAS outputs. This is a semantic wrapper around build_stas3_base_tx/1 that enforces merge-specific constraints.

Parameters

  • config - A base_config() map with:
    • :token_inputs - Exactly 2 token inputs
    • :destinations - 1-2 STAS3 output destinations
    • Other fields as per base_config()

Returns

  • {:ok, transaction} on success
  • {:error, reason} on validation failure

build_stas3_redeem_tx(config)

@spec build_stas3_redeem_tx(map()) :: {:ok, BSV.Transaction.t()} | {:error, term()}

Build a STAS3 redeem transaction.

Redeems STAS tokens back to regular P2PKH satoshis. Only the issuer can redeem. This is NOT a wrapper around build_stas3_base_tx/1 because the primary output is P2PKH rather than STAS3.

Parameters

  • config - A map with:
    • :token_input - A single TokenInput (the STAS UTXO to redeem)
    • :fee_txid, :fee_vout, :fee_satoshis, :fee_locking_script, :fee_private_key - Funding input for fees
    • :redeem_satoshis - Amount to redeem as P2PKH output
    • :redeem_pkh - The 20-byte pubkey hash for the P2PKH redeem output
    • :remaining_destinations - Optional list of Stas3OutputParams for remaining STAS outputs (default [])
    • :fee_rate - Fee rate in sat/KB

Rules

  • Token input owner must be the issuer (owner_pkh == redemption_pkh from script)
  • Frozen inputs cannot be redeemed
  • Conservation: stas_in == redeem_satoshis + sum(remaining STAS outputs)
  • Uses spending type 1 (regular)

Returns

  • {:ok, transaction} on success
  • {:error, reason} on validation failure

build_stas3_split_tx(config)

@spec build_stas3_split_tx(base_config()) ::
  {:ok, BSV.Transaction.t()} | {:error, term()}

Build a STAS3 split transaction.

Splits a single STAS input into 1-4 STAS outputs. This is a semantic wrapper around build_stas3_base_tx/1 that enforces split-specific constraints: exactly 1 STAS input and 1-4 destinations.

Parameters

  • config - A base_config() map with:
    • :token_inputs - Exactly 1 token input
    • :destinations - 1-4 STAS3 output destinations
    • Other fields as per base_config()

Returns

  • {:ok, transaction} on success
  • {:error, reason} on validation failure

build_stas3_swap_flow_tx(config)

@spec build_stas3_swap_flow_tx(base_config()) ::
  {:ok, BSV.Transaction.t()} | {:error, term()}

Build a STAS3 swap flow transaction with auto-detected mode.

Reads each input's locking script to detect swap action data:

  • Both inputs have swap action data → swap-swap (spending type 4)
  • Otherwise → transfer-swap (spending type 1)

Parameters

  • config - A base_config() map with exactly 2 token inputs.

Returns

  • {:ok, transaction} on success
  • {:error, reason} on validation failure

build_stas3_swap_swap_tx(config)

@spec build_stas3_swap_swap_tx(base_config()) ::
  {:ok, BSV.Transaction.t()} | {:error, term()}

Build a STAS3 swap-swap transaction.

Both sides are swap requests (spending type 4). Requires exactly 2 STAS inputs, both carrying swap action data. Rejects frozen inputs.

Outputs can be 2-4 STAS outputs:

  • Outputs 0-1: principal swap legs (neutral action data)
  • Output 2: optional remainder for leg 1
  • Output 3: optional remainder for leg 2

Parameters

  • config - A base_config() map with exactly 2 token inputs and 2-4 destinations.

Returns

  • {:ok, transaction} on success
  • {:error, reason} on validation failure (wrong input count, frozen inputs)

build_stas3_transfer_swap_tx(config)

@spec build_stas3_transfer_swap_tx(base_config()) ::
  {:ok, BSV.Transaction.t()} | {:error, term()}

Build a STAS3 transfer-swap transaction.

One side transfers (spending type 1), the other side's swap request is consumed. Requires exactly 2 STAS inputs. Rejects frozen inputs.

Outputs can be 2-4 STAS outputs:

  • Outputs 0-1: principal swap legs (neutral action data)
  • Output 2: optional remainder for leg 1
  • Output 3: optional remainder for leg 2

Parameters

  • config - A base_config() map with exactly 2 token inputs and 2-4 destinations.

Returns

  • {:ok, transaction} on success
  • {:error, reason} on validation failure (wrong input count, frozen inputs)

build_stas3_unfreeze_tx(config)

@spec build_stas3_unfreeze_tx(base_config()) ::
  {:ok, BSV.Transaction.t()} | {:error, term()}

Build a STAS3 unfreeze transaction.

resolve_stas3_swap_mode(token_inputs)

@spec resolve_stas3_swap_mode([BSV.Tokens.TokenInput.t()]) ::
  :swap_swap | :transfer_swap

Detect whether a swap is transfer-swap or swap-swap based on input locking scripts.

Reads each input's locking script and checks for swap action data:

  • Both inputs have swap action data → :swap_swap
  • Otherwise → :transfer_swap

Parameters

  • token_inputs - List of exactly 2 TokenInput structs

Returns

  • :swap_swap or :transfer_swap