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

feat: dogecoin #2185

Merged
merged 14 commits into from
Jul 21, 2022
Merged
2 changes: 2 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ jobs:
REACT_APP_UNCHAINED_AVALANCHE_WS_URL: wss://dev-api.avalanche.shapeshift.com
REACT_APP_UNCHAINED_BITCOIN_HTTP_URL: https://dev-api.bitcoin.shapeshift.com
REACT_APP_UNCHAINED_BITCOIN_WS_URL: wss://dev-api.bitcoin.shapeshift.com
REACT_APP_UNCHAINED_DOGECOIN_HTTP_URL: https://dev-api.dogecoin.shapeshift.com
REACT_APP_UNCHAINED_DOGECOIN_WS_URL: wss://dev-api.dogecoin.shapeshift.com
REACT_APP_UNCHAINED_COSMOS_HTTP_URL: https://dev-api.cosmos.shapeshift.com
REACT_APP_UNCHAINED_COSMOS_WS_URL: wss://dev-api.cosmos.shapeshift.com
REACT_APP_PORTIS_DAPP_ID: 8609e6a8-e0dc-45e6-a0ad-edde63a4cdda
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@
"@formatjs/intl-pluralrules": "^5.0.2",
"@metamask/detect-provider": "^1.2.0",
"@reduxjs/toolkit": "^1.8.2",
"@shapeshiftoss/asset-service": "^6.4.0",
"@shapeshiftoss/caip": "^6.3.0",
"@shapeshiftoss/chain-adapters": "^7.7.0",
"@shapeshiftoss/asset-service": "^6.5.0",
"@shapeshiftoss/caip": "^6.5.0",
"@shapeshiftoss/chain-adapters": "^7.9.0",
"@shapeshiftoss/errors": "^1.1.2",
"@shapeshiftoss/hdwallet-core": "^1.27.0",
"@shapeshiftoss/hdwallet-keepkey": "^1.27.0",
Expand All @@ -107,8 +107,8 @@
"@shapeshiftoss/logger": "^1.1.2",
"@shapeshiftoss/market-service": "^6.4.2",
"@shapeshiftoss/swapper": "^8.4.0",
"@shapeshiftoss/types": "^7.0.0",
"@shapeshiftoss/unchained-client": "^9.2.0",
"@shapeshiftoss/types": "^7.1.0",
"@shapeshiftoss/unchained-client": "^9.3.0",
"@uniswap/sdk": "^3.0.3",
"@unstoppabledomains/resolution": "^7.1.4",
"@visx/axis": "^2.10.0",
Expand Down
8 changes: 8 additions & 0 deletions react-app-rewired/headers/csps/chains/dogecoin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { Csp } from '../../types'

export const csp: Csp = {
'connect-src': [
process.env.REACT_APP_UNCHAINED_DOGECOIN_HTTP_URL!,
process.env.REACT_APP_UNCHAINED_DOGECOIN_WS_URL!,
],
}
3 changes: 3 additions & 0 deletions sample.env
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ REACT_APP_UNCHAINED_BITCOIN_HTTP_URL=https://dev-api.bitcoin.shapeshift.com
REACT_APP_UNCHAINED_BITCOIN_WS_URL=wss://dev-api.bitcoin.shapeshift.com
REACT_APP_UNCHAINED_COSMOS_HTTP_URL=https://dev-api.cosmos.shapeshift.com
REACT_APP_UNCHAINED_COSMOS_WS_URL=wss://dev-api.cosmos.shapeshift.com
REACT_APP_UNCHAINED_DOGECOIN_WS_URL=wss://dev-api.dogecoin.shapeshift.com
REACT_APP_UNCHAINED_DOGECOIN_HTTP_URL=https://dev-api.dogecoin.shapeshift.com
REACT_APP_UNCHAINED_OSMOSIS_HTTP_URL=https://dev-api.osmosis.shapeshift.com
REACT_APP_UNCHAINED_OSMOSIS_WS_URL=wss://dev-api.osmosis.shapeshift.com
REACT_APP_PORTIS_DAPP_ID=8609e6a8-e0dc-45e6-a0ad-edde63a4cdda
Expand All @@ -34,6 +36,7 @@ REACT_APP_FEATURE_COWSWAP=false
REACT_APP_FEATURE_COINBASE_RAMP=false
REACT_APP_FEATURE_JUNOPAY=false
REACT_APP_FEATURE_PENDO=false
REACT_APP_FEATURE_DOGECOIN=false

REACT_APP_GEM_COINIFY_SUPPORTED_COINS=https://api.gem.co/institutions/coinify/supported_currencies
REACT_APP_GEM_WYRE_SUPPORTED_COINS=https://api.gem.co/institutions/wyre/supported_currencies
Expand Down
8 changes: 7 additions & 1 deletion src/components/Modals/FiatRamps/views/Manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const ManagerRouter: React.FC<ManagerRouterProps> = ({ fiatRampProvider }) => {
const [selectedAsset, setSelectedAsset] = useState<FiatRampAsset | null>(null)
// We keep addresses in manager so we don't have to on every <Overview /> mount
const [btcAddress, setBtcAddress] = useState<string>('')
const [dogeAddress, setDogeAddress] = useState<string>('')
const [ethAddress, setEthAddress] = useState<string>('')
const [cosmosAddress, setCosmosAddress] = useState<string>('')
const [supportsAddressVerifying, setSupportsAddressVerifying] = useState<boolean>(false)
Expand All @@ -68,6 +69,7 @@ const ManagerRouter: React.FC<ManagerRouterProps> = ({ fiatRampProvider }) => {
const chainAdapterManager = useChainAdapters()
const ethereumChainAdapter = chainAdapterManager.get(KnownChainIds.EthereumMainnet)
const bitcoinChainAdapter = chainAdapterManager.get(KnownChainIds.BitcoinMainnet)
const dogecoinChainAdapter = chainAdapterManager.get(KnownChainIds.DogecoinMainnet)
const cosmosChainAdapter = chainAdapterManager.get(KnownChainIds.CosmosMainnet)

const [chainId, setChainId] = useState<ChainIdType>(ethChainId)
Expand All @@ -88,14 +90,17 @@ const ManagerRouter: React.FC<ManagerRouterProps> = ({ fiatRampProvider }) => {
if (supportsBTC(wallet) && bitcoinChainAdapter) {
setBtcAddress(await bitcoinChainAdapter.getAddress(payload))
}
if (supportsBTC(wallet) && dogecoinChainAdapter) {
setDogeAddress(await dogecoinChainAdapter.getAddress(payload))
}
if (supportsCosmos(wallet) && cosmosChainAdapter) {
setCosmosAddress(await cosmosChainAdapter.getAddress(payload))
}
} catch (e) {
moduleLogger.error(e, { fn: 'getAddress' }, 'GetAddress Failed')
}
})()
}, [wallet, bitcoinChainAdapter, ethereumChainAdapter, cosmosChainAdapter])
}, [wallet, bitcoinChainAdapter, dogecoinChainAdapter, ethereumChainAdapter, cosmosChainAdapter])

useEffect(() => {
;(async () => {
Expand Down Expand Up @@ -156,6 +161,7 @@ const ManagerRouter: React.FC<ManagerRouterProps> = ({ fiatRampProvider }) => {
onIsSelectingAsset={handleIsSelectingAsset}
onFiatRampActionClick={handleFiatRampActionClick}
btcAddress={btcAddress}
dogeAddress={dogeAddress}
cosmosAddress={cosmosAddress}
ethAddress={ethAddress}
supportsAddressVerifying={supportsAddressVerifying}
Expand Down
4 changes: 4 additions & 0 deletions src/components/Modals/FiatRamps/views/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type OverviewProps = {
selectedAsset: FiatRampAsset | null
fiatRampProvider: FiatRamp
btcAddress: string
dogeAddress: string
ethAddress: string
cosmosAddress: string
ensName: string
Expand All @@ -47,6 +48,7 @@ type OverviewProps = {
type GenerateAddressProps = {
selectedAsset: FiatRampAsset | null
btcAddress: string
dogeAddress: string
ethAddress: string
cosmosAddress: string
ensName: string
Expand Down Expand Up @@ -82,6 +84,7 @@ export const Overview: React.FC<OverviewProps> = ({
supportsAddressVerifying,
setSupportsAddressVerifying,
btcAddress,
dogeAddress,
ethAddress,
cosmosAddress,
ensName,
Expand All @@ -104,6 +107,7 @@ export const Overview: React.FC<OverviewProps> = ({
const [addressOrNameFull, addressFull, addressOrNameEllipsed] = generateAddresses({
selectedAsset,
btcAddress,
dogeAddress,
ethAddress,
cosmosAddress,
ensName,
Expand Down
33 changes: 30 additions & 3 deletions src/components/Modals/Send/hooks/useFormSend/useFormSend.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ExternalLinkIcon } from '@chakra-ui/icons'
import { Link, Text, useToast } from '@chakra-ui/react'
import { fromAssetId } from '@shapeshiftoss/caip'
import { bitcoin, ChainAdapter, ethereum, FeeData } from '@shapeshiftoss/chain-adapters'
import { bitcoin, ChainAdapter, dogecoin, ethereum, FeeData } from '@shapeshiftoss/chain-adapters'
import { supportsETH } from '@shapeshiftoss/hdwallet-core'
import { KnownChainIds } from '@shapeshiftoss/types'
import { useTranslate } from 'react-polyglot'
Expand Down Expand Up @@ -74,13 +74,13 @@ export const useFormSend = () => {

if (!accountType) {
throw new Error(
`useFormSend: could not get accountType from accountId: ${data.accountId}`,
`useFormSend: could not get bitcoin accountType from accountId: ${data.accountId}`,
)
}

if (!utxoParams) {
throw new Error(
`useFormSend: could not get utxoParams from accountId: ${data.accountId}`,
`useFormSend: could not get bitcoin utxoParams from accountId: ${data.accountId}`,
)
}

Expand All @@ -95,6 +95,33 @@ export const useFormSend = () => {
},
sendMax: data.sendMax,
})
} else if (adapterType === KnownChainIds.DogecoinMainnet) {
const fees = estimatedFees[feeType] as FeeData<KnownChainIds.DogecoinMainnet>

const { accountType, utxoParams } = accountIdToUtxoParams(data.accountId, 0)
if (!accountType) {
throw new Error(
`useFormSend: could not get dogecoin accountType from accountId: ${data.accountId}`,
)
}

if (!utxoParams) {
throw new Error(
`useFormSend: could not get dogecoin utxoParams from accountId: ${data.accountId}`,
)
}

result = await (adapter as unknown as dogecoin.ChainAdapter).buildSendTransaction({
to,
value,
wallet,
bip44Params: utxoParams.bip44Params,
chainSpecific: {
satoshiPerByte: fees.chainSpecific.satoshiPerByte,
accountType,
},
sendMax: data.sendMax,
})
} else {
throw new Error('unsupported adapterType')
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChainId, fromAccountId, fromAssetId } from '@shapeshiftoss/caip'
import { bitcoin, cosmos, ethereum, FeeDataEstimate } from '@shapeshiftoss/chain-adapters'
import { bitcoin, cosmos, dogecoin, ethereum, FeeDataEstimate } from '@shapeshiftoss/chain-adapters'
import { KnownChainIds } from '@shapeshiftoss/types'
import { debounce } from 'lodash'
import { useCallback, useEffect, useMemo, useState } from 'react'
Expand Down Expand Up @@ -149,6 +149,19 @@ export const useSendDetails = (): UseSendDetailsReturnType => {
sendMax: values.sendMax,
})
}
case KnownChainIds.DogecoinMainnet: {
const dogecoinChainAdapter = (await chainAdapterManager.get(
KnownChainIds.DogecoinMainnet,
)) as dogecoin.ChainAdapter | undefined
if (!dogecoinChainAdapter)
throw new Error(`No adapter available for ${KnownChainIds.DogecoinMainnet}`)
return dogecoinChainAdapter.getFeeData({
to: values.address,
value,
chainSpecific: { pubkey: account },
sendMax: values.sendMax,
})
}
default:
throw new Error('unsupported chain type')
}
Expand Down Expand Up @@ -255,6 +268,22 @@ export const useSendDetails = (): UseSendDetailsReturnType => {
const fastFee = adapterFees.fast.txFee
return { adapterFees, fastFee }
}
case KnownChainIds.DogecoinMainnet: {
const dogeAdapter = (await chainAdapterManager.get(KnownChainIds.DogecoinMainnet)) as
| dogecoin.ChainAdapter
| undefined
if (!dogeAdapter)
throw new Error(`No adapter available for ${KnownChainIds.DogecoinMainnet}`)
const value = assetBalance
const adapterFees = await dogeAdapter.getFeeData({
to,
value,
chainSpecific: { pubkey: account },
sendMax: true,
})
const fastFee = adapterFees.fast.txFee // this is actually average fee for doge
return { adapterFees, fastFee }
}
default: {
throw new Error(
`useSendDetails(handleSendMax): no adapter available for chainId ${chainId}`,
Expand Down
11 changes: 7 additions & 4 deletions src/components/Trade/hooks/useSwapper/useSwapper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useToast } from '@chakra-ui/react'
import { ChainId, fromAssetId } from '@shapeshiftoss/caip'
import { ChainId, fromAssetId, toAccountId } from '@shapeshiftoss/caip'
import { avalanche, ethereum } from '@shapeshiftoss/chain-adapters'
import { HDWallet } from '@shapeshiftoss/hdwallet-core'
import {
Expand Down Expand Up @@ -319,11 +319,14 @@ export const useSwapper = () => {

if (!receiveAddressAccountSpecifiers)
throw new Error('no receiveAddressAccountSpecifiers')
const receiveAddressAccountSpecifier = receiveAddressAccountSpecifiers[buyAsset.chainId]
if (!receiveAddressAccountSpecifier) throw new Error('no receiveAddressAccountSpecifier')
const account = receiveAddressAccountSpecifiers[buyAsset.chainId]
if (!account) throw new Error(`no account for ${buyAsset.chainId}`)

const { chainId } = buyAsset
const accountId = toAccountId({ chainId, account })

const { accountType: receiveAddressAccountType, utxoParams: receiveAddressUtxoParams } =
accountIdToUtxoParams(receiveAddressAccountSpecifiers[buyAsset.chainId], 0)
accountIdToUtxoParams(accountId, 0)

const receiveAddress = await chainAdapter.getAddress({
wallet,
Expand Down
3 changes: 3 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const validators = {
REACT_APP_UNCHAINED_AVALANCHE_WS_URL: url(),
REACT_APP_UNCHAINED_BITCOIN_HTTP_URL: url(),
REACT_APP_UNCHAINED_BITCOIN_WS_URL: url(),
REACT_APP_UNCHAINED_DOGECOIN_HTTP_URL: url(),
REACT_APP_UNCHAINED_DOGECOIN_WS_URL: url(),
REACT_APP_UNCHAINED_COSMOS_HTTP_URL: url(),
REACT_APP_UNCHAINED_COSMOS_WS_URL: url(),
REACT_APP_UNCHAINED_OSMOSIS_HTTP_URL: url(),
Expand All @@ -42,6 +44,7 @@ const validators = {
REACT_APP_FEATURE_OSMOSIS: bool({ default: false }),
REACT_APP_FEATURE_AVALANCHE: bool({ default: false }),
REACT_APP_FEATURE_THOR: bool({ default: false }),
REACT_APP_FEATURE_DOGECOIN: bool({ default: false }),
REACT_APP_FEATURE_COWSWAP: bool({ default: false }),
REACT_APP_FEATURE_COINBASE_RAMP: bool({ default: false }),
REACT_APP_FEATURE_JUNOPAY: bool({ default: false }),
Expand Down
37 changes: 35 additions & 2 deletions src/context/AppProvider/AppContext.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { btcChainId, cosmosChainId, ethChainId, osmosisChainId } from '@shapeshiftoss/caip'
import {
btcChainId,
cosmosChainId,
dogeChainId,
ethChainId,
osmosisChainId,
} from '@shapeshiftoss/caip'
import {
bitcoin,
convertXpubVersion,
dogecoin,
toRootDerivationPath,
utxoAccountParams,
} from '@shapeshiftoss/chain-adapters'
Expand Down Expand Up @@ -139,7 +146,7 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
adapter as unknown as bitcoin.ChainAdapter
).getSupportedAccountTypes()
for (const accountType of supportedAccountTypes) {
const accountParams = utxoAccountParams(accountType, 0)
const accountParams = utxoAccountParams(chainId, accountType, 0)
const { bip44Params, scriptType } = accountParams
const pubkeys = await wallet.getPublicKeys([
{
Expand All @@ -159,6 +166,32 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
}
break
}
case dogeChainId: {
if (!supportsBTC(wallet)) continue
const supportedAccountTypes = (
adapter as unknown as dogecoin.ChainAdapter
).getSupportedAccountTypes()
for (const accountType of supportedAccountTypes) {
const accountParams = utxoAccountParams(chainId, accountType, 0)
const { bip44Params, scriptType } = accountParams
const addressNList = bip32ToAddressNList(toRootDerivationPath(bip44Params))
const pubkeys = await wallet.getPublicKeys([
{
coin: 'dogecoin',
addressNList,
curve: 'secp256k1',
scriptType,
},
])
if (!pubkeys?.[0]?.xpub) {
throw new Error(`usePubkeys: error getting dogecoin xpub`)
}
const pubkey = pubkeys[0].xpub
if (!pubkey) continue
acc.push({ [chainId]: pubkey })
}
break
}
case cosmosChainId: {
if (!supportsCosmos(wallet)) continue
const pubkey = await adapter.getAddress({ wallet })
Expand Down
11 changes: 10 additions & 1 deletion src/context/PluginProvider/PluginProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@ type PluginProviderContextProps = {
routes: Route[]
}

const activePlugins = ['bitcoin', 'cosmos', 'ethereum', 'foxPage', 'osmosis', 'avalanche', 'pendo']
const activePlugins = [
'bitcoin',
'cosmos',
'dogecoin',
'ethereum',
'foxPage',
'osmosis',
'avalanche',
'pendo',
]

// don't export me, access me through the getter
let _chainAdapterManager: ChainAdapterManager | undefined
Expand Down
4 changes: 3 additions & 1 deletion src/context/TransactionsProvider/TransactionsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ export const TransactionsProvider = ({ children }: TransactionsProviderProps): J
supportedAccountTypes.map(async accountType => {
moduleLogger.info({ chainId, accountType }, 'subscribing txs')

const accountParams = accountType ? utxoAccountParams(accountType, 0) : {}
const accountParams = accountType
? utxoAccountParams(chainId, accountType, 0)
: {}

return adapter?.subscribeTxs(
{ wallet, accountType, ...accountParams },
Expand Down
4 changes: 4 additions & 0 deletions src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
btcChainId,
ChainId,
cosmosChainId,
dogeChainId,
ethChainId,
osmosisChainId,
} from '@shapeshiftoss/caip'
Expand Down Expand Up @@ -31,6 +32,9 @@ export const walletSupportsChain: UseWalletSupportsChain = ({ chainId, wallet })
case cosmosChainId: {
return supportsCosmos(wallet)
}
case dogeChainId: {
return supportsBTC(wallet)
}
case osmosisChainId: {
return supportsOsmosis(wallet)
}
Expand Down
Loading