@logswap/sdk 0.5.61 → 0.5.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/history.d.ts +9 -0
- package/dist/history.js +25 -5
- package/package.json +1 -1
- package/src/history.ts +36 -6
package/dist/history.d.ts
CHANGED
|
@@ -36,6 +36,13 @@ export interface EventLogsQuery {
|
|
|
36
36
|
toBlock?: bigint;
|
|
37
37
|
/** Unix seconds: only events at or after this time. On the chain path it becomes a block search. */
|
|
38
38
|
since?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Only the newest `latest` events (still returned oldest first) — a pool's tape, not its history.
|
|
41
|
+
* On the chain path the node is asked for the last {@link LATEST_SCAN_BLOCKS} blocks only.
|
|
42
|
+
*/
|
|
43
|
+
latest?: number;
|
|
44
|
+
/** Only events from these transactions — e.g. the `RouterCall`s behind a page of routed swaps. */
|
|
45
|
+
transactionHashes?: Hex[];
|
|
39
46
|
signal?: AbortSignal;
|
|
40
47
|
}
|
|
41
48
|
/**
|
|
@@ -50,3 +57,5 @@ export declare function tableFor(c: LogswapClient, address: Address, event: stri
|
|
|
50
57
|
field: string;
|
|
51
58
|
type: string;
|
|
52
59
|
};
|
|
60
|
+
/** How far back the chain path looks for a `latest` tape: a tape is recent by definition. */
|
|
61
|
+
export declare const LATEST_SCAN_BLOCKS = 5000n;
|
package/dist/history.js
CHANGED
|
@@ -97,9 +97,19 @@ async function fromIndexer(c, q) {
|
|
|
97
97
|
filter.blockNumber = range;
|
|
98
98
|
if (q.since !== undefined)
|
|
99
99
|
filter.blockTimestamp = { greaterThanOrEqualTo: new Date(q.since * 1000).toISOString() };
|
|
100
|
+
if (q.transactionHashes)
|
|
101
|
+
filter.txHash = { in: q.transactionHashes.map((h) => h.toLowerCase()) };
|
|
102
|
+
// a tape is one page from the head, newest first; history is every page from the start
|
|
103
|
+
const pageSize = q.latest ?? PAGE;
|
|
104
|
+
const order = q.latest !== undefined ? "[BLOCK_NUMBER_DESC, LOG_INDEX_DESC]" : "PRIMARY_KEY_ASC";
|
|
100
105
|
const selection = [...inputs.map((i) => column(i.name)), "contractAddress", "blockNumber", "blockTimestamp", "txHash", "logIndex"].join(" ");
|
|
101
|
-
|
|
102
|
-
|
|
106
|
+
// postgraphile refuses a null or an empty filter, so each argument appears only when it has content
|
|
107
|
+
const hasCondition = Object.keys(condition).length > 0;
|
|
108
|
+
const hasFilter = Object.keys(filter).length > 0;
|
|
109
|
+
const decl = `$after: Cursor${hasCondition ? `, $condition: ${type}Condition` : ""}${hasFilter ? `, $filter: ${type}Filter` : ""}`;
|
|
110
|
+
const argsOf = `first: ${pageSize}, after: $after, orderBy: ${order}${hasCondition ? ", condition: $condition" : ""}${hasFilter ? ", filter: $filter" : ""}`;
|
|
111
|
+
const query = `query History(${decl}) {
|
|
112
|
+
${field}(${argsOf}) {
|
|
103
113
|
pageInfo { hasNextPage endCursor } nodes { ${selection} }
|
|
104
114
|
}
|
|
105
115
|
}`;
|
|
@@ -108,10 +118,10 @@ async function fromIndexer(c, q) {
|
|
|
108
118
|
for (let i = 0;; i++) {
|
|
109
119
|
if (i === MAX_PAGES)
|
|
110
120
|
throw new Error(`history: ${field} has more than ${PAGE * MAX_PAGES} rows`);
|
|
111
|
-
const d = await gql(q.indexer, query, { after,
|
|
121
|
+
const d = await gql(q.indexer, query, { after, ...(hasCondition ? { condition } : {}), ...(hasFilter ? { filter } : {}) }, q.signal);
|
|
112
122
|
const page = d[field];
|
|
113
123
|
rows.push(...page.nodes);
|
|
114
|
-
if (!page.pageInfo.hasNextPage || !page.pageInfo.endCursor)
|
|
124
|
+
if (q.latest !== undefined || !page.pageInfo.hasNextPage || !page.pageInfo.endCursor)
|
|
115
125
|
break;
|
|
116
126
|
after = page.pageInfo.endCursor;
|
|
117
127
|
}
|
|
@@ -130,12 +140,22 @@ async function fromIndexer(c, q) {
|
|
|
130
140
|
.sort((a, b) => (a.blockNumber === b.blockNumber ? a.logIndex - b.logIndex : a.blockNumber < b.blockNumber ? -1 : 1));
|
|
131
141
|
}
|
|
132
142
|
// ─── the chain path ──────────────────────────────────────────────────────────
|
|
143
|
+
/** How far back the chain path looks for a `latest` tape: a tape is recent by definition. */
|
|
144
|
+
export const LATEST_SCAN_BLOCKS = 5000n;
|
|
133
145
|
async function fromChain(c, q) {
|
|
134
146
|
let fromBlock = q.fromBlock ?? 0n;
|
|
135
147
|
const toBlock = q.toBlock ?? (await c.public.getBlockNumber());
|
|
136
148
|
if (q.since !== undefined)
|
|
137
149
|
fromBlock = await blockAtOrAfter(c, BigInt(q.since), fromBlock, toBlock);
|
|
138
|
-
|
|
150
|
+
if (q.latest !== undefined && toBlock - fromBlock > LATEST_SCAN_BLOCKS)
|
|
151
|
+
fromBlock = toBlock - LATEST_SCAN_BLOCKS;
|
|
152
|
+
let logs = (await c.public.getLogs({ address: q.address, event: q.event, args: q.args, fromBlock, toBlock }));
|
|
153
|
+
if (q.transactionHashes) {
|
|
154
|
+
const want = new Set(q.transactionHashes.map((h) => h.toLowerCase()));
|
|
155
|
+
logs = logs.filter((l) => want.has(l.transactionHash.toLowerCase()));
|
|
156
|
+
}
|
|
157
|
+
if (q.latest !== undefined)
|
|
158
|
+
logs = logs.slice(-q.latest);
|
|
139
159
|
return logs.map((l) => ({
|
|
140
160
|
address: q.address,
|
|
141
161
|
args: l.args,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logswap/sdk",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.62",
|
|
4
4
|
"description": "TypeScript SDK for Logswap, the liquidity primitive introducing the logarithmic invariant — typed wrappers over the CPoolManager / FPoolManager / Router / Lens surface.",
|
|
5
5
|
"license": "GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
package/src/history.ts
CHANGED
|
@@ -40,6 +40,13 @@ export interface EventLogsQuery {
|
|
|
40
40
|
toBlock?: bigint;
|
|
41
41
|
/** Unix seconds: only events at or after this time. On the chain path it becomes a block search. */
|
|
42
42
|
since?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Only the newest `latest` events (still returned oldest first) — a pool's tape, not its history.
|
|
45
|
+
* On the chain path the node is asked for the last {@link LATEST_SCAN_BLOCKS} blocks only.
|
|
46
|
+
*/
|
|
47
|
+
latest?: number;
|
|
48
|
+
/** Only events from these transactions — e.g. the `RouterCall`s behind a page of routed swaps. */
|
|
49
|
+
transactionHashes?: Hex[];
|
|
43
50
|
signal?: AbortSignal;
|
|
44
51
|
}
|
|
45
52
|
|
|
@@ -119,10 +126,19 @@ async function fromIndexer<A>(c: LogswapClient, q: EventLogsQuery): Promise<Hist
|
|
|
119
126
|
if (q.toBlock !== undefined) range.lessThanOrEqualTo = q.toBlock.toString();
|
|
120
127
|
if (Object.keys(range).length) filter.blockNumber = range;
|
|
121
128
|
if (q.since !== undefined) filter.blockTimestamp = { greaterThanOrEqualTo: new Date(q.since * 1000).toISOString() };
|
|
129
|
+
if (q.transactionHashes) filter.txHash = { in: q.transactionHashes.map((h) => h.toLowerCase()) };
|
|
130
|
+
// a tape is one page from the head, newest first; history is every page from the start
|
|
131
|
+
const pageSize = q.latest ?? PAGE;
|
|
132
|
+
const order = q.latest !== undefined ? "[BLOCK_NUMBER_DESC, LOG_INDEX_DESC]" : "PRIMARY_KEY_ASC";
|
|
122
133
|
|
|
123
134
|
const selection = [...inputs.map((i) => column(i.name!)), "contractAddress", "blockNumber", "blockTimestamp", "txHash", "logIndex"].join(" ");
|
|
124
|
-
|
|
125
|
-
|
|
135
|
+
// postgraphile refuses a null or an empty filter, so each argument appears only when it has content
|
|
136
|
+
const hasCondition = Object.keys(condition).length > 0;
|
|
137
|
+
const hasFilter = Object.keys(filter).length > 0;
|
|
138
|
+
const decl = `$after: Cursor${hasCondition ? `, $condition: ${type}Condition` : ""}${hasFilter ? `, $filter: ${type}Filter` : ""}`;
|
|
139
|
+
const argsOf = `first: ${pageSize}, after: $after, orderBy: ${order}${hasCondition ? ", condition: $condition" : ""}${hasFilter ? ", filter: $filter" : ""}`;
|
|
140
|
+
const query = `query History(${decl}) {
|
|
141
|
+
${field}(${argsOf}) {
|
|
126
142
|
pageInfo { hasNextPage endCursor } nodes { ${selection} }
|
|
127
143
|
}
|
|
128
144
|
}`;
|
|
@@ -135,12 +151,12 @@ async function fromIndexer<A>(c: LogswapClient, q: EventLogsQuery): Promise<Hist
|
|
|
135
151
|
const d: Record<string, Conn> = await gql<Record<string, Conn>>(
|
|
136
152
|
q.indexer!,
|
|
137
153
|
query,
|
|
138
|
-
{ after,
|
|
154
|
+
{ after, ...(hasCondition ? { condition } : {}), ...(hasFilter ? { filter } : {}) },
|
|
139
155
|
q.signal,
|
|
140
156
|
);
|
|
141
157
|
const page: Conn = d[field]!;
|
|
142
158
|
rows.push(...page.nodes);
|
|
143
|
-
if (!page.pageInfo.hasNextPage || !page.pageInfo.endCursor) break;
|
|
159
|
+
if (q.latest !== undefined || !page.pageInfo.hasNextPage || !page.pageInfo.endCursor) break;
|
|
144
160
|
after = page.pageInfo.endCursor;
|
|
145
161
|
}
|
|
146
162
|
// a table can hold a previous deployment's rows (an indexer not yet reset): keep this contract's
|
|
@@ -160,12 +176,26 @@ async function fromIndexer<A>(c: LogswapClient, q: EventLogsQuery): Promise<Hist
|
|
|
160
176
|
|
|
161
177
|
// ─── the chain path ──────────────────────────────────────────────────────────
|
|
162
178
|
|
|
179
|
+
/** How far back the chain path looks for a `latest` tape: a tape is recent by definition. */
|
|
180
|
+
export const LATEST_SCAN_BLOCKS = 5_000n;
|
|
181
|
+
|
|
163
182
|
async function fromChain<A>(c: LogswapClient, q: EventLogsQuery): Promise<HistoryLog<A>[]> {
|
|
164
183
|
let fromBlock = q.fromBlock ?? 0n;
|
|
165
184
|
const toBlock = q.toBlock ?? (await c.public.getBlockNumber());
|
|
166
185
|
if (q.since !== undefined) fromBlock = await blockAtOrAfter(c, BigInt(q.since), fromBlock, toBlock);
|
|
167
|
-
|
|
168
|
-
|
|
186
|
+
if (q.latest !== undefined && toBlock - fromBlock > LATEST_SCAN_BLOCKS) fromBlock = toBlock - LATEST_SCAN_BLOCKS;
|
|
187
|
+
let logs = (await c.public.getLogs({ address: q.address, event: q.event, args: q.args, fromBlock, toBlock } as never)) as unknown as Array<{
|
|
188
|
+
args: A;
|
|
189
|
+
blockNumber: bigint;
|
|
190
|
+
transactionHash: Hex;
|
|
191
|
+
logIndex: number;
|
|
192
|
+
}>;
|
|
193
|
+
if (q.transactionHashes) {
|
|
194
|
+
const want = new Set(q.transactionHashes.map((h) => h.toLowerCase()));
|
|
195
|
+
logs = logs.filter((l) => want.has(l.transactionHash.toLowerCase()));
|
|
196
|
+
}
|
|
197
|
+
if (q.latest !== undefined) logs = logs.slice(-q.latest);
|
|
198
|
+
return logs.map((l) => ({
|
|
169
199
|
address: q.address,
|
|
170
200
|
args: l.args,
|
|
171
201
|
blockNumber: l.blockNumber,
|