@scallop-io/scallop-deepbook-kit 0.1.3

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 ADDED
@@ -0,0 +1,360 @@
1
+ # Scallop DeepBook Kit
2
+
3
+ A comprehensive toolkit for interacting with DeepBook V3 Margin Pools on the Sui blockchain.
4
+ 一個在 Sui 區塊鏈上與 DeepBook V3 Margin Pools 互動的完整工具套件。
5
+
6
+ ## Features | 功能特色
7
+
8
+ - **DeepBook V3 Integration** | **DeepBook V3 整合**
9
+ Complete integration with DeepBook V3 Margin Pool system
10
+ 完整整合 DeepBook V3 Margin Pool 系統
11
+
12
+ - **Simplified API** | **簡化的 API**
13
+ Clean and intuitive API for complex margin operations
14
+ 簡潔直觀的 API,處理複雜的 margin 操作
15
+
16
+ - **Supplier Cap Management** | **Supplier Cap 管理**
17
+ Automatic creation and management of Supplier Credentials
18
+ 自動創建和管理供應者憑證
19
+
20
+ - **Referral System** | **推薦系統**
21
+ Built-in referral creation and fee withdrawal support
22
+ 內建推薦系統創建和費用提取支援
23
+
24
+ - **Balance Tracking** | **餘額追蹤**
25
+ Query wallet and margin pool balances in real-time
26
+ 即時查詢錢包和 margin pool 餘額
27
+
28
+ - **TypeScript Support** | **TypeScript 支援**
29
+ Full TypeScript support with comprehensive type definitions
30
+ 完整的 TypeScript 支援與詳盡的型別定義
31
+
32
+ - **Environment Management** | **環境管理**
33
+ Easy-to-use environment variable management utilities
34
+ 易於使用的環境變數管理工具
35
+
36
+ ## Prerequisites | 環境需求
37
+
38
+ - **Node.js** >= 18.0.0
39
+ - **pnpm** >= 9.0.0
40
+ - **Sui Testnet Account** with SUI and DBUSDC balance
41
+ **Sui 測試網帳戶**,需包含 SUI 和 DBUSDC 餘額
42
+
43
+ ## Installation | 安裝
44
+
45
+ ```bash
46
+ # Clone the repository | 克隆儲存庫
47
+ git clone https://github.com/your-username/scallop-deepbook-kit.git
48
+ cd scallop-deepbook-kit
49
+
50
+ # Install dependencies | 安裝依賴
51
+ pnpm install
52
+
53
+ # Setup environment variables | 設定環境變數
54
+ cp .env.example .env
55
+ # Edit .env and add your PRIVATE_KEY | 編輯 .env 並新增您的 PRIVATE_KEY
56
+ ```
57
+
58
+ ## Quick Start | 快速開始
59
+
60
+ ### 1. Configure Environment | 配置環境
61
+
62
+ Create a `.env` file in the project root:
63
+ 在專案根目錄建立 `.env` 檔案:
64
+
65
+ ```env
66
+ # Required: Your wallet private key (hex format, without 0x prefix)
67
+ # 必需:您的錢包私鑰(hex 格式,不含 0x 前綴)
68
+ PRIVATE_KEY=your_private_key_here
69
+
70
+ # Optional: These will be auto-generated and saved
71
+ # 可選:這些會自動產生並儲存
72
+ # SUPPLIER_CAP_ID=
73
+ # SUI_REFERRAL_ID=
74
+ # DBUSDC_REFERRAL_ID=
75
+ ```
76
+
77
+ ### 2. Run the Demo | 執行示範
78
+
79
+ ```bash
80
+ # Run the complete toolkit demo | 執行完整的 toolkit 示範
81
+ pnpm example:toolkit
82
+ ```
83
+
84
+ The demo will:
85
+ 示範程式將會:
86
+
87
+ - Create or load Supplier Cap | 創建或載入 Supplier Cap
88
+ - Create referrals for SUI and DBUSDC | 為 SUI 和 DBUSDC 創建 referrals
89
+ - Withdraw all existing supplies | 提取所有現有的供應
90
+ - Supply 0.1 SUI and 10 DBUSDC to margin pools | 供應 0.1 SUI 和 10 DBUSDC 到 margin pools
91
+ - Track and display balance changes | 追蹤並顯示餘額變化
92
+
93
+ ### 3. Use the Toolkit in Your Code | 在程式碼中使用 Toolkit
94
+
95
+ ```typescript
96
+ import { DeepBookMarginToolkit } from './toolkit';
97
+
98
+ // Initialize the toolkit | 初始化 toolkit
99
+ const toolkit = new DeepBookMarginToolkit({
100
+ network: 'testnet',
101
+ privateKey: process.env.PRIVATE_KEY!,
102
+ supplierCapId: process.env.SUPPLIER_CAP_ID, // Optional | 可選
103
+ });
104
+
105
+ // Initialize (creates Supplier Cap if needed) | 初始化(需要時創建 Supplier Cap)
106
+ await toolkit.initialize();
107
+
108
+ // Create a referral | 創建 referral
109
+ const referralId = await toolkit.createSupplyReferral('SUI');
110
+
111
+ // Supply to margin pool | 供應到 margin pool
112
+ await toolkit.supplyToMarginPool('SUI', 0.1, referralId);
113
+
114
+ // Get balance | 查詢餘額
115
+ const balance = await toolkit.getBalance('SUI');
116
+ console.log(`Supply amount: ${balance.userSupplyAmount}`);
117
+ console.log(`Wallet balance: ${balance.walletBalance}`);
118
+
119
+ // Withdraw from margin pool | 從 margin pool 提取
120
+ await toolkit.withdrawFromMarginPool('SUI'); // Withdraws all | 提取全部
121
+
122
+ // Withdraw referral fees | 提取 referral 費用
123
+ await toolkit.withdrawReferralFees('SUI', referralId);
124
+ ```
125
+
126
+ ## API Reference | API 參考
127
+
128
+ ### DeepBookMarginToolkit
129
+
130
+ #### Constructor | 建構函式
131
+
132
+ ```typescript
133
+ new DeepBookMarginToolkit(config: ToolkitConfig)
134
+ ```
135
+
136
+ **Parameters | 參數:**
137
+
138
+ - `config.network`: `'testnet' | 'mainnet'` - Network type | 網路類型
139
+ - `config.privateKey`: `string` - Private key (hex, no 0x prefix) | 私鑰(hex 格式,無 0x 前綴)
140
+ - `config.supplierCapId?`: `string` - Optional existing Supplier Cap ID | 可選的現有 Supplier Cap ID
141
+
142
+ #### Methods | 方法
143
+
144
+ ##### `initialize(): Promise<string>`
145
+
146
+ Initialize the toolkit and create Supplier Cap if needed.
147
+ 初始化 toolkit 並在需要時創建 Supplier Cap。
148
+
149
+ **Returns | 返回:** Supplier Cap ID
150
+
151
+ ##### `createSupplyReferral(coin: MarginCoinType): Promise<string | null>`
152
+
153
+ Create a supply referral for the specified coin.
154
+ 為指定的幣種創建供應 referral。
155
+
156
+ **Parameters | 參數:**
157
+
158
+ - `coin`: `'SUI' | 'DBUSDC'` - Coin type | 幣種
159
+
160
+ **Returns | 返回:** Referral ID or null
161
+
162
+ ##### `supplyToMarginPool(coin: MarginCoinType, amount: number, referralId?: string): Promise<boolean>`
163
+
164
+ Supply funds to the margin pool.
165
+ 供應資金到 margin pool。
166
+
167
+ **Parameters | 參數:**
168
+
169
+ - `coin`: `'SUI' | 'DBUSDC'` - Coin type | 幣種
170
+ - `amount`: `number` - Amount in human-readable units | 人類可讀單位的金額
171
+ - `referralId?`: `string` - Optional referral ID | 可選的 referral ID
172
+
173
+ **Returns | 返回:** Success status
174
+
175
+ ##### `withdrawFromMarginPool(coin: MarginCoinType, amount?: number): Promise<boolean>`
176
+
177
+ Withdraw funds from the margin pool.
178
+ 從 margin pool 提取資金。
179
+
180
+ **Parameters | 參數:**
181
+
182
+ - `coin`: `'SUI' | 'DBUSDC'` - Coin type | 幣種
183
+ - `amount?`: `number` - Optional amount, omit to withdraw all | 可選的金額,省略則提取全部
184
+
185
+ **Returns | 返回:** Success status
186
+
187
+ ##### `withdrawReferralFees(coin: MarginCoinType, referralId: string): Promise<boolean>`
188
+
189
+ Withdraw accumulated referral fees.
190
+ 提取累積的 referral 費用。
191
+
192
+ **Parameters | 參數:**
193
+
194
+ - `coin`: `'SUI' | 'DBUSDC'` - Coin type | 幣種
195
+ - `referralId`: `string` - Referral Object ID | Referral 物件 ID
196
+
197
+ **Returns | 返回:** Success status
198
+
199
+ ##### `getBalance(coin: MarginCoinType): Promise<MarginBalance>`
200
+
201
+ Query margin balance for a coin.
202
+ 查詢幣種的 margin 餘額。
203
+
204
+ **Parameters | 參數:**
205
+
206
+ - `coin`: `'SUI' | 'DBUSDC'` - Coin type | 幣種
207
+
208
+ **Returns | 返回:** Balance information with `userSupplyAmount` and `walletBalance`
209
+
210
+ ##### `getAddress(): string`
211
+
212
+ Get the wallet address.
213
+ 獲取錢包地址。
214
+
215
+ **Returns | 返回:** Wallet address
216
+
217
+ ##### `getSupplierCapId(): string | undefined`
218
+
219
+ Get the Supplier Cap ID.
220
+ 獲取 Supplier Cap ID。
221
+
222
+ **Returns | 返回:** Supplier Cap ID or undefined
223
+
224
+ ## Development Commands | 開發指令
225
+
226
+ ### Build | 建置
227
+
228
+ ```bash
229
+ pnpm build # Compile TypeScript | 編譯 TypeScript
230
+ pnpm build:watch # Watch mode compilation | 監聽模式編譯
231
+ pnpm clean # Remove build artifacts | 清除建置檔案
232
+ ```
233
+
234
+ ### Code Quality | 程式碼品質
235
+
236
+ ```bash
237
+ pnpm lint # Check code style with ESLint | 使用 ESLint 檢查程式碼風格
238
+ pnpm lint:fix # Auto-fix ESLint issues | 自動修正 ESLint 問題
239
+ pnpm format # Format code with Prettier | 使用 Prettier 格式化程式碼
240
+ pnpm format:check # Check code formatting | 檢查程式碼格式
241
+ ```
242
+
243
+ ### Testing | 測試
244
+
245
+ ```bash
246
+ pnpm test # Run tests | 執行測試
247
+ pnpm test:watch # Run tests in watch mode | 監聽模式執行測試
248
+ pnpm test:coverage # Generate coverage report | 產生覆蓋率報告
249
+ ```
250
+
251
+ ### Examples | 範例
252
+
253
+ ```bash
254
+ pnpm example:toolkit # Run the DeepBook Margin Toolkit demo | 執行 DeepBook Margin Toolkit 示範
255
+ ```
256
+
257
+ ## Project Structure | 專案結構
258
+
259
+ ```
260
+ .
261
+ ├── src/
262
+ │ ├── toolkit/ # Core toolkit implementation | 核心 toolkit 實作
263
+ │ │ ├── DeepBookMarginToolkit.ts # Main toolkit class | 主要 toolkit 類別
264
+ │ │ ├── types.ts # Type definitions | 型別定義
265
+ │ │ └── index.ts # Exports | 匯出
266
+ │ ├── examples/ # Example scripts | 範例程式
267
+ │ │ └── toolkit-demo.ts # Complete demo | 完整示範
268
+ │ ├── utils/ # Utility functions | 工具函式
269
+ │ │ └── env-manager.ts # Environment variable management | 環境變數管理
270
+ │ ├── config.ts # Configuration loader | 配置載入器
271
+ │ └── testnet-config.ts # Testnet constants | 測試網常數
272
+ ├── tests/ # Test files | 測試檔案
273
+ ├── dist/ # Build output (git-ignored) | 建置輸出(git 忽略)
274
+ └── .env # Environment variables (git-ignored) | 環境變數(git 忽略)
275
+ ```
276
+
277
+ ## Tech Stack | 技術堆疊
278
+
279
+ ### Core Dependencies | 核心依賴
280
+
281
+ - **[@mysten/sui](https://www.npmjs.com/package/@mysten/sui)** ^1.44.0 - Sui blockchain SDK | Sui 區塊鏈 SDK
282
+ - **[@mysten/deepbook-v3](https://www.npmjs.com/package/@mysten/deepbook-v3)** ^0.20.2 - DeepBook V3 SDK
283
+ - **[dotenv](https://www.npmjs.com/package/dotenv)** ^17.2.3 - Environment variable management | 環境變數管理
284
+
285
+ ### Development Tools | 開發工具
286
+
287
+ - **[TypeScript](https://www.typescriptlang.org/)** ^5.9.3 - Type-safe JavaScript | 型別安全的 JavaScript
288
+ - **[Jest](https://jestjs.io/)** ^30.2.0 - Testing framework | 測試框架
289
+ - **[ESLint](https://eslint.org/)** ^9.39.1 - Code linting | 程式碼檢查
290
+ - **[Prettier](https://prettier.io/)** ^3.6.2 - Code formatting | 程式碼格式化
291
+ - **[tsx](https://www.npmjs.com/package/tsx)** ^4.19.2 - TypeScript execution | TypeScript 執行工具
292
+
293
+ ### Package Manager | 套件管理器
294
+
295
+ - **[pnpm](https://pnpm.io/)** ^10.21.0 - Fast, disk space efficient package manager | 快速、節省磁碟空間的套件管理器
296
+
297
+ ## Configuration | 配置
298
+
299
+ ### Testnet Configuration | 測試網配置
300
+
301
+ The toolkit uses predefined testnet configurations for:
302
+ toolkit 使用預定義的測試網配置:
303
+
304
+ - **Coins | 幣種**: SUI, DBUSDC, DEEP
305
+ - **Pools | 池子**: SUI/DBUSDC trading pool
306
+ - **Margin Pools | Margin 池子**: SUI and DBUSDC margin pools
307
+
308
+ These configurations are defined in `src/testnet-config.ts`.
309
+ 這些配置定義於 `src/testnet-config.ts`。
310
+
311
+ ## Environment Variables | 環境變數
312
+
313
+ | Variable | Description | Required | Auto-generated |
314
+ | -------------------- | ------------------------------- | -------- | -------------- |
315
+ | `PRIVATE_KEY` | Wallet private key (hex, no 0x) | ✅ Yes | ❌ No |
316
+ | `SUPPLIER_CAP_ID` | Supplier Cap Object ID | ❌ No | ✅ Yes |
317
+ | `SUI_REFERRAL_ID` | SUI Supply Referral ID | ❌ No | ✅ Yes |
318
+ | `DBUSDC_REFERRAL_ID` | DBUSDC Supply Referral ID | ❌ No | ✅ Yes |
319
+
320
+ | 變數 | 說明 | 必需 | 自動產生 |
321
+ | -------------------- | ----------------------- | ----- | -------- |
322
+ | `PRIVATE_KEY` | 錢包私鑰(hex,無 0x) | ✅ 是 | ❌ 否 |
323
+ | `SUPPLIER_CAP_ID` | Supplier Cap 物件 ID | ❌ 否 | ✅ 是 |
324
+ | `SUI_REFERRAL_ID` | SUI 供應 Referral ID | ❌ 否 | ✅ 是 |
325
+ | `DBUSDC_REFERRAL_ID` | DBUSDC 供應 Referral ID | ❌ 否 | ✅ 是 |
326
+
327
+ ## Troubleshooting | 疑難排解
328
+
329
+ ### Common Issues | 常見問題
330
+
331
+ **Issue | 問題:** "Supplier Cap not initialized"
332
+ **Solution | 解決方法:** Call `await toolkit.initialize()` before using other methods | 在使用其他方法前呼叫 `await toolkit.initialize()`
333
+
334
+ **Issue | 問題:** Transaction fails due to insufficient balance
335
+ **Solution | 解決方法:** Ensure you have enough SUI and DBUSDC in your wallet | 確保錢包中有足夠的 SUI 和 DBUSDC
336
+
337
+ **Issue | 問題:** "Failed to create Supplier Cap"
338
+ **Solution | 解決方法:** Check network connectivity and wallet balance | 檢查網路連線和錢包餘額
339
+
340
+ ## Contributing | 貢獻
341
+
342
+ Contributions are welcome! Please feel free to submit a Pull Request.
343
+ 歡迎貢獻!請隨時提交 Pull Request。
344
+
345
+ ## License | 授權
346
+
347
+ MIT License - see [LICENSE](LICENSE) file for details.
348
+ MIT 授權 - 詳情請見 [LICENSE](LICENSE) 檔案。
349
+
350
+ ## Links | 連結
351
+
352
+ - [DeepBook Documentation](https://docs.sui.io/standards/deepbookv3-sdk)
353
+ - [Sui Documentation](https://docs.sui.io/)
354
+ - [DeepBook V3 SDK](https://www.npmjs.com/package/@mysten/deepbook-v3)
355
+ - [Sui TypeScript SDK](https://www.npmjs.com/package/@mysten/sui)
356
+
357
+ ---
358
+
359
+ **Made with ❤️ for the Sui and DeepBook community**
360
+ **用 ❤️ 為 Sui 和 DeepBook 社群打造**
@@ -0,0 +1,80 @@
1
+ import * as _mysten_deepbook_v3 from '@mysten/deepbook-v3';
2
+ import { MarginPoolContract, DeepBookConfig } from '@mysten/deepbook-v3';
3
+ import { SuiClient } from '@mysten/sui/client';
4
+ import { Transaction } from '@mysten/sui/transactions';
5
+
6
+ type NetworkType = 'testnet' | 'mainnet';
7
+ type MarginCoinType = 'SUI' | 'DBUSDC';
8
+ interface ToolkitConfig {
9
+ network: NetworkType;
10
+ privateKey: string;
11
+ supplierCapId?: string;
12
+ fullnodeUrl?: string;
13
+ }
14
+ interface TransactionResult {
15
+ digest: string;
16
+ status: string;
17
+ objectId?: string;
18
+ }
19
+ interface MarginBalance {
20
+ userSupplyAmount: number;
21
+ walletBalance: number;
22
+ }
23
+ interface ReferralInfo {
24
+ referralId: string;
25
+ coin: MarginCoinType;
26
+ owner: string;
27
+ }
28
+
29
+ declare class DeepBookMarginToolkit {
30
+ #private;
31
+ private suiClient;
32
+ private keypair;
33
+ private address;
34
+ private marginPoolContract;
35
+ private supplierCapId?;
36
+ constructor(config: ToolkitConfig);
37
+ initialize(): Promise<string>;
38
+ createSupplierCap(): Promise<string | null>;
39
+ createSupplyReferral(coin: MarginCoinType): Promise<string | null>;
40
+ supplyToMarginPool(coin: MarginCoinType, amount: number, referralId?: string): Promise<boolean>;
41
+ withdrawFromMarginPool(coin: MarginCoinType, amount?: number): Promise<boolean>;
42
+ withdrawReferralFees(coin: MarginCoinType, referralId: string): Promise<boolean>;
43
+ getBalance(coin: MarginCoinType): Promise<MarginBalance>;
44
+ getSupplierCapId(): string | undefined;
45
+ getAddress(): string;
46
+ }
47
+
48
+ declare const MARGIN_POOL_PARAM_KEYS: readonly ["supplyCap", "maxUtilizationRate", "protocolSpread", "minBorrow", "interestRate", "totalSupply", "supplyShares", "totalBorrow", "borrowShares", "lastUpdateTimestamp"];
49
+ declare const MARGIN_POOL_W_SUPPLIER_CAP_PARAM_KEYS: readonly ["userSupplyShares", "userSupplyAmount"];
50
+
51
+ type MarginPoolParamKey = (typeof MARGIN_POOL_PARAM_KEYS)[number];
52
+ type MarginPoolWithSupplierCapParamKey = (typeof MARGIN_POOL_W_SUPPLIER_CAP_PARAM_KEYS)[number];
53
+ type InterestConfig = {
54
+ midKink: number;
55
+ highKink: number;
56
+ baseBorrowApr: number;
57
+ midBorrowApr: number;
58
+ highBorrowApr: number;
59
+ maxBorrowApr: number;
60
+ borrowApr: number;
61
+ };
62
+ type MarginPoolParams = Record<MarginPoolParamKey | MarginPoolWithSupplierCapParamKey, number> & InterestConfig & {
63
+ address: string;
64
+ type: string;
65
+ scalar: number;
66
+ decimals: number;
67
+ };
68
+ declare class DeepBookMarginPool {
69
+ #private;
70
+ readonly suiClient: SuiClient;
71
+ marginPoolContract: MarginPoolContract;
72
+ dbConfig: DeepBookConfig;
73
+ constructor(env?: NetworkType, address?: string, suiClient?: SuiClient, dbConfig?: DeepBookConfig);
74
+ get env(): _mysten_deepbook_v3.Environment;
75
+ getPoolParameters(coinKey: string, supplierCapId?: string, tx?: Transaction): Promise<MarginPoolParams>;
76
+ getPoolParameters(coinKey: string, supplierCapId: string | undefined, tx: Transaction, inspect: true): Promise<MarginPoolParams>;
77
+ getPoolParameters(coinKey: string, supplierCapId: string | undefined, tx: Transaction, inspect: false): Promise<Transaction>;
78
+ }
79
+
80
+ export { DeepBookMarginPool, DeepBookMarginToolkit, type MarginBalance, type MarginCoinType, type MarginPoolParams, type NetworkType, type ReferralInfo, type ToolkitConfig, type TransactionResult };
@@ -0,0 +1,80 @@
1
+ import * as _mysten_deepbook_v3 from '@mysten/deepbook-v3';
2
+ import { MarginPoolContract, DeepBookConfig } from '@mysten/deepbook-v3';
3
+ import { SuiClient } from '@mysten/sui/client';
4
+ import { Transaction } from '@mysten/sui/transactions';
5
+
6
+ type NetworkType = 'testnet' | 'mainnet';
7
+ type MarginCoinType = 'SUI' | 'DBUSDC';
8
+ interface ToolkitConfig {
9
+ network: NetworkType;
10
+ privateKey: string;
11
+ supplierCapId?: string;
12
+ fullnodeUrl?: string;
13
+ }
14
+ interface TransactionResult {
15
+ digest: string;
16
+ status: string;
17
+ objectId?: string;
18
+ }
19
+ interface MarginBalance {
20
+ userSupplyAmount: number;
21
+ walletBalance: number;
22
+ }
23
+ interface ReferralInfo {
24
+ referralId: string;
25
+ coin: MarginCoinType;
26
+ owner: string;
27
+ }
28
+
29
+ declare class DeepBookMarginToolkit {
30
+ #private;
31
+ private suiClient;
32
+ private keypair;
33
+ private address;
34
+ private marginPoolContract;
35
+ private supplierCapId?;
36
+ constructor(config: ToolkitConfig);
37
+ initialize(): Promise<string>;
38
+ createSupplierCap(): Promise<string | null>;
39
+ createSupplyReferral(coin: MarginCoinType): Promise<string | null>;
40
+ supplyToMarginPool(coin: MarginCoinType, amount: number, referralId?: string): Promise<boolean>;
41
+ withdrawFromMarginPool(coin: MarginCoinType, amount?: number): Promise<boolean>;
42
+ withdrawReferralFees(coin: MarginCoinType, referralId: string): Promise<boolean>;
43
+ getBalance(coin: MarginCoinType): Promise<MarginBalance>;
44
+ getSupplierCapId(): string | undefined;
45
+ getAddress(): string;
46
+ }
47
+
48
+ declare const MARGIN_POOL_PARAM_KEYS: readonly ["supplyCap", "maxUtilizationRate", "protocolSpread", "minBorrow", "interestRate", "totalSupply", "supplyShares", "totalBorrow", "borrowShares", "lastUpdateTimestamp"];
49
+ declare const MARGIN_POOL_W_SUPPLIER_CAP_PARAM_KEYS: readonly ["userSupplyShares", "userSupplyAmount"];
50
+
51
+ type MarginPoolParamKey = (typeof MARGIN_POOL_PARAM_KEYS)[number];
52
+ type MarginPoolWithSupplierCapParamKey = (typeof MARGIN_POOL_W_SUPPLIER_CAP_PARAM_KEYS)[number];
53
+ type InterestConfig = {
54
+ midKink: number;
55
+ highKink: number;
56
+ baseBorrowApr: number;
57
+ midBorrowApr: number;
58
+ highBorrowApr: number;
59
+ maxBorrowApr: number;
60
+ borrowApr: number;
61
+ };
62
+ type MarginPoolParams = Record<MarginPoolParamKey | MarginPoolWithSupplierCapParamKey, number> & InterestConfig & {
63
+ address: string;
64
+ type: string;
65
+ scalar: number;
66
+ decimals: number;
67
+ };
68
+ declare class DeepBookMarginPool {
69
+ #private;
70
+ readonly suiClient: SuiClient;
71
+ marginPoolContract: MarginPoolContract;
72
+ dbConfig: DeepBookConfig;
73
+ constructor(env?: NetworkType, address?: string, suiClient?: SuiClient, dbConfig?: DeepBookConfig);
74
+ get env(): _mysten_deepbook_v3.Environment;
75
+ getPoolParameters(coinKey: string, supplierCapId?: string, tx?: Transaction): Promise<MarginPoolParams>;
76
+ getPoolParameters(coinKey: string, supplierCapId: string | undefined, tx: Transaction, inspect: true): Promise<MarginPoolParams>;
77
+ getPoolParameters(coinKey: string, supplierCapId: string | undefined, tx: Transaction, inspect: false): Promise<Transaction>;
78
+ }
79
+
80
+ export { DeepBookMarginPool, DeepBookMarginToolkit, type MarginBalance, type MarginCoinType, type MarginPoolParams, type NetworkType, type ReferralInfo, type ToolkitConfig, type TransactionResult };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ 'use strict';var client=require('@mysten/sui/client'),ed25519=require('@mysten/sui/keypairs/ed25519'),transactions=require('@mysten/sui/transactions'),deepbookV3=require('@mysten/deepbook-v3'),cryptography=require('@mysten/sui/cryptography'),bcs$1=require('@mysten/bcs'),bcs=require('@mysten/sui/bcs'),bignumber_js=require('bignumber.js');var D={MARGIN_INITIAL_PACKAGE_ID:"0x7f2d8f15343f210e813595a8798d6197d152061d0a35be938372f4b1cd66f209"},c={DEEP:{address:"0x36dbef866a1d62bf7328989a10fb2f07d769f4ee587c0de4a0a256e57e0a58a8",type:"0x36dbef866a1d62bf7328989a10fb2f07d769f4ee587c0de4a0a256e57e0a58a8::deep::DEEP",scalar:1e6,decimals:6},SUI:{address:"0x0000000000000000000000000000000000000000000000000000000000000002",type:"0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI",scalar:1e9,decimals:9},DBUSDC:{address:"0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7",type:"0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7::DBUSDC::DBUSDC",scalar:1e6,decimals:6},DBUSDT:{address:"0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7",type:"0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7::DBUSDT::DBUSDT",scalar:1e6,decimals:6},WAL:{address:"0x9ef7676a9f81937a52ae4b2af8d511a28a0b080477c0c2db40b0ab8882240d76",type:"0x9ef7676a9f81937a52ae4b2af8d511a28a0b080477c0c2db40b0ab8882240d76::wal::WAL",scalar:1e9,decimals:9}},f={DEEP_SUI:{address:"0x48c95963e9eac37a316b7ae04a0deb761bcdcc2b67912374d6036e7f0e9bae9f",baseCoin:"DEEP",quoteCoin:"SUI",lotSize:1e6,tickSize:1e6},SUI_DBUSDC:{address:"0x1c19362ca52b8ffd7a33cee805a67d40f31e6ba303753fd3a4cfdfacea7163a5",baseCoin:"SUI",quoteCoin:"DBUSDC",lotSize:1e6,tickSize:1e3},DEEP_DBUSDC:{address:"0xe86b991f8632217505fd859445f9803967ac84a9d4a1219065bf191fcb74b622",baseCoin:"DEEP",quoteCoin:"DBUSDC",lotSize:1e6,tickSize:1e3},DBUSDT_DBUSDC:{address:"0x83970bb02e3636efdff8c141ab06af5e3c9a22e2f74d7f02a9c3430d0d10c1ca",baseCoin:"DBUSDT",quoteCoin:"DBUSDC",lotSize:1e6,tickSize:1e3},WAL_DBUSDC:{address:"0xeb524b6aea0ec4b494878582e0b78924208339d360b62aec4a8ecd4031520dbb",baseCoin:"WAL",quoteCoin:"DBUSDC",lotSize:1e6,tickSize:1e3},WAL_SUI:{address:"0x8c1c1b186c4fddab1ebd53e0895a36c1d1b3b9a77cd34e607bef49a38af0150a",baseCoin:"WAL",quoteCoin:"SUI",lotSize:1e6,tickSize:1e6}},d={SUI:{address:"0xe620d6a5390e57e88baff18af89383130d4210eb496a024edcd62f270a655af7",coinType:"0x2::sui::SUI"},DBUSDC:{address:"0xfd0dc290a120ad6c534507614d4dc0b2e78baab649c35bfacbaec2ce18140b69",coinType:"0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7::DBUSDC::DBUSDC"}};var P=["supplyCap","maxUtilizationRate","protocolSpread","minBorrow","interestRate","totalSupply","supplyShares","totalBorrow","borrowShares","lastUpdateTimestamp"],b=["userSupplyShares","userSupplyAmount"],B={supplyCap:"U64",maxUtilizationRate:"U64",protocolSpread:"U64",minBorrow:"U64",interestRate:"U64",totalSupply:"U64",supplyShares:"U64",totalBorrow:"U64",borrowShares:"U64",lastUpdateTimestamp:"U64",userSupplyShares:"U64",userSupplyAmount:"U64"};var k=n=>/^0x[0-9a-fA-F]+$|^[0-9a-fA-F]+$/.test(n),L=n=>/^[a-zA-Z0-9+/]+={0,2}$/g.test(n),x=n=>{if(k(n))return bcs$1.fromHex(n);if(L(n))return bcs$1.fromBase64(n);throw new Error("The string is not a valid hex or base64 string.")},_=n=>{if(n.length===cryptography.LEGACY_PRIVATE_KEY_SIZE)return n.slice(0,cryptography.PRIVATE_KEY_SIZE);if(n.length===cryptography.PRIVATE_KEY_SIZE+1&&n[0]===0)return n.slice(1);if(n.length===cryptography.PRIVATE_KEY_SIZE)return n;throw new Error("invalid secret key")};var w=class{suiClient;keypair;address;marginPoolContract;supplierCapId;constructor(r){let a=r.fullnodeUrl??client.getFullnodeUrl(r.network);this.suiClient=new client.SuiClient({url:a}),this.keypair=this.#r(r.privateKey),this.address=this.keypair.getPublicKey().toSuiAddress(),this.supplierCapId=r.supplierCapId;let e={DEEP:{address:c.DEEP.address,type:c.DEEP.type,scalar:c.DEEP.scalar},SUI:{address:c.SUI.address,type:c.SUI.type,scalar:c.SUI.scalar},DBUSDC:{address:c.DBUSDC.address,type:c.DBUSDC.type,scalar:c.DBUSDC.scalar}},t={SUI_DBUSDC:{address:f.SUI_DBUSDC.address,baseCoin:f.SUI_DBUSDC.baseCoin,quoteCoin:f.SUI_DBUSDC.quoteCoin}},i={SUI:{address:d.SUI.address,type:d.SUI.coinType},DBUSDC:{address:d.DBUSDC.address,type:d.DBUSDC.coinType}},o=new deepbookV3.DeepBookConfig({address:this.address,env:r.network,coins:e,pools:t,marginPools:i});this.marginPoolContract=new deepbookV3.MarginPoolContract(o);}#r(r){if(r.startsWith(cryptography.SUI_PRIVATE_KEY_PREFIX)){let{secretKey:a}=cryptography.decodeSuiPrivateKey(r);return ed25519.Ed25519Keypair.fromSecretKey(_(a))}return ed25519.Ed25519Keypair.fromSecretKey(_(x(r)))}async#e(){let r=`${D.MARGIN_INITIAL_PACKAGE_ID}::margin_pool::SupplierCap`;return (await this.suiClient.getOwnedObjects({owner:this.address,filter:{StructType:r},options:{showType:true}})).data?.[0]?.data?.objectId}async initialize(){if(this.supplierCapId)return this.supplierCapId;let r=await this.#e();if(r)return this.supplierCapId=r,r;let a=await this.createSupplierCap();if(!a)throw new Error("Failed to create Supplier Cap");return this.supplierCapId=a,a}async createSupplierCap(){try{let r=new transactions.Transaction,a=this.marginPoolContract.mintSupplierCap()(r);r.transferObjects([a],this.address);let e=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:r,options:{showEffects:!0,showObjectChanges:!0}});if(e.errors&&e.errors.length>0)throw new Error(`Transaction failed with errors: ${e.errors.map(t=>t.toString()).join(", ")}`);if(e.objectChanges){for(let t of e.objectChanges)if(t.type==="created"&&t.objectType.includes("SupplierCap"))return t.objectId}return null}catch(r){throw new Error(`Failed to create Supplier Cap: ${r.message||r}`)}}async createSupplyReferral(r){try{let a=new transactions.Transaction;this.marginPoolContract.mintSupplyReferral(r)(a);let e=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:a,options:{showEffects:!0,showObjectChanges:!0}});if(e.errors&&e.errors.length>0)throw new Error(`Transaction failed with errors: ${e.errors.map(t=>t.toString()).join(", ")}`);if(e.objectChanges){for(let t of e.objectChanges)if(t.type==="created"&&t.objectType.includes("SupplyReferral"))return t.objectId}return null}catch(a){throw new Error(`Failed to create Supply Referral: ${a.message||a}`)}}async supplyToMarginPool(r,a,e){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let t=new transactions.Transaction;t.setSender(this.address);let i=t.object(this.supplierCapId);t.add(this.marginPoolContract.supplyToMarginPool(r,i,a,e));let{errors:o}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:t,options:{showEffects:!0,showObjectChanges:!0}});if(o&&o.length>0)throw new Error(`Transaction failed with errors: ${o.map(s=>s.toString()).join(", ")}`);return !0}catch(t){throw new Error(`Failed to supply to margin pool: ${t.message||t}`)}}async withdrawFromMarginPool(r,a){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let e=new transactions.Transaction,t=e.object(this.supplierCapId),o=this.marginPoolContract.withdrawFromMarginPool(r,t,a)(e);e.transferObjects([o],this.address);let{errors:s}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:e,options:{showEffects:!0,showObjectChanges:!0}});if(s&&s.length>0)throw new Error(`Transaction failed with errors: ${s.map(l=>l.toString()).join(", ")}`);return !0}catch(e){throw new Error(`Failed to withdraw from margin pool: ${e.message||e}`)}}async withdrawReferralFees(r,a){try{let e=new transactions.Transaction;e.add(this.marginPoolContract.withdrawReferralFees(r,a));let{errors:t}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:e,options:{showEffects:!0,showObjectChanges:!0,showBalanceChanges:!0}});if(t&&t.length>0)throw new Error(`Transaction failed with errors: ${t.map(i=>i.toString()).join(", ")}`);return !0}catch(e){throw new Error(`Failed to withdraw referral fees: ${e.message||e}`)}}async getBalance(r){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let a=new transactions.Transaction;a.add(this.marginPoolContract.userSupplyAmount(r,this.supplierCapId));let e=await this.suiClient.devInspectTransactionBlock({sender:this.address,transactionBlock:a}),t=0;if(e&&e.results&&e.results[0]&&e.results[0].returnValues){let p=e.results[0].returnValues[0];if(p&&p[0]){let m=Buffer.from(p[0]).readBigUInt64LE(),C=r==="SUI"?c.SUI.scalar:c.DBUSDC.scalar;t=Number(m)/C;}}let i=r==="SUI"?c.SUI.type:c.DBUSDC.type,o=await this.suiClient.getBalance({owner:this.address,coinType:i}),s=r==="SUI"?c.SUI.scalar:c.DBUSDC.scalar,l=Number(o.totalBalance)/s;return {userSupplyAmount:t,walletBalance:l}}catch(a){throw new Error(`Failed to get balance: ${a.message||a}`)}}getSupplierCapId(){return this.supplierCapId}getAddress(){return this.address}};var X=new Set(b),J=n=>X.has(n),I=class{constructor(r="testnet",a="",e=new client.SuiClient({url:client.getFullnodeUrl(r)}),t){this.suiClient=e;this.dbConfig=t??new deepbookV3.DeepBookConfig({env:r,address:a,coins:c,pools:f,marginPools:{SUI:{address:d.SUI.address,type:d.SUI.coinType},DBUSDC:{address:d.DBUSDC.address,type:d.DBUSDC.coinType}}}),this.marginPoolContract=new deepbookV3.MarginPoolContract(this.dbConfig);}marginPoolContract;dbConfig;get env(){return this.dbConfig.env}#r(r,a,e,t){if(J(a)){let i=this.marginPoolContract[a];if(t==null)throw new Error(`supplierCap is required for '${a}'.`);r.add(i(e,t));}else {let i=this.marginPoolContract[a];r.add(i(e));}}#e(r,a){let e=r.results;return e?a.reduce((t,i,o)=>{let s=e[o]?.returnValues?.[0]?.[0];if(!s)return t;let l=bcs.bcs[B[i]];return t[i]=l.parse(new Uint8Array(s)),t},{}):{}}#t(r,a){let e=this.dbConfig.getCoin(a),t={supplyCap:0,maxUtilizationRate:0,protocolSpread:0,minBorrow:0,interestRate:0,totalSupply:0,supplyShares:0,totalBorrow:0,borrowShares:0,lastUpdateTimestamp:0,userSupplyShares:0,userSupplyAmount:0,decimals:0,midKink:0,highKink:0,baseBorrowApr:0,midBorrowApr:0,highBorrowApr:0,maxBorrowApr:0,borrowApr:0,...e};if(!e)return t;let i=new Set(["interestRate","maxUtilizationRate","protocolSpread"]);for(let[o,s]of Object.entries(r))o==="lastUpdateTimestamp"?t[o]=Number(s):i.has(o)?t[o]=new bignumber_js.BigNumber(s).dividedBy(deepbookV3.FLOAT_SCALAR).toNumber():t[o]=new bignumber_js.BigNumber(s).dividedBy(e.scalar).toNumber();return t}#a(r,a){let e=BigInt(a.base_rate),t=BigInt(a.base_slope),i=BigInt(a.excess_slope),o=BigInt(a.optimal_utilization),s=r<0n?0n:r>BigInt(deepbookV3.FLOAT_SCALAR)?BigInt(deepbookV3.FLOAT_SCALAR):BigInt(r);return s<=o?e+t*s/o:e+t+i*(s-o)/(BigInt(deepbookV3.FLOAT_SCALAR)-o)}#o(r,a,e){let t=BigInt(r.base_rate),i=BigInt(r.base_slope),o=BigInt(r.excess_slope),s=BigInt(r.optimal_utilization),l=BigInt(a.max_utilization_rate),p=s,m=l,C=t,E=t+i,T=t+i+o*(l-s)/(1000000000n-s),A=t+i+o,U=this.#a(BigInt(bignumber_js.BigNumber(e.total_borrow).dividedBy(e.total_supply).shiftedBy(9).decimalPlaces(0).toString()),r),u=M=>bignumber_js.BigNumber(M).dividedBy(deepbookV3.FLOAT_SCALAR).toNumber();return {raw:{midKink:p,highKink:m,baseBorrowApr:C,midBorrowApr:E,highBorrowApr:T,maxBorrowApr:A,borrowApr:U},normalized:{midKink:u(p),highKink:u(m),baseBorrowApr:u(C),midBorrowApr:u(E),highBorrowApr:u(T),maxBorrowApr:u(A),borrowApr:u(U)}}}async#i(r){let{address:a}=this.dbConfig.getMarginPool(r),t=((await this.suiClient.getObject({id:a,options:{showContent:true}})).data?.content).fields,i=t.config.fields,o=i.interest_config.fields,s=i.margin_pool_config.fields,l=t.state.fields,{normalized:p}=this.#o(o,s,l);return p}async getPoolParameters(r,a,e=new transactions.Transaction,t=true){if(P.forEach(p=>this.#r(e,p,r)),a&&b.forEach(p=>this.#r(e,p,r,a)),!t)return e;let i=[...P,...b],o=await this.suiClient.devInspectTransactionBlock({transactionBlock:e,sender:this.dbConfig.address}),s=await this.#i(r);return {...this.#t(this.#e(o,i),r),...s}}};exports.DeepBookMarginPool=I;exports.DeepBookMarginToolkit=w;
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import {getFullnodeUrl,SuiClient}from'@mysten/sui/client';import {Ed25519Keypair}from'@mysten/sui/keypairs/ed25519';import {Transaction}from'@mysten/sui/transactions';import {DeepBookConfig,MarginPoolContract,FLOAT_SCALAR}from'@mysten/deepbook-v3';import {SUI_PRIVATE_KEY_PREFIX,decodeSuiPrivateKey,LEGACY_PRIVATE_KEY_SIZE,PRIVATE_KEY_SIZE}from'@mysten/sui/cryptography';import {fromHex,fromBase64}from'@mysten/bcs';import {bcs}from'@mysten/sui/bcs';import {BigNumber}from'bignumber.js';var D={MARGIN_INITIAL_PACKAGE_ID:"0x7f2d8f15343f210e813595a8798d6197d152061d0a35be938372f4b1cd66f209"},c={DEEP:{address:"0x36dbef866a1d62bf7328989a10fb2f07d769f4ee587c0de4a0a256e57e0a58a8",type:"0x36dbef866a1d62bf7328989a10fb2f07d769f4ee587c0de4a0a256e57e0a58a8::deep::DEEP",scalar:1e6,decimals:6},SUI:{address:"0x0000000000000000000000000000000000000000000000000000000000000002",type:"0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI",scalar:1e9,decimals:9},DBUSDC:{address:"0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7",type:"0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7::DBUSDC::DBUSDC",scalar:1e6,decimals:6},DBUSDT:{address:"0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7",type:"0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7::DBUSDT::DBUSDT",scalar:1e6,decimals:6},WAL:{address:"0x9ef7676a9f81937a52ae4b2af8d511a28a0b080477c0c2db40b0ab8882240d76",type:"0x9ef7676a9f81937a52ae4b2af8d511a28a0b080477c0c2db40b0ab8882240d76::wal::WAL",scalar:1e9,decimals:9}},f={DEEP_SUI:{address:"0x48c95963e9eac37a316b7ae04a0deb761bcdcc2b67912374d6036e7f0e9bae9f",baseCoin:"DEEP",quoteCoin:"SUI",lotSize:1e6,tickSize:1e6},SUI_DBUSDC:{address:"0x1c19362ca52b8ffd7a33cee805a67d40f31e6ba303753fd3a4cfdfacea7163a5",baseCoin:"SUI",quoteCoin:"DBUSDC",lotSize:1e6,tickSize:1e3},DEEP_DBUSDC:{address:"0xe86b991f8632217505fd859445f9803967ac84a9d4a1219065bf191fcb74b622",baseCoin:"DEEP",quoteCoin:"DBUSDC",lotSize:1e6,tickSize:1e3},DBUSDT_DBUSDC:{address:"0x83970bb02e3636efdff8c141ab06af5e3c9a22e2f74d7f02a9c3430d0d10c1ca",baseCoin:"DBUSDT",quoteCoin:"DBUSDC",lotSize:1e6,tickSize:1e3},WAL_DBUSDC:{address:"0xeb524b6aea0ec4b494878582e0b78924208339d360b62aec4a8ecd4031520dbb",baseCoin:"WAL",quoteCoin:"DBUSDC",lotSize:1e6,tickSize:1e3},WAL_SUI:{address:"0x8c1c1b186c4fddab1ebd53e0895a36c1d1b3b9a77cd34e607bef49a38af0150a",baseCoin:"WAL",quoteCoin:"SUI",lotSize:1e6,tickSize:1e6}},d={SUI:{address:"0xe620d6a5390e57e88baff18af89383130d4210eb496a024edcd62f270a655af7",coinType:"0x2::sui::SUI"},DBUSDC:{address:"0xfd0dc290a120ad6c534507614d4dc0b2e78baab649c35bfacbaec2ce18140b69",coinType:"0xf7152c05930480cd740d7311b5b8b45c6f488e3a53a11c3f74a6fac36a52e0d7::DBUSDC::DBUSDC"}};var P=["supplyCap","maxUtilizationRate","protocolSpread","minBorrow","interestRate","totalSupply","supplyShares","totalBorrow","borrowShares","lastUpdateTimestamp"],b=["userSupplyShares","userSupplyAmount"],B={supplyCap:"U64",maxUtilizationRate:"U64",protocolSpread:"U64",minBorrow:"U64",interestRate:"U64",totalSupply:"U64",supplyShares:"U64",totalBorrow:"U64",borrowShares:"U64",lastUpdateTimestamp:"U64",userSupplyShares:"U64",userSupplyAmount:"U64"};var k=n=>/^0x[0-9a-fA-F]+$|^[0-9a-fA-F]+$/.test(n),L=n=>/^[a-zA-Z0-9+/]+={0,2}$/g.test(n),x=n=>{if(k(n))return fromHex(n);if(L(n))return fromBase64(n);throw new Error("The string is not a valid hex or base64 string.")},_=n=>{if(n.length===LEGACY_PRIVATE_KEY_SIZE)return n.slice(0,PRIVATE_KEY_SIZE);if(n.length===PRIVATE_KEY_SIZE+1&&n[0]===0)return n.slice(1);if(n.length===PRIVATE_KEY_SIZE)return n;throw new Error("invalid secret key")};var w=class{suiClient;keypair;address;marginPoolContract;supplierCapId;constructor(r){let a=r.fullnodeUrl??getFullnodeUrl(r.network);this.suiClient=new SuiClient({url:a}),this.keypair=this.#r(r.privateKey),this.address=this.keypair.getPublicKey().toSuiAddress(),this.supplierCapId=r.supplierCapId;let e={DEEP:{address:c.DEEP.address,type:c.DEEP.type,scalar:c.DEEP.scalar},SUI:{address:c.SUI.address,type:c.SUI.type,scalar:c.SUI.scalar},DBUSDC:{address:c.DBUSDC.address,type:c.DBUSDC.type,scalar:c.DBUSDC.scalar}},t={SUI_DBUSDC:{address:f.SUI_DBUSDC.address,baseCoin:f.SUI_DBUSDC.baseCoin,quoteCoin:f.SUI_DBUSDC.quoteCoin}},i={SUI:{address:d.SUI.address,type:d.SUI.coinType},DBUSDC:{address:d.DBUSDC.address,type:d.DBUSDC.coinType}},o=new DeepBookConfig({address:this.address,env:r.network,coins:e,pools:t,marginPools:i});this.marginPoolContract=new MarginPoolContract(o);}#r(r){if(r.startsWith(SUI_PRIVATE_KEY_PREFIX)){let{secretKey:a}=decodeSuiPrivateKey(r);return Ed25519Keypair.fromSecretKey(_(a))}return Ed25519Keypair.fromSecretKey(_(x(r)))}async#e(){let r=`${D.MARGIN_INITIAL_PACKAGE_ID}::margin_pool::SupplierCap`;return (await this.suiClient.getOwnedObjects({owner:this.address,filter:{StructType:r},options:{showType:true}})).data?.[0]?.data?.objectId}async initialize(){if(this.supplierCapId)return this.supplierCapId;let r=await this.#e();if(r)return this.supplierCapId=r,r;let a=await this.createSupplierCap();if(!a)throw new Error("Failed to create Supplier Cap");return this.supplierCapId=a,a}async createSupplierCap(){try{let r=new Transaction,a=this.marginPoolContract.mintSupplierCap()(r);r.transferObjects([a],this.address);let e=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:r,options:{showEffects:!0,showObjectChanges:!0}});if(e.errors&&e.errors.length>0)throw new Error(`Transaction failed with errors: ${e.errors.map(t=>t.toString()).join(", ")}`);if(e.objectChanges){for(let t of e.objectChanges)if(t.type==="created"&&t.objectType.includes("SupplierCap"))return t.objectId}return null}catch(r){throw new Error(`Failed to create Supplier Cap: ${r.message||r}`)}}async createSupplyReferral(r){try{let a=new Transaction;this.marginPoolContract.mintSupplyReferral(r)(a);let e=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:a,options:{showEffects:!0,showObjectChanges:!0}});if(e.errors&&e.errors.length>0)throw new Error(`Transaction failed with errors: ${e.errors.map(t=>t.toString()).join(", ")}`);if(e.objectChanges){for(let t of e.objectChanges)if(t.type==="created"&&t.objectType.includes("SupplyReferral"))return t.objectId}return null}catch(a){throw new Error(`Failed to create Supply Referral: ${a.message||a}`)}}async supplyToMarginPool(r,a,e){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let t=new Transaction;t.setSender(this.address);let i=t.object(this.supplierCapId);t.add(this.marginPoolContract.supplyToMarginPool(r,i,a,e));let{errors:o}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:t,options:{showEffects:!0,showObjectChanges:!0}});if(o&&o.length>0)throw new Error(`Transaction failed with errors: ${o.map(s=>s.toString()).join(", ")}`);return !0}catch(t){throw new Error(`Failed to supply to margin pool: ${t.message||t}`)}}async withdrawFromMarginPool(r,a){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let e=new Transaction,t=e.object(this.supplierCapId),o=this.marginPoolContract.withdrawFromMarginPool(r,t,a)(e);e.transferObjects([o],this.address);let{errors:s}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:e,options:{showEffects:!0,showObjectChanges:!0}});if(s&&s.length>0)throw new Error(`Transaction failed with errors: ${s.map(l=>l.toString()).join(", ")}`);return !0}catch(e){throw new Error(`Failed to withdraw from margin pool: ${e.message||e}`)}}async withdrawReferralFees(r,a){try{let e=new Transaction;e.add(this.marginPoolContract.withdrawReferralFees(r,a));let{errors:t}=await this.suiClient.signAndExecuteTransaction({signer:this.keypair,transaction:e,options:{showEffects:!0,showObjectChanges:!0,showBalanceChanges:!0}});if(t&&t.length>0)throw new Error(`Transaction failed with errors: ${t.map(i=>i.toString()).join(", ")}`);return !0}catch(e){throw new Error(`Failed to withdraw referral fees: ${e.message||e}`)}}async getBalance(r){try{if(!this.supplierCapId)throw new Error("Supplier Cap not initialized. Call initialize() first.");let a=new Transaction;a.add(this.marginPoolContract.userSupplyAmount(r,this.supplierCapId));let e=await this.suiClient.devInspectTransactionBlock({sender:this.address,transactionBlock:a}),t=0;if(e&&e.results&&e.results[0]&&e.results[0].returnValues){let p=e.results[0].returnValues[0];if(p&&p[0]){let m=Buffer.from(p[0]).readBigUInt64LE(),C=r==="SUI"?c.SUI.scalar:c.DBUSDC.scalar;t=Number(m)/C;}}let i=r==="SUI"?c.SUI.type:c.DBUSDC.type,o=await this.suiClient.getBalance({owner:this.address,coinType:i}),s=r==="SUI"?c.SUI.scalar:c.DBUSDC.scalar,l=Number(o.totalBalance)/s;return {userSupplyAmount:t,walletBalance:l}}catch(a){throw new Error(`Failed to get balance: ${a.message||a}`)}}getSupplierCapId(){return this.supplierCapId}getAddress(){return this.address}};var X=new Set(b),J=n=>X.has(n),I=class{constructor(r="testnet",a="",e=new SuiClient({url:getFullnodeUrl(r)}),t){this.suiClient=e;this.dbConfig=t??new DeepBookConfig({env:r,address:a,coins:c,pools:f,marginPools:{SUI:{address:d.SUI.address,type:d.SUI.coinType},DBUSDC:{address:d.DBUSDC.address,type:d.DBUSDC.coinType}}}),this.marginPoolContract=new MarginPoolContract(this.dbConfig);}marginPoolContract;dbConfig;get env(){return this.dbConfig.env}#r(r,a,e,t){if(J(a)){let i=this.marginPoolContract[a];if(t==null)throw new Error(`supplierCap is required for '${a}'.`);r.add(i(e,t));}else {let i=this.marginPoolContract[a];r.add(i(e));}}#e(r,a){let e=r.results;return e?a.reduce((t,i,o)=>{let s=e[o]?.returnValues?.[0]?.[0];if(!s)return t;let l=bcs[B[i]];return t[i]=l.parse(new Uint8Array(s)),t},{}):{}}#t(r,a){let e=this.dbConfig.getCoin(a),t={supplyCap:0,maxUtilizationRate:0,protocolSpread:0,minBorrow:0,interestRate:0,totalSupply:0,supplyShares:0,totalBorrow:0,borrowShares:0,lastUpdateTimestamp:0,userSupplyShares:0,userSupplyAmount:0,decimals:0,midKink:0,highKink:0,baseBorrowApr:0,midBorrowApr:0,highBorrowApr:0,maxBorrowApr:0,borrowApr:0,...e};if(!e)return t;let i=new Set(["interestRate","maxUtilizationRate","protocolSpread"]);for(let[o,s]of Object.entries(r))o==="lastUpdateTimestamp"?t[o]=Number(s):i.has(o)?t[o]=new BigNumber(s).dividedBy(FLOAT_SCALAR).toNumber():t[o]=new BigNumber(s).dividedBy(e.scalar).toNumber();return t}#a(r,a){let e=BigInt(a.base_rate),t=BigInt(a.base_slope),i=BigInt(a.excess_slope),o=BigInt(a.optimal_utilization),s=r<0n?0n:r>BigInt(FLOAT_SCALAR)?BigInt(FLOAT_SCALAR):BigInt(r);return s<=o?e+t*s/o:e+t+i*(s-o)/(BigInt(FLOAT_SCALAR)-o)}#o(r,a,e){let t=BigInt(r.base_rate),i=BigInt(r.base_slope),o=BigInt(r.excess_slope),s=BigInt(r.optimal_utilization),l=BigInt(a.max_utilization_rate),p=s,m=l,C=t,E=t+i,T=t+i+o*(l-s)/(1000000000n-s),A=t+i+o,U=this.#a(BigInt(BigNumber(e.total_borrow).dividedBy(e.total_supply).shiftedBy(9).decimalPlaces(0).toString()),r),u=M=>BigNumber(M).dividedBy(FLOAT_SCALAR).toNumber();return {raw:{midKink:p,highKink:m,baseBorrowApr:C,midBorrowApr:E,highBorrowApr:T,maxBorrowApr:A,borrowApr:U},normalized:{midKink:u(p),highKink:u(m),baseBorrowApr:u(C),midBorrowApr:u(E),highBorrowApr:u(T),maxBorrowApr:u(A),borrowApr:u(U)}}}async#i(r){let{address:a}=this.dbConfig.getMarginPool(r),t=((await this.suiClient.getObject({id:a,options:{showContent:true}})).data?.content).fields,i=t.config.fields,o=i.interest_config.fields,s=i.margin_pool_config.fields,l=t.state.fields,{normalized:p}=this.#o(o,s,l);return p}async getPoolParameters(r,a,e=new Transaction,t=true){if(P.forEach(p=>this.#r(e,p,r)),a&&b.forEach(p=>this.#r(e,p,r,a)),!t)return e;let i=[...P,...b],o=await this.suiClient.devInspectTransactionBlock({transactionBlock:e,sender:this.dbConfig.address}),s=await this.#i(r);return {...this.#t(this.#e(o,i),r),...s}}};export{I as DeepBookMarginPool,w as DeepBookMarginToolkit};
package/package.json ADDED
@@ -0,0 +1,95 @@
1
+ {
2
+ "name": "@scallop-io/scallop-deepbook-kit",
3
+ "version": "0.1.3",
4
+ "description": "A toolkit for integrating Scallop with DeepBook functionality",
5
+ "keywords": [
6
+ "scallop",
7
+ "deepbook",
8
+ "sui",
9
+ "defi",
10
+ "blockchain",
11
+ "dex"
12
+ ],
13
+ "author": "team@scallop.io",
14
+ "homepage": "https://github.com/scallop-io/scallop-deepbook-kit#readme",
15
+ "bugs": "https://github.com/scallop-io/scallop-deepbook-kit/issues",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/scallop-io/scallop-deepbook-kit.git"
19
+ },
20
+ "license": "MIT",
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "main": "dist/index.js",
25
+ "module": "dist/index.mjs",
26
+ "types": "dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "source": "./src/index.ts",
30
+ "import": "./dist/index.mjs",
31
+ "require": "./dist/index.js",
32
+ "default": "./dist/index.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "src"
38
+ ],
39
+ "devDependencies": {
40
+ "@types/jest": "^30.0.0",
41
+ "@types/node": "^24.10.0",
42
+ "@typescript-eslint/eslint-plugin": "^8.46.4",
43
+ "@typescript-eslint/parser": "^8.46.4",
44
+ "eslint": "^9.39.1",
45
+ "eslint-config-prettier": "^10.1.8",
46
+ "eslint-plugin-prettier": "^5.5.4",
47
+ "husky": "^8.0.3",
48
+ "jest": "^30.2.0",
49
+ "prettier": "^3.6.2",
50
+ "ts-jest": "^29.4.5",
51
+ "tsup": "^8.5.1",
52
+ "tsx": "^4.19.2",
53
+ "typescript": "^5.9.3"
54
+ },
55
+ "dependencies": {
56
+ "@mysten/bcs": "^1.9.2",
57
+ "@mysten/deepbook-v3": "^0.21.0",
58
+ "@mysten/sui": "^1.45.0",
59
+ "bignumber.js": "^9.3.1",
60
+ "dotenv": "^17.2.3"
61
+ },
62
+ "lint-staged": {
63
+ "**/*.ts": [
64
+ "pnpm run format:fix"
65
+ ],
66
+ "**/*.json|md": [
67
+ "pnpm run format:fix"
68
+ ]
69
+ },
70
+ "husky": {
71
+ "hooks": {
72
+ "pre-commit": "lint-staged"
73
+ }
74
+ },
75
+ "engines": {
76
+ "node": ">=18.0.0",
77
+ "pnpm": ">=9.0.0"
78
+ },
79
+ "scripts": {
80
+ "build": "npm run build:tsup",
81
+ "build:prod": "tsup --env.NODE_ENV production",
82
+ "build:tsup": "tsup",
83
+ "build:watch": "tsc --watch",
84
+ "example:toolkit": "tsx src/examples/toolkit-demo.ts",
85
+ "clean": "rm -rf dist",
86
+ "lint": "eslint src --ext .ts",
87
+ "format:fix": "prettier --ignore-path 'dist/* docs/*' --write '**/*.{ts,json,md}'",
88
+ "lint:fix": "eslint src --ext .ts --fix",
89
+ "format": "prettier --write \"src/**/*.ts\"",
90
+ "format:check": "prettier --check \"src/**/*.ts\"",
91
+ "test": "jest",
92
+ "test:watch": "jest --watch",
93
+ "test:coverage": "jest --coverage"
94
+ }
95
+ }