@varla/sdk 1.11.3 → 1.13.2

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 (244) hide show
  1. package/AGENTS.md +82 -94
  2. package/CHANGELOG.md +359 -0
  3. package/README.md +227 -274
  4. package/dist/abi/full/OpinionCtfExecutionEngineAdapter.js +1 -0
  5. package/dist/abi/full/OpinionCtfExecutionEngineAdapter.js.map +1 -0
  6. package/dist/abi/full/OracleUpdaterRouter.d.ts +30 -9
  7. package/dist/abi/full/OracleUpdaterRouter.d.ts.map +1 -1
  8. package/dist/abi/full/OracleUpdaterRouter.js +37 -9
  9. package/dist/abi/full/OracleUpdaterRouter.js.map +1 -0
  10. package/dist/abi/full/PolymarketCtfAdapter.js +1 -0
  11. package/dist/abi/full/PolymarketCtfAdapter.js.map +1 -0
  12. package/dist/abi/full/VarlaAccessManager.js +1 -0
  13. package/dist/abi/full/VarlaAccessManager.js.map +1 -0
  14. package/dist/abi/full/VarlaConvertLiquidator.d.ts +35 -0
  15. package/dist/abi/full/VarlaConvertLiquidator.d.ts.map +1 -1
  16. package/dist/abi/full/VarlaConvertLiquidator.js +46 -0
  17. package/dist/abi/full/VarlaConvertLiquidator.js.map +1 -0
  18. package/dist/abi/full/VarlaCore.js +1 -0
  19. package/dist/abi/full/VarlaCore.js.map +1 -0
  20. package/dist/abi/full/VarlaInterestRateStrategy.js +1 -0
  21. package/dist/abi/full/VarlaInterestRateStrategy.js.map +1 -0
  22. package/dist/abi/full/VarlaLiquidator.d.ts +36 -1
  23. package/dist/abi/full/VarlaLiquidator.d.ts.map +1 -1
  24. package/dist/abi/full/VarlaLiquidator.js +47 -1
  25. package/dist/abi/full/VarlaLiquidator.js.map +1 -0
  26. package/dist/abi/full/VarlaMergeLiquidator.d.ts +35 -0
  27. package/dist/abi/full/VarlaMergeLiquidator.d.ts.map +1 -1
  28. package/dist/abi/full/VarlaMergeLiquidator.js +46 -0
  29. package/dist/abi/full/VarlaMergeLiquidator.js.map +1 -0
  30. package/dist/abi/full/VarlaOracle.js +1 -0
  31. package/dist/abi/full/VarlaOracle.js.map +1 -0
  32. package/dist/abi/full/VarlaPool.js +1 -0
  33. package/dist/abi/full/VarlaPool.js.map +1 -0
  34. package/dist/abi/full/VarlaProxyAdmin.js +1 -0
  35. package/dist/abi/full/VarlaProxyAdmin.js.map +1 -0
  36. package/dist/abi/index.js +1 -0
  37. package/dist/abi/index.js.map +1 -0
  38. package/dist/abi/subsets/VarlaOracle.registry.js +1 -0
  39. package/dist/abi/subsets/VarlaOracle.registry.js.map +1 -0
  40. package/dist/abi.js +1 -0
  41. package/dist/abi.js.map +1 -0
  42. package/dist/actions/admin.js +1 -0
  43. package/dist/actions/admin.js.map +1 -0
  44. package/dist/actions/core.js +1 -0
  45. package/dist/actions/core.js.map +1 -0
  46. package/dist/actions/erc1155.js +1 -0
  47. package/dist/actions/erc1155.js.map +1 -0
  48. package/dist/actions/erc20.js +1 -0
  49. package/dist/actions/erc20.js.map +1 -0
  50. package/dist/actions/index.d.ts +7 -7
  51. package/dist/actions/index.d.ts.map +1 -1
  52. package/dist/actions/index.js +8 -7
  53. package/dist/actions/index.js.map +1 -0
  54. package/dist/actions/liquidator.js +1 -0
  55. package/dist/actions/liquidator.js.map +1 -0
  56. package/dist/actions/oracle.d.ts +1 -2
  57. package/dist/actions/oracle.d.ts.map +1 -1
  58. package/dist/actions/oracle.js +1 -0
  59. package/dist/actions/oracle.js.map +1 -0
  60. package/dist/actions/oracleUpdaterRouter.d.ts +8 -1
  61. package/dist/actions/oracleUpdaterRouter.d.ts.map +1 -1
  62. package/dist/actions/oracleUpdaterRouter.js +14 -1
  63. package/dist/actions/oracleUpdaterRouter.js.map +1 -0
  64. package/dist/actions/pool.js +1 -0
  65. package/dist/actions/pool.js.map +1 -0
  66. package/dist/actions/rbac.js +1 -0
  67. package/dist/actions/rbac.js.map +1 -0
  68. package/dist/actions/tx.js +1 -0
  69. package/dist/actions/tx.js.map +1 -0
  70. package/dist/actions/utils.js +1 -0
  71. package/dist/actions/utils.js.map +1 -0
  72. package/dist/addresses/bsc.js +1 -0
  73. package/dist/addresses/bsc.js.map +1 -0
  74. package/dist/addresses/index.js +1 -0
  75. package/dist/addresses/index.js.map +1 -0
  76. package/dist/addresses/polygon.js +1 -0
  77. package/dist/addresses/polygon.js.map +1 -0
  78. package/dist/addresses.js +1 -0
  79. package/dist/addresses.js.map +1 -0
  80. package/dist/batch.js +1 -0
  81. package/dist/batch.js.map +1 -0
  82. package/dist/contracts.d.ts +1 -2
  83. package/dist/contracts.d.ts.map +1 -1
  84. package/dist/contracts.js +2 -2
  85. package/dist/contracts.js.map +1 -0
  86. package/dist/errors.d.ts +87 -0
  87. package/dist/errors.d.ts.map +1 -0
  88. package/dist/errors.js +240 -0
  89. package/dist/errors.js.map +1 -0
  90. package/dist/events/decode.js +1 -0
  91. package/dist/events/decode.js.map +1 -0
  92. package/dist/events/defs.js +1 -0
  93. package/dist/events/defs.js.map +1 -0
  94. package/dist/events/index.d.ts +3 -3
  95. package/dist/events/index.d.ts.map +1 -1
  96. package/dist/events/index.js +4 -3
  97. package/dist/events/index.js.map +1 -0
  98. package/dist/events/logs.js +1 -0
  99. package/dist/events/logs.js.map +1 -0
  100. package/dist/events/oracleRegistrySync.js +1 -0
  101. package/dist/events/oracleRegistrySync.js.map +1 -0
  102. package/dist/events/recent.d.ts +1 -1
  103. package/dist/events/recent.d.ts.map +1 -1
  104. package/dist/events/recent.js +2 -1
  105. package/dist/events/recent.js.map +1 -0
  106. package/dist/format.js +1 -0
  107. package/dist/format.js.map +1 -0
  108. package/dist/generated.d.ts +136 -10
  109. package/dist/generated.d.ts.map +1 -1
  110. package/dist/generated.js +1 -0
  111. package/dist/generated.js.map +1 -0
  112. package/dist/index.d.ts +6 -5
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/index.js +12 -9
  115. package/dist/index.js.map +1 -0
  116. package/dist/leverage/deleverageExecute.d.ts +36 -0
  117. package/dist/leverage/deleverageExecute.d.ts.map +1 -0
  118. package/dist/leverage/deleverageExecute.js +53 -0
  119. package/dist/leverage/deleverageExecute.js.map +1 -0
  120. package/dist/leverage/execute.d.ts +62 -0
  121. package/dist/leverage/execute.d.ts.map +1 -0
  122. package/dist/leverage/execute.js +84 -0
  123. package/dist/leverage/execute.js.map +1 -0
  124. package/dist/leverage/index.d.ts +32 -0
  125. package/dist/leverage/index.d.ts.map +1 -0
  126. package/dist/leverage/index.js +12 -0
  127. package/dist/leverage/index.js.map +1 -0
  128. package/dist/leverage/math.d.ts +119 -0
  129. package/dist/leverage/math.d.ts.map +1 -0
  130. package/dist/leverage/math.js +304 -0
  131. package/dist/leverage/math.js.map +1 -0
  132. package/dist/leverage/plan.d.ts +143 -0
  133. package/dist/leverage/plan.d.ts.map +1 -0
  134. package/dist/leverage/plan.js +204 -0
  135. package/dist/leverage/plan.js.map +1 -0
  136. package/dist/leverage/preflight.d.ts +27 -0
  137. package/dist/leverage/preflight.d.ts.map +1 -0
  138. package/dist/leverage/preflight.js +34 -0
  139. package/dist/leverage/preflight.js.map +1 -0
  140. package/dist/leverage/types.d.ts +157 -0
  141. package/dist/leverage/types.d.ts.map +1 -0
  142. package/dist/leverage/types.js +43 -0
  143. package/dist/leverage/types.js.map +1 -0
  144. package/dist/meta.d.ts +42 -0
  145. package/dist/meta.d.ts.map +1 -0
  146. package/dist/meta.js +47 -0
  147. package/dist/meta.js.map +1 -0
  148. package/dist/types.js +1 -0
  149. package/dist/types.js.map +1 -0
  150. package/dist/views/accessManager.js +1 -0
  151. package/dist/views/accessManager.js.map +1 -0
  152. package/dist/views/adapters.js +1 -0
  153. package/dist/views/adapters.js.map +1 -0
  154. package/dist/views/admin.d.ts.map +1 -1
  155. package/dist/views/admin.js +1 -0
  156. package/dist/views/admin.js.map +1 -0
  157. package/dist/views/core.d.ts +55 -7
  158. package/dist/views/core.d.ts.map +1 -1
  159. package/dist/views/core.js +185 -36
  160. package/dist/views/core.js.map +1 -0
  161. package/dist/views/index.d.ts +5 -5
  162. package/dist/views/index.d.ts.map +1 -1
  163. package/dist/views/index.js +6 -5
  164. package/dist/views/index.js.map +1 -0
  165. package/dist/views/lenders.js +1 -0
  166. package/dist/views/lenders.js.map +1 -0
  167. package/dist/views/liquidators.js +1 -0
  168. package/dist/views/liquidators.js.map +1 -0
  169. package/dist/views/oracle.js +1 -0
  170. package/dist/views/oracle.js.map +1 -0
  171. package/dist/views/pool.js +1 -0
  172. package/dist/views/pool.js.map +1 -0
  173. package/dist/views/system.d.ts.map +1 -1
  174. package/dist/views/system.js +1 -0
  175. package/dist/views/system.js.map +1 -0
  176. package/package.json +18 -5
  177. package/src/abi/README.md +17 -0
  178. package/src/abi/full/OpinionCtfExecutionEngineAdapter.ts +320 -0
  179. package/src/abi/full/OracleUpdaterRouter.ts +528 -0
  180. package/src/abi/full/PolymarketCtfAdapter.ts +312 -0
  181. package/src/abi/full/VarlaAccessManager.ts +1171 -0
  182. package/src/abi/full/VarlaConvertLiquidator.ts +834 -0
  183. package/src/abi/full/VarlaCore.ts +2277 -0
  184. package/src/abi/full/VarlaInterestRateStrategy.ts +442 -0
  185. package/src/abi/full/VarlaLiquidator.ts +914 -0
  186. package/src/abi/full/VarlaMergeLiquidator.ts +797 -0
  187. package/src/abi/full/VarlaOracle.ts +1825 -0
  188. package/src/abi/full/VarlaPool.ts +1637 -0
  189. package/src/abi/full/VarlaProxyAdmin.ts +301 -0
  190. package/src/abi/index.ts +17 -0
  191. package/src/abi/subsets/VarlaOracle.registry.ts +784 -0
  192. package/src/abi.ts +2 -0
  193. package/src/actions/admin.ts +357 -0
  194. package/src/actions/core.ts +68 -0
  195. package/src/actions/erc1155.ts +22 -0
  196. package/src/actions/erc20.ts +22 -0
  197. package/src/actions/index.ts +13 -0
  198. package/src/actions/liquidator.ts +76 -0
  199. package/src/actions/oracle.ts +618 -0
  200. package/src/actions/oracleUpdaterRouter.ts +233 -0
  201. package/src/actions/pool.ts +76 -0
  202. package/src/actions/rbac.ts +72 -0
  203. package/src/actions/tx.ts +16 -0
  204. package/src/actions/utils.ts +15 -0
  205. package/src/addresses/README.md +17 -0
  206. package/src/addresses/bsc.json +16 -0
  207. package/src/addresses/bsc.ts +15 -0
  208. package/src/addresses/index.ts +6 -0
  209. package/src/addresses/polygon.json +16 -0
  210. package/src/addresses/polygon.ts +15 -0
  211. package/src/addresses.ts +2 -0
  212. package/src/batch.ts +55 -0
  213. package/src/contracts.ts +232 -0
  214. package/src/errors.ts +305 -0
  215. package/src/events/decode.ts +37 -0
  216. package/src/events/defs.ts +70 -0
  217. package/src/events/index.ts +7 -0
  218. package/src/events/logs.ts +42 -0
  219. package/src/events/oracleRegistrySync.ts +206 -0
  220. package/src/events/recent.ts +39 -0
  221. package/src/format.ts +121 -0
  222. package/src/generated.ts +27 -0
  223. package/src/index.ts +18 -0
  224. package/src/leverage/deleverageExecute.ts +111 -0
  225. package/src/leverage/execute.ts +172 -0
  226. package/src/leverage/index.ts +88 -0
  227. package/src/leverage/math.ts +446 -0
  228. package/src/leverage/plan.ts +356 -0
  229. package/src/leverage/preflight.ts +63 -0
  230. package/src/leverage/types.ts +204 -0
  231. package/src/meta.ts +82 -0
  232. package/src/types.ts +25 -0
  233. package/src/views/accessManager.ts +286 -0
  234. package/src/views/adapters.ts +27 -0
  235. package/src/views/admin.ts +92 -0
  236. package/src/views/core.ts +1370 -0
  237. package/src/views/index.ts +11 -0
  238. package/src/views/lenders.ts +65 -0
  239. package/src/views/liquidators.ts +227 -0
  240. package/src/views/oracle.ts +739 -0
  241. package/src/views/pool.ts +277 -0
  242. package/src/views/system.ts +42 -0
  243. package/BACKEND.md +0 -404
  244. package/FRONTEND.md +0 -484
@@ -0,0 +1,232 @@
1
+ // Note: explicit .js extension is required for Node ESM resolution.
2
+
3
+ import {
4
+ type Address,
5
+ erc20Abi,
6
+ erc1155Abi,
7
+ erc4626Abi,
8
+ type GetContractReturnType,
9
+ getContract,
10
+ type PublicClient,
11
+ } from "viem";
12
+
13
+ import { abis, addresses } from "./generated.js";
14
+ import type { AddressBook, ChainKey } from "./types.js";
15
+
16
+ /**
17
+ * A typed viem Contract instance.
18
+ *
19
+ * Note: `getContract` infers method typings from the ABI, so consumers get
20
+ * `contract.read.*` methods with proper argument/return inference.
21
+ */
22
+ export type ReadonlyContract<TAbi extends readonly unknown[]> = GetContractReturnType<
23
+ TAbi,
24
+ PublicClient
25
+ >;
26
+
27
+ export type VarlaContracts = {
28
+ chain: ChainKey;
29
+ addressBook: AddressBook;
30
+
31
+ accessManager: ReadonlyContract<typeof abis.VARLAACCESSMANAGER_ABI>;
32
+ oracle: ReadonlyContract<typeof abis.VARLAORACLE_ABI>;
33
+ core: ReadonlyContract<typeof abis.VARLACORE_ABI>;
34
+ pool: ReadonlyContract<typeof abis.VARLAPOOL_ABI>;
35
+
36
+ // Optional extras (depend on deployment)
37
+ oracleUpdaterRouter?: ReadonlyContract<typeof abis.ORACLEUPDATERROUTER_ABI>;
38
+ interestRateStrategy?: ReadonlyContract<typeof abis.VARLAINTERESTRATESTRATEGY_ABI>;
39
+ proxyAdmin?: ReadonlyContract<typeof abis.VARLAPROXYADMIN_ABI>;
40
+
41
+ liquidator?: ReadonlyContract<typeof abis.VARLALIQUIDATOR_ABI>;
42
+ mergeLiquidator?: ReadonlyContract<typeof abis.VARLAMERGELIQUIDATOR_ABI>;
43
+ convertLiquidator?: ReadonlyContract<typeof abis.VARLACONVERTLIQUIDATOR_ABI>;
44
+
45
+ polymarketCtfAdapter?: ReadonlyContract<typeof abis.POLYMARKETCTFADAPTER_ABI>;
46
+ opinionCtfExecutionEngineAdapter?: ReadonlyContract<
47
+ typeof abis.OPINIONCTFEXECUTIONENGINEADAPTER_ABI
48
+ >;
49
+ };
50
+
51
+ export type GetVarlaContractsParams = {
52
+ chain: ChainKey;
53
+ client: PublicClient;
54
+ };
55
+
56
+ export function getAddressBook(chain: ChainKey): AddressBook {
57
+ if (chain === "polygon") return addresses.polygon;
58
+ if (chain === "bsc") return addresses.bsc;
59
+
60
+ // TypeScript should make this unreachable, but keep a runtime guard.
61
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
62
+ throw new Error(`Unsupported chain key: ${chain as string}`);
63
+ }
64
+
65
+ function mustAddress(book: AddressBook, key: keyof AddressBook): Address {
66
+ const v = book[key];
67
+ if (!v) {
68
+ throw new Error(`Missing required deployment address for '${String(key)}'`);
69
+ }
70
+ return v as Address;
71
+ }
72
+
73
+ /**
74
+ * Returns typed readonly viem contract instances for all known Varla deployments on a chain.
75
+ *
76
+ * Optional deployments are returned as `undefined`.
77
+ */
78
+ export function getVarlaContracts({ chain, client }: GetVarlaContractsParams): VarlaContracts {
79
+ const book = getAddressBook(chain);
80
+
81
+ const accessManager = getContract({
82
+ address: mustAddress(book, "accessManager"),
83
+ abi: abis.VARLAACCESSMANAGER_ABI,
84
+ client,
85
+ });
86
+
87
+ const oracle = getContract({
88
+ address: mustAddress(book, "oracle"),
89
+ abi: abis.VARLAORACLE_ABI,
90
+ client,
91
+ });
92
+
93
+ const core = getContract({
94
+ address: mustAddress(book, "core"),
95
+ abi: abis.VARLACORE_ABI,
96
+ client,
97
+ });
98
+
99
+ const pool = getContract({
100
+ address: mustAddress(book, "pool"),
101
+ abi: abis.VARLAPOOL_ABI,
102
+ client,
103
+ });
104
+
105
+ const oracleUpdaterRouter = book.oracleUpdaterRouter
106
+ ? getContract({
107
+ address: book.oracleUpdaterRouter as Address,
108
+ abi: abis.ORACLEUPDATERROUTER_ABI,
109
+ client,
110
+ })
111
+ : undefined;
112
+
113
+ const interestRateStrategy = book.interestRateStrategy
114
+ ? getContract({
115
+ address: book.interestRateStrategy as Address,
116
+ abi: abis.VARLAINTERESTRATESTRATEGY_ABI,
117
+ client,
118
+ })
119
+ : undefined;
120
+
121
+ const proxyAdmin = book.proxyAdmin
122
+ ? getContract({
123
+ address: book.proxyAdmin as Address,
124
+ abi: abis.VARLAPROXYADMIN_ABI,
125
+ client,
126
+ })
127
+ : undefined;
128
+
129
+ const liquidator = book.liquidator
130
+ ? getContract({
131
+ address: book.liquidator as Address,
132
+ abi: abis.VARLALIQUIDATOR_ABI,
133
+ client,
134
+ })
135
+ : undefined;
136
+
137
+ const mergeLiquidator = book.mergeLiquidator
138
+ ? getContract({
139
+ address: book.mergeLiquidator as Address,
140
+ abi: abis.VARLAMERGELIQUIDATOR_ABI,
141
+ client,
142
+ })
143
+ : undefined;
144
+
145
+ const convertLiquidator = book.convertLiquidator
146
+ ? getContract({
147
+ address: book.convertLiquidator as Address,
148
+ abi: abis.VARLACONVERTLIQUIDATOR_ABI,
149
+ client,
150
+ })
151
+ : undefined;
152
+
153
+ const polymarketCtfAdapter = book.polymarketCtfAdapter
154
+ ? getContract({
155
+ address: book.polymarketCtfAdapter as Address,
156
+ abi: abis.POLYMARKETCTFADAPTER_ABI,
157
+ client,
158
+ })
159
+ : undefined;
160
+
161
+ const opinionCtfExecutionEngineAdapter = book.opinionCtfExecutionEngineAdapter
162
+ ? getContract({
163
+ address: book.opinionCtfExecutionEngineAdapter as Address,
164
+ abi: abis.OPINIONCTFEXECUTIONENGINEADAPTER_ABI,
165
+ client,
166
+ })
167
+ : undefined;
168
+
169
+ return {
170
+ chain,
171
+ addressBook: book,
172
+ accessManager,
173
+ oracle,
174
+ core,
175
+ pool,
176
+ oracleUpdaterRouter,
177
+ interestRateStrategy,
178
+ proxyAdmin,
179
+ liquidator,
180
+ mergeLiquidator,
181
+ convertLiquidator,
182
+ polymarketCtfAdapter,
183
+ opinionCtfExecutionEngineAdapter,
184
+ };
185
+ }
186
+
187
+ /**
188
+ * Same as `getVarlaContracts`, but throws if any optional deployment addresses are missing.
189
+ * Useful for backend services that assume a fully-featured deployment.
190
+ */
191
+ export function getRequiredVarlaContracts(
192
+ params: GetVarlaContractsParams & {
193
+ require?: Array<
194
+ | "oracleUpdaterRouter"
195
+ | "interestRateStrategy"
196
+ | "proxyAdmin"
197
+ | "liquidator"
198
+ | "mergeLiquidator"
199
+ | "convertLiquidator"
200
+ | "polymarketCtfAdapter"
201
+ | "opinionCtfExecutionEngineAdapter"
202
+ >;
203
+ },
204
+ ): Required<VarlaContracts> {
205
+ const c = getVarlaContracts(params);
206
+ const require = params.require ?? [];
207
+
208
+ // Convert the optional keys into a runtime check while preserving a nice signature.
209
+ for (const k of require) {
210
+ if (!c[k]) {
211
+ throw new Error(`Missing required deployment: '${k}' on chain '${c.chain}'`);
212
+ }
213
+ }
214
+
215
+ return c as Required<VarlaContracts>;
216
+ }
217
+
218
+ // ---------------------------------------------------------------------------
219
+ // Generic helpers (for UIs): ERC20 / ERC1155 / ERC4626
220
+ // ---------------------------------------------------------------------------
221
+
222
+ export function getErc20(params: { client: PublicClient; address: Address }) {
223
+ return getContract({ address: params.address, abi: erc20Abi, client: params.client });
224
+ }
225
+
226
+ export function getErc1155(params: { client: PublicClient; address: Address }) {
227
+ return getContract({ address: params.address, abi: erc1155Abi, client: params.client });
228
+ }
229
+
230
+ export function getErc4626(params: { client: PublicClient; address: Address }) {
231
+ return getContract({ address: params.address, abi: erc4626Abi, client: params.client });
232
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,305 @@
1
+ // Note: explicit .js extension is required for Node ESM resolution.
2
+
3
+ /**
4
+ * Error decoding utilities for Varla Protocol contracts.
5
+ *
6
+ * Usage:
7
+ * import { decodeVarlaError, isVarlaError } from "@varla/sdk/errors";
8
+ *
9
+ * try {
10
+ * await publicClient.simulateContract(...);
11
+ * } catch (err) {
12
+ * const decoded = decodeVarlaError(err);
13
+ * if (decoded) console.log(decoded.name, decoded.args);
14
+ * }
15
+ */
16
+
17
+ import { type Abi, type DecodeErrorResultReturnType, decodeErrorResult, type Hex } from "viem";
18
+
19
+ /** Minimal ABI error item shape (matches viem/abitype). */
20
+ type AbiErrorItem = {
21
+ type: "error";
22
+ name: string;
23
+ inputs: readonly { name: string; type: string; indexed?: boolean; components?: readonly any[] }[];
24
+ };
25
+
26
+ import { abis } from "./generated.js";
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // Types
30
+ // ---------------------------------------------------------------------------
31
+
32
+ export type DecodedVarlaError = {
33
+ /** The Solidity custom error name, e.g. "InsufficientCollateral". */
34
+ name: string;
35
+ /** Which contract ABI matched. */
36
+ contract: string;
37
+ /** Decoded arguments (typed per ABI). */
38
+ args: readonly unknown[];
39
+ /** The raw 4-byte selector. */
40
+ selector: Hex;
41
+ /** The full revert data. */
42
+ data: Hex;
43
+ };
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // Internal: ABI registry with contract labels
47
+ // ---------------------------------------------------------------------------
48
+
49
+ type LabeledAbi = { label: string; abi: Abi };
50
+
51
+ /** All Varla contract ABIs, labeled for error attribution. */
52
+ const VARLA_ABIS: readonly LabeledAbi[] = [
53
+ { label: "VarlaCore", abi: abis.VARLACORE_ABI as unknown as Abi },
54
+ { label: "VarlaPool", abi: abis.VARLAPOOL_ABI as unknown as Abi },
55
+ { label: "VarlaOracle", abi: abis.VARLAORACLE_ABI as unknown as Abi },
56
+ { label: "VarlaLiquidator", abi: abis.VARLALIQUIDATOR_ABI as unknown as Abi },
57
+ { label: "VarlaMergeLiquidator", abi: abis.VARLAMERGELIQUIDATOR_ABI as unknown as Abi },
58
+ { label: "VarlaConvertLiquidator", abi: abis.VARLACONVERTLIQUIDATOR_ABI as unknown as Abi },
59
+ { label: "VarlaAccessManager", abi: abis.VARLAACCESSMANAGER_ABI as unknown as Abi },
60
+ { label: "OracleUpdaterRouter", abi: abis.ORACLEUPDATERROUTER_ABI as unknown as Abi },
61
+ {
62
+ label: "VarlaInterestRateStrategy",
63
+ abi: abis.VARLAINTERESTRATESTRATEGY_ABI as unknown as Abi,
64
+ },
65
+ { label: "VarlaProxyAdmin", abi: abis.VARLAPROXYADMIN_ABI as unknown as Abi },
66
+ { label: "PolymarketCtfAdapter", abi: abis.POLYMARKETCTFADAPTER_ABI as unknown as Abi },
67
+ {
68
+ label: "OpinionCtfExecutionEngineAdapter",
69
+ abi: abis.OPINIONCTFEXECUTIONENGINEADAPTER_ABI as unknown as Abi,
70
+ },
71
+ ] as const;
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // Lazy-built selector → { label, errorAbi } map for O(1) lookup
75
+ // ---------------------------------------------------------------------------
76
+
77
+ type ErrorEntry = { label: string; errorItem: AbiErrorItem };
78
+
79
+ let selectorMap: Map<string, ErrorEntry> | undefined;
80
+
81
+ function ensureSelectorMap(): Map<string, ErrorEntry> {
82
+ if (selectorMap) return selectorMap;
83
+
84
+ // We need to compute the 4-byte selectors ourselves from ABI error items.
85
+ // viem's `toFunctionSelector` works for errors too (same keccak256 scheme).
86
+ // But we can also just try decoding against each ABI — the selector map is
87
+ // an optimization for O(1) lookup vs O(n) trial decoding.
88
+ //
89
+ // For simplicity and correctness, we build it lazily by extracting error items.
90
+ selectorMap = new Map();
91
+
92
+ for (const { label, abi } of VARLA_ABIS) {
93
+ for (const item of abi) {
94
+ if ((item as any).type === "error") {
95
+ const errorItem = item as AbiErrorItem;
96
+ // Compute selector: keccak256 of signature, take first 4 bytes.
97
+ const sig = formatErrorSignature(errorItem);
98
+ const selector = computeSelector(sig);
99
+ // First match wins (in case of selector collisions across contracts).
100
+ if (!selectorMap.has(selector)) {
101
+ selectorMap.set(selector, { label, errorItem });
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ return selectorMap;
108
+ }
109
+
110
+ function formatErrorSignature(errorItem: AbiErrorItem): string {
111
+ const inputs = (errorItem.inputs ?? [])
112
+ .map((i: { type: string; components?: readonly any[] }) => {
113
+ if ((i as any).components) {
114
+ // Tuple type — recurse.
115
+ return formatTupleType((i as any).components);
116
+ }
117
+ return i.type;
118
+ })
119
+ .join(",");
120
+ return `${errorItem.name}(${inputs})`;
121
+ }
122
+
123
+ function formatTupleType(
124
+ components: readonly { type: string; components?: readonly any[] }[],
125
+ ): string {
126
+ const inner = components
127
+ .map((c) => {
128
+ if (c.components) return formatTupleType(c.components);
129
+ return c.type;
130
+ })
131
+ .join(",");
132
+ return `(${inner})`;
133
+ }
134
+
135
+ function computeSelector(signature: string): string {
136
+ // Use a simple approach: try to use globalThis.crypto if available (Bun / browser),
137
+ // otherwise fall back to encoding.
138
+ // For Bun: crypto.subtle is available but is async. Use the sync digest approach.
139
+ const encoded = new TextEncoder().encode(signature);
140
+
141
+ // Bun and modern runtimes have crypto.createHash or Bun.hash.
142
+ // Use a portable approach: manually compute or use viem's toFunctionSelector.
143
+ // Since we already import viem, use its keccak256.
144
+ // Import dynamically to keep this simple.
145
+ const hash = keccak256Bytes(encoded);
146
+ return hash.slice(0, 10); // "0x" + 4 bytes = 10 chars
147
+ }
148
+
149
+ /**
150
+ * Simple keccak256 using viem's built-in.
151
+ */
152
+ function keccak256Bytes(data: Uint8Array): string {
153
+ // viem exports keccak256 which accepts Hex | ByteArray.
154
+ // We import it at the top level to avoid dynamic imports.
155
+ return keccak256Fn(data);
156
+ }
157
+
158
+ // We import keccak256 lazily to avoid circular issues and keep the import clean.
159
+ import { keccak256 as keccak256Fn } from "viem";
160
+
161
+ // ---------------------------------------------------------------------------
162
+ // Public API
163
+ // ---------------------------------------------------------------------------
164
+
165
+ /**
166
+ * Extract revert data from various error shapes.
167
+ *
168
+ * Supports:
169
+ * - viem `ContractFunctionRevertedError` (`.data?.data` or `.data`)
170
+ * - Raw hex string
171
+ * - `{ data: Hex }` object
172
+ */
173
+ export function extractRevertData(err: unknown): Hex | null {
174
+ if (typeof err === "string" && err.startsWith("0x") && err.length >= 10) {
175
+ return err as Hex;
176
+ }
177
+
178
+ if (err && typeof err === "object") {
179
+ const anyErr = err as any;
180
+
181
+ // viem ContractFunctionRevertedError: err.data is an object with a `data` hex field,
182
+ // or err.cause?.data, or err.walk?.() to find the inner error.
183
+ if (typeof anyErr.data === "string" && (anyErr.data as string).startsWith("0x")) {
184
+ return anyErr.data as Hex;
185
+ }
186
+
187
+ if (anyErr.data && typeof anyErr.data === "object") {
188
+ if (typeof anyErr.data.data === "string" && (anyErr.data.data as string).startsWith("0x")) {
189
+ return anyErr.data.data as Hex;
190
+ }
191
+ }
192
+
193
+ // Walk cause chain (viem errors often nest).
194
+ if (anyErr.cause) {
195
+ return extractRevertData(anyErr.cause);
196
+ }
197
+ }
198
+
199
+ return null;
200
+ }
201
+
202
+ /**
203
+ * Attempt to decode revert data against all known Varla contract ABIs.
204
+ *
205
+ * @param errOrData - A caught error object, or raw revert data hex string.
206
+ * @returns Decoded error info, or `null` if no match.
207
+ *
208
+ * @example
209
+ * ```ts
210
+ * import { decodeVarlaError } from "@varla/sdk/errors";
211
+ *
212
+ * try {
213
+ * await publicClient.simulateContract({ ... });
214
+ * } catch (err) {
215
+ * const decoded = decodeVarlaError(err);
216
+ * if (decoded) {
217
+ * console.log(`Revert: ${decoded.name} on ${decoded.contract}`);
218
+ * console.log("Args:", decoded.args);
219
+ * }
220
+ * }
221
+ * ```
222
+ */
223
+ export function decodeVarlaError(errOrData: unknown): DecodedVarlaError | null {
224
+ const data =
225
+ typeof errOrData === "string" && errOrData.startsWith("0x")
226
+ ? (errOrData as Hex)
227
+ : extractRevertData(errOrData);
228
+
229
+ if (!data || data.length < 10) return null;
230
+
231
+ const selector = data.slice(0, 10) as Hex;
232
+ const map = ensureSelectorMap();
233
+ const entry = map.get(selector);
234
+
235
+ if (!entry) return null;
236
+
237
+ // Use viem's decodeErrorResult for proper ABI-based decoding.
238
+ try {
239
+ const decoded: DecodeErrorResultReturnType = decodeErrorResult({
240
+ abi: [entry.errorItem] as Abi,
241
+ data,
242
+ });
243
+ return {
244
+ name: decoded.errorName,
245
+ contract: entry.label,
246
+ args: decoded.args ?? [],
247
+ selector,
248
+ data,
249
+ };
250
+ } catch {
251
+ // Decoding failed (e.g. data too short for the error's parameters).
252
+ return null;
253
+ }
254
+ }
255
+
256
+ /**
257
+ * Type guard: returns true if the error is a Varla custom error revert.
258
+ */
259
+ export function isVarlaError(err: unknown): boolean {
260
+ return decodeVarlaError(err) !== null;
261
+ }
262
+
263
+ /**
264
+ * Format a decoded error into a human-readable string.
265
+ *
266
+ * Example output: `"VarlaCore.InsufficientCollateral(required=1000, actual=500)"`
267
+ */
268
+ export function formatVarlaError(decoded: DecodedVarlaError): string {
269
+ const args =
270
+ decoded.args.length > 0 ? `(${decoded.args.map((a) => String(a)).join(", ")})` : "()";
271
+ return `${decoded.contract}.${decoded.name}${args}`;
272
+ }
273
+
274
+ /**
275
+ * Convenience: decode + format in one call.
276
+ *
277
+ * @returns Human-readable error string, or `null` if not a known Varla error.
278
+ */
279
+ export function tryFormatVarlaError(errOrData: unknown): string | null {
280
+ const decoded = decodeVarlaError(errOrData);
281
+ if (!decoded) return null;
282
+ return formatVarlaError(decoded);
283
+ }
284
+
285
+ /**
286
+ * Get all known custom error names across all Varla contracts.
287
+ *
288
+ * Useful for logging/alerting configuration.
289
+ */
290
+ export function getAllVarlaErrorNames(): string[] {
291
+ const map = ensureSelectorMap();
292
+ return [...new Set([...map.values()].map((e) => e.errorItem.name))];
293
+ }
294
+
295
+ /**
296
+ * Get all known error selectors mapped to their names.
297
+ */
298
+ export function getVarlaErrorSelectors(): ReadonlyMap<Hex, { name: string; contract: string }> {
299
+ const map = ensureSelectorMap();
300
+ const result = new Map<Hex, { name: string; contract: string }>();
301
+ for (const [sel, entry] of map) {
302
+ result.set(sel as Hex, { name: entry.errorItem.name, contract: entry.label });
303
+ }
304
+ return result;
305
+ }
@@ -0,0 +1,37 @@
1
+ // Note: explicit .js extension is required for Node ESM resolution.
2
+
3
+ import type { AbiEvent, Log } from "viem";
4
+ import { decodeEventLog } from "viem";
5
+
6
+ export type DecodedEvent<TArgs = Record<string, unknown>> = {
7
+ args: TArgs;
8
+ eventName: string;
9
+ log: Log;
10
+ };
11
+
12
+ /**
13
+ * Decode logs for a single event definition. Returns only successfully decoded entries.
14
+ */
15
+ export function decodeEventLogs(params: { event: AbiEvent; logs: Log[] }): DecodedEvent[] {
16
+ const out: DecodedEvent[] = [];
17
+
18
+ for (const log of params.logs) {
19
+ try {
20
+ const decoded = decodeEventLog({
21
+ abi: [params.event] as any,
22
+ data: log.data,
23
+ topics: log.topics as any,
24
+ }) as any;
25
+
26
+ out.push({
27
+ args: decoded.args as Record<string, unknown>,
28
+ eventName: decoded.eventName as string,
29
+ log,
30
+ });
31
+ } catch {
32
+ // ignore logs that don't decode cleanly (RPCs can return unrelated logs when address is omitted)
33
+ }
34
+ }
35
+
36
+ return out;
37
+ }
@@ -0,0 +1,70 @@
1
+ // Note: explicit .js extension is required for Node ESM resolution.
2
+
3
+ import type { AbiEvent } from "viem";
4
+ import { getAbiItem } from "viem";
5
+
6
+ import { abis } from "../generated.js";
7
+
8
+ // ---------------------------------------------------------------------------
9
+ // Oracle
10
+ // ---------------------------------------------------------------------------
11
+
12
+ export const ORACLE_EVENTS = {
13
+ PositionConfigured: getAbiItem({
14
+ abi: abis.VARLAORACLE_ABI,
15
+ name: "PositionConfigured",
16
+ }) as AbiEvent,
17
+ OppositePositionsConfigured: getAbiItem({
18
+ abi: abis.VARLAORACLE_ABI,
19
+ name: "OppositePositionsConfigured",
20
+ }) as AbiEvent,
21
+ NegRiskPositionConfigured: getAbiItem({
22
+ abi: abis.VARLAORACLE_ABI,
23
+ name: "NegRiskPositionConfigured",
24
+ }) as AbiEvent,
25
+ NegRiskPositionsBatchConfigured: getAbiItem({
26
+ abi: abis.VARLAORACLE_ABI,
27
+ name: "NegRiskPositionsBatchConfigured",
28
+ }) as AbiEvent,
29
+ PriceUpdated: getAbiItem({
30
+ abi: abis.VARLAORACLE_ABI,
31
+ name: "PriceUpdated",
32
+ }) as AbiEvent,
33
+ PositionInvalidated: getAbiItem({
34
+ abi: abis.VARLAORACLE_ABI,
35
+ name: "PositionInvalidated",
36
+ }) as AbiEvent,
37
+ PositionValidated: getAbiItem({
38
+ abi: abis.VARLAORACLE_ABI,
39
+ name: "PositionValidated",
40
+ }) as AbiEvent,
41
+ } as const;
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Core
45
+ // ---------------------------------------------------------------------------
46
+
47
+ export const CORE_EVENTS = {
48
+ Deposit: getAbiItem({ abi: abis.VARLACORE_ABI, name: "Deposit" }) as AbiEvent,
49
+ Withdraw: getAbiItem({ abi: abis.VARLACORE_ABI, name: "Withdraw" }) as AbiEvent,
50
+ Borrow: getAbiItem({ abi: abis.VARLACORE_ABI, name: "Borrow" }) as AbiEvent,
51
+ Repay: getAbiItem({ abi: abis.VARLACORE_ABI, name: "Repay" }) as AbiEvent,
52
+ Liquidate: getAbiItem({ abi: abis.VARLACORE_ABI, name: "Liquidate" }) as AbiEvent,
53
+ LiquidationDebtRepaid: getAbiItem({
54
+ abi: abis.VARLACORE_ABI,
55
+ name: "LiquidationDebtRepaid",
56
+ }) as AbiEvent,
57
+ } as const;
58
+
59
+ // ---------------------------------------------------------------------------
60
+ // Pool
61
+ // ---------------------------------------------------------------------------
62
+
63
+ export const POOL_EVENTS = {
64
+ Draw: getAbiItem({ abi: abis.VARLAPOOL_ABI, name: "Draw" }) as AbiEvent,
65
+ Repay: getAbiItem({ abi: abis.VARLAPOOL_ABI, name: "Repay" }) as AbiEvent,
66
+ AccrueInterest: getAbiItem({
67
+ abi: abis.VARLAPOOL_ABI,
68
+ name: "AccrueInterest",
69
+ }) as AbiEvent,
70
+ } as const;
@@ -0,0 +1,7 @@
1
+ // Note: explicit .js extension is required for Node ESM resolution.
2
+
3
+ export * from "./decode.js";
4
+ export * from "./defs.js";
5
+ export * from "./logs.js";
6
+ export * from "./oracleRegistrySync.js";
7
+ export * from "./recent.js";
@@ -0,0 +1,42 @@
1
+ // Note: explicit .js extension is required for Node ESM resolution.
2
+
3
+ import type { AbiEvent, Address, Log, PublicClient } from "viem";
4
+
5
+ export type GetEventLogsChunkedParams = {
6
+ client: PublicClient;
7
+ address?: Address | Address[];
8
+ event: AbiEvent;
9
+ // We keep args loosely typed here because viem's `getLogs` args typing is heavily generic
10
+ // and we want this helper to be ergonomic.
11
+ args?: Record<string, unknown> | readonly unknown[];
12
+ strict?: boolean;
13
+ fromBlock: bigint;
14
+ toBlock: bigint;
15
+ /** Max number of blocks per request. */
16
+ blockRange?: bigint;
17
+ };
18
+
19
+ /**
20
+ * Fetch logs in block-range chunks to avoid RPC limits/timeouts.
21
+ */
22
+ export async function getEventLogsChunked(params: GetEventLogsChunkedParams): Promise<Log[]> {
23
+ const range = params.blockRange ?? 10_000n;
24
+ if (range <= 0n) throw new Error(`blockRange must be > 0 (got ${range})`);
25
+
26
+ const out: Log[] = [];
27
+ let start = params.fromBlock;
28
+ while (start <= params.toBlock) {
29
+ const end = start + range - 1n <= params.toBlock ? start + range - 1n : params.toBlock;
30
+ const logs = await params.client.getLogs({
31
+ address: params.address,
32
+ event: params.event as any,
33
+ args: params.args as any,
34
+ strict: params.strict as any,
35
+ fromBlock: start,
36
+ toBlock: end,
37
+ } as any);
38
+ out.push(...logs);
39
+ start = end + 1n;
40
+ }
41
+ return out;
42
+ }