@voidaisdk/bridge-sdk 0.0.2 → 0.0.4
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 +125 -109
- package/dist/api/client.d.ts +5 -15
- package/dist/api/client.js +22 -77
- package/dist/core/bridge.js +4 -1
- package/dist/index.js +1 -1
- package/dist/wallet/bittensor.js +2 -1
- package/dist/wallet/ethereum.js +2 -2
- package/dist/wallet/solana.js +1 -1
- package/dist-browser/voidai-sdk.js +1 -1
- package/package.json +11 -4
package/README.md
CHANGED
|
@@ -41,8 +41,8 @@ pnpm add voidai-sdk
|
|
|
41
41
|
import { BridgeSDK } from 'voidai-sdk';
|
|
42
42
|
|
|
43
43
|
const sdk = new BridgeSDK({
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
apiKey: process.env.VOIDAI_API_KEY!,
|
|
45
|
+
environment: 'testnet', // 'devnet' | 'testnet' | 'mainnet'
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
// Wait for authentication & API key validation
|
|
@@ -56,8 +56,8 @@ await sdk.ready;
|
|
|
56
56
|
```typescript
|
|
57
57
|
// Get all active chains
|
|
58
58
|
const chains = await sdk.api.getSupportedChains({
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
isActive: true,
|
|
60
|
+
isCcipSupported: true,
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
// Get assets (optionally filtered by chain)
|
|
@@ -85,29 +85,31 @@ console.log('Connected:', solanaAccount.address);
|
|
|
85
85
|
```typescript
|
|
86
86
|
// Bridge TAO from Bittensor to Ethereum
|
|
87
87
|
const result = await sdk.bridge.bridge({
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
fromWallet: '5DqAEsZi...', // Bittensor address
|
|
89
|
+
toWallet: '0x742d35...', // Ethereum address
|
|
90
|
+
fromToken: 'tao',
|
|
91
|
+
toToken: 'wtao',
|
|
92
|
+
fromChain: 'BITTENSOR',
|
|
93
|
+
toChain: 'ETHEREUM_SEPOLIA',
|
|
94
|
+
amount: 1.0,
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
console.log('Bridge identifier:', result.identifier);
|
|
98
98
|
|
|
99
99
|
// For EVM burn flows (wTAO → TAO), use the pre-built transaction
|
|
100
100
|
if (result.evmTransaction) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
101
|
+
const txHash = await window.ethereum.request({
|
|
102
|
+
method: 'eth_sendTransaction',
|
|
103
|
+
params: [
|
|
104
|
+
{
|
|
105
|
+
from: ethAccount.address,
|
|
106
|
+
to: result.evmTransaction.to,
|
|
107
|
+
data: result.evmTransaction.data,
|
|
108
|
+
value: result.evmTransaction.value,
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
});
|
|
112
|
+
console.log('Transaction sent:', txHash);
|
|
111
113
|
}
|
|
112
114
|
```
|
|
113
115
|
|
|
@@ -115,25 +117,27 @@ if (result.evmTransaction) {
|
|
|
115
117
|
|
|
116
118
|
```typescript
|
|
117
119
|
const route = await sdk.bridge.routeSwap({
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
operationType: 'SWAP',
|
|
121
|
+
originAssetId: 1,
|
|
122
|
+
destinationAssetId: 2,
|
|
123
|
+
fromAddress: '0xSource...',
|
|
124
|
+
toAddress: '0xDestination...',
|
|
125
|
+
amount: 0.5,
|
|
124
126
|
});
|
|
125
127
|
|
|
126
128
|
if (route.success && route.data) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
129
|
+
// Execute via MetaMask
|
|
130
|
+
await window.ethereum.request({
|
|
131
|
+
method: 'eth_sendTransaction',
|
|
132
|
+
params: [
|
|
133
|
+
{
|
|
134
|
+
from: '0xSource...',
|
|
135
|
+
to: route.data.to,
|
|
136
|
+
data: route.data.data,
|
|
137
|
+
value: route.data.value,
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
});
|
|
137
141
|
}
|
|
138
142
|
```
|
|
139
143
|
|
|
@@ -142,9 +146,9 @@ if (route.success && route.data) {
|
|
|
142
146
|
```typescript
|
|
143
147
|
// Bridge fee estimate
|
|
144
148
|
const bridgeFee = await sdk.bridge.getBridgeFeeEstimate({
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
fromToken: 'tao',
|
|
150
|
+
toToken: 'wtao',
|
|
151
|
+
amount: 2.5,
|
|
148
152
|
});
|
|
149
153
|
|
|
150
154
|
console.log('Bridge fee:', bridgeFee.data.fee);
|
|
@@ -152,11 +156,11 @@ console.log('Recipient will receive:', bridgeFee.data.recipientAmount);
|
|
|
152
156
|
|
|
153
157
|
// Router swap fee estimate
|
|
154
158
|
const swapFee = await sdk.bridge.getRouterSwapFeeEstimate({
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
originAssetId: 1,
|
|
160
|
+
destinationAssetId: 2,
|
|
161
|
+
amount: 0.75,
|
|
162
|
+
operationType: 'SWAP',
|
|
163
|
+
toAddress: '0xDestination...',
|
|
160
164
|
});
|
|
161
165
|
|
|
162
166
|
console.log('Total fee:', swapFee.totalFee);
|
|
@@ -176,6 +180,7 @@ console.log('Total fee:', swapFee.totalFee);
|
|
|
176
180
|
## 💡 Key Features
|
|
177
181
|
|
|
178
182
|
### ✅ Multi-Chain Support
|
|
183
|
+
|
|
179
184
|
- **Bittensor** (TAO, Alpha)
|
|
180
185
|
- **Ethereum** (Mainnet, Sepolia)
|
|
181
186
|
- **Base** (Mainnet, Sepolia)
|
|
@@ -183,26 +188,31 @@ console.log('Total fee:', swapFee.totalFee);
|
|
|
183
188
|
- More chains added regularly
|
|
184
189
|
|
|
185
190
|
### ✅ Wallet Integration
|
|
191
|
+
|
|
186
192
|
- **Bittensor**: Talisman, Subwallet, Polkadot.js
|
|
187
193
|
- **Ethereum**: MetaMask
|
|
188
194
|
- **Solana**: Phantom
|
|
189
195
|
|
|
190
196
|
### ✅ Bridge Operations
|
|
197
|
+
|
|
191
198
|
- TAO ↔ wTAO (Bittensor ↔ Ethereum)
|
|
192
199
|
- Alpha ↔ wAlpha
|
|
193
200
|
- Cross-chain asset transfers
|
|
194
201
|
- Automatic EVM transaction building for burn operations
|
|
195
202
|
|
|
196
203
|
### ✅ Routing & Swaps
|
|
204
|
+
|
|
197
205
|
- Unified route-transaction API
|
|
198
206
|
- SWAP, BRIDGE, and CCIP operations
|
|
199
207
|
- Fee estimation before execution
|
|
200
208
|
|
|
201
209
|
### ✅ Frontend vs Backend
|
|
210
|
+
|
|
202
211
|
- **BridgeSDK** – Frontend usage (apiKey only, no secretKey)
|
|
203
212
|
- **BridgeSDKServer** – Backend usage (apiKey + secretKey for JWT auth, no wallets)
|
|
204
213
|
|
|
205
214
|
### ✅ Production Ready
|
|
215
|
+
|
|
206
216
|
- TypeScript-first with full type definitions
|
|
207
217
|
- Automatic JWT refresh on token expiry
|
|
208
218
|
- Normalized error messages
|
|
@@ -217,16 +227,18 @@ For server-side or backend integrations, use `BridgeSDKServer` with both `apiKey
|
|
|
217
227
|
import { BridgeSDKServer } from 'voidai-sdk';
|
|
218
228
|
|
|
219
229
|
const sdk = new BridgeSDKServer({
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
230
|
+
apiKey: process.env.VOIDAI_API_KEY!,
|
|
231
|
+
secretKey: process.env.VOIDAI_SECRET_KEY!,
|
|
232
|
+
environment: 'production',
|
|
223
233
|
});
|
|
224
234
|
|
|
225
235
|
await sdk.ready;
|
|
226
236
|
|
|
227
237
|
// Same bridge/api API, no wallets
|
|
228
238
|
const chains = await sdk.api.getSupportedChains();
|
|
229
|
-
const result = await sdk.bridge.bridge({
|
|
239
|
+
const result = await sdk.bridge.bridge({
|
|
240
|
+
/* ... */
|
|
241
|
+
});
|
|
230
242
|
```
|
|
231
243
|
|
|
232
244
|
`BridgeSDKServer` exposes `config`, `api`, `bridge`, and `ready` – no `wallets` (use `BridgeSDK` in frontend for that).
|
|
@@ -235,11 +247,11 @@ const result = await sdk.bridge.bridge({ /* ... */ });
|
|
|
235
247
|
|
|
236
248
|
The SDK supports three environments:
|
|
237
249
|
|
|
238
|
-
| Environment | Base URL
|
|
239
|
-
|
|
240
|
-
| `development` | `http://localhost:3003`
|
|
241
|
-
| `staging` | `https://api-staging.voidai.envistudios.com` | Testing & QA
|
|
242
|
-
| `production` | `https://api.voidai.envistudios.com`
|
|
250
|
+
| Environment | Base URL | Use Case |
|
|
251
|
+
| ------------- | -------------------------------------------- | ----------------- |
|
|
252
|
+
| `development` | `http://localhost:3003` | Local development |
|
|
253
|
+
| `staging` | `https://api-staging.voidai.envistudios.com` | Testing & QA |
|
|
254
|
+
| `production` | `https://api.voidai.envistudios.com` | Live applications |
|
|
243
255
|
|
|
244
256
|
## 📝 Example: Complete Bridge Flow
|
|
245
257
|
|
|
@@ -247,51 +259,53 @@ The SDK supports three environments:
|
|
|
247
259
|
import { BridgeSDK } from 'voidai-sdk';
|
|
248
260
|
|
|
249
261
|
async function bridgeTAO() {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
await sdk.ready;
|
|
262
|
+
// 1. Initialize SDK
|
|
263
|
+
const sdk = new BridgeSDK({
|
|
264
|
+
apiKey: process.env.VOIDAI_API_KEY!,
|
|
265
|
+
environment: 'staging',
|
|
266
|
+
});
|
|
257
267
|
|
|
258
|
-
|
|
259
|
-
const bittensorAccount = await sdk.wallets.bittensor.connect();
|
|
260
|
-
const ethAccount = await sdk.wallets.ethereum.connect();
|
|
268
|
+
await sdk.ready;
|
|
261
269
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
toToken: 'wtao',
|
|
266
|
-
amount: 1.0,
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
console.log(`Fee: ${fee.data.fee}, You'll receive: ${fee.data.recipientAmount}`);
|
|
270
|
-
|
|
271
|
-
// 4. Execute bridge
|
|
272
|
-
const result = await sdk.bridge.bridge({
|
|
273
|
-
fromWallet: bittensorAccount.address,
|
|
274
|
-
toWallet: ethAccount.address,
|
|
275
|
-
fromToken: 'tao',
|
|
276
|
-
toToken: 'wtao',
|
|
277
|
-
fromChain: 'BITTENSOR',
|
|
278
|
-
toChain: 'ETHEREUM_SEPOLIA',
|
|
279
|
-
amount: 1.0,
|
|
280
|
-
});
|
|
270
|
+
// 2. Connect wallets
|
|
271
|
+
const bittensorAccount = await sdk.wallets.bittensor.connect();
|
|
272
|
+
const ethAccount = await sdk.wallets.ethereum.connect();
|
|
281
273
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
method: 'eth_sendTransaction',
|
|
288
|
-
params: [{
|
|
289
|
-
from: ethAccount.address,
|
|
290
|
-
...result.evmTransaction,
|
|
291
|
-
}],
|
|
274
|
+
// 3. Estimate fees
|
|
275
|
+
const fee = await sdk.bridge.getBridgeFeeEstimate({
|
|
276
|
+
fromToken: 'tao',
|
|
277
|
+
toToken: 'wtao',
|
|
278
|
+
amount: 1.0,
|
|
292
279
|
});
|
|
293
|
-
|
|
294
|
-
|
|
280
|
+
|
|
281
|
+
console.log(`Fee: ${fee.data.fee}, You'll receive: ${fee.data.recipientAmount}`);
|
|
282
|
+
|
|
283
|
+
// 4. Execute bridge
|
|
284
|
+
const result = await sdk.bridge.bridge({
|
|
285
|
+
fromWallet: bittensorAccount.address,
|
|
286
|
+
toWallet: ethAccount.address,
|
|
287
|
+
fromToken: 'tao',
|
|
288
|
+
toToken: 'wtao',
|
|
289
|
+
fromChain: 'BITTENSOR',
|
|
290
|
+
toChain: 'ETHEREUM_SEPOLIA',
|
|
291
|
+
amount: 1.0,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
console.log('Bridge initiated:', result.identifier);
|
|
295
|
+
|
|
296
|
+
// 5. Execute on-chain transaction (if EVM burn flow)
|
|
297
|
+
if (result.evmTransaction) {
|
|
298
|
+
const txHash = await window.ethereum.request({
|
|
299
|
+
method: 'eth_sendTransaction',
|
|
300
|
+
params: [
|
|
301
|
+
{
|
|
302
|
+
from: ethAccount.address,
|
|
303
|
+
...result.evmTransaction,
|
|
304
|
+
},
|
|
305
|
+
],
|
|
306
|
+
});
|
|
307
|
+
console.log('On-chain tx:', txHash);
|
|
308
|
+
}
|
|
295
309
|
}
|
|
296
310
|
|
|
297
311
|
bridgeTAO().catch(console.error);
|
|
@@ -351,12 +365,12 @@ bridge-sdk/
|
|
|
351
365
|
|
|
352
366
|
```html
|
|
353
367
|
<script type="module">
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
368
|
+
import { BridgeSDK } from './node_modules/voidai-sdk/dist-browser/voidai-sdk.js';
|
|
369
|
+
|
|
370
|
+
const sdk = new BridgeSDK({
|
|
371
|
+
apiKey: 'your-api-key',
|
|
372
|
+
environment: 'staging',
|
|
373
|
+
});
|
|
360
374
|
</script>
|
|
361
375
|
```
|
|
362
376
|
|
|
@@ -375,15 +389,17 @@ The SDK throws `Error` instances with user-friendly messages:
|
|
|
375
389
|
|
|
376
390
|
```typescript
|
|
377
391
|
try {
|
|
378
|
-
|
|
392
|
+
await sdk.bridge.bridge({
|
|
393
|
+
/* ... */
|
|
394
|
+
});
|
|
379
395
|
} catch (error) {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
396
|
+
// error.message contains a clear, actionable message
|
|
397
|
+
console.error('Bridge failed:', error.message);
|
|
398
|
+
|
|
399
|
+
// Common errors:
|
|
400
|
+
// - "Session expired or unauthorized..." → Check API key
|
|
401
|
+
// - "Failed to execute bridge swap" → Check parameters
|
|
402
|
+
// - "User rejected the connection request" → User cancelled wallet
|
|
387
403
|
}
|
|
388
404
|
```
|
|
389
405
|
|
package/dist/api/client.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { AxiosRequestConfig } from 'axios';
|
|
1
2
|
import { BridgeConfig } from '../config';
|
|
2
|
-
import { Chain,
|
|
3
|
+
import { Chain, AssetsApiResponse, ApiKeyValidationData, BridgeSwapRequest, BridgeSwapResponse, RouteTransactionRequest, RouteTransactionResponse, BridgeFeeEstimateRequest, BridgeFeeEstimateResponse, RouterSwapFeeEstimateRequest, RouterSwapFeeEstimateResponse, CancelCcipRequest, CancelRouterSwapRequest, CancelBridgeSwapRequest, CancelOperationResponse, ApiTransactionsResponse, ValidateBurnRequest, ValidateBurnResponse, CcipTxConfirmationRequest, CcipTxConfirmationResponse } from '../types';
|
|
3
4
|
export declare class VoidAIBridgeClient {
|
|
4
5
|
private config;
|
|
5
6
|
private client;
|
|
@@ -8,9 +9,7 @@ export declare class VoidAIBridgeClient {
|
|
|
8
9
|
readonly ready: Promise<void>;
|
|
9
10
|
constructor(config: BridgeConfig);
|
|
10
11
|
/**
|
|
11
|
-
* Authenticate and set Authorization header
|
|
12
|
-
* New flow: POST /api/v1/auth/login
|
|
13
|
-
* Fallback: GET /api/v1/auth/validate-api-key (legacy)
|
|
12
|
+
* Authenticate via POST /api/v1/auth/login and set Authorization header.
|
|
14
13
|
*/
|
|
15
14
|
private authenticate;
|
|
16
15
|
private setAccessToken;
|
|
@@ -31,21 +30,12 @@ export declare class VoidAIBridgeClient {
|
|
|
31
30
|
login(): Promise<string>;
|
|
32
31
|
private tryDecodeTokenToValidationData;
|
|
33
32
|
private base64UrlDecode;
|
|
34
|
-
/**
|
|
35
|
-
* Validate API key with the backend
|
|
36
|
-
* @throws Error if API key is invalid
|
|
37
|
-
*/
|
|
38
|
-
validateApiKey(): Promise<ApiKeyValidationData>;
|
|
39
|
-
/**
|
|
40
|
-
* Get validation URL - uses baseUrl from config
|
|
41
|
-
*/
|
|
42
|
-
private getValidationUrl;
|
|
43
33
|
/**
|
|
44
34
|
* Get validated API key data
|
|
45
35
|
*/
|
|
46
36
|
getValidatedApiKeyData(): ApiKeyValidationData | null;
|
|
47
37
|
private getUrl;
|
|
48
|
-
get<T>(path: string, params?: any, retryAttempted?: boolean): Promise<T>;
|
|
38
|
+
get<T>(path: string, params?: any, retryAttempted?: boolean, requestConfig?: AxiosRequestConfig): Promise<T>;
|
|
49
39
|
post<T>(path: string, data?: any, retryAttempted?: boolean): Promise<T>;
|
|
50
40
|
delete<T>(path: string, params?: any, retryAttempted?: boolean): Promise<T>;
|
|
51
41
|
patch<T>(path: string, data?: any, retryAttempted?: boolean): Promise<T>;
|
|
@@ -96,7 +86,7 @@ export declare class VoidAIBridgeClient {
|
|
|
96
86
|
/**
|
|
97
87
|
* Get list of supported assets
|
|
98
88
|
*/
|
|
99
|
-
getAssetList(chainId?: string): Promise<
|
|
89
|
+
getAssetList(chainId?: string, page?: number, limit?: number): Promise<AssetsApiResponse>;
|
|
100
90
|
/**
|
|
101
91
|
* Get bridge fee estimate
|
|
102
92
|
* @param params - Fee estimation parameters
|
package/dist/api/client.js
CHANGED
|
@@ -17,31 +17,15 @@ class VoidAIBridgeClient {
|
|
|
17
17
|
},
|
|
18
18
|
});
|
|
19
19
|
// Start auth immediately. Requests will await this promise.
|
|
20
|
-
// New flow: POST /auth/login to get JWT. Fallback to validate-api-key for backward compatibility.
|
|
21
20
|
this.ready = this.authenticate().then(() => undefined);
|
|
22
21
|
}
|
|
23
22
|
/**
|
|
24
|
-
* Authenticate and set Authorization header
|
|
25
|
-
* New flow: POST /api/v1/auth/login
|
|
26
|
-
* Fallback: GET /api/v1/auth/validate-api-key (legacy)
|
|
23
|
+
* Authenticate via POST /api/v1/auth/login and set Authorization header.
|
|
27
24
|
*/
|
|
28
25
|
async authenticate() {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// Populate validatedApiKeyData from JWT payload (best-effort) so existing getters keep working.
|
|
33
|
-
this.validatedApiKeyData = this.tryDecodeTokenToValidationData(token);
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
// If login isn't available or fails unexpectedly, fallback to legacy validation
|
|
37
|
-
// (do not break current working functionality).
|
|
38
|
-
try {
|
|
39
|
-
await this.validateApiKey();
|
|
40
|
-
}
|
|
41
|
-
catch (fallbackError) {
|
|
42
|
-
throw error;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
26
|
+
const token = await this.login();
|
|
27
|
+
this.setAccessToken(token);
|
|
28
|
+
this.validatedApiKeyData = this.tryDecodeTokenToValidationData(token);
|
|
45
29
|
}
|
|
46
30
|
setAccessToken(token) {
|
|
47
31
|
this.accessToken = token;
|
|
@@ -80,7 +64,9 @@ class VoidAIBridgeClient {
|
|
|
80
64
|
headers: { 'Content-Type': 'application/json' },
|
|
81
65
|
timeout: 10000,
|
|
82
66
|
});
|
|
83
|
-
if (response.data &&
|
|
67
|
+
if (response.data &&
|
|
68
|
+
response.data.success &&
|
|
69
|
+
response.data.accessToken) {
|
|
84
70
|
return response.data.accessToken;
|
|
85
71
|
}
|
|
86
72
|
const errorData = response.data;
|
|
@@ -128,53 +114,6 @@ class VoidAIBridgeClient {
|
|
|
128
114
|
// @ts-ignore
|
|
129
115
|
return atob(padded);
|
|
130
116
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Validate API key with the backend
|
|
133
|
-
* @throws Error if API key is invalid
|
|
134
|
-
*/
|
|
135
|
-
async validateApiKey() {
|
|
136
|
-
try {
|
|
137
|
-
// Use a temporary axios instance for validation since baseUrl might be different
|
|
138
|
-
const validationUrl = this.getValidationUrl();
|
|
139
|
-
const response = await axios_1.default.get(validationUrl, {
|
|
140
|
-
headers: {
|
|
141
|
-
'api-key': this.config.apiKey,
|
|
142
|
-
},
|
|
143
|
-
timeout: 10000,
|
|
144
|
-
});
|
|
145
|
-
if (response.data.success) {
|
|
146
|
-
this.validatedApiKeyData = response.data.data;
|
|
147
|
-
return response.data.data;
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
const error = new Error(response.data.error.message);
|
|
151
|
-
error.code = response.data.error.code;
|
|
152
|
-
throw error;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
catch (error) {
|
|
156
|
-
// If validation fails, ensure we don't keep stale validated data around.
|
|
157
|
-
this.validatedApiKeyData = null;
|
|
158
|
-
if (axios_1.default.isAxiosError(error)) {
|
|
159
|
-
if (error.response?.status === 401) {
|
|
160
|
-
const errorData = error.response.data;
|
|
161
|
-
const apiError = new Error(errorData.error?.message || 'API key is invalid or inactive');
|
|
162
|
-
apiError.code = errorData.error?.code || 'INVALID_API_KEY';
|
|
163
|
-
throw apiError;
|
|
164
|
-
}
|
|
165
|
-
throw new Error(`Failed to validate API key: ${error.message}`);
|
|
166
|
-
}
|
|
167
|
-
throw error;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Get validation URL - uses baseUrl from config
|
|
172
|
-
*/
|
|
173
|
-
getValidationUrl() {
|
|
174
|
-
const baseUrl = this.config.getBaseUrl();
|
|
175
|
-
const cleanBase = baseUrl.replace(/\/$/, '');
|
|
176
|
-
return `${cleanBase}/api/v1/auth/validate-api-key`;
|
|
177
|
-
}
|
|
178
117
|
/**
|
|
179
118
|
* Get validated API key data
|
|
180
119
|
*/
|
|
@@ -188,11 +127,14 @@ class VoidAIBridgeClient {
|
|
|
188
127
|
const cleanPath = path.replace(/^\//, '');
|
|
189
128
|
return `${cleanBase}/${cleanPath}`;
|
|
190
129
|
}
|
|
191
|
-
async get(path, params, retryAttempted = false) {
|
|
130
|
+
async get(path, params, retryAttempted = false, requestConfig) {
|
|
192
131
|
await this.ready;
|
|
193
132
|
const url = this.getUrl(path);
|
|
194
133
|
try {
|
|
195
|
-
const response = await this.client.get(url, {
|
|
134
|
+
const response = await this.client.get(url, {
|
|
135
|
+
params,
|
|
136
|
+
...(requestConfig || {}),
|
|
137
|
+
});
|
|
196
138
|
return response.data;
|
|
197
139
|
}
|
|
198
140
|
catch (error) {
|
|
@@ -202,7 +144,7 @@ class VoidAIBridgeClient {
|
|
|
202
144
|
try {
|
|
203
145
|
await this.authenticate();
|
|
204
146
|
// Retry the original request once with fresh credentials.
|
|
205
|
-
return await this.get(path, params, true);
|
|
147
|
+
return await this.get(path, params, true, requestConfig);
|
|
206
148
|
}
|
|
207
149
|
catch (retryError) {
|
|
208
150
|
this.handleError(retryError);
|
|
@@ -376,17 +318,20 @@ class VoidAIBridgeClient {
|
|
|
376
318
|
/**
|
|
377
319
|
* Get list of supported assets
|
|
378
320
|
*/
|
|
379
|
-
async getAssetList(chainId) {
|
|
380
|
-
const
|
|
321
|
+
async getAssetList(chainId, page = 1, limit = 20) {
|
|
322
|
+
const queryParams = {
|
|
323
|
+
page: String(page),
|
|
324
|
+
limit: String(limit),
|
|
325
|
+
};
|
|
326
|
+
const response = await this.get('api/v1/asset/assets', queryParams);
|
|
381
327
|
if (!response.success || !response.data) {
|
|
382
328
|
throw new Error(response.message || 'Failed to fetch assets');
|
|
383
329
|
}
|
|
384
|
-
|
|
385
|
-
// Filter by chainId if provided
|
|
330
|
+
// Filter by chainId if provided (client-side filtering after pagination)
|
|
386
331
|
if (chainId !== undefined) {
|
|
387
|
-
assets = assets.filter(asset => asset.chainId === chainId);
|
|
332
|
+
response.data.assets = response.data.assets.filter((asset) => asset.chainId === chainId);
|
|
388
333
|
}
|
|
389
|
-
return
|
|
334
|
+
return response;
|
|
390
335
|
}
|
|
391
336
|
/**
|
|
392
337
|
* Get bridge fee estimate
|
package/dist/core/bridge.js
CHANGED
|
@@ -41,7 +41,10 @@ class Bridge {
|
|
|
41
41
|
},
|
|
42
42
|
],
|
|
43
43
|
functionName: 'burn',
|
|
44
|
-
args: [
|
|
44
|
+
args: [
|
|
45
|
+
maybeWithEncoded.encodedData,
|
|
46
|
+
maybeWithEncoded.signature,
|
|
47
|
+
],
|
|
45
48
|
});
|
|
46
49
|
// Attach the prepared transaction payload in a non-breaking way.
|
|
47
50
|
maybeWithEncoded.evmTransaction = {
|
package/dist/index.js
CHANGED
|
@@ -38,7 +38,7 @@ class BridgeSDK {
|
|
|
38
38
|
this.wallets = {
|
|
39
39
|
bittensor: new bittensor_1.BittensorWallet(),
|
|
40
40
|
ethereum: new ethereum_1.EthereumWallet(),
|
|
41
|
-
solana: new solana_1.SolanaWallet()
|
|
41
|
+
solana: new solana_1.SolanaWallet(),
|
|
42
42
|
};
|
|
43
43
|
this.bridge = new bridge_1.Bridge(this.api);
|
|
44
44
|
}
|
package/dist/wallet/bittensor.js
CHANGED
|
@@ -131,7 +131,8 @@ class BittensorWallet {
|
|
|
131
131
|
return !!injectedWeb3[extensionName];
|
|
132
132
|
}
|
|
133
133
|
const supportedExtensions = ['talisman', 'subwallet-js', 'polkadot-js'];
|
|
134
|
-
return supportedExtensions.some(name => !!injectedWeb3[name]) ||
|
|
134
|
+
return (supportedExtensions.some((name) => !!injectedWeb3[name]) ||
|
|
135
|
+
Object.keys(injectedWeb3).length > 0);
|
|
135
136
|
}
|
|
136
137
|
/**
|
|
137
138
|
* Get the wallet extension instance (for advanced usage)
|
package/dist/wallet/ethereum.js
CHANGED
|
@@ -16,7 +16,7 @@ class EthereumWallet {
|
|
|
16
16
|
if (typeof window === 'undefined') {
|
|
17
17
|
return false;
|
|
18
18
|
}
|
|
19
|
-
return typeof window.ethereum !== 'undefined' && window.ethereum.isMetaMask;
|
|
19
|
+
return (typeof window.ethereum !== 'undefined' && window.ethereum.isMetaMask);
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* Connect to MetaMask wallet
|
|
@@ -40,7 +40,7 @@ class EthereumWallet {
|
|
|
40
40
|
const chainId = await ethereum.request({ method: 'eth_chainId' });
|
|
41
41
|
this.account = {
|
|
42
42
|
address: accounts[0],
|
|
43
|
-
chainId: chainId
|
|
43
|
+
chainId: chainId,
|
|
44
44
|
};
|
|
45
45
|
this.chainId = chainId;
|
|
46
46
|
// Listen for account changes
|
package/dist/wallet/solana.js
CHANGED
|
@@ -37,7 +37,7 @@ class SolanaWallet {
|
|
|
37
37
|
}
|
|
38
38
|
this.account = {
|
|
39
39
|
address: response.publicKey.toString(),
|
|
40
|
-
publicKey: response.publicKey.toString()
|
|
40
|
+
publicKey: response.publicKey.toString(),
|
|
41
41
|
};
|
|
42
42
|
// Listen for disconnect
|
|
43
43
|
solana.on('disconnect', this.handleDisconnect.bind(this));
|