@lombard.finance/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -0
- package/dist/index.js +12574 -0
- package/dist/index.js.map +1 -0
- package/package.json +55 -0
- package/src/btcSdk/utils/getOutputScript.ts +54 -0
- package/src/common/const.ts +3 -0
- package/src/common/types/internalTypes.ts +8 -0
- package/src/common/types/types.ts +13 -0
- package/src/common/utils/convertSatoshi.ts +21 -0
- package/src/common/utils/getErrorMessage.ts +35 -0
- package/src/common/utils/isValidChain.ts +5 -0
- package/src/index.ts +5 -0
- package/src/provider/Provider.ts +174 -0
- package/src/provider/ReadProvider.ts +120 -0
- package/src/provider/index.ts +2 -0
- package/src/provider/rpcUrlConfig.ts +8 -0
- package/src/provider/types.ts +58 -0
- package/src/provider/utils/getMaxPriorityFeePerGas.ts +25 -0
- package/src/sdk/apiConfig.ts +20 -0
- package/src/sdk/generateDepositBtcAddress/generateDepositBtcAddress.stories.tsx +52 -0
- package/src/sdk/generateDepositBtcAddress/generateDepositBtcAddress.ts +64 -0
- package/src/sdk/generateDepositBtcAddress/index.ts +1 -0
- package/src/sdk/getDepositBtcAddress/getDepositBtcAddress.stories.tsx +53 -0
- package/src/sdk/getDepositBtcAddress/getDepositBtcAddress.ts +101 -0
- package/src/sdk/getDepositBtcAddress/index.ts +1 -0
- package/src/sdk/getDepositsByAddress/getDepositsByAddress.stories.tsx +49 -0
- package/src/sdk/getDepositsByAddress/getDepositsByAddress.ts +146 -0
- package/src/sdk/getDepositsByAddress/index.ts +1 -0
- package/src/sdk/index.ts +3 -0
- package/src/sdk/internalTypes.ts +5 -0
- package/src/sdk/utils/getCainIdByName.ts +21 -0
- package/src/sdk/utils/getChainNameById.ts +17 -0
- package/src/stories/components/Button/Button.tsx +43 -0
- package/src/stories/components/Button/index.ts +1 -0
- package/src/stories/components/CodeBlock/CodeBlock.tsx +24 -0
- package/src/stories/components/CodeBlock/CodeBlockStyles.css +3 -0
- package/src/stories/components/CodeBlock/index.ts +1 -0
- package/src/stories/components/Spinner/Spinner.tsx +25 -0
- package/src/stories/components/Spinner/index.ts +1 -0
- package/src/stories/const.ts +1 -0
- package/src/stories/hooks/useConnect.ts +47 -0
- package/src/stories/hooks/useQuery.ts +56 -0
- package/src/stories/utils/connectInjectedWallet.ts +12 -0
- package/src/stories/utils/fromCamelCase.ts +16 -0
- package/src/stories/utils/getMetaTitle.ts +7 -0
- package/src/stories/utils/getWalletInfo.ts +31 -0
- package/src/vite-env.d.ts +1 -0
- package/src/web3Sdk/abi/IERC20.json +222 -0
- package/src/web3Sdk/abi/LBTC.json +1400 -0
- package/src/web3Sdk/abi/index.ts +4 -0
- package/src/web3Sdk/approveLBTC/approveLBTC.stories.tsx +77 -0
- package/src/web3Sdk/approveLBTC/approveLBTC.ts +48 -0
- package/src/web3Sdk/approveLBTC/index.ts +1 -0
- package/src/web3Sdk/claimLBTC/claimLBTC.stories.tsx +77 -0
- package/src/web3Sdk/claimLBTC/claimLBTC.ts +62 -0
- package/src/web3Sdk/claimLBTC/index.ts +1 -0
- package/src/web3Sdk/index.ts +4 -0
- package/src/web3Sdk/internalTypes.ts +19 -0
- package/src/web3Sdk/lbtcAddressConfig.ts +16 -0
- package/src/web3Sdk/signLbtcDestionationAddr/index.ts +1 -0
- package/src/web3Sdk/signLbtcDestionationAddr/signLbtcDestionationAddr.stories.tsx +97 -0
- package/src/web3Sdk/signLbtcDestionationAddr/signLbtcDestionationAddr.ts +25 -0
- package/src/web3Sdk/unstakeLBTC/index.ts +1 -0
- package/src/web3Sdk/unstakeLBTC/unstakeLBTC.stories.tsx +77 -0
- package/src/web3Sdk/unstakeLBTC/unstakeLBTC.ts +51 -0
- package/src/web3Sdk/utils/getGasMultiplier.ts +19 -0
- package/src/web3Sdk/utils/getLbtcTokenContract.ts +28 -0
- package/src/web3Sdk/utils/getTokenABI.ts +12 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { defaultEnv } from '../../common/const';
|
|
3
|
+
import { Button } from '../../stories/components/Button';
|
|
4
|
+
import { CodeBlock } from '../../stories/components/CodeBlock';
|
|
5
|
+
import { useConnect } from '../../stories/hooks/useConnect';
|
|
6
|
+
import useQuery from '../../stories/hooks/useQuery';
|
|
7
|
+
import { approveLBTC, IApproveLBTCParams } from './approveLBTC';
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: 'Web3SDK/approveLBTC',
|
|
11
|
+
component: StoryView,
|
|
12
|
+
tags: ['autodocs'],
|
|
13
|
+
} satisfies Meta<typeof StoryView>;
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
|
|
17
|
+
type Story = StoryObj<typeof meta>;
|
|
18
|
+
|
|
19
|
+
export const WithParams: Story = {
|
|
20
|
+
args: {
|
|
21
|
+
amount: 0.00001,
|
|
22
|
+
spender: '',
|
|
23
|
+
env: defaultEnv,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type ClaimLBTCProps = Pick<IApproveLBTCParams, 'spender' | 'amount' | 'env'>;
|
|
28
|
+
|
|
29
|
+
export function StoryView(props: ClaimLBTCProps) {
|
|
30
|
+
const {
|
|
31
|
+
data: connectData,
|
|
32
|
+
error: connectError,
|
|
33
|
+
isLoading: isConnectLoading,
|
|
34
|
+
connect,
|
|
35
|
+
} = useConnect();
|
|
36
|
+
|
|
37
|
+
const request = async () => {
|
|
38
|
+
if (!connectData) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return approveLBTC({ ...connectData, ...props });
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const { data, error, isLoading, refetch } = useQuery(request, [], false);
|
|
46
|
+
|
|
47
|
+
const formattedConnectData = connectData && {
|
|
48
|
+
account: connectData.account,
|
|
49
|
+
chainId: connectData.chainId,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
<div className="mb-4">
|
|
55
|
+
<Button
|
|
56
|
+
onClick={connect}
|
|
57
|
+
disabled={isConnectLoading}
|
|
58
|
+
isLoading={isConnectLoading}
|
|
59
|
+
>
|
|
60
|
+
Connect
|
|
61
|
+
</Button>
|
|
62
|
+
|
|
63
|
+
<CodeBlock text={connectError || formattedConnectData} />
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<Button
|
|
67
|
+
onClick={refetch}
|
|
68
|
+
disabled={isLoading || !connectData}
|
|
69
|
+
isLoading={isLoading}
|
|
70
|
+
>
|
|
71
|
+
Approve LBTC
|
|
72
|
+
</Button>
|
|
73
|
+
|
|
74
|
+
<CodeBlock text={error || data} />
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { IEnvParam } from '../../common/types/internalTypes';
|
|
2
|
+
import { toSatoshi } from '../../common/utils/convertSatoshi';
|
|
3
|
+
import { IWeb3SendResult, Provider } from '../../provider';
|
|
4
|
+
import { IProviderBasedParams } from '../internalTypes';
|
|
5
|
+
import { getGasMultiplier } from '../utils/getGasMultiplier';
|
|
6
|
+
import { getLbtcTokenContract } from '../utils/getLbtcTokenContract';
|
|
7
|
+
|
|
8
|
+
export interface IApproveLBTCParams extends IProviderBasedParams, IEnvParam {
|
|
9
|
+
/**
|
|
10
|
+
* Spender address
|
|
11
|
+
*/
|
|
12
|
+
spender: string;
|
|
13
|
+
/**
|
|
14
|
+
* The amount of LBTC to approve
|
|
15
|
+
*/
|
|
16
|
+
amount: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Approves the transfer of a specified amount of LBTC tokens.
|
|
21
|
+
*
|
|
22
|
+
* @param {IApproveLBTCParams} params
|
|
23
|
+
*
|
|
24
|
+
* @returns {Promise<IWeb3SendResult>} transaction promise
|
|
25
|
+
*/
|
|
26
|
+
export function approveLBTC({
|
|
27
|
+
spender,
|
|
28
|
+
amount,
|
|
29
|
+
env,
|
|
30
|
+
...providerParams
|
|
31
|
+
}: IApproveLBTCParams): Promise<IWeb3SendResult> {
|
|
32
|
+
const provider = new Provider(providerParams);
|
|
33
|
+
const tokenContract = getLbtcTokenContract(provider, env);
|
|
34
|
+
const amountSat = toSatoshi(amount);
|
|
35
|
+
|
|
36
|
+
const tx = tokenContract.methods.approve(spender, amountSat);
|
|
37
|
+
|
|
38
|
+
return provider.sendTransactionAsync(
|
|
39
|
+
provider.account,
|
|
40
|
+
tokenContract.options.address,
|
|
41
|
+
{
|
|
42
|
+
data: tx.encodeABI(),
|
|
43
|
+
estimate: true,
|
|
44
|
+
estimateFee: true,
|
|
45
|
+
gasLimitMultiplier: getGasMultiplier(provider.chainId),
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './approveLBTC';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { defaultEnv } from '../../common/const';
|
|
3
|
+
import { Button } from '../../stories/components/Button';
|
|
4
|
+
import { CodeBlock } from '../../stories/components/CodeBlock';
|
|
5
|
+
import { useConnect } from '../../stories/hooks/useConnect';
|
|
6
|
+
import useQuery from '../../stories/hooks/useQuery';
|
|
7
|
+
import { claimLBTC, IClaimLBTCParams } from './claimLBTC';
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: 'Web3SDK/claimLBTC',
|
|
11
|
+
component: StoryView,
|
|
12
|
+
tags: ['autodocs'],
|
|
13
|
+
} satisfies Meta<typeof StoryView>;
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
|
|
17
|
+
type Story = StoryObj<typeof meta>;
|
|
18
|
+
|
|
19
|
+
export const WithParams: Story = {
|
|
20
|
+
args: {
|
|
21
|
+
proofSignature: '',
|
|
22
|
+
data: '',
|
|
23
|
+
env: defaultEnv,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type ClaimLBTCProps = Pick<IClaimLBTCParams, 'data' | 'env' | 'proofSignature'>;
|
|
28
|
+
|
|
29
|
+
export function StoryView(props: ClaimLBTCProps) {
|
|
30
|
+
const {
|
|
31
|
+
data: connectData,
|
|
32
|
+
error: connectError,
|
|
33
|
+
isLoading: isConnectLoading,
|
|
34
|
+
connect,
|
|
35
|
+
} = useConnect();
|
|
36
|
+
|
|
37
|
+
const request = async () => {
|
|
38
|
+
if (!connectData) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return claimLBTC({ ...connectData, ...props });
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const { data, error, isLoading, refetch } = useQuery(request, [], false);
|
|
46
|
+
|
|
47
|
+
const formattedConnectData = connectData && {
|
|
48
|
+
account: connectData.account,
|
|
49
|
+
chainId: connectData.chainId,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
<div className="mb-4">
|
|
55
|
+
<Button
|
|
56
|
+
onClick={connect}
|
|
57
|
+
disabled={isConnectLoading}
|
|
58
|
+
isLoading={isConnectLoading}
|
|
59
|
+
>
|
|
60
|
+
Connect
|
|
61
|
+
</Button>
|
|
62
|
+
|
|
63
|
+
<CodeBlock text={connectError || formattedConnectData} />
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<Button
|
|
67
|
+
onClick={refetch}
|
|
68
|
+
disabled={isLoading || !connectData}
|
|
69
|
+
isLoading={isLoading}
|
|
70
|
+
>
|
|
71
|
+
Claim LBTC
|
|
72
|
+
</Button>
|
|
73
|
+
|
|
74
|
+
<CodeBlock text={error || data} />
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { IEnvParam } from '../../common/types/internalTypes';
|
|
2
|
+
import { getErrorMessage } from '../../common/utils/getErrorMessage';
|
|
3
|
+
import { IWeb3SendResult, Provider } from '../../provider';
|
|
4
|
+
import { IProviderBasedParams } from '../internalTypes';
|
|
5
|
+
import { getGasMultiplier } from '../utils/getGasMultiplier';
|
|
6
|
+
import { getLbtcTokenContract } from '../utils/getLbtcTokenContract';
|
|
7
|
+
|
|
8
|
+
const INSUFFICIENT_FUNDS_PARTIAL_ERROR = 'insufficient funds';
|
|
9
|
+
const INSUFFICIENT_FUNDS_ERROR = 'Insufficient funds for transfer';
|
|
10
|
+
|
|
11
|
+
export interface IClaimLBTCParams extends IProviderBasedParams, IEnvParam {
|
|
12
|
+
/**
|
|
13
|
+
* Raw payload from deposit notarization.
|
|
14
|
+
*/
|
|
15
|
+
data: string;
|
|
16
|
+
/**
|
|
17
|
+
* Signature from deposit notarization.
|
|
18
|
+
*/
|
|
19
|
+
proofSignature: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Claims LBTC.
|
|
24
|
+
*
|
|
25
|
+
* @param {IClaimLBTCParams} params - The parameters for claiming LBTC.
|
|
26
|
+
*
|
|
27
|
+
* @returns {Promise<IWeb3SendResult>} transaction promise
|
|
28
|
+
*/
|
|
29
|
+
export async function claimLBTC({
|
|
30
|
+
data,
|
|
31
|
+
proofSignature,
|
|
32
|
+
env,
|
|
33
|
+
...providerParams
|
|
34
|
+
}: IClaimLBTCParams): Promise<IWeb3SendResult> {
|
|
35
|
+
const provider = new Provider(providerParams);
|
|
36
|
+
const tokenContract = getLbtcTokenContract(provider, env);
|
|
37
|
+
|
|
38
|
+
const tx = tokenContract.methods.mint(data, proofSignature);
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const result = await provider.sendTransactionAsync(
|
|
42
|
+
provider.account,
|
|
43
|
+
tokenContract.options.address,
|
|
44
|
+
{
|
|
45
|
+
data: tx.encodeABI(),
|
|
46
|
+
estimate: true,
|
|
47
|
+
estimateFee: true,
|
|
48
|
+
gasLimitMultiplier: getGasMultiplier(provider.chainId),
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return result;
|
|
53
|
+
} catch (error) {
|
|
54
|
+
const errorMessage = getErrorMessage(error);
|
|
55
|
+
|
|
56
|
+
if (errorMessage.includes(INSUFFICIENT_FUNDS_PARTIAL_ERROR)) {
|
|
57
|
+
throw new Error(INSUFFICIENT_FUNDS_ERROR);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
throw new Error(errorMessage);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './claimLBTC';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Web3 from 'web3';
|
|
2
|
+
import { TChainId } from '../common/types/types';
|
|
3
|
+
|
|
4
|
+
export interface IProviderBasedParams {
|
|
5
|
+
/**
|
|
6
|
+
* The web3 instance with write access.
|
|
7
|
+
*
|
|
8
|
+
* {@inheritDoc Web3}
|
|
9
|
+
*/
|
|
10
|
+
web3: Web3;
|
|
11
|
+
/**
|
|
12
|
+
* Current chain ID
|
|
13
|
+
*/
|
|
14
|
+
chainId: TChainId;
|
|
15
|
+
/**
|
|
16
|
+
* Current account address
|
|
17
|
+
*/
|
|
18
|
+
account: string;
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defaultEnv } from '../common/const';
|
|
2
|
+
import { OChainId, TChainId, TEnv } from '../common/types/types';
|
|
3
|
+
|
|
4
|
+
type LbtcTokenConfig = Partial<Record<TChainId, string>>;
|
|
5
|
+
|
|
6
|
+
const testnetConfig: LbtcTokenConfig = {
|
|
7
|
+
[OChainId.holesky]: '0xED7bfd5C1790576105Af4649817f6d35A75CD818',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const mainnetConfig: LbtcTokenConfig = {
|
|
11
|
+
[OChainId.ethereum]: '0x8236a87084f8b84306f72007f36f2618a5634494',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function getLbtcAddressConfig(env: TEnv = defaultEnv): LbtcTokenConfig {
|
|
15
|
+
return env === 'prod' ? mainnetConfig : testnetConfig;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './signLbtcDestionationAddr';
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Meta } from '@storybook/react';
|
|
2
|
+
import Web3, { FMT_BYTES, FMT_NUMBER } from 'web3';
|
|
3
|
+
import { OChainId, TChainId } from '../../common/types/types';
|
|
4
|
+
import { Button } from '../../stories/components/Button';
|
|
5
|
+
import { CodeBlock } from '../../stories/components/CodeBlock';
|
|
6
|
+
import { useConnect } from '../../stories/hooks/useConnect';
|
|
7
|
+
import useQuery from '../../stories/hooks/useQuery';
|
|
8
|
+
import { fromCamelCase } from '../../stories/utils/fromCamelCase';
|
|
9
|
+
import { signLbtcDestionationAddr } from './signLbtcDestionationAddr';
|
|
10
|
+
|
|
11
|
+
const { name } = signLbtcDestionationAddr;
|
|
12
|
+
const nameWithWhitespaces = fromCamelCase(name);
|
|
13
|
+
|
|
14
|
+
const meta = {
|
|
15
|
+
title: 'Web3SDK/signLbtcDestionationAddr',
|
|
16
|
+
component: StoryView,
|
|
17
|
+
tags: ['autodocs'],
|
|
18
|
+
} satisfies Meta<typeof StoryView>;
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
|
|
22
|
+
export function StoryView() {
|
|
23
|
+
const {
|
|
24
|
+
data: connectData,
|
|
25
|
+
error: connectError,
|
|
26
|
+
isLoading: isConnectLoading,
|
|
27
|
+
connect,
|
|
28
|
+
} = useConnect();
|
|
29
|
+
|
|
30
|
+
const request = async () => {
|
|
31
|
+
if (!connectData) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return signLbtcDestionationAddr(connectData);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const { data, error, isLoading, refetch } = useQuery(request, [], false);
|
|
39
|
+
|
|
40
|
+
const formattedConnectData = connectData && {
|
|
41
|
+
account: connectData.account,
|
|
42
|
+
chainId: connectData.chainId,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<>
|
|
47
|
+
<p>
|
|
48
|
+
This method is used to get the signature of the Liquid BTC destination
|
|
49
|
+
address. The signature is used for generating the deposit address.
|
|
50
|
+
</p>
|
|
51
|
+
|
|
52
|
+
<div className="mb-4">
|
|
53
|
+
<Button
|
|
54
|
+
onClick={connect}
|
|
55
|
+
disabled={isConnectLoading}
|
|
56
|
+
isLoading={isConnectLoading}
|
|
57
|
+
>
|
|
58
|
+
Connect
|
|
59
|
+
</Button>
|
|
60
|
+
|
|
61
|
+
<CodeBlock text={connectError || formattedConnectData} />
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<Button
|
|
65
|
+
onClick={refetch}
|
|
66
|
+
disabled={isLoading || !connectData}
|
|
67
|
+
isLoading={isLoading}
|
|
68
|
+
>
|
|
69
|
+
{nameWithWhitespaces}
|
|
70
|
+
</Button>
|
|
71
|
+
|
|
72
|
+
<CodeBlock text={error || data} />
|
|
73
|
+
</>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function getWalletInfo(web3: Web3) {
|
|
78
|
+
const [account] = await web3.eth.getAccounts();
|
|
79
|
+
|
|
80
|
+
if (!account) {
|
|
81
|
+
throw new Error('No account found');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const chainId = await web3.eth.getChainId({
|
|
85
|
+
bytes: FMT_BYTES.HEX,
|
|
86
|
+
number: FMT_NUMBER.NUMBER,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
account,
|
|
91
|
+
chainId,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function isValidChain(chainId: number): chainId is TChainId {
|
|
96
|
+
return Object.values(OChainId).includes(chainId as TChainId);
|
|
97
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Provider } from '../../provider';
|
|
2
|
+
import { IProviderBasedParams } from '../internalTypes';
|
|
3
|
+
|
|
4
|
+
export type SignLbtcDestionationAddrParams = IProviderBasedParams;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Signs the destination address for the LBTC in active chain
|
|
8
|
+
* in the current account. Signing is necessary for the
|
|
9
|
+
* generation of the deposit address.
|
|
10
|
+
*
|
|
11
|
+
* @param {SignLbtcDestionationAddrParams} params - The parameters for signing the destination address.
|
|
12
|
+
*
|
|
13
|
+
* @returns {Promise<string>} The signature of the message.
|
|
14
|
+
*/
|
|
15
|
+
export async function signLbtcDestionationAddr({
|
|
16
|
+
web3,
|
|
17
|
+
chainId,
|
|
18
|
+
account,
|
|
19
|
+
}: SignLbtcDestionationAddrParams): Promise<string> {
|
|
20
|
+
const provider = new Provider({ web3, chainId, account });
|
|
21
|
+
|
|
22
|
+
const message = `destination chain id is ${chainId}`;
|
|
23
|
+
|
|
24
|
+
return provider.signMessage(message);
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './unstakeLBTC';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { defaultEnv } from '../../common/const';
|
|
3
|
+
import { Button } from '../../stories/components/Button';
|
|
4
|
+
import { CodeBlock } from '../../stories/components/CodeBlock';
|
|
5
|
+
import { useConnect } from '../../stories/hooks/useConnect';
|
|
6
|
+
import useQuery from '../../stories/hooks/useQuery';
|
|
7
|
+
import { IUnstakeLBTCParams, unstakeLBTC } from './unstakeLBTC';
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: 'Web3SDK/unstakeLBTC',
|
|
11
|
+
component: StoryView,
|
|
12
|
+
tags: ['autodocs'],
|
|
13
|
+
} satisfies Meta<typeof StoryView>;
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
|
|
17
|
+
type Story = StoryObj<typeof meta>;
|
|
18
|
+
|
|
19
|
+
export const WithParams: Story = {
|
|
20
|
+
args: {
|
|
21
|
+
amount: 0.00001,
|
|
22
|
+
btcAddress: '',
|
|
23
|
+
env: defaultEnv,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type ClaimLBTCProps = Pick<IUnstakeLBTCParams, 'btcAddress' | 'env' | 'amount'>;
|
|
28
|
+
|
|
29
|
+
export function StoryView(props: ClaimLBTCProps) {
|
|
30
|
+
const {
|
|
31
|
+
data: connectData,
|
|
32
|
+
error: connectError,
|
|
33
|
+
isLoading: isConnectLoading,
|
|
34
|
+
connect,
|
|
35
|
+
} = useConnect();
|
|
36
|
+
|
|
37
|
+
const request = async () => {
|
|
38
|
+
if (!connectData) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return unstakeLBTC({ ...connectData, ...props });
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const { data, error, isLoading, refetch } = useQuery(request, [], false);
|
|
46
|
+
|
|
47
|
+
const formattedConnectData = connectData && {
|
|
48
|
+
account: connectData.account,
|
|
49
|
+
chainId: connectData.chainId,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
<div className="mb-4">
|
|
55
|
+
<Button
|
|
56
|
+
onClick={connect}
|
|
57
|
+
disabled={isConnectLoading}
|
|
58
|
+
isLoading={isConnectLoading}
|
|
59
|
+
>
|
|
60
|
+
Connect
|
|
61
|
+
</Button>
|
|
62
|
+
|
|
63
|
+
<CodeBlock text={connectError || formattedConnectData} />
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<Button
|
|
67
|
+
onClick={refetch}
|
|
68
|
+
disabled={isLoading || !connectData}
|
|
69
|
+
isLoading={isLoading}
|
|
70
|
+
>
|
|
71
|
+
Unstake LBTC
|
|
72
|
+
</Button>
|
|
73
|
+
|
|
74
|
+
<CodeBlock text={error || data} />
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getOutputScript } from '../../btcSdk/utils/getOutputScript';
|
|
2
|
+
import { IEnvParam } from '../../common/types/internalTypes';
|
|
3
|
+
import { toSatoshi } from '../../common/utils/convertSatoshi';
|
|
4
|
+
import { IWeb3SendResult, Provider } from '../../provider';
|
|
5
|
+
import { IProviderBasedParams } from '../internalTypes';
|
|
6
|
+
import { getGasMultiplier } from '../utils/getGasMultiplier';
|
|
7
|
+
import { getLbtcTokenContract } from '../utils/getLbtcTokenContract';
|
|
8
|
+
|
|
9
|
+
export interface IUnstakeLBTCParams extends IProviderBasedParams, IEnvParam {
|
|
10
|
+
/**
|
|
11
|
+
* The BTC address to send the BTC to.
|
|
12
|
+
*/
|
|
13
|
+
btcAddress: string;
|
|
14
|
+
/**
|
|
15
|
+
* The amount of LBTC to unstake.
|
|
16
|
+
*/
|
|
17
|
+
amount: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Unstakes LBTC to the specified BTC address.
|
|
22
|
+
*
|
|
23
|
+
* @param {IUnstakeLBTCParams} params
|
|
24
|
+
*
|
|
25
|
+
* @returns {Promise<IWeb3SendResult>} transaction promise
|
|
26
|
+
*/
|
|
27
|
+
export function unstakeLBTC({
|
|
28
|
+
btcAddress,
|
|
29
|
+
amount,
|
|
30
|
+
env,
|
|
31
|
+
...providerParams
|
|
32
|
+
}: IUnstakeLBTCParams): Promise<IWeb3SendResult> {
|
|
33
|
+
const provider = new Provider(providerParams);
|
|
34
|
+
const tokenContract = getLbtcTokenContract(provider, env);
|
|
35
|
+
const outputScript = getOutputScript(btcAddress, env);
|
|
36
|
+
|
|
37
|
+
const amountSat = toSatoshi(amount);
|
|
38
|
+
|
|
39
|
+
const tx = tokenContract.methods.burn(outputScript, amountSat);
|
|
40
|
+
|
|
41
|
+
return provider.sendTransactionAsync(
|
|
42
|
+
provider.account,
|
|
43
|
+
tokenContract.options.address,
|
|
44
|
+
{
|
|
45
|
+
data: tx.encodeABI(),
|
|
46
|
+
estimate: true,
|
|
47
|
+
estimateFee: true,
|
|
48
|
+
gasLimitMultiplier: getGasMultiplier(provider.chainId),
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { OChainId } from '../../common/types/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns the gas multiplier for the given chain ID.
|
|
5
|
+
*
|
|
6
|
+
* @param chainId - Chain ID.
|
|
7
|
+
*
|
|
8
|
+
* @returns Gas multiplier.
|
|
9
|
+
*/
|
|
10
|
+
export function getGasMultiplier(chainId: number): number {
|
|
11
|
+
switch (chainId) {
|
|
12
|
+
case OChainId.ethereum:
|
|
13
|
+
return 1.3;
|
|
14
|
+
case OChainId.holesky:
|
|
15
|
+
return 1.5;
|
|
16
|
+
default:
|
|
17
|
+
return 1.3;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { TChainId, TEnv } from '../../common/types/types';
|
|
2
|
+
import { Provider } from '../../provider';
|
|
3
|
+
import { getLbtcAddressConfig } from '../lbtcAddressConfig';
|
|
4
|
+
import { getTokenABI } from './getTokenABI';
|
|
5
|
+
|
|
6
|
+
export function getLbtcTokenContract(provider: Provider, env?: TEnv) {
|
|
7
|
+
const lbtcAddressConfig = getLbtcAddressConfig(env);
|
|
8
|
+
|
|
9
|
+
const tokenAddress = lbtcAddressConfig[provider.chainId as TChainId];
|
|
10
|
+
|
|
11
|
+
if (!tokenAddress) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
`Token address for chain ${provider.chainId} is not defined`,
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const abi = getTokenABI('LBTC');
|
|
18
|
+
|
|
19
|
+
const contract = provider.createContract(abi, tokenAddress);
|
|
20
|
+
|
|
21
|
+
if (!contract.options.address) {
|
|
22
|
+
contract.options.address = tokenAddress;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return contract as typeof contract & {
|
|
26
|
+
options: typeof contract.options & { address: string };
|
|
27
|
+
};
|
|
28
|
+
}
|