web3-core#TransactionReceipt TypeScript Examples

The following examples show how to use web3-core#TransactionReceipt. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: test-contract-error.ts    From moonbeam with GNU General Public License v3.0 6 votes vote down vote up
describeDevMoonbeamAllEthTxTypes("Contract loop error", (context) => {
  it("should fail with OutOfGas on infinite loop transaction", async function () {
    const { contract, rawTx } = await createContract(context, "InfiniteContract");
    const infiniteTx = await createContractExecution(
      context,
      {
        contract,
        contractCall: contract.methods.infinite(),
      },
      { nonce: 1 }
    );

    const { txResults } = await context.createBlock({
      transactions: [rawTx, infiniteTx],
    });

    const receipt: TransactionReceipt = await context.web3.eth.getTransactionReceipt(
      txResults[1].result
    );
    expect(receipt.status).to.eq(false);
  });
});
Example #2
Source File: test-gas-estimation.ts    From moonbeam with GNU General Public License v3.0 6 votes vote down vote up
describeDevMoonbeamAllEthTxTypes("Estimate Gas - Supplied estimate is sufficient", (context) => {
  it("should estimate sufficient gas for creation", async function () {
    const contract = await getCompiled("Incrementer");
    // ask RPC for an gas estimate of deploying this contract
    const estimate = await context.web3.eth.estimateGas({
      from: GENESIS_ACCOUNT,
      data: contract.byteCode,
    });

    // attempt a transaction with our estimated gas
    const { rawTx } = await createContract(context, "Incrementer", { gas: estimate });
    const { txResults } = await context.createBlock({ transactions: [rawTx] });
    const receipt: TransactionReceipt = await context.web3.eth.getTransactionReceipt(
      txResults[0].result
    );

    // the transaction should succeed because the estimate should have been sufficient
    expect(receipt.status).to.equal(true);
  });
});
Example #3
Source File: index.ts    From index-ui with MIT License 6 votes vote down vote up
waitTransaction = async (provider: provider, txHash: string) => {
  const web3 = new Web3(provider)
  let txReceipt: TransactionReceipt | null = null
  while (txReceipt == null) {
    txReceipt = await web3.eth.getTransactionReceipt(txHash)
    await sleep(2000)
  }
  return txReceipt.status
}
Example #4
Source File: contracts.ts    From moonbeam with GNU General Public License v3.0 6 votes vote down vote up
// Deploy and instantiate a contract with manuel seal
export async function deployContractManualSeal(
  web3: Web3,
  contractByteCode: string,
  contractABI: AbiItem[],
  account: string = GENESIS_ACCOUNT,
  privateKey: string = GENESIS_ACCOUNT_PRIVATE_KEY
): Promise<Contract> {
  const tx = await web3.eth.accounts.signTransaction(
    {
      from: account,
      data: contractByteCode,
      value: "0x00",
      gasPrice: 1_000_000_000,
      gas: "0x100000",
    },
    privateKey
  );
  await customWeb3Request(web3, "eth_sendRawTransaction", [tx.rawTransaction]);
  let rcpt: TransactionReceipt = await web3.eth.getTransactionReceipt(tx.transactionHash);
  return new web3.eth.Contract(contractABI, rcpt.contractAddress);
}
Example #5
Source File: load-gas-loop.ts    From moonbeam with GNU General Public License v3.0 6 votes vote down vote up
callContract = async (loopCount: number) => {
  const contract = new web3.eth.Contract(contractAbi, contractAddress);

  const encoded = await contract.methods.big_loop(loopCount).encodeABI();

  const tx = await web3.eth.accounts.signTransaction(
    {
      from: deployer.address,
      to: contractAddress,
      data: encoded,
      gasPrice: web3.utils.toWei("1", "Gwei"),
      gas: 21829 + 381 * loopCount,
      nonce: nonce++,
    },
    deployer.privateKey
  );

  const result = await customRequest("eth_sendRawTransaction", [tx.rawTransaction]);
  if (result.error) {
    console.error(result.error);
    throw new Error(`Error calling contract!`);
  }

  console.log(`Transaction for Loop count ${loopCount} sent: ${tx.transactionHash}`);
  const startTime = Date.now();
  while (Date.now() - startTime < 60000) {
    let rcpt: TransactionReceipt = await web3.eth.getTransactionReceipt(tx.transactionHash);
    if (rcpt) {
      console.log(`Loop count ${loopCount} - block #${rcpt.blockNumber} (${rcpt.blockHash})`);
      return;
    }
    await new Promise((resolve) => {
      setTimeout(resolve, 2000);
    });
  }
  throw new Error("Failed to verify contract call (timeout)");
}
Example #6
Source File: to-promises.ts    From ethereum-sdk with MIT License 6 votes vote down vote up
export function toPromises(promiEvent: PromiEvent<any>) {
	return {
		hash: new Promise<string>((resolve, reject) => {
			promiEvent.on("error", reject)
			promiEvent.on("transactionHash", resolve)
		}),
		receipt: new Promise<TransactionReceipt>((resolve, reject) => {
			promiEvent.on("error", reject)
			promiEvent.on("receipt", resolve)
		}),
	}
}
Example #7
Source File: index.ts    From ethereum-sdk with MIT License 6 votes vote down vote up
constructor(
		private readonly receipt: Promise<TransactionReceipt>,
		public readonly hash: Word,
		public readonly data: Binary,
		public readonly nonce: number,
		public readonly from: Address,
		public readonly to?: Address
	) {
	}
Example #8
Source File: reducer.ts    From luaswap-interface with GNU General Public License v3.0 5 votes vote down vote up
receiveTxReceipt = (txHash: string, receipt: TransactionReceipt): ReceiveTxReceiptAction => ({
  type: RECEIVE_TX_RECEIPT,
  txHash,
  receipt
})
Example #9
Source File: EthereumService.ts    From tatum-blockchain-connector with MIT License 5 votes vote down vote up
public abstract getTransaction(hash: string, testnet?: boolean): Promise<Transaction & TransactionReceipt>
Example #10
Source File: app.service.ts    From tatum-blockchain-connector with MIT License 5 votes vote down vote up
public getTransaction(
    hash: string,
    testnet?: boolean,
  ): Promise<Transaction & TransactionReceipt> {
    return Promise.resolve(undefined);
  }
Example #11
Source File: uniswap-contract-strongly-typed-example.ts    From ethereum-abi-types-generator with MIT License 5 votes vote down vote up
/**
   * Make the trade encoding the data and sending the transaction
   * @param ethAmount The eth amount
   * @param minTokens The min tokens
   */
  public async tradeWithBuildingTransactionConfig(
    ethAmount: BigNumber,
    minTokens: BigNumber
  ): Promise<string> {
    const exchangeAddress = await this.getExchangeAddress(
      AbiExamples.funContractAddress
    );

    const exchangeContract = this.getExchangeContractForTokenByExchangeAddress(
      exchangeAddress
    );

    // you can build the data up like this if you want?
    const data = exchangeContract.methods
      .ethToTokenSwapInput(
        web3.utils.toHex(minTokens as any),
        this.generateTradeDeadlineUnixTime()
      )
      .encodeABI();

    this.logUniswapOutput(`Encoded abi and generated data ${data}`);
    // Uniswap class - Encoded abi and generated data 0xf39b5b9b0000000000000000000000000000000000000000000000000000000000000384000000000000000000000000000000000000000000000000000000005eac075c

    // and build up a `TransactionConfig`
    const transactionConfig: TransactionConfig = {
      from: mockEthereumAddress,
      to: exchangeAddress,
      data,
      value: web3.utils.toWei(ethAmount.toFixed(), 'ether'),
      gas: web3.utils.numberToHex(21912),
    };

    this.logUniswapOutput(
      `Transaction config built up ${JSON.stringify(transactionConfig)}`
    );
    // Uniswap class - Transaction config built up {"from":"0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b","to":"0x60a87cC7Fca7E53867facB79DA73181B1bB4238B","data":"0xf39b5b9b0000000000000000000000000000000000000000000000000000000000000384000000000000000000000000000000000000000000000000000000005eac075c","value":"10000000000000000"}

    // obviously if your using a wallet provider do your standard
    // web3.eth.sendTransaction :)
    const signedTransaction = await web3.eth.accounts.signTransaction(
      transactionConfig,
      '0x0123456789012345678901234567890123456789012345678901234567890123'
    );

    // and send it through web3...
    // not actually going to send here as we have no private keys
    // but if you were using metamask or other wallet providers it would trigger a signer
    // this is merely an example
    const transactionReceipt = (await web3.eth.sendSignedTransaction(
      signedTransaction.rawTransaction!
    )) as TransactionReceipt;

    this.logUniswapOutput(
      `Transaction sent ${transactionReceipt.transactionHash}`
    );
    // Uniswap class - Transaction sent 0x972c2155137efecb126dc5f4f72fb451753eab8f5fce45aad73e00861ae27fe1

    return transactionReceipt.transactionHash;
  }
Example #12
Source File: loadIncomingTransactions.ts    From multisig-react with MIT License 5 votes vote down vote up
batchIncomingTxsTokenDataRequest = (txs: IncomingTxServiceModel[]) => {
  const batch = new web3ReadOnly.BatchRequest()
  const { nativeCoin } = getNetworkInfo()

  const whenTxsValues = txs.map((tx) => {
    const methods = [
      'symbol',
      'decimals',
      { method: 'getTransaction', args: [tx.transactionHash], type: 'eth' },
      { method: 'getTransactionReceipt', args: [tx.transactionHash], type: 'eth' },
    ]

    return generateBatchRequests<
      [
        IncomingTxServiceModel,
        string | undefined,
        string | undefined,
        Transaction | undefined,
        TransactionReceipt | undefined,
      ]
    >({
      abi: ALTERNATIVE_TOKEN_ABI as AbiItem[],
      address: tx.tokenAddress,
      batch,
      context: tx,
      methods,
    })
  })

  batch.execute()

  return Promise.all(whenTxsValues).then((txsValues) =>
    txsValues.map(([tx, symbolFetched, decimals, ethTx, ethTxReceipt]) => {
      let symbol = symbolFetched
      if (!symbolFetched) {
        symbol = isENSContract(tx.tokenAddress) ? 'ENS' : nativeCoin.symbol
      }
      return [
        tx,
        symbol,
        decimals ? decimals : nativeCoin.decimals,
        new bn(ethTx?.gasPrice ?? 0).times(ethTxReceipt?.gasUsed ?? 0),
      ]
    }),
  )
}
Example #13
Source File: reducer.ts    From PolkaBridge-Farming with MIT License 5 votes vote down vote up
receiveTxReceipt = (txHash: string, receipt: TransactionReceipt): ReceiveTxReceiptAction => ({
  type: RECEIVE_TX_RECEIPT,
  txHash,
  receipt,
})
Example #14
Source File: load-gas-loop.ts    From moonbeam with GNU General Public License v3.0 5 votes vote down vote up
deployContract = async () => {
  // 1M gas contract call (big_loop)
  const tokens = (await customRequest("eth_getBalance", [deployer.address])).result;
  nonce = (await customRequest("eth_getTransactionCount", [deployer.address])).result;
  console.log(`Using account ${deployer.address} [nonce: ${nonce}]: ${tokens} DEVs`);

  const code = await customRequest("eth_getCode", [contractAddress]);
  if (code.result != "0x") {
    console.log("Contract already deployed");
    return;
  }

  const tx = await web3.eth.accounts.signTransaction(
    {
      from: deployer.address,
      data: contractBytecode,
      value: "0x00",
      gasPrice: web3.utils.toWei("1", "Gwei"),
      gas: 172663,
      nonce: nonce++,
    },
    deployer.privateKey
  );
  const result = await customRequest("eth_sendRawTransaction", [tx.rawTransaction]);
  if (result.error) {
    console.error(`Error deploying contract!`);
    console.error(result.error);
    return;
  }
  console.log(`Transaction sent: ${tx.transactionHash}`);
  const startTime = Date.now();
  while (Date.now() - startTime < 40000) {
    let rcpt: TransactionReceipt = await web3.eth.getTransactionReceipt(tx.transactionHash);
    if (rcpt) {
      console.log(`Transaction done - block #${rcpt.blockNumber} (${rcpt.blockHash})`);
      return;
    }
    await new Promise((resolve) => {
      setTimeout(resolve, 2000);
    });
  }
  throw new Error("Failed to verify contract deployment (timeout)");
}
Example #15
Source File: test-log-filtering.ts    From moonbeam with GNU General Public License v3.0 5 votes vote down vote up
describeDevMoonbeamAllEthTxTypes("Log - Filter out non-matching", (context) => {
  let non_matching_cases = null;
  function getNonMatchingCases(receipt: TransactionReceipt) {
    return [
      // Non-existant address.
      {
        fromBlock: "0x0",
        toBlock: "latest",
        address: "0x0000000000000000000000000000000000000000",
      },
      // Non-existant topic.
      {
        fromBlock: "0x0",
        toBlock: "latest",
        topics: ["0x0000000000000000000000000000000000000000000000000000000000000000"],
      },
      // Existant address + non-existant topic.
      {
        fromBlock: "0x0",
        toBlock: "latest",
        address: receipt.contractAddress,
        topics: ["0x0000000000000000000000000000000000000000000000000000000000000000"],
      },
      // Non-existant address + existant topic.
      {
        fromBlock: "0x0",
        toBlock: "latest",
        address: "0x0000000000000000000000000000000000000000",
        topics: receipt.logs[0].topics,
      },
    ];
  }
  before("Setup: Create block with transfer", async () => {
    const { rawTx } = await createContract(context, "SingleEventContract", {
      from: GENESIS_ACCOUNT,
    });
    const { txResults } = await context.createBlock({ transactions: [rawTx] });
    const receipt = await context.web3.eth.getTransactionReceipt(txResults[0].result);
    non_matching_cases = getNonMatchingCases(receipt);
  });
  it("EthFilterApi::getFilterLogs - should filter out non-matching cases.", async function () {
    let create_filter;
    for (var item of non_matching_cases) {
      create_filter = await customWeb3Request(context.web3, "eth_newFilter", [item]);
      let poll = await customWeb3Request(context.web3, "eth_getFilterLogs", [create_filter.result]);
      expect(poll.result.length).to.be.eq(0);
    }
  });
  it("EthApi::getLogs - should filter out non-matching cases.", async function () {
    for (var item of non_matching_cases) {
      let request = await customWeb3Request(context.web3, "eth_getLogs", [item]);
      expect(request.result.length).to.be.eq(0);
    }
  });
});
Example #16
Source File: Open.tsx    From multisig-react with MIT License 4 votes vote down vote up
Open = (): React.ReactElement => {
  const [loading, setLoading] = useState(false)
  const [showProgress, setShowProgress] = useState(false)
  const [creationTxPromise, setCreationTxPromise] = useState<PromiEvent<TransactionReceipt>>()
  const [safeCreationPendingInfo, setSafeCreationPendingInfo] = useState<any>()
  const [safePropsFromUrl, setSafePropsFromUrl] = useState()
  const userAccount = useSelector(userAccountSelector)
  const dispatch = useDispatch()

  useEffect(() => {
    // #122: Allow to migrate an old Multisig by passing the parameters to the URL.
    const query = queryString.parse(window.location.search, { arrayFormat: 'comma' })
    const { name, owneraddresses, ownernames, threshold } = query
    if (validateQueryParams(owneraddresses, ownernames, threshold, name)) {
      setSafePropsFromUrl({
        name,
        ownerAddresses: owneraddresses,
        ownerNames: ownernames,
        threshold,
      } as any)
    }
  }, [])

  // check if there is a safe being created
  useEffect(() => {
    const load = async () => {
      const pendingCreation = await loadFromStorage<{ txHash: string }>(SAFE_PENDING_CREATION_STORAGE_KEY)
      if (pendingCreation && pendingCreation.txHash) {
        setSafeCreationPendingInfo(pendingCreation)
        setShowProgress(true)
      } else {
        setShowProgress(false)
      }
      setLoading(false)
    }

    load()
  }, [])

  const createSafeProxy = async (formValues?: any) => {
    let values = formValues

    // save form values, used when the user rejects the TX and wants to retry
    if (formValues) {
      const copy = { ...formValues }
      saveToStorage(SAFE_PENDING_CREATION_STORAGE_KEY, copy)
    } else {
      values = await loadFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY)
    }

    const promiEvent = createSafe(values, userAccount)
    setCreationTxPromise(promiEvent)
    setShowProgress(true)
  }

  const onSafeCreated = async (safeAddress): Promise<void> => {
    const pendingCreation = await loadFromStorage<{ txHash: string }>(SAFE_PENDING_CREATION_STORAGE_KEY)

    const name = getSafeNameFrom(pendingCreation)
    const ownersNames = getNamesFrom(pendingCreation)
    const ownerAddresses = getAccountsFrom(pendingCreation)
    const safeProps = await getSafeProps(safeAddress, name, ownersNames, ownerAddresses)

    await dispatch(addOrUpdateSafe(safeProps))

    removeFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY)
    const url = {
      pathname: `${SAFELIST_ADDRESS}/${safeProps.address}/balances`,
      state: {
        name,
        tx: pendingCreation?.txHash,
      },
    }

    history.push(url)
  }

  const onCancel = () => {
    removeFromStorage(SAFE_PENDING_CREATION_STORAGE_KEY)
    history.push({
      pathname: `${WELCOME_ADDRESS}`,
    })
  }

  const onRetry = async () => {
    const values = await loadFromStorage<{ txHash?: string }>(SAFE_PENDING_CREATION_STORAGE_KEY)
    delete values?.txHash
    await saveToStorage(SAFE_PENDING_CREATION_STORAGE_KEY, values)
    setSafeCreationPendingInfo(values)
    createSafeProxy()
  }

  if (loading || showProgress === undefined) {
    return <Loader size="md" />
  }

  return (
    <Page>
      {showProgress ? (
        <Opening
          creationTxHash={safeCreationPendingInfo?.txHash}
          onCancel={onCancel}
          onRetry={onRetry}
          onSuccess={onSafeCreated}
          submittedPromise={creationTxPromise}
        />
      ) : (
        <Layout onCallSafeContractSubmit={createSafeProxy} safeProps={safePropsFromUrl} />
      )}
    </Page>
  )
}
Example #17
Source File: Contracts.ts    From perpetual with Apache License 2.0 4 votes vote down vote up
private async _send( // tslint:disable-line:function-name
    method: ContractSendMethod,
    sendOptions: SendOptions = {},
  ): Promise<TxResult> {
    const {
      confirmations,
      confirmationType,
      gasMultiplier,
      ...txOptions
    } = sendOptions;

    if (!Object.values(ConfirmationType).includes(confirmationType)) {
      throw new Error(`Invalid confirmation type: ${confirmationType}`);
    }

    if (confirmationType === ConfirmationType.Simulate || !txOptions.gas) {
      const gasEstimate = await this.estimateGas(method, txOptions);
      txOptions.gas = Math.floor(gasEstimate * gasMultiplier);

      if (confirmationType === ConfirmationType.Simulate) {
        return {
          gasEstimate,
          gas: txOptions.gas,
        };
      }
    }

    const promi: PromiEvent<Contract> = method.send(this.toNativeSendOptions(txOptions) as any);

    let hashOutcome = OUTCOMES.INITIAL;
    let confirmationOutcome = OUTCOMES.INITIAL;

    let transactionHash: string;
    let hashPromise: Promise<string>;
    let confirmationPromise: Promise<TransactionReceipt>;

    if ([
      ConfirmationType.Hash,
      ConfirmationType.Both,
    ].includes(confirmationType)) {
      hashPromise = new Promise(
        (resolve, reject) => {
          promi.on('error', (error: Error) => {
            if (hashOutcome === OUTCOMES.INITIAL) {
              hashOutcome = OUTCOMES.REJECTED;
              reject(error);
              (promi as any).off();
            }
          });

          promi.on('transactionHash', (txHash: string) => {
            if (hashOutcome === OUTCOMES.INITIAL) {
              hashOutcome = OUTCOMES.RESOLVED;
              resolve(txHash);
              if (confirmationType !== ConfirmationType.Both) {
                (promi as any).off();
              }
            }
          });
        },
      );
      transactionHash = await hashPromise;
    }

    if ([
      ConfirmationType.Confirmed,
      ConfirmationType.Both,
    ].includes(confirmationType)) {
      confirmationPromise = new Promise(
        (resolve, reject) => {
          promi.on('error', (error: Error) => {
            if (
              confirmationOutcome === OUTCOMES.INITIAL
              && (
                confirmationType === ConfirmationType.Confirmed
                || hashOutcome === OUTCOMES.RESOLVED
              )
            ) {
              confirmationOutcome = OUTCOMES.REJECTED;
              reject(error);
              (promi as any).off();
            }
          });

          if (confirmations) {
            promi.on('confirmation', (confNumber: number, receipt: TransactionReceipt) => {
              if (confNumber >= confirmations) {
                if (confirmationOutcome === OUTCOMES.INITIAL) {
                  confirmationOutcome = OUTCOMES.RESOLVED;
                  resolve(receipt);
                  (promi as any).off();
                }
              }
            });
          } else {
            promi.on('receipt', (receipt: TransactionReceipt) => {
              confirmationOutcome = OUTCOMES.RESOLVED;
              resolve(receipt);
              (promi as any).off();
            });
          }
        },
      );
    }

    if (confirmationType === ConfirmationType.Hash) {
      return this.normalizeResponse({ transactionHash });
    }

    if (confirmationType === ConfirmationType.Confirmed) {
      return confirmationPromise;
    }

    return this.normalizeResponse({
      transactionHash,
      confirmation: confirmationPromise,
    });
  }
Example #18
Source File: actions.ts    From moonbeam with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Non-exported function that takes fundsRequests from the pendingQueue and
 * resolves them with a series of different worker addresses to avoid a
 * nonce conflict.
 * @param web3Api Instance of the web3 API connected to the chain endpoint
 * @param workers Array of worker accounts that will be used to sign the transfer txs
 * @param pendingQueue Queue of tasks
 * @param discordUserReceivers Map with the timestamp of the last received request of
 * a discord user
 * @param addressReceivers Map with the timestamp of the last received request of an
 * address
 */
async function resolveFundsRequests(
  web3Api: Web3,
  workers: WorkerAccount[],
  pendingQueue: FundsRequest[],
  discordUserReceivers: Receivers,
  addressReceivers: Receivers
) {
  type TransferReceipts = {
    request: FundsRequest;
    receiptPromise: PromiEvent<TransactionReceipt>;
  };

  let transferReceipts: TransferReceipts[] = [];

  for (const worker of workers) {
    const workerBalance = BigInt(await web3Api.eth.getBalance(worker.address));
    const requiredBalance = params.TOKEN_COUNT * 10n ** TOKEN_DECIMAL + 21000n;

    // if the worker doesn't have enough balance, skip before
    // consuming a task from the queue. This way workers
    // at the end of the list, which are not used that often,
    // will resolve the requests until this worker is funded again
    if (workerBalance < requiredBalance) continue;

    const fundsRequest = pendingQueue.pop();

    // if the fr is undefined, it means that the queue is empty
    if (!fundsRequest) continue;

    let waitForReceipt = new Promise(async (resolve) => {
      await web3Api.eth
        .sendSignedTransaction(
          (
            await web3Api.eth.accounts.signTransaction(
              {
                value: `${params.TOKEN_COUNT * 10n ** TOKEN_DECIMAL}`,
                gasPrice: params.GAS_PRICE.toString(),
                gas: "21000",
                to: fundsRequest.address,
              },
              worker.privateKey
            )
          ).rawTransaction
        )
        .on("confirmation", (nbrOfBlocks, receipt) => {
          // wait for 1 block confirmation to avoid Low Priority failure on next transaction
          if (nbrOfBlocks >= 1) {
            resolve(receipt);
          }
        });
    });

    transferReceipts.push({
      request: fundsRequest,
      receiptPromise: waitForReceipt,
    });
  }

  for (const tr of transferReceipts) {
    try {
      const receipt = await tr.receiptPromise;
      const accountBalance = BigInt(await web3Api.eth.getBalance(tr.request.address));

      const fundsTransactionEmbed = new MessageEmbed()
        .setColor(EMBED_COLOR_CORRECT)
        .setTitle("Transaction of funds")
        .addField("To account", tr.request.address, true)
        .addField("Amount sent", `${params.TOKEN_COUNT} DEV`, true)
        .addField("Transaction Hash", `${receipt.transactionHash}`, false)
        .addField("Current account balance", `${accountBalance / 10n ** TOKEN_DECIMAL} DEV`, false)
        .setFooter(
          `Funds transactions are limited to once every ${params.FAUCET_SEND_INTERVAL} hour(s)`
        );

      tr.request.discordChannel.send(fundsTransactionEmbed);
    } catch (error) {
      // rollback the update of user/address last funds request
      discordUserReceivers[tr.request.discordUser] = tr.request.prevTimestampUser;
      addressReceivers[tr.request.address] = tr.request.prevTimestampAddress;

      // alert in channel
      const errorEmbed = new MessageEmbed()
        .setColor(EMBED_COLOR_ERROR)
        .setTitle("Could not submit the transaction")
        .setFooter(
          "The transaction of funds could not be submitted. " +
            "Please, try requesting funds again or contact an admin."
        );

      // send message
      tr.request.discordChannel.send(errorEmbed);

      console.log(new Date().toISOString(), "ERROR_2_1", error.stack || error);
    }
  }
}