@glowlabs-org/utils 0.2.154 → 0.2.156
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/README.md +175 -17
- package/dist/cjs/browser.d.ts +2 -0
- package/dist/cjs/browser.js +7 -1
- package/dist/cjs/browser.js.map +1 -1
- package/dist/cjs/{farms-router-DwbBMkUd.js → farms-router-DekpTBQj.js} +750 -11
- package/dist/cjs/farms-router-DekpTBQj.js.map +1 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/abis/rewardKernelABI.d.ts +418 -0
- package/dist/cjs/lib/control-api/farms-router.d.ts +2 -1
- package/dist/cjs/lib/control-api/region-router.d.ts +2 -1
- package/dist/cjs/lib/control-api/wallets-router.d.ts +2 -2
- package/dist/cjs/lib/hooks/use-rewards-kernel.d.ts +45 -0
- package/dist/cjs/lib/types/index.d.ts +77 -1
- package/dist/esm/browser.d.ts +2 -0
- package/dist/esm/browser.js +2 -2
- package/dist/esm/{farms-router-C0g4hf2Z.js → farms-router-L56VPDNz.js} +749 -12
- package/dist/esm/farms-router-L56VPDNz.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -2
- package/dist/esm/lib/abis/rewardKernelABI.d.ts +418 -0
- package/dist/esm/lib/control-api/farms-router.d.ts +2 -1
- package/dist/esm/lib/control-api/region-router.d.ts +2 -1
- package/dist/esm/lib/control-api/wallets-router.d.ts +2 -2
- package/dist/esm/lib/hooks/use-rewards-kernel.d.ts +45 -0
- package/dist/esm/lib/types/index.d.ts +77 -1
- package/package.json +1 -1
- package/src/browser.ts +2 -0
- package/src/index.ts +1 -0
- package/src/lib/abis/rewardKernelABI.ts +264 -0
- package/src/lib/control-api/farms-router.ts +33 -0
- package/src/lib/control-api/region-router.ts +29 -0
- package/src/lib/control-api/wallets-router.ts +36 -2
- package/src/lib/hooks/README.md +295 -0
- package/src/lib/hooks/use-rewards-kernel.ts +547 -0
- package/src/lib/types/index.ts +91 -1
- package/dist/cjs/farms-router-DwbBMkUd.js.map +0 -1
- package/dist/esm/farms-router-C0g4hf2Z.js.map +0 -1
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type WalletClient,
|
|
3
|
+
type PublicClient,
|
|
4
|
+
type Address,
|
|
5
|
+
formatEther,
|
|
6
|
+
} from "viem";
|
|
7
|
+
import { REWARDS_KERNEL_ABI } from "../abis/rewardKernelABI";
|
|
8
|
+
import { getAddresses } from "../../constants/addresses";
|
|
9
|
+
import {
|
|
10
|
+
parseViemError,
|
|
11
|
+
waitForViemTransactionWithRetry,
|
|
12
|
+
} from "../../utils/transaction-utils";
|
|
13
|
+
import {
|
|
14
|
+
sentryAddBreadcrumb,
|
|
15
|
+
sentryCaptureException,
|
|
16
|
+
} from "../../utils/sentry";
|
|
17
|
+
|
|
18
|
+
export enum RewardsKernelError {
|
|
19
|
+
CONTRACT_NOT_AVAILABLE = "Contract not available",
|
|
20
|
+
SIGNER_NOT_AVAILABLE = "Signer not available",
|
|
21
|
+
UNKNOWN_ERROR = "Unknown error",
|
|
22
|
+
INVALID_PARAMETERS = "Invalid parameters",
|
|
23
|
+
ALREADY_CLAIMED = "Already claimed from this nonce",
|
|
24
|
+
NOT_FINALIZED = "Nonce not yet finalized",
|
|
25
|
+
NONCE_REJECTED = "Cannot claim from rejected nonce",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Token and amount structure matching the contract
|
|
29
|
+
export interface TokenAndAmount {
|
|
30
|
+
token: `0x${string}`;
|
|
31
|
+
amount: bigint;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Reward metadata structure
|
|
35
|
+
export interface RewardMeta {
|
|
36
|
+
merkleRoot: string;
|
|
37
|
+
pushTimestamp: number;
|
|
38
|
+
rejected: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Parameters for claiming a payout
|
|
42
|
+
export interface ClaimPayoutParams {
|
|
43
|
+
nonce: bigint;
|
|
44
|
+
proof: `0x${string}`[]; // bytes32[] as hex strings
|
|
45
|
+
tokensAndAmounts: TokenAndAmount[];
|
|
46
|
+
from: `0x${string}`; // Address providing the tokens
|
|
47
|
+
to: `0x${string}`; // Address receiving the tokens
|
|
48
|
+
isGuardedToken: boolean[]; // Which tokens are guarded
|
|
49
|
+
toCounterfactual: boolean[]; // Whether to send to counterfactual wallet
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Type-guard style helper to ensure a wallet client exists
|
|
53
|
+
function assertWalletClient(
|
|
54
|
+
maybeWalletClient: WalletClient | undefined
|
|
55
|
+
): asserts maybeWalletClient is WalletClient {
|
|
56
|
+
if (!maybeWalletClient) {
|
|
57
|
+
throw new Error(RewardsKernelError.SIGNER_NOT_AVAILABLE);
|
|
58
|
+
}
|
|
59
|
+
if (!maybeWalletClient.account) {
|
|
60
|
+
throw new Error("Wallet client must have an account");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function useRewardsKernel(
|
|
65
|
+
walletClient: WalletClient | undefined,
|
|
66
|
+
publicClient: PublicClient | undefined,
|
|
67
|
+
CHAIN_ID: number
|
|
68
|
+
) {
|
|
69
|
+
// Use dynamic addresses based on chain configuration
|
|
70
|
+
const ADDRESSES = getAddresses(CHAIN_ID);
|
|
71
|
+
|
|
72
|
+
// Framework-agnostic processing flag
|
|
73
|
+
let isProcessing = false;
|
|
74
|
+
const setIsProcessing = (value: boolean) => {
|
|
75
|
+
isProcessing = value;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Helper to assert public client is available
|
|
79
|
+
function assertPublicClient(
|
|
80
|
+
maybePublicClient: PublicClient | undefined
|
|
81
|
+
): asserts maybePublicClient is PublicClient {
|
|
82
|
+
if (!maybePublicClient) {
|
|
83
|
+
throw new Error("Public client not available");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Claim payout from a finalized nonce
|
|
89
|
+
* @param params Parameters for claiming the payout
|
|
90
|
+
*/
|
|
91
|
+
async function claimPayout(params: ClaimPayoutParams): Promise<string> {
|
|
92
|
+
assertWalletClient(walletClient);
|
|
93
|
+
assertPublicClient(publicClient);
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
setIsProcessing(true);
|
|
97
|
+
|
|
98
|
+
sentryAddBreadcrumb({
|
|
99
|
+
category: "rewards-kernel",
|
|
100
|
+
message: "claimPayout.start",
|
|
101
|
+
level: "info",
|
|
102
|
+
data: {
|
|
103
|
+
chainId: walletClient?.chain?.id,
|
|
104
|
+
contract: ADDRESSES.REWARDS_KERNEL,
|
|
105
|
+
nonce: params.nonce.toString(),
|
|
106
|
+
to: params.to,
|
|
107
|
+
from: params.from,
|
|
108
|
+
tokensCount: params.tokensAndAmounts.length,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const {
|
|
113
|
+
nonce,
|
|
114
|
+
proof,
|
|
115
|
+
tokensAndAmounts,
|
|
116
|
+
from,
|
|
117
|
+
to,
|
|
118
|
+
isGuardedToken,
|
|
119
|
+
toCounterfactual,
|
|
120
|
+
} = params;
|
|
121
|
+
|
|
122
|
+
// Validate parameters
|
|
123
|
+
if (!proof || proof.length === 0) {
|
|
124
|
+
throw new Error("Merkle proof is required");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!tokensAndAmounts || tokensAndAmounts.length === 0) {
|
|
128
|
+
throw new Error("Tokens and amounts are required");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (isGuardedToken.length !== tokensAndAmounts.length) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
"isGuardedToken array length must match tokensAndAmounts"
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (toCounterfactual.length !== tokensAndAmounts.length) {
|
|
138
|
+
throw new Error(
|
|
139
|
+
"toCounterfactual array length must match tokensAndAmounts"
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!from || !to) {
|
|
144
|
+
throw new Error(RewardsKernelError.INVALID_PARAMETERS);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Check if already claimed
|
|
148
|
+
const owner = walletClient.account?.address;
|
|
149
|
+
if (!owner) {
|
|
150
|
+
throw new Error("No account found in wallet client");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const alreadyClaimed = await isClaimed(owner, nonce);
|
|
154
|
+
if (alreadyClaimed) {
|
|
155
|
+
throw new Error(RewardsKernelError.ALREADY_CLAIMED);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Check if finalized
|
|
159
|
+
const finalized = await isFinalized(nonce);
|
|
160
|
+
if (!finalized) {
|
|
161
|
+
throw new Error(RewardsKernelError.NOT_FINALIZED);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Run a simulation first to surface any revert reason
|
|
165
|
+
try {
|
|
166
|
+
await publicClient.simulateContract({
|
|
167
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
168
|
+
abi: REWARDS_KERNEL_ABI,
|
|
169
|
+
functionName: "claimPayout",
|
|
170
|
+
args: [
|
|
171
|
+
nonce,
|
|
172
|
+
proof as `0x${string}`[],
|
|
173
|
+
tokensAndAmounts as readonly {
|
|
174
|
+
token: `0x${string}`;
|
|
175
|
+
amount: bigint;
|
|
176
|
+
}[],
|
|
177
|
+
from as Address,
|
|
178
|
+
to as Address,
|
|
179
|
+
isGuardedToken,
|
|
180
|
+
toCounterfactual,
|
|
181
|
+
],
|
|
182
|
+
account: walletClient.account!,
|
|
183
|
+
});
|
|
184
|
+
} catch (simulationError) {
|
|
185
|
+
sentryCaptureException(simulationError, {
|
|
186
|
+
action: "claimPayout.simulate",
|
|
187
|
+
chainId: walletClient?.chain?.id,
|
|
188
|
+
contract: ADDRESSES.REWARDS_KERNEL,
|
|
189
|
+
nonce: nonce.toString(),
|
|
190
|
+
});
|
|
191
|
+
throw new Error(parseViemError(simulationError));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Execute the transaction
|
|
195
|
+
const hash = await walletClient.writeContract({
|
|
196
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
197
|
+
abi: REWARDS_KERNEL_ABI,
|
|
198
|
+
functionName: "claimPayout",
|
|
199
|
+
args: [
|
|
200
|
+
nonce,
|
|
201
|
+
proof as `0x${string}`[],
|
|
202
|
+
tokensAndAmounts as readonly {
|
|
203
|
+
token: `0x${string}`;
|
|
204
|
+
amount: bigint;
|
|
205
|
+
}[],
|
|
206
|
+
from as Address,
|
|
207
|
+
to as Address,
|
|
208
|
+
isGuardedToken,
|
|
209
|
+
toCounterfactual,
|
|
210
|
+
],
|
|
211
|
+
chain: walletClient.chain,
|
|
212
|
+
account: walletClient.account!,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
await waitForViemTransactionWithRetry(publicClient, hash);
|
|
216
|
+
|
|
217
|
+
return hash;
|
|
218
|
+
} catch (error) {
|
|
219
|
+
sentryCaptureException(error, {
|
|
220
|
+
action: "claimPayout",
|
|
221
|
+
chainId: walletClient?.chain?.id,
|
|
222
|
+
contract: ADDRESSES.REWARDS_KERNEL,
|
|
223
|
+
nonce: params.nonce.toString(),
|
|
224
|
+
from: params.from,
|
|
225
|
+
to: params.to,
|
|
226
|
+
});
|
|
227
|
+
throw new Error(parseViemError(error));
|
|
228
|
+
} finally {
|
|
229
|
+
setIsProcessing(false);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Get reward metadata for a specific nonce
|
|
235
|
+
* @param nonce The nonce to query
|
|
236
|
+
*/
|
|
237
|
+
async function getRewardMeta(nonce: bigint): Promise<RewardMeta> {
|
|
238
|
+
assertPublicClient(publicClient);
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
const result = (await publicClient.readContract({
|
|
242
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
243
|
+
abi: REWARDS_KERNEL_ABI,
|
|
244
|
+
functionName: "getRewardMeta",
|
|
245
|
+
args: [nonce],
|
|
246
|
+
})) as any;
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
merkleRoot: result[0],
|
|
250
|
+
pushTimestamp: Number(result[1]),
|
|
251
|
+
rejected: result[2],
|
|
252
|
+
};
|
|
253
|
+
} catch (error) {
|
|
254
|
+
throw new Error(parseViemError(error));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Get the maximum claimable amount for a token at a specific nonce
|
|
260
|
+
* @param nonce The nonce to query
|
|
261
|
+
* @param token The token address
|
|
262
|
+
*/
|
|
263
|
+
async function getMaxReward(
|
|
264
|
+
nonce: bigint,
|
|
265
|
+
token: `0x${string}`
|
|
266
|
+
): Promise<bigint> {
|
|
267
|
+
assertPublicClient(publicClient);
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
const result = (await publicClient.readContract({
|
|
271
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
272
|
+
abi: REWARDS_KERNEL_ABI,
|
|
273
|
+
functionName: "getMaxReward",
|
|
274
|
+
args: [nonce, token as Address],
|
|
275
|
+
})) as bigint;
|
|
276
|
+
|
|
277
|
+
return result;
|
|
278
|
+
} catch (error) {
|
|
279
|
+
throw new Error(parseViemError(error));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Get the amount already claimed for a token at a specific nonce
|
|
285
|
+
* @param nonce The nonce to query
|
|
286
|
+
* @param token The token address
|
|
287
|
+
*/
|
|
288
|
+
async function getAmountClaimed(
|
|
289
|
+
nonce: bigint,
|
|
290
|
+
token: `0x${string}`
|
|
291
|
+
): Promise<bigint> {
|
|
292
|
+
assertPublicClient(publicClient);
|
|
293
|
+
|
|
294
|
+
try {
|
|
295
|
+
const result = (await publicClient.readContract({
|
|
296
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
297
|
+
abi: REWARDS_KERNEL_ABI,
|
|
298
|
+
functionName: "getAmountClaimed",
|
|
299
|
+
args: [nonce, token as Address],
|
|
300
|
+
})) as bigint;
|
|
301
|
+
|
|
302
|
+
return result;
|
|
303
|
+
} catch (error) {
|
|
304
|
+
throw new Error(parseViemError(error));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Check if a nonce is finalized and claimable
|
|
310
|
+
* @param nonce The nonce to check
|
|
311
|
+
*/
|
|
312
|
+
async function isFinalized(nonce: bigint): Promise<boolean> {
|
|
313
|
+
assertPublicClient(publicClient);
|
|
314
|
+
|
|
315
|
+
try {
|
|
316
|
+
const result = (await publicClient.readContract({
|
|
317
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
318
|
+
abi: REWARDS_KERNEL_ABI,
|
|
319
|
+
functionName: "isFinalized",
|
|
320
|
+
args: [nonce],
|
|
321
|
+
})) as boolean;
|
|
322
|
+
|
|
323
|
+
return result;
|
|
324
|
+
} catch (error) {
|
|
325
|
+
throw new Error(parseViemError(error));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Check if a user has already claimed from a specific nonce
|
|
331
|
+
* @param user The user address
|
|
332
|
+
* @param nonce The nonce to check
|
|
333
|
+
*/
|
|
334
|
+
async function isClaimed(
|
|
335
|
+
user: `0x${string}`,
|
|
336
|
+
nonce: bigint
|
|
337
|
+
): Promise<boolean> {
|
|
338
|
+
assertPublicClient(publicClient);
|
|
339
|
+
|
|
340
|
+
try {
|
|
341
|
+
const result = (await publicClient.readContract({
|
|
342
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
343
|
+
abi: REWARDS_KERNEL_ABI,
|
|
344
|
+
functionName: "isClaimed",
|
|
345
|
+
args: [user as Address, nonce],
|
|
346
|
+
})) as boolean;
|
|
347
|
+
|
|
348
|
+
return result;
|
|
349
|
+
} catch (error) {
|
|
350
|
+
throw new Error(parseViemError(error));
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Get the next nonce that will be used for posting
|
|
356
|
+
*/
|
|
357
|
+
async function getNextPostNonce(): Promise<bigint> {
|
|
358
|
+
assertPublicClient(publicClient);
|
|
359
|
+
|
|
360
|
+
try {
|
|
361
|
+
const result = (await publicClient.readContract({
|
|
362
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
363
|
+
abi: REWARDS_KERNEL_ABI,
|
|
364
|
+
functionName: "$nextPostNonce",
|
|
365
|
+
args: [],
|
|
366
|
+
})) as bigint;
|
|
367
|
+
|
|
368
|
+
return result;
|
|
369
|
+
} catch (error) {
|
|
370
|
+
throw new Error(parseViemError(error));
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Get the finality period in seconds
|
|
376
|
+
*/
|
|
377
|
+
async function getFinality(): Promise<bigint> {
|
|
378
|
+
assertPublicClient(publicClient);
|
|
379
|
+
|
|
380
|
+
try {
|
|
381
|
+
const result = (await publicClient.readContract({
|
|
382
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
383
|
+
abi: REWARDS_KERNEL_ABI,
|
|
384
|
+
functionName: "FINALITY",
|
|
385
|
+
args: [],
|
|
386
|
+
})) as bigint;
|
|
387
|
+
|
|
388
|
+
return result;
|
|
389
|
+
} catch (error) {
|
|
390
|
+
throw new Error(parseViemError(error));
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Get the foundation multisig address
|
|
396
|
+
*/
|
|
397
|
+
async function getFoundationMultisig(): Promise<string> {
|
|
398
|
+
assertPublicClient(publicClient);
|
|
399
|
+
|
|
400
|
+
try {
|
|
401
|
+
const result = (await publicClient.readContract({
|
|
402
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
403
|
+
abi: REWARDS_KERNEL_ABI,
|
|
404
|
+
functionName: "FOUNDATION_MULTISIG",
|
|
405
|
+
args: [],
|
|
406
|
+
})) as string;
|
|
407
|
+
|
|
408
|
+
return result;
|
|
409
|
+
} catch (error) {
|
|
410
|
+
throw new Error(parseViemError(error));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Get the rejection multisig address
|
|
416
|
+
*/
|
|
417
|
+
async function getRejectionMultisig(): Promise<string> {
|
|
418
|
+
assertPublicClient(publicClient);
|
|
419
|
+
|
|
420
|
+
try {
|
|
421
|
+
const result = (await publicClient.readContract({
|
|
422
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
423
|
+
abi: REWARDS_KERNEL_ABI,
|
|
424
|
+
functionName: "REJECTION_MULTISIG",
|
|
425
|
+
args: [],
|
|
426
|
+
})) as string;
|
|
427
|
+
|
|
428
|
+
return result;
|
|
429
|
+
} catch (error) {
|
|
430
|
+
throw new Error(parseViemError(error));
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Get the counterfactual holder factory address
|
|
436
|
+
*/
|
|
437
|
+
async function getCFHFactory(): Promise<string> {
|
|
438
|
+
assertPublicClient(publicClient);
|
|
439
|
+
|
|
440
|
+
try {
|
|
441
|
+
const result = (await publicClient.readContract({
|
|
442
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
443
|
+
abi: REWARDS_KERNEL_ABI,
|
|
444
|
+
functionName: "CFH_FACTORY",
|
|
445
|
+
args: [],
|
|
446
|
+
})) as string;
|
|
447
|
+
|
|
448
|
+
return result;
|
|
449
|
+
} catch (error) {
|
|
450
|
+
throw new Error(parseViemError(error));
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Estimate gas for claiming a payout
|
|
456
|
+
* @param params Parameters for claiming the payout
|
|
457
|
+
* @param ethPriceInUSD Current ETH price in USD (for cost estimation)
|
|
458
|
+
*/
|
|
459
|
+
async function estimateGasForClaimPayout(
|
|
460
|
+
params: ClaimPayoutParams,
|
|
461
|
+
ethPriceInUSD: number | null
|
|
462
|
+
): Promise<string> {
|
|
463
|
+
assertWalletClient(walletClient);
|
|
464
|
+
assertPublicClient(publicClient);
|
|
465
|
+
|
|
466
|
+
try {
|
|
467
|
+
const {
|
|
468
|
+
nonce,
|
|
469
|
+
proof,
|
|
470
|
+
tokensAndAmounts,
|
|
471
|
+
from,
|
|
472
|
+
to,
|
|
473
|
+
isGuardedToken,
|
|
474
|
+
toCounterfactual,
|
|
475
|
+
} = params;
|
|
476
|
+
|
|
477
|
+
const gasPrice = await publicClient.getGasPrice();
|
|
478
|
+
if (!gasPrice) {
|
|
479
|
+
throw new Error("Could not fetch gas price to estimate cost.");
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const estimatedGas = await publicClient.estimateContractGas({
|
|
483
|
+
address: ADDRESSES.REWARDS_KERNEL as Address,
|
|
484
|
+
abi: REWARDS_KERNEL_ABI,
|
|
485
|
+
functionName: "claimPayout",
|
|
486
|
+
args: [
|
|
487
|
+
nonce,
|
|
488
|
+
proof as `0x${string}`[],
|
|
489
|
+
tokensAndAmounts as readonly {
|
|
490
|
+
token: `0x${string}`;
|
|
491
|
+
amount: bigint;
|
|
492
|
+
}[],
|
|
493
|
+
from as Address,
|
|
494
|
+
to as Address,
|
|
495
|
+
isGuardedToken,
|
|
496
|
+
toCounterfactual,
|
|
497
|
+
],
|
|
498
|
+
account: walletClient.account!,
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
const estimatedCost: bigint = estimatedGas * gasPrice;
|
|
502
|
+
|
|
503
|
+
if (ethPriceInUSD) {
|
|
504
|
+
const estimatedCostInEth = formatEther(estimatedCost);
|
|
505
|
+
const estimatedCostInUSD = (
|
|
506
|
+
parseFloat(estimatedCostInEth) * ethPriceInUSD
|
|
507
|
+
).toFixed(2);
|
|
508
|
+
return estimatedCostInUSD;
|
|
509
|
+
} else {
|
|
510
|
+
throw new Error(
|
|
511
|
+
"Could not fetch the ETH price to calculate cost in USD."
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
} catch (error: any) {
|
|
515
|
+
throw new Error(parseViemError(error));
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return {
|
|
520
|
+
// Core contract functions
|
|
521
|
+
claimPayout,
|
|
522
|
+
|
|
523
|
+
// View functions
|
|
524
|
+
getRewardMeta,
|
|
525
|
+
getMaxReward,
|
|
526
|
+
getAmountClaimed,
|
|
527
|
+
isFinalized,
|
|
528
|
+
isClaimed,
|
|
529
|
+
getNextPostNonce,
|
|
530
|
+
getFinality,
|
|
531
|
+
getFoundationMultisig,
|
|
532
|
+
getRejectionMultisig,
|
|
533
|
+
getCFHFactory,
|
|
534
|
+
|
|
535
|
+
// Gas estimation
|
|
536
|
+
estimateGasForClaimPayout,
|
|
537
|
+
|
|
538
|
+
// State
|
|
539
|
+
get isProcessing() {
|
|
540
|
+
return isProcessing;
|
|
541
|
+
},
|
|
542
|
+
addresses: ADDRESSES,
|
|
543
|
+
|
|
544
|
+
// Wallet client availability
|
|
545
|
+
isSignerAvailable: !!walletClient,
|
|
546
|
+
};
|
|
547
|
+
}
|
package/src/lib/types/index.ts
CHANGED
|
@@ -573,7 +573,9 @@ export interface WalletFarmInfo {
|
|
|
573
573
|
protocolDepositPaidCurrency: string;
|
|
574
574
|
|
|
575
575
|
builtEpoch: number;
|
|
576
|
-
builtAt
|
|
576
|
+
builtAt?: string; // ISO 8601
|
|
577
|
+
glowSplitPercent6Decimals: string; // Wallet's GLW reward split (6 decimals)
|
|
578
|
+
depositSplitPercent6Decimals: string; // Wallet's deposit reward split (6 decimals)
|
|
577
579
|
}
|
|
578
580
|
|
|
579
581
|
export interface WalletDetails {
|
|
@@ -586,6 +588,94 @@ export interface WalletDetails {
|
|
|
586
588
|
ownedFarms: WalletFarmInfo[];
|
|
587
589
|
}
|
|
588
590
|
|
|
591
|
+
export interface WeeklyReward {
|
|
592
|
+
weekNumber: number;
|
|
593
|
+
paymentCurrency: PaymentCurrency;
|
|
594
|
+
protocolDepositRewardsReceived: string; // Protocol deposit rewards received by wallet
|
|
595
|
+
glowInflationTotal: string; // GLW inflation rewards (18 decimals)
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
export interface WeeklyRewardsSummary {
|
|
599
|
+
totalProtocolDepositRewardsReceived: string;
|
|
600
|
+
totalGlowInflation: string;
|
|
601
|
+
weeksActive: number;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export interface WalletWeeklyRewardsResponse {
|
|
605
|
+
wallet: string;
|
|
606
|
+
summary: WeeklyRewardsSummary;
|
|
607
|
+
rewards: WeeklyReward[];
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
export interface WeeklyRewardsQuery {
|
|
611
|
+
startWeek?: number; // Inclusive lower bound epoch/week
|
|
612
|
+
endWeek?: number; // Inclusive upper bound epoch/week
|
|
613
|
+
paymentCurrency?: PaymentCurrency; // Filter by payment currency
|
|
614
|
+
limit?: number; // Max rows to return (default 52, capped at 520)
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// ----------------------------- Farm Weekly Rewards ---------------------------
|
|
618
|
+
export interface FarmWeeklyReward {
|
|
619
|
+
weekNumber: number;
|
|
620
|
+
paymentCurrency: PaymentCurrency;
|
|
621
|
+
protocolDepositPaidTotal: string; // Total amount farm paid as protocol deposit
|
|
622
|
+
glowInflationTotal: string; // Total GLW inflation rewards allocated to farm (18 decimals)
|
|
623
|
+
expectedProductionTotal: string; // Farm's weekly carbon credit production in WAD (18 decimals)
|
|
624
|
+
protocolDepositRewardsDistributed: string; // Portion of protocol deposits distributed to wallets
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
export interface FarmWeeklyRewardsSummary {
|
|
628
|
+
totalProtocolDepositPaid: string;
|
|
629
|
+
totalGlowInflation: string;
|
|
630
|
+
totalExpectedProduction: string;
|
|
631
|
+
weeksActive: number;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
export interface FarmWeeklyRewardsResponse {
|
|
635
|
+
farmId: string;
|
|
636
|
+
summary: FarmWeeklyRewardsSummary;
|
|
637
|
+
rewards: FarmWeeklyReward[];
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
export interface FarmWeeklyRewardsQuery {
|
|
641
|
+
startWeek?: number; // Inclusive lower bound epoch/week
|
|
642
|
+
endWeek?: number; // Inclusive upper bound epoch/week
|
|
643
|
+
paymentCurrency?: PaymentCurrency; // Filter by payment currency
|
|
644
|
+
limit?: number; // Max rows to return (default 52, capped at 520)
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// ----------------------------- Region Weekly Rewards -------------------------
|
|
648
|
+
export interface RegionWeeklyReward {
|
|
649
|
+
weekNumber: number;
|
|
650
|
+
paymentCurrency: PaymentCurrency;
|
|
651
|
+
protocolDepositPaidTotal: string; // Total amount paid by all farms in region as protocol deposit
|
|
652
|
+
glowInflationTotal: string; // Total GLW inflation rewards allocated to region (18 decimals)
|
|
653
|
+
expectedProductionTotal: string; // Region's total weekly carbon credit production in WAD (18 decimals)
|
|
654
|
+
protocolDepositRewardsDistributed: string; // Always "0" for regions (tracked at farm level)
|
|
655
|
+
createdAt?: string; // ISO 8601
|
|
656
|
+
updatedAt?: string; // ISO 8601
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
export interface RegionWeeklyRewardsSummary {
|
|
660
|
+
totalProtocolDepositPaid: string;
|
|
661
|
+
totalGlowInflation: string;
|
|
662
|
+
totalExpectedProduction: string;
|
|
663
|
+
weeksActive: number;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export interface RegionWeeklyRewardsResponse {
|
|
667
|
+
regionId: number;
|
|
668
|
+
summary: RegionWeeklyRewardsSummary;
|
|
669
|
+
rewards: RegionWeeklyReward[];
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
export interface RegionWeeklyRewardsQuery {
|
|
673
|
+
startWeek?: number; // Inclusive lower bound epoch/week
|
|
674
|
+
endWeek?: number; // Inclusive upper bound epoch/week
|
|
675
|
+
paymentCurrency?: PaymentCurrency; // Filter by payment currency
|
|
676
|
+
limit?: number; // Max rows to return (default 52, capped at 520)
|
|
677
|
+
}
|
|
678
|
+
|
|
589
679
|
// ----------------------------- Farms Reward Score ---------------------------
|
|
590
680
|
export interface EstimateRewardScoreParams {
|
|
591
681
|
userId: string;
|