@riftresearch/sdk 0.4.2 → 0.5.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/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // ../common/src/constants.ts
1
+ // ../common/dist/index.js
2
2
  var CBBTC_ADDRESS = "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf";
3
3
  var CBBTC_ADDRESS_LOWER = CBBTC_ADDRESS.toLowerCase();
4
4
  var BTC_CHAIN = {
@@ -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
  }
@@ -155,17 +106,17 @@ import { match, P } from "ts-pattern";
155
106
  var CBBTC_ADDRESS2 = "0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf";
156
107
  var isBitcoin = (currency) => currency.chain.kind === "BITCOIN";
157
108
  var isCbBtc = (currency) => currency.chain.kind === "EVM" && currency.token.kind === "TOKEN" && currency.token.address.toLowerCase() === CBBTC_ADDRESS2;
158
- var isEvmToken2 = (currency) => currency.chain.kind === "EVM";
159
- var isSameEvmChain2 = (a, b) => a.chain.kind === "EVM" && b.chain.kind === "EVM" && a.chain.chainId === b.chain.chainId;
109
+ var isEvmToken = (currency) => currency.chain.kind === "EVM";
110
+ var isSameEvmChain = (a, b) => a.chain.kind === "EVM" && b.chain.kind === "EVM" && a.chain.chainId === b.chain.chainId;
160
111
  function detectRoute(from, to) {
161
112
  return match({ from, to }).with({ from: P.when(isCbBtc), to: P.when(isBitcoin) }, () => ({
162
113
  type: "direct_rift",
163
114
  direction: "to_btc"
164
- })).with({ from: P.when(isBitcoin), to: P.when(isEvmToken2) }, () => ({
115
+ })).with({ from: P.when(isBitcoin), to: P.when(isEvmToken) }, () => ({
165
116
  type: "direct_rift",
166
117
  direction: "from_btc"
167
118
  })).with({
168
- from: P.when((c) => isEvmToken2(c) && !isCbBtc(c)),
119
+ from: P.when((c) => isEvmToken(c) && !isCbBtc(c)),
169
120
  to: P.when(isBitcoin)
170
121
  }, ({ from: from2 }) => {
171
122
  if (from2.chain.kind !== "EVM") {
@@ -176,8 +127,8 @@ function detectRoute(from, to) {
176
127
  evmChainId: from2.chain.chainId
177
128
  };
178
129
  }).with({
179
- from: P.when(isEvmToken2),
180
- to: P.when((c) => isEvmToken2(c) && isSameEvmChain2(from, to))
130
+ from: P.when(isEvmToken),
131
+ to: P.when((c) => isEvmToken(c) && isSameEvmChain(from, to))
181
132
  }, ({ from: from2 }) => {
182
133
  if (from2.chain.kind !== "EVM") {
183
134
  throw new Error("Expected EVM chain");
@@ -214,9 +165,8 @@ class RiftSdk {
214
165
  integratorName;
215
166
  debug;
216
167
  constructor(options) {
217
- this.riftClient = new SwapRouterClient({
218
- baseUrl: options.apiUrl ?? "https://router-api-v2-production.up.railway.app"
219
- });
168
+ const baseUrl = (options.apiUrl ?? "https://router-api-v2-production.up.railway.app").replace(/\/$/, "");
169
+ this.riftClient = createClient(baseUrl);
220
170
  this.preflightCheckBalances = options.preflight?.checkBalances !== false;
221
171
  this.integratorName = options.integratorName;
222
172
  this.debug = options.debug ?? false;
@@ -230,6 +180,24 @@ class RiftSdk {
230
180
  }
231
181
  console.log(`[RiftSdk] ${message}`);
232
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);
200
+ }
233
201
  async getQuote(params) {
234
202
  const route = detectRoute(params.from, params.to);
235
203
  const isMonochain = route.type === "oneinch_monochain";
@@ -239,12 +207,18 @@ class RiftSdk {
239
207
  to: params.to,
240
208
  amount: params.amount
241
209
  };
242
- const riftQuote = await this.riftClient.quote(quoteRequest);
210
+ const riftQuote = this.unwrapEdenResult(await this.riftClient.quote.post(quoteRequest));
243
211
  const quote = this.buildQuoteResult(riftQuote, params);
244
212
  const isChained = route.type === "direct_rift" && route.direction === "from_btc" && !isCbBtc(params.to);
245
213
  return {
246
214
  quote,
247
- executeSwap: async (context = {}) => {
215
+ executeSwap: async (context) => {
216
+ if (!context?.destinationAddress) {
217
+ throw new Error("destinationAddress is required to execute swap");
218
+ }
219
+ if (params.from.chain.kind === "BITCOIN" && !context.refundAddress) {
220
+ throw new Error("refundAddress is required for BTC swaps (Bitcoin refund address)");
221
+ }
248
222
  this.logDebug("executeSwap called", {
249
223
  route: route.type,
250
224
  mode: params.mode,
@@ -252,20 +226,20 @@ class RiftSdk {
252
226
  to: params.to,
253
227
  amount: params.amount
254
228
  });
255
- const refundAddress = params.refundAddress ?? this.getRefundAddress(params, context);
229
+ const refundAddress = context.refundAddress ?? this.getRefundAddress(params, context);
256
230
  this.logDebug("resolved refund address", { refundAddress });
257
231
  if (this.preflightCheckBalances) {
258
232
  this.logDebug("running preflight balance check");
259
233
  await this.assertSufficientBalance(params.from, quote.from.amount, context);
260
234
  }
261
235
  this.logDebug("creating swap", { quoteId: riftQuote.id });
262
- const swapResponse = await this.riftClient.createSwap({
236
+ const swapResponse = this.unwrapEdenResult(await this.riftClient.swap.post({
263
237
  id: riftQuote.id,
264
- destinationAddress: params.destinationAddress,
238
+ destinationAddress: context.destinationAddress,
265
239
  refundAddress,
266
240
  integratorName: this.integratorName,
267
241
  approvalMode: params.approvalMode
268
- });
242
+ }));
269
243
  this.logDebug("swap created", {
270
244
  swapId: swapResponse.swapId,
271
245
  steps: swapResponse.executionSteps.length
@@ -288,16 +262,16 @@ class RiftSdk {
288
262
  stepId: step.id,
289
263
  oneinchSwap: true
290
264
  });
291
- await this.riftClient.reportStepResult(swapResponse.swapId, {
265
+ this.unwrapEdenResult(await this.riftClient.swap({ swapId: swapResponse.swapId }).tx.post({
292
266
  stepId: step.id,
293
267
  ...result
294
- });
268
+ }));
295
269
  }
296
270
  }
297
271
  this.logDebug("fetching swap status", {
298
272
  swapId: swapResponse.swapId
299
273
  });
300
- const swap = await this.riftClient.getSwap(swapResponse.swapId);
274
+ const swap = this.unwrapEdenResult(await this.riftClient.swap({ swapId: swapResponse.swapId }).get());
301
275
  this.logDebug("swap fetched", {
302
276
  swapId: swapResponse.swapId,
303
277
  status: swap.status
@@ -472,7 +446,7 @@ class RiftSdk {
472
446
  return context.sendBitcoin;
473
447
  }
474
448
  async getSwapStatus(swapId) {
475
- return this.riftClient.getSwap(swapId);
449
+ return this.unwrapEdenResult(await this.riftClient.swap({ swapId }).get());
476
450
  }
477
451
  }
478
452
  function createRiftSdk(options) {
@@ -484,6 +458,7 @@ export {
484
458
  createRiftSdk,
485
459
  createCurrency,
486
460
  createClient,
461
+ SwapRouterApiError,
487
462
  RiftSdk,
488
463
  Currencies
489
464
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riftresearch/sdk",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "SDK for swapping between bitcoin and evm chains",
5
5
  "license": "MIT",
6
6
  "files": [