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:

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
}