UNPKG

@robertprp/intents-sdk

Version:

Shogun Network Intent-based cross-chain swaps SDK

111 lines 5.13 kB
import { getContract, isAddress as isEvmAddress } from 'viem'; import { ChainID } from '../../chains.js'; import { isNativeEvmToken, MAX_UINT_128 } from '../../constants.js'; import { InsufficientBalanceError, ValidationError } from '../../errors/index.js'; import { BaseValidator } from '../../utils/base-validator.js'; import { ERC20ABI } from './abi/erc20.js'; import { ChainProvider } from './chain-provider.js'; /** * Chain-specific validator implementations */ export class EvmValidator extends BaseValidator { isValidAddress(address) { return isEvmAddress(address); } isValidTokenAddress(tokenAddress) { return isEvmAddress(tokenAddress); } isValidAmount(amount) { return amount > 0n && amount < MAX_UINT_128; } getChainName() { return 'EVM'; } async validateCrossChainOrderFeasability(order) { const chain = order.sourceChainId; const client = ChainProvider.getClient(chain); const user = order.user; if (isNativeEvmToken(order.sourceTokenAddress)) { throw new ValidationError('Native token is not supported.'); } if (order.sourceChainId === ChainID.Hyperliquid && isNativeEvmToken(order.destinationTokenAddress)) { throw new ValidationError('HYPE native token as destination address is not supported.'); } const ERC20Contract = getContract({ address: order.sourceTokenAddress, abi: ERC20ABI, client: { public: client, chain, }, }); const balance = await ERC20Contract.read.balanceOf([user]); if (balance < order.sourceTokenAmount) { throw new InsufficientBalanceError(`Insufficient balance for token ${order.sourceTokenAddress}. Current balance: ${balance}. Required balance: ${order.sourceTokenAmount}`); } // Temporary allowance turn off. This should be handled in the frontend. // const permit2Address = PERMIT2_ADDRESS[chain]; // const allowance = await ERC20Contract.read.allowance([user, permit2Address]); // if (allowance < order.sourceTokenAmount) { // throw new InsufficientAllowanceError( // `Insufficient allowance for token ${order.sourceTokenAddress} on permit2 address ${permit2Address}. Current allowance: ${allowance}. Required allowance: ${order.sourceTokenAmount}`, // ); // } } async validateSingleChainOrderFeasability(order) { const chain = order.chainId; const validSingleChainChains = [ChainID.Hyperliquid, ChainID.Base]; if (!validSingleChainChains.includes(chain)) { throw new ValidationError(`Chain ${chain} is not supported for single chain orders`); } if (order.chainId === ChainID.Hyperliquid && isNativeEvmToken(order.tokenOut)) { throw new ValidationError('HYPE native token as destination address is not supported.'); } const client = ChainProvider.getClient(chain); const user = order.user; if (isNativeEvmToken(order.tokenIn)) { throw new ValidationError('Native token is not supported.'); } const ERC20Contract = getContract({ address: order.tokenIn, abi: ERC20ABI, client: { public: client, chain, }, }); const balance = await ERC20Contract.read.balanceOf([user]); if (balance < order.amountIn) { throw new InsufficientBalanceError(`Insufficient balance for token ${order.tokenIn}. Current balance: ${balance}. Required balance: ${order.amountIn}`); } // const permit2Address = PERMIT2_ADDRESS[chain]; // const allowance = await ERC20Contract.read.allowance([user, permit2Address]); // if (allowance < order.amountIn) { // throw new InsufficientAllowanceError( // `Insufficient allowance for token ${order.tokenIn} on permit2 address ${permit2Address}. Current allowance: ${allowance}. Required allowance: ${order.amountIn}`, // ); // } } async validateDcaSingleChainOrderFeasability(order) { const chain = order.chainId; const client = ChainProvider.getClient(chain); const user = order.user; if (isNativeEvmToken(order.tokenIn)) { throw new ValidationError('Native token is not supported for DCA orders.'); } const ERC20Contract = getContract({ address: order.tokenIn, abi: ERC20ABI, client: { public: client, chain, }, }); const totalAmountIn = order.amountInPerInterval * BigInt(order.totalIntervals); const balance = await ERC20Contract.read.balanceOf([user]); if (balance < totalAmountIn) { throw new InsufficientBalanceError(`Insufficient balance for DCA order. Token: ${order.tokenIn}. Current balance: ${balance}. Required total: ${totalAmountIn}`); } } } //# sourceMappingURL=validator.js.map