Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 5 additions & 19 deletions examples/sendTransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,10 @@ int main() {
const auto timeoutBlockHeight =
recentBlockHash.lastValidBlockHeight +
mango_v3::MAXIMUM_NUMBER_OF_BLOCKS_FOR_TRANSACTION;
uint8_t timeout = 15; // add a 15 sec timeout
while (timeout > 0) {
// Check if we are past validBlockHeight
auto currentBlockHeight =
connection.getBlockHeight(solana::Commitment::CONFIRMED);
if (timeoutBlockHeight <= currentBlockHeight) {
spdlog::error("Timed out for txid: {}, current BlockHeight: {}", b58Sig,
currentBlockHeight);
return EXIT_FAILURE;
}
const auto res = connection.getSignatureStatus(b58Sig).value;
if (res.has_value() && !res.value().err.has_value() &&
res.value().confirmationStatus == "finalized") {
break;
}
timeout--;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
bool confirmed = false;
confirmed =
connection.confirmTransaction(b58Sig, solana::Commitment::FINALIZED,140);
if (confirmed) return EXIT_SUCCESS;

return EXIT_SUCCESS;
return EXIT_FAILURE;
}
9 changes: 8 additions & 1 deletion include/solana.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const std::string MEMO_PROGRAM_ID =
"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
const std::string MAINNET_BETA = "https://api.mainnet-beta.solana.com";
const std::string DEVNET = "https://api.devnet.solana.com";
const int MAXIMUM_NUMBER_OF_BLOCKS_FOR_TRANSACTION = 152;

struct PublicKey {
static const auto SIZE = crypto_sign_PUBLICKEYBYTES;
Expand Down Expand Up @@ -188,7 +189,7 @@ struct SignatureStatus {
std::optional<std::string> err = std::nullopt;
/** cluster confirmation status, if data available. Possible responses:
* `processed`, `confirmed`, `finalized` */
std::string confirmationStatus;
Commitment confirmationStatus;
};

/**
Expand Down Expand Up @@ -542,6 +543,12 @@ class Connection {
uint64_t getBlockHeight(
const Commitment &commitment = Commitment::FINALIZED) const;

/**
* Returns of the current Transaction has been confirmed or not
*/
bool confirmTransaction(std::string transactionSignature,
Commitment confirmLevel, uint16_t timeout=200) const;

/**
* Fetch the current statuses of a batch of signatures
*/
Expand Down
23 changes: 23 additions & 0 deletions lib/solana.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#include <cpr/cpr.h>
#include <sodium.h>

#include <chrono>
#include <cstdint>
#include <iterator>
#include <optional>
#include <ostream>
#include <solana.hpp>
#include <string>
#include <thread>
#include <vector>

#include "base64.hpp"
Expand Down Expand Up @@ -501,6 +503,27 @@ Connection::getSignatureStatus(const std::string &signature,
return {res.context, res.value[0]};
}

bool Connection::confirmTransaction(std::string transactionSignature,
Comment thread
Lioncat2002 marked this conversation as resolved.
Commitment confirmLevel,
uint16_t retries) const {
const auto timeoutBlockheight =
getLatestBlockhash(confirmLevel).lastValidBlockHeight +
solana::MAXIMUM_NUMBER_OF_BLOCKS_FOR_TRANSACTION;
while (retries > 0) {
auto currentBlockheight = getBlockHeight(confirmLevel);
const auto res = getSignatureStatus(transactionSignature, true).value;
Comment thread
Lioncat2002 marked this conversation as resolved.
if (timeoutBlockheight <= currentBlockheight)
throw std::runtime_error("Transaction timeout");
if (res.has_value() && res.value().confirmationStatus == confirmLevel) {
return true;
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));

retries--;
}
return false;
}

Version Connection::getVersion() const {
// create request
json params = {};
Expand Down
21 changes: 7 additions & 14 deletions tests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,26 +55,19 @@ TEST_CASE("Simulate & Send Transaction") {
CHECK_EQ(transactionSignature, b58Sig);
}

TEST_CASE("Request Airdrop") {
TEST_CASE("Request Airdrop & Confirm Transaction") {
const solana::Keypair keyPair = solana::Keypair::fromFile(KEY_PAIR_FILE);
const auto connection = solana::rpc::Connection(solana::DEVNET);
// request Airdrop
const auto prev_sol = connection.getBalance(keyPair.publicKey);
const auto signature = connection.requestAirdrop(keyPair.publicKey, 50001);
uint8_t timeout = 15;
// check signature status
// this is a temporary fix. This will be changed to the confirmTransaction
// function call once it gets implemented
while (timeout > 0) {
const auto res = connection.getSignatureStatus(signature, true).value;
if (res.has_value() && res.value().confirmationStatus == "finalized") {
break;
}
timeout--;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// check if balance is updated after status is finalized
uint8_t retries = 140;
// using confirmTransaction to check if the airdrop went through
bool confirmed = false;
confirmed = connection.confirmTransaction(
signature, solana::Commitment::FINALIZED, retries);
const auto new_sol = connection.getBalance(keyPair.publicKey);
CHECK_EQ(confirmed, true);
CHECK_GT(new_sol, prev_sol);
}

Expand Down