-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: initial swap monitor testing ft_swap: parse redeem params to get fill vaa add id for redeem event ft_watcher: parse swap event and input ft_watcher: plug swap layer into ft watcher Signed-off-by: bingyuyap <[email protected]>
- Loading branch information
Showing
8 changed files
with
305 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
...m_sepolia/receipt_0x8e61395ff443d67697fdafad62403dca90f2ffb0181e141b0c1ed52090873d13.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"to": "0xdA11B3bc8705D84BEae4a796035bDcCc9b59d1ee", | ||
"from": "0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9", | ||
"contractAddress": null, | ||
"transactionIndex": 0, | ||
"logsBloom": "0x0200000000400100008000010000000100000000000000000800010000020000000200000000000001000200000000000000000000000008000000000080000000000000000000400800000800000000000000000000000000000000000000000002000002000002800000000001380000000000010100000000001000840000000000000000040000020000000000020000010001000020000000000000040000000000000020000200000000000000000000000000000000000000000000000000001200000040000000000000000000000000000000000000000000002000400002000000000000000018000000000c080000000800000000000000000000", | ||
"blockHash": "0x823e2da477c5e8f8aff4bec177b11adca3ad16550d65faf38a3895e4c23d503b", | ||
"transactionHash": "0x8e61395ff443d67697fdafad62403dca90f2ffb0181e141b0c1ed52090873d13", | ||
"logs": [ | ||
{ | ||
"transactionIndex": 0, | ||
"blockNumber": 20034952, | ||
"transactionHash": "0x8e61395ff443d67697fdafad62403dca90f2ffb0181e141b0c1ed52090873d13", | ||
"address": "0xdA11B3bc8705D84BEae4a796035bDcCc9b59d1ee", | ||
"topics": [ | ||
"0x5cdf07ad0fc222442720b108e3ed4c4640f0fadc2ab2253e66f259a0fea83480", | ||
"0x00000000000000000000000095ced938f7991cd0dfcb48f0a06a40fa1af46ebc" | ||
], | ||
"data": "0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000004a817c80000000000000000000000000000000000000000000000000000000000009f6a8c", | ||
"logIndex": 7, | ||
"blockHash": "0x823e2da477c5e8f8aff4bec177b11adca3ad16550d65faf38a3895e4c23d503b" | ||
} | ||
], | ||
"blockNumber": 20034952, | ||
"confirmations": 1, | ||
"status": 1, | ||
"type": 2, | ||
"byzantium": true | ||
} |
18 changes: 18 additions & 0 deletions
18
...polia/transaction_0x8e61395ff443d67697fdafad62403dca90f2ffb0181e141b0c1ed52090873d13.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"hash": "0x8e61395ff443d67697fdafad62403dca90f2ffb0181e141b0c1ed52090873d13", | ||
"type": 2, | ||
"accessList": [], | ||
"blockHash": "0x823e2da477c5e8f8aff4bec177b11adca3ad16550d65faf38a3895e4c23d503b", | ||
"blockNumber": 20034952, | ||
"transactionIndex": 0, | ||
"confirmations": 1, | ||
"from": "0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9", | ||
"to": "0xdA11B3bc8705D84BEae4a796035bDcCc9b59d1ee", | ||
"nonce": 19, | ||
"data": "0x604009a900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000001800100000000010026ef88e25acfa030a19569d2e6bf14c4c79a74d8b13d290c070f29a61082f4306b33c82d9a3159a1f97e94ed5b06a06aa343f39ac63a773093417b10d1ccdfe60066b24580000000000001cb0406e59555bf0371b7c4fff1812a11a8d92dad02ad422062971d61dcce2cd000000000000000022001c6fa7af3bedbad3a3d65f36aabc97431b1bbe4c2d2f6e0e47ca60203452f5d6100000000000000000000000000000000000000000000000000000004a8b7328c00000005000000000000000000000027aa2c95ecc476da8c735e951c5308579c8a1cb5b068dc7427a85554c8e0dc562300000000000000000000000092e813b6baf1d17618586118c1a3cfffe2d283dc00720100019fb9f4f1d72bf9e5bd12c996bb162a33ceed72d2e24e985bca01b09c21663b1e000000000000000000000000da11b3bc8705d84beae4a796035bdccc9b59d1ee002d0100000000000000000000000095ced938f7991cd0dfcb48f0a06a40fa1af46ebc02000f42400000009f6a8c0000000000000000000000000000000000000000000000000000000000000000f80000000000000005000000000000000000000027a65fc943419a5ad590042fd67c9791fd015acf53a54cc823edb8ff81b9ed722e000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af315500000000000000000000000092e813b6baf1d17618586118c1a3cfffe2d283dc00000000c6fa7af3bedbad3a3d65f36aabc97431b1bbe4c2d2f6e0e47ca60203452f5d6100000000000000000000000092e813b6baf1d17618586118c1a3cfffe2d283dc00000000000000000000000000000000000000000000000000000004a8b7328ccb0406e59555bf0371b7c4fff1812a11a8d92dad02ad422062971d61dcce2cd000000000000000000000000000000000000000000000000000000000000000000000000000000041cb279020da108b02ca3efc668b320ed18b3daf092b86c39a748ee523a9142e214d4c3191d296681b4efd8c1399da400f2963bf2e8a4b0c869b2b4084596da3291c00000000000000000000000000000000000000000000000000000000000000", | ||
"r": "0x700b0cf7513be7506ac000bfe48c87ff69f15cff40ddf457477f8a722d0238f9", | ||
"s": "0x212632d962cdadfb8edf9a2fd54d99db96bce957d03f7b077b64db3613218279", | ||
"v": 1, | ||
"creates": null, | ||
"chainId": 1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { ethers } from 'ethers'; | ||
import { RedeemSwap } from '../types'; | ||
import { parseVaa } from '@wormhole-foundation/wormhole-monitor-common'; | ||
|
||
class SwapLayerParser { | ||
private provider: ethers.providers.JsonRpcProvider; | ||
private swapLayerAddress: string; | ||
private swapLayerInterface: ethers.utils.Interface; | ||
|
||
constructor(provider: ethers.providers.JsonRpcProvider, swapLayerAddress: string) { | ||
this.provider = provider; | ||
this.swapLayerAddress = swapLayerAddress; | ||
this.swapLayerInterface = new ethers.utils.Interface([ | ||
'event Redeemed(address indexed recipient, address outputToken, uint256 outputAmount, uint256 relayingFee)', | ||
]); | ||
} | ||
|
||
async parseSwapLayerTransaction(txHash: string, blockTime: number): Promise<RedeemSwap | null> { | ||
const receipt = await this.provider.getTransactionReceipt(txHash); | ||
|
||
const tx = await this.provider.getTransaction(txHash); | ||
if (!receipt || !tx) return null; | ||
|
||
// Remove the function selector (first 4 bytes) | ||
const inputData = '0x' + tx.data.slice(10); | ||
|
||
// Use AbiCoder to decode the raw input data | ||
let fillVaaId: string = ''; | ||
const abiCoder = new ethers.utils.AbiCoder(); | ||
try { | ||
const decodedInput = abiCoder.decode(['bytes', 'tuple(bytes, bytes, bytes)'], inputData); | ||
|
||
const encodedWormholeMessage = decodedInput[1][0]; | ||
if (encodedWormholeMessage && encodedWormholeMessage.length >= 8) { | ||
const vaaBytes = Buffer.from(encodedWormholeMessage.slice(2), 'hex'); // Remove leading '0x' | ||
const parsedVaa = parseVaa(vaaBytes); | ||
|
||
fillVaaId = `${parsedVaa.emitterChain}/${parsedVaa.emitterAddress.toString('hex')}/${ | ||
parsedVaa.sequence | ||
}`; | ||
} | ||
} catch (error) { | ||
console.error('Error decoding input data:', error); | ||
} | ||
|
||
const swapEvent = receipt.logs | ||
.filter((log) => log.address.toLowerCase() === this.swapLayerAddress.toLowerCase()) | ||
.map((log) => { | ||
try { | ||
return this.swapLayerInterface.parseLog(log); | ||
} catch (e) { | ||
return null; | ||
} | ||
}) | ||
.find((event) => event && event.name === 'Redeemed'); | ||
|
||
if (!swapEvent) return null; | ||
|
||
return { | ||
tx_hash: txHash, | ||
recipient: swapEvent.args.recipient, | ||
output_amount: BigInt(swapEvent.args.outputAmount.toString()), | ||
output_token: swapEvent.args.outputToken, | ||
timestamp: new Date(blockTime * 1000), | ||
relaying_fee: BigInt(swapEvent.args.relayingFee.toString()), | ||
fill_vaa_id: fillVaaId, | ||
}; | ||
} | ||
|
||
async getFTSwapInRange(fromBlock: number, toBlock: number): Promise<RedeemSwap[]> { | ||
const filter = { | ||
address: this.swapLayerAddress, | ||
fromBlock, | ||
toBlock, | ||
topics: [this.swapLayerInterface.getEventTopic('Redeemed')], | ||
}; | ||
|
||
const logs = await this.provider.getLogs(filter); | ||
|
||
const blocks: Map<number, ethers.providers.Block> = new Map(); | ||
|
||
const results = await Promise.all( | ||
logs.map(async (log) => { | ||
const blockTime = await this.fetchBlockTime(blocks, log.blockNumber); | ||
const txHash = log.transactionHash; | ||
return this.parseSwapLayerTransaction(txHash, blockTime); | ||
}) | ||
); | ||
|
||
return results.filter((result): result is RedeemSwap => result !== null); | ||
} | ||
|
||
private async fetchBlockTime( | ||
blocks: Map<number, ethers.providers.Block>, | ||
blockNumber: number | ||
): Promise<number> { | ||
let block = blocks.get(blockNumber); | ||
if (!block) { | ||
block = await this.provider.getBlock(blockNumber); | ||
blocks.set(blockNumber, block); | ||
} | ||
return block.timestamp; | ||
} | ||
} | ||
|
||
export default SwapLayerParser; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.