Skip to content

Commit

Permalink
Merge pull request #129 from consensusnetworks/feature/wallet-connect…
Browse files Browse the repository at this point in the history
…-init

Add WalletConnect functionality (enable, disable, sendTransaction)
  • Loading branch information
ccali11 authored Sep 20, 2022
2 parents 6488a07 + 0b5fdc5 commit ab3b95d
Show file tree
Hide file tree
Showing 8 changed files with 1,814 additions and 1,080 deletions.
2 changes: 2 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"@heroicons/vue": "^1.0.6",
"@ledgerhq/hw-app-eth": "^6.29.4",
"@ledgerhq/hw-transport-webhid": "^6.27.2",
"@walletconnect/client": "^1.8.0",
"@walletconnect/qrcode-modal": "^1.8.0",
"buffer": "^6.0.3",
"ethers": "^5.6.9",
"iotex-antenna": "^0.31.3",
Expand Down
76 changes: 50 additions & 26 deletions apps/web/src/components/Wallet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
</p>
</div>
<div class="coinbase-div">
<button
class="coinbase-btn"
@click="connectWallet('CoinbaseWallet')"
>
<button class="coinbase-btn" @click="connectWallet('CoinbaseWallet')">
{{ coinbaseButtonText }}
</button>
<p>
Expand All @@ -23,42 +20,46 @@
</p>
</div>
<div class="ioPay-div">
<button
class="iopay-btn"
@click="connectWallet('IoPay')"
>
<button class="iopay-btn" @click="connectWallet('IoPay')">
{{ ioPayButtonText }}
</button>
<p>
Connected ioPay Account:
<span> {{ ioPayAccountsResult }} </span>
</p>
</div>
<button
class="ledger-btn"
@click="connectWallet('Ledger')"
>
<button class="ledger-btn" @click="connectWallet('Ledger')">
Connect Ledger
</button>
<div>
<button
class="wallet-connect-btn"
@click="connectWallet('WalletConnect')"
>
WalletConnect
</button>
<button
class="wallet-connect-btn"
@click="sendTransaction('WalletConnect')"
>
Send WalletConnect Transaction
</button>
<button
class="wallet-connect-btn"
@click="disconnectWallet('WalletConnect')"
>
Disable WalletConnect
</button>
</div>
</div>
<div class="form-container">
<form @submit.prevent="sendTransaction(selectedProvider)">
<label for="address">Address</label>
<input
v-model="toAddress"
type="text"
placeholder="To Address"
>
<br>
<input v-model="toAddress" type="text" placeholder="To Address" />
<br />
<label for="amount">Amount</label>
<input
v-model="amount"
type="text"
placeholder="Amount Ether"
>
<button type="submit">
Send Transaction
</button>
<input v-model="amount" type="text" placeholder="Amount Ether" />
<button type="submit">Send Transaction</button>
</form>
</div>
</div>
Expand All @@ -81,6 +82,7 @@ const {
toAddress,
amount,
connectWallet,
disconnectWallet,
sendTransaction,
} = useWallet()
Expand Down Expand Up @@ -190,4 +192,26 @@ input {
width: 500px;
padding: 1rem;
}
.wallet-connect-btn {
display: flex;
justify-content: center;
align-items: center;
border-radius: 8px;
font-size: 16px;
height: 44px;
/* width: 50%; */
transition: all 0.15s ease-in-out 0s;
background-color: rgb(64, 153, 255);
border: none;
color: rgb(255, 255, 255);
box-shadow: rgb(50 50 93 / 11%) 0px 4px 6px 0px,
rgb(0 0 0 / 8%) 0px 1px 3px 0px, rgb(0 0 0 / 6%) 0px 0px 1px 0px inset;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
padding: 8px 12px;
cursor: pointer;
will-change: transform;
}
</style>
33 changes: 24 additions & 9 deletions apps/web/src/composables/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ import { ethers } from 'ethers'
import useIoPay from '@/composables/iopay'
import useLedger from '@/composables/ledger'
import useEthers from '@/composables/ethers'
import useWalletConnect from '@/composables/walletConnect'
import { BrowserProviders } from '@/interfaces/BrowserProviders'
import { EthersProvider } from '@/interfaces/EthersProvider'
import { ProviderString } from '@/types/ProviderString'

const amount = ref<string>('')
const toAddress = ref<string>('')
const { requestEthersAccount } = useEthers()

const defaultProviders = {
MetaMask: undefined,
CoinbaseWallet: undefined,
}

const ethersProviderList = ['MetaMask', 'CoinbaseWallet']

const { requestEthersAccount } = useEthers()
const { enableWalletConnect, disableWalletConnect, sendWalletConnectTx } =
useWalletConnect()

const amount = ref<string>('0.01')
const toAddress = ref<string>('0xD4e5faa8aD7d499Aa03BDDE2a3116E66bc8F8203')
// Test ethereum send to address : 0xD4e5faa8aD7d499Aa03BDDE2a3116E66bc8F8203
// Test iotex send to address: acc://06da5e904240736b1e21ca6dbbd5f619860803af04ff3d54/acme

Expand All @@ -40,7 +43,9 @@ export default function useWallet() {
try {
setSelectedProvider(provider)
selectedAccount.value = 'Not Active'
if (ethersProviderList.includes(provider)) {
if (provider === 'WalletConnect') {
enableWalletConnect()
} else if (ethersProviderList.includes(provider)) {
const browserExtensionProvider =
availableProviders.value[provider as keyof BrowserProviders]
const accounts = await requestEthersAccount(
Expand All @@ -65,9 +70,20 @@ export default function useWallet() {
}
}

// TODO: Fold this into the logic of switching to/from other wallet provider depending on front-end implementation
async function disconnectWallet(provider: ProviderString) {
selectedAccount.value = ''
selectedProvider.value = ''
if (provider === 'WalletConnect') {
await disableWalletConnect()
}
}

async function sendTransaction(provider: string) {
try {
if (ethersProviderList.includes(provider)) {
if (provider === 'WalletConnect') {
await sendWalletConnectTx(amount.value, toAddress.value)
} else if (ethersProviderList.includes(provider)) {
const browserProvider =
availableProviders.value[provider as keyof BrowserProviders]
const web3Provider: ethers.providers.Web3Provider =
Expand All @@ -84,14 +100,12 @@ export default function useWallet() {
} else if (selectedProvider.value === 'IoPay') {
await sendIoPayTransaction(toAddress.value, amount.value)
} else if (selectedProvider.value === 'Ledger') {

// npm run dev:ethereum in another process
// const ledgerEth = await getLedgerEthSigner()
// Create - { to: ... }
// Serialize - ethers.utils.serializeTransaction
// Sign - ledgerEth.signTransaction
// Send - (new ethers.providers.JsonRpcProvider("http://127.0.0.1:8545")).sendTransaction

} else {
throw new Error('Provider selected not yet supported')
}
Expand All @@ -106,6 +120,7 @@ export default function useWallet() {
toAddress,
amount,
connectWallet,
disconnectWallet,
sendTransaction,
}
}
Expand Down
84 changes: 84 additions & 0 deletions apps/web/src/composables/walletConnect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import WalletConnect from '@walletconnect/client'
import QRCodeModal from '@walletconnect/qrcode-modal'
import { ref, Ref } from 'vue'
import { ethers } from 'ethers'

export default function useWalletConnect() {
const connector: Ref<WalletConnect | undefined> = ref()
const walletConnectAddress: Ref<string> = ref('')
function enableWalletConnect() {
connector.value = new WalletConnect({
bridge: 'https://bridge.walletconnect.org', // Required
qrcodeModal: QRCodeModal,
})
if (!connector.value.connected) {
connector.value.createSession()
}
connector.value.on('connect', (error: any, payload: any) => {
if (error) {
throw error
}
// Get provided accounts and chainId
const { accounts, chainId } = payload.params[0]
walletConnectAddress.value = accounts[0]
})
connector.value.on('session_update', (error: any, payload: any) => {
if (error) {
throw error
}
// Get updated accounts and chainId
const { accounts, chainId } = payload.params[0]
})
connector.value.on('disconnect', (error: any) => {
if (error) {
console.log(`disconnect error :>> ${error}`)
// throw error
}
// Delete connector
try {
connector.value?.killSession()
} catch (error) {
console.log(`disconnect error in listener :>> ${error}`)
}
})
return
}

async function sendWalletConnectTx(amount: string, toAddress: string) {
const amountInWei = ethers.utils.parseEther(amount).toString()

// TODO: Better understand and handle gasPrice and gasLimit
const gasLimit = ethers.utils.hexlify(21000).toString()
const gasPrice = ethers.utils.hexlify(1000000000).toString()
const tx = {
from: walletConnectAddress.value,
to: toAddress,
gas: gasLimit,
gasPrice: gasPrice,
value: amountInWei,
// data: 'data', // TODO: Determine when this is needed.
// nonce: 'nonce', // TODO: Determine when this is needed.
}
try {
const result = await connector.value?.sendTransaction(tx)
console.log('result :>> ', result)
} catch (err) {
console.log('error in sendWalletConnectTx :>> ', err)
}
}

async function disableWalletConnect() {
try {
await connector.value?.killSession()
} catch (err) {
console.log('error in disableWalletConnect :>> ', err)
}
}

return {
enableWalletConnect,
sendWalletConnectTx,
disableWalletConnect,
walletConnectAddress,
}
}
7 changes: 6 additions & 1 deletion apps/web/src/types/ProviderString.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
import { BrowserProviders } from '@/interfaces/BrowserProviders'
export type ProviderString = keyof BrowserProviders | 'IoPay' | 'Ledger' |''
export type ProviderString =
| keyof BrowserProviders
| 'IoPay'
| 'Ledger'
| 'WalletConnect'
| ''
27 changes: 24 additions & 3 deletions contracts/evm/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import localtunnel from 'localtunnel'
import os from 'os'
import { task } from 'hardhat/config'
import '@typechain/hardhat'
import '@nomiclabs/hardhat-waffle'
Expand All @@ -13,8 +15,10 @@ task('accounts', 'Prints the list of accounts', async (taskArgs: any, hre: { eth
}
})

// Get shared test seed
const mnemonic = process.env.LEDGER_SEED
// Use Ledger seed for consistency from localnet to testnet
const defaultSeed = 'test test test test test test test test test test test junk'
const mnemonic = process.env.LEDGER_SEED || defaultSeed
console.log('Your mnemonic is', mnemonic)

// Go to https://hardhat.org/config/ to learn more
const config: HardhatUserConfig = {
Expand All @@ -30,9 +34,26 @@ const config: HardhatUserConfig = {
},
networks: {
hardhat: {
accounts: mnemonic ? { mnemonic } : {}
chainId: 1337,
accounts: { mnemonic, accountsBalance: '32000000000000000000' }
}
}
}

// Start a local tunnel for using RPC with https
const localSubdomain = `cn-hh-${os.userInfo().username.toLowerCase()}`
const localUrl = `https://${localSubdomain}.loca.lt`
console.log('Your local tunnel is', localUrl)
localtunnel({ port: 8545, subdomain: localSubdomain }).then((tunnel: localtunnel.Tunnel) => {
if (localUrl === tunnel.url) {
console.log('Your local tunnel is now available at', localUrl)
} else {
console.log('Your desired local tunnel url is not available')
}
process.on('SIGINT', () => {
tunnel.close()
process.exit(0)
})
})

export default config
3 changes: 2 additions & 1 deletion contracts/evm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
"@typechain/ethers-v5": "^10.1.0",
"@typechain/hardhat": "^6.1.2",
"@types/chai": "^4.3.1",
"@types/localtunnel": "^2.0.1",
"@types/mocha": "^9.1.1",
"@types/node": "^17.0.45",
"chai": "^4.3.6",
"ethereum-waffle": "^3.4.4",
"ethers": "^5.6.9",
"hardhat": "^2.9.9",
"localtunnel": "^2.0.2",
"ts-node": "^10.8.2",
"typechain": "^8.1.0"
}
Expand Down
Loading

0 comments on commit ab3b95d

Please sign in to comment.