@riftresearch/sdk 0.4.1 → 0.4.3

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/dist/index.d.ts CHANGED
@@ -136,6 +136,9 @@ interface SwapStatusResponse {
136
136
  depositTransaction?: TxHash;
137
137
  quote: QuoteResponse;
138
138
  }
139
+ interface ErrorResponse {
140
+ error: string;
141
+ }
139
142
  /**
140
143
  * Execution actions - the mechanism by which a step is executed.
141
144
  */
@@ -228,11 +231,15 @@ declare const Currencies: {
228
231
  CBBTC: Currency;
229
232
  };
230
233
  };
231
- import { treaty } from "@elysiajs/eden";
232
- import { Elysia } from "elysia";
233
- declare const app: Elysia;
234
+ import { Treaty } from "@elysiajs/eden";
235
+ declare const app: unknown;
234
236
  declare const appTyped: typeof app;
235
237
  type App = typeof appTyped;
238
+ declare class SwapRouterApiError extends Error {
239
+ status: number;
240
+ body: ErrorResponse | undefined;
241
+ constructor(message: string, status: number, body?: ErrorResponse);
242
+ }
236
243
  /**
237
244
  * Create a type-safe API client for the Rift Swap Router.
238
245
  *
@@ -283,7 +290,7 @@ type App = typeof appTyped;
283
290
  * ```
284
291
  */
285
292
  /** Type of the Rift API client */
286
- type RiftClient = ReturnType<typeof treaty<App>>;
293
+ type RiftClient = Treaty.Create<App>;
287
294
  declare function createClient(baseUrl: string): RiftClient;
288
295
  /**
289
296
  * Discriminated union of all possible swap routes.
@@ -430,6 +437,8 @@ type ExecuteSwapContext<chain extends Chain2 | undefined = Chain2 | undefined> =
430
437
  interface RiftSdkOptions {
431
438
  /** Rift API URL. Defaults to production API */
432
439
  apiUrl?: string;
440
+ /** Enable verbose debug logging for swap execution */
441
+ debug?: boolean;
433
442
  /** Optional preflight checks before executing swaps */
434
443
  preflight?: {
435
444
  /** Check sender balance before executing EVM steps (default: true) */
@@ -442,7 +451,10 @@ declare class RiftSdk {
442
451
  private riftClient;
443
452
  private preflightCheckBalances;
444
453
  private integratorName;
454
+ private debug;
445
455
  constructor(options: RiftSdkOptions);
456
+ private logDebug;
457
+ private unwrapEdenResult;
446
458
  /**
447
459
  * Get a quote for a swap and return a function to execute it.
448
460
  *
@@ -493,4 +505,4 @@ declare class RiftSdk {
493
505
  getSwapStatus(swapId: string): Promise<SwapStatusResponse>;
494
506
  }
495
507
  declare function createRiftSdk(options: RiftSdkOptions): RiftSdk;
496
- export { getSupportedModes, detectRoute, createRiftSdk, createCurrency, createClient, TradeParameters, TokenIdentifier, SwapStatus2 as SwapStatus, SwapRoute, SwapResult, SwapResponse, SupportedModes, SendBitcoinFn, RiftSwap, RiftSdkOptions, RiftSdk, RiftClient, QuoteResult, NativeToken, GetQuoteResult, ExecutionStep, ExecutionAction, EvmChain, EvmCallStep, EvmCallKind, Erc20Token, Currency, Currencies, Chain, BtcTransferStep, BtcTransferKind, BitcoinChain, App };
508
+ export { getSupportedModes, detectRoute, createRiftSdk, createCurrency, createClient, TradeParameters, TokenIdentifier, SwapStatus2 as SwapStatus, SwapRouterApiError, SwapRoute, SwapResult, SwapResponse, SupportedModes, SendBitcoinFn, RiftSwap, RiftSdkOptions, RiftSdk, RiftClient, QuoteResult, NativeToken, GetQuoteResult, ExecutionStep, ExecutionAction, EvmChain, EvmCallStep, EvmCallKind, Erc20Token, Currency, Currencies, Chain, BtcTransferStep, BtcTransferKind, BitcoinChain, App };
package/dist/index.js CHANGED
@@ -85,7 +85,9 @@ var Currencies = {
85
85
  }
86
86
  }
87
87
  };
88
- // src/apiClient.ts
88
+ // src/client.ts
89
+ import { treaty } from "@elysiajs/eden";
90
+
89
91
  class SwapRouterApiError extends Error {
90
92
  status;
91
93
  body;
@@ -96,57 +98,6 @@ class SwapRouterApiError extends Error {
96
98
  this.body = body;
97
99
  }
98
100
  }
99
-
100
- class SwapRouterClient {
101
- baseUrl;
102
- fetch;
103
- constructor(options) {
104
- this.baseUrl = options.baseUrl.replace(/\/$/, "");
105
- this.fetch = options.fetch ?? globalThis.fetch;
106
- }
107
- async request(method, path, body) {
108
- const url = `${this.baseUrl}${path}`;
109
- const response = await this.fetch(url, {
110
- method,
111
- headers: body ? { "Content-Type": "application/json" } : undefined,
112
- body: body ? JSON.stringify(body) : undefined
113
- });
114
- const text = await response.text();
115
- let data;
116
- try {
117
- data = JSON.parse(text);
118
- } catch {
119
- if (!response.ok) {
120
- throw new SwapRouterApiError(text || `Request failed with status ${response.status}`, response.status);
121
- }
122
- throw new SwapRouterApiError(`Invalid JSON response: ${text}`, response.status);
123
- }
124
- if (!response.ok) {
125
- throw new SwapRouterApiError(data.error ?? `Request failed with status ${response.status}`, response.status, data);
126
- }
127
- return data;
128
- }
129
- async health() {
130
- return this.request("GET", "/health");
131
- }
132
- async status() {
133
- return this.request("GET", "/status");
134
- }
135
- async quote(request) {
136
- return this.request("POST", "/quote", request);
137
- }
138
- async createSwap(request) {
139
- return this.request("POST", "/swap", request);
140
- }
141
- async getSwap(swapId) {
142
- return this.request("GET", `/swap/${swapId}`);
143
- }
144
- async reportStepResult(swapId, result) {
145
- await this.request("POST", `/swap/${swapId}/tx`, result);
146
- }
147
- }
148
- // src/client.ts
149
- import { treaty } from "@elysiajs/eden";
150
101
  function createClient(baseUrl) {
151
102
  return treaty(baseUrl);
152
103
  }
@@ -212,12 +163,40 @@ class RiftSdk {
212
163
  riftClient;
213
164
  preflightCheckBalances;
214
165
  integratorName;
166
+ debug;
215
167
  constructor(options) {
216
- this.riftClient = new SwapRouterClient({
217
- baseUrl: options.apiUrl ?? "https://router-api-v2-production.up.railway.app"
218
- });
168
+ const baseUrl = (options.apiUrl ?? "https://router-api-v2-production.up.railway.app").replace(/\/$/, "");
169
+ this.riftClient = createClient(baseUrl);
219
170
  this.preflightCheckBalances = options.preflight?.checkBalances !== false;
220
171
  this.integratorName = options.integratorName;
172
+ this.debug = options.debug ?? false;
173
+ }
174
+ logDebug(message, data) {
175
+ if (!this.debug)
176
+ return;
177
+ if (data) {
178
+ console.log(`[RiftSdk] ${message}`, data);
179
+ return;
180
+ }
181
+ console.log(`[RiftSdk] ${message}`);
182
+ }
183
+ unwrapEdenResult(result) {
184
+ if (!result.error) {
185
+ if (result.data === null) {
186
+ throw new SwapRouterApiError(`Request failed with status ${result.status}`, result.status);
187
+ }
188
+ return result.data;
189
+ }
190
+ const error = result.error;
191
+ const status = error.status ?? result.status;
192
+ const value = error.value;
193
+ let message = `Request failed with status ${status}`;
194
+ if (value && typeof value === "object" && "error" in value && typeof value.error === "string") {
195
+ message = value.error;
196
+ } else if (typeof error.message === "string") {
197
+ message = error.message;
198
+ }
199
+ throw new SwapRouterApiError(message, status, value);
221
200
  }
222
201
  async getQuote(params) {
223
202
  const route = detectRoute(params.from, params.to);
@@ -228,34 +207,69 @@ class RiftSdk {
228
207
  to: params.to,
229
208
  amount: params.amount
230
209
  };
231
- const riftQuote = await this.riftClient.quote(quoteRequest);
210
+ const riftQuote = this.unwrapEdenResult(await this.riftClient.quote.post(quoteRequest));
232
211
  const quote = this.buildQuoteResult(riftQuote, params);
233
212
  const isChained = route.type === "direct_rift" && route.direction === "from_btc" && !isCbBtc(params.to);
234
213
  return {
235
214
  quote,
236
215
  executeSwap: async (context = {}) => {
216
+ this.logDebug("executeSwap called", {
217
+ route: route.type,
218
+ mode: params.mode,
219
+ from: params.from,
220
+ to: params.to,
221
+ amount: params.amount
222
+ });
237
223
  const refundAddress = params.refundAddress ?? this.getRefundAddress(params, context);
224
+ this.logDebug("resolved refund address", { refundAddress });
238
225
  if (this.preflightCheckBalances) {
226
+ this.logDebug("running preflight balance check");
239
227
  await this.assertSufficientBalance(params.from, quote.from.amount, context);
240
228
  }
241
- const swapResponse = await this.riftClient.createSwap({
229
+ this.logDebug("creating swap", { quoteId: riftQuote.id });
230
+ const swapResponse = this.unwrapEdenResult(await this.riftClient.swap.post({
242
231
  id: riftQuote.id,
243
232
  destinationAddress: params.destinationAddress,
244
233
  refundAddress,
245
234
  integratorName: this.integratorName,
246
235
  approvalMode: params.approvalMode
236
+ }));
237
+ this.logDebug("swap created", {
238
+ swapId: swapResponse.swapId,
239
+ steps: swapResponse.executionSteps.length
247
240
  });
248
241
  this.assertEvmChainMatchForSteps(swapResponse.executionSteps, context);
249
242
  for (const step of swapResponse.executionSteps) {
243
+ this.logDebug("executing step", {
244
+ stepId: step.id,
245
+ action: step.action,
246
+ kind: "kind" in step ? step.kind : undefined,
247
+ chainId: "chainId" in step ? step.chainId : undefined
248
+ });
250
249
  const result = await this.executeStep(step, context);
250
+ this.logDebug("step completed", {
251
+ stepId: step.id,
252
+ txHash: result.txHash
253
+ });
251
254
  if (isMonochain && step.action === "evm_call" && step.kind === "oneinch_swap" && result.txHash) {
252
- await this.riftClient.reportStepResult(swapResponse.swapId, {
255
+ this.logDebug("reporting step result", {
253
256
  stepId: step.id,
254
- ...result
257
+ oneinchSwap: true
255
258
  });
259
+ this.unwrapEdenResult(await this.riftClient.swap({ swapId: swapResponse.swapId }).tx.post({
260
+ stepId: step.id,
261
+ ...result
262
+ }));
256
263
  }
257
264
  }
258
- const swap = await this.riftClient.getSwap(swapResponse.swapId);
265
+ this.logDebug("fetching swap status", {
266
+ swapId: swapResponse.swapId
267
+ });
268
+ const swap = this.unwrapEdenResult(await this.riftClient.swap({ swapId: swapResponse.swapId }).get());
269
+ this.logDebug("swap fetched", {
270
+ swapId: swapResponse.swapId,
271
+ status: swap.status
272
+ });
259
273
  return this.buildSwapResult(swap, {
260
274
  chained: isChained,
261
275
  riftSwapId: swapResponse.swapId
@@ -426,7 +440,7 @@ class RiftSdk {
426
440
  return context.sendBitcoin;
427
441
  }
428
442
  async getSwapStatus(swapId) {
429
- return this.riftClient.getSwap(swapId);
443
+ return this.unwrapEdenResult(await this.riftClient.swap({ swapId }).get());
430
444
  }
431
445
  }
432
446
  function createRiftSdk(options) {
@@ -438,6 +452,7 @@ export {
438
452
  createRiftSdk,
439
453
  createCurrency,
440
454
  createClient,
455
+ SwapRouterApiError,
441
456
  RiftSdk,
442
457
  Currencies
443
458
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riftresearch/sdk",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "SDK for swapping between bitcoin and evm chains",
5
5
  "license": "MIT",
6
6
  "files": [