@robertprp/intents-sdk
Version:
Shogun Network Intent-based cross-chain swaps SDK
102 lines (80 loc) • 3.5 kB
text/typescript
import { ChainType, chainIdToChainTypeMap, type SupportedChain } from '../chains.js';
import { EvmValidator } from '../core/evm/validator.js';
import type { CreateCrossChainOrderParams } from '../core/orders/cross-chain.js';
import type { CreateSingleChainOrderParams } from '../core/orders/single-chain.js';
import { SolanaValidator } from '../core/solana/validator.js';
import { SuiValidator } from '../core/sui/validator.js';
import { ValidationError } from '../errors/index.js';
export interface IAddressValidator {
isValidAddress(address: string): boolean;
}
export interface ITokenValidator {
isValidTokenAddress(tokenAddress: string): boolean;
}
export interface IAmountValidator {
isValidAmount(amount: bigint): boolean;
}
export interface IDeadlineValidator {
isValidDeadline(deadline: number): boolean;
}
export interface IChainValidator extends IAddressValidator, ITokenValidator, IAmountValidator {
validateSourceChain(order: CreateCrossChainOrderParams & { user: string }): Promise<void>;
validateDestinationChain(order: CreateCrossChainOrderParams): void;
validateSingleChainOrder(order: CreateSingleChainOrderParams & { user: string }): Promise<void>;
}
/**
* CommonValidator - Handles validations shared across chains
*/
export class CommonValidator implements IDeadlineValidator {
isValidDeadline(deadline: number): boolean {
return deadline > Math.floor(Date.now() / 1000);
}
validateDeadline(deadline: number): void {
if (!this.isValidDeadline(deadline)) {
throw new ValidationError('Deadline must be in the future');
}
}
}
export class ValidatorFactory {
private static validators: Map<ChainType, IChainValidator> = new Map();
static getValidator(chainType: ChainType): IChainValidator {
if (!this.validators.has(chainType)) {
switch (chainType) {
case ChainType.EVM:
this.validators.set(chainType, new EvmValidator());
break;
case ChainType.Solana:
this.validators.set(chainType, new SolanaValidator());
break;
case ChainType.Sui:
this.validators.set(chainType, new SuiValidator());
break;
default:
throw new ValidationError(`Chain type ${chainType} validation is not implemented.`);
}
}
return this.validators.get(chainType)!;
}
static getValidatorForChain(chainId: SupportedChain): IChainValidator {
const chainType = chainIdToChainTypeMap[chainId];
return this.getValidator(chainType);
}
}
export class CrossChainOrderValidator {
private readonly commonValidator = new CommonValidator();
async validateOrder(order: CreateCrossChainOrderParams & { user: string }): Promise<void> {
const sourceValidator = ValidatorFactory.getValidatorForChain(order.sourceChainId);
await sourceValidator.validateSourceChain({ ...order, user: order.user });
const destinationValidator = ValidatorFactory.getValidatorForChain(order.destinationChainId);
destinationValidator.validateDestinationChain(order);
this.commonValidator.validateDeadline(order.deadline);
}
}
export class SingleChainOrderValidator {
private readonly commonValidator = new CommonValidator();
async validateOrder(order: CreateSingleChainOrderParams & { user: string }): Promise<void> {
this.commonValidator.validateDeadline(order.deadline);
const chainValidator = ValidatorFactory.getValidatorForChain(order.chainId);
chainValidator.validateSingleChainOrder(order);
}
}