Making Transactions by Gateway API
While simple queries using the Gateway API are straightforward, as shown in our Making API Calls examples, 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 can be created and submitted in a similar manner, such as our following example of Creating a Token. To see all of the various types of transactions that can be made, see the API Specification. |
The Gateway offers endpoints under /transaction/
which enables you to make a transaction for any Radix account that you (or your client software) is able to cryptographically sign.
Usage of the transaction
endpoint requires the following steps:
-
Build the transaction that you want by calling the
/transaction/build
api path with the desired input parameters. This returns aunsigned_transaction
blob. -
Sign the transaction locally using the private key of the account.
-
Finalize and submit the transaction by calling the
/transaction/finalize
and optionallytransaction/submit
if required, with the signature, public key, and blob bytes.
1. Build the Transaction
The /transaction
endpoint allows you to ask an gateway to build a transaction for you by providing some simple parameters. To do a token transfer transaction, you will use a transaction action type of TransferTokens
for which you will need the following pieces of information:
-
The address the transfer is from_account (ours)
-
The address the transfer is to_account (our recipient)
-
The amount of tokens to send
-
The rri 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 1x10^18 subunits (called "attos"), so to send 3.5 XRD tokens, the amount would be calculated by 3.5 x 1E18 = 3500000000000000000
.
The rri
(Radix Resource Identifier) is a unique string for each token created on Radix, including XRD (as we saw in Making API Calls).
With this information, you can construct a call to the RPC method construction.build_transaction
with your inputs sent as an actions
array inside the params
object.
A well-formed build request from the command line might look like this:
curl -d '{
"network_identifier": {
"network": "mainnet"
},
"actions": [
{
"type": "TransferTokens",
"from_account": {
"address": "rdx1qspl7mgjqwgwqyjvy2tj8swe8a4lr6mxqdhwmn60cujl6a85mqh69eg37p9ph"
},
"to_account": {
"address": "rdx1qthu8yn06k75dnwpkysyl8smtwn0v4xy29auzjlcrw7vgduxvnwnst6derj"
},
"amount": {
"token_identifier": {
"rri": "xrd_rr1qy5wfsfh"
},
"value": "1000000000000000000"
}
}
],
"fee_payer": {
"address": "rdx1qspl7mgjqwgwqyjvy2tj8swe8a4lr6mxqdhwmn60cujl6a85mqh69eg37p9ph"
},
"disable_token_mint_and_burn": true
}' -H 'X-Radixdlt-Target-Gw-Api: 1.0' -H "Content-Type: application/json" -X POST "https://mainnet.radixdlt.com/transaction/build" | python -m json.tool
From this call, you should get back a response like this:
{
"transaction_build": {
"fee": {
"value": "72600000000000000",
"token_identifier": {
"rri": "xrd_rr1qy5wfsfh"
}
},
"unsigned_transaction": "0d0001073b07270cb1c58d2ef5cad10a24d14625a7727510bbce2acc710e885cf99eb00000002010021000000000000000000000000000000000000000000000000000101ed50bab1800002004506000403dc62fa04804f75d009a2fac32c8ceb9dc5eaccd54934fe20ef5b86be40c7a2ab010000000000000000000000000000000000000000075df8c7a1dedbb7599c80000008000002004506000403dc62fa04804f75d009a2fac32c8ceb9dc5eaccd54934fe20ef5b86be40c7a2ab010000000000000000000000000000000000000000075df8c793fe2503b2388000020045060004038639dc49e14a94448045a3c595996282d8419eb9ae949dfb84b7bc48ba3d4fee010000000000000000000000000000000000000000000000000de0b6b3a764000000",
"payload_to_sign": "5abf81346f75464c3ad8c0242fcedb8e7c8c5d1479fa6392591e492bdfd73b6e"
}
}
You will need the returned values of unsigned_transaction
in the following steps.
2. Sign the Transaction Locally
Next, you need to sign the payload_to_sign
using the private key of your account (ie. the "from" 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 encoded signature in hex that you will use in the following step.
3. Finalize and Submit the Transaction
Finally, you call transaction endpoint /transaction/finalize
in order to submit your signed output and submit the transaction to the network, using the following parameters:
-
unsigned_transaction is the contents you received previously as a response from
/construction/build
. -
publicKey is the 66 hexadecimal characters of your public key that corresponds to the
privateKey
you used to sign in Section 2, “Sign the Transaction Locally”, also known as a "compressed public key." -
bytes is the signed output you generated in the previous step.
A call from the command line for this might look like:
curl -d '{
"network_identifier": {
"network": "mainnet"
},
"unsigned_transaction": "0d0001073b07270cb1c58d2ef5cad10a24d14625a7727510bbce2acc710e885cf99eb00000002010021000000000000000000000000000000000000000000000000000101ed50bab1800002004506000403dc62fa04804f75d009a2fac32c8ceb9dc5eaccd54934fe20ef5b86be40c7a2ab010000000000000000000000000000000000000000075df8c7a1dedbb7599c80000008000002004506000403dc62fa04804f75d009a2fac32c8ceb9dc5eaccd54934fe20ef5b86be40c7a2ab010000000000000000000000000000000000000000075df8c793fe2503b2388000020045060004038639dc49e14a94448045a3c595996282d8419eb9ae949dfb84b7bc48ba3d4fee010000000000000000000000000000000000000000000000000de0b6b3a764000000",
"signature": {
"public_key": {
"hex": "03f89249c269bde09e72f351b0debb348ced0d3542d7dc26ff1bf39b7ed4bb25ca"
},
"bytes": "0d00010779c779406687996e102114ad1383167041502508bf88fe95918f2322f8ce0f0a00000002010021000000000000000000000000000000000000000000000000056d726770c110800002004506000403f89249c269bde09e72f351b0debb348ced0d3542d7dc26ff1bf39b7ed4bb25ca010000000000000000000000000000000000000000000000056a1c54ea050f800000010007023568346d337509003f54347c2a10a8f09efd8398ed4b259909a3f848cc9fa05ca20e225f8bfb1d2d1a0000000003d0f1475cabcb81651b60d980e7be247997878aba3a419d4a119b020060040003d0f1475cabcb81651b60d980e7be247997878aba3a419d4a119b0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000002005f06000403f89249c269bde09e72f351b0debb348ced0d3542d7dc26ff1bf39b7ed4bb25ca03d0f1475cabcb81651b60d980e7be247997878aba3a419d4a119b00000000000000000000000000000000000000000000152d02c7e14af680000002006d050003d0f1475cabcb81651b60d980e7be247997878aba3a419d4a119b00063568346d3375000a5465737420746f6b656e000a5465737420746f6b656e001668747470733a2f2f746573742d746f6b656e2e636f6d001668747470733a2f2f746573742d746f6b656e2e636f6d000b013819d07e36a62c4f97c5dda50a251c5964377267402c4b6490d61ef1e153ce134fd3db27e151727289a19b1c6dad6d678547225e36153ec67f699944f0c5578f"
},
"submit": true
}' -H 'X-Radixdlt-Target-Gw-Api: 1.0' -H "Content-Type: application/json" -X POST "https://mainnet.radixdlt.com/transaction/finalize" | python -m json.tool
Note that we used the submit
parameter to submit the transaction in the same step as finalizing it.
You should get a response with a txID (transaction id), being 32 bytes (64 hexadecimal characters).
{
"signed_transaction": "0d0001073b07270cb1c58d2ef5cad10a24d14625a7727510bbce2acc710e885cf99eb00000002010021000000000000000000000000000000000000000000000000000101ed50bab1800002004506000403dc62fa04804f75d009a2fac32c8ceb9dc5eaccd54934fe20ef5b86be40c7a2ab010000000000000000000000000000000000000000075df8c7a1dedbb7599c80000008000002004506000403dc62fa04804f75d009a2fac32c8ceb9dc5eaccd54934fe20ef5b86be40c7a2ab010000000000000000000000000000000000000000075df8c793fe2503b2388000020045060004038639dc49e14a94448045a3c595996282d8419eb9ae949dfb84b7bc48ba3d4fee010000000000000000000000000000000000000000000000000de0b6b3a764000000",
"transaction_identifier": {
"hash": "d275sdsf35b3cb37903982ccae91b20e2e05c592808a70c6b41eae0d81e39666c3"
}
}
At this point you’re done, and your transaction has been submitted to the network.
In the event that you chose not to use the submit
parameter and set it to false, you will receive the same return parameters, but you will have to take a final step of passing this updated blob (which now includes your signature) to the submit_transaction
method.
This approach requires an extra roundtrip, but can be used if you want to know the transaction ID before submitting it for processing.
4. (Optional) Submit a Finalized Transaction to the Network
If you elected not to use submit
when finalizing, you will now have to submit the fully prepared transaction to the network.
Call transaction endpoint /transaction/submit
with your updated signed_transaction
blob, and (optionally) the transaction ID.
IMPORTANT: The signed_transaction
returned from finalize_transaction
are different than the unsigned_transaction
returned from build_transaction
! The updated signed_transaction
includes your signature, so be sure to submit the new one!
curl -d '{
"network_identifier": {
"network": "mainnet"
},
"signed_transaction": "0d0001073b07270cb1c58d2ef5cad10a24d14625a7727510bbce2acc710e885cf99eb00000002010021000000000000000000000000000000000000000000000000000101ed50bab1800002004506000403dc62fa04804f75d009a2fac32c8ceb9dc5eaccd54934fe20ef5b86be40c7a2ab010000000000000000000000000000000000000000075df8c7a1dedbb7599c80000008000002004506000403dc62fa04804f75d009a2fac32c8ceb9dc5eaccd54934fe20ef5b86be40c7a2ab010000000000000000000000000000000000000000075df8c793fe2503b2388000020045060004038639dc49e14a94448045a3c595996282d8419eb9ae949dfb84b7bc48ba3d4fee010000000000000000000000000000000000000000000000000de0b6b3a764000000"
}' -H 'X-Radixdlt-Target-Gw-Api: 1.0' -H "Content-Type: application/json" -X POST "https://mainnet.radixdlt.com/transaction/submit" | python -m json.tool
If the response to this call is your same transaction ID, this indicates that the transaction was submitted successfully. 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 transactions.get_transaction_status
with the transaction’s txID
like this:
curl -d '{
"network_identifier": {
"network": "mainnet"
},
"transaction_identifier": {
"hash": "d275ff35b3cb37903982ccae91b20e2e05c592808a70c6b41eae0d81e39666c3"
}
}' -H 'X-Radixdlt-Target-Gw-Api: 1.0' -H "Content-Type: application/json" -X POST "https://mainnet.radixdlt.com/transaction/status" | python -m json.tool
The response:
{
"ledger_state": {
"version": 54973189,
"timestamp": "2022-02-10T19:55:59.454Z",
"epoch": 5435,
"round": 8357
},
"transaction": {
"transaction_status": {
"status": "CONFIRMED",
"confirmed_time": "2022-02-10T15:25:45.634Z",
"ledger_state_version": 54921133
},
"transaction_identifier": {
"hash": "d275ff35b3cb37903982ccae91b20e2e05c592808a70c6b41eae0d81e39666c3"
},
"actions": [
{
"from_account": {
"address": "rdx1qspl7mgjqwgwqyjvy2tj8swe8a4lr6mxqdhwmn60cujl6a85mqh69eg37p9ph"
},
"to_account": {
"address": "rdx1qthu8yn06k75dnwpkysyl8smtwn0v4xy29auzjlcrw7vgduxvnwnst6derj"
},
"amount": {
"value": "1000000000000000000",
"token_identifier": {
"rri": "xrd_tr1qyf0x76s"
}
},
"type": "TransferTokens"
}
],
"fee_paid": {
"value": "72600000000000000",
"token_identifier": {
"rri": "xrd_rr1qy5wfsfh"
}
},
"metadata": {
"hex": "0d00010771eeb1593283fb56c98e2af8231b28c39861e9586cf5ef42a8f669ca07b15ef100000000010021000000000000000000000000000000000000000000000000000101ed50bab1800002004506000403f89249c269bde09e72f351b0debb348ced0d3542d7dc26ff1bf39b7ed4bb25ca0100000000000000000000000000000000000000000000000377765afca29700000008000002004506000403f89249c269bde09e72f351b0debb348ced0d3542d7dc26ff1bf39b7ed4bb25ca010000000000000000000000000000000000000000000000036995a448fb3300000200450600040273cad5ab910b3a614b345d8aa7178a0e0da4765c4fc6976bc3bdba2109ac3c81010000000000000000000000000000000000000000000000000de0b6b3a7640000000b01d28ed9fa9498d9a2743d3d500a6a86c1983579606d3d53e96f9b9a62a8d055175ebdbb78101855328330f2c6345464056d0fba5dc9a743455eb6675857af84a4"
}
}
}
will return one of following values depending on the status of the transaction:
PENDING
|
The transaction is processing 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. |