@storm-trade/trading-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +354 -0
  2. package/dist/api-clients/clients/config-client.d.ts +56 -0
  3. package/dist/api-clients/clients/config-client.esm.js +72 -0
  4. package/dist/api-clients/clients/config-client.esm.js.map +1 -0
  5. package/dist/api-clients/clients/config-client.js +74 -0
  6. package/dist/api-clients/clients/config-client.js.map +1 -0
  7. package/dist/api-clients/clients/oracle-client.d.ts +17 -0
  8. package/dist/api-clients/clients/oracle-client.esm.js +24 -0
  9. package/dist/api-clients/clients/oracle-client.esm.js.map +1 -0
  10. package/dist/api-clients/clients/oracle-client.js +26 -0
  11. package/dist/api-clients/clients/oracle-client.js.map +1 -0
  12. package/dist/api-clients/clients/storm-client.d.ts +8 -0
  13. package/dist/api-clients/clients/storm-client.esm.js +18 -0
  14. package/dist/api-clients/clients/storm-client.esm.js.map +1 -0
  15. package/dist/api-clients/clients/storm-client.js +20 -0
  16. package/dist/api-clients/clients/storm-client.js.map +1 -0
  17. package/dist/api-clients/contracts/jetton-master.d.ts +8 -0
  18. package/dist/api-clients/contracts/jetton-master.esm.js +21 -0
  19. package/dist/api-clients/contracts/jetton-master.esm.js.map +1 -0
  20. package/dist/api-clients/contracts/jetton-master.js +23 -0
  21. package/dist/api-clients/contracts/jetton-master.js.map +1 -0
  22. package/dist/api-clients/contracts/position-manager/position-manager-packers.d.ts +10 -0
  23. package/dist/api-clients/contracts/position-manager/position-manager-packers.esm.js +148 -0
  24. package/dist/api-clients/contracts/position-manager/position-manager-packers.esm.js.map +1 -0
  25. package/dist/api-clients/contracts/position-manager/position-manager-packers.js +157 -0
  26. package/dist/api-clients/contracts/position-manager/position-manager-packers.js.map +1 -0
  27. package/dist/api-clients/contracts/position-manager/position-manager.types.d.ts +165 -0
  28. package/dist/api-clients/contracts/position-manager.d.ts +9 -0
  29. package/dist/api-clients/contracts/position-manager.esm.js +55 -0
  30. package/dist/api-clients/contracts/position-manager.esm.js.map +1 -0
  31. package/dist/api-clients/contracts/position-manager.js +57 -0
  32. package/dist/api-clients/contracts/position-manager.js.map +1 -0
  33. package/dist/api-clients/contracts/vault.d.ts +8 -0
  34. package/dist/api-clients/contracts/vault.esm.js +30 -0
  35. package/dist/api-clients/contracts/vault.esm.js.map +1 -0
  36. package/dist/api-clients/contracts/vault.js +32 -0
  37. package/dist/api-clients/contracts/vault.js.map +1 -0
  38. package/dist/api-clients/index.d.ts +7 -0
  39. package/dist/api-clients/index.esm.js +8 -0
  40. package/dist/api-clients/index.esm.js.map +1 -0
  41. package/dist/api-clients/index.js +20 -0
  42. package/dist/api-clients/index.js.map +1 -0
  43. package/dist/api-clients/utils/address-to-cell.d.ts +2 -0
  44. package/dist/api-clients/utils/address-to-cell.esm.js +8 -0
  45. package/dist/api-clients/utils/address-to-cell.esm.js.map +1 -0
  46. package/dist/api-clients/utils/address-to-cell.js +10 -0
  47. package/dist/api-clients/utils/address-to-cell.js.map +1 -0
  48. package/dist/api-clients/utils/ton-client-abstract.d.ts +8 -0
  49. package/dist/api-clients/utils/ton-client-abstract.esm.js +45 -0
  50. package/dist/api-clients/utils/ton-client-abstract.esm.js.map +1 -0
  51. package/dist/api-clients/utils/ton-client-abstract.js +47 -0
  52. package/dist/api-clients/utils/ton-client-abstract.js.map +1 -0
  53. package/dist/base-packers/index.d.ts +5 -0
  54. package/dist/base-packers/index.esm.js +4 -0
  55. package/dist/base-packers/index.esm.js.map +1 -0
  56. package/dist/base-packers/index.js +28 -0
  57. package/dist/base-packers/index.js.map +1 -0
  58. package/dist/base-packers/opcodes.d.ts +14 -0
  59. package/dist/base-packers/opcodes.esm.js +20 -0
  60. package/dist/base-packers/opcodes.esm.js.map +1 -0
  61. package/dist/base-packers/opcodes.js +20 -0
  62. package/dist/base-packers/opcodes.js.map +1 -0
  63. package/dist/base-packers/oracle-packer.d.ts +3 -0
  64. package/dist/base-packers/oracle-packer.esm.js +23 -0
  65. package/dist/base-packers/oracle-packer.esm.js.map +1 -0
  66. package/dist/base-packers/oracle-packer.js +25 -0
  67. package/dist/base-packers/oracle-packer.js.map +1 -0
  68. package/dist/base-packers/oracle-packer.types.d.ts +14 -0
  69. package/dist/base-packers/order-packers.d.ts +12 -0
  70. package/dist/base-packers/order-packers.esm.js +122 -0
  71. package/dist/base-packers/order-packers.esm.js.map +1 -0
  72. package/dist/base-packers/order-packers.js +133 -0
  73. package/dist/base-packers/order-packers.js.map +1 -0
  74. package/dist/base-packers/order-packers.types.d.ts +80 -0
  75. package/dist/base-packers/order-packers.types.esm.js +15 -0
  76. package/dist/base-packers/order-packers.types.esm.js.map +1 -0
  77. package/dist/base-packers/order-packers.types.js +15 -0
  78. package/dist/base-packers/order-packers.types.js.map +1 -0
  79. package/dist/common-packers/fees.d.ts +23 -0
  80. package/dist/common-packers/fees.esm.js +13 -0
  81. package/dist/common-packers/fees.esm.js.map +1 -0
  82. package/dist/common-packers/fees.js +15 -0
  83. package/dist/common-packers/fees.js.map +1 -0
  84. package/dist/common-packers/index.d.ts +2 -0
  85. package/dist/common-packers/index.esm.js +2 -0
  86. package/dist/common-packers/index.esm.js.map +1 -0
  87. package/dist/common-packers/index.js +15 -0
  88. package/dist/common-packers/index.js.map +1 -0
  89. package/dist/common-packers/order-packers.d.ts +10 -0
  90. package/dist/common-packers/order-packers.esm.js +146 -0
  91. package/dist/common-packers/order-packers.esm.js.map +1 -0
  92. package/dist/common-packers/order-packers.js +155 -0
  93. package/dist/common-packers/order-packers.js.map +1 -0
  94. package/dist/common-packers/order-packers.types.d.ts +102 -0
  95. package/dist/sdk/index.d.ts +2 -0
  96. package/dist/sdk/index.esm.js +2 -0
  97. package/dist/sdk/index.esm.js.map +1 -0
  98. package/dist/sdk/index.js +8 -0
  99. package/dist/sdk/index.js.map +1 -0
  100. package/dist/sdk/sdk.d.ts +42 -0
  101. package/dist/sdk/sdk.esm.js +352 -0
  102. package/dist/sdk/sdk.esm.js.map +1 -0
  103. package/dist/sdk/sdk.js +354 -0
  104. package/dist/sdk/sdk.js.map +1 -0
  105. package/dist/sdk/sdk.types.d.ts +327 -0
  106. package/package.json +102 -0
package/README.md ADDED
@@ -0,0 +1,354 @@
1
+ # @storm-trade/trading-sdk
2
+
3
+ A powerful TypeScript-based SDK for financial trading operations, specifically designed for [Storm Trade](https://app.storm.tg).
4
+ This SDK provides a comprehensive set of tools for managing trading positions, orders, and liquidity operations.
5
+
6
+ ## Features
7
+
8
+ - 📈 Market & Limit Orders
9
+ - 🛡️ Stop Loss & Take Profit Orders
10
+ - 💰 Liquidity Management
11
+ - 💼 Position Management
12
+ - 🔄 Margin Operations
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @storm-trade/trading-sdk @ton/ton
18
+ ```
19
+
20
+ ## SDK Initialization
21
+
22
+ ```typescript
23
+ import { TonClient } from '@ton/ton';
24
+ import { TradingSdk } from '@storm-trade/trading-sdk/sdk';
25
+ import { StormClient, OracleClient } from '@storm-trade/trading-sdk/api-clients';
26
+
27
+ // Stage Environment URLs
28
+ const ORACLE_URL = 'https://oracle.stage.stormtrade.dev';
29
+ const STORM_API_URL = 'https://api.stage.stormtrade.dev/api';
30
+ const TON_CENTER = 'https://testnet.toncenter.com/api/v2/jsonRPC';
31
+
32
+ // For Mainnet use (when available)
33
+ // const ORACLE_URL = 'https://oracle.storm.tg';
34
+ // const STORM_API_URL = 'https://api5.storm.tg/api';
35
+ // const TON_CENTER = 'https://toncenter.com/api/v2/jsonRPC';
36
+
37
+ // Initialize TonClient
38
+ const tonClient = new TonClient({
39
+ endpoint: TON_CENTER,
40
+ apiKey: YOUR_TONCENTER_API_KEY, // Get your API key from https://toncenter.com/
41
+ });
42
+
43
+ // Initialize the SDK
44
+ const tradingSdk = new StormTradingSdk(
45
+ new StormClient(STORM_API_URL, new OracleClient(ORACLE_URL)),
46
+ tonClient,
47
+ TRADER_ADDRESS, // Your TON wallet address (as string or Address object)
48
+ );
49
+
50
+ // Initialize the SDK (required before using it)
51
+ await tradingSdk.init();
52
+ ```
53
+
54
+ ## Understanding Value Formats
55
+
56
+ All amount values in the SDK use the smallest unit of the respective asset:
57
+
58
+ | Asset | Decimals | Example |
59
+ |-------------|----------|----------------------------------------|
60
+ | TON | 9 | 1 TON = 1_000_000_000n (1e9 nanotons) |
61
+ | USDT | 6 | 1 USDT = 1_000_000n (1e6 units) |
62
+ | NOT | 9 | 1 NOT = 1_000_000_000n (1e9 units) |
63
+ | Leverage | 9 | 2x = 2_000_000_000n |
64
+ | Price | 9 | 100$ = 100_000_000_000n |
65
+
66
+ ## Usage Examples
67
+
68
+ ### Creating Market Orders
69
+
70
+ ```typescript
71
+ // Market order using native TON as collateral
72
+ const marketOrderParams = await tradingSdk.createMarketOpenOrder({
73
+ baseAssetName: 'XRP', // The asset you want to trade
74
+ collateralAssetName: 'TON', // Using TON as collateral
75
+ direction: Direction.long, // Opening a long position
76
+ amount: 1_000_000_000n, // 1 TON (amount of collateral to use)
77
+ leverage: 2_000_000_000n, // 2x leverage
78
+ // Optional parameters
79
+ minBaseAssetAmount: 900_000_000n, // Minimum base asset to receive (slippage protection)
80
+ stopTriggerPrice: 80_000_000_000n, // Auto-create stop loss at execution
81
+ takeTriggerPrice: 120_000_000_000n, // Auto-create take profit at execution
82
+ expiration: Math.floor(Date.now() / 1000) + 15 * 60, // Custom expiration in Unix timestamp in seconds
83
+ });
84
+ ```
85
+
86
+ #### Market Orders
87
+
88
+ ```typescript
89
+ // Market order using a Jetton (NOT) as collateral
90
+ const marketOrderWithJetton = await tradingSdk.createMarketOpenOrder({
91
+ baseAssetName: 'XRP', // The trading pair's base asset
92
+ collateralAssetName: 'NOT', // Using NOT jetton as collateral
93
+ direction: Direction.long, // Opening a long position
94
+ amount: 1_00_000_000n, // 0.1 NOT (amount of collateral to use)
95
+ leverage: 2000_000_000n, // 2x leverage
96
+ minBaseAssetAmount: 90_000_000n, // Minimum amount of XRP to receive (slippage protection)
97
+ });
98
+
99
+ // Market order using native TON as collateral
100
+ const marketOrderWithTON = await tradingSdk.createMarketOpenOrder({
101
+ baseAssetName: 'XRP', // The trading pair's base asset
102
+ collateralAssetName: 'TON', // Using native TON as collateral
103
+ direction: Direction.short, // Opening a short position (betting price will go down)
104
+ amount: 100_000_000n, // 0.1 TON (amount of collateral to use)
105
+ leverage: 3000_000_000n, // 3x leverage
106
+ minBaseAssetAmount: 90_000_000n, // Minimum amount of XRP to receive (slippage protection)
107
+ });
108
+ ```
109
+
110
+ Market orders execute immediately at the current market price. The examples show:
111
+
112
+ 1. Using different collateral types (Jetton vs Native TON)
113
+ 2. Different trading directions (long vs short)
114
+ 3. Different leverage amounts (2x vs 3x)
115
+ 4. Slippage protection with minBaseAssetAmount
116
+
117
+ ### Creating Limit Orders
118
+
119
+ ```typescript
120
+ const limitOrderParams = await tradingSdk.createLimitOrder({
121
+ baseAssetName: 'XRP', // The trading pair's base asset
122
+ limitPrice: 1_00_000_000_000n, // Price in nanotons (1e9 TON), here it's 100 TON
123
+ collateralAssetName: 'TON', // Using TON as collateral
124
+ direction: Direction.long, // Opening a long position
125
+ amount: 1_000_000_000n, // 1 TON (amount of collateral to use)
126
+ leverage: 2000_000_000n, // Leverage of 2x (specified in 1e9 format)
127
+ });
128
+ ```
129
+
130
+ This example creates a limit order with the following characteristics:
131
+
132
+ - Trading XRP with TON as collateral
133
+ - Setting a limit price of 100 TON per XRP
134
+ - Opening a long position (betting that XRP price will go up)
135
+ - Using 1 TON as collateral (specified as 1e9 units)
136
+ - Using 2x leverage to amplify potential gains (and risks)
137
+
138
+ #### Stop Market and Stop Limit Orders
139
+
140
+ ```typescript
141
+ // Stop market order
142
+ const stopMarketOrder = await tradingSdk.createStopMarketOrder({
143
+ baseAssetName: 'XRP',
144
+ collateralAssetName: 'TON',
145
+ direction: Direction.long,
146
+ amount: 1_000_000_000n, // 1 TON (amount of collateral to use)
147
+ leverage: 2_000_000_000n, // 2x leverage
148
+ stopPrice: 105_000_000_000n, // Triggers when price reaches 105 TON per XRP
149
+ minBaseAssetAmount: 900_000_000n, // Minimum amount of XRP to receive (slippage protection)
150
+ });
151
+
152
+ // Stop limit order
153
+ const stopLimitOrder = await tradingSdk.createStopLimitOrder({
154
+ baseAssetName: 'XRP',
155
+ collateralAssetName: 'TON',
156
+ direction: Direction.long,
157
+ amount: 1_000_000_000n, // 1 TON (amount of collateral to use)
158
+ leverage: 2_000_000_000n, // 2x leverage
159
+ stopPrice: 105_000_000_000n, // Triggers when price reaches 105 TON per XRP
160
+ limitPrice: 106_000_000_000n, // Limit price for execution after trigger
161
+ });
162
+ ```
163
+
164
+ ### Liquidity Management
165
+
166
+ ```typescript
167
+ // Providing liquidity with NOT jetton
168
+ await tradingSdk.provideLiquidity({
169
+ assetName: 'NOT', // The asset to provide liquidity for
170
+ amount: 1_00_000_000n, // 0.1 NOT (amount of collateral to use)
171
+ });
172
+
173
+ // Providing liquidity with USDT
174
+ await tradingSdk.provideLiquidity({
175
+ assetName: 'USDT', // USDT as liquidity asset
176
+ amount: 1_000_000n, // 1 USDT (USDT uses 6 decimal places)
177
+ });
178
+
179
+ // Providing liquidity with native TON
180
+ await tradingSdk.provideLiquidity({
181
+ assetName: 'TON', // Native TON as liquidity asset
182
+ amount: 1_00_000_000n, // 0.1 TON
183
+ });
184
+ ```
185
+
186
+ Liquidity provision examples demonstrate:
187
+
188
+ 1. Support for different asset types (Jettons and native TON)
189
+ 2. Different decimal precision handling:
190
+ - TON and most assets (9 decimals):
191
+ - 1 TON = 1_000_000_000n (1e9 nanotons)
192
+ - 0.5 TON = 500_000_000n (0.5 \* 1e9 nanotons)
193
+ - USDT (6 decimals):
194
+ - 1 USDT = 1_000_000n (1e6 units)
195
+ - 0.5 USDT = 500_000n (0.5 \* 1e6 units)
196
+ 3. The provided liquidity can be used by traders for leveraged trading
197
+
198
+ ### Position Management
199
+
200
+ ```typescript
201
+ // Adding margin to an existing position
202
+ await tradingSdk.addMargin({
203
+ baseAssetName: 'BTC', // The trading pair's base asset
204
+ collateralAssetName: 'TON', // Collateral type to add
205
+ amount: 500_000_000n, // Adding 0.5 TON as additional margin
206
+ direction: Direction.long, // For the long position
207
+ });
208
+
209
+ // Removing margin from a position
210
+ await tradingSdk.removeMargin({
211
+ baseAssetName: 'BTC', // The trading pair's base asset
212
+ collateralAssetName: 'TON', // Collateral type to remove
213
+ amount: 200_000_000n, // Removing 0.2 TON of margin
214
+ direction: Direction.long, // From the long position
215
+ });
216
+ ```
217
+
218
+ ### Stop Loss and Take Profit Orders
219
+
220
+ ```typescript
221
+ // Setting a Stop Loss order
222
+ const stopLossOrder = await tradingSdk.createStopLossOrder({
223
+ baseAssetName: 'XRP',
224
+ collateralAssetName: 'TON',
225
+ direction: Direction.long,
226
+ amount: 1_000_000_000n, // 1 TON (amount of collateral to use)
227
+ triggerPrice: 90_000_000_000n, // Stop loss triggers at 90 TON per XRP
228
+ });
229
+
230
+ // Setting a Take Profit order
231
+ const takeProfitOrder = await tradingSdk.createTakeProfitOrder({
232
+ baseAssetName: 'XRP',
233
+ collateralAssetName: 'TON',
234
+ direction: Direction.long,
235
+ amount: 1_000_000_000n, // 1 TON (amount of collateral to use)
236
+ triggerPrice: 110_000_000_000n, // Take profit triggers at 110 TON per XRP
237
+ });
238
+ ```
239
+
240
+ ### Closing a Position
241
+
242
+ ```typescript
243
+ // Close position (partially or fully)
244
+ const closePositionParams = await tradingSdk.createClosePositionOrder({
245
+ baseAssetName: 'XRP', // The asset in the position
246
+ collateralAssetName: 'TON', // Collateral asset of the position
247
+ direction: Direction.long, // Direction of the position to close
248
+ size: 1_000_000_000n, // Amount of base asset to close (1 XRP)
249
+ });
250
+ ```
251
+
252
+ ### Canceling an Order
253
+
254
+ ```typescript
255
+ // Cancel a pending order
256
+ const cancelOrderParams = await tradingSdk.cancelOrder({
257
+ baseAssetName: 'XRP',
258
+ collateralAssetName: 'TON',
259
+ direction: Direction.long,
260
+ orderType: OrderType.limit, // Order type to cancel
261
+ orderIndex: 0, // Order index in the position (can be retrieved from tradingSdk.getPositionManagerData)
262
+ });
263
+ ```
264
+
265
+ ### Managing Position Margin
266
+
267
+ ```typescript
268
+ // Add margin to position
269
+ const addMarginParams = await tradingSdk.addMargin({
270
+ baseAssetName: 'XRP',
271
+ collateralAssetName: 'TON',
272
+ direction: Direction.long, // Direction of the position
273
+ amount: 500_000_000n, // Adding 0.5 TON as additional margin
274
+ // Optional parameter
275
+ oraclePayload: oracleData, // Custom oracle data (if available)
276
+ });
277
+
278
+ // Remove margin from a position
279
+ const removeMarginParams = await tradingSdk.removeMargin({
280
+ baseAssetName: 'XRP',
281
+ collateralAssetName: 'TON',
282
+ direction: Direction.long, // Direction of the position
283
+ amount: 200_000_000n, // Removing 0.2 TON of margin
284
+ // Optional parameter
285
+ oraclePayload: oracleData, // Custom oracle data (if available)
286
+ });
287
+ ```
288
+
289
+ ### Liquidity Management
290
+
291
+ ```typescript
292
+ // Providing liquidity with native TON
293
+ const provideLiquidityParams = await tradingSdk.provideLiquidity({
294
+ assetName: 'TON', // Asset to provide as liquidity
295
+ amount: 1_000_000_000n, // 1 TON
296
+ });
297
+
298
+ // Withdraw liquidity
299
+ const withdrawLiquidityParams = await tradingSdk.withdrawLiquidity({
300
+ assetName: 'TON', // Asset to withdraw
301
+ amountOfSLP: 500_000_000n, // 0.5 SLP tokens (Storm Liquidity Provider tokens)
302
+ });
303
+ ```
304
+
305
+ ## Integration with TON Connect
306
+
307
+ For frontend applications, you can integrate with TON Connect to allow users to connect their TON wallets:
308
+
309
+ ```typescript
310
+ import { TonConnectUI } from '@tonconnect/ui';
311
+ import { StormTradingSdk } from '@storm-trade/trading-sdk';
312
+ import { StormClient, OracleClient } from '@storm-trade/trading-sdk';
313
+
314
+ // Initialize TonConnect UI
315
+ const tonConnectUI = new TonConnectUI({
316
+ manifestUrl: 'https://your-app.com/tonconnect-manifest.json',
317
+ });
318
+
319
+ // Initialize Storm Trading SDK with TON Connect
320
+ const tradingSdk = new StormTradingSdk(
321
+ new StormClient(STORM_API_URL, new OracleClient(ORACLE_URL)),
322
+ tonConnectUI.connector, // Use TonConnect as the client
323
+ tonConnectUI.wallet?.account.address || '', // User's wallet address from TON Connect
324
+ );
325
+
326
+ // Initialize the SDK
327
+ await tradingSdk.init();
328
+
329
+ // Format transaction parameters for TON Connect
330
+ const formatTxParamsForTonConnect = (txParams) => {
331
+ return {
332
+ validUntil: Math.floor(Date.now() / 1000) + 300, // 5 minutes
333
+ messages: [
334
+ {
335
+ address: txParams.to.toString(),
336
+ amount: txParams.value.toString(),
337
+ payload: txParams.body.toBoc().toString('base64')
338
+ }
339
+ ]
340
+ };
341
+ };
342
+
343
+ // Usage example
344
+ const txParams = await tradingSdk.provideLiquidity({
345
+ assetName: 'TON',
346
+ amount: 1_000_000_000n, // 1 TON
347
+ });
348
+
349
+ // Convert params for TON Connect
350
+ const transaction = formatTxParamsForTonConnect(txParams);
351
+
352
+ // Send transaction through TON Connect
353
+ const result = await tonConnectUI.sendTransaction(transaction);
354
+ ```
@@ -0,0 +1,56 @@
1
+ export type Asset = {
2
+ name: string;
3
+ decimals: number;
4
+ assetId: string;
5
+ };
6
+ export type Market = {
7
+ address: string;
8
+ quoteAsset: string;
9
+ baseAsset: string;
10
+ name: string;
11
+ ticker: string;
12
+ quoteAssetId: string;
13
+ settlementToken: string;
14
+ type: string;
15
+ vaultAddress: string;
16
+ };
17
+ export type LiquiditySource = {
18
+ asset: Asset;
19
+ vaultAddress: string;
20
+ quoteAssetId: string;
21
+ lpJettonMaster: string;
22
+ };
23
+ export type StormConfig = {
24
+ referralCollectionAddress: string;
25
+ genesisCollectionAddress: string;
26
+ assets: Asset[];
27
+ openedMarkets: Market[];
28
+ liquiditySources: LiquiditySource[];
29
+ stormJettonMasterAddress: string;
30
+ };
31
+ export type AssetConfigInfo = {
32
+ name: string;
33
+ type: string;
34
+ index: number;
35
+ };
36
+ export declare class ConfigClient {
37
+ private readonly CONFIG_URL;
38
+ private cfg?;
39
+ private assetIndexByName;
40
+ private vaultByNames;
41
+ private ammByBaseAsset;
42
+ private assetsConfig;
43
+ private assetsInfo;
44
+ constructor(CONFIG_URL: string);
45
+ fetchConfig(): Promise<this>;
46
+ fetchAssetsConfig(): Promise<this>;
47
+ provideConfig(stormConfig: StormConfig): this;
48
+ provideAssetsConfig(assetsConfig: AssetConfigInfo[]): void;
49
+ getAssetIndexByName(assetName: string): number | undefined;
50
+ getAmmByAssetName(baseAsset: string, collateralAsset: string): Market | undefined;
51
+ getVaultConfigByAssetName(assetName: string): LiquiditySource | undefined;
52
+ requireAssetIndexByName(assetName: string): number;
53
+ requireAmmByAssetName(baseAsset: string, collateralAsset: string): Market;
54
+ requireVaultConfigByAssetName(assetName: string): LiquiditySource;
55
+ config(): StormConfig | undefined;
56
+ }
@@ -0,0 +1,72 @@
1
+ class ConfigClient {
2
+ CONFIG_URL;
3
+ cfg;
4
+ assetIndexByName = new Map();
5
+ vaultByNames = new Map();
6
+ ammByBaseAsset = new Map();
7
+ assetsConfig = [];
8
+ assetsInfo = [];
9
+ constructor(CONFIG_URL) {
10
+ this.CONFIG_URL = CONFIG_URL;
11
+ }
12
+ async fetchConfig() {
13
+ const response = await fetch(this.CONFIG_URL);
14
+ this.provideConfig(await response.json());
15
+ return this;
16
+ }
17
+ async fetchAssetsConfig() {
18
+ const response = await fetch(`${this.CONFIG_URL}/assets`);
19
+ this.provideAssetsConfig(await response.json());
20
+ return this;
21
+ }
22
+ provideConfig(stormConfig) {
23
+ this.cfg = stormConfig;
24
+ this.vaultByNames = new Map(stormConfig.liquiditySources.map(ls => [ls.asset.name, ls]));
25
+ this.ammByBaseAsset = new Map(stormConfig.openedMarkets.map(market => [
26
+ `${market.baseAsset}:${market.settlementToken}`,
27
+ market,
28
+ ]));
29
+ this.assetsInfo = stormConfig.assets;
30
+ return this;
31
+ }
32
+ provideAssetsConfig(assetsConfig) {
33
+ this.assetsConfig = assetsConfig;
34
+ this.assetIndexByName = new Map(assetsConfig.map(ac => [ac.name, ac.index]));
35
+ }
36
+ getAssetIndexByName(assetName) {
37
+ return this.assetIndexByName.get(assetName);
38
+ }
39
+ getAmmByAssetName(baseAsset, collateralAsset) {
40
+ return this.ammByBaseAsset.get(`${baseAsset}:${collateralAsset}`);
41
+ }
42
+ getVaultConfigByAssetName(assetName) {
43
+ return this.vaultByNames.get(assetName);
44
+ }
45
+ requireAssetIndexByName(assetName) {
46
+ const assetIndex = this.assetIndexByName.get(assetName);
47
+ if (!assetIndex) {
48
+ throw new Error(`Asset ${assetName} not found`);
49
+ }
50
+ return assetIndex;
51
+ }
52
+ requireAmmByAssetName(baseAsset, collateralAsset) {
53
+ const amm = this.ammByBaseAsset.get(`${baseAsset}:${collateralAsset}`);
54
+ if (!amm) {
55
+ throw new Error();
56
+ }
57
+ return amm;
58
+ }
59
+ requireVaultConfigByAssetName(assetName) {
60
+ const vault = this.vaultByNames.get(assetName);
61
+ if (!vault) {
62
+ throw new Error();
63
+ }
64
+ return vault;
65
+ }
66
+ config() {
67
+ return this.cfg;
68
+ }
69
+ }
70
+
71
+ export { ConfigClient };
72
+ //# sourceMappingURL=config-client.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-client.esm.js","sources":["../../../src/api-clients/clients/config-client.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ class ConfigClient {
4
+ CONFIG_URL;
5
+ cfg;
6
+ assetIndexByName = new Map();
7
+ vaultByNames = new Map();
8
+ ammByBaseAsset = new Map();
9
+ assetsConfig = [];
10
+ assetsInfo = [];
11
+ constructor(CONFIG_URL) {
12
+ this.CONFIG_URL = CONFIG_URL;
13
+ }
14
+ async fetchConfig() {
15
+ const response = await fetch(this.CONFIG_URL);
16
+ this.provideConfig(await response.json());
17
+ return this;
18
+ }
19
+ async fetchAssetsConfig() {
20
+ const response = await fetch(`${this.CONFIG_URL}/assets`);
21
+ this.provideAssetsConfig(await response.json());
22
+ return this;
23
+ }
24
+ provideConfig(stormConfig) {
25
+ this.cfg = stormConfig;
26
+ this.vaultByNames = new Map(stormConfig.liquiditySources.map(ls => [ls.asset.name, ls]));
27
+ this.ammByBaseAsset = new Map(stormConfig.openedMarkets.map(market => [
28
+ `${market.baseAsset}:${market.settlementToken}`,
29
+ market,
30
+ ]));
31
+ this.assetsInfo = stormConfig.assets;
32
+ return this;
33
+ }
34
+ provideAssetsConfig(assetsConfig) {
35
+ this.assetsConfig = assetsConfig;
36
+ this.assetIndexByName = new Map(assetsConfig.map(ac => [ac.name, ac.index]));
37
+ }
38
+ getAssetIndexByName(assetName) {
39
+ return this.assetIndexByName.get(assetName);
40
+ }
41
+ getAmmByAssetName(baseAsset, collateralAsset) {
42
+ return this.ammByBaseAsset.get(`${baseAsset}:${collateralAsset}`);
43
+ }
44
+ getVaultConfigByAssetName(assetName) {
45
+ return this.vaultByNames.get(assetName);
46
+ }
47
+ requireAssetIndexByName(assetName) {
48
+ const assetIndex = this.assetIndexByName.get(assetName);
49
+ if (!assetIndex) {
50
+ throw new Error(`Asset ${assetName} not found`);
51
+ }
52
+ return assetIndex;
53
+ }
54
+ requireAmmByAssetName(baseAsset, collateralAsset) {
55
+ const amm = this.ammByBaseAsset.get(`${baseAsset}:${collateralAsset}`);
56
+ if (!amm) {
57
+ throw new Error();
58
+ }
59
+ return amm;
60
+ }
61
+ requireVaultConfigByAssetName(assetName) {
62
+ const vault = this.vaultByNames.get(assetName);
63
+ if (!vault) {
64
+ throw new Error();
65
+ }
66
+ return vault;
67
+ }
68
+ config() {
69
+ return this.cfg;
70
+ }
71
+ }
72
+
73
+ exports.ConfigClient = ConfigClient;
74
+ //# sourceMappingURL=config-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-client.js","sources":["../../../src/api-clients/clients/config-client.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { Cell } from '@ton/ton';
2
+ export type LastPriceResponse = {
3
+ result_message: {
4
+ price_ref: string;
5
+ signatures_ref: string;
6
+ };
7
+ };
8
+ export declare class OracleClient {
9
+ private client;
10
+ constructor(baseURL: string);
11
+ getPrice(symbol: string): Promise<{
12
+ result_message: {
13
+ priceRef: Cell;
14
+ signaturesRef: Cell;
15
+ };
16
+ }>;
17
+ }
@@ -0,0 +1,24 @@
1
+ import { createFetchInstance } from '@hastom/fetch';
2
+ import { Cell } from '@ton/ton';
3
+
4
+ class OracleClient {
5
+ client;
6
+ constructor(baseURL) {
7
+ this.client = createFetchInstance({ baseURL });
8
+ }
9
+ async getPrice(symbol) {
10
+ const res = await this.client.get(`feed/${symbol}/last`);
11
+ const jsonResp = await res.json();
12
+ const { price_ref, signatures_ref } = jsonResp.result_message;
13
+ return {
14
+ ...jsonResp,
15
+ result_message: {
16
+ priceRef: Cell.fromBase64(price_ref),
17
+ signaturesRef: Cell.fromBase64(signatures_ref),
18
+ },
19
+ };
20
+ }
21
+ }
22
+
23
+ export { OracleClient };
24
+ //# sourceMappingURL=oracle-client.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oracle-client.esm.js","sources":["../../../src/api-clients/clients/oracle-client.ts"],"sourcesContent":[null],"names":[],"mappings":";;;MAWa,YAAY,CAAA;AACf,IAAA,MAAM;AAEd,IAAA,WAAA,CAAY,OAAe,EAAA;QACzB,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,EAAE,OAAO,EAAE,CAAC;;IAGhD,MAAM,QAAQ,CAAC,MAAc,EAAA;AAC3B,QAAA,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA,KAAA,EAAQ,MAAM,CAAA,KAAA,CAAO,CAAC;AACxD,QAAA,MAAM,QAAQ,GAAsB,MAAM,GAAG,CAAC,IAAI,EAAE;QACpD,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC,cAAc;QAE7D,OAAO;AACL,YAAA,GAAG,QAAQ;AACX,YAAA,cAAc,EAAE;AACd,gBAAA,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;AACpC,gBAAA,aAAa,EAAE,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC;AAC/C,aAAA;SACF;;AAEJ;;;;"}
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ var fetch = require('@hastom/fetch');
4
+ var ton = require('@ton/ton');
5
+
6
+ class OracleClient {
7
+ client;
8
+ constructor(baseURL) {
9
+ this.client = fetch.createFetchInstance({ baseURL });
10
+ }
11
+ async getPrice(symbol) {
12
+ const res = await this.client.get(`feed/${symbol}/last`);
13
+ const jsonResp = await res.json();
14
+ const { price_ref, signatures_ref } = jsonResp.result_message;
15
+ return {
16
+ ...jsonResp,
17
+ result_message: {
18
+ priceRef: ton.Cell.fromBase64(price_ref),
19
+ signaturesRef: ton.Cell.fromBase64(signatures_ref),
20
+ },
21
+ };
22
+ }
23
+ }
24
+
25
+ exports.OracleClient = OracleClient;
26
+ //# sourceMappingURL=oracle-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oracle-client.js","sources":["../../../src/api-clients/clients/oracle-client.ts"],"sourcesContent":[null],"names":["createFetchInstance","Cell"],"mappings":";;;;;MAWa,YAAY,CAAA;AACf,IAAA,MAAM;AAEd,IAAA,WAAA,CAAY,OAAe,EAAA;QACzB,IAAI,CAAC,MAAM,GAAGA,yBAAmB,CAAC,EAAE,OAAO,EAAE,CAAC;;IAGhD,MAAM,QAAQ,CAAC,MAAc,EAAA;AAC3B,QAAA,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA,KAAA,EAAQ,MAAM,CAAA,KAAA,CAAO,CAAC;AACxD,QAAA,MAAM,QAAQ,GAAsB,MAAM,GAAG,CAAC,IAAI,EAAE;QACpD,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC,cAAc;QAE7D,OAAO;AACL,YAAA,GAAG,QAAQ;AACX,YAAA,cAAc,EAAE;AACd,gBAAA,QAAQ,EAAEC,QAAI,CAAC,UAAU,CAAC,SAAS,CAAC;AACpC,gBAAA,aAAa,EAAEA,QAAI,CAAC,UAAU,CAAC,cAAc,CAAC;AAC/C,aAAA;SACF;;AAEJ;;;;"}
@@ -0,0 +1,8 @@
1
+ import { ConfigClient } from './config-client';
2
+ import { OracleClient } from './oracle-client';
3
+ export declare class StormClient {
4
+ readonly oracleClient: OracleClient;
5
+ private readonly client;
6
+ readonly config: ConfigClient;
7
+ constructor(baseURL: string, oracleClient: OracleClient);
8
+ }
@@ -0,0 +1,18 @@
1
+ import { createFetchInstance } from '@hastom/fetch';
2
+ import { ConfigClient } from './config-client.esm.js';
3
+
4
+ class StormClient {
5
+ oracleClient;
6
+ client;
7
+ config;
8
+ constructor(baseURL, oracleClient) {
9
+ this.oracleClient = oracleClient;
10
+ this.client = createFetchInstance({
11
+ baseURL,
12
+ });
13
+ this.config = new ConfigClient(`${baseURL}/config`);
14
+ }
15
+ }
16
+
17
+ export { StormClient };
18
+ //# sourceMappingURL=storm-client.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storm-client.esm.js","sources":["../../../src/api-clients/clients/storm-client.ts"],"sourcesContent":[null],"names":[],"mappings":";;;MAIa,WAAW,CAAA;AAMJ,IAAA,YAAA;AALD,IAAA,MAAM;AACP,IAAA,MAAM;IAEtB,WACE,CAAA,OAAe,EACC,YAA0B,EAAA;QAA1B,IAAY,CAAA,YAAA,GAAZ,YAAY;AAE5B,QAAA,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC;YAChC,OAAO;AACR,SAAA,CAAC;QACF,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,CAAG,EAAA,OAAO,CAAS,OAAA,CAAA,CAAC;;AAEtD;;;;"}