@riftresearch/sdk 0.2.2 → 0.2.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 CHANGED
@@ -2,19 +2,15 @@
2
2
 
3
3
  SDK for swapping between Bitcoin and EVM chains.
4
4
 
5
- ## Installation
5
+ ## Quickstart
6
+
7
+ Install the SDK:
6
8
 
7
9
  ```bash
8
10
  npm install @riftresearch/sdk
9
- # or
10
- pnpm add @riftresearch/sdk
11
- # or
12
- yarn add @riftresearch/sdk
13
- # or
14
- bun add @riftresearch/sdk
15
11
  ```
16
12
 
17
- ## Quickstart
13
+ Then use it:
18
14
 
19
15
  ```ts
20
16
  import { RiftSdk, BTC, type Currency } from '@riftresearch/sdk'
@@ -46,8 +42,8 @@ const sdk = new RiftSdk({
46
42
  publicClient,
47
43
  walletClient,
48
44
  sendBitcoin: async ({ recipient, amountSats }) => {
49
- // Only needed for BTC -> ERC20 swaps
50
- throw new Error('Not implemented')
45
+ // Implement your Bitcoin wallet connection, e.g.:
46
+ // window.bitcoin.transfer({ recipient, amountSats })
51
47
  },
52
48
  })
53
49
 
@@ -71,13 +67,3 @@ console.log(`Swap ID: ${swap.swapId}`) // API order ID
71
67
  const status = await sdk.getOrderStatus(swap.swapId)
72
68
  console.log(`Status: ${status.status}`)
73
69
  ```
74
-
75
- ## Build & Publish
76
-
77
- The SDK uses **bunup**.
78
-
79
- - Build: `bun run --filter '@riftresearch/sdk' build`
80
- - Publish (from repo root): `bun run publish:sdk`
81
- - Release (version bump + build + publish): `bun run release:sdk`
82
-
83
- The `dist/` directory is what gets published to npm.
package/dist/index.d.ts CHANGED
@@ -412,12 +412,18 @@ interface RiftSdkOptions {
412
412
  sendBitcoin: SendBitcoinFn;
413
413
  /** Rift API URL. Defaults to production API */
414
414
  apiUrl?: string;
415
+ /** Optional preflight checks before executing swaps */
416
+ preflight?: {
417
+ /** Check sender balance before executing EVM steps (default: true) */
418
+ checkBalances?: boolean;
419
+ };
415
420
  }
416
421
  declare class RiftSdk {
417
422
  private riftClient;
418
423
  private publicClient;
419
424
  private walletClient;
420
425
  private sendBitcoinFn;
426
+ private preflightCheckBalances;
421
427
  constructor(options: RiftSdkOptions);
422
428
  /**
423
429
  * Get a quote for a swap and return a function to execute it.
@@ -451,8 +457,11 @@ declare class RiftSdk {
451
457
  private executeBtcTransferStep;
452
458
  private buildQuoteResult;
453
459
  private buildOrderResult;
460
+ private assertSufficientBalance;
454
461
  private getAddress;
455
462
  private getRefundAddress;
463
+ private assertEvmChainMatch;
464
+ private assertEvmChainMatchForSteps;
456
465
  /**
457
466
  * Get the current status of an order by its ID.
458
467
  */
package/dist/index.js CHANGED
@@ -157,6 +157,7 @@ class RiftSdk {
157
157
  publicClient;
158
158
  walletClient;
159
159
  sendBitcoinFn;
160
+ preflightCheckBalances;
160
161
  constructor(options) {
161
162
  this.riftClient = new SwapRouterClient({
162
163
  baseUrl: options.apiUrl ?? "https://router-api-v2-production.up.railway.app"
@@ -164,6 +165,7 @@ class RiftSdk {
164
165
  this.publicClient = options.publicClient;
165
166
  this.walletClient = options.walletClient;
166
167
  this.sendBitcoinFn = options.sendBitcoin;
168
+ this.preflightCheckBalances = options.preflight?.checkBalances !== false;
167
169
  }
168
170
  async getQuote(params) {
169
171
  const route = detectRoute(params.from, params.to);
@@ -181,12 +183,16 @@ class RiftSdk {
181
183
  quote,
182
184
  executeSwap: async () => {
183
185
  const refundAddress = params.refundAddress ?? this.getRefundAddress(params);
186
+ if (this.preflightCheckBalances) {
187
+ await this.assertSufficientBalance(params.from, quote.from.amount);
188
+ }
184
189
  const orderResponse = await this.riftClient.createOrder({
185
190
  id: riftQuote.id,
186
191
  destinationAddress: params.destinationAddress,
187
192
  refundAddress,
188
193
  approvalMode: params.approvalMode
189
194
  });
195
+ this.assertEvmChainMatchForSteps(orderResponse.executionSteps);
190
196
  for (const step of orderResponse.executionSteps) {
191
197
  const result = await this.executeStep(step);
192
198
  if (isMonochain && step.action === "evm_call" && step.kind === "oneinch_swap" && result.txHash) {
@@ -277,6 +283,29 @@ class RiftSdk {
277
283
  rift: swap
278
284
  };
279
285
  }
286
+ async assertSufficientBalance(currency, amount) {
287
+ if (currency.chain.kind !== "EVM")
288
+ return;
289
+ this.assertEvmChainMatch(currency.chain.chainId);
290
+ const required = BigInt(amount);
291
+ const owner = this.getAddress();
292
+ if (currency.token.kind === "NATIVE") {
293
+ const balance2 = await this.publicClient.getBalance({ address: owner });
294
+ if (balance2 < required) {
295
+ throw new Error(`Insufficient balance for native token. Need ${required.toString()}, have ${balance2.toString()}`);
296
+ }
297
+ return;
298
+ }
299
+ const balance = await this.publicClient.readContract({
300
+ address: currency.token.address,
301
+ abi: erc20Abi,
302
+ functionName: "balanceOf",
303
+ args: [owner]
304
+ });
305
+ if (balance < required) {
306
+ throw new Error(`Insufficient balance for token ${currency.token.address}. Need ${required.toString()}, have ${balance.toString()}`);
307
+ }
308
+ }
280
309
  getAddress() {
281
310
  const account = this.walletClient.account;
282
311
  if (!account) {
@@ -290,6 +319,35 @@ class RiftSdk {
290
319
  }
291
320
  return this.getAddress();
292
321
  }
322
+ assertEvmChainMatch(expectedChainId) {
323
+ const walletChainId = this.walletClient.chain?.id;
324
+ if (!walletChainId) {
325
+ throw new Error("Wallet client is missing an EVM chain configuration");
326
+ }
327
+ if (walletChainId !== expectedChainId) {
328
+ throw new Error(`Wallet client chain mismatch. Expected ${expectedChainId}, got ${walletChainId}`);
329
+ }
330
+ const publicChainId = this.publicClient.chain?.id;
331
+ if (!publicChainId) {
332
+ throw new Error("Public client is missing an EVM chain configuration");
333
+ }
334
+ if (publicChainId !== expectedChainId) {
335
+ throw new Error(`Public client chain mismatch. Expected ${expectedChainId}, got ${publicChainId}`);
336
+ }
337
+ }
338
+ assertEvmChainMatchForSteps(steps) {
339
+ const evmSteps = steps.filter((step) => step.action === "evm_call");
340
+ const firstStep = evmSteps[0];
341
+ if (!firstStep)
342
+ return;
343
+ const expectedChainId = firstStep.chainId;
344
+ for (const step of evmSteps) {
345
+ if (step.chainId !== expectedChainId) {
346
+ throw new Error(`Mixed EVM chain IDs in execution steps. Expected ${expectedChainId}, got ${step.chainId}`);
347
+ }
348
+ }
349
+ this.assertEvmChainMatch(expectedChainId);
350
+ }
293
351
  async getOrderStatus(orderId) {
294
352
  return this.riftClient.getOrder(orderId);
295
353
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riftresearch/sdk",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "SDK for swapping between bitcoin and evm chains",
5
5
  "license": "MIT",
6
6
  "files": [