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:
- Given a key pair, derive the account indentifier using 
/construction/deriveendpoint - Call 
/construction/preprocessand/construction/metadatato construct parameters for/construction/payloadsrequest - Create an unsigned transaction blob using 
construction/payloadsendpoint - Call 
construction/parse(optional) to check if the unsigned transaction does what you expect - Use detached signer to sign the transaction
 - Call 
construction/combineto generate signed blob to be sent via/construction/submitendpoint - Call 
construction/parseagain (optional) to confirm correctness of the signed transaction - Get a future transaction hash using 
/construction/hashenpoint - Submit the signed transaction blob via 
/construction/submitendpoint 
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:
- TypeScript
 - Python
 
async function send(privateKey: string, to: string, valueNano: number, feeNano: number) {
  const publicKey = mina.derivePublicKey(privateKey)
  const publicKeyRaw = mina.publicKeyToRaw(publicKey)
  // get transfer payload to sign
  const payloadsResponse = await txPayloads(
    publicKeyRaw,
    publicKey,
    to,
    feeNano,
    valueNano,
  )
  // sign and combine transfer payload
  const combineResponse = await txCombine(payloadsResponse, privateKey)
  const blob = combineResponse.signed_transaction
  // // get future transaction hash
  const txHashResponse = await txHash(blob)
  const hash = txHashResponse.transaction_identifier.hash
  // submit transaction. this call will fail if tx is not in mempool
  await txSubmit(blob)
  // wait for transaction confirmation:
  // for that, track blocks until we meet our transaction in the last one
  let latestBlock = (await networkStatus()).current_block_identifier.index
  while (true) {
    // check if our transaction exists in the latest block
    const txs = (await waitForBlock(latestBlock)).block.transactions
    const hashes = txs.map((tx: any) => tx.transaction_identifier.hash)
    if (hashes.includes(hash)) {
      break
    }
    latestBlock += 1
  }
  return hash
}
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