Transactions by API

While simple queries using the Radix Node JSON-RPC API are straightforward, as shown in An Introduction to the Radix API, creating and submitting a transaction is a more complex multi-step process. This document provides an example of the steps of this process for a transfer of tokens. Other transactions may be created and submitted in a similar manner.

Usage of the API’s methods to create and submit a transactions requires the following steps:

  1. Call radix.buildTransaction with the desired input parameters to build the transaction, returning a transaction blob and a hash

  2. Locally sign the hash

  3. Call radix.finalizeTransaction with the signature, public key, and blob to finalize the transaction – making it ready to go on the node but awaiting your signal

  4. Call radix.submitTransaction to tell the node to submit the transaction to the network

Step 1: Build the Transaction

The RPC API allows you to ask an archive node to build a transaction by providing some simple parameters. To do a token transfer transaction, you will use a transaction type of TokenTransfer for which you will need the following pieces of information:

  • The address the transfer is from (ours)

  • The address the transfer is to (our recipient)

  • The amount of tokens to send

  • The tokenIdentifier for the type of token we wish to send

Keep in mind that amount is expressed in the minimum subunits of the token. Each “whole” XRD token is divided into 1E18 subunits, so to send 3 XRD tokens, the amount would be calculated by 3 x 1E18.

The tokenIdentifier is an RRI (Radix Resource Identifier); each token on Radix is assigned one, including XRD whose tokenIdentifier is xrd_rb1qya85pwq.

With this information, you can construct a call to the RPC method radix.buildTransaction with your inputs sent as an object inside an array inside “params”. (Yes, this is a double array.)

A well-formed request from the command line might look like this:

curl -d '{
	"jsonrpc": "2.0",
	"id": 1,
	"method": "radix.buildTransaction",
	"params": [
		[{
			"type": "TokenTransfer",
			"from": "brx1qsp7gmwkw8n0pxly7vg378jj6m766jx8v9t38keug9ps0djxpw0vh6g35esw4",
			"to": "brx1qsp80ekxpdan9suf6jvwackthmwws5rvpq4fvadq3crnuy5uedf6uac6qene4",
			"amount": "3000000000000000000",
			"tokenIdentifier": "xrd_rb1qya85pwq"
		}]
	]
}' -H "Content-Type: application/json" -X POST "https://betanet.radixdlt.com/rpc" | python -m json.tool

From this call, you should get back a response like this:

{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "fee": "100000000000000000",
        "transaction": {
            "blob": "010301040277e6c60b7b32c389d498eee2cbbedce8506c082a9675a08e073e129ccb53ae7700000000000000000000000000000000000000000000000029a2241af62c0000041737b8b7b59f001da0ba0a769eafff6d336f12dc230cf572f23e35b34aeb767a000000000103010403e46dd671e6f09be4f3111f1e52d6fdad48c7615713db3c414307b6460b9ecbe90000000000000000000000000000000000000000000000006124fee993bc00000005000000020103010403e46dd671e6f09be4f3111f1e52d6fdad48c7615713db3c414307b6460b9ecbe90000000000000000000000000000000000000000000000005fc1b9713632000000",
            "hashOfBlobToSign": "387bf61cccc3a9cba19cb64c179864c130fa8414ea563736e25b07603a77c59c"
        }
    }
}

You will need the returned values of blob and hashOfBlobToSign in the following steps.

Step 2: Sign the Transaction Locally

Next, you need to sign the hashOfBlobToSign received in Step 1 using the private key of your account. The details of doing so are outside the scope of this doc, but Radix follows a similar signature method as that of Bitcoin, using ECDSA signatures using EC curve “secp256k1”.

The result should be a DER format signature that you will use in the following step.

Step 3: Finalize the Transaction

Now you call the RPC method radix.finalizeTransaction and pass in [{ blob: string}, signatureDER, publicKey] as the "params" where:

  • blob is the contents you received previously as a response from radix.buildTransaction.

  • publicKey is the 33 bytes compressed format (66 hexadecimal characters) of your public key corresponding to the privateKey that you used to sign in the previous step.

A call from the command line for this might look like:

curl -d '{
	"jsonrpc": "2.0",
	"id": 1,
	"method": "radix.finalizeTransaction",
	"params": [
        {
            "blob": "0103010402fde6498387bc1286497815333e1645e729777a5d59e4f283f8f0294c277d641d0000000000000000000000000000000000000000000000000000000000000001045b2cc1b402f7fddce48930513f63309a0784fb8132a0a8a00c0ae372bbd718c700000005010301040279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800000000000000000000000000000000000000000000000030927f74c9ddfff7000500000002010301040279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817980000000000000000000000000000000000000000000000002f2f39fc6c53fff700"
        },
        "3044022030e30d57ed3e192ccc49760b6ad31ab273d3fedf6a1b0e23d3852b0c17b0379d022007169b64bea69120e303daff67633849d5f8f0591cf5ef599c9f4382dd7dfb8f",
        "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
	]
}' -H "Content-Type: application/json" -X POST "https://betanet.radixdlt.com/rpc" | python -m json.tool

You should get a response with a txID (transaction id), being 32 bytes (64 hexadecimal characters).

For example: "3052cc8b8831b027fccaf0ce5eebcb16e6fa37e4ad8a6433f4c15ca7855beb0b"

The transaction has not yet been submitted to the network! It is now queued up and ready to go at the validator node. The txID will be used to initiate submitting the transaction, as well as to track its status.

Step 4: Submit the Transaction to the Network

Now call RPC method radix.submitTransaction with [{blob: string }, signatureDER, publicKey, txID] as params. These are the same params as the call in the previous step, but appended with the txID you received.

curl -d '{
	"jsonrpc": "2.0",
	"id": 1,
	"method": "radix.submitTransaction",
	"params": [
        {
            "blob": "0103010402fde6498387bc1286497815333e1645e729777a5d59e4f283f8f0294c277d641d0000000000000000000000000000000000000000000000000000000000000001045b2cc1b402f7fddce48930513f63309a0784fb8132a0a8a00c0ae372bbd718c700000005010301040279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800000000000000000000000000000000000000000000000030927f74c9ddfff7000500000002010301040279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817980000000000000000000000000000000000000000000000002f2f39fc6c53fff700"
        },
        "3044022030e30d57ed3e192ccc49760b6ad31ab273d3fedf6a1b0e23d3852b0c17b0379d022007169b64bea69120e303daff67633849d5f8f0591cf5ef599c9f4382dd7dfb8f",
        "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
        "3052cc8b8831b027fccaf0ce5eebcb16e6fa37e4ad8a6433f4c15ca7855beb0b"
	]
}' -H "Content-Type: application/json" -X POST "https://betanet.radixdlt.com/rpc" | python -m json.tool

If the response to this call is OK, this indicates that the transaction was successful. The transaction has now been submitted to the “mempool” of the network where, if all is well, it should be swiftly processed and confirmed.

To poll for the transaction’s status, you may call RPC method radix.statusOfTransaction with the transaction’s txID like this:

curl -d '{
	"jsonrpc": "2.0",
	"id": 1,
	"method": "radix.statusOfTransaction",
	"params": ["3052cc8b8831b027fccaf0ce5eebcb16e6fa37e4ad8a6433f4c15ca7855beb0b"]
}' -H "Content-Type: application/json" -X POST "https://betanet.radixdlt.com/rpc" | python -m json.tool

The call can return one of these values:

PENDING

The transaction is still being processed and should not be considered complete.

CONFIRMED

The transaction has been accepted as valid and has been committed to the ledger.

FAILED

There was a problem, or a conflict, with the transaction causing it to be rejected.