diff --git a/src/contract.ts b/src/contract.ts index afc0b421..baa3e5a1 100644 --- a/src/contract.ts +++ b/src/contract.ts @@ -1,6 +1,7 @@ import { Address, UniqueArray, + LT_COLLATOR, } from './utils'; import { AbiParam, @@ -278,9 +279,9 @@ export class Contract { : subscriber.transactions(this.address) ).flatMap(item => item.transactions) .takeWhile(item => range == null || - (range.fromLt == null || item.id.lt > range.fromLt) && + (range.fromLt == null || LT_COLLATOR.compare(item.id.lt, range.fromLt) > 0) && (range.fromUtime == null || item.createdAt > range.fromUtime) && - (range.toLt == null || item.id.lt < range.toLt) && + (range.toLt == null || LT_COLLATOR.compare(item.id.lt, range.toLt) < 0) && (range.toUtime == null || item.createdAt < range.toUtime), ) .flatMap(tx => this.decodeTransactionEvents({ transaction: tx }) @@ -318,10 +319,10 @@ export class Contract { } const filteredTransactions = transactions.filter((item) => ( - (range?.fromLt == null || item.id.lt > range.fromLt) && + (range?.fromLt == null || LT_COLLATOR.compare(item.id.lt, range.fromLt) > 0) && (range?.fromUtime == null || item.createdAt > range.fromUtime) && - (range?.toLt == null || item.id.lt < range?.toLt) && - (range?.toUtime == null || item.createdAt < range?.toUtime) + (range?.toLt == null || LT_COLLATOR.compare(item.id.lt, range.toLt) < 0) && + (range?.toUtime == null || item.createdAt < range.toUtime) )); if (filteredTransactions.length > 0) { diff --git a/src/index.ts b/src/index.ts index 2e049f43..023e1538 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,7 +36,7 @@ export * from './api'; export * from './models'; export * from './contract'; export { Stream, Subscriber } from './stream'; -export { Address, CheckAddress, AddressLiteral, UniqueArray, mergeTransactions } from './utils'; +export { Address, CheckAddress, AddressLiteral, UniqueArray, mergeTransactions, LT_COLLATOR } from './utils'; /** * @category Provider @@ -858,6 +858,11 @@ export class ProviderRpcClient { address: new Address(data.address), state: data.state, }), + 'messageStatusUpdated': (data) => ({ + address: new Address(data.address), + hash: data.hash, + transaction: data.transaction != null ? parseTransaction(data.transaction) : undefined, + }), 'networkChanged': data => data, 'permissionsChanged': (data) => ({ permissions: parsePermissions(data.permissions), diff --git a/src/stream.ts b/src/stream.ts index c4cf802d..24020fa7 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -1,5 +1,5 @@ import { ProviderEvent, ProviderEventData } from './api'; -import { Address, getUniqueId } from './utils'; +import { Address, getUniqueId, LT_COLLATOR } from './utils'; import { TransactionId, Transaction, TransactionsBatchInfo, TransactionWithAccount } from './models'; import { ProviderRpcClient, Subscription } from './index'; @@ -788,8 +788,6 @@ type UnorderedTransactionsScannerParams = { onEnd: (eof: boolean) => void; fromLt?: string; fromUtime?: number; - toLt?: string; - toUtime?: number; }; class UnorderedTransactionsScanner implements Scanner { @@ -829,40 +827,33 @@ class UnorderedTransactionsScanner implements Scanner { break; } - const fromFilteredTransactions = transactions.filter((item) => ( - (params.fromLt == null || item.id.lt > params.fromLt) && + const filteredTransactions = transactions.filter((item) => ( + (params.fromLt == null || LT_COLLATOR.compare(item.id.lt, params.fromLt) > 0) && (params.fromUtime == null || item.createdAt > params.fromUtime) )); - if (fromFilteredTransactions.length == 0) { + if (filteredTransactions.length == 0) { state.complete = true; break; } - const toFilteredTransactions = fromFilteredTransactions.filter((item) => ( - (params.toLt == null || item.id.lt < params.toLt) && - (params.toUtime == null || item.createdAt < params.toUtime) - )); - - if (toFilteredTransactions.length > 0) { - const info = { - maxLt: toFilteredTransactions[0].id.lt, - minLt: toFilteredTransactions[toFilteredTransactions.length - 1].id.lt, - batchType: 'old', - } as TransactionsBatchInfo; - - this.queue.enqueue(async () => { - const isRunning = this.params.onData({ - address: this.params.address, - transactions: toFilteredTransactions, - info, - }); - if (!isRunning) { - state.complete = true; - this.isRunning = false; - } + const info = { + maxLt: filteredTransactions[0].id.lt, + minLt: filteredTransactions[filteredTransactions.length - 1].id.lt, + batchType: 'old', + } as TransactionsBatchInfo; + + this.queue.enqueue(async () => { + const isRunning = this.params.onData({ + address: this.params.address, + transactions: filteredTransactions, + info, }); - } + if (!isRunning) { + state.complete = true; + this.isRunning = false; + } + }); if (continuation != null) { this.continuation = continuation; diff --git a/src/utils.ts b/src/utils.ts index 41c09163..9d9b3ab3 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -77,6 +77,11 @@ type IsHexString = ? IsHexString : T extends '' ? L['length'] extends 32 ? true : never : never +/** + * @category Utils + */ +export const LT_COLLATOR: Intl.Collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }); + /** * Modifies knownTransactions array, merging it with new transactions. * All arrays are assumed to be sorted by descending logical time. @@ -113,7 +118,7 @@ export function mergeTransactions( let i = 0; while ( i < knownTransactions.length && - knownTransactions[i].id.lt.localeCompare(info.maxLt) >= 0 + LT_COLLATOR.compare(knownTransactions[i].id.lt, info.maxLt) >= 0 ) { ++i; }