ICP Rosetta construction API reference
This section will give you an overview of how the flow of operations in the construction API works. It will guide you through each of the necessary endpoints that you will have to call in order to post a valid transaction with your signature to the ICP ledger. As an example of such a transaction, this guide will use a simple transfer between accounts.
It is recommended to first read through the interactions of each endpoint to acquire an understanding of how the flow of operations works. Although the example of transferring tokens is only one use case of the construction API of Rosetta, it serves as a good example of what to expect from the interaction with the Construction-API. The other functionalities that are supported by ICP Rosetta through the construction API follow a similar flow of operations.
- Prerequisites
http://127.0.0.1:8081
Key generation
For the purpose of this guide, you need to have a private key available with which you can sign messages.
The Rosetta architecture is built so that no private keys are ever sent to Rosetta. All the signing and thus handling of private keys can be done offline.
Rosetta supports multiple types of keys. The two that are used most often are Edwards2559
and Secp256k1
. If you want to use Rosetta together with dfx
, you will be using ECDSA
keys with an Secp256k1
curve type. For a guide on how to create a new identity, you can look at the relevant dfx
section.
For this guide we will be using the identity.pem
that is created with dfx identity new
.
Construction API endpoints
See construction API overview for a high-level overview of the transaction flow. This documentation will provide code snippets for interacting with Rosetta through regular curl
commands as well as providing you with a Rosetta-client example implementation in Python. Feel free to use these code snippets as a starting point to write your own Rosetta client in your language of choice.
The endpoints that make up the flow of operations are the following:
- construction/combine: Combine signatures and an unsigned transaction into a signed transaction.
- construction/derive: Derive an
accountIdentifier
from your public key. - construction/metadata: Fetch transaction-specific metadata from the ICP ledger.
- construction/payloads: Fetch signable payloads for the requested set of operations.
- construction/preprocess: Fetch transaction-specific parameters to call the
construction/metadata
endpoint with. - construction/submit: Send signed transactions to the ICP Ledger canister.
Construction-combine
This section details how to call the construction/combine
endpoint of the Rosetta construction API.
The request and response types can be found in the official documentation.
Signing payloads
The payloads that one receives from the construction/payloads
endpoint contain a hex string that needs to be signed with the private key of the accountidentifier
that is associated with the hex string.
Here is an example of such a payload:
{"account_identifier":{"address":"8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"},"hex_bytes":"0a69632d72657175657374df3e33267733b2030e8a4fc1d7eb6e0884ab461806630921a9c0c9749abb99de","signature_type":"ecdsa"}
This means that we need to sign the hex bytes 0a69632d72657175657374df3e33267733b2030e8a4fc1d7eb6e0884ab461806630921a9c0c9749abb99de
with the private key associated with the accountidentifier
8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4
using an ecdsa
signature type. This would result in the signature in hex representation 3046022100ce0807d84c8321bf3525361ad25654be81076e75e8c004970789d385f195fc500221008eebd282efabb878ac54e77dc4230acf54d103ef05253db44cb9fba0fb382764
Fetching a signed transaction
The construction/combine
endpoint will create a signed transaction and return it. A call to the endpoint may look like the following:
curl --location '0.0.0.0:8081/construction/combine' --header 'Content-Type: application/json' --data '{
"network_identifier": {
"blockchain": "Internet Computer",
"network": "00000000000000020101"
},
"unsigned_transaction": "a2677570646174657381826b5452414e53414354494f4ea56b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758480a0b08baea959fe0a9e58dbd0112040a02080a1a0308904e2a220a207f622708b363917e3ba0ef8ac1cb0dfe241ef5ffca54f32c1480473ee3a12cad3a0a0899d9c88df3d893e0176673656e646572581d2e70031d8e7ff922b6ad9f2a9eb3c1e77ffa7b6c0d0120dd4ac7e4f7026e696e67726573735f6578706972790070696e67726573735f6578706972696573811b17c04eff12cf8023",
"signatures": [
{
"signing_payload": {
"account_identifier": {
"address": "8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"
},
"hex_bytes": "0a69632d726571756573748c85871f2b1d1edea73797b31cd63094fa82052fed84c06d45d6c719170d8f6f",
"signature_type": "ecdsa"
},
"signature_type": "ecdsa",
"public_key": {
"hex_bytes": "047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c757367",
"curve_type": "secp256k1"
},
"hex_bytes": "877f315ab0e84ac781395b4c1ce2978f77e316abe2f6eb058a22e80e14246d5c9e2e2d8ff863dca53be432aa65154a39d4b6b5304774e8ebcbe3117fd17e35dd"
},
{
"signing_payload": {
"account_identifier": {
"address": "8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"
},
"hex_bytes": "0a69632d726571756573747a67e99e9f5e1cdfa741f8f757bb8c04f00a5fdb20a68bb273ce80973af7a6de",
"signature_type": "ecdsa"
},
"signature_type": "ecdsa",
"public_key": {
"hex_bytes": "047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c757367",
"curve_type": "secp256k1"
},
"hex_bytes": "bbb93c5e86b8b42128dcac381051e996949f0d8cfc70cc3e8f2bbd2d4788cce7ac8c8d5bc179adf528cebd2c8b61e6288e0b0595d85a11b56fd1649dbaafcffb"
}
]
}'
The response will resemble the following:
{'signed_transaction': '81826b5452414e53414354494f4e81a266757064617465a367636f6e74656e74bf6c726571756573745f747970656463616c6c6b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758480a0b08baea959fe0a9e58dbd0112040a02080a1a0308904e2a220a207f622708b363917e3ba0ef8ac1cb0dfe241ef5ffca54f32c1480473ee3a12cad3a0a0899d9c88df3d893e0176673656e646572581d2e70031d8e7ff922b6ad9f2a9eb3c1e77ffa7b6c0d0120dd4ac7e4f7026e696e67726573735f6578706972791b17c04eff12cf8023ff6d73656e6465725f7075626b657958583056301006072a8648ce3d020106052b8104000a034200047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c7573676a73656e6465725f7369675840877f315ab0e84ac781395b4c1ce2978f77e316abe2f6eb058a22e80e14246d5c9e2e2d8ff863dca53be432aa65154a39d4b6b5304774e8ebcbe3117fd17e35dd6a726561645f7374617465a367636f6e74656e74bf6c726571756573745f747970656a726561645f73746174656673656e646572581d2e70031d8e7ff922b6ad9f2a9eb3c1e77ffa7b6c0d0120dd4ac7e4f70265706174687381824e726571756573745f73746174757358208c85871f2b1d1edea73797b31cd63094fa82052fed84c06d45d6c719170d8f6f6e696e67726573735f6578706972791b17c04eff12cf8023ff6d73656e6465725f7075626b657958583056301006072a8648ce3d020106052b8104000a034200047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c7573676a73656e6465725f7369675840bbb93c5e86b8b42128dcac381051e996949f0d8cfc70cc3e8f2bbd2d4788cce7ac8c8d5bc179adf528cebd2c8b61e6288e0b0595d85a11b56fd1649dbaafcffb'}
Construction-derive
This section details how to derive an ICP address using the Rosetta construction API.
The ICP ledger is using accountidentifiers
to represent public keys internally. To derive an accountidentifier
from a public key the Rosetta API offers the construction/derive
endpoint.
The request and response types can be found in the official documentation.
How to derive accountidentifiers
You have to provide Rosetta with the public key representation as specified in the Rosetta-API standard. An example of a call to the derive endpoint can be found below:
curl --location '0.0.0.0:8081/construction/derive' --header 'Content-Type: application/json' --data '{
"network_identifier": {
"blockchain":"Internet Computer",
"network":"00000000000000020101"
},
"public_key": {
"hex_bytes": "047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c757367",
"curve_type": "secp256k1"
}
}'
The response is the accountidentifier
used by the ICP ledger:
{"account_identifier":{"address":"8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"}}⏎
Construction-metadata
This section details how to call the construction/metadata
endpoint of the Rosetta construction API.
The request and response types can be found in the official documentation.
How to fetch metadata from the ICP ledger
An example of a call to the metadata endpoint can be found below:
curl --location '0.0.0.0:8081/construction/metadata' --header 'Content-Type: application/json' --data '{
"network_identifier": {
"blockchain": "Internet Computer",
"network": "00000000000000020101"
},
"options": {
"request_types": [
"TRANSACTION"
]
},
"public_keys": [
{
"hex_bytes": "047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c757367",
"curve_type": "secp256k1"
}
]
}'
The response would resemble the following:
{"metadata":{},"suggested_fee":[{"value":"10000","currency":{"symbol":"ICP","decimals":8}}]}⏎
For the request type TRANSACTION
the metadata includes the suggested fee for this operation.
In the case of the ICP ledger, this fee is 10_000
e8s of ICP.
Construction-payloads
This section details how to call the construction/payloads
endpoint of the Rosetta construction API.
The request and response types can be found in the official documentation.
The payloads endpoint is responsible for providing the necessary payload that needs to be signed by the sender of the transaction.
Payloads request structure
Additionally to the set of operations and the required public keys, the user has the option to specify a few things in the metadata. These are comprised of two types of metadata:
- Non-request-specific metadata: These are options that can be set by the user that are independent of the request type that is being made.
ingress_start
: This field stipulates from which point in time onwards the request should be valid. If not set, this field will be set to the current time by Rosetta.ingress_end
: This field determines until when the request will be valid. The returned unsigned transaction is only valid until this point in time.
- Request-specific metadata: These are options that can be set for specific request types. For ICP Rosetta, they are relevant for
TRANSACTION
request types.
Payloads-return structure
There are multiple payloads that need to be signed by the user. The reason for that is twofold:
The first reason has to do with how ICP processes requests. For a call to ICP to be successful and for the user to be able to read the response of the call, two HTTP calls have to be made:
- The first HTTP call (`Call Request`) contains all the information that ICP needs to know to be able to call
the correct canister with the desired arguments. This call returns an ID, which essentially serves as a ticket for
the caller. With this ticket a user can then query ICP periodically (`Read-State Request`) and essentially ask
whether the original request has been processed and if there is a response. If the latter is true, ICP will return
the result in bytes. The Rosetta API then converts these bytes into a readable format. This is why for every
transaction that is requested from the user, there must be at least two payloads.The second reason has to do with how ICP validates requests. Every
Call Request
andRead-State Request
need to be forwarded to ICP with a valid signature that is associated with each of these requests. Every request is only valid for a limited period of time (EXPIRY_INTERVAL
). This time interval is in the range of a couple of minutes. To extend the overall time period in which the transaction can be posted, Rosetta will create a set of payloads, each being valid for a specific time interval. Together the payloads in this set cover the entire requested time period. For example, if theEXPIRY_INTERVAL
was 5 minutes and the requested time period is 20 minutes from now, Rosetta would need to create at least 20/5 payloads for eachCall Request
andRead-State Request
. This amounts to a total of at least 20/5*2 payloads for this example.
An example of a call to the payloads endpoint would resemble the following. This example does not set any metadata, so the unsigned transaction that is returned will be valid for the next 4 minutes. This time interval is set by Rosetta and can be changed by
setting ingress_end
. The created_at_time
will be set to the current time if not provided, and the memo
will be left blank.
curl --location '0.0.0.0:8081/construction/payloads' --header 'Content-Type: application/json' --data '{
"network_identifier": {
"blockchain": "Internet Computer",
"network": "00000000000000020101"
},
"public_keys": [
{
"hex_bytes": "047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c757367",
"curve_type": "secp256k1"
}
],
"operations": [
{
"operation_identifier": {
"index": 0
},
"type": "TRANSACTION",
"account": {
"address": "8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"
},
"amount": {
"value": "-10",
"currency": {
"symbol": "ICP",
"decimals": 8
}
}
},
{
"operation_identifier": {
"index": 1
},
"type": "TRANSACTION",
"account": {
"address": "7f622708b363917e3ba0ef8ac1cb0dfe241ef5ffca54f32c1480473ee3a12cad"
},
"amount": {
"value": "10",
"currency": {
"symbol": "ICP",
"decimals": 8
}
}
},
{
"operation_identifier": {
"index": 2
},
"type": "FEE",
"account": {
"address": "8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"
},
"amount": {
"value": "-10000",
"currency": {
"symbol": "ICP",
"decimals": 8
}
}
}
]
}'
The returned object contains an unsigned transaction as well as the payloads. The unsigned transaction is the hex format serialized content that is sent to ICP. It contains all the information that a replica needs to determine which canister to call, at what endpoint, and with which function parameters. The payloads are stipulated by the Rosetta-API standard, and each payload gives information about which account has to sign what bytes in order for the unsigned transaction to be converted into a signed transaction successfully.
In the case of this example, there are two returned payloads: one for the Call Request
and the other for the Read-State Request
. Both of these payloads will need to be signed in the next step.
The unsigned transaction will thus be valid for the next 4 minutes since we did not specify any ingress_interval
.
{'unsigned_transaction': 'a2677570646174657381826b5452414e53414354494f4ea56b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758480a0b08baea959fe0a9e58dbd0112040a02080a1a0308904e2a220a207f622708b363917e3ba0ef8ac1cb0dfe241ef5ffca54f32c1480473ee3a12cad3a0a0899d9c88df3d893e0176673656e646572581d2e70031d8e7ff922b6ad9f2a9eb3c1e77ffa7b6c0d0120dd4ac7e4f7026e696e67726573735f6578706972790070696e67726573735f6578706972696573811b17c04eff12cf8023', 'payloads': [{'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573748c85871f2b1d1edea73797b31cd63094fa82052fed84c06d45d6c719170d8f6f', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573747a67e99e9f5e1cdfa741f8f757bb8c04f00a5fdb20a68bb273ce80973af7a6de', 'signature_type': 'ecdsa'}]}
Here is an example call that sets the ingress_start
time to the current time and the ingress_end
time to an hour from now. The created_at_time
is also set to the current time, and the memo is set to 1234
.
curl --location '0.0.0.0:8081/construction/payloads' --header 'Content-Type: application/json' --data '{
"network_identifier": {
"blockchain": "Internet Computer",
"network": "00000000000000020101"
},
"public_keys": [
{
"hex_bytes": "047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c757367",
"curve_type": "secp256k1"
}
],
"operations": [
{
"operation_identifier": {
"index": 0
},
"type": "TRANSACTION",
"account": {
"address": "8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"
},
"amount": {
"value": "-10",
"currency": {
"symbol": "ICP",
"decimals": 8
}
}
},
{
"operation_identifier": {
"index": 1
},
"type": "TRANSACTION",
"account": {
"address": "7f622708b363917e3ba0ef8ac1cb0dfe241ef5ffca54f32c1480473ee3a12cad"
},
"amount": {
"value": "10",
"currency": {
"symbol": "ICP",
"decimals": 8
}
}
},
{
"operation_identifier": {
"index": 2
},
"type": "FEE",
"account": {
"address": "8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"
},
"amount": {
"value": "-10000",
"currency": {
"symbol": "ICP",
"decimals": 8
}
}
}
],
"metadata": {
"created_at_time": 1711114402000000000,
"memo": 1234,
"ingress_start": 1711114402000000000,
"ingress_end": 1711118002000000000
}
}'
The response object is considerably larger, as Rosetta will create multiple payloads to make up a vector of valid unsigned transactions that can be posted any time between ingress_start
and ingress_end
. To account for edge cases around the time that an unsigned transaction expires, with respect to the expiry time, Rosetta creates overlapping payloads. This means that if the first payload p1
is valid from t0
until t0 + 4[min]
, then the next payload p2
will be valid from t0 + 4[min] - 1[min]
. If you want to post the transaction around the timestamp t0 + 4[min]
you would run into issues if you only used p1
. However, with this overlap of expiry timeframes, the payload with the most remaining time where it is valid is chosen; in this case, it would be p2
.
{'unsigned_transaction': 'a2677570646174657381826b5452414e53414354494f4ea56b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758400a0308d20912040a02080a1a0308904e2a220a207f622708b363917e3ba0ef8ac1cb0dfe241ef5ffca54f32c1480473ee3a12cad3a0a0880a88faab9afc6df176673656e646572581d2e70031d8e7ff922b6ad9f2a9eb3c1e77ffa7b6c0d0120dd4ac7e4f7026e696e67726573735f6578706972790070696e67726573735f6578706972696573981e1b17bf19b3766134001b17bf19cf66efe4001b17bf19eb577e94001b17bf1a07480d44001b17bf1a23389bf4001b17bf1a3f292aa4001b17bf1a5b19b954001b17bf1a770a4804001b17bf1a92fad6b4001b17bf1aaeeb6564001b17bf1acadbf414001b17bf1ae6cc82c4001b17bf1b02bd1174001b17bf1b1eada024001b17bf1b3a9e2ed4001b17bf1b568ebd84001b17bf1b727f4c34001b17bf1b8e6fdae4001b17bf1baa606994001b17bf1bc650f844001b17bf1be24186f4001b17bf1bfe3215a4001b17bf1c1a22a454001b17bf1c36133304001b17bf1c5203c1b4001b17bf1c6df45064001b17bf1c89e4df14001b17bf1ca5d56dc4001b17bf1cc1c5fc74001b17bf1cddb68b2400', 'payloads': [{'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573748776ff8cadde7db2869b982613605b8ffc589c8076c9d218938dd34bceb65053', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573740cb2acc0f1e8d4bb5c548c314366e054546a0f12c0812ca7d79f5054417c4766', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374c667c1bfee121306e47efc786975d24bc45ef695ab136984686fe05807b5d3fc', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374ae6c99721423e443cbee85a412758a3c648af6343083ef33f4561a9a6e9a0e90', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374840797507bff7f2e414f5de66485aa1472c4c22ec6fe74a3e2055a05d68d2990', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374b61bc3f40a8c4b0797caadabf2e7ec8be4e83b08a77ff741a8392fb5bb50e997', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374c73a424262bd16be54e66454810a9e044029407cee6a51fc9329f341c2a07be7', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d7265717565737451ff8666ae06d35298e64e95feaf15925d26d022bcf2f9757cefd2e1ad9234a0', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374235f797fcb30fee026103498ecf2c3ae31471aa8df9e37775a6e53d3d39822bc', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573747f6300ffabb785fb729872e80d2d5b5779a55653d32e737e33c6087f87440136', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374f41be959d8964e89297749e4dcdb842b0c40040b468929c300784520873e010c', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374bfc2ad014c96d845a3ba909566e3ac2ef559f413d0ada3634e8571af8cde221b', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573747602e0b73155acd4164b38f1fce7190adf22b8c2be9458a8a7020b9bc8a035d6', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374576014eeed8f969b6d8282ea809f5463abcfee4fe1b85c66ed2558a1bccf9d2e', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573749b9b0982e759f36d64112c36240baae20f74a950456f85f476173c0e1d7a1112', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d7265717565737495a3c640d6afa4788566871b4e9005564050f5a50db982669734bc565c02a571', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374225b80f8c6b8b0b7c9530d76b7ae2105db2a5928693ecb83eaa2b94417065548', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374975b57eb2e361dfd725e216d17faa1a7e33f8f07571f2fb0f511a9a9cbd188b3', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374a97c5f07aa93de14d35acd02589f910037ec9b2905c8122afccfe4b450c2c87c', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d7265717565737478e6451c4a152eb21c5cf592a15cc614da4fe2974b8035f1d9289845ba8ec441', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573749e8c5d45ddc058b079b4e2d55d7e648e0592d928a3f16e46a28a403a4a5353bd', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374a71a256363ffe14f72e4d7089b2d8bd5eb146828af8f42f06b991a497f8248f8', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374af91da9bb735a3e019d2040ee8d256028ee15ab903154bbfe719b1848895c799', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573746c5d45bae14d7dbfbfe8c457f7ec5f90fadd84998fa1e4b4a82b3d5b3e78df3b', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573745679674251d700e27898126831718c357a51207ea576f8ca98311cd511620424', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573748527d97c6c73ed5b029185e9ff1e6ae43d6be6c63cd4a1625c80e58a9b0a27c1', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d7265717565737477b3732e005efacdbf199232458b4fd944afa8c6b02ffc596609f9f8cecd2124', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573745ff9e9b9dd96e7d178556950396ec4728799ba5d951fa8c97988bdd559e2c90a', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374ee37ac86cc8fac294d7d583907f5890bead9cd2c050994be9911905b21034231', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573748888e8e2caaf5a9a2c27740c856ef5989688ca6f054e6ecf48b4abe3df615765', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374bfd1ab13546257bc98ec8869686a5e67a7b18a492e2b180884a363634ff4dff6', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374534eacdaa96ec016484591cb8afd5747a57e822cf376f6d66e073f51cb35621b', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374bb851b91a1e423b7156f2e9bebd0162304d559fc25c78ab37a066b08893dc876', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573745bbf4aedc27de6f9e56147aa2fb98612c314f77e0f93386071ae6e957c6115d7', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d7265717565737424ba149c7a17a5db9637b62dd3f0e7a0c5889783885cc422367d679715375fcc', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374491720a59529b9a024adef7ceaf2c0b2e13fc5b6e34d663f077e561eba0ab993', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374941297b35c4a155574a16e6fe650a53faee1d79c17342bc48be5109389441e78', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d7265717565737455fbeb4dd1093d34cf7d1c43c5161bd1149a725e028e7a4e902a66458740bb99', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573747319e73b4abf8b1ace7cf984e8031c765f454b345132226913e4158488a62c34', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374faebb1c5f081eac503c2f84ed314480ebf12cffd8fbc8283ac576507fde33e65', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374e5bfa91de5dbcac59b9e5cd359b83ac0462106f95d583517673b4e2d64b66d8e', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573747c66057f52df54383603e89639c76f03cdcc993bc5e183746b0539c5caf29553', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374acb4f1b2436a7bc1ea43ec689b109e9c2b2d6bddaaa6e24b149116d1871f88db', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d7265717565737416e4d851f448ecec39ad5f36025231e964614b090c1f65060b936cfc612f3258', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573744cfcbc9827757f6a3e4f00940c914702c4db94788774174c2010cb591bbacac4', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573743582dfa2f5a62da191a7f66deab81c14ec4abe2f0e6ff7a11c2a4e7aea74f49e', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573747eb1cd4999a738d5d623a8c440b20db7d498d669e01e2a2be412fa1c536e1a8a', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d7265717565737452c0289e6c2197e3ae5b7909982d1568d6fd21b1dea4950ef714ef5885c94317', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374903544af2282dc516f1a6b16329c52cb0fac5a7468e5feca0b79759136a23efd', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573743a1144b583d499772161f7483e52a5fb33d1d7ddb8afe1d80a5a7233f64340e1', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374937081c10b1f0b5c4382d2b3adb540c4c55ea1b599c7958bb95cb46da3b400eb', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d7265717565737414cd50b2fda5168e6d706ba789eb3a982c6d2d67963af2dcd8ed67e2b3a2cdd0', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573744203d03b10942912b052d1283085a0ada54127916259cc19a286472f8c14bd5a', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374b8bbcd7d5c614ee55df27478902cc6e87dc2e14332727407db3eba92883b480e', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573746b56ce66def8b9080a3b9e2b7779a8013673af9b361c8003475ee38bf9599559', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374f631f74ff8be50ed1e5f94dd807758f02bdd3976796af4d257a170b4b5037c92', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d72657175657374a31cef8e8bd04cc46cc6e965543d5bf0fcdb0b017b32243f3e5514be0d628bb2', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d7265717565737407bf0dba46a3373fd5db8cbcaa0580cc81df4e4d874acef3b5b552c5b4d6cd4c', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573740558eea4d38d5e013acbf0569c7b43eb3b85fac98327b16f9978abd4e318feb4', 'signature_type': 'ecdsa'}, {'account_identifier': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'hex_bytes': '0a69632d726571756573745fc08041dd435165bd45bf7e708ccf17805feae2ce0adecc17a698e9777f1ade', 'signature_type': 'ecdsa'}]}
Construction-preprocess
This section details how to call the construction/preprocess
endpoint of the Rosetta construction API.
Preprocess is called prior to /construction/payloads
to construct a request for any metadata that is needed for transaction construction. The ICP Rosetta implementation will return the required list of public keys that has to be provided by the user, and in the metadata, it returns the request type that is associated with the given set of operations.
The metadata returned from this endpoint will be sent to the /construction/metadata
endpoint UNMODIFIED by the caller (in an offline execution environment).
The request and response types can be found in the official documentation.
An example of a call to the preprocess endpoint would resemble the following:
curl --location '0.0.0.0:8081/construction/preprocess' --header 'Content-Type: application/json' --data '{
"network_identifier": {
"blockchain": "Internet Computer",
"network": "00000000000000020101"
},
"operations": [
{
"operation_identifier": {
"index": 0
},
"type": "TRANSACTION",
"account": {
"address": "8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"
},
"amount": {
"value": "-10",
"currency": {
"symbol": "ICP",
"decimals": 8
}
}
},
{
"operation_identifier": {
"index": 1
},
"type": "TRANSACTION",
"account": {
"address": "7f622708b363917e3ba0ef8ac1cb0dfe241ef5ffca54f32c1480473ee3a12cad"
},
"amount": {
"value": "10",
"currency": {
"symbol": "ICP",
"decimals": 8
}
}
}
],
"metadata": null
}'
Here you are creating two operations, one for debiting the account that the tokens are sent from and a credit operation for the account where the tokens are sent to.
For this example, you are sending ICP to the arbitrary account 7f622708b363917e3ba0ef8ac1cb0dfe241ef5ffca54f32c1480473ee3a12cad
.
The response would look something like this.
{"options":{"request_types":["TRANSACTION"]},"required_public_keys":[{"address":"8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4"}]}
It contains two fields. The options
object has to be forwarded to the construction/metadata
endpoint to fetch network-specific data.
The required_public_keys
field indicates for which account-id
the construction/payloads
endpoint will need the full public key.
The required public key in this case is the public key that corresponds to the sending account. You can derive this public key from the provided private key. To validate that the accountidentifiers
match up, you can call construction/derive
with the public key.
Construction-submit
This section details how to call the construction/submit
endpoint of the Rosetta construction API.
The request and response types can be found in the official documentation.
The endpoint sends two transactions to the IC. The first being the Call Request
, which contains the information of what to submit, which canister, what function in the canister, and with what arguments it should be called.
The second is a Read-State Request
, which continuously fetches the current status of the Call Request
from the IC. It returns either containing some error or the response of the canister.
This means that a call to the construction/submit
endpoint is blocking until a result is available. Inside the returned object you will find information about the response from the ledger.
The construction/submit
endpoint can be called with the following:
curl --location '0.0.0.0:8081/construction/submit' --header 'Content-Type: application/json' --data '{
"network_identifier": {
"blockchain": "Internet Computer",
"network": "00000000000000020101"
},
"signed_transaction": "a168726571756573747381826b5452414e53414354494f4e81a266757064617465a367636f6e74656e74bf6c726571756573745f747970656463616c6c6b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758480a0b0899f29a9eeae1e288e20112040a02080a1a0308904e2a220a207f622708b363917e3ba0ef8ac1cb0dfe241ef5ffca54f32c1480473ee3a12cad3a0a089cd7c5caff8791e0176673656e646572581d2e70031d8e7ff922b6ad9f2a9eb3c1e77ffa7b6c0d0120dd4ac7e4f7026e696e67726573735f6578706972791b17c04477da6ec16aff6d73656e6465725f7075626b657958583056301006072a8648ce3d020106052b8104000a034200047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c7573676a73656e6465725f73696758406c382fa3a993266ef760e87f2a24098ee77577d2627d0648eb80c09abdfc8e1e69db98391bf28f8bd76d0baa18e3635a36c7da21258351db57879be677cb74bf6a726561645f7374617465a367636f6e74656e74bf6c726571756573745f747970656a726561645f73746174656673656e646572581d2e70031d8e7ff922b6ad9f2a9eb3c1e77ffa7b6c0d0120dd4ac7e4f70265706174687381824e726571756573745f7374617475735820f44e9df174422a8da79510951553aa40f05069061ce7c4d4f49d95299760196e6e696e67726573735f6578706972791b17c04477da6ec16aff6d73656e6465725f7075626b657958583056301006072a8648ce3d020106052b8104000a034200047a83e378053f87b49aeae53b3ed274c8b2ffbe59d9a51e3c4d850ca8ac1684f7131b778317c0db04de661c7d08321d60c0507868af41fe3150d21b3c6c7573676a73656e6465725f73696758401f7fedfbd38d5a9e73491f41d5f923bac0f6696729b29eb7bba02621f9bd184e9cc7c9b455c72bf6940a3ff12e8346d087ac630868771be0dde72343d8549e1c"
}'
The response would resemble the following:
{'transaction_identifier': {'hash': '93b71e1bdb5016e31f28a7762283c896f1d749cdbd8569c1bf8487f804f7923b'}, 'metadata': {'operations': [{'account': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'amount': {'currency': {'decimals': 8, 'symbol': 'ICP'}, 'value': '-10'}, 'metadata': {'block_index': 342, 'transaction_identifier': {'hash': '93b71e1bdb5016e31f28a7762283c896f1d749cdbd8569c1bf8487f804f7923b'}}, 'operation_identifier': {'index': 0}, 'status': 'COMPLETED', 'type': 'TRANSACTION'}, {'account': {'address': '7f622708b363917e3ba0ef8ac1cb0dfe241ef5ffca54f32c1480473ee3a12cad'}, 'amount': {'currency': {'decimals': 8, 'symbol': 'ICP'}, 'value': '10'}, 'metadata': {'block_index': 342, 'transaction_identifier': {'hash': '93b71e1bdb5016e31f28a7762283c896f1d749cdbd8569c1bf8487f804f7923b'}}, 'operation_identifier': {'index': 1}, 'status': 'COMPLETED', 'type': 'TRANSACTION'}, {'account': {'address': '8b84c3a3529d02a9decb5b1a27e7c8d886e17e07ea0a538269697ef09c2a27b4'}, 'amount': {'currency': {'decimals': 8, 'symbol': 'ICP'}, 'value': '-10000'}, 'metadata': {'block_index': 342, 'transaction_identifier': {'hash': '93b71e1bdb5016e31f28a7762283c896f1d749cdbd8569c1bf8487f804f7923b'}}, 'operation_identifier': {'index': 2}, 'status': 'COMPLETED', 'type': 'FEE'}]}}
To know whether the transaction was successful or not, you can look at the status
field. If it says "status": "COMPLETED,
then the transaction was successful. This is true for any transaction type supported by Rosetta.
Alternatively, a user can query the /block
or block/transaction
endpoints to see whether the transaction has been included in the blockchain of the ICP ledger.