Skip to content

Commit 6e67683

Browse files
authored
test: borrow (#11)
1 parent 98bbfb3 commit 6e67683

File tree

7 files changed

+170
-18
lines changed

7 files changed

+170
-18
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
"test:client": "vitest --project client",
2323
"test:client:local": "ENVIRONMENT=local vitest --project client",
2424
"test:react": "vitest --project react",
25+
"test:withdraw": "vitest --project client packages/client/src/actions/withdraw.test.ts",
26+
"test:borrow": "vitest --project client packages/client/src/actions/borrow.test.ts",
2527
"test": "vitest"
2628
},
2729
"license": "MIT",

packages/client/src/actions/__snapshots__/markets.test.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ exports[`Given the Aave Protocol v3 > When fetching user market state > Then it
9393
"__typename": "MarketUserState",
9494
"availableBorrowsBase": Any<String>,
9595
"currentLiquidationThreshold": Any<String>,
96-
"eModeEnabled": Any<Boolean>,
96+
"eModeEnabled": false,
9797
"healthFactor": Any<String>,
98-
"isInIsolationMode": Any<Boolean>,
98+
"isInIsolationMode": false,
9999
"ltv": Any<String>,
100100
"netAPY": Any<String>,
101101
"netWorth": Any<String>,
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import type {
2+
Market,
3+
MarketUserReserveSupplyPosition,
4+
SupplyRequest,
5+
} from '@aave/graphql';
6+
import { assertOk, bigDecimal, evmAddress } from '@aave/types';
7+
import type { WalletClient } from 'viem';
8+
import { beforeAll, describe, expect, it } from 'vitest';
9+
import {
10+
client,
11+
createNewWallet,
12+
DEFAULT_MARKET_ADDRESS,
13+
ETHEREUM_FORK_ID,
14+
fundErc20Address,
15+
WETH_ADDRESS,
16+
} from '../test-utils';
17+
import { sendWith } from '../viem';
18+
import { market } from './markets';
19+
import { borrow, collateralToggle, supply } from './transactions';
20+
import { userBorrows, userSupplies } from './user';
21+
22+
async function supplyAndCheck(
23+
wallet: WalletClient,
24+
request: SupplyRequest,
25+
): Promise<MarketUserReserveSupplyPosition[]> {
26+
const userAddress = evmAddress(wallet.account!.address);
27+
const result = await supply(client, request)
28+
.andThen(sendWith(wallet))
29+
.andThen(() =>
30+
userSupplies(client, {
31+
markets: [{ address: request.market, chainId: request.chainId }],
32+
user: userAddress,
33+
}),
34+
);
35+
assertOk(result);
36+
expect(result.value).toEqual([
37+
expect.objectContaining({
38+
balance: expect.objectContaining({
39+
amount: expect.objectContaining({
40+
value: expect.toBeBigDecimalCloseTo(
41+
'erc20' in request.amount
42+
? request.amount.erc20.value
43+
: request.amount.native,
44+
),
45+
}),
46+
}),
47+
// Check if the position can be used as collateral
48+
canBeCollateral: true,
49+
}),
50+
]);
51+
return result.value!;
52+
}
53+
54+
describe('Given an Aave Market', () => {
55+
let marketInfo: Market;
56+
let initialPosition: MarketUserReserveSupplyPosition | undefined;
57+
58+
const wallet: WalletClient = createNewWallet();
59+
60+
beforeAll(async () => {
61+
// Set up market info first
62+
const result = await market(client, {
63+
address: DEFAULT_MARKET_ADDRESS,
64+
chainId: ETHEREUM_FORK_ID,
65+
});
66+
assertOk(result);
67+
marketInfo = result.value!;
68+
69+
// Set up wallet and supply position
70+
await fundErc20Address(
71+
WETH_ADDRESS,
72+
evmAddress(wallet.account!.address),
73+
bigDecimal('0.011'),
74+
);
75+
const supplyResult = await supplyAndCheck(wallet, {
76+
market: marketInfo.address,
77+
chainId: marketInfo.chain.chainId,
78+
supplier: evmAddress(wallet.account!.address),
79+
amount: {
80+
erc20: {
81+
currency: WETH_ADDRESS,
82+
value: '0.01',
83+
},
84+
},
85+
});
86+
initialPosition = supplyResult[0];
87+
});
88+
89+
describe('And a user with a supply position', () => {
90+
describe('When user set the supply as collateral', async () => {
91+
it('Then it should be possible to borrow from the reserve', async () => {
92+
// Enable collateral
93+
const result = await collateralToggle(client, {
94+
market: initialPosition!.market.address,
95+
underlyingToken: initialPosition!.currency.address,
96+
chainId: initialPosition!.market.chain.chainId,
97+
user: evmAddress(wallet.account!.address),
98+
})
99+
.andThen(sendWith(wallet))
100+
.andTee((tx) => console.log(`tx to enable collateral: ${tx}`))
101+
.andThen(() => {
102+
return userSupplies(client, {
103+
markets: [
104+
{
105+
address: initialPosition!.market.address,
106+
chainId: initialPosition!.market.chain.chainId,
107+
},
108+
],
109+
user: evmAddress(wallet.account!.address),
110+
});
111+
});
112+
assertOk(result);
113+
expect(result.value).toEqual([
114+
expect.objectContaining({
115+
isCollateral: true,
116+
}),
117+
]);
118+
119+
// Borrow from the reserve
120+
const borrowReserve = marketInfo.borrowReserves.find(
121+
(reserve) => reserve.underlyingToken.symbol === 'USDC',
122+
)!;
123+
const borrowResult = await borrow(client, {
124+
market: marketInfo.address,
125+
chainId: marketInfo.chain.chainId,
126+
borrower: evmAddress(wallet.account!.address),
127+
amount: {
128+
erc20: {
129+
currency: borrowReserve.underlyingToken.address,
130+
value: '10',
131+
},
132+
},
133+
})
134+
.andThen(sendWith(wallet))
135+
.andTee((tx) => console.log(`tx to borrow: ${tx}`))
136+
.andThen(() =>
137+
userBorrows(client, {
138+
markets: [
139+
{
140+
address: marketInfo.address,
141+
chainId: marketInfo.chain.chainId,
142+
},
143+
],
144+
user: evmAddress(wallet.account!.address),
145+
}),
146+
);
147+
assertOk(borrowResult);
148+
});
149+
});
150+
});
151+
});

packages/client/src/actions/borrow.todo.ts

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
// THIS IS A VERY WIP
4+
5+
describe('Given an Aave Market', () => {
6+
describe('And a user with a supply position', () => {
7+
describe('When the user enables e-mode for that market', () => {
8+
it('Then it should be possible to borrow from the reserve', () => {
9+
expect(true).toBe(true);
10+
});
11+
});
12+
});
13+
});

packages/client/src/actions/markets.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ describe('Given the Aave Protocol v3', () => {
6060
expect(result.value).toMatchSnapshot({
6161
availableBorrowsBase: expect.any(String),
6262
currentLiquidationThreshold: expect.any(String),
63-
eModeEnabled: expect.any(Boolean),
6463
healthFactor: expect.any(String),
65-
isInIsolationMode: expect.any(Boolean),
6664
ltv: expect.any(String),
6765
netAPY: expect.any(String),
6866
netWorth: expect.any(String),

packages/graphql/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
"gql:download:staging": "gql-tada generate schema 'https://api.v3.staging.aave.com/graphql' --output './schema.graphql'",
4141
"gql:download:local": "gql-tada generate schema 'http://localhost:3011/graphql' --output './schema.graphql'",
4242
"gql:generate": "gql-tada generate output",
43-
"gql:turbo": "gql-tada turbo"
43+
"gql:turbo": "gql-tada turbo",
44+
"prebuild": "pnpm run gql:turbo"
4445
},
4546
"dependencies": {
4647
"@aave/types": "workspace:*",

0 commit comments

Comments
 (0)