Skip to content
Draft
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
1,145 changes: 1,117 additions & 28 deletions sui-agent/package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions sui-agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"license": "ISC",
"description": "",
"dependencies": {
"@mysten/sui": "^1.21.0",
"@suilend/sdk": "^1.1.36",
"aftermath-ts-sdk": "^1.2.49",
"atoma-sdk": "github:atoma-network/atoma-sdk-typescript",
"axios": "^1.7.9",
Expand All @@ -32,7 +34,7 @@
"@types/express": "^5.0.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"prettier": "^3.4.2",
"eslint": "^8.57.0"
"eslint": "^8.57.0",
"prettier": "^3.4.2"
}
}
242 changes: 242 additions & 0 deletions sui-agent/src/agents/ToolRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ import {
getAfSuiExchangeRateWrapper,
getStakeTransactionWrapper,
} from '../utils/toolWrappers';
import {
depositIntoObligationWrapper,
depositLiquidityAndGetCTokensWrapper,
redeemCtokensAndWithdrawLiquidityWrapper,
withdrawAndSendToUserWrapper,
} from '../tools/suilend/depositWithdraw';
import {
borrowAndSendToUserWrapper,
repayIntoObligationWrapper,
} from '../tools/suilend/borrowRepay';
import { liquidateAndRedeemWrapper } from '../tools/suilend/liquidation';

/*
format for tool registry is:
Expand Down Expand Up @@ -565,4 +576,235 @@ export function registerAllTools(tools: Tools) {
],
getStakeTransactionWrapper,
);

// Suilend Tools

// 1. Deposit Into Obligation
tools.registerTool(
'deposit_into_obligation',
'Tool to deposit coins into an obligation',
[
{
name: 'lendingMarketId',
type: 'string',
description: 'ID of the lending market',
required: true,
},
{
name: 'lendingMarketType',
type: 'string',
description: 'Type of the lending market',
required: true,
},
{
name: 'ownerId',
type: 'string',
description: 'Address of the owner',
required: true,
},
{
name: 'coinType',
type: 'string',
description: 'Type of coin to deposit',
required: true,
},
{
name: 'value',
type: 'string',
description: 'Amount to deposit (in base units)',
required: true,
},
{
name: 'obligationOwnerCapId',
type: 'string',
description: 'Obligation owner capability ID',
required: true,
},
],
depositIntoObligationWrapper,
);

// 2. Deposit Liquidity and Get CTokens
tools.registerTool(
'deposit_liquidity_get_ctokens',
'Tool to deposit liquidity and receive CTokens',
[
{
name: 'lendingMarketId',
type: 'string',
description: 'ID of the lending market',
required: true,
},
{
name: 'lendingMarketType',
type: 'string',
description: 'Type of the lending market',
required: true,
},
{
name: 'ownerId',
type: 'string',
description: 'Address of the owner',
required: true,
},
{
name: 'coinType',
type: 'string',
description: 'Type of coin to deposit',
required: true,
},
{
name: 'value',
type: 'string',
description: 'Amount to deposit (in base units)',
required: true,
},
],
depositLiquidityAndGetCTokensWrapper,
);

// 3. Withdraw and Send to User
tools.registerTool(
'withdraw_and_send',
'Tool to withdraw funds and send them to a user',
[
{
name: 'lendingMarketId',
type: 'string',
description: 'ID of the lending market',
required: true,
},
{
name: 'lendingMarketType',
type: 'string',
description: 'Type of the lending market',
required: true,
},
{
name: 'ownerId',
type: 'string',
description: 'Address of the recipient',
required: true,
},
{
name: 'obligationOwnerCapId',
type: 'string',
description: 'Obligation owner capability ID',
required: true,
},
{
name: 'obligationId',
type: 'string',
description: 'ID of the obligation',
required: true,
},
{
name: 'coinType',
type: 'string',
description: 'Type of coin to withdraw',
required: true,
},
{
name: 'value',
type: 'string',
description: 'Amount to withdraw (in base units)',
required: true,
},
],
withdrawAndSendToUserWrapper,
);

// 4. Redeem CTokens and Withdraw Liquidity
tools.registerTool(
'redeem_ctokens_and_withdraw',
'Tool to redeem CTokens and withdraw underlying liquidity',
[
{
name: 'lendingMarketId',
type: 'string',
description: 'ID of the lending market',
required: true,
},
{
name: 'lendingMarketType',
type: 'string',
description: 'Type of the lending market',
required: true,
},
{
name: 'ownerId',
type: 'string',
description: 'Address of the owner',
required: true,
},
{
name: 'ctokenCoinTypes',
type: 'array',
description: 'Array of CToken coin types to redeem',
required: true,
},
],
redeemCtokensAndWithdrawLiquidityWrapper,
);

// 5. Borrow and Send to User
tools.registerTool(
'borrow_and_send',
'Tool to borrow funds and send them to a user',
[],
borrowAndSendToUserWrapper,
);

// 6. Repay Into Obligation
tools.registerTool(
'repay_into_obligation',
'Tool to repay funds into an obligation',
[],
repayIntoObligationWrapper,
);

// 7. Liquidate and Redeem
tools.registerTool(
'liquidate_and_redeem',
'Tool to liquidate an underwater position and redeem collateral',
[
{
name: 'lendingMarketId',
type: 'string',
description: 'ID of the lending market',
required: true,
},
{
name: 'lendingMarketType',
type: 'string',
description: 'Type of the lending market',
required: true,
},
{
name: 'obligation',
type: 'string',
description: 'ID of the obligation to liquidate',
required: true,
},
{
name: 'repayCoinType',
type: 'string',
description: 'Type of coin used to repay the debt',
required: true,
},
{
name: 'withdrawCoinType',
type: 'string',
description: 'Type of collateral coin to withdraw',
required: true,
},
{
name: 'repayCoinId',
type: 'string',
description: 'ID of the coin object used for repayment',
required: true,
},
],
liquidateAndRedeemWrapper,
);
}
112 changes: 112 additions & 0 deletions sui-agent/src/tools/suilend/borrowRepay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { Transaction } from '@mysten/sui/transactions';
import { handleError } from '../../utils';
import { suilendClientWrapper } from '.';

/**
* Borrow and send funds to user
* @param ownerId - The owner ID
* @param obligationOwnerCapId - The obligation owner cap ID
* @param obligationId - The obligation ID
* @param coinType - The coin type
* @param value - The value
* @returns A JSON string containing the result of the borrow and send to user operation
*/
export async function borrowAndSendToUserWrapper(
ownerId: string,
obligationOwnerCapId: string,
obligationId: string,
coinType: string,
value: string,
): Promise<string> {
try {
const client = await suilendClientWrapper();
const transaction = new Transaction();
await client.borrowAndSendToUser(
ownerId,
obligationOwnerCapId,
obligationId,
coinType,
value,
transaction,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the setup is generally cool. Except the transaction is not properly handled / We have errors with the transaction. We can have a separated util for suilend transactions.

);
return JSON.stringify([
{
reasoning: 'Successfully borrowed and sent funds to user',
response: JSON.stringify(
{
ownerId: ownerId,
obligationId: obligationId,
coinType: coinType,
borrowedAmount: value,
status: 'success',
},
null,
2,
),
status: 'success',
query: `Borrowed ${value} of ${coinType} for ${ownerId}`,
errors: [],
},
]);
} catch (error: unknown) {
return JSON.stringify([
handleError(error, {
reasoning: 'Failed to borrow and send funds to user',
query: `Attempted to borrow ${value} of ${coinType}`,
}),
]);
}
}

/**
* Repay into obligation
* @param ownerId - The owner ID
* @param obligationId - The obligation ID
* @param coinType - The coin type
* @param value - The value
* @returns A JSON string containing the result of the repay into obligation operation
*/
export async function repayIntoObligationWrapper(
ownerId: string,
obligationId: string,
coinType: string,
value: string,
): Promise<string> {
try {
const client = await suilendClientWrapper();
const transaction = new Transaction();
await client.repayIntoObligation(
ownerId,
obligationId,
coinType,
value,
transaction,
);
return JSON.stringify([
{
reasoning: 'Successfully repaid into obligation',
response: JSON.stringify(
{
ownerId: ownerId,
obligationId: obligationId,
coinType: coinType,
repaidAmount: value,
status: 'success',
},
null,
2,
),
status: 'success',
query: `Repaid ${value} of ${coinType} into obligation`,
errors: [],
},
]);
} catch (error: unknown) {
return JSON.stringify([
handleError(error, {
reasoning: 'Failed to repay into obligation',
query: `Attempted to repay ${value} of ${coinType}`,
}),
]);
}
}
Loading