@riftresearch/sdk 0.12.2 → 0.13.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
@@ -67,3 +67,37 @@ console.log(`Swap ID: ${swap.swapId}`)
67
67
  const status = await sdk.getSwapStatus(swap.swapId)
68
68
  console.log(`Status: ${status.status}`)
69
69
  ```
70
+
71
+ ## Limit Orders
72
+
73
+ You can place limit orders with a fixed price instead of using a market quote:
74
+
75
+ ```ts
76
+ import { RiftSdk, Currencies } from '@riftresearch/sdk'
77
+ import { createPublicClient, createWalletClient, http } from 'viem'
78
+ import { base } from 'viem/chains'
79
+ import { privateKeyToAccount } from 'viem/accounts'
80
+
81
+ const account = privateKeyToAccount('0x...')
82
+ const publicClient = createPublicClient({ chain: base, transport: http() })
83
+ const walletClient = createWalletClient({ account, chain: base, transport: http() })
84
+
85
+ const sdk = new RiftSdk({ integratorName: 'my-app' })
86
+
87
+ const result = await sdk.createLimitOrder({
88
+ from: Currencies.Base.USDC,
89
+ to: Currencies.Bitcoin.BTC,
90
+ pricing: {
91
+ sellAmount: '1000000', // 1 USDC (6 decimals)
92
+ buyAmount: '2500', // 2500 sats
93
+ },
94
+ destinationAddress: 'bc1q...',
95
+ refundAddress: '0x...',
96
+ walletClient,
97
+ publicClient,
98
+ validUntil: Math.floor(Date.now() / 1000) + 3600, // optional: order expires in 1 hour
99
+ })
100
+
101
+ console.log(`Order ID: ${result.swapId}`)
102
+ console.log(`Status: ${result.status}`)
103
+ ```
package/dist/index.d.ts CHANGED
@@ -417,7 +417,8 @@ type CreateLimitOrderOptions<chain extends Chain2 | undefined = Chain2 | undefin
417
417
  destinationAddress: string;
418
418
  refundAddress?: string;
419
419
  approvalMode?: "full" | "partial";
420
- validForSeconds?: number;
420
+ /** Absolute Unix timestamp in UTC seconds when the limit order expires. Defaults to now + 1 year if not provided. */
421
+ validUntil?: number;
421
422
  };
422
423
  type ExecuteSwapOnExecuteStepCallback = (type: ExecuteSwapStepType) => void | Promise<void>;
423
424
  type ExecuteSwapContext<chain extends Chain2 | undefined = Chain2 | undefined> = {
@@ -483,6 +484,7 @@ declare class RiftSdk {
483
484
  getQuote(params: QuoteParameters): Promise<GetQuoteResult>;
484
485
  createLimitOrder<chain extends Chain3 | undefined = Chain3 | undefined>(options: CreateLimitOrderOptions<chain>): Promise<SwapResult>;
485
486
  private assertPositiveIntegerString;
487
+ private assertValidLimitValidUntil;
486
488
  private executeOrderFlow;
487
489
  /**
488
490
  * Execute a single step from the server's execution steps.
package/dist/index.js CHANGED
@@ -255,6 +255,10 @@ function createClient(baseUrl) {
255
255
  var GAS_LIMIT_MULTIPLIER_NUMERATOR = 3n;
256
256
  var GAS_LIMIT_MULTIPLIER_DENOMINATOR = 2n;
257
257
  var GPV2_SETTLEMENT = "0x9008d19f58aabd9ed0d60971565aa8510560ab41";
258
+ var DEFAULT_LIMIT_VALIDITY_WINDOW_SECONDS = 365 * 24 * 60 * 60;
259
+ var MIN_LIMIT_VALIDITY_LEAD_TIME_SECONDS = 60;
260
+ var MAX_LIMIT_VALIDITY_WINDOW_SECONDS = DEFAULT_LIMIT_VALIDITY_WINDOW_SECONDS;
261
+ var MAX_COW_VALID_TO = 4294967295;
258
262
 
259
263
  class RiftSdk {
260
264
  riftClient;
@@ -369,8 +373,8 @@ class RiftSdk {
369
373
  }
370
374
  this.assertPositiveIntegerString(options.pricing.buyAmount, "pricing.buyAmount");
371
375
  this.assertPositiveIntegerString(options.pricing.sellAmount, "pricing.sellAmount");
372
- if (options.validForSeconds !== undefined && (!Number.isInteger(options.validForSeconds) || options.validForSeconds <= 0)) {
373
- throw new Error("validForSeconds must be a positive integer when provided");
376
+ if (options.validUntil !== undefined) {
377
+ this.assertValidLimitValidUntil(options.validUntil, "validUntil");
374
378
  }
375
379
  let refundAddress;
376
380
  let senderAddress;
@@ -431,7 +435,7 @@ class RiftSdk {
431
435
  destinationAddress: options.destinationAddress,
432
436
  refundAddress,
433
437
  ...options.approvalMode ? { approvalMode: options.approvalMode } : {},
434
- ...typeof options.validForSeconds === "number" ? { validForSeconds: options.validForSeconds } : {},
438
+ ...typeof options.validUntil === "number" ? { validUntil: options.validUntil } : {},
435
439
  integratorName: this.integratorName
436
440
  };
437
441
  this.logDebug("creating limit order", {
@@ -450,6 +454,19 @@ class RiftSdk {
450
454
  throw new Error(`${field} must be greater than zero`);
451
455
  }
452
456
  }
457
+ assertValidLimitValidUntil(validUntil, field) {
458
+ if (!Number.isInteger(validUntil)) {
459
+ throw new Error(`${field} must be an integer when provided`);
460
+ }
461
+ if (validUntil > MAX_COW_VALID_TO) {
462
+ throw new Error(`${field} exceeds the maximum supported Unix timestamp`);
463
+ }
464
+ const nowSeconds = Math.floor(Date.now() / 1000);
465
+ const secondsUntilExpiry = validUntil - nowSeconds;
466
+ if (secondsUntilExpiry < MIN_LIMIT_VALIDITY_LEAD_TIME_SECONDS || secondsUntilExpiry > MAX_LIMIT_VALIDITY_WINDOW_SECONDS) {
467
+ throw new Error(`${field} must be between 60 seconds and 31536000 seconds in the future`);
468
+ }
469
+ }
453
470
  async executeOrderFlow(params) {
454
471
  const swapResponse = await params.createOrder();
455
472
  this.logDebug("order created", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riftresearch/sdk",
3
- "version": "0.12.2",
3
+ "version": "0.13.0",
4
4
  "description": "SDK for swapping between bitcoin and evm chains",
5
5
  "license": "MIT",
6
6
  "files": [