Skip to content

Commit

Permalink
feat: sui intents (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
R0bi7 authored Nov 5, 2024
1 parent e347d9c commit e572a44
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 34 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
],
"type": "module",
"dependencies": {
"@mysten/sui": "^1.14.1",
"@mysten/wallet-standard": "^0.13.9",
"@uniswap/permit2-sdk": "^1.3.0",
"tiny-invariant": "^1.1.0",
"viem": "^2.21.35"
Expand Down
15 changes: 14 additions & 1 deletion src/entities/Providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
type PublicClient,
type WalletClient,
} from "viem"
import { type Wallet, type WalletAccount } from "@mysten/wallet-standard"
import { getFullnodeUrl, SuiClient } from "@mysten/sui/client"
import type { SuiNetworkType } from "../types.js"

export type CustomProvider = { request(...args: any): Promise<any> }

Expand All @@ -27,7 +30,15 @@ export class EvmProvider {
}

export class SuiProvider {
// TODO
public readonly wallet: Wallet
public readonly account: WalletAccount
public readonly client: SuiClient

constructor(wallet: Wallet, account: WalletAccount, net: SuiNetworkType) {
this.wallet = wallet
this.account = account
this.client = new SuiClient({ url: getFullnodeUrl(net) })
}
}

export type ChainProviderType = EvmProvider | SuiProvider
Expand All @@ -37,3 +48,5 @@ export type ChainProvider<T = undefined> = T extends "evm"
: T extends "sui"
? SuiProvider
: ChainProviderType

export type NonEmptyChainProviders = [ChainProvider, ...ChainProvider[]]
34 changes: 18 additions & 16 deletions src/services/EvmIntentService.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type Address, type Hash, parseEventLogs, type TransactionReceipt } from "viem"
import { type IntentExecutePayload } from "./IntentService.js"
import { type CreateIntentOrderPayload } from "./IntentService.js"
import { erc20Abi, intentAbi } from "../abis/index.js"
import { SwapOrder, EvmProvider } from "../entities/index.js"
import type { EvmChainConfig, Result } from "../types.js"
import type { ChainConfig, EvmChainConfig, Result } from "../types.js"

export class EvmIntentService {
private constructor() {}
Expand Down Expand Up @@ -78,22 +78,24 @@ export class EvmIntentService {
}

/**
* Execute EVM intent order
* Create EVM intent order
* @param payload - Intent payload
* @param chainConfig - EVM chain config
* @param fromChainConfig - EVM chain config
* @param toChainConfig - Destination chain config
* @param provider - EVM provider
*/
static async executeOrder(
payload: IntentExecutePayload,
chainConfig: EvmChainConfig,
static async createIntentOrder(
payload: CreateIntentOrderPayload,
fromChainConfig: EvmChainConfig,
toChainConfig: ChainConfig,
provider: EvmProvider,
): Promise<Result<Hash>> {
try {
const intent = new SwapOrder(
0n,
chainConfig.intentContract,
chainConfig.nid,
chainConfig.nid,
fromChainConfig.intentContract,
fromChainConfig.nid,
toChainConfig.nid,
payload.fromAddress,
payload.toAddress,
payload.token,
Expand All @@ -103,12 +105,12 @@ export class EvmIntentService {
new Uint8Array(),
)

const isNative = payload.token.toLowerCase() == chainConfig.nativeToken.toLowerCase()
const isNative = payload.token.toLowerCase() == fromChainConfig.nativeToken.toLowerCase()

return {
ok: true,
value: await provider.walletClient.writeContract({
address: chainConfig.intentContract,
address: fromChainConfig.intentContract,
abi: intentAbi,
functionName: "swap",
args: [intent.toObjectData()],
Expand All @@ -126,13 +128,13 @@ export class EvmIntentService {

/**
* Retrieve Intent order
* @param hash - Transaction hash
* @param txHash - Transaction hash
* @param chainConfig - EVM chain config
* @param provider - EVM provider
*/
static async getOrder(hash: Hash, chainConfig: EvmChainConfig, provider: EvmProvider): Promise<Result<SwapOrder>> {
static async getOrder(txHash: Hash, chainConfig: EvmChainConfig, provider: EvmProvider): Promise<Result<SwapOrder>> {
try {
const receipt = await provider.publicClient.getTransactionReceipt({ hash })
const receipt = await provider.publicClient.getTransactionReceipt({ hash: txHash })
const logs = parseEventLogs({
abi: intentAbi,
eventName: "SwapIntent",
Expand Down Expand Up @@ -162,7 +164,7 @@ export class EvmIntentService {

return {
ok: false,
error: new Error(`No order found for ${hash}`),
error: new Error(`No order found for ${txHash}`),
}
} catch (e) {
return {
Expand Down
54 changes: 37 additions & 17 deletions src/services/IntentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { type Address, type Hash } from "viem"
import type { Chain, ChainConfig, ChainType, Result } from "../types.js"
import { chainConfig, supportedChains } from "../constants.js"
import { isEvmChainConfig, isSuiChainConfig } from "../guards.js"
import { type ChainProvider, EvmProvider, SuiProvider } from "../entities/index.js"
import { type ChainProvider, type NonEmptyChainProviders, EvmProvider, SuiProvider } from "../entities/index.js"
import { EvmIntentService } from "./EvmIntentService.js"
import { SuiIntentService } from "./SuiIntentService.js"

export type IntentQuoteRequest = {
srcNID: string
Expand All @@ -20,15 +21,15 @@ export type IntentQuoteResponse = {

export type IntentExecutionRequest = {
uuid: string
txData: any // TODO: introduce typing (evm and sui tx type)
txHash: string
}

export type IntentExecutionResponse = {
message: string
code: number
}

export type IntentExecutePayload = {
export type CreateIntentOrderPayload = {
fromAddress: string
toAddress: string
fromChain: Chain
Expand All @@ -40,9 +41,9 @@ export type IntentExecutePayload = {
}

export class IntentService {
private readonly providers: ChainProvider[]
private readonly providers: NonEmptyChainProviders

constructor(chainProviders: ChainProvider[]) {
constructor(chainProviders: NonEmptyChainProviders) {
this.providers = chainProviders
}

Expand All @@ -55,7 +56,7 @@ export class IntentService {
* Check whether intent contract is allowed to move the given payload amount
* @param payload -Intent payload
*/
public async isAllowanceValid(payload: IntentExecutePayload): Promise<Result<boolean>> {
public async isAllowanceValid(payload: CreateIntentOrderPayload): Promise<Result<boolean>> {
try {
const fromChainConfig = chainConfig[payload.fromChain]

Expand All @@ -75,11 +76,10 @@ export class IntentService {
this.getChainProvider(fromChainConfig.chain.type),
)
} else if (isSuiChainConfig(fromChainConfig)) {
// TODO

// no allowance required on SUI
return {
ok: false,
error: new Error(`Not implemented`),
ok: true,
value: true,
}
} else {
return {
Expand All @@ -95,7 +95,25 @@ export class IntentService {
}
}

public async executeIntent(payload: IntentExecutePayload): Promise<Result<Hash>> {
public async executeIntentOrder(payload: CreateIntentOrderPayload): Promise<Result<any>> {
try {
const txHash = await this.createIntentOrder(payload)

// TODO

return {
ok: true,
value: undefined,
}
} catch (e) {
return {
ok: false,
error: e,
}
}
}

private async createIntentOrder(payload: CreateIntentOrderPayload): Promise<Result<Hash | string>> {
try {
const fromChainConfig = chainConfig[payload.fromChain]

Expand All @@ -116,17 +134,19 @@ export class IntentService {
}

if (isEvmChainConfig(fromChainConfig)) {
return EvmIntentService.executeOrder(
return EvmIntentService.createIntentOrder(
payload,
fromChainConfig,
toChainConfig,
this.getChainProvider(fromChainConfig.chain.type),
)
} else if (isSuiChainConfig(fromChainConfig)) {
// TODO
return {
ok: false,
error: new Error(`SUI not implemented`),
}
return SuiIntentService.createIntentOrder(
payload,
fromChainConfig,
toChainConfig,
this.getChainProvider(fromChainConfig.chain.type),
)
} else {
return {
ok: false,
Expand Down
Loading

0 comments on commit e572a44

Please sign in to comment.