@soroswap/sdk 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +389 -0
- package/dist/auth/auth-manager.d.ts +57 -0
- package/dist/auth/auth-manager.d.ts.map +1 -0
- package/dist/auth/auth-manager.js +165 -0
- package/dist/auth/auth-manager.js.map +1 -0
- package/dist/cache/token-cache.d.ts +48 -0
- package/dist/cache/token-cache.d.ts.map +1 -0
- package/dist/cache/token-cache.js +88 -0
- package/dist/cache/token-cache.js.map +1 -0
- package/dist/clients/http-client.d.ts +41 -0
- package/dist/clients/http-client.d.ts.map +1 -0
- package/dist/clients/http-client.js +121 -0
- package/dist/clients/http-client.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/soroswap-sdk.d.ts +78 -0
- package/dist/soroswap-sdk.d.ts.map +1 -0
- package/dist/soroswap-sdk.js +173 -0
- package/dist/soroswap-sdk.js.map +1 -0
- package/dist/types/auth.d.ts +16 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +3 -0
- package/dist/types/auth.js.map +1 -0
- package/dist/types/common.d.ts +24 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +31 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/index.d.ts +184 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +48 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/quote.d.ts +78 -0
- package/dist/types/quote.d.ts.map +1 -0
- package/dist/types/quote.js +3 -0
- package/dist/types/quote.js.map +1 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
# Soroswap SDK
|
|
2
|
+
|
|
3
|
+
Official TypeScript SDK for [Soroswap.Finance](https://soroswap.finance) - The first DEX and exchange aggregator built on Stellar, powered by smart contracts on Soroban.
|
|
4
|
+
|
|
5
|
+
## ๐ Features
|
|
6
|
+
|
|
7
|
+
- **๐ Automatic Authentication**: Handles login, token refresh, and session management
|
|
8
|
+
- **๐ฑ Trading Operations**: Get quotes, send transactions, and access multiple protocols
|
|
9
|
+
- **๐ง Liquidity Management**: Add/remove liquidity and track positions
|
|
10
|
+
- **๐ Market Data**: Access pools, prices, and asset information
|
|
11
|
+
- **๐ Server-Side Focused**: Secure handling of credentials and sensitive operations
|
|
12
|
+
- **๐ TypeScript Support**: Full type safety with comprehensive interfaces
|
|
13
|
+
- **โก Token Caching**: In-memory token management with automatic refresh
|
|
14
|
+
- **๐งช Well Tested**: Comprehensive unit test coverage
|
|
15
|
+
|
|
16
|
+
## ๐ Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm install soroswap-sdk
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## ๐ Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { SoroswapSDK } from 'soroswap-sdk';
|
|
26
|
+
|
|
27
|
+
// Initialize the SDK
|
|
28
|
+
const soroswapClient = new SoroswapSDK({
|
|
29
|
+
email: 'your-email@example.com',
|
|
30
|
+
password: 'your-password',
|
|
31
|
+
defaultNetwork: 'mainnet', // or 'testnet'
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Get a quote for a swap
|
|
35
|
+
const quote = await soroswapClient.quote({
|
|
36
|
+
assetIn: 'CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA',
|
|
37
|
+
assetOut: 'CDTKPWPLOURQA2SGTKTUQOWRCBZEORB4BWBOMJ3D3ZTQQSGE5F6JBQLV',
|
|
38
|
+
amount: '10000000',
|
|
39
|
+
tradeType: 'EXACT_IN',
|
|
40
|
+
protocols: ['soroswap', 'aqua'],
|
|
41
|
+
from: 'YOUR_WALLET_ADDRESS',
|
|
42
|
+
to: 'RECIPIENT_ADDRESS'
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Sign the transaction with your preferred signer
|
|
46
|
+
const signedXdr = await yourSigner.sign(quote.xdr);
|
|
47
|
+
|
|
48
|
+
// Send the signed transaction
|
|
49
|
+
const result = await soroswapClient.send(signedXdr, 100);
|
|
50
|
+
console.log('Transaction hash:', result.hash);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## ๐ง Configuration
|
|
54
|
+
|
|
55
|
+
### SDK Configuration Options
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
interface SoroswapSDKConfig {
|
|
59
|
+
email: string; // Your Soroswap account email
|
|
60
|
+
password: string; // Your Soroswap account password
|
|
61
|
+
defaultNetwork?: Network; // 'mainnet' | 'testnet' (defaults to 'mainnet')
|
|
62
|
+
timeout?: number; // Request timeout in ms (defaults to 30000)
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Environment Variables
|
|
67
|
+
|
|
68
|
+
For better security, you can use environment variables:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
const sdk = new SoroswapSDK({
|
|
72
|
+
email: process.env.SOROSWAP_EMAIL!,
|
|
73
|
+
password: process.env.SOROSWAP_PASSWORD!,
|
|
74
|
+
defaultNetwork: process.env.NODE_ENV === 'production' ? 'mainnet' : 'testnet'
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## ๐ API Reference
|
|
79
|
+
|
|
80
|
+
### Authentication
|
|
81
|
+
|
|
82
|
+
The SDK handles authentication automatically, but you can also manage it manually:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// Check authentication status
|
|
86
|
+
const isAuth = sdk.isAuthenticated();
|
|
87
|
+
|
|
88
|
+
// Get user information
|
|
89
|
+
const userInfo = sdk.getUserInfo();
|
|
90
|
+
|
|
91
|
+
// Logout (clears tokens)
|
|
92
|
+
sdk.logout();
|
|
93
|
+
|
|
94
|
+
// Register a new user
|
|
95
|
+
await sdk.register({
|
|
96
|
+
username: 'newuser',
|
|
97
|
+
email: 'user@example.com',
|
|
98
|
+
password: 'SecurePassword123!'
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Trading Operations
|
|
103
|
+
|
|
104
|
+
#### Get Available Protocols
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
const protocols = await sdk.getProtocols('mainnet');
|
|
108
|
+
// Returns: ['soroswap', 'phoenix', 'aqua']
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Get Quote
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const quote = await sdk.quote({
|
|
115
|
+
assetIn: 'TOKEN_A_CONTRACT',
|
|
116
|
+
assetOut: 'TOKEN_B_CONTRACT',
|
|
117
|
+
amount: '1000000',
|
|
118
|
+
tradeType: 'EXACT_IN',
|
|
119
|
+
protocols: ['soroswap', 'aqua'],
|
|
120
|
+
slippageTolerance: '50', // 0.5% in basis points
|
|
121
|
+
maxHops: 2,
|
|
122
|
+
feeBps: 30, // Optional fee in basis points
|
|
123
|
+
referralId: 'REFERRAL_WALLET_ADDRESS' // Required if feeBps is provided
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### Send Signed Transaction
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
const result = await sdk.send(signedXdr, 100); // fee in stroops
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Pool Operations
|
|
134
|
+
|
|
135
|
+
#### Get Pools
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Get all pools for specific protocols
|
|
139
|
+
const pools = await sdk.getPools(
|
|
140
|
+
'mainnet',
|
|
141
|
+
['soroswap', 'aqua'],
|
|
142
|
+
['SOROSWAP', 'STELLAR_EXPERT'] // Optional asset list filter
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// Get specific pool for token pair
|
|
146
|
+
const pool = await sdk.getPoolByTokens(
|
|
147
|
+
'TOKEN_A_CONTRACT',
|
|
148
|
+
'TOKEN_B_CONTRACT',
|
|
149
|
+
'mainnet',
|
|
150
|
+
['soroswap']
|
|
151
|
+
);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Liquidity Operations
|
|
155
|
+
|
|
156
|
+
#### Add Liquidity
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
const addLiquidityTx = await sdk.addLiquidity({
|
|
160
|
+
assetA: 'TOKEN_A_CONTRACT',
|
|
161
|
+
assetB: 'TOKEN_B_CONTRACT',
|
|
162
|
+
amountA: '1000000',
|
|
163
|
+
amountB: '2000000',
|
|
164
|
+
to: 'YOUR_WALLET_ADDRESS',
|
|
165
|
+
slippageTolerance: '50' // 0.5%
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Sign and send the transaction
|
|
169
|
+
const signedXdr = await yourSigner.sign(addLiquidityTx.xdr);
|
|
170
|
+
const result = await sdk.send(signedXdr, 100);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### Remove Liquidity
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const removeLiquidityTx = await sdk.removeLiquidity({
|
|
177
|
+
assetA: 'TOKEN_A_CONTRACT',
|
|
178
|
+
assetB: 'TOKEN_B_CONTRACT',
|
|
179
|
+
liquidity: '500000',
|
|
180
|
+
amountA: '450000',
|
|
181
|
+
amountB: '900000',
|
|
182
|
+
to: 'YOUR_WALLET_ADDRESS',
|
|
183
|
+
slippageTolerance: '50'
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### Get User Positions
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
const positions = await sdk.getUserPositions(
|
|
191
|
+
'USER_WALLET_ADDRESS',
|
|
192
|
+
'mainnet'
|
|
193
|
+
);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Market Data
|
|
197
|
+
|
|
198
|
+
#### Get Asset Prices
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
// Single asset price
|
|
202
|
+
const price = await sdk.getPrice(
|
|
203
|
+
'TOKEN_CONTRACT_ADDRESS',
|
|
204
|
+
'mainnet',
|
|
205
|
+
'USD'
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
// Multiple asset prices
|
|
209
|
+
const prices = await sdk.getPrice([
|
|
210
|
+
'TOKEN_A_CONTRACT',
|
|
211
|
+
'TOKEN_B_CONTRACT'
|
|
212
|
+
], 'mainnet', 'USD');
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
#### Get Asset Lists
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
// Get all available asset lists
|
|
219
|
+
const assetLists = await sdk.getAssetList();
|
|
220
|
+
|
|
221
|
+
// Get specific asset list
|
|
222
|
+
const soroswapAssets = await sdk.getAssetList('SOROSWAP');
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### System Information
|
|
226
|
+
|
|
227
|
+
#### Health Check
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
const health = await sdk.checkHealth();
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### Get Contract Addresses
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const factoryAddress = await sdk.getContractAddress('mainnet', 'factory');
|
|
237
|
+
const routerAddress = await sdk.getContractAddress('mainnet', 'router');
|
|
238
|
+
const aggregatorAddress = await sdk.getContractAddress('mainnet', 'aggregator');
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### Get Testnet Tokens
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
const testnetTokens = await sdk.getTokens();
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## ๐ Security Best Practices
|
|
248
|
+
|
|
249
|
+
1. **Environment Variables**: Store credentials in environment variables, not in code
|
|
250
|
+
2. **Server-Side Only**: This SDK is designed for server-side use only
|
|
251
|
+
3. **Token Management**: The SDK handles token refresh automatically
|
|
252
|
+
4. **Error Handling**: Always wrap API calls in try-catch blocks
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
try {
|
|
256
|
+
const quote = await sdk.quote(quoteParams);
|
|
257
|
+
// Handle success
|
|
258
|
+
} catch (error) {
|
|
259
|
+
console.error('Quote failed:', error.message);
|
|
260
|
+
// Handle error
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## ๐๏ธ Development
|
|
265
|
+
|
|
266
|
+
### Building
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
pnpm run build
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Testing
|
|
273
|
+
|
|
274
|
+
The SDK includes two types of tests:
|
|
275
|
+
|
|
276
|
+
#### Unit Tests (Mocked)
|
|
277
|
+
Fast tests that mock all external dependencies:
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
# Run unit tests (default)
|
|
281
|
+
pnpm test
|
|
282
|
+
|
|
283
|
+
# Run with coverage
|
|
284
|
+
pnpm run test:coverage
|
|
285
|
+
|
|
286
|
+
# Watch mode for development
|
|
287
|
+
pnpm run test:watch
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
#### Integration Tests (Real API)
|
|
291
|
+
Tests that actually call the Soroswap API:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
# Set up credentials first
|
|
295
|
+
export SOROSWAP_EMAIL="your-email@example.com"
|
|
296
|
+
export SOROSWAP_PASSWORD="your-password"
|
|
297
|
+
|
|
298
|
+
# Run integration tests
|
|
299
|
+
pnpm run test:integration
|
|
300
|
+
|
|
301
|
+
# Run both unit and integration tests
|
|
302
|
+
pnpm run test:all
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Note**: Integration tests require valid Soroswap credentials and may fail due to network issues or API changes. See [Integration Test Documentation](./tests/integration/README.md) for detailed setup.
|
|
306
|
+
|
|
307
|
+
### Linting
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
pnpm run lint
|
|
311
|
+
pnpm run lint:fix
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## ๐ Frontend Integration Considerations
|
|
315
|
+
|
|
316
|
+
While this SDK is server-side focused, you can create secure frontend integrations:
|
|
317
|
+
|
|
318
|
+
### Recommended Architecture
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
// Backend API endpoint
|
|
322
|
+
app.post('/api/quote', async (req, res) => {
|
|
323
|
+
try {
|
|
324
|
+
const quote = await soroswapSDK.quote(req.body);
|
|
325
|
+
// Only return the XDR and quote data, not sensitive info
|
|
326
|
+
res.json({
|
|
327
|
+
xdr: quote.xdr,
|
|
328
|
+
trade: quote.trade,
|
|
329
|
+
priceImpact: quote.priceImpact
|
|
330
|
+
});
|
|
331
|
+
} catch (error) {
|
|
332
|
+
res.status(500).json({ error: error.message });
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// Frontend widget
|
|
337
|
+
async function getQuote(quoteParams) {
|
|
338
|
+
const response = await fetch('/api/quote', {
|
|
339
|
+
method: 'POST',
|
|
340
|
+
headers: { 'Content-Type': 'application/json' },
|
|
341
|
+
body: JSON.stringify(quoteParams)
|
|
342
|
+
});
|
|
343
|
+
return response.json();
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## ๐ Type Definitions
|
|
348
|
+
|
|
349
|
+
The SDK exports comprehensive TypeScript types:
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
import {
|
|
353
|
+
SoroswapSDKConfig,
|
|
354
|
+
Network,
|
|
355
|
+
TradeType,
|
|
356
|
+
QuoteDto,
|
|
357
|
+
QuoteResponse,
|
|
358
|
+
Pool,
|
|
359
|
+
UserPosition,
|
|
360
|
+
PriceData,
|
|
361
|
+
// ... and many more
|
|
362
|
+
} from 'soroswap-sdk';
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## ๐ค Contributing
|
|
366
|
+
|
|
367
|
+
We welcome contributions! Please read our contributing guidelines and submit pull requests to help improve the SDK.
|
|
368
|
+
|
|
369
|
+
## ๐ License
|
|
370
|
+
|
|
371
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
372
|
+
|
|
373
|
+
## ๐ Links
|
|
374
|
+
|
|
375
|
+
- [Soroswap.Finance](https://soroswap.finance)
|
|
376
|
+
- [Documentation](https://docs.soroswap.finance)
|
|
377
|
+
- [API Documentation](https://api.soroswap.finance)
|
|
378
|
+
- [GitHub Repository](https://github.com/soroswap/sdk)
|
|
379
|
+
|
|
380
|
+
## ๐ Support
|
|
381
|
+
|
|
382
|
+
For support and questions:
|
|
383
|
+
- Create an issue on [GitHub](https://github.com/soroswap/sdk/issues)
|
|
384
|
+
- Join our [Discord community](https://discord.gg/soroswap)
|
|
385
|
+
- Follow us on [Twitter](https://twitter.com/SoroswapFinance)
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
Built with โค๏ธ by the Soroswap team for the Stellar ecosystem.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { HttpClient } from '../clients/http-client';
|
|
2
|
+
import { AuthLoginDto, AuthRegisterDto, AuthResponse } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Authentication manager handles login, registration, and token refresh
|
|
5
|
+
*/
|
|
6
|
+
export declare class AuthManager {
|
|
7
|
+
private tokenCache;
|
|
8
|
+
private credentials;
|
|
9
|
+
private httpClient;
|
|
10
|
+
constructor(credentials: AuthLoginDto);
|
|
11
|
+
/**
|
|
12
|
+
* Set HTTP client (injected dependency)
|
|
13
|
+
*/
|
|
14
|
+
setHttpClient(httpClient: HttpClient): void;
|
|
15
|
+
/**
|
|
16
|
+
* Get current valid access token, refreshing if necessary
|
|
17
|
+
*/
|
|
18
|
+
getValidAccessToken(): Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Login with credentials
|
|
21
|
+
*/
|
|
22
|
+
login(): Promise<AuthResponse>;
|
|
23
|
+
/**
|
|
24
|
+
* Register new user
|
|
25
|
+
*/
|
|
26
|
+
register(userData: AuthRegisterDto): Promise<{
|
|
27
|
+
message: string;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Refresh access token using refresh token
|
|
31
|
+
*/
|
|
32
|
+
refreshTokens(): Promise<AuthResponse>;
|
|
33
|
+
/**
|
|
34
|
+
* Get current user information
|
|
35
|
+
*/
|
|
36
|
+
getUserInfo(): {
|
|
37
|
+
username: string;
|
|
38
|
+
role: string;
|
|
39
|
+
} | null;
|
|
40
|
+
/**
|
|
41
|
+
* Check if user is authenticated
|
|
42
|
+
*/
|
|
43
|
+
isAuthenticated(): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Logout (clear tokens)
|
|
46
|
+
*/
|
|
47
|
+
logout(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Get token provider function for HTTP client
|
|
50
|
+
*/
|
|
51
|
+
getTokenProvider(): () => Promise<string | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Update credentials (for switching users)
|
|
54
|
+
*/
|
|
55
|
+
updateCredentials(credentials: AuthLoginDto): void;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=auth-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-manager.d.ts","sourceRoot":"","sources":["../../src/auth/auth-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EACL,YAAY,EACZ,eAAe,EACf,YAAY,EAEb,MAAM,UAAU,CAAC;AAElB;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,UAAU,CAA2B;gBAEjC,WAAW,EAAE,YAAY;IAKrC;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAI3C;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC;IA6B5C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,YAAY,CAAC;IA6BpC;;OAEG;IACG,QAAQ,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAQvE;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,YAAY,CAAC;IAuC5C;;OAEG;IACH,WAAW,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAIxD;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,MAAM,IAAI,IAAI;IAId;;OAEG;IACH,gBAAgB,IAAI,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAWhD;;OAEG;IACH,iBAAiB,CAAC,WAAW,EAAE,YAAY,GAAG,IAAI;CAInD"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthManager = void 0;
|
|
4
|
+
const token_cache_1 = require("../cache/token-cache");
|
|
5
|
+
/**
|
|
6
|
+
* Authentication manager handles login, registration, and token refresh
|
|
7
|
+
*/
|
|
8
|
+
class AuthManager {
|
|
9
|
+
constructor(credentials) {
|
|
10
|
+
this.httpClient = null; // Will be injected
|
|
11
|
+
this.credentials = credentials;
|
|
12
|
+
this.tokenCache = new token_cache_1.TokenCache();
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Set HTTP client (injected dependency)
|
|
16
|
+
*/
|
|
17
|
+
setHttpClient(httpClient) {
|
|
18
|
+
this.httpClient = httpClient;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get current valid access token, refreshing if necessary
|
|
22
|
+
*/
|
|
23
|
+
async getValidAccessToken() {
|
|
24
|
+
// Check if we have valid tokens
|
|
25
|
+
if (this.tokenCache.hasValidTokens()) {
|
|
26
|
+
return this.tokenCache.getAccessToken();
|
|
27
|
+
}
|
|
28
|
+
// Check if we need to refresh
|
|
29
|
+
if (this.tokenCache.needsRefresh() && this.tokenCache.getRefreshToken()) {
|
|
30
|
+
try {
|
|
31
|
+
await this.refreshTokens();
|
|
32
|
+
const token = this.tokenCache.getAccessToken();
|
|
33
|
+
if (token) {
|
|
34
|
+
return token;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.log("๐ | getValidAccessToken | error:", error);
|
|
39
|
+
// Token refresh failed, attempting new login
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Login fresh
|
|
43
|
+
await this.login();
|
|
44
|
+
const token = this.tokenCache.getAccessToken();
|
|
45
|
+
if (!token) {
|
|
46
|
+
throw new Error('Failed to obtain access token after login');
|
|
47
|
+
}
|
|
48
|
+
return token;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Login with credentials
|
|
52
|
+
*/
|
|
53
|
+
async login() {
|
|
54
|
+
if (!this.httpClient) {
|
|
55
|
+
throw new Error('HTTP client not initialized');
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const response = await this.httpClient.post('/login', this.credentials);
|
|
59
|
+
// Calculate expiration time (assume 1 hour if not provided)
|
|
60
|
+
const expiresIn = 60 * 60 * 1000; // 1 hour in milliseconds
|
|
61
|
+
const expiresAt = Date.now() + expiresIn;
|
|
62
|
+
// Store tokens in cache
|
|
63
|
+
const tokenData = {
|
|
64
|
+
access_token: response.access_token,
|
|
65
|
+
refresh_token: response.refresh_token,
|
|
66
|
+
expires_at: expiresAt,
|
|
67
|
+
username: response.username,
|
|
68
|
+
role: response.role,
|
|
69
|
+
};
|
|
70
|
+
this.tokenCache.setTokens(tokenData);
|
|
71
|
+
return response;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
this.tokenCache.clear();
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Register new user
|
|
80
|
+
*/
|
|
81
|
+
async register(userData) {
|
|
82
|
+
if (!this.httpClient) {
|
|
83
|
+
throw new Error('HTTP client not initialized');
|
|
84
|
+
}
|
|
85
|
+
return this.httpClient.post('/register', userData);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Refresh access token using refresh token
|
|
89
|
+
*/
|
|
90
|
+
async refreshTokens() {
|
|
91
|
+
if (!this.httpClient) {
|
|
92
|
+
throw new Error('HTTP client not initialized');
|
|
93
|
+
}
|
|
94
|
+
const refreshToken = this.tokenCache.getRefreshToken();
|
|
95
|
+
if (!refreshToken) {
|
|
96
|
+
throw new Error('No refresh token available');
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
// Use refresh token as bearer token
|
|
100
|
+
const response = await this.httpClient.post('/refresh', {}, {
|
|
101
|
+
headers: {
|
|
102
|
+
Authorization: `Bearer ${refreshToken}`
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
// Calculate expiration time
|
|
106
|
+
const expiresIn = 60 * 60 * 1000; // 1 hour in milliseconds
|
|
107
|
+
const expiresAt = Date.now() + expiresIn;
|
|
108
|
+
// Update tokens in cache
|
|
109
|
+
const tokenData = {
|
|
110
|
+
access_token: response.access_token,
|
|
111
|
+
refresh_token: response.refresh_token,
|
|
112
|
+
expires_at: expiresAt,
|
|
113
|
+
username: response.username,
|
|
114
|
+
role: response.role,
|
|
115
|
+
};
|
|
116
|
+
this.tokenCache.setTokens(tokenData);
|
|
117
|
+
return response;
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
this.tokenCache.clear();
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get current user information
|
|
126
|
+
*/
|
|
127
|
+
getUserInfo() {
|
|
128
|
+
return this.tokenCache.getUserInfo();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Check if user is authenticated
|
|
132
|
+
*/
|
|
133
|
+
isAuthenticated() {
|
|
134
|
+
return this.tokenCache.hasValidTokens();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Logout (clear tokens)
|
|
138
|
+
*/
|
|
139
|
+
logout() {
|
|
140
|
+
this.tokenCache.clear();
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get token provider function for HTTP client
|
|
144
|
+
*/
|
|
145
|
+
getTokenProvider() {
|
|
146
|
+
return async () => {
|
|
147
|
+
try {
|
|
148
|
+
return await this.getValidAccessToken();
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
console.log("๐ | return | error:", error);
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Update credentials (for switching users)
|
|
158
|
+
*/
|
|
159
|
+
updateCredentials(credentials) {
|
|
160
|
+
this.credentials = credentials;
|
|
161
|
+
this.tokenCache.clear(); // Clear existing tokens
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.AuthManager = AuthManager;
|
|
165
|
+
//# sourceMappingURL=auth-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-manager.js","sourceRoot":"","sources":["../../src/auth/auth-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { TokenData } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* In-memory token cache with automatic expiration handling
|
|
4
|
+
* Stores access and refresh tokens with timestamps
|
|
5
|
+
*/
|
|
6
|
+
export declare class TokenCache {
|
|
7
|
+
private tokenData;
|
|
8
|
+
/**
|
|
9
|
+
* Store token data in cache
|
|
10
|
+
*/
|
|
11
|
+
setTokens(tokenData: TokenData): void;
|
|
12
|
+
/**
|
|
13
|
+
* Get current access token if valid
|
|
14
|
+
*/
|
|
15
|
+
getAccessToken(): string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Get refresh token
|
|
18
|
+
*/
|
|
19
|
+
getRefreshToken(): string | null;
|
|
20
|
+
/**
|
|
21
|
+
* Get user information
|
|
22
|
+
*/
|
|
23
|
+
getUserInfo(): {
|
|
24
|
+
username: string;
|
|
25
|
+
role: string;
|
|
26
|
+
} | null;
|
|
27
|
+
/**
|
|
28
|
+
* Check if we have valid tokens
|
|
29
|
+
*/
|
|
30
|
+
hasValidTokens(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Check if we need to refresh tokens
|
|
33
|
+
*/
|
|
34
|
+
needsRefresh(): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Clear all cached tokens
|
|
37
|
+
*/
|
|
38
|
+
clear(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Get token expiration time
|
|
41
|
+
*/
|
|
42
|
+
getExpirationTime(): number | null;
|
|
43
|
+
/**
|
|
44
|
+
* Check if tokens exist (regardless of expiration)
|
|
45
|
+
*/
|
|
46
|
+
hasTokens(): boolean;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=token-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-cache.d.ts","sourceRoot":"","sources":["../../src/cache/token-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAA0B;IAE3C;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAIrC;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAgB/B;;OAEG;IACH,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC;;OAEG;IACH,WAAW,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAWxD;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,YAAY,IAAI,OAAO;IAWvB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,iBAAiB,IAAI,MAAM,GAAG,IAAI;IAIlC;;OAEG;IACH,SAAS,IAAI,OAAO;CAGrB"}
|