Skip to content

Commit

Permalink
feat: walletconnect wallet (#1733)
Browse files Browse the repository at this point in the history
* feat: init walletconnect integration

* chore: lint

* fix: wallet init

* fix: wallet init

* fix: add imagedelivery to headers

* chore: use package version

* chore: show/hide WalletConnect based on flag

* fix: headers for macos/ios safari

* fix: show feature flag nav item for alt host

* perf: add env var for better local development

* chore: remove unecessary code

* chore: remove package dep

* chore: add hdwallet-walletconnect alpha dependency

* fix: add walletconnect csp entries

* fix: utilize feature flag

* fix: add mobileEnabled field to WalletConnect config

* chore: run linter

* fix: remove usage of process.env

* chore: run linter

* fix: apply code review suggestions

* fix: use structured logging

* fix: apply code review suggestions

* fix: update csp for wallet logos

* chore: add flag to sample.env

* chore: yarn.lock

* docs: fleek info

* fix: img source csp

* chore: revert readme to develop

* fix: image fetched by walletconnect

* feat: WalletConnect rejection

* chore: lint

* chore: lint

* chore: update hdwallet-walletconnect dependency

* chore: upgrade hdwallet-walletconnect

* fix: set wc connect modal error to null on init

* chore: run linter

* fix: walletconnect refresh bug

* chore: upgrade hdwallet dependency

* chore: bump hdwallet dependencies

* fix: csp for walletconnect desktop logos

* chore: bump hdwallet package versions

* fix: disable trade max with walletconnect

* fix: disable sendmax with walletconnect

* chore: run linter

* chore: update hdwallet dependencies

* chore: run linter

* fix: hide fiat sendMax with WalletConnect

* fix: stylistic changes

* fix: typo

* feat: add copy to walletconnect option in selectmodal

* fix: constrain icon width for selectmodal options

* fix: update return value

Co-authored-by: pastaghost <[email protected]>
Co-authored-by: 0xdef1cafe <[email protected]>
  • Loading branch information
3 people authored and stackedq committed Jul 21, 2022
1 parent 8e6d4bf commit ea60e8e
Show file tree
Hide file tree
Showing 28 changed files with 760 additions and 40 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"@shapeshiftoss/hdwallet-native-vault": "^1.27.0",
"@shapeshiftoss/hdwallet-portis": "^1.27.0",
"@shapeshiftoss/hdwallet-tallyho": "^1.27.0",
"@shapeshiftoss/hdwallet-walletconnect": "^1.27.0",
"@shapeshiftoss/hdwallet-xdefi": "^1.27.0",
"@shapeshiftoss/investor-foxy": "^4.0.4",
"@shapeshiftoss/investor-yearn": "^4.0.4",
Expand All @@ -117,6 +118,7 @@
"@visx/responsive": "^2.10.0",
"@visx/shape": "^2.10.0",
"@visx/tooltip": "^2.10.0",
"@walletconnect/web3-provider": "^1.7.8",
"allsettled-polyfill": "^1.0.4",
"axios": "^0.26.1",
"bignumber.js": "^9.0.2",
Expand Down
5 changes: 3 additions & 2 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
<meta name="referrer" content="no-referrer">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta http-equiv="Content-Security-Policy" content="%REACT_APP_CSP_META%" />
<!-- WalletConnect uses the first image found in the head metadata for their wallet connect SDKs (web, kotlin, swift) -->
<link rel="apple-touch-icon" sizes="192x192" href="%PUBLIC_URL%/icon-192x192.png" integrity="%REACT_APP_SRI_ICON_192X192_PNG%" crossorigin="anonymous" />
<link rel="apple-touch-icon" sizes="512x512" href="%PUBLIC_URL%/icon-512x512.png" integrity="%REACT_APP_SRI_ICON_512X512_PNG%" crossorigin="anonymous" />
<link rel="icon" type="image/png" href="%PUBLIC_URL%/favicon.png" integrity="%REACT_APP_SRI_FAVICON_PNG%" crossorigin="anonymous" />
<link rel="icon" type="image/svg+xml" href="%PUBLIC_URL%/favicon.svg" integrity="%REACT_APP_SRI_FAVICON_SVG%" crossorigin="anonymous" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no,viewport-fit=cover" />
Expand All @@ -19,8 +22,6 @@
name="description"
content="ShapeShift DAO | Your Web3 & DeFi Portal"
/>
<link rel="apple-touch-icon" sizes="192x192" href="%PUBLIC_URL%/icon-192x192.png" integrity="%REACT_APP_SRI_ICON_192X192_PNG%" crossorigin="anonymous" />
<link rel="apple-touch-icon" sizes="512x512" href="%PUBLIC_URL%/icon-512x512.png" integrity="%REACT_APP_SRI_ICON_512X512_PNG%" crossorigin="anonymous" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
Expand Down
9 changes: 9 additions & 0 deletions react-app-rewired/headers/csps/wallets/walletconnect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { Csp } from '../../types'

export const csp: Csp = {
'connect-src': [
'wss://*.bridge.walletconnect.org/',
'https://registry.walletconnect.com/api/v2/wallets',
],
'img-src': ['https://imagedelivery.net/', 'https://registry.walletconnect.com/api/v2/logo/'],
}
4 changes: 4 additions & 0 deletions sample.env
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ REACT_APP_FRIENDLY_CAPTCHA_SITE_KEY=FCMM7AFC0S6A8NUK

REACT_APP_FEATURE_MULTI_CURRENCY=false
REACT_APP_FEATURE_OSMOSIS=false
REACT_APP_FEATURE_WALLETCONNECT_WALLET=false
REACT_APP_FEATURE_AVALANCHE=false
REACT_APP_FEATURE_THOR=false
REACT_APP_FEATURE_COWSWAP=false
Expand All @@ -41,6 +42,9 @@ REACT_APP_GEM_WYRE_SUPPORTED_COINS=https://api.gem.co/institutions/wyre/supporte
REACT_APP_GEM_ASSET_LOGO=https://gem-widgets-assets.s3-us-west-2.amazonaws.com/currencies/crypto/
REACT_APP_GEM_ENV=production
REACT_APP_GEM_API_KEY=bb4164a72246dae1e03010d664d6cdae4e19b2554de02e3bf6c3cd30aa7e359e

# IP/Hostname used for connecting external devices to localhost
REACT_APP_LOCAL_IP=192.168.1.222
REACT_APP_TOKEMAK_STATS_URL=https://stats.tokemaklabs.com/
REACT_APP_BOARDROOM_API_BASE_URL=https://api.boardroom.info/v1/protocols/shapeshift/
REACT_APP_BOARDROOM_APP_BASE_URL=https://boardroom.io/shapeshift/
Expand Down
5 changes: 4 additions & 1 deletion src/Routes/RoutesCommon.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getConfig } from 'config'
import {
FaFlag,
FaHistory,
Expand Down Expand Up @@ -150,7 +151,9 @@ export const routes: Array<NestedRoute> = [
path: '/flags',
label: 'navBar.featureFlags',
icon: <FaFlag />,
hide: window.location.hostname !== 'localhost',
hide:
window.location.hostname !== 'localhost' &&
window.location.hostname !== getConfig().REACT_APP_LOCAL_IP,
main: Flags,
},
]
18 changes: 17 additions & 1 deletion src/assets/translations/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
"verify": "Verify",
"notRobot": "I am not a Robot",
"skip": "Skip",
"generalError": "An error has occurred"
"generalError": "An error has occurred",
"walletSupportsETHOnly": "Ethereum Only"
},
"updateToast": {
"body": "A new version of the app is available",
Expand Down Expand Up @@ -852,6 +853,21 @@
"body": "Unable to connect Portis wallet"
}
},
"walletConnect": {
"errors": {
"unknown": "An unexpected error occurred communicating with WalletConnect",
"connectFailure": "Unable to connect WalletConnect wallet"
},
"connect": {
"header": "Pair WalletConnect",
"body": "Click Pair then select WalletConnect from the popup window",
"button": "Pair"
},
"failure": {
"header": "Error",
"body": "Unable to connect WalletConnect wallet"
}
},
"xdefi": {
"errors": {
"unknown": "An unexpected error occurred communicating with XDEFI",
Expand Down
15 changes: 15 additions & 0 deletions src/assets/translations/es/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,21 @@
"body": "Al conectar una billetera, acepta los Términos de servicio de ShapeShift y reconoce que ha leído y comprende el descargo de responsabilidad de ShapeShift.",
"footer": "¿No tienes billetera?",
"create": "Crea una"
},
"walletConnect": {
"errors": {
"unknown": "Ocurrió un error inesperado al comunicarse con WalletConnect",
"connectFailure": "No se puede conectar la billetera WalletConnect"
},
"connect": {
"header": "Emparejar WalletConnect",
"body": "Haga clic en Emparejar y luego seleccione WalletConnect en la ventana emergente",
"button": "Emparejar"
},
"failure": {
"header": "Error",
"body": "No se puede conectar la billetera WalletConnect"
}
}
},
"graph": {
Expand Down
15 changes: 15 additions & 0 deletions src/assets/translations/fr/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,21 @@
"body": "En connectant un porte-monnaie, vous acceptez les conditions d'utilisation de ShapeShift et reconnaissez avoir lu et compris la clause de non-responsabilité de ShapeShift.",
"footer": "Vous n'avez pas de porte-monnaie ?",
"create": "Créez-en un"
},
"walletConnect": {
"errors": {
"unknown": "Une erreur inattendue s'est produite lors de la communication avec WalletConnect",
"connectFailure": "Impossible de connecter le porte-monnaie WalletConnect."
},
"connect": {
"header": "Appairer WalletConnect",
"body": "Cliquez sur Appairer et connectez-vous à WalletConnect à partir de la fenêtre popup",
"button": "Appairer"
},
"failure": {
"header": "Erreur",
"body": "Impossible de se connecter au porte-monnaie WalletConnect"
}
}
},
"graph": {
Expand Down
15 changes: 15 additions & 0 deletions src/assets/translations/id/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,21 @@
"body": "Dengan menghubungkan dompet, Anda menyetujui Persyaratan Layanan ShapeShift dan mengakui bahwa Anda telah membaca dan memahami penafian ShapeShift.",
"footer": "Tidak punya dompet?",
"create": "Buat Satu"
},
"walletConnect": {
"errors": {
"unknown": "Terjadi kesalahan tak terduga saat berkomunikasi dengan WalletConnect",
"connectFailure": "Tidak dapat menghubungkan dompet WalletConnect"
},
"connect": {
"header": "Pasangkan WalletConnect",
"body": "Klik Pasangkan lalu pilih WalletConnect dari jendela popup",
"button": "Pasangkan"
},
"failure": {
"header": "Kesalahan",
"body": "Tidak dapat menghubungkan dompet WalletConnect"
}
}
},
"graph": {
Expand Down
15 changes: 15 additions & 0 deletions src/assets/translations/ko/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,21 @@
"body": "지갑을 연결하는 것으로, 셰이프시프트의 서비스 약관에 동의하며 셰이프시프트의 면책 및 면피 조항을 읽고 이해했음을 확인합니다.",
"footer": "지갑이 없으신가요?",
"create": "지갑 만들기"
},
"walletConnect": {
"errors": {
"unknown": "WalletConnect와 연동하는 도중에 예기치 못한 오류가 발생했습니다.",
"connectFailure": "WalletConnect 지갑을 연결할 수 없습니다."
},
"connect": {
"header": "WalletConnect 지갑 연동하기",
"body": "연결하기 버튼을 누른 후 팝업창에서 WalletConnect를 선택하세요.",
"button": "연결하기"
},
"failure": {
"header": "오류 발생",
"body": "WalletConnect 지갑을 연결할 수 없습니다."
}
}
},
"graph": {
Expand Down
16 changes: 16 additions & 0 deletions src/assets/translations/pt/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,22 @@
"header": "Conecte sua carteira",
"body": "Ao conectar sua carteira, você concorda com os Termos de Serviço da ShapeShift e reconhece que leu e entendeu o aviso legal da ShapeShift.",
"footer": "Não tem carteira?",
"create": "Crie um"
},
"walletConnect": {
"errors": {
"unknown": "Ocorreu um erro inesperado na comunicação com a WalletConnect",
"connectFailure": "Não foi possível conectar sua carteira WalletConnect"
},
"connect": {
"header": "Emparelhar WalletConnect",
"body": "Clique em Emparelhar e conecte sua carteira WalletConnect na janela pop-up",
"button": "Emparelhar"
},
"failure": {
"header": "Erro",
"body": "Não foi possível conectar sua carteira WalletConnect"
},
"create": "Crie uma carteira"
}
},
Expand Down
15 changes: 15 additions & 0 deletions src/assets/translations/ru/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,21 @@
"selectModal": {
"header": "Подключить кошелек",
"body": "Подключая кошелек, вы соглашаетесь с Условиями предоставления услуг ShapeShift и подтверждаете, что прочитали и поняли отказ от ответственности ShapeShift."
},
"walletConnect": {
"errors": {
"unknown": "Возникла непредвиденная ошибка при соединении с WalletConnect",
"connectFailure": "Невозможно подключить кошелек WalletConnect"
},
"connect": {
"header": "Обьединить WalletConnect",
"body": "Нажмите обьединить, затем выберите WalletConnect во всплывающем окне",
"button": "Обьединить"
},
"failure": {
"header": "Ошибка",
"body": "Невозможно подключить кошелек WalletConnect"
}
}
},
"graph": {
Expand Down
15 changes: 15 additions & 0 deletions src/assets/translations/zh/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,21 @@
"body": "连接一个钱包代表您同意接受 ShapeShift 的服务条款并确认您已经阅读并理解 Shapeshift 的免责声明。",
"footer": "还没有钱包?",
"create": "创建一个"
},
"walletConnect": {
"errors": {
"unknown": "与您的 WalletConnect 通讯出现未知错误",
"connectFailure": "无法连接 WalletConnect"
},
"connect": {
"header": "与 WalletConnect 配对",
"body": "点击配对并在弹窗中选择 WalletConnect",
"button": "配对"
},
"failure": {
"header": "错误",
"body": "无法连接 WalletConnect"
}
}
},
"graph": {
Expand Down
19 changes: 19 additions & 0 deletions src/components/Icons/WalletConnectIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createIcon } from '@chakra-ui/react'

/**
* WalletConnect Icon
*
* @see https://github.com/WalletConnect/walletconnect-docs/blob/main/static/img/walletconnect-logo.svg
*/
export const WalletConnectIcon = createIcon({
displayName: 'WalletConnectIcon',
path: (
<svg>
<path
d='M61.4385429,36.2562612 C110.349767,-11.6319051 189.65053,-11.6319051 238.561752,36.2562612 L244.448297,42.0196786 C246.893858,44.4140867 246.893858,48.2961898 244.448297,50.690599 L224.311602,70.406102 C223.088821,71.6033071 221.106302,71.6033071 219.883521,70.406102 L211.782937,62.4749541 C177.661245,29.0669724 122.339051,29.0669724 88.2173582,62.4749541 L79.542302,70.9685592 C78.3195204,72.1657633 76.337001,72.1657633 75.1142214,70.9685592 L54.9775265,51.2530561 C52.5319653,48.8586469 52.5319653,44.9765439 54.9775265,42.5821357 L61.4385429,36.2562612 Z M280.206339,77.0300061 L298.128036,94.5769031 C300.573585,96.9713 300.573599,100.85338 298.128067,103.247793 L217.317896,182.368927 C214.872352,184.763353 210.907314,184.76338 208.461736,182.368989 C208.461726,182.368979 208.461714,182.368967 208.461704,182.368957 L151.107561,126.214385 C150.496171,125.615783 149.504911,125.615783 148.893521,126.214385 C148.893517,126.214389 148.893514,126.214393 148.89351,126.214396 L91.5405888,182.368927 C89.095052,184.763359 85.1300133,184.763399 82.6844276,182.369014 C82.6844133,182.369 82.684398,182.368986 82.6843827,182.36897 L1.87196327,103.246785 C-0.573596939,100.852377 -0.573596939,96.9702735 1.87196327,94.5758653 L19.7936929,77.028998 C22.2392531,74.6345898 26.2042918,74.6345898 28.6498531,77.028998 L86.0048306,133.184355 C86.6162214,133.782957 87.6074796,133.782957 88.2188704,133.184355 C88.2188796,133.184346 88.2188878,133.184338 88.2188969,133.184331 L145.571,77.028998 C148.016505,74.6345347 151.981544,74.6344449 154.427161,77.028798 C154.427195,77.0288316 154.427229,77.0288653 154.427262,77.028899 L211.782164,133.184331 C212.393554,133.782932 213.384814,133.782932 213.996204,133.184331 L271.350179,77.0300061 C273.79574,74.6355969 277.760778,74.6355969 280.206339,77.0300061 Z'
fill='#3B99FC'
></path>
</svg>
),
viewBox: '0 0 300 185',
})
15 changes: 13 additions & 2 deletions src/components/Modals/Send/views/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { SlideTransition } from 'components/SlideTransition'
import { Text } from 'components/Text'
import { TokenRow } from 'components/TokenRow/TokenRow'
import { useModal } from 'hooks/useModal/useModal'
import { useWallet } from 'hooks/useWallet/useWallet'

import type { SendInput } from '../Form'
import { useSendDetails } from '../hooks/useSendDetails/useSendDetails'
Expand Down Expand Up @@ -52,6 +53,10 @@ export const Details = () => {
toggleCurrency,
} = useSendDetails()

const {
state: { wallet },
} = useWallet()

if (
!(
asset &&
Expand Down Expand Up @@ -135,7 +140,11 @@ export const Details = () => {
{cryptoSymbol}
</Button>
}
inputRightElement={<SendMaxButton onClick={handleSendMax} />}
inputRightElement={
wallet?.getVendor() === 'WalletConnect' ? null : (
<SendMaxButton onClick={handleSendMax} />
)
}
rules={{
required: true,
}}
Expand All @@ -161,7 +170,9 @@ export const Details = () => {
</Button>
}
inputRightElement={
<SendMaxButton onClick={handleSendMax} data-test='send-max-button' />
wallet?.getVendor() === 'WalletConnect' ? null : (
<SendMaxButton onClick={handleSendMax} />
)
}
rules={{
required: true,
Expand Down
24 changes: 13 additions & 11 deletions src/components/Trade/TradeInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,17 +293,19 @@ export const TradeInput = ({ history }: RouterProps) => {
/>
}
inputRightElement={
<Button
h='1.75rem'
size='sm'
variant='ghost'
colorScheme='blue'
isDisabled={isSendMaxLoading || !hasValidBalance || !quote}
onClick={onSetMaxTrade}
data-test='token-row-sell-max-button'
>
Max
</Button>
!(wallet?.getVendor() === 'WalletConnect') ? (
<Button
h='1.75rem'
size='sm'
variant='ghost'
colorScheme='blue'
isDisabled={isSendMaxLoading || !hasValidBalance || !quote}
onClick={onSetMaxTrade}
data-test='token-row-sell-max-button'
>
Max
</Button>
) : null
}
data-test='trade-form-token-input-row-sell'
/>
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ const validators = {
REACT_APP_FEATURE_YEARN: bool({ default: true }),
REACT_APP_FEATURE_OSMOSIS: bool({ default: false }),
REACT_APP_FEATURE_MULTI_CURRENCY: bool({ default: false }),
REACT_APP_FEATURE_WALLETCONNECT_WALLET: bool({ default: false }),
REACT_APP_FEATURE_AVALANCHE: bool({ default: false }),
REACT_APP_FEATURE_THOR: 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 }),
REACT_APP_TOKEMAK_STATS_URL: url({ default: 'https://stats.tokemaklabs.com/' }),
REACT_APP_COINGECKO_API_KEY: str({ default: '' }), // not required, we can fall back to the free tier
REACT_APP_LOCAL_IP: str({ default: '192.168.1.222' }),
REACT_APP_BOARDROOM_API_BASE_URL: url({
default: 'https://api.boardroom.info/v1/protocols/shapeshift/',
}),
Expand Down
1 change: 1 addition & 0 deletions src/context/WalletProvider/KeyManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export enum KeyManager {
TallyHo = 'tallyho',
Portis = 'portis',
Demo = 'demo',
WalletConnect = 'walletconnect',
XDefi = 'xdefi',
Keplr = 'keplr',
}
Loading

0 comments on commit ea60e8e

Please sign in to comment.