Skip to content

Commit 8e4233e

Browse files
committed
fix: items
1 parent 251dc2a commit 8e4233e

File tree

7 files changed

+67
-26
lines changed

7 files changed

+67
-26
lines changed

apps/web-app/src/components/MoneyMarket/components/BorrowDialog/BorrowDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ const BorrowDialogForm = () => {
104104
};
105105

106106
const handleEscapes = (e: Event) => {
107-
borrowRequestStore.getState().reset();
107+
// borrowRequestStore.getState().reset();
108108
e.preventDefault();
109109
};
110110

apps/web-app/src/components/MoneyMarket/components/LendDialog/LendDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ const LendDialogForm = () => {
9494
};
9595

9696
const handleEscapes = (e: Event) => {
97-
lendRequestStore.getState().reset();
97+
// lendRequestStore.getState().reset();
9898
e.preventDefault();
9999
};
100100

apps/web-app/src/components/MoneyMarket/components/WithdrawDialog/WithdrawDialog.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { Item, ItemContent, ItemGroup } from '@/components/ui/item';
1313
import { useAppForm } from '@/hooks/app-form';
1414
import { sdk } from '@/lib/sdk';
1515
import { useSlayerTx } from '@/lib/transactions';
16+
import { shouldUseFullAmount } from '@/lib/utils';
1617
import { validateDecimal } from '@/lib/validations';
1718
import { Decimal } from '@sovryn/slayer-shared';
1819
import { useMemo } from 'react';
@@ -101,8 +102,9 @@ const WithdrawDialogForm = () => {
101102
token: position.token,
102103
},
103104
value.amount,
104-
// if max amount + summary.borrowPowerUsed.eq(0) then flag it as true
105-
false,
105+
// if position can be withdrawn in full and user entered near full amount, use full withdrawal to avoid dust issues
106+
maximumWithdrawAmount.eq(position.supplied) &&
107+
shouldUseFullAmount(value.amount, position.supplied),
106108
{
107109
account: address!,
108110
},
@@ -124,7 +126,7 @@ const WithdrawDialogForm = () => {
124126
};
125127

126128
const handleEscapes = (e: Event) => {
127-
withdrawRequestStore.getState().reset();
129+
// withdrawRequestStore.getState().reset();
128130
e.preventDefault();
129131
};
130132

apps/web-app/src/lib/transactions/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import type { SdkTransactionRequest } from '@sovryn/slayer-sdk';
2+
import debug from 'debug';
23
import { useCallback, useEffect } from 'react';
34
import type { Account, Chain } from 'viem';
45
import { useStore } from 'zustand';
56
import { txStore, type TxHandlers } from './store';
67

8+
const log = debug('slayer-app:useSlayerTx');
9+
710
export const useSlayerTx = <chain extends Chain, account extends Account>(
811
handlers: TxHandlers = {},
912
) => {
@@ -12,14 +15,18 @@ export const useSlayerTx = <chain extends Chain, account extends Account>(
1215
const begin = useCallback(
1316
async (waitFor: () => Promise<SdkTransactionRequest<chain, account>[]>) => {
1417
setIsFetching(true);
18+
log('Beginning transaction preparation...');
1519
if (waitFor) {
1620
const txs = await waitFor();
21+
log('Prepared transactions:', txs);
1722
setItems(txs);
1823
setHandlers(handlers);
1924
return new Promise<boolean>((resolve) => {
2025
const originalOnClosed = handlers.onClosed;
2126
handlers.onClosed = (withSuccess: boolean) => {
27+
log('Transaction modal closed with success:', withSuccess);
2228
if (originalOnClosed) {
29+
log('Calling onClosed handler with success:', withSuccess);
2330
originalOnClosed(withSuccess);
2431
}
2532
resolve(withSuccess);

apps/web-app/src/lib/utils.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ export function cn(...inputs: Array<ClassValue>) {
77
return twMerge(clsx(inputs));
88
}
99

10-
export function isFullAmount<T extends Decimalish = Decimalish>(
10+
// if value is within percentageThreshold of total, return true
11+
// e.g. value=99, total=100, percentageThreshold=1 => true
12+
// it helps to decide whether to use full amount in cases like withdrawing nearly all supplied assets
13+
export function shouldUseFullAmount<T extends Decimalish = Decimalish>(
1114
value: T,
1215
total: T,
13-
// default to 0.1% threshold
14-
percentageThreshold = 0.1,
16+
// default to 0.5% (half percent) threshold
17+
percentageThreshold = 0.5,
1518
): boolean {
1619
const decimalValue = Decimal.from(value);
1720
const decimalTotal = Decimal.from(total);

packages/sdk/src/managers/money-market/money-market.manager.ts

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { areAddressesEqual, Decimal, Decimalish } from '@sovryn/slayer-shared';
2+
import debug from 'debug';
23
import { Account, Address, encodeFunctionData, type Chain } from 'viem';
4+
import { bobSepolia } from 'viem/chains';
35
import { BaseClient, type SdkRequestOptions } from '../../lib/context.js';
46
import { buildQuery, toAddress } from '../../lib/helpers.js';
57
import {
@@ -16,6 +18,12 @@ import {
1618
TransactionOpts,
1719
} from '../../types.js';
1820

21+
const log = debug('slayer-sdk:managers:money-market');
22+
23+
const aWETH = {
24+
[bobSepolia.id]: '0x63719589aC40057556a791FAa701264567b5b627',
25+
} as const;
26+
1927
const poolAbi = [
2028
{
2129
type: 'function',
@@ -63,17 +71,6 @@ const poolAbi = [
6371
],
6472
outputs: [],
6573
},
66-
{
67-
type: 'function',
68-
name: 'withdrawETH',
69-
stateMutability: 'nonpayable',
70-
inputs: [
71-
{ type: 'address', name: 'pool' },
72-
{ type: 'uint256', name: 'amount' },
73-
{ type: 'address', name: 'to' },
74-
],
75-
outputs: [],
76-
},
7774
{
7875
type: 'function',
7976
name: 'setUserUseReserveAsCollateral',
@@ -123,6 +120,18 @@ const wethGatewayAbi = [
123120
],
124121
outputs: [],
125122
},
123+
124+
{
125+
type: 'function',
126+
name: 'withdrawETH',
127+
stateMutability: 'nonpayable',
128+
inputs: [
129+
{ type: 'address', name: 'pool' },
130+
{ type: 'uint256', name: 'amount' },
131+
{ type: 'address', name: 'to' },
132+
],
133+
outputs: [],
134+
},
126135
] as const;
127136

128137
export class MoneyMarketManager<chain extends Chain> extends BaseClient<chain> {
@@ -323,9 +332,21 @@ export class MoneyMarketManager<chain extends Chain> extends BaseClient<chain> {
323332
const pool = reserve.pool;
324333
const value = Decimal.from(amount);
325334

335+
log(
336+
`Preparing withdraw of ${value.toString()} ${asset.symbol} from pool ${pool.id}`,
337+
{ reserve, amount, isMaxAmount, opts },
338+
);
339+
326340
if (asset.isNative || areAddressesEqual(asset.address, pool.weth)) {
341+
const aWethAddress = aWETH[this.ctx.chainId as keyof typeof aWETH];
342+
if (!aWethAddress) {
343+
throw new Error(
344+
`aWETH address not configured for chain ${this.ctx.chainId}`,
345+
);
346+
}
347+
327348
const approval = await makeApprovalTransaction({
328-
token: pool.weth,
349+
token: aWethAddress,
329350
spender: pool.wethGateway,
330351
amount: isMaxAmount
331352
? Decimal.MAX_UINT_256.toBigInt()
@@ -350,12 +371,12 @@ export class MoneyMarketManager<chain extends Chain> extends BaseClient<chain> {
350371
title: `Withdraw ${asset.symbol}`,
351372
description: `Withdraw ${value.toString()} ${asset.symbol}`,
352373
request: makeTransactionRequest({
353-
to: pool.address,
374+
to: pool.wethGateway,
354375
value: 0n,
355376
chain: this.ctx.publicClient.chain,
356377
account: opts.account,
357378
data: encodeFunctionData({
358-
abi: poolAbi,
379+
abi: wethGatewayAbi,
359380
functionName: 'withdrawETH',
360381
args: [
361382
toAddress(pool.address),

packages/shared/src/lib/decimal.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ D.set({
1111
});
1212

1313
const DEFAULT_PRECISION = 18;
14+
const MAX_UINT_128 = '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
1415
const MAX_UINT_256 =
1516
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
1617

@@ -24,12 +25,19 @@ export class Decimal {
2425

2526
static ZERO = new Decimal('0');
2627
static ONE = new Decimal('1');
27-
static INFINITY = new Decimal('Infinity', 0);
28-
static MAX_UINT_256 = new Decimal(MAX_UINT_256, 0);
28+
static INFINITY = new Decimal(MAX_UINT_256, 0).sub('1', 0);
29+
static MAX_UINT_128 = new Decimal(MAX_UINT_128, 0).sub('1', 0);
30+
static MAX_UINT_256 = new Decimal(MAX_UINT_256, 0).sub('1', 0);
2931

3032
static DEFAULT_PRECISION = DEFAULT_PRECISION;
3133

3234
constructor(value: string, precision: number = DEFAULT_PRECISION) {
35+
if (value?.toLowerCase() === 'infinity') {
36+
this.d = new D(MAX_UINT_256).sub(new D(1));
37+
this.precision = 0;
38+
return;
39+
}
40+
3341
this.d = new D(value);
3442
this.precision = precision;
3543
}
@@ -47,8 +55,8 @@ export class Decimal {
4755
}
4856

4957
if (typeof value === 'string') {
50-
if (value === 'Infinity') {
51-
return new Decimal(MAX_UINT_256, 0);
58+
if (value?.toLowerCase() === 'infinity') {
59+
return new Decimal(MAX_UINT_256, 0).sub('1', 0);
5260
}
5361

5462
if (!stringRepresentationFormat.test(value)) {

0 commit comments

Comments
 (0)