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

fix: fallback fees for doge #5853

Merged
merged 5 commits into from
Dec 13, 2023
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
29 changes: 8 additions & 21 deletions packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,38 +383,25 @@ export abstract class UtxoBaseAdapter<T extends UtxoChainId> implements IChainAd
throw new Error('UtxoBaseAdapter: failed to get fee data')
}

// TODO: when does this happen and why?
if (!data.fast?.satsPerKiloByte || data.fast.satsPerKiloByte < 0) {
data.fast = data.average
}
// ensure higher confirmation speeds never have lower fees than lower confirmation speeds
if (data.slow.satsPerKiloByte > data.average.satsPerKiloByte)
data.average.satsPerKiloByte = data.slow.satsPerKiloByte
if (data.average.satsPerKiloByte > data.fast.satsPerKiloByte)
data.fast.satsPerKiloByte = data.average.satsPerKiloByte

const utxos = await this.providers.http.getUtxos({ pubkey })

const utxoSelectInput = { from, to, value, opReturnData, utxos, sendMax }

// We have to round because coinselect library uses sats per byte which cant be decimals
const fastPerByte = String(Math.round(data.fast.satsPerKiloByte / 1024))
const averagePerByte = String(Math.round(data.average.satsPerKiloByte / 1024))
const slowPerByte = String(Math.round(data.slow.satsPerKiloByte / 1024))
const fastPerByte = String(Math.round(data.fast.satsPerKiloByte / 1000))
const averagePerByte = String(Math.round(data.average.satsPerKiloByte / 1000))
const slowPerByte = String(Math.round(data.slow.satsPerKiloByte / 1000))

const { fee: fastFee } = utxoSelect({ ...utxoSelectInput, satoshiPerByte: fastPerByte })
const { fee: averageFee } = utxoSelect({ ...utxoSelectInput, satoshiPerByte: averagePerByte })
const { fee: slowFee } = utxoSelect({ ...utxoSelectInput, satoshiPerByte: slowPerByte })

// Special, temporary case for DOGE to provide a workable fee value when the node is struggling
const isDoge = pubkey.startsWith('dgub')
const allFeesDefined =
fastFee !== undefined && averageFee !== undefined && slowFee !== undefined
if (isDoge && !allFeesDefined) {
const satoshiPerByte = '20000'
const fee = utxoSelect({ ...utxoSelectInput, satoshiPerByte }).fee
return {
fast: { txFee: String(fee), chainSpecific: { satoshiPerByte } },
average: { txFee: String(fee), chainSpecific: { satoshiPerByte } },
slow: { txFee: String(fee), chainSpecific: { satoshiPerByte } },
} as FeeDataEstimate<T>
}

return {
fast: { txFee: String(fastFee), chainSpecific: { satoshiPerByte: fastPerByte } },
average: { txFee: String(averageFee), chainSpecific: { satoshiPerByte: averagePerByte } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import type { BIP44Params } from '@shapeshiftoss/types'
import { KnownChainIds, UtxoAccountType } from '@shapeshiftoss/types'
import * as unchained from '@shapeshiftoss/unchained-client'

import type { FeeDataEstimate, GetFeeDataInput } from '../../types'
import { ChainAdapterDisplayName } from '../../types'
import type { ChainAdapterArgs } from '../UtxoBaseAdapter'
import { UtxoBaseAdapter } from '../UtxoBaseAdapter'
import { utxoSelect } from '../utxoSelect'

const SUPPORTED_CHAIN_IDS = [KnownChainIds.DogecoinMainnet]
const DEFAULT_CHAIN_ID = KnownChainIds.DogecoinMainnet
Expand Down Expand Up @@ -54,4 +56,54 @@ export class ChainAdapter extends UtxoBaseAdapter<KnownChainIds.DogecoinMainnet>
getFeeAssetId(): AssetId {
return this.assetId
}

async getFeeData({
to,
value,
chainSpecific: { from, pubkey, opReturnData },
sendMax = false,
}: GetFeeDataInput<KnownChainIds.DogecoinMainnet>): Promise<
FeeDataEstimate<KnownChainIds.DogecoinMainnet>
> {
if (!to) throw new Error('to is required')
if (!value) throw new Error('value is required')
if (!pubkey) throw new Error('pubkey is required')

const { fast, average, slow } = await this.providers.http.getNetworkFees()

if (!(fast?.satsPerKiloByte && average?.satsPerKiloByte && slow?.satsPerKiloByte)) {
throw new Error('UtxoBaseAdapter: failed to get fee data')
}

// sane default for invalid fee data from the node
// see: https://github.com/dogecoin/dogecoin/issues/3385
if (fast.satsPerKiloByte <= 0) fast.satsPerKiloByte = 500000000 // 5 DOGE per kB
if (average.satsPerKiloByte <= 0) average.satsPerKiloByte = 100000000 // 1 DOGE per kB
if (slow.satsPerKiloByte <= 0) slow.satsPerKiloByte = 50000000 // .5 DOGE per kB

// ensure higher confirmation speeds never have lower fees than lower confirmation speeds
if (slow.satsPerKiloByte > average.satsPerKiloByte)
average.satsPerKiloByte = slow.satsPerKiloByte
if (average.satsPerKiloByte > fast.satsPerKiloByte)
fast.satsPerKiloByte = average.satsPerKiloByte

const utxos = await this.providers.http.getUtxos({ pubkey })

const utxoSelectInput = { from, to, value, opReturnData, utxos, sendMax }

// We have to round because coinselect library uses sats per byte which cant be decimals
const fastPerByte = String(Math.round(fast.satsPerKiloByte / 1000))
const averagePerByte = String(Math.round(average.satsPerKiloByte / 1000))
const slowPerByte = String(Math.round(slow.satsPerKiloByte / 1000))

const { fee: fastFee } = utxoSelect({ ...utxoSelectInput, satoshiPerByte: fastPerByte })
const { fee: averageFee } = utxoSelect({ ...utxoSelectInput, satoshiPerByte: averagePerByte })
const { fee: slowFee } = utxoSelect({ ...utxoSelectInput, satoshiPerByte: slowPerByte })

return {
fast: { txFee: String(fastFee), chainSpecific: { satoshiPerByte: fastPerByte } },
average: { txFee: String(averageFee), chainSpecific: { satoshiPerByte: averagePerByte } },
slow: { txFee: String(slowFee), chainSpecific: { satoshiPerByte: slowPerByte } },
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ export const AssetChainDropdown: React.FC<ChainDropdownProps> = ({
borderRadius='full'
color='text.base'
isDisabled
variant='ghost'
isLoading={isLoading}
variant={!isLoading ? 'ghost' : undefined}
_disabled={disabled}
_hover={hover}
{...buttonProps}
Expand Down
11 changes: 9 additions & 2 deletions src/components/MultiHopTrade/components/AssetSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const TradeAssetAwaitingAsset = () => {
type TradeAssetSelectProps = {
assetId?: AssetId
isReadOnly?: boolean
isLoading: boolean
onAssetClick?: () => void
onAssetChange: (asset: Asset) => void
}
Expand All @@ -40,11 +41,16 @@ export const TradeAssetSelectWithAsset: React.FC<TradeAssetSelectProps> = ({
onAssetChange,
assetId,
isReadOnly,
isLoading,
}) => {
const assets = useAppSelector(selectAssets)
const asset = useAppSelector(state => selectAssetById(state, assetId ?? ''))

const { data, isLoading, isError } = useGetRelatedAssetIdsQuery(assetId ?? '')
const {
data,
isLoading: isRelatedAssetsLoading,
isError,
} = useGetRelatedAssetIdsQuery(assetId ?? '')

const handleAssetChange = useCallback(
(assetId: AssetId) => {
Expand Down Expand Up @@ -80,6 +86,7 @@ export const TradeAssetSelectWithAsset: React.FC<TradeAssetSelectProps> = ({
isDisabled={isReadOnly}
_disabled={disabledStyle}
rightIcon={rightIcon}
isLoading={isLoading || isRelatedAssetsLoading}
>
{icon}
{asset?.symbol}
Expand All @@ -89,7 +96,7 @@ export const TradeAssetSelectWithAsset: React.FC<TradeAssetSelectProps> = ({
assetIds={data}
assetId={assetId}
onClick={handleAssetChange}
isLoading={isLoading}
isLoading={isLoading || isRelatedAssetsLoading}
isError={isError}
/>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -557,9 +557,10 @@ export const TradeInput = memo(() => {
assetId={sellAsset.assetId}
onAssetClick={handleSellAssetClick}
onAssetChange={setSellAsset}
isLoading={isSupportedAssetsLoading}
/>
),
[handleSellAssetClick, sellAsset.assetId, setSellAsset],
[handleSellAssetClick, isSupportedAssetsLoading, sellAsset.assetId, setSellAsset],
)

const buyTradeAssetSelect = useMemo(
Expand All @@ -568,9 +569,10 @@ export const TradeInput = memo(() => {
assetId={buyAsset.assetId}
onAssetClick={handleBuyAssetClick}
onAssetChange={setBuyAsset}
isLoading={isSupportedAssetsLoading}
/>
),
[buyAsset.assetId, handleBuyAssetClick, setBuyAsset],
[buyAsset.assetId, handleBuyAssetClick, isSupportedAssetsLoading, setBuyAsset],
)

return (
Expand Down
14 changes: 11 additions & 3 deletions src/pages/Lending/Pool/components/Borrow/BorrowInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ export const BorrowInput = ({
const translate = useTranslate()
const history = useHistory()

const { data: borrowAssets } = useLendingSupportedAssets({ type: 'borrow' })
const { data: borrowAssets, isLoading: isLendingSupportedAssetsLoading } =
useLendingSupportedAssets({ type: 'borrow' })

const collateralAsset = useAppSelector(state => selectAssetById(state, collateralAssetId))

Expand Down Expand Up @@ -346,19 +347,26 @@ export const BorrowInput = ({
onAssetClick={noop}
onAssetChange={handleAssetChange}
isReadOnly
isLoading={isLendingSupportedAssetsLoading}
/>
)
}, [collateralAssetId, handleAssetChange])
}, [collateralAssetId, handleAssetChange, isLendingSupportedAssetsLoading])

const borrowAssetSelectComponent = useMemo(() => {
return (
<TradeAssetSelect
assetId={borrowAsset?.assetId ?? ''}
onAssetClick={handleBorrowAssetClick}
onAssetChange={handleAssetChange}
isLoading={isLendingSupportedAssetsLoading}
/>
)
}, [borrowAsset?.assetId, handleAssetChange, handleBorrowAssetClick])
}, [
borrowAsset?.assetId,
handleAssetChange,
handleBorrowAssetClick,
isLendingSupportedAssetsLoading,
])

const quoteErrorTranslation = useMemo(() => {
if (_isSmartContractAddress) return 'trade.errors.smartContractWalletNotSupported'
Expand Down
19 changes: 16 additions & 3 deletions src/pages/Lending/Pool/components/Repay/RepayInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ export const RepayInput = ({

const swapIcon = useMemo(() => <ArrowDownIcon />, [])

const { data: lendingSupportedAssets } = useLendingSupportedAssets({ type: 'borrow' })
const { data: lendingSupportedAssets, isLoading: isLendingSupportedAssetsLoading } =
useLendingSupportedAssets({ type: 'borrow' })

useEffect(() => {
if (!(lendingSupportedAssets && collateralAsset)) return
Expand Down Expand Up @@ -159,9 +160,15 @@ export const RepayInput = ({
// Users have the possibility to repay in any supported asset, not only their collateral/borrowed asset
// https://docs.thorchain.org/thorchain-finance/lending#loan-repayment-closeflow
isReadOnly={false}
isLoading={isLendingSupportedAssetsLoading}
/>
)
}, [handleAssetChange, handleRepaymentAssetClick, repaymentAsset?.assetId])
}, [
handleAssetChange,
handleRepaymentAssetClick,
isLendingSupportedAssetsLoading,
repaymentAsset?.assetId,
])

const collateralAssetSelectComponent = useMemo(() => {
return (
Expand All @@ -170,9 +177,15 @@ export const RepayInput = ({
onAssetClick={handleRepaymentAssetClick}
onAssetChange={handleAssetChange}
isReadOnly
isLoading={isLendingSupportedAssetsLoading}
/>
)
}, [collateralAssetId, handleAssetChange, handleRepaymentAssetClick])
}, [
collateralAssetId,
handleAssetChange,
handleRepaymentAssetClick,
isLendingSupportedAssetsLoading,
])

const handleSeenNotice = useCallback(() => setSeenNotice(true), [])

Expand Down