Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions packages/cli/src/commands/borrows/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
type ChainId,
type EvmAddress,
InvariantError,
invariant,
ok,
ResultAsync,
type UnexpectedError,
type UserBorrowItem,
type UserBorrowsRequest,
} from '@aave/client';

import { userBorrows } from '@aave/client/actions';

import * as common from '../../common.js';

export default class ListBorrows extends common.V4Command {
static override description = 'List user borrows for a specific chain';

static override flags = {
user: common.address({
required: true,
description: 'User address',
}),
chain_id: common.chain({
required: true,
description: 'Chain ID to query borrows from',
}),
};

override headers = [
{ value: 'Asset' },
{ value: 'Borrowed' },
{ value: 'Interest Owed' },
{ value: 'Total Debt' },
{ value: 'Borrow APY' },
{ value: 'Spoke' },
];

private getBorrowsRequest(): ResultAsync<
UserBorrowsRequest,
InvariantError | UnexpectedError
> {
return ResultAsync.fromPromise(
this.parse(ListBorrows),
(error) => new InvariantError(String(error)),
).andThen(({ flags }) => {
const user = flags.user as EvmAddress;
const chainId = flags.chain_id as ChainId;

invariant(user, 'You must provide a user address');
invariant(chainId, 'You must provide a chain ID');

return ok({
query: {
userChains: {
user,
chainIds: [chainId],
},
},
});
});
}

async run(): Promise<UserBorrowItem[] | InvariantError | UnexpectedError> {
const result = await this.getBorrowsRequest()
.andThen((request) => userBorrows(this.client, request))
.andThen((borrows) => {
if (borrows.length === 0) {
this.log('No borrows found for this user.');
return ok(borrows);
}

this.display(
borrows.map((item) => [
item.principal.token.info.name,
`${item.principal.amount.value.toFixed(4)} `,
`${item.interest.amount.value.toFixed(4)} `,
`${(item.debt.amount.value).toFixed(4)} `,
`${item.reserve.summary.borrowApy.normalized.toFixed(4)}%`,
item.reserve.spoke.name,
]),
);
return ok(borrows);
});

if (result.isErr()) {
this.error(result.error);
}

return result.value;
}
}
94 changes: 94 additions & 0 deletions packages/cli/src/commands/positions/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import {
type ChainId,
type EvmAddress,
InvariantError,
invariant,
ok,
ResultAsync,
type UnexpectedError,
type UserPosition,
type UserPositionsRequest,
} from '@aave/client';
import { userPositions } from '@aave/client/actions';

import * as common from '../../common.js';

export default class ListPositions extends common.V4Command {
static override description = 'List user positions across chains';

static override flags = {
user: common.address({
required: true,
description: 'User address',
}),
chain_id: common.chain({
required: true,
description: 'Filter by chain ID',
}),
};

override headers = [
{ value: 'Position ID' },
{ value: 'Spoke' },
{ value: 'Chain' },
{ value: 'Total Supplied' },
{ value: 'Total Borrowed' },
{ value: 'Health Factor' },
{ value: 'Collateral Enabled' },
];

private getPositionsRequest(): ResultAsync<
UserPositionsRequest,
InvariantError | UnexpectedError
> {
return ResultAsync.fromPromise(
this.parse(ListPositions),
(error) => new InvariantError(String(error)),
).andThen(({ flags }) => {
const user = flags.user as EvmAddress;
const chainId = flags.chain_id as ChainId;

invariant(user, 'You must provide a user address');
invariant(chainId, 'You must provide a chain ID');

return ok({
user,
filter: {
chainIds: [chainId],
},
});
});
}

async run(): Promise<UserPosition[] | InvariantError | UnexpectedError> {
const result = await this.getPositionsRequest()
.andThen((request) => userPositions(this.client, request))
.andThen((positions) => {
if (positions.length === 0) {
this.log('No positions found for this user');
return ok(positions);
}

this.display(
positions.map((item) => [
item.id,
item.spoke.name,
`${item.spoke.chain.name} (id=${item.spoke.chain.chainId})`,
`${item.totalSupplied.current.symbol}${item.totalSupplied.current.value.toFixed(2)}`,
`${item.totalDebt.current.symbol}${item.totalDebt.current.value.toFixed(2)}`,
item.healthFactor.current?.toFixed(2) ?? 'N/A',
Number(item.totalCollateral.current.value.toFixed(0)) > 0
? 'Yes'
: 'No',
]),
);
return ok(positions);
});

if (result.isErr()) {
this.error(result.error);
}

return result.value;
}
}
94 changes: 94 additions & 0 deletions packages/cli/src/commands/supplies/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import {
type ChainId,
type EvmAddress,
InvariantError,
invariant,
ok,
ResultAsync,
type UnexpectedError,
type UserSuppliesRequest,
type UserSupplyItem,
} from '@aave/client';
import { userSupplies } from '@aave/client/actions';

import * as common from '../../common.js';

export default class ListSupplies extends common.V4Command {
static override description = 'List user supplies for a specific chain';

static override flags = {
user: common.address({
required: true,
description: 'User address',
}),
chain_id: common.chain({
required: true,
description: 'Chain ID to query supplies from',
}),
};

override headers = [
{ value: 'Asset' },
{ value: 'Supplied' },
{ value: 'Interest Earned' },
{ value: 'Withdrawable' },
{ value: 'APY' },
{ value: 'Collateral' },
{ value: 'Spoke' },
];

private getSuppliesRequest(): ResultAsync<
UserSuppliesRequest,
InvariantError | UnexpectedError
> {
return ResultAsync.fromPromise(
this.parse(ListSupplies),
(error) => new InvariantError(String(error)),
).andThen(({ flags }) => {
const user = flags.user as EvmAddress;
const chainId = flags.chain_id as ChainId;

invariant(user, 'You must provide a user address');
invariant(chainId, 'You must provide a chain ID');

return ok({
query: {
userChains: {
user,
chainIds: [chainId],
},
},
});
});
}

async run(): Promise<UserSupplyItem[] | InvariantError | UnexpectedError> {
const result = await this.getSuppliesRequest()
.andThen((request) => userSupplies(this.client, request))
.andThen((supplies) => {
if (supplies.length === 0) {
this.log('No supplies found for this user');
return ok(supplies);
}

this.display(
supplies.map((item) => [
`${item.reserve.asset.underlying.info.name} (${item.reserve.asset.underlying.info.symbol})`,
`${item.principal.amount.value.toFixed(4)} `,
`${item.interest.amount.value.toFixed(4)} `,
`${item.withdrawable.amount.value.toFixed(4)}`,
`${item.reserve.summary.supplyApy.normalized.toFixed(4)}%`,
item.isCollateral ? 'Yes' : 'No',
item.reserve.spoke.name,
]),
);
return ok(supplies);
});

if (result.isErr()) {
this.error(result.error);
}

return result.value;
}
}