Skip to content

Conversation

@AmpedFinance
Copy link

@AmpedFinance AmpedFinance commented Jan 25, 2025

Amped Finance Integration

Description

Implementation of Amped Finance perpetual swaps and AMM exchange integration:

Core Features

✅ Liquidity Operations

  • Add/Remove liquidity (Single token operations)
  • ALP token management
  • Liquidity pool balance tracking

✅ Leveraged Trading

  • Long position management
  • Position size/leverage validation

✅ Information Services

  • Real-time position tracking
  • Liquidity pool analytics
  • Return estimation calculators

✅ Risk Management

  • Slippage protection (0.3% default)
  • Leverage limits enforcement
  • Position size validation

Technical Improvements

Enhanced error handling with contextual messages
Robust input validation for financial operations
Type-safe implementations for core operations
Gas-optimized transaction building
Comprehensive response formatting

Supported Networks

Sonic (Mainnet)

Test Results

All core test suites passing (6/6):

  • ✅ Liquidity Operations
  • ✅ Position Management
  • ✅ Trading Validation
  • ✅ Risk Parameters
  • ✅ Information Queries
  • ✅ Error Handling

Implementation Details

Modular architecture with separated concerns:

  • Liquidity management module
  • Perpetual trading engine
  • Risk management system

Features

  • Leveraged perpetual trading (up to 11x)
  • Single-asset liquidity provisioning
  • Real-time position monitoring
  • ALP token redemption
  • Collateral management
  • Risk parameter enforcement
  • Position P&L calculations

Next Steps

  • Limit orders implementation
  • Trigger orders for TP and SL
  • Partial close of open positions

References
Amped Finance
Protocol Type: Decentralized Perpetual Exchange
Twitter: @AmpedFinance
Documentation: https://amped.gitbook.io/amped/

@AmpedFinance AmpedFinance changed the title feat: [WIP] Amped Finance integration feat: Amped Finance integration Feb 2, 2025
@AmpedFinance AmpedFinance changed the title feat: Amped Finance integration feat: Amped Finance Feb 2, 2025
[NETWORKS.BASE]: 8453
} as const;

export const RPC_URLS = {
Copy link
Contributor

Choose a reason for hiding this comment

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

do not need do this. Check venus project and how we get provider

export const BASIS_POINTS_DIVISOR = 10000;

// Supported chains
export const supportedChains = [146, 8453] as const;
Copy link
Contributor

Choose a reason for hiding this comment

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

too much redundant variables. Check venus project

NATIVE_TOKEN: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' as Address,
WRAPPED_NATIVE_TOKEN: '0x039e2fb66102314ce7b64ce5ce3e5183bc94ad38' as Address,
WETH: '0x50c42deacd8fc9773493ed674b675be577f2634b' as Address,
USDC: '0x29219dd400f2bf60e5a23d13be72b486d4038894' as Address,
Copy link
Contributor

Choose a reason for hiding this comment

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

No need create your own token list of USDC, WETH, etc...

decimals: 18,
},
rpcUrls: {
default: {
Copy link
Contributor

Choose a reason for hiding this comment

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

No need do this. We have proper way to get provider. Check venus project

export type SupportedNetwork = typeof NETWORKS[keyof typeof NETWORKS];

// Explicit lowercase chain name type for standardization
export type LowercaseChainName = 'sonic' | 'base';
Copy link
Contributor

Choose a reason for hiding this comment

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

what for this? If you want create enum with supported chains - do it.

* @param props.walletClient - Optional Viem Wallet Client for interacting with the blockchain
* @param options - System tools (notify)
* @returns Transaction result with liquidity addition details
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Why you have 2 addLiquidity functions? slippageTolerance - not use anywhere.

import { SupportedToken, getTokenAddress, getChainFromName } from '../../utils.js';
import type { PublicClient, WalletClient } from 'viem';
import { encodeFunctionData, Address } from 'viem';
import { Router } from '../../abis/Router.js';
Copy link
Contributor

Choose a reason for hiding this comment

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

this imports not use in code. We have strict rules in our project, it will not even compile with such imports and functions.

await notify(`Adding liquidity with ${tokenSymbol} on ${networkName}...`);

// Get user token balances
const userBalanceResult = await getUserTokenBalances({
Copy link
Contributor

Choose a reason for hiding this comment

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

why if user want work with one token we must fetch his balances for all supported tokens?

tokenSymbol: TokenSymbol;
amount: string;
slippageTolerance?: number;
percentOfBalance?: number;
Copy link
Contributor

Choose a reason for hiding this comment

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

percentOfBalance?: number; - it can't be undefined. Check venus project and how we treat optional parametrs

Comment on lines 206 to 238
if (allowance < amountInWei) {
await notify(`Allowance is ${formatUnits(allowance, tokenDecimals)}, needs ${formatUnits(amountInWei, tokenDecimals)}. Requesting approval for GlpManager...`);
try {
// Send approval with viem walletClient
const MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
await notify(`Setting unlimited approval (MAX_UINT256) for ${tokenSymbol} for GlpManager`);

await notify('Sending approval transaction with viem...');
approvalHash = await walletClient.writeContract({
address: tokenInAddress as `0x${string}`,
abi: ERC20,
functionName: 'approve',
args: [glpManagerAddressTyped, MAX_UINT256],
account: walletClient.account,
chain: walletClient.chain,
});

await notify(`Approval transaction sent: ${approvalHash}. Waiting for confirmation...`);
// Wait for receipt with viem publicClient
const receipt = await publicClient.waitForTransactionReceipt({ hash: approvalHash });

if (receipt.status === 'success') {
await notify('Approval confirmed.');
// Verify allowance after approval
const newAllowance = await publicClient.readContract({
address: tokenInAddress as `0x${string}`,
abi: ERC20,
functionName: 'allowance',
args: [account, glpManagerAddressTyped],
});
await notify(`New allowance for GlpManager: ${formatUnits(newAllowance, tokenDecimals)} ${tokenSymbol}`);
if (newAllowance < amountInWei) {
return toResult(`Approval transaction successful but allowance for GlpManager is still insufficient. Required: ${formatUnits(amountInWei, tokenDecimals)}, Granted: ${formatUnits(newAllowance, tokenDecimals)}`, true);
Copy link
Contributor

Choose a reason for hiding this comment

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

we have checkToApprove

* @returns APR information including base APR and reward rates
*/
export async function getALPAPR(
{ chainName, account, tokenAddress, publicClient }: Props,
Copy link
Contributor

Choose a reason for hiding this comment

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

tokenAddress - what for?

const rewardTokenPriceFormatted = Number(formatUnits(rewardTokenPrice, 30)).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 });
const rewardTokenSymbol = networkName === NETWORKS.SONIC ? 'wS' : 'WETH'; // Get symbol for logging

await options.notify('APR calculation completed');
Copy link
Contributor

@OoXooOx OoXooOx May 29, 2025

Choose a reason for hiding this comment

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

we have 1-3 notify in execute functions
You have -
marketSwap.ts: 8 occurrences
getSwapsLiquidity.ts: 14 occurrences
getPerpsLiquidity.ts: 14 occurrences
closePosition.ts: 12 occurrences
getPerpsLiquidity.ts (leverage folder): 14 occurrences
getAllOpenPositions.ts: 18 occurrences
getPosition.ts: 17 occurrences
claimRewards.ts: 3 occurrences

Copy link
Contributor

Choose a reason for hiding this comment

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

Here maybe it's correct, because all info which goes in toResult - going through AI and it can be cut or modified, but in notify you can convey immutable data to user. But no need such notify quantity in execution functions.

}

// Define the specific ABI for the functions we need
const GLP_TOKEN_ABI = [
Copy link
Contributor

Choose a reason for hiding this comment

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

why you have ABI here?

displaySymbol = 'ETH'; // Ensure display symbol is native
}

if (addressForVaultCall && addressForVaultCall !== '0x0000000000000000000000000000000000000000') {
Copy link
Contributor

Choose a reason for hiding this comment

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

viem -> zeroAddress

}

// Explicitly get contracts for the network to satisfy linter potentially
const currentNetworkContracts = CONTRACT_ADDRESSES[networkName];
Copy link
Contributor

Choose a reason for hiding this comment

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

you already check chain. currentNetworkContracts can't be undefined. You have a lot such redundant checks throughout all project.

Comment on lines 219 to 238
let receipt: TransactionReceipt | null = null;
let attempts = 0;
const maxAttempts = 5;
const retryDelayMs = 3000;

while (attempts < maxAttempts) {
try {
receipt = await publicClient.getTransactionReceipt({ hash: txHash });
if (receipt) {
break; // Exit loop if receipt is found
}
} catch (e) {
// Log error during attempts, but continue retrying
await notify(`Attempt ${attempts + 1} to get receipt failed: ${(e as Error).message}`);
}
attempts++;
if (attempts < maxAttempts) {
await notify(`Retrying in ${retryDelayMs / 1000}s... (${attempts}/${maxAttempts})`);
await new Promise(resolve => setTimeout(resolve, retryDelayMs));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

good idea with retry

return toResult(`Transaction ${txHash} failed with status: ${receipt.status}`, true);
}

const removeLiquidityEvents = receipt.logs.filter(log => {
Copy link
Contributor

Choose a reason for hiding this comment

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

too hard logic. Check venus project and way how parse events with viem

* @param options - System tools for blockchain interactions
* @returns Detailed information about the position including size, collateral, PnL, etc.
*/
export async function getPosition({ chainName, account, indexToken, collateralToken, isLong }: Props, { notify, getProvider }: FunctionOptions): Promise<FunctionReturn> {
Copy link
Contributor

Choose a reason for hiding this comment

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

we need proper names for args for AI. indexToken - > tokenSymbol, collateralToken -> collateralTokenSymbol

},
],
required: ['chainName', 'account', 'tokenSymbol'],
parameters: {
Copy link
Contributor

Choose a reason for hiding this comment

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

we don't have parameters in examples.

},
tokenSymbol: {
type: 'string',
description: `Symbol of the token to provide as liquidity. Sonic: ${sonicTokenSymbols}, Base: ${baseTokenSymbols}`,
Copy link
Contributor

Choose a reason for hiding this comment

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

If you want use enum - do it. Description is not proper place for supported token list

},
minUsdg: {
type: 'string',
description: 'Minimum USDG to receive in decimal format (e.g., "1.5" for 1.5 USDG). Uses 18 decimals. Defaults to "0" if not specified.',
Copy link
Contributor

@OoXooOx OoXooOx May 29, 2025

Choose a reason for hiding this comment

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

Uses 18 decimals. Defaults to "0" if not specified. - what for? Use must specify token amount and inside functions you must handle decimals. Do not leave this for AI

* Maps from token symbol to token data for each supported chain
* Using Partial<Record> to allow for partial token support on each chain
*/
const TOKEN_MAP: Record<string, Partial<Record<TokenSymbol, TokenData>>> = {
Copy link
Contributor

Choose a reason for hiding this comment

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

do not do this. If you need specific tokens - it's ok. But not reassign WS, USDC, Anon. We already have our token list https://github.com/RealWagmi/heyanon-tokenlist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants