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
@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() }
@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
@spec build_stas3_base_tx(base_config()) :: {:ok, BSV.Transaction.t()} | {:error, term()}
Build a generic STAS3 spend transaction.
@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- Abase_config()map. The spend_type will be overridden to:confiscation.
Returns
{:ok, transaction}on success{:error, reason}on validation failure
@spec build_stas3_freeze_tx(base_config()) :: {:ok, BSV.Transaction.t()} | {:error, term()}
Build a STAS3 freeze transaction.
@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.
@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- Abase_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
@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 singleTokenInput(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 ofStas3OutputParamsfor 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
@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- Abase_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
@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- Abase_config()map with exactly 2 token inputs.
Returns
{:ok, transaction}on success{:error, reason}on validation failure
@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- Abase_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)
@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- Abase_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)
@spec build_stas3_unfreeze_tx(base_config()) :: {:ok, BSV.Transaction.t()} | {:error, term()}
Build a STAS3 unfreeze transaction.
@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 2TokenInputstructs
Returns
:swap_swapor:transfer_swap