Exchange Integration
In a private coin like Stegos, where each utxo has a cloaked public key, one usually needs a secret key to find whether a particular utxo belongs to a particular user.
Exchange services usually handle a large number of users. For security reasons, they store secret keys in a secure place, often without access to the internet. Thus the standard Stegos approach is incompatible with standard exchange processes.
To get around this problem, for exchanges we make use of Public
outputs.
Public outputs are already used in the validator service award: they store recipient and amount data in open form. This means anybody can see this data, for example via a block explorer.
Transaction signing
Stegos handles transaction signing differently from the standard sign(bytes, secret_key)
approach: in order to sign a transaction, it is necessary to calculate data based on inputs and outputs.
So transaction signing cannot be split from serialization. To simplify this process, we introduce the api method
create_raw_transaction
for signing transactions from raw data.
Integration design
To allow exchanges to store secret keys in a seperate location without access to the internet, we propose the folowing architecture:
In this architecture, a keypair would be created for each exchange user. This can be done on demand, or at the time the user joins the exchange.
The secret part of the keypair, would be stored in some secret place, which we’ll call the Cold wallet
.
This Cold wallet
has a node which starts in offline mode. In order to start a node in offline mode, the flag -X
should be passed:
./stegosd -X -n mainnet
Cold wallet
can be limited to a single api call by create_raw_transaction
.
In this architecture, exchange integrators will also need to develop an output explorer which observes blockchain history and searches for users’ UTXOs by recepient
address.
This can be easily done by subscribing to chain updates. See Blockchain notifications.
In order to fully isolate Cold wallet
from the network it is also necessary to deliver full inputs to Cold wallet
.
See: outputs_list
for more information about output retrival.
Finally, it is necessary to send transactions to the network. To do this, use the broadcast_transaction
method.
Exchange API (offline signing)
To allow exchanges to split their keys, we designed an api for offline signing.
Websocket protocol
For all integration we use the same protocol described in the protocol section of the websocket API page.
Outputs list
Returns full output blobs, by UTXO IDs.
Request
{
"type": "outputs_list",
"utxos": // Array of UTXO IDs
[
"output_hash",.. // HEX represented Hash of output (UTXO ID)
]
}
Request example
{
"type": "outputs_list",
"utxos": [
"33a3362aa631a9e6bff4d7c492c97112e0699917f9c3a236711ed3cb3f7281f3"
]
}
Response
{
"type": "outputs_list",
"utxos": // Array of UTXOs
[
"output",.. // HEX represented full output
]
}
Response example
{
"type": "outputs_list",
"utxos": [
"0a970e0a240a220a20a60855d848ea7eb398b17ad289b21fe722032459ce6d70396e4dc0ed31f0ca2a12c7050a220a202cfd1846752b83dd4940c1748df08ada0d048cdd5c674a428b4db98a415a496112a00540257d4ad865a3558a2d5fcabd5d3ebc89b5b653799b2f019aaa4eae6839ad7bca6b274354d8cc0edffcf56658a4f99623febeb614e509bb204177cc67717a28ee52262f6e3295126d94784e854578150d9c41b37fbafd1c38d814b233e3c43b688d144eb2ce408eca7ab1512086e5c68833520deffa64c8944fb6bbd2bada7c9cf86f40e457600fe41ea17077965121aaee6b949433e60dd18d229fde016404f4830465e1626142b8357ac1dd6e43291e8091aab2134f24c6f5def7a6b0a109c0acbcca164c7e6a38a73a9596fc5fd04aabc51e99281e9f31948af7a2c9d70ac4e6be138b9327b3f3eaa484ef1638174890e8a5c7dc71f328040fc525781b20c4f124df51a8574b02714c8c3778b688c4de71e9698145714592bef4868d096464c84fc5d167fea0a801072ad502e67759a3a9771999d878a15e91781ebea26d10c954ac7219ad7dc689bc06442fced2f45cf15d983f11799e1e21ba8517e17e8a47db2a974a598c4919c5fad7e0a2bf832f1cd5a2ffbe20fd02f7bf5ce16f41a086790e27526375b452debd093af790364dbd6b637ab19766718cdd6187220344473047a8c1de168121924ae96c7cdc97ef592051ea84bf4eed5db29cf71736449efc9699c28fdfe88b8f99e3d8a12a717c3e5225471d97fd57da8682b9d23e740a51b243af9981b8cc83863f35793dfa805ef469a8dae9dd756b98fc9dd600e2cea3172cabfbf9edc84dae088aec305c80d05f97ac5f03d4533ea9ae8bea51c4b975a69bdd34a5777b4d7bf977343fb184f4b1aff44797961fa87d3822cd3912e90cbf5804b6ebd5ffce783f9538b07d4e20f24aab4b192579cddd3cd47a4d61d3f8c162dbd5fb951c4cf7a0dce6b05a6a90dab403925b3fa9658cfb73b20394ee089fef7816efa05af6c53bfd03e273e34e82e0c7b6a71b1f06c114e5370c22220a20787eb91b0aa4263c9b52bcbf733fc41d466b74ab0dd78b9981db96df6a6e845e2a8008375db1a9787c0bec5345fba7aac5945feebe62d9447c4521e012daad23e950811a9456e45e2337d17c8f346b7e0ef25d84e6a625fdfbce15c612e195bb00df06968ad5c1f86cec544098a2b12c64ce7f80a77ff701e09189ea9504a55761fe95fc614821502c24af9fcf951e15f17286f6fac813b3d20593a31586480ea57e523ecfc88d7211661e997969cca96450fc754985feebe35dc3d4aebb7d3a97f6b1df11e6c724d61e1bd697dcc636311ad27399a6308a84e184cbbd0c5877ae57ed070f60290ac79d07d0a72642a9dd56ac1dec7967ec8cc3e39e047b1a9a789a817b92387c505cb8e7fc0a8d9bc95969b33505030d44a7b33585a6f5c6965973df3014f21565c577454614ac827dd16695718eba7fb45f292d7cc1a74cd7a024b18613213c93df858d0afb386866b24023e7a2ff90295c403ab8ccd77c162eadced305cea587925e13a054f60aa5e3d7c1a917371acb5532c6fffed349abe77a268941d9f5eed6c739e44cbce61d34ec2b9b62e4b06fc7ede3532e7978bb335f8139ea46a91ac66531a13783aa0f79be168bf7c159e6feb52008f6b5a0bca48f0ae4414ba8cd6b0a602f7264d72a09bb31bca13008d2f0050f5750c04b74c8a5844b2639c657b28cccd2c802a501cc11dad2028a63a0d912ca6a800eab99df20f244122898cc875570a7ca5655f9f07419aa62fd860cfd5f07c738203e465a1d0bacdd6c7099a1c6da09e7b36327efca84e2ab606c596a009928d95387ac1cf79ae31df8b9ded35b10538e7694dfcfbdef9878a933f7eeed1fa461f2af51f867a37c37d02c132f08e928012800b3137845dd8260c4efcf668279a027548cfa46ea057c9dc47c28d56ffccc559c32e9b4768eef9db59d4b99d28fd1f1d8ef64acd0db41bea6dc498d0929ab3ef82b92b7df4cc10a3a0a359e947a71e8a20302ae6eec47e214cfb5b81ac9b16cc97d9b70749fb3aa386151ff29414590e7d63f4fa0c40c2d56483bdddf7894b2bcf597106c260b9ed72ad88c1c8bf6c782b3314b0cfd1ef30f974d05279ba45ab22adcfdab53766166479abfc56ea51a2fdcd28290806b15d39b2d0dd6209517ad2ecd74ebb83b3a9644e5a20f9533b0987afc3f4384ea3686622cd821d967f856d9798c89da014b71e1fd624a9504309b0cdfd66d3e316b100ad14e8aeeda632cb2b8383520dd1e5b3d3854312bfc4922d295322a5ea2415026a4956c100b9945be2c5882674c32713ac3a5a996aac3e5221067e503aa4ef8df630c5f4803f9fef82e689a9e5e76303f9c8c822842219db161f64ce1ee47eb558c264d37ab0c4ca53ac8d7bc907849cb47628a2f19e802862be5d9be621facf8712826418e8bfe0a34cd9bde681a1173480cb2922b2ff4925bdcac1acf19aea3ae76275f1954b92b24e897c5cdb8770f4f7b617ee5261b53766ab4"
]
}
Creating and signing transaction
Creates transaction based on array of UTXO IDs, and pre-filled data for newly created outputs.
Request
{
"type":"create_raw_transaction",
"txins": // array of inputs
[
"output_hash",.. // HEX represented Hash of output (UTXO ID).
],
"txouts": // array of outputs, that should be created
[
{
"output_type":"payment", // type of output could be payment | public_paymnet
"comment": "string", // STRING comment that should be sent to recipient, in output
"amount": num, // amount that should be transfered NUMBER
"recipient":"bech32" // (BECH32 form of recipient public key )
}
],
"secret_key":"bytes", // array of 32 bytes, which is a secret key canonical representation
"fee": num, // numeric amount of fee
"unspent_list": // array with full UTXO of inputs
[
"0a970e0a240...66ab4",.. // HEX represented blob of input
]
}
If input is missing in **unspent_list**, then inputs will be searched in the local copy of the blockchain.
Request example
{
"type": "create_raw_transaction",
"txins": [
"33a3362aa631a9e6bff4d7c492c97112e0699917f9c3a236711ed3cb3f7281f3"
],
"txouts": [
{
"output_type": "public_payment",
"amount": 400000000,
"recipient": "stt1jz93s3534w5z58r4was0dg0lhgk58l2n0nf43nkpadvk7ue7gyus2wsars"
}
],
"secret_key": [
189, 97, 253, 136, 193, 119, 245, 54, 13, 211, 102, 4, 143, 172, 130, 249, 89, 80, 185, 46, 33, 245, 162, 159, 75, 33, 177, 123, 158, 110, 143, 1
],
"fee": 100000000,
"unspent_list": [
"0a970e0a240a220a20a60855d848ea7eb398b17ad289b21fe722032459ce6d70396e4dc0ed31f0ca2a12c7050a220a202cfd1846752b83dd4940c1748df08ada0d048cdd5c674a428b4db98a415a496112a00540257d4ad865a3558a2d5fcabd5d3ebc89b5b653799b2f019aaa4eae6839ad7bca6b274354d8cc0edffcf56658a4f99623febeb614e509bb204177cc67717a28ee52262f6e3295126d94784e854578150d9c41b37fbafd1c38d814b233e3c43b688d144eb2ce408eca7ab1512086e5c68833520deffa64c8944fb6bbd2bada7c9cf86f40e457600fe41ea17077965121aaee6b949433e60dd18d229fde016404f4830465e1626142b8357ac1dd6e43291e8091aab2134f24c6f5def7a6b0a109c0acbcca164c7e6a38a73a9596fc5fd04aabc51e99281e9f31948af7a2c9d70ac4e6be138b9327b3f3eaa484ef1638174890e8a5c7dc71f328040fc525781b20c4f124df51a8574b02714c8c3778b688c4de71e9698145714592bef4868d096464c84fc5d167fea0a801072ad502e67759a3a9771999d878a15e91781ebea26d10c954ac7219ad7dc689bc06442fced2f45cf15d983f11799e1e21ba8517e17e8a47db2a974a598c4919c5fad7e0a2bf832f1cd5a2ffbe20fd02f7bf5ce16f41a086790e27526375b452debd093af790364dbd6b637ab19766718cdd6187220344473047a8c1de168121924ae96c7cdc97ef592051ea84bf4eed5db29cf71736449efc9699c28fdfe88b8f99e3d8a12a717c3e5225471d97fd57da8682b9d23e740a51b243af9981b8cc83863f35793dfa805ef469a8dae9dd756b98fc9dd600e2cea3172cabfbf9edc84dae088aec305c80d05f97ac5f03d4533ea9ae8bea51c4b975a69bdd34a5777b4d7bf977343fb184f4b1aff44797961fa87d3822cd3912e90cbf5804b6ebd5ffce783f9538b07d4e20f24aab4b192579cddd3cd47a4d61d3f8c162dbd5fb951c4cf7a0dce6b05a6a90dab403925b3fa9658cfb73b20394ee089fef7816efa05af6c53bfd03e273e34e82e0c7b6a71b1f06c114e5370c22220a20787eb91b0aa4263c9b52bcbf733fc41d466b74ab0dd78b9981db96df6a6e845e2a8008375db1a9787c0bec5345fba7aac5945feebe62d9447c4521e012daad23e950811a9456e45e2337d17c8f346b7e0ef25d84e6a625fdfbce15c612e195bb00df06968ad5c1f86cec544098a2b12c64ce7f80a77ff701e09189ea9504a55761fe95fc614821502c24af9fcf951e15f17286f6fac813b3d20593a31586480ea57e523ecfc88d7211661e997969cca96450fc754985feebe35dc3d4aebb7d3a97f6b1df11e6c724d61e1bd697dcc636311ad27399a6308a84e184cbbd0c5877ae57ed070f60290ac79d07d0a72642a9dd56ac1dec7967ec8cc3e39e047b1a9a789a817b92387c505cb8e7fc0a8d9bc95969b33505030d44a7b33585a6f5c6965973df3014f21565c577454614ac827dd16695718eba7fb45f292d7cc1a74cd7a024b18613213c93df858d0afb386866b24023e7a2ff90295c403ab8ccd77c162eadced305cea587925e13a054f60aa5e3d7c1a917371acb5532c6fffed349abe77a268941d9f5eed6c739e44cbce61d34ec2b9b62e4b06fc7ede3532e7978bb335f8139ea46a91ac66531a13783aa0f79be168bf7c159e6feb52008f6b5a0bca48f0ae4414ba8cd6b0a602f7264d72a09bb31bca13008d2f0050f5750c04b74c8a5844b2639c657b28cccd2c802a501cc11dad2028a63a0d912ca6a800eab99df20f244122898cc875570a7ca5655f9f07419aa62fd860cfd5f07c738203e465a1d0bacdd6c7099a1c6da09e7b36327efca84e2ab606c596a009928d95387ac1cf79ae31df8b9ded35b10538e7694dfcfbdef9878a933f7eeed1fa461f2af51f867a37c37d02c132f08e928012800b3137845dd8260c4efcf668279a027548cfa46ea057c9dc47c28d56ffccc559c32e9b4768eef9db59d4b99d28fd1f1d8ef64acd0db41bea6dc498d0929ab3ef82b92b7df4cc10a3a0a359e947a71e8a20302ae6eec47e214cfb5b81ac9b16cc97d9b70749fb3aa386151ff29414590e7d63f4fa0c40c2d56483bdddf7894b2bcf597106c260b9ed72ad88c1c8bf6c782b3314b0cfd1ef30f974d05279ba45ab22adcfdab53766166479abfc56ea51a2fdcd28290806b15d39b2d0dd6209517ad2ecd74ebb83b3a9644e5a20f9533b0987afc3f4384ea3686622cd821d967f856d9798c89da014b71e1fd624a9504309b0cdfd66d3e316b100ad14e8aeeda632cb2b8383520dd1e5b3d3854312bfc4922d295322a5ea2415026a4956c100b9945be2c5882674c32713ac3a5a996aac3e5221067e503aa4ef8df630c5f4803f9fef82e689a9e5e76303f9c8c822842219db161f64ce1ee47eb558c264d37ab0c4ca53ac8d7bc907849cb47628a2f19e802862be5d9be621facf8712826418e8bfe0a34cd9bde681a1173480cb2922b2ff4925bdcac1acf19aea3ae76275f1954b92b24e897c5cdb8770f4f7b617ee5261b53766ab4"
]
}
Response
{
"type": "create_raw_transaction",
"txouts": // Array of newly created outputs hashes
[
"output_hash", // Hash of output in HEX
],
"data": "12d...01" // Transaction data serialized in protobuf and HEX encoded.
}
Response example
{
"type": "create_raw_transaction",
"txouts": [
"b6cfc6222d0bc0e7b5bcca0d7ef11af42474b207c8f598db9d7848391f8587fb"
],
"data": "12d2010a220a2033a3362aa631a9e6bff4d7c492c97112e0699917f9c3a236711ed3cb3f7281f3123912370a240a220a20908b184691aba82a1c757760f6a1ffba2d43fd537cd358cec1eb596f733e413910bca3b9e2b9a78fa0d901188088debe011a220a20f12eea29dd6f2aab5abc362bad4260e54ee7a57cf32e0c18e7918ab4060ea8022080c2d72f2a480a220a20623d503d4dd8fdaed3b891d63f3fedd09e044d10443bb92c308577bbd1dae20c12220a2094862dd404a2527afd9bdacdf788f7cc00e05429bf8f004161fab50ac310a401"
}
Broadcasting transaction
Request
{
"type": "broadcast_transaction",
"txouts": [
"output_hash",.. // HEX represented Hash of transaction output.
]
"data": "hex", // HEX represented, protobuf encoded tx data that is returned in create_raw_transaction response.
}
Request example
{
"type": "broadcast_transaction",
"data": "12cf010a220a20d73728ef7c62e2b1e53fdfb22d689c73ee1d4c3d6fbd9a3015c70b7254f830be123812360a240a220a20d6fd504ef470d801e2810ffa32aeaca08bbf92c609f5dd4ca4010ce280c02f7410d3d09afd91c7edbefc0118b0dcb80b1a220a20000000000000000000000000000000000000000000000000000000000000000020e8072a480a220a20e894a0f3918a045bf38f02db081dbb9ad23fb23cc73850db9a75c95b2627ad0c12220a20020ff98a4ecf4251955c1ffc6ff9d18a2b96cfdd1a8be3973400eaca128e0824""
}
Response
{
"type": "broadcast_transaction",
"hash": "output_hash", // HEX represented hash of output (UTXO ID)
"status": {
"status": "status" // Status of processing (accepted/created/prepared/rejected)
}
}
status `rejected` mean that transaction was not processed.
{
"type": "broadcast_transaction",
"hash": "6dd4d515d5b1061c00f8dc2c549faa4ed6db8f1736a5fffa873f95a7dd7fe11d",
"status": {
"status": "accepted"
}
}