Skip to content

Commit e9cab71

Browse files
committed
refactor: correct code
1 parent 6b697a2 commit e9cab71

File tree

3 files changed

+186
-137
lines changed

3 files changed

+186
-137
lines changed

apps/kyberswap-interface/.env.production

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ VITE_ZAP_EARN_URL=https://zap-earn-service-v3.kyberengineering.io/api
4747
VITE_AFFILIATE_SERVICE=https://affiliate-service.kyberengineering.io/api
4848
VITE_SOLANA_RPC=https://solana.kyberengineering.io
4949

50-
VITE_CROSSCHAIN_AGGREGATOR_API=https://pre-crosschain-aggregator.kyberengineering.io
50+
# VITE_CROSSCHAIN_AGGREGATOR_API=https://pre-crosschain-aggregator.kyberengineering.io
51+
VITE_CROSSCHAIN_AGGREGATOR_API=http://localhost:8080

apps/kyberswap-interface/src/pages/CrossChainSwap/adapters/KyberAcrossAdapter.ts

Lines changed: 115 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@ import { arbitrum, base, blast, bsc, linea, mainnet, optimism, polygon, scroll,
1616
import { monad, plasma } from 'components/Web3Provider'
1717
import { NETWORKS_INFO } from 'hooks/useChainsConfig'
1818

19-
import { AcrossClient, createAcrossClient } from '@across-protocol/app-sdk'
19+
import {
20+
AcrossClient,
21+
createAcrossClient,
22+
parseDepositLogs,
23+
parseFillLogs,
24+
waitForDepositTx,
25+
waitForFillTx,
26+
} from '@across-protocol/app-sdk'
2027
import { Quote } from '../registry'
2128
import {
2229
BaseSwapAdapter,
@@ -58,6 +65,22 @@ const chainIdToSpokePoolPeriphery: Record<number, Address> = {
5865
[ChainId.BLAST]: '0x924a9f036260DdD5808007E1AA95f08eD08aA569',
5966
}
6067

68+
// Chain ID to SpokePool address mapping (Across protocol)
69+
// These are the official Across SpokePool contract addresses for destination chains
70+
const chainIdToSpokePool: Record<number, Address> = {
71+
[ChainId.MAINNET]: '0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5',
72+
[ChainId.ARBITRUM]: '0xe35e9842fceaCA96570B734083f4a58e8F7C5f2A',
73+
[ChainId.OPTIMISM]: '0x6f26Bf09B1C792e3228e5467807a900A503c0281',
74+
[ChainId.MATIC]: '0x9295ee1d8C5b022Be115A2AD3c30C72E34e7F096',
75+
[ChainId.BASE]: '0x09aea4b2242abC8bb4BB78D537A67a245A7bEC64',
76+
[ChainId.LINEA]: '0x7E63A5f1a8F0B4d0934B2f2327DAED3F6bb2ee75',
77+
[ChainId.ZKSYNC]: '0xE0B015E54d54fc84a6cB9B666099c46adE9335FF',
78+
[ChainId.SCROLL]: '0x3baD7AD0728f9917d1Bf08af5782dCbD516cDd96',
79+
[ChainId.BLAST]: '0x2D509190Ed0172ba588407D4c2df918F955Cc6E1',
80+
[ChainId.BSCMAINNET]: '0x4e8E101924eDE233C13e2D8622DC8aED2872d505',
81+
[ChainId.UNICHAIN]: '0xeF684C38F94F48775959ECf2012D7E864ffb9dd4',
82+
}
83+
6184
// TransferType enum
6285
export enum TransferType {
6386
Approval = 0,
@@ -182,32 +205,6 @@ export const spokePoolPeripheryAbi = [
182205
},
183206
] as const
184207

185-
// V3FundsDeposited event ABI for parsing deposit ID from logs
186-
const V3FundsDepositedAbi = [
187-
{
188-
anonymous: false,
189-
inputs: [
190-
{ indexed: false, internalType: 'address', name: 'inputToken', type: 'address' },
191-
{ indexed: false, internalType: 'address', name: 'outputToken', type: 'address' },
192-
{ indexed: false, internalType: 'uint256', name: 'inputAmount', type: 'uint256' },
193-
{ indexed: false, internalType: 'uint256', name: 'outputAmount', type: 'uint256' },
194-
{ indexed: true, internalType: 'uint256', name: 'destinationChainId', type: 'uint256' },
195-
{ indexed: true, internalType: 'uint32', name: 'depositId', type: 'uint32' },
196-
{ indexed: false, internalType: 'uint32', name: 'quoteTimestamp', type: 'uint32' },
197-
{ indexed: false, internalType: 'uint32', name: 'fillDeadline', type: 'uint32' },
198-
{ indexed: false, internalType: 'uint32', name: 'exclusivityDeadline', type: 'uint32' },
199-
{ indexed: true, internalType: 'address', name: 'depositor', type: 'address' },
200-
{ indexed: false, internalType: 'address', name: 'recipient', type: 'address' },
201-
{ indexed: false, internalType: 'address', name: 'exclusiveRelayer', type: 'address' },
202-
{ indexed: false, internalType: 'bytes', name: 'message', type: 'bytes' },
203-
],
204-
name: 'V3FundsDeposited',
205-
type: 'event',
206-
},
207-
] as const
208-
209-
// V3FundsDeposited event signature
210-
const V3_FUNDS_DEPOSITED_EVENT_SIGNATURE = '0xa123dc29aebf7d0c3322c8eeb5b999e859f39937950ed31056532713d0de396f'
211208

212209
// Progress tracking types
213210
type ProgressMeta = ApproveMeta | SwapAndBridgeMeta | FillMeta | undefined
@@ -253,13 +250,23 @@ export type SwapAndBridgeProgress =
253250
status: 'txSuccess'
254251
txReceipt: TransactionReceipt
255252
depositId: bigint
253+
depositLog: ReturnType<typeof parseDepositLogs>
256254
meta: SwapAndBridgeMeta
257255
}
258256
| {
259257
step: 'fill'
260258
status: 'pending'
261259
meta: FillMeta
262260
}
261+
| {
262+
step: 'fill'
263+
status: 'txSuccess'
264+
txReceipt: TransactionReceipt
265+
fillTxTimestamp: bigint
266+
actionSuccess: boolean | undefined
267+
fillLog: ReturnType<typeof parseFillLogs>
268+
meta: FillMeta
269+
}
263270
| {
264271
step: 'approve' | 'swapAndBridge' | 'fill'
265272
status: 'error'
@@ -271,12 +278,14 @@ export interface ExecuteSwapAndBridgeParams {
271278
// Wallet and clients
272279
walletClient: WalletClient
273280
originChain: ViemChain
281+
destinationChain: ViemChain
274282
// User address
275283
userAddress: Address
276284
// Swap and bridge data
277285
swapAndDepositData: SwapAndDepositData
278286
// Contract addresses
279287
spokePoolPeripheryAddress: Address
288+
destinationSpokePoolAddress: Address
280289
// Options
281290
isNative?: boolean
282291
infiniteApproval?: boolean
@@ -289,25 +298,10 @@ export interface ExecuteSwapAndBridgeParams {
289298
export interface ExecuteSwapAndBridgeResponse {
290299
depositId?: bigint
291300
swapAndBridgeTxReceipt?: TransactionReceipt
301+
fillTxReceipt?: TransactionReceipt
292302
error?: Error
293303
}
294304

295-
/**
296-
* Gets deposit info from transaction logs
297-
*/
298-
function getDepositFromLogs(receipt: TransactionReceipt): { depositId: bigint } {
299-
const depositLog = receipt.logs.find(log => log.topics[0] === V3_FUNDS_DEPOSITED_EVENT_SIGNATURE)
300-
301-
if (!depositLog) {
302-
throw new Error('V3FundsDeposited event not found in transaction logs')
303-
}
304-
305-
// depositId is the second indexed parameter (topics[2])
306-
const depositId = BigInt(depositLog.topics[2] || '0')
307-
308-
return { depositId }
309-
}
310-
311305
/**
312306
* Transforms raw API quote data (with string values) to properly typed SwapAndDepositData (with bigint values)
313307
* The API returns numeric values as strings, but the contract expects bigint types
@@ -435,6 +429,14 @@ export class KyberAcrossAdapter extends BaseSwapAdapter {
435429
throw new Error(`Unsupported chain: ${originChainId}`)
436430
}
437431

432+
// Get destination chain from quoteParams
433+
const destinationChainId = quote.quote.quoteParams.toChain as ChainId
434+
const destinationChain = chainIdToViemChain[destinationChainId]
435+
436+
if (!destinationChain) {
437+
throw new Error(`Unsupported destination chain: ${destinationChainId}`)
438+
}
439+
438440
// Get spokePoolPeripheryAddress from rawQuote or use fallback mapping
439441
const spokePoolPeripheryAddress: Address =
440442
rawQuote.spokePoolPeripheryAddress || chainIdToSpokePoolPeriphery[originChainId]
@@ -443,6 +445,14 @@ export class KyberAcrossAdapter extends BaseSwapAdapter {
443445
throw new Error(`No SpokePoolPeriphery address found for chain: ${originChainId}`)
444446
}
445447

448+
// Get destinationSpokePoolAddress from rawQuote or use fallback mapping
449+
const destinationSpokePoolAddress: Address =
450+
rawQuote.destinationSpokePoolAddress || chainIdToSpokePool[destinationChainId]
451+
452+
if (!destinationSpokePoolAddress) {
453+
throw new Error(`No SpokePool address found for destination chain: ${destinationChainId}`)
454+
}
455+
446456
// Get user address from quote params
447457
const userAddress = quote.quote.quoteParams.sender as Address
448458

@@ -457,16 +467,17 @@ export class KyberAcrossAdapter extends BaseSwapAdapter {
457467
this.executeSwapAndBridge({
458468
walletClient,
459469
originChain,
470+
destinationChain,
460471
userAddress,
461472
swapAndDepositData,
462473
spokePoolPeripheryAddress,
474+
destinationSpokePoolAddress,
463475
isNative,
464476
infiniteApproval: false,
465477
skipAllowanceCheck: false,
466478
throwOnError: true,
467-
onProgress: (progress: SwapAndBridgeProgress) => {
468-
// Resolve when swapAndBridge transaction is pending (similar to Across SDK behavior)
469-
if (progress.step === 'swapAndBridge' && progress.status === 'txPending') {
479+
onProgress: progress => {
480+
if (progress.step === 'swapAndBridge' && 'txHash' in progress) {
470481
resolve({
471482
sender: quote.quote.quoteParams.sender,
472483
sourceTxHash: progress.txHash,
@@ -485,10 +496,6 @@ export class KyberAcrossAdapter extends BaseSwapAdapter {
485496
recipient: quote.quote.quoteParams.recipient,
486497
})
487498
}
488-
489-
if (progress.status === 'error') {
490-
reject(progress.error)
491-
}
492499
},
493500
}).catch(reject)
494501
})
@@ -504,9 +511,11 @@ export class KyberAcrossAdapter extends BaseSwapAdapter {
504511
const {
505512
walletClient,
506513
originChain,
514+
destinationChain,
507515
userAddress,
508516
swapAndDepositData,
509517
spokePoolPeripheryAddress,
518+
destinationSpokePoolAddress,
510519
isNative = false,
511520
infiniteApproval = false,
512521
skipAllowanceCheck = false,
@@ -523,8 +532,9 @@ export class KyberAcrossAdapter extends BaseSwapAdapter {
523532
let currentProgressMeta: ProgressMeta
524533

525534
try {
526-
// Create public client for reading blockchain state
535+
// Create public clients for reading blockchain state
527536
const originClient = this.acrossClient.getPublicClient(originChain.id)
537+
const destinationClient = this.acrossClient.getPublicClient(destinationChain.id)
528538

529539
// Step 1: Check and handle approval if necessary (skip for native ETH)
530540
if (!skipAllowanceCheck && !isNative) {
@@ -631,39 +641,67 @@ export class KyberAcrossAdapter extends BaseSwapAdapter {
631641
}
632642
onProgressHandler(currentProgress)
633643

634-
// Wait for transaction confirmation
635-
const swapAndBridgeTxReceipt = await originClient.waitForTransactionReceipt({
636-
hash: swapAndBridgeTxHash,
644+
// Wait for deposit transaction and parse logs using SDK
645+
const { depositId, depositTxReceipt } = await waitForDepositTx({
646+
originChainId: originChain.id,
647+
transactionHash: swapAndBridgeTxHash,
648+
publicClient: originClient,
637649
})
638-
639-
// Parse deposit ID from logs
640-
const deposit = getDepositFromLogs(swapAndBridgeTxReceipt)
641-
const depositId = deposit.depositId
650+
const depositLog = parseDepositLogs(depositTxReceipt.logs)
642651

643652
currentProgress = {
644653
step: 'swapAndBridge',
645654
status: 'txSuccess',
646-
txReceipt: swapAndBridgeTxReceipt,
655+
txReceipt: depositTxReceipt,
647656
depositId,
657+
depositLog,
648658
meta: currentProgressMeta,
649659
}
650660
onProgressHandler(currentProgress)
651661

652-
// Step 3: Notify about fill pending
662+
// Step 3: Wait for fill on destination chain
653663
currentProgressMeta = {
654664
depositId,
655665
}
656-
657666
currentProgress = {
658667
step: 'fill',
659668
status: 'pending',
660669
meta: currentProgressMeta,
661670
}
662671
onProgressHandler(currentProgress)
663672

673+
const destinationBlock = await destinationClient.getBlockNumber()
674+
675+
const { fillTxReceipt, fillTxTimestamp, actionSuccess } = await waitForFillTx({
676+
deposit: {
677+
originChainId: originChain.id,
678+
destinationChainId: destinationChain.id,
679+
destinationSpokePoolAddress,
680+
message: swapAndDepositData.depositData.message,
681+
},
682+
depositId,
683+
depositTxHash: depositTxReceipt.transactionHash,
684+
destinationChainClient: destinationClient,
685+
fromBlock: destinationBlock - 100n,
686+
})
687+
688+
const fillLog = parseFillLogs(fillTxReceipt.logs)
689+
690+
currentProgress = {
691+
step: 'fill',
692+
status: 'txSuccess',
693+
txReceipt: fillTxReceipt,
694+
fillTxTimestamp,
695+
actionSuccess,
696+
fillLog,
697+
meta: currentProgressMeta,
698+
}
699+
onProgressHandler(currentProgress)
700+
664701
return {
665702
depositId,
666-
swapAndBridgeTxReceipt,
703+
swapAndBridgeTxReceipt: depositTxReceipt,
704+
fillTxReceipt,
667705
}
668706
} catch (error) {
669707
currentProgress = {
@@ -683,11 +721,21 @@ export class KyberAcrossAdapter extends BaseSwapAdapter {
683721
}
684722

685723
// getTransactionStatus is empty for now - will be added later
686-
async getTransactionStatus(_params: NormalizedTxResponse): Promise<SwapStatus> {
687-
// TODO: Implement transaction status tracking
688-
return {
689-
txHash: '',
690-
status: 'Processing',
724+
async getTransactionStatus(params: NormalizedTxResponse): Promise<SwapStatus> {
725+
try {
726+
const res = await fetch(`https://app.across.to/api/deposit/status?depositTxHash=${params.sourceTxHash}`).then(
727+
res => res.json(),
728+
)
729+
return {
730+
txHash: res.fillTx || '',
731+
status: res.status === 'refunded' ? 'Refunded' : res.status === 'filled' ? 'Success' : 'Processing',
732+
}
733+
} catch (error) {
734+
console.error('Error fetching transaction status:', error)
735+
return {
736+
txHash: '',
737+
status: 'Processing',
738+
}
691739
}
692740
}
693741
}

0 commit comments

Comments
 (0)