@glowlabs-org/utils 0.2.92 → 0.2.94
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/dist/cjs/browser.js +675 -636
- package/dist/cjs/browser.js.map +1 -1
- package/dist/cjs/constants/addresses.d.ts +1 -1
- package/dist/cjs/{farms-router-ClIWm9AQ.js → farms-router-pMZv3N9H.js} +107 -29
- package/dist/cjs/farms-router-pMZv3N9H.js.map +1 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/lib/abis/forwarderABI.d.ts +22 -0
- package/dist/cjs/lib/control-api/control-router.d.ts +16 -0
- package/dist/cjs/lib/types/index.d.ts +13 -2
- package/dist/cjs/utils/stake-control.d.ts +33 -0
- package/dist/esm/browser.js +669 -633
- package/dist/esm/browser.js.map +1 -1
- package/dist/esm/constants/addresses.d.ts +1 -1
- package/dist/esm/{farms-router-DVSHNqsT.js → farms-router-sm5H9Ax6.js} +105 -30
- package/dist/esm/farms-router-sm5H9Ax6.js.map +1 -0
- package/dist/esm/index.js +2 -2
- package/dist/esm/lib/abis/forwarderABI.d.ts +22 -0
- package/dist/esm/lib/control-api/control-router.d.ts +16 -0
- package/dist/esm/lib/types/index.d.ts +13 -2
- package/dist/esm/utils/stake-control.d.ts +33 -0
- package/package.json +1 -1
- package/src/constants/addresses.ts +3 -2
- package/src/lib/abis/forwarderABI.ts +28 -0
- package/src/lib/control-api/control-router.ts +43 -0
- package/src/lib/hooks/use-forwarder.ts +29 -24
- package/src/lib/types/index.ts +15 -12
- package/src/utils/stake-control.ts +82 -1
- package/dist/cjs/farms-router-ClIWm9AQ.js.map +0 -1
- package/dist/esm/farms-router-DVSHNqsT.js.map +0 -1
|
@@ -3,6 +3,11 @@ export const FORWARDER_ABI = [
|
|
|
3
3
|
inputs: [
|
|
4
4
|
{ internalType: "contract USDG", name: "_usdg", type: "address" },
|
|
5
5
|
{ internalType: "contract IERC20", name: "_usdc", type: "address" },
|
|
6
|
+
{
|
|
7
|
+
internalType: "contract CounterfactualHolderFactory",
|
|
8
|
+
name: "_cfhFactory",
|
|
9
|
+
type: "address",
|
|
10
|
+
},
|
|
6
11
|
],
|
|
7
12
|
stateMutability: "payable",
|
|
8
13
|
type: "constructor",
|
|
@@ -58,6 +63,11 @@ export const FORWARDER_ABI = [
|
|
|
58
63
|
{ internalType: "address", name: "token", type: "address" },
|
|
59
64
|
{ internalType: "address", name: "to", type: "address" },
|
|
60
65
|
{ internalType: "uint256", name: "amount", type: "uint256" },
|
|
66
|
+
{
|
|
67
|
+
internalType: "bool",
|
|
68
|
+
name: "sendToCounterfactualWallet",
|
|
69
|
+
type: "bool",
|
|
70
|
+
},
|
|
61
71
|
{ internalType: "string", name: "message", type: "string" },
|
|
62
72
|
],
|
|
63
73
|
name: "forward",
|
|
@@ -65,6 +75,19 @@ export const FORWARDER_ABI = [
|
|
|
65
75
|
stateMutability: "nonpayable",
|
|
66
76
|
type: "function",
|
|
67
77
|
},
|
|
78
|
+
{
|
|
79
|
+
inputs: [],
|
|
80
|
+
name: "i_CFHFactory",
|
|
81
|
+
outputs: [
|
|
82
|
+
{
|
|
83
|
+
internalType: "contract CounterfactualHolderFactory",
|
|
84
|
+
name: "",
|
|
85
|
+
type: "address",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
stateMutability: "view",
|
|
89
|
+
type: "function",
|
|
90
|
+
},
|
|
68
91
|
{
|
|
69
92
|
inputs: [],
|
|
70
93
|
name: "i_USDC",
|
|
@@ -90,6 +113,11 @@ export const FORWARDER_ABI = [
|
|
|
90
113
|
inputs: [
|
|
91
114
|
{ internalType: "uint256", name: "amount", type: "uint256" },
|
|
92
115
|
{ internalType: "address", name: "to", type: "address" },
|
|
116
|
+
{
|
|
117
|
+
internalType: "bool",
|
|
118
|
+
name: "sendToCounterfactualWallet",
|
|
119
|
+
type: "bool",
|
|
120
|
+
},
|
|
93
121
|
{ internalType: "string", name: "message", type: "string" },
|
|
94
122
|
],
|
|
95
123
|
name: "swapUSDCAndForwardUSDG",
|
|
@@ -19,6 +19,22 @@ import type {
|
|
|
19
19
|
RestakeRequest,
|
|
20
20
|
} from "../types";
|
|
21
21
|
|
|
22
|
+
export interface PayProtocolDepositUsingStakedControlRequest {
|
|
23
|
+
wallet: string;
|
|
24
|
+
regionId: number;
|
|
25
|
+
applicationId: string;
|
|
26
|
+
amount: string;
|
|
27
|
+
signature: string;
|
|
28
|
+
deadline: string;
|
|
29
|
+
nonce: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface PayProtocolDepositUsingStakedControlResponse {
|
|
33
|
+
success: true;
|
|
34
|
+
farmId: string;
|
|
35
|
+
applicationId: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
22
38
|
// --------------------------------------------------------------------------
|
|
23
39
|
|
|
24
40
|
/**
|
|
@@ -229,6 +245,7 @@ export function ControlRouter(baseUrl: string) {
|
|
|
229
245
|
let isUnstaking = false;
|
|
230
246
|
let isRestaking = false;
|
|
231
247
|
let isRetryingFailedOperation = false;
|
|
248
|
+
let isPayingProtocolDepositUsingStakedControl = false;
|
|
232
249
|
|
|
233
250
|
const stakeGctl = async (stakeRequest: StakeRequest): Promise<boolean> => {
|
|
234
251
|
isStaking = true;
|
|
@@ -299,6 +316,28 @@ export function ControlRouter(baseUrl: string) {
|
|
|
299
316
|
}
|
|
300
317
|
};
|
|
301
318
|
|
|
319
|
+
const payProtocolDepositUsingStakedControl = async (
|
|
320
|
+
paymentRequest: PayProtocolDepositUsingStakedControlRequest
|
|
321
|
+
): Promise<PayProtocolDepositUsingStakedControlResponse> => {
|
|
322
|
+
isPayingProtocolDepositUsingStakedControl = true;
|
|
323
|
+
try {
|
|
324
|
+
const response =
|
|
325
|
+
await request<PayProtocolDepositUsingStakedControlResponse>(
|
|
326
|
+
`/pay-protocol-deposit-staked`,
|
|
327
|
+
{
|
|
328
|
+
method: "POST",
|
|
329
|
+
headers: { "Content-Type": "application/json" },
|
|
330
|
+
body: JSON.stringify(paymentRequest),
|
|
331
|
+
}
|
|
332
|
+
);
|
|
333
|
+
return response;
|
|
334
|
+
} catch (error) {
|
|
335
|
+
throw new Error(parseApiError(error));
|
|
336
|
+
} finally {
|
|
337
|
+
isPayingProtocolDepositUsingStakedControl = false;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
302
341
|
// --------------------------- Public API ----------------------------------
|
|
303
342
|
return {
|
|
304
343
|
// Queries
|
|
@@ -322,6 +361,7 @@ export function ControlRouter(baseUrl: string) {
|
|
|
322
361
|
unstakeGctl,
|
|
323
362
|
restakeGctl,
|
|
324
363
|
retryFailedOperation,
|
|
364
|
+
payProtocolDepositUsingStakedControl,
|
|
325
365
|
|
|
326
366
|
// Processing flags
|
|
327
367
|
get isStaking() {
|
|
@@ -336,5 +376,8 @@ export function ControlRouter(baseUrl: string) {
|
|
|
336
376
|
get isRetryingFailedOperation() {
|
|
337
377
|
return isRetryingFailedOperation;
|
|
338
378
|
},
|
|
379
|
+
get isPayingProtocolDepositUsingStakedControl() {
|
|
380
|
+
return isPayingProtocolDepositUsingStakedControl;
|
|
381
|
+
},
|
|
339
382
|
} as const;
|
|
340
383
|
}
|
|
@@ -3,7 +3,7 @@ import { FORWARDER_ABI } from "../abis/forwarderABI";
|
|
|
3
3
|
import { ERC20_ABI } from "../abis/erc20.abi";
|
|
4
4
|
import { getAddresses } from "../../constants/addresses";
|
|
5
5
|
import { formatEther } from "viem";
|
|
6
|
-
import { PendingTransferType } from "../types";
|
|
6
|
+
import { PendingTransferType, TRANSFER_TYPES } from "../types";
|
|
7
7
|
|
|
8
8
|
export enum ForwarderError {
|
|
9
9
|
CONTRACT_NOT_AVAILABLE = "Contract not available",
|
|
@@ -96,55 +96,55 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
96
96
|
} = params;
|
|
97
97
|
|
|
98
98
|
switch (type) {
|
|
99
|
-
case
|
|
99
|
+
case TRANSFER_TYPES.PayProtocolFeeAndMintGCTLAndStake:
|
|
100
100
|
if (!applicationId) {
|
|
101
101
|
throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
|
|
102
102
|
}
|
|
103
103
|
return `PayProtocolFeeAndMintGCTLAndStake::${applicationId}`;
|
|
104
104
|
|
|
105
|
-
case
|
|
105
|
+
case TRANSFER_TYPES.PayProtocolFee:
|
|
106
106
|
if (!applicationId) {
|
|
107
107
|
throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
|
|
108
108
|
}
|
|
109
109
|
return `PayProtocolFee::${applicationId}`;
|
|
110
110
|
|
|
111
|
-
case
|
|
111
|
+
case TRANSFER_TYPES.SponsorProtocolFee:
|
|
112
112
|
if (!applicationId) {
|
|
113
113
|
throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
|
|
114
114
|
}
|
|
115
115
|
return `SponsorProtocolFee::${applicationId}`;
|
|
116
116
|
|
|
117
|
-
case
|
|
117
|
+
case TRANSFER_TYPES.SponsorProtocolFeeAndMintGCTLAndStake:
|
|
118
118
|
if (!applicationId) {
|
|
119
119
|
throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
|
|
120
120
|
}
|
|
121
121
|
return `SponsorProtocolFeeAndMintGCTLAndStake::${applicationId}`;
|
|
122
122
|
|
|
123
|
-
case
|
|
123
|
+
case TRANSFER_TYPES.MintGCTLAndStake:
|
|
124
124
|
if (!regionId) {
|
|
125
125
|
throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
|
|
126
126
|
}
|
|
127
127
|
return `MintGCTLAndStake::${regionId}`;
|
|
128
128
|
|
|
129
|
-
case
|
|
129
|
+
case TRANSFER_TYPES.MintGCTL:
|
|
130
130
|
if (!userAddress) {
|
|
131
131
|
throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
|
|
132
132
|
}
|
|
133
133
|
return `MintGCTL::${userAddress}`;
|
|
134
134
|
|
|
135
|
-
case
|
|
135
|
+
case TRANSFER_TYPES.BuySolarFarm:
|
|
136
136
|
if (!farmId) {
|
|
137
137
|
throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
|
|
138
138
|
}
|
|
139
139
|
return `BuySolarFarm::${farmId}`;
|
|
140
140
|
|
|
141
|
-
case
|
|
141
|
+
case TRANSFER_TYPES.PayAuditFees:
|
|
142
142
|
if (!applicationId) {
|
|
143
143
|
throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
|
|
144
144
|
}
|
|
145
145
|
return `PayAuditFees::${applicationId}`;
|
|
146
146
|
|
|
147
|
-
case
|
|
147
|
+
case TRANSFER_TYPES.CommitKickstarter:
|
|
148
148
|
if (!kickstarterId) {
|
|
149
149
|
throw new Error(ForwarderError.MISSING_REQUIRED_PARAMS);
|
|
150
150
|
}
|
|
@@ -288,13 +288,14 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
288
288
|
const message = constructForwardMessage(params);
|
|
289
289
|
|
|
290
290
|
// Special handling: PayAuditFees can ONLY be USDC, and must call forward()
|
|
291
|
-
const isAuditFees = params.type ===
|
|
291
|
+
const isAuditFees = params.type === TRANSFER_TYPES.PayAuditFees;
|
|
292
292
|
if (isAuditFees && currency !== "USDC") {
|
|
293
293
|
throw new Error("PayAuditFees only supports USDC");
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
// CommitKickstarter supports only USDC or USDG (GLW not allowed)
|
|
297
|
-
const isCommitKickstarter =
|
|
297
|
+
const isCommitKickstarter =
|
|
298
|
+
params.type === TRANSFER_TYPES.CommitKickstarter;
|
|
298
299
|
if (isCommitKickstarter && currency === "GLW") {
|
|
299
300
|
throw new Error("CommitKickstarter supports only USDC or USDG");
|
|
300
301
|
}
|
|
@@ -340,7 +341,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
340
341
|
if (!isAuditFees && currency === "USDC") {
|
|
341
342
|
await forwarderContract
|
|
342
343
|
.getFunction("swapUSDCAndForwardUSDG")
|
|
343
|
-
.staticCall(amount, ADDRESSES.FOUNDATION_WALLET, message, {
|
|
344
|
+
.staticCall(amount, ADDRESSES.FOUNDATION_WALLET, true, message, {
|
|
344
345
|
from: owner,
|
|
345
346
|
});
|
|
346
347
|
} else {
|
|
@@ -352,6 +353,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
352
353
|
? ADDRESSES.AUDIT_FEE_WALLET
|
|
353
354
|
: ADDRESSES.FOUNDATION_WALLET,
|
|
354
355
|
amount,
|
|
356
|
+
true,
|
|
355
357
|
message,
|
|
356
358
|
{ from: owner }
|
|
357
359
|
);
|
|
@@ -366,6 +368,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
366
368
|
tx = await forwarderContract.getFunction("swapUSDCAndForwardUSDG")(
|
|
367
369
|
amount,
|
|
368
370
|
ADDRESSES.FOUNDATION_WALLET,
|
|
371
|
+
true,
|
|
369
372
|
message
|
|
370
373
|
);
|
|
371
374
|
} else {
|
|
@@ -375,6 +378,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
375
378
|
? ADDRESSES.AUDIT_FEE_WALLET
|
|
376
379
|
: ADDRESSES.FOUNDATION_WALLET,
|
|
377
380
|
amount,
|
|
381
|
+
true,
|
|
378
382
|
message
|
|
379
383
|
);
|
|
380
384
|
}
|
|
@@ -410,7 +414,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
410
414
|
return forwardTokens({
|
|
411
415
|
amount,
|
|
412
416
|
userAddress,
|
|
413
|
-
type:
|
|
417
|
+
type: TRANSFER_TYPES.PayProtocolFeeAndMintGCTLAndStake,
|
|
414
418
|
currency,
|
|
415
419
|
applicationId,
|
|
416
420
|
regionId,
|
|
@@ -436,7 +440,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
436
440
|
return forwardTokens({
|
|
437
441
|
amount,
|
|
438
442
|
userAddress,
|
|
439
|
-
type:
|
|
443
|
+
type: TRANSFER_TYPES.SponsorProtocolFeeAndMintGCTLAndStake,
|
|
440
444
|
currency,
|
|
441
445
|
applicationId,
|
|
442
446
|
});
|
|
@@ -456,7 +460,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
456
460
|
return forwardTokens({
|
|
457
461
|
amount,
|
|
458
462
|
userAddress,
|
|
459
|
-
type:
|
|
463
|
+
type: TRANSFER_TYPES.PayProtocolFee,
|
|
460
464
|
currency,
|
|
461
465
|
applicationId,
|
|
462
466
|
});
|
|
@@ -476,7 +480,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
476
480
|
return forwardTokens({
|
|
477
481
|
amount,
|
|
478
482
|
userAddress,
|
|
479
|
-
type:
|
|
483
|
+
type: TRANSFER_TYPES.SponsorProtocolFee,
|
|
480
484
|
currency,
|
|
481
485
|
applicationId,
|
|
482
486
|
});
|
|
@@ -503,7 +507,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
503
507
|
return forwardTokens({
|
|
504
508
|
amount,
|
|
505
509
|
userAddress,
|
|
506
|
-
type:
|
|
510
|
+
type: TRANSFER_TYPES.MintGCTLAndStake,
|
|
507
511
|
currency,
|
|
508
512
|
regionId,
|
|
509
513
|
});
|
|
@@ -529,7 +533,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
529
533
|
return forwardTokens({
|
|
530
534
|
amount,
|
|
531
535
|
userAddress,
|
|
532
|
-
type:
|
|
536
|
+
type: TRANSFER_TYPES.MintGCTL,
|
|
533
537
|
currency,
|
|
534
538
|
});
|
|
535
539
|
}
|
|
@@ -547,7 +551,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
547
551
|
return forwardTokens({
|
|
548
552
|
amount,
|
|
549
553
|
userAddress,
|
|
550
|
-
type:
|
|
554
|
+
type: TRANSFER_TYPES.PayAuditFees,
|
|
551
555
|
currency: "USDC",
|
|
552
556
|
applicationId,
|
|
553
557
|
});
|
|
@@ -567,7 +571,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
567
571
|
return forwardTokens({
|
|
568
572
|
amount,
|
|
569
573
|
userAddress,
|
|
570
|
-
type:
|
|
574
|
+
type: TRANSFER_TYPES.BuySolarFarm,
|
|
571
575
|
currency,
|
|
572
576
|
farmId,
|
|
573
577
|
});
|
|
@@ -591,7 +595,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
591
595
|
return forwardTokens({
|
|
592
596
|
amount,
|
|
593
597
|
userAddress,
|
|
594
|
-
type:
|
|
598
|
+
type: TRANSFER_TYPES.CommitKickstarter,
|
|
595
599
|
currency,
|
|
596
600
|
kickstarterId,
|
|
597
601
|
});
|
|
@@ -614,7 +618,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
614
618
|
throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);
|
|
615
619
|
|
|
616
620
|
const { amount, currency = "USDC" } = params;
|
|
617
|
-
const isAuditFees = params.type ===
|
|
621
|
+
const isAuditFees = params.type === TRANSFER_TYPES.PayAuditFees;
|
|
618
622
|
if (isAuditFees && currency !== "USDC") {
|
|
619
623
|
throw new Error("PayAuditFees only supports USDC");
|
|
620
624
|
}
|
|
@@ -650,7 +654,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
650
654
|
!isAuditFees && currency === "USDC"
|
|
651
655
|
? await forwarderContract
|
|
652
656
|
.getFunction("swapUSDCAndForwardUSDG")
|
|
653
|
-
.estimateGas(amount, ADDRESSES.FOUNDATION_WALLET, message)
|
|
657
|
+
.estimateGas(amount, ADDRESSES.FOUNDATION_WALLET, true, message)
|
|
654
658
|
: await forwarderContract
|
|
655
659
|
.getFunction("forward")
|
|
656
660
|
.estimateGas(
|
|
@@ -659,6 +663,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
|
|
|
659
663
|
? ADDRESSES.AUDIT_FEE_WALLET
|
|
660
664
|
: ADDRESSES.FOUNDATION_WALLET,
|
|
661
665
|
amount,
|
|
666
|
+
true,
|
|
662
667
|
message
|
|
663
668
|
);
|
|
664
669
|
const estimatedCost: bigint = estimatedGas * gasPrice;
|
package/src/lib/types/index.ts
CHANGED
|
@@ -51,20 +51,23 @@ export interface PendingTransfer {
|
|
|
51
51
|
kickstarterId?: string;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
export const TRANSFER_TYPES =
|
|
55
|
-
"PayProtocolFeeAndMintGCTLAndStake",
|
|
56
|
-
"PayProtocolFee",
|
|
57
|
-
"PayAuditFees",
|
|
58
|
-
"CommitKickstarter",
|
|
59
|
-
"MintGCTLAndStake",
|
|
60
|
-
"MintGCTL",
|
|
61
|
-
"BuySolarFarm",
|
|
62
|
-
"SponsorProtocolFee",
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
export const TRANSFER_TYPES = {
|
|
55
|
+
PayProtocolFeeAndMintGCTLAndStake: "PayProtocolFeeAndMintGCTLAndStake",
|
|
56
|
+
PayProtocolFee: "PayProtocolFee",
|
|
57
|
+
PayAuditFees: "PayAuditFees",
|
|
58
|
+
CommitKickstarter: "CommitKickstarter",
|
|
59
|
+
MintGCTLAndStake: "MintGCTLAndStake",
|
|
60
|
+
MintGCTL: "MintGCTL",
|
|
61
|
+
BuySolarFarm: "BuySolarFarm",
|
|
62
|
+
SponsorProtocolFee: "SponsorProtocolFee",
|
|
63
|
+
SponsorProtocolFeeAndMintGCTLAndStake:
|
|
64
|
+
"SponsorProtocolFeeAndMintGCTLAndStake",
|
|
65
|
+
PayProtocolDepositUsingStakedControl: "PayProtocolDepositUsingStakedControl",
|
|
66
|
+
} as const;
|
|
65
67
|
|
|
66
68
|
// Pending transfer type filter for listing endpoint
|
|
67
|
-
export type PendingTransferType =
|
|
69
|
+
export type PendingTransferType =
|
|
70
|
+
(typeof TRANSFER_TYPES)[keyof typeof TRANSFER_TYPES];
|
|
68
71
|
|
|
69
72
|
export interface TransferDetails extends PendingTransfer {
|
|
70
73
|
blockNumber: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TRANSFER_TYPES } from "src/browser";
|
|
2
|
+
import { verifyTypedData, type Hex, getAddress } from "viem";
|
|
2
3
|
import z from "zod";
|
|
3
4
|
|
|
4
5
|
export const stakeControlEIP712Domain = (chainId: number) => ({
|
|
@@ -57,6 +58,15 @@ export const commitKickstarterEIP712Types = {
|
|
|
57
58
|
],
|
|
58
59
|
} as const;
|
|
59
60
|
|
|
61
|
+
export const payProtocolDepositUsingStakedControlEIP712Types = {
|
|
62
|
+
PayProtocolDepositUsingStakedControl: [
|
|
63
|
+
{ name: "amount", type: "uint256" },
|
|
64
|
+
{ name: "applicationId", type: "string" },
|
|
65
|
+
{ name: "nonce", type: "uint256" },
|
|
66
|
+
{ name: "deadline", type: "uint256" },
|
|
67
|
+
],
|
|
68
|
+
} as const;
|
|
69
|
+
|
|
60
70
|
// Separate request schemas for clarity between stake and unstake
|
|
61
71
|
export const stakeSignatureRequestSchema = z.object({
|
|
62
72
|
wallet: z.string().regex(/^0x[a-fA-F0-9]{40}$/),
|
|
@@ -105,6 +115,16 @@ export const commitKickstarterSignatureRequestSchema = z.object({
|
|
|
105
115
|
deadline: z.string(),
|
|
106
116
|
});
|
|
107
117
|
|
|
118
|
+
export const payProtocolDepositUsingStakedControlSignatureRequestSchema =
|
|
119
|
+
z.object({
|
|
120
|
+
wallet: z.string().regex(/^0x[a-fA-F0-9]{40}$/),
|
|
121
|
+
signature: z.string().regex(/^0x[a-fA-F0-9]{130}$/),
|
|
122
|
+
nonce: z.string(),
|
|
123
|
+
amount: z.string(),
|
|
124
|
+
applicationId: z.string(),
|
|
125
|
+
deadline: z.string(),
|
|
126
|
+
});
|
|
127
|
+
|
|
108
128
|
export type StakeSignatureRequest = z.infer<typeof stakeSignatureRequestSchema>;
|
|
109
129
|
export type UnstakeUnlockSignatureRequest = z.infer<
|
|
110
130
|
typeof unstakeUnlockSignatureRequestSchema
|
|
@@ -118,6 +138,9 @@ export type RestakeSignatureRequest = z.infer<
|
|
|
118
138
|
export type CommitKickstarterSignatureRequest = z.infer<
|
|
119
139
|
typeof commitKickstarterSignatureRequestSchema
|
|
120
140
|
>;
|
|
141
|
+
export type PayProtocolDepositUsingStakedControlSignatureRequest = z.infer<
|
|
142
|
+
typeof payProtocolDepositUsingStakedControlSignatureRequestSchema
|
|
143
|
+
>;
|
|
121
144
|
|
|
122
145
|
export type StakeMessage = {
|
|
123
146
|
nonce: bigint;
|
|
@@ -156,6 +179,13 @@ export type CommitKickstarterMessage = {
|
|
|
156
179
|
deadline: bigint;
|
|
157
180
|
};
|
|
158
181
|
|
|
182
|
+
export type PayProtocolDepositUsingStakedControlMessage = {
|
|
183
|
+
amount: bigint;
|
|
184
|
+
applicationId: string;
|
|
185
|
+
nonce: bigint;
|
|
186
|
+
deadline: bigint;
|
|
187
|
+
};
|
|
188
|
+
|
|
159
189
|
export type SignatureValidationReason =
|
|
160
190
|
| "deadline_expired"
|
|
161
191
|
| "signature_failed"
|
|
@@ -196,6 +226,11 @@ type CommitKickstarterMessageInput = Pick<
|
|
|
196
226
|
"nonce" | "amount" | "kickstarterId" | "deadline"
|
|
197
227
|
>;
|
|
198
228
|
|
|
229
|
+
type PayProtocolDepositUsingStakedControlMessageInput = Pick<
|
|
230
|
+
PayProtocolDepositUsingStakedControlSignatureRequest,
|
|
231
|
+
"amount" | "applicationId" | "nonce" | "deadline"
|
|
232
|
+
>;
|
|
233
|
+
|
|
199
234
|
export function buildStakeMessage(req: StakeMessageInput): StakeMessage {
|
|
200
235
|
const nonce = BigInt(req.nonce);
|
|
201
236
|
const amount = BigInt(req.amount);
|
|
@@ -266,6 +301,20 @@ export function buildCommitKickstarterMessage(
|
|
|
266
301
|
return { nonce, amount, kickstarterId, deadline };
|
|
267
302
|
}
|
|
268
303
|
|
|
304
|
+
export function buildPayProtocolDepositUsingStakedControlMessage(
|
|
305
|
+
req: PayProtocolDepositUsingStakedControlMessageInput
|
|
306
|
+
): PayProtocolDepositUsingStakedControlMessage {
|
|
307
|
+
const amount = BigInt(req.amount);
|
|
308
|
+
const nonce = BigInt(req.nonce);
|
|
309
|
+
const deadline = BigInt(req.deadline);
|
|
310
|
+
const applicationId = req.applicationId;
|
|
311
|
+
if (amount < 0n) throw new Error("Amount must be non-negative");
|
|
312
|
+
if (nonce < 0n) throw new Error("Nonce must be non-negative");
|
|
313
|
+
if (deadline < 0n) throw new Error("Deadline must be non-negative");
|
|
314
|
+
if (!applicationId) throw new Error("applicationId must be non-empty");
|
|
315
|
+
return { amount, applicationId, nonce, deadline };
|
|
316
|
+
}
|
|
317
|
+
|
|
269
318
|
// Helper to validate the signature using viem
|
|
270
319
|
export async function validateStakeSignature(
|
|
271
320
|
input: StakeSignatureRequest,
|
|
@@ -428,3 +477,35 @@ export async function validateCommitKickstarterSignature(
|
|
|
428
477
|
return { valid: false, recovered: null, reason: "signature_failed" };
|
|
429
478
|
}
|
|
430
479
|
}
|
|
480
|
+
|
|
481
|
+
export async function validatePayProtocolDepositUsingStakedControlSignature(
|
|
482
|
+
input: PayProtocolDepositUsingStakedControlSignatureRequest,
|
|
483
|
+
domain: ReturnType<
|
|
484
|
+
typeof stakeControlEIP712Domain
|
|
485
|
+
> = stakeControlEIP712Domain(1)
|
|
486
|
+
): Promise<SignatureValidationResult> {
|
|
487
|
+
const message = buildPayProtocolDepositUsingStakedControlMessage({
|
|
488
|
+
amount: input.amount,
|
|
489
|
+
applicationId: input.applicationId,
|
|
490
|
+
nonce: input.nonce,
|
|
491
|
+
deadline: input.deadline,
|
|
492
|
+
});
|
|
493
|
+
if (isDeadlineExpired(message.deadline)) {
|
|
494
|
+
return { valid: false, recovered: null, reason: "deadline_expired" };
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
const verified = await verifyTypedData({
|
|
498
|
+
address: getAddress(input.wallet as Hex),
|
|
499
|
+
domain,
|
|
500
|
+
types: payProtocolDepositUsingStakedControlEIP712Types,
|
|
501
|
+
primaryType: TRANSFER_TYPES.PayProtocolDepositUsingStakedControl,
|
|
502
|
+
message,
|
|
503
|
+
signature: input.signature as Hex,
|
|
504
|
+
});
|
|
505
|
+
return verified
|
|
506
|
+
? { valid: true, recovered: input.wallet, reason: null }
|
|
507
|
+
: { valid: false, recovered: null, reason: "signer_mismatch" };
|
|
508
|
+
} catch (_) {
|
|
509
|
+
return { valid: false, recovered: null, reason: "signature_failed" };
|
|
510
|
+
}
|
|
511
|
+
}
|