-
Notifications
You must be signed in to change notification settings - Fork 395
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
Binance Smart Chain support #2659
Changes from 24 commits
5754ab6
05f96a0
2aa6920
57a4b74
8ac10df
797869e
599a9b2
2f9191d
fdfb95f
7a7c9f2
cc25336
379717c
a7cb97b
16da743
07fe5ba
fe6c8c5
9265b9c
1476c03
3bf8cb0
a508ad8
65db03a
1304ccb
5f1bb26
8ed47c9
695715a
f3673b0
7cb4384
d40bd51
017c09e
45a2a1f
6cd98f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ export const coinTypesByAssetSymbol = { | |
RBTC: 137, | ||
MATIC: 966, | ||
AVAX: 9000, | ||
BNB: 714, | ||
} as const | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
import { EVMNetwork, Network } from "../networks" | ||
import { AVAX, BTC, ETH, MATIC, OPTIMISTIC_ETH, RBTC } from "./currencies" | ||
import { AVAX, BNB, BTC, ETH, MATIC, OPTIMISTIC_ETH, RBTC } from "./currencies" | ||
|
||
export const ETHEREUM: EVMNetwork = { | ||
name: "Ethereum", | ||
|
@@ -41,6 +41,14 @@ export const AVALANCHE: EVMNetwork = { | |
coingeckoPlatformID: "avalanche", | ||
} | ||
|
||
export const BINANCE_SMART_CHAIN: EVMNetwork = { | ||
name: "BNB Smart Chain", | ||
baseAsset: BNB, | ||
chainID: "56", | ||
family: "EVM", | ||
coingeckoPlatformID: "binance-smart-chain", | ||
} | ||
|
||
export const OPTIMISM: EVMNetwork = { | ||
name: "Optimism", | ||
baseAsset: OPTIMISTIC_ETH, | ||
|
@@ -77,7 +85,9 @@ export const EIP_1559_COMPLIANT_CHAIN_IDS = new Set( | |
) | ||
|
||
export const CHAINS_WITH_MEMPOOL = new Set( | ||
[ETHEREUM, POLYGON, AVALANCHE, GOERLI].map((network) => network.chainID) | ||
[ETHEREUM, POLYGON, AVALANCHE, GOERLI, BINANCE_SMART_CHAIN].map( | ||
(network) => network.chainID | ||
) | ||
) | ||
|
||
export const NETWORK_BY_CHAIN_ID = { | ||
|
@@ -87,6 +97,7 @@ export const NETWORK_BY_CHAIN_ID = { | |
[ARBITRUM_ONE.chainID]: ARBITRUM_ONE, | ||
[AVALANCHE.chainID]: AVALANCHE, | ||
[OPTIMISM.chainID]: OPTIMISM, | ||
[BINANCE_SMART_CHAIN.chainID]: BINANCE_SMART_CHAIN, | ||
[GOERLI.chainID]: GOERLI, | ||
[FORK.chainID]: FORK, | ||
} | ||
|
@@ -107,6 +118,7 @@ export const CHAIN_ID_TO_0X_API_BASE: { | |
[GOERLI.chainID]: "goerli.api.0x.org", | ||
[ARBITRUM_ONE.chainID]: "arbitrum.api.0x.org", | ||
[AVALANCHE.chainID]: "avalanche.api.0x.org", | ||
[BINANCE_SMART_CHAIN.chainID]: "bsc.api.0x.org", | ||
} | ||
|
||
export const NETWORKS_SUPPORTING_SWAPS = new Set( | ||
|
@@ -132,6 +144,7 @@ export const CHAIN_ID_TO_RPC_URLS: { | |
[ARBITRUM_ONE.chainID]: ["https://rpc.ankr.com/arbitrum"], | ||
[GOERLI.chainID]: ["https://ethereum-goerli-rpc.allthatnode.com"], | ||
[AVALANCHE.chainID]: ["https://api.avax.network/ext/bc/C/rpc"], | ||
[BINANCE_SMART_CHAIN.chainID]: ["https://rpc.ankr.com/bsc"], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's add the official one as well |
||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,7 +2,12 @@ import { createSlice } from "@reduxjs/toolkit" | |||||||||||||||||||||
import { createBackgroundAsyncThunk } from "./utils" | ||||||||||||||||||||||
import { AccountBalance, AddressOnNetwork, NameOnNetwork } from "../accounts" | ||||||||||||||||||||||
import { EVMNetwork, Network } from "../networks" | ||||||||||||||||||||||
import { AnyAsset, AnyAssetAmount, SmartContractFungibleAsset } from "../assets" | ||||||||||||||||||||||
import { | ||||||||||||||||||||||
AnyAsset, | ||||||||||||||||||||||
AnyAssetAmount, | ||||||||||||||||||||||
isFungibleAsset, | ||||||||||||||||||||||
SmartContractFungibleAsset, | ||||||||||||||||||||||
} from "../assets" | ||||||||||||||||||||||
import { | ||||||||||||||||||||||
AssetMainCurrencyAmount, | ||||||||||||||||||||||
AssetDecimalAmount, | ||||||||||||||||||||||
|
@@ -11,6 +16,7 @@ import { DomainName, HexString, URI } from "../types" | |||||||||||||||||||||
import { normalizeEVMAddress } from "../lib/utils" | ||||||||||||||||||||||
import { AccountSigner } from "../services/signing" | ||||||||||||||||||||||
import { TEST_NETWORK_BY_CHAIN_ID } from "../constants" | ||||||||||||||||||||||
import { convertFixedPoint } from "../lib/fixed-point" | ||||||||||||||||||||||
|
||||||||||||||||||||||
/** | ||||||||||||||||||||||
* The set of available UI account types. These may or may not map 1-to-1 to | ||||||||||||||||||||||
|
@@ -172,9 +178,27 @@ function updateCombinedData(immerState: AccountState) { | |||||||||||||||||||||
[symbol: string]: AnyAssetAmount | ||||||||||||||||||||||
}>((acc, combinedAssetAmount) => { | ||||||||||||||||||||||
const assetSymbol = combinedAssetAmount.asset.symbol | ||||||||||||||||||||||
let { amount } = combinedAssetAmount | ||||||||||||||||||||||
|
||||||||||||||||||||||
if (acc[assetSymbol]?.asset) { | ||||||||||||||||||||||
const accAsset = acc[assetSymbol].asset | ||||||||||||||||||||||
const decimals = isFungibleAsset(accAsset) ? accAsset.decimals : 0 | ||||||||||||||||||||||
const targetDecimals = isFungibleAsset(combinedAssetAmount.asset) | ||||||||||||||||||||||
? combinedAssetAmount.asset.decimals | ||||||||||||||||||||||
: 0 | ||||||||||||||||||||||
|
||||||||||||||||||||||
if (targetDecimals > decimals) { | ||||||||||||||||||||||
amount = convertFixedPoint( | ||||||||||||||||||||||
combinedAssetAmount?.amount, | ||||||||||||||||||||||
decimals, | ||||||||||||||||||||||
targetDecimals | ||||||||||||||||||||||
) | ||||||||||||||||||||||
} | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should be converting here from newAmountDecimals to existingDecimals right? Otherwise the balance is wrong after the object spread below replaces the existing asset (and it's decimals).
Suggested change
Then we can change the existing logic to not overwrite the existing asset if (acc[assetSymbol]) {
acc[assetSymbol].amount += amount
} else {
acc[assetSymbol] = {
...combinedAssetAmount,
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch! |
||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
acc[assetSymbol] = { | ||||||||||||||||||||||
...combinedAssetAmount, | ||||||||||||||||||||||
amount: (acc[assetSymbol]?.amount || 0n) + combinedAssetAmount.amount, | ||||||||||||||||||||||
amount: (acc[assetSymbol]?.amount || 0n) + amount, | ||||||||||||||||||||||
} | ||||||||||||||||||||||
return acc | ||||||||||||||||||||||
}, {}) | ||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -110,6 +110,13 @@ const selectPairedAssetSymbol = ( | |
pairedAssetSymbol: string | ||
) => pairedAssetSymbol | ||
|
||
const selectChainID = ( | ||
_: AssetsState, | ||
_2: string, | ||
_3: string, | ||
chainID: string | ||
) => chainID | ||
|
||
/** | ||
* Executes an asset transfer between two addresses, for a set amount. Supports | ||
* an optional fixed gas limit. | ||
|
@@ -187,9 +194,21 @@ export const transferAsset = createBackgroundAsyncThunk( | |
* the selector will return them in the order [ETH, USD]. | ||
*/ | ||
export const selectAssetPricePoint = createSelector( | ||
[selectAssetsState, selectAssetSymbol, selectPairedAssetSymbol], | ||
(assets, assetSymbol, pairedAssetSymbol) => { | ||
const pricedAsset = assets.find( | ||
[ | ||
selectAssetsState, | ||
selectAssetSymbol, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can pass the asset object here instead of the If we pass the asset here we should be able to match by the symbol and use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with you that maybe we should pass on the whole asset here. However, we will probably want to expand the assets to include the home network. Let's fix it in another issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is def strange here. I think creating a new ticket was a good call for this work. |
||
selectPairedAssetSymbol, | ||
selectChainID, | ||
], | ||
(assets, assetSymbol, pairedAssetSymbol, chainID) => { | ||
const pricedAsset = ( | ||
chainID | ||
? assets.filter( | ||
(asset) => | ||
"homeNetwork" in asset && asset.homeNetwork.chainID === chainID | ||
) | ||
: assets | ||
).find( | ||
(asset) => | ||
asset.symbol === assetSymbol && | ||
pairedAssetSymbol in asset.recentPrices && | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,7 +82,8 @@ const computeCombinedAssetAmountsData = ( | |
assets: AssetsState, | ||
mainCurrencySymbol: string, | ||
currentNetwork: EVMNetwork, | ||
hideDust: boolean | ||
hideDust: boolean, | ||
useCurrentNetwork = false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The API naming is misleading here because it comes from the selector api. I would have used something like |
||
): { | ||
combinedAssetAmounts: CompleteAssetAmount[] | ||
totalMainCurrencyAmount: number | undefined | ||
|
@@ -98,7 +99,8 @@ const computeCombinedAssetAmountsData = ( | |
const assetPricePoint = selectAssetPricePoint( | ||
assets, | ||
assetAmount.asset.symbol, | ||
mainCurrencySymbol | ||
mainCurrencySymbol, | ||
useCurrentNetwork ? currentNetwork.chainID : undefined | ||
) | ||
|
||
const mainCurrencyEnrichedAssetAmount = | ||
|
@@ -260,7 +262,8 @@ export const selectCurrentAccountBalances = createSelector( | |
assets, | ||
mainCurrencySymbol, | ||
currentNetwork, | ||
hideDust | ||
hideDust, | ||
true | ||
) | ||
|
||
return { | ||
|
@@ -319,14 +322,16 @@ const getAccountType = ( | |
const getTotalBalance = ( | ||
accountBalances: { [assetSymbol: string]: AccountBalance }, | ||
assets: AssetsState, | ||
mainCurrencySymbol: string | ||
mainCurrencySymbol: string, | ||
chainID: string | ||
) => { | ||
return Object.values(accountBalances) | ||
.map(({ assetAmount }) => { | ||
const assetPricePoint = selectAssetPricePoint( | ||
assets, | ||
assetAmount.asset.symbol, | ||
mainCurrencySymbol | ||
mainCurrencySymbol, | ||
chainID | ||
) | ||
|
||
if (typeof assetPricePoint === "undefined") { | ||
|
@@ -397,7 +402,12 @@ function getNetworkAccountTotalsByCategory( | |
avatarURL: accountData.ens.avatarURL ?? accountData.defaultAvatar, | ||
localizedTotalMainCurrencyAmount: formatCurrencyAmount( | ||
mainCurrencySymbol, | ||
getTotalBalance(accountData.balances, assets, mainCurrencySymbol), | ||
getTotalBalance( | ||
accountData.balances, | ||
assets, | ||
mainCurrencySymbol, | ||
network.chainID | ||
), | ||
desiredDecimals.default | ||
), | ||
} | ||
|
@@ -469,7 +479,8 @@ export const selectAccountTotalsForOverview = createSelector( | |
accountsTotal[normalizedAddress].totals[chainID] = getTotalBalance( | ||
accountData.balances, | ||
assetsState, | ||
mainCurrencySymbol | ||
mainCurrencySymbol, | ||
chainID | ||
) | ||
}) | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love to see this list expand :)