Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into fix_thor_borked_wi…
Browse files Browse the repository at this point in the history
…thdraws
  • Loading branch information
gomesalexandre committed Dec 13, 2023
2 parents eb45efb + c33be94 commit 7d5e684
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 24 deletions.
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
52 changes: 52 additions & 0 deletions packages/chain-adapters/src/utxo/dogecoin/DogecoinChainAdapter.ts
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 @@ -2,8 +2,8 @@ import { Alert, AlertIcon, Skeleton, useToast } from '@chakra-ui/react'
import { AddressZero } from '@ethersproject/constants'
import type { AccountId } from '@shapeshiftoss/caip'
import { fromAccountId, fromAssetId, toAssetId } from '@shapeshiftoss/caip'
import { type GetFeeDataInput, type UtxoChainId } from '@shapeshiftoss/chain-adapters'
import type { Asset } from '@shapeshiftoss/types'
import type { GetFeeDataInput, UtxoChainId } from '@shapeshiftoss/chain-adapters'
import type { Asset, KnownChainIds } from '@shapeshiftoss/types'
import { Err, Ok, type Result } from '@sniptt/monads'
import { useQueryClient } from '@tanstack/react-query'
import { getOrCreateContractByType } from 'contracts/contractManager'
Expand All @@ -21,6 +21,7 @@ import { useTranslate } from 'react-polyglot'
import { encodeFunctionData, getAddress } from 'viem'
import { Amount } from 'components/Amount/Amount'
import type { StepComponentProps } from 'components/DeFi/components/Steps'
import { getChainShortName } from 'components/MultiHopTrade/components/MultiHopTradeConfirm/utils/getChainShortName'
import { Row } from 'components/Row/Row'
import { Text } from 'components/Text'
import type { TextPropTypes } from 'components/Text/Text'
Expand Down Expand Up @@ -326,7 +327,12 @@ export const Withdraw: React.FC<WithdrawProps> = ({ accountId, fromAddress, onNe
} catch (error) {
console.error(error)
// Assume insufficient amount for gas if we've thrown on the try block above
return Err(translate('common.insufficientAmountForGas', { assetSymbol: feeAsset.symbol }))
return Err(
translate('common.insufficientAmountForGas', {
assetSymbol: feeAsset.symbol,
chainSymbol: getChainShortName(feeAsset.chainId as KnownChainIds),
}),
)
}
},
[
Expand All @@ -344,6 +350,7 @@ export const Withdraw: React.FC<WithdrawProps> = ({ accountId, fromAddress, onNe
queryClient,
feeAsset.assetId,
feeAsset.symbol,
feeAsset.chainId,
translate,
assetId,
],
Expand Down

0 comments on commit 7d5e684

Please sign in to comment.