UNPKG

@robertprp/intents-sdk

Version:

Shogun Network Intent-based cross-chain swaps SDK

207 lines (184 loc) 6.45 kB
import { type Address } from 'viem'; import { type SupportedEvmChain } from '../../chains.js'; import type { EVMConfig } from '../../config.js'; import { SINGLE_CHAIN_GUARD_ADDRESSES, CROSS_CHAIN_GUARD_ADDRESSES, MAX_UINT_32, DCA_SINGLE_CHAIN_GUARD_ADDRESSES, } from '../../constants.js'; import { getEVMCrossChainOrderTypedData, getEVMDcaSingleChainOrderTypedData, getEVMSingleChainOrderTypedData, } from './order-signature.js'; import { type CrossChainPermitTransferFrom, type DcaSingleChainPermitTransferFrom, type SingleChainPermitTransferFrom, type TransferData, } from './permit2.js'; import { ChainProvider } from './chain-provider.js'; import type { CrossChainOrder } from '../orders/cross-chain.js'; import type { SingleChainOrder } from '../orders/single-chain.js'; import type { CrossChainOrderPrepared, DcaSingleChainOrderPrepared, SingleChainOrderPrepared, } from '../../types/intent.js'; import type { DcaSingleChainOrder } from '../orders/dca-single-chain.js'; export class EVMIntentProvider { provider: ChainProvider; constructor(config: EVMConfig) { this.provider = new ChainProvider(config); } async prepareSingleChainOrder(order: SingleChainOrder): Promise<SingleChainOrderPrepared> { const { orderTypedData: dataToSign, nonce } = await getEVMSingleChainOrderTypedData(order); const signature = await this.provider.walletClient.signTypedData({ message: dataToSign.message, primaryType: dataToSign.primaryType, types: dataToSign.types, domain: dataToSign.domain, account: this.provider.getAccount(), }); return { order, preparedData: { nonce: nonce.toString(), signature: signature.slice(2), }, }; } async prepareCrossChainOrder(order: CrossChainOrder): Promise<CrossChainOrderPrepared> { const { orderTypedData: dataToSign, nonce } = await getEVMCrossChainOrderTypedData(order); const signature = await this.provider.walletClient.signTypedData({ message: dataToSign.message, primaryType: dataToSign.primaryType, types: dataToSign.types, domain: dataToSign.domain, account: this.provider.getAccount(), }); return { order, preparedData: { nonce: nonce.toString(), signature: signature.slice(2), }, }; } static getCrossChainPermissionMessage(order: CrossChainOrder, nonce: bigint): CrossChainPermitTransferFrom { const spender = CROSS_CHAIN_GUARD_ADDRESSES[order.sourceChainId as SupportedEvmChain] as Address; return { permitted: { token: order.sourceTokenAddress as Address, amount: order.sourceTokenAmount, }, spender, nonce, deadline: BigInt(order.deadline), witness: { user: order.user as Address, tokenIn: order.sourceTokenAddress as Address, srcChainId: order.sourceChainId, deadline: order.deadline, amountIn: order.sourceTokenAmount, minStablecoinsAmount: order.minStablecoinAmount, nonce, executionDetailsHash: order.getExecutionDetailsHash(), }, }; } static getSingleChainLimitPermissionMessage(order: SingleChainOrder, nonce: bigint): SingleChainPermitTransferFrom { const spender = SINGLE_CHAIN_GUARD_ADDRESSES[order.chainId as SupportedEvmChain] as Address; const requestedOutput: TransferData = { token: order.tokenOut as Address, receiver: order.destinationAddress as Address, amount: order.amountOutMin, }; const extraTransfers: TransferData[] = order.extraTransfers?.map((transfer) => ({ token: transfer.token as Address, receiver: transfer.receiver as Address, amount: transfer.amount, })) || []; return { permitted: { token: order.tokenIn as Address, amount: order.amountIn, }, spender, nonce, deadline: BigInt(order.deadline), witness: { user: order.user as Address, tokenIn: order.tokenIn as Address, amountIn: order.amountIn, requestedOutput, encodedExternalCallData: '0x', // TODO: Update when external call data is supported extraTransfers, deadline: order.deadline, nonce, }, }; } static getRandomNonce(): bigint { return BigInt(Math.floor(Math.random() * Number(MAX_UINT_32))); } async prepareDcaSingleChainOrder(order: DcaSingleChainOrder): Promise<DcaSingleChainOrderPrepared> { const { orderTypedData: dataToSign, nonce } = await getEVMDcaSingleChainOrderTypedData(order); const signature = await this.provider.walletClient.signTypedData({ message: dataToSign.message, primaryType: dataToSign.primaryType, types: dataToSign.types, domain: dataToSign.domain, account: this.provider.getAccount(), }); return { order, preparedData: { nonce: nonce.toString(), signature: signature.slice(2), }, }; } static getDcaSingleChainPermissionMessage( order: DcaSingleChainOrder, nonce: bigint, ): DcaSingleChainPermitTransferFrom { const spender = DCA_SINGLE_CHAIN_GUARD_ADDRESSES[order.chainId as SupportedEvmChain] as Address; const requestedOutput: TransferData = { token: order.tokenOut as Address, receiver: order.destinationAddress as Address, amount: BigInt(order.amountOutMin), }; const extraTransfers: TransferData[] = order.extraTransfers?.map((transfer) => ({ token: transfer.token as Address, receiver: transfer.receiver as Address, amount: transfer.amount, })) || []; const totalAmountIn = BigInt(order.amountInPerInterval) * BigInt(order.totalIntervals); return { permitted: { token: order.tokenIn as Address, amount: totalAmountIn, }, spender, nonce, deadline: BigInt(order.deadline), witness: { user: order.user as Address, tokenIn: order.tokenIn as Address, startTime: order.startTime, amountInPerInterval: BigInt(order.amountInPerInterval), totalIntervals: order.totalIntervals, intervalDuration: order.intervalDuration, requestedOutput, encodedExternalCallData: '0x', // TODO: Update when external call data is supported extraTransfers, deadline: order.deadline, nonce, }, }; } }