Skip to content

Commit 07f442e

Browse files
committed
Add: Lending protocol frontend
1 parent c920916 commit 07f442e

23 files changed

Lines changed: 21433 additions & 0 deletions
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
# misc
15+
.DS_Store
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
# DeFi Lending Platform - Example Application
2+
3+
This is an **example application** designed for **educational purposes** to help developers learn how to interact with the =nil; blockchain using a frontend application. The app demonstrates the process of transacting with =nil;, including transacting with methods and tokens. It also showcases best practices for connecting a frontend application to the blockchain and calling smart contract methods, including handling tokens.
4+
5+
## Purpose
6+
7+
The goal of this application is to give developers an understanding of how to build frontend applications that interact with =nil; and its smart contracts. By going through this example, you can learn the following:
8+
9+
- How to **connect to the =nil; wallet**.
10+
- How to **read data** from a smart contract.
11+
- How to **call smart contract methods** for transactions such as lending, borrowing, and repaying, including sending tokens along with method calls via the =nil; wallet.
12+
- How to structure your frontend code to handle receipts and errors.
13+
14+
### Features
15+
16+
This application allows you to:
17+
18+
- Depositing assets (ETH or USDT) into the protocol
19+
- Borrowing assets up to 80% of your deposit value
20+
- Repaying loans with 5% interest (105% of the borrowed amount)
21+
- Viewing real-time deposit and loan balances
22+
23+
> Note: This example application only supports whole numbers (no decimals) for all transactions.
24+
25+
This repository is designed to provide a simple yet functional template for building decentralized applications (dApps) on top of =nil;.
26+
27+
---
28+
29+
## Pre-requisites
30+
31+
Before running this application, ensure that you have the following:
32+
33+
- **=nil; wallet extension** installed on your browser. You can get it from the [Chrome Web Store](https://chromewebstore.google.com/detail/nil-wallet/kfiailmjchdbjmadbkkldiahpggcjffp?hl=en-GB&utm_source=ext_sidebar).
34+
- **Node.js** and **npm** installed on your machine.
35+
- A basic understanding of React, TypeScript, and how smart contracts work.
36+
37+
---
38+
39+
## Installation
40+
41+
### 1. Clone the repository
42+
43+
First, clone this repository to your local machine:
44+
45+
```bash
46+
git clone https://github.com/NilFoundation/nil
47+
cd nil/academy/lending-protocol/frontend
48+
```
49+
50+
### 2. Install dependencies
51+
52+
Install the necessary dependencies using npm:
53+
54+
```bash
55+
npm install --legacy-peer-deps
56+
```
57+
58+
### 3. Configure the RPC URL
59+
60+
Before running the frontend application, you must deploy the lending pool contract and obtain its address.
61+
62+
<strong>Deploy the Lending Pool Contract</strong>
63+
64+
If you haven’t already deployed the contract, navigate to the lending protocol directory and deploy it using Hardhat:
65+
66+
```bash
67+
cd ../ # Move to the lending protocol directory
68+
npx hardhat compile
69+
npx hardhat run-lending-protocol
70+
```
71+
72+
Once the deployment completes, look for a log similar to:
73+
74+
`Lending Pool deployed at: 0xYourContractAddressHere`
75+
76+
Copy the contract address.
77+
78+
<strong>Configure the Frontend with the Contract Address</strong>
79+
80+
You need to specify the RPC URL for your =nil; blockchain in the `constants.js` file, which is used to connect to the blockchain network.
81+
82+
In `src/constants.js`, update the following line with your RPC URL:
83+
84+
```javascript
85+
const NIL_RPC_URL = "<YOUR_RPC_URL>";
86+
const contractAddress = "your_contract_address";
87+
```
88+
89+
### 4. Run the Application
90+
91+
Once the installation is complete, start the development server with:
92+
93+
```bash
94+
npm run start
95+
```
96+
97+
This will launch the application, and you can access it via `http://localhost:3000/` in your web browser.
98+
99+
---
100+
101+
## Coding Patterns and Best Practices
102+
103+
This section will walk you through the key coding patterns used in this app. These patterns will help you interact with the =nil; blockchain and smart contracts.
104+
105+
### 1. **Connecting to the Wallet**
106+
107+
To interact with =nil; via a frontend, the first step is to connect to the user's wallet. The app uses `eth_requestAccounts` to prompt the user to connect their =nil; wallet.
108+
109+
```javascript
110+
const connectWallet = async () => {
111+
try {
112+
if (window.nil) {
113+
const accounts = await window.nil.request({
114+
method: "eth_requestAccounts",
115+
});
116+
setAccount(accounts[0]);
117+
setWalletConnected(true);
118+
} else {
119+
alert("Please install =nil; wallet from the chrome store!");
120+
}
121+
} catch (error) {
122+
console.error("Error connecting wallet:", error);
123+
}
124+
};
125+
```
126+
127+
---
128+
129+
### 2. **Reading Data from a Smart Contract**
130+
131+
To interact with a smart contract, we use the `getContract` method from `niljs`. This allows us to call both **view functions** (read operations) and **write functions** (state-changing operations).
132+
133+
In this particular case, we use it to read transaction data from the contract.
134+
135+
```javascript
136+
const fetchUserAmounts = async () => {
137+
if (!walletConnected || !account) return;
138+
139+
setIsLoadingAmounts(true);
140+
try {
141+
const client = await publicClient.publicClient;
142+
const contract = await getContract({
143+
abi: contractABI,
144+
address: contractAddress,
145+
client,
146+
});
147+
148+
const globalLedger = await contract.read.globalLedger();
149+
150+
const globalLedgerContract = await getContract({
151+
abi: globalLedgerAbi.abi,
152+
address: globalLedger,
153+
client,
154+
});
155+
156+
const ethDepositAmount = await globalLedgerContract.read.getDeposit([
157+
account,
158+
ETH,
159+
]);
160+
const usdtDepositAmount = await globalLedgerContract.read.getDeposit([
161+
account,
162+
USDT,
163+
]);
164+
165+
console.log("ETH deposit:", ethDepositAmount);
166+
console.log("USDT deposit:", usdtDepositAmount);
167+
} catch (error) {
168+
console.error("Error fetching user amounts:", error);
169+
} finally {
170+
setIsLoadingAmounts(false);
171+
}
172+
};
173+
```
174+
175+
If you want to **write to a contract**, please refer to [this example](https://github.com/NilFoundation/nil/blob/main/uniswap/tasks/uniswap/demo-router.ts#L81).
176+
177+
---
178+
179+
### 3. **Calling a Contract Method with and Without Tokens**
180+
181+
There are two ways to interact with smart contracts: calling a method **without** tokens (e.g., borrowing) and calling a method **with** tokens (e.g., deposit or repay).
182+
183+
#### Example: Calling a Method Without Tokens (Borrowing)
184+
185+
```javascript
186+
const handleBorrow = async () => {
187+
if (!walletConnected || !amount) return;
188+
189+
try {
190+
const token = selectedToken === "ETH" ? ETH : USDT;
191+
const data = encodeFunctionData({
192+
abi: contractABI,
193+
functionName: "borrow",
194+
args: [Number(amount), token],
195+
});
196+
197+
const txData = {
198+
to: contractAddress,
199+
data,
200+
};
201+
202+
await window.nil.request({
203+
method: "eth_sendTransaction",
204+
params: [txData],
205+
});
206+
} catch (error) {
207+
console.error("Error in borrowing:", error);
208+
}
209+
};
210+
```
211+
212+
#### Example: Calling a Method With Tokens (Deposit or Repay)
213+
214+
```javascript
215+
const handleDeposit = async () => {
216+
if (!walletConnected || !amount) return;
217+
218+
try {
219+
const token = selectedToken === "ETH" ? ETH : USDT;
220+
const data = encodeFunctionData({
221+
abi: contractABI,
222+
functionName: "deposit",
223+
});
224+
225+
const txData = {
226+
to: contractAddress,
227+
data,
228+
tokens: [
229+
{
230+
id: token,
231+
amount: Number(amount),
232+
},
233+
],
234+
};
235+
236+
await window.nil.request({
237+
method: "eth_sendTransaction",
238+
params: [txData],
239+
});
240+
} catch (error) {
241+
console.error("Error in depositing:", error);
242+
}
243+
};
244+
```
245+
246+
---
247+
248+
### 4. **Error Handling in Transactions**
249+
250+
Handling errors in blockchain transactions is crucial. This application shows how you can processes transaction receipts and extracts error messages when transactions fail.
251+
252+
Example: Processing Errors from Receipts
253+
254+
```javascript
255+
export function processReceipts(receipts) {
256+
for (let i = 0; i < receipts.length; i++) {
257+
const receipt = receipts[i];
258+
259+
// If the transaction is not successful, return the error message or status
260+
if (!receipt.success || receipt.status !== "Success") {
261+
const errorMessage = receipt.errorMessage || receipt.status;
262+
return errorMessage; // Exit the loop and return the first error message encountered
263+
}
264+
}
265+
266+
// If all transactions are successful, return null
267+
return null;
268+
}
269+
```
270+
271+
This function is used after transactions are completed to check if any errors occurred.
272+
273+
```javascript
274+
const receipts = await waitTillCompleted(client, txHash);
275+
const error = processReceipts(receipts);
276+
if (error) {
277+
console.log(`Transaction failed: ${error}`);
278+
alert(`Transaction failed: ${error}`);
279+
} else {
280+
alert("Transaction successful!");
281+
}
282+
```
283+
This ensures that failed transactions return clear error messages to the user.
284+
285+
## Contribution Guidelines
286+
287+
1. **Fork** the repository.
288+
2. Check for open issues [here](https://github.com/NilFoundation/nil/issues).
289+
3. Read the [Contribution Guide](https://github.com/NilFoundation/nil/blob/main/CONTRIBUTION-GUIDE.md).
290+
4. **Submit** a pull request with a detailed description of your changes based on the Contribution Guide.
291+
292+
Feel free to contribute and report any issues you encounter. Happy coding!

0 commit comments

Comments
 (0)