Skip to content

Commit 8e183df

Browse files
committed
feat: add support for mayan hyperliquid (draft)
1 parent 8c434be commit 8e183df

File tree

2 files changed

+137
-21
lines changed

2 files changed

+137
-21
lines changed

src/core/EVM/EVMStepExecutor.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ export class EVMStepExecutor extends BaseStepExecutor {
318318
!!step.estimate.approvalAddress
319319

320320
let signedNativePermitTypedData: SignedTypedData | undefined
321+
let stepTransactionSignedNativePermitTypedData: SignedTypedData | undefined
321322
if (checkForAllowance) {
322323
// Check if token needs approval and get approval transaction or message data when available
323324
const allowanceResult = await checkAllowance({
@@ -330,6 +331,7 @@ export class EVMStepExecutor extends BaseStepExecutor {
330331
batchingSupported,
331332
permit2Supported,
332333
disableMessageSigning,
334+
switchChainHook: this.executionOptions?.switchChainHook!,
333335
})
334336

335337
if (allowanceResult.status === 'BATCH_APPROVAL') {
@@ -342,6 +344,16 @@ export class EVMStepExecutor extends BaseStepExecutor {
342344
if (allowanceResult.status === 'NATIVE_PERMIT') {
343345
signedNativePermitTypedData = allowanceResult.data
344346
}
347+
if (allowanceResult.status === 'DESTINATION_NATIVE_PERMIT') {
348+
stepTransactionSignedNativePermitTypedData = (
349+
allowanceResult as any
350+
)?.data?.find(
351+
(p: any) => p.status === 'DESTINATION_NATIVE_PERMIT'
352+
)?.data
353+
signedNativePermitTypedData = (allowanceResult as any)?.data?.find(
354+
(p: any) => p.status === 'NATIVE_PERMIT'
355+
)?.data
356+
}
345357
if (
346358
allowanceResult.status === 'ACTION_REQUIRED' &&
347359
!this.allowUserInteraction
@@ -401,7 +413,8 @@ export class EVMStepExecutor extends BaseStepExecutor {
401413
) {
402414
const updatedStep = await this.getUpdatedStep(
403415
step,
404-
signedNativePermitTypedData
416+
stepTransactionSignedNativePermitTypedData ||
417+
signedNativePermitTypedData
405418
)
406419
const comparedStep = await stepComparison(
407420
this.statusManager,

src/core/EVM/checkAllowance.ts

Lines changed: 123 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@ import { signTypedData } from 'viem/actions'
44
import { getAction } from 'viem/utils'
55
import { MaxUint256 } from '../../constants.js'
66
import type { StatusManager } from '../StatusManager.js'
7-
import type { ExecutionOptions, Process, ProcessType } from '../types.js'
7+
import type {
8+
ExecutionOptions,
9+
Process,
10+
ProcessType,
11+
SwitchChainHook,
12+
} from '../types.js'
813
import { getActionWithFallback } from './getActionWithFallback.js'
9-
import { getAllowance } from './getAllowance.js'
14+
// import { getAllowance } from './getAllowance.js'
1015
import { parseEVMErrors } from './parseEVMErrors.js'
1116
import { getNativePermit } from './permits/getNativePermit.js'
1217
import type { NativePermitData } from './permits/types.js'
@@ -25,6 +30,7 @@ export type CheckAllowanceParams = {
2530
batchingSupported?: boolean
2631
permit2Supported?: boolean
2732
disableMessageSigning?: boolean
33+
switchChainHook: SwitchChainHook
2834
}
2935

3036
export type AllowanceResult =
@@ -39,6 +45,10 @@ export type AllowanceResult =
3945
status: 'NATIVE_PERMIT'
4046
data: SignedTypedData
4147
}
48+
| {
49+
status: 'DESTINATION_NATIVE_PERMIT'
50+
data: SignedTypedData[]
51+
}
4252

4353
export const checkAllowance = async ({
4454
client,
@@ -50,6 +60,7 @@ export const checkAllowance = async ({
5060
batchingSupported = false,
5161
permit2Supported = false,
5262
disableMessageSigning = false,
63+
switchChainHook,
5364
}: CheckAllowanceParams): Promise<AllowanceResult> => {
5465
// Find existing or create new allowance process
5566
const allowanceProcess: Process = statusManager.findOrCreateProcess({
@@ -81,18 +92,18 @@ export const checkAllowance = async ({
8192

8293
const fromAmount = BigInt(step.action.fromAmount)
8394

84-
const approved = await getAllowance(
85-
client,
86-
step.action.fromToken.address as Address,
87-
client.account!.address,
88-
spenderAddress as Address
89-
)
95+
// const approved = await getAllowance(
96+
// client,
97+
// step.action.fromToken.address as Address,
98+
// client.account!.address,
99+
// spenderAddress as Address
100+
// )
90101

91-
// Return early if already approved
92-
if (fromAmount <= approved) {
93-
statusManager.updateProcess(step, allowanceProcess.type, 'DONE')
94-
return { status: 'DONE' }
95-
}
102+
// // Return early if already approved
103+
// if (fromAmount <= approved) {
104+
// statusManager.updateProcess(step, allowanceProcess.type, 'DONE')
105+
// return { status: 'DONE' }
106+
// }
96107

97108
const isRelayerTransaction = isRelayerStep(step)
98109

@@ -101,10 +112,16 @@ export const checkAllowance = async ({
101112
!!chain.permit2Proxy && !batchingSupported && !disableMessageSigning
102113

103114
let nativePermitData: NativePermitData | undefined
115+
let destinationChainNativePermitData: NativePermitData | undefined
104116
if (isRelayerTransaction) {
105-
nativePermitData = step.typedData.find(
117+
const permitData = step.typedData?.find(
106118
(p) => p.primaryType === 'Permit'
107119
) as NativePermitData
120+
if (permitData && permitData.domain.chainId === chain.id) {
121+
nativePermitData = permitData
122+
} else {
123+
destinationChainNativePermitData = permitData
124+
}
108125
} else if (isNativePermitAvailable) {
109126
nativePermitData = await getActionWithFallback(
110127
client,
@@ -119,12 +136,28 @@ export const checkAllowance = async ({
119136
)
120137
}
121138

139+
if (isRelayerTransaction && !nativePermitData) {
140+
nativePermitData = await getActionWithFallback(
141+
client,
142+
getNativePermit,
143+
'getNativePermit',
144+
{
145+
chainId: chain.id,
146+
tokenAddress: step.action.fromToken.address as Address,
147+
spenderAddress: chain.permit2Proxy as Address,
148+
amount: fromAmount,
149+
}
150+
)
151+
}
152+
122153
statusManager.updateProcess(step, allowanceProcess.type, 'ACTION_REQUIRED')
123154

124155
if (!allowUserInteraction) {
125156
return { status: 'ACTION_REQUIRED' }
126157
}
127158

159+
const arr: any = []
160+
128161
if (isNativePermitAvailable && nativePermitData) {
129162
const signature = await getAction(
130163
client,
@@ -138,15 +171,55 @@ export const checkAllowance = async ({
138171
message: nativePermitData.message,
139172
})
140173
statusManager.updateProcess(step, allowanceProcess.type, 'DONE')
141-
return {
142-
status: 'NATIVE_PERMIT',
143-
data: {
144-
...nativePermitData,
145-
signature,
146-
},
174+
if (destinationChainNativePermitData) {
175+
arr.push({
176+
status: 'DESTINATION_NATIVE_PERMIT',
177+
data: {
178+
...nativePermitData,
179+
signature,
180+
},
181+
})
182+
} else {
183+
return {
184+
status: 'NATIVE_PERMIT',
185+
data: {
186+
...nativePermitData,
187+
signature,
188+
},
189+
}
147190
}
148191
}
149192

193+
// if (destinationChainNativePermitData) {
194+
// const updatedClient = await switchChainHook(
195+
// destinationChainNativePermitData.domain.chainId as number
196+
// )
197+
// if (!updatedClient) {
198+
// throw new Error('Client not updated')
199+
// }
200+
// const signature = await getAction(
201+
// updatedClient,
202+
// signTypedData,
203+
// 'signTypedData'
204+
// )({
205+
// account: client.account!,
206+
// domain: destinationChainNativePermitData.domain,
207+
// types: destinationChainNativePermitData.types,
208+
// primaryType: 'Permit',
209+
// message: destinationChainNativePermitData.message,
210+
// })
211+
// // statusManager.updateProcess(step, allowanceProcess.type, 'DONE')
212+
// await switchChainHook(chain.id)
213+
// arr.push({
214+
// status: 'DESTINATION_NATIVE_PERMIT',
215+
// data: {
216+
// ...destinationChainNativePermitData,
217+
// signature,
218+
// },
219+
// })
220+
// return { status: 'DESTINATION_NATIVE_PERMIT', data: arr }
221+
// }
222+
150223
// Set new allowance
151224
const approveAmount = permit2Supported ? MaxUint256 : fromAmount
152225
const approveTxHash = await setAllowance(
@@ -158,6 +231,36 @@ export const checkAllowance = async ({
158231
batchingSupported
159232
)
160233

234+
if (destinationChainNativePermitData) {
235+
const updatedClient = await switchChainHook(
236+
destinationChainNativePermitData.domain.chainId as number
237+
)
238+
if (!updatedClient) {
239+
throw new Error('Client not updated')
240+
}
241+
const signature = await getAction(
242+
updatedClient,
243+
signTypedData,
244+
'signTypedData'
245+
)({
246+
account: client.account!,
247+
domain: destinationChainNativePermitData.domain,
248+
types: destinationChainNativePermitData.types,
249+
primaryType: 'Permit',
250+
message: destinationChainNativePermitData.message,
251+
})
252+
// statusManager.updateProcess(step, allowanceProcess.type, 'DONE')
253+
await switchChainHook(chain.id)
254+
arr.push({
255+
status: 'DESTINATION_NATIVE_PERMIT',
256+
data: {
257+
...destinationChainNativePermitData,
258+
signature,
259+
},
260+
})
261+
return { status: 'DESTINATION_NATIVE_PERMIT', data: arr }
262+
}
263+
161264
if (batchingSupported) {
162265
statusManager.updateProcess(step, allowanceProcess.type, 'DONE')
163266
return {

0 commit comments

Comments
 (0)