Manage Witnet UTXOs

Efficiently manage UTXOs in Witnet with the Witnet SDK.

Transactions in Witnet get paid by signing Unspent Transaction Outputs (or UTXOs), pretty much the same as transactions in Bitcoin. And just like Bitcoin, UTXOs in Witnet can be time-locked. Time-locked UTXOs cannot be spent until the time-lock timestamp is reached.

Aside from UTXOs, Witnet addresses may also hold rights to withdraw delegated stake from network validators. Delegated stake can be withdrawn into UTXOs by means of Unstake Transactions (aka. Stake Withdrawal Transactions). Withdrawn UTXOs get time-locked for a minimum of two weeks.

The balance of any Witnet address is therefore divided in three different fields:

locked

Sum of all time-locked UTXOs, in nanowits. Cannot be spent at this moment.

staked

Funds currently staked into one or more validators, in nanowits. Delegated stake can be eventually withdrawn. Once withdrawn, deposits will remain time-locked for at least two weeks.

unlocked

Sum of currently unlocked UTXOs, in nanowits.

List locked and unlocked UTXOs of some random address

const { Witnet } = require("@witnet/sdk")
const provider = await Witnet.Provider.fromEnv()
const utxos = await provider.getUtxos("wit165ec489lcrt27w5wa7q9je7rgr4dtvyff9vwsc")

Get total balance of some random address

const { utils, Witnet } = require("@witnet/sdk")
const provider = await Witnet.Provider.fromEnv()
const balance = await provider.getBalance("wit165ec489lcrt27w5wa7q9je7rgr4dtvyff9vwsc")

Select all spendable UTXOs in a wallet

const { Witnet } = require("@witnet/sdk")
const wallet = await Witnet.Wallet.fromEnv()
let utxos = await wallet.selectUtxos()

Select spendable UTXOs in a wallet as to cover some target value

Different strategies are possible when selecting input UTXOs as for covering some target value:

UTXO Selection Strategy
Description

"big-first"

Higher value UTXOs are selected first, until target value is covered.

"random"

UTXOs are selected randomly, until target value is covered.

"slim-fit"

The smallest of all UTXOs that individually covers target value is selected. If none fulfills this condition, UTXOs get then selected by following the BigFirst strategy.

"small-first"

Smaller value UTXOs are selected first, until target value is covered.

const { Witnet } = require("@witnet/sdk")

const wallet = await Witnet.Wallet.fromEnv()
const utxos = await wallet.selectUtxos({
    strategy: Witnet.UtxoSelectionStrategy.SmallFirst,
    value: Witnet.Coins.fromWits(10000.0) // 10,000 Wits
});

Joining wallet's spendable UTXOs into a specific wallet account

Joining multiple spendable UTXOs of a wallet into a single UTXO of some specific value is possible by creating a Value Transfer Transaction (or VTT) where all inputs correspond to the spendable UTXOs that are to be joined. The sum of all input UTXOs will then be available as a single UTXO to the recipient of such VTT.

const { Witnet } = require("@witnet/sdk")

const wallet = await Witnet.Wallet.fromEnv({
    strategy: Witnet.UtxoSelectionStrategy.SlimFit,
})
const vtt = await Witnet.ValueTransfers.from(wallet)
const receipt = await vtt.sendTransaction({
    recipients: [[ 
        wallet.accounts[0].pkh, 
        Witnet.Coins.fromWits(10000.0),  // 10,000.00 $WIT
    ]], 
})

The more input UTXOs a VTT has, the greater the transaction weight will be. Because no more than 20,000 VTT weight units can be included within a Witnet block, you can get an exception if trying to build a transaction with too many inputs. In such cases, try changing the UTXO selection strategy to either SlimFit or BigFirst , or creating multiple VTTs with lower target values.

Splitting UTXOs

Splitting spendable funds into multiple smaller UTXOs enables automation scripts and bots to eventually handle concurrent data request transactions signed from one specific address.

const { Witnet } = require("@witnet/sdk")

const wallet = await Witnet.Wallet.fromEnv({
    strategy: Witnet.UtxoSelectionStrategy.BigFirst
})
const vtt = await Witnet.ValueTransfers.from(wallet)
let splits = 50
let coins = Witnet.Coins.fromWits(10000.0 / splits) // 200.0 $WIT per split
const receipt = await vtt.sendTransaction({
    recipients: Array(splits).fill([ "wit1...", coins ]) 
})

Due to the VTT weight limitation, the maximum number of output UTXOs in a VTT is restricted to 50.

Last updated

Was this helpful?