@cowprotocol/sdk-trading 0.3.2-beta.0 → 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/dist/index.js CHANGED
@@ -63,17 +63,62 @@ var import_sdk_order_book = require("@cowprotocol/sdk-order-book");
63
63
  var import_sdk_config = require("@cowprotocol/sdk-config");
64
64
  var DEFAULT_QUOTE_VALIDITY = 60 * 30;
65
65
  var DEFAULT_SLIPPAGE_BPS = 50;
66
- var ETH_FLOW_DEFAULT_SLIPPAGE_BPS = {
67
- ...(0, import_sdk_config.mapSupportedNetworks)(DEFAULT_SLIPPAGE_BPS),
68
- // 0.5% by default for most chains
69
- [import_sdk_config.SupportedChainId.MAINNET]: 200
70
- // 2% for mainnet
71
- };
66
+ var ETH_FLOW_DEFAULT_SLIPPAGE_BPS = (0, import_sdk_config.mapSupportedNetworks)(DEFAULT_SLIPPAGE_BPS);
72
67
  var SIGN_SCHEME_MAP = {
73
68
  [import_sdk_order_book.EcdsaSigningScheme.EIP712]: import_sdk_order_book.SigningScheme.EIP712,
74
69
  [import_sdk_order_book.EcdsaSigningScheme.ETHSIGN]: import_sdk_order_book.SigningScheme.ETHSIGN
75
70
  };
76
71
  var GAS_LIMIT_DEFAULT = BigInt(15e4);
72
+ var ERC20_APPROVE_ABI = [
73
+ {
74
+ constant: false,
75
+ inputs: [
76
+ {
77
+ name: "_spender",
78
+ type: "address"
79
+ },
80
+ {
81
+ name: "_value",
82
+ type: "uint256"
83
+ }
84
+ ],
85
+ name: "approve",
86
+ outputs: [
87
+ {
88
+ name: "",
89
+ type: "bool"
90
+ }
91
+ ],
92
+ payable: false,
93
+ stateMutability: "nonpayable",
94
+ type: "function"
95
+ }
96
+ ];
97
+ var ERC20_ALLOWANCE_ABI = [
98
+ {
99
+ constant: true,
100
+ inputs: [
101
+ {
102
+ name: "_owner",
103
+ type: "address"
104
+ },
105
+ {
106
+ name: "_spender",
107
+ type: "address"
108
+ }
109
+ ],
110
+ name: "allowance",
111
+ outputs: [
112
+ {
113
+ name: "",
114
+ type: "uint256"
115
+ }
116
+ ],
117
+ payable: false,
118
+ stateMutability: "view",
119
+ type: "function"
120
+ }
121
+ ];
77
122
 
78
123
  // src/postCoWProtocolTrade.ts
79
124
  var import_sdk_order_signing2 = require("@cowprotocol/sdk-order-signing");
@@ -365,10 +410,18 @@ async function postSellNativeCurrencyOrder(orderBookApi, appData, _params, addit
365
410
  }
366
411
 
367
412
  // src/postCoWProtocolTrade.ts
413
+ var import_sdk_common5 = require("@cowprotocol/sdk-common");
414
+
415
+ // src/utils/resolveSigner.ts
368
416
  var import_sdk_common4 = require("@cowprotocol/sdk-common");
369
- async function postCoWProtocolTrade(orderBookApi, appData, params, additionalParams = {}, paramSigner) {
417
+ function resolveSigner(signer) {
370
418
  const adapter = (0, import_sdk_common4.getGlobalAdapter)();
371
- const signer = paramSigner ? adapter.createSigner(paramSigner) : adapter.signer;
419
+ return signer ? adapter.createSigner(signer) : adapter.signer;
420
+ }
421
+
422
+ // src/postCoWProtocolTrade.ts
423
+ async function postCoWProtocolTrade(orderBookApi, appData, params, additionalParams = {}, paramSigner) {
424
+ const signer = resolveSigner(paramSigner);
372
425
  const { networkCostsAmount = "0", signingScheme: _signingScheme = import_sdk_order_book4.SigningScheme.EIP712 } = additionalParams;
373
426
  const isEthFlow = getIsEthFlowOrder(params);
374
427
  if (isEthFlow) {
@@ -384,7 +437,7 @@ async function postCoWProtocolTrade(orderBookApi, appData, params, additionalPar
384
437
  const chainId = orderBookApi.context.chainId;
385
438
  const from = owner || await signer.getAddress();
386
439
  const orderToSign = getOrderToSign({ chainId, from, networkCostsAmount, isEthFlow }, params, appData.appDataKeccak256);
387
- (0, import_sdk_common4.log)("Signing order...");
440
+ (0, import_sdk_common5.log)("Signing order...");
388
441
  const { signature, signingScheme } = await (async () => {
389
442
  if (_signingScheme === import_sdk_order_book4.SigningScheme.PRESIGN) {
390
443
  return { signature: from, signingScheme: import_sdk_order_book4.SigningScheme.PRESIGN };
@@ -402,24 +455,24 @@ async function postCoWProtocolTrade(orderBookApi, appData, params, additionalPar
402
455
  appData: fullAppData,
403
456
  appDataHash: appDataKeccak256
404
457
  };
405
- (0, import_sdk_common4.log)("Posting order...");
458
+ (0, import_sdk_common5.log)("Posting order...");
406
459
  const orderId = await orderBookApi.sendOrder(orderBody);
407
- (0, import_sdk_common4.log)(`Order created, id: ${orderId}`);
460
+ (0, import_sdk_common5.log)(`Order created, id: ${orderId}`);
408
461
  return { orderId, signature, signingScheme, orderToSign };
409
462
  }
410
463
 
411
464
  // src/getQuote.ts
412
- var import_sdk_common9 = require("@cowprotocol/sdk-common");
413
- var import_sdk_order_book6 = require("@cowprotocol/sdk-order-book");
465
+ var import_sdk_common11 = require("@cowprotocol/sdk-common");
466
+ var import_sdk_order_book7 = require("@cowprotocol/sdk-order-book");
414
467
 
415
468
  // src/appDataUtils.ts
416
469
  var import_sdk_app_data = require("@cowprotocol/sdk-app-data");
417
- var import_sdk_common5 = require("@cowprotocol/sdk-common");
470
+ var import_sdk_common6 = require("@cowprotocol/sdk-common");
418
471
  var import_deepmerge = __toESM(require("deepmerge"));
419
472
  async function buildAppData({ slippageBps, appCode, orderClass: orderClassName, partnerFee }, advancedParams) {
420
473
  const quoteParams = { slippageBips: slippageBps };
421
474
  const orderClass = { orderClass: orderClassName };
422
- const metadataApiSdk = new import_sdk_app_data.MetadataApi((0, import_sdk_common5.getGlobalAdapter)());
475
+ const metadataApiSdk = new import_sdk_app_data.MetadataApi((0, import_sdk_common6.getGlobalAdapter)());
423
476
  const doc = await metadataApiSdk.generateAppDataDoc(
424
477
  (0, import_deepmerge.default)(
425
478
  {
@@ -437,7 +490,7 @@ async function buildAppData({ slippageBps, appCode, orderClass: orderClassName,
437
490
  return { doc, fullAppData, appDataKeccak256 };
438
491
  }
439
492
  async function generateAppDataFromDoc(doc) {
440
- const adapter = (0, import_sdk_common5.getGlobalAdapter)();
493
+ const adapter = (0, import_sdk_common6.getGlobalAdapter)();
441
494
  const fullAppData = await (0, import_sdk_app_data.stringifyDeterministic)(doc);
442
495
  const appDataKeccak256 = adapter.utils.keccak256(adapter.utils.toUtf8Bytes(fullAppData));
443
496
  return { fullAppData, appDataKeccak256 };
@@ -486,12 +539,16 @@ async function getOrderTypedData(chainId, orderToSign) {
486
539
  };
487
540
  }
488
541
 
542
+ // src/resolveSlippageSuggestion.ts
543
+ var import_sdk_common10 = require("@cowprotocol/sdk-common");
544
+ var import_sdk_order_book6 = require("@cowprotocol/sdk-order-book");
545
+
489
546
  // src/suggestSlippageBps.ts
490
- var import_sdk_common8 = require("@cowprotocol/sdk-common");
547
+ var import_sdk_common9 = require("@cowprotocol/sdk-common");
491
548
  var import_sdk_order_book5 = require("@cowprotocol/sdk-order-book");
492
549
 
493
550
  // src/suggestSlippageFromFee.ts
494
- var import_sdk_common6 = require("@cowprotocol/sdk-common");
551
+ var import_sdk_common7 = require("@cowprotocol/sdk-common");
495
552
  function suggestSlippageFromFee(params) {
496
553
  const { feeAmount, multiplyingFactorPercent } = params;
497
554
  if (feeAmount < 0n) {
@@ -500,11 +557,11 @@ function suggestSlippageFromFee(params) {
500
557
  if (multiplyingFactorPercent < 0) {
501
558
  throw new Error("multiplyingFactorPercent must be non-negative: " + multiplyingFactorPercent);
502
559
  }
503
- return (0, import_sdk_common6.applyPercentage)(feeAmount, multiplyingFactorPercent);
560
+ return (0, import_sdk_common7.applyPercentage)(feeAmount, multiplyingFactorPercent);
504
561
  }
505
562
 
506
563
  // src/suggestSlippageFromVolume.ts
507
- var import_sdk_common7 = require("@cowprotocol/sdk-common");
564
+ var import_sdk_common8 = require("@cowprotocol/sdk-common");
508
565
  function suggestSlippageFromVolume(params) {
509
566
  const { sellAmountBeforeNetworkCosts, sellAmountAfterNetworkCosts, isSell, slippagePercent } = params;
510
567
  const sellAmount = isSell ? sellAmountAfterNetworkCosts : sellAmountBeforeNetworkCosts;
@@ -514,7 +571,7 @@ function suggestSlippageFromVolume(params) {
514
571
  if (slippagePercent < 0) {
515
572
  throw new Error("slippagePercent must be non-negative: " + slippagePercent);
516
573
  }
517
- return (0, import_sdk_common7.applyPercentage)(sellAmount, slippagePercent);
574
+ return (0, import_sdk_common8.applyPercentage)(sellAmount, slippagePercent);
518
575
  }
519
576
 
520
577
  // src/suggestSlippageBps.ts
@@ -522,7 +579,13 @@ var MAX_SLIPPAGE_BPS = 1e4;
522
579
  var SLIPPAGE_FEE_MULTIPLIER_PERCENT = 50;
523
580
  var SLIPPAGE_VOLUME_MULTIPLIER_PERCENT = 0.5;
524
581
  function suggestSlippageBps(params) {
525
- const { quote, tradeParameters, trader, isEthFlow } = params;
582
+ const {
583
+ quote,
584
+ tradeParameters,
585
+ trader,
586
+ isEthFlow,
587
+ volumeMultiplierPercent = SLIPPAGE_VOLUME_MULTIPLIER_PERCENT
588
+ } = params;
526
589
  const { sellTokenDecimals, buyTokenDecimals } = tradeParameters;
527
590
  const { isSell, sellAmountBeforeNetworkCosts, sellAmountAfterNetworkCosts } = (0, import_sdk_order_book5.getQuoteAmountsWithCosts)({
528
591
  sellDecimals: sellTokenDecimals,
@@ -539,7 +602,7 @@ function suggestSlippageBps(params) {
539
602
  isSell,
540
603
  sellAmountBeforeNetworkCosts,
541
604
  sellAmountAfterNetworkCosts,
542
- slippagePercent: SLIPPAGE_VOLUME_MULTIPLIER_PERCENT
605
+ slippagePercent: volumeMultiplierPercent
543
606
  });
544
607
  const totalSlippageBps = slippageBpsFromFee + slippageBpsFromVolume;
545
608
  const slippagePercent = getSlippagePercent({
@@ -548,13 +611,57 @@ function suggestSlippageBps(params) {
548
611
  sellAmountAfterNetworkCosts,
549
612
  slippage: totalSlippageBps
550
613
  });
551
- const slippageBps = (0, import_sdk_common8.percentageToBps)(slippagePercent);
552
- return Math.max(Math.min(slippageBps, MAX_SLIPPAGE_BPS), getDefaultSlippageBps(trader.chainId, isEthFlow));
614
+ const slippageBps = (0, import_sdk_common9.percentageToBps)(slippagePercent);
615
+ const lowerCap = isEthFlow ? ETH_FLOW_DEFAULT_SLIPPAGE_BPS[trader.chainId] : 0;
616
+ return Math.max(Math.min(slippageBps, MAX_SLIPPAGE_BPS), lowerCap);
617
+ }
618
+
619
+ // src/resolveSlippageSuggestion.ts
620
+ async function resolveSlippageSuggestion(chainId, tradeParameters, trader, quote, isEthFlow, advancedSettings) {
621
+ const suggestSlippageParams = {
622
+ isEthFlow,
623
+ quote,
624
+ tradeParameters,
625
+ trader,
626
+ advancedSettings
627
+ };
628
+ const getSlippageSuggestion = advancedSettings?.getSlippageSuggestion;
629
+ const priceQuality = advancedSettings?.quoteRequest?.priceQuality ?? import_sdk_order_book6.PriceQuality.OPTIMAL;
630
+ const defaultSuggestion = suggestSlippageBps(suggestSlippageParams);
631
+ if (priceQuality === import_sdk_order_book6.PriceQuality.FAST || !getSlippageSuggestion) {
632
+ return { slippageBps: defaultSuggestion };
633
+ }
634
+ const amountsAndCosts = (0, import_sdk_order_book6.getQuoteAmountsAndCosts)({
635
+ orderParams: quote.quote,
636
+ slippagePercentBps: 0,
637
+ partnerFeeBps: getPartnerFeeBps(tradeParameters.partnerFee),
638
+ sellDecimals: tradeParameters.sellTokenDecimals,
639
+ buyDecimals: tradeParameters.buyTokenDecimals
640
+ });
641
+ try {
642
+ const suggestedSlippage = await getSlippageSuggestion({
643
+ chainId,
644
+ sellToken: tradeParameters.sellToken,
645
+ buyToken: tradeParameters.buyToken,
646
+ sellAmount: amountsAndCosts.afterSlippage.sellAmount,
647
+ buyAmount: amountsAndCosts.afterSlippage.buyAmount
648
+ });
649
+ const suggestedSlippageBps = suggestedSlippage.slippageBps;
650
+ return {
651
+ slippageBps: suggestedSlippageBps ? suggestSlippageBps({
652
+ ...suggestSlippageParams,
653
+ volumeMultiplierPercent: (0, import_sdk_common10.bpsToPercentage)(suggestedSlippageBps)
654
+ }) : defaultSuggestion
655
+ };
656
+ } catch (e) {
657
+ (0, import_sdk_common10.log)(`getSlippageSuggestion() error: ${e.message || String(e)}`);
658
+ return { slippageBps: defaultSuggestion };
659
+ }
553
660
  }
554
661
 
555
662
  // src/getQuote.ts
556
663
  var ETH_FLOW_AUX_QUOTE_PARAMS = {
557
- signingScheme: import_sdk_order_book6.SigningScheme.EIP1271,
664
+ signingScheme: import_sdk_order_book7.SigningScheme.EIP1271,
558
665
  onchainOrder: true,
559
666
  // Ethflow orders are subsidized in the backend.
560
667
  // This means we can assume the verification gas costs are zero for the quote/fee estimation
@@ -570,17 +677,22 @@ async function getQuoteRaw(_tradeParameters, trader, advancedSettings, _orderBoo
570
677
  amount,
571
678
  kind,
572
679
  partnerFee,
573
- validFor = DEFAULT_QUOTE_VALIDITY,
680
+ validFor,
681
+ validTo,
574
682
  slippageBps,
575
683
  env = "prod"
576
684
  } = tradeParameters;
577
- (0, import_sdk_common9.log)(
685
+ if (validTo !== void 0 && validFor !== void 0) {
686
+ throw new Error("Cannot specify both validFor and validTo. Use validFor for relative time or validTo for absolute time.");
687
+ }
688
+ const effectiveValidFor = validFor ?? DEFAULT_QUOTE_VALIDITY;
689
+ (0, import_sdk_common11.log)(
578
690
  `getQuote for: Swap ${amount} ${sellToken} for ${buyToken} on chain ${chainId} with ${slippageBps !== void 0 ? `${slippageBps} BPS` : "AUTO"} slippage`
579
691
  );
580
- const orderBookApi = _orderBookApi || new import_sdk_order_book6.OrderBookApi({ chainId, env });
692
+ const orderBookApi = _orderBookApi || new import_sdk_order_book7.OrderBookApi({ chainId, env });
581
693
  const receiver = tradeParameters.receiver || from;
582
694
  const isSell = kind === "sell";
583
- (0, import_sdk_common9.log)("Building app data...");
695
+ (0, import_sdk_common11.log)("Building app data...");
584
696
  const defaultSlippageBps = getDefaultSlippageBps(chainId, isEthFlow);
585
697
  const slippageBpsOrDefault = slippageBps ?? defaultSlippageBps;
586
698
  const buildAppDataParams = {
@@ -591,40 +703,41 @@ async function getQuoteRaw(_tradeParameters, trader, advancedSettings, _orderBoo
591
703
  };
592
704
  const appDataInfo = await buildAppData(buildAppDataParams, advancedSettings?.appData);
593
705
  const { appDataKeccak256, fullAppData } = appDataInfo;
594
- (0, import_sdk_common9.log)(`App data: appDataKeccak256=${appDataKeccak256} fullAppData=${fullAppData}`);
706
+ (0, import_sdk_common11.log)(`App data: appDataKeccak256=${appDataKeccak256} fullAppData=${fullAppData}`);
595
707
  const quoteRequest = {
596
708
  from,
597
709
  sellToken,
598
710
  buyToken,
599
711
  receiver,
600
- validFor,
712
+ ...validTo !== void 0 ? { validTo } : { validFor: effectiveValidFor },
601
713
  appData: fullAppData,
602
714
  appDataHash: appDataKeccak256,
603
- priceQuality: import_sdk_order_book6.PriceQuality.OPTIMAL,
715
+ priceQuality: import_sdk_order_book7.PriceQuality.OPTIMAL,
604
716
  // Do not change this parameter because we rely on the fact that quote has id
605
- signingScheme: import_sdk_order_book6.SigningScheme.EIP712,
717
+ signingScheme: import_sdk_order_book7.SigningScheme.EIP712,
606
718
  ...isEthFlow ? ETH_FLOW_AUX_QUOTE_PARAMS : {},
607
- ...isSell ? { kind: import_sdk_order_book6.OrderQuoteSideKindSell.SELL, sellAmountBeforeFee: amount } : { kind: import_sdk_order_book6.OrderQuoteSideKindBuy.BUY, buyAmountAfterFee: amount },
719
+ ...isSell ? { kind: import_sdk_order_book7.OrderQuoteSideKindSell.SELL, sellAmountBeforeFee: amount } : { kind: import_sdk_order_book7.OrderQuoteSideKindBuy.BUY, buyAmountAfterFee: amount },
608
720
  ...advancedSettings?.quoteRequest
609
721
  };
610
- (0, import_sdk_common9.log)("Getting quote...");
722
+ (0, import_sdk_common11.log)("Getting quote...");
611
723
  const quote = await orderBookApi.getQuote(quoteRequest);
612
- const suggestedSlippageBps = suggestSlippageBps({
613
- isEthFlow,
614
- quote,
724
+ const { slippageBps: suggestedSlippageBps } = await resolveSlippageSuggestion(
725
+ chainId,
615
726
  tradeParameters,
616
727
  trader,
728
+ quote,
729
+ isEthFlow,
617
730
  advancedSettings
618
- });
731
+ );
619
732
  const commonResult = {
620
733
  isEthFlow,
621
734
  quote,
622
735
  orderBookApi,
623
- suggestedSlippageBps
736
+ suggestedSlippageBps: suggestedSlippageBps || defaultSlippageBps
624
737
  };
625
738
  if (slippageBps === void 0) {
626
- if (suggestedSlippageBps > defaultSlippageBps) {
627
- (0, import_sdk_common9.log)(
739
+ if (suggestedSlippageBps) {
740
+ (0, import_sdk_common11.log)(
628
741
  `Suggested slippage is greater than ${defaultSlippageBps} BPS (default), using the suggested slippage (${suggestedSlippageBps} BPS)`
629
742
  );
630
743
  const newAppDataInfo = await buildAppData(
@@ -634,7 +747,7 @@ async function getQuoteRaw(_tradeParameters, trader, advancedSettings, _orderBoo
634
747
  },
635
748
  advancedSettings?.appData
636
749
  );
637
- (0, import_sdk_common9.log)(
750
+ (0, import_sdk_common11.log)(
638
751
  `App data with new suggested slippage: appDataKeccak256=${newAppDataInfo.appDataKeccak256} fullAppData=${newAppDataInfo.fullAppData}`
639
752
  );
640
753
  return {
@@ -644,9 +757,7 @@ async function getQuoteRaw(_tradeParameters, trader, advancedSettings, _orderBoo
644
757
  slippageBps: suggestedSlippageBps
645
758
  };
646
759
  } else {
647
- (0, import_sdk_common9.log)(
648
- `Suggested slippage is only ${suggestedSlippageBps} BPS. Using the default slippage (${defaultSlippageBps} BPS)`
649
- );
760
+ (0, import_sdk_common11.log)(`No suggested slippage. Using the default slippage (${defaultSlippageBps} BPS)`);
650
761
  }
651
762
  }
652
763
  return {
@@ -661,7 +772,7 @@ async function getQuote(_tradeParameters, trader, advancedSettings, _orderBookAp
661
772
  const { quote, orderBookApi, tradeParameters, slippageBps, suggestedSlippageBps, appDataInfo, isEthFlow } = await getQuoteRaw(_tradeParameters, trader, advancedSettings, _orderBookApi);
662
773
  const { partnerFee, sellTokenDecimals, buyTokenDecimals } = tradeParameters;
663
774
  const { chainId, account: from } = trader;
664
- const amountsAndCosts = (0, import_sdk_order_book6.getQuoteAmountsAndCosts)({
775
+ const amountsAndCosts = (0, import_sdk_order_book7.getQuoteAmountsAndCosts)({
665
776
  orderParams: quote.quote,
666
777
  slippagePercentBps: slippageBps,
667
778
  partnerFeeBps: getPartnerFeeBps(partnerFee),
@@ -688,7 +799,7 @@ async function getQuote(_tradeParameters, trader, advancedSettings, _orderBookAp
688
799
  };
689
800
  }
690
801
  async function getTrader(swapParameters) {
691
- const signer = (0, import_sdk_common9.getGlobalAdapter)().signerOrNull();
802
+ const signer = (0, import_sdk_common11.getGlobalAdapter)().signerOrNull();
692
803
  const account = swapParameters.owner || await signer?.getAddress();
693
804
  return {
694
805
  chainId: swapParameters.chainId,
@@ -697,8 +808,7 @@ async function getTrader(swapParameters) {
697
808
  };
698
809
  }
699
810
  async function getQuoteWithSigner(swapParameters, advancedSettings, orderBookApi) {
700
- const adapter = (0, import_sdk_common9.getGlobalAdapter)();
701
- const signer = swapParameters.signer ? adapter.createSigner(swapParameters.signer) : adapter.signer;
811
+ const signer = resolveSigner(swapParameters.signer);
702
812
  const trader = await getTrader(swapParameters);
703
813
  const result = await getQuote(swapParameters, trader, advancedSettings, orderBookApi);
704
814
  return {
@@ -754,8 +864,8 @@ async function postSwapOrderFromQuote({
754
864
  }
755
865
 
756
866
  // src/postLimitOrder.ts
757
- var import_sdk_order_book7 = require("@cowprotocol/sdk-order-book");
758
- var import_sdk_common10 = require("@cowprotocol/sdk-common");
867
+ var import_sdk_order_book8 = require("@cowprotocol/sdk-order-book");
868
+ var import_sdk_common12 = require("@cowprotocol/sdk-common");
759
869
  async function postLimitOrder(params, advancedSettings, _orderBookApi) {
760
870
  const appDataSlippage = advancedSettings?.appData?.metadata?.quote?.slippageBips;
761
871
  const partnerFeeOverride = advancedSettings?.appData?.metadata?.partnerFee;
@@ -772,9 +882,9 @@ async function postLimitOrder(params, advancedSettings, _orderBookApi) {
772
882
  params.env = "prod";
773
883
  }
774
884
  const { appCode, chainId, sellToken, buyToken, sellAmount, buyAmount, partnerFee } = params;
775
- (0, import_sdk_common10.log)(`Limit order ${sellAmount} ${sellToken} for ${buyAmount} ${buyToken} on chain ${chainId}`);
776
- const orderBookApi = _orderBookApi || new import_sdk_order_book7.OrderBookApi({ chainId, env: params.env });
777
- (0, import_sdk_common10.log)("Building app data...");
885
+ (0, import_sdk_common12.log)(`Limit order ${sellAmount} ${sellToken} for ${buyAmount} ${buyToken} on chain ${chainId}`);
886
+ const orderBookApi = _orderBookApi || new import_sdk_order_book8.OrderBookApi({ chainId, env: params.env });
887
+ (0, import_sdk_common12.log)("Building app data...");
778
888
  const appDataInfo = await buildAppData(
779
889
  {
780
890
  slippageBps: params.slippageBps,
@@ -787,35 +897,109 @@ async function postLimitOrder(params, advancedSettings, _orderBookApi) {
787
897
  return postCoWProtocolTrade(orderBookApi, appDataInfo, params, advancedSettings?.additionalParams, params.signer);
788
898
  }
789
899
 
790
- // src/getPreSignTransaction.ts
900
+ // src/getSettlementContract.ts
901
+ var import_sdk_common13 = require("@cowprotocol/sdk-common");
791
902
  var import_sdk_config5 = require("@cowprotocol/sdk-config");
792
- var import_sdk_common11 = require("@cowprotocol/sdk-common");
793
- async function getPreSignTransaction(signer, chainId, account, orderId) {
794
- const contract = import_sdk_common11.ContractFactory.createSettlementContract(account, signer);
795
- const settlementContractAddress = import_sdk_config5.COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS[chainId];
903
+ function getSettlementContract(chainId, signer) {
904
+ return import_sdk_common13.ContractFactory.createSettlementContract(import_sdk_config5.COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS[chainId], signer);
905
+ }
906
+
907
+ // src/getPreSignTransaction.ts
908
+ async function getPreSignTransaction(signer, chainId, orderId) {
909
+ const contract = getSettlementContract(chainId, signer);
796
910
  const preSignatureCall = contract.interface.encodeFunctionData("setPreSignature", [orderId, true]);
797
911
  const gas = await contract.estimateGas.setPreSignature?.(orderId, true).catch(() => GAS_LIMIT_DEFAULT) || GAS_LIMIT_DEFAULT;
798
912
  return {
799
913
  data: preSignatureCall,
800
914
  gasLimit: "0x" + calculateGasMargin(gas).toString(16),
801
- to: settlementContractAddress,
802
- // Para onde enviar a transação
915
+ to: contract.address,
803
916
  value: "0"
804
917
  };
805
918
  }
806
919
 
807
920
  // src/tradingSdk.ts
808
- var import_sdk_common12 = require("@cowprotocol/sdk-common");
809
- var import_sdk_common13 = require("@cowprotocol/sdk-common");
921
+ var import_sdk_common14 = require("@cowprotocol/sdk-common");
922
+ var import_sdk_order_signing4 = require("@cowprotocol/sdk-order-signing");
923
+
924
+ // src/onChainCancellation.ts
925
+ var CANCELLATION_GAS_LIMIT_DEFAULT = 150000n;
926
+ async function getEthFlowCancellation(ethFlowContract, order) {
927
+ const cancelOrderParams = {
928
+ buyToken: order.buyToken,
929
+ receiver: order.receiver || order.owner,
930
+ sellAmount: order.sellAmount,
931
+ buyAmount: order.buyAmount,
932
+ appData: order.appData.toString(),
933
+ feeAmount: order.feeAmount,
934
+ validTo: order.validTo.toString(),
935
+ partiallyFillable: false,
936
+ quoteId: 0
937
+ // value doesn't matter, set to 0 for reducing gas costs
938
+ };
939
+ return getOnChainCancellation(ethFlowContract, cancelOrderParams);
940
+ }
941
+ async function getSettlementCancellation(settlementContract, order) {
942
+ const cancelOrderParams = order.uid;
943
+ return getOnChainCancellation(settlementContract, cancelOrderParams);
944
+ }
945
+ async function getOnChainCancellation(contract, cancelOrderParams) {
946
+ const estimatedGas = await (async () => {
947
+ try {
948
+ if (contract.estimateGas.invalidateOrder) {
949
+ const estimated = await contract.estimateGas.invalidateOrder(cancelOrderParams);
950
+ return BigInt(estimated.toHexString ? estimated.toHexString() : `0x${estimated.toString(16)}`);
951
+ }
952
+ return CANCELLATION_GAS_LIMIT_DEFAULT;
953
+ } catch (error) {
954
+ console.error(error);
955
+ return CANCELLATION_GAS_LIMIT_DEFAULT;
956
+ }
957
+ })();
958
+ const data = contract.interface.encodeFunctionData("invalidateOrder", [cancelOrderParams]);
959
+ return {
960
+ estimatedGas,
961
+ transaction: {
962
+ data,
963
+ gasLimit: "0x" + estimatedGas.toString(16),
964
+ to: contract.address,
965
+ value: "0x0"
966
+ }
967
+ };
968
+ }
969
+
970
+ // src/utils/resolveOrderBookApi.ts
971
+ var import_sdk_order_book9 = require("@cowprotocol/sdk-order-book");
972
+ var orderBookApiCache = /* @__PURE__ */ new Map([
973
+ ["prod", /* @__PURE__ */ new Map()],
974
+ ["staging", /* @__PURE__ */ new Map()]
975
+ ]);
976
+ function resolveOrderBookApi(chainId, env, existingOrderBookApi) {
977
+ if (existingOrderBookApi) {
978
+ existingOrderBookApi.context.chainId = chainId;
979
+ existingOrderBookApi.context.env = env;
980
+ return existingOrderBookApi;
981
+ }
982
+ const envCache = orderBookApiCache.get(env) ?? /* @__PURE__ */ new Map();
983
+ const cached = envCache.get(chainId);
984
+ if (cached)
985
+ return cached;
986
+ const orderBookApi = new import_sdk_order_book9.OrderBookApi({ chainId, env });
987
+ envCache.set(chainId, orderBookApi);
988
+ orderBookApiCache.set(env, envCache);
989
+ return orderBookApi;
990
+ }
991
+
992
+ // src/tradingSdk.ts
993
+ var import_sdk_config6 = require("@cowprotocol/sdk-config");
810
994
  var TradingSdk = class {
811
995
  constructor(traderParams = {}, options = {}, adapter) {
812
996
  this.traderParams = traderParams;
813
997
  this.options = options;
814
998
  if (options.enableLogging !== void 0) {
815
- (0, import_sdk_common12.enableLogging)(options.enableLogging);
999
+ (0, import_sdk_common14.enableLogging)(options.enableLogging);
816
1000
  }
817
1001
  if (adapter) {
818
- (0, import_sdk_common13.setGlobalAdapter)(adapter);
1002
+ (0, import_sdk_common14.setGlobalAdapter)(adapter);
819
1003
  }
820
1004
  }
821
1005
  setTraderParams(params) {
@@ -847,7 +1031,7 @@ var TradingSdk = class {
847
1031
  }),
848
1032
  // It's important to get a fresh instance of the signer
849
1033
  // Because quote might be called with another signer
850
- signer: (0, import_sdk_common12.getGlobalAdapter)().signer
1034
+ signer: (0, import_sdk_common14.getGlobalAdapter)().signer
851
1035
  }
852
1036
  },
853
1037
  advancedSettings2
@@ -908,16 +1092,123 @@ var TradingSdk = class {
908
1092
  );
909
1093
  }
910
1094
  async getPreSignTransaction(params) {
911
- const adapter = (0, import_sdk_common12.getGlobalAdapter)();
912
1095
  const traderParams = this.mergeParams(params);
913
- const signer = traderParams.signer ? adapter.createSigner(traderParams.signer) : adapter.signer;
914
- return getPreSignTransaction(signer, traderParams.chainId, params.account, params.orderId);
1096
+ const signer = resolveSigner(traderParams.signer);
1097
+ return getPreSignTransaction(signer, traderParams.chainId, params.orderUid);
1098
+ }
1099
+ async getOrder(params) {
1100
+ const orderBookApi = this.resolveOrderBookApi(params);
1101
+ return orderBookApi.getOrder(params.orderUid);
1102
+ }
1103
+ async offChainCancelOrder(params) {
1104
+ const orderBookApi = this.resolveOrderBookApi(params);
1105
+ const signer = resolveSigner(params.signer);
1106
+ const { orderUid } = params;
1107
+ const chainId = params.chainId || this.traderParams.chainId;
1108
+ if (!chainId) {
1109
+ throw new Error("Chain ID is missing in offChainCancelOrder() call");
1110
+ }
1111
+ const orderCancellationSigning = await import_sdk_order_signing4.OrderSigningUtils.signOrderCancellations([orderUid], chainId, signer);
1112
+ await orderBookApi.sendSignedOrderCancellations({
1113
+ ...orderCancellationSigning,
1114
+ orderUids: [orderUid]
1115
+ });
1116
+ return true;
1117
+ }
1118
+ async onChainCancelOrder(params, _order) {
1119
+ const chainId = params.chainId || this.traderParams.chainId;
1120
+ if (!chainId) {
1121
+ throw new Error("Chain ID is missing in offChainCancelOrder() call");
1122
+ }
1123
+ const order = _order ?? await this.getOrder(params);
1124
+ const isEthFlowOrder = !!order.onchainOrderData;
1125
+ const signer = params.signer ? (0, import_sdk_common14.getGlobalAdapter)().createSigner(params.signer) : (0, import_sdk_common14.getGlobalAdapter)().signer;
1126
+ const { transaction } = await (isEthFlowOrder ? getEthFlowCancellation(getEthFlowContract(signer, chainId, params.env ?? this.traderParams.env), order) : getSettlementCancellation(getSettlementContract(chainId, signer), order));
1127
+ const txReceipt = await signer.sendTransaction(transaction);
1128
+ return txReceipt.hash;
1129
+ }
1130
+ /**
1131
+ * Checks the current allowance for the CoW Protocol Vault Relayer to spend an ERC-20 token.
1132
+ *
1133
+ * @param params - Parameters including token address and owner address
1134
+ * @returns Promise resolving to the current allowance amount as a bigint
1135
+ *
1136
+ * @example
1137
+ * ```typescript
1138
+ * const params = {
1139
+ * tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
1140
+ * owner: '0x123...',
1141
+ * chainId: 1,
1142
+ * }
1143
+ *
1144
+ * const allowance = await sdk.getCowProtocolAllowance(params)
1145
+ * console.log('Current allowance:', allowance.toString())
1146
+ * ```
1147
+ */
1148
+ async getCowProtocolAllowance(params) {
1149
+ const chainId = params.chainId || this.traderParams.chainId;
1150
+ if (!chainId) {
1151
+ throw new Error("Chain ID is missing in getCowProtocolAllowance() call");
1152
+ }
1153
+ const adapter = (0, import_sdk_common14.getGlobalAdapter)();
1154
+ const vaultRelayerAddress = import_sdk_config6.COW_PROTOCOL_VAULT_RELAYER_ADDRESS[chainId];
1155
+ return await adapter.readContract({
1156
+ address: params.tokenAddress,
1157
+ abi: ERC20_ALLOWANCE_ABI,
1158
+ functionName: "allowance",
1159
+ args: [params.owner, vaultRelayerAddress]
1160
+ });
1161
+ }
1162
+ /**
1163
+ * Approves the CoW Protocol Vault Relayer to spend a specified amount of an ERC-20 token.
1164
+ * This method creates an on-chain approval transaction.
1165
+ *
1166
+ * @param params - Parameters including token address and amount to approve
1167
+ * @returns Promise resolving to the transaction hash of the approval transaction
1168
+ *
1169
+ * @example
1170
+ * ```typescript
1171
+ * const params = {
1172
+ * tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
1173
+ * amount: '1000000000', // 1000 USDC (6 decimals)
1174
+ * chainId: 1,
1175
+ * }
1176
+ *
1177
+ * const txHash = await sdk.approveCowProtocol(params)
1178
+ * console.log('Approval transaction:', txHash)
1179
+ * ```
1180
+ */
1181
+ async approveCowProtocol(params) {
1182
+ const chainId = params.chainId || this.traderParams.chainId;
1183
+ if (!chainId) {
1184
+ throw new Error("Chain ID is missing in approveCowProtocol() call");
1185
+ }
1186
+ const adapter = (0, import_sdk_common14.getGlobalAdapter)();
1187
+ const signer = resolveSigner(params.signer);
1188
+ const vaultRelayerAddress = import_sdk_config6.COW_PROTOCOL_VAULT_RELAYER_ADDRESS[chainId];
1189
+ const txParams = {
1190
+ to: params.tokenAddress,
1191
+ data: adapter.utils.encodeFunction(ERC20_APPROVE_ABI, "approve", [
1192
+ vaultRelayerAddress,
1193
+ "0x" + params.amount.toString(16)
1194
+ ])
1195
+ };
1196
+ const txReceipt = await signer.sendTransaction(txParams);
1197
+ return txReceipt.hash;
1198
+ }
1199
+ resolveOrderBookApi(params) {
1200
+ const chainId = params.chainId ?? this.traderParams.chainId;
1201
+ const env = params.env ?? this.traderParams.env ?? "prod";
1202
+ if (!chainId) {
1203
+ throw new Error("Chain ID is missing in getOrder() call");
1204
+ }
1205
+ return resolveOrderBookApi(chainId, env);
915
1206
  }
916
1207
  mergeParams(params) {
917
1208
  const { chainId, signer, appCode, env } = params;
918
1209
  const traderParams = {
919
1210
  chainId: chainId || this.traderParams.chainId,
920
- signer: signer || this.traderParams.signer || (0, import_sdk_common12.getGlobalAdapter)().signer,
1211
+ signer: signer || this.traderParams.signer || (0, import_sdk_common14.getGlobalAdapter)().signer,
921
1212
  appCode: appCode || this.traderParams.appCode,
922
1213
  env: env || this.traderParams.env
923
1214
  };