@glowlabs-org/utils 0.2.1 → 0.2.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.
@@ -0,0 +1,577 @@
1
+ import { ethers } from 'ethers';
2
+
3
+ const HUB_URL = "https://glow.org";
4
+ const GCA_URLS = ["http://95.217.194.59:35015"];
5
+
6
+ /**
7
+ * @dev This is actually not as intuitive as it seems.
8
+ * Glow actually has 18 decimals, but glow weight is based on the amount of protocol fees (USDC) that the farm paid
9
+ * Therefore, the weight is based on the amount of USDC that was paid, which has 8 decimals
10
+ */
11
+ const GLOW_WEIGHT_DECIMAL_PRECISION = 8;
12
+ /**
13
+ * @dev This is actually not as intuitive as it seems.
14
+ * USDG weight is based on the amount of carbon credits produced, but the max value of a weight is ((2*64)-1) / 5 so we need to choose sensible precision to make sure that number never overflows
15
+ */
16
+ const USDG_WEIGHT_DECIMAL_PRECISION = 8;
17
+ const MAX_WEIGHT = (BigInt(2) ** BigInt(64) - BigInt(1)) / BigInt(5);
18
+
19
+ const FORWARDER_ABI = [
20
+ {
21
+ inputs: [{ internalType: "address", name: "_forwarder", type: "address" }],
22
+ stateMutability: "nonpayable",
23
+ type: "constructor",
24
+ },
25
+ {
26
+ inputs: [{ internalType: "address", name: "target", type: "address" }],
27
+ name: "AddressEmptyCode",
28
+ type: "error",
29
+ },
30
+ {
31
+ inputs: [{ internalType: "address", name: "account", type: "address" }],
32
+ name: "AddressInsufficientBalance",
33
+ type: "error",
34
+ },
35
+ { inputs: [], name: "FailedInnerCall", type: "error" },
36
+ {
37
+ inputs: [{ internalType: "address", name: "token", type: "address" }],
38
+ name: "SafeERC20FailedOperation",
39
+ type: "error",
40
+ },
41
+ {
42
+ anonymous: false,
43
+ inputs: [
44
+ { indexed: true, internalType: "address", name: "from", type: "address" },
45
+ { indexed: true, internalType: "address", name: "to", type: "address" },
46
+ {
47
+ indexed: true,
48
+ internalType: "address",
49
+ name: "token",
50
+ type: "address",
51
+ },
52
+ {
53
+ indexed: false,
54
+ internalType: "uint256",
55
+ name: "amount",
56
+ type: "uint256",
57
+ },
58
+ {
59
+ indexed: false,
60
+ internalType: "string",
61
+ name: "message",
62
+ type: "string",
63
+ },
64
+ ],
65
+ name: "Forward",
66
+ type: "event",
67
+ },
68
+ {
69
+ inputs: [],
70
+ name: "FORWARD_ADDRESS",
71
+ outputs: [{ internalType: "address", name: "", type: "address" }],
72
+ stateMutability: "view",
73
+ type: "function",
74
+ },
75
+ {
76
+ inputs: [
77
+ { internalType: "address", name: "token", type: "address" },
78
+ { internalType: "address", name: "to", type: "address" },
79
+ { internalType: "uint256", name: "amount", type: "uint256" },
80
+ { internalType: "string", name: "message", type: "string" },
81
+ ],
82
+ name: "forward",
83
+ outputs: [],
84
+ stateMutability: "nonpayable",
85
+ type: "function",
86
+ },
87
+ ];
88
+
89
+ const ERC20_ABI = [
90
+ {
91
+ inputs: [
92
+ { name: "spender", type: "address" },
93
+ { name: "amount", type: "uint256" },
94
+ ],
95
+ name: "approve",
96
+ outputs: [{ name: "", type: "bool" }],
97
+ stateMutability: "nonpayable",
98
+ type: "function",
99
+ },
100
+ {
101
+ inputs: [
102
+ { name: "owner", type: "address" },
103
+ { name: "spender", type: "address" },
104
+ ],
105
+ name: "allowance",
106
+ outputs: [{ name: "", type: "uint256" }],
107
+ stateMutability: "view",
108
+ type: "function",
109
+ },
110
+ {
111
+ inputs: [
112
+ { name: "to", type: "address" },
113
+ { name: "amount", type: "uint256" },
114
+ ],
115
+ name: "transfer",
116
+ outputs: [{ name: "", type: "bool" }],
117
+ stateMutability: "nonpayable",
118
+ type: "function",
119
+ },
120
+ {
121
+ inputs: [{ name: "account", type: "address" }],
122
+ name: "balanceOf",
123
+ outputs: [{ name: "", type: "uint256" }],
124
+ stateMutability: "view",
125
+ type: "function",
126
+ },
127
+ {
128
+ inputs: [
129
+ { name: "account", type: "address" },
130
+ { name: "amount", type: "uint256" },
131
+ ],
132
+ name: "mint",
133
+ outputs: [{ name: "", type: "bool" }],
134
+ stateMutability: "nonpayable",
135
+ type: "function",
136
+ },
137
+ ];
138
+
139
+ // Contract-specific addresses
140
+ const mainnetAddresses = {
141
+ USDG: "0xe010ec500720bE9EF3F82129E7eD2Ee1FB7955F2",
142
+ GLW: "0xf4fbC617A5733EAAF9af08E1Ab816B103388d8B6",
143
+ USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
144
+ FORWARDER: "0x0000000000000000000000000000000000000000", // TODO: Update with actual mainnet address
145
+ FOUNDATION_WALLET: "0x0000000000000000000000000000000000000000", // TODO: Update with actual mainnet foundation wallet
146
+ };
147
+ const sepoliaAddresses = {
148
+ USDG: "0xda78313A3fF949890112c1B746AB1c75d1b1c17B",
149
+ GLW: "0x2039161fcE4C8e5CF5FE64e17Fd290E8dFF3c9BD",
150
+ USDC: "0x93c898be98cd2618ba84a6dccf5003d3bbe40356",
151
+ FORWARDER: "0x9c1d61303D46BFAb1eC5F25c12A1Bf4cB3d06416",
152
+ FOUNDATION_WALLET: "0x5e230FED487c86B90f6508104149F087d9B1B0A7",
153
+ };
154
+ const getAddresses = (CHAIN_ID) => {
155
+ switch (CHAIN_ID) {
156
+ case 1:
157
+ return mainnetAddresses;
158
+ case 11155111:
159
+ return sepoliaAddresses;
160
+ default:
161
+ console.warn(`Unsupported chain ID: ${CHAIN_ID}, falling back to mainnet addresses`);
162
+ return mainnetAddresses;
163
+ }
164
+ };
165
+ const DECIMALS_BY_TOKEN = {
166
+ USDC: 6,
167
+ USDG: 6,
168
+ GLW: 18,
169
+ };
170
+
171
+ var ForwarderError;
172
+ (function (ForwarderError) {
173
+ ForwarderError["CONTRACT_NOT_AVAILABLE"] = "Contract not available";
174
+ ForwarderError["SIGNER_NOT_AVAILABLE"] = "Signer not available";
175
+ ForwarderError["UNKNOWN_ERROR"] = "Unknown error";
176
+ ForwarderError["INVALID_FORWARD_TYPE"] = "Invalid forward type";
177
+ ForwarderError["MISSING_REQUIRED_PARAMS"] = "Missing required parameters";
178
+ })(ForwarderError || (ForwarderError = {}));
179
+ // Utility to extract the most useful revert reason from an ethers error object
180
+ function parseEthersError(error) {
181
+ if (!error)
182
+ return "Unknown error";
183
+ const possibleError = error;
184
+ // If the error originates from a callStatic it will often be found at `error?.error?.body`
185
+ if (possibleError?.error?.body) {
186
+ try {
187
+ const body = JSON.parse(possibleError.error.body);
188
+ // Hardhat style errors
189
+ if (body?.error?.message)
190
+ return body.error.message;
191
+ }
192
+ catch { }
193
+ }
194
+ // Found on MetaMask/Alchemy shape errors
195
+ if (possibleError?.data?.message)
196
+ return possibleError.data.message;
197
+ if (possibleError?.error?.message)
198
+ return possibleError.error.message;
199
+ // Standard ethers v5 message
200
+ if (possibleError?.reason)
201
+ return possibleError.reason;
202
+ if (possibleError?.message)
203
+ return possibleError.message;
204
+ return ForwarderError.UNKNOWN_ERROR;
205
+ }
206
+ // Type-guard style helper to ensure a signer exists throughout the rest of the function.
207
+ function assertSigner(maybeSigner) {
208
+ if (!maybeSigner) {
209
+ throw new Error(ForwarderError.SIGNER_NOT_AVAILABLE);
210
+ }
211
+ }
212
+ function useForwarder(signer, CHAIN_ID) {
213
+ // Use dynamic addresses based on chain configuration
214
+ const ADDRESSES = getAddresses(CHAIN_ID);
215
+ // Framework-agnostic processing flag
216
+ let isProcessing = false;
217
+ const setIsProcessing = (value) => {
218
+ isProcessing = value;
219
+ };
220
+ // Returns a contract instance for Forwarder
221
+ function getForwarderContract() {
222
+ assertSigner(signer);
223
+ return new ethers.Contract(ADDRESSES.FORWARDER, FORWARDER_ABI, signer);
224
+ }
225
+ /**
226
+ * Construct the message for the forward call based on type and parameters
227
+ */
228
+ function constructForwardMessage(params) {
229
+ const { type, applicationId, farmId, regionId, userAddress } = params;
230
+ switch (type) {
231
+ case "PayProtocolFeeAndMintGCTLAndStake":
232
+ if (!applicationId) {
233
+ throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
234
+ }
235
+ return `PayProtocolFeeAndMintGCTLAndStake::${applicationId}`;
236
+ case "PayProtocolFee":
237
+ if (!applicationId) {
238
+ throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
239
+ }
240
+ return `PayProtocolFee::${applicationId}`;
241
+ case "MintGCTLAndStake":
242
+ if (!regionId) {
243
+ throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
244
+ }
245
+ return `MintGCTLAndStake::${regionId}`;
246
+ case "MintGCTL":
247
+ if (!userAddress) {
248
+ throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
249
+ }
250
+ return `MintGCTL::${userAddress}`;
251
+ case "BuySolarFarm":
252
+ if (!farmId) {
253
+ throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
254
+ }
255
+ return `BuySolarFarm::${farmId}`;
256
+ default:
257
+ throw new Error(ForwarderError.INVALID_FORWARD_TYPE);
258
+ }
259
+ }
260
+ /**
261
+ * Get the appropriate token contract based on currency
262
+ */
263
+ function getTokenContract(currency = "USDC") {
264
+ assertSigner(signer);
265
+ let tokenAddress;
266
+ switch (currency) {
267
+ case "USDC":
268
+ tokenAddress = ADDRESSES.USDC;
269
+ break;
270
+ case "GLW":
271
+ tokenAddress = ADDRESSES.GLW;
272
+ break;
273
+ case "USDG":
274
+ tokenAddress = ADDRESSES.USDG;
275
+ break;
276
+ default:
277
+ throw new Error(`Currency ${currency} not yet supported. Only USDC, GLW, and USDG are currently supported.`);
278
+ }
279
+ return new ethers.Contract(tokenAddress, ERC20_ABI, signer);
280
+ }
281
+ /**
282
+ * Check current token allowance for the forwarder contract
283
+ * @param owner The wallet address to check allowance for
284
+ * @param currency The currency to check allowance for
285
+ */
286
+ async function checkTokenAllowance(owner, currency = "USDC") {
287
+ assertSigner(signer);
288
+ try {
289
+ const tokenContract = getTokenContract(currency);
290
+ if (!tokenContract)
291
+ throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);
292
+ const allowance = await tokenContract.allowance(owner, ADDRESSES.FORWARDER);
293
+ return allowance;
294
+ }
295
+ catch (error) {
296
+ throw new Error(parseEthersError(error));
297
+ }
298
+ }
299
+ /**
300
+ * Check user's token balance
301
+ * @param owner The wallet address to check balance for
302
+ * @param currency The currency to check balance for
303
+ */
304
+ async function checkTokenBalance(owner, currency = "USDC") {
305
+ assertSigner(signer);
306
+ try {
307
+ const tokenContract = getTokenContract(currency);
308
+ if (!tokenContract)
309
+ throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);
310
+ const balance = await tokenContract.balanceOf(owner);
311
+ return balance;
312
+ }
313
+ catch (error) {
314
+ throw new Error(parseEthersError(error));
315
+ }
316
+ }
317
+ /**
318
+ * Approve tokens for the forwarder contract
319
+ * @param amount Amount to approve (BigNumber)
320
+ * @param currency The currency to approve
321
+ */
322
+ async function approveToken(amount, currency = "USDC") {
323
+ assertSigner(signer);
324
+ try {
325
+ const tokenContract = getTokenContract(currency);
326
+ if (!tokenContract)
327
+ throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);
328
+ setIsProcessing(true);
329
+ // Approve only the specific amount needed
330
+ const approveTx = await tokenContract.approve(ADDRESSES.FORWARDER, amount);
331
+ await approveTx.wait();
332
+ return true;
333
+ }
334
+ catch (error) {
335
+ throw new Error(parseEthersError(error));
336
+ }
337
+ finally {
338
+ setIsProcessing(false);
339
+ }
340
+ }
341
+ /**
342
+ * Forward tokens through the forwarder contract with type-specific handling
343
+ * @param params Forward parameters including type, amount, and required fields
344
+ */
345
+ async function forwardTokens(params) {
346
+ assertSigner(signer);
347
+ try {
348
+ const forwarderContract = getForwarderContract();
349
+ if (!forwarderContract)
350
+ throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);
351
+ setIsProcessing(true);
352
+ const { amount, currency = "USDC" } = params;
353
+ const tokenContract = getTokenContract(currency);
354
+ if (!tokenContract)
355
+ throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);
356
+ const owner = await signer.getAddress();
357
+ // Construct the appropriate message for this forward type
358
+ const message = constructForwardMessage(params);
359
+ // Check allowance and approve if necessary
360
+ const allowance = await tokenContract.allowance(owner, ADDRESSES.FORWARDER);
361
+ if (allowance.lt(amount)) {
362
+ try {
363
+ const approveTx = await tokenContract.approve(ADDRESSES.FORWARDER, ethers.constants.MaxUint256);
364
+ await approveTx.wait();
365
+ }
366
+ catch (approveError) {
367
+ throw new Error(parseEthersError(approveError) || "Token approval failed");
368
+ }
369
+ }
370
+ // Get the token address based on currency
371
+ let tokenAddress;
372
+ switch (currency) {
373
+ case "USDC":
374
+ tokenAddress = ADDRESSES.USDC;
375
+ break;
376
+ case "USDG":
377
+ tokenAddress = ADDRESSES.USDG;
378
+ break;
379
+ case "GLW":
380
+ tokenAddress = ADDRESSES.GLW;
381
+ break;
382
+ default:
383
+ throw new Error(`Unsupported currency for forwarding: ${currency}`);
384
+ }
385
+ // Run a static call first to surface any revert reason
386
+ try {
387
+ await forwarderContract.callStatic.forward(tokenAddress, ADDRESSES.FOUNDATION_WALLET, amount, message, { from: owner });
388
+ }
389
+ catch (staticError) {
390
+ throw new Error(parseEthersError(staticError));
391
+ }
392
+ // Execute the forward transaction
393
+ const tx = await forwarderContract.forward(tokenAddress, ADDRESSES.FOUNDATION_WALLET, amount, message);
394
+ await tx.wait();
395
+ return tx.hash;
396
+ }
397
+ catch (txError) {
398
+ throw new Error(parseEthersError(txError));
399
+ }
400
+ finally {
401
+ setIsProcessing(false);
402
+ }
403
+ }
404
+ /**
405
+ * Forward tokens for protocol fee payment and GCTL minting with staking
406
+ */
407
+ async function payProtocolFeeAndMintGCTLAndStake(amount, userAddress, applicationId, regionId, currency = "USDC") {
408
+ assertSigner(signer);
409
+ // GCTL minting only supports USDC and USDG
410
+ if (currency === "GLW") {
411
+ throw new Error("GCTL minting is not supported with GLW payment. Use USDC or USDG.");
412
+ }
413
+ return forwardTokens({
414
+ amount,
415
+ userAddress,
416
+ type: "PayProtocolFeeAndMintGCTLAndStake",
417
+ currency,
418
+ applicationId,
419
+ regionId,
420
+ });
421
+ }
422
+ /**
423
+ * Forward tokens for protocol fee payment only
424
+ */
425
+ async function payProtocolFee(amount, userAddress, applicationId, currency = "USDC") {
426
+ assertSigner(signer);
427
+ return forwardTokens({
428
+ amount,
429
+ userAddress,
430
+ type: "PayProtocolFee",
431
+ currency,
432
+ applicationId,
433
+ });
434
+ }
435
+ /**
436
+ * Forward USDC to mint GCTL and stake to a region
437
+ */
438
+ async function mintGCTLAndStake(amount, userAddress, regionId) {
439
+ assertSigner(signer);
440
+ return forwardTokens({
441
+ amount,
442
+ userAddress,
443
+ type: "MintGCTLAndStake",
444
+ currency: "USDC",
445
+ regionId,
446
+ });
447
+ }
448
+ /**
449
+ * Forward USDC to mint GCTL (existing functionality, keeping for compatibility)
450
+ */
451
+ async function mintGCTL(amount, userAddress) {
452
+ assertSigner(signer);
453
+ return forwardTokens({
454
+ amount,
455
+ userAddress,
456
+ type: "MintGCTL",
457
+ currency: "USDC",
458
+ });
459
+ }
460
+ /**
461
+ * Forward tokens to buy a solar farm
462
+ */
463
+ async function buySolarFarm(amount, userAddress, farmId, currency = "USDC") {
464
+ assertSigner(signer);
465
+ return forwardTokens({
466
+ amount,
467
+ userAddress,
468
+ type: "BuySolarFarm",
469
+ currency,
470
+ farmId,
471
+ });
472
+ }
473
+ /**
474
+ * Estimate gas for forwarding with type-specific handling
475
+ * @param params Forward parameters
476
+ * @param ethPriceInUSD Current ETH price in USD (for cost estimation)
477
+ */
478
+ async function estimateGasForForward(params, ethPriceInUSD) {
479
+ assertSigner(signer);
480
+ try {
481
+ const forwarderContract = getForwarderContract();
482
+ if (!forwarderContract)
483
+ throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);
484
+ const { amount, currency = "USDC" } = params;
485
+ // Construct the appropriate message for this forward type
486
+ const message = constructForwardMessage(params);
487
+ // Get token address
488
+ let tokenAddress;
489
+ switch (currency) {
490
+ case "USDC":
491
+ tokenAddress = ADDRESSES.USDC;
492
+ break;
493
+ case "USDG":
494
+ tokenAddress = ADDRESSES.USDG;
495
+ break;
496
+ case "GLW":
497
+ tokenAddress = ADDRESSES.GLW;
498
+ break;
499
+ default:
500
+ throw new Error(`Unsupported currency for gas estimation: ${currency}`);
501
+ }
502
+ const gasPrice = await signer.getGasPrice();
503
+ const estimatedGas = await forwarderContract.estimateGas.forward(tokenAddress, ADDRESSES.FOUNDATION_WALLET, amount, message);
504
+ const estimatedCost = estimatedGas.mul(gasPrice);
505
+ if (ethPriceInUSD) {
506
+ const estimatedCostInEth = ethers.utils.formatEther(estimatedCost);
507
+ const estimatedCostInUSD = (parseFloat(estimatedCostInEth) * ethPriceInUSD).toFixed(2);
508
+ return estimatedCostInUSD;
509
+ }
510
+ else {
511
+ throw new Error("Could not fetch the ETH price to calculate cost in USD.");
512
+ }
513
+ }
514
+ catch (error) {
515
+ throw new Error(parseEthersError(error));
516
+ }
517
+ }
518
+ /**
519
+ * Mint test USDC (only works on testnets with mintable USDC contracts)
520
+ * @param amount Amount of USDC to mint (BigNumber, 6 decimals)
521
+ * @param recipient Address to mint USDC to
522
+ */
523
+ async function mintTestUSDC(amount, recipient) {
524
+ assertSigner(signer);
525
+ if (CHAIN_ID !== 11155111) {
526
+ throw new Error("Minting test USDC is only supported on Sepolia");
527
+ }
528
+ try {
529
+ const usdcContract = getTokenContract("USDC"); // Use getTokenContract for consistency
530
+ if (!usdcContract)
531
+ throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);
532
+ setIsProcessing(true);
533
+ // Try to call mint function (common for test tokens)
534
+ const tx = await usdcContract.mint(recipient, amount);
535
+ await tx.wait();
536
+ return tx.hash;
537
+ }
538
+ catch (error) {
539
+ // If mint function doesn't exist or fails, provide helpful error
540
+ const errorMessage = parseEthersError(error);
541
+ if (errorMessage.includes("mint")) {
542
+ throw new Error("This USDC contract doesn't support minting");
543
+ }
544
+ throw new Error(errorMessage);
545
+ }
546
+ finally {
547
+ setIsProcessing(false);
548
+ }
549
+ }
550
+ return {
551
+ // New methods for different forward types
552
+ forwardTokens,
553
+ payProtocolFeeAndMintGCTLAndStake,
554
+ payProtocolFee,
555
+ mintGCTLAndStake,
556
+ mintGCTL,
557
+ buySolarFarm,
558
+ // Token operations
559
+ approveToken,
560
+ checkTokenAllowance,
561
+ checkTokenBalance,
562
+ // Utility methods
563
+ estimateGasForForward,
564
+ mintTestUSDC,
565
+ constructForwardMessage,
566
+ // State
567
+ get isProcessing() {
568
+ return isProcessing;
569
+ },
570
+ addresses: ADDRESSES,
571
+ // Signer availability
572
+ isSignerAvailable: !!signer,
573
+ };
574
+ }
575
+
576
+ export { DECIMALS_BY_TOKEN as D, ForwarderError as F, GLOW_WEIGHT_DECIMAL_PRECISION as G, HUB_URL as H, MAX_WEIGHT as M, USDG_WEIGHT_DECIMAL_PRECISION as U, GCA_URLS as a, getAddresses as g, useForwarder as u };
577
+ //# sourceMappingURL=use-forwarder-DD_5ZFZg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-forwarder-DD_5ZFZg.js","sources":["../../src/constants/urls.ts","../../src/constants/weights.ts","../../src/lib/abis/forwarderABI.ts","../../src/lib/abis/erc20.abi.ts","../../src/constants/addresses.ts","../../src/lib/hooks/use-forwarder.ts"],"sourcesContent":["export const HUB_URL = \"https://glow.org\";\n\nexport const GCA_URLS = [\"http://95.217.194.59:35015\"];\n","/**\n * @dev This is actually not as intuitive as it seems.\n * Glow actually has 18 decimals, but glow weight is based on the amount of protocol fees (USDC) that the farm paid\n * Therefore, the weight is based on the amount of USDC that was paid, which has 8 decimals\n */\nexport const GLOW_WEIGHT_DECIMAL_PRECISION = 8;\n\n/**\n * @dev This is actually not as intuitive as it seems.\n * USDG weight is based on the amount of carbon credits produced, but the max value of a weight is ((2*64)-1) / 5 so we need to choose sensible precision to make sure that number never overflows\n */\nexport const USDG_WEIGHT_DECIMAL_PRECISION = 8;\n\nexport const MAX_WEIGHT: bigint =\n (BigInt(2) ** BigInt(64) - BigInt(1)) / BigInt(5);\n","export const FORWARDER_ABI = [\n {\n inputs: [{ internalType: \"address\", name: \"_forwarder\", type: \"address\" }],\n stateMutability: \"nonpayable\",\n type: \"constructor\",\n },\n {\n inputs: [{ internalType: \"address\", name: \"target\", type: \"address\" }],\n name: \"AddressEmptyCode\",\n type: \"error\",\n },\n {\n inputs: [{ internalType: \"address\", name: \"account\", type: \"address\" }],\n name: \"AddressInsufficientBalance\",\n type: \"error\",\n },\n { inputs: [], name: \"FailedInnerCall\", type: \"error\" },\n {\n inputs: [{ internalType: \"address\", name: \"token\", type: \"address\" }],\n name: \"SafeERC20FailedOperation\",\n type: \"error\",\n },\n {\n anonymous: false,\n inputs: [\n { indexed: true, internalType: \"address\", name: \"from\", type: \"address\" },\n { indexed: true, internalType: \"address\", name: \"to\", type: \"address\" },\n {\n indexed: true,\n internalType: \"address\",\n name: \"token\",\n type: \"address\",\n },\n {\n indexed: false,\n internalType: \"uint256\",\n name: \"amount\",\n type: \"uint256\",\n },\n {\n indexed: false,\n internalType: \"string\",\n name: \"message\",\n type: \"string\",\n },\n ],\n name: \"Forward\",\n type: \"event\",\n },\n {\n inputs: [],\n name: \"FORWARD_ADDRESS\",\n outputs: [{ internalType: \"address\", name: \"\", type: \"address\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [\n { internalType: \"address\", name: \"token\", type: \"address\" },\n { internalType: \"address\", name: \"to\", type: \"address\" },\n { internalType: \"uint256\", name: \"amount\", type: \"uint256\" },\n { internalType: \"string\", name: \"message\", type: \"string\" },\n ],\n name: \"forward\",\n outputs: [],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n] as const;\n","export const ERC20_ABI = [\n {\n inputs: [\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n name: \"approve\",\n outputs: [{ name: \"\", type: \"bool\" }],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n {\n inputs: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n ],\n name: \"allowance\",\n outputs: [{ name: \"\", type: \"uint256\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [\n { name: \"to\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n name: \"transfer\",\n outputs: [{ name: \"\", type: \"bool\" }],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n {\n inputs: [{ name: \"account\", type: \"address\" }],\n name: \"balanceOf\",\n outputs: [{ name: \"\", type: \"uint256\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [\n { name: \"account\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n name: \"mint\",\n outputs: [{ name: \"\", type: \"bool\" }],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n];\n","type ContractKeys = \"USDC\" | \"FORWARDER\" | \"FOUNDATION_WALLET\" | \"GLW\" | \"USDG\";\n\n// Contract-specific addresses\nconst mainnetAddresses: Record<ContractKeys, `0x${string}`> = {\n USDG: \"0xe010ec500720bE9EF3F82129E7eD2Ee1FB7955F2\",\n GLW: \"0xf4fbC617A5733EAAF9af08E1Ab816B103388d8B6\",\n USDC: \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n FORWARDER: \"0x0000000000000000000000000000000000000000\", // TODO: Update with actual mainnet address\n FOUNDATION_WALLET: \"0x0000000000000000000000000000000000000000\", // TODO: Update with actual mainnet foundation wallet\n};\n\nconst sepoliaAddresses: Record<ContractKeys, `0x${string}`> = {\n USDG: \"0xda78313A3fF949890112c1B746AB1c75d1b1c17B\",\n GLW: \"0x2039161fcE4C8e5CF5FE64e17Fd290E8dFF3c9BD\",\n USDC: \"0x93c898be98cd2618ba84a6dccf5003d3bbe40356\",\n FORWARDER: \"0x9c1d61303D46BFAb1eC5F25c12A1Bf4cB3d06416\",\n FOUNDATION_WALLET: \"0x5e230FED487c86B90f6508104149F087d9B1B0A7\",\n};\n\nexport const getAddresses = (\n CHAIN_ID: number\n): Record<ContractKeys, `0x${string}`> => {\n switch (CHAIN_ID) {\n case 1:\n return mainnetAddresses;\n case 11155111:\n return sepoliaAddresses;\n default:\n console.warn(\n `Unsupported chain ID: ${CHAIN_ID}, falling back to mainnet addresses`\n );\n return mainnetAddresses;\n }\n};\n\nexport const DECIMALS_BY_TOKEN: Record<string, number> = {\n USDC: 6,\n USDG: 6,\n GLW: 18,\n};\n","import { BigNumber, ethers } from \"ethers\";\nimport { FORWARDER_ABI } from \"../abis/forwarderABI\";\nimport { ERC20_ABI } from \"../abis/erc20.abi\";\nimport { getAddresses } from \"../../constants/addresses\";\n\nexport enum ForwarderError {\n CONTRACT_NOT_AVAILABLE = \"Contract not available\",\n SIGNER_NOT_AVAILABLE = \"Signer not available\",\n UNKNOWN_ERROR = \"Unknown error\",\n INVALID_FORWARD_TYPE = \"Invalid forward type\",\n MISSING_REQUIRED_PARAMS = \"Missing required parameters\",\n}\n\n// Forward types based on API router documentation\nexport type ForwardType =\n | \"PayProtocolFeeAndMintGCTLAndStake\"\n | \"PayProtocolFee\"\n | \"MintGCTLAndStake\"\n | \"MintGCTL\"\n | \"BuySolarFarm\";\n\n// Currency types\nexport type Currency = \"USDC\" | \"GLW\" | \"USDG\";\n\n// Forward parameters interface\nexport interface ForwardParams {\n amount: BigNumber;\n userAddress: string;\n type: ForwardType;\n currency?: Currency;\n applicationId?: string;\n farmId?: string;\n regionId?: number;\n}\n\n// Utility to extract the most useful revert reason from an ethers error object\nfunction parseEthersError(error: unknown): string {\n if (!error) return \"Unknown error\";\n const possibleError: any = error;\n\n // If the error originates from a callStatic it will often be found at `error?.error?.body`\n if (possibleError?.error?.body) {\n try {\n const body = JSON.parse(possibleError.error.body);\n // Hardhat style errors\n if (body?.error?.message) return body.error.message as string;\n } catch {}\n }\n\n // Found on MetaMask/Alchemy shape errors\n if (possibleError?.data?.message) return possibleError.data.message as string;\n if (possibleError?.error?.message)\n return possibleError.error.message as string;\n\n // Standard ethers v5 message\n if (possibleError?.reason) return possibleError.reason as string;\n if (possibleError?.message) return possibleError.message as string;\n\n return ForwarderError.UNKNOWN_ERROR;\n}\n\n// Type-guard style helper to ensure a signer exists throughout the rest of the function.\nfunction assertSigner(\n maybeSigner: ethers.providers.JsonRpcSigner | undefined\n): asserts maybeSigner is ethers.providers.JsonRpcSigner {\n if (!maybeSigner) {\n throw new Error(ForwarderError.SIGNER_NOT_AVAILABLE);\n }\n}\n\nexport function useForwarder(\n signer: ethers.providers.JsonRpcSigner | undefined,\n CHAIN_ID: number\n) {\n // Use dynamic addresses based on chain configuration\n const ADDRESSES = getAddresses(CHAIN_ID);\n\n // Framework-agnostic processing flag\n let isProcessing = false;\n const setIsProcessing = (value: boolean) => {\n isProcessing = value;\n };\n\n // Returns a contract instance for Forwarder\n function getForwarderContract() {\n assertSigner(signer);\n return new ethers.Contract(ADDRESSES.FORWARDER, FORWARDER_ABI, signer);\n }\n\n /**\n * Construct the message for the forward call based on type and parameters\n */\n function constructForwardMessage(params: ForwardParams): string {\n const { type, applicationId, farmId, regionId, userAddress } = params;\n\n switch (type) {\n case \"PayProtocolFeeAndMintGCTLAndStake\":\n if (!applicationId) {\n throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);\n }\n return `PayProtocolFeeAndMintGCTLAndStake::${applicationId}`;\n\n case \"PayProtocolFee\":\n if (!applicationId) {\n throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);\n }\n return `PayProtocolFee::${applicationId}`;\n\n case \"MintGCTLAndStake\":\n if (!regionId) {\n throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);\n }\n return `MintGCTLAndStake::${regionId}`;\n\n case \"MintGCTL\":\n if (!userAddress) {\n throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);\n }\n return `MintGCTL::${userAddress}`;\n\n case \"BuySolarFarm\":\n if (!farmId) {\n throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);\n }\n return `BuySolarFarm::${farmId}`;\n\n default:\n throw new Error(ForwarderError.INVALID_FORWARD_TYPE);\n }\n }\n\n /**\n * Get the appropriate token contract based on currency\n */\n function getTokenContract(currency: Currency = \"USDC\") {\n assertSigner(signer);\n\n let tokenAddress: string;\n switch (currency) {\n case \"USDC\":\n tokenAddress = ADDRESSES.USDC;\n break;\n case \"GLW\":\n tokenAddress = ADDRESSES.GLW;\n break;\n case \"USDG\":\n tokenAddress = ADDRESSES.USDG;\n break;\n default:\n throw new Error(\n `Currency ${currency} not yet supported. Only USDC, GLW, and USDG are currently supported.`\n );\n }\n\n return new ethers.Contract(tokenAddress, ERC20_ABI, signer);\n }\n\n /**\n * Check current token allowance for the forwarder contract\n * @param owner The wallet address to check allowance for\n * @param currency The currency to check allowance for\n */\n async function checkTokenAllowance(\n owner: string,\n currency: Currency = \"USDC\"\n ): Promise<BigNumber> {\n assertSigner(signer);\n\n try {\n const tokenContract = getTokenContract(currency);\n if (!tokenContract)\n throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);\n\n const allowance: BigNumber = await tokenContract.allowance(\n owner,\n ADDRESSES.FORWARDER\n );\n return allowance;\n } catch (error) {\n throw new Error(parseEthersError(error));\n }\n }\n\n /**\n * Check user's token balance\n * @param owner The wallet address to check balance for\n * @param currency The currency to check balance for\n */\n async function checkTokenBalance(\n owner: string,\n currency: Currency = \"USDC\"\n ): Promise<BigNumber> {\n assertSigner(signer);\n\n try {\n const tokenContract = getTokenContract(currency);\n if (!tokenContract)\n throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);\n\n const balance: BigNumber = await tokenContract.balanceOf(owner);\n return balance;\n } catch (error) {\n throw new Error(parseEthersError(error));\n }\n }\n\n /**\n * Approve tokens for the forwarder contract\n * @param amount Amount to approve (BigNumber)\n * @param currency The currency to approve\n */\n async function approveToken(\n amount: BigNumber,\n currency: Currency = \"USDC\"\n ): Promise<boolean> {\n assertSigner(signer);\n\n try {\n const tokenContract = getTokenContract(currency);\n if (!tokenContract)\n throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);\n\n setIsProcessing(true);\n\n // Approve only the specific amount needed\n const approveTx = await tokenContract.approve(\n ADDRESSES.FORWARDER,\n amount\n );\n await approveTx.wait();\n\n return true;\n } catch (error) {\n throw new Error(parseEthersError(error));\n } finally {\n setIsProcessing(false);\n }\n }\n\n /**\n * Forward tokens through the forwarder contract with type-specific handling\n * @param params Forward parameters including type, amount, and required fields\n */\n async function forwardTokens(params: ForwardParams): Promise<string> {\n assertSigner(signer);\n\n try {\n const forwarderContract = getForwarderContract();\n if (!forwarderContract)\n throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);\n\n setIsProcessing(true);\n\n const { amount, currency = \"USDC\" } = params;\n const tokenContract = getTokenContract(currency);\n if (!tokenContract)\n throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);\n\n const owner = await signer.getAddress();\n\n // Construct the appropriate message for this forward type\n const message = constructForwardMessage(params);\n\n // Check allowance and approve if necessary\n const allowance: BigNumber = await tokenContract.allowance(\n owner,\n ADDRESSES.FORWARDER\n );\n\n if (allowance.lt(amount)) {\n try {\n const approveTx = await tokenContract.approve(\n ADDRESSES.FORWARDER,\n ethers.constants.MaxUint256\n );\n await approveTx.wait();\n } catch (approveError) {\n throw new Error(\n parseEthersError(approveError) || \"Token approval failed\"\n );\n }\n }\n\n // Get the token address based on currency\n let tokenAddress: string;\n switch (currency) {\n case \"USDC\":\n tokenAddress = ADDRESSES.USDC;\n break;\n case \"USDG\":\n tokenAddress = ADDRESSES.USDG;\n break;\n case \"GLW\":\n tokenAddress = ADDRESSES.GLW;\n break;\n default:\n throw new Error(`Unsupported currency for forwarding: ${currency}`);\n }\n\n // Run a static call first to surface any revert reason\n try {\n await forwarderContract.callStatic.forward(\n tokenAddress,\n ADDRESSES.FOUNDATION_WALLET,\n amount,\n message,\n { from: owner }\n );\n } catch (staticError) {\n throw new Error(parseEthersError(staticError));\n }\n\n // Execute the forward transaction\n const tx = await forwarderContract.forward(\n tokenAddress,\n ADDRESSES.FOUNDATION_WALLET,\n amount,\n message\n );\n await tx.wait();\n\n return tx.hash;\n } catch (txError: any) {\n throw new Error(parseEthersError(txError));\n } finally {\n setIsProcessing(false);\n }\n }\n\n /**\n * Forward tokens for protocol fee payment and GCTL minting with staking\n */\n async function payProtocolFeeAndMintGCTLAndStake(\n amount: BigNumber,\n userAddress: string,\n applicationId: string,\n regionId?: number,\n currency: Currency = \"USDC\"\n ): Promise<string> {\n assertSigner(signer);\n\n // GCTL minting only supports USDC and USDG\n if (currency === \"GLW\") {\n throw new Error(\n \"GCTL minting is not supported with GLW payment. Use USDC or USDG.\"\n );\n }\n\n return forwardTokens({\n amount,\n userAddress,\n type: \"PayProtocolFeeAndMintGCTLAndStake\",\n currency,\n applicationId,\n regionId,\n });\n }\n\n /**\n * Forward tokens for protocol fee payment only\n */\n async function payProtocolFee(\n amount: BigNumber,\n userAddress: string,\n applicationId: string,\n currency: Currency = \"USDC\"\n ): Promise<string> {\n assertSigner(signer);\n\n return forwardTokens({\n amount,\n userAddress,\n type: \"PayProtocolFee\",\n currency,\n applicationId,\n });\n }\n\n /**\n * Forward USDC to mint GCTL and stake to a region\n */\n async function mintGCTLAndStake(\n amount: BigNumber,\n userAddress: string,\n regionId?: number\n ): Promise<string> {\n assertSigner(signer);\n\n return forwardTokens({\n amount,\n userAddress,\n type: \"MintGCTLAndStake\",\n currency: \"USDC\",\n regionId,\n });\n }\n\n /**\n * Forward USDC to mint GCTL (existing functionality, keeping for compatibility)\n */\n async function mintGCTL(\n amount: BigNumber,\n userAddress: string\n ): Promise<string> {\n assertSigner(signer);\n\n return forwardTokens({\n amount,\n userAddress,\n type: \"MintGCTL\",\n currency: \"USDC\",\n });\n }\n\n /**\n * Forward tokens to buy a solar farm\n */\n async function buySolarFarm(\n amount: BigNumber,\n userAddress: string,\n farmId: string,\n currency: Currency = \"USDC\"\n ): Promise<string> {\n assertSigner(signer);\n\n return forwardTokens({\n amount,\n userAddress,\n type: \"BuySolarFarm\",\n currency,\n farmId,\n });\n }\n\n /**\n * Estimate gas for forwarding with type-specific handling\n * @param params Forward parameters\n * @param ethPriceInUSD Current ETH price in USD (for cost estimation)\n */\n async function estimateGasForForward(\n params: ForwardParams,\n ethPriceInUSD: number | null\n ): Promise<string> {\n assertSigner(signer);\n\n try {\n const forwarderContract = getForwarderContract();\n if (!forwarderContract)\n throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);\n\n const { amount, currency = \"USDC\" } = params;\n\n // Construct the appropriate message for this forward type\n const message = constructForwardMessage(params);\n\n // Get token address\n let tokenAddress: string;\n switch (currency) {\n case \"USDC\":\n tokenAddress = ADDRESSES.USDC;\n break;\n case \"USDG\":\n tokenAddress = ADDRESSES.USDG;\n break;\n case \"GLW\":\n tokenAddress = ADDRESSES.GLW;\n break;\n default:\n throw new Error(\n `Unsupported currency for gas estimation: ${currency}`\n );\n }\n\n const gasPrice = await signer.getGasPrice();\n const estimatedGas = await forwarderContract.estimateGas.forward(\n tokenAddress,\n ADDRESSES.FOUNDATION_WALLET,\n amount,\n message\n );\n const estimatedCost = estimatedGas.mul(gasPrice);\n\n if (ethPriceInUSD) {\n const estimatedCostInEth = ethers.utils.formatEther(estimatedCost);\n const estimatedCostInUSD = (\n parseFloat(estimatedCostInEth) * ethPriceInUSD\n ).toFixed(2);\n return estimatedCostInUSD;\n } else {\n throw new Error(\n \"Could not fetch the ETH price to calculate cost in USD.\"\n );\n }\n } catch (error: any) {\n throw new Error(parseEthersError(error));\n }\n }\n\n /**\n * Mint test USDC (only works on testnets with mintable USDC contracts)\n * @param amount Amount of USDC to mint (BigNumber, 6 decimals)\n * @param recipient Address to mint USDC to\n */\n async function mintTestUSDC(\n amount: BigNumber,\n recipient: string\n ): Promise<string> {\n assertSigner(signer);\n if (CHAIN_ID !== 11155111) {\n throw new Error(\"Minting test USDC is only supported on Sepolia\");\n }\n\n try {\n const usdcContract = getTokenContract(\"USDC\"); // Use getTokenContract for consistency\n if (!usdcContract) throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);\n\n setIsProcessing(true);\n\n // Try to call mint function (common for test tokens)\n const tx = await usdcContract.mint(recipient, amount);\n await tx.wait();\n\n return tx.hash;\n } catch (error: any) {\n // If mint function doesn't exist or fails, provide helpful error\n const errorMessage = parseEthersError(error);\n if (errorMessage.includes(\"mint\")) {\n throw new Error(\"This USDC contract doesn't support minting\");\n }\n throw new Error(errorMessage);\n } finally {\n setIsProcessing(false);\n }\n }\n\n return {\n // New methods for different forward types\n forwardTokens,\n payProtocolFeeAndMintGCTLAndStake,\n payProtocolFee,\n mintGCTLAndStake,\n mintGCTL,\n buySolarFarm,\n\n // Token operations\n approveToken,\n checkTokenAllowance,\n checkTokenBalance,\n\n // Utility methods\n estimateGasForForward,\n mintTestUSDC,\n constructForwardMessage,\n\n // State\n get isProcessing() {\n return isProcessing;\n },\n addresses: ADDRESSES,\n\n // Signer availability\n isSignerAvailable: !!signer,\n };\n}\n"],"names":[],"mappings":"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"}