Set up the repo and install packages
Step 1: Create a new repo with create-react-app
Create a new typescript based react project with react with name banana-rainbow-integ
and now let's move into to the directory
Copy npx create - react - app banana - wallet - demo -- template typescript
cd banana - rainbow - integ
Step 2: Installing rainbowkit, wagmi and Banana rainbow plugin package
Copy npm install @rainbow-me/rainbowkit@0.8.1 wagmi@0.9.0 @rize-labs/banana-rainbowkit-plugin
Step 3: Fixing webpack 5 and polyfill issues
Copy npm install react-app-rewired
npm install stream-browserify constants-browserify crypto-browserify os-browserify path-browserify process stream-browserify buffer ethers@^5.7.2
Create a file name `config-overrides.js` with the below content
Copy const { ProvidePlugin } = require ( "webpack" )
module . exports = {
webpack : function (config , env) {
config . module .rules = config . module . rules .map (rule => {
if ( rule .oneOf instanceof Array ) {
rule .oneOf[ rule . oneOf . length - 1 ].exclude = [ /\.(js | mjs | jsx | cjs | ts | tsx) $ / , /\.html $ / , /\.json $ / ];
}
return rule;
});
config . resolve .fallback = {
... config . resolve .fallback ,
stream : require .resolve ( "stream-browserify" ) ,
buffer : require .resolve ( "buffer" ) ,
crypto : require .resolve ( "crypto-browserify" ) ,
process : require .resolve ( "process" ) ,
os : require .resolve ( "os-browserify" ) ,
path : require .resolve ( "path-browserify" ) ,
constants : require .resolve ( "constants-browserify" ) ,
fs : false
}
config . resolve .extensions = [ ... config . resolve .extensions , ".ts" , ".js" ]
config .ignoreWarnings = [ /Failed to parse source map/ ];
config .plugins = [
... config .plugins ,
new ProvidePlugin ({
Buffer : [ "buffer" , "Buffer" ] ,
}) ,
new ProvidePlugin ({
process : [ "process" ]
}) ,
]
return config;
} ,
}
Step 4: Modify package.json
Change package.json
accordingly to use the start app with react-app-rewired
Copy react - scripts start -> react - app - rewired start
Smart Contracts
We will be having a very basic smart contract for the demo purpose for this demo. There will be two functionalities:
Make a transaction to the blockchain by making a state variable change its value.
Fetch value of state variable
Here is the smart contract code:
Copy pragma solidity ^ 0.8 . 12 ;
contract Sample {
uint public stakedAmount = 0 ;
function stake () external payable {
stakedAmount = stakedAmount + msg .value;
}
function returnStake () external {
payable ( 0x48701dF467Ba0efC8D8f34B2686Dc3b0A0b1cab5 ) .transfer (stakedAmount);
}
}
You can deploy it using remix.ethereum.org and save the smart contract address.
For your reference a sample contract has been deployed here:
Copy 0x59DC70db4A6914Bece003Eff48C8fa4166aaC05a
Building the frontend
We will have a simple front end with some buttons to interact with the blockchain. Although Banana SDK provides you with a smart contract wallet you don't need worry about its deployment. Everything is handled by us in the SDK so you can just concentrate on building your Dapp.
In App.tsx
let's import the required for rainbow
Importing required modules for rainbow
Copy import "@rainbow-me/rainbowkit/styles.css" ;
import {
RainbowKitProvider ,
connectorsForWallets ,
} from "@rainbow-me/rainbowkit" ;
import {
metaMaskWallet ,
injectedWallet ,
rainbowWallet ,
walletConnectWallet ,
} from "@rainbow-me/rainbowkit/wallets" ;
let's import modules required from wagmi
Copy import { polygonMumbai , optimismGoerli , goerli , gnosis , gnosisChiado } from "@wagmi/chains" ;
import { jsonRpcProvider } from 'wagmi/providers/jsonRpc' ;
import { configureChains , createClient , WagmiConfig } from "wagmi" ;
Importing BananaWallet plugin from banana-rainbowkit-plugin package
Copy import { BananaWallet , astarChain } from '@rize-labs/banana-rainbowkit-plugin'
Configure chains and providers
Copy const { chains , provider } = configureChains (
// currently on these three chains are supported by BananaWallet
[polygonMumbai , optimismGoerli , goerli , gnosis , gnosisChiado , astarChain] ,
[
jsonRpcProvider ({
rpc : chain => ({ http : chain . rpcUrls . default .http[ 0 ] }) ,
}) ,
]
);
Creating connectors for rainbow
Copy const connectors = connectorsForWallets ([
{
groupName : "Recommended" ,
wallets : [
BananaWallet ({ chains , connect : { networkId : 592 } }) , // networkId: 592 for astar
metaMaskWallet ({ chains , shimDisconnect : true }) ,
rainbowWallet ({ chains }) ,
walletConnectWallet ({ chains }) ,
injectedWallet ({ chains , shimDisconnect : true }) ,
] ,
} ,
]);
Creating wagmiClient
Copy const wagmiClient = createClient ({
autoConnect : true ,
connectors ,
provider ,
});
Providing context of Rainbowkit and wagmi
Copy return (
< div className = "App" >
< WagmiConfig client = {wagmiClient}>
< RainbowKitProvider chains = {chains}>
< Demo />
</ RainbowKitProvider >
</ WagmiConfig >
</ div >
);
Putting all together you can find the final App.tsx file here:
Let's start creating Demo.tsx which will contain logic for doing multiple things with wallet instance
Importing Hooks from wagmi
Copy import { useSigner , useProvider , useAccount } from "wagmi" ;
Extracting signers and providers from wagmi hooks
Copy const { isConnected } = useAccount ();
const provider = useProvider ();
const { data: signer } = useSigner ();
Implementing function to getChainid of current chain
Copy const getChainID = async () => {
try {
//@ts-ignore
const chainId = await signer .getChainId ();
setOutput ( JSON .stringify ( chainId .toString ()));
} catch (e) {
console .error (e);
}
};
Implementing function to getBalance of an address
Copy const getBalance = async () => {
try {
//@ts-ignore
const account = await signer .getAddress ();
const balanceChk1 = await provider ! .getBalance (account);
setOutput ( JSON .stringify (balanceChk1));
} catch (e) {
console .error (e);
}
};
Implementing function to get network info
Copy const getNetworks = async () => {
try {
const network = await provider ! .getNetwork ();
setOutput ( JSON .stringify (network));
} catch (e) {
console .error (e);
}
};
Implementing function to sign Message using Banana Wallet
Copy const signMessage = async () => {
try {
setIsLoading ( true );
const message = "Welcome to Banana Wallet" ;
//@ts-ignore
const sig = await signer .signBananaMessage (message);
setOutput ( JSON .stringify (sig));
setIsLoading ( false );
} catch (e) {
setIsLoading ( false );
console .error (e);
}
};
implementing function to sendEth
Copy const sendETH = async () => {
try {
setIsLoading ( true );
//@ts-ignore
const toAddress = ethers . Wallet .createRandom ().address;
const tx1 = {
gasLimit : "0x55555" ,
to : toAddress ,
value : ethers . utils .parseEther ( "0.000001" ) ,
data : "0x" ,
};
//@ts-ignore
const txnResp = await signer .sendTransaction (tx1);
setOutput ( JSON .stringify (txnResp));
setIsLoading ( false );
} catch (e) {
setIsLoading ( false );
console .error (e);
}
};
Implementing function to make call to smart contract method
Copy const stakeTxn = async () => {
try {
setIsLoading ( true );
const amount = "0.00001" ;
const tx = {
gasLimit : "0x55555" ,
to : SampleContractAddress ,
value : ethers . utils .parseEther (amount) ,
data : new ethers . utils .Interface (SampleAbi) .encodeFunctionData (
"stake" ,
[]
) ,
};
//@ts-ignore
const txn = await signer .sendTransaction (tx);
setOutput ( JSON .stringify (txn));
setIsLoading ( false )
} catch (err) {
setIsLoading ( false );
console .log (err);
}
};
Putting all together
Full code can be found here
Last updated 10 months ago