@lombard.finance/sdk 2.0.7 → 2.0.8
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/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +422 -1631
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/sdk/getNetworkFeeSignature/getNetworkFeeSignature.stories.tsx +2 -2
- package/src/sdk/index.ts +2 -0
- package/src/sdk/storeNetworkFeeSignature/storeNetworkFeeSignature.stories.tsx +3 -3
- package/src/sdk/storeStakeAndBakeSignature/index.ts +1 -0
- package/src/sdk/storeStakeAndBakeSignature/storeStakeAndBakeSignature.stories.tsx +143 -0
- package/src/sdk/storeStakeAndBakeSignature/storeStakeAndBakeSignature.ts +56 -0
- package/src/web3Sdk/getLBTCMintingFee/getLBTCMintingFee.stories.tsx +2 -2
- package/src/web3Sdk/index.ts +2 -11
- package/src/web3Sdk/signStakeAndBake/config.ts +13 -0
- package/src/web3Sdk/signStakeAndBake/getTypedData.ts +82 -0
- package/src/web3Sdk/signStakeAndBake/index.ts +2 -0
- package/src/web3Sdk/signStakeAndBake/signStakeAndBake.stories.tsx +143 -0
- package/src/web3Sdk/signStakeAndBake/signStakeAndBake.ts +99 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { FormControl, InputLabel, MenuItem, Select } from '@mui/material';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { OChainId, OEnv } from '../../common/types/types';
|
|
5
|
+
import { Button } from '../../stories/components/Button';
|
|
6
|
+
import { CodeBlock } from '../../stories/components/CodeBlock';
|
|
7
|
+
import { useConnect } from '../../stories/hooks/useConnect';
|
|
8
|
+
import useQuery from '../../stories/hooks/useQuery';
|
|
9
|
+
import { signStakeAndBake } from '../../web3Sdk/signStakeAndBake/signStakeAndBake';
|
|
10
|
+
import {
|
|
11
|
+
IStoreStakeAndBakeSignatureParams,
|
|
12
|
+
storeStakeAndBakeSignature,
|
|
13
|
+
} from './storeStakeAndBakeSignature';
|
|
14
|
+
|
|
15
|
+
const EXPIRY_OPTIONS = {
|
|
16
|
+
'10 seconds': 10,
|
|
17
|
+
'1 minute': 60,
|
|
18
|
+
'1 hour': 3600,
|
|
19
|
+
'1 day': 86400,
|
|
20
|
+
'1 year': 31536000,
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
type ExpiryOption = keyof typeof EXPIRY_OPTIONS;
|
|
24
|
+
|
|
25
|
+
const meta = {
|
|
26
|
+
title: 'SDK/storeStakeAndBakeSignature',
|
|
27
|
+
component: StoryView,
|
|
28
|
+
tags: ['autodocs'],
|
|
29
|
+
} satisfies Meta<typeof StoryView>;
|
|
30
|
+
|
|
31
|
+
export default meta;
|
|
32
|
+
|
|
33
|
+
type Story = StoryObj<typeof meta>;
|
|
34
|
+
|
|
35
|
+
export const WithParams: Story = {
|
|
36
|
+
args: {
|
|
37
|
+
env: OEnv.stage,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
type StoreStakeAndBakeSignatureProps = Pick<
|
|
42
|
+
IStoreStakeAndBakeSignatureParams,
|
|
43
|
+
'env'
|
|
44
|
+
>;
|
|
45
|
+
|
|
46
|
+
export function StoryView(props: StoreStakeAndBakeSignatureProps) {
|
|
47
|
+
const [selectedExpiry, setSelectedExpiry] =
|
|
48
|
+
useState<ExpiryOption>('10 seconds');
|
|
49
|
+
|
|
50
|
+
const {
|
|
51
|
+
data: connectData,
|
|
52
|
+
error: connectError,
|
|
53
|
+
isLoading: isConnectLoading,
|
|
54
|
+
connect,
|
|
55
|
+
} = useConnect();
|
|
56
|
+
|
|
57
|
+
const request = async () => {
|
|
58
|
+
if (!connectData || !connectData.provider) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const chainId = OChainId.holesky;
|
|
63
|
+
const expiryDate =
|
|
64
|
+
Math.floor(Date.now() / 1000) + EXPIRY_OPTIONS[selectedExpiry];
|
|
65
|
+
|
|
66
|
+
const { signature, typedData } = await signStakeAndBake({
|
|
67
|
+
provider: connectData.provider,
|
|
68
|
+
address: connectData.account,
|
|
69
|
+
chainId,
|
|
70
|
+
env: props.env,
|
|
71
|
+
value: '1999',
|
|
72
|
+
expiryDate,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return storeStakeAndBakeSignature({
|
|
76
|
+
...props,
|
|
77
|
+
signature,
|
|
78
|
+
typedData,
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const { data, error, isLoading, refetch } = useQuery(
|
|
83
|
+
request,
|
|
84
|
+
[selectedExpiry],
|
|
85
|
+
false,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const formattedConnectData = connectData && {
|
|
89
|
+
account: connectData.account,
|
|
90
|
+
chainId: connectData.chainId,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<>
|
|
95
|
+
<p>
|
|
96
|
+
This method stores the stake and bake signature in the backend. The
|
|
97
|
+
signature is used to approve spending of tokens.
|
|
98
|
+
</p>
|
|
99
|
+
|
|
100
|
+
<div className="mb-4">
|
|
101
|
+
<Button
|
|
102
|
+
onClick={connect}
|
|
103
|
+
disabled={isConnectLoading}
|
|
104
|
+
isLoading={isConnectLoading}
|
|
105
|
+
>
|
|
106
|
+
Connect
|
|
107
|
+
</Button>
|
|
108
|
+
|
|
109
|
+
<CodeBlock text={connectError || formattedConnectData} />
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div className="mb-4">
|
|
113
|
+
<FormControl fullWidth>
|
|
114
|
+
<InputLabel id="expiry-select-label">Expiry Time</InputLabel>
|
|
115
|
+
<Select
|
|
116
|
+
labelId="expiry-select-label"
|
|
117
|
+
value={selectedExpiry}
|
|
118
|
+
label="Expiry Time"
|
|
119
|
+
onChange={e => setSelectedExpiry(e.target.value as ExpiryOption)}
|
|
120
|
+
>
|
|
121
|
+
{Object.keys(EXPIRY_OPTIONS).map(option => (
|
|
122
|
+
<MenuItem key={option} value={option}>
|
|
123
|
+
{option}
|
|
124
|
+
</MenuItem>
|
|
125
|
+
))}
|
|
126
|
+
</Select>
|
|
127
|
+
</FormControl>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<Button
|
|
131
|
+
onClick={refetch}
|
|
132
|
+
disabled={
|
|
133
|
+
isLoading || !connectData || connectData.chainId !== OChainId.holesky
|
|
134
|
+
}
|
|
135
|
+
isLoading={isLoading}
|
|
136
|
+
>
|
|
137
|
+
Store Stake and Bake Signature
|
|
138
|
+
</Button>
|
|
139
|
+
|
|
140
|
+
<CodeBlock text={error || data} />
|
|
141
|
+
</>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { IEnvParam } from '../../common/types/internalTypes';
|
|
3
|
+
import { getErrorMessage } from '../../common/utils/getErrorMessage';
|
|
4
|
+
import { getApiConfig } from '../apiConfig';
|
|
5
|
+
|
|
6
|
+
export type IStoreStakeAndBakeSignatureStatus = 'success';
|
|
7
|
+
|
|
8
|
+
interface IStoreStakeAndBakeSignatureResponse {
|
|
9
|
+
status: IStoreStakeAndBakeSignatureStatus;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface IStoreStakeAndBakeSignatureParams extends IEnvParam {
|
|
13
|
+
/**
|
|
14
|
+
* signature
|
|
15
|
+
*/
|
|
16
|
+
signature: string;
|
|
17
|
+
/**
|
|
18
|
+
* JSON typed data used for the signature
|
|
19
|
+
*/
|
|
20
|
+
typedData: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Store stake and bake signature
|
|
25
|
+
*
|
|
26
|
+
* @param {IStoreStakeAndBakeSignatureParams} params - The parameters for storing stake and bake signature
|
|
27
|
+
*
|
|
28
|
+
* @returns {Promise<IStoreStakeAndBakeSignatureStatus>} Response promise with status
|
|
29
|
+
*
|
|
30
|
+
*/
|
|
31
|
+
export async function storeStakeAndBakeSignature({
|
|
32
|
+
signature,
|
|
33
|
+
typedData,
|
|
34
|
+
env,
|
|
35
|
+
}: IStoreStakeAndBakeSignatureParams): Promise<IStoreStakeAndBakeSignatureStatus> {
|
|
36
|
+
const { baseApiUrl } = getApiConfig(env);
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const { data } = await axios.post<IStoreStakeAndBakeSignatureResponse>(
|
|
40
|
+
`${baseApiUrl}/api/v1/claimer/save-stake-and-bake-signature`,
|
|
41
|
+
null,
|
|
42
|
+
{
|
|
43
|
+
params: {
|
|
44
|
+
typed_data: typedData,
|
|
45
|
+
signature,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
return data.status;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const errorMsg = getErrorMessage(error);
|
|
53
|
+
|
|
54
|
+
throw new Error(errorMsg);
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/web3Sdk/index.ts
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
export * from '../sdk/getNetworkFeeSignature';
|
|
2
|
-
export * from '../sdk/storeNetworkFeeSignature';
|
|
3
|
-
export * from './approveLBTC';
|
|
4
|
-
export * from './claimLBTC';
|
|
5
|
-
export * from './getBasculeDepositStatus';
|
|
6
1
|
export * from './getLBTCMintingFee';
|
|
7
|
-
export * from './getLBTCTotalSupply';
|
|
8
|
-
export * from './getPermitNonce';
|
|
9
|
-
export * from './lbtcAddressConfig';
|
|
10
|
-
export * from './lbtcOFTAdapterAddressConfig';
|
|
11
2
|
export * from './signLbtcDestionationAddr';
|
|
12
3
|
export * from './signNetworkFee';
|
|
13
|
-
export * from './
|
|
14
|
-
export * from './
|
|
4
|
+
export * from './signStakeAndBake';
|
|
5
|
+
export * from './signStakeAndBake/config';
|
|
15
6
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { OChainId, TChainId } from '../../common/types/types';
|
|
2
|
+
|
|
3
|
+
export const STAKE_AND_BAKE_SPENDER_ADDRESSES: Record<number, string> = {
|
|
4
|
+
[OChainId.holesky]: '0x52BD640617eeD47A00dA0da93351092D49208d1d',
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const getStakeAndBakeSpenderAddress = (chainId: TChainId): string => {
|
|
8
|
+
const address = STAKE_AND_BAKE_SPENDER_ADDRESSES[chainId];
|
|
9
|
+
if (!address) {
|
|
10
|
+
throw new Error(`No spender address configured for chain ID ${chainId}`);
|
|
11
|
+
}
|
|
12
|
+
return address;
|
|
13
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { IEnvParam } from '../../common/types/internalTypes';
|
|
2
|
+
import { TChainId } from '../../common/types/types';
|
|
3
|
+
import { getPermitNonce } from '../getPermitNonce';
|
|
4
|
+
import { getLbtcAddressConfig } from '../lbtcAddressConfig';
|
|
5
|
+
|
|
6
|
+
export interface IStakeAndBakeTypedData extends IEnvParam {
|
|
7
|
+
chainId: TChainId;
|
|
8
|
+
expiryDate: number;
|
|
9
|
+
owner: string;
|
|
10
|
+
spender: string;
|
|
11
|
+
value: string;
|
|
12
|
+
rpcUrl?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Generates EIP-712 typed data for stake and bake signature
|
|
17
|
+
*
|
|
18
|
+
* @param {IStakeAndBakeTypedData} params - Parameters for generating typed data
|
|
19
|
+
* @returns {object} The typed data object conforming to EIP-712
|
|
20
|
+
*/
|
|
21
|
+
export async function getStakeAndBakeTypedData({
|
|
22
|
+
chainId,
|
|
23
|
+
expiryDate,
|
|
24
|
+
owner,
|
|
25
|
+
spender,
|
|
26
|
+
value,
|
|
27
|
+
env,
|
|
28
|
+
rpcUrl,
|
|
29
|
+
}: IStakeAndBakeTypedData) {
|
|
30
|
+
const lbtcAddresses = getLbtcAddressConfig(env);
|
|
31
|
+
const verifyingContract = lbtcAddresses[chainId];
|
|
32
|
+
|
|
33
|
+
const nonce = await getPermitNonce({
|
|
34
|
+
owner,
|
|
35
|
+
chainId,
|
|
36
|
+
rpcUrl,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
domain: {
|
|
41
|
+
name: 'Lombard Staked Bitcoin',
|
|
42
|
+
version: '1',
|
|
43
|
+
chainId,
|
|
44
|
+
verifyingContract,
|
|
45
|
+
},
|
|
46
|
+
types: {
|
|
47
|
+
EIP712Domain: [
|
|
48
|
+
{
|
|
49
|
+
name: 'name',
|
|
50
|
+
type: 'string',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'version',
|
|
54
|
+
type: 'string',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'chainId',
|
|
58
|
+
type: 'uint256',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'verifyingContract',
|
|
62
|
+
type: 'address',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
Permit: [
|
|
66
|
+
{ name: 'owner', type: 'address' },
|
|
67
|
+
{ name: 'spender', type: 'address' },
|
|
68
|
+
{ name: 'value', type: 'uint256' },
|
|
69
|
+
{ name: 'nonce', type: 'uint256' },
|
|
70
|
+
{ name: 'deadline', type: 'uint256' },
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
primaryType: 'Permit',
|
|
74
|
+
message: {
|
|
75
|
+
owner,
|
|
76
|
+
spender,
|
|
77
|
+
value,
|
|
78
|
+
nonce,
|
|
79
|
+
deadline: expiryDate.toString(),
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { FormControl, InputLabel, MenuItem, Select } from '@mui/material';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { OChainId, OEnv } from '../../common/types/types';
|
|
5
|
+
import { Button } from '../../stories/components/Button';
|
|
6
|
+
import { CodeBlock } from '../../stories/components/CodeBlock';
|
|
7
|
+
import { useConnect } from '../../stories/hooks/useConnect';
|
|
8
|
+
import useQuery from '../../stories/hooks/useQuery';
|
|
9
|
+
import { fromCamelCase } from '../../stories/utils/fromCamelCase';
|
|
10
|
+
import { ISignStakeAndBakeParams, signStakeAndBake } from './signStakeAndBake';
|
|
11
|
+
|
|
12
|
+
const { name } = signStakeAndBake;
|
|
13
|
+
const nameWithWhitespaces = fromCamelCase(name);
|
|
14
|
+
|
|
15
|
+
const EXPIRY_OPTIONS = {
|
|
16
|
+
'10 seconds': 10,
|
|
17
|
+
'1 minute': 60,
|
|
18
|
+
'1 hour': 3600,
|
|
19
|
+
'1 day': 86400,
|
|
20
|
+
'1 year': 31536000,
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
type ExpiryOption = keyof typeof EXPIRY_OPTIONS;
|
|
24
|
+
|
|
25
|
+
const meta = {
|
|
26
|
+
title: 'Web3SDK/signStakeAndBake',
|
|
27
|
+
component: StoryView,
|
|
28
|
+
tags: ['autodocs'],
|
|
29
|
+
} satisfies Meta<typeof StoryView>;
|
|
30
|
+
|
|
31
|
+
export default meta;
|
|
32
|
+
|
|
33
|
+
type Story = StoryObj<typeof meta>;
|
|
34
|
+
|
|
35
|
+
export const WithParams: Story = {
|
|
36
|
+
args: {
|
|
37
|
+
env: OEnv.stage,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
type SignStakeAndBakeProps = Pick<ISignStakeAndBakeParams, 'env'>;
|
|
42
|
+
|
|
43
|
+
export function StoryView(props: SignStakeAndBakeProps) {
|
|
44
|
+
const [selectedExpiry, setSelectedExpiry] =
|
|
45
|
+
useState<ExpiryOption>('10 seconds');
|
|
46
|
+
|
|
47
|
+
const {
|
|
48
|
+
data: connectData,
|
|
49
|
+
error: connectError,
|
|
50
|
+
isLoading: isConnectLoading,
|
|
51
|
+
connect,
|
|
52
|
+
} = useConnect();
|
|
53
|
+
|
|
54
|
+
const request = async () => {
|
|
55
|
+
if (!connectData || !connectData.provider) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const chainId = OChainId.holesky;
|
|
60
|
+
const expiryDate =
|
|
61
|
+
Math.floor(Date.now() / 1000) + EXPIRY_OPTIONS[selectedExpiry];
|
|
62
|
+
|
|
63
|
+
return signStakeAndBake({
|
|
64
|
+
provider: connectData.provider,
|
|
65
|
+
address: connectData.account,
|
|
66
|
+
chainId,
|
|
67
|
+
env: props.env,
|
|
68
|
+
value: '1999',
|
|
69
|
+
expiryDate,
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const { data, error, isLoading, refetch } = useQuery(
|
|
74
|
+
request,
|
|
75
|
+
[selectedExpiry],
|
|
76
|
+
false,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const formattedConnectData = connectData && {
|
|
80
|
+
account: connectData.account,
|
|
81
|
+
chainId: connectData.chainId,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<>
|
|
86
|
+
<p>
|
|
87
|
+
This method is used to sign a permit for stake and bake operations. The
|
|
88
|
+
signature is used to approve spending of tokens.
|
|
89
|
+
</p>
|
|
90
|
+
|
|
91
|
+
<div className="mb-4">
|
|
92
|
+
<Button
|
|
93
|
+
onClick={connect}
|
|
94
|
+
disabled={isConnectLoading}
|
|
95
|
+
isLoading={isConnectLoading}
|
|
96
|
+
>
|
|
97
|
+
Connect
|
|
98
|
+
</Button>
|
|
99
|
+
|
|
100
|
+
<CodeBlock text={connectError || formattedConnectData} />
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div className="mb-4">
|
|
104
|
+
<FormControl fullWidth>
|
|
105
|
+
<InputLabel id="expiry-select-label">Expiry Time</InputLabel>
|
|
106
|
+
<Select
|
|
107
|
+
labelId="expiry-select-label"
|
|
108
|
+
value={selectedExpiry}
|
|
109
|
+
label="Expiry Time"
|
|
110
|
+
onChange={e => setSelectedExpiry(e.target.value as ExpiryOption)}
|
|
111
|
+
>
|
|
112
|
+
{Object.keys(EXPIRY_OPTIONS).map(option => (
|
|
113
|
+
<MenuItem key={option} value={option}>
|
|
114
|
+
{option}
|
|
115
|
+
</MenuItem>
|
|
116
|
+
))}
|
|
117
|
+
</Select>
|
|
118
|
+
</FormControl>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<Button
|
|
122
|
+
onClick={refetch}
|
|
123
|
+
disabled={
|
|
124
|
+
isLoading || !connectData || connectData.chainId !== OChainId.holesky
|
|
125
|
+
}
|
|
126
|
+
isLoading={isLoading}
|
|
127
|
+
>
|
|
128
|
+
{nameWithWhitespaces}
|
|
129
|
+
</Button>
|
|
130
|
+
|
|
131
|
+
<CodeBlock
|
|
132
|
+
text={
|
|
133
|
+
error ||
|
|
134
|
+
(data && {
|
|
135
|
+
...data,
|
|
136
|
+
signature: data.signature,
|
|
137
|
+
typedData: data.typedData ? JSON.parse(data.typedData) : '',
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
/>
|
|
141
|
+
</>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { IEnvParam } from '../../common/types/internalTypes';
|
|
2
|
+
import { TChainId } from '../../common/types/types';
|
|
3
|
+
import { Provider } from '../../provider';
|
|
4
|
+
import { IProviderBasedParams } from '../types';
|
|
5
|
+
import { getStakeAndBakeSpenderAddress } from './config';
|
|
6
|
+
import { getStakeAndBakeTypedData } from './getTypedData';
|
|
7
|
+
|
|
8
|
+
const NO_SIGNATURE_ERROR =
|
|
9
|
+
'Failed to obtain a valid signature. The response is undefined or invalid.';
|
|
10
|
+
|
|
11
|
+
export interface ISignStakeAndBakeParams
|
|
12
|
+
extends Pick<IProviderBasedParams, 'provider'>,
|
|
13
|
+
IEnvParam {
|
|
14
|
+
/**
|
|
15
|
+
* The address to sign with (owner)
|
|
16
|
+
*/
|
|
17
|
+
address: string;
|
|
18
|
+
/**
|
|
19
|
+
* Chain ID for the signature
|
|
20
|
+
*/
|
|
21
|
+
chainId: TChainId;
|
|
22
|
+
/**
|
|
23
|
+
* The value to approve
|
|
24
|
+
*/
|
|
25
|
+
value: string;
|
|
26
|
+
/**
|
|
27
|
+
* Expiry date in seconds
|
|
28
|
+
*/
|
|
29
|
+
expiryDate: number;
|
|
30
|
+
/**
|
|
31
|
+
* Optional RPC URL for the network
|
|
32
|
+
*/
|
|
33
|
+
rpcUrl?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ISignStakeAndBakeResult {
|
|
37
|
+
/**
|
|
38
|
+
* The signature
|
|
39
|
+
*/
|
|
40
|
+
signature: string;
|
|
41
|
+
/**
|
|
42
|
+
* The typed data used to generate the signature
|
|
43
|
+
*/
|
|
44
|
+
typedData: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Signs stake and bake authorization with EIP-712
|
|
49
|
+
*
|
|
50
|
+
* @param {ISignStakeAndBakeParams} params - Parameters for signing
|
|
51
|
+
* @returns {Promise<ISignStakeAndBakeResult>} The signature and typed data
|
|
52
|
+
*/
|
|
53
|
+
export async function signStakeAndBake({
|
|
54
|
+
address,
|
|
55
|
+
provider,
|
|
56
|
+
chainId,
|
|
57
|
+
value,
|
|
58
|
+
env,
|
|
59
|
+
expiryDate,
|
|
60
|
+
rpcUrl,
|
|
61
|
+
}: ISignStakeAndBakeParams): Promise<ISignStakeAndBakeResult> {
|
|
62
|
+
const providerInstance = new Provider({
|
|
63
|
+
provider,
|
|
64
|
+
account: address,
|
|
65
|
+
chainId,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const spender = getStakeAndBakeSpenderAddress(chainId);
|
|
69
|
+
|
|
70
|
+
const typedDataObject = await getStakeAndBakeTypedData({
|
|
71
|
+
chainId,
|
|
72
|
+
expiryDate,
|
|
73
|
+
owner: address,
|
|
74
|
+
spender,
|
|
75
|
+
value,
|
|
76
|
+
env,
|
|
77
|
+
rpcUrl,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const typedData = JSON.stringify(typedDataObject);
|
|
81
|
+
|
|
82
|
+
const signature = await providerInstance.web3?.currentProvider?.request<
|
|
83
|
+
'eth_signTypedData_v4',
|
|
84
|
+
string
|
|
85
|
+
>({
|
|
86
|
+
method: 'eth_signTypedData_v4',
|
|
87
|
+
params: [address, typedData],
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (typeof signature === 'string') {
|
|
91
|
+
return { signature, typedData };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!signature?.result) {
|
|
95
|
+
throw new Error(NO_SIGNATURE_ERROR);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return { signature: signature.result, typedData };
|
|
99
|
+
}
|