Package-level declarations
Introduction
This library is comprehensive and therefore complex. Learning it is best accomplished via example code, with this documentation used as a reference. The library contains Wallet, Blockchain, Network and Scripting sections. All are needed to implement a fully-functional Nexa wallet, but portions can be used separately if full functionality is not needed.
Basic Objects
Multiple blockchains are supported via the ChainSelector object. Currently this includes Nexa and Bitcoin Cash, and all of the secondary (i.e. regtest and testnet) networks for these two blockchains.
This is accomplished using a class hierarchy, with interfaces designated by iXXXX (for example iBlockHeader, iBlock, iTransaction, iTxInput, iTxOutput, iTxOutpoint). These interfaces are implemented by a class that implements common functionality "CommonBlockHeader", and this class is the parent of blockchain-specific derived classes (NexaBlockHeader, BchBlockHeader).
Rather than create instances of blockchain-specific classes, it is best to use the "xxxFor" and "xxxFrom" APIs (blockFor, blockFromHex, blockHeaderFor, txFor, txFromHex, txInputFor, txOutputFor).
These "factory" APIs create the correct derived class, returning the interface type. Using them, it is surprising how much common code can be written that works across both BCH and NEXA, and potentially other UTXO-based chains.
Blockchains and Wallets
APIs exist to create wallets, launch blockchains, and attach the two. Right now, a wallet can only attach to a single blockchain. See newWallet, openWallet, and deleteWallet.
Blockchain
The Blockchain class represents a blockchain and synchronizes with the public chain. It stores block headers to a database and has APIs to query the chain.
Blockchain objects (Blocks and Transactions)
Although one may create Nexa or Bch objects directly, it is recommended that construction of blockchain objects occur via global helper functions:
These functions will create the correct blockchain-specific derived class, returning the parent iXXXX object. By doing this whenever possible, you maximize the likelihood that your source code will apply to multiple blockchains. To use blockchain-specific functionality, you may downcast "(header as NexaBlockHeader)" when needed.
Network Access
You may access either P2P or Electrum nodes in the network via the RequestMgr class. This class automatically manages connection for you. Going lower, you may directly connect to a specific node via the P2pClient or ElectrumClient classes.
Scripting
Full scripting functionality is available via the OP class, which captures all opcodes, and via the SatoshiScript and ScriptTemplate classes.
The SatoshiScript class is the generalized script language. ScriptTemplate creates the Nexa-specific script template transaction output. Note that a partner library Nexa Script Machine can be used to execute and debug these scripts.
Wallet
At the top level, the Bip44Wallet exists to create an manage a bip-44 compliant (meaning based on a 12-word recovery key) wallet. If set up, this object automatically uses the Blockchain Network and Scripting APIs to automatically sync with the blockchain and parse and create transactions. However, it is also possible to use this object in an offline mode, simply by not "hooking" it to a network object. After creating this object, use the Wallet interface for general purpose functionality, to allow your code to work with any wallet type.
Example
import org.nexa.libnexakotlin.*
class Test
{
fun docObjectExample()
{
// This is the Nexa genesis block
val hdr = blockFromHex(ChainSelector.NEXA, "00000000000000000000000000000000000000000000000000000000000000000000011e0000000000000000000000000000000000000000000000000000000000000000cdafb522e41f4b94618c8ee546f0fab8aaae7057f80e4730ea32df145dec73910000000000000000000000000000000000000000000000000000000000000000c0b2b16200ffffff00000000000000000000000000000000000000000000000000000000007201000000000000010000000403001700010000020000000000000000000100000000000000000000a06a00023b1c4c99526575746572733a204a6170616e20504d204b697368696461206261636b7320424f4a20756c7472612d6561737920706f6c696379207768696c652079656e20776f7272696573206d6f756e74204254433a3734313731313a3030303030303030303030303030303030303037356634626330386531643738613361623361663832373464313333333463306163326465323533303937363800000000")
println("Height ${hdr.height} Size ${hdr.size} Chain Work ${hdr.chainWork}")
val tx = hdr.txes[0]
println("Tx 0 inputs: ${tx.inputs.size}")
println("Tx 0 outputs: ${tx.outputs.size}")
// I'm cheating here a little because I know this is the genesis block so I know that the last output
// of the last transaction is text within an OP_RETURN script.
val output0Asm = tx.outputs.last().script.toAsm(" ")
println("tx 0 output 0: $output0Asm")
val stmts = tx.outputs.last().script.parsed()
println("\nNexa genesis block says:" + OP.parse(stmts.last()).data!!.decodeUtf8())
// Create a regtest address object
val addr = PayAddress("nexareg:nqtsq5g53q3sqyhhp45a86792a7wkkm3gyw9gylhp7kr703l")
}
fun docWalletExample()
{
// This needs to be run before APIs are called, but you should do a single time upon app startup
initializeLibNexa()
// This call automatically creates the underlying blockchain object if it hasn't already been created.
val wal = openOrNewWallet("exampleWallet", ChainSelector.NEXAREGTEST)
while(!wal.synced())
{
// Note that the blockchain may also be syncing headers simultaneously with the wallet syncing, so both
// numbers may increase.
//
// Sync also depends on time -- if the synced block isn't recent enough the wallet does not believe its
// synced. So if you are using REGTEST make sure you have recently created a new block before running this test.
println("syncing ${wal.chainstate?.syncedHeight} of ${wal.blockchain.curHeight}..." )
millisleep(2000U)
}
val newAddress = wal.getNewAddress()
println("wallet balance is: ${wal.balance}. An address for this wallet is ${newAddress}.")
try
{
// send some coins to myself. Amounts in this library are ALWAYS in the finest unit.
wal.send(10000, wal.getNewAddress())
}
catch (e: WalletNotEnoughBalanceException)
{
if (wal.balance <= 10000) println("You don't have enough coins to actually send.")
}
}
}
Types
Header of a block for bitcoin-family cryptocurrencies
A block that contains a subset of the total number of transactions, and includes a merkle proof that the provided transactions are part of the block
Bitcoin transaction
Spend a coin (aka UTXO, prevout) in a transaction
Output of a bitcoin transaction
Helper class that saves/loads data needed by the Bip44Wallet
Access and track a blockchain
An array of block hashes, starting at the current block, and ending at the genesis block. The creator can skip blocks, populating whatever hashes he feels is most likely to identify a specific chain, closest to the splitoff point. Typically, some kind of exponential backoff is used. For example: The next 10 hashes are the previous 10 blocks (gap 1). After these, the gap is multiplied by 2 for each hash, until the genesis block is added
Bloom filter update flags Must be consistent with same named fields in C++ code in bloom.h:bloomflags
This class is needed because ByteArray's equality is by object, not contents. So ByteArrays probably do not work as you expect as the key in any map-like data structures, for example.
Call the passed function after this function has been called 'count times
Organize multiple callbacks for a function that accepts a single parameter
Organize multiple callbacks for a function that accepts two parameters. This is a convenience class for this common case. For larger numbers of parameters you can always place them in an object or a list and use the single-parameter callbacker
A CAPD message (see https://spec.nexa.org/network/capd/)
Identify the cryptocurrency/blockchain.
The CnxnMgr handles discovery, connection, and maintenance of all connections into the Peer-2-Peer network. This allows higher layers to treat peers as a grab bag of nodes, ignoring issues like reconnecting, periodically cycling connections, and searching for new nodes.
This class provides implementations to for functions that are common to many blockchains and wallet types
This class accepts insertions of integers in a random order and tracks the maximum sequence of contiguous integers that has been provided. You must not provide the same integer multiple times. An example use is async parallel requests for an indexed resource, and then filtering the responses for N in a row that have some property
Full node sends this back in response to an info request about UTXOs
Open a JSON-RPC over TCP connection to an Electrum X server
Electrum server never replied
The reply doesn't adhere to the protocol in some manner
The request was not accepted by the server
A passed entity was not found (transaction, block, scripthash, etc).
Electrum server never replied
Electrum server never replied
This class behaves like a function and its sole purpose is to wrap a bytearray into another class so that when we serialize it we know not to include the length
Extended inventory object -- uses a variable sized byte array is the identifier rather than the constant 32 bytes of Inv
Helper class that glues a wallet to a blockchain
Helper class to pass around ip and port pairs If resolutionNeeded is true, the system will use a nslookup to resolve this to ip addresses, and return a random one (if the domain is a seeder that returns multiple choices) when resolve is called
defines what UTXOs are being spent and proves ability to spend
Reference to a UTXO
defines new UTXOs
A connection manager that handles connections to multiple nodes
Application should set this to put network operations into their own context (for performance)
Header of a block for Nexa
A block that contains a subset of the total number of transactions, and includes a merkle proof that the provided transactions are part of the block
Construct a Nexa-style sighash type byte array
blockchain transaction
Spend a coin (aka UTXO, prevout) in a transaction
Output of a bitcoin transaction
Represents a "standard" P2PKH payment destination
Represents a "standard" P2PKT payment destination
Represents an arbitrary P2SH destination
Represents a P2PK (pay to public key) destination wrapped in a P2SH script
A destination for payments. This includes all the information needed to send and spend from this destination. It is often assumed that Bitcoin addresses are payment destinations, but this is not true. You really need an output script, and also (if P2SH) a redeem script. The reason why P2PKH addresses "work" as payment destinations is because they imply a specific script. But "baking in" this assumption will make the wallet a lot less flexible.
This is a clean-room implementation of PBKDF2 using RFC 2898 as a reference.
keep track of when something can happen, if there's a minimum time interval where it should happen
This class tracks possible blockchain nodes -- we have learned about this node from some source but the data may not be accurate
Identify what type of public key is needed
A script the can be run in Nexa or BCH transaction validation virtual machine
This enum captures both secret types and versions. When you create a new version of a certain type of secret, create a new enum, and have your class handle multiple enum values converting the old to the new format.
A secured secret holds some encrypted data, and a public value that is used to initialize the encryption. It also must be provided with a function to be used to decrypt the secret. That function may throw a WalletLockedException if it cannot decrypt the secret at this time.
A secured secret holds some encrypted data, and a public value that is used to initialize the encryption. It also must be provided with a function to be used to decrypt the secret. That function may throw a WalletLockedException if it cannot decrypt the secret at this time.
This represents something that can be spent. It may not be spendable by ME, in which case the secret and perhaps other items will be unknown
Extended inventory object -- uses a variable sized byte array is the identifier rather than the constant 32 bytes of Inv
Flags controlling the behavior of Wallet.txCompleter
This class behaves like a function and its sole purpose is to wrap a bytearray into another class so that when we serialize it we know to include the length
This class defines a wallet interface. A wallet is a set of payment destinations that are being tracked on a particular blockchain.
Properties
The number of decimal places needed to express 1 satoshi in the "normal" currency units
How to display BCH crypto unit
Convert a ChainSelector to its currency code of its common unit
Convert a ChainSelector to its currency code at 100M/1000 units
Convert a ChainSelector to its uri and address prefix
The decimal number 0, with the correct "currency" rounding mode CurrencyMath. Same as CURRENCY_ZERO
The decimal number 1, with the correct "currency" rounding mode CurrencyMath.
The decimal number -1, with the correct "currency" rounding mode CurrencyMath.
The decimal number 0, with the correct "currency" rounding mode CurrencyMath. Same as CURRENCY_0
Convert a uri or address prefix to a ChainSelector -- throws exception if not found
Tell the system details about how we want bigdecimal math handled
How many decimal places we need to do math without creating cumulative rounding errors
How convert BigDecimals to strings in preparation for serialization/deserialization
Adjust how many blocks are held in RAM
Adjust how many headers are held in RAM
Adjust how many merkle blocks are held in RAM
Adjust how many tx are held in RAM
How all fiat currencies are displayed (2 decimal places)
callback to notify app of any exception that happened within the coroutine launch. Return False to raise the exception, causing program abort. If null, exception is logged and ignored
Application should set this to put non-network libnexakotlin operations into their own context (for performance). network operations have their own context: @ref NetExecContext
Provide the line separator for this platform
Network-defined bloom filter maximum size TODO: associate this value with the blockchain
How the mBCH crypto unit is displayed (5 optional decimal places)
If we fall below this many unused addresses, make more. This happens whenever the wallet "sees" an address being used by a transaction. In the situation where a foreign same-seed wallet is spending, we might miss some transactions if more than this number of addresses are used in a block. The situation occurs because tx are not committed in creation order in blocks, so if we are tracking N unused addresses, the N+1th unused address could appear in the block first, but we haven't yet started tracking it. Ofc, no money is lost, the SPV wallet just doesn't 'see' the deposit/UTXO. Set this number high enough that such a situation would be extremely unlikely. Also to avoid race conditions when installing the bloom filter and using an address, it makes sense to generate the new ones well before they are used.
The number of decimal places needed to express 1 Satoshi (or equivalent) in the units used in the GUI
add or remove elements in this list to control the servers that we use to get electrum data by default
How the NEXA crypto unit is displayed (2 decimal places) 21 trillion Nexa possible
How the NEX crypto is displayed in input fields (2 optional decimal places, no thousands separator)
Tell the system details about how we want bigdecimal math handled
add or remove elements in this list to control the servers that we use to get electrum data by default
Satoshis (finest unit) per microBCH unit
Redefine this to override how source loc files are shown
Return true if this platform supports ktor TLS TCP sockets
TDPP protocol operation flags: You are expected to fund missing tokens
TDPP protocol operation flags: Do not fund this transaction with native coins
TDPP protocol operation flags: Do not independently post this transaction to the blockchain (it is not valid)
TDPP protocol operation flags: Do not change the order of inputs or outputs, the counterparty will reject adjustments
TDPP protocol operation flags: You should partially sign this transaction so that additional inputs/outputs can be added
The number of decimal places needed to express 1 Satoshi (or equivalent) in the units used in the GUI
How the uBCH crypto unit is displayed (2 optional decimal places)
tell the system details about how we want bigdecimal math handled
Convert a uri or address prefix to a ChainSelector -- throws exception if not found
Functions
In platforms that use an application context object (Android), return that object. This is meant to be called only in platform specific upper layers, so each platform specific code should "know" what to cast the returned Any into.
convert this byte to an int, treating the byte as unsigned I am wrapping toUByte() because something seems broken there -- toUInt().toInt() sign extends, toUByte does not. This seems inconsistent confusing.
Close a connection to trigger an early wake
Given recovery phrase words converted to a byte array (see @Bip39WordsToBytes) calculate the bip39 checksum
Return the Bip44 address number based on this blockchain
Synonym of connectBlockchain
Construct the proper derived-class block object for the passed blockchain, and initialize it from the passed serialized data
Construct the proper derived-class block object for the passed blockchain, based on the passed serialized hex string
Construct the proper derived-class block header object for the passed blockchain, and initialize it from the passed serialized data
Construct the proper derived-class block header object for the passed blockchain, based on the passed serialized hex string
This function will split the wallet's native coin so that there are numUtxos of amt satoshis. If the wallet already has some UTXOs that fit the requirements, they count. So its possible that no transactions will be created
This function will split the wallet's Tokens so that there are numUtxos of amt satoshis. If the wallet already has some UTXOs that fit the requirements, they count. So its possible that no transactions will be created
Connect to, and return an existing blockchain. Create the blockchain object and start it processing, if it does not already exist.
Convert a BigDecimal of unknown math mode (rounding & precision) into one that is appropriate for currency mathematics (with lots of decimal places)
Create a BigDecimal that is appropriate for currency mathematics (with lots of decimal places)
Convert a TxOutput type raw byte into a type enum
Convert transaction output type into a script type (for correct annotation of the script contained in the output)
Convert a script type into the type field needed for the script to be used in a transaction output
return the directory where databases are placed on this platform, "" if its in the current directory (not a specific location), or null if you do not know
This function helps us identify what version a database is to run the appropriate migration
Decode a token description document JSON file into a TokenDesc structure, the hash of the proper part of the TDD, and its signature bytes. check the signature and fill TokenDesc pubkey with the resulting pubkey if an address is provided, and the signature matches that address.
Convert a byte array that contains a utf8 string into a String
Path should not contain extension (will be added) & directories may be ignored if the platform places its databases in a standard location.
Delete a wallet on disk
Delete a wallet on disk
Deserialize any object that is nullable, but prepending a byte indicating whether this object is null or not. This API should only be used for DISK serialization because this nullable technique is not part of the network protocol. However, in one case we store to disk the network serialization of an object (if it exists).
Returns the minimum amount of native coins (in the finest unit) that must be in every UTXO.
Convert a string into a utf-8 encoded byte array.
Convert a string into a utf-8 encoded byte array.
Convert a string into a utf-8 encoded byte array.
Returns milliseconds since the epoch
Returns milliseconds since the epoch
Returns seconds since the epoch
Returns seconds since the epoch
Asynchronously fast forward a Bip44Wallet by searching address derivation paths using Rostrum.
Get a BigDecimal from a string
Get a BigDecimal from a string
Given some entropy, generate a Bip 39 secret word list, with checksum.
Return a ByteArray with a lot of cryptgraphically strong random bits
Calculate the ancestor height of the block at the passed height. This follows the Nexa ancestor algorithm, returning the height of the block indicated by the ancestorHash in the Nexa block header.
Return the directory that this application may use for its files
Return the directory that this application may use for its files
Return the directory that this application may use for its files
Access system properties or environment variables (in that order of preference)
Returns a predicate function that accepts a Spendable. This function returns the token amount if the BCHspendable is in the passed group and has properties based on passed flags, and is not already reserved.
Return false if this node has no internet connection, or true if it does or null if you can't tell
Return false if this node has no internet connection, or true if it does or null if you can't tell
Return false if this node has no internet connection, or true if it does or null if you can't tell
Return false if this node has no internet connection, or true if it does or null if you can't tell
Initialize the lowest level nexa library. This function loads the .so file and calls a "native" init function.
Turn the lowest '1' bit in the binary representation of a number into a '0'.
given a byte array, convert it into some string form of IP address Should support ipv4 and ipv6 at a minimum
given a byte array, convert it into some string form of IP address Should support ipv4 and ipv6 at a minimum
Enqueue a job to run, but do not enqueue the same job (by name) if its already in the queue. This is useful if your job handles the "latest" state anyway. For example let's say you are updating a counter and want to do something (maybe save to disk) whenever the counter 100 (flush to disk every 100 updates). Using this function, every time I increment the counter, I can check and then launch the save in a separate thread. If you just used laterJob() you might enqueue 20 saves before the first one ran and set the counter back to 0. (yes this example is contrived and there's an easy workaround) counter += 1 if (counter 100) laterOneJob("flushCheck") { save(); counter = 0 }
Launch a coroutine within the libnexakotlin handler threads, or a scope you provide. This is a small helper function to launch a couroutine outside of the kotlin default handler (which tends to get busy), with a default exception handler that logs the exception and continues.
Construct the proper derived-class merkle block object for the passed blockchain, and initialize it from the passed serialized data
Get a new scope to handle all coroutines related to a particular spending proposal
Create a new wallet. A HD BIP44 compliant recovery key will be automatically generated.
Create a BigDecimal that is appropriate for Nexa currency mathematics (with 2 decimal places)
Create a wallet that is not actively connected to a blockchain. This is used in applications that trust a blockchain data provider, or just for operations like signing messages. You still need to tell me what blockchain this wallet uses so it can create addresses in the proper space.
Create a wallet that is not actively connected to a blockchain. This is used in applications that trust a blockchain data provider, or just for operations like signing messages. You still need to tell me what blockchain this wallet uses so it can create addresses in the proper space.
Open a plain key/value pair database for general storage
Open this wallet if it exists, or create a new HD BIP44 wallet
Open an existing HD BIP44 wallet.
If you are going to create a wallet DB, you must specify the chain. Otherwise its optional (will be loaded from the db)
Construct the proper derived-class outpoint object for the passed blockchain, based on the passed serialized bytes
Construct the proper derived-class outpoint object for the passed blockchain, based on the transaction identifier, and output index. You must provide the proper identifier for this blockchain (e.g. use txid for BCH and txidem for Nexa).
This function create a pay-to-pubkey-template address from a pubkey. This is very uncommon since it cannot be used to sign anything and typically if the address isn't yours, you would have been given the address, not the pubkey. It is used when recovering pubkeys from signed messages or from inside scripts.
Provide the best ktor http client (engine) offered by this platform
Sanity check a date: returns false if before the genesis block (rounded) or after 24 hours from now.
Create a new HD BIP44 wallet from an recovery phrase.
convert a domain name into an address
convert a domain name into an address
Convert Satoshi a Nexa-unit display string
Parse out the data that would be pushed to the script stack from a byte array that corresponds to a script instruction.
Parse out a script num from a byte array that corresponds to a script instruction pushing it to the script's stack if scriptBytes is an invalid push, null is returned
Sets the log location and file name (if relevant for this platform). This function should be called early in the initialization; however since GetLog() is often called to init a global variable, this set function MUST apply to all iLogging objects that have already been created. You may pass "" to stop logging on platforms that create a separate log file
Show a particular property of an object (internal CLI API)
Show the an object (internal CLI API)
Show the properties of an object (internal CLI API)
Shutdown the libnexa processing threads and any other tasks needed to stop. Thread stopping occurs via join() so if you have launched an infinite loop as a libnexa job @see laterJob @see laterOneJob, this function will not return. Shutdown is permanent. After calling this function, do not call initializeLibNexa again (and expect that it will work).
signs a transaction in place, with all inputs that have a BCHspendable with secrets (skips those that do not so others can sign) by default the sighashtype is ALL/ALL
split a (IP or FQDN):port formatted string (e.g 192.168.100.10:54 or www.example.com:54) into a string IP address (or FQDN) and an integer port
Get this string as a BigDecimal currency value (using your default locale's number representation)
tokenizeScriptBin is the opposite of flatten in the sense that each element in data will be 1 instruction
convert this byte to an Int, treating the byte as unsigned
convert this byte to a Long, treating the byte as unsigned
convert this byte to an unsigned Int, treating the byte as unsigned
convert this byte to an unsigned Long, treating the byte as unsigned
Construct the proper derived-class transaction object for the passed blockchain
Construct the proper derived-class transaction object for the passed blockchain, based on the passed serialized bytes
Construct the proper derived-class transaction object for the passed blockchain, based on the passed serialized hex string
Construct the proper derived-class transaction input object for the passed blockchain. This object is created with default values that then need to be set to an actual input for use.
Construct the proper derived-class transaction input object for the passed blockchain, for the passed Spendable object. This does not solve the input (create a valid input script), since that would require the complete transaction.
Construct the proper derived-class transaction output object for the passed blockchain This object is created with default values that then need to be set to an actual output for use.
Construct the proper derived-class transaction output object to send tokens (and some native). Only works for Nexa family.
Construct the proper derived-class transaction output object for the passed blockchain, and initialize it from the passed serialized data
Construct the proper derived-class transaction output object for the passed blockchain, and initialize it from the passed data
Create a BigDecimal that is appropriate for u-BCH (micro bitcoin cash) currency mathematics (with 2 decimal places)
How many blocks are found (on average) in a single week in this blockchain