@varla/sdk 1.1.0 → 1.2.0

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.
Files changed (43) hide show
  1. package/dist/events/decode.d.ts +14 -0
  2. package/dist/events/decode.d.ts.map +1 -0
  3. package/dist/events/decode.js +26 -0
  4. package/dist/events/defs.d.ts +24 -0
  5. package/dist/events/defs.d.ts.map +1 -0
  6. package/dist/events/defs.js +61 -0
  7. package/dist/events/index.d.ts +3 -0
  8. package/dist/events/index.d.ts.map +1 -1
  9. package/dist/events/index.js +3 -0
  10. package/dist/events/oracleRegistrySync.d.ts +6 -6
  11. package/dist/events/oracleRegistrySync.d.ts.map +1 -1
  12. package/dist/events/oracleRegistrySync.js +94 -30
  13. package/dist/events/recent.d.ts +19 -0
  14. package/dist/events/recent.d.ts.map +1 -0
  15. package/dist/events/recent.js +24 -0
  16. package/dist/format.d.ts +36 -0
  17. package/dist/format.d.ts.map +1 -0
  18. package/dist/format.js +109 -0
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +2 -0
  22. package/dist/views/accessManager.d.ts +124 -0
  23. package/dist/views/accessManager.d.ts.map +1 -0
  24. package/dist/views/accessManager.js +178 -0
  25. package/dist/views/admin.d.ts +13606 -0
  26. package/dist/views/admin.d.ts.map +1 -0
  27. package/dist/views/admin.js +25 -0
  28. package/dist/views/core.d.ts +150 -0
  29. package/dist/views/core.d.ts.map +1 -1
  30. package/dist/views/core.js +156 -0
  31. package/dist/views/index.d.ts +3 -0
  32. package/dist/views/index.d.ts.map +1 -1
  33. package/dist/views/index.js +3 -0
  34. package/dist/views/liquidators.d.ts +40 -0
  35. package/dist/views/liquidators.d.ts.map +1 -0
  36. package/dist/views/liquidators.js +20 -0
  37. package/dist/views/oracle.d.ts +50 -0
  38. package/dist/views/oracle.d.ts.map +1 -1
  39. package/dist/views/oracle.js +72 -0
  40. package/dist/views/pool.d.ts +43 -8
  41. package/dist/views/pool.d.ts.map +1 -1
  42. package/dist/views/pool.js +27 -0
  43. package/package.json +2 -1
@@ -0,0 +1,14 @@
1
+ import type { AbiEvent, Log } from "viem";
2
+ export type DecodedEvent<TArgs = Record<string, unknown>> = {
3
+ args: TArgs;
4
+ eventName: string;
5
+ log: Log;
6
+ };
7
+ /**
8
+ * Decode logs for a single event definition. Returns only successfully decoded entries.
9
+ */
10
+ export declare function decodeEventLogs(params: {
11
+ event: AbiEvent;
12
+ logs: Log[];
13
+ }): DecodedEvent[];
14
+ //# sourceMappingURL=decode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../../src/events/decode.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAG1C,MAAM,MAAM,YAAY,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC1D,IAAI,EAAE,KAAK,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,GAAG,EAAE,CAAA;CAAE,GAAG,YAAY,EAAE,CAsBxF"}
@@ -0,0 +1,26 @@
1
+ // Note: explicit .js extension is required for Node ESM resolution.
2
+ import { decodeEventLog } from "viem";
3
+ /**
4
+ * Decode logs for a single event definition. Returns only successfully decoded entries.
5
+ */
6
+ export function decodeEventLogs(params) {
7
+ const out = [];
8
+ for (const log of params.logs) {
9
+ try {
10
+ const decoded = decodeEventLog({
11
+ abi: [params.event],
12
+ data: log.data,
13
+ topics: log.topics,
14
+ });
15
+ out.push({
16
+ args: decoded.args,
17
+ eventName: decoded.eventName,
18
+ log,
19
+ });
20
+ }
21
+ catch {
22
+ // ignore logs that don't decode cleanly (RPCs can return unrelated logs when address is omitted)
23
+ }
24
+ }
25
+ return out;
26
+ }
@@ -0,0 +1,24 @@
1
+ import type { AbiEvent } from "viem";
2
+ export declare const ORACLE_EVENTS: {
3
+ readonly PositionConfigured: AbiEvent;
4
+ readonly OppositePositionsConfigured: AbiEvent;
5
+ readonly NegRiskPositionConfigured: AbiEvent;
6
+ readonly NegRiskPositionsBatchConfigured: AbiEvent;
7
+ readonly PriceUpdated: AbiEvent;
8
+ readonly PositionInvalidated: AbiEvent;
9
+ readonly PositionValidated: AbiEvent;
10
+ };
11
+ export declare const CORE_EVENTS: {
12
+ readonly Deposit: AbiEvent;
13
+ readonly Withdraw: AbiEvent;
14
+ readonly Borrow: AbiEvent;
15
+ readonly Repay: AbiEvent;
16
+ readonly Liquidate: AbiEvent;
17
+ readonly LiquidationDebtRepaid: AbiEvent;
18
+ };
19
+ export declare const POOL_EVENTS: {
20
+ readonly Draw: AbiEvent;
21
+ readonly Repay: AbiEvent;
22
+ readonly AccrueInterest: AbiEvent;
23
+ };
24
+ //# sourceMappingURL=defs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../src/events/defs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AASrC,eAAO,MAAM,aAAa;iCAIlB,QAAQ;0CAIR,QAAQ;wCAIR,QAAQ;8CAIR,QAAQ;2BAIR,QAAQ;kCAIR,QAAQ;gCAIR,QAAQ;CACN,CAAC;AAMX,eAAO,MAAM,WAAW;sBAC+C,QAAQ;uBACN,QAAQ;qBACZ,QAAQ;oBACV,QAAQ;wBACA,QAAQ;oCAI3E,QAAQ;CACN,CAAC;AAMX,eAAO,MAAM,WAAW;mBACyC,QAAQ;oBACN,QAAQ;6BAInE,QAAQ;CACN,CAAC"}
@@ -0,0 +1,61 @@
1
+ // Note: explicit .js extension is required for Node ESM resolution.
2
+ import { getAbiItem } from "viem";
3
+ import { abis } from "../generated.js";
4
+ // ---------------------------------------------------------------------------
5
+ // Oracle
6
+ // ---------------------------------------------------------------------------
7
+ export const ORACLE_EVENTS = {
8
+ PositionConfigured: getAbiItem({
9
+ abi: abis.VARLAORACLE_ABI,
10
+ name: "PositionConfigured",
11
+ }),
12
+ OppositePositionsConfigured: getAbiItem({
13
+ abi: abis.VARLAORACLE_ABI,
14
+ name: "OppositePositionsConfigured",
15
+ }),
16
+ NegRiskPositionConfigured: getAbiItem({
17
+ abi: abis.VARLAORACLE_ABI,
18
+ name: "NegRiskPositionConfigured",
19
+ }),
20
+ NegRiskPositionsBatchConfigured: getAbiItem({
21
+ abi: abis.VARLAORACLE_ABI,
22
+ name: "NegRiskPositionsBatchConfigured",
23
+ }),
24
+ PriceUpdated: getAbiItem({
25
+ abi: abis.VARLAORACLE_ABI,
26
+ name: "PriceUpdated",
27
+ }),
28
+ PositionInvalidated: getAbiItem({
29
+ abi: abis.VARLAORACLE_ABI,
30
+ name: "PositionInvalidated",
31
+ }),
32
+ PositionValidated: getAbiItem({
33
+ abi: abis.VARLAORACLE_ABI,
34
+ name: "PositionValidated",
35
+ }),
36
+ };
37
+ // ---------------------------------------------------------------------------
38
+ // Core
39
+ // ---------------------------------------------------------------------------
40
+ export const CORE_EVENTS = {
41
+ Deposit: getAbiItem({ abi: abis.VARLACORE_ABI, name: "Deposit" }),
42
+ Withdraw: getAbiItem({ abi: abis.VARLACORE_ABI, name: "Withdraw" }),
43
+ Borrow: getAbiItem({ abi: abis.VARLACORE_ABI, name: "Borrow" }),
44
+ Repay: getAbiItem({ abi: abis.VARLACORE_ABI, name: "Repay" }),
45
+ Liquidate: getAbiItem({ abi: abis.VARLACORE_ABI, name: "Liquidate" }),
46
+ LiquidationDebtRepaid: getAbiItem({
47
+ abi: abis.VARLACORE_ABI,
48
+ name: "LiquidationDebtRepaid",
49
+ }),
50
+ };
51
+ // ---------------------------------------------------------------------------
52
+ // Pool
53
+ // ---------------------------------------------------------------------------
54
+ export const POOL_EVENTS = {
55
+ Draw: getAbiItem({ abi: abis.VARLAPOOL_ABI, name: "Draw" }),
56
+ Repay: getAbiItem({ abi: abis.VARLAPOOL_ABI, name: "Repay" }),
57
+ AccrueInterest: getAbiItem({
58
+ abi: abis.VARLAPOOL_ABI,
59
+ name: "AccrueInterest",
60
+ }),
61
+ };
@@ -1,3 +1,6 @@
1
1
  export * from "./logs.js";
2
+ export * from "./defs.js";
3
+ export * from "./decode.js";
4
+ export * from "./recent.js";
2
5
  export * from "./oracleRegistrySync.js";
3
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/events/index.ts"],"names":[],"mappings":"AAEA,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/events/index.ts"],"names":[],"mappings":"AAEA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC"}
@@ -1,3 +1,6 @@
1
1
  // Note: explicit .js extension is required for Node ESM resolution.
2
2
  export * from "./logs.js";
3
+ export * from "./defs.js";
4
+ export * from "./decode.js";
5
+ export * from "./recent.js";
3
6
  export * from "./oracleRegistrySync.js";
@@ -1,17 +1,16 @@
1
1
  import type { Address, PublicClient } from "viem";
2
2
  /**
3
- * Minimal, production-friendly registry sync for VarlaOracle.
3
+ * Production-friendly registry sync for VarlaOracle.
4
4
  *
5
- * Design goals:
6
- * - Event-driven discovery of configured positionIds.
7
- * - Follow-up hydration via multicall (reuses Phase 2 batching).
8
- *
9
- * Note: `configurePositionsBatch` emits `PositionConfigured` per position.
5
+ * - Discovers configured `positionIds` from `PositionConfigured` events.
6
+ * - Optionally enriches opposites / negRisk info from events (cheap), then hydrates
7
+ * canonical state from contract views via multicall.
10
8
  */
11
9
  export type OracleRegistryEntry = {
12
10
  positionId: bigint;
13
11
  conditionId: `0x${string}`;
14
12
  resolutionTime: bigint;
13
+ riskTier: number;
15
14
  isNegRisk: boolean;
16
15
  negRiskMarketId: `0x${string}`;
17
16
  oppositePositionId: bigint;
@@ -21,6 +20,7 @@ export type SyncOracleRegistryViaEventsParams = {
21
20
  oracleAddress: Address;
22
21
  fromBlock: bigint;
23
22
  toBlock: bigint;
23
+ /** Max number of blocks per request. */
24
24
  blockRange?: bigint;
25
25
  multicallChunkSize?: number;
26
26
  /** Limit how many discovered ids to hydrate (useful for testing). */
@@ -1 +1 @@
1
- {"version":3,"file":"oracleRegistrySync.d.ts","sourceRoot":"","sources":["../../src/events/oracleRegistrySync.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAOlD;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,KAAK,MAAM,EAAE,CAAC;IAC/B,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,MAAM,EAAE,YAAY,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,iCAAiC,GACxC,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,mBAAmB,EAAE,CAAA;CAAE,CAAC,CA+FpE"}
1
+ {"version":3,"file":"oracleRegistrySync.d.ts","sourceRoot":"","sources":["../../src/events/oracleRegistrySync.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAQlD;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,KAAK,MAAM,EAAE,CAAC;IAC/B,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,MAAM,EAAE,YAAY,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAcF,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,iCAAiC,GACxC,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,mBAAmB,EAAE,CAAA;CAAE,CAAC,CAwJpE"}
@@ -1,39 +1,84 @@
1
1
  // Note: explicit .js extension is required for Node ESM resolution.
2
- import { decodeEventLog, getAbiItem } from "viem";
3
2
  import { multicallChunks } from "../batch.js";
4
3
  import { abis } from "../generated.js";
4
+ import { decodeEventLogs } from "./decode.js";
5
+ import { ORACLE_EVENTS } from "./defs.js";
5
6
  import { getEventLogsChunked } from "./logs.js";
7
+ function uniqBigints(values) {
8
+ const set = new Set();
9
+ const out = [];
10
+ for (const v of values) {
11
+ const k = v.toString();
12
+ if (set.has(k))
13
+ continue;
14
+ set.add(k);
15
+ out.push(v);
16
+ }
17
+ return out;
18
+ }
6
19
  export async function syncOracleRegistryViaEvents(params) {
7
20
  const abi = abis.VARLAORACLE_ABI;
8
- const item = getAbiItem({ abi, name: "PositionConfigured" });
9
- const logs = await getEventLogsChunked({
21
+ // ---------------------------------------------------------------------------
22
+ // 1) Discover ids (PositionConfigured)
23
+ // ---------------------------------------------------------------------------
24
+ const configuredLogs = await getEventLogsChunked({
10
25
  client: params.client,
11
26
  address: params.oracleAddress,
12
- event: item,
27
+ event: ORACLE_EVENTS.PositionConfigured,
13
28
  fromBlock: params.fromBlock,
14
29
  toBlock: params.toBlock,
15
30
  blockRange: params.blockRange,
16
31
  });
17
- const set = new Set();
18
- const ids = [];
19
- for (const l of logs) {
20
- const decoded = decodeEventLog({
21
- abi: [item],
22
- data: l.data,
23
- topics: l.topics,
32
+ const configuredDecoded = decodeEventLogs({
33
+ event: ORACLE_EVENTS.PositionConfigured,
34
+ logs: configuredLogs,
35
+ });
36
+ let ids = uniqBigints(configuredDecoded.map((d) => d.args.positionId));
37
+ if (params.maxIds)
38
+ ids = ids.slice(0, params.maxIds);
39
+ if (ids.length === 0)
40
+ return { positionIds: [], entries: [] };
41
+ // ---------------------------------------------------------------------------
42
+ // 2) Optional enrichment from events (non-authoritative)
43
+ // ---------------------------------------------------------------------------
44
+ const oppositeById = new Map();
45
+ {
46
+ const logs = await getEventLogsChunked({
47
+ client: params.client,
48
+ address: params.oracleAddress,
49
+ event: ORACLE_EVENTS.OppositePositionsConfigured,
50
+ fromBlock: params.fromBlock,
51
+ toBlock: params.toBlock,
52
+ blockRange: params.blockRange,
24
53
  });
25
- const pid = decoded.args.positionId;
26
- const key = pid.toString();
27
- if (!set.has(key)) {
28
- set.add(key);
29
- ids.push(pid);
30
- if (params.maxIds && ids.length >= params.maxIds)
31
- break;
54
+ const decoded = decodeEventLogs({ event: ORACLE_EVENTS.OppositePositionsConfigured, logs });
55
+ for (const d of decoded) {
56
+ const yes = d.args.yesPositionId;
57
+ const no = d.args.noPositionId;
58
+ oppositeById.set(yes.toString(), no);
59
+ oppositeById.set(no.toString(), yes);
32
60
  }
33
61
  }
34
- if (ids.length === 0)
35
- return { positionIds: [], entries: [] };
36
- const chunkSize = params.multicallChunkSize ?? 128;
62
+ const negRiskMarketById = new Map();
63
+ {
64
+ const logs = await getEventLogsChunked({
65
+ client: params.client,
66
+ address: params.oracleAddress,
67
+ event: ORACLE_EVENTS.NegRiskPositionConfigured,
68
+ fromBlock: params.fromBlock,
69
+ toBlock: params.toBlock,
70
+ blockRange: params.blockRange,
71
+ });
72
+ const decoded = decodeEventLogs({ event: ORACLE_EVENTS.NegRiskPositionConfigured, logs });
73
+ for (const d of decoded) {
74
+ const pid = d.args.positionId;
75
+ const marketId = d.args.marketId;
76
+ negRiskMarketById.set(pid.toString(), marketId);
77
+ }
78
+ }
79
+ // ---------------------------------------------------------------------------
80
+ // 3) Hydrate canonical state from views (authoritative)
81
+ // ---------------------------------------------------------------------------
37
82
  const calls = ids.flatMap((pid) => [
38
83
  {
39
84
  address: params.oracleAddress,
@@ -47,6 +92,12 @@ export async function syncOracleRegistryViaEvents(params) {
47
92
  functionName: "getResolutionTime",
48
93
  args: [pid],
49
94
  },
95
+ {
96
+ address: params.oracleAddress,
97
+ abi,
98
+ functionName: "getRiskTier",
99
+ args: [pid],
100
+ },
50
101
  {
51
102
  address: params.oracleAddress,
52
103
  abi,
@@ -66,27 +117,40 @@ export async function syncOracleRegistryViaEvents(params) {
66
117
  args: [pid],
67
118
  },
68
119
  ]);
69
- const res = await multicallChunks({ client: params.client, contracts: calls, chunkSize });
120
+ const chunkSize = params.multicallChunkSize ?? 128;
121
+ const res = await multicallChunks({
122
+ client: params.client,
123
+ contracts: calls,
124
+ chunkSize,
125
+ });
70
126
  const entries = [];
71
- // 5 results per pid.
72
127
  for (let i = 0; i < ids.length; i++) {
73
- const base = i * 5;
128
+ const base = i * 6;
74
129
  const r0 = res[base + 0];
75
130
  const r1 = res[base + 1];
76
131
  const r2 = res[base + 2];
77
132
  const r3 = res[base + 3];
78
133
  const r4 = res[base + 4];
79
- for (const r of [r0, r1, r2, r3, r4]) {
80
- if (r.status !== "success")
134
+ const r5 = res[base + 5];
135
+ for (const r of [r0, r1, r2, r3, r4, r5]) {
136
+ if (r.status !== "success") {
81
137
  throw new Error(`Oracle registry multicall failed: ${String(r.error)}`);
138
+ }
82
139
  }
140
+ const pid = ids[i];
141
+ const pidKey = pid.toString();
142
+ // Prefer on-chain view results (authoritative), but fall back to event-enriched values
143
+ // if they look more complete.
144
+ const opposite = r3.result || (oppositeById.get(pidKey) ?? 0n);
145
+ const market = r5.result || (negRiskMarketById.get(pidKey) ?? "0x" + "0".repeat(64));
83
146
  entries.push({
84
- positionId: ids[i],
147
+ positionId: pid,
85
148
  conditionId: r0.result,
86
149
  resolutionTime: r1.result,
87
- oppositePositionId: r2.result,
88
- isNegRisk: r3.result,
89
- negRiskMarketId: r4.result,
150
+ riskTier: Number(r2.result),
151
+ oppositePositionId: opposite,
152
+ isNegRisk: r4.result,
153
+ negRiskMarketId: market,
90
154
  });
91
155
  }
92
156
  return { positionIds: ids, entries };
@@ -0,0 +1,19 @@
1
+ import type { Address, AbiEvent, PublicClient } from "viem";
2
+ export type GetRecentEventsParams = {
3
+ client: PublicClient;
4
+ address: Address;
5
+ event: AbiEvent;
6
+ /** Look back N blocks from the current head. */
7
+ lookbackBlocks?: bigint;
8
+ /** Chunk size for log fetching. */
9
+ blockRange?: bigint;
10
+ };
11
+ /**
12
+ * Frontend-friendly helper: fetch and decode recent events by looking back from head.
13
+ */
14
+ export declare function getRecentEvents(params: GetRecentEventsParams): Promise<{
15
+ fromBlock: bigint;
16
+ toBlock: bigint;
17
+ decoded: import("./decode.js").DecodedEvent<Record<string, unknown>>[];
18
+ }>;
19
+ //# sourceMappingURL=recent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recent.d.ts","sourceRoot":"","sources":["../../src/events/recent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAO,MAAM,MAAM,CAAC;AAKjE,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;IAChB,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,qBAAqB;;;;GAmBlE"}
@@ -0,0 +1,24 @@
1
+ // Note: explicit .js extension is required for Node ESM resolution.
2
+ import { getEventLogsChunked } from "./logs.js";
3
+ import { decodeEventLogs } from "./decode.js";
4
+ /**
5
+ * Frontend-friendly helper: fetch and decode recent events by looking back from head.
6
+ */
7
+ export async function getRecentEvents(params) {
8
+ const head = await params.client.getBlockNumber();
9
+ const lookback = params.lookbackBlocks ?? 2000n;
10
+ const fromBlock = head > lookback ? head - lookback : 0n;
11
+ const logs = await getEventLogsChunked({
12
+ client: params.client,
13
+ address: params.address,
14
+ event: params.event,
15
+ fromBlock,
16
+ toBlock: head,
17
+ blockRange: params.blockRange,
18
+ });
19
+ return {
20
+ fromBlock,
21
+ toBlock: head,
22
+ decoded: decodeEventLogs({ event: params.event, logs }),
23
+ };
24
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Format a WAD (1e18) fixed-point value into a decimal string.
3
+ *
4
+ * - No scientific notation.
5
+ * - Trims trailing zeros.
6
+ * - If `fractionDigits` is provided, it rounds HALF UP to that many digits.
7
+ */
8
+ export declare function formatWad(wad: bigint, params?: {
9
+ decimals?: number;
10
+ fractionDigits?: number;
11
+ }): string;
12
+ /**
13
+ * Format BPS (1e4 = 100%) as a percentage string.
14
+ *
15
+ * Example:
16
+ * - 1500 -> "15%"
17
+ * - 1234 -> "12.34%"
18
+ */
19
+ export declare function formatBps(bps: bigint | number): string;
20
+ /**
21
+ * Format a price with 8 decimals (1e8 = 1.00) into a decimal string.
22
+ *
23
+ * Returns numbers only (no "$" prefix).
24
+ */
25
+ export declare function formatPriceE8(priceE8: bigint, params?: {
26
+ fractionDigits?: number;
27
+ }): string;
28
+ /**
29
+ * Parse a decimal string into a bigint with `decimals` fixed-point precision.
30
+ *
31
+ * - Accepts "123", "123.", "123.45"
32
+ * - Rejects commas and scientific notation.
33
+ */
34
+ export declare function parseUnits(input: string, decimals: number): bigint;
35
+ export declare function parseWad(input: string, decimals?: number): bigint;
36
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GACtD,MAAM,CAIR;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAYtD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAE3F;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAuBlE;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,MAAM,CAE7D"}
package/dist/format.js ADDED
@@ -0,0 +1,109 @@
1
+ // Note: explicit .js extension is required for Node ESM resolution.
2
+ /**
3
+ * Format a WAD (1e18) fixed-point value into a decimal string.
4
+ *
5
+ * - No scientific notation.
6
+ * - Trims trailing zeros.
7
+ * - If `fractionDigits` is provided, it rounds HALF UP to that many digits.
8
+ */
9
+ export function formatWad(wad, params) {
10
+ const decimals = params?.decimals ?? 18;
11
+ const fractionDigits = params?.fractionDigits;
12
+ return formatUnits(wad, decimals, fractionDigits);
13
+ }
14
+ /**
15
+ * Format BPS (1e4 = 100%) as a percentage string.
16
+ *
17
+ * Example:
18
+ * - 1500 -> "15%"
19
+ * - 1234 -> "12.34%"
20
+ */
21
+ export function formatBps(bps) {
22
+ const b = typeof bps === "bigint" ? bps : BigInt(bps);
23
+ // percent = bps / 100
24
+ const sign = b < 0n ? "-" : "";
25
+ const v = b < 0n ? -b : b;
26
+ const int = v / 100n;
27
+ const frac = v % 100n;
28
+ if (frac === 0n)
29
+ return `${sign}${int}%`;
30
+ const fracStr = frac.toString().padStart(2, "0");
31
+ // trim trailing zeros
32
+ const trimmed = fracStr.replace(/0+$/, "");
33
+ return `${sign}${int}.${trimmed}%`;
34
+ }
35
+ /**
36
+ * Format a price with 8 decimals (1e8 = 1.00) into a decimal string.
37
+ *
38
+ * Returns numbers only (no "$" prefix).
39
+ */
40
+ export function formatPriceE8(priceE8, params) {
41
+ return formatUnits(priceE8, 8, params?.fractionDigits);
42
+ }
43
+ /**
44
+ * Parse a decimal string into a bigint with `decimals` fixed-point precision.
45
+ *
46
+ * - Accepts "123", "123.", "123.45"
47
+ * - Rejects commas and scientific notation.
48
+ */
49
+ export function parseUnits(input, decimals) {
50
+ const s = input.trim();
51
+ if (s.length === 0)
52
+ throw new Error("Empty input");
53
+ if (!Number.isInteger(decimals) || decimals < 0)
54
+ throw new Error("Invalid decimals");
55
+ if (!/^[+-]?\d*(?:\.\d*)?$/.test(s)) {
56
+ throw new Error(`Invalid decimal string: ${input}`);
57
+ }
58
+ const sign = s.startsWith("-") ? -1n : 1n;
59
+ const unsigned = s.startsWith("-") || s.startsWith("+") ? s.slice(1) : s;
60
+ const [intPartRaw, fracPartRaw = ""] = unsigned.split(".");
61
+ const intPart = intPartRaw.length ? intPartRaw : "0";
62
+ const fracPart = fracPartRaw;
63
+ if (fracPart.length > decimals) {
64
+ // We intentionally do NOT round in parse. Callers can round before parsing.
65
+ throw new Error(`Too many decimals (max ${decimals})`);
66
+ }
67
+ const fracPadded = fracPart.padEnd(decimals, "0");
68
+ const combined = `${intPart}${fracPadded}`.replace(/^0+(?=\d)/, "");
69
+ const v = combined.length ? BigInt(combined) : 0n;
70
+ return sign * v;
71
+ }
72
+ export function parseWad(input, decimals = 18) {
73
+ return parseUnits(input, decimals);
74
+ }
75
+ // -----------------
76
+ // Internal helpers
77
+ // -----------------
78
+ function formatUnits(value, decimals, fractionDigits) {
79
+ if (!Number.isInteger(decimals) || decimals < 0)
80
+ throw new Error("Invalid decimals");
81
+ const sign = value < 0n ? "-" : "";
82
+ let v = value < 0n ? -value : value;
83
+ // Optional rounding to fractionDigits
84
+ if (fractionDigits !== undefined) {
85
+ if (!Number.isInteger(fractionDigits) || fractionDigits < 0) {
86
+ throw new Error("Invalid fractionDigits");
87
+ }
88
+ if (fractionDigits < decimals) {
89
+ const drop = decimals - fractionDigits;
90
+ const base = 10n ** BigInt(drop);
91
+ const half = base / 2n;
92
+ // half-up rounding
93
+ v = (v + half) / base;
94
+ // Now v is in units of 10^fractionDigits
95
+ decimals = fractionDigits;
96
+ }
97
+ }
98
+ const base = 10n ** BigInt(decimals);
99
+ const int = v / base;
100
+ const frac = v % base;
101
+ if (decimals === 0)
102
+ return `${sign}${int}`;
103
+ let fracStr = frac.toString().padStart(decimals, "0");
104
+ // Trim trailing zeros
105
+ fracStr = fracStr.replace(/0+$/, "");
106
+ if (fracStr.length === 0)
107
+ return `${sign}${int}`;
108
+ return `${sign}${int}.${fracStr}`;
109
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./types.js";
2
2
  export * from "./contracts.js";
3
3
  export * from "./views/index.js";
4
+ export * from "./format.js";
4
5
  export * from "./events/index.js";
5
6
  export * from "./batch.js";
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAG3B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,kBAAkB,CAAC;AAGjC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAG3B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,kBAAkB,CAAC;AAGjC,cAAc,aAAa,CAAC;AAG5B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -4,6 +4,8 @@ export * from "./types.js";
4
4
  export * from "./contracts.js";
5
5
  // Higher-level read helpers (views/facades).
6
6
  export * from "./views/index.js";
7
+ // Pure formatting helpers (no chain calls).
8
+ export * from "./format.js";
7
9
  // Indexer/event helpers.
8
10
  export * from "./events/index.js";
9
11
  // Low-level batching utilities (multicall chunking).