After several checks made with the help of the community here on Stack-Exchange, I was able to move forward with my problem.

Now I have reached the point that the transactions are not sent even though the wallet is active and connected correctly.

Checking the logs of my Monero full-node on Testnet, when I try to send the transaction, I get this error log:

2023-08-19 16:46:23.292 E Key image already spent in blockchain: b561176c54524cde8f5311d8304f45a2fae1c48395a0502cc30e48a86df6d2c7
2023-08-19 16:46:23.293 I tx used wrong inputs, rejected
2023-08-19 16:46:23.293 E Transaction verification failed: <1291ff117cab830744fc7f7e401046656c623db1e04a718fd5b6dbbeced27d64>
2023-08-19 16:46:23.294 W [on_send_raw_tx]: tx verification failed: double spend, invalid input

Apparently the transaction uses wrong inputs, but I can't figure out why.

Below is the complete js code using the monero-javascript library:

async function sendTransaction(toAddress, amount) {
    const daemon = await monerojs.connectToDaemonRpc("http://localhost:28081");    
    let wallet = await MoneroWalletFull.openWallet({
        path: `<mypath>`,
        password: password,
        networkType: MoneroNetworkType.TESTNET,
        serverUri: ""

      daemonHeight = await daemon.getHeight();
      let sync = await syncWallet(wallet, daemonHeight)
      console.log("Wallet opened"+ sync);
      walletHeight = await wallet.getHeight();
      console.error("Wallet height:", walletHeight);
      console.error("Daemon height:", daemonHeight);
      let isSynced = walletHeight === daemonHeight;
      if (isSynced) {
        console.log("Wallet is synchronized with the daemon");
      } else {
        console.error("Wallet is not synchronized with the daemon");
        console.error("Wallet height:", walletHeight);
        console.error("Daemon height:", daemonHeight);
    const balance = await getBalance(wallet);
    if (balance < amount) {
      throw new Error('Insufficient balance');
    let unlockedBalance = await wallet.getUnlockedBalance(0, 0)
    let amountInAtomic = ATOMICUNIT_PER_XMR * amount
        throw new Error("Error no unlocked balance")
    const tx = await wallet.createTx({
      accountIndex: 0,
      address: toAddress,
      amount: amountInAtomic.toString(),
    let hash = tx.state.hash
    return hash

async function syncWallet(wallet, height) {
  try {
    const syncResult = await wallet.sync(height);
    console.log('Sync progress:', syncResult);
    await wallet.save()
    if (!(await wallet.isSynced())) {
      throw new Error("Errore durante la sincronizzazione!")
    else return true
  } catch (error) {
    throw new Error("Error during sync of the wallet: " + error.message);
async function getBalance(wallet) {
      const balance = parseFloat((await wallet.getBalance(0)).toString()) / ATOMICUNIT_PER_XMR
      const unlockedBalance = await getUnlockedBalance(wallet)
      let balances= {balance,unlockedBalance}
      return balances
async function getUnlockedBalance(wallet) {
      const balance = parseFloat((await wallet.getUnlockedBalance(0, 0)).toString()) / ATOMICUNIT_PER_XMR
      return balance

Could you help me understand how to solve this error by providing me code examples or useful links to solve this problem?

  • "Below is the complete js code using the monero-javascript library", except it's not. There isn't a library method named syncWallet so where is that? You have to have fully scanned/synced the wallet with the blockchain.
    – jtgrassie
    Aug 25, 2023 at 2:43
  • The function simply calls the sync() method. I've updated the post so you can see it.
    – AlexCav
    Aug 25, 2023 at 13:12
  • If you read the docs you'll see your usage of sync is incorrect. You have to a) sync/scan the blockchain from at least the height you received XMR and b) use a listener to know when it's complete.
    – jtgrassie
    Aug 25, 2023 at 13:18
  • Is there examples for the use of Listeners in the docs?
    – AlexCav
    Aug 25, 2023 at 13:27
  • In the README there's sample code
    – jtgrassie
    Aug 26, 2023 at 16:24


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.