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: add WalletConnect integration for Ledger devices #720

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
9114e0e
feat: add WalletConnect integration for Ledger devices
devin-ai-integration[bot] Feb 6, 2025
1313fb3
Merge branch 'master-polymorpher' into devin/1738830151-fix-ledger-si…
polymorpher Feb 6, 2025
4e02ae5
fix: update WalletConnect integration to use wagmi contract methods
devin-ai-integration[bot] Feb 6, 2025
085b220
chore: update babel config to support optional chaining
devin-ai-integration[bot] Feb 7, 2025
5e3867e
Merge branch 'master' into devin/1738830151-fix-ledger-signing
polymorpher Feb 12, 2025
258e27e
Reapply "fix: update chromedriver and add M1/M2 Mac support (#718)"
polymorpher Feb 12, 2025
e624b4e
chore: update @wagmi/core and viem dependencies
devin-ai-integration[bot] Feb 12, 2025
35fbbac
chore: remove @babel/polyfill import in favor of babel useBuiltIns usage
devin-ai-integration[bot] Feb 12, 2025
b36cc73
feat: add wagmi configuration for Harmony Mainnet
devin-ai-integration[bot] Feb 12, 2025
9f19746
feat: add contract interaction utilities using wagmi
devin-ai-integration[bot] Feb 12, 2025
b6328e0
fix: use numeric decimals instead of string unit for parseUnits
devin-ai-integration[bot] Feb 12, 2025
cbd48e1
fix: add TypeScript types for contract interaction utilities
devin-ai-integration[bot] Feb 12, 2025
128db1e
fix: handle undefined amount in contract interactions
devin-ai-integration[bot] Feb 12, 2025
f85cd48
fix: restore parseUnits usage for amount conversion
devin-ai-integration[bot] Feb 12, 2025
975a4b2
chore: resolve merge conflicts in yarn.lock
devin-ai-integration[bot] Feb 12, 2025
4653e59
remove some dependencies
polymorpher Feb 12, 2025
5c61134
add back package
polymorpher Feb 12, 2025
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
5 changes: 5 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
"@ledgerhq/hw-transport-webhid": "^5.7.0",
"@ledgerhq/hw-transport-webusb": "4.74.1",
"@metamask/detect-provider": "1.2.0",
"@wagmi/vue": "^0.1.9",
"@reown/appkit": "^1.6.6",
"@reown/appkit-adapter-wagmi": "^1.6.6",
"@tanstack/vue-query": "^4.36.1",
"viem": "^1.21.4",
"@safe-global/safe-apps-provider": "^0.16.0",
"@safe-global/safe-apps-react-sdk": "^4.6.4",
"@safe-global/safe-apps-sdk": "^7.10.1",
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/ActionModal/components/ActionModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,8 @@ const SIGN_METHODS = {
MATHWALLET: `mathwallet`,
ONEWALLET: `onewallet`,
METAMASK: `metamask`,
MULTISIG: 'multisig'
MULTISIG: 'multisig',
WALLETCONNECT: 'walletconnect'
}

const signMethodOptions = {
Expand Down Expand Up @@ -1302,4 +1303,4 @@ export default {
top: 0;
}
} */
</style>
</style>
6 changes: 3 additions & 3 deletions frontend/src/components/common/TmSessionExisting.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
/>
<LiSession
v-if="!isMobileApp && !isIframe"
id="use-ledger-nano"
id="use-ledger-walletconnect"
icon="vpn_key"
title="Use Ledger Nano (Pending Maintenance)"
route="ledger"
title="Use Ledger via WalletConnect"
route="walletconnect"
/>

<LiSession
Expand Down
66 changes: 66 additions & 0 deletions frontend/src/components/common/TmSessionWalletConnect.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<template>
<SessionFrame>
<div class="session-container">
<h2 class="session-title">Use Ledger with WalletConnect</h2>
<div class="session-main">
<p>Connect your Ledger device through Ledger Live using WalletConnect</p>
<TmBtn value="Connect Wallet" @click.native="signIn()" />
</div>
</div>
</SessionFrame>
</template>

<script>
import SessionFrame from "common/SessionFrame"
import { sessionType } from "src/ActionModal/components/ActionModal"
import { initWalletConnect } from "scripts/walletconnect-utils"
import { toBech32 } from "@harmony-js/crypto"
import TmBtn from "common/TmBtn"

export default {
name: 'session-walletconnect',
components: {
SessionFrame,
TmBtn
},
data: () => ({
modal: null
}),
mounted() {
// TODO: Replace with actual project ID from cloud.reown.com
this.modal = initWalletConnect('harmony-staking-dashboard')
},
methods: {
async signIn() {
try {
const accounts = await this.modal.getAccounts()
if (accounts.length === 0) {
console.error("No accounts found")
return
}

this.$store.dispatch("signIn", {
sessionType: sessionType.WALLETCONNECT,
address: toBech32(accounts[0])
})

this.$router.push('/')
} catch (ex) {
console.error("WalletConnect error:", ex)
}
}
}
}
</script>

<style scoped>
.session-title {
padding: 0 1rem;
margin: 0;
}

.session-main {
padding: 1rem;
text-align: center;
}
</style>
10 changes: 10 additions & 0 deletions frontend/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,16 @@ export default [
feature: "Session",
},
},
{
path: `/walletconnect`,
name: `walletconnect`,
components: {
session: require(`./components/common/TmSessionWalletConnect`).default,
},
meta: {
feature: "Session",
},
},
{
path: `/multisig`,
name: `multisig`,
Expand Down
93 changes: 93 additions & 0 deletions frontend/src/scripts/walletconnect-utils/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { createAppKit } from '@reown/appkit/vue'
import { mainnet } from '@reown/appkit/networks'
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { toBech32 } from "@harmony-js/crypto"

const HARMONY_MAINNET = {
id: 1666600000,
name: 'Harmony Mainnet',
network: 'harmony',
nativeCurrency: { name: 'ONE', symbol: 'ONE', decimals: 18 },
rpcUrls: {
default: { http: ['https://api.harmony.one'] },
public: { http: ['https://api.harmony.one'] },
},
blockExplorers: {
default: { name: 'Explorer', url: 'https://explorer.harmony.one/' },
},
}

export const initWalletConnect = (projectId) => {
const metadata = {
name: 'Harmony Staking',
description: 'Harmony Staking Dashboard',
url: window.location.origin,
icons: ['https://staking.harmony.one/icons/icon-512x512.png']
}

const wagmiAdapter = new WagmiAdapter({
networks: [HARMONY_MAINNET],
projectId
})

return createAppKit({
adapters: [wagmiAdapter],
networks: [HARMONY_MAINNET],
projectId,
metadata,
features: {
analytics: true
}
})
}

export const processWalletConnectMessage = async (transactionData, fee, networkConfig) => {
const { gasEstimate } = fee
const { chain_id, rpc_url } = networkConfig

const harmony = new Harmony(rpc_url, {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incorrect. Harmony class is undefined. Please do not simply copy from old implementations. Instead, properly invoke correct contract calling methods from wagmi

chainType: ChainType.Harmony,
chainId: chain_id
})

const txnParams = {
gasLimit: Unit.Wei(new BN(gasEstimate).add(new BN("20000"))).toHex(),
gasPrice: Unit.Wei(new BN(1000000000)).toHex(),
chainId: harmony.chainId
}

switch (transactionData.type) {
case "MsgSend":
return harmony.transactions.signTransaction({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, this is incorrect because the instance harmony would not exist and would not have the field transactions

...txnParams,
to: transactionData.to,
value: Unit.Wei(transactionData.amount).toHex(),
data: "0x"
})

case "MsgDelegate":
return harmony.stakings.delegate({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

...txnParams,
delegatorAddress: transactionData.delegatorAddress,
validatorAddress: transactionData.validatorAddress,
amount: Unit.Wei(transactionData.amount).toHex()
})

case "MsgUndelegate":
return harmony.stakings.undelegate({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

...txnParams,
delegatorAddress: transactionData.delegatorAddress,
validatorAddress: transactionData.validatorAddress,
amount: Unit.Wei(transactionData.amount).toHex()
})

case "MsgWithdrawDelegationReward":
return harmony.stakings.collectRewards({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

...txnParams,
delegatorAddress: transactionData.delegatorAddress
})

default:
throw new Error(`Unknown transaction type: ${transactionData.type}`)
}
}
Loading