@riftresearch/sdk 0.1.1

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 ADDED
@@ -0,0 +1,1390 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
19
+
20
+ // node_modules/@cowprotocol/sdk-common/dist/index.js
21
+ var require_dist = __commonJS((exports, module) => {
22
+ var __defProp2 = Object.defineProperty;
23
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
24
+ var __getOwnPropNames2 = Object.getOwnPropertyNames;
25
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
26
+ var __export = (target, all) => {
27
+ for (var name in all)
28
+ __defProp2(target, name, { get: all[name], enumerable: true });
29
+ };
30
+ var __copyProps = (to, from, except, desc) => {
31
+ if (from && typeof from === "object" || typeof from === "function") {
32
+ for (let key of __getOwnPropNames2(from))
33
+ if (!__hasOwnProp2.call(to, key) && key !== except)
34
+ __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
35
+ }
36
+ return to;
37
+ };
38
+ var __toCommonJS = (mod) => __copyProps(__defProp2({}, "__esModule", { value: true }), mod);
39
+ var src_exports = {};
40
+ __export(src_exports, {
41
+ AbstractProviderAdapter: () => AbstractProviderAdapter,
42
+ AbstractSigner: () => AbstractSigner,
43
+ AdapterContext: () => AdapterContext,
44
+ AdapterUtils: () => AdapterUtils,
45
+ ContractFactory: () => ContractFactory,
46
+ CowError: () => CowError,
47
+ ERC20_ALLOWANCE_ABI: () => ERC20_ALLOWANCE_ABI,
48
+ ERC20_APPROVE_ABI: () => ERC20_APPROVE_ABI,
49
+ EthFlowAbi: () => EthFlowAbi,
50
+ GPV2SettlementAbi: () => GPV2SettlementAbi,
51
+ MAX_UINT256: () => MAX_UINT256,
52
+ MAX_UINT32: () => MAX_UINT32,
53
+ ONE: () => ONE,
54
+ TTLCache: () => TTLCache,
55
+ ZERO: () => ZERO,
56
+ ZERO_ADDRESS: () => ZERO_ADDRESS,
57
+ ZERO_HASH: () => ZERO_HASH,
58
+ applyPercentage: () => applyPercentage,
59
+ bpsToPercentage: () => bpsToPercentage,
60
+ enableLogging: () => enableLogging,
61
+ getGlobalAdapter: () => getGlobalAdapter,
62
+ isValidPrivateKey: () => isValidPrivateKey,
63
+ jsonWithBigintReplacer: () => jsonWithBigintReplacer,
64
+ log: () => log,
65
+ normalizePrivateKey: () => normalizePrivateKey,
66
+ percentageToBps: () => percentageToBps,
67
+ setGlobalAdapter: () => setGlobalAdapter
68
+ });
69
+ module.exports = __toCommonJS(src_exports);
70
+ var AbstractProviderAdapter = class {
71
+ ZERO_ADDRESS;
72
+ };
73
+ var AdapterUtils = class {
74
+ };
75
+ var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
76
+ var EthFlowAbi = [
77
+ {
78
+ inputs: [
79
+ {
80
+ components: [
81
+ {
82
+ internalType: "contract IERC20",
83
+ name: "buyToken",
84
+ type: "address"
85
+ },
86
+ {
87
+ internalType: "address",
88
+ name: "receiver",
89
+ type: "address"
90
+ },
91
+ {
92
+ internalType: "uint256",
93
+ name: "sellAmount",
94
+ type: "uint256"
95
+ },
96
+ {
97
+ internalType: "uint256",
98
+ name: "buyAmount",
99
+ type: "uint256"
100
+ },
101
+ {
102
+ internalType: "bytes32",
103
+ name: "appData",
104
+ type: "bytes32"
105
+ },
106
+ {
107
+ internalType: "uint256",
108
+ name: "feeAmount",
109
+ type: "uint256"
110
+ },
111
+ {
112
+ internalType: "uint32",
113
+ name: "validTo",
114
+ type: "uint32"
115
+ },
116
+ {
117
+ internalType: "bool",
118
+ name: "partiallyFillable",
119
+ type: "bool"
120
+ },
121
+ {
122
+ internalType: "int64",
123
+ name: "quoteId",
124
+ type: "int64"
125
+ }
126
+ ],
127
+ internalType: "struct EthFlowOrder.Data",
128
+ name: "order",
129
+ type: "tuple"
130
+ }
131
+ ],
132
+ name: "createOrder",
133
+ outputs: [
134
+ {
135
+ internalType: "bytes32",
136
+ name: "orderHash",
137
+ type: "bytes32"
138
+ }
139
+ ],
140
+ stateMutability: "payable",
141
+ type: "function"
142
+ },
143
+ {
144
+ inputs: [
145
+ {
146
+ components: [
147
+ {
148
+ internalType: "contract IERC20",
149
+ name: "buyToken",
150
+ type: "address"
151
+ },
152
+ {
153
+ internalType: "address",
154
+ name: "receiver",
155
+ type: "address"
156
+ },
157
+ {
158
+ internalType: "uint256",
159
+ name: "sellAmount",
160
+ type: "uint256"
161
+ },
162
+ {
163
+ internalType: "uint256",
164
+ name: "buyAmount",
165
+ type: "uint256"
166
+ },
167
+ {
168
+ internalType: "bytes32",
169
+ name: "appData",
170
+ type: "bytes32"
171
+ },
172
+ {
173
+ internalType: "uint256",
174
+ name: "feeAmount",
175
+ type: "uint256"
176
+ },
177
+ {
178
+ internalType: "uint32",
179
+ name: "validTo",
180
+ type: "uint32"
181
+ },
182
+ {
183
+ internalType: "bool",
184
+ name: "partiallyFillable",
185
+ type: "bool"
186
+ },
187
+ {
188
+ internalType: "int64",
189
+ name: "quoteId",
190
+ type: "int64"
191
+ }
192
+ ],
193
+ internalType: "struct EthFlowOrder.Data",
194
+ name: "order",
195
+ type: "tuple"
196
+ }
197
+ ],
198
+ name: "invalidateOrder",
199
+ outputs: [],
200
+ stateMutability: "nonpayable",
201
+ type: "function"
202
+ },
203
+ {
204
+ inputs: [
205
+ {
206
+ internalType: "bytes32",
207
+ name: "",
208
+ type: "bytes32"
209
+ }
210
+ ],
211
+ name: "orders",
212
+ outputs: [
213
+ {
214
+ internalType: "address",
215
+ name: "owner",
216
+ type: "address"
217
+ },
218
+ {
219
+ internalType: "uint32",
220
+ name: "validTo",
221
+ type: "uint32"
222
+ }
223
+ ],
224
+ stateMutability: "view",
225
+ type: "function"
226
+ }
227
+ ];
228
+ var GPV2SettlementAbi = [
229
+ {
230
+ anonymous: false,
231
+ inputs: [
232
+ {
233
+ indexed: true,
234
+ internalType: "address",
235
+ name: "owner",
236
+ type: "address"
237
+ },
238
+ {
239
+ indexed: false,
240
+ internalType: "contract IERC20",
241
+ name: "sellToken",
242
+ type: "address"
243
+ },
244
+ {
245
+ indexed: false,
246
+ internalType: "contract IERC20",
247
+ name: "buyToken",
248
+ type: "address"
249
+ },
250
+ {
251
+ indexed: false,
252
+ internalType: "uint256",
253
+ name: "sellAmount",
254
+ type: "uint256"
255
+ },
256
+ {
257
+ indexed: false,
258
+ internalType: "uint256",
259
+ name: "buyAmount",
260
+ type: "uint256"
261
+ },
262
+ {
263
+ indexed: false,
264
+ internalType: "uint256",
265
+ name: "feeAmount",
266
+ type: "uint256"
267
+ },
268
+ {
269
+ indexed: false,
270
+ internalType: "bytes",
271
+ name: "orderUid",
272
+ type: "bytes"
273
+ }
274
+ ],
275
+ name: "Trade",
276
+ type: "event"
277
+ },
278
+ {
279
+ inputs: [
280
+ {
281
+ internalType: "bytes",
282
+ name: "orderUid",
283
+ type: "bytes"
284
+ },
285
+ {
286
+ internalType: "bool",
287
+ name: "signed",
288
+ type: "bool"
289
+ }
290
+ ],
291
+ name: "setPreSignature",
292
+ outputs: [],
293
+ stateMutability: "nonpayable",
294
+ type: "function"
295
+ },
296
+ {
297
+ inputs: [
298
+ {
299
+ internalType: "bytes",
300
+ name: "orderUid",
301
+ type: "bytes"
302
+ }
303
+ ],
304
+ name: "invalidateOrder",
305
+ outputs: [],
306
+ stateMutability: "nonpayable",
307
+ type: "function"
308
+ },
309
+ {
310
+ inputs: [],
311
+ name: "domainSeparator",
312
+ outputs: [{ name: "", type: "bytes32" }],
313
+ stateMutability: "nonpayable",
314
+ type: "function"
315
+ }
316
+ ];
317
+ var ERC20_APPROVE_ABI = [
318
+ {
319
+ constant: false,
320
+ inputs: [
321
+ {
322
+ name: "_spender",
323
+ type: "address"
324
+ },
325
+ {
326
+ name: "_value",
327
+ type: "uint256"
328
+ }
329
+ ],
330
+ name: "approve",
331
+ outputs: [
332
+ {
333
+ name: "",
334
+ type: "bool"
335
+ }
336
+ ],
337
+ payable: false,
338
+ stateMutability: "nonpayable",
339
+ type: "function"
340
+ }
341
+ ];
342
+ var ERC20_ALLOWANCE_ABI = [
343
+ {
344
+ constant: true,
345
+ inputs: [
346
+ {
347
+ name: "_owner",
348
+ type: "address"
349
+ },
350
+ {
351
+ name: "_spender",
352
+ type: "address"
353
+ }
354
+ ],
355
+ name: "allowance",
356
+ outputs: [
357
+ {
358
+ name: "",
359
+ type: "uint256"
360
+ }
361
+ ],
362
+ payable: false,
363
+ stateMutability: "view",
364
+ type: "function"
365
+ }
366
+ ];
367
+ var AdapterContext = class _AdapterContext {
368
+ static _instance;
369
+ _adapter;
370
+ constructor() {}
371
+ static getInstance() {
372
+ if (!_AdapterContext._instance) {
373
+ _AdapterContext._instance = new _AdapterContext;
374
+ }
375
+ return _AdapterContext._instance;
376
+ }
377
+ setAdapter(adapter) {
378
+ this._adapter = adapter;
379
+ }
380
+ getAdapter() {
381
+ if (!this._adapter) {
382
+ throw new Error("Provider adapter is not configurated. Configure with CowSdk or using AdapterContext.getInstance().setAdapter()");
383
+ }
384
+ return this._adapter;
385
+ }
386
+ };
387
+ function getGlobalAdapter() {
388
+ return AdapterContext.getInstance().getAdapter();
389
+ }
390
+ function setGlobalAdapter(adapter) {
391
+ const instance = AdapterContext.getInstance();
392
+ instance.setAdapter(adapter);
393
+ }
394
+ var ContractFactory = class {
395
+ static createEthFlowContract(address, signer) {
396
+ const adapter = getGlobalAdapter();
397
+ return {
398
+ address,
399
+ estimateGas: {
400
+ createOrder: async (order, options) => {
401
+ const txParams = {
402
+ to: address,
403
+ data: adapter.utils.encodeFunction(EthFlowAbi, "createOrder", [order]),
404
+ value: options?.value || "0"
405
+ };
406
+ return await signer.estimateGas(txParams);
407
+ },
408
+ invalidateOrder: async (order) => {
409
+ const txParams = {
410
+ to: address,
411
+ data: adapter.utils.encodeFunction(EthFlowAbi, "invalidateOrder", [order])
412
+ };
413
+ return await signer.estimateGas(txParams);
414
+ },
415
+ orders: async (orderHash) => {
416
+ const txParams = {
417
+ to: address,
418
+ data: adapter.utils.encodeFunction(EthFlowAbi, "orders", [orderHash])
419
+ };
420
+ return await signer.estimateGas(txParams);
421
+ }
422
+ },
423
+ interface: {
424
+ encodeFunctionData: (functionName, args) => {
425
+ return adapter.utils.encodeFunction(EthFlowAbi, functionName, args);
426
+ },
427
+ decodeFunctionData: (functionName, data) => {
428
+ return adapter.utils.decodeFunctionData(EthFlowAbi, functionName, data);
429
+ },
430
+ parseLog(event) {
431
+ return adapter.utils.createInterface(EthFlowAbi).parseLog(event);
432
+ },
433
+ getEventTopic(eventFragment) {
434
+ return adapter.utils.createInterface(EthFlowAbi).getEventTopic(eventFragment);
435
+ }
436
+ },
437
+ functions: {
438
+ createOrder: async (order, options) => {
439
+ const txParams = {
440
+ to: address,
441
+ data: adapter.utils.encodeFunction(EthFlowAbi, "createOrder", [order]),
442
+ value: options?.value || "0"
443
+ };
444
+ return await signer.sendTransaction(txParams);
445
+ },
446
+ invalidateOrder: async (order) => {
447
+ const txParams = {
448
+ to: address,
449
+ data: adapter.utils.encodeFunction(EthFlowAbi, "invalidateOrder", [order])
450
+ };
451
+ return await signer.sendTransaction(txParams);
452
+ },
453
+ orders: async (orderHash) => {
454
+ return await adapter.readContract({
455
+ address,
456
+ abi: EthFlowAbi,
457
+ functionName: "orders",
458
+ args: [orderHash]
459
+ });
460
+ }
461
+ },
462
+ createOrder: async (order, options) => {
463
+ const txParams = {
464
+ to: address,
465
+ data: adapter.utils.encodeFunction(EthFlowAbi, "createOrder", [order]),
466
+ value: options?.value || "0"
467
+ };
468
+ return await signer.sendTransaction(txParams);
469
+ },
470
+ invalidateOrder: async (order) => {
471
+ const txParams = {
472
+ to: address,
473
+ data: adapter.utils.encodeFunction(EthFlowAbi, "invalidateOrder", [order])
474
+ };
475
+ return await signer.sendTransaction(txParams);
476
+ },
477
+ orders: async (orderHash) => {
478
+ return await adapter.readContract({
479
+ address,
480
+ abi: EthFlowAbi,
481
+ functionName: "orders",
482
+ args: [orderHash]
483
+ });
484
+ }
485
+ };
486
+ }
487
+ static createSettlementContract(address, signer) {
488
+ const adapter = getGlobalAdapter();
489
+ return {
490
+ address,
491
+ estimateGas: {
492
+ setPreSignature: async (orderUid, signed) => {
493
+ const txParams = {
494
+ to: address,
495
+ data: adapter.utils.encodeFunction(GPV2SettlementAbi, "setPreSignature", [orderUid, signed])
496
+ };
497
+ return await signer.estimateGas(txParams);
498
+ },
499
+ invalidateOrder: async (orderUid) => {
500
+ const txParams = {
501
+ to: address,
502
+ data: adapter.utils.encodeFunction(GPV2SettlementAbi, "invalidateOrder", [orderUid])
503
+ };
504
+ return await signer.estimateGas(txParams);
505
+ },
506
+ domainSeparator: async () => {
507
+ const txParams = {
508
+ to: address,
509
+ data: adapter.utils.encodeFunction(GPV2SettlementAbi, "domainSeparator", [])
510
+ };
511
+ return await signer.estimateGas(txParams);
512
+ }
513
+ },
514
+ interface: {
515
+ encodeFunctionData: (functionName, args) => {
516
+ return adapter.utils.encodeFunction(GPV2SettlementAbi, functionName, args);
517
+ },
518
+ decodeFunctionData: (functionName, data) => {
519
+ return adapter.utils.decodeFunctionData(GPV2SettlementAbi, functionName, data);
520
+ },
521
+ parseLog(event) {
522
+ return adapter.utils.createInterface(GPV2SettlementAbi).parseLog(event);
523
+ },
524
+ getEventTopic(eventFragment) {
525
+ return adapter.utils.createInterface(GPV2SettlementAbi).getEventTopic(eventFragment);
526
+ }
527
+ },
528
+ functions: {
529
+ setPreSignature: async (orderUid, signed) => {
530
+ const txParams = {
531
+ to: address,
532
+ data: adapter.utils.encodeFunction(GPV2SettlementAbi, "setPreSignature", [orderUid, signed])
533
+ };
534
+ return await signer.sendTransaction(txParams);
535
+ },
536
+ invalidateOrder: async (orderUid) => {
537
+ const txParams = {
538
+ to: address,
539
+ data: adapter.utils.encodeFunction(GPV2SettlementAbi, "invalidateOrder", [orderUid])
540
+ };
541
+ return await signer.sendTransaction(txParams);
542
+ },
543
+ domainSeparator: async () => {
544
+ return await adapter.readContract({
545
+ address,
546
+ abi: GPV2SettlementAbi,
547
+ functionName: "domainSeparator",
548
+ args: []
549
+ });
550
+ }
551
+ },
552
+ setPreSignature: async (orderUid, signed) => {
553
+ const txParams = {
554
+ to: address,
555
+ data: adapter.utils.encodeFunction(GPV2SettlementAbi, "setPreSignature", [orderUid, signed])
556
+ };
557
+ return await signer.sendTransaction(txParams);
558
+ },
559
+ invalidateOrder: async (orderUid) => {
560
+ const txParams = {
561
+ to: address,
562
+ data: adapter.utils.encodeFunction(GPV2SettlementAbi, "invalidateOrder", [orderUid])
563
+ };
564
+ return await signer.sendTransaction(txParams);
565
+ },
566
+ domainSeparator: async () => {
567
+ return await adapter.readContract({
568
+ address,
569
+ abi: GPV2SettlementAbi,
570
+ functionName: "domainSeparator",
571
+ args: []
572
+ });
573
+ }
574
+ };
575
+ }
576
+ };
577
+ var AbstractSigner = class {
578
+ };
579
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
580
+ var ZERO = BigInt(0);
581
+ var ONE = BigInt(1);
582
+ var ZERO_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000";
583
+ var MAX_UINT32 = BigInt(2) ** BigInt(32) - BigInt(1);
584
+ var CowError = class extends Error {
585
+ error_code;
586
+ constructor(message, error_code) {
587
+ super(message);
588
+ this.error_code = error_code;
589
+ }
590
+ };
591
+ var logEnabled = false;
592
+ function log(text) {
593
+ if (!logEnabled)
594
+ return;
595
+ console.log(`[COW SDK] ${text}`);
596
+ }
597
+ function enableLogging(enabled) {
598
+ logEnabled = enabled;
599
+ }
600
+ var jsonWithBigintReplacer = (_key, value) => {
601
+ if (typeof value === "bigint") {
602
+ return value.toString();
603
+ }
604
+ if (typeof value === "object" && value !== null && "_isBigNumber" in value) {
605
+ return value.toString();
606
+ }
607
+ return value;
608
+ };
609
+ var SCALE = 1e6;
610
+ var SCALE_BIGINT = BigInt(SCALE);
611
+ var BPS_FACTOR = 10000n;
612
+ function percentageToBps(percentage) {
613
+ const bps = typeof percentage === "bigint" ? Number(percentage * BPS_FACTOR) : percentage * Number(BPS_FACTOR);
614
+ return Math.round(bps);
615
+ }
616
+ function bpsToPercentage(bps) {
617
+ return bps / 100;
618
+ }
619
+ function applyPercentage(value, percentage) {
620
+ const valueMultiplied = value * BigInt(Math.floor(percentage * SCALE)) / SCALE_BIGINT;
621
+ const roundUp = valueMultiplied % 100n >= 50n ? 1n : 0n;
622
+ return valueMultiplied / 100n + roundUp;
623
+ }
624
+ function normalizePrivateKey(privateKey) {
625
+ if (!privateKey || typeof privateKey !== "string") {
626
+ throw new CowError("Private key must be a non-empty string");
627
+ }
628
+ const cleanKey = privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey;
629
+ if (!/^[a-fA-F0-9]{64}$/.test(cleanKey)) {
630
+ throw new CowError("Invalid private key format: must be exactly 64 hexadecimal characters (with or without 0x prefix)");
631
+ }
632
+ return `0x${cleanKey}`;
633
+ }
634
+ function isValidPrivateKey(privateKey) {
635
+ try {
636
+ normalizePrivateKey(privateKey);
637
+ return true;
638
+ } catch {
639
+ return false;
640
+ }
641
+ }
642
+ var MemoryStorage = class {
643
+ storage = /* @__PURE__ */ new Map;
644
+ getItem(key) {
645
+ return this.storage.get(key) ?? null;
646
+ }
647
+ setItem(key, value) {
648
+ this.storage.set(key, value);
649
+ }
650
+ removeItem(key) {
651
+ this.storage.delete(key);
652
+ }
653
+ size(prefix) {
654
+ if (!prefix)
655
+ return this.storage.size;
656
+ let count = 0;
657
+ for (const key of this.storage.keys()) {
658
+ if (key.startsWith(prefix))
659
+ count++;
660
+ }
661
+ return count;
662
+ }
663
+ clear(prefix) {
664
+ if (!prefix) {
665
+ this.storage.clear();
666
+ return;
667
+ }
668
+ const keysToDelete = [];
669
+ for (const key of this.storage.keys()) {
670
+ if (key.startsWith(prefix))
671
+ keysToDelete.push(key);
672
+ }
673
+ keysToDelete.forEach((key) => this.storage.delete(key));
674
+ }
675
+ };
676
+ var LocalStorageWrapper = class {
677
+ fallback = new MemoryStorage;
678
+ getItem(key) {
679
+ try {
680
+ return typeof localStorage !== "undefined" ? localStorage.getItem(key) : this.fallback.getItem(key);
681
+ } catch {
682
+ return this.fallback.getItem(key);
683
+ }
684
+ }
685
+ setItem(key, value) {
686
+ try {
687
+ if (typeof localStorage !== "undefined") {
688
+ localStorage.setItem(key, value);
689
+ } else {
690
+ this.fallback.setItem(key, value);
691
+ }
692
+ } catch {
693
+ this.fallback.setItem(key, value);
694
+ }
695
+ }
696
+ removeItem(key) {
697
+ try {
698
+ if (typeof localStorage !== "undefined") {
699
+ localStorage.removeItem(key);
700
+ } else {
701
+ this.fallback.removeItem(key);
702
+ }
703
+ } catch {
704
+ this.fallback.removeItem(key);
705
+ }
706
+ }
707
+ };
708
+ var DEFAULT_KEY_PREFIX = "ttl-cache";
709
+ var DEFAULT_TTL = 2 * 60 * 1000;
710
+ var TTLCache = class {
711
+ storage;
712
+ keyPrefix;
713
+ ttl;
714
+ keys = /* @__PURE__ */ new Set;
715
+ get isMemoryStorage() {
716
+ return this.storage instanceof MemoryStorage;
717
+ }
718
+ constructor(keyPrefix = DEFAULT_KEY_PREFIX, useLocalStorage = true, ttl = DEFAULT_TTL) {
719
+ this.keyPrefix = keyPrefix;
720
+ this.ttl = ttl;
721
+ this.storage = useLocalStorage ? new LocalStorageWrapper : new MemoryStorage;
722
+ if (useLocalStorage && typeof localStorage === "undefined") {
723
+ this.storage = new MemoryStorage;
724
+ }
725
+ }
726
+ set(key, value) {
727
+ if (this.ttl <= 0)
728
+ return;
729
+ const entry = {
730
+ value,
731
+ timestamp: Date.now(),
732
+ ttl: this.ttl
733
+ };
734
+ const storageKey = this.getStorageKey(key);
735
+ try {
736
+ this.storage.setItem(storageKey, JSON.stringify(entry));
737
+ } catch (error) {
738
+ console.warn("TTLCache: Failed to store cache entry", error);
739
+ }
740
+ this.keys.add(storageKey);
741
+ }
742
+ get(key) {
743
+ const storageKey = this.getStorageKey(key);
744
+ const item = this.storage.getItem(storageKey);
745
+ if (!item) {
746
+ return;
747
+ }
748
+ try {
749
+ const entry = JSON.parse(item);
750
+ const now = Date.now();
751
+ if (now - entry.timestamp > entry.ttl) {
752
+ this.storage.removeItem(storageKey);
753
+ this.keys.delete(storageKey);
754
+ return;
755
+ }
756
+ return entry.value;
757
+ } catch (error) {
758
+ console.warn("TTLCache: Failed to parse cache entry", error);
759
+ this.storage.removeItem(storageKey);
760
+ this.keys.delete(storageKey);
761
+ return;
762
+ }
763
+ }
764
+ delete(key) {
765
+ const storageKey = this.getStorageKey(key);
766
+ this.storage.removeItem(storageKey);
767
+ this.keys.delete(storageKey);
768
+ }
769
+ clear() {
770
+ const prefix = this.keyPrefix + ":";
771
+ if (this.isMemoryStorage) {
772
+ this.storage.clear(prefix);
773
+ this.keys.clear();
774
+ return;
775
+ }
776
+ if (typeof localStorage !== "undefined") {
777
+ try {
778
+ const keysToDelete = [];
779
+ for (let i = 0;i < localStorage.length; i++) {
780
+ const key = localStorage.key(i);
781
+ if (key && key.startsWith(prefix)) {
782
+ keysToDelete.push(key);
783
+ }
784
+ }
785
+ keysToDelete.forEach((key) => localStorage.removeItem(key));
786
+ } catch {
787
+ console.warn("TTLCache: Failed to clear localStorage cache");
788
+ }
789
+ }
790
+ for (const key of Array.from(this.keys)) {
791
+ try {
792
+ this.storage.removeItem(key);
793
+ } catch (error) {
794
+ console.warn("TTLCache: Failed to remove cache key", error);
795
+ }
796
+ this.keys.delete(key);
797
+ }
798
+ }
799
+ size() {
800
+ const prefix = this.keyPrefix + ":";
801
+ if (this.isMemoryStorage && this.storage instanceof MemoryStorage) {
802
+ return this.storage.size(prefix);
803
+ }
804
+ if (typeof localStorage === "undefined") {
805
+ return this.keys.size;
806
+ }
807
+ if (typeof localStorage !== "undefined") {
808
+ try {
809
+ let count = 0;
810
+ for (let i = 0;i < localStorage.length; i++) {
811
+ const key = localStorage.key(i);
812
+ if (key && key.startsWith(prefix)) {
813
+ count++;
814
+ }
815
+ }
816
+ return count;
817
+ } catch {
818
+ return this.keys.size;
819
+ }
820
+ }
821
+ return this.keys.size;
822
+ }
823
+ cleanup() {
824
+ const prefix = this.keyPrefix + ":";
825
+ if (typeof localStorage !== "undefined") {
826
+ try {
827
+ const keysToDelete = [];
828
+ const now2 = Date.now();
829
+ for (let i = 0;i < localStorage.length; i++) {
830
+ const key = localStorage.key(i);
831
+ if (key && key.startsWith(prefix)) {
832
+ const item = localStorage.getItem(key);
833
+ if (item) {
834
+ try {
835
+ const entry = JSON.parse(item);
836
+ if (now2 - entry.timestamp > entry.ttl) {
837
+ keysToDelete.push(key);
838
+ }
839
+ } catch {
840
+ keysToDelete.push(key);
841
+ }
842
+ }
843
+ }
844
+ }
845
+ keysToDelete.forEach((key) => localStorage.removeItem(key));
846
+ } catch {
847
+ console.warn("TTLCache: Failed to cleanup expired entries");
848
+ }
849
+ }
850
+ const now = Date.now();
851
+ for (const key of Array.from(this.keys)) {
852
+ const item = this.storage.getItem(key);
853
+ if (!item) {
854
+ this.keys.delete(key);
855
+ continue;
856
+ }
857
+ try {
858
+ const entry = JSON.parse(item);
859
+ if (now - entry.timestamp > entry.ttl) {
860
+ this.storage.removeItem(key);
861
+ this.keys.delete(key);
862
+ }
863
+ } catch {
864
+ this.storage.removeItem(key);
865
+ this.keys.delete(key);
866
+ }
867
+ }
868
+ }
869
+ getStorageKey(key) {
870
+ return `${this.keyPrefix}:${key}`;
871
+ }
872
+ };
873
+ });
874
+
875
+ // src/rift-api-client.ts
876
+ var BTC = {
877
+ chain: { kind: "BITCOIN" },
878
+ token: { kind: "NATIVE", decimals: 8 }
879
+ };
880
+ var CBBTC_ETHEREUM = {
881
+ chain: { kind: "EVM", chainId: 1 },
882
+ token: {
883
+ kind: "TOKEN",
884
+ address: "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
885
+ decimals: 8
886
+ }
887
+ };
888
+ var CBBTC_BASE = {
889
+ chain: { kind: "EVM", chainId: 8453 },
890
+ token: {
891
+ kind: "TOKEN",
892
+ address: "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
893
+ decimals: 8
894
+ }
895
+ };
896
+
897
+ class SwapRouterApiError extends Error {
898
+ status;
899
+ body;
900
+ constructor(message, status, body) {
901
+ super(message);
902
+ this.name = "SwapRouterApiError";
903
+ this.status = status;
904
+ this.body = body;
905
+ }
906
+ }
907
+
908
+ class SwapRouterClient {
909
+ baseUrl;
910
+ fetch;
911
+ constructor(options) {
912
+ this.baseUrl = options.baseUrl.replace(/\/$/, "");
913
+ this.fetch = options.fetch ?? globalThis.fetch;
914
+ }
915
+ async request(method, path, body) {
916
+ const url = `${this.baseUrl}${path}`;
917
+ const response = await this.fetch(url, {
918
+ method,
919
+ headers: body ? { "Content-Type": "application/json" } : undefined,
920
+ body: body ? JSON.stringify(body) : undefined
921
+ });
922
+ const text = await response.text();
923
+ let data;
924
+ try {
925
+ data = JSON.parse(text);
926
+ } catch {
927
+ if (!response.ok) {
928
+ throw new SwapRouterApiError(text || `Request failed with status ${response.status}`, response.status);
929
+ }
930
+ throw new SwapRouterApiError(`Invalid JSON response: ${text}`, response.status);
931
+ }
932
+ if (!response.ok) {
933
+ throw new SwapRouterApiError(data.error ?? `Request failed with status ${response.status}`, response.status, data);
934
+ }
935
+ return data;
936
+ }
937
+ async health() {
938
+ return this.request("GET", "/health");
939
+ }
940
+ async status() {
941
+ return this.request("GET", "/status");
942
+ }
943
+ async quote(request) {
944
+ return this.request("POST", "/quote", request);
945
+ }
946
+ async createOrder(request) {
947
+ return this.request("POST", "/order", request);
948
+ }
949
+ async getOrder(orderId) {
950
+ return this.request("GET", `/order/${orderId}`);
951
+ }
952
+ }
953
+ // src/router.ts
954
+ import { match, P } from "ts-pattern";
955
+ var CBBTC_ADDRESS = "0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf";
956
+ var isBitcoin = (currency) => currency.chain.kind === "BITCOIN";
957
+ var isCbBtc = (currency) => currency.chain.kind === "EVM" && currency.token.kind === "TOKEN" && currency.token.address.toLowerCase() === CBBTC_ADDRESS;
958
+ var isEvmToken = (currency) => currency.chain.kind === "EVM";
959
+ function detectRoute(from, to) {
960
+ return match({ from, to }).with({ from: P.when(isCbBtc), to: P.when(isBitcoin) }, () => ({
961
+ type: "direct_rift",
962
+ direction: "to_btc"
963
+ })).with({ from: P.when(isBitcoin), to: P.when(isEvmToken) }, () => ({
964
+ type: "direct_rift",
965
+ direction: "from_btc"
966
+ })).with({
967
+ from: P.when((c) => isEvmToken(c) && !isCbBtc(c)),
968
+ to: P.when(isBitcoin)
969
+ }, ({ from: from2 }) => {
970
+ if (from2.chain.kind !== "EVM") {
971
+ throw new Error("Expected EVM chain");
972
+ }
973
+ return {
974
+ type: "cowswap_then_rift",
975
+ evmChainId: from2.chain.chainId
976
+ };
977
+ }).otherwise(() => {
978
+ throw new Error("Invalid swap: one side must be BTC");
979
+ });
980
+ }
981
+ function getCbBtcAddress(chainId) {
982
+ return CBBTC_ADDRESS;
983
+ }
984
+ var NATIVE_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
985
+ function getTokenAddress(currency) {
986
+ if (currency.token.kind === "NATIVE") {
987
+ return NATIVE_TOKEN_ADDRESS;
988
+ }
989
+ return currency.token.address;
990
+ }
991
+ function isNativeToken(currency) {
992
+ return currency.token.kind === "NATIVE";
993
+ }
994
+ function getTokenDecimals(currency) {
995
+ return currency.token.decimals;
996
+ }
997
+ function getSupportedModes(from, to) {
998
+ const route = detectRoute(from, to);
999
+ if (route.type === "cowswap_then_rift") {
1000
+ return { exactInput: true, exactOutput: true };
1001
+ }
1002
+ if (route.direction === "to_btc") {
1003
+ return { exactInput: true, exactOutput: true };
1004
+ }
1005
+ if (isCbBtc(to)) {
1006
+ return { exactInput: true, exactOutput: true };
1007
+ }
1008
+ return { exactInput: true, exactOutput: false };
1009
+ }
1010
+ // src/sdk.ts
1011
+ import { match as match2 } from "ts-pattern";
1012
+ import { erc20Abi } from "viem";
1013
+
1014
+ // src/cowswap.ts
1015
+ var import_sdk_common = __toESM(require_dist(), 1);
1016
+ import { OrderKind } from "@cowprotocol/sdk-order-book";
1017
+ import { TradingSdk } from "@cowprotocol/sdk-trading";
1018
+ import { ViemAdapter } from "@cowprotocol/sdk-viem-adapter";
1019
+ function createCowSwapSdk(chainId, publicClient, walletClient) {
1020
+ const adapter = new ViemAdapter({
1021
+ provider: publicClient,
1022
+ walletClient
1023
+ });
1024
+ import_sdk_common.setGlobalAdapter(adapter);
1025
+ return new TradingSdk({
1026
+ chainId,
1027
+ appCode: "rift.trade"
1028
+ }, {}, adapter);
1029
+ }
1030
+ var MAX_UINT256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn;
1031
+ async function ensureCowSwapApproval(sdk, tokenAddress, ownerAddress, amount) {
1032
+ const currentAllowance = await sdk.getCowProtocolAllowance({
1033
+ tokenAddress,
1034
+ owner: ownerAddress
1035
+ });
1036
+ if (currentAllowance >= BigInt(amount)) {
1037
+ return false;
1038
+ }
1039
+ await sdk.approveCowProtocol({
1040
+ tokenAddress,
1041
+ amount: MAX_UINT256
1042
+ });
1043
+ return true;
1044
+ }
1045
+ async function getCowSwapQuote(sdk, params) {
1046
+ const { quoteResults, postSwapOrderFromQuote } = await sdk.getQuote({
1047
+ kind: params.kind === "SELL" ? OrderKind.SELL : OrderKind.BUY,
1048
+ sellToken: params.sellToken,
1049
+ sellTokenDecimals: params.sellTokenDecimals,
1050
+ buyToken: params.buyToken,
1051
+ buyTokenDecimals: params.buyTokenDecimals,
1052
+ amount: params.amount,
1053
+ receiver: params.receiver,
1054
+ slippageBps: params.slippageBps
1055
+ });
1056
+ const validTo = quoteResults.quoteResponse.quote.validTo;
1057
+ const expiresAt = new Date(validTo * 1000);
1058
+ const quote = {
1059
+ quoteId: quoteResults.quoteResponse.id?.toString() ?? "",
1060
+ buyAmount: quoteResults.amountsAndCosts.afterSlippage.buyAmount.toString(),
1061
+ sellAmount: quoteResults.amountsAndCosts.afterSlippage.sellAmount.toString(),
1062
+ feeAmount: quoteResults.amountsAndCosts.costs.networkFee.amountInSellCurrency.toString(),
1063
+ expiresAt
1064
+ };
1065
+ return {
1066
+ quote,
1067
+ postOrder: async () => {
1068
+ const { orderId } = await postSwapOrderFromQuote();
1069
+ return orderId;
1070
+ }
1071
+ };
1072
+ }
1073
+
1074
+ // src/swap-id.ts
1075
+ function encodeSwapId(data) {
1076
+ let raw;
1077
+ if (data.type === "rift") {
1078
+ raw = data.chained ? `r|${data.riftOrderId}|c` : `r|${data.riftOrderId}`;
1079
+ } else {
1080
+ raw = `c|${data.cowOrderId}|${data.riftOrderId}`;
1081
+ }
1082
+ return toBase64Url(raw);
1083
+ }
1084
+ function decodeSwapId(encoded) {
1085
+ const raw = fromBase64Url(encoded);
1086
+ const parts = raw.split("|");
1087
+ if (parts[0] === "r" && (parts.length === 2 || parts.length === 3)) {
1088
+ return {
1089
+ type: "rift",
1090
+ riftOrderId: parts[1],
1091
+ chained: parts[2] === "c"
1092
+ };
1093
+ }
1094
+ if (parts[0] === "c" && parts.length === 3) {
1095
+ return { type: "cowswap_rift", cowOrderId: parts[1], riftOrderId: parts[2] };
1096
+ }
1097
+ throw new Error(`Invalid swap ID format: ${encoded}`);
1098
+ }
1099
+ function toBase64Url(str) {
1100
+ return Buffer.from(str, "utf-8").toString("base64url");
1101
+ }
1102
+ function fromBase64Url(str) {
1103
+ return Buffer.from(str, "base64url").toString("utf-8");
1104
+ }
1105
+
1106
+ // src/sdk.ts
1107
+ class RiftSdk {
1108
+ riftClient;
1109
+ publicClient;
1110
+ walletClient;
1111
+ sendBitcoinFn;
1112
+ constructor(options) {
1113
+ this.riftClient = new SwapRouterClient({
1114
+ baseUrl: options.apiUrl ?? "https://api.rift.trade"
1115
+ });
1116
+ this.publicClient = options.publicClient;
1117
+ this.walletClient = options.walletClient;
1118
+ this.sendBitcoinFn = options.sendBitcoin;
1119
+ }
1120
+ async getQuote(params) {
1121
+ const route = detectRoute(params.from, params.to);
1122
+ return match2(route).with({ type: "direct_rift", direction: "to_btc" }, () => this.getDirectRiftQuote(params, "to_btc")).with({ type: "direct_rift", direction: "from_btc" }, () => this.getDirectRiftQuote(params, "from_btc")).with({ type: "cowswap_then_rift" }, (r) => this.getCowswapThenRiftQuote(params, r.evmChainId)).exhaustive();
1123
+ }
1124
+ async getDirectRiftQuote(params, direction) {
1125
+ const quoteRequest = {
1126
+ type: params.mode === "exact_input" ? "EXACT_INPUT" : "EXACT_OUTPUT",
1127
+ from: params.from,
1128
+ to: params.to,
1129
+ amount: params.amount
1130
+ };
1131
+ const riftQuote = await this.riftClient.quote(quoteRequest);
1132
+ const quote = this.buildQuoteResult(riftQuote, params);
1133
+ const isChained = direction === "from_btc" && !isCbBtc(params.to);
1134
+ return {
1135
+ quote,
1136
+ executeSwap: async () => {
1137
+ const refundAddress = params.refundAddress ?? await this.getRefundAddress(params);
1138
+ const swap = await this.riftClient.createOrder({
1139
+ id: riftQuote.id,
1140
+ userDestinationAddress: params.destinationAddress,
1141
+ refundAddress
1142
+ });
1143
+ await this.executeDeposit(swap, params, direction);
1144
+ return this.buildSwapResult(swap, { chained: isChained });
1145
+ }
1146
+ };
1147
+ }
1148
+ async getCowswapThenRiftQuote(params, evmChainId) {
1149
+ const cbBtcAddress = getCbBtcAddress(evmChainId);
1150
+ const cbBtcCurrency = {
1151
+ chain: { kind: "EVM", chainId: evmChainId },
1152
+ token: { kind: "TOKEN", address: cbBtcAddress, decimals: 8 }
1153
+ };
1154
+ if (params.mode === "exact_input") {
1155
+ return this.getCowswapThenRiftExactInput(params, evmChainId, cbBtcAddress, cbBtcCurrency);
1156
+ } else {
1157
+ return this.getCowswapThenRiftExactOutput(params, evmChainId, cbBtcAddress, cbBtcCurrency);
1158
+ }
1159
+ }
1160
+ async getCowswapThenRiftExactInput(params, evmChainId, cbBtcAddress, cbBtcCurrency) {
1161
+ const cowSdk = createCowSwapSdk(evmChainId, this.publicClient, this.walletClient);
1162
+ const sellToken = getTokenAddress(params.from);
1163
+ const { quote: cowQuote } = await getCowSwapQuote(cowSdk, {
1164
+ sellToken,
1165
+ buyToken: cbBtcAddress,
1166
+ amount: params.amount,
1167
+ sellTokenDecimals: getTokenDecimals(params.from),
1168
+ buyTokenDecimals: 8,
1169
+ kind: "SELL",
1170
+ slippageBps: params.preswapSlippageBps
1171
+ });
1172
+ const riftQuote = await this.riftClient.quote({
1173
+ type: "EXACT_INPUT",
1174
+ from: cbBtcCurrency,
1175
+ to: BTC,
1176
+ amount: cowQuote.buyAmount
1177
+ });
1178
+ const quote = this.buildCombinedQuoteResult(params, cowQuote, riftQuote);
1179
+ return {
1180
+ quote,
1181
+ executeSwap: () => this.executeCowswapThenRift(params, riftQuote, evmChainId, cbBtcAddress, sellToken)
1182
+ };
1183
+ }
1184
+ async getCowswapThenRiftExactOutput(params, evmChainId, cbBtcAddress, cbBtcCurrency) {
1185
+ const cowSdk = createCowSwapSdk(evmChainId, this.publicClient, this.walletClient);
1186
+ const sellToken = getTokenAddress(params.from);
1187
+ const riftQuote = await this.riftClient.quote({
1188
+ type: "EXACT_OUTPUT",
1189
+ from: cbBtcCurrency,
1190
+ to: BTC,
1191
+ amount: params.amount
1192
+ });
1193
+ const { quote: cowQuote } = await getCowSwapQuote(cowSdk, {
1194
+ sellToken,
1195
+ buyToken: cbBtcAddress,
1196
+ amount: riftQuote.from.amount,
1197
+ sellTokenDecimals: getTokenDecimals(params.from),
1198
+ buyTokenDecimals: 8,
1199
+ kind: "BUY",
1200
+ slippageBps: params.preswapSlippageBps
1201
+ });
1202
+ const quote = this.buildCombinedQuoteResult(params, cowQuote, riftQuote);
1203
+ return {
1204
+ quote,
1205
+ executeSwap: () => this.executeCowswapThenRift(params, riftQuote, evmChainId, cbBtcAddress, sellToken)
1206
+ };
1207
+ }
1208
+ async executeCowswapThenRift(params, riftQuote, evmChainId, cbBtcAddress, sellToken) {
1209
+ const refundAddress = params.refundAddress ?? await this.getRefundAddress(params);
1210
+ const swap = await this.riftClient.createOrder({
1211
+ id: riftQuote.id,
1212
+ userDestinationAddress: params.destinationAddress,
1213
+ refundAddress
1214
+ });
1215
+ const cowSdk = createCowSwapSdk(evmChainId, this.publicClient, this.walletClient);
1216
+ const sellAmount = params.mode === "exact_input" ? params.amount : riftQuote.from.amount;
1217
+ if (!isNativeToken(params.from)) {
1218
+ const ownerAddress = await this.getAddress();
1219
+ await ensureCowSwapApproval(cowSdk, sellToken, ownerAddress, sellAmount);
1220
+ }
1221
+ const { postOrder } = await getCowSwapQuote(cowSdk, {
1222
+ sellToken,
1223
+ buyToken: cbBtcAddress,
1224
+ amount: sellAmount,
1225
+ sellTokenDecimals: getTokenDecimals(params.from),
1226
+ buyTokenDecimals: 8,
1227
+ kind: params.mode === "exact_input" ? "SELL" : "BUY",
1228
+ receiver: swap.deposit_vault_address,
1229
+ slippageBps: params.preswapSlippageBps
1230
+ });
1231
+ const cowOrderId = await postOrder();
1232
+ return this.buildSwapResult(swap, { cowOrderId });
1233
+ }
1234
+ buildQuoteResult(riftQuote, params) {
1235
+ return {
1236
+ quoteId: riftQuote.id,
1237
+ from: {
1238
+ currency: params.from,
1239
+ amount: riftQuote.from.amount
1240
+ },
1241
+ to: {
1242
+ currency: params.to,
1243
+ amount: riftQuote.to.amount
1244
+ },
1245
+ fees: {
1246
+ protocol: riftQuote.fees.raw.protocolFeeBps.toString(),
1247
+ liquidity: riftQuote.fees.raw.liquidityFeeBps.toString(),
1248
+ network: riftQuote.fees.raw.networkFeeSats,
1249
+ totalUsd: riftQuote.fees.usd.marketMaker + riftQuote.fees.usd.protocol + riftQuote.fees.usd.network
1250
+ },
1251
+ expiresAt: new Date(riftQuote.expiresAt)
1252
+ };
1253
+ }
1254
+ buildCombinedQuoteResult(params, cowQuote, riftQuote) {
1255
+ const earliestExpiry = new Date(Math.min(cowQuote.expiresAt.getTime(), new Date(riftQuote.expiresAt).getTime()));
1256
+ const fromAmount = params.mode === "exact_input" ? params.amount : cowQuote.sellAmount;
1257
+ return {
1258
+ quoteId: `${cowQuote.quoteId}:${riftQuote.id}`,
1259
+ from: {
1260
+ currency: params.from,
1261
+ amount: fromAmount
1262
+ },
1263
+ to: {
1264
+ currency: params.to,
1265
+ amount: riftQuote.to.amount
1266
+ },
1267
+ fees: {
1268
+ protocol: riftQuote.fees.raw.protocolFeeBps.toString(),
1269
+ liquidity: riftQuote.fees.raw.liquidityFeeBps.toString(),
1270
+ network: riftQuote.fees.raw.networkFeeSats,
1271
+ totalUsd: riftQuote.fees.usd.marketMaker + riftQuote.fees.usd.protocol + riftQuote.fees.usd.network
1272
+ },
1273
+ expiresAt: earliestExpiry
1274
+ };
1275
+ }
1276
+ buildSwapResult(swap, options) {
1277
+ const { cowOrderId, preswap, chained } = options ?? {};
1278
+ const swapId = cowOrderId ? encodeSwapId({ type: "cowswap_rift", cowOrderId, riftOrderId: swap.id }) : encodeSwapId({ type: "rift", riftOrderId: swap.id, chained });
1279
+ return {
1280
+ swapId,
1281
+ status: this.mapStatus(swap.status, chained),
1282
+ rift: swap,
1283
+ preswap
1284
+ };
1285
+ }
1286
+ async executeDeposit(swap, params, direction) {
1287
+ if (direction === "from_btc") {
1288
+ await this.sendBitcoinFn({
1289
+ recipient: swap.deposit_vault_address,
1290
+ amountSats: swap.quote.from.amount
1291
+ });
1292
+ } else {
1293
+ await this.transferErc20(getTokenAddress(params.from), swap.deposit_vault_address, swap.quote.from.amount);
1294
+ }
1295
+ }
1296
+ async transferErc20(tokenAddress, to, amount) {
1297
+ const address = await this.getAddress();
1298
+ const hash = await this.walletClient.writeContract({
1299
+ account: address,
1300
+ address: tokenAddress,
1301
+ abi: erc20Abi,
1302
+ functionName: "transfer",
1303
+ args: [to, BigInt(amount)],
1304
+ chain: this.walletClient.chain
1305
+ });
1306
+ return hash;
1307
+ }
1308
+ async getAddress() {
1309
+ const addresses = await this.walletClient.getAddresses();
1310
+ const address = addresses[0];
1311
+ if (!address) {
1312
+ throw new Error("No address available in wallet");
1313
+ }
1314
+ return address;
1315
+ }
1316
+ async getRefundAddress(params) {
1317
+ if (params.from.chain.kind === "BITCOIN") {
1318
+ throw new Error("refundAddress is required for BTC swaps (Bitcoin refund address)");
1319
+ }
1320
+ return this.getAddress();
1321
+ }
1322
+ mapStatus(status, isChained) {
1323
+ return match2(status).with("waiting_user_deposit_initiated", () => "pending_deposit").with("waiting_user_deposit_confirmed", () => "deposit_detected").with("waiting_mm_deposit_initiated", () => "processing").with("waiting_mm_deposit_confirmed", () => isChained ? "processing" : "funds_received").with("settling", () => isChained ? "swapping" : "settling").with("settled", () => "completed").with("failed", () => "failed").with("refunding_user", () => "refunding").exhaustive();
1324
+ }
1325
+ async getSwapStatus(swapId) {
1326
+ const decoded = decodeSwapId(swapId);
1327
+ if (decoded.type === "rift") {
1328
+ const rift2 = await this.riftClient.getOrder(decoded.riftOrderId);
1329
+ return {
1330
+ swapId,
1331
+ status: this.mapStatus(rift2.status, decoded.chained),
1332
+ rift: rift2
1333
+ };
1334
+ }
1335
+ const [preswap, rift] = await Promise.all([
1336
+ this.getCowSwapOrder(decoded.cowOrderId),
1337
+ this.riftClient.getOrder(decoded.riftOrderId)
1338
+ ]);
1339
+ const status = this.computeOverallStatus(preswap.status, rift.status);
1340
+ return {
1341
+ swapId,
1342
+ status,
1343
+ rift,
1344
+ preswap
1345
+ };
1346
+ }
1347
+ async getCowSwapOrder(orderId) {
1348
+ const chains = ["mainnet", "base"];
1349
+ const maxRetries = 3;
1350
+ const retryDelayMs = 2000;
1351
+ for (let attempt = 0;attempt < maxRetries; attempt++) {
1352
+ const results = await Promise.allSettled(chains.map((chain) => this.fetchCowSwapOrder(chain, orderId)));
1353
+ const success = results.find((result) => result.status === "fulfilled");
1354
+ if (success)
1355
+ return success.value;
1356
+ if (attempt === maxRetries - 1) {
1357
+ const reasons = results.map((result) => result.status === "rejected" ? result.reason?.message ?? String(result.reason) : "unknown failure").join("; ");
1358
+ throw new Error(`Failed to fetch CowSwap order ${orderId}: ${reasons}`);
1359
+ }
1360
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
1361
+ }
1362
+ throw new Error(`Failed to fetch CowSwap order ${orderId}`);
1363
+ }
1364
+ async fetchCowSwapOrder(chain, orderId) {
1365
+ const response = await fetch(`https://api.cow.fi/${chain}/api/v1/orders/${orderId}`);
1366
+ if (!response.ok) {
1367
+ throw new Error(`HTTP ${response.status} from CowSwap ${chain} for order ${orderId}`);
1368
+ }
1369
+ return response.json();
1370
+ }
1371
+ computeOverallStatus(cowStatus, riftStatus) {
1372
+ if (cowStatus === "cancelled" || cowStatus === "expired") {
1373
+ return "failed";
1374
+ }
1375
+ if (cowStatus === "presignaturePending" || cowStatus === "open") {
1376
+ return "pending_deposit";
1377
+ }
1378
+ return this.mapStatus(riftStatus);
1379
+ }
1380
+ }
1381
+ export {
1382
+ getSupportedModes,
1383
+ encodeSwapId,
1384
+ detectRoute,
1385
+ decodeSwapId,
1386
+ RiftSdk,
1387
+ CBBTC_ETHEREUM,
1388
+ CBBTC_BASE,
1389
+ BTC
1390
+ };