• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

decentraland / marketplace / 13292072337

12 Feb 2025 06:15PM UTC coverage: 66.189% (+0.2%) from 66.034%
13292072337

push

github

web-flow
fix: Gas estimations for trades (#2375)

2708 of 5325 branches covered (50.85%)

Branch coverage included in aggregate %.

16 of 17 new or added lines in 2 files covered. (94.12%)

4 existing lines in 3 files now uncovered.

7912 of 10720 relevant lines covered (73.81%)

77.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.52
/webapp/src/components/Modals/BuyWithCryptoModal/utils.ts
1
import { BigNumber, ethers } from 'ethers'
3✔
2
import { ChainId, Network, Order, Item } from '@dcl/schemas'
3✔
3
import { getNetwork } from '@dcl/schemas/dist/dapps/chain-id'
3✔
4
import { Env } from '@dcl/ui-env'
3✔
5
import { getNetworkProvider } from 'decentraland-dapps/dist/lib/eth'
3✔
6
import { Wallet } from 'decentraland-dapps/dist/modules/wallet/types'
7
import type { ChainData, Token } from 'decentraland-transactions/crossChain'
8
import { ContractName, getContract, getContractName } from 'decentraland-transactions'
3✔
9
import { config } from '../../../config'
3✔
10
import { NFT } from '../../../modules/nft/types'
11
import { estimateTradeGas } from '../../../utils/trades'
3✔
12

13
export const getShouldUseMetaTx = (
51✔
14
  assetChainId: ChainId,
15
  selectedChain: ChainId,
16
  selectedTokenAddress: string,
17
  destinyChainMANA: string,
18
  connectedNetwork: Network
19
) => {
20
  return (
21
    getNetwork(assetChainId) === Network.MATIC &&
108✔
22
    getNetwork(selectedChain) === Network.MATIC &&
23
    selectedTokenAddress.toLowerCase() === destinyChainMANA.toLowerCase() &&
24
    connectedNetwork === Network.ETHEREUM // only trigger meta tx if connected to Ethereum
25
  )
26
}
27

28
export function isToken(opt: Token | ChainData): opt is Token {
25✔
29
  return (opt as Token).decimals !== undefined
24✔
30
}
31

32
export function isChainData(opt: Token | ChainData): opt is ChainData {
1✔
33
  return (opt as ChainData).axelarChainName !== undefined
×
34
}
35

36
export function getMANAToken(chainId: ChainId) {
203✔
37
  const MANAContract = getContract(ContractName.MANAToken, chainId)
202✔
38
  return {
202✔
39
    type: 'evm' as Token['type'],
40
    chainId: chainId.toString(),
41
    address: MANAContract.address,
42
    name: MANAContract.name,
43
    symbol: 'MANA',
44
    decimals: 18,
45
    logoURI: 'https://assets.coingecko.com/coins/images/878/small/decentraland-mana.png',
46
    coingeckoId: '', // not necessary
47
    subGraphId: '', // won't be used since we'll send the metatx or transaction directly
48
    subGraphOnly: false,
49
    volatility: 0, // won't be used since we'll send the metatx or transaction directly
50
    usdPrice: 0 // not necessary
51
  }
52
}
53

54
function truncateToDecimals(num: number, dec = 2) {
×
55
  const calcDec = Math.pow(10, dec)
58✔
56
  return Math.trunc(num * calcDec) / calcDec
58✔
57
}
58

59
export function formatPrice(price: string | number, token: Token): number {
59✔
60
  // Convert price to a number if it's a string
61
  const numericPrice = typeof price === 'string' ? parseFloat(price) : price
58✔
62

63
  // Determine the minimum number of decimals to show based on the value
64
  let decimalsToShow: number
65
  if (token.usdPrice && token.usdPrice >= 1.5) {
58✔
66
    decimalsToShow = 4 // For tokens priced over $1.5, show up to 4 decimals
67
  } else {
68
    decimalsToShow = 2 // Default to 2 decimals
69
  }
70

71
  // Ensure small values are displayed with at least two significant digits
72
  if (numericPrice !== 0 && numericPrice < 0.01) {
58✔
73
    const significantDigits = Math.ceil(-Math.log10(numericPrice)) + 1
6✔
74
    decimalsToShow = Math.max(decimalsToShow, significantDigits)
6✔
75
  }
76

77
  // Format the price using toFixed to round and limit the number of decimals
78
  const formattedPrice = truncateToDecimals(typeof price === 'string' ? Number(price) : price, decimalsToShow)
58✔
79

80
  return formattedPrice
58✔
81
}
82

83
// this are the default chains for the buy with crypto modal since we support buying with MANA on both chains
84
// for L1 and L2 NFTs respectively
85
export const DEFAULT_CHAINS = [
3✔
86
  {
87
    chainId: ChainId.MATIC_MAINNET.toString(),
88
    networkName: 'Polygon',
89
    nativeCurrency: {
90
      name: 'MATIC',
91
      symbol: 'MATIC',
92
      decimals: 18,
93
      icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/matic.svg'
94
    }
95
  },
96
  {
97
    chainId: ChainId.ETHEREUM_MAINNET.toString(),
98
    networkName: 'Ethereum',
99
    nativeCurrency: {
100
      name: 'Ethereum',
101
      symbol: 'ETH',
102
      decimals: 18,
103
      icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/eth.svg'
104
    }
105
  },
106
  {
107
    chainId: ChainId.OPTIMISM_MAINNET.toString(),
108
    networkName: 'Optimism',
109
    nativeCurrency: {
110
      name: 'Optimism',
111
      symbol: 'ETH',
112
      decimals: 18,
113
      icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/optimism.svg'
114
    }
115
  },
116
  {
117
    chainId: ChainId.ARBITRUM_MAINNET.toString(),
118
    networkName: 'Arbitrum',
119
    nativeCurrency: {
120
      name: 'Arbitrum',
121
      symbol: 'ETH',
122
      decimals: 18,
123
      icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/arbitrum.svg'
124
    }
125
  },
126
  {
127
    chainId: ChainId.AVALANCHE_MAINNET.toString(),
128
    networkName: 'Avalanche',
129
    nativeCurrency: {
130
      name: 'Avalanche',
131
      symbol: 'AVAX',
132
      decimals: 18,
133
      icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/avalanche.svg'
134
    }
135
  },
136
  {
137
    chainId: ChainId.BSC_MAINNET.toString(),
138
    networkName: 'BNB Chain',
139
    nativeCurrency: {
140
      name: 'BNB',
141
      symbol: 'BNB',
142
      decimals: 18,
143
      icon: 'https://raw.githubusercontent.com/axelarnetwork/axelar-docs/main/public/images/chains/binance.svg'
144
    }
145
  },
146
  {
147
    chainId: ChainId.FANTOM_MAINNET.toString(),
148
    networkName: 'Fantom',
149
    nativeCurrency: {
150
      name: 'FTM',
151
      symbol: 'FTM',
152
      decimals: 18,
153
      icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/ftm.svg'
154
    }
155
  }
156
] as ChainData[]
157

158
export const TESTNET_DEFAULT_CHAINS = [
3✔
159
  {
160
    chainId: ChainId.MATIC_AMOY.toString(),
161
    networkName: 'Polygon Amoy',
162
    nativeCurrency: {
163
      name: 'MATIC',
164
      symbol: 'MATIC',
165
      decimals: 18,
166
      icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/matic.svg'
167
    }
168
  },
169
  {
170
    chainId: ChainId.ETHEREUM_SEPOLIA.toString(),
171
    networkName: 'Ethereum Sepolia',
172
    nativeCurrency: {
173
      name: 'Ethereum',
174
      symbol: 'ETH',
175
      decimals: 18,
176
      icon: 'https://raw.githubusercontent.com/0xsquid/assets/main/images/tokens/eth.svg'
177
    }
178
  }
179
] as ChainData[]
180

181
export const getDefaultChains = () => {
229✔
182
  if (config.is(Env.DEVELOPMENT)) {
228!
183
    return TESTNET_DEFAULT_CHAINS
×
184
  }
185
  return DEFAULT_CHAINS
228✔
186
}
187

188
export const estimateMintNftGas = async (selectedChain: ChainId, wallet: Wallet, asset: Item): Promise<BigNumber> => {
3✔
189
  const networkProvider = await getNetworkProvider(selectedChain)
2✔
190
  const provider = new ethers.providers.Web3Provider(networkProvider)
2✔
191
  console.log('Estimating minting gas for asset', asset)
2✔
192

193
  if (asset.tradeId) {
2✔
194
    return estimateTradeGas(asset.tradeId, selectedChain, wallet.address, provider)
2✔
195
  }
196

197
  const contract = getContract(ContractName.CollectionStore, asset.chainId)
×
198
  const c = new ethers.Contract(contract.address, contract.abi, provider)
×
199

UNCOV
200
  return c.estimateGas.buy([[asset.contractAddress, [asset.itemId], [asset.price], [wallet.address]]], { from: wallet.address })
×
201
}
202

203
export const estimateBuyNftGas = async (
3✔
204
  selectedChain: ChainId,
205
  wallet: Wallet,
206
  asset: NFT,
207
  order: Order,
208
  fingerprint?: string
209
): Promise<BigNumber> => {
210
  const networkProvider = await getNetworkProvider(selectedChain)
2✔
211
  const provider = new ethers.providers.Web3Provider(networkProvider)
2✔
212

213
  const contractName = getContractName(order.marketplaceAddress)
2✔
214
  const contract = getContract(contractName, order.chainId)
2✔
215
  const c = new ethers.Contract(contract.address, contract.abi, provider)
2✔
216
  if (order.tradeId) {
2✔
217
    return estimateTradeGas(order.tradeId, order.chainId, wallet.address, provider)
2✔
218
  }
219
  // Old order
UNCOV
220
  return fingerprint
×
221
    ? c.estimateGas.safeExecuteOrder(asset.contractAddress, asset.tokenId, order.price, fingerprint, { from: wallet.address })
222
    : c.estimateGas.executeOrder(asset.contractAddress, asset.tokenId, order.price, { from: wallet.address })
223
}
224

225
export const estimateNameMintingGas = async (name: string, selectedChain: ChainId, ownerAddress: string): Promise<BigNumber> => {
3✔
226
  const networkProvider = await getNetworkProvider(selectedChain)
×
227
  const provider = new ethers.providers.Web3Provider(networkProvider)
×
228
  const contract = getContract(ContractName.DCLControllerV2, selectedChain)
×
229
  const c = new ethers.Contract(contract.address, contract.abi, provider)
×
NEW
230
  return c.estimateGas.register(name, ownerAddress, { from: ownerAddress })
×
231
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc