|
|
|
@ -1,38 +1,67 @@ |
|
|
|
|
import { DomainToChain } from '../../consts/domains'; |
|
|
|
|
import { Message, MessageStatus, PartialTransactionReceipt } from '../../types'; |
|
|
|
|
import { |
|
|
|
|
Message, |
|
|
|
|
MessageStatus, |
|
|
|
|
MessageStub, |
|
|
|
|
PartialTransactionReceipt, |
|
|
|
|
} from '../../types'; |
|
|
|
|
import { logger } from '../../utils/logger'; |
|
|
|
|
|
|
|
|
|
import { MessageEntry, MessagesQueryResult, TransactionEntry } from './types'; |
|
|
|
|
import { |
|
|
|
|
MessageEntry, |
|
|
|
|
MessageStubEntry, |
|
|
|
|
MessagesQueryResult, |
|
|
|
|
MessagesStubQueryResult, |
|
|
|
|
TransactionEntry, |
|
|
|
|
} from './types'; |
|
|
|
|
|
|
|
|
|
export function parseResultData( |
|
|
|
|
export function parseMessageStubResult( |
|
|
|
|
data: MessagesStubQueryResult | undefined, |
|
|
|
|
): MessageStub[] { |
|
|
|
|
if (!data?.message?.length) return []; |
|
|
|
|
return data.message |
|
|
|
|
.map(parseMessageStub) |
|
|
|
|
.filter((m): m is MessageStub => !!m); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export function parseMessageQueryResult( |
|
|
|
|
data: MessagesQueryResult | undefined, |
|
|
|
|
): Message[] { |
|
|
|
|
if (!data?.message?.length) return []; |
|
|
|
|
return data.message.map(parseMessage).filter((m): m is Message => !!m); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function parseMessage(m: MessageEntry): Message | null { |
|
|
|
|
function parseMessageStub(m: MessageStubEntry): MessageStub | null { |
|
|
|
|
try { |
|
|
|
|
const { delivered_message, message_states } = m; |
|
|
|
|
let status = MessageStatus.Pending; |
|
|
|
|
let destinationTransaction: PartialTransactionReceipt | undefined = |
|
|
|
|
undefined; |
|
|
|
|
if (delivered_message) { |
|
|
|
|
status = MessageStatus.Delivered; |
|
|
|
|
destinationTransaction = parseTransaction(delivered_message.transaction); |
|
|
|
|
} else if (message_states.length > 0) { |
|
|
|
|
const latestState = message_states.at(-1); |
|
|
|
|
if (latestState && latestState.processable) { |
|
|
|
|
status = MessageStatus.Failing; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
const status = getMessageStatus(m); |
|
|
|
|
return { |
|
|
|
|
id: m.id, |
|
|
|
|
status, |
|
|
|
|
sender: decodeBinaryHex(m.sender), |
|
|
|
|
recipient: decodeBinaryHex(m.recipient), |
|
|
|
|
originChainId: DomainToChain[m.origin], |
|
|
|
|
destinationChainId: DomainToChain[m.destination], |
|
|
|
|
timestamp: parseTimestampString(m.timestamp), |
|
|
|
|
}; |
|
|
|
|
} catch (error) { |
|
|
|
|
logger.error('Error parsing message', error); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function parseMessage(m: MessageEntry): Message | null { |
|
|
|
|
try { |
|
|
|
|
const status = getMessageStatus(m); |
|
|
|
|
const destinationTransaction = |
|
|
|
|
status === MessageStatus.Delivered && m.delivered_message?.transaction |
|
|
|
|
? parseTransaction(m.delivered_message.transaction) |
|
|
|
|
: undefined; |
|
|
|
|
return { |
|
|
|
|
id: m.id, |
|
|
|
|
status, |
|
|
|
|
sender: decodeBinaryHex(m.sender), |
|
|
|
|
recipient: decodeBinaryHex(m.recipient), |
|
|
|
|
body: m.msg_body ?? '', |
|
|
|
|
body: decodeBinaryHex(m.msg_body ?? ''), |
|
|
|
|
originChainId: DomainToChain[m.origin], |
|
|
|
|
destinationChainId: DomainToChain[m.destination], |
|
|
|
|
timestamp: parseTimestampString(m.timestamp), |
|
|
|
@ -59,11 +88,20 @@ function parseTimestampString(t: string) { |
|
|
|
|
return new Date(t).getTime(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO use text in db instead of bytea
|
|
|
|
|
// TODO remove when db uses text
|
|
|
|
|
function decodeBinaryHex(b: string) { |
|
|
|
|
return btoa(b); |
|
|
|
|
// const byteArray = b.substring(3).map(c => parseInt(c))
|
|
|
|
|
// return Array.from(byteArray, (byte)=>
|
|
|
|
|
// ('0' + (byte & 0xFF).toString(16)).slice(-2)
|
|
|
|
|
// ).join('')
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getMessageStatus(m: MessageEntry | MessageStubEntry) { |
|
|
|
|
const { delivered_message, message_states } = m; |
|
|
|
|
if (delivered_message) { |
|
|
|
|
return MessageStatus.Delivered; |
|
|
|
|
} else if (message_states.length > 0) { |
|
|
|
|
const latestState = message_states.at(-1); |
|
|
|
|
if (latestState && latestState.processable) { |
|
|
|
|
return MessageStatus.Failing; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return MessageStatus.Pending; |
|
|
|
|
} |
|
|
|
|