Skip to content

Instantly share code, notes, and snippets.

@libevm
Created June 26, 2023 06:30
Show Gist options
  • Select an option

  • Save libevm/ea87efcfc7d16cd64b403ecf95a0daf0 to your computer and use it in GitHub Desktop.

Select an option

Save libevm/ea87efcfc7d16cd64b403ecf95a0daf0 to your computer and use it in GitHub Desktop.
viem example for mantle
const mantleTestnet = {
id: 5001,
name: "Mantle Testnet",
network: "Mantle Testnet",
nativeCurrency: {
decimals: 18,
name: "Mantle",
symbol: "MNT",
},
rpcUrls: {
public: { http: ["https://rpc.testnet.mantle.xyz"] },
default: { http: ["https://rpc.testnet.mantle.xyz"] },
},
blockExplorers: {
default: {
name: "Mantle Explorer",
url: "https://explorer.testnet.mantle.xyz/",
},
},
contracts: {
multicall3: {
address: "0xca11bde05977b3631167028862be2a173976ca11",
blockCreated: 56133,
},
},
};
import { createPublicClient, http, getContract } from "viem";
const client = createPublicClient({
chain: mantleTestnet,
transport: http(),
});
const abi = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"tokens","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokens","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"tokenOwner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"drip","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"tokens","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"tokens","type":"uint256"},{"name":"data","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"newOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"tokenAddress","type":"address"},{"name":"tokens","type":"uint256"}],"name":"transferAnyERC20Token","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"tokenOwner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"tokens","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tokenOwner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"tokens","type":"uint256"}],"name":"Approval","type":"event"}];
const main = async () => {
const contract = getContract({
address: "0xa35d7f5dd89a336A427Ebb63C428C3068b6c3105",
abi: abi,
publicClient: client,
});
const totalSupply = await contract.read.totalSupply()
console.log('total supply', totalSupply)
const unwatch = contract.watchEvent.Transfer({}, {
onLogs: (x) => {
console.log(x);
},
});
setTimeout(() => {
console.log('unwatching transfer events')
unwatch()
}, 1000)
};
main();
@krzysu
Copy link
Copy Markdown

krzysu commented Oct 16, 2024

For reference, you can achieve the same result using Web3.js v4. Below is a code sample showcasing:

  • Initialize a Web3 instance with the Mantle mainnet provider.
  • Fetch chain data, including the current chain ID (which returns 5000) and block number.
  • Interact with a deployed USDC contract on the Mantle mainnet (reusing the ABI from the viem example above) by calling its methods to get the contract name and total supply.
  • Subscribe to Transfer events emitted by the contract, starting from the latest block.
  • Log each Transfer event when it occurs.
  • Unsubscribe from events after 5 seconds and close the WebSocket connection to cleanly exit.
import { Web3 } from "web3";
import abi from "./abi.js";

// WebSocket provider is required for contract subscriptions
const web3 = new Web3("wss://mantle-rpc.publicnode.com");

// Alternatively, use an HTTP provider if you don't need subscriptions
// const web3 = new Web3("https://mantle-rpc.publicnode.com");

const main = async () => {
  // Fetch some chain data
  const chainId = await web3.eth.getChainId();
  console.log("Connected to chain with ID:", chainId.toString());

  const blockNumber = await web3.eth.getBlockNumber();
  console.log("Current block number:", blockNumber.toString());

  // Interact with a deployed contract (USDC on Mantle mainnet in this case)
  const contract = new web3.eth.Contract(
    abi,
    "0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9"
  );

  const name = await contract.methods.name().call();
  console.log("Contract name:", name);

  const totalSupply = await contract.methods.totalSupply().call();
  console.log("Total supply:", totalSupply);

  // Subscribe to Transfer events from the contract, starting from the latest block
  const subscription = contract.events.Transfer({
    fromBlock: blockNumber,
  });
  console.log("Subscribed to Transfer events from contract");

  subscription.on("data", (event) => {
    console.log("Transfer event:", event);
  });

  setTimeout(async () => {
    console.log("Unsubscribing from Transfer events...");
    await subscription.unsubscribe();

    // Close the WebSocket connection to gracefully end the program
    web3.currentProvider.disconnect();
    console.log("WebSocket connection closed.");
  }, 5 * 1000); // Unsubscribe after 5 seconds
};

main();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment