Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: release v1.722.0 #8337

Merged
merged 7 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/swapper/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { assertUnreachable } from '@shapeshiftoss/utils'

import { COW_SWAP_SUPPORTED_CHAIN_IDS } from './cowswap-utils/constants'
import { arbitrumBridgeSwapper } from './swappers/ArbitrumBridgeSwapper/ArbitrumBridgeSwapper'
import { arbitrumBridgeApi } from './swappers/ArbitrumBridgeSwapper/endpoints'
import { ARBITRUM_BRIDGE_SUPPORTED_CHAIN_IDS } from './swappers/ArbitrumBridgeSwapper/utils/constants'
Expand All @@ -8,7 +9,6 @@ import { CHAINFLIP_SUPPORTED_CHAIN_IDS } from './swappers/ChainflipSwapper/const
import { chainflipApi } from './swappers/ChainflipSwapper/endpoints'
import { cowSwapper } from './swappers/CowSwapper/CowSwapper'
import { cowApi } from './swappers/CowSwapper/endpoints'
import { COW_SWAP_SUPPORTED_CHAIN_IDS } from './swappers/CowSwapper/utils/constants'
import { jupiterApi } from './swappers/JupiterSwapper/endpoints'
import { jupiterSwapper } from './swappers/JupiterSwapper/JupiterSwapper'
import { JUPITER_SUPPORTED_CHAIN_IDS } from './swappers/JupiterSwapper/utils/constants'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,26 @@ import type { ChainId } from '@shapeshiftoss/caip'
import { KnownChainIds } from '@shapeshiftoss/types'
import { zeroAddress } from 'viem'

import type { SupportedChainIds } from '../../../types'
import type { SupportedChainIds } from '../types'

export const DEFAULT_ADDRESS = zeroAddress
export const ORDER_TYPE_FIELDS = [
{ name: 'sellToken', type: 'address' },
{ name: 'buyToken', type: 'address' },
{ name: 'receiver', type: 'address' },
{ name: 'sellAmount', type: 'uint256' },
{ name: 'buyAmount', type: 'uint256' },
{ name: 'validTo', type: 'uint32' },
{ name: 'appData', type: 'bytes32' },
{ name: 'feeAmount', type: 'uint256' },
{ name: 'kind', type: 'string' },
{ name: 'partiallyFillable', type: 'bool' },
{ name: 'sellTokenBalance', type: 'string' },
{ name: 'buyTokenBalance', type: 'string' },
]

export const COW_SWAP_VAULT_RELAYER_ADDRESS = '0xc92e8bdf79f0507f65a392b0ab4667716bfe0110'
export const COW_SWAP_SETTLEMENT_ADDRESS = '0x9008D19f58AAbD9eD0D60971565AA8510560ab41'
export const CANCELLATIONS_TYPE_FIELDS = [{ name: 'orderUids', type: 'bytes[]' }]

// Address used by CowSwap to buy ETH
// See https://github.com/gnosis/gp-v2-contracts/commit/821b5a8da213297b0f7f1d8b17c893c5627020af#diff-12bbbe13cd5cf42d639e34a39d8795021ba40d3ee1e1a8282df652eb161a11d6R13
export const COW_SWAP_NATIVE_ASSET_MARKER_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
export const DEFAULT_ADDRESS = zeroAddress

export const SUPPORTED_CHAIN_IDS: ChainId[] = [
KnownChainIds.EthereumMainnet,
Expand All @@ -23,3 +33,10 @@ export const COW_SWAP_SUPPORTED_CHAIN_IDS: SupportedChainIds = {
sell: SUPPORTED_CHAIN_IDS,
buy: SUPPORTED_CHAIN_IDS,
}

export const COW_SWAP_VAULT_RELAYER_ADDRESS = '0xc92e8bdf79f0507f65a392b0ab4667716bfe0110'
export const COW_SWAP_SETTLEMENT_ADDRESS = '0x9008D19f58AAbD9eD0D60971565AA8510560ab41'

// Address used by CowSwap to buy ETH
// See https://github.com/gnosis/gp-v2-contracts/commit/821b5a8da213297b0f7f1d8b17c893c5627020af#diff-12bbbe13cd5cf42d639e34a39d8795021ba40d3ee1e1a8282df652eb161a11d6R13
export const COW_SWAP_NATIVE_ASSET_MARKER_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
116 changes: 97 additions & 19 deletions packages/swapper/src/cowswap-utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
import type { LatestAppDataDocVersion } from '@cowprotocol/app-data'
import { MetadataApi, stringifyDeterministic } from '@cowprotocol/app-data'
import type { OrderClass, OrderClass1 } from '@cowprotocol/app-data/dist/generatedTypes/v1.3.0'
import type { ChainId } from '@shapeshiftoss/caip'
import { fromChainId } from '@shapeshiftoss/caip'
import { ASSET_NAMESPACE, fromChainId, toAssetId } from '@shapeshiftoss/caip'
import type { EvmChainAdapter, SignTypedDataInput } from '@shapeshiftoss/chain-adapters'
import { toAddressNList } from '@shapeshiftoss/chain-adapters'
import type { ETHSignTypedData, HDWallet } from '@shapeshiftoss/hdwallet-core'
import type { AccountMetadata, TypedDataTypes, UnsignedOrderCreation } from '@shapeshiftoss/types'
import { CowNetwork, KnownChainIds, TypedDataPrimaryType } from '@shapeshiftoss/types'
import {
bnOrZero,
convertDecimalPercentageToBasisPoints,
getNativeFeeAssetReference,
} from '@shapeshiftoss/utils'
import type { TypedData } from 'eip-712'
import type { TypedDataDomain } from 'ethers'
import { ethers } from 'ethers'
import type { Address } from 'viem'
import { keccak256, stringToBytes } from 'viem'

import { COW_SWAP_SETTLEMENT_ADDRESS } from '../swappers/CowSwapper'

export const ORDER_TYPE_FIELDS = [
{ name: 'sellToken', type: 'address' },
{ name: 'buyToken', type: 'address' },
{ name: 'receiver', type: 'address' },
{ name: 'sellAmount', type: 'uint256' },
{ name: 'buyAmount', type: 'uint256' },
{ name: 'validTo', type: 'uint32' },
{ name: 'appData', type: 'bytes32' },
{ name: 'feeAmount', type: 'uint256' },
{ name: 'kind', type: 'string' },
{ name: 'partiallyFillable', type: 'bool' },
{ name: 'sellTokenBalance', type: 'string' },
{ name: 'buyTokenBalance', type: 'string' },
]

export const CANCELLATIONS_TYPE_FIELDS = [{ name: 'orderUids', type: 'bytes[]' }]
import type { AffiliateAppDataFragment } from '../swappers/CowSwapper'
import { getTreasuryAddressFromChainId } from '../swappers/utils/helpers/helpers'
import {
CANCELLATIONS_TYPE_FIELDS,
COW_SWAP_NATIVE_ASSET_MARKER_ADDRESS,
COW_SWAP_SETTLEMENT_ADDRESS,
ORDER_TYPE_FIELDS,
} from './constants'

export * from './constants'

export const getCowNetwork = (chainId: ChainId): CowNetwork | undefined => {
switch (chainId) {
Expand Down Expand Up @@ -157,3 +159,79 @@ export const signCowOrderCancellation = async (

return signature
}

export const cowSwapTokenToAssetId = (chainId: ChainId, cowSwapToken: Address) => {
const { chainNamespace, chainReference } = fromChainId(chainId)
return cowSwapToken.toLowerCase() === COW_SWAP_NATIVE_ASSET_MARKER_ADDRESS.toLowerCase()
? toAssetId({
chainId,
assetNamespace: 'slip44',
assetReference: getNativeFeeAssetReference(chainNamespace, chainReference),
})
: toAssetId({
chainId,
assetNamespace: ASSET_NAMESPACE.erc20,
assetReference: cowSwapToken,
})
}

export const getAffiliateAppDataFragmentByChainId = ({
affiliateBps,
chainId,
}: {
affiliateBps: string
chainId: ChainId
}): AffiliateAppDataFragment => {
const hasAffiliateFee = bnOrZero(affiliateBps).gt(0)
if (!hasAffiliateFee) return {}

return {
partnerFee: {
bps: Number(affiliateBps),
recipient: getTreasuryAddressFromChainId(chainId),
},
}
}

type AppDataInfo = {
doc: LatestAppDataDocVersion
fullAppData: string
appDataKeccak256: string
env?: string
}

const generateAppDataFromDoc = async (
doc: LatestAppDataDocVersion,
): Promise<Pick<AppDataInfo, 'fullAppData' | 'appDataKeccak256'>> => {
const appData = await stringifyDeterministic(doc)
const appDataKeccak256 = keccak256(stringToBytes(appData))

return { fullAppData: appData, appDataKeccak256 }
}

const metadataApi = new MetadataApi()

// See https://api.cow.fi/docs/#/default/post_api_v1_quote / https://github.com/cowprotocol/app-data
export const getFullAppData = async (
slippageTolerancePercentage: string,
affiliateAppDataFragment: AffiliateAppDataFragment,
orderClass1: OrderClass1,
) => {
const APP_CODE = 'shapeshift'
const orderClass: OrderClass = { orderClass: orderClass1 }
const quote = {
slippageBips: convertDecimalPercentageToBasisPoints(slippageTolerancePercentage).toNumber(),
}

const appDataDoc = await metadataApi.generateAppDataDoc({
appCode: APP_CODE,
metadata: {
quote,
orderClass,
...affiliateAppDataFragment,
},
})

const { fullAppData, appDataKeccak256 } = await generateAppDataFromDoc(appDataDoc)
return { appDataHash: appDataKeccak256, appData: fullAppData }
}
13 changes: 6 additions & 7 deletions packages/swapper/src/swappers/CowSwapper/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import type { InterpolationOptions } from 'node-polyglot'
import { v4 as uuid } from 'uuid'

import { getDefaultSlippageDecimalPercentageForSwapper } from '../../constants'
import { assertGetCowNetwork } from '../../cowswap-utils'
import {
assertGetCowNetwork,
getAffiliateAppDataFragmentByChainId,
getFullAppData,
} from '../../cowswap-utils'
import type {
CommonTradeQuoteInput,
EvmMessageToSign,
Expand All @@ -31,12 +35,7 @@ import { getCowSwapTradeQuote } from './getCowSwapTradeQuote/getCowSwapTradeQuot
import { getCowSwapTradeRate } from './getCowSwapTradeRate/getCowSwapTradeRate'
import type { CowSwapGetTradesResponse, CowSwapGetTransactionsResponse } from './types'
import { cowService } from './utils/cowService'
import {
deductAffiliateFeesFromAmount,
deductSlippageFromAmount,
getAffiliateAppDataFragmentByChainId,
getFullAppData,
} from './utils/helpers/helpers'
import { deductAffiliateFeesFromAmount, deductSlippageFromAmount } from './utils/helpers/helpers'

const tradeQuoteMetadata: Map<string, { chainId: EvmChainId }> = new Map()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { AssetId } from '@shapeshiftoss/caip'
import type { Asset } from '@shapeshiftoss/types'

import { SUPPORTED_CHAIN_IDS } from '../../../cowswap-utils/constants'
import { isNativeEvmAsset } from '../../utils/helpers/helpers'
import { COWSWAP_UNSUPPORTED_ASSETS } from '../utils/blacklist'
import { SUPPORTED_CHAIN_IDS } from '../utils/constants'

export const filterAssetIdsBySellable = (assets: Asset[]): AssetId[] => {
return assets
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { AssetId } from '@shapeshiftoss/caip'

import { SUPPORTED_CHAIN_IDS } from '../../../cowswap-utils/constants'
import type { BuyAssetBySellIdInput } from '../../../types'
import { isNativeEvmAsset } from '../../utils/helpers/helpers'
import { COWSWAP_UNSUPPORTED_ASSETS } from '../utils/blacklist'
import { SUPPORTED_CHAIN_IDS } from '../utils/constants'

export const filterBuyAssetsBySellAssetId = ({
assets,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { Ok } from '@sniptt/monads'
import type { AxiosResponse } from 'axios'
import { describe, expect, it, vi } from 'vitest'

import {
COW_SWAP_NATIVE_ASSET_MARKER_ADDRESS,
DEFAULT_ADDRESS,
} from '../../../cowswap-utils/constants'
import type { GetTradeQuoteInput, SwapperConfig, TradeQuote } from '../../../types'
import { SwapperName, TradeQuoteError } from '../../../types'
import {
Expand All @@ -15,7 +19,6 @@ import {
WETH,
XDAI,
} from '../../utils/test-data/assets'
import { COW_SWAP_NATIVE_ASSET_MARKER_ADDRESS, DEFAULT_ADDRESS } from '../utils/constants'
import { cowService } from '../utils/cowService'
import type { CowSwapSellQuoteApiInput } from '../utils/helpers/helpers'
import { getCowSwapTradeQuote } from './getCowSwapTradeQuote'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,16 @@ import type { AxiosError } from 'axios'
import { zeroAddress } from 'viem'

import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants'
import { getCowNetwork } from '../../../cowswap-utils'
import {
getAffiliateAppDataFragmentByChainId,
getCowNetwork,
getFullAppData,
} from '../../../cowswap-utils'
import {
COW_SWAP_NATIVE_ASSET_MARKER_ADDRESS,
COW_SWAP_VAULT_RELAYER_ADDRESS,
SUPPORTED_CHAIN_IDS,
} from '../../../cowswap-utils/constants'
import type {
GetEvmTradeQuoteInputBase,
SwapErrorRight,
Expand All @@ -18,16 +27,9 @@ import type {
import { SwapperName, TradeQuoteError } from '../../../types'
import { createTradeAmountTooSmallErr, makeSwapErrorRight } from '../../../utils'
import { isNativeEvmAsset } from '../../utils/helpers/helpers'
import {
COW_SWAP_NATIVE_ASSET_MARKER_ADDRESS,
COW_SWAP_VAULT_RELAYER_ADDRESS,
SUPPORTED_CHAIN_IDS,
} from '../utils/constants'
import { cowService } from '../utils/cowService'
import {
assertValidTrade,
getAffiliateAppDataFragmentByChainId,
getFullAppData,
getNowPlusThirtyMinutesTimestamp,
getValuesFromQuoteResponse,
} from '../utils/helpers/helpers'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@ import type { AxiosError } from 'axios'
import { zeroAddress } from 'viem'

import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants'
import { getCowNetwork } from '../../../cowswap-utils'
import type { GetEvmTradeRateInput, SwapErrorRight, SwapperConfig, TradeRate } from '../../../types'
import { SwapperName, TradeQuoteError } from '../../../types'
import { createTradeAmountTooSmallErr, makeSwapErrorRight } from '../../../utils'
import { isNativeEvmAsset } from '../../utils/helpers/helpers'
import {
getAffiliateAppDataFragmentByChainId,
getCowNetwork,
getFullAppData,
} from '../../../cowswap-utils'
import {
COW_SWAP_NATIVE_ASSET_MARKER_ADDRESS,
COW_SWAP_VAULT_RELAYER_ADDRESS,
SUPPORTED_CHAIN_IDS,
} from '../utils/constants'
} from '../../../cowswap-utils/constants'
import type { GetEvmTradeRateInput, SwapErrorRight, SwapperConfig, TradeRate } from '../../../types'
import { SwapperName, TradeQuoteError } from '../../../types'
import { createTradeAmountTooSmallErr, makeSwapErrorRight } from '../../../utils'
import { isNativeEvmAsset } from '../../utils/helpers/helpers'
import { cowService } from '../utils/cowService'
import {
assertValidTrade,
getAffiliateAppDataFragmentByChainId,
getFullAppData,
getNowPlusThirtyMinutesTimestamp,
getValuesFromQuoteResponse,
} from '../utils/helpers/helpers'
Expand Down
1 change: 0 additions & 1 deletion packages/swapper/src/swappers/CowSwapper/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './types'
export * from './utils'
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import type { AxiosStatic } from 'axios'
import type { Awaitable, HookCleanupCallback } from 'vitest'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'

import { getFullAppData, getNowPlusThirtyMinutesTimestamp } from './helpers'
import { getFullAppData } from '../../../../cowswap-utils'
import { getNowPlusThirtyMinutesTimestamp } from './helpers'

vi.mock('../cowService', async () => {
const axios: AxiosStatic = await vi.importMock('axios')
Expand Down
Loading
Loading