voidai-sdk 0.1.0 → 0.1.2
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 +370 -54
- package/dist/api/client.d.ts +65 -3
- package/dist/api/client.js +270 -12
- package/dist/config.d.ts +12 -2
- package/dist/config.js +12 -5
- package/dist/core/bridge.d.ts +29 -0
- package/dist/core/bridge.js +115 -0
- package/dist/index.d.ts +31 -3
- package/dist/index.js +29 -4
- package/dist/types/index.d.ts +167 -4
- package/dist-browser/voidai-sdk.js +1 -1
- package/dist-browser/voidai-sdk.js.LICENSE.txt +4 -0
- package/package.json +3 -2
- package/dist/auth/session.d.ts +0 -50
- package/dist/auth/session.js +0 -110
package/dist/api/client.js
CHANGED
|
@@ -7,14 +7,180 @@ exports.VoidAIBridgeClient = void 0;
|
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
8
|
class VoidAIBridgeClient {
|
|
9
9
|
constructor(config) {
|
|
10
|
+
this.validatedApiKeyData = null;
|
|
11
|
+
this.accessToken = null;
|
|
10
12
|
this.config = config;
|
|
11
13
|
this.client = axios_1.default.create({
|
|
12
14
|
timeout: 10000,
|
|
13
15
|
headers: {
|
|
14
16
|
'Content-Type': 'application/json',
|
|
15
|
-
'
|
|
17
|
+
'api-key': this.config.apiKey,
|
|
16
18
|
},
|
|
17
19
|
});
|
|
20
|
+
// Start auth immediately. Requests will await this promise.
|
|
21
|
+
// New flow: POST /auth/login to get JWT. Fallback to validate-api-key for backward compatibility.
|
|
22
|
+
this.ready = this.authenticate().then(() => undefined);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Authenticate and set Authorization header for subsequent requests.
|
|
26
|
+
* New flow: POST /api/v1/auth/login
|
|
27
|
+
* Fallback: GET /api/v1/auth/validate-api-key (legacy)
|
|
28
|
+
*/
|
|
29
|
+
async authenticate() {
|
|
30
|
+
try {
|
|
31
|
+
const token = await this.login();
|
|
32
|
+
this.setAccessToken(token);
|
|
33
|
+
// Populate validatedApiKeyData from JWT payload (best-effort) so existing getters keep working.
|
|
34
|
+
this.validatedApiKeyData = this.tryDecodeTokenToValidationData(token);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
// If login isn't available or fails unexpectedly, fallback to legacy validation
|
|
38
|
+
// (do not break current working functionality).
|
|
39
|
+
try {
|
|
40
|
+
await this.validateApiKey();
|
|
41
|
+
}
|
|
42
|
+
catch (fallbackError) {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
setAccessToken(token) {
|
|
48
|
+
this.accessToken = token;
|
|
49
|
+
this.client.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get access token (available after successful auth)
|
|
53
|
+
*/
|
|
54
|
+
getAccessToken() {
|
|
55
|
+
return this.accessToken;
|
|
56
|
+
}
|
|
57
|
+
getLoginUrl() {
|
|
58
|
+
const baseUrl = this.config.getBaseUrl();
|
|
59
|
+
const cleanBase = baseUrl.replace(/\/$/, '');
|
|
60
|
+
return `${cleanBase}/api/v1/auth/login`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get EVM bridge contract address for burn operations.
|
|
64
|
+
*/
|
|
65
|
+
getBridgeContractAddress() {
|
|
66
|
+
return this.config.bridgeContractAddress;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Login to obtain JWT access token.
|
|
70
|
+
* Frontend usage: { apiKey }
|
|
71
|
+
* Backend usage: { apiKey, secretKey }
|
|
72
|
+
*/
|
|
73
|
+
async login() {
|
|
74
|
+
const loginUrl = this.getLoginUrl();
|
|
75
|
+
const body = {
|
|
76
|
+
apiKey: this.config.apiKey,
|
|
77
|
+
...(this.config.secretKey ? { secretKey: this.config.secretKey } : {}),
|
|
78
|
+
};
|
|
79
|
+
try {
|
|
80
|
+
const response = await axios_1.default.post(loginUrl, body, {
|
|
81
|
+
headers: { 'Content-Type': 'application/json' },
|
|
82
|
+
timeout: 10000,
|
|
83
|
+
});
|
|
84
|
+
if (response.data && response.data.success && response.data.accessToken) {
|
|
85
|
+
return response.data.accessToken;
|
|
86
|
+
}
|
|
87
|
+
const errorData = response.data;
|
|
88
|
+
throw new Error(errorData?.error?.message || errorData?.message || 'Failed to login');
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
92
|
+
// If backend returns 401/403 or structured error, surface message.
|
|
93
|
+
const data = error.response?.data;
|
|
94
|
+
const msg = data?.error?.message || data?.message || error.message || 'Failed to login';
|
|
95
|
+
throw new Error(msg);
|
|
96
|
+
}
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
tryDecodeTokenToValidationData(token) {
|
|
101
|
+
try {
|
|
102
|
+
const parts = token.split('.');
|
|
103
|
+
if (parts.length < 2)
|
|
104
|
+
return null;
|
|
105
|
+
const payload = parts[1];
|
|
106
|
+
const json = this.base64UrlDecode(payload);
|
|
107
|
+
const parsed = JSON.parse(json);
|
|
108
|
+
// backend token contains: keyId, name, sub/id, apiKey, etc.
|
|
109
|
+
if (!parsed?.keyId || !parsed?.name)
|
|
110
|
+
return null;
|
|
111
|
+
return {
|
|
112
|
+
keyId: String(parsed.keyId),
|
|
113
|
+
tenantId: String(parsed.sub || parsed.id || ''),
|
|
114
|
+
name: String(parsed.name),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
base64UrlDecode(input) {
|
|
122
|
+
const base64 = input.replace(/-/g, '+').replace(/_/g, '/');
|
|
123
|
+
const pad = base64.length % 4;
|
|
124
|
+
const padded = pad ? base64 + '='.repeat(4 - pad) : base64;
|
|
125
|
+
// Node (backend) vs Browser
|
|
126
|
+
if (typeof Buffer !== 'undefined') {
|
|
127
|
+
return Buffer.from(padded, 'base64').toString('utf8');
|
|
128
|
+
}
|
|
129
|
+
// @ts-ignore
|
|
130
|
+
return atob(padded);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Validate API key with the backend
|
|
134
|
+
* @throws Error if API key is invalid
|
|
135
|
+
*/
|
|
136
|
+
async validateApiKey() {
|
|
137
|
+
try {
|
|
138
|
+
// Use a temporary axios instance for validation since baseUrl might be different
|
|
139
|
+
const validationUrl = this.getValidationUrl();
|
|
140
|
+
const response = await axios_1.default.get(validationUrl, {
|
|
141
|
+
headers: {
|
|
142
|
+
'api-key': this.config.apiKey,
|
|
143
|
+
},
|
|
144
|
+
timeout: 10000,
|
|
145
|
+
});
|
|
146
|
+
if (response.data.success) {
|
|
147
|
+
this.validatedApiKeyData = response.data.data;
|
|
148
|
+
return response.data.data;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
const error = new Error(response.data.error.message);
|
|
152
|
+
error.code = response.data.error.code;
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
// If validation fails, ensure we don't keep stale validated data around.
|
|
158
|
+
this.validatedApiKeyData = null;
|
|
159
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
160
|
+
if (error.response?.status === 401) {
|
|
161
|
+
const errorData = error.response.data;
|
|
162
|
+
const apiError = new Error(errorData.error?.message || 'API key is invalid or inactive');
|
|
163
|
+
apiError.code = errorData.error?.code || 'INVALID_API_KEY';
|
|
164
|
+
throw apiError;
|
|
165
|
+
}
|
|
166
|
+
throw new Error(`Failed to validate API key: ${error.message}`);
|
|
167
|
+
}
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get validation URL - uses baseUrl from config
|
|
173
|
+
*/
|
|
174
|
+
getValidationUrl() {
|
|
175
|
+
const baseUrl = this.config.getBaseUrl();
|
|
176
|
+
const cleanBase = baseUrl.replace(/\/$/, '');
|
|
177
|
+
return `${cleanBase}/api/v1/auth/validate-api-key`;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get validated API key data
|
|
181
|
+
*/
|
|
182
|
+
getValidatedApiKeyData() {
|
|
183
|
+
return this.validatedApiKeyData;
|
|
18
184
|
}
|
|
19
185
|
getUrl(path) {
|
|
20
186
|
const baseUrl = this.config.getBaseUrl();
|
|
@@ -23,28 +189,64 @@ class VoidAIBridgeClient {
|
|
|
23
189
|
const cleanPath = path.replace(/^\//, '');
|
|
24
190
|
return `${cleanBase}/${cleanPath}`;
|
|
25
191
|
}
|
|
26
|
-
async get(path, params) {
|
|
192
|
+
async get(path, params, retryAttempted = false) {
|
|
193
|
+
await this.ready;
|
|
27
194
|
const url = this.getUrl(path);
|
|
28
195
|
try {
|
|
29
196
|
const response = await this.client.get(url, { params });
|
|
30
197
|
return response.data;
|
|
31
198
|
}
|
|
32
199
|
catch (error) {
|
|
200
|
+
// If token is expired or unauthorized, transparently re-authenticate once and retry.
|
|
201
|
+
const status = error?.response?.status ?? error?.statusCode;
|
|
202
|
+
if (status === 401 && !retryAttempted) {
|
|
203
|
+
try {
|
|
204
|
+
await this.authenticate();
|
|
205
|
+
// Retry the original request once with fresh credentials.
|
|
206
|
+
return await this.get(path, params, true);
|
|
207
|
+
}
|
|
208
|
+
catch (retryError) {
|
|
209
|
+
this.handleError(retryError);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
33
212
|
this.handleError(error);
|
|
34
|
-
throw error;
|
|
35
213
|
}
|
|
36
214
|
}
|
|
37
|
-
async post(path, data) {
|
|
215
|
+
async post(path, data, retryAttempted = false) {
|
|
216
|
+
await this.ready;
|
|
38
217
|
const url = this.getUrl(path);
|
|
39
218
|
try {
|
|
40
219
|
const response = await this.client.post(url, data);
|
|
41
220
|
return response.data;
|
|
42
221
|
}
|
|
43
222
|
catch (error) {
|
|
223
|
+
// If token is expired or unauthorized, transparently re-authenticate once and retry.
|
|
224
|
+
const status = error?.response?.status ?? error?.statusCode;
|
|
225
|
+
if (status === 401 && !retryAttempted) {
|
|
226
|
+
try {
|
|
227
|
+
await this.authenticate();
|
|
228
|
+
// Retry the original request once with fresh credentials.
|
|
229
|
+
return await this.post(path, data, true);
|
|
230
|
+
}
|
|
231
|
+
catch (retryError) {
|
|
232
|
+
this.handleError(retryError);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
44
235
|
this.handleError(error);
|
|
45
|
-
throw error;
|
|
46
236
|
}
|
|
47
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* Bridge swap operation
|
|
240
|
+
*/
|
|
241
|
+
async bridgeSwap(payload) {
|
|
242
|
+
return this.post('api/v1/bridge/swap', payload);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Route transaction operation (SWAP / BRIDGE / CCIP)
|
|
246
|
+
*/
|
|
247
|
+
async routeTransaction(payload) {
|
|
248
|
+
return this.post('api/v1/bridge/route-transaction', payload);
|
|
249
|
+
}
|
|
48
250
|
/**
|
|
49
251
|
* Get list of supported chains
|
|
50
252
|
* @param options - Optional query parameters
|
|
@@ -63,26 +265,82 @@ class VoidAIBridgeClient {
|
|
|
63
265
|
if (options?.chainId !== undefined) {
|
|
64
266
|
params.chain_id = options.chainId;
|
|
65
267
|
}
|
|
66
|
-
const response = await this.get('api/chains', params);
|
|
67
|
-
|
|
268
|
+
const response = await this.get('api/v1/chain/chains', params);
|
|
269
|
+
if (!response.success || !response.data) {
|
|
270
|
+
throw new Error(response.message || 'Failed to fetch chains');
|
|
271
|
+
}
|
|
272
|
+
return response.data.chains;
|
|
68
273
|
}
|
|
69
274
|
/**
|
|
70
275
|
* Get list of supported assets
|
|
71
276
|
*/
|
|
72
277
|
async getAssetList(chainId) {
|
|
73
|
-
const response = await this.get('api/asset');
|
|
278
|
+
const response = await this.get('api/v1/asset/assets');
|
|
279
|
+
if (!response.success || !response.data) {
|
|
280
|
+
throw new Error(response.message || 'Failed to fetch assets');
|
|
281
|
+
}
|
|
282
|
+
let assets = response.data.assets;
|
|
74
283
|
// Filter by chainId if provided
|
|
75
284
|
if (chainId !== undefined) {
|
|
76
|
-
|
|
285
|
+
assets = assets.filter(asset => asset.chainId === chainId);
|
|
77
286
|
}
|
|
78
|
-
return
|
|
287
|
+
return assets;
|
|
79
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Get bridge fee estimate
|
|
291
|
+
* @param params - Fee estimation parameters
|
|
292
|
+
*/
|
|
293
|
+
async getBridgeFeeEstimate(params) {
|
|
294
|
+
const queryParams = {
|
|
295
|
+
fromToken: params.fromToken,
|
|
296
|
+
toToken: params.toToken,
|
|
297
|
+
amount: String(params.amount),
|
|
298
|
+
};
|
|
299
|
+
return this.get('api/v1/bridge/call-fee', queryParams);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Get router swap fee estimate
|
|
303
|
+
* @param params - Fee estimation parameters
|
|
304
|
+
*/
|
|
305
|
+
async getRouterSwapFeeEstimate(params) {
|
|
306
|
+
const queryParams = {
|
|
307
|
+
originAssetId: String(params.originAssetId),
|
|
308
|
+
destinationAssetId: String(params.destinationAssetId),
|
|
309
|
+
amount: String(params.amount),
|
|
310
|
+
operationType: params.operationType,
|
|
311
|
+
toAddress: params.toAddress,
|
|
312
|
+
};
|
|
313
|
+
return this.get('api/v1/router-swap/call-fee', queryParams);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Normalize and rethrow errors with backend message (if available) so
|
|
317
|
+
* integrators can surface meaningful reasons to their users.
|
|
318
|
+
*/
|
|
80
319
|
handleError(error) {
|
|
81
320
|
if (axios_1.default.isAxiosError(error)) {
|
|
82
|
-
|
|
321
|
+
const status = error.response?.status;
|
|
322
|
+
const data = error.response?.data;
|
|
323
|
+
// Try to extract a human friendly message from common backend shapes
|
|
324
|
+
let backendMessage = data?.error?.message ||
|
|
325
|
+
data?.message ||
|
|
326
|
+
(typeof data?.error === 'string' ? data.error : undefined) ||
|
|
327
|
+
(data?.success === false && data?.message ? data.message : undefined);
|
|
328
|
+
// For auth failures, avoid leaking raw backend JSON and give a clearer hint.
|
|
329
|
+
if (status === 401 &&
|
|
330
|
+
(backendMessage === 'Unauthorized' ||
|
|
331
|
+
data?.statusCode === 401 ||
|
|
332
|
+
data?.message === 'Unauthorized')) {
|
|
333
|
+
backendMessage =
|
|
334
|
+
'Session expired or unauthorized. Please verify your API key/secret and try again.';
|
|
335
|
+
}
|
|
336
|
+
const message = backendMessage ||
|
|
337
|
+
error.message ||
|
|
338
|
+
(status ? `Request failed with status ${status}` : 'Request failed');
|
|
339
|
+
throw new Error(message);
|
|
83
340
|
}
|
|
84
341
|
else {
|
|
85
|
-
|
|
342
|
+
const message = error?.message || 'Unexpected error';
|
|
343
|
+
throw new Error(message);
|
|
86
344
|
}
|
|
87
345
|
}
|
|
88
346
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import { BridgeSDKOptions, Environment } from './types';
|
|
1
|
+
import { BridgeSDKOptions, BridgeSDKServerOptions, Environment } from './types';
|
|
2
|
+
/** Internal: options accepted by BridgeConfig (frontend or server) */
|
|
3
|
+
type BridgeConfigOptions = BridgeSDKOptions | BridgeSDKServerOptions;
|
|
2
4
|
export declare class BridgeConfig {
|
|
3
5
|
readonly apiKey: string;
|
|
6
|
+
readonly secretKey?: string;
|
|
4
7
|
readonly environment: Environment;
|
|
5
8
|
readonly baseUrl: string;
|
|
9
|
+
/**
|
|
10
|
+
* EVM bridge contract address used for burn operations
|
|
11
|
+
* (wTAO/wALPHA -> TAO/ALPHA). Network-specific values can be
|
|
12
|
+
* configured here per environment.
|
|
13
|
+
*/
|
|
14
|
+
readonly bridgeContractAddress: string;
|
|
6
15
|
private static readonly DEFAULTS;
|
|
7
|
-
constructor(options:
|
|
16
|
+
constructor(options: BridgeConfigOptions);
|
|
8
17
|
getBaseUrl(): string;
|
|
9
18
|
}
|
|
19
|
+
export {};
|
package/dist/config.js
CHANGED
|
@@ -7,6 +7,7 @@ class BridgeConfig {
|
|
|
7
7
|
throw new Error('BridgeSDK: apiKey is required');
|
|
8
8
|
}
|
|
9
9
|
this.apiKey = options.apiKey;
|
|
10
|
+
this.secretKey = 'secretKey' in options ? options.secretKey : undefined;
|
|
10
11
|
this.environment = options.environment || 'production';
|
|
11
12
|
// Ensure environment is valid, default to production if invalid
|
|
12
13
|
const validEnvironments = ['development', 'staging', 'production'];
|
|
@@ -14,8 +15,10 @@ class BridgeConfig {
|
|
|
14
15
|
this.environment = 'production';
|
|
15
16
|
}
|
|
16
17
|
const defaults = BridgeConfig.DEFAULTS[this.environment];
|
|
17
|
-
//
|
|
18
|
-
|
|
18
|
+
// Base URL & bridge contract address are derived from environment;
|
|
19
|
+
// consumers should not override these at runtime.
|
|
20
|
+
this.baseUrl = defaults.baseUrl;
|
|
21
|
+
this.bridgeContractAddress = defaults.bridgeContractAddress;
|
|
19
22
|
}
|
|
20
23
|
getBaseUrl() {
|
|
21
24
|
return this.baseUrl;
|
|
@@ -24,12 +27,16 @@ class BridgeConfig {
|
|
|
24
27
|
exports.BridgeConfig = BridgeConfig;
|
|
25
28
|
BridgeConfig.DEFAULTS = {
|
|
26
29
|
development: {
|
|
27
|
-
|
|
30
|
+
// Local/dev backend
|
|
31
|
+
baseUrl: 'https://api-sdk-dev.voidai.envistudios.com/',
|
|
32
|
+
bridgeContractAddress: '0x6266ce15aC4f32F096Ff91881dd887a0F4bBa569',
|
|
28
33
|
},
|
|
29
34
|
staging: {
|
|
30
|
-
baseUrl: 'https://api-
|
|
35
|
+
baseUrl: 'https://api-sdk-stage.voidai.envistudios.com/',
|
|
36
|
+
bridgeContractAddress: '0x6266ce15aC4f32F096Ff91881dd887a0F4bBa569',
|
|
31
37
|
},
|
|
32
38
|
production: {
|
|
33
|
-
baseUrl: 'https://api.voidai.envistudios.com',
|
|
39
|
+
baseUrl: 'https://api-sdk.voidai.envistudios.com/',
|
|
40
|
+
bridgeContractAddress: '0x6266ce15aC4f32F096Ff91881dd887a0F4bBa569',
|
|
34
41
|
},
|
|
35
42
|
};
|
package/dist/core/bridge.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { VoidAIBridgeClient } from '../api/client';
|
|
2
|
+
import { BridgeSwapRequest, BridgeSwapResponse, RouteSwapRequest, RouteBridgeRequest, RouteCcipRequest, RouteTransactionResponse, BridgeFeeEstimateRequest, BridgeFeeEstimateResponse, RouterSwapFeeEstimateRequest, RouterSwapFeeEstimateResponse } from '../types';
|
|
2
3
|
/**
|
|
3
4
|
* Bridge API Methods
|
|
4
5
|
* Provides read-only API methods for bridge operations
|
|
@@ -14,4 +15,32 @@ export declare class Bridge {
|
|
|
14
15
|
* Get transaction history for an address
|
|
15
16
|
*/
|
|
16
17
|
getHistory(address: string): Promise<any[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Initiate a bridge operation (formerly swap).
|
|
20
|
+
*/
|
|
21
|
+
bridge(payload: BridgeSwapRequest): Promise<BridgeSwapResponse>;
|
|
22
|
+
/**
|
|
23
|
+
* Alias for backward compatibility.
|
|
24
|
+
*/
|
|
25
|
+
swap(payload: BridgeSwapRequest): Promise<BridgeSwapResponse>;
|
|
26
|
+
/**
|
|
27
|
+
* Route a SWAP operation through the unified route-transaction API.
|
|
28
|
+
*/
|
|
29
|
+
routeSwap(payload: RouteSwapRequest): Promise<RouteTransactionResponse>;
|
|
30
|
+
/**
|
|
31
|
+
* Route a BRIDGE operation through the unified route-transaction API.
|
|
32
|
+
*/
|
|
33
|
+
routeBridge(payload: RouteBridgeRequest): Promise<RouteTransactionResponse>;
|
|
34
|
+
/**
|
|
35
|
+
* Route a CCIP operation through the unified route-transaction API.
|
|
36
|
+
*/
|
|
37
|
+
routeCcip(payload: RouteCcipRequest): Promise<RouteTransactionResponse>;
|
|
38
|
+
/**
|
|
39
|
+
* Get bridge fee estimate
|
|
40
|
+
*/
|
|
41
|
+
getBridgeFeeEstimate(params: BridgeFeeEstimateRequest): Promise<BridgeFeeEstimateResponse>;
|
|
42
|
+
/**
|
|
43
|
+
* Get router swap fee estimate
|
|
44
|
+
*/
|
|
45
|
+
getRouterSwapFeeEstimate(params: RouterSwapFeeEstimateRequest): Promise<RouterSwapFeeEstimateResponse>;
|
|
17
46
|
}
|
package/dist/core/bridge.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Bridge = void 0;
|
|
4
|
+
const viem_1 = require("viem");
|
|
4
5
|
/**
|
|
5
6
|
* Bridge API Methods
|
|
6
7
|
* Provides read-only API methods for bridge operations
|
|
@@ -22,5 +23,119 @@ class Bridge {
|
|
|
22
23
|
async getHistory(address) {
|
|
23
24
|
return this.apiClient.get(`/transactions/history/${address}`);
|
|
24
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Initiate a bridge operation (formerly swap).
|
|
28
|
+
*/
|
|
29
|
+
async bridge(payload) {
|
|
30
|
+
try {
|
|
31
|
+
const response = await this.apiClient.bridgeSwap(payload);
|
|
32
|
+
// For EVM flows that return encodedData + signature, prepare
|
|
33
|
+
// a ready-to-send Ethereum transaction for the bridge contract.
|
|
34
|
+
const maybeWithEncoded = response;
|
|
35
|
+
if (maybeWithEncoded.encodedData && maybeWithEncoded.signature) {
|
|
36
|
+
// IMPORTANT:
|
|
37
|
+
// - The bridge contract address is configured per environment
|
|
38
|
+
// in BridgeConfig (config.ts). The encodedData & signature are
|
|
39
|
+
// already validated/constructed by the backend.
|
|
40
|
+
// - We simply ABI-encode the function call so frontend integrators
|
|
41
|
+
// can pass it directly to MetaMask / wallet providers.
|
|
42
|
+
const bridgeContractAddress = this.apiClient.getBridgeContractAddress();
|
|
43
|
+
const calldata = (0, viem_1.encodeFunctionData)({
|
|
44
|
+
abi: [
|
|
45
|
+
{
|
|
46
|
+
type: 'function',
|
|
47
|
+
name: 'burn',
|
|
48
|
+
stateMutability: 'nonpayable',
|
|
49
|
+
inputs: [
|
|
50
|
+
{ name: 'encodedData', type: 'bytes' },
|
|
51
|
+
{ name: 'signature', type: 'bytes' },
|
|
52
|
+
],
|
|
53
|
+
outputs: [],
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
functionName: 'burn',
|
|
57
|
+
args: [maybeWithEncoded.encodedData, maybeWithEncoded.signature],
|
|
58
|
+
});
|
|
59
|
+
// Attach the prepared transaction payload in a non-breaking way.
|
|
60
|
+
maybeWithEncoded.evmTransaction = {
|
|
61
|
+
to: bridgeContractAddress,
|
|
62
|
+
data: calldata,
|
|
63
|
+
value: '0x0',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return response;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
// Surface a clean error message while preserving the original error for debugging.
|
|
70
|
+
const message = error?.message || 'Failed to execute bridge swap';
|
|
71
|
+
throw new Error(message);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Alias for backward compatibility.
|
|
76
|
+
*/
|
|
77
|
+
async swap(payload) {
|
|
78
|
+
return this.bridge(payload);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Route a SWAP operation through the unified route-transaction API.
|
|
82
|
+
*/
|
|
83
|
+
async routeSwap(payload) {
|
|
84
|
+
try {
|
|
85
|
+
return await this.apiClient.routeTransaction(payload);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
const message = error?.message || 'Failed to route SWAP transaction';
|
|
89
|
+
throw new Error(message);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Route a BRIDGE operation through the unified route-transaction API.
|
|
94
|
+
*/
|
|
95
|
+
async routeBridge(payload) {
|
|
96
|
+
try {
|
|
97
|
+
return await this.apiClient.routeTransaction(payload);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
const message = error?.message || 'Failed to route BRIDGE transaction';
|
|
101
|
+
throw new Error(message);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Route a CCIP operation through the unified route-transaction API.
|
|
106
|
+
*/
|
|
107
|
+
async routeCcip(payload) {
|
|
108
|
+
try {
|
|
109
|
+
return await this.apiClient.routeTransaction(payload);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
const message = error?.message || 'Failed to route CCIP transaction';
|
|
113
|
+
throw new Error(message);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get bridge fee estimate
|
|
118
|
+
*/
|
|
119
|
+
async getBridgeFeeEstimate(params) {
|
|
120
|
+
try {
|
|
121
|
+
return await this.apiClient.getBridgeFeeEstimate(params);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
const message = error?.message || 'Failed to get bridge fee estimate';
|
|
125
|
+
throw new Error(message);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get router swap fee estimate
|
|
130
|
+
*/
|
|
131
|
+
async getRouterSwapFeeEstimate(params) {
|
|
132
|
+
try {
|
|
133
|
+
return await this.apiClient.getRouterSwapFeeEstimate(params);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
const message = error?.message || 'Failed to get router swap fee estimate';
|
|
137
|
+
throw new Error(message);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
25
140
|
}
|
|
26
141
|
exports.Bridge = Bridge;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,12 +4,16 @@ import { BittensorWallet } from './wallet/bittensor';
|
|
|
4
4
|
import { EthereumWallet } from './wallet/ethereum';
|
|
5
5
|
import { SolanaWallet } from './wallet/solana';
|
|
6
6
|
import { Bridge } from './core/bridge';
|
|
7
|
-
import { BridgeSDKOptions } from './types';
|
|
7
|
+
import { BridgeSDKOptions, BridgeSDKServerOptions, ApiKeyValidationData } from './types';
|
|
8
8
|
export * from './types';
|
|
9
9
|
export * from './config';
|
|
10
10
|
export * from './wallet/bittensor';
|
|
11
11
|
export * from './wallet/ethereum';
|
|
12
12
|
export * from './wallet/solana';
|
|
13
|
+
/**
|
|
14
|
+
* BridgeSDK – for frontend/browser usage.
|
|
15
|
+
* Use apiKey only; do not pass secretKey in frontend.
|
|
16
|
+
*/
|
|
13
17
|
export declare class BridgeSDK {
|
|
14
18
|
readonly config: BridgeConfig;
|
|
15
19
|
readonly api: VoidAIBridgeClient;
|
|
@@ -19,9 +23,33 @@ export declare class BridgeSDK {
|
|
|
19
23
|
solana: SolanaWallet;
|
|
20
24
|
};
|
|
21
25
|
readonly bridge: Bridge;
|
|
26
|
+
/**
|
|
27
|
+
* Resolves once the SDK has validated the API key (or rejects if invalid).
|
|
28
|
+
* Consumers can await this if they want to gate UI on readiness.
|
|
29
|
+
*/
|
|
30
|
+
readonly ready: Promise<void>;
|
|
22
31
|
constructor(options: BridgeSDKOptions);
|
|
23
32
|
/**
|
|
24
|
-
*
|
|
33
|
+
* Get validated API key data (available after successful validation)
|
|
34
|
+
*/
|
|
35
|
+
getValidatedApiKeyData(): ApiKeyValidationData | null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* BridgeSDKServer – for backend/server usage.
|
|
39
|
+
* Requires apiKey + secretKey for JWT authentication.
|
|
40
|
+
* No wallet integrations (use BridgeSDK in frontend for that).
|
|
41
|
+
*/
|
|
42
|
+
export declare class BridgeSDKServer {
|
|
43
|
+
readonly config: BridgeConfig;
|
|
44
|
+
readonly api: VoidAIBridgeClient;
|
|
45
|
+
readonly bridge: Bridge;
|
|
46
|
+
/**
|
|
47
|
+
* Resolves once the SDK has validated the API key (or rejects if invalid).
|
|
48
|
+
*/
|
|
49
|
+
readonly ready: Promise<void>;
|
|
50
|
+
constructor(options: BridgeSDKServerOptions);
|
|
51
|
+
/**
|
|
52
|
+
* Get validated API key data (available after successful validation)
|
|
25
53
|
*/
|
|
26
|
-
|
|
54
|
+
getValidatedApiKeyData(): ApiKeyValidationData | null;
|
|
27
55
|
}
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.BridgeSDK = void 0;
|
|
17
|
+
exports.BridgeSDKServer = exports.BridgeSDK = void 0;
|
|
18
18
|
const config_1 = require("./config");
|
|
19
19
|
const client_1 = require("./api/client");
|
|
20
20
|
const bittensor_1 = require("./wallet/bittensor");
|
|
@@ -26,10 +26,15 @@ __exportStar(require("./config"), exports);
|
|
|
26
26
|
__exportStar(require("./wallet/bittensor"), exports);
|
|
27
27
|
__exportStar(require("./wallet/ethereum"), exports);
|
|
28
28
|
__exportStar(require("./wallet/solana"), exports);
|
|
29
|
+
/**
|
|
30
|
+
* BridgeSDK – for frontend/browser usage.
|
|
31
|
+
* Use apiKey only; do not pass secretKey in frontend.
|
|
32
|
+
*/
|
|
29
33
|
class BridgeSDK {
|
|
30
34
|
constructor(options) {
|
|
31
35
|
this.config = new config_1.BridgeConfig(options);
|
|
32
36
|
this.api = new client_1.VoidAIBridgeClient(this.config);
|
|
37
|
+
this.ready = this.api.ready;
|
|
33
38
|
this.wallets = {
|
|
34
39
|
bittensor: new bittensor_1.BittensorWallet(),
|
|
35
40
|
ethereum: new ethereum_1.EthereumWallet(),
|
|
@@ -38,10 +43,30 @@ class BridgeSDK {
|
|
|
38
43
|
this.bridge = new bridge_1.Bridge(this.api);
|
|
39
44
|
}
|
|
40
45
|
/**
|
|
41
|
-
*
|
|
46
|
+
* Get validated API key data (available after successful validation)
|
|
42
47
|
*/
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
getValidatedApiKeyData() {
|
|
49
|
+
return this.api.getValidatedApiKeyData();
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
exports.BridgeSDK = BridgeSDK;
|
|
53
|
+
/**
|
|
54
|
+
* BridgeSDKServer – for backend/server usage.
|
|
55
|
+
* Requires apiKey + secretKey for JWT authentication.
|
|
56
|
+
* No wallet integrations (use BridgeSDK in frontend for that).
|
|
57
|
+
*/
|
|
58
|
+
class BridgeSDKServer {
|
|
59
|
+
constructor(options) {
|
|
60
|
+
this.config = new config_1.BridgeConfig(options);
|
|
61
|
+
this.api = new client_1.VoidAIBridgeClient(this.config);
|
|
62
|
+
this.ready = this.api.ready;
|
|
63
|
+
this.bridge = new bridge_1.Bridge(this.api);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get validated API key data (available after successful validation)
|
|
67
|
+
*/
|
|
68
|
+
getValidatedApiKeyData() {
|
|
69
|
+
return this.api.getValidatedApiKeyData();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.BridgeSDKServer = BridgeSDKServer;
|