@vulcx/sdk 0.2.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.
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # @vulcx/sdk
2
+
3
+ TypeScript SDK for the Vulcx DEX aggregator API. Works in Node.js, browsers, and any JavaScript runtime with `fetch`.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @vulcx/sdk
9
+ ```
10
+
11
+ Or via CDN:
12
+
13
+ ```html
14
+ <script src="https://unpkg.com/@vulcx/sdk"></script>
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```typescript
20
+ import { VulcxSDK } from "@vulcx/sdk";
21
+
22
+ const vulcx = new VulcxSDK({
23
+ apiKey: "vulcx_your_api_key_here",
24
+ chain: "solana", // or "fogo"
25
+ });
26
+
27
+ // Get a quote
28
+ const quote = await vulcx.quote({
29
+ inputMint: "So11111111111111111111111111111111111111112",
30
+ outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
31
+ amount: "1000000000", // 1 SOL in lamports
32
+ swapMode: "ExactIn",
33
+ slippageBps: 50,
34
+ });
35
+
36
+ console.log(`Output: ${quote.amountOut}, Impact: ${quote.priceImpactPercent}`);
37
+ ```
38
+
39
+ ## API
40
+
41
+ ### `new VulcxSDK(config)`
42
+
43
+ | Parameter | Type | Default | Description |
44
+ | ----------- | -------- | ----------------------------- | -------------------------- |
45
+ | `apiKey` | `string` | **required** | Your API key |
46
+ | `chain` | `string` | `"solana"` | `"solana"` or `"fogo"` |
47
+ | `baseUrl` | `string` | `"https://api.vulcx.xyz"` | API base URL |
48
+ | `timeout` | `number` | `30000` | Request timeout in ms |
49
+ | `retries` | `number` | `2` | Retry count for 429/5xx |
50
+
51
+ ### `sdk.quote(params): Promise<QuoteResponse>`
52
+
53
+ ```typescript
54
+ const quote = await vulcx.quote({
55
+ inputMint: "So111...",
56
+ outputMint: "EPjFW...",
57
+ amount: "1000000000",
58
+ swapMode: "ExactIn", // or "ExactOut"
59
+ slippageBps: 50, // optional, default 50
60
+ });
61
+ ```
62
+
63
+ ### `sdk.swap(params): Promise<SwapResponse>`
64
+
65
+ Returns a base64-encoded unsigned transaction.
66
+
67
+ ```typescript
68
+ const swap = await vulcx.swap({
69
+ userWallet: "9WzDX...",
70
+ inputMint: "So111...",
71
+ outputMint: "EPjFW...",
72
+ amount: "1000000000",
73
+ swapMode: "ExactIn",
74
+ slippageBps: 50,
75
+ skipSimulation: false,
76
+ });
77
+
78
+ // Sign and send swap.transaction with your wallet adapter
79
+ ```
80
+
81
+ ### `sdk.instructions(params): Promise<InstructionsResponse>`
82
+
83
+ Returns raw instructions for composability.
84
+
85
+ ```typescript
86
+ const ixs = await vulcx.instructions({
87
+ userWallet: "9WzDX...",
88
+ inputMint: "So111...",
89
+ outputMint: "EPjFW...",
90
+ amount: "1000000000",
91
+ swapMode: "ExactIn",
92
+ });
93
+
94
+ // Build your own transaction with ixs.instructions
95
+ ```
96
+
97
+ ## Error Handling
98
+
99
+ ```typescript
100
+ import { VulcxSDK, NoRouteError, RateLimitError, AuthError } from "@vulcx/sdk";
101
+
102
+ try {
103
+ const quote = await vulcx.quote({ ... });
104
+ } catch (err) {
105
+ if (err instanceof NoRouteError) {
106
+ console.log("No route found between tokens");
107
+ } else if (err instanceof RateLimitError) {
108
+ console.log("Rate limited, try again later");
109
+ } else if (err instanceof AuthError) {
110
+ console.log("Invalid API key");
111
+ }
112
+ }
113
+ ```
114
+
115
+ ## Framework Examples
116
+
117
+ ### React
118
+
119
+ ```tsx
120
+ import { VulcxSDK } from "@vulcx/sdk";
121
+ import { useEffect, useState } from "react";
122
+
123
+ const sdk = new VulcxSDK({ apiKey: "vulcx_..." });
124
+
125
+ function SwapPage() {
126
+ const [quote, setQuote] = useState(null);
127
+
128
+ useEffect(() => {
129
+ sdk.quote({
130
+ inputMint: "So111...",
131
+ outputMint: "EPjFW...",
132
+ amount: "1000000000",
133
+ swapMode: "ExactIn",
134
+ }).then(setQuote);
135
+ }, []);
136
+
137
+ return <div>{quote && <p>Output: {quote.amountOut}</p>}</div>;
138
+ }
139
+ ```
140
+
141
+ ### Node.js
142
+
143
+ ```javascript
144
+ const { VulcxSDK } = require("@vulcx/sdk");
145
+
146
+ const sdk = new VulcxSDK({ apiKey: process.env.VULCX_KEY });
147
+ const quote = await sdk.quote({ ... });
148
+ ```
@@ -0,0 +1,13 @@
1
+ import type { SDKConfig, QuoteRequest, QuoteResponse, SwapRequest, SwapResponse, InstructionsRequest, InstructionsResponse } from "./types";
2
+ export declare class VulcxSDK {
3
+ private readonly apiKey;
4
+ private readonly chain;
5
+ private readonly baseUrl;
6
+ private readonly timeout;
7
+ private readonly retries;
8
+ constructor(config: SDKConfig);
9
+ quote(params: QuoteRequest): Promise<QuoteResponse>;
10
+ swap(params: SwapRequest): Promise<SwapResponse>;
11
+ instructions(params: InstructionsRequest): Promise<InstructionsResponse>;
12
+ private request;
13
+ }
@@ -0,0 +1,20 @@
1
+ export declare class VulcxError extends Error {
2
+ readonly statusCode: number;
3
+ readonly body?: unknown | undefined;
4
+ constructor(message: string, statusCode: number, body?: unknown | undefined);
5
+ }
6
+ export declare class RateLimitError extends VulcxError {
7
+ constructor(body?: unknown);
8
+ }
9
+ export declare class NoRouteError extends VulcxError {
10
+ constructor(body?: unknown);
11
+ }
12
+ export declare class BadRequestError extends VulcxError {
13
+ constructor(message: string, body?: unknown);
14
+ }
15
+ export declare class AuthError extends VulcxError {
16
+ constructor(body?: unknown);
17
+ }
18
+ export declare class ServerError extends VulcxError {
19
+ constructor(message: string, body?: unknown);
20
+ }
@@ -0,0 +1,155 @@
1
+ 'use strict';
2
+
3
+ class VulcxError extends Error {
4
+ constructor(message, statusCode, body) {
5
+ super(message);
6
+ this.statusCode = statusCode;
7
+ this.body = body;
8
+ this.name = "VulcxError";
9
+ }
10
+ }
11
+ class RateLimitError extends VulcxError {
12
+ constructor(body) {
13
+ super("Rate limit exceeded", 429, body);
14
+ this.name = "RateLimitError";
15
+ }
16
+ }
17
+ class NoRouteError extends VulcxError {
18
+ constructor(body) {
19
+ super("No route found", 404, body);
20
+ this.name = "NoRouteError";
21
+ }
22
+ }
23
+ class BadRequestError extends VulcxError {
24
+ constructor(message, body) {
25
+ super(message, 400, body);
26
+ this.name = "BadRequestError";
27
+ }
28
+ }
29
+ class AuthError extends VulcxError {
30
+ constructor(body) {
31
+ super("Invalid or missing API key", 401, body);
32
+ this.name = "AuthError";
33
+ }
34
+ }
35
+ class ServerError extends VulcxError {
36
+ constructor(message, body) {
37
+ super(message, 500, body);
38
+ this.name = "ServerError";
39
+ }
40
+ }
41
+
42
+ const DEFAULT_BASE_URL = "https://api.vulcx.xyz";
43
+ const DEFAULT_TIMEOUT = 30000;
44
+ const DEFAULT_RETRIES = 2;
45
+ class VulcxSDK {
46
+ constructor(config) {
47
+ if (!config.apiKey)
48
+ throw new Error("apiKey is required");
49
+ this.apiKey = config.apiKey;
50
+ this.chain = config.chain ?? "solana";
51
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
52
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
53
+ this.retries = config.retries ?? DEFAULT_RETRIES;
54
+ }
55
+ async quote(params) {
56
+ const qs = new URLSearchParams({
57
+ inputMint: params.inputMint,
58
+ outputMint: params.outputMint,
59
+ amount: params.amount,
60
+ swapMode: params.swapMode,
61
+ });
62
+ if (params.slippageBps !== undefined) {
63
+ qs.set("slippageBps", String(params.slippageBps));
64
+ }
65
+ return this.request("GET", `/api/v1/quote?${qs}`);
66
+ }
67
+ async swap(params) {
68
+ return this.request("POST", "/api/v1/swap", params);
69
+ }
70
+ async instructions(params) {
71
+ return this.request("POST", "/api/v1/instructions", params);
72
+ }
73
+ async request(method, path, body) {
74
+ const separator = path.includes("?") ? "&" : "?";
75
+ const url = `${this.baseUrl}${path}${separator}chain=${this.chain}`;
76
+ const headers = {
77
+ Authorization: `Bearer ${this.apiKey}`,
78
+ Accept: "application/json",
79
+ };
80
+ if (body) {
81
+ headers["Content-Type"] = "application/json";
82
+ }
83
+ let lastError;
84
+ for (let attempt = 0; attempt <= this.retries; attempt++) {
85
+ if (attempt > 0) {
86
+ await sleep(Math.min(1000 * 2 ** (attempt - 1), 8000));
87
+ }
88
+ try {
89
+ const controller = new AbortController();
90
+ const timer = setTimeout(() => controller.abort(), this.timeout);
91
+ const res = await fetch(url, {
92
+ method,
93
+ headers,
94
+ body: body ? JSON.stringify(body) : undefined,
95
+ signal: controller.signal,
96
+ });
97
+ clearTimeout(timer);
98
+ if (res.ok) {
99
+ const parsed = (await res.json());
100
+ // API responses wrap the payload in {success, data}; hand back the
101
+ // payload the way the method signatures promise.
102
+ if (parsed && typeof parsed === "object" && "success" in parsed) {
103
+ if (!parsed.success) {
104
+ throw new VulcxError(parsed.error ?? "request failed", res.status, parsed);
105
+ }
106
+ return parsed.data;
107
+ }
108
+ return parsed;
109
+ }
110
+ const errBody = await res.json().catch(() => ({}));
111
+ const errMsg = errBody?.error ?? res.statusText;
112
+ switch (res.status) {
113
+ case 401:
114
+ case 403:
115
+ throw new AuthError(errBody);
116
+ case 400:
117
+ throw new BadRequestError(errMsg, errBody);
118
+ case 404:
119
+ throw new NoRouteError(errBody);
120
+ case 429:
121
+ lastError = new RateLimitError(errBody);
122
+ continue;
123
+ default:
124
+ if (res.status >= 500) {
125
+ lastError = new ServerError(errMsg, errBody);
126
+ continue;
127
+ }
128
+ throw new VulcxError(errMsg, res.status, errBody);
129
+ }
130
+ }
131
+ catch (err) {
132
+ if (err instanceof AuthError ||
133
+ err instanceof BadRequestError ||
134
+ err instanceof NoRouteError ||
135
+ err instanceof VulcxError) {
136
+ throw err;
137
+ }
138
+ lastError = err;
139
+ }
140
+ }
141
+ throw lastError ?? new Error("request failed");
142
+ }
143
+ }
144
+ function sleep(ms) {
145
+ return new Promise((r) => setTimeout(r, ms));
146
+ }
147
+
148
+ exports.AuthError = AuthError;
149
+ exports.BadRequestError = BadRequestError;
150
+ exports.NoRouteError = NoRouteError;
151
+ exports.RateLimitError = RateLimitError;
152
+ exports.ServerError = ServerError;
153
+ exports.VulcxError = VulcxError;
154
+ exports.VulcxSDK = VulcxSDK;
155
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":[null,null],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ type SwapMode = "ExactIn" | "ExactOut";
2
+ type Chain = "solana" | "fogo";
3
+ type PriceImpactSeverity = "none" | "low" | "moderate" | "high" | "extreme";
4
+ interface SDKConfig {
5
+ apiKey: string;
6
+ chain?: Chain;
7
+ baseUrl?: string;
8
+ timeout?: number;
9
+ retries?: number;
10
+ }
11
+ interface QuoteRequest {
12
+ inputMint: string;
13
+ outputMint: string;
14
+ amount: string;
15
+ swapMode: SwapMode;
16
+ slippageBps?: number;
17
+ }
18
+ interface RouteInfo {
19
+ poolAddress: string;
20
+ poolType: string;
21
+ percent: number;
22
+ inputMint: string;
23
+ outputMint: string;
24
+ }
25
+ interface QuoteResponse {
26
+ inputMint: string;
27
+ outputMint: string;
28
+ amountIn: string;
29
+ amountOut: string;
30
+ priceImpactBps: number;
31
+ priceImpactPercent: string;
32
+ priceImpactSeverity: PriceImpactSeverity;
33
+ priceImpactWarning: string;
34
+ feeBps: number;
35
+ routes: RouteInfo[];
36
+ routePath: string[];
37
+ hopCount: number;
38
+ otherAmountThreshold: string;
39
+ }
40
+ interface SwapRequest {
41
+ userWallet: string;
42
+ inputMint: string;
43
+ outputMint: string;
44
+ amount: string;
45
+ swapMode: SwapMode;
46
+ slippageBps?: number;
47
+ skipSimulation?: boolean;
48
+ }
49
+ interface SimulationResult {
50
+ success: boolean;
51
+ computeUnitsConsumed: number;
52
+ computeUnitsTotal: number;
53
+ logs: string[];
54
+ error: string;
55
+ slippageExceeded: boolean;
56
+ insufficientFunds: boolean;
57
+ accountsNeeded: string[];
58
+ }
59
+ interface SwapResponse {
60
+ transaction: string;
61
+ lastValidBlockHeight: number;
62
+ amountIn: string;
63
+ amountOut: string;
64
+ minAmountOut?: string;
65
+ maxAmountIn?: string;
66
+ feeAmount: string;
67
+ simulation?: SimulationResult;
68
+ computeUnitsEstimate: number;
69
+ route: string[];
70
+ hopCount: number;
71
+ pools: string[];
72
+ isSplitRoute: boolean;
73
+ splitPercents?: number[];
74
+ }
75
+ interface InstructionsRequest {
76
+ userWallet: string;
77
+ inputMint: string;
78
+ outputMint: string;
79
+ amount: string;
80
+ swapMode: SwapMode;
81
+ slippageBps?: number;
82
+ }
83
+ interface RawAccountMeta {
84
+ publicKey: string;
85
+ isSigner: boolean;
86
+ isWritable: boolean;
87
+ }
88
+ interface RawInstruction {
89
+ programId: string;
90
+ accounts: RawAccountMeta[];
91
+ data: string;
92
+ }
93
+ interface InstructionsResponse {
94
+ instructions: RawInstruction[];
95
+ addressLookupTableAddresses: string[];
96
+ amountIn: string;
97
+ amountOut: string;
98
+ otherAmountThreshold: string;
99
+ feeAmount: string;
100
+ hopCount: number;
101
+ route: string[];
102
+ pools: string[];
103
+ }
104
+
105
+ declare class VulcxSDK {
106
+ private readonly apiKey;
107
+ private readonly chain;
108
+ private readonly baseUrl;
109
+ private readonly timeout;
110
+ private readonly retries;
111
+ constructor(config: SDKConfig);
112
+ quote(params: QuoteRequest): Promise<QuoteResponse>;
113
+ swap(params: SwapRequest): Promise<SwapResponse>;
114
+ instructions(params: InstructionsRequest): Promise<InstructionsResponse>;
115
+ private request;
116
+ }
117
+
118
+ declare class VulcxError extends Error {
119
+ readonly statusCode: number;
120
+ readonly body?: unknown | undefined;
121
+ constructor(message: string, statusCode: number, body?: unknown | undefined);
122
+ }
123
+ declare class RateLimitError extends VulcxError {
124
+ constructor(body?: unknown);
125
+ }
126
+ declare class NoRouteError extends VulcxError {
127
+ constructor(body?: unknown);
128
+ }
129
+ declare class BadRequestError extends VulcxError {
130
+ constructor(message: string, body?: unknown);
131
+ }
132
+ declare class AuthError extends VulcxError {
133
+ constructor(body?: unknown);
134
+ }
135
+ declare class ServerError extends VulcxError {
136
+ constructor(message: string, body?: unknown);
137
+ }
138
+
139
+ export { AuthError, BadRequestError, NoRouteError, RateLimitError, ServerError, VulcxError, VulcxSDK };
140
+ export type { Chain, InstructionsRequest, InstructionsResponse, PriceImpactSeverity, QuoteRequest, QuoteResponse, RawAccountMeta, RawInstruction, RouteInfo, SDKConfig, SimulationResult, SwapMode, SwapRequest, SwapResponse };
@@ -0,0 +1,147 @@
1
+ class VulcxError extends Error {
2
+ constructor(message, statusCode, body) {
3
+ super(message);
4
+ this.statusCode = statusCode;
5
+ this.body = body;
6
+ this.name = "VulcxError";
7
+ }
8
+ }
9
+ class RateLimitError extends VulcxError {
10
+ constructor(body) {
11
+ super("Rate limit exceeded", 429, body);
12
+ this.name = "RateLimitError";
13
+ }
14
+ }
15
+ class NoRouteError extends VulcxError {
16
+ constructor(body) {
17
+ super("No route found", 404, body);
18
+ this.name = "NoRouteError";
19
+ }
20
+ }
21
+ class BadRequestError extends VulcxError {
22
+ constructor(message, body) {
23
+ super(message, 400, body);
24
+ this.name = "BadRequestError";
25
+ }
26
+ }
27
+ class AuthError extends VulcxError {
28
+ constructor(body) {
29
+ super("Invalid or missing API key", 401, body);
30
+ this.name = "AuthError";
31
+ }
32
+ }
33
+ class ServerError extends VulcxError {
34
+ constructor(message, body) {
35
+ super(message, 500, body);
36
+ this.name = "ServerError";
37
+ }
38
+ }
39
+
40
+ const DEFAULT_BASE_URL = "https://api.vulcx.xyz";
41
+ const DEFAULT_TIMEOUT = 30000;
42
+ const DEFAULT_RETRIES = 2;
43
+ class VulcxSDK {
44
+ constructor(config) {
45
+ if (!config.apiKey)
46
+ throw new Error("apiKey is required");
47
+ this.apiKey = config.apiKey;
48
+ this.chain = config.chain ?? "solana";
49
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
50
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
51
+ this.retries = config.retries ?? DEFAULT_RETRIES;
52
+ }
53
+ async quote(params) {
54
+ const qs = new URLSearchParams({
55
+ inputMint: params.inputMint,
56
+ outputMint: params.outputMint,
57
+ amount: params.amount,
58
+ swapMode: params.swapMode,
59
+ });
60
+ if (params.slippageBps !== undefined) {
61
+ qs.set("slippageBps", String(params.slippageBps));
62
+ }
63
+ return this.request("GET", `/api/v1/quote?${qs}`);
64
+ }
65
+ async swap(params) {
66
+ return this.request("POST", "/api/v1/swap", params);
67
+ }
68
+ async instructions(params) {
69
+ return this.request("POST", "/api/v1/instructions", params);
70
+ }
71
+ async request(method, path, body) {
72
+ const separator = path.includes("?") ? "&" : "?";
73
+ const url = `${this.baseUrl}${path}${separator}chain=${this.chain}`;
74
+ const headers = {
75
+ Authorization: `Bearer ${this.apiKey}`,
76
+ Accept: "application/json",
77
+ };
78
+ if (body) {
79
+ headers["Content-Type"] = "application/json";
80
+ }
81
+ let lastError;
82
+ for (let attempt = 0; attempt <= this.retries; attempt++) {
83
+ if (attempt > 0) {
84
+ await sleep(Math.min(1000 * 2 ** (attempt - 1), 8000));
85
+ }
86
+ try {
87
+ const controller = new AbortController();
88
+ const timer = setTimeout(() => controller.abort(), this.timeout);
89
+ const res = await fetch(url, {
90
+ method,
91
+ headers,
92
+ body: body ? JSON.stringify(body) : undefined,
93
+ signal: controller.signal,
94
+ });
95
+ clearTimeout(timer);
96
+ if (res.ok) {
97
+ const parsed = (await res.json());
98
+ // API responses wrap the payload in {success, data}; hand back the
99
+ // payload the way the method signatures promise.
100
+ if (parsed && typeof parsed === "object" && "success" in parsed) {
101
+ if (!parsed.success) {
102
+ throw new VulcxError(parsed.error ?? "request failed", res.status, parsed);
103
+ }
104
+ return parsed.data;
105
+ }
106
+ return parsed;
107
+ }
108
+ const errBody = await res.json().catch(() => ({}));
109
+ const errMsg = errBody?.error ?? res.statusText;
110
+ switch (res.status) {
111
+ case 401:
112
+ case 403:
113
+ throw new AuthError(errBody);
114
+ case 400:
115
+ throw new BadRequestError(errMsg, errBody);
116
+ case 404:
117
+ throw new NoRouteError(errBody);
118
+ case 429:
119
+ lastError = new RateLimitError(errBody);
120
+ continue;
121
+ default:
122
+ if (res.status >= 500) {
123
+ lastError = new ServerError(errMsg, errBody);
124
+ continue;
125
+ }
126
+ throw new VulcxError(errMsg, res.status, errBody);
127
+ }
128
+ }
129
+ catch (err) {
130
+ if (err instanceof AuthError ||
131
+ err instanceof BadRequestError ||
132
+ err instanceof NoRouteError ||
133
+ err instanceof VulcxError) {
134
+ throw err;
135
+ }
136
+ lastError = err;
137
+ }
138
+ }
139
+ throw lastError ?? new Error("request failed");
140
+ }
141
+ }
142
+ function sleep(ms) {
143
+ return new Promise((r) => setTimeout(r, ms));
144
+ }
145
+
146
+ export { AuthError, BadRequestError, NoRouteError, RateLimitError, ServerError, VulcxError, VulcxSDK };
147
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":[null,null],"names":[],"mappings":"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"}
@@ -0,0 +1,161 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.VulcxSDK = {}));
5
+ })(this, (function (exports) { 'use strict';
6
+
7
+ class VulcxError extends Error {
8
+ constructor(message, statusCode, body) {
9
+ super(message);
10
+ this.statusCode = statusCode;
11
+ this.body = body;
12
+ this.name = "VulcxError";
13
+ }
14
+ }
15
+ class RateLimitError extends VulcxError {
16
+ constructor(body) {
17
+ super("Rate limit exceeded", 429, body);
18
+ this.name = "RateLimitError";
19
+ }
20
+ }
21
+ class NoRouteError extends VulcxError {
22
+ constructor(body) {
23
+ super("No route found", 404, body);
24
+ this.name = "NoRouteError";
25
+ }
26
+ }
27
+ class BadRequestError extends VulcxError {
28
+ constructor(message, body) {
29
+ super(message, 400, body);
30
+ this.name = "BadRequestError";
31
+ }
32
+ }
33
+ class AuthError extends VulcxError {
34
+ constructor(body) {
35
+ super("Invalid or missing API key", 401, body);
36
+ this.name = "AuthError";
37
+ }
38
+ }
39
+ class ServerError extends VulcxError {
40
+ constructor(message, body) {
41
+ super(message, 500, body);
42
+ this.name = "ServerError";
43
+ }
44
+ }
45
+
46
+ const DEFAULT_BASE_URL = "https://api.vulcx.xyz";
47
+ const DEFAULT_TIMEOUT = 30000;
48
+ const DEFAULT_RETRIES = 2;
49
+ class VulcxSDK {
50
+ constructor(config) {
51
+ if (!config.apiKey)
52
+ throw new Error("apiKey is required");
53
+ this.apiKey = config.apiKey;
54
+ this.chain = config.chain ?? "solana";
55
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
56
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
57
+ this.retries = config.retries ?? DEFAULT_RETRIES;
58
+ }
59
+ async quote(params) {
60
+ const qs = new URLSearchParams({
61
+ inputMint: params.inputMint,
62
+ outputMint: params.outputMint,
63
+ amount: params.amount,
64
+ swapMode: params.swapMode,
65
+ });
66
+ if (params.slippageBps !== undefined) {
67
+ qs.set("slippageBps", String(params.slippageBps));
68
+ }
69
+ return this.request("GET", `/api/v1/quote?${qs}`);
70
+ }
71
+ async swap(params) {
72
+ return this.request("POST", "/api/v1/swap", params);
73
+ }
74
+ async instructions(params) {
75
+ return this.request("POST", "/api/v1/instructions", params);
76
+ }
77
+ async request(method, path, body) {
78
+ const separator = path.includes("?") ? "&" : "?";
79
+ const url = `${this.baseUrl}${path}${separator}chain=${this.chain}`;
80
+ const headers = {
81
+ Authorization: `Bearer ${this.apiKey}`,
82
+ Accept: "application/json",
83
+ };
84
+ if (body) {
85
+ headers["Content-Type"] = "application/json";
86
+ }
87
+ let lastError;
88
+ for (let attempt = 0; attempt <= this.retries; attempt++) {
89
+ if (attempt > 0) {
90
+ await sleep(Math.min(1000 * 2 ** (attempt - 1), 8000));
91
+ }
92
+ try {
93
+ const controller = new AbortController();
94
+ const timer = setTimeout(() => controller.abort(), this.timeout);
95
+ const res = await fetch(url, {
96
+ method,
97
+ headers,
98
+ body: body ? JSON.stringify(body) : undefined,
99
+ signal: controller.signal,
100
+ });
101
+ clearTimeout(timer);
102
+ if (res.ok) {
103
+ const parsed = (await res.json());
104
+ // API responses wrap the payload in {success, data}; hand back the
105
+ // payload the way the method signatures promise.
106
+ if (parsed && typeof parsed === "object" && "success" in parsed) {
107
+ if (!parsed.success) {
108
+ throw new VulcxError(parsed.error ?? "request failed", res.status, parsed);
109
+ }
110
+ return parsed.data;
111
+ }
112
+ return parsed;
113
+ }
114
+ const errBody = await res.json().catch(() => ({}));
115
+ const errMsg = errBody?.error ?? res.statusText;
116
+ switch (res.status) {
117
+ case 401:
118
+ case 403:
119
+ throw new AuthError(errBody);
120
+ case 400:
121
+ throw new BadRequestError(errMsg, errBody);
122
+ case 404:
123
+ throw new NoRouteError(errBody);
124
+ case 429:
125
+ lastError = new RateLimitError(errBody);
126
+ continue;
127
+ default:
128
+ if (res.status >= 500) {
129
+ lastError = new ServerError(errMsg, errBody);
130
+ continue;
131
+ }
132
+ throw new VulcxError(errMsg, res.status, errBody);
133
+ }
134
+ }
135
+ catch (err) {
136
+ if (err instanceof AuthError ||
137
+ err instanceof BadRequestError ||
138
+ err instanceof NoRouteError ||
139
+ err instanceof VulcxError) {
140
+ throw err;
141
+ }
142
+ lastError = err;
143
+ }
144
+ }
145
+ throw lastError ?? new Error("request failed");
146
+ }
147
+ }
148
+ function sleep(ms) {
149
+ return new Promise((r) => setTimeout(r, ms));
150
+ }
151
+
152
+ exports.AuthError = AuthError;
153
+ exports.BadRequestError = BadRequestError;
154
+ exports.NoRouteError = NoRouteError;
155
+ exports.RateLimitError = RateLimitError;
156
+ exports.ServerError = ServerError;
157
+ exports.VulcxError = VulcxError;
158
+ exports.VulcxSDK = VulcxSDK;
159
+
160
+ }));
161
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":[null,null],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ export type SwapMode = "ExactIn" | "ExactOut";
2
+ export type Chain = "solana" | "fogo";
3
+ export type PriceImpactSeverity = "none" | "low" | "moderate" | "high" | "extreme";
4
+ export interface SDKConfig {
5
+ apiKey: string;
6
+ chain?: Chain;
7
+ baseUrl?: string;
8
+ timeout?: number;
9
+ retries?: number;
10
+ }
11
+ export interface QuoteRequest {
12
+ inputMint: string;
13
+ outputMint: string;
14
+ amount: string;
15
+ swapMode: SwapMode;
16
+ slippageBps?: number;
17
+ }
18
+ export interface RouteInfo {
19
+ poolAddress: string;
20
+ poolType: string;
21
+ percent: number;
22
+ inputMint: string;
23
+ outputMint: string;
24
+ }
25
+ export interface QuoteResponse {
26
+ inputMint: string;
27
+ outputMint: string;
28
+ amountIn: string;
29
+ amountOut: string;
30
+ priceImpactBps: number;
31
+ priceImpactPercent: string;
32
+ priceImpactSeverity: PriceImpactSeverity;
33
+ priceImpactWarning: string;
34
+ feeBps: number;
35
+ routes: RouteInfo[];
36
+ routePath: string[];
37
+ hopCount: number;
38
+ otherAmountThreshold: string;
39
+ }
40
+ export interface SwapRequest {
41
+ userWallet: string;
42
+ inputMint: string;
43
+ outputMint: string;
44
+ amount: string;
45
+ swapMode: SwapMode;
46
+ slippageBps?: number;
47
+ skipSimulation?: boolean;
48
+ }
49
+ export interface SimulationResult {
50
+ success: boolean;
51
+ computeUnitsConsumed: number;
52
+ computeUnitsTotal: number;
53
+ logs: string[];
54
+ error: string;
55
+ slippageExceeded: boolean;
56
+ insufficientFunds: boolean;
57
+ accountsNeeded: string[];
58
+ }
59
+ export interface SwapResponse {
60
+ transaction: string;
61
+ lastValidBlockHeight: number;
62
+ amountIn: string;
63
+ amountOut: string;
64
+ minAmountOut?: string;
65
+ maxAmountIn?: string;
66
+ feeAmount: string;
67
+ simulation?: SimulationResult;
68
+ computeUnitsEstimate: number;
69
+ route: string[];
70
+ hopCount: number;
71
+ pools: string[];
72
+ isSplitRoute: boolean;
73
+ splitPercents?: number[];
74
+ }
75
+ export interface InstructionsRequest {
76
+ userWallet: string;
77
+ inputMint: string;
78
+ outputMint: string;
79
+ amount: string;
80
+ swapMode: SwapMode;
81
+ slippageBps?: number;
82
+ }
83
+ export interface RawAccountMeta {
84
+ publicKey: string;
85
+ isSigner: boolean;
86
+ isWritable: boolean;
87
+ }
88
+ export interface RawInstruction {
89
+ programId: string;
90
+ accounts: RawAccountMeta[];
91
+ data: string;
92
+ }
93
+ export interface InstructionsResponse {
94
+ instructions: RawInstruction[];
95
+ addressLookupTableAddresses: string[];
96
+ amountIn: string;
97
+ amountOut: string;
98
+ otherAmountThreshold: string;
99
+ feeAmount: string;
100
+ hopCount: number;
101
+ route: string[];
102
+ pools: string[];
103
+ }
104
+ export interface APIErrorBody {
105
+ error: string;
106
+ }
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@vulcx/sdk",
3
+ "version": "0.2.0",
4
+ "description": "TypeScript SDK for the Vulcx DEX aggregator API",
5
+ "main": "dist/index.cjs.js",
6
+ "module": "dist/index.esm.js",
7
+ "browser": "dist/index.umd.js",
8
+ "unpkg": "dist/index.umd.js",
9
+ "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.esm.js",
13
+ "require": "./dist/index.cjs.js",
14
+ "types": "./dist/index.d.ts"
15
+ }
16
+ },
17
+ "type": "module",
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "scripts": {
22
+ "build": "rollup -c",
23
+ "dev": "rollup -c -w",
24
+ "typecheck": "tsc --noEmit"
25
+ },
26
+ "devDependencies": {
27
+ "@rollup/plugin-typescript": "^12.1.2",
28
+ "rollup": "^4.34.8",
29
+ "rollup-plugin-dts": "^6.1.1",
30
+ "tslib": "^2.8.1",
31
+ "typescript": "^5.7.3"
32
+ },
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/argyros-ag/sdk"
37
+ },
38
+ "keywords": [
39
+ "solana",
40
+ "dex",
41
+ "aggregator",
42
+ "swap",
43
+ "fogo",
44
+ "vulcx"
45
+ ]
46
+ }