Custodial Accounts Transactions

Introduction

Our system differentiates between custodial accounts and non-custodial accounts:

  • Non-custodial accounts: When users log in using MetaMask, WalletConnect, or Xaman Wallet, they are utilizing non-custodial accounts.

  • Custodial accounts: When users log in using Google, Facebook, or Email, they are utilizing custodial accounts. These accounts allow us to track and regulate transactions, making it easier for users without web3 wallets to access our system.

Transaction Types

Transactions in our system cover a wide range of web3 transactions, including but not limited to:

  • Sending ERC20 tokens

  • Bridging ERC20 tokens

  • Staking ERC20 tokens

  • Sending ERC721 NFTs (collectibles)

  • Bridging ERC721 NFTs (collectibles)

Transaction Process for Custodial Accounts

Custodial account transactions are unique as these users cannot sign transactions using their web3 wallets. To ensure security and align with the characteristics of web3 transactions, we have developed a special application called the Custodial Signer. This application securely handles the transaction signing process by communicating with a server specifically designed to manage custodial account transactions.

Integration Guide

To use custodial accounts to complete transactions, there are two approaches:

  1. Using the React SDK:

    • This is the simpler method. The React SDK provides a wagmi provider and implements the Futureverse Connector, which can directly communicate with the custodial signer to complete the signing process and send the transaction to the blockchain.

  2. Using the Barebones Solution:

    • This method is more complex. It requires users to implement a popup window and communicate with the custodial signer via post messages to obtain the signature. Then, the obtained signature is used to send the transaction to the blockchain.

Code Example: Barebones Solution

Step 1: Get Signature by Communicating with Custodial Signer

import { ethers } from 'ethers'

const rawTransactionWithoutSignature = {
  to: 'the destination wallet address',
  value: ethers.parseEther('0.01'),
  chainId: 'the chain id',
  gasLimit: 210000,
  gasPrice: ethers.parseUnits('10.0', 'gwei'),
}
let nonce = 0

const custodialSignerUrl = 'the custodial signer service url'

async function signTransaction() {
  if (typeof window === 'undefined') {
    return
  }

  const fromAccount = 'your own wallet address'

  const transactionCount = await provider.getTransactionCount(fromAccount)
  nonce = transactionCount + 1

  const serializedUnsignedTransaction = ethers.Transaction.from({
    ...rawTransactionWithoutSignature,
    nonce,
  }).unsignedSerialized

  const signTransactionPayload = {
    account: fromAccount,
    transaction: serializedUnsignedTransaction,
  }

  const id = 'client:2' // must be formatted as `client:${ an identifier number }`
  const tag = 'fv/sign-tx' // do not change this

  const encodedPayload = {
    id,
    tag,
    payload: signTransactionPayload,
  }

  window.open(
    `${custodialSignerUrl}?request=${base64UrlEncode(JSON.stringify(encodedPayload))}`,
    'futureverse_wallet', // don't change this
    'popup,right=0,width=290,height=286,menubar=no,toolbar=no,location=no,status=0'
  )

  window.addEventListener('message', (ev) => {
    if (ev.origin === custodialSignerUrl) {
      const dataR = signMessageType.decode(ev.data)

      if (E.isRight(dataR)) {
        transactionSignature = dataR.right.payload.response.signature
      }
    }
  })
}

Step 2: Send Transaction to Blockchain

sync function sendTransaction() {
  if (transactionSignature == null || fromAccount == null) {
    return;
  }

  const rawTransactionWithSignature = {
    ...rawTransactionWithoutSignature,
    signature: transactionSignature,
    from: fromAccount,
    nonce,
  };

  const serializedSignedTransaction = ethers.Transaction.from(
    rawTransactionWithSignature
  ).serialized;

  const transactionResponse = await provider.broadcastTransaction(
    serializedSignedTransaction
  );
}

Last updated

© 2023 -> ♾️