Your first transaction
In this section we will walk through a complete payment without ever touching the network. We need a Private Key, an Output that pays to that key, a Transaction that spends the Output, and a check that the spend is valid. The Developer Guide’s walkthrough explains what happens inside a Transaction. Here we will be focusing on the code.
-
A Private Key and its Address. We load a fixed testnet key from its WIF string, so that every run gives the same result, and derive its Address.
final privateKey = SVPrivateKey.fromWIF('cVVvUsNHhbrgd7aW3gnuGo2qJM45LhHhTCVXrDSJDDcNGE6qmyCs');final myAddress = privateKey.toAddress(networkType: NetworkType.TEST);// myAddress: mu4DpTaD75nheE4z5CQazqm1ivej1vzL4L -
Something to spend. In a real wallet the coins arrive in someone else’s Transaction, and you would fetch that Transaction (or only its Output) from a node or an API. For a test, we can build that Transaction ourselves. The following helper makes a Transaction with one Output that pays
satoshisto a given Locking Script. Its one Input imitates a coinbase, so it spends nothing./// Builds a Transaction that pays [satoshis] to [lockingScript], so that the/// examples have an Output to spend without touching the network./// Its single Input imitates a coinbase Input (there is no previous Output).Transaction fundingTransaction(SVScript lockingScript, BigInt satoshis) {final coinbaseInput = TransactionInput('00' * 32, // previous transaction id: all zeros0xFFFFFFFF, // previous output index: noneTransactionInput.MAX_SEQ_NUMBER,scriptBuilder: DefaultUnlockBuilder.fromScript(ScriptBuilder().number(0).number(0).build()),);return Transaction()..addInput(coinbaseInput)..addOutput(TransactionOutput(satoshis, lockingScript));}Let’s lock 100,000 satoshis to our Address with a P2PKH Locking Script:
final lockingScript = P2PKHLockBuilder.fromAddress(myAddress).getScriptPubkey();final fundingTx = fundingTransaction(lockingScript, BigInt.from(100000)); -
The spend. A
TransactionBuilderspends Output 0 of the funding Transaction, pays 60,000 satoshis to a recipient, and returns the rest, less the fee, to our own Address. The signer holds the Private Key and the Sighash type. The unlocker builds the P2PKH Unlocking Script (Signature and Public Key) once the signer has signed.final recipient = Address('n3aZKucfWmXeXhX13MREQQnqNfbrWiYKtg');final signer = DefaultTransactionSigner(SighashType.SIGHASH_ALL.value | SighashType.SIGHASH_FORKID.value,privateKey,);final unlocker = P2PKHUnlockBuilder(privateKey.publicKey);final spendingTx = TransactionBuilder().spendFromTxnWithSigner(signer, fundingTx, 0, TransactionInput.MAX_SEQ_NUMBER, unlocker).spendToPKH(recipient, BigInt.from(60000)).sendChangeToPKH(myAddress).withFeePerKb(100).build(true);Calling
build(true)runs the builder’s sanity checks (amounts, dust, fees), and then signs every Input that has a signer. -
Checking it. The Interpreter runs the Unlocking Script followed by the Locking Script, exactly as a node would. It returns normally if the spend is valid, and throws a
ScriptExceptionif it is not.final interpreter = Interpreter();interpreter.correctlySpends(spendingTx.inputs[0].script!, // the Unlocking Script the signer producedfundingTx.outputs[0].script, // the Locking Script we are spendingspendingTx,0, // input index{VerifyFlag.SIGHASH_FORKID, VerifyFlag.UTXO_AFTER_GENESIS},Coin.ofSat(fundingTx.outputs[0].satoshis),); -
Serialising it. The raw hex is what we hand to a node or a transaction-processing API for broadcasting.
final rawHex = spendingTx.serialize(); // hand this to a node or a transaction-processing APIfinal txId = spendingTx.id;
The result has two Outputs. Do note that the builder puts the Change Output first, so outputs[0] holds the
39,994 satoshis of change and outputs[1] is the payment. Signatures are deterministic (RFC 6979), so this
example always produces the Transaction ID 8c9dd1cb…c979c9de13.
Broadcasting is the one step we cannot do offline. We send the signed Transaction to a broadcaster such as Arcade, or hand it to the payee, who broadcasts it. See Broadcasting and merkle proofs and Paying peer to peer. To spend real coins, replace the local funding Transaction with the Transaction or Output that paid your Address, as shown in The transaction builder.
- The transaction builder: the other ways of adding Inputs, and signing later.
- Fees and change: how the fee is worked out, and how to control it.
- Verifying a spend: handling Interpreter failures.

