@lombard.finance/sdk-sui 1.0.1
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 +90 -0
- package/package.json +58 -0
- package/src/common/parameters.ts +16 -0
- package/src/const/const.ts +3 -0
- package/src/const/errors.ts +4 -0
- package/src/const/getConfig.ts +101 -0
- package/src/const/index.ts +3 -0
- package/src/getUnifiedChainId.ts +30 -0
- package/src/index.ts +9 -0
- package/src/rewards/index.ts +1 -0
- package/src/rewards/lib/claim-reward.ts +106 -0
- package/src/vite-env.d.ts +1 -0
- package/src/web3Sdk/claimLBTC/claimLBTC.ts +89 -0
- package/src/web3Sdk/claimLBTC/index.ts +1 -0
- package/src/web3Sdk/getAllCoinsOfType/getAllCoinsOfType.ts +32 -0
- package/src/web3Sdk/getAllCoinsOfType/index.ts +1 -0
- package/src/web3Sdk/getBalance/getBalance.ts +41 -0
- package/src/web3Sdk/getBalance/index.ts +1 -0
- package/src/web3Sdk/prepareAmount/index.ts +1 -0
- package/src/web3Sdk/prepareAmount/prepareCoinsTransaction.ts +88 -0
- package/src/web3Sdk/signLbtcDestionationAddrSui/index.ts +1 -0
- package/src/web3Sdk/signLbtcDestionationAddrSui/signLbtcDestinationAddrSui.ts +44 -0
- package/src/web3Sdk/signTermsOfService/index.ts +1 -0
- package/src/web3Sdk/signTermsOfService/signTermsOfService.ts +32 -0
- package/src/web3Sdk/unstakeLBTC/index.ts +1 -0
- package/src/web3Sdk/unstakeLBTC/unstakeLBTC.ts +69 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# @lombard.finance/sdk-sui
|
|
2
|
+
|
|
3
|
+
The Lombard's SDK SUI package provides a set of functions that allow interacting with the Lombard protocol and its features on SUI.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lombard.finance/sdk @lombard.finance/sdk-sui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Generating a BTC deposit address
|
|
14
|
+
|
|
15
|
+
Similar to the EVM SDK (`@lombard.finance/sdk`) the generation of the deposit address requires a signature.
|
|
16
|
+
To successfully generate a deposit address run `signLbtcDestinationAddrSui` and then use the generated signature as a parameter of the EVM SDK's `generateDepositBtcAddress`.
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
|
|
20
|
+
const { signature } = await signLbtcDestinationAddrSui({
|
|
21
|
+
// The Sui chain id
|
|
22
|
+
chainId: SUI_MAINNET_CHAIN,
|
|
23
|
+
// The Sui wallet provider, see `@wallet-standard/base`
|
|
24
|
+
wallet,
|
|
25
|
+
// The wallet account, see `@wallet-standard/core`
|
|
26
|
+
account,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const depositAddress = await generateDepositBtcAddress({
|
|
30
|
+
// The connected address
|
|
31
|
+
address,
|
|
32
|
+
// The chosen Solana chain (network) - prefixed with `solana:`
|
|
33
|
+
chainId: SUI_MAINNET_CHAIN,
|
|
34
|
+
// The generated signature:
|
|
35
|
+
signature,
|
|
36
|
+
// Optional env
|
|
37
|
+
env: Env.prod,
|
|
38
|
+
// Optional partnerId
|
|
39
|
+
partnerId,
|
|
40
|
+
}),
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Claiming LBTC
|
|
45
|
+
|
|
46
|
+
This operation mints the deposited amount of BTC into LBTC and transfers that
|
|
47
|
+
to the provided recipient address.
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
const { digest } = await claimLBTC({
|
|
51
|
+
// The Sui chain id
|
|
52
|
+
chainId: SUI_MAINNET_CHAIN,
|
|
53
|
+
// The Sui wallet provider, see `@wallet-standard/base`
|
|
54
|
+
wallet,
|
|
55
|
+
// The raw paylod from a deposit, obtained from `getDepositsByAddress`
|
|
56
|
+
payload,
|
|
57
|
+
// The proof of a deposit, obtained from `getDepositsByAddress
|
|
58
|
+
proof,
|
|
59
|
+
// The wallet account, see `@wallet-standard/core`
|
|
60
|
+
walletAccount,
|
|
61
|
+
// The Sui client, see @mysten/sui/client
|
|
62
|
+
client,
|
|
63
|
+
// Optional env
|
|
64
|
+
env = Env.prod,
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Unstaking LBTC
|
|
69
|
+
|
|
70
|
+
This operation burns given amount of LBTC and initiates transfer of BTC to the
|
|
71
|
+
given BTC address.
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
const { digest } = await unstakeLBTC({
|
|
75
|
+
// The Sui chain id
|
|
76
|
+
chainId,
|
|
77
|
+
// The Sui wallet provider, see `@wallet-standard/base`
|
|
78
|
+
wallet,
|
|
79
|
+
// The wallet account, see `@wallet-standard/core`
|
|
80
|
+
walletAccount,
|
|
81
|
+
// The Sui client, see @mysten/sui/client
|
|
82
|
+
client,
|
|
83
|
+
// The BTC destination address
|
|
84
|
+
btcAddress,
|
|
85
|
+
// The amount of LBTC to unstake, e.g. BigNumber(1.2)
|
|
86
|
+
amount,
|
|
87
|
+
// Optional env
|
|
88
|
+
env = Env.prod,
|
|
89
|
+
});
|
|
90
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lombard.finance/sdk-sui",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"exports": {
|
|
5
|
+
".": {
|
|
6
|
+
"import": "./dist/index.js",
|
|
7
|
+
"require": "./dist/index.cjs",
|
|
8
|
+
"types": "./src/index.ts"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"types": "./src/index.ts",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src"
|
|
17
|
+
],
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">= 22.14.0"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build-docs": "rimraf ./sdk-docs && typedoc --out sdk-docs",
|
|
23
|
+
"build-storybook": "storybook build -o sdk-storybook",
|
|
24
|
+
"build": "yarn types && vite build",
|
|
25
|
+
"lint": "biome lint",
|
|
26
|
+
"storybook": "storybook dev -p 6006",
|
|
27
|
+
"types": "tsc --noEmit"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@bitcoin-js/tiny-secp256k1-asmjs": "2.2.3",
|
|
31
|
+
"axios": "^1",
|
|
32
|
+
"bignumber.js": "^9",
|
|
33
|
+
"bitcoinjs-lib": "6.1.5",
|
|
34
|
+
"web3": "^4"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@lombard.finance/sdk-common": "^3.0.0",
|
|
38
|
+
"@lombard.finance/sdk": "^3.1.0",
|
|
39
|
+
"@mysten/sui": "^1.21.1"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@chromatic-com/storybook": "1.6.1",
|
|
43
|
+
"@storybook/addon-essentials": "^8.2.9",
|
|
44
|
+
"@storybook/addon-interactions": "^8.2.9",
|
|
45
|
+
"@storybook/addon-links": "^8.2.9",
|
|
46
|
+
"@storybook/addon-onboarding": "^8.2.9",
|
|
47
|
+
"@storybook/blocks": "^8.2.9",
|
|
48
|
+
"@storybook/react": "^8.2.9",
|
|
49
|
+
"@storybook/react-vite": "^8.2.9",
|
|
50
|
+
"@storybook/test": "^8.2.9",
|
|
51
|
+
"axios": "^1.7.4",
|
|
52
|
+
"bignumber.js": "^9.1.2",
|
|
53
|
+
"rimraf": "^5",
|
|
54
|
+
"storybook": "^8.2.9",
|
|
55
|
+
"typedoc": "^0.26.6",
|
|
56
|
+
"typescript": "^5.4.5"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Env } from '@lombard.finance/sdk-common';
|
|
2
|
+
import {
|
|
3
|
+
Wallet,
|
|
4
|
+
WalletAccount,
|
|
5
|
+
WalletWithFeatures,
|
|
6
|
+
} from '@wallet-standard/base';
|
|
7
|
+
|
|
8
|
+
type EnvParameter = {
|
|
9
|
+
env?: Env;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export interface CommonWriteParameters<WF extends Wallet['features']>
|
|
13
|
+
extends EnvParameter {
|
|
14
|
+
walletClient: WalletWithFeatures<WF>;
|
|
15
|
+
account: WalletAccount;
|
|
16
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { DEFAULT_ENV, Env } from '@lombard.finance/sdk-common';
|
|
2
|
+
|
|
3
|
+
interface IConfig {
|
|
4
|
+
mint: {
|
|
5
|
+
target: `0x${string}::treasury::${'mint' | 'mint_v2'}`;
|
|
6
|
+
denyList: `0x${string}`;
|
|
7
|
+
};
|
|
8
|
+
redeem: {
|
|
9
|
+
target: `0x${string}::treasury::redeem`;
|
|
10
|
+
};
|
|
11
|
+
LBTC: `0x${string}::lbtc::LBTC`;
|
|
12
|
+
treasuryAddress: `0x${string}`;
|
|
13
|
+
consortiumAddress: `0x${string}`;
|
|
14
|
+
bascule: `0x${string}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// https://github.com/lombard-finance/sui-contracts/blob/main/staging.json
|
|
18
|
+
const stageConfig: IConfig = {
|
|
19
|
+
mint: {
|
|
20
|
+
target:
|
|
21
|
+
// lbtc_v2_current
|
|
22
|
+
'0x2721ad6e939baca77b36f415ab91edb1c91b256cbc8614f8f6c84bf06faf74af::treasury::mint',
|
|
23
|
+
denyList: '0x403',
|
|
24
|
+
},
|
|
25
|
+
redeem: {
|
|
26
|
+
// lbtc_v2_current
|
|
27
|
+
target:
|
|
28
|
+
'0x2721ad6e939baca77b36f415ab91edb1c91b256cbc8614f8f6c84bf06faf74af::treasury::redeem',
|
|
29
|
+
},
|
|
30
|
+
// lbtc_v1_deprecated - This is intentional
|
|
31
|
+
LBTC: '0x2d66430a27565b912f21be970e5ae1e8c0359f0b518c3235b751c75976791ce0::lbtc::LBTC',
|
|
32
|
+
// objects.treasury
|
|
33
|
+
treasuryAddress:
|
|
34
|
+
'0xf9621182bf6af94142e81f5c268d1a959991df2766a5b0755c528b70e5b33531',
|
|
35
|
+
// objects.consortium
|
|
36
|
+
consortiumAddress:
|
|
37
|
+
'0xd8a7bff969c0f7069ccda1601516fc93013d8c06835646f718d7d345409340cc',
|
|
38
|
+
// objects.bascule
|
|
39
|
+
bascule: '0x61cf6760a04f4af6938543e1e9c0b84f7b271cf9069f0cb6c8017093fd814c68',
|
|
40
|
+
} as const;
|
|
41
|
+
|
|
42
|
+
// https://github.com/lombard-finance/sui-contracts/blob/main/gastald.json
|
|
43
|
+
const testnetConfig: IConfig = {
|
|
44
|
+
mint: {
|
|
45
|
+
// lbtc_v2_current
|
|
46
|
+
target:
|
|
47
|
+
'0xbe409fa89cd3eedbe426fdae9c53a231f2fff9dc66c3ca797163b5b5b2aba977::treasury::mint_v2',
|
|
48
|
+
denyList: '0x403',
|
|
49
|
+
},
|
|
50
|
+
redeem: {
|
|
51
|
+
// lbtc_v2_current
|
|
52
|
+
target:
|
|
53
|
+
'0xbe409fa89cd3eedbe426fdae9c53a231f2fff9dc66c3ca797163b5b5b2aba977::treasury::redeem',
|
|
54
|
+
},
|
|
55
|
+
// lbtc_v1_deprecated - This is intentional
|
|
56
|
+
LBTC: '0x50454d0b0fbad1288a6ab74f2e8ce0905a3317870673ab7787ebcf6f322b45fa::lbtc::LBTC',
|
|
57
|
+
// objects.treasury
|
|
58
|
+
treasuryAddress:
|
|
59
|
+
'0xc8f3d6d596ed86012a289166400d3650d9f888f612bf9c35b0cde7bc1b053408',
|
|
60
|
+
// objects.consortium
|
|
61
|
+
consortiumAddress:
|
|
62
|
+
'0x5d0922bfc25cd4babc76e7e320b0e9b4d4950408bae9632a5fedf2a1f8dc29dc',
|
|
63
|
+
// objects.bascule
|
|
64
|
+
bascule: '0xd8b1c1f9b893330180fa1fc52a316461a5fabd258fa15633e9a5ba5da71af49e',
|
|
65
|
+
} as const;
|
|
66
|
+
|
|
67
|
+
// https://github.com/lombard-finance/sui-contracts/blob/main/mainnet.json
|
|
68
|
+
const prodConfig: IConfig = {
|
|
69
|
+
mint: {
|
|
70
|
+
// lbtc_v2_current
|
|
71
|
+
target:
|
|
72
|
+
'0x818430a456ff977f7320f78650d19801f90758d200a01dd3c2c679472c521357::treasury::mint_v2',
|
|
73
|
+
denyList: '0x403',
|
|
74
|
+
},
|
|
75
|
+
redeem: {
|
|
76
|
+
// lbtc_v2_current
|
|
77
|
+
target:
|
|
78
|
+
'0x818430a456ff977f7320f78650d19801f90758d200a01dd3c2c679472c521357::treasury::redeem',
|
|
79
|
+
},
|
|
80
|
+
// lbtc_v1_deprecated - This is intentional
|
|
81
|
+
LBTC: '0x3e8e9423d80e1774a7ca128fccd8bf5f1f7753be658c5e645929037f7c819040::lbtc::LBTC',
|
|
82
|
+
// objects.treasury
|
|
83
|
+
treasuryAddress:
|
|
84
|
+
'0x1adadbca040f368abd554ac55e7c216ea6df2ff891fc647f037d66669661584a',
|
|
85
|
+
// objects.consortium
|
|
86
|
+
consortiumAddress:
|
|
87
|
+
'0x9f68fe752d0879d615415e39207f0363a6fc8e0b3b335e976f5f18b31f55faf3',
|
|
88
|
+
// objects.bascule
|
|
89
|
+
bascule: '0x138938cb496cf0900be970dde1407d86497b8c69182cb5aa22dc4767c92bedcc',
|
|
90
|
+
} as const;
|
|
91
|
+
|
|
92
|
+
export function getConfig(env: Env = DEFAULT_ENV): typeof prodConfig {
|
|
93
|
+
switch (env) {
|
|
94
|
+
case Env.prod:
|
|
95
|
+
return prodConfig;
|
|
96
|
+
case Env.testnet:
|
|
97
|
+
return testnetConfig;
|
|
98
|
+
default:
|
|
99
|
+
return stageConfig;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SuiChain,
|
|
3
|
+
SUI_TESTNET_CHAIN,
|
|
4
|
+
SUI_MAINNET_CHAIN,
|
|
5
|
+
} from '@mysten/wallet-standard';
|
|
6
|
+
|
|
7
|
+
const ERROR_NOT_FOUND_UNIFIED_ID = new Error("Unified ID hasn't been found");
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* It's an internal type defined by the backend.
|
|
11
|
+
* The main purpose is the unification of chain IDs for different networks.
|
|
12
|
+
*/
|
|
13
|
+
const UnifiedChainId = {
|
|
14
|
+
[SUI_TESTNET_CHAIN]:
|
|
15
|
+
'452312848583266388373324160190187140051835877600158453279131187532193639852',
|
|
16
|
+
[SUI_MAINNET_CHAIN]:
|
|
17
|
+
'452312848583266388373324160190187140051835877600158453279131187531808459402',
|
|
18
|
+
} as Record<SuiChain, string>;
|
|
19
|
+
|
|
20
|
+
type UnifiedChainId = (typeof UnifiedChainId)[keyof typeof UnifiedChainId];
|
|
21
|
+
|
|
22
|
+
export function getUnifiedChainId(chainId: SuiChain) {
|
|
23
|
+
const unifiedChainId = UnifiedChainId[chainId];
|
|
24
|
+
|
|
25
|
+
if (!unifiedChainId) {
|
|
26
|
+
throw ERROR_NOT_FOUND_UNIFIED_ID;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return unifiedChainId;
|
|
30
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './web3Sdk/signLbtcDestionationAddrSui';
|
|
2
|
+
export * from './web3Sdk/claimLBTC';
|
|
3
|
+
export * from './web3Sdk/getBalance';
|
|
4
|
+
export * from './web3Sdk/unstakeLBTC';
|
|
5
|
+
export * from './web3Sdk/signTermsOfService';
|
|
6
|
+
export * from './const';
|
|
7
|
+
|
|
8
|
+
// Rewards:
|
|
9
|
+
export * from './rewards';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { claimReward, type ClaimRewardParameters } from './lib/claim-reward';
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import BigNumber from 'bignumber.js';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import { CommonWriteParameters } from '../../common/parameters';
|
|
4
|
+
import { SuiSignPersonalMessageFeature } from '@mysten/wallet-standard';
|
|
5
|
+
import {
|
|
6
|
+
getApiConfig,
|
|
7
|
+
getRewardSigningData,
|
|
8
|
+
getRewardWithdrawalFee,
|
|
9
|
+
isRewardTokenSupported,
|
|
10
|
+
RewardToken,
|
|
11
|
+
RewardWithdrawal,
|
|
12
|
+
RewardWithdrawalStatus,
|
|
13
|
+
} from '@lombard.finance/sdk';
|
|
14
|
+
|
|
15
|
+
type Response = {
|
|
16
|
+
withdrawal: {
|
|
17
|
+
account_id: string;
|
|
18
|
+
amount: string;
|
|
19
|
+
created_at: string;
|
|
20
|
+
fee: string;
|
|
21
|
+
id: string;
|
|
22
|
+
nonce: string;
|
|
23
|
+
signature: string;
|
|
24
|
+
status: RewardWithdrawalStatus;
|
|
25
|
+
to: string;
|
|
26
|
+
tx_hash?: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type ClaimRewardParameters = {
|
|
31
|
+
/** The reward token. */
|
|
32
|
+
rewardToken: RewardToken;
|
|
33
|
+
/** The amount of reward to be withdrawn (claimed). */
|
|
34
|
+
amount: BigNumber.Value;
|
|
35
|
+
/** The destination address. */
|
|
36
|
+
to: string;
|
|
37
|
+
} & CommonWriteParameters<SuiSignPersonalMessageFeature>;
|
|
38
|
+
|
|
39
|
+
const REQUEST_WITHDRAW_URL =
|
|
40
|
+
'/api/v1/distribution/account/{from}/withdrawals/{to}';
|
|
41
|
+
|
|
42
|
+
/** Claims a reward */
|
|
43
|
+
export async function claimReward({
|
|
44
|
+
account: from,
|
|
45
|
+
rewardToken,
|
|
46
|
+
amount,
|
|
47
|
+
to,
|
|
48
|
+
walletClient,
|
|
49
|
+
env,
|
|
50
|
+
}: ClaimRewardParameters) {
|
|
51
|
+
if (!isRewardTokenSupported(rewardToken)) {
|
|
52
|
+
throw new Error(`Unknown reward token: ${RewardToken}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const withdrawalFee = await getRewardWithdrawalFee({
|
|
56
|
+
address: from.address,
|
|
57
|
+
rewardToken,
|
|
58
|
+
env,
|
|
59
|
+
});
|
|
60
|
+
const signingData = await getRewardSigningData({
|
|
61
|
+
from: from.address,
|
|
62
|
+
to,
|
|
63
|
+
amount,
|
|
64
|
+
fee: withdrawalFee,
|
|
65
|
+
rewardToken,
|
|
66
|
+
env,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const { signature } = await walletClient.features[
|
|
70
|
+
'sui:signPersonalMessage'
|
|
71
|
+
].signPersonalMessage({
|
|
72
|
+
account: from,
|
|
73
|
+
message: Buffer.from(signingData) as unknown as Uint8Array,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const payload = {
|
|
77
|
+
amount: BigNumber(amount).toFixed(),
|
|
78
|
+
fee: BigNumber(withdrawalFee).toFixed(),
|
|
79
|
+
signature,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const { baseApiUrl } = getApiConfig(env);
|
|
83
|
+
const { data: withdrawData } = await axios.post<Response>(
|
|
84
|
+
REQUEST_WITHDRAW_URL.replace('{from}', from.address).replace('{to}', to),
|
|
85
|
+
payload,
|
|
86
|
+
{
|
|
87
|
+
baseURL: baseApiUrl,
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
return mapDataToRewardWithdrawal(withdrawData.withdrawal);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function mapDataToRewardWithdrawal(data: Response['withdrawal']) {
|
|
95
|
+
const withdrawal: RewardWithdrawal = {
|
|
96
|
+
amount: BigNumber(data.amount),
|
|
97
|
+
rewardToken: RewardToken.BABY,
|
|
98
|
+
fee: BigNumber(data.fee),
|
|
99
|
+
to: data.to,
|
|
100
|
+
signature: data.signature,
|
|
101
|
+
status: data.status,
|
|
102
|
+
txHash: data.tx_hash,
|
|
103
|
+
timestamp: new Date(data.created_at),
|
|
104
|
+
};
|
|
105
|
+
return withdrawal;
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Transaction } from '@mysten/sui/transactions';
|
|
2
|
+
import { SuiChain, SuiSignTransactionFeature } from '@mysten/wallet-standard';
|
|
3
|
+
import { WalletWithFeatures } from '@wallet-standard/base';
|
|
4
|
+
import type { WalletAccount } from '@wallet-standard/core';
|
|
5
|
+
import { DEFAULT_ENV, Env } from '@lombard.finance/sdk-common';
|
|
6
|
+
import { SuiClient } from '@mysten/sui/client';
|
|
7
|
+
import type { SuiTransactionBlockResponse } from '@mysten/sui/client';
|
|
8
|
+
import { getConfig } from '../../const';
|
|
9
|
+
|
|
10
|
+
type Not0xPrefixedHex = string;
|
|
11
|
+
|
|
12
|
+
interface IClaimLBTCParams {
|
|
13
|
+
chainId: SuiChain;
|
|
14
|
+
wallet: WalletWithFeatures<SuiSignTransactionFeature>;
|
|
15
|
+
payload: Not0xPrefixedHex;
|
|
16
|
+
proof: Not0xPrefixedHex;
|
|
17
|
+
walletAccount: WalletAccount;
|
|
18
|
+
client: SuiClient;
|
|
19
|
+
env?: Env;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const SIGN_TRANSACTION_V2_FEATURE = 'sui:signTransaction';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Claims LBTC.
|
|
26
|
+
*/
|
|
27
|
+
export async function claimLBTC({
|
|
28
|
+
chainId,
|
|
29
|
+
wallet,
|
|
30
|
+
payload,
|
|
31
|
+
proof,
|
|
32
|
+
walletAccount,
|
|
33
|
+
client,
|
|
34
|
+
env = DEFAULT_ENV,
|
|
35
|
+
}: IClaimLBTCParams): Promise<SuiTransactionBlockResponse> {
|
|
36
|
+
const transaction = new Transaction();
|
|
37
|
+
|
|
38
|
+
const {
|
|
39
|
+
mint: { target, denyList },
|
|
40
|
+
treasuryAddress,
|
|
41
|
+
consortiumAddress,
|
|
42
|
+
bascule,
|
|
43
|
+
LBTC,
|
|
44
|
+
} = getConfig(env);
|
|
45
|
+
|
|
46
|
+
transaction.moveCall({
|
|
47
|
+
target,
|
|
48
|
+
arguments: [
|
|
49
|
+
transaction.object(treasuryAddress),
|
|
50
|
+
transaction.object(consortiumAddress),
|
|
51
|
+
transaction.object(denyList),
|
|
52
|
+
transaction.object(bascule),
|
|
53
|
+
transaction.pure.vector('u8', Array.from(Buffer.from(payload, 'hex'))),
|
|
54
|
+
transaction.pure.vector('u8', Array.from(Buffer.from(proof, 'hex'))),
|
|
55
|
+
],
|
|
56
|
+
typeArguments: [LBTC],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (wallet.features[SIGN_TRANSACTION_V2_FEATURE]) {
|
|
60
|
+
const signedTransaction = await wallet.features[
|
|
61
|
+
'sui:signTransaction'
|
|
62
|
+
].signTransaction({
|
|
63
|
+
chain: chainId,
|
|
64
|
+
transaction,
|
|
65
|
+
account: walletAccount,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return client.executeTransactionBlock({
|
|
69
|
+
transactionBlock: signedTransaction.bytes,
|
|
70
|
+
signature: signedTransaction.signature,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
transaction.setSender(walletAccount.address);
|
|
75
|
+
|
|
76
|
+
const signedTransaction = await wallet.features[
|
|
77
|
+
// @ts-ignore The current wallet standard interface version doesn't support this type
|
|
78
|
+
'sui:signTransactionBlock'
|
|
79
|
+
].signTransactionBlock({
|
|
80
|
+
chain: chainId,
|
|
81
|
+
transactionBlock: transaction,
|
|
82
|
+
account: walletAccount,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return client.executeTransactionBlock({
|
|
86
|
+
transactionBlock: signedTransaction.transactionBlockBytes,
|
|
87
|
+
signature: signedTransaction.signature,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './claimLBTC';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { WalletAccount } from '@wallet-standard/core';
|
|
2
|
+
import type { CoinStruct } from '@mysten/sui/client';
|
|
3
|
+
import { SuiClient } from '@mysten/sui/client';
|
|
4
|
+
|
|
5
|
+
interface IUnstakeLBTCParams {
|
|
6
|
+
walletAccount: WalletAccount;
|
|
7
|
+
client: SuiClient;
|
|
8
|
+
coinType: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function getAllCoinsOfType({
|
|
12
|
+
walletAccount,
|
|
13
|
+
client,
|
|
14
|
+
coinType,
|
|
15
|
+
}: IUnstakeLBTCParams) {
|
|
16
|
+
let cursor: string | null | undefined = undefined;
|
|
17
|
+
let coins: CoinStruct[] = [];
|
|
18
|
+
|
|
19
|
+
do {
|
|
20
|
+
const response = await client.getCoins({
|
|
21
|
+
owner: walletAccount.address,
|
|
22
|
+
coinType,
|
|
23
|
+
cursor,
|
|
24
|
+
limit: 50,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
coins = coins.concat(response.data);
|
|
28
|
+
cursor = response.nextCursor;
|
|
29
|
+
} while (cursor);
|
|
30
|
+
|
|
31
|
+
return coins;
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './getAllCoinsOfType';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { WalletAccount } from '@wallet-standard/core';
|
|
2
|
+
import { Env } from '@lombard.finance/sdk-common';
|
|
3
|
+
import { SuiClient } from '@mysten/sui/client';
|
|
4
|
+
import BigNumber from 'bignumber.js';
|
|
5
|
+
import { ERROR_COIN_METADATA_NOT_FUND } from '../../const';
|
|
6
|
+
|
|
7
|
+
interface IGetBalanceParams {
|
|
8
|
+
walletAccount: WalletAccount;
|
|
9
|
+
client: SuiClient;
|
|
10
|
+
coinType: string;
|
|
11
|
+
env?: Env;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface IGetBalanceResult {
|
|
15
|
+
total: BigNumber;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function getBalance({
|
|
19
|
+
walletAccount,
|
|
20
|
+
client,
|
|
21
|
+
coinType,
|
|
22
|
+
}: IGetBalanceParams): Promise<IGetBalanceResult> {
|
|
23
|
+
const coinBalance = await client.getBalance({
|
|
24
|
+
owner: walletAccount.address,
|
|
25
|
+
coinType,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const coinMetadata = await client.getCoinMetadata({
|
|
29
|
+
coinType,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (!coinMetadata) {
|
|
33
|
+
throw ERROR_COIN_METADATA_NOT_FUND;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const total = new BigNumber(coinBalance.totalBalance).div(
|
|
37
|
+
new BigNumber(10).pow(coinMetadata.decimals),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return { total };
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './getBalance';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './prepareCoinsTransaction';
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Transaction } from '@mysten/sui/transactions';
|
|
2
|
+
import type { WalletAccount } from '@wallet-standard/core';
|
|
3
|
+
import type { CoinStruct } from '@mysten/sui/client';
|
|
4
|
+
import { SuiClient } from '@mysten/sui/client';
|
|
5
|
+
import BigNumber from 'bignumber.js';
|
|
6
|
+
import {
|
|
7
|
+
ERROR_COIN_METADATA_NOT_FUND,
|
|
8
|
+
ERROR_NOT_ENOUGH_BALANCE,
|
|
9
|
+
} from '../../const';
|
|
10
|
+
import { getAllCoinsOfType } from '../getAllCoinsOfType';
|
|
11
|
+
|
|
12
|
+
interface IUnstakeLBTCParams {
|
|
13
|
+
walletAccount: WalletAccount;
|
|
14
|
+
client: SuiClient;
|
|
15
|
+
amount: BigNumber;
|
|
16
|
+
coinType: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function prepareCoinsTransaction({
|
|
20
|
+
walletAccount,
|
|
21
|
+
client,
|
|
22
|
+
amount,
|
|
23
|
+
coinType,
|
|
24
|
+
}: IUnstakeLBTCParams) {
|
|
25
|
+
const coins = await getAllCoinsOfType({ walletAccount, client, coinType });
|
|
26
|
+
|
|
27
|
+
const transaction = new Transaction();
|
|
28
|
+
|
|
29
|
+
const preparedCoins = await (async () => {
|
|
30
|
+
const coinMetadata = await client.getCoinMetadata({
|
|
31
|
+
coinType,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (!coinMetadata) {
|
|
35
|
+
throw ERROR_COIN_METADATA_NOT_FUND;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const unstakeAmount = BigInt(
|
|
39
|
+
amount
|
|
40
|
+
.multipliedBy(new BigNumber(10).pow(coinMetadata.decimals))
|
|
41
|
+
.toString(10),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const selectedCoins = [] as CoinStruct[];
|
|
45
|
+
let selectedAmount = BigInt(0);
|
|
46
|
+
|
|
47
|
+
for (const coin of coins) {
|
|
48
|
+
if (selectedAmount + BigInt(coin.balance) < unstakeAmount) {
|
|
49
|
+
selectedCoins.push(coin);
|
|
50
|
+
selectedAmount += BigInt(coin.balance);
|
|
51
|
+
} else if (selectedAmount + BigInt(coin.balance) === unstakeAmount) {
|
|
52
|
+
selectedCoins.push(coin);
|
|
53
|
+
|
|
54
|
+
const coinObjects = selectedCoins.map(coin =>
|
|
55
|
+
transaction.object(coin.coinObjectId),
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
if (coinObjects.length > 1) {
|
|
59
|
+
const [coin, ...rest] = coinObjects;
|
|
60
|
+
transaction.mergeCoins(coin, rest);
|
|
61
|
+
return coin;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return coinObjects[0];
|
|
65
|
+
} else if (selectedAmount + BigInt(coin.balance) > unstakeAmount) {
|
|
66
|
+
const remaining = unstakeAmount - selectedAmount;
|
|
67
|
+
const [splitCoin] = transaction.splitCoins(
|
|
68
|
+
transaction.object(coin.coinObjectId),
|
|
69
|
+
[transaction.pure.u64(remaining)],
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
if (selectedCoins.length === 0) {
|
|
73
|
+
return transaction.object(splitCoin);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
transaction.mergeCoins(
|
|
77
|
+
splitCoin,
|
|
78
|
+
selectedCoins.map(coin => transaction.object(coin.coinObjectId)),
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
return transaction.object(splitCoin);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
throw ERROR_NOT_ENOUGH_BALANCE;
|
|
85
|
+
})();
|
|
86
|
+
|
|
87
|
+
return { transaction, preparedCoins };
|
|
88
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './signLbtcDestinationAddrSui';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SuiChain,
|
|
3
|
+
SuiSignPersonalMessageFeature,
|
|
4
|
+
} from '@mysten/wallet-standard';
|
|
5
|
+
|
|
6
|
+
import { WalletWithFeatures } from '@wallet-standard/base';
|
|
7
|
+
import type { WalletAccount } from '@wallet-standard/core';
|
|
8
|
+
import { getUnifiedChainId } from '../../getUnifiedChainId';
|
|
9
|
+
|
|
10
|
+
export const SIGNATURE_SIZE = -132;
|
|
11
|
+
|
|
12
|
+
interface SignLbtcDestinationAddrSuiParams {
|
|
13
|
+
chainId: SuiChain;
|
|
14
|
+
wallet: WalletWithFeatures<SuiSignPersonalMessageFeature>;
|
|
15
|
+
account: WalletAccount;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Signs the destination address for the LBTC in active chain
|
|
20
|
+
* in the current account. Signing is necessary for the
|
|
21
|
+
* generation of the deposit address.
|
|
22
|
+
*
|
|
23
|
+
* @param {SignLbtcDestinationAddrSuiParams} params
|
|
24
|
+
*
|
|
25
|
+
* @returns {Promise<{ bytes: string; signature: string }>} The signature and the message.
|
|
26
|
+
*/
|
|
27
|
+
export async function signLbtcDestinationAddrSui({
|
|
28
|
+
chainId,
|
|
29
|
+
wallet,
|
|
30
|
+
account,
|
|
31
|
+
}: SignLbtcDestinationAddrSuiParams): Promise<{
|
|
32
|
+
bytes: string;
|
|
33
|
+
signature: string;
|
|
34
|
+
}> {
|
|
35
|
+
const message = Buffer.from(
|
|
36
|
+
`destination chain id is ${getUnifiedChainId(chainId)}`,
|
|
37
|
+
'utf8',
|
|
38
|
+
) as unknown as Uint8Array;
|
|
39
|
+
|
|
40
|
+
return wallet.features['sui:signPersonalMessage'].signPersonalMessage({
|
|
41
|
+
message,
|
|
42
|
+
account,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './signTermsOfService';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { SuiSignPersonalMessageFeature } from '@mysten/wallet-standard';
|
|
2
|
+
|
|
3
|
+
import { WalletWithFeatures } from '@wallet-standard/base';
|
|
4
|
+
import type { WalletAccount } from '@wallet-standard/core';
|
|
5
|
+
|
|
6
|
+
const SIGN_MESSAGE =
|
|
7
|
+
'I have read and agreed to the terms of service: https://docs.lombard.finance/legals/terms-of-service';
|
|
8
|
+
|
|
9
|
+
interface SignTermsOfServiceParams {
|
|
10
|
+
wallet: WalletWithFeatures<SuiSignPersonalMessageFeature>;
|
|
11
|
+
account: WalletAccount;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Signs terms of service.
|
|
16
|
+
*
|
|
17
|
+
* @param {SignTermsOfServiceParams} params
|
|
18
|
+
*
|
|
19
|
+
* @returns {Promise<{ bytes: string; signature: string }>} The signature and the message.
|
|
20
|
+
*/
|
|
21
|
+
export async function signTermsOfService({
|
|
22
|
+
wallet,
|
|
23
|
+
account,
|
|
24
|
+
}: SignTermsOfServiceParams): Promise<{
|
|
25
|
+
bytes: string;
|
|
26
|
+
signature: string;
|
|
27
|
+
}> {
|
|
28
|
+
return wallet.features['sui:signPersonalMessage'].signPersonalMessage({
|
|
29
|
+
message: Buffer.from(SIGN_MESSAGE, 'utf8') as unknown as Uint8Array,
|
|
30
|
+
account,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './unstakeLBTC';
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { SuiChain, SuiSignTransactionFeature } from '@mysten/wallet-standard';
|
|
2
|
+
import { WalletWithFeatures } from '@wallet-standard/base';
|
|
3
|
+
import type { WalletAccount } from '@wallet-standard/core';
|
|
4
|
+
import { DEFAULT_ENV, Env, getOutputScript } from '@lombard.finance/sdk-common';
|
|
5
|
+
import type { SuiTransactionBlockResponse } from '@mysten/sui/client';
|
|
6
|
+
import { SuiClient } from '@mysten/sui/client';
|
|
7
|
+
import BigNumber from 'bignumber.js';
|
|
8
|
+
import { getConfig } from '../../const';
|
|
9
|
+
import { prepareCoinsTransaction } from '../prepareAmount';
|
|
10
|
+
|
|
11
|
+
interface IUnstakeLBTCParams {
|
|
12
|
+
chainId: SuiChain;
|
|
13
|
+
wallet: WalletWithFeatures<SuiSignTransactionFeature>;
|
|
14
|
+
walletAccount: WalletAccount;
|
|
15
|
+
client: SuiClient;
|
|
16
|
+
btcAddress: string;
|
|
17
|
+
amount: BigNumber;
|
|
18
|
+
env?: Env;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Unstake LBTC.
|
|
23
|
+
*/
|
|
24
|
+
export async function unstakeLBTC({
|
|
25
|
+
chainId,
|
|
26
|
+
wallet,
|
|
27
|
+
walletAccount,
|
|
28
|
+
client,
|
|
29
|
+
btcAddress,
|
|
30
|
+
amount,
|
|
31
|
+
env = DEFAULT_ENV,
|
|
32
|
+
}: IUnstakeLBTCParams): Promise<SuiTransactionBlockResponse> {
|
|
33
|
+
const config = getConfig(env);
|
|
34
|
+
|
|
35
|
+
const { transaction, preparedCoins: unstakingCoins } =
|
|
36
|
+
await prepareCoinsTransaction({
|
|
37
|
+
walletAccount,
|
|
38
|
+
client,
|
|
39
|
+
amount,
|
|
40
|
+
coinType: config.LBTC,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const scriptPubKey = Array.from(
|
|
44
|
+
Buffer.from(getOutputScript(btcAddress, env).replace(/^0x/, ''), 'hex'),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
transaction.moveCall({
|
|
48
|
+
target: config.redeem.target,
|
|
49
|
+
arguments: [
|
|
50
|
+
transaction.object(config.treasuryAddress),
|
|
51
|
+
unstakingCoins,
|
|
52
|
+
transaction.pure.vector('u8', scriptPubKey),
|
|
53
|
+
],
|
|
54
|
+
typeArguments: [config.LBTC],
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const signedTransaction = await wallet.features[
|
|
58
|
+
'sui:signTransaction'
|
|
59
|
+
].signTransaction({
|
|
60
|
+
chain: chainId,
|
|
61
|
+
transaction,
|
|
62
|
+
account: walletAccount,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return client.executeTransactionBlock({
|
|
66
|
+
transactionBlock: signedTransaction.bytes,
|
|
67
|
+
signature: signedTransaction.signature,
|
|
68
|
+
});
|
|
69
|
+
}
|