@riftresearch/sdk 0.2.4 → 0.4.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 CHANGED
@@ -13,44 +13,41 @@ npm install @riftresearch/sdk
13
13
  Then use it:
14
14
 
15
15
  ```ts
16
- import { RiftSdk, BTC, type Currency } from '@riftresearch/sdk'
16
+ import { RiftSdk, Currencies, createCurrency } from '@riftresearch/sdk'
17
17
  import { createPublicClient, createWalletClient, http } from 'viem'
18
18
  import { privateKeyToAccount } from 'viem/accounts'
19
- import { base } from 'viem/chains'
19
+ import { ethereum } from 'viem/chains'
20
20
 
21
- // Define USDC on Base
22
- const USDC_BASE: Currency = {
23
- chain: { kind: 'EVM', chainId: 8453 },
24
- token: {
25
- kind: 'TOKEN',
26
- address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
27
- decimals: 6,
28
- },
29
- }
30
21
 
31
22
  // Setup viem clients
32
23
  const account = privateKeyToAccount('0x...')
33
- const publicClient = createPublicClient({ chain: base, transport: http() })
24
+ const publicClient = createPublicClient({ chain: ethereum, transport: http(process.env.ETH_RPC) })
34
25
  const walletClient = createWalletClient({
35
26
  account,
36
- chain: base,
37
- transport: http(),
27
+ chain: ethereum,
28
+ transport: http(process.env.ETH_RPC),
38
29
  })
39
30
 
31
+ // Bitcoin sender implementation
32
+ const sendBitcoin = async ({ recipient, amountSats }) => {
33
+ // Implement your Bitcoin wallet connection, e.g.:
34
+ // window.bitcoin.transfer({ recipient, amountSats })
35
+ }
36
+
40
37
  // Initialize SDK
41
- const sdk = new RiftSdk({
42
- publicClient,
43
- walletClient,
44
- sendBitcoin: async ({ recipient, amountSats }) => {
45
- // Implement your Bitcoin wallet connection, e.g.:
46
- // window.bitcoin.transfer({ recipient, amountSats })
47
- },
38
+ const sdk = new RiftSdk({})
39
+
40
+ // Optionally create a custom ERC-20
41
+ const ethereumPepe = createCurrency({
42
+ chainId: 1,
43
+ address: '0x6982508145454Ce325dDbE47a25d4ec3d2311933',
44
+ decimals: 18,
48
45
  })
49
46
 
50
47
  // Get a quote
51
48
  const { quote, executeSwap } = await sdk.getQuote({
52
- from: USDC_BASE,
53
- to: BTC,
49
+ from: Currencies.Ethereum.USDC,
50
+ to: Currencies.Bitcoin.BTC,
54
51
  amount: '100000000', // 100 USDC (6 decimals)
55
52
  mode: 'exact_input',
56
53
  destinationAddress: 'bc1q...',
@@ -60,10 +57,14 @@ console.log(`Swapping ${quote.from.amount} USDC for ${quote.to.amount} sats`)
60
57
  console.log(`Fees: $${quote.fees.totalUsd.toFixed(2)}`)
61
58
 
62
59
  // Execute the swap
63
- const swap = await executeSwap()
64
- console.log(`Swap ID: ${swap.swapId}`) // API order ID
60
+ const swap = await executeSwap({
61
+ publicClient,
62
+ walletClient,
63
+ sendBitcoin,
64
+ })
65
+ console.log(`Swap ID: ${swap.swapId}`)
65
66
 
66
67
  // Check status
67
- const status = await sdk.getOrderStatus(swap.swapId)
68
+ const status = await sdk.getSwapStatus(swap.swapId)
68
69
  console.log(`Status: ${status.status}`)
69
70
  ```
package/dist/index.d.ts CHANGED
@@ -127,9 +127,10 @@ interface ExactOutputQuoteResponse extends QuoteResponseBase {
127
127
  * Use `mode` to determine which fields are specified vs calculated.
128
128
  */
129
129
  type QuoteResponse = ExactInputQuoteResponse | ExactOutputQuoteResponse;
130
- type OrderStatus = "waiting_for_deposit" | "deposit_confirming" | "initiating_transfer" | "confirming_transfer" | "swap_complete" | "refunding_user" | "failed";
131
- interface OrderStatusResponse {
132
- status: OrderStatus;
130
+ declare const SWAP_STATUSES: readonly ["waiting_for_deposit", "deposit_confirming", "initiating_payout", "confirming_payout", "swap_complete", "refunding_user", "failed"];
131
+ type SwapStatus = (typeof SWAP_STATUSES)[number];
132
+ interface SwapStatusResponse {
133
+ status: SwapStatus;
133
134
  destinationAddress: Address;
134
135
  payoutTransaction?: TxHash;
135
136
  depositTransaction?: TxHash;
@@ -192,22 +193,41 @@ interface BtcTransferStep {
192
193
  */
193
194
  type ExecutionStep = EvmCallStep | BtcTransferStep;
194
195
  /**
195
- * Order response with execution steps that the client must execute.
196
+ * Swap response with execution steps that the client must execute.
196
197
  */
197
- interface OrderResponse {
198
- /** The Rift swap/order ID */
198
+ interface SwapResponse {
199
+ /** The Rift swap ID */
199
200
  swapId: string;
200
201
  /** Normalized quote matching /quote response */
201
202
  quote: QuoteResponse;
202
203
  /** Ordered list of steps the client must execute */
203
204
  executionSteps: ExecutionStep[];
204
205
  }
205
- /** Native BTC on Bitcoin */
206
- declare const BTC: Currency;
207
- /** cbBTC on Ethereum mainnet */
208
- declare const CBBTC_ETHEREUM: Currency;
209
- /** cbBTC on Base */
210
- declare const CBBTC_BASE: Currency;
206
+ /** Create an ERC-20 currency on an EVM chain */
207
+ declare function createCurrency(params: {
208
+ chainId: number;
209
+ address: string;
210
+ decimals: number;
211
+ }): Currency;
212
+ declare const Currencies: {
213
+ Bitcoin: {
214
+ BTC: Currency;
215
+ };
216
+ Ethereum: {
217
+ ETH: Currency;
218
+ WETH: Currency;
219
+ USDC: Currency;
220
+ USDT: Currency;
221
+ CBBTC: Currency;
222
+ WBTC: Currency;
223
+ };
224
+ Base: {
225
+ ETH: Currency;
226
+ WETH: Currency;
227
+ USDC: Currency;
228
+ CBBTC: Currency;
229
+ };
230
+ };
211
231
  import { treaty } from "@elysiajs/eden";
212
232
  import { Elysia } from "elysia";
213
233
  declare const app: Elysia;
@@ -247,19 +267,19 @@ type App = typeof appTyped;
247
267
  * console.log('Quote ID:', quote.id)
248
268
  * console.log('You will receive:', quote.to.amount)
249
269
  *
250
- * // Create an order from the quote
251
- * const { data: order, error: orderError } = await api.order.post({
270
+ * // Create a swap from the quote
271
+ * const { data: swap, error: swapError } = await api.swap.post({
252
272
  * id: quote.id,
253
273
  * destinationAddress: '0x...',
254
274
  * refundAddress: 'bc1q...',
255
275
  * })
256
276
  *
257
- * if (order) {
258
- * console.log('Deposit to:', order.deposit_vault_address)
277
+ * if (swap) {
278
+ * console.log('Deposit to:', swap.deposit_vault_address)
259
279
  * }
260
280
  *
261
- * // Check order status
262
- * const { data: status } = await api.order({ orderId: order.id }).get()
281
+ * // Check swap status
282
+ * const { data: status } = await api.swap({ swapId: swap.id }).get()
263
283
  * ```
264
284
  */
265
285
  /** Type of the Rift API client */
@@ -304,8 +324,9 @@ interface SupportedModes {
304
324
  * - ERC20 → BTC: exact_input only (1inch is exact-input quoting)
305
325
  */
306
326
  declare function getSupportedModes(from: Currency, to: Currency): SupportedModes;
307
- import { PublicClient, WalletClient } from "viem";
308
- type RiftOrder = OrderStatusResponse;
327
+ import { Account, PublicClient, Transport, WalletClient } from "viem";
328
+ import { Chain as Chain2 } from "viem/chains";
329
+ type RiftSwap = SwapStatusResponse;
309
330
  interface TradeParameters {
310
331
  /** The currency to swap from */
311
332
  from: Currency;
@@ -325,11 +346,6 @@ interface TradeParameters {
325
346
  * - "partial": approve only the sell amount
326
347
  */
327
348
  approvalMode?: "full" | "partial";
328
- /**
329
- * Slippage tolerance for the 1inch swap leg, in basis points.
330
- * e.g., 50 = 0.5%, 100 = 1%
331
- */
332
- preswapSlippageBps?: number;
333
349
  }
334
350
  /**
335
351
  * Base fields shared by all quote results.
@@ -369,14 +385,14 @@ interface ExactOutputQuoteResult extends QuoteResultBase {
369
385
  type QuoteResult = ExactInputQuoteResult | ExactOutputQuoteResult;
370
386
  interface GetQuoteResult {
371
387
  quote: QuoteResult;
372
- executeSwap: () => Promise<OrderResult>;
388
+ executeSwap: <chain extends Chain2 | undefined = Chain2 | undefined>(context?: ExecuteSwapContext<chain>) => Promise<SwapResult>;
373
389
  }
374
- interface OrderResult {
390
+ interface SwapResult {
375
391
  swapId: string;
376
392
  status: SwapStatus2;
377
- rift: RiftOrder;
393
+ rift: RiftSwap;
378
394
  }
379
- type SwapStatus2 = OrderStatus;
395
+ type SwapStatus2 = SwapStatus;
380
396
  /**
381
397
  * Function type for sending Bitcoin.
382
398
  * Implementers provide this function to handle BTC transactions in their app.
@@ -403,13 +419,15 @@ type SendBitcoinFn = (params: {
403
419
  /** Amount to send in satoshis */
404
420
  amountSats: string;
405
421
  }) => Promise<void>;
406
- interface RiftSdkOptions {
422
+ type ExecuteSwapContext<chain extends Chain2 | undefined = Chain2 | undefined> = {
407
423
  /** Viem PublicClient for reading chain data */
408
- publicClient: PublicClient;
424
+ publicClient?: PublicClient<Transport, chain>;
409
425
  /** Viem WalletClient for signing and sending transactions */
410
- walletClient: WalletClient;
426
+ walletClient?: WalletClient<Transport, chain, Account | undefined>;
411
427
  /** Function to send Bitcoin (implement using your preferred wallet) */
412
- sendBitcoin: SendBitcoinFn;
428
+ sendBitcoin?: SendBitcoinFn;
429
+ };
430
+ interface RiftSdkOptions {
413
431
  /** Rift API URL. Defaults to production API */
414
432
  apiUrl?: string;
415
433
  /** Optional preflight checks before executing swaps */
@@ -417,28 +435,32 @@ interface RiftSdkOptions {
417
435
  /** Check sender balance before executing EVM steps (default: true) */
418
436
  checkBalances?: boolean;
419
437
  };
438
+ /** Name of the integrator using the SDK */
439
+ integratorName: string;
420
440
  }
421
441
  declare class RiftSdk {
422
442
  private riftClient;
423
- private publicClient;
424
- private walletClient;
425
- private sendBitcoinFn;
426
443
  private preflightCheckBalances;
444
+ private integratorName;
427
445
  constructor(options: RiftSdkOptions);
428
446
  /**
429
447
  * Get a quote for a swap and return a function to execute it.
430
448
  *
431
449
  * @example
432
450
  * const { quote, executeSwap } = await sdk.getQuote({
433
- * from: CBBTC_BASE,
434
- * to: BTC,
451
+ * from: Currencies.Base.CBBTC,
452
+ * to: Currencies.Bitcoin.BTC,
435
453
  * amount: '100000000', // 1 cbBTC
436
454
  * mode: 'exact_input',
437
455
  * destinationAddress: 'bc1q...',
438
456
  * })
439
457
  *
440
458
  * console.log(`You'll receive: ${quote.to.amount} sats`)
441
- * const swap = await executeSwap()
459
+ * const swap = await executeSwap({
460
+ * publicClient,
461
+ * walletClient,
462
+ * sendBitcoin,
463
+ * })
442
464
  */
443
465
  getQuote(params: TradeParameters): Promise<GetQuoteResult>;
444
466
  /**
@@ -456,15 +478,19 @@ declare class RiftSdk {
456
478
  */
457
479
  private executeBtcTransferStep;
458
480
  private buildQuoteResult;
459
- private buildOrderResult;
481
+ private buildSwapResult;
460
482
  private assertSufficientBalance;
461
483
  private getAddress;
462
484
  private getRefundAddress;
463
485
  private assertEvmChainMatch;
464
486
  private assertEvmChainMatchForSteps;
487
+ private requirePublicClient;
488
+ private requireWalletClient;
489
+ private requireSendBitcoin;
465
490
  /**
466
- * Get the current status of an order by its ID.
491
+ * Get the current status of a swap by its ID.
467
492
  */
468
- getOrderStatus(orderId: string): Promise<OrderStatusResponse>;
493
+ getSwapStatus(swapId: string): Promise<SwapStatusResponse>;
469
494
  }
470
- export { getSupportedModes, detectRoute, createClient, TradeParameters, TokenIdentifier, SwapStatus2 as SwapStatus, SwapRoute, SupportedModes, SendBitcoinFn, RiftSdkOptions, RiftSdk, RiftOrder, RiftClient, QuoteResult, OrderResult, OrderResponse, NativeToken, GetQuoteResult, ExecutionStep, ExecutionAction, EvmChain, EvmCallStep, EvmCallKind, Erc20Token, Currency, Chain, CBBTC_ETHEREUM, CBBTC_BASE, BtcTransferStep, BtcTransferKind, BitcoinChain, BTC, App };
495
+ 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 };
package/dist/index.js CHANGED
@@ -17,17 +17,73 @@ var CBBTC_TOKEN = {
17
17
  address: CBBTC_ADDRESS,
18
18
  decimals: 8
19
19
  };
20
- var BTC = {
21
- chain: BTC_CHAIN,
22
- token: { kind: "NATIVE", decimals: 8 }
23
- };
24
- var CBBTC_ETHEREUM = {
25
- chain: ETH_CHAIN,
26
- token: CBBTC_TOKEN
27
- };
28
- var CBBTC_BASE = {
29
- chain: BASE_CHAIN,
30
- token: CBBTC_TOKEN
20
+ function createCurrency(params) {
21
+ return {
22
+ chain: { kind: "EVM", chainId: params.chainId },
23
+ token: {
24
+ kind: "TOKEN",
25
+ address: params.address,
26
+ decimals: params.decimals
27
+ }
28
+ };
29
+ }
30
+ var Currencies = {
31
+ Bitcoin: {
32
+ BTC: {
33
+ chain: BTC_CHAIN,
34
+ token: { kind: "NATIVE", decimals: 8 }
35
+ }
36
+ },
37
+ Ethereum: {
38
+ ETH: {
39
+ chain: ETH_CHAIN,
40
+ token: { kind: "NATIVE", decimals: 18 }
41
+ },
42
+ WETH: createCurrency({
43
+ chainId: 1,
44
+ address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
45
+ decimals: 18
46
+ }),
47
+ USDC: createCurrency({
48
+ chainId: 1,
49
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
50
+ decimals: 6
51
+ }),
52
+ USDT: createCurrency({
53
+ chainId: 1,
54
+ address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
55
+ decimals: 6
56
+ }),
57
+ CBBTC: {
58
+ chain: ETH_CHAIN,
59
+ token: CBBTC_TOKEN
60
+ },
61
+ WBTC: createCurrency({
62
+ chainId: 1,
63
+ address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
64
+ decimals: 8
65
+ })
66
+ },
67
+ Base: {
68
+ ETH: {
69
+ chain: BASE_CHAIN,
70
+ token: { kind: "NATIVE", decimals: 18 }
71
+ },
72
+ WETH: createCurrency({
73
+ chainId: 8453,
74
+ address: "0x4200000000000000000000000000000000000006",
75
+ decimals: 18
76
+ }),
77
+ USDC: createCurrency({
78
+ chainId: 8453,
79
+ address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
80
+ decimals: 6
81
+ }),
82
+ CBBTC: {
83
+ chain: BASE_CHAIN,
84
+ token: CBBTC_TOKEN
85
+ }
86
+ }
31
87
  };
32
88
  // src/apiClient.ts
33
89
  class SwapRouterApiError extends Error {
@@ -79,14 +135,14 @@ class SwapRouterClient {
79
135
  async quote(request) {
80
136
  return this.request("POST", "/quote", request);
81
137
  }
82
- async createOrder(request) {
83
- return this.request("POST", "/order", request);
138
+ async createSwap(request) {
139
+ return this.request("POST", "/swap", request);
84
140
  }
85
- async getOrder(orderId) {
86
- return this.request("GET", `/order/${orderId}`);
141
+ async getSwap(swapId) {
142
+ return this.request("GET", `/swap/${swapId}`);
87
143
  }
88
- async reportStepResult(orderId, result) {
89
- await this.request("POST", `/order/${orderId}/tx`, result);
144
+ async reportStepResult(swapId, result) {
145
+ await this.request("POST", `/swap/${swapId}/tx`, result);
90
146
  }
91
147
  }
92
148
  // src/client.ts
@@ -154,18 +210,14 @@ function getSupportedModes(from, to) {
154
210
  import { erc20Abi } from "viem";
155
211
  class RiftSdk {
156
212
  riftClient;
157
- publicClient;
158
- walletClient;
159
- sendBitcoinFn;
160
213
  preflightCheckBalances;
214
+ integratorName;
161
215
  constructor(options) {
162
216
  this.riftClient = new SwapRouterClient({
163
217
  baseUrl: options.apiUrl ?? "https://router-api-v2-production.up.railway.app"
164
218
  });
165
- this.publicClient = options.publicClient;
166
- this.walletClient = options.walletClient;
167
- this.sendBitcoinFn = options.sendBitcoin;
168
219
  this.preflightCheckBalances = options.preflight?.checkBalances !== false;
220
+ this.integratorName = options.integratorName;
169
221
  }
170
222
  async getQuote(params) {
171
223
  const route = detectRoute(params.from, params.to);
@@ -181,50 +233,53 @@ class RiftSdk {
181
233
  const isChained = route.type === "direct_rift" && route.direction === "from_btc" && !isCbBtc(params.to);
182
234
  return {
183
235
  quote,
184
- executeSwap: async () => {
185
- const refundAddress = params.refundAddress ?? this.getRefundAddress(params);
236
+ executeSwap: async (context = {}) => {
237
+ const refundAddress = params.refundAddress ?? this.getRefundAddress(params, context);
186
238
  if (this.preflightCheckBalances) {
187
- await this.assertSufficientBalance(params.from, quote.from.amount);
239
+ await this.assertSufficientBalance(params.from, quote.from.amount, context);
188
240
  }
189
- const orderResponse = await this.riftClient.createOrder({
241
+ const swapResponse = await this.riftClient.createSwap({
190
242
  id: riftQuote.id,
191
243
  destinationAddress: params.destinationAddress,
192
244
  refundAddress,
245
+ integratorName: this.integratorName,
193
246
  approvalMode: params.approvalMode
194
247
  });
195
- this.assertEvmChainMatchForSteps(orderResponse.executionSteps);
196
- for (const step of orderResponse.executionSteps) {
197
- const result = await this.executeStep(step);
248
+ this.assertEvmChainMatchForSteps(swapResponse.executionSteps, context);
249
+ for (const step of swapResponse.executionSteps) {
250
+ const result = await this.executeStep(step, context);
198
251
  if (isMonochain && step.action === "evm_call" && step.kind === "oneinch_swap" && result.txHash) {
199
- await this.riftClient.reportStepResult(orderResponse.swapId, {
252
+ await this.riftClient.reportStepResult(swapResponse.swapId, {
200
253
  stepId: step.id,
201
254
  ...result
202
255
  });
203
256
  }
204
257
  }
205
- const swap = await this.riftClient.getOrder(orderResponse.swapId);
206
- return this.buildOrderResult(swap, {
258
+ const swap = await this.riftClient.getSwap(swapResponse.swapId);
259
+ return this.buildSwapResult(swap, {
207
260
  chained: isChained,
208
- riftOrderId: orderResponse.swapId
261
+ riftSwapId: swapResponse.swapId
209
262
  });
210
263
  }
211
264
  };
212
265
  }
213
- async executeStep(step) {
266
+ async executeStep(step, context) {
214
267
  switch (step.action) {
215
268
  case "evm_call":
216
- return this.executeEvmCallStep(step);
269
+ return this.executeEvmCallStep(step, context);
217
270
  case "btc_transfer":
218
- return this.executeBtcTransferStep(step);
271
+ return this.executeBtcTransferStep(step, context);
219
272
  }
220
273
  }
221
- async executeEvmCallStep(step) {
222
- const account = this.walletClient.account;
274
+ async executeEvmCallStep(step, context) {
275
+ const walletClient = this.requireWalletClient(context);
276
+ const publicClient = this.requirePublicClient(context);
277
+ const account = walletClient.account;
223
278
  if (!account) {
224
279
  throw new Error("No account configured on wallet client");
225
280
  }
226
281
  if (step.kind === "approval" && step.tokenAddress && step.spenderAddress && step.amount) {
227
- const allowance = await this.publicClient.readContract({
282
+ const allowance = await publicClient.readContract({
228
283
  address: step.tokenAddress,
229
284
  abi: erc20Abi,
230
285
  functionName: "allowance",
@@ -234,18 +289,18 @@ class RiftSdk {
234
289
  return {};
235
290
  }
236
291
  }
237
- const txHash = await this.walletClient.sendTransaction({
292
+ const txHash = await walletClient.sendTransaction({
238
293
  account,
239
294
  to: step.to,
240
295
  data: step.calldata,
241
- value: step.value ? BigInt(step.value) : undefined,
242
- chain: this.walletClient.chain
296
+ value: step.value ? BigInt(step.value) : undefined
243
297
  });
244
- await this.publicClient.waitForTransactionReceipt({ hash: txHash });
298
+ await publicClient.waitForTransactionReceipt({ hash: txHash });
245
299
  return { txHash };
246
300
  }
247
- async executeBtcTransferStep(step) {
248
- await this.sendBitcoinFn({
301
+ async executeBtcTransferStep(step, context) {
302
+ const sendBitcoin = this.requireSendBitcoin(context);
303
+ await sendBitcoin({
249
304
  recipient: step.toAddress,
250
305
  amountSats: step.amountSats
251
306
  });
@@ -272,31 +327,32 @@ class RiftSdk {
272
327
  };
273
328
  }
274
329
  }
275
- buildOrderResult(swap, options) {
276
- const riftOrderId = options?.riftOrderId;
277
- if (!riftOrderId) {
278
- throw new Error("Missing rift order id for order result.");
330
+ buildSwapResult(swap, options) {
331
+ const riftSwapId = options?.riftSwapId;
332
+ if (!riftSwapId) {
333
+ throw new Error("Missing rift swap id for swap result.");
279
334
  }
280
335
  return {
281
- swapId: riftOrderId,
336
+ swapId: riftSwapId,
282
337
  status: swap.status,
283
338
  rift: swap
284
339
  };
285
340
  }
286
- async assertSufficientBalance(currency, amount) {
341
+ async assertSufficientBalance(currency, amount, context) {
287
342
  if (currency.chain.kind !== "EVM")
288
343
  return;
289
- this.assertEvmChainMatch(currency.chain.chainId);
344
+ this.assertEvmChainMatch(currency.chain.chainId, context);
290
345
  const required = BigInt(amount);
291
- const owner = this.getAddress();
346
+ const owner = this.getAddress(context);
347
+ const publicClient = this.requirePublicClient(context);
292
348
  if (currency.token.kind === "NATIVE") {
293
- const balance2 = await this.publicClient.getBalance({ address: owner });
349
+ const balance2 = await publicClient.getBalance({ address: owner });
294
350
  if (balance2 < required) {
295
351
  throw new Error(`Insufficient balance for native token. Need ${required.toString()}, have ${balance2.toString()}`);
296
352
  }
297
353
  return;
298
354
  }
299
- const balance = await this.publicClient.readContract({
355
+ const balance = await publicClient.readContract({
300
356
  address: currency.token.address,
301
357
  abi: erc20Abi,
302
358
  functionName: "balanceOf",
@@ -306,28 +362,31 @@ class RiftSdk {
306
362
  throw new Error(`Insufficient balance for token ${currency.token.address}. Need ${required.toString()}, have ${balance.toString()}`);
307
363
  }
308
364
  }
309
- getAddress() {
310
- const account = this.walletClient.account;
365
+ getAddress(context) {
366
+ const walletClient = this.requireWalletClient(context);
367
+ const account = walletClient.account;
311
368
  if (!account) {
312
369
  throw new Error("No account configured on wallet client");
313
370
  }
314
371
  return account.address;
315
372
  }
316
- getRefundAddress(params) {
373
+ getRefundAddress(params, context) {
317
374
  if (params.from.chain.kind === "BITCOIN") {
318
375
  throw new Error("refundAddress is required for BTC swaps (Bitcoin refund address)");
319
376
  }
320
- return this.getAddress();
377
+ return this.getAddress(context);
321
378
  }
322
- assertEvmChainMatch(expectedChainId) {
323
- const walletChainId = this.walletClient.chain?.id;
379
+ assertEvmChainMatch(expectedChainId, context) {
380
+ const walletClient = this.requireWalletClient(context);
381
+ const publicClient = this.requirePublicClient(context);
382
+ const walletChainId = walletClient.chain?.id;
324
383
  if (!walletChainId) {
325
384
  throw new Error("Wallet client is missing an EVM chain configuration");
326
385
  }
327
386
  if (walletChainId !== expectedChainId) {
328
387
  throw new Error(`Wallet client chain mismatch. Expected ${expectedChainId}, got ${walletChainId}`);
329
388
  }
330
- const publicChainId = this.publicClient.chain?.id;
389
+ const publicChainId = publicClient.chain?.id;
331
390
  if (!publicChainId) {
332
391
  throw new Error("Public client is missing an EVM chain configuration");
333
392
  }
@@ -335,7 +394,7 @@ class RiftSdk {
335
394
  throw new Error(`Public client chain mismatch. Expected ${expectedChainId}, got ${publicChainId}`);
336
395
  }
337
396
  }
338
- assertEvmChainMatchForSteps(steps) {
397
+ assertEvmChainMatchForSteps(steps, context) {
339
398
  const evmSteps = steps.filter((step) => step.action === "evm_call");
340
399
  const firstStep = evmSteps[0];
341
400
  if (!firstStep)
@@ -346,18 +405,39 @@ class RiftSdk {
346
405
  throw new Error(`Mixed EVM chain IDs in execution steps. Expected ${expectedChainId}, got ${step.chainId}`);
347
406
  }
348
407
  }
349
- this.assertEvmChainMatch(expectedChainId);
408
+ this.assertEvmChainMatch(expectedChainId, context);
350
409
  }
351
- async getOrderStatus(orderId) {
352
- return this.riftClient.getOrder(orderId);
410
+ requirePublicClient(context) {
411
+ if (!context.publicClient) {
412
+ throw new Error("publicClient is required to execute EVM steps");
413
+ }
414
+ return context.publicClient;
415
+ }
416
+ requireWalletClient(context) {
417
+ if (!context.walletClient) {
418
+ throw new Error("walletClient is required to execute EVM steps");
419
+ }
420
+ return context.walletClient;
353
421
  }
422
+ requireSendBitcoin(context) {
423
+ if (!context.sendBitcoin) {
424
+ throw new Error("sendBitcoin is required to execute BTC transfers");
425
+ }
426
+ return context.sendBitcoin;
427
+ }
428
+ async getSwapStatus(swapId) {
429
+ return this.riftClient.getSwap(swapId);
430
+ }
431
+ }
432
+ function createRiftSdk(options) {
433
+ return new RiftSdk(options);
354
434
  }
355
435
  export {
356
436
  getSupportedModes,
357
437
  detectRoute,
438
+ createRiftSdk,
439
+ createCurrency,
358
440
  createClient,
359
441
  RiftSdk,
360
- CBBTC_ETHEREUM,
361
- CBBTC_BASE,
362
- BTC
442
+ Currencies
363
443
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riftresearch/sdk",
3
- "version": "0.2.4",
3
+ "version": "0.4.0",
4
4
  "description": "SDK for swapping between bitcoin and evm chains",
5
5
  "license": "MIT",
6
6
  "files": [