@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 +22 -0
- package/FRONTEND.md +252 -0
- package/README.md +2 -0
- package/package.json +4 -2
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
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@varla/sdk",
|
|
3
|
-
"version": "1.10.
|
|
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
|
".": {
|