Skip to content

Commit b42dca3

Browse files
authored
Merge pull request #279 from node-real/feat/binance-web3-wallet-extension-support
feat(binanceWallet): add browser extension support and improve desktop connection UX
2 parents 1af318e + fc1c64b commit b42dca3

9 files changed

Lines changed: 254 additions & 84 deletions

File tree

.changeset/warm-seahorses-watch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@node-real/walletkit': minor
3+
---
4+
5+
feat(binanceWallet): add browser extension support and improve desktop connection UX

.claude/settings.local.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(pnpm install:*)",
5+
"Bash(export:*)",
6+
"Bash(source:*)",
7+
"Bash(find:*)"
8+
]
9+
}
10+
}

CLAUDE.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# CLAUDE.md
2+
3+
## Project Overview
4+
5+
WalletKit is a React component library for connecting wallets to dApps. Supports EVM, Solana, and Tron chains.
6+
7+
- Monorepo managed by pnpm workspaces
8+
- Main package: `packages/walletkit` (published as `@node-real/walletkit`)
9+
- Package manager: pnpm 9.x (requires Node.js v20+)
10+
11+
## Common Commands
12+
13+
```sh
14+
# Install dependencies
15+
pnpm install
16+
17+
# Development (runs __dev__ example with hot reload)
18+
pnpm dev
19+
20+
# Build the walletkit package
21+
pnpm build
22+
23+
# Lint
24+
pnpm lint
25+
26+
# Create a changeset for versioning
27+
pnpm changeset
28+
```
29+
30+
## Project Structure
31+
32+
- `packages/walletkit/src/core/` - Shared core (UI components, configs, providers, utils)
33+
- `packages/walletkit/src/evm/` - EVM wallet connectors (wagmi-based)
34+
- `packages/walletkit/src/solana/` - Solana wallet adapters
35+
- `packages/walletkit/src/tron/` - Tron wallet adapters
36+
- `packages/walletkit/src/core/configs/` - Per-wallet config (name, logos, download URLs, spinner color)
37+
- `packages/walletkit/src/evm/wallets/` - Per-wallet connector logic with platform behaviors
38+
39+
## Code Standards
40+
41+
- All generated code, comments, and commit messages MUST be in English only.
42+
- Never expose private information (local filesystem paths, usernames, home directories, machine-specific details) in code, comments, commits, or PR descriptions.
43+
- Follow existing code patterns - check sibling wallet implementations for reference (e.g., `trustWallet/`, `okxWallet/`).
44+
- Use `@/` path alias for imports within `packages/walletkit/src/`.
45+
- Use `sleep` from `@/core/utils/common`, not from external packages.
46+
- Commits follow [Conventional Commits](https://www.conventionalcommits.org/) (enforced by commitlint).
47+
- Release workflow uses changesets: branch off `main` -> PR -> `pnpm changeset` -> merge to `alpha` -> test -> merge to `main`.

packages/walletkit/CHANGELOG.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,39 @@
11
# @node-real/walletkit
22

3+
## 2.8.0
4+
5+
### Minor Changes
6+
7+
- 5758de4: Use behavior configuration to control different connection behaviors on different
8+
platform
9+
- 5758de4: Refactor & add ConnectButton & ProfileModal
10+
- 5758de4: Support tg
11+
12+
### Patch Changes
13+
14+
- 5758de4: Update website
15+
- 5758de4: Support solana on mobile
16+
- 5758de4: Update trust deeplink on ios
17+
- 5758de4: Fix binance web3 wallet successfully detected trustwallet on mobile
18+
- 5758de4: Support connecting to a specified wallet based on its wallet id
19+
- 5758de4: Remove debug code
20+
- 5758de4: Fix styles
21+
- 5758de4: Only use binance sdk on pc
22+
- 5758de4: Fix trust issue
23+
- 5758de4: Export a method to check whether a provider exists
24+
- 5758de4: Add new wallet
25+
- 5758de4: Update tron dependencies
26+
- 5758de4: Fix an issue where solana is disconnected when trust evm wallet is disconnected
27+
- 5758de4: Add deeplink for tw solana on mobile
28+
- 5758de4: Remove metaMask support on tg
29+
- 5758de4: Remove unused packages
30+
- 5758de4: Fix the trust wallet will automatically connect when the page loaded
31+
- 5758de4: Trigger uri connection by user
32+
- 5758de4: Fix the trust wallet will automatically connect when the page loaded
33+
- 5758de4: Update demo
34+
- 5758de4: Use window.trustwallet as TW provider to avoid conflicts
35+
- 5758de4: Add deelink for phantom
36+
337
## 2.8.0-alpha.10
438

539
### Minor Changes

packages/walletkit/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@node-real/walletkit",
3-
"version": "2.8.0-alpha.10",
3+
"version": "2.8.0",
44
"author": "node-real",
55
"private": false,
66
"description": "WalletKit is a React component library for easily connecting a wallet to your dApp.",
@@ -54,7 +54,7 @@
5454
"wagmi": "^2"
5555
},
5656
"dependencies": {
57-
"@binance/w3w-wagmi-connector-v2": "^1.2.5",
57+
"@binance/w3w-wagmi-connector-v2": "1.2.11",
5858
"@metamask/jazzicon": "^2",
5959
"@solana/wallet-adapter-react": "^0",
6060
"@solana/wallet-adapter-wallets": "^0",

packages/walletkit/src/core/configs/binanceWallet/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ export const binanceWalletConfig: WalletConfig = {
1010
downloadUrls: {
1111
default: 'https://www.binance.com/en/web3wallet',
1212
},
13-
spinnerColor: undefined,
13+
spinnerColor: '#F0B90B',
1414
};

packages/walletkit/src/evm/wallets/binanceWallet/index.tsx

Lines changed: 82 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,67 @@ import { isMobile, isTMA } from '@/core/base/utils/mobile';
33
import { binanceWalletConfig } from '@/core/configs/binanceWallet';
44
import { EvmWallet } from '../types';
55
import { getEvmInjectedProvider } from '../../utils/getEvmInjectedProvider';
6-
import { sleep } from 'tronweb/utils';
6+
import { sleep } from '@/core/utils/common';
77
import { injected } from '../injected';
88

99
export interface BinanceWalletOptions extends Partial<EvmWallet> {
1010
connectorOptions?: BinanceW3WParameters;
1111
}
1212

13-
export function binanceWallet(props: BinanceWalletOptions = {}): EvmWallet {
14-
const { connectorOptions = {}, ...restProps } = props;
13+
/**
14+
* Detect if running inside the Binance App in-app browser.
15+
* The Binance App sets window.isBinance = true.
16+
*/
17+
function isInBinanceApp(): boolean {
18+
if (typeof window === 'undefined') return false;
19+
return Boolean(window.isBinance);
20+
}
1521

16-
const getProvider = () => {
17-
if (typeof window === 'undefined') return;
18-
return getEvmInjectedProvider('isBinance');
19-
};
22+
/**
23+
* Detect if the Binance Web3 Wallet browser extension is installed.
24+
* The extension injects window.binancew3w.
25+
*/
26+
function isBinanceExtensionInstalled(): boolean {
27+
if (typeof window === 'undefined') return false;
28+
return Boolean(window.binancew3w);
29+
}
2030

21-
const isInstalled = () => {
22-
return !!getProvider();
23-
};
31+
/**
32+
* Get the Binance EVM provider.
33+
* Priority: window.ethereum.isBinance > window.binancew3w.ethereum
34+
*/
35+
function getBinanceProvider(): any {
36+
if (typeof window === 'undefined') return undefined;
37+
// Standard EIP-1193: injected by Binance App or extension via window.ethereum
38+
const injectedProvider = getEvmInjectedProvider('isBinance');
39+
if (injectedProvider) return injectedProvider;
40+
// Fallback: standalone provider from extension
41+
return window.binancew3w?.ethereum;
42+
}
43+
44+
/**
45+
* Returns true if any Binance wallet source is available.
46+
*/
47+
function isBinanceInstalled(): boolean {
48+
return isInBinanceApp() || isBinanceExtensionInstalled() || Boolean(getBinanceProvider());
49+
}
50+
51+
export function binanceWallet(props: BinanceWalletOptions = {}): EvmWallet {
52+
const { connectorOptions = {}, ...restProps } = props;
2453

2554
return {
2655
...binanceWalletConfig,
2756
id: 'binanceWeb3Wallet',
2857
walletType: 'evm',
2958
behaviors: [
59+
// Behavior 1: Telegram Mini App - always use SDK connector
3060
{
31-
platforms: ['tg-android', 'tg-ios', 'tg-pc', 'browser-pc'],
32-
connectType: 'sdk',
61+
platforms: ['tg-android', 'tg-ios', 'tg-pc'],
62+
connectType: 'sdk' as const,
3363
getCreateConnectorFn() {
64+
// In TMA, intercept bnc:// deep links and convert to HTTPS download links
3465
if (typeof window !== 'undefined' && isMobile() && isTMA()) {
3566
const originalAppendChild = document.body.appendChild;
36-
3767
document.body.appendChild = function (node, ...params) {
3868
if (node instanceof HTMLAnchorElement && node.href?.startsWith('bnc://')) {
3969
node.href = `https://app.binance.com/en/download?_dp=${window.btoa(node.href)}`;
@@ -44,42 +74,67 @@ export function binanceWallet(props: BinanceWalletOptions = {}): EvmWallet {
4474
}
4575

4676
const connector = getWagmiConnectorV2();
47-
return connector({
48-
...connectorOptions,
49-
});
77+
return (connector as any)({ ...connectorOptions });
78+
},
79+
},
80+
81+
// Behavior 2: Desktop browser - smart connector selection
82+
// Binance App or extension installed -> injected (instant, like MetaMask)
83+
// No extension -> SDK (QR/deeplink modal)
84+
{
85+
platforms: ['browser-pc'],
86+
get connectType() {
87+
return isBinanceInstalled() ? ('default' as const) : ('sdk' as const);
88+
},
89+
isInstalled: isBinanceInstalled,
90+
getCreateConnectorFn() {
91+
if (isBinanceInstalled()) {
92+
return injected({
93+
shimDisconnect: true,
94+
target: {
95+
id: 'binanceWeb3Wallet',
96+
name: 'Binance Wallet',
97+
async provider() {
98+
return getBinanceProvider();
99+
},
100+
},
101+
...connectorOptions,
102+
});
103+
}
104+
// No extension: SDK connector opens QR/deeplink modal
105+
const connector = getWagmiConnectorV2();
106+
return (connector as any)({ ...connectorOptions });
50107
},
51108
},
109+
110+
// Behavior 3: Mobile browser - injected + deep link fallback
52111
{
53112
platforms: ['browser-android', 'browser-ios'],
54-
connectType: 'default',
55-
isInstalled,
113+
connectType: 'default' as const,
114+
isInstalled: isBinanceInstalled,
56115
getAppLink() {
57116
const url = window.location.href;
58117
const base = 'bnc://app.binance.com/mp/app';
59118
const appId = 'yFK5FCqYprrXDiVFbhyRx7';
60-
61119
const startPagePath = window.btoa('/pages/browser/index');
62120
const startPageQuery = window.btoa(`url=${url}`);
63121
const deeplink = `${base}?appId=${appId}&startPagePath=${startPagePath}&startPageQuery=${startPageQuery}`;
64122
const dp = window.btoa(deeplink);
65-
const http = `https://app.binance.com/en/download?_dp=${dp}`;
66-
67-
return http;
123+
return `https://app.binance.com/en/download?_dp=${dp}`;
68124
},
69125
getCreateConnectorFn() {
70126
let isReady = false;
71-
72127
return injected({
73128
shimDisconnect: true,
74129
target: {
75-
id: binanceWallet().id,
76-
name: binanceWallet().name,
130+
id: 'binanceWeb3Wallet',
131+
name: 'Binance Wallet',
77132
async provider() {
78-
if (isMobile() && isInstalled() && !isReady) {
133+
if (isMobile() && isBinanceInstalled() && !isReady) {
79134
await sleep(3000);
80135
}
81136
isReady = true;
82-
return getProvider();
137+
return getBinanceProvider();
83138
},
84139
},
85140
...connectorOptions,

packages/walletkit/src/typings.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ interface Window {
77
bitkeep: any;
88
tron: any;
99
solana: any;
10+
isBinance?: boolean;
11+
binancew3w?: { ethereum?: any };
12+
BinanceChain?: any;
1013
}
1114

1215
declare module '@metamask/jazzicon';

0 commit comments

Comments
 (0)