Course lesson
Interact with a Solidity Smart Contract Using Ethers and the Contract ABI in SvetleKit
Now is time to setup the client to talk with the contract, for that you will need to store and access the contract ABI (this is a file generated by the contract compilation) as well as use ethers to set up a connection to the contract.
- Duration
- 5 min
- Access
- Included
- Transcript
- Retained from source evidence
Now is time to setup the client to talk with the contract, for that you will need to store and access the contract ABI (this is a file generated by the contract compilation) as well as use ethers to set up a connection to the contract.
Once set up is complete, we will listen to any tip events that come in from the contract and display tip information in the application.
Important
SvelteKit is still in beta. Expect bugs! Read more here, and track progress towards 1.0 here.
This lesson was recorded before the latest breaking changes, the content is still valid but it sometimes references a file that does not exists anymore.
Now:
src/routes/index.svelte is called src/routes/+page.svelte
src/routes/__layout.svelte is called src/routes/+layout.svelte
Everything else is 100% valid. This particular content will be updated when Sveltekit reaches 1.0.0 stable.
Setup communication with the contract
Now is time to setup the client to talk with the contract, for that you first need to import the contract ABI, a file generated by the contract compilation under src/artifacts/src/contracts/TipJar.sol/TipJar.json-
import TipJarABI from '../artifacts/src/contracts/TipJar.sol/TipJar.json';With that in place, you'll need the contract address and setup the "connection" with it. Let's check how to do it
import TipJarABI from '../artifacts/src/contracts/TipJar.sol/TipJar.json';
// Create 2 new variables
const contractAddress = import.meta.env.VITE_CONTRACT_ADDRESS;
let contract = null;
async function setupContract() {
if (isConnected && provider) {
contract = new ethers.Contract(contractAddress, TipJarABI.abi, provider); // Get the contract object
contract.on('NewTip', async () => { // Listen for events on the contract
// update balance after a new tip was made
balance = await provider.getBalance(userAddress);
});
}
}
async function setup(accounts) {
...
...
setupContract();
}The contract address will be stored in an environment variable inside the .env file.
Recall the address of the contract on lesson 07? Well, you need that, if you don't recall it, let's deploy the contract again
$ npm run hardhat:deployAnd copy the TipJar address into the .env file under the variable VITE_CONTRACT_ADRESS^ (if the .envfile don't exists, just create it).
SvelteKit offers a simple way to retrieve the enviroment variables by using import.meta.env. Every variable named with the VITE_ prefix will be avaible for the frontend to import.
Now in the setupContract function there are two steps.
- Setup the contract object by calling
ethers.Contractthat receives thecontractAddress, theABIcode and the priovider. - Setup a listener for the
NewTipevent that you know you'll need: The listener callback just update the balance displayed in the screen.
Finally let's create a function to read the tips stored in the contract and render that in the UI
// Read the tips from the contract
async function getTips() {
if (isConnected) {
const tips = await contract.getAllTips(); // use the getAllTips function to get all the tips
allTips = [
...tips.map((item) => {
// parse the tips and store them in the allTips array
return {
address: item.sender,
timestamp: new Date(item.timestamp * 1000).toLocaleDateString(),
message: item.message,
name: item.name,
amount: ethers.utils.formatEther(item.amount.toString())
};
})
];
}
}<table class="mt-8 border-collapse table-auto w-2/3 mx-auto text-sm h-80 overflow-auto">
<thead>
<tr>
<th class="border-b border-gray-600 font-medium p-4 pl-8 pt-0 pb-3 text-gray-400 text-left"
>address</th
>
<th class="border-b border-gray-600 font-medium p-4 pl-8 pt-0 pb-3 text-gray-400 text-left"
>Name</th
>
<th class="border-b border-gray-600 font-medium p-4 pl-8 pt-0 pb-3 text-gray-400 text-left"
>Message</th
>
<th class="border-b border-gray-600 font-medium p-4 pl-8 pt-0 pb-3 text-gray-400 text-left"
>Timestamp</th
>
<th class="border-b border-gray-600 font-medium p-4 pl-8 pt-0 pb-3 text-gray-400 text-left"
>Amount</th
>
</tr>
</thead>
<tbody>
{#each allTips as item}
<tr>
<td class="border-b border-gray-700 p-4 pl-8 text-gray-500">{item.address}</td>
<td class="border-b border-gray-700 p-4 pl-8 text-gray-500">{item.name}</td>
<td class="border-b border-gray-700 p-4 pl-8 text-gray-500">{item.message}</td>
<td class="border-b border-gray-700 p-4 pl-8 text-gray-500">{item.timestamp}</td>
<td class="border-b border-gray-700 p-4 pl-8 text-gray-500">{item.amount} eth</td>
</tr>
{/each}
</tbody>
</table>