Skip to content

Commit

Permalink
ft_watcher: track fill vaas for cctp execution and fill accounts for …
Browse files Browse the repository at this point in the history
…local execution

Signed-off-by: bingyuyap <[email protected]>
  • Loading branch information
bingyuyap committed Aug 8, 2024
1 parent 63aaa73 commit 938471c
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 16 deletions.
10 changes: 10 additions & 0 deletions common/src/solana.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,13 @@ export async function makeRpcCall(
export function decodeBase64Data(encodedData: string) {
return new Uint8Array(Buffer.from(encodedData, 'base64'));
}

const SOLANA_SEQ_LOG = 'Program log: Sequence: ';
export function parseWormholeSequenceFromLogs(logs: string[]): number | null {
for (const log of logs) {
if (log.startsWith(SOLANA_SEQ_LOG)) {
return parseInt(log.replace(SOLANA_SEQ_LOG, ''), 10);
}
}
return null;
}
9 changes: 6 additions & 3 deletions database/fast-transfer-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ CREATE TABLE fast_transfer_executions (
execution_payer VARCHAR(255),
execution_tx_hash VARCHAR(255),
execution_slot BIGINT,
execution_time TIMESTAMP
execution_time TIMESTAMP,
-- fill_id can be a vaa id (cctp) or solana account pubkey (local)
fill_id VARCHAR(255),
);

-- Settlement is created when the settlement is created in the `settleFastTransfer`
Expand Down Expand Up @@ -96,11 +98,12 @@ CREATE TABLE auction_history_mapping (

-- Redeem Swaps table to track the final swap before funds reach the user's account
CREATE TABLE redeem_swaps (
fill_vaa_id VARCHAR(255) PRIMARY KEY,
-- fill_id can be a vaa id (cctp) or solana account pubkey (local)
fill_id VARCHAR(255) PRIMARY KEY,
tx_hash VARCHAR(255) NOT NULL,
recipient VARCHAR(255) NOT NULL,
output_token VARCHAR(255) NOT NULL,
output_amount BIGINT NOT NULL,
relaying_fee BIGINT NOT NULL,
timestamp TIMESTAMP NOT NULL
redeem_time TIMESTAMP NOT NULL
);
4 changes: 2 additions & 2 deletions watcher/src/fastTransfer/swapLayer/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ class SwapLayerParser {
recipient: swapEvent.args.recipient,
output_amount: BigInt(swapEvent.args.outputAmount.toString()),
output_token: swapEvent.args.outputToken,
timestamp: new Date(blockTime * 1000),
redeem_time: new Date(blockTime * 1000),
relaying_fee: BigInt(swapEvent.args.relayingFee.toString()),
fill_vaa_id: fillVaaId,
fill_id: fillVaaId,
};
}

Expand Down
6 changes: 4 additions & 2 deletions watcher/src/fastTransfer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export type FastTransferExecutionInfo = {
execution_time: Date;
execution_tx_hash: string;
execution_slot: bigint;
// fill_id can be a vaa id (cctp) or a Solana public key
fill_id: string;
};

export type FastTransferSettledInfo = {
Expand Down Expand Up @@ -149,6 +151,6 @@ export type RedeemSwap = {
output_token: string;
output_amount: bigint;
relaying_fee: bigint;
timestamp: Date;
fill_vaa_id: string;
redeem_time: Date;
fill_id: string;
};
3 changes: 1 addition & 2 deletions watcher/src/watchers/FTEVMWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { AXIOS_CONFIG_JSON, RPCS_BY_CHAIN } from '../consts';
import { makeBlockKey } from '../databases/utils';
import TokenRouterParser from '../fastTransfer/tokenRouter/parser';
import SwapLayerParser from '../fastTransfer/swapLayer/parser';
import { MarketOrder, RedeemSwap } from '../fastTransfer/types';
import { Block } from './EVMWatcher';
import { BigNumber } from 'ethers';
import axios from 'axios';
Expand Down Expand Up @@ -151,7 +150,7 @@ export class FTEVMWatcher extends Watcher {
}

if (swapLayerResults.length) {
await this.saveBatch(swapLayerResults, 'redeem_swaps', 'fill_vaa_id', fromBlock, toBlock);
await this.saveBatch(swapLayerResults, 'redeem_swaps', 'fill_id', fromBlock, toBlock);
}

// we do not need to compare the lastBlockTime from tokenRouter and swapLayer as they both use toBlock
Expand Down
31 changes: 26 additions & 5 deletions watcher/src/watchers/FTSolanaWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ import {
AuctionUpdatedEvent,
} from '../fastTransfer/types';
import knex, { Knex } from 'knex';
import { assertEnvironmentVariable } from '@wormhole-foundation/wormhole-monitor-common';
import {
assertEnvironmentVariable,
parseWormholeSequenceFromLogs,
} from '@wormhole-foundation/wormhole-monitor-common';
import { getLogger } from '../utils/logger';
import base58 from 'bs58';
import {
Expand Down Expand Up @@ -503,7 +506,8 @@ export class FTSolanaWatcher extends SolanaWatcher {
tx: VersionedTransactionResponse,
payerAccount: PublicKey,
auctionAccountPubkey: PublicKey,
fastVaaAccount: PublicKey
fastVaaAccount: PublicKey,
fillVaaId: string
): Promise<{ id: FastTransferId; info: FastTransferExecutionInfo }> {
const vaaAccount = await VaaAccount.fetch(
this.matchingEngineProgram.program.provider.connection,
Expand Down Expand Up @@ -542,6 +546,7 @@ export class FTSolanaWatcher extends SolanaWatcher {
execution_time: new Date(tx.blockTime! * 1000),
execution_tx_hash: tx.transaction.signatures[0],
execution_slot: BigInt(tx.slot),
fill_id: fillVaaId,
},
};
}
Expand All @@ -556,14 +561,28 @@ export class FTSolanaWatcher extends SolanaWatcher {
throw new Error('Insufficient account key indexes for parseExecuteFastOrderCctp');
}
const payerAccountPubkey = accountKeys[accountKeyIndexes[0]];
const custodianAccountPubkey = accountKeys[accountKeyIndexes[3]];
const fastVaaAccountPubkey = accountKeys[accountKeyIndexes[4]];
const auctionAccountPubkey = accountKeys[accountKeyIndexes[5]];
const seq = parseWormholeSequenceFromLogs(res.meta?.logMessages || []);

if (!seq) {
throw new Error('Cannot find fill sequnece');
}

// in `execute_fast_order_cctp` (see: https://github.com/wormhole-foundation/example-liquidity-layer/blob/63f2b423026ac1ad8b099bc3ecd44ba4fc64aae2/solana/programs/matching-engine/src/processor/auction/execute_fast_order/cctp.rs#L158)
// custodian is used as the emitter
const emitterInHex = custodianAccountPubkey.toBuffer().toString('hex');

// matching engine only exists in Solana. This only checks for Solana matching engine anyways. So we can be sure that emitter chain is always 1
const fillVaaId = `1/${emitterInHex}/${seq}`;

const { id, info } = await this.computeExecutionData(
res,
payerAccountPubkey,
auctionAccountPubkey,
fastVaaAccountPubkey
fastVaaAccountPubkey,
fillVaaId
);

await this.saveFastTransferInfo('fast_transfer_executions', info);
Expand All @@ -583,18 +602,20 @@ export class FTSolanaWatcher extends SolanaWatcher {
) {
const accountKeys = res.transaction.message.getAccountKeys().staticAccountKeys;
const accountKeyIndexes = instruction.accountKeyIndexes;
if (accountKeyIndexes.length < 4) {
if (accountKeyIndexes.length < 5) {
throw new Error('Insufficient account key indexes for parseExecuteFastOrderLocal');
}
const payerAccountPubkey = accountKeys[accountKeyIndexes[0]];
const fastVaaAccountPubkey = accountKeys[accountKeyIndexes[2]];
const auctionAccountPubkey = accountKeys[accountKeyIndexes[3]];
const fastFillAccountPubkey = accountKeys[accountKeyIndexes[4]];

const { id, info } = await this.computeExecutionData(
res,
payerAccountPubkey,
auctionAccountPubkey,
fastVaaAccountPubkey
fastVaaAccountPubkey,
fastFillAccountPubkey.toBase58()
);

await this.saveFastTransferInfo('fast_transfer_executions', info);
Expand Down
4 changes: 2 additions & 2 deletions watcher/src/watchers/__tests__/FTEVMWatcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ describe('SwapLayerParser', () => {
output_token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
output_amount: BigInt('20000000000'),
relaying_fee: BigInt('10447500'),
timestamp: new Date(mockBlock.timestamp * 1000),
fill_vaa_id: '1/cb0406e59555bf0371b7c4fff1812a11a8d92dad02ad422062971d61dcce2cd0/2',
redeem_time: new Date(mockBlock.timestamp * 1000),
fill_id: '1/cb0406e59555bf0371b7c4fff1812a11a8d92dad02ad422062971d61dcce2cd0/2',
});
});
});
2 changes: 2 additions & 0 deletions watcher/src/watchers/__tests__/FTSolanaWatcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ test('should parse executeFastOrderLocal', async () => {
execution_time: new Date('2024-05-23T15:58:23.000Z'),
execution_tx_hash: txHash,
fast_vaa_hash: 'fd99d2d20f7458cae97de7d7bcf94cbdc5ac734264fa495bf01f1748e28039da',
fill_id: 'B2qkDPs1gPh69uvKN5mbtHRAFtiMaZCe4vu6Wp3yaaJ1',
});
});

Expand Down Expand Up @@ -156,6 +157,7 @@ test('should parse executeFastOrderCctp', async () => {
execution_slot: 301864332n,
execution_time: new Date('2024-05-28T03:15:19.000Z'),
fast_vaa_hash: '14a5187e40e4fd2b2950cd8332b4142259757f4cbf7cffcb7cc95249df8415b9',
fill_id: '1/3e374fcd3aaf2ed067f3c93d21416855ec7916cfd2c2127bcbc68b3b1fb73077/7970',
});
});

Expand Down

0 comments on commit 938471c

Please sign in to comment.