Skip to content

Commit

Permalink
feat: add support for Brave wallet (#828)
Browse files Browse the repository at this point in the history
Signed-off-by: Logan Nguyen <[email protected]>
Signed-off-by: Eric Le Ponner <[email protected]>
Co-authored-by: Logan Nguyen <[email protected]>
  • Loading branch information
ericleponner and quiet-node authored Jan 31, 2024
1 parent 66b4e82 commit 873d342
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 33 deletions.
18 changes: 9 additions & 9 deletions src/utils/wallet/WalletDriver_Blade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ export class WalletDriver_Blade extends WalletDriver_Hedera {
const hNetwork = WalletDriver_Blade.makeHederaNetwork(network)
if (hNetwork !== null) {
const {BladeConnector, ConnectorStrategy} = await import("@bladelabs/blade-web3.js")
newConnector = await BladeConnector.init(
ConnectorStrategy.EXTENSION,
{
name: "HashScan",
description: "A ledger explorer for Hedera network",
url: "https://hashscan.io",
icons: [ HederaLogo ]
}
)
try {
newConnector = await BladeConnector.init(
ConnectorStrategy.EXTENSION,
{
name: "HashScan",
description: "A ledger explorer for Hedera network",
url: "https://hashscan.io",
icons: [ HederaLogo ]
}
)
const params = {
network: hNetwork,
dAppCode: "HashScan"
Expand Down
82 changes: 82 additions & 0 deletions src/utils/wallet/WalletDriver_Brave.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*-
*
* Hedera Mirror Node Explorer
*
* Copyright (C) 2021 - 2023 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import {BaseProvider} from '@metamask/providers';
import {WalletDriver_Ethereum} from "@/utils/wallet/WalletDriver_Ethereum";
import {WalletDriverError} from "@/utils/wallet/WalletDriverError";

export class WalletDriver_Brave extends WalletDriver_Ethereum {

private braveProvider: BaseProvider|null = null

//
// Public
//

public constructor() {
super("Brave Wallet",
"https://brave.com/static-assets/images/optimized/brave-branding-assets/images/brave-logo-color-RGB_reversed.png",
"https://brave.com/static-assets/images/brave-logo-no-shadow.png")
}

//
// WalletDriver_Ethereum
//

public async isExpectedProvider(provider: object): Promise<boolean> {
// https://wallet-docs.brave.com/ethereum/wallet-detection/
const clientVersion = await (provider as any).request({method: "web3_clientVersion"})
const isBraveWallet = clientVersion.split('/')[0] === 'BraveWallet'
this.braveProvider = isBraveWallet ? provider as BaseProvider : null
return this.braveProvider !== null
}

public async connect(network: string): Promise<string[]> {
const result = await super.connect(network)
this.braveProvider?.on('chainChanged', this.handleDisconnect)
return Promise.resolve(result)
}

public async disconnect(): Promise<void> {
this.braveProvider?.removeListener("chainChanged", this.handleDisconnect)
this.braveProvider = null
return super.disconnect()
}

//
// WalletDriver
//

public extensionNotFound(): WalletDriverError {
// Brave wallet is builtin to Brave browser => we adapt wording
const message = "Cannot access to " + this.name
const extra = "Make sure to use Brave browser and enable wallet in browser settings."
return new WalletDriverError(message, extra)
}


//
// Private
//

private readonly handleDisconnect = () => this.disconnect()


}
4 changes: 3 additions & 1 deletion src/utils/wallet/WalletManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,18 @@ import {WalletDriver_Hedera} from "@/utils/wallet/WalletDriver_Hedera";
import {WalletDriver_Metamask} from "@/utils/wallet/WalletDriver_Metamask";
import {WalletDriver_Ethereum} from "@/utils/wallet/WalletDriver_Ethereum";
import {WalletDriver_Coinbase} from "@/utils/wallet/WalletDriver_Coinbase";
import {WalletDriver_Brave} from '@/utils/wallet//WalletDriver_Brave';

export class WalletManager {

private readonly routeManager: RouteManager
private readonly bladeDriver = new WalletDriver_Blade()
private readonly braveDriver = new WalletDriver_Brave()
private readonly hashpackDriver = new WalletDriver_Hashpack()
private readonly metamaskDriver = new WalletDriver_Metamask()
private readonly coinbaseDriver = new WalletDriver_Coinbase()
private readonly drivers: Array<WalletDriver> = [
this.bladeDriver, this.hashpackDriver, this.metamaskDriver, this.coinbaseDriver]
this.bladeDriver, this.hashpackDriver, this.metamaskDriver, this.coinbaseDriver, this.braveDriver]
private readonly timeout = 30000; // milliseconds


Expand Down
15 changes: 8 additions & 7 deletions tests/unit/App.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,20 @@ describe("App.vue", () => {
expect(cards[2].text()).toMatch(RegExp("^HCS Messages"))

const logos = wrapper.findAll("img")
expect(logos.length).toBe(12)
expect(logos.length).toBe(13)
expect(logos[0].attributes('alt')).toBe("")
expect(logos[1].attributes('alt')).toBe("wallet logo")
expect(logos[2].attributes('alt')).toBe("wallet logo")
expect(logos[3].attributes('alt')).toBe("wallet logo")
expect(logos[4].attributes('alt')).toBe("wallet logo")
expect(logos[5].attributes('alt')).toBe("Modal close icon")
expect(logos[6].attributes('alt')).toBe("Product Logo")
expect(logos[7].attributes('alt')).toBe("Modal close icon")
expect(logos[8].attributes('alt')).toBe("Trend Up")
expect(logos[5].attributes('alt')).toBe("wallet logo")
expect(logos[6].attributes('alt')).toBe("Modal close icon")
expect(logos[7].attributes('alt')).toBe("Product Logo")
expect(logos[8].attributes('alt')).toBe("Modal close icon")
expect(logos[9].attributes('alt')).toBe("Trend Up")
expect(logos[10].attributes('alt')).toBe("Built On Hedera")
expect(logos[11].attributes('alt')).toBe("Sponsor Logo")
expect(logos[10].attributes('alt')).toBe("Trend Up")
expect(logos[11].attributes('alt')).toBe("Built On Hedera")
expect(logos[12].attributes('alt')).toBe("Sponsor Logo")

mock.restore()
wrapper.unmount()
Expand Down
33 changes: 17 additions & 16 deletions tests/unit/TopNavBar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe("TopNavBar.vue", () => {
"Connect WalletCANCELCONNECT DisclaimerPlease don't show me this next timeCANCELAGREEFillerFillerCLOSEDashboardTransactionsTokensTopicsContractsAccountsNodesStakingBlocksMAINNETTESTNETPREVIEWNETCONNECT WALLET...")

const links = wrapper.findAll("a")
expect(links.length).toBe(17)
expect(links.length).toBe(18)

wrapper.unmount()
await flushPromises()
Expand All @@ -83,29 +83,30 @@ describe("TopNavBar.vue", () => {
"Connect WalletCANCELCONNECT DisclaimerPlease don't show me this next timeCANCELAGREEFillerFillerCLOSEDashboardTransactionsTokensTopicsContractsAccountsNodesStakingBlocksMAINNETTESTNETPREVIEWNETCONNECT WALLET...")

const links = wrapper.findAll("a")
expect(links.length).toBe(17)

expect(links[8].text()).toBe("Dashboard")
expect(links[9].text()).toBe("Transactions")
expect(links[10].text()).toBe("Tokens")
expect(links[11].text()).toBe("Topics")
expect(links[12].text()).toBe("Contracts")
expect(links[13].text()).toBe("Accounts")
expect(links[14].text()).toBe("Nodes")
expect(links[15].text()).toBe("Staking")
expect(links[16].text()).toBe("Blocks")
expect(links.length).toBe(18)

expect(links[9].text()).toBe("Dashboard")
expect(links[10].text()).toBe("Transactions")
expect(links[11].text()).toBe("Tokens")
expect(links[12].text()).toBe("Topics")
expect(links[13].text()).toBe("Contracts")
expect(links[14].text()).toBe("Accounts")
expect(links[15].text()).toBe("Nodes")
expect(links[16].text()).toBe("Staking")
expect(links[17].text()).toBe("Blocks")

expect(wrapper.findComponent(SearchBar).exists()).toBe(true)

const logos = wrapper.findAll("img")
expect(logos.length).toBe(8)
expect(logos.length).toBe(9)
expect(logos[1].attributes('alt')).toBe("wallet logo")
expect(logos[2].attributes('alt')).toBe("wallet logo")
expect(logos[3].attributes('alt')).toBe("wallet logo")
expect(logos[4].attributes('alt')).toBe("wallet logo")
expect(logos[5].attributes('alt')).toBe("Modal close icon")
expect(logos[6].attributes('alt')).toBe("Product Logo")
expect(logos[7].attributes('alt')).toBe("Modal close icon")
expect(logos[5].attributes('alt')).toBe("wallet logo")
expect(logos[6].attributes('alt')).toBe("Modal close icon")
expect(logos[7].attributes('alt')).toBe("Product Logo")
expect(logos[8].attributes('alt')).toBe("Modal close icon")

wrapper.unmount()
await flushPromises()
Expand Down

0 comments on commit 873d342

Please sign in to comment.