Skip to content

Commit

Permalink
Merge branch 'main' into fork-demo
Browse files Browse the repository at this point in the history
  • Loading branch information
Gergő Nagy authored Mar 8, 2022
2 parents a08397c + 3586294 commit 83fe2ce
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 35 deletions.
5 changes: 2 additions & 3 deletions .env.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ HIDE_CREATE_PHRASE=false
HIDE_IMPORT_LEDGER=false
GAS_PRICE_POOLING_FREQUENCY=120
ETHEREUM_NETWORK=mainnet
PERSIST_UI_LOCATION=false
PERSIST_UI_LOCATION=true
USE_MAINNET_FORK=false
MAINNET_FORK_URL="http://127.0.0.1:8545"
MAINNET_FORK_CHAIN_ID=1337

MAINNET_FORK_CHAIN_ID=1337
51 changes: 32 additions & 19 deletions background/redux-slices/0x-swap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { fetchJson } from "@ethersproject/web"
import { BigNumber, ethers, utils } from "ethers"

import { createBackgroundAsyncThunk } from "./utils"
import { SmartContractFungibleAsset } from "../assets"
import { FungibleAsset, SmartContractFungibleAsset } from "../assets"
import logger from "../lib/logger"
import {
isValidSwapPriceResponse,
Expand All @@ -15,8 +15,8 @@ import { ERC20_ABI } from "../lib/erc20"
import { COMMUNITY_MULTISIG_ADDRESS } from "../constants"

interface SwapAssets {
sellAsset: SmartContractFungibleAsset
buyAsset: SmartContractFungibleAsset
sellAsset: SmartContractFungibleAsset | FungibleAsset
buyAsset: SmartContractFungibleAsset | FungibleAsset
}

type SwapAmount =
Expand Down Expand Up @@ -47,6 +47,10 @@ export const initialState: SwapState = {
inProgressApprovalContract: undefined,
}

// The magic string used by the 0x API to signify we're dealing with ETH rather
// than an ERC-20
const ZEROX_ETH_SIGNIFIER = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"

const swapSlice = createSlice({
name: "0x-swap",
initialState,
Expand Down Expand Up @@ -132,10 +136,15 @@ function build0xUrlFromSwapRequest(
"buyAmount" in amount ? assets.buyAsset.decimals : assets.sellAsset.decimals
)

// When available, use smart contract addresses. Once non-smart contract
// assets are added (e.g., ETH), switch to `.symbol` for those.
const sellToken = assets.sellAsset.contractAddress
const buyToken = assets.buyAsset.contractAddress
// When available, use smart contract addresses.
const sellToken =
"contractAddress" in assets.sellAsset
? assets.sellAsset.contractAddress
: assets.sellAsset.symbol
const buyToken =
"contractAddress" in assets.buyAsset
? assets.buyAsset.contractAddress
: assets.buyAsset.symbol

// Depending on whether the set amount is buy or sell, request the trade.
// The /price endpoint is for RFQ-T indicative quotes, while /quote is for
Expand Down Expand Up @@ -233,20 +242,24 @@ export const fetchSwapPrice = createBackgroundAsyncThunk(

const quote = apiData

// Check if we have to approve the asset we want to swap.
const assetContract = new ethers.Contract(
quote.sellTokenAddress,
ERC20_ABI,
signer
)

const existingAllowance: BigNumber =
await assetContract.callStatic.allowance(
await signer.getAddress(),
quote.allowanceTarget
let needsApproval = false
// If we aren't selling ETH, check whether we need an approval to swap
// TODO Handle other non-ETH base assets
if (quote.sellTokenAddress !== ZEROX_ETH_SIGNIFIER) {
const assetContract = new ethers.Contract(
quote.sellTokenAddress,
ERC20_ABI,
signer
)

const needsApproval = existingAllowance.lt(quote.sellAmount)
const existingAllowance: BigNumber =
await assetContract.callStatic.allowance(
await signer.getAddress(),
quote.allowanceTarget
)

needsApproval = existingAllowance.lt(quote.sellAmount)
}

dispatch(setLatestQuoteRequest(quoteRequest))

Expand Down
33 changes: 20 additions & 13 deletions ui/pages/Swap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { selectCurrentAccountBalances } from "@tallyho/tally-background/redux-slices/selectors"
import {
AnyAsset,
FungibleAsset,
isSmartContractFungibleAsset,
SmartContractFungibleAsset,
} from "@tallyho/tally-background/assets"
Expand All @@ -25,7 +26,7 @@ import { AsyncThunkFulfillmentType } from "@tallyho/tally-background/redux-slice
import logger from "@tallyho/tally-background/lib/logger"
import { useHistory, useLocation } from "react-router-dom"
import { normalizeEVMAddress } from "@tallyho/tally-background/lib/utils"
import { CompleteSmartContractFungibleAssetAmount } from "@tallyho/tally-background/redux-slices/accounts"
import { CompleteAssetAmount } from "@tallyho/tally-background/redux-slices/accounts"
import {
clearTransactionState,
selectDefaultNetworkFeeSettings,
Expand Down Expand Up @@ -75,13 +76,17 @@ export default function Swap(): ReactElement {

const accountBalances = useBackgroundSelector(selectCurrentAccountBalances)

// TODO Expand these to fungible assets by supporting direct ETH swaps,
// TODO then filter by the current chain.

// TODO We're special-casing ETH here in an odd way. Going forward, we should
// filter by current chain and better handle network-native base assets
const ownedSellAssetAmounts =
accountBalances?.assetAmounts.filter(
(assetAmount): assetAmount is CompleteSmartContractFungibleAssetAmount =>
isSmartContractFungibleAsset(assetAmount.asset)
(
assetAmount
): assetAmount is CompleteAssetAmount<
SmartContractFungibleAsset | FungibleAsset
> =>
isSmartContractFungibleAsset(assetAmount.asset) ||
assetAmount.asset.symbol === "ETH"
) ?? []

const buyAssets = useBackgroundSelector((state) => {
Expand Down Expand Up @@ -174,8 +179,10 @@ export default function Swap(): ReactElement {
selectInProgressApprovalContract
)
const isApprovalInProgress =
sellAsset &&
"contractAddress" in sellAsset &&
normalizeEVMAddress(inProgressApprovalContract || "0x") ===
normalizeEVMAddress(sellAsset?.contractAddress || "0x")
normalizeEVMAddress(sellAsset?.contractAddress || "0x")

const [sellAmountLoading, setSellAmountLoading] = useState(false)
const [buyAmountLoading, setBuyAmountLoading] = useState(false)
Expand Down Expand Up @@ -247,8 +254,8 @@ export default function Swap(): ReactElement {
requestedQuote: "buy" | "sell",
amount: string,
// Fixed asset in the swap.
fixedAsset?: SmartContractFungibleAsset | undefined,
quoteAsset?: SmartContractFungibleAsset | undefined
fixedAsset?: SmartContractFungibleAsset | FungibleAsset | undefined,
quoteAsset?: SmartContractFungibleAsset | FungibleAsset | undefined
): Promise<void> => {
if (requestedQuote === "sell") {
setBuyAmount("")
Expand Down Expand Up @@ -355,7 +362,7 @@ export default function Swap(): ReactElement {
)

const updateSellAsset = useCallback(
(asset: SmartContractFungibleAsset) => {
(asset: SmartContractFungibleAsset | FungibleAsset) => {
setSellAsset(asset)
// Updating the sell asset quotes the new sell asset against the existing
// buy amount.
Expand All @@ -364,7 +371,7 @@ export default function Swap(): ReactElement {
[buyAmount, updateSwapData]
)
const updateBuyAsset = useCallback(
(asset: SmartContractFungibleAsset) => {
(asset: SmartContractFungibleAsset | FungibleAsset) => {
setBuyAsset(asset)
// Updating the buy asset quotes the new buy asset against the existing
// sell amount.
Expand Down Expand Up @@ -433,7 +440,7 @@ export default function Swap(): ReactElement {
<SharedActivityHeader label="Swap Assets" activity="swap" />
<div className="form">
<div className="form_input">
<SharedAssetInput
<SharedAssetInput<SmartContractFungibleAsset | FungibleAsset>
amount={sellAmount}
assetsAndAmounts={sellAssetAmounts}
selectedAsset={sellAsset}
Expand All @@ -453,7 +460,7 @@ export default function Swap(): ReactElement {
Switch Assets
</button>
<div className="form_input">
<SharedAssetInput
<SharedAssetInput<SmartContractFungibleAsset | FungibleAsset>
amount={buyAmount}
// FIXME Merge master asset list with account balances.
assetsAndAmounts={buyAssets.map((asset) => ({ asset }))}
Expand Down

0 comments on commit 83fe2ce

Please sign in to comment.