pinpet-sdk 0.1.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 +674 -0
- package/dist/index.d.ts +342 -0
- package/dist/pinpet-sdk.cjs.js +50648 -0
- package/dist/pinpet-sdk.cjs.js.map +1 -0
- package/dist/pinpet-sdk.esm.js +39265 -0
- package/dist/pinpet-sdk.esm.js.map +1 -0
- package/dist/pinpet-sdk.js +39277 -0
- package/dist/pinpet-sdk.js.map +1 -0
- package/package.json +67 -0
- package/src/idl/pinpet.json +3511 -0
- package/src/index.js +43 -0
- package/src/modules/chain.js +1102 -0
- package/src/modules/close.js +0 -0
- package/src/modules/fast.js +431 -0
- package/src/modules/param.js +171 -0
- package/src/modules/simulator/buy.js_del +711 -0
- package/src/modules/simulator/buy_sell_token.js +300 -0
- package/src/modules/simulator/calcLiq.js +701 -0
- package/src/modules/simulator/long_shrot_stop.js +602 -0
- package/src/modules/simulator/sell.js_del +323 -0
- package/src/modules/simulator/stop_loss_utils.js +223 -0
- package/src/modules/simulator/utils.js +44 -0
- package/src/modules/simulator.js +133 -0
- package/src/modules/token.js +140 -0
- package/src/modules/trading.js +1087 -0
- package/src/sdk.js +370 -0
- package/src/types/index.d.ts +342 -0
- package/src/utils/constants.js +49 -0
- package/src/utils/curve_amm.js +884 -0
- package/src/utils/orderUtils.js +465 -0
|
File without changes
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const OrderUtils = require('../utils/orderUtils');
|
|
3
|
+
const CurveAMM = require('../utils/curve_amm');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Data configuration mapping
|
|
7
|
+
* Define processing methods and configurations for different data types
|
|
8
|
+
*/
|
|
9
|
+
const DATA_CONFIGS = {
|
|
10
|
+
// Simple data types - direct API calls
|
|
11
|
+
mints: {
|
|
12
|
+
useManager: false,
|
|
13
|
+
endpoint: '/api/mints',
|
|
14
|
+
method: 'GET'
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
// Order data types - return raw data + utility methods
|
|
18
|
+
orders: {
|
|
19
|
+
useManager: false,
|
|
20
|
+
endpoint: '/api/mint_orders',
|
|
21
|
+
method: 'GET'
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
// Token details interface
|
|
25
|
+
mint_info: {
|
|
26
|
+
useManager: false,
|
|
27
|
+
endpoint: '/api/details',
|
|
28
|
+
method: 'POST'
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
// User orders interface
|
|
32
|
+
user_orders: {
|
|
33
|
+
useManager: false,
|
|
34
|
+
endpoint: '/api/user_orders',
|
|
35
|
+
method: 'GET'
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Fast API Module
|
|
41
|
+
* Access data through API interfaces from centralized servers, quickly obtain transaction parameters
|
|
42
|
+
* Enables smooth trading operations
|
|
43
|
+
*/
|
|
44
|
+
class FastModule {
|
|
45
|
+
constructor(sdk) {
|
|
46
|
+
this.sdk = sdk;
|
|
47
|
+
this.baseUrl = sdk.spinFastApiUrl;
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if (!this.baseUrl) {
|
|
51
|
+
throw new Error('FastModule requires spinFastApiUrl configuration');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Create axios instance
|
|
55
|
+
this.httpClient = axios.create({
|
|
56
|
+
baseURL: this.baseUrl,
|
|
57
|
+
timeout: 10000,
|
|
58
|
+
headers: {
|
|
59
|
+
'Accept': 'application/json',
|
|
60
|
+
'Content-Type': 'application/json'
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Unified data access entry - intelligent proxy mode
|
|
67
|
+
* @param {string} type - Data type ('mints', 'orders', 'price', etc.)
|
|
68
|
+
* @param {Object} options - Request parameters
|
|
69
|
+
* @returns {Promise<Object|DataManager>} Return data or manager instance based on type
|
|
70
|
+
*/
|
|
71
|
+
async get(type, options = {}) {
|
|
72
|
+
const config = DATA_CONFIGS[type];
|
|
73
|
+
|
|
74
|
+
if (!config) {
|
|
75
|
+
throw new Error(`Unsupported data type: ${type}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (config.useManager) {
|
|
79
|
+
// Complex data → return manager instance
|
|
80
|
+
if (!config.ManagerClass) {
|
|
81
|
+
throw new Error(`Data manager ${type} not yet implemented`);
|
|
82
|
+
}
|
|
83
|
+
return new config.ManagerClass(this.sdk, options);
|
|
84
|
+
} else {
|
|
85
|
+
// Simple data → directly return API result
|
|
86
|
+
return this._directApiCall(config, options);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get token list
|
|
92
|
+
* @param {Object} options - Query parameters
|
|
93
|
+
* @param {number} options.page - Page number, default 1
|
|
94
|
+
* @param {number} options.limit - Items per page, default 10
|
|
95
|
+
* @param {string} options.sort_by - Sort method, default 'slot_asc'
|
|
96
|
+
* @returns {Promise<Object>} Token list data
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* const result = await sdk.fast.mints({ page: 1, limit: 10 });
|
|
100
|
+
* // Return format:
|
|
101
|
+
* // {
|
|
102
|
+
* // "success": true,
|
|
103
|
+
* // "data": {
|
|
104
|
+
* // "mints": ["56hfrQYiyRSUZdRKDuUvsqRik8j2UDW9kCisy7BiRxmg", "4RGUZQ7PGF2JQWXKxr9hybPs1ZY3LWDb4QQ7FSHx92g9"],
|
|
105
|
+
* // "total": null,
|
|
106
|
+
* // "page": 1,
|
|
107
|
+
* // "limit": 10,
|
|
108
|
+
* // "has_next": false,
|
|
109
|
+
* // "has_prev": false,
|
|
110
|
+
* // "next_cursor": null,
|
|
111
|
+
* // "sort_by": "slot_asc"
|
|
112
|
+
* // },
|
|
113
|
+
* // "message": "Operation successful"
|
|
114
|
+
* // }
|
|
115
|
+
*
|
|
116
|
+
* // 使用代币地址:
|
|
117
|
+
* const mintAddresses = result.data.mints; // 字符串数组
|
|
118
|
+
*/
|
|
119
|
+
async mints(options = {}) {
|
|
120
|
+
return this.get('mints', options);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 获取代币详情信息
|
|
125
|
+
* @param {string|Array} mint - 代币地址或地址数组
|
|
126
|
+
* @returns {Promise<Object>} 代币详情数据
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* // 获取单个代币详情
|
|
130
|
+
* const info = await sdk.fast.mint_info('56hfrQYiyRSUZdRKDuUvsqRik8j2UDW9kCisy7BiRxmg');
|
|
131
|
+
* // 返回格式:
|
|
132
|
+
* // {
|
|
133
|
+
* // "success": true,
|
|
134
|
+
* // "data": {
|
|
135
|
+
* // "details": [
|
|
136
|
+
* // {
|
|
137
|
+
* // "mint_account": "56hfrQYiyRSUZdRKDuUvsqRik8j2UDW9kCisy7BiRxmg",
|
|
138
|
+
* // "payer": "Hfi9FpHeqAz8qih87NccCqRQY7VWs3JH8ixqqBXRBLH5",
|
|
139
|
+
* // "curve_account": "4xPzWMvbGT2AMmCMcvCw3h3PA3iG6kNKixfJyZ45r2BA",
|
|
140
|
+
* // "pool_token_account": "7FsTN832wYsfa1fThy4sKZiMNavVRJ6gPk3SXbEwcAXH",
|
|
141
|
+
* // "pool_sol_account": "3j4PfGm7YNhpBLijBHgNXggvVzsDMYTJW5fNJQ6cV89N",
|
|
142
|
+
* // "fee_recipient": "4nffmKaNrex34LkJ99RLxMt2BbgXeopUi8kJnom3YWbv",
|
|
143
|
+
* // "base_fee_recipient": "A2eUsnXoMniwjjkqkrxcRcugntAcBsEY7yusoo2HXRTf",
|
|
144
|
+
* // "params_account": "DVRnPDW1MvUhRhDfE1kU6aGHoQoufBCmQNbqUH4WFgUd",
|
|
145
|
+
* // "name": "Hello",
|
|
146
|
+
* // "symbol": "HLO",
|
|
147
|
+
* // "uri": "https://example.com/hello-token.json",
|
|
148
|
+
* // "swap_fee": 250,
|
|
149
|
+
* // "borrow_fee": 300,
|
|
150
|
+
* // "fee_discount_flag": 2,
|
|
151
|
+
* // "create_timestamp": 1755667440,
|
|
152
|
+
* // "latest_price": "13514066072452801812769",
|
|
153
|
+
* // "latest_trade_time": 1755667451,
|
|
154
|
+
* // "total_sol_amount": 214303125000,
|
|
155
|
+
* // "total_margin_sol_amount": 5837102249,
|
|
156
|
+
* // "total_force_liquidations": 4,
|
|
157
|
+
* // "total_close_profit": 1605153562,
|
|
158
|
+
* // "created_by": "Hfi9FpHeqAz8qih87NccCqRQY7VWs3JH8ixqqBXRBLH5",
|
|
159
|
+
* // "last_updated_at": "2025-08-20T05:24:12.327211706Z"
|
|
160
|
+
* // }
|
|
161
|
+
* // ],
|
|
162
|
+
* // "total": 1
|
|
163
|
+
* // },
|
|
164
|
+
* // "message": "Operation successful"
|
|
165
|
+
* // }
|
|
166
|
+
*
|
|
167
|
+
* // 获取多个代币详情
|
|
168
|
+
* const info = await sdk.fast.mint_info(['56hfrQYiyRSUZdRKDuUvsqRik8j2UDW9kCisy7BiRxmg', 'another_mint_address']);
|
|
169
|
+
*
|
|
170
|
+
* // 使用详情数据:
|
|
171
|
+
* const details = info.data.details; // 详情数组
|
|
172
|
+
* const firstDetail = details[0]; // 第一个代币的详情
|
|
173
|
+
*/
|
|
174
|
+
async mint_info(mint) {
|
|
175
|
+
// 确保 mint 是数组格式
|
|
176
|
+
const mints = Array.isArray(mint) ? mint : [mint];
|
|
177
|
+
|
|
178
|
+
// 验证输入
|
|
179
|
+
if (mints.length === 0) {
|
|
180
|
+
throw new Error('mint_info: 至少需要提供一个代币地址');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 验证地址格式
|
|
184
|
+
for (const mintAddress of mints) {
|
|
185
|
+
if (!mintAddress || typeof mintAddress !== 'string') {
|
|
186
|
+
throw new Error('mint_info: 代币地址必须是有效的字符串');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return this.get('mint_info', { mints });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 直接API调用方法
|
|
195
|
+
* @private
|
|
196
|
+
* @param {Object} config - 数据配置
|
|
197
|
+
* @param {Object} params - 请求参数
|
|
198
|
+
* @returns {Promise<Object>} API响应数据
|
|
199
|
+
*/
|
|
200
|
+
async _directApiCall(config, params = {}) {
|
|
201
|
+
try {
|
|
202
|
+
//console.log(`FastModule: 请求API ${config.endpoint}`, params);
|
|
203
|
+
|
|
204
|
+
const requestConfig = {
|
|
205
|
+
method: config.method || 'GET',
|
|
206
|
+
url: config.endpoint
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// 根据请求方法设置参数
|
|
210
|
+
if (config.method === 'POST') {
|
|
211
|
+
requestConfig.data = params; // POST 请求使用 data
|
|
212
|
+
} else {
|
|
213
|
+
requestConfig.params = params; // GET 请求使用 params
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const response = await this.httpClient.request(requestConfig);
|
|
217
|
+
|
|
218
|
+
// 检查API响应格式
|
|
219
|
+
if (!response.data || !response.data.success) {
|
|
220
|
+
throw new Error(`API请求失败: ${response.data?.message || '未知错误'}`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return response.data;
|
|
224
|
+
|
|
225
|
+
} catch (error) {
|
|
226
|
+
if (error.response) {
|
|
227
|
+
// API返回错误
|
|
228
|
+
throw new Error(`API请求失败 [${error.response.status}]: ${error.response.data?.message || error.message}`);
|
|
229
|
+
} else if (error.request) {
|
|
230
|
+
// 网络错误
|
|
231
|
+
throw new Error(`网络请求失败: 无法连接到 ${this.baseUrl}`);
|
|
232
|
+
} else {
|
|
233
|
+
// 其他错误
|
|
234
|
+
throw new Error(`请求处理失败: ${error.message}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
// ========== 预留方法 ==========
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* 获取订单数据 Get Orders Data
|
|
245
|
+
* @param {string} mint - 代币地址 Token mint address
|
|
246
|
+
* @param {Object} options - 查询参数 Query parameters
|
|
247
|
+
* @param {string} options.type - 订单类型 Order type: "up_orders" (做空/short) 或 "down_orders" (做多/long)
|
|
248
|
+
* @param {number} options.page - 页码,默认1 Page number, default 1
|
|
249
|
+
* @param {number} options.limit - 每页数量,默认500 Items per page, default 500
|
|
250
|
+
* @returns {Promise<Object>} 订单数据,包含原始订单列表 Order data with raw order list
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* // 获取做多订单 Get long orders
|
|
254
|
+
* const ordersData = await sdk.fast.orders('6ZDJtGFTzrF3FaN5uaqa1h8EexW7BtQd4FwA9Dt7m3ee', { type: 'down_orders' });
|
|
255
|
+
*
|
|
256
|
+
* // 返回值示例 Return value example:
|
|
257
|
+
* // {
|
|
258
|
+
* // "success": true,
|
|
259
|
+
* // "data": {
|
|
260
|
+
* // "orders": [
|
|
261
|
+
* // {
|
|
262
|
+
* // "order_type": 1, // 订单类型 1=做多, 2=做空
|
|
263
|
+
* // "mint": "6ZDJtGFTzrF3FaN5uaqa1h8EexW7BtQd4FwA9Dt7m3ee", // 代币地址
|
|
264
|
+
* // "user": "JD1eNPaJpbtejKfgimbLYLkvpsTHyYzKCCozVLGLS6zu", // 用户地址
|
|
265
|
+
* // "lock_lp_start_price": "46618228118401293964111", // LP 开始价格(字符串)
|
|
266
|
+
* // "lock_lp_end_price": "45827474968448818396222", // LP 结束价格(字符串)
|
|
267
|
+
* // "lock_lp_sol_amount": 3299491609, // LP 锁定 SOL 数量(lamports)
|
|
268
|
+
* // "lock_lp_token_amount": 713848715669, // LP 锁定代币数量(最小单位)
|
|
269
|
+
* // "start_time": 1756352482, // 开始时间(Unix 时间戳)
|
|
270
|
+
* // "end_time": 1756525282, // 结束时间(Unix 时间戳)
|
|
271
|
+
* // "margin_sol_amount": 571062973, // 保证金 SOL 数量(lamports)
|
|
272
|
+
* // "borrow_amount": 3860656108, // 借款数量(lamports)
|
|
273
|
+
* // "position_asset_amount": 713848715669, // 持仓资产数量(最小单位)
|
|
274
|
+
* // "borrow_fee": 300, // 借款费用(基点,300 = 3%)
|
|
275
|
+
* // "order_pda": "5aVwYyzvC5Y2qykDgwG8o7EUwCrL8WgCJpgxoH3mihYb" // 订单 PDA 地址
|
|
276
|
+
* // }
|
|
277
|
+
* // ],
|
|
278
|
+
* // "total": 12, // 总订单数量
|
|
279
|
+
* // "order_type": "down_orders", // 订单类型(字符串)
|
|
280
|
+
* // "mint_account": "6ZDJtGFTzrF3FaN5uaqa1h8EexW7BtQd4FwA9Dt7m3ee", // 查询的代币地址
|
|
281
|
+
* // "page": 1, // 当前页码
|
|
282
|
+
* // "limit": 50, // 每页限制
|
|
283
|
+
* // "has_next": false, // 是否有下一页
|
|
284
|
+
* // "has_prev": false // 是否有上一页
|
|
285
|
+
* // },
|
|
286
|
+
* // "message": "Operation successful" // 操作结果消息
|
|
287
|
+
* // }
|
|
288
|
+
*
|
|
289
|
+
* // 使用工具方法处理数据 Use utility methods to process data:
|
|
290
|
+
* const lpPairs = OrderUtils.buildLpPairs(ordersData.data.orders); // 构建 LP 配对数组
|
|
291
|
+
* const orderAccounts = OrderUtils.buildOrderAccounts(ordersData.data.orders); // 构建订单账户数组
|
|
292
|
+
*
|
|
293
|
+
* // 访问订单数据 Access order data:
|
|
294
|
+
* const orders = ordersData.data.orders; // 订单数组
|
|
295
|
+
* const totalOrders = ordersData.data.total; // 总订单数量
|
|
296
|
+
* const firstOrder = orders[0]; // 第一个订单
|
|
297
|
+
* const orderPda = firstOrder.order_pda; // 订单 PDA 地址
|
|
298
|
+
* const userAddress = firstOrder.user; // 用户地址
|
|
299
|
+
* const marginAmount = firstOrder.margin_sol_amount; // 保证金数量(lamports)
|
|
300
|
+
* const borrowFee = firstOrder.borrow_fee; // 借款费用(基点)
|
|
301
|
+
*
|
|
302
|
+
* // 获取做空订单 Get short orders:
|
|
303
|
+
* const shortOrders = await sdk.fast.orders(mint, { type: 'up_orders' });
|
|
304
|
+
*
|
|
305
|
+
* // 分页获取订单 Get paginated orders:
|
|
306
|
+
* const pageTwo = await sdk.fast.orders(mint, { type: 'down_orders', page: 2, limit: 100 });
|
|
307
|
+
*/
|
|
308
|
+
async orders(mint, options = {}) {
|
|
309
|
+
const params = {
|
|
310
|
+
mint: mint,
|
|
311
|
+
type: options.type || 'down_orders',
|
|
312
|
+
page: options.page || 1,
|
|
313
|
+
limit: options.limit || 500,
|
|
314
|
+
...options
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
return this.get('orders', params);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* 获取价格数据(预留 - 简单直读模式)
|
|
322
|
+
* @param {string} mint - 代币地址
|
|
323
|
+
* @returns {Promise<string>} 最新价格字符串
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* // 获取代币最新价格
|
|
327
|
+
* const price = await sdk.fast.price('56hfrQYiyRSUZdRKDuUvsqRik8j2UDW9kCisy7BiRxmg');
|
|
328
|
+
* console.log('最新价格 Latest price:', price); // "13514066072452801812769"
|
|
329
|
+
*/
|
|
330
|
+
async price(mint) {
|
|
331
|
+
// 验证输入 Validate input
|
|
332
|
+
if (!mint || typeof mint !== 'string') {
|
|
333
|
+
throw new Error('price: 代币地址必须是有效的字符串 mint address must be a valid string');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// 调用 mint_info 接口 Call mint_info API
|
|
337
|
+
const result = await this.mint_info(mint);
|
|
338
|
+
|
|
339
|
+
// 检查返回数据 Check return data
|
|
340
|
+
if (!result || !result.data || !result.data.details || result.data.details.length === 0) {
|
|
341
|
+
throw new Error('price: 无法获取代币信息 Unable to fetch token information');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// 提取最新价格 Extract latest price
|
|
345
|
+
let latestPrice = result.data.details[0].latest_price;
|
|
346
|
+
|
|
347
|
+
if (!latestPrice) {
|
|
348
|
+
//throw new Error('price: 代币没有价格数据 Token has no price data');
|
|
349
|
+
const initialPrice = CurveAMM.getInitialPrice();
|
|
350
|
+
if (initialPrice === null) {
|
|
351
|
+
throw new Error('price: 无法计算初始价格 Unable to calculate initial price');
|
|
352
|
+
}
|
|
353
|
+
latestPrice = initialPrice.toString();
|
|
354
|
+
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return latestPrice;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* 获取用户订单 Get User Orders
|
|
362
|
+
* @param {string} user - 用户地址
|
|
363
|
+
* @param {string} mint - 代币地址
|
|
364
|
+
* @param {Object} options - 查询参数
|
|
365
|
+
* @param {number} options.page - 页码,默认1
|
|
366
|
+
* @param {number} options.limit - 每页数量,默认200
|
|
367
|
+
* @param {string} options.order_by - 排序方式,默认'start_time_desc'
|
|
368
|
+
* @returns {Promise<Object>} 用户订单数据
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* const userOrders = await sdk.fast.user_orders(
|
|
372
|
+
* '8iGFeUkRpyRx8w5uoUMbfZepUr6BfTdPuJmqGoNBntdb',
|
|
373
|
+
* '4Kq51Kt48FCwdo5CeKjRVPodH1ticHa7mZ5n5gqMEy1X',
|
|
374
|
+
* { page: 1, limit: 200, order_by: 'start_time_desc' }
|
|
375
|
+
* );
|
|
376
|
+
* // 返回格式:
|
|
377
|
+
* // {
|
|
378
|
+
* // "success": true,
|
|
379
|
+
* // "data": {
|
|
380
|
+
* // "orders": [
|
|
381
|
+
* // {
|
|
382
|
+
* // "order_type": 2,
|
|
383
|
+
* // "mint": "4Kq51Kt48FCwdo5CeKjRVPodH1ticHa7mZ5n5gqMEy1X",
|
|
384
|
+
* // "user": "8iGFeUkRpyRx8w5uoUMbfZepUr6BfTdPuJmqGoNBntdb",
|
|
385
|
+
* // "lock_lp_start_price": "753522984132656210522",
|
|
386
|
+
* // "lock_lp_end_price": "833102733432007194898",
|
|
387
|
+
* // "lock_lp_sol_amount": 2535405978,
|
|
388
|
+
* // "lock_lp_token_amount": 32000000000000,
|
|
389
|
+
* // "start_time": 1755964862,
|
|
390
|
+
* // "end_time": 1756137662,
|
|
391
|
+
* // "margin_sol_amount": 1909140052,
|
|
392
|
+
* // "borrow_amount": 32000000000000,
|
|
393
|
+
* // "position_asset_amount": 656690798,
|
|
394
|
+
* // "borrow_fee": 1200,
|
|
395
|
+
* // "order_pda": "59yP5tpDP6DBcyy4mge9wKKKdLmk45Th4sbd6Un9LxVN"
|
|
396
|
+
* // }
|
|
397
|
+
* // ],
|
|
398
|
+
* // "total": 11,
|
|
399
|
+
* // "user": "8iGFeUkRpyRx8w5uoUMbfZepUr6BfTdPuJmqGoNBntdb",
|
|
400
|
+
* // "mint_account": "4Kq51Kt48FCwdo5CeKjRVPodH1ticHa7mZ5n5gqMEy1X",
|
|
401
|
+
* // "page": 1,
|
|
402
|
+
* // "limit": 200,
|
|
403
|
+
* // "has_next": false,
|
|
404
|
+
* // "has_prev": false
|
|
405
|
+
* // },
|
|
406
|
+
* // "message": "Operation successful"
|
|
407
|
+
* // }
|
|
408
|
+
*
|
|
409
|
+
* // 使用订单数据:
|
|
410
|
+
* const orders = userOrders.data.orders; // 订单数组
|
|
411
|
+
* const totalCount = userOrders.data.total; // 总数量
|
|
412
|
+
*/
|
|
413
|
+
async user_orders(user, mint, options = {}) {
|
|
414
|
+
const params = {
|
|
415
|
+
user: user,
|
|
416
|
+
mint: mint,
|
|
417
|
+
page: options.page || 1,
|
|
418
|
+
limit: options.limit || 200,
|
|
419
|
+
order_by: options.order_by || 'start_time_desc',
|
|
420
|
+
...options
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
return this.get('user_orders', params);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
module.exports = FastModule;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
const { PublicKey, Transaction, SystemProgram } = require('@solana/web3.js');
|
|
2
|
+
const anchor = require('@coral-xyz/anchor');
|
|
3
|
+
// 统一使用 buffer 包,所有平台一致
|
|
4
|
+
const { Buffer } = require('buffer');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Parameter Module
|
|
8
|
+
* Handles creation and management of partner parameters
|
|
9
|
+
*/
|
|
10
|
+
class ParamModule {
|
|
11
|
+
constructor(sdk) {
|
|
12
|
+
this.sdk = sdk;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Create partner parameters
|
|
17
|
+
* @param {Object} params - Creation parameters
|
|
18
|
+
* @param {PublicKey} params.partner - Partner public key
|
|
19
|
+
* @returns {Promise<Object>} Object containing transaction, signers and account info
|
|
20
|
+
*/
|
|
21
|
+
async createParams({ partner }) {
|
|
22
|
+
console.log('Param Module - CreateParams:', {
|
|
23
|
+
partner: partner.toString()
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Calculate Admin account address (globally unique)
|
|
27
|
+
const [adminAccount] = PublicKey.findProgramAddressSync(
|
|
28
|
+
[Buffer.from("admin")],
|
|
29
|
+
this.sdk.programId
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Calculate partner parameters account address (using partner address as seed)
|
|
33
|
+
const [paramsAccount] = PublicKey.findProgramAddressSync(
|
|
34
|
+
[Buffer.from("params"), partner.toBuffer()],
|
|
35
|
+
this.sdk.programId
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
console.log('Calculated account addresses:');
|
|
39
|
+
console.log(' Admin account:', adminAccount.toString());
|
|
40
|
+
console.log(' Partner parameters account:', paramsAccount.toString());
|
|
41
|
+
|
|
42
|
+
// Create transaction instructions
|
|
43
|
+
const createParamsIx = await this.sdk.program.methods
|
|
44
|
+
.createParams()
|
|
45
|
+
.accounts({
|
|
46
|
+
partner: partner,
|
|
47
|
+
adminAccount: adminAccount,
|
|
48
|
+
params: paramsAccount,
|
|
49
|
+
systemProgram: SystemProgram.programId,
|
|
50
|
+
})
|
|
51
|
+
.instruction();
|
|
52
|
+
|
|
53
|
+
// Create transaction and add instructions
|
|
54
|
+
const transaction = new Transaction();
|
|
55
|
+
transaction.add(createParamsIx);
|
|
56
|
+
|
|
57
|
+
console.log('Partner parameters creation transaction built');
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
transaction,
|
|
61
|
+
signers: [], // createParams doesn't need additional signers, only partner signature
|
|
62
|
+
accounts: {
|
|
63
|
+
partner,
|
|
64
|
+
adminAccount,
|
|
65
|
+
paramsAccount
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get partner parameters account data
|
|
72
|
+
* @param {PublicKey} partner - Partner public key
|
|
73
|
+
* @returns {Promise<Object>} Parameters account data
|
|
74
|
+
*/
|
|
75
|
+
async getParams(partner) {
|
|
76
|
+
// 计算合作伙伴参数账户地址
|
|
77
|
+
const [paramsAccount] = PublicKey.findProgramAddressSync(
|
|
78
|
+
[Buffer.from("params"), partner.toBuffer()],
|
|
79
|
+
this.sdk.programId
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
// Check if account exists
|
|
84
|
+
const accountInfo = await this.sdk.connection.getAccountInfo(paramsAccount);
|
|
85
|
+
if (!accountInfo) {
|
|
86
|
+
throw new Error('Partner parameters account does not exist');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Try to parse data using Anchor
|
|
90
|
+
if (this.sdk.program.account.params) {
|
|
91
|
+
const paramsData = await this.sdk.program.account.params.fetch(paramsAccount);
|
|
92
|
+
return {
|
|
93
|
+
address: paramsAccount,
|
|
94
|
+
data: paramsData
|
|
95
|
+
};
|
|
96
|
+
} else {
|
|
97
|
+
// If Anchor is not available, return basic info
|
|
98
|
+
return {
|
|
99
|
+
address: paramsAccount,
|
|
100
|
+
accountInfo: accountInfo
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
} catch (error) {
|
|
104
|
+
throw new Error(`Failed to get partner parameters: ${error.message}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get Admin account data
|
|
110
|
+
* @returns {Promise<Object>} Admin account data
|
|
111
|
+
*/
|
|
112
|
+
async getAdmin() {
|
|
113
|
+
// Calculate Admin account address
|
|
114
|
+
const [adminAccount] = PublicKey.findProgramAddressSync(
|
|
115
|
+
[Buffer.from("admin")],
|
|
116
|
+
this.sdk.programId
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
// 检查账户是否存在
|
|
121
|
+
const accountInfo = await this.sdk.connection.getAccountInfo(adminAccount);
|
|
122
|
+
if (!accountInfo) {
|
|
123
|
+
throw new Error('Admin account does not exist');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 尝试使用 Anchor 解析数据
|
|
127
|
+
if (this.sdk.program.account.admin) {
|
|
128
|
+
const adminData = await this.sdk.program.account.admin.fetch(adminAccount);
|
|
129
|
+
return {
|
|
130
|
+
address: adminAccount,
|
|
131
|
+
data: adminData
|
|
132
|
+
};
|
|
133
|
+
} else {
|
|
134
|
+
// 如果 Anchor 不可用,返回基本信息
|
|
135
|
+
return {
|
|
136
|
+
address: adminAccount,
|
|
137
|
+
accountInfo: accountInfo
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
throw new Error(`Failed to get Admin account: ${error.message}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Calculate partner parameters account address
|
|
147
|
+
* @param {PublicKey} partner - Partner public key
|
|
148
|
+
* @returns {PublicKey} Parameters account address
|
|
149
|
+
*/
|
|
150
|
+
getParamsAddress(partner) {
|
|
151
|
+
const [paramsAccount] = PublicKey.findProgramAddressSync(
|
|
152
|
+
[Buffer.from("params"), partner.toBuffer()],
|
|
153
|
+
this.sdk.programId
|
|
154
|
+
);
|
|
155
|
+
return paramsAccount;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Calculate Admin account address
|
|
160
|
+
* @returns {PublicKey} Admin account address
|
|
161
|
+
*/
|
|
162
|
+
getAdminAddress() {
|
|
163
|
+
const [adminAccount] = PublicKey.findProgramAddressSync(
|
|
164
|
+
[Buffer.from("admin")],
|
|
165
|
+
this.sdk.programId
|
|
166
|
+
);
|
|
167
|
+
return adminAccount;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
module.exports = ParamModule;
|