description |
---|
Create and deploy a simple frontend locally |
{% hint style="info" %} Please complete Counter tutorial to deploy the counter smart contract before continuing with this page {% endhint %}
In this tutorial, we'll go over how to:
- Set up your frontend project
- Connect to a Sei wallet
- Query and display the current count
- Execute the counter smart contract's
increment
function
To create a project from scratch we recommend using the typescript template from Vite, which makes development and debugging much easier.
yarn create vite my-counter-frontend --template react-ts
This will create a new folder with a React project that uses typescript. Open this folder in your favorite IDE.
From a terminal at the root of this project install the required project dependencies including @sei-js/core and @sei-js/react as well as some node polyfill libraries.
yarn && yarn add @sei-js/core @sei-js/react
or
npm install && npm install @sei-js/core @sei-js/react
Replace your App.tsx
file with the following code to set up a SeiWalletProvider context, define your chain info, and set connection URLs.
{% tabs %} {% tab title="Typescript (highly recommended)" %}
import { SeiWalletProvider } from '@sei-js/react';
import './App.css';
import Home from './Home.tsx';
function App() {
return (
// Set up SeiWalletProvider for easy wallet connection and to use hooks in @sei-js/react
<SeiWalletProvider
chainConfiguration={{
chainId: 'atlantic-2',
restUrl: 'https://rest.atlantic-2.seinetwork.io',
rpcUrl: 'https://rpc.atlantic-2.seinetwork.io'
}}
wallets={['compass', 'fin']}>
<Home />
</SeiWalletProvider>
);
}
export default App;
{% endtab %}
{% tab title="Javascript" %}
import { SeiWalletProvider } from '@sei-js/react';
import './App.css';
import Home from './Home.jsx';
function App() {
return (
// Set up SeiWalletProvider for easy wallet connection and to use hooks in @sei-js/react
<SeiWalletProvider
chainConfiguration={{
chainId: 'atlantic-2',
restUrl: 'https://rest.atlantic-2.seinetwork.io',
rpcUrl: 'https://rpc.atlantic-2.seinetwork.io'
}}
wallets={['compass', 'fin']}>
<Home />
</SeiWalletProvider>
);
}
export default App;
{% endtab %} {% endtabs %}
Detailed outline of App.tsx
Wallet Provider Setup
- Imports
SeiWalletProvider
from the@sei-js/react
package. - Wraps the
Home
component with theSeiWalletProvider
to provide the wallet context.
Chain Configuration
- Specifies the
chainConfiguration
prop inSeiWalletProvider
to set up the blockchain network:chainId
: Identifies the Sei network (in this case,atlantic-2
).restUrl
: REST URL for the Sei (You may need your own provider).rpcUrl
: RPC URL for the Sei (You may need your own provider).
Supported Wallets
- Sets up supported wallet types (
'compass', 'fin', 'leap', 'keplr'
) in thewallets
prop.
Create a new file called Home.tsx inside your src
directory with the following code.
{% tabs %} {% tab title="Typescript (highly recommended)" %}
import { useCallback, useEffect, useState } from 'react';
import { useCosmWasmClient, useSigningCosmWasmClient, useWallet, WalletConnectButton } from '@sei-js/react';
const CONTRACT_ADDRESS = 'YOUR_COUNTER_CONTRACT ADDRESS'; // (atlantic-2 example) sei18g4g35mhy5s88nshpa6flvpj9ex6u88l6mhjmzjchnrfa7xr00js0gswru
function Home() {
const [count, setCount] = useState<number | undefined>();
const [error, setError] = useState<string>('');
const [isIncrementing, setIsIncrementing] = useState<boolean>(false);
// Helpful hook for getting the currently connected wallet and chain info
const { connectedWallet, accounts } = useWallet();
// For querying cosmwasm smart contracts
const { cosmWasmClient: queryClient } = useCosmWasmClient();
// For executing messages on cosmwasm smart contracts
const { signingCosmWasmClient: signingClient } = useSigningCosmWasmClient();
const fetchCount = useCallback(async () => {
const response = await queryClient?.queryContractSmart(CONTRACT_ADDRESS, { get_count: {} });
return response?.count;
}, [queryClient]);
useEffect(() => {
fetchCount().then(setCount);
}, [connectedWallet, fetchCount]);
const incrementCounter = async () => {
setIsIncrementing(true);
try {
const senderAddress = accounts[0].address;
// Build message content
const msg = { increment: {} };
// Define gas price and limit
const fee = {
amount: [{ amount: '0.1', denom: 'usei' }],
gas: '200000'
};
// Call smart contract execute msg
await signingClient?.execute(senderAddress, CONTRACT_ADDRESS, msg, fee);
// Updates the counter state again
const updatedCount = await fetchCount();
setCount(updatedCount);
setIsIncrementing(false);
setError('');
} catch (error) {
if (error instanceof Error) {
setError(error.message);
} else {
setError('unknown error');
}
setIsIncrementing(false);
}
};
// Helpful component for wallet connection
if (!connectedWallet) return <WalletConnectButton />;
return (
<div>
<h1>Count is: {count ? count : '---'}</h1>
<button disabled={isIncrementing} onClick={incrementCounter}>
{isIncrementing ? 'incrementing...' : 'increment'}
</button>
{error && <p style={{ color: 'red' }}>{error}</p>}
</div>
);
}
export default Home;
{% endtab %}
{% tab title="Javascript" %}
import { useCallback, useEffect, useState } from 'react';
import { useCosmWasmClient, useSigningCosmWasmClient, useWallet, WalletConnectButton } from '@sei-js/react';
const CONTRACT_ADDRESS = 'YOUR_COUNTER_CONTRACT ADDRESS'; // (atlantic-2 example) sei18g4g35mhy5s88nshpa6flvpj9ex6u88l6mhjmzjchnrfa7xr00js0gswru
function Home() {
const [count, setCount] = useState();
const [error, setError] = useState('');
const [isIncrementing, setIsIncrementing] = useState(false);
// Helpful hook for getting the currently connected wallet and chain info
const { connectedWallet, accounts } = useWallet();
// For querying cosmwasm smart contracts
const { cosmWasmClient: queryClient } = useCosmWasmClient();
// For executing messages on cosmwasm smart contracts
const { signingCosmWasmClient: signingClient } = useSigningCosmWasmClient();
const fetchCount = useCallback(async () => {
const response = await queryClient?.queryContractSmart(CONTRACT_ADDRESS, { get_count: {} });
return response?.count;
}, [queryClient]);
useEffect(() => {
fetchCount().then(setCount);
}, [connectedWallet, fetchCount]);
const incrementCounter = async () => {
setIsIncrementing(true);
try {
const senderAddress = accounts[0].address;
// Build message content
const msg = { increment: {} };
// Define gas price and limit
const fee = {
amount: [{ amount: '0.1', denom: 'usei' }],
gas: '200000'
};
// Call smart contract execute msg
await signingClient?.execute(senderAddress, CONTRACT_ADDRESS, msg, fee);
// Updates the counter state again
const updatedCount = await fetchCount();
setCount(updatedCount);
setIsIncrementing(false);
setError('');
} catch (error) {
if (error instanceof Error) {
setError(error.message);
} else {
setError('unknown error');
}
setIsIncrementing(false);
}
};
// Helpful component for wallet connection
if (!connectedWallet) return <WalletConnectButton />;
return (
<div>
<h1>Count is: {count ? count : '---'}</h1>
<button disabled={isIncrementing} onClick={incrementCounter}>
{isIncrementing ? 'incrementing...' : 'increment'}
</button>
{error && <p style={{ color: 'red' }}>{error}</p>}
</div>
);
}
export default Home;
{% endtab %} {% endtabs %}
Detailed outline of Home.tsx
Render Logic
- If no wallet is connected, it shows a
WalletConnectButton
which is a pre built component inside @sei-js/react. - Otherwise, displays the counter value and an "Increment" button.
- Disables the increment button when a transaction is pending
- Catches and displays error messages, if any.
Wallet and Client Setup
- Utilizes
useWallet()
from@sei-js/react
to get the connected wallet and accounts. - Uses
useCosmWasmClient
anduseSigningCosmWasmClient
hooks from@sei-js/react
to instantiatequeryClient
andsigningClient
. The signing client can be used for querying, but it is not recommended to use a signing client when only a query client is needed.
Fetching Counter Value
fetchCount
function usesqueryClient.queryContractSmart
to query the smart contract (CONTRACT_ADDRESS)
with the query{ get_count: {} }
Incrementing Counter
incrementCounter
function:- Extracts
senderAddress
from the connected wallet's accounts. - Builds a message (
msg
) with{ increment: {} }
to be sent to the smart contract. - Specifies the transaction fee (
fee
) with gas price and gas limit. - Calls
signingClient.execute
to execute the contract with the built message and fee.
- Extracts
By leveraging @sei-js and its hooks, the component provides a way to connect to a wallet, query a CosmWasm smart contract to get the current counter state, and increment it with an execute message.
If you run this code as is, then it will throw an error - you need to tell it which contract to use. We have deployed a counter contract for you on the atlantic-2 testnet.
To use it, set CONTRACT_ADDRESS
to sei18g4g35mhy5s88nshpa6flvpj9ex6u88l6mhjmzjchnrfa7xr00js0gswru
Run yarn dev
from the terminal and navigate to http://localhost:5173/ to view your application.
{% hint style="info" %}
If this is your first time using Sei, you might see an error which says your account does not exist on chain.
You can claim some testnet tokens for development purposes here: https://atlantic-2.app.sei.io/faucet
Once you have funded your account, try the increment button again!
{% endhint %}
You have now created a simple website for querying and executing a smart contract on Sei!
{% hint style="info" %} Please see Javascript reference for more examples on how to do even more with your frontend. {% endhint %}