@glowlabs-org/utils 0.2.91 → 0.2.93

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.
@@ -1,4 +1,18 @@
1
1
  import type { StakeRequest, RegionStake, WalletRegionStake, WalletRegionUnlocked, TransferDetails, GlwRegionRewardsResponse, MintedEventsResponse, StakeEventsResponse, FailedOperationsResponse, PendingTransfersResponse, PendingTransferType, RestakeRequest } from "../types";
2
+ export interface PayProtocolDepositUsingStakedControlRequest {
3
+ wallet: string;
4
+ regionId: number;
5
+ applicationId: string;
6
+ amount: string;
7
+ signature: string;
8
+ deadline: string;
9
+ nonce: string;
10
+ }
11
+ export interface PayProtocolDepositUsingStakedControlResponse {
12
+ success: true;
13
+ farmId: string;
14
+ applicationId: string;
15
+ }
2
16
  export declare function ControlRouter(baseUrl: string): {
3
17
  readonly fetchGctlBalance: (wallet: string) => Promise<string>;
4
18
  readonly fetchGctlPrice: () => Promise<string>;
@@ -18,8 +32,10 @@ export declare function ControlRouter(baseUrl: string): {
18
32
  readonly unstakeGctl: (unstakeRequest: StakeRequest) => Promise<boolean>;
19
33
  readonly restakeGctl: (restakeRequest: RestakeRequest) => Promise<boolean>;
20
34
  readonly retryFailedOperation: (operationId: string) => Promise<boolean>;
35
+ readonly payProtocolDepositUsingStakedControl: (paymentRequest: PayProtocolDepositUsingStakedControlRequest) => Promise<PayProtocolDepositUsingStakedControlResponse>;
21
36
  readonly isStaking: boolean;
22
37
  readonly isUnstaking: boolean;
23
38
  readonly isRestaking: boolean;
24
39
  readonly isRetryingFailedOperation: boolean;
40
+ readonly isPayingProtocolDepositUsingStakedControl: boolean;
25
41
  };
@@ -34,8 +34,19 @@ export interface PendingTransfer {
34
34
  regionId?: number;
35
35
  kickstarterId?: string;
36
36
  }
37
- export declare const TRANSFER_TYPES: readonly ["PayProtocolFeeAndMintGCTLAndStake", "PayProtocolFee", "PayAuditFees", "CommitKickstarter", "MintGCTLAndStake", "MintGCTL", "BuySolarFarm", "SponsorProtocolFee", "SponsorProtocolFeeAndMintGCTLAndStake"];
38
- export type PendingTransferType = (typeof TRANSFER_TYPES)[number];
37
+ export declare const TRANSFER_TYPES: {
38
+ readonly PayProtocolFeeAndMintGCTLAndStake: "PayProtocolFeeAndMintGCTLAndStake";
39
+ readonly PayProtocolFee: "PayProtocolFee";
40
+ readonly PayAuditFees: "PayAuditFees";
41
+ readonly CommitKickstarter: "CommitKickstarter";
42
+ readonly MintGCTLAndStake: "MintGCTLAndStake";
43
+ readonly MintGCTL: "MintGCTL";
44
+ readonly BuySolarFarm: "BuySolarFarm";
45
+ readonly SponsorProtocolFee: "SponsorProtocolFee";
46
+ readonly SponsorProtocolFeeAndMintGCTLAndStake: "SponsorProtocolFeeAndMintGCTLAndStake";
47
+ readonly PayProtocolDepositUsingStakedControl: "PayProtocolDepositUsingStakedControl";
48
+ };
49
+ export type PendingTransferType = (typeof TRANSFER_TYPES)[keyof typeof TRANSFER_TYPES];
39
50
  export interface TransferDetails extends PendingTransfer {
40
51
  blockNumber: string;
41
52
  failureInfo?: {
@@ -190,6 +201,7 @@ export interface KickstarterDetails extends Kickstarter {
190
201
  contributorsCount: number;
191
202
  farmCount: number;
192
203
  solarFarmApplications: SolarFarmApplication[];
204
+ sponsoredFarms: SponsoredFarm[];
193
205
  }
194
206
  export interface CommitKickstarterPayload {
195
207
  wallet: string;
@@ -86,6 +86,21 @@ export declare const commitKickstarterEIP712Types: {
86
86
  readonly type: "uint256";
87
87
  }];
88
88
  };
89
+ export declare const payProtocolDepositUsingStakedControlEIP712Types: {
90
+ readonly PayProtocolDepositUsingStakedControl: readonly [{
91
+ readonly name: "amount";
92
+ readonly type: "uint256";
93
+ }, {
94
+ readonly name: "applicationId";
95
+ readonly type: "string";
96
+ }, {
97
+ readonly name: "nonce";
98
+ readonly type: "uint256";
99
+ }, {
100
+ readonly name: "deadline";
101
+ readonly type: "uint256";
102
+ }];
103
+ };
89
104
  export declare const stakeSignatureRequestSchema: z.ZodObject<{
90
105
  wallet: z.ZodString;
91
106
  signature: z.ZodString;
@@ -128,11 +143,20 @@ export declare const commitKickstarterSignatureRequestSchema: z.ZodObject<{
128
143
  kickstarterId: z.ZodString;
129
144
  deadline: z.ZodString;
130
145
  }, z.core.$strip>;
146
+ export declare const payProtocolDepositUsingStakedControlSignatureRequestSchema: z.ZodObject<{
147
+ wallet: z.ZodString;
148
+ signature: z.ZodString;
149
+ nonce: z.ZodString;
150
+ amount: z.ZodString;
151
+ applicationId: z.ZodString;
152
+ deadline: z.ZodString;
153
+ }, z.core.$strip>;
131
154
  export type StakeSignatureRequest = z.infer<typeof stakeSignatureRequestSchema>;
132
155
  export type UnstakeUnlockSignatureRequest = z.infer<typeof unstakeUnlockSignatureRequestSchema>;
133
156
  export type UnstakeMoveSignatureRequest = z.infer<typeof unstakeMoveSignatureRequestSchema>;
134
157
  export type RestakeSignatureRequest = z.infer<typeof restakeSignatureRequestSchema>;
135
158
  export type CommitKickstarterSignatureRequest = z.infer<typeof commitKickstarterSignatureRequestSchema>;
159
+ export type PayProtocolDepositUsingStakedControlSignatureRequest = z.infer<typeof payProtocolDepositUsingStakedControlSignatureRequestSchema>;
136
160
  export type StakeMessage = {
137
161
  nonce: bigint;
138
162
  amount: bigint;
@@ -165,6 +189,12 @@ export type CommitKickstarterMessage = {
165
189
  kickstarterId: string;
166
190
  deadline: bigint;
167
191
  };
192
+ export type PayProtocolDepositUsingStakedControlMessage = {
193
+ amount: bigint;
194
+ applicationId: string;
195
+ nonce: bigint;
196
+ deadline: bigint;
197
+ };
168
198
  export type SignatureValidationReason = "deadline_expired" | "signature_failed" | "signer_mismatch" | null;
169
199
  export type SignatureValidationResult = {
170
200
  valid: boolean;
@@ -176,14 +206,17 @@ type UnstakeUnlockMessageInput = Pick<UnstakeUnlockSignatureRequest, "nonce" | "
176
206
  type UnstakeMoveMessageInput = Pick<UnstakeMoveSignatureRequest, "nonce" | "amount" | "fromZoneId" | "toZoneId" | "deadline">;
177
207
  type RestakeMessageInput = Pick<RestakeSignatureRequest, "nonce" | "amount" | "fromZoneId" | "toZoneId" | "deadline">;
178
208
  type CommitKickstarterMessageInput = Pick<CommitKickstarterSignatureRequest, "nonce" | "amount" | "kickstarterId" | "deadline">;
209
+ type PayProtocolDepositUsingStakedControlMessageInput = Pick<PayProtocolDepositUsingStakedControlSignatureRequest, "amount" | "applicationId" | "nonce" | "deadline">;
179
210
  export declare function buildStakeMessage(req: StakeMessageInput): StakeMessage;
180
211
  export declare function buildUnstakeUnlockMessage(req: UnstakeUnlockMessageInput): UnstakeUnlockMessage;
181
212
  export declare function buildUnstakeMoveMessage(req: UnstakeMoveMessageInput): UnstakeMoveMessage;
182
213
  export declare function buildRestakeMessage(req: RestakeMessageInput): RestakeMessage;
183
214
  export declare function buildCommitKickstarterMessage(req: CommitKickstarterMessageInput): CommitKickstarterMessage;
215
+ export declare function buildPayProtocolDepositUsingStakedControlMessage(req: PayProtocolDepositUsingStakedControlMessageInput): PayProtocolDepositUsingStakedControlMessage;
184
216
  export declare function validateStakeSignature(input: StakeSignatureRequest, domain?: ReturnType<typeof stakeControlEIP712Domain>): Promise<SignatureValidationResult>;
185
217
  export declare function validateUnstakeUnlockSignature(input: UnstakeUnlockSignatureRequest, domain?: ReturnType<typeof stakeControlEIP712Domain>): Promise<SignatureValidationResult>;
186
218
  export declare function validateUnstakeMoveSignature(input: UnstakeMoveSignatureRequest, domain?: ReturnType<typeof stakeControlEIP712Domain>): Promise<SignatureValidationResult>;
187
219
  export declare function validateRestakeSignature(input: RestakeSignatureRequest, domain?: ReturnType<typeof stakeControlEIP712Domain>): Promise<SignatureValidationResult>;
188
220
  export declare function validateCommitKickstarterSignature(input: CommitKickstarterSignatureRequest, domain?: ReturnType<typeof stakeControlEIP712Domain>): Promise<SignatureValidationResult>;
221
+ export declare function validatePayProtocolDepositUsingStakedControlSignature(input: PayProtocolDepositUsingStakedControlSignatureRequest, domain?: ReturnType<typeof stakeControlEIP712Domain>): Promise<SignatureValidationResult>;
189
222
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glowlabs-org/utils",
3
- "version": "0.2.91",
3
+ "version": "0.2.93",
4
4
  "description": "A library containing all typechain types and addresses relating to the glow guarded launch",
5
5
  "keywords": [],
6
6
  "author": "",
@@ -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 "PayProtocolFeeAndMintGCTLAndStake":
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 "PayProtocolFee":
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 "SponsorProtocolFee":
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 "SponsorProtocolFeeAndMintGCTLAndStake":
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 "MintGCTLAndStake":
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 "MintGCTL":
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 "BuySolarFarm":
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 "PayAuditFees":
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 "CommitKickstarter":
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 === "PayAuditFees";
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 = params.type === "CommitKickstarter";
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
  }
@@ -410,7 +411,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
410
411
  return forwardTokens({
411
412
  amount,
412
413
  userAddress,
413
- type: "PayProtocolFeeAndMintGCTLAndStake",
414
+ type: TRANSFER_TYPES.PayProtocolFeeAndMintGCTLAndStake,
414
415
  currency,
415
416
  applicationId,
416
417
  regionId,
@@ -436,7 +437,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
436
437
  return forwardTokens({
437
438
  amount,
438
439
  userAddress,
439
- type: "SponsorProtocolFeeAndMintGCTLAndStake",
440
+ type: TRANSFER_TYPES.SponsorProtocolFeeAndMintGCTLAndStake,
440
441
  currency,
441
442
  applicationId,
442
443
  });
@@ -456,7 +457,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
456
457
  return forwardTokens({
457
458
  amount,
458
459
  userAddress,
459
- type: "PayProtocolFee",
460
+ type: TRANSFER_TYPES.PayProtocolFee,
460
461
  currency,
461
462
  applicationId,
462
463
  });
@@ -476,7 +477,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
476
477
  return forwardTokens({
477
478
  amount,
478
479
  userAddress,
479
- type: "SponsorProtocolFee",
480
+ type: TRANSFER_TYPES.SponsorProtocolFee,
480
481
  currency,
481
482
  applicationId,
482
483
  });
@@ -503,7 +504,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
503
504
  return forwardTokens({
504
505
  amount,
505
506
  userAddress,
506
- type: "MintGCTLAndStake",
507
+ type: TRANSFER_TYPES.MintGCTLAndStake,
507
508
  currency,
508
509
  regionId,
509
510
  });
@@ -529,7 +530,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
529
530
  return forwardTokens({
530
531
  amount,
531
532
  userAddress,
532
- type: "MintGCTL",
533
+ type: TRANSFER_TYPES.MintGCTL,
533
534
  currency,
534
535
  });
535
536
  }
@@ -547,7 +548,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
547
548
  return forwardTokens({
548
549
  amount,
549
550
  userAddress,
550
- type: "PayAuditFees",
551
+ type: TRANSFER_TYPES.PayAuditFees,
551
552
  currency: "USDC",
552
553
  applicationId,
553
554
  });
@@ -567,7 +568,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
567
568
  return forwardTokens({
568
569
  amount,
569
570
  userAddress,
570
- type: "BuySolarFarm",
571
+ type: TRANSFER_TYPES.BuySolarFarm,
571
572
  currency,
572
573
  farmId,
573
574
  });
@@ -591,7 +592,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
591
592
  return forwardTokens({
592
593
  amount,
593
594
  userAddress,
594
- type: "CommitKickstarter",
595
+ type: TRANSFER_TYPES.CommitKickstarter,
595
596
  currency,
596
597
  kickstarterId,
597
598
  });
@@ -614,7 +615,7 @@ export function useForwarder(signer: Signer | undefined, CHAIN_ID: number) {
614
615
  throw new Error(ForwarderError.CONTRACT_NOT_AVAILABLE);
615
616
 
616
617
  const { amount, currency = "USDC" } = params;
617
- const isAuditFees = params.type === "PayAuditFees";
618
+ const isAuditFees = params.type === TRANSFER_TYPES.PayAuditFees;
618
619
  if (isAuditFees && currency !== "USDC") {
619
620
  throw new Error("PayAuditFees only supports USDC");
620
621
  }
@@ -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
- "SponsorProtocolFeeAndMintGCTLAndStake",
64
- ] as const;
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 = (typeof TRANSFER_TYPES)[number];
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;
@@ -251,6 +254,7 @@ export interface KickstarterDetails extends Kickstarter {
251
254
  contributorsCount: number;
252
255
  farmCount: number;
253
256
  solarFarmApplications: SolarFarmApplication[];
257
+ sponsoredFarms: SponsoredFarm[];
254
258
  }
255
259
 
256
260
  export interface CommitKickstarterPayload {
@@ -1,4 +1,5 @@
1
- import { verifyTypedData, type Hex } from "viem";
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
+ }