Accept Direct Payments with Pay & Engine

Learn how to accept fiat and crypto from your customers with Pay and trigger Engine actions, like minting NFTs or transferring tokens to user wallets.

Requirements

Purchase Flow Overview

Before jumping in, it's important to understand the full system, from initial purchase to the eventual transfer of assets. This is a four step process (with an optional fifth):

  • User Initiates Purchase: User sends specified funds (ETH, MATIC, USD, etc.) to your wallet via thirdweb Pay.
    • Your wallet can be any business wallet you choose or your Engine backend wallet.
    • Use the purchaseData field to pass any item data needed in the webhook. E.g., { nftId: 1 }.
  • Pay Processes Purchase: thirdweb Pay processes the transaction and sends a Purchase Complete webhook to your dapp’s server when the transaction is complete.
  • Your Server Calls Engine: Your server processes the webhook and sends a contract call to the thirdweb Engine backend wallet to perform the item purchase.
  • Engine Executes the Transaction: Engine backend wallet executes the transaction needed to deliver the token(s) to the user’s address.
  • (Optional) User Is Notified : Your server confirms the completed Engine transaction and notifies the user.

Now, let's get started.

  • Set Up Thirdweb Engine

    • If you haven't already, log in and deploy an Engine instance

    • Create or import a backend wallet for Engine in your Engine dashboard.

    • Send the required funds to the backend wallet

      • For example, if purchasing with Arb Nova USDC, then your backend wallet should hold this ERC20 token.
      • If your backend wallet holds an ERC20 token, ensure to add a native token balance as well to cover gas costs. For example, for a transaction on Arbitrum Nova, your backend wallet should hold both Arb Nova USDC (for payment) and Arb Nova ETH (for gas).
      • Your backend wallet should hold enough liquidity to handle any anticipated purchasing volume.
    • Make a plan to monitor and keep the float wallet topped up to avoid any issues with the service.

  • Integrate thirdweb Pay (Client)

    • Integrate thirdweb Pay on the client side to enable fiat and crypto payments.

    • Specify the required parameters for your Pay transaction.

      const quote = await getBuyWithFiatQuote({
      client: client, // thirdweb client
      fromCurrencySymbol: "USD", // fiat currency symbol
      toChainId: arbnova.id, // arbitrum nova chain id
      toAmount: "100", // amount of token to buy
      toTokenAddress: USDC_TOKEN_ADDRESS, // address of payment token
      fromAddress: "<USERS_WALLET_ADDRESS>",
      toAddress: "<YOUR_WALLET_ADDRESS>",
      purchaseData: {
      nftId: 1,
      },
      });
      ParameterTypeDescription
      fromCurrencySymbolstringThe fiat currency symbol you'd like to accept (currently limited to USD and EUR)
      toChainIdstringChain ID for the destination token.
      toTokenAddressstringAddress of the destination token.
      toAmountstringThe price of the asset denominated in your desination token.
      fromAddressstringThe user's wallet address.
      toAddressstringThe wallet you'd like funds to be sent to. This can be your business wallet or an Engine backend wallet.
      purchaseDataObjectAny details you need to pass in order to track your transaction. If this is a secondary sale, you may want to include details like { nftId: 1, orderId: 1 }
  • Integrate thirdweb Pay (Server)

    • Log in & create a “Purchase Complete” webhook in your Team > Connect > Pay > Webhooks page.
    • The Pay webhook POST response will include the BuyWithCryptoStatus or BuyWithFiatStatus in the body.
      • This will also include the purchaseData you previously passed (metadata identifying the customer information, etc.).
      • A request will be sent on every status change.
    • Listen for completed purchase statuses. Note that if this is a two-step BuyWithFiat transaction (onramp, then swap), you should also listen for CRYPTO_SWAP_COMPLETED
    • When a purchase is completed, determine the purchaser, order and validate the amounts.
      • The fromAddress in the status will show purchasing address
      • The purchaseData will contain more information you previously for the purchase details
      • Validate the information. For example, 100 USDC was sent to your wallet.
    • Send a contract call to Engine for the float wallet to purchase the item
      • For example, send a transaction to the float wallet for mintTo(fromAddress)
      • For secondary purchases, like a marketplace direct listing, you can use the appropriate Engine endpoint, passing the ultimate recipient of the NFT as the buyer
    • Confirm the purchase was successful.

Once you've completed all of these steps, you'll be ready to offer a great purchase UX for your users.