or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

address-display.mdcommon-types.mdconfiguration.mdcrypto-components.mdhooks.mdindex.mdnft-components.mdpayment.mdwallet-connection.md
tile.json

hooks.mddocs/

0

# React Hooks

1

2

React hooks for accessing Web3 state and functionality from any component within a Web3ConfigProvider context.

3

4

## Capabilities

5

6

### useAccount

7

8

Hook to access the current connected account information including address, name, avatar, and connection status.

9

10

```typescript { .api }

11

/**

12

* Hook to access the current connected account information

13

* @returns Object containing account information

14

*/

15

function useAccount(): Pick<ConfigConsumerProps, 'account'>;

16

17

interface ConfigConsumerProps {

18

account?: Account;

19

}

20

21

interface Account {

22

address: string;

23

name?: string;

24

avatar?: string;

25

addresses?: [`0x${string}`, ...`0x${string}`[]] | readonly `0x${string}`[];

26

status?: ConnectStatus;

27

}

28

29

const enum ConnectStatus {

30

Connected = 'connected',

31

Disconnected = 'disconnected',

32

Signed = 'signed',

33

}

34

```

35

36

**Usage Examples:**

37

38

```typescript

39

import { useAccount } from "@ant-design/web3";

40

41

function AccountDisplay() {

42

const { account } = useAccount();

43

44

if (!account) {

45

return <div>No account connected</div>;

46

}

47

48

return (

49

<div>

50

<h3>Connected Account</h3>

51

<p>Address: {account.address}</p>

52

{account.name && <p>Name: {account.name}</p>}

53

<p>Status: {account.status}</p>

54

{account.avatar && (

55

<img src={account.avatar} alt="Avatar" width={32} height={32} />

56

)}

57

{account.addresses && (

58

<div>

59

<h4>Multiple Addresses:</h4>

60

<ul>

61

{account.addresses.map((addr, index) => (

62

<li key={index}>{addr}</li>

63

))}

64

</ul>

65

</div>

66

)}

67

</div>

68

);

69

}

70

71

// Conditional rendering based on connection status

72

function ConditionalContent() {

73

const { account } = useAccount();

74

75

switch (account?.status) {

76

case 'connected':

77

return <div>Wallet connected: {account.address}</div>;

78

case 'signed':

79

return <div>Wallet signed in: {account.address}</div>;

80

case 'disconnected':

81

default:

82

return <div>Please connect your wallet</div>;

83

}

84

}

85

86

// Using account in effects

87

function AccountWatcher() {

88

const { account } = useAccount();

89

90

useEffect(() => {

91

if (account?.address) {

92

console.log('Account changed:', account.address);

93

// Fetch user data, update UI, etc.

94

fetchUserData(account.address);

95

}

96

}, [account?.address]);

97

98

return <div>Watching account changes...</div>;

99

}

100

```

101

102

### useConnection

103

104

Hook to access wallet connection and disconnection functions for programmatic wallet management.

105

106

```typescript { .api }

107

/**

108

* Hook to access wallet connection and disconnection functions

109

* @returns Object containing connect and disconnect functions

110

*/

111

function useConnection(): Pick<ConfigConsumerProps, 'connect' | 'disconnect'>;

112

113

interface ConfigConsumerProps {

114

connect?: (wallet?: Wallet, options?: ConnectOptions) => Promise<void | Account>;

115

disconnect?: () => Promise<void>;

116

}

117

118

interface ConnectOptions {

119

connectType?: 'extension' | 'qrCode' | 'openMobile';

120

}

121

122

interface Wallet extends WalletMetadata {

123

_standardWallet?: any;

124

_isMobileWallet?: boolean;

125

hasWalletReady?: () => Promise<boolean>;

126

hasExtensionInstalled?: () => Promise<boolean>;

127

getQrCode?: () => Promise<{ uri: string }>;

128

customQrCodePanel?: boolean;

129

}

130

```

131

132

**Usage Examples:**

133

134

```typescript

135

import { useConnection } from "@ant-design/web3";

136

137

function CustomConnectButton() {

138

const { connect, disconnect } = useConnection();

139

const { account } = useAccount();

140

141

const handleConnect = async () => {

142

try {

143

const result = await connect();

144

console.log('Connected:', result);

145

} catch (error) {

146

console.error('Connection failed:', error);

147

}

148

};

149

150

const handleDisconnect = async () => {

151

try {

152

await disconnect();

153

console.log('Disconnected successfully');

154

} catch (error) {

155

console.error('Disconnection failed:', error);

156

}

157

};

158

159

if (account) {

160

return (

161

<button onClick={handleDisconnect}>

162

Disconnect {account.address}

163

</button>

164

);

165

}

166

167

return (

168

<button onClick={handleConnect}>

169

Connect Wallet

170

</button>

171

);

172

}

173

174

// Connect to specific wallet

175

function WalletSpecificConnect() {

176

const { connect } = useConnection();

177

178

const connectToMetaMask = async () => {

179

const metaMaskWallet = {

180

name: "MetaMask",

181

remark: "Connect with MetaMask",

182

icon: "metamask-icon",

183

extensions: [{

184

key: 'Chrome',

185

browserIcon: 'chrome',

186

browserName: 'Chrome',

187

link: 'https://metamask.io',

188

description: 'MetaMask extension'

189

}]

190

};

191

192

try {

193

await connect(metaMaskWallet, { connectType: 'extension' });

194

} catch (error) {

195

console.error('MetaMask connection failed:', error);

196

}

197

};

198

199

return <button onClick={connectToMetaMask}>Connect MetaMask</button>;

200

}

201

202

// Connection with loading state

203

function ConnectWithLoading() {

204

const { connect, disconnect } = useConnection();

205

const { account } = useAccount();

206

const [loading, setLoading] = useState(false);

207

208

const handleConnect = async () => {

209

setLoading(true);

210

try {

211

await connect();

212

} catch (error) {

213

console.error('Connection error:', error);

214

} finally {

215

setLoading(false);

216

}

217

};

218

219

return (

220

<button onClick={handleConnect} disabled={loading}>

221

{loading ? 'Connecting...' : account ? 'Connected' : 'Connect'}

222

</button>

223

);

224

}

225

```

226

227

### useProvider

228

229

Hook to access the complete Web3 provider context with optional prop overrides for customization and testing.

230

231

```typescript { .api }

232

/**

233

* Hook to access the Web3 provider context with optional prop overrides

234

* @param props - Optional props to override context values

235

* @returns Complete provider interface with merged context and props

236

*/

237

function useProvider(

238

props?: UniversalWeb3ProviderInterface

239

): UniversalWeb3ProviderInterface;

240

241

interface UniversalWeb3ProviderInterface {

242

account?: Account;

243

chain?: Chain;

244

balance?: Balance;

245

availableWallets?: Wallet[];

246

availableChains?: Chain[];

247

extendsContextFromParent?: boolean;

248

addressPrefix?: string | false;

249

connect?: (wallet?: Wallet, options?: ConnectOptions) => Promise<void | Account>;

250

disconnect?: () => Promise<void>;

251

switchChain?: (chain: Chain) => Promise<void>;

252

getNFTMetadata?: (params: { address: string; tokenId?: bigint }) => Promise<NFTMetadata>;

253

sign?: SignConfig;

254

}

255

256

interface Balance {

257

value?: bigint;

258

coverAddress?: boolean;

259

name?: string;

260

symbol?: string;

261

icon?: React.ReactNode;

262

decimal?: number;

263

}

264

265

interface Chain {

266

id: ChainIds | number;

267

name: string;

268

type?: ChainType;

269

icon?: React.ReactNode;

270

browser?: {

271

icon?: React.ReactNode;

272

getBrowserLink?: (address: string, type: BrowserLinkType) => string;

273

};

274

nativeCurrency?: BalanceMetadata & { name: string };

275

}

276

```

277

278

**Usage Examples:**

279

280

```typescript

281

import { useProvider } from "@ant-design/web3";

282

283

// Access full provider context

284

function ProviderInfo() {

285

const provider = useProvider();

286

287

return (

288

<div>

289

<h3>Provider Information</h3>

290

<p>Current Chain: {provider.chain?.name}</p>

291

<p>Account: {provider.account?.address}</p>

292

<p>Balance: {provider.balance?.value?.toString()}</p>

293

<p>Available Wallets: {provider.availableWallets?.length}</p>

294

<p>Available Chains: {provider.availableChains?.length}</p>

295

</div>

296

);

297

}

298

299

// Override provider values

300

function CustomProvider() {

301

const customChain = {

302

id: 1337,

303

name: "Local Testnet",

304

type: ChainType.EVM

305

};

306

307

const provider = useProvider({

308

chain: customChain,

309

addressPrefix: "local:"

310

});

311

312

return (

313

<div>

314

<p>Using custom chain: {provider.chain?.name}</p>

315

<p>Address prefix: {provider.addressPrefix}</p>

316

</div>

317

);

318

}

319

320

// Chain switching functionality

321

function ChainSwitcher() {

322

const provider = useProvider();

323

324

const switchToPolygon = async () => {

325

const polygonChain = {

326

id: 137,

327

name: "Polygon",

328

type: ChainType.EVM

329

};

330

331

try {

332

await provider.switchChain?.(polygonChain);

333

console.log('Switched to Polygon');

334

} catch (error) {

335

console.error('Chain switch failed:', error);

336

}

337

};

338

339

return (

340

<div>

341

<p>Current: {provider.chain?.name}</p>

342

<button onClick={switchToPolygon}>Switch to Polygon</button>

343

</div>

344

);

345

}

346

347

// NFT metadata fetching

348

function NFTLoader() {

349

const provider = useProvider();

350

const [metadata, setMetadata] = useState(null);

351

352

const loadNFT = async () => {

353

if (provider.getNFTMetadata) {

354

try {

355

const nftData = await provider.getNFTMetadata({

356

address: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",

357

tokenId: BigInt(1)

358

});

359

setMetadata(nftData);

360

} catch (error) {

361

console.error('NFT load failed:', error);

362

}

363

}

364

};

365

366

return (

367

<div>

368

<button onClick={loadNFT}>Load NFT</button>

369

{metadata && <p>NFT Name: {metadata.name}</p>}

370

</div>

371

);

372

}

373

```

374

375

### useNFT

376

377

Hook for loading NFT metadata with automatic caching, loading states, and error handling.

378

379

```typescript { .api }

380

/**

381

* Hook for loading NFT metadata

382

* @param address - NFT contract address

383

* @param tokenId - NFT token ID

384

* @param getNFTMetadata - Custom metadata fetcher function

385

* @returns Object containing loading state, metadata, and error

386

*/

387

function useNFT(

388

address?: string,

389

tokenId?: bigint | number,

390

getNFTMetadata?: Web3ConfigProviderProps['getNFTMetadata']

391

): { loading: boolean; metadata: NFTMetadata; error?: Error };

392

393

interface NFTMetadata {

394

name?: string;

395

description?: string;

396

image?: string;

397

dna?: string;

398

edition?: string | number;

399

date?: number;

400

attributes?: Array<{

401

trait_type?: string;

402

value?: string;

403

}>;

404

compiler?: string;

405

}

406

```

407

408

**Usage Examples:**

409

410

```typescript

411

import { useNFT } from "@ant-design/web3";

412

413

// Basic NFT loading

414

function NFTDisplay() {

415

const { loading, metadata, error } = useNFT(

416

"0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",

417

BigInt(1)

418

);

419

420

if (loading) return <div>Loading NFT...</div>;

421

if (error) return <div>Error: {error.message}</div>;

422

423

return (

424

<div>

425

<h3>{metadata.name}</h3>

426

<p>{metadata.description}</p>

427

{metadata.image && (

428

<img src={metadata.image} alt={metadata.name} width={300} />

429

)}

430

{metadata.attributes && (

431

<div>

432

<h4>Attributes:</h4>

433

{metadata.attributes.map((attr, index) => (

434

<div key={index}>

435

{attr.trait_type}: {attr.value}

436

</div>

437

))}

438

</div>

439

)}

440

</div>

441

);

442

}

443

444

// Dynamic NFT loading with state

445

function DynamicNFTViewer() {

446

const [contractAddress, setContractAddress] = useState("");

447

const [tokenId, setTokenId] = useState("");

448

449

const { loading, metadata, error } = useNFT(

450

contractAddress || undefined,

451

tokenId ? BigInt(tokenId) : undefined

452

);

453

454

return (

455

<div>

456

<input

457

placeholder="Contract Address"

458

value={contractAddress}

459

onChange={(e) => setContractAddress(e.target.value)}

460

/>

461

<input

462

placeholder="Token ID"

463

value={tokenId}

464

onChange={(e) => setTokenId(e.target.value)}

465

/>

466

467

{loading && <div>Loading...</div>}

468

{error && <div>Error: {error.message}</div>}

469

{metadata.name && (

470

<div>

471

<h3>{metadata.name}</h3>

472

{metadata.image && <img src={metadata.image} width={200} />}

473

</div>

474

)}

475

</div>

476

);

477

}

478

479

// Custom metadata fetcher

480

function CustomNFTLoader() {

481

const customFetcher = async ({ address, tokenId }) => {

482

const response = await fetch(`/api/nft/${address}/${tokenId}`);

483

if (!response.ok) throw new Error('Failed to fetch NFT');

484

return response.json();

485

};

486

487

const { loading, metadata, error } = useNFT(

488

"0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",

489

BigInt(1234),

490

customFetcher

491

);

492

493

return (

494

<div>

495

{loading ? "Loading..." : metadata.name || "No NFT data"}

496

</div>

497

);

498

}

499

500

// NFT with fallback handling

501

function RobustNFTDisplay() {

502

const { loading, metadata, error } = useNFT(

503

"0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",

504

BigInt(9999)

505

);

506

507

if (loading) {

508

return (

509

<div className="nft-loading">

510

<div className="spinner" />

511

<span>Loading NFT metadata...</span>

512

</div>

513

);

514

}

515

516

if (error) {

517

return (

518

<div className="nft-error">

519

<h4>Failed to load NFT</h4>

520

<p>{error.message}</p>

521

<button onClick={() => window.location.reload()}>

522

Retry

523

</button>

524

</div>

525

);

526

}

527

528

return (

529

<div className="nft-card">

530

<img

531

src={metadata.image || '/placeholder-nft.png'}

532

alt={metadata.name || 'NFT'}

533

onError={(e) => {

534

e.target.src = '/placeholder-nft.png';

535

}}

536

/>

537

<h3>{metadata.name || 'Unnamed NFT'}</h3>

538

<p>{metadata.description || 'No description available'}</p>

539

</div>

540

);

541

}

542

```

543

544

## Hook Integration Patterns

545

546

### Combined Hook Usage

547

548

```typescript

549

import { useAccount, useConnection, useProvider } from "@ant-design/web3";

550

551

function WalletManager() {

552

const { account } = useAccount();

553

const { connect, disconnect } = useConnection();

554

const provider = useProvider();

555

556

const handleChainSwitch = async (chainId: number) => {

557

const targetChain = provider.availableChains?.find(

558

chain => chain.id === chainId

559

);

560

561

if (targetChain && provider.switchChain) {

562

await provider.switchChain(targetChain);

563

}

564

};

565

566

return (

567

<div>

568

{account ? (

569

<div>

570

<p>Connected: {account.address}</p>

571

<p>Chain: {provider.chain?.name}</p>

572

<button onClick={() => disconnect()}>Disconnect</button>

573

<select onChange={(e) => handleChainSwitch(Number(e.target.value))}>

574

{provider.availableChains?.map(chain => (

575

<option key={chain.id} value={chain.id}>{chain.name}</option>

576

))}

577

</select>

578

</div>

579

) : (

580

<button onClick={() => connect()}>Connect Wallet</button>

581

)}

582

</div>

583

);

584

}

585

```

586

587

### Testing with Hooks

588

589

```typescript

590

import { renderHook } from '@testing-library/react';

591

import { useProvider } from "@ant-design/web3";

592

593

// Test hook with mock data

594

const wrapper = ({ children }) => (

595

<Web3ConfigProvider

596

account={{ address: "0x123", status: "connected" }}

597

chain={{ id: 1, name: "Ethereum" }}

598

>

599

{children}

600

</Web3ConfigProvider>

601

);

602

603

const { result } = renderHook(() => useProvider(), { wrapper });

604

expect(result.current.account?.address).toBe("0x123");

605

```