rpcpool / yellowstone-grpc

solana geyser grpc service
GNU Affero General Public License v3.0
308 stars 111 forks source link

Get block time of the block where the transaction is located #452

Closed uetkaje closed 2 weeks ago

uetkaje commented 2 weeks ago

Hi,

I need to get block time where the transaction is located.

{
        accounts: {},
        slots: {},
        transactions: {
            pumpFun: {
                accountInclude: ["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"],
                accountExclude: [],
                accountRequired: []
            }
        },
        transactionsStatus: {},
        entry: {},
    blocks: {},
        blocksMeta: {
        blockMeta: {}
    },
        commitment: "confirmed",
        accountsDataSlice: [],
        ping: undefined
}

With above subscribe request, the transaction message comes before the block meta message. So I can't get block time using the transaction's slot. Is there any way to achieve this?

Thanks in advance.

Best regards, Emre

fanatid commented 2 weeks ago

on processed commitment level it's not possible to get block time before tx

benjiqq commented 2 weeks ago

@uetkaje your example commit level is confirmed. try processed? then map after the after fact. not sure whats the best way I created this issue for general case https://github.com/rpcpool/yellowstone-grpc/issues/455

fanatid commented 2 weeks ago

issue for this: https://github.com/rpcpool/yellowstone-grpc/issues/228

uetkaje commented 2 weeks ago

@benjiqq I tried processed commitment. As @fanatid said, transactions come before block meta. There is no way to do this.

Temporary workaround:

const blocks: Record<string, number> = {};

const handleBlockMeta = async (data: SubscribeUpdate): Promise<void> => {
    blocks[data.blockMeta.slot] = parseInt(data.blockMeta.blockTime!.timestamp);
};

const handleTransaction = async (data: SubscribeUpdate): Promise<void> => {
    const transaction = data.transaction?.transaction;
    const message = transaction?.transaction?.message;
    const meta = transaction?.meta;
    if (!transaction || !message || !meta)
            return;
    if (meta?.err)
        return;
    const slot = parseInt(data.transaction.slot);
    const maxSlot = Math.max(...Object.keys(blocks).map(b => parseInt(b)));
    const timestamp = Math.floor(((blocks[maxSlot.toString()] * 1000) + ((slot - maxSlot) * 400)) / 1000);
};

I will track issue #228

Thanks a lot.

benjiqq commented 2 weeks ago

@uetkaje thats a good approach, not sure whyat block data comes after tx?