@varla/sdk 1.10.9 → 1.10.11

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/AGENTS.md ADDED
@@ -0,0 +1,22 @@
1
+ # @varla/sdk (AGENTS)
2
+
3
+ Published package: **@varla/sdk**
4
+
5
+ ## Install & build
6
+ - Install (repo root): `bun install`
7
+ - Build: `cd packages/sdk && bun run build`
8
+ - Prepack (clean + regenerate + build): `cd packages/sdk && bun run prepack`
9
+
10
+ ## Tests
11
+ - Quick: `cd packages/sdk && bun run test:quick`
12
+ - Types: `cd packages/sdk && bun run test:types`
13
+ - Slow RPC (opt-in): `cd packages/sdk && bun run test:rpc:slow`
14
+
15
+ ## Key exports
16
+ - Addresses: `@varla/sdk/addresses`
17
+ - ABIs: `@varla/sdk/abi`
18
+ - Core types/bindings: `@varla/sdk` (`getVarlaContracts`, `getRequiredVarlaContracts`)
19
+ - Views: `@varla/sdk` or `@varla/sdk/views`
20
+ - Actions: `@varla/sdk/actions`
21
+ - Events/indexer: `@varla/sdk/events`
22
+ - Utilities: `@varla/sdk/batch`, `@varla/sdk/format`
package/FRONTEND.md ADDED
@@ -0,0 +1,252 @@
1
+ # Frontend integration guide (Next.js + RainbowKit + wagmi/viem)
2
+
3
+ This SDK is intentionally **batteries-not-included** for:
4
+
5
+ - RPC configuration (URLs, retries, fallbacks, rate limits)
6
+ - wallet connection / signers
7
+ - transaction lifecycle UX (toasts, confirmations, polling, reorg handling)
8
+
9
+ The SDK *does* provide:
10
+
11
+ - ABIs + deployed addresses
12
+ - typed viem contract bindings (`getVarlaContracts`)
13
+ - high-level read facades (`@varla/sdk/views`)
14
+ - simulate-first write helpers (`@varla/sdk/actions`)
15
+
16
+ This doc shows a recommended integration setup for **Next.js + RainbowKit**.
17
+
18
+ ---
19
+
20
+ ## 1) Setup: wagmi config with explicit RPCs
21
+
22
+ The SDK does not ship RPC URLs. Your app should configure those.
23
+
24
+ Example `wagmi.ts` (app-side):
25
+
26
+ ```ts
27
+ import { http, fallback } from "viem";
28
+ import { polygon, bsc } from "wagmi/chains";
29
+ import { getDefaultConfig } from "@rainbow-me/rainbowkit";
30
+
31
+ const polygonRpc = process.env.NEXT_PUBLIC_POLYGON_RPC_URL;
32
+ const bscRpc = process.env.NEXT_PUBLIC_BSC_RPC_URL;
33
+
34
+ if (!polygonRpc) throw new Error("Missing NEXT_PUBLIC_POLYGON_RPC_URL");
35
+ if (!bscRpc) throw new Error("Missing NEXT_PUBLIC_BSC_RPC_URL");
36
+
37
+ export const wagmiConfig = getDefaultConfig({
38
+ appName: "Your App",
39
+ projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID!,
40
+ chains: [polygon, bsc],
41
+ transports: {
42
+ [polygon.id]: fallback([
43
+ http(polygonRpc),
44
+ // Optionally add a backup RPC:
45
+ // http("https://polygon-rpc.com"),
46
+ ]),
47
+ [bsc.id]: fallback([
48
+ http(bscRpc),
49
+ // http("https://bsc-dataseed.binance.org"),
50
+ ]),
51
+ },
52
+ });
53
+ ```
54
+
55
+ Notes:
56
+ - If you need retries/backoff, implement it at the **RPC transport** layer.
57
+ - For high-volume reads, prefer multicall + chunking (the SDK includes `multicallChunks`).
58
+
59
+ ---
60
+
61
+ ## 2) Getting Varla contract bindings (typed viem)
62
+
63
+ In components/hooks, pull the active `PublicClient` from wagmi and pass it to the SDK:
64
+
65
+ ```ts
66
+ import { usePublicClient } from "wagmi";
67
+ import { getVarlaContracts } from "@varla/sdk";
68
+
69
+ export function useVarlaContracts() {
70
+ const publicClient = usePublicClient();
71
+ // You may want to map `publicClient.chain?.id` to a Varla ChainKey.
72
+ const chainKey = publicClient.chain?.id === 56 ? "bsc" : "polygon";
73
+ return getVarlaContracts({ chain: chainKey, client: publicClient });
74
+ }
75
+ ```
76
+
77
+ ---
78
+
79
+ ## 3) Reads
80
+
81
+ ### Direct reads
82
+ You can call typed reads on the viem contracts. Reminder: **viem args are arrays**.
83
+
84
+ ```ts
85
+ const hf = await c.core.read.getHealthFactor([userAddress]);
86
+ ```
87
+
88
+ ### Prefer SDK view facades for common UI needs
89
+
90
+ ```ts
91
+ import * as views from "@varla/sdk/views";
92
+
93
+ const snap = await views.readAccountSnapshot({
94
+ core: c.core,
95
+ user: userAddress,
96
+ });
97
+ ```
98
+
99
+ ---
100
+
101
+ ## 4) Writes (simulate-first) with wagmi
102
+
103
+ The SDK write helpers return simulated requests; **you send them with your wallet client**.
104
+
105
+ ### Pattern
106
+
107
+ 1) simulate via `PublicClient`
108
+ 2) send via `WalletClient`
109
+ 3) wait for receipt
110
+
111
+ ```ts
112
+ import { useWalletClient, usePublicClient } from "wagmi";
113
+ import * as actions from "@varla/sdk/actions";
114
+
115
+ export function useBorrow() {
116
+ const publicClient = usePublicClient();
117
+ const { data: walletClient } = useWalletClient();
118
+
119
+ return async function borrow(params: {
120
+ coreAddress: `0x${string}`;
121
+ amount: bigint;
122
+ account: `0x${string}`;
123
+ }) {
124
+ if (!walletClient) throw new Error("Wallet not connected");
125
+
126
+ const sim = await actions.prepareCoreBorrow({
127
+ publicClient,
128
+ coreAddress: params.coreAddress,
129
+ account: params.account,
130
+ amount: params.amount,
131
+ });
132
+
133
+ const hash = await actions.sendTx({ walletClient, request: sim.request });
134
+ await publicClient.waitForTransactionReceipt({ hash });
135
+ return hash;
136
+ };
137
+ }
138
+ ```
139
+
140
+ ### UX expectations
141
+ Your app should own:
142
+ - network switching (`switchChain`) when connected chain != expected chain
143
+ - user rejection handling
144
+ - toasts and pending state
145
+ - refreshing query caches after confirmed receipts
146
+
147
+ ---
148
+
149
+ ## 5) Retries, fallbacks, and rate limits
150
+
151
+ The SDK intentionally does not enforce a retry policy.
152
+
153
+ Recommended approach:
154
+
155
+ - configure **multiple RPC endpoints** per chain via wagmi/viem `fallback([http(...), http(...)])`
156
+ - keep multicalls bounded:
157
+ - use `@varla/sdk/batch` `multicallChunks` (already used internally by many views)
158
+ - treat RPC errors as expected and surface “try again” UX
159
+
160
+ ---
161
+
162
+ ## 6) Gotchas
163
+
164
+ - **Viem args are arrays**: `read.fn([arg1, arg2])`.
165
+ - Writes should generally be **simulate-first** to get revert reasons early.
166
+ - Some admin flows may require **two-phase execution** (example: oracle seeding opposites requires markets configured first).
167
+
168
+ ---
169
+
170
+ ## 7) Standard “tx runner” helper (simulate → send → wait → error mapping)
171
+
172
+ Most apps end up writing the same glue code around transactions.
173
+
174
+ Recommended: centralize it in one place (app-side), and have UI components call it.
175
+
176
+ This helper:
177
+ - runs SDK `prepare*` (simulation)
178
+ - sends with the connected `walletClient`
179
+ - waits for a receipt
180
+ - normalizes common error cases
181
+
182
+ ```ts
183
+ import type { PublicClient, WalletClient } from "viem";
184
+ import { sendTx } from "@varla/sdk/actions";
185
+
186
+ export type TxRunnerErrorCode =
187
+ | "WALLET_NOT_CONNECTED"
188
+ | "USER_REJECTED"
189
+ | "SIMULATION_REVERT"
190
+ | "UNKNOWN";
191
+
192
+ export class TxRunnerError extends Error {
193
+ code: TxRunnerErrorCode;
194
+ cause?: unknown;
195
+ constructor(code: TxRunnerErrorCode, message: string, cause?: unknown) {
196
+ super(message);
197
+ this.code = code;
198
+ this.cause = cause;
199
+ }
200
+ }
201
+
202
+ function isUserRejectedRequest(err: unknown): boolean {
203
+ // Wallets vary. This is intentionally heuristic.
204
+ const msg = String((err as any)?.message ?? "").toLowerCase();
205
+ return msg.includes("user rejected") || msg.includes("rejected the request") || msg.includes("denied");
206
+ }
207
+
208
+ /**
209
+ * Runs a simulate-first tx end-to-end.
210
+ *
211
+ * Usage:
212
+ * await runTx({ publicClient, walletClient, simulate: () => actions.prepareCoreBorrow(...) })
213
+ */
214
+ export async function runTx(params: {
215
+ publicClient: Pick<PublicClient, "waitForTransactionReceipt">;
216
+ walletClient: Pick<WalletClient, "writeContract"> | undefined;
217
+ simulate: () => Promise<{ request: any }>;
218
+ }): Promise<`0x${string}`> {
219
+ if (!params.walletClient) {
220
+ throw new TxRunnerError("WALLET_NOT_CONNECTED", "Wallet not connected");
221
+ }
222
+
223
+ let sim: { request: any };
224
+ try {
225
+ sim = await params.simulate();
226
+ } catch (err) {
227
+ throw new TxRunnerError("SIMULATION_REVERT", "Transaction simulation failed", err);
228
+ }
229
+
230
+ try {
231
+ const hash = await sendTx({ walletClient: params.walletClient, request: sim.request });
232
+ await params.publicClient.waitForTransactionReceipt({ hash });
233
+ return hash;
234
+ } catch (err) {
235
+ if (isUserRejectedRequest(err)) {
236
+ throw new TxRunnerError("USER_REJECTED", "User rejected the transaction", err);
237
+ }
238
+ throw new TxRunnerError("UNKNOWN", "Transaction failed", err);
239
+ }
240
+ }
241
+ ```
242
+
243
+ With wagmi hooks, you’d pass:
244
+ - `usePublicClient()` → `publicClient`
245
+ - `useWalletClient().data` → `walletClient`
246
+ - `simulate: () => actions.prepare...({ publicClient, account, ... })`
247
+
248
+ This keeps UI components clean, and gives you one place to wire:
249
+ - toasts
250
+ - analytics
251
+ - receipt confirmations
252
+ - error mapping
package/README.md CHANGED
@@ -22,6 +22,8 @@ npm i @varla/sdk
22
22
 
23
23
  ## Usage
24
24
 
25
+ Frontend (Next.js + RainbowKit + wagmi/viem): see [`FRONTEND.md`](./FRONTEND.md).
26
+
25
27
  ## Testing (SDK)
26
28
 
27
29
  Run from `packages/sdk`:
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@varla/sdk",
3
- "version": "1.10.9",
3
+ "version": "1.10.11",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "files": [
8
8
  "dist",
9
- "README.md"
9
+ "README.md",
10
+ "FRONTEND.md",
11
+ "AGENTS.md"
10
12
  ],
11
13
  "exports": {
12
14
  ".": {