Appendix

/*
 *  Removes '0x' from hexadecimal numbers if they have it
 */
function HexFix(word) {
  if (typeof word === 'string') {
    var Word = word;
    if (word.startsWith('0x')) {
      Word = Word.slice(2);
    }
    return Word;
  }
  return '';
}
/*
 * Retrieves a Wallet
 * 
 * Blockchain: Blockchain where the wallet is registered
 * Address: Wallet Address
 */
function GetWallet(Blockchain, Address) {
  let data = {
    "Blockchain": HexFix(Blockchain),
    "Address": HexFix(Address),
    "Version": Version
  };

  return fetch(NAG_URL + 'Circular_GetWallet_', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data)
  })
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .catch((error) => {
    console.error('Error:', error);
  });
}
/*
 * Retrieves the balance of a specified asset in a Wallet
 * 
 * Blockchain: Blockchain where the wallet is registered
 * Address: Wallet address
 * Asset: Asset Name (example 'CIRX')
 */
function GetWalletBalance(Blockchain, Address, Asset) {
  let data = {
    "Blockchain": HexFix(Blockchain),
    "Address": HexFix(Address),
    "Asset": Asset,
    "Version": Version
  };

  return fetch(NAG_URL + 'Circular_GetWalletBalance_', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data)
  })
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .catch((error) => {
    console.error('Error:', error);
  });
}
/*
 * Retrieves the Nonce of a Wallet
 * 
 * Blockchain: Blockchain where the wallet is registered
 * Address: Wallet address
 */
function GetWalletNonce(Blockchain, Address) {
  let data = {
    "Blockchain": HexFix(Blockchain),
    "Address": HexFix(Address),
    "Version": Version
  };

  return fetch(NAG_URL + 'Circular_GetWalletNonce_', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data)
  })
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .catch((error) => {
    console.error('Error:', error);
  });
}
/*
 * Resolves the domain name, returning the wallet address
 * 
 * A single wallet can have multiple domain associations
 * 
 * Blockchain : Blockchain where the domain and wallet are registered
 * Name: Domain Name
 */
function GetDomain(Blockchain, Name) {
  let data = {
    "Blockchain": HexFix(Blockchain),
    "Domain": Name,
    "Version": Version
  };

  return fetch(NAG_URL + 'Circular_ResolveDomain_', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data)
  })
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .catch((error) => {
    console.error('Error:', error);
  });
}
/*
 * Retrieve a desired block
 * 
 * Blockchain: Blockchain where to search the block
 * Num: Block number
 */
async function GetBlock(Blockchain, Num) {
  let data = {
    "Blockchain": HexFix(Blockchain),
    "BlockNumber": String(Num),
    "Version": Version
  };

  return fetch(NAG_URL + 'Circular_GetBlock_', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data)
  })
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .catch((error) => {
    console.error('Error:', error);
  });
}
/*
 * Searches a Transaction by its ID
 * 
 * The transaction will be searched initially between the pending transactions
 * and then in the blockchain.
 * 
 * Blockchain: Blockchain where to search the transaction
 * TxID: Transaction ID
 * Start: Starting block
 * End: End block
 * If End = 0, Start indicates the number of blocks starting from the
 * last block minted.
 */
async function GetTransactionbyID(Blockchain, TxID, Start, End) {
  try {
    let data = {
      "Blockchain": HexFix(Blockchain),
      "ID": HexFix(TxID),
      "Start": String(Start),
      "End": String(End),
      "Version": Version
    };

    const response = await fetch(NAG_URL + 'Circular_GetTransactionbyID_', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    });

    if (!response.ok) {
      throw new Error('Network response was not ok');
    }

    return response.json();

  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
}
/*
 * Submits a transaction to a desired blockchain
 * 
 * ID: Transaction ID
 * From: Transaction Sender
 * To: Transaction recipient
 * Timestamp: Formatted Timestamp YYYY:MM:DD-hh:mm:ss
 * Type: Transaction Type (Refer to Documentation)
 * Payload: Transaction payload
 * Nonce: Wallet nonce
 * Signature: Transaction Signature
 * Blockchain: Blockchain where the transaction will be submitted
 */
async function SendTransaction(ID, From, To, Timestamp, Type, Payload, Nonce, Signature, Blockchain) {
  let data = {
    "ID": HexFix(ID),
    "From": HexFix(From),
    "To": HexFix(To),
    "Timestamp": Timestamp,
    "Payload": String(HexFix(Payload)),
    "Nonce": String(Nonce),
    "Signature": HexFix(Signature),
    "Blockchain": HexFix(Blockchain),
    "Type": Type,
    "Version": Version
  };

  try {
    const response = await fetch(NAG_URL + 'Circular_AddTransaction_', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data)
    });

    const text = await response.text(); // The response text from the server

    // Check if the response is in JSON format
    try {
      const jsonResponse = JSON.parse(text);
      return jsonResponse; // Return the parsed JSON
    } catch (e) {
      // If the response is not in JSON format, return it as-is with status
      return { status: response.status, message: text };
    }

  } catch (error) {
    console.error('Error:', error);
    // Return a custom JSON object indicating the error
    return { success: false, message: 'Server unreachable', error: error.toString() };
  }
}
var intervalSec = 15;

/*
 * Recursive transaction finality polling
 * Will search a transaction every intervalSec seconds with a desired timeout.
 * 
 * Blockchain: Blockchain where the transaction was submitted
 * TxID: Transaction ID
 * timeoutSec: Waiting timeout
 */
function GetTransactionOutcome(Blockchain, TxID, timeoutSec) {
  return new Promise((resolve, reject) => {
    const startTime = Date.now();
    const interval = intervalSec * 1000; // Convert seconds to milliseconds
    const timeout = timeoutSec * 1000;   // Convert seconds to milliseconds

    const checkTransaction = () => {
      const elapsedTime = Date.now() - startTime;
      console.log('Checking transaction...', { elapsedTime, timeout });

      if (elapsedTime > timeout) {
        console.log('Timeout exceeded');
        reject(new Error('Timeout exceeded'));
        return;
      }

      GetTransactionbyID(Blockchain, TxID, 0, 10)
        .then(data => {
          console.log('Data received:', data);
          if (data.Result === 200 && data.Response !== 'Transaction Not Found' && data.Response.Status !== 'Pending') {
            resolve(data.Response); // Resolve if transaction is found and not 'Transaction Not Found'
          } else {
            console.log('Transaction not found, polling again...');
            setTimeout(checkTransaction, interval); // Continue polling
          }
        })
        .catch(error => {
          console.log('Error fetching transaction:', error);
          reject(error); // Reject on error
        });
    };

    setTimeout(checkTransaction, interval); // Start polling
  });
}

Last updated