Skip to main content

Sending transactions

info

This flow is also described in the Construction API Overview article in the official Rosetta documentation.

The steps needed to send payment in MINA token are following:

  1. Given a key pair, derive the account indentifier using /construction/derive endpoint
  2. Call /construction/preprocess and /construction/metadata to construct parameters for /construction/payloads request
  3. Create an unsigned transaction blob using construction/payloads endpoint
  4. Call construction/parse (optional) to check if the unsigned transaction does what you expect
  5. Use detached signer to sign the transaction
  6. Call construction/combine to generate signed blob to be sent via /construction/submit endpoint
  7. Call construction/parse again (optional) to confirm correctness of the signed transaction
  8. Get a future transaction hash using /construction/hash enpoint
  9. Submit the signed transaction blob via /construction/submit endpoint

For ease of readability, this sample implementation skips the sanity checks (steps 4 and 7) and combines steps 2 and 3 in a single tx_payloads function call.

Before running this sample:

  • Make sure you followed Offline signer tool article and generated a key pair
  • Send some test funds on the account you've generated.

The implementation is as follows:

def withdrawal_flow(vault_keypair, dest_address, value_nano, fee_nano=None):
"""
Full withdrawal flow example (without sanity check)
If fee_nano is None - fee will be suggested by Rosetta API response
"""

vault_pubkey = vault_keypair["public"]
vault_private_key = vault_keypair["private"]

# derive vault address
derive_response = derive_account_identifier(vault_pubkey)
vault_address = derive_response["account_identifier"]["address"]

# get transfer payload to sign
payloads_response = tx_payloads(
vault_pubkey, vault_address, dest_address, fee_nano, value_nano)

# sign transfer payload
signature = sign_transaction(
SIGNER_PATH,
vault_private_key,
payloads_response["unsigned_transaction"])

# get signed transaction blob
combine_response = tx_combine(vault_pubkey, payloads_response, signature)
signed_transaction_blob = combine_response['signed_transaction']

# sanity check may be performed here
# for that - use tx_parse function output
# to doublecheck it corresponds what you want to do
# parsed_tx = tx_parse(signed_transaction_blob, True)

# get future transaction hash
tx_hash_response = tx_hash(signed_transaction_blob)
future_tx_hash = tx_hash_response['transaction_identifier']['hash']

# submit transaction. this call will fail if tx is not in mempool
tx_submit(signed_transaction_blob)

# wait for transaction confirmation:
# for that, track blocks until we meet our transaction in the last one
latest_block = network_status()["current_block_identifier"]["index"]
while True:
# check if our transaction exists in the latest block
txs = wait_for_block(latest_block)['block']['transactions']
hashes = [tx['transaction_identifier']['hash'] for tx in txs]
if future_tx_hash in hashes:
break
latest_block += 1

return future_tx_hash