@shapeshiftoss/swapper 8.5.1 → 8.6.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/api.d.ts CHANGED
@@ -164,7 +164,8 @@ export declare enum SwapErrorTypes {
164
164
  VALIDATION_FAILED = "VALIDATION_FAILED",
165
165
  MAKE_MEMO_FAILED = "MAKE_MEMO_FAILED",
166
166
  PRICE_RATIO_FAILED = "PRICE_RATIO_FAILED",
167
- POOL_NOT_FOUND = "POOL_NOT_FOUND"
167
+ POOL_NOT_FOUND = "POOL_NOT_FOUND",
168
+ GET_TRADE_TXS_FAILED = "GET_TRADE_TXS_FAILED"
168
169
  }
169
170
  export interface Swapper<T extends ChainId> {
170
171
  /** Human readable swapper name */
package/dist/api.js CHANGED
@@ -36,4 +36,5 @@ var SwapErrorTypes;
36
36
  SwapErrorTypes["MAKE_MEMO_FAILED"] = "MAKE_MEMO_FAILED";
37
37
  SwapErrorTypes["PRICE_RATIO_FAILED"] = "PRICE_RATIO_FAILED";
38
38
  SwapErrorTypes["POOL_NOT_FOUND"] = "POOL_NOT_FOUND";
39
+ SwapErrorTypes["GET_TRADE_TXS_FAILED"] = "GET_TRADE_TXS_FAILED";
39
40
  })(SwapErrorTypes = exports.SwapErrorTypes || (exports.SwapErrorTypes = {}));
@@ -25,12 +25,6 @@ class SwapperManager {
25
25
  addSwapper(swapperInstance) {
26
26
  validateSwapper(swapperInstance);
27
27
  const swapperType = swapperInstance.getType();
28
- const swapper = this.swappers.get(swapperType);
29
- if (swapper)
30
- throw new api_1.SwapError('[addSwapper] - swapper already exists', {
31
- code: api_1.SwapErrorTypes.MANAGER_ERROR,
32
- details: { swapperType }
33
- });
34
28
  this.swappers.set(swapperType, swapperInstance);
35
29
  return this;
36
30
  }
@@ -2,7 +2,8 @@ import { AssetId } from '@shapeshiftoss/caip';
2
2
  import { ethereum } from '@shapeshiftoss/chain-adapters';
3
3
  import { Asset, KnownChainIds } from '@shapeshiftoss/types';
4
4
  import Web3 from 'web3';
5
- import { ApprovalNeededInput, ApprovalNeededOutput, ApproveInfiniteInput, BuildTradeInput, BuyAssetBySellIdInput, ExecuteTradeInput, GetTradeQuoteInput, Swapper, SwapperType, Trade, TradeQuote, TradeResult, TradeTxs } from '../../api';
5
+ import { ApprovalNeededInput, ApprovalNeededOutput, ApproveInfiniteInput, BuildTradeInput, BuyAssetBySellIdInput, ExecuteTradeInput, GetTradeQuoteInput, Swapper, SwapperType, TradeQuote, TradeResult, TradeTxs } from '../../api';
6
+ import { CowTrade } from './types';
6
7
  /**
7
8
  * CowSwap only supports ERC-20 swaps, hence ETH is not supported
8
9
  * In order to get rates correctly, we need WETH asset to be passed as feeAsset
@@ -18,7 +19,7 @@ export declare class CowSwapper implements Swapper<KnownChainIds.EthereumMainnet
18
19
  deps: CowSwapperDeps;
19
20
  constructor(deps: CowSwapperDeps);
20
21
  getType(): SwapperType;
21
- buildTrade(args: BuildTradeInput): Promise<Trade<KnownChainIds.EthereumMainnet>>;
22
+ buildTrade(args: BuildTradeInput): Promise<CowTrade<KnownChainIds.EthereumMainnet>>;
22
23
  getTradeQuote(input: GetTradeQuoteInput): Promise<TradeQuote<KnownChainIds.EthereumMainnet>>;
23
24
  getUsdRate(input: Asset): Promise<string>;
24
25
  executeTrade(args: ExecuteTradeInput<KnownChainIds.EthereumMainnet>): Promise<TradeResult>;
@@ -26,5 +27,5 @@ export declare class CowSwapper implements Swapper<KnownChainIds.EthereumMainnet
26
27
  approveInfinite(args: ApproveInfiniteInput<KnownChainIds.EthereumMainnet>): Promise<string>;
27
28
  filterBuyAssetsBySellAssetId(args: BuyAssetBySellIdInput): AssetId[];
28
29
  filterAssetIdsBySellable(assetIds: AssetId[]): AssetId[];
29
- getTradeTxs(): Promise<TradeTxs>;
30
+ getTradeTxs(args: TradeResult): Promise<TradeTxs>;
30
31
  }
@@ -5,6 +5,8 @@ const api_1 = require("../../api");
5
5
  const cowApprovalNeeded_1 = require("./cowApprovalNeeded/cowApprovalNeeded");
6
6
  const cowApproveInfinite_1 = require("./cowApproveInfinite/cowApproveInfinite");
7
7
  const cowBuildTrade_1 = require("./cowBuildTrade/cowBuildTrade");
8
+ const cowExecuteTrade_1 = require("./cowExecuteTrade/cowExecuteTrade");
9
+ const cowGetTradeTxs_1 = require("./cowGetTradeTxs/cowGetTradeTxs");
8
10
  const getCowSwapTradeQuote_1 = require("./getCowSwapTradeQuote/getCowSwapTradeQuote");
9
11
  const blacklist_1 = require("./utils/blacklist");
10
12
  const helpers_1 = require("./utils/helpers/helpers");
@@ -26,8 +28,7 @@ class CowSwapper {
26
28
  return (0, helpers_1.getUsdRate)(this.deps, input);
27
29
  }
28
30
  async executeTrade(args) {
29
- console.info(args);
30
- throw new Error('CowSwapper: executeTrade unimplemented');
31
+ return (0, cowExecuteTrade_1.cowExecuteTrade)(this.deps, args);
31
32
  }
32
33
  async approvalNeeded(args) {
33
34
  return (0, cowApprovalNeeded_1.cowApprovalNeeded)(this.deps, args);
@@ -47,8 +48,8 @@ class CowSwapper {
47
48
  filterAssetIdsBySellable(assetIds) {
48
49
  return assetIds.filter((id) => id.startsWith('eip155:1/erc20') && !blacklist_1.COWSWAP_UNSUPPORTED_ASSETS.includes(id));
49
50
  }
50
- async getTradeTxs() {
51
- throw new Error('CowSwapper: executeTrade unimplemented');
51
+ async getTradeTxs(args) {
52
+ return (0, cowGetTradeTxs_1.cowGetTradeTxs)(this.deps, args);
52
53
  }
53
54
  }
54
55
  exports.CowSwapper = CowSwapper;
@@ -1,4 +1,5 @@
1
1
  import { KnownChainIds } from '@shapeshiftoss/types';
2
- import { BuildTradeInput, Trade } from '../../../api';
2
+ import { BuildTradeInput } from '../../../api';
3
3
  import { CowSwapperDeps } from '../CowSwapper';
4
- export declare function cowBuildTrade(deps: CowSwapperDeps, input: BuildTradeInput): Promise<Trade<KnownChainIds.EthereumMainnet>>;
4
+ import { CowTrade } from '../types';
5
+ export declare function cowBuildTrade(deps: CowSwapperDeps, input: BuildTradeInput): Promise<CowTrade<KnownChainIds.EthereumMainnet>>;
@@ -12,7 +12,7 @@ const helpers_2 = require("../utils/helpers/helpers");
12
12
  async function cowBuildTrade(deps, input) {
13
13
  try {
14
14
  const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber, wallet } = input;
15
- const { adapter, feeAsset, web3 } = deps;
15
+ const { adapter, web3 } = deps;
16
16
  const { assetReference: sellAssetErc20Address, assetNamespace: sellAssetNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
17
17
  const { assetReference: buyAssetErc20Address, assetNamespace: buyAssetNamespace } = (0, caip_1.fromAssetId)(buyAsset.assetId);
18
18
  if (buyAssetNamespace !== 'erc20' || sellAssetNamespace !== 'erc20') {
@@ -57,36 +57,29 @@ async function cowBuildTrade(deps, input) {
57
57
  spenderAddress: constants_1.COW_SWAP_VAULT_RELAYER_ADDRESS,
58
58
  contractAddress: sellAssetErc20Address
59
59
  });
60
- const [feeDataOptions, feeAssetUsdRate, sellAssetUsdRate] = await Promise.all([
60
+ const [feeDataOptions, sellAssetUsdRate] = await Promise.all([
61
61
  adapter.getFeeData({
62
62
  to: sellAssetErc20Address,
63
63
  value: '0',
64
64
  chainSpecific: { from: receiveAddress, contractData: data }
65
65
  }),
66
- (0, helpers_2.getUsdRate)(deps, feeAsset),
67
66
  (0, helpers_2.getUsdRate)(deps, sellAsset)
68
67
  ]);
69
68
  const feeData = feeDataOptions['fast'];
70
- // quote.feeAmount is expressed in sellAsset token
71
- // We need fee to be expressed in feeAsset token
72
- // feeInFeeAsset * feeAssetUsdRate = feeInSellAsset * sellAssetUsdRate
73
- // hence feeInFeeAsset = feeInSellAsset * sellAssetUsdRate / feeAssetUsdRate
74
- const feeInSellAsset = (0, bignumber_1.bnOrZero)(quote.feeAmount).div((0, bignumber_1.bn)(10).exponentiatedBy(sellAsset.precision));
75
- // feeInFeeAsset = feeInSellAsset * sellAssetUsdRate / feeAssetUsdRate
76
- const feeInFeeAsset = feeInSellAsset
69
+ // calculating trade fee in USD
70
+ const tradeFeeFiat = (0, bignumber_1.bnOrZero)(quote.feeAmount)
71
+ .div((0, bignumber_1.bn)(10).exponentiatedBy(sellAsset.precision))
77
72
  .multipliedBy((0, bignumber_1.bnOrZero)(sellAssetUsdRate))
78
- .div((0, bignumber_1.bnOrZero)(feeAssetUsdRate));
79
- // taking precision into account
80
- const fee = feeInFeeAsset.multipliedBy((0, bignumber_1.bn)(10).exponentiatedBy(feeAsset.precision)).toString();
73
+ .toString();
81
74
  const trade = {
82
75
  rate,
83
76
  feeData: {
84
- fee,
77
+ fee: '0',
85
78
  chainSpecific: {
86
79
  estimatedGas: feeData.chainSpecific.gasLimit,
87
80
  gasPrice: feeData.chainSpecific.gasPrice
88
81
  },
89
- tradeFee: '0'
82
+ tradeFee: tradeFeeFiat
90
83
  },
91
84
  sellAmount: normalizedSellAmount,
92
85
  buyAmount: quote.buyAmount,
@@ -94,7 +87,9 @@ async function cowBuildTrade(deps, input) {
94
87
  buyAsset,
95
88
  sellAsset,
96
89
  sellAssetAccountNumber,
97
- receiveAddress
90
+ receiveAddress,
91
+ feeAmountInSellToken: quote.feeAmount,
92
+ sellAmountWithoutFee: quote.sellAmount
98
93
  };
99
94
  const allowanceRequired = await (0, helpers_1.getAllowanceRequired)({
100
95
  adapter,
@@ -0,0 +1,4 @@
1
+ import { KnownChainIds } from '@shapeshiftoss/types';
2
+ import { ExecuteTradeInput, TradeResult } from '../../../api';
3
+ import { CowSwapperDeps } from '../CowSwapper';
4
+ export declare function cowExecuteTrade({ apiUrl, adapter }: CowSwapperDeps, { trade, wallet }: ExecuteTradeInput<KnownChainIds.EthereumMainnet>): Promise<TradeResult>;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cowExecuteTrade = void 0;
4
+ const caip_1 = require("@shapeshiftoss/caip");
5
+ const chain_adapters_1 = require("@shapeshiftoss/chain-adapters");
6
+ const hdwallet_core_1 = require("@shapeshiftoss/hdwallet-core");
7
+ const ethers_1 = require("ethers");
8
+ const api_1 = require("../../../api");
9
+ const constants_1 = require("../utils/constants");
10
+ const cowService_1 = require("../utils/cowService");
11
+ const helpers_1 = require("../utils/helpers/helpers");
12
+ async function cowExecuteTrade({ apiUrl, adapter }, { trade, wallet }) {
13
+ const cowTrade = trade;
14
+ const { sellAsset, buyAsset, feeAmountInSellToken, sellAmountWithoutFee } = cowTrade;
15
+ const { assetReference: sellAssetErc20Address, assetNamespace: sellAssetNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
16
+ const { assetReference: buyAssetErc20Address, assetNamespace: buyAssetNamespace } = (0, caip_1.fromAssetId)(buyAsset.assetId);
17
+ if (buyAssetNamespace !== 'erc20' || sellAssetNamespace !== 'erc20') {
18
+ throw new api_1.SwapError('[cowExecuteTrade] - Both assets need to be ERC-20 to use CowSwap', {
19
+ code: api_1.SwapErrorTypes.UNSUPPORTED_PAIR,
20
+ details: { buyAssetNamespace, sellAssetNamespace }
21
+ });
22
+ }
23
+ try {
24
+ const orderToSign = {
25
+ sellToken: sellAssetErc20Address,
26
+ buyToken: buyAssetErc20Address,
27
+ sellAmount: sellAmountWithoutFee,
28
+ buyAmount: trade.buyAmount,
29
+ validTo: (0, helpers_1.getNowPlusThirtyMinutesTimestamp)(),
30
+ appData: constants_1.DEFAULT_APP_DATA,
31
+ feeAmount: feeAmountInSellToken,
32
+ kind: constants_1.ORDER_KIND_SELL,
33
+ partiallyFillable: false,
34
+ receiver: trade.receiveAddress,
35
+ sellTokenBalance: constants_1.ERC20_TOKEN_BALANCE,
36
+ buyTokenBalance: constants_1.ERC20_TOKEN_BALANCE
37
+ };
38
+ // We need to construct orderDigest, sign it and send it to cowSwap API, in order to submit a trade
39
+ // Some context about this : https://docs.cow.fi/tutorials/how-to-submit-orders-via-the-api/4.-signing-the-order
40
+ // For more info, check hashOrder method implementation
41
+ const orderDigest = (0, helpers_1.hashOrder)((0, helpers_1.domain)(1, constants_1.COW_SWAP_SETTLEMENT_ADDRESS), orderToSign);
42
+ const bip44Params = chain_adapters_1.ethereum.ChainAdapter.defaultBIP44Params;
43
+ const message = {
44
+ messageToSign: {
45
+ addressNList: (0, hdwallet_core_1.bip32ToAddressNList)((0, chain_adapters_1.toRootDerivationPath)(bip44Params)),
46
+ message: ethers_1.ethers.utils.arrayify(orderDigest)
47
+ },
48
+ wallet
49
+ };
50
+ const signatureOrderDigest = await adapter.signMessage(message);
51
+ // Passing the signature through split/join to normalize the `v` byte.
52
+ // Some wallets do not pad it with `27`, which causes a signature failure
53
+ // `splitSignature` pads it if needed, and `joinSignature` simply puts it back together
54
+ const signature = ethers_1.ethers.utils.joinSignature(ethers_1.ethers.utils.splitSignature(signatureOrderDigest));
55
+ /**
56
+ * /v1/orders
57
+ * params: {
58
+ * sellToken: contract address of token to sell
59
+ * buyToken: contractAddress of token to buy
60
+ * receiver: receiver address
61
+ * validTo: time duration during which order is valid (putting current timestamp + 30 minutes for real order)
62
+ * appData: appData that can be used later, can be defaulted to "0x0000000000000000000000000000000000000000000000000000000000000000"
63
+ * partiallyFillable: false
64
+ * from: sender address
65
+ * kind: "sell" or "buy"
66
+ * feeAmount: amount of fee in sellToken base
67
+ * sellTokenBalance: "erc20" string,
68
+ * buyTokenBalance: "erc20" string,
69
+ * signingScheme: the signing scheme used for the signature
70
+ * signature: a signed message specific to cowswap for this order
71
+ * from: same as receiver address in our case
72
+ * }
73
+ */
74
+ const ordersResponse = await cowService_1.cowService.post(`${apiUrl}/v1/orders/`, {
75
+ ...orderToSign,
76
+ signingScheme: constants_1.SIGNING_SCHEME,
77
+ signature,
78
+ from: trade.receiveAddress
79
+ });
80
+ return { tradeId: ordersResponse.data };
81
+ }
82
+ catch (e) {
83
+ if (e instanceof api_1.SwapError)
84
+ throw e;
85
+ throw new api_1.SwapError('[cowExecuteTrade]', {
86
+ cause: e,
87
+ code: api_1.SwapErrorTypes.EXECUTE_TRADE_FAILED
88
+ });
89
+ }
90
+ }
91
+ exports.cowExecuteTrade = cowExecuteTrade;
@@ -0,0 +1,3 @@
1
+ import { TradeResult, TradeTxs } from '../../../api';
2
+ import { CowSwapperDeps } from '../CowSwapper';
3
+ export declare function cowGetTradeTxs(deps: CowSwapperDeps, input: TradeResult): Promise<TradeTxs>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cowGetTradeTxs = void 0;
4
+ const api_1 = require("../../../api");
5
+ const constants_1 = require("../utils/constants");
6
+ const cowService_1 = require("../utils/cowService");
7
+ async function cowGetTradeTxs(deps, input) {
8
+ try {
9
+ const getOrdersResponse = await cowService_1.cowService.get(`${deps.apiUrl}/v1/orders/${input.tradeId}`);
10
+ const { data: { status } } = getOrdersResponse;
11
+ if (status !== constants_1.ORDER_STATUS_FULFILLED) {
12
+ return {
13
+ sellTxid: ''
14
+ };
15
+ }
16
+ const getTradesResponse = await cowService_1.cowService.get(`${deps.apiUrl}/v1/trades/?orderUid=${input.tradeId}`);
17
+ return {
18
+ sellTxid: '',
19
+ buyTxid: getTradesResponse.data[0].txHash
20
+ };
21
+ }
22
+ catch (e) {
23
+ if (e instanceof api_1.SwapError)
24
+ throw e;
25
+ throw new api_1.SwapError('[cowGetTradeTxs]', {
26
+ cause: e,
27
+ code: api_1.SwapErrorTypes.GET_TRADE_TXS_FAILED
28
+ });
29
+ }
30
+ }
31
+ exports.cowGetTradeTxs = cowGetTradeTxs;
@@ -12,7 +12,7 @@ const helpers_2 = require("../utils/helpers/helpers");
12
12
  async function getCowSwapTradeQuote(deps, input) {
13
13
  try {
14
14
  const { sellAsset, buyAsset, sellAmount, sellAssetAccountNumber, wallet } = input;
15
- const { adapter, feeAsset, web3 } = deps;
15
+ const { adapter, web3 } = deps;
16
16
  const { assetReference: sellAssetErc20Address, assetNamespace: sellAssetNamespace } = (0, caip_1.fromAssetId)(sellAsset.assetId);
17
17
  const { assetReference: buyAssetErc20Address, assetNamespace: buyAssetNamespace } = (0, caip_1.fromAssetId)(buyAsset.assetId);
18
18
  if (buyAssetNamespace !== 'erc20' || sellAssetNamespace !== 'erc20') {
@@ -61,33 +61,26 @@ async function getCowSwapTradeQuote(deps, input) {
61
61
  spenderAddress: constants_1.COW_SWAP_VAULT_RELAYER_ADDRESS,
62
62
  contractAddress: sellAssetErc20Address
63
63
  });
64
- const [feeDataOptions, feeAssetUsdRate, sellAssetUsdRate] = await Promise.all([
64
+ const [feeDataOptions, sellAssetUsdRate] = await Promise.all([
65
65
  adapter.getFeeData({
66
66
  to: sellAssetErc20Address,
67
67
  value: '0',
68
68
  chainSpecific: { from: receiveAddress, contractData: data }
69
69
  }),
70
- (0, helpers_2.getUsdRate)(deps, feeAsset),
71
70
  (0, helpers_2.getUsdRate)(deps, sellAsset)
72
71
  ]);
73
72
  const feeData = feeDataOptions['fast'];
74
- // quote.feeAmount is expressed in sellAsset token
75
- // We need fee to be expressed in feeAsset token
76
- // feeInFeeAsset * feeAssetUsdRate = feeInSellAsset * sellAssetUsdRate
77
- // hence feeInFeeAsset = feeInSellAsset * sellAssetUsdRate / feeAssetUsdRate
78
- const feeInSellAsset = (0, bignumber_1.bnOrZero)(quote.feeAmount).div((0, bignumber_1.bn)(10).exponentiatedBy(sellAsset.precision));
79
- // feeInFeeAsset = feeInSellAsset * sellAssetUsdRate / feeAssetUsdRate
80
- const feeInFeeAsset = feeInSellAsset
73
+ // calculating trade fee in USD
74
+ const tradeFeeFiat = (0, bignumber_1.bnOrZero)(quote.feeAmount)
75
+ .div((0, bignumber_1.bn)(10).exponentiatedBy(sellAsset.precision))
81
76
  .multipliedBy((0, bignumber_1.bnOrZero)(sellAssetUsdRate))
82
- .div((0, bignumber_1.bnOrZero)(feeAssetUsdRate));
83
- // taking precision into account
84
- const fee = feeInFeeAsset.multipliedBy((0, bignumber_1.bn)(10).exponentiatedBy(feeAsset.precision)).toString();
77
+ .toString();
85
78
  return {
86
79
  rate,
87
80
  minimum,
88
81
  maximum,
89
82
  feeData: {
90
- fee,
83
+ fee: '0',
91
84
  chainSpecific: {
92
85
  estimatedGas: feeData.chainSpecific.gasLimit,
93
86
  gasPrice: feeData.chainSpecific.gasPrice,
@@ -95,7 +88,7 @@ async function getCowSwapTradeQuote(deps, input) {
95
88
  .multipliedBy((0, bignumber_1.bnOrZero)(feeData.chainSpecific.gasPrice))
96
89
  .toString()
97
90
  },
98
- tradeFee: '0'
91
+ tradeFee: tradeFeeFiat
99
92
  },
100
93
  sellAmount: normalizedSellAmount,
101
94
  buyAmount: quote.buyAmount,
@@ -1,3 +1,5 @@
1
+ import { ChainId } from '@shapeshiftoss/caip';
2
+ import { Trade } from '../../api';
1
3
  export declare type CowSwapPriceResponse = {
2
4
  amount: string;
3
5
  token: string;
@@ -18,3 +20,14 @@ export declare type CowSwapQuoteResponse = {
18
20
  from: string;
19
21
  expiration: string;
20
22
  };
23
+ export declare type CowSwapGetOrdersResponse = {
24
+ status: string;
25
+ };
26
+ export declare type CowSwapGetTradesElement = {
27
+ txHash: string;
28
+ };
29
+ export declare type CowSwapGetTradesResponse = Array<CowSwapGetTradesElement>;
30
+ export interface CowTrade<C extends ChainId> extends Trade<C> {
31
+ feeAmountInSellToken: string;
32
+ sellAmountWithoutFee: string;
33
+ }
@@ -8,4 +8,8 @@ export declare const DEFAULT_SOURCE: {
8
8
  export declare const DEFAULT_ADDRESS = "0x0000000000000000000000000000000000000000";
9
9
  export declare const DEFAULT_APP_DATA = "0x0000000000000000000000000000000000000000000000000000000000000000";
10
10
  export declare const COW_SWAP_VAULT_RELAYER_ADDRESS = "0xc92e8bdf79f0507f65a392b0ab4667716bfe0110";
11
+ export declare const COW_SWAP_SETTLEMENT_ADDRESS = "0x9008D19f58AAbD9eD0D60971565AA8510560ab41";
11
12
  export declare const ORDER_KIND_SELL = "sell";
13
+ export declare const SIGNING_SCHEME = "ethsign";
14
+ export declare const ERC20_TOKEN_BALANCE = "erc20";
15
+ export declare const ORDER_STATUS_FULFILLED = "fulfilled";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ORDER_KIND_SELL = exports.COW_SWAP_VAULT_RELAYER_ADDRESS = exports.DEFAULT_APP_DATA = exports.DEFAULT_ADDRESS = exports.DEFAULT_SOURCE = exports.MIN_COWSWAP_VALUE_USD = exports.MAX_COWSWAP_TRADE = exports.MAX_ALLOWANCE = void 0;
3
+ exports.ORDER_STATUS_FULFILLED = exports.ERC20_TOKEN_BALANCE = exports.SIGNING_SCHEME = exports.ORDER_KIND_SELL = exports.COW_SWAP_SETTLEMENT_ADDRESS = exports.COW_SWAP_VAULT_RELAYER_ADDRESS = exports.DEFAULT_APP_DATA = exports.DEFAULT_ADDRESS = exports.DEFAULT_SOURCE = exports.MIN_COWSWAP_VALUE_USD = exports.MAX_COWSWAP_TRADE = exports.MAX_ALLOWANCE = void 0;
4
4
  const constants_1 = require("@ethersproject/constants");
5
5
  exports.MAX_ALLOWANCE = '100000000000000000000000000';
6
6
  exports.MAX_COWSWAP_TRADE = '100000000000000000000000000';
@@ -9,4 +9,8 @@ exports.DEFAULT_SOURCE = [{ name: 'CowSwap', proportion: '1' }];
9
9
  exports.DEFAULT_ADDRESS = constants_1.AddressZero;
10
10
  exports.DEFAULT_APP_DATA = constants_1.HashZero;
11
11
  exports.COW_SWAP_VAULT_RELAYER_ADDRESS = '0xc92e8bdf79f0507f65a392b0ab4667716bfe0110';
12
+ exports.COW_SWAP_SETTLEMENT_ADDRESS = '0x9008D19f58AAbD9eD0D60971565AA8510560ab41';
12
13
  exports.ORDER_KIND_SELL = 'sell';
14
+ exports.SIGNING_SCHEME = 'ethsign';
15
+ exports.ERC20_TOKEN_BALANCE = 'erc20';
16
+ exports.ORDER_STATUS_FULFILLED = 'fulfilled';
@@ -1,5 +1,28 @@
1
+ import { TypedDataDomain, TypedDataField } from '@ethersproject/abstract-signer';
1
2
  import { Asset } from '@shapeshiftoss/types';
2
3
  import { CowSwapperDeps } from '../../CowSwapper';
4
+ export declare const ORDER_TYPE_FIELDS: {
5
+ name: string;
6
+ type: string;
7
+ }[];
8
+ /**
9
+ * EIP-712 typed data type definitions.
10
+ */
11
+ export declare type TypedDataTypes = Record<string, Array<TypedDataField>>;
12
+ export declare type CowSwapOrder = {
13
+ sellToken: string;
14
+ buyToken: string;
15
+ sellAmount: string;
16
+ buyAmount: string;
17
+ validTo: number;
18
+ appData: string;
19
+ feeAmount: string;
20
+ kind: string;
21
+ partiallyFillable: boolean;
22
+ receiver: string;
23
+ sellTokenBalance: string;
24
+ buyTokenBalance: string;
25
+ };
3
26
  export declare type CowSwapQuoteApiInput = {
4
27
  appData: string;
5
28
  buyToken: string;
@@ -13,3 +36,17 @@ export declare type CowSwapQuoteApiInput = {
13
36
  };
14
37
  export declare const getUsdRate: ({ apiUrl, feeAsset }: CowSwapperDeps, input: Asset) => Promise<string>;
15
38
  export declare const getNowPlusThirtyMinutesTimestamp: () => number;
39
+ export declare const hashTypedData: (domain: TypedDataDomain, types: TypedDataTypes, data: Record<string, unknown>) => string;
40
+ /**
41
+ * Compute the 32-byte signing hash for the specified order.
42
+ * Implementation is following https://github.com/cowprotocol/contracts/blob/main/src/ts/order.ts
43
+ * Some more ressources that can be useful :
44
+ * https://docs.cow.fi/tutorials/how-to-submit-orders-via-the-api/4.-signing-the-order
45
+ * https://docs.cow.fi/smart-contracts/settlement-contract/signature-schemes
46
+ *
47
+ * @param domain The EIP-712 domain separator to compute the hash for.
48
+ * @param order The order to compute the digest for.
49
+ * @return Hex-encoded 32-byte order digest.
50
+ */
51
+ export declare const hashOrder: (domain: TypedDataDomain, order: CowSwapOrder) => string;
52
+ export declare const domain: (chainId: number, verifyingContract: string) => TypedDataDomain;
@@ -1,12 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getNowPlusThirtyMinutesTimestamp = exports.getUsdRate = void 0;
3
+ exports.domain = exports.hashOrder = exports.hashTypedData = exports.getNowPlusThirtyMinutesTimestamp = exports.getUsdRate = exports.ORDER_TYPE_FIELDS = void 0;
4
4
  const caip_1 = require("@shapeshiftoss/caip");
5
+ const ethers_1 = require("ethers");
5
6
  const api_1 = require("../../../../api");
6
7
  const bignumber_1 = require("../../../utils/bignumber");
7
8
  const cowService_1 = require("../cowService");
8
9
  const USDC_CONTRACT_ADDRESS = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
9
10
  const USDC_ASSET_PRECISION = 6;
11
+ exports.ORDER_TYPE_FIELDS = [
12
+ { name: 'sellToken', type: 'address' },
13
+ { name: 'buyToken', type: 'address' },
14
+ { name: 'receiver', type: 'address' },
15
+ { name: 'sellAmount', type: 'uint256' },
16
+ { name: 'buyAmount', type: 'uint256' },
17
+ { name: 'validTo', type: 'uint32' },
18
+ { name: 'appData', type: 'bytes32' },
19
+ { name: 'feeAmount', type: 'uint256' },
20
+ { name: 'kind', type: 'string' },
21
+ { name: 'partiallyFillable', type: 'bool' },
22
+ { name: 'sellTokenBalance', type: 'string' },
23
+ { name: 'buyTokenBalance', type: 'string' }
24
+ ];
10
25
  const getUsdRate = async ({ apiUrl, feeAsset }, input) => {
11
26
  // Replacing ETH by WETH specifically for CowSwap in order to get an usd rate when called with ETH as feeAsset
12
27
  const asset = input.assetId !== caip_1.ethAssetId ? input : feeAsset;
@@ -51,3 +66,31 @@ const getNowPlusThirtyMinutesTimestamp = () => {
51
66
  return Math.round(ts.getTime() / 1000);
52
67
  };
53
68
  exports.getNowPlusThirtyMinutesTimestamp = getNowPlusThirtyMinutesTimestamp;
69
+ const hashTypedData = (domain, types, data) => {
70
+ return ethers_1.ethers.utils._TypedDataEncoder.hash(domain, types, data);
71
+ };
72
+ exports.hashTypedData = hashTypedData;
73
+ /**
74
+ * Compute the 32-byte signing hash for the specified order.
75
+ * Implementation is following https://github.com/cowprotocol/contracts/blob/main/src/ts/order.ts
76
+ * Some more ressources that can be useful :
77
+ * https://docs.cow.fi/tutorials/how-to-submit-orders-via-the-api/4.-signing-the-order
78
+ * https://docs.cow.fi/smart-contracts/settlement-contract/signature-schemes
79
+ *
80
+ * @param domain The EIP-712 domain separator to compute the hash for.
81
+ * @param order The order to compute the digest for.
82
+ * @return Hex-encoded 32-byte order digest.
83
+ */
84
+ const hashOrder = (domain, order) => {
85
+ return (0, exports.hashTypedData)(domain, { Order: exports.ORDER_TYPE_FIELDS }, order);
86
+ };
87
+ exports.hashOrder = hashOrder;
88
+ const domain = (chainId, verifyingContract) => {
89
+ return {
90
+ name: 'Gnosis Protocol',
91
+ version: 'v2',
92
+ chainId,
93
+ verifyingContract
94
+ };
95
+ };
96
+ exports.domain = domain;
@@ -4,7 +4,7 @@ import { ApprovalNeededOutput, BuildTradeInput, BuyAssetBySellIdInput, ExecuteTr
4
4
  import { OsmoSwapperDeps } from './utils/types';
5
5
  export declare class OsmosisSwapper implements Swapper<ChainId> {
6
6
  readonly name = "Osmosis";
7
- supportAssets: string[];
7
+ supportedAssetIds: string[];
8
8
  deps: OsmoSwapperDeps;
9
9
  getType(): SwapperType;
10
10
  constructor(deps: OsmoSwapperDeps);
@@ -10,7 +10,7 @@ class OsmosisSwapper {
10
10
  constructor(deps) {
11
11
  this.name = 'Osmosis';
12
12
  this.deps = deps;
13
- this.supportAssets = [caip_1.cosmosAssetId, caip_1.osmosisAssetId];
13
+ this.supportedAssetIds = [caip_1.cosmosAssetId, caip_1.osmosisAssetId];
14
14
  }
15
15
  getType() {
16
16
  return api_1.SwapperType.Osmosis;
@@ -52,13 +52,13 @@ class OsmosisSwapper {
52
52
  });
53
53
  }
54
54
  filterBuyAssetsBySellAssetId(args) {
55
- const { sellAssetId } = args;
56
- if (!this.supportAssets.includes(sellAssetId))
55
+ const { assetIds = [], sellAssetId } = args;
56
+ if (!this.supportedAssetIds.includes(sellAssetId))
57
57
  return [];
58
- return this.supportAssets;
58
+ return assetIds.filter((assetId) => this.supportedAssetIds.includes(assetId) && assetId !== sellAssetId);
59
59
  }
60
60
  filterAssetIdsBySellable() {
61
- return this.supportAssets;
61
+ return this.supportedAssetIds;
62
62
  }
63
63
  async buildTrade(args) {
64
64
  const { sellAsset, buyAsset, sellAmount, receiveAddress } = args;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshiftoss/swapper",
3
- "version": "8.5.1",
3
+ "version": "8.6.0",
4
4
  "description": "An interface and implementations to trade coins via various protocols",
5
5
  "repository": "https://github.com/shapeshift/lib",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "@shapeshiftoss/caip": "^6.2.0",
35
35
  "@shapeshiftoss/chain-adapters": "^7.2.0",
36
36
  "@shapeshiftoss/errors": "^1.1.2",
37
- "@shapeshiftoss/hdwallet-core": "^1.23.0",
37
+ "@shapeshiftoss/hdwallet-core": "^1.27.0",
38
38
  "@shapeshiftoss/types": "^7.0.0"
39
39
  },
40
40
  "devDependencies": {
@@ -42,7 +42,7 @@
42
42
  "@shapeshiftoss/caip": "^6.2.0",
43
43
  "@shapeshiftoss/chain-adapters": "^7.2.0",
44
44
  "@shapeshiftoss/errors": "^1.1.2",
45
- "@shapeshiftoss/hdwallet-core": "^1.23.0",
45
+ "@shapeshiftoss/hdwallet-core": "^1.27.0",
46
46
  "@shapeshiftoss/types": "^7.0.0",
47
47
  "@types/readline-sync": "^1.4.4",
48
48
  "readline-sync": "^1.4.10",