Biconomy Gasless SDK (EOA)
DashboardMediumWebsite
  • 🚀Getting Started
  • Introduction
    • 🤘Why Biconomy?
    • 🙂How we simplify transactions
  • Products
    • 💸Gasless Transactions
      • Choose An Approach to Enable Gasless
        • Standard EIP 2771 Approach
          • 1. Register Artifacts on the Dashboard
          • 2. Code Changes
            • Using SDK
            • Using API
        • Custom Implementation Approach
          • 1. Register Artifacts on the Dashboard
          • 2. Code Changes
            • Using SDK
            • Using API
        • Smart Contract Wallet Approach
          • Gnosis
        • Network Agnostic Transactions
          • EIP-2771 Approach
          • Custom Approach
      • Conditional Whitelisting
      • Gasless SDK (EOA) 3
      • Networks Supported
    • ↔️Hyphen - Instant Cross-Chain Transfers
      • SDK
        • DepositManager
        • TransferManager
        • TokenManager
      • APIs
      • Helper Methods
      • Migrating from Hyphen V1
      • Contract Addresses
      • Hyphen Widget
  • Guides
    • 💻Dashboard
      • DApp Statistics
    • ⛽Gas Tank Deposits
      • Via Dashboard
      • Via Smart Contract
  • api
    • 🔧Native Meta Transaction
      • Get Retried Hashes
    • 🌎Dashboard APIs
    • ⚪Whitelist API
      • Whitelist Destination Address
      • Whitelist Proxy Contracts
    • 〰️ Check Limits
    • 💿Biconomy Data API
      • 👨‍🚀Unique User Data
      • 🧑‍🔧Per User Limits Data
      • ⛽Gas Tank Balance Data
  • SDK
    • 📙Gasless SDK (EOA)
      • Configuration
  • Tutorials
    • 🔰Native Meta Transactions
      • How To Build Your First DApp
        • Write Your First Smart Contract
        • Initialize Web3 on Client Side
        • Executing First Blockchain Transaction
      • Enable Native Meta Transactions
        • Smart Contract
          • Describe Your Structs
          • Declare Your Variables
          • Modify Respective Function
        • Client Side
          • Design Your JSON structure
          • Design Your Domain Separator
          • Design Data Types
          • Define Data To Sign
          • Generate Signatures
      • Integrate Biconomy
        • Register On Dashboard
        • Integrate Gasless SDK (EOA)
      • Summary
  • BICO Staking
    • 🪁Safety Module
  • Get in touch
    • 👥Contact Us
  • Misc
    • 🧩Projects on Biconomy
    • 🌐Supported Networks
    • 📫Contract Addresses
    • ✔︎ Smart Contracts Audit
    • ❓FAQs
Powered by GitBook
On this page
  • Smart Contract changes - Personal Signature
  • Smart Contract changes - EIP-712 Signature
  • Client Side changes
  • SDK Integration
  • 1. Importing Gasless SDK (EOA)
  • 2. Initializing SDK
  • 3. Initialize your dApp after Gasless SDK (EOA) initialization
  • 4. Sign & Send Meta Transactions

Was this helpful?

  1. Products
  2. Gasless Transactions
  3. Choose An Approach to Enable Gasless
  4. Network Agnostic Transactions

Custom Approach

PreviousEIP-2771 ApproachNextConditional Whitelisting

Last updated 2 years ago

Was this helpful?

Read more about Custom Approach .

Smart Contract changes - Personal Signature

  1. Inherit contract in your contract

  2. Replace msg.sender in your contract with msgSender()

Smart Contract changes - EIP-712 Signature

  1. Inherit contract in your contract

  2. Replace msg.sender in your contract with msgSender()

  3. Deploy contract on the desired network.

Client Side changes

Now the contracts are updated and deployed, it's time to do the changes on your client-side.

  1. After Registering Your dApp, SmartContact & Contract method on Desired network on Biconomy Dashboard, copy the <api-key>, you will need it on the client-side code.

  2. It is important that you need to make 2 providers on your client-side. One normal provider from your connected wallet eg window.ethereum for Metamask, to take the User Signature on the wallet pop-up window. Second provider object to be used with Biconomy to send the transaction. This second provider (network provider) should be a provider initialised with network RPC URL. That's it.

  3. In this custom approach instead of calling you contract methods directly, you will need to call executeMetaTransaction() method and pass your contract method in functionSignature along with other params.

  4. So the flow will be like this, to take the user signature you need to use the wallet provider. Once you get the user signature, pass that signature in the executeMetaTransaction()along with functionSignature and other params and call executeMetaTransaction() method using the second provider which was passed to Biconomy object.

SDK Integration

In basic terms, you need one provider object for sending meta transactions using Gasless SDK (EOA), another for signing meta transaction parameters.

1. Importing Gasless SDK (EOA)

npm install @biconomy/mexa
// Install Biconomy
<script src="https://cdn.jsdelivr.net/npm/@biconomy/mexa@latest/dist/mexa.js"></script>

// Import Biconomy
let Biconomy = window.Biconomy.default;

2. Initializing SDK

import {Biconomy} from "@biconomy/mexa";

// We're creating a 2nd Ethers provider linked to your L2 network of choice
let biconomy = new Biconomy(new Web3.providers.HttpProvider("YOUR RPC URL HERE")
                            ,{apiKey: <API Key>, debug: true});
let biconomyWeb3 = new Web3(biconomy);

/*
    This provider linked to your wallet.
    If needed, substitute your wallet solution in place of window.ethereum 
*/
let walletWeb3 = new Web3(window.ethereum);
import {Biconomy} from "@biconomy/mexa";

// We're creating a 2nd Ethers provider linked to your L2 network of choice
let biconomy = new Biconomy(new ethers.providers.JsonRpcProvider("YOUR RPC URL HERE"),
                            {apiKey: <API Key>, debug: true});
let networkProvider = new ethers.providers.Web3Provider(biconomy);

/*
    This provider linked to your wallet.
    If needed, substitute your wallet solution in place of window.ethereum 
*/
let walletProvider = new ethers.providers.Web3Provider(window.ethereum);

3. Initialize your dApp after Gasless SDK (EOA) initialization

Gasless SDK (EOA) fetches data from Biconomy's servers. Because of this, it's best to initialize your dApp or perform any action after the biconomy.READY event occurs.

If there is an error while initializing Gasless SDK (EOA), it's good to catch and log a biconomy.ERROR event for better debugging.

biconomy.onEvent(biconomy.READY, () => {
  // Initialize your contracts here using biconomy's provider instance
  // Initialize dapp here like getting user accounts etc
}).onEvent(biconomy.ERROR, (error, message) => {
  // Handle error while initializing mexa
});

4. Sign & Send Meta Transactions

let walletProvider, walletSigner;

//networkProvider as defined above for ethers can be used for sendTransaction (send raw transaxction) or waitForTransaction for special cases (i.e. backend private key etc)  

// Initialize Constants
const domainType = [
    { name: "name", type: "string" },
    { name: "version", type: "string" },
    { name: "verifyingContract", type: "address" },
    { name: "salt", type: "bytes32" },
];
const metaTransactionType = [
    { name: "nonce", type: "uint256" },
    { name: "from", type: "address" },
    { name: "functionSignature", type: "bytes" }
];
// replace the chainId 42 if network is not kovan
let domainData = {
    name: "TestContract",
    version: "1",
    verifyingContract: config.contract.address,
    // converts Number to bytes32. Use your own chainId instead of 42 for other networks
    salt: ethers.utils.hexZeroPad((ethers.BigNumber.from(42)).toHexString(), 32)
};


let contract = new ethers.Contract(<CONTRACT_ADDRESS>,
              <CONTRACT_ABI>, biconomy.getSignerByAddress(userAddress));
let contractInterface = new ethers.utils.Interface(<CONTRACT_ABI>);

 /*
  This provider is linked to your wallet.
  If needed, substitute your wallet solution in place of window.ethereum 
 */
walletProvider = new ethers.providers.Web3Provider(window.ethereum);
walletSigner = walletProvider.getSigner();

let nonce = await contract.getNonce(userAddress);
let functionSignature = contractInterface.encodeFunctionData("setQuote", [newQuote]);
                
let message = {};
message.nonce = parseInt(nonce);
message.from = userAddress;
message.functionSignature = functionSignature;

const dataToSign = JSON.stringify({
  types: {
    EIP712Domain: domainType,
    MetaTransaction: metaTransactionType
  },
  domain: domainData,
  primaryType: "MetaTransaction",
  message: message
});

/*Its important to use eth_signTypedData_v3 and not v4 to get EIP712 signature 
because we have used salt in domain data instead of chainId*/
// Get the EIP-712 Signature and send the transaction
let signature = await walletProvider.send("eth_signTypedData_v3", [userAddress, dataToSign])
let { r, s, v } = getSignatureParameters(signature);
let tx = contract.executeMetaTransaction(userAddress,
             functionSignature, r, s, v);
             
await tx.wait(1);
console.log("Transaction hash : ", tx.hash); 
             
             
//////////
/*helper*/

const getSignatureParameters = signature => {
        if (!ethers.utils.isHexString(signature)) {
            throw new Error(
                'Given value "'.concat(signature, '" is not a valid hex string.')
            );
        }
        var r = signature.slice(0, 66);
        var s = "0x".concat(signature.slice(66, 130));
        var v = "0x".concat(signature.slice(130, 132));
        v = ethers.BigNumber.from(v).toNumber();
        if (![27, 28].includes(v)) v += 27;
        return {
            r: r,
            s: s,
            v: v
        };
    };             
// This web3 instance is used to get user signature from connected wallet
let walletWeb3 = new Web3(window.ethereum);

// Initialize constants
const domainType = [
    { name: "name", type: "string" },
    { name: "version", type: "string" },
    { name: "verifyingContract", type: "address" },
    { name: "salt", type: "bytes32" },
];
const metaTransactionType = [
    { name: "nonce", type: "uint256" },
    { name: "from", type: "address" },
    { name: "functionSignature", type: "bytes" }
];
// replace the chainId 42 if network is not kovan
let domainData = {
    name: "TestContract",
    version: "1",
    verifyingContract: config.contract.address,
    // converts Number to bytes32. Use your chainId instead of 42 if network is not Kovan
    salt: '0x' + (42).toString(16).padStart(64, '0')


let contract = new biconomyWeb3.eth.Contract(
            <Your Contract ABI>,
            <Your Contract Address>
          );
  
let nonce = await contract.methods.getNonce(userAddress).call();
// Create your target method signature.. here we are calling setQuote() method of our contract
let functionSignature = contract.methods.setQuote(newQuote).encodeABI();
let message = {};
message.nonce = parseInt(nonce);
message.from = userAddress;
message.functionSignature = functionSignature;

const dataToSign = JSON.stringify({
  types: {
    EIP712Domain: domainType,
    MetaTransaction: metaTransactionType
  },
  domain: domainData,
  primaryType: "MetaTransaction",
  message: message
});

// NOTE: Using walletWeb3 here, as it is connected to the wallet where user account is present.
// Get the EIP-712 Signature and send the transaction
walletWeb3.currentProvider.send({
    jsonrpc: "2.0",
    id: 999999999999,
    method: "eth_signTypedData_v4",
    params: [userAddress, dataToSign]
  },function(error, response) {
    // Check github repository for getSignatureParameters helper method
    let { r, s, v } = getSignatureParameters(response.result);
    
    let tx = contract.methods.executeMetaTransaction(userAddress,
    functionSignature, r, s, v)
      .send(from: userAddress);

    tx.on("transactionHash", function(hash) {
      // Handle transaction hash
    }).once("confirmation", function(confirmationNumber, receipt) {
      // Handle confirmation
    }).on("error", function(error) {
      // Handle error
    });
    
  }
);

You can use Gasless SDK (EOA) either with or . We'll be making two provider objects, one linked to your dApp's network RPC, and the other to your user's wallet.

for complete example code

for complete example code

💸
here
BasicMetaTransaction
EIP712MetaTransaction
Web3.js
Ethers.js
Check out the repository
Check out the repository