@dilukangelo/web3-ai-skills 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/package.json +4 -3
- package/template/.agent/ARCHITECTURE.md +19 -14
- package/template/.agent/GEMINI.md +6 -6
- package/template/.agent/skills/account-abstraction/SKILL.md +258 -0
- package/template/.agent/skills/hardhat-foundry-testing/SKILL.md +289 -0
- package/template/.agent/skills/thirdweb-sdk/SKILL.md +242 -0
- package/template/.agent/skills/web3-api-providers/SKILL.md +281 -0
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ This creates a `.agent/` folder in your current directory with all Web3 agents,
|
|
|
38
38
|
| **web3-infra** | RPC optimization, Multicall3, MEV protection |
|
|
39
39
|
| **web3-orchestrator** | Multi-agent coordination for full-stack DApps |
|
|
40
40
|
|
|
41
|
-
### 🧩
|
|
41
|
+
### 🧩 12 Skills
|
|
42
42
|
|
|
43
43
|
| Skill | Description |
|
|
44
44
|
|-------|-------------|
|
|
@@ -50,6 +50,10 @@ This creates a `.agent/` folder in your current directory with all Web3 agents,
|
|
|
50
50
|
| **rpc-optimization** | Multicall3, batching, caching, MEV protection |
|
|
51
51
|
| **subgraph-indexing** | The Graph, Ponder, Subsquid, Envio |
|
|
52
52
|
| **clean-code** | Web3-specific coding standards |
|
|
53
|
+
| **web3-api-providers** | Alchemy, Moralis, Infura, QuickNode enhanced APIs |
|
|
54
|
+
| **thirdweb-sdk** | Contract deploy, embed wallets, Engine, Pay |
|
|
55
|
+
| **hardhat-foundry-testing** | Forge cheatcodes, Hardhat plugins, fuzz/invariant, CI |
|
|
56
|
+
| **account-abstraction** | ERC-4337, paymasters, session keys, EIP-7702 |
|
|
53
57
|
|
|
54
58
|
### 🔄 4 Workflows
|
|
55
59
|
|
|
@@ -71,7 +75,7 @@ After running `init`, your project will have a `.agent/` folder:
|
|
|
71
75
|
├── GEMINI.md # Core AI instructions
|
|
72
76
|
├── ARCHITECTURE.md # System overview
|
|
73
77
|
├── agents/ # 6 specialist agents
|
|
74
|
-
├── skills/ #
|
|
78
|
+
├── skills/ # 12 domain skills
|
|
75
79
|
├── workflows/ # 4 slash commands
|
|
76
80
|
└── scripts/ # Validation scripts
|
|
77
81
|
```
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dilukangelo/web3-ai-skills",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "CLI to initialize Web3 AI Agent Skills — Solidity, Rust, DApp frontends, auditing, RPC, and indexing for 2026",
|
|
5
5
|
"main": "bin/cli.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"web3-ai-skills": "
|
|
9
|
-
"w3ai": "
|
|
8
|
+
"web3-ai-skills": "bin/cli.js",
|
|
9
|
+
"w3ai": "bin/cli.js"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"bin/",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"homepage": "https://github.com/dilukangelosl/web3-ai-skills#readme",
|
|
44
44
|
"dependencies": {
|
|
45
|
+
"@dilukangelo/web3-ai-skills": "file:dilukangelo-web3-ai-skills-1.0.1.tgz",
|
|
45
46
|
"chalk": "^5.3.0",
|
|
46
47
|
"commander": "^14.0.3",
|
|
47
48
|
"fs-extra": "^11.3.3",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
Web3 AI Skills is a modular system consisting of:
|
|
10
10
|
|
|
11
11
|
- **6 Specialist Agents** — Web3-specific role-based AI personas
|
|
12
|
-
- **
|
|
12
|
+
- **12 Skills** — Deep domain knowledge modules for blockchain development
|
|
13
13
|
- **4 Workflows** — Slash command procedures for common Web3 tasks
|
|
14
14
|
|
|
15
15
|
---
|
|
@@ -21,7 +21,7 @@ Web3 AI Skills is a modular system consisting of:
|
|
|
21
21
|
├── GEMINI.md # Core instructions
|
|
22
22
|
├── ARCHITECTURE.md # This file
|
|
23
23
|
├── agents/ # 6 Specialist Agents
|
|
24
|
-
├── skills/ #
|
|
24
|
+
├── skills/ # 12 Skills
|
|
25
25
|
├── workflows/ # 4 Slash Commands
|
|
26
26
|
└── scripts/ # Validation Scripts
|
|
27
27
|
```
|
|
@@ -32,16 +32,16 @@ Web3 AI Skills is a modular system consisting of:
|
|
|
32
32
|
|
|
33
33
|
| Agent | Focus | Skills Used |
|
|
34
34
|
| ---------------------- | --------------------------------- | ------------------------------------------------ |
|
|
35
|
-
| `solidity-expert` | EVM smart contracts, Foundry | solidity-patterns, smart-contract-auditing
|
|
35
|
+
| `solidity-expert` | EVM smart contracts, Foundry | solidity-patterns, smart-contract-auditing, hardhat-foundry-testing |
|
|
36
36
|
| `rust-web3` | Solana/Anchor, CosmWasm, Rust | rust-smart-contracts |
|
|
37
|
-
| `web3-frontend` | Next.js + RainbowKit + Wagmi | rainbowkit-wagmi, dapp-patterns
|
|
38
|
-
| `contract-auditor` | Security audits, Slither, Mythril | smart-contract-auditing
|
|
39
|
-
| `web3-infra` | RPC, indexers, nodes, subgraphs | rpc-optimization, subgraph-indexing
|
|
37
|
+
| `web3-frontend` | Next.js + RainbowKit + Wagmi | rainbowkit-wagmi, dapp-patterns, thirdweb-sdk, account-abstraction |
|
|
38
|
+
| `contract-auditor` | Security audits, Slither, Mythril | smart-contract-auditing, hardhat-foundry-testing |
|
|
39
|
+
| `web3-infra` | RPC, indexers, nodes, subgraphs | rpc-optimization, subgraph-indexing, web3-api-providers |
|
|
40
40
|
| `web3-orchestrator` | Multi-agent Web3 coordination | All skills |
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
-
## 🧩 Skills (
|
|
44
|
+
## 🧩 Skills (12)
|
|
45
45
|
|
|
46
46
|
### Smart Contracts
|
|
47
47
|
|
|
@@ -50,6 +50,7 @@ Web3 AI Skills is a modular system consisting of:
|
|
|
50
50
|
| `solidity-patterns` | Solidity 0.8.x+, ERC standards, gas optimization |
|
|
51
51
|
| `rust-smart-contracts` | Anchor/Solana programs, CosmWasm, Stylus |
|
|
52
52
|
| `smart-contract-auditing` | Audit methodology, Slither, Mythril, Aderyn |
|
|
53
|
+
| `hardhat-foundry-testing` | Toolchains, cheatcodes, fuzz/invariant testing, CI |
|
|
53
54
|
|
|
54
55
|
### DApp Frontend
|
|
55
56
|
|
|
@@ -57,13 +58,16 @@ Web3 AI Skills is a modular system consisting of:
|
|
|
57
58
|
| --------------------------- | -------------------------------------------------- |
|
|
58
59
|
| `rainbowkit-wagmi` | RainbowKit v2, Wagmi v2, viem, wallet integration |
|
|
59
60
|
| `dapp-patterns` | DApp architecture, IPFS, ENS, signing patterns |
|
|
61
|
+
| `thirdweb-sdk` | Contract deploy, in-app wallets, Engine, Pay |
|
|
62
|
+
| `account-abstraction` | ERC-4337, paymasters, session keys, EIP-7702 |
|
|
60
63
|
|
|
61
64
|
### Infrastructure
|
|
62
65
|
|
|
63
66
|
| Skill | Description |
|
|
64
67
|
| --------------------------- | -------------------------------------------------- |
|
|
65
68
|
| `rpc-optimization` | RPC management, Multicall3, batching, MEV |
|
|
66
|
-
| `subgraph-indexing` | The Graph, Ponder,
|
|
69
|
+
| `subgraph-indexing` | The Graph, Ponder, Subsquid, Envio, event parsing |
|
|
70
|
+
| `web3-api-providers` | Alchemy, Moralis, Infura, QuickNode enhanced APIs |
|
|
67
71
|
|
|
68
72
|
### General
|
|
69
73
|
|
|
@@ -111,9 +115,9 @@ skill-name/
|
|
|
111
115
|
| Metric | Value |
|
|
112
116
|
| ------------------- | ------------ |
|
|
113
117
|
| **Total Agents** | 6 |
|
|
114
|
-
| **Total Skills** |
|
|
118
|
+
| **Total Skills** | 12 |
|
|
115
119
|
| **Total Workflows** | 4 |
|
|
116
|
-
| **Coverage** | Web3 / EVM / Solana / DApp |
|
|
120
|
+
| **Coverage** | Web3 / EVM / Solana / DApp / AA / APIs |
|
|
117
121
|
|
|
118
122
|
---
|
|
119
123
|
|
|
@@ -121,9 +125,10 @@ skill-name/
|
|
|
121
125
|
|
|
122
126
|
| Need | Agent | Skills |
|
|
123
127
|
| ------------------- | -------------------- | -------------------------------------------- |
|
|
124
|
-
| Solidity Contract | `solidity-expert` | solidity-patterns,
|
|
128
|
+
| Solidity Contract | `solidity-expert` | solidity-patterns, hardhat-foundry-testing |
|
|
125
129
|
| Rust Contract | `rust-web3` | rust-smart-contracts |
|
|
126
|
-
| DApp Frontend | `web3-frontend` | rainbowkit-wagmi, dapp-patterns
|
|
127
|
-
| Contract Audit | `contract-auditor` | smart-contract-auditing
|
|
128
|
-
| RPC / Infra | `web3-infra` | rpc-optimization, subgraph-indexing
|
|
130
|
+
| DApp Frontend | `web3-frontend` | rainbowkit-wagmi, dapp-patterns, thirdweb-sdk |
|
|
131
|
+
| Contract Audit | `contract-auditor` | smart-contract-auditing, hardhat-foundry-testing |
|
|
132
|
+
| RPC / Infra | `web3-infra` | rpc-optimization, subgraph-indexing, web3-api-providers |
|
|
133
|
+
| Account Abstraction | `web3-frontend` | account-abstraction, thirdweb-sdk |
|
|
129
134
|
| Full-Stack DApp | `web3-orchestrator` | All skills |
|
|
@@ -67,11 +67,11 @@ When auto-applying an agent, inform the user:
|
|
|
67
67
|
|
|
68
68
|
| Project Type | Primary Agent | Skills |
|
|
69
69
|
| -------------------------------------------- | --------------------- | -------------------------------------------- |
|
|
70
|
-
| **SMART CONTRACTS** (Solidity, EVM) | `solidity-expert` | solidity-patterns, smart-contract-auditing
|
|
71
|
-
| **RUST CONTRACTS** (Solana, Anchor, CosmWasm) | `rust-web3` | rust-smart-contracts
|
|
72
|
-
| **DAPP FRONTEND** (Next.js, RainbowKit) | `web3-frontend` | rainbowkit-wagmi, dapp-patterns
|
|
73
|
-
| **SECURITY AUDIT** (Contract audit) | `contract-auditor` | smart-contract-auditing,
|
|
74
|
-
| **RPC / INFRA** (Nodes, indexers)
|
|
70
|
+
| **SMART CONTRACTS** (Solidity, EVM) | `solidity-expert` | solidity-patterns, smart-contract-auditing, hardhat-foundry-testing |
|
|
71
|
+
| **RUST CONTRACTS** (Solana, Anchor, CosmWasm) | `rust-web3` | rust-smart-contracts |
|
|
72
|
+
| **DAPP FRONTEND** (Next.js, RainbowKit) | `web3-frontend` | rainbowkit-wagmi, dapp-patterns, thirdweb-sdk, account-abstraction |
|
|
73
|
+
| **SECURITY AUDIT** (Contract audit) | `contract-auditor` | smart-contract-auditing, hardhat-foundry-testing |
|
|
74
|
+
| **RPC / INFRA** (Nodes, indexers, APIs) | `web3-infra` | rpc-optimization, subgraph-indexing, web3-api-providers |
|
|
75
75
|
|
|
76
76
|
---
|
|
77
77
|
|
|
@@ -130,6 +130,6 @@ When user's prompt is NOT in English:
|
|
|
130
130
|
### Agents & Skills
|
|
131
131
|
|
|
132
132
|
- **Core Agents**: `solidity-expert`, `rust-web3`, `web3-frontend`, `contract-auditor`, `web3-infra`, `web3-orchestrator`
|
|
133
|
-
- **Key Skills**: `solidity-patterns`, `rust-smart-contracts`, `rainbowkit-wagmi`, `smart-contract-auditing`, `rpc-optimization`, `dapp-patterns`, `clean-code`, `subgraph-indexing`
|
|
133
|
+
- **Key Skills**: `solidity-patterns`, `rust-smart-contracts`, `rainbowkit-wagmi`, `smart-contract-auditing`, `rpc-optimization`, `dapp-patterns`, `clean-code`, `subgraph-indexing`, `web3-api-providers`, `thirdweb-sdk`, `hardhat-foundry-testing`, `account-abstraction`
|
|
134
134
|
|
|
135
135
|
---
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: account-abstraction
|
|
3
|
+
description: ERC-4337 smart accounts, paymasters, bundlers, session keys, and gas sponsorship. Alchemy AA SDK, Pimlico, ZeroDev, Safe, and EIP-7702.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Account Abstraction — Smart Accounts & Gas Sponsorship
|
|
7
|
+
|
|
8
|
+
Expert knowledge for implementing ERC-4337 account abstraction in Web3 applications.
|
|
9
|
+
|
|
10
|
+
## Use this skill when
|
|
11
|
+
|
|
12
|
+
- Implementing smart contract wallets (not EOAs)
|
|
13
|
+
- Sponsoring gas for users (gasless transactions)
|
|
14
|
+
- Setting up session keys for limited permissions
|
|
15
|
+
- Batching multiple transactions into one
|
|
16
|
+
- Building onboarding flows without requiring ETH
|
|
17
|
+
|
|
18
|
+
## Do not use this skill when
|
|
19
|
+
|
|
20
|
+
- Connecting external wallets like MetaMask (use `rainbowkit-wagmi`)
|
|
21
|
+
- General DApp architecture (use `dapp-patterns`)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Core Concepts
|
|
26
|
+
|
|
27
|
+
### Architecture
|
|
28
|
+
```
|
|
29
|
+
User → Signs UserOperation
|
|
30
|
+
↓
|
|
31
|
+
Bundler → Bundles UserOps into single tx
|
|
32
|
+
↓
|
|
33
|
+
EntryPoint Contract → Validates & executes
|
|
34
|
+
↓
|
|
35
|
+
Smart Account → Executes the actual call(s)
|
|
36
|
+
↓
|
|
37
|
+
Paymaster → Sponsors gas (optional)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Key Components
|
|
41
|
+
| Component | Role |
|
|
42
|
+
|-----------|------|
|
|
43
|
+
| **Smart Account** | Contract wallet that holds assets and executes operations |
|
|
44
|
+
| **UserOperation** | Pseudo-transaction signed by the user |
|
|
45
|
+
| **Bundler** | Service that batches UserOps into on-chain transactions |
|
|
46
|
+
| **Paymaster** | Contract that pays gas on behalf of users |
|
|
47
|
+
| **EntryPoint** | Singleton contract that validates and executes UserOps |
|
|
48
|
+
| **Account Factory** | Contract that deploys new smart accounts |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Alchemy Account Kit (AA SDK)
|
|
53
|
+
|
|
54
|
+
### Setup
|
|
55
|
+
```typescript
|
|
56
|
+
import { createModularAccountAlchemyClient } from '@account-kit/smart-contracts'
|
|
57
|
+
import { alchemy, sepolia } from '@account-kit/infra'
|
|
58
|
+
import { LocalAccountSigner } from '@aa-sdk/core'
|
|
59
|
+
|
|
60
|
+
const client = await createModularAccountAlchemyClient({
|
|
61
|
+
transport: alchemy({ apiKey: ALCHEMY_API_KEY }),
|
|
62
|
+
chain: sepolia,
|
|
63
|
+
signer: LocalAccountSigner.privateKeyToAccountSigner(PRIVATE_KEY),
|
|
64
|
+
// Gas sponsorship
|
|
65
|
+
gasManagerConfig: {
|
|
66
|
+
policyId: ALCHEMY_GAS_POLICY_ID,
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Send Sponsored Transaction
|
|
72
|
+
```typescript
|
|
73
|
+
const { hash } = await client.sendUserOperation({
|
|
74
|
+
uo: {
|
|
75
|
+
target: contractAddress,
|
|
76
|
+
data: encodeFunctionData({
|
|
77
|
+
abi: contractAbi,
|
|
78
|
+
functionName: 'mint',
|
|
79
|
+
args: [1n],
|
|
80
|
+
}),
|
|
81
|
+
value: 0n,
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
// Wait for confirmation
|
|
86
|
+
const receipt = await client.waitForUserOperationTransaction({ hash })
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Batch Transactions
|
|
90
|
+
```typescript
|
|
91
|
+
const { hash } = await client.sendUserOperation({
|
|
92
|
+
uo: [
|
|
93
|
+
{
|
|
94
|
+
target: tokenAddress,
|
|
95
|
+
data: encodeFunctionData({
|
|
96
|
+
abi: erc20Abi,
|
|
97
|
+
functionName: 'approve',
|
|
98
|
+
args: [spender, amount],
|
|
99
|
+
}),
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
target: spender,
|
|
103
|
+
data: encodeFunctionData({
|
|
104
|
+
abi: spenderAbi,
|
|
105
|
+
functionName: 'deposit',
|
|
106
|
+
args: [amount],
|
|
107
|
+
}),
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
})
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Pimlico (Bundler + Paymaster)
|
|
116
|
+
|
|
117
|
+
### Setup
|
|
118
|
+
```typescript
|
|
119
|
+
import { createSmartAccountClient } from 'permissionless'
|
|
120
|
+
import { toSimpleSmartAccount } from 'permissionless/accounts'
|
|
121
|
+
import { createPimlicoClient } from 'permissionless/clients/pimlico'
|
|
122
|
+
|
|
123
|
+
// Pimlico bundler + paymaster client
|
|
124
|
+
const pimlicoClient = createPimlicoClient({
|
|
125
|
+
transport: http(`https://api.pimlico.io/v2/${chainId}/rpc?apikey=${PIMLICO_KEY}`),
|
|
126
|
+
entryPoint: { address: entryPoint07Address, version: '0.7' },
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
// Smart account
|
|
130
|
+
const account = await toSimpleSmartAccount({
|
|
131
|
+
client: publicClient,
|
|
132
|
+
owner: signer,
|
|
133
|
+
entryPoint: { address: entryPoint07Address, version: '0.7' },
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
// Smart account client with gas sponsorship
|
|
137
|
+
const smartAccountClient = createSmartAccountClient({
|
|
138
|
+
account,
|
|
139
|
+
chain,
|
|
140
|
+
bundlerTransport: http(`https://api.pimlico.io/v2/${chainId}/rpc?apikey=${PIMLICO_KEY}`),
|
|
141
|
+
paymaster: pimlicoClient,
|
|
142
|
+
})
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Send Gasless Transaction
|
|
146
|
+
```typescript
|
|
147
|
+
const hash = await smartAccountClient.sendTransaction({
|
|
148
|
+
to: contractAddress,
|
|
149
|
+
data: calldata,
|
|
150
|
+
value: 0n,
|
|
151
|
+
})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## ZeroDev (Kernel Accounts)
|
|
157
|
+
|
|
158
|
+
### Setup
|
|
159
|
+
```typescript
|
|
160
|
+
import { createKernelAccount, createKernelAccountClient } from '@zerodev/sdk'
|
|
161
|
+
import { signerToEcdsaValidator } from '@zerodev/ecdsa-validator'
|
|
162
|
+
|
|
163
|
+
const ecdsaValidator = await signerToEcdsaValidator(publicClient, { signer })
|
|
164
|
+
|
|
165
|
+
const account = await createKernelAccount(publicClient, {
|
|
166
|
+
plugins: { sudo: ecdsaValidator },
|
|
167
|
+
entryPoint: entryPoint07Address,
|
|
168
|
+
})
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Session Keys
|
|
172
|
+
```typescript
|
|
173
|
+
import { signerToSessionKeyValidator } from '@zerodev/session-key'
|
|
174
|
+
|
|
175
|
+
const sessionKeyValidator = await signerToSessionKeyValidator(publicClient, {
|
|
176
|
+
signer: sessionKeySigner,
|
|
177
|
+
validatorData: {
|
|
178
|
+
permissions: [{
|
|
179
|
+
target: contractAddress,
|
|
180
|
+
functionName: 'transfer',
|
|
181
|
+
args: [{ condition: 'EQUAL', value: recipientAddress }],
|
|
182
|
+
valueLimit: parseEther('0.1'),
|
|
183
|
+
}],
|
|
184
|
+
},
|
|
185
|
+
})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Safe Smart Accounts
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
import Safe from '@safe-global/protocol-kit'
|
|
194
|
+
|
|
195
|
+
const protocolKit = await Safe.init({
|
|
196
|
+
provider: rpcUrl,
|
|
197
|
+
signer: privateKey,
|
|
198
|
+
safeAddress: existingSafeAddress,
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
// Create transaction
|
|
202
|
+
const safeTransaction = await protocolKit.createTransaction({
|
|
203
|
+
transactions: [{
|
|
204
|
+
to: recipient,
|
|
205
|
+
value: parseEther('0.1').toString(),
|
|
206
|
+
data: '0x',
|
|
207
|
+
}],
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
// Sign and execute
|
|
211
|
+
const signedTx = await protocolKit.signTransaction(safeTransaction)
|
|
212
|
+
const result = await protocolKit.executeTransaction(signedTx)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## EIP-7702 (Native AA — Pectra Upgrade)
|
|
218
|
+
|
|
219
|
+
The next evolution: EOAs can temporarily delegate to smart contract code.
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
// EOA signs an authorization to delegate to a smart contract
|
|
223
|
+
const authorization = {
|
|
224
|
+
chainId: 1,
|
|
225
|
+
codeAddress: smartAccountImplementation, // Contract to delegate to
|
|
226
|
+
nonce: await getTransactionCount(client, { address: eoa }),
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Send transaction with authorization list
|
|
230
|
+
const hash = await sendTransaction(client, {
|
|
231
|
+
authorizationList: [authorization],
|
|
232
|
+
to: targetContract,
|
|
233
|
+
data: calldata,
|
|
234
|
+
})
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### EIP-7702 vs ERC-4337
|
|
238
|
+
| Feature | ERC-4337 | EIP-7702 |
|
|
239
|
+
|---------|----------|----------|
|
|
240
|
+
| **Type** | Smart contract wallet | EOA delegation |
|
|
241
|
+
| **Deployment** | New contract per user | No deployment needed |
|
|
242
|
+
| **Compatibility** | New address | Same EOA address |
|
|
243
|
+
| **Bundler** | Required | Optional |
|
|
244
|
+
| **Gas Efficiency** | Higher overhead | Lower overhead |
|
|
245
|
+
| **Adoption** | Production-ready | Pectra upgrade |
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Provider Selection
|
|
250
|
+
|
|
251
|
+
| Provider | Smart Accounts | Paymaster | Bundler | Session Keys |
|
|
252
|
+
|----------|---------------|-----------|---------|-------------|
|
|
253
|
+
| **Alchemy AA** | Modular Account | ✅ Gas Manager | ✅ | ✅ |
|
|
254
|
+
| **Pimlico** | Any (Simple, Kernel, Safe) | ✅ Verifying | ✅ | Via account |
|
|
255
|
+
| **ZeroDev** | Kernel Account | ✅ | ✅ | ✅ Native |
|
|
256
|
+
| **Safe** | Safe Multisig | Via relay | Via relay | ✅ Modules |
|
|
257
|
+
| **Biconomy** | Nexus Account | ✅ | ✅ | ✅ |
|
|
258
|
+
| **thirdweb** | In-App Wallet | ✅ Built-in | ✅ Built-in | ❌ |
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hardhat-foundry-testing
|
|
3
|
+
description: Smart contract development toolchains and testing strategies. Foundry cheatcodes, Hardhat plugins, fuzz testing, invariant testing, fork testing, gas snapshots, and CI/CD pipelines.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hardhat & Foundry Testing — Smart Contract Toolchains
|
|
7
|
+
|
|
8
|
+
Expert knowledge for testing, debugging, and deploying smart contracts with Foundry and Hardhat.
|
|
9
|
+
|
|
10
|
+
## Use this skill when
|
|
11
|
+
|
|
12
|
+
- Setting up Foundry or Hardhat projects
|
|
13
|
+
- Writing unit, fuzz, or invariant tests
|
|
14
|
+
- Fork testing against mainnet state
|
|
15
|
+
- Debugging failing transactions
|
|
16
|
+
- Setting up CI/CD for Solidity projects
|
|
17
|
+
- Comparing Foundry vs Hardhat for a project
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Foundry
|
|
22
|
+
|
|
23
|
+
### Project Commands
|
|
24
|
+
```bash
|
|
25
|
+
forge init my-project # New project
|
|
26
|
+
forge build # Compile
|
|
27
|
+
forge test # Run tests
|
|
28
|
+
forge test -vvvv # Verbose (show traces)
|
|
29
|
+
forge test --match-test "test_Transfer" # Single test
|
|
30
|
+
forge test --gas-report # Gas usage
|
|
31
|
+
forge coverage # Code coverage
|
|
32
|
+
forge snapshot # Gas snapshots
|
|
33
|
+
forge fmt # Format code
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Cheatcodes (vm.)
|
|
37
|
+
|
|
38
|
+
```solidity
|
|
39
|
+
// Identity
|
|
40
|
+
vm.prank(alice); // Next call as alice
|
|
41
|
+
vm.startPrank(alice); // All calls as alice until stopPrank
|
|
42
|
+
vm.stopPrank();
|
|
43
|
+
|
|
44
|
+
// State manipulation
|
|
45
|
+
vm.deal(alice, 10 ether); // Set ETH balance
|
|
46
|
+
deal(address(token), alice, 1000e18); // Set ERC-20 balance
|
|
47
|
+
vm.store(addr, slot, value); // Set storage slot
|
|
48
|
+
|
|
49
|
+
// Time & block
|
|
50
|
+
vm.warp(block.timestamp + 1 days); // Set timestamp
|
|
51
|
+
vm.roll(block.number + 100); // Set block number
|
|
52
|
+
|
|
53
|
+
// Expectations
|
|
54
|
+
vm.expectRevert(MyContract.InsufficientBalance.selector);
|
|
55
|
+
vm.expectEmit(true, true, false, true);
|
|
56
|
+
emit Transfer(alice, bob, 100);
|
|
57
|
+
|
|
58
|
+
// Environment
|
|
59
|
+
vm.envUint("PRIVATE_KEY"); // Read .env
|
|
60
|
+
vm.createSelectFork("mainnet"); // Fork mainnet
|
|
61
|
+
|
|
62
|
+
// Snapshots
|
|
63
|
+
uint256 snap = vm.snapshot(); // Save state
|
|
64
|
+
vm.revertTo(snap); // Restore state
|
|
65
|
+
|
|
66
|
+
// Labels (for traces)
|
|
67
|
+
vm.label(alice, "Alice");
|
|
68
|
+
vm.label(address(token), "USDC");
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Fuzz Testing
|
|
72
|
+
```solidity
|
|
73
|
+
function testFuzz_Deposit(uint256 amount) public {
|
|
74
|
+
// Bound inputs to valid range
|
|
75
|
+
amount = bound(amount, 1, MAX_DEPOSIT);
|
|
76
|
+
|
|
77
|
+
vm.deal(alice, amount);
|
|
78
|
+
vm.prank(alice);
|
|
79
|
+
vault.deposit{value: amount}();
|
|
80
|
+
|
|
81
|
+
assertEq(vault.balanceOf(alice), amount);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Invariant Testing
|
|
86
|
+
```solidity
|
|
87
|
+
// Define target contract and selectors
|
|
88
|
+
function setUp() public {
|
|
89
|
+
targetContract(address(vault));
|
|
90
|
+
// Only call these functions during invariant testing
|
|
91
|
+
bytes4[] memory selectors = new bytes4[](2);
|
|
92
|
+
selectors[0] = vault.deposit.selector;
|
|
93
|
+
selectors[1] = vault.withdraw.selector;
|
|
94
|
+
targetSelector(FuzzSelector(address(vault), selectors));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function invariant_TotalAssetsMatchDeposits() public {
|
|
98
|
+
assertEq(
|
|
99
|
+
address(vault).balance,
|
|
100
|
+
vault.totalDeposits()
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function invariant_NoNegativeBalances() public {
|
|
105
|
+
for (uint i = 0; i < actors.length; i++) {
|
|
106
|
+
assertGe(vault.balanceOf(actors[i]), 0);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Fork Testing
|
|
112
|
+
```solidity
|
|
113
|
+
function setUp() public {
|
|
114
|
+
// Fork mainnet at specific block
|
|
115
|
+
vm.createSelectFork("mainnet", 18_000_000);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function test_SwapOnUniswap() public {
|
|
119
|
+
// Interact with real mainnet contracts
|
|
120
|
+
IUniswapV2Router02 router = IUniswapV2Router02(UNISWAP_ROUTER);
|
|
121
|
+
|
|
122
|
+
vm.deal(alice, 1 ether);
|
|
123
|
+
vm.startPrank(alice);
|
|
124
|
+
|
|
125
|
+
address[] memory path = new address[](2);
|
|
126
|
+
path[0] = WETH;
|
|
127
|
+
path[1] = USDC;
|
|
128
|
+
|
|
129
|
+
router.swapExactETHForTokens{value: 1 ether}(
|
|
130
|
+
0, path, alice, block.timestamp
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
assertGt(IERC20(USDC).balanceOf(alice), 0);
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Deployment Scripts
|
|
138
|
+
```solidity
|
|
139
|
+
// script/Deploy.s.sol
|
|
140
|
+
contract DeployScript is Script {
|
|
141
|
+
function run() public {
|
|
142
|
+
uint256 key = vm.envUint("PRIVATE_KEY");
|
|
143
|
+
vm.startBroadcast(key);
|
|
144
|
+
|
|
145
|
+
MyContract c = new MyContract(arg1, arg2);
|
|
146
|
+
console.log("Deployed:", address(c));
|
|
147
|
+
|
|
148
|
+
vm.stopBroadcast();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
```bash
|
|
153
|
+
forge script script/Deploy.s.sol \
|
|
154
|
+
--rpc-url $RPC_URL \
|
|
155
|
+
--broadcast \
|
|
156
|
+
--verify \
|
|
157
|
+
--etherscan-api-key $ETHERSCAN_KEY \
|
|
158
|
+
-vvvv
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Hardhat
|
|
164
|
+
|
|
165
|
+
### Project Setup
|
|
166
|
+
```bash
|
|
167
|
+
npx hardhat init # New project
|
|
168
|
+
npx hardhat compile # Compile
|
|
169
|
+
npx hardhat test # Run tests
|
|
170
|
+
npx hardhat node # Local node
|
|
171
|
+
npx hardhat run scripts/deploy.ts --network mainnet
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Configuration
|
|
175
|
+
```typescript
|
|
176
|
+
// hardhat.config.ts
|
|
177
|
+
import { HardhatUserConfig } from 'hardhat/config'
|
|
178
|
+
import '@nomicfoundation/hardhat-toolbox'
|
|
179
|
+
|
|
180
|
+
const config: HardhatUserConfig = {
|
|
181
|
+
solidity: {
|
|
182
|
+
version: '0.8.24',
|
|
183
|
+
settings: {
|
|
184
|
+
optimizer: { enabled: true, runs: 200 },
|
|
185
|
+
viaIR: false,
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
networks: {
|
|
189
|
+
mainnet: {
|
|
190
|
+
url: process.env.ETH_RPC_URL,
|
|
191
|
+
accounts: [process.env.PRIVATE_KEY!],
|
|
192
|
+
},
|
|
193
|
+
base: {
|
|
194
|
+
url: process.env.BASE_RPC_URL,
|
|
195
|
+
accounts: [process.env.PRIVATE_KEY!],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
etherscan: {
|
|
199
|
+
apiKey: process.env.ETHERSCAN_KEY,
|
|
200
|
+
},
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export default config
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Essential Plugins
|
|
207
|
+
| Plugin | Purpose |
|
|
208
|
+
|--------|---------|
|
|
209
|
+
| `@nomicfoundation/hardhat-toolbox` | All-in-one (ethers, chai, coverage, gas) |
|
|
210
|
+
| `@nomicfoundation/hardhat-verify` | Contract verification |
|
|
211
|
+
| `hardhat-gas-reporter` | Gas usage per function |
|
|
212
|
+
| `hardhat-deploy` | Deterministic deployments |
|
|
213
|
+
| `@openzeppelin/hardhat-upgrades` | Proxy deploy + upgrade |
|
|
214
|
+
|
|
215
|
+
### Testing with Hardhat
|
|
216
|
+
```typescript
|
|
217
|
+
import { expect } from 'chai'
|
|
218
|
+
import { ethers } from 'hardhat'
|
|
219
|
+
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'
|
|
220
|
+
|
|
221
|
+
describe('MyToken', () => {
|
|
222
|
+
async function deployFixture() {
|
|
223
|
+
const [owner, alice, bob] = await ethers.getSigners()
|
|
224
|
+
const Token = await ethers.getContractFactory('MyToken')
|
|
225
|
+
const token = await Token.deploy('MyToken', 'MTK')
|
|
226
|
+
return { token, owner, alice, bob }
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
it('should transfer tokens', async () => {
|
|
230
|
+
const { token, owner, alice } = await loadFixture(deployFixture)
|
|
231
|
+
await token.mint(owner.address, 1000)
|
|
232
|
+
await token.transfer(alice.address, 500)
|
|
233
|
+
expect(await token.balanceOf(alice.address)).to.equal(500)
|
|
234
|
+
})
|
|
235
|
+
})
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## CI/CD (GitHub Actions)
|
|
241
|
+
|
|
242
|
+
```yaml
|
|
243
|
+
# .github/workflows/ci.yml
|
|
244
|
+
name: Solidity CI
|
|
245
|
+
|
|
246
|
+
on: [push, pull_request]
|
|
247
|
+
|
|
248
|
+
jobs:
|
|
249
|
+
test:
|
|
250
|
+
runs-on: ubuntu-latest
|
|
251
|
+
steps:
|
|
252
|
+
- uses: actions/checkout@v4
|
|
253
|
+
with:
|
|
254
|
+
submodules: recursive
|
|
255
|
+
|
|
256
|
+
- name: Install Foundry
|
|
257
|
+
uses: foundry-rs/foundry-toolchain@v1
|
|
258
|
+
|
|
259
|
+
- name: Build
|
|
260
|
+
run: forge build --sizes
|
|
261
|
+
|
|
262
|
+
- name: Test
|
|
263
|
+
run: forge test -vvv
|
|
264
|
+
|
|
265
|
+
- name: Gas Snapshot
|
|
266
|
+
run: forge snapshot --check
|
|
267
|
+
|
|
268
|
+
- name: Coverage
|
|
269
|
+
run: forge coverage --report lcov
|
|
270
|
+
|
|
271
|
+
- name: Slither
|
|
272
|
+
uses: crytic/slither-action@v0.4.0
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Foundry vs Hardhat
|
|
278
|
+
|
|
279
|
+
| Feature | Foundry | Hardhat |
|
|
280
|
+
|---------|---------|---------|
|
|
281
|
+
| **Speed** | ⚡ Very fast (Rust) | Slower (Node.js) |
|
|
282
|
+
| **Test Language** | Solidity | TypeScript/JS |
|
|
283
|
+
| **Fuzz Testing** | ✅ Built-in | ❌ Needs plugins |
|
|
284
|
+
| **Invariant Testing** | ✅ Built-in | ❌ |
|
|
285
|
+
| **Fork Testing** | ✅ Fast | ✅ Slower |
|
|
286
|
+
| **Cheatcodes** | ✅ Extensive | ✅ network-helpers |
|
|
287
|
+
| **Plugin Ecosystem** | Growing | Mature |
|
|
288
|
+
| **Deployment** | forge script | hardhat-deploy |
|
|
289
|
+
| **When to Use** | Performance, Solidity-native | TypeScript ecosystem, plugins |
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thirdweb-sdk
|
|
3
|
+
description: thirdweb SDK for deploying contracts, connecting wallets (email/passkey/social), gasless transactions, Engine backend, and cross-chain payments.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# thirdweb SDK — Unified Web3 Development Platform
|
|
7
|
+
|
|
8
|
+
Expert knowledge for building with thirdweb's SDK across frontend, backend, and on-chain.
|
|
9
|
+
|
|
10
|
+
## Use this skill when
|
|
11
|
+
|
|
12
|
+
- Deploying contracts without writing deploy scripts
|
|
13
|
+
- Adding wallet connection with email, passkey, or social login
|
|
14
|
+
- Setting up gasless/sponsored transactions
|
|
15
|
+
- Using thirdweb Engine for backend wallet management
|
|
16
|
+
- Implementing cross-chain payments or token swaps
|
|
17
|
+
|
|
18
|
+
## Do not use this skill when
|
|
19
|
+
|
|
20
|
+
- Using RainbowKit for wallet connection (use `rainbowkit-wagmi`)
|
|
21
|
+
- Writing raw Solidity patterns (use `solidity-patterns`)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
### Installation
|
|
28
|
+
```bash
|
|
29
|
+
npm install thirdweb
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Client
|
|
33
|
+
```typescript
|
|
34
|
+
import { createThirdwebClient } from 'thirdweb'
|
|
35
|
+
|
|
36
|
+
const client = createThirdwebClient({
|
|
37
|
+
clientId: process.env.NEXT_PUBLIC_THIRDWEB_CLIENT_ID!,
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Wallet Connection (Connect)
|
|
44
|
+
|
|
45
|
+
### ConnectButton (Quick Setup)
|
|
46
|
+
```typescript
|
|
47
|
+
import { ConnectButton } from 'thirdweb/react'
|
|
48
|
+
import { ThirdwebProvider } from 'thirdweb/react'
|
|
49
|
+
|
|
50
|
+
export default function App() {
|
|
51
|
+
return (
|
|
52
|
+
<ThirdwebProvider>
|
|
53
|
+
<ConnectButton client={client} />
|
|
54
|
+
</ThirdwebProvider>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### In-App Wallets (Email, Passkey, Social)
|
|
60
|
+
```typescript
|
|
61
|
+
import { ConnectButton } from 'thirdweb/react'
|
|
62
|
+
import { inAppWallet, createWallet } from 'thirdweb/wallets'
|
|
63
|
+
|
|
64
|
+
const wallets = [
|
|
65
|
+
inAppWallet({
|
|
66
|
+
auth: {
|
|
67
|
+
options: ['email', 'passkey', 'google', 'apple', 'discord'],
|
|
68
|
+
},
|
|
69
|
+
executionMode: {
|
|
70
|
+
mode: 'EIP7702',
|
|
71
|
+
sponsorGas: true, // Gasless for users
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
createWallet('io.metamask'),
|
|
75
|
+
createWallet('com.coinbase.wallet'),
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
<ConnectButton client={client} wallets={wallets} />
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### ConnectEmbed (Inline)
|
|
82
|
+
```typescript
|
|
83
|
+
import { ConnectEmbed } from 'thirdweb/react'
|
|
84
|
+
|
|
85
|
+
// Renders wallet options directly on page (not modal)
|
|
86
|
+
<ConnectEmbed client={client} wallets={wallets} />
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Contract Interaction
|
|
92
|
+
|
|
93
|
+
### Read Contract
|
|
94
|
+
```typescript
|
|
95
|
+
import { getContract, readContract } from 'thirdweb'
|
|
96
|
+
import { ethereum } from 'thirdweb/chains'
|
|
97
|
+
|
|
98
|
+
const contract = getContract({
|
|
99
|
+
client,
|
|
100
|
+
chain: ethereum,
|
|
101
|
+
address: '0x...',
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const totalSupply = await readContract({
|
|
105
|
+
contract,
|
|
106
|
+
method: 'function totalSupply() view returns (uint256)',
|
|
107
|
+
params: [],
|
|
108
|
+
})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Write Contract
|
|
112
|
+
```typescript
|
|
113
|
+
import { prepareContractCall, sendTransaction } from 'thirdweb'
|
|
114
|
+
import { useActiveAccount } from 'thirdweb/react'
|
|
115
|
+
|
|
116
|
+
const account = useActiveAccount()
|
|
117
|
+
|
|
118
|
+
const transaction = prepareContractCall({
|
|
119
|
+
contract,
|
|
120
|
+
method: 'function mint(address to, uint256 amount)',
|
|
121
|
+
params: [account.address, 100n],
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
const { transactionHash } = await sendTransaction({
|
|
125
|
+
account,
|
|
126
|
+
transaction,
|
|
127
|
+
})
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Deploy Contract
|
|
131
|
+
```bash
|
|
132
|
+
# Deploy from CLI
|
|
133
|
+
npx thirdweb deploy
|
|
134
|
+
|
|
135
|
+
# Or programmatically
|
|
136
|
+
import { deployContract } from 'thirdweb/deploys'
|
|
137
|
+
|
|
138
|
+
const address = await deployContract({
|
|
139
|
+
client,
|
|
140
|
+
chain: ethereum,
|
|
141
|
+
account,
|
|
142
|
+
bytecode: '0x...',
|
|
143
|
+
abi: contractAbi,
|
|
144
|
+
constructorParams: [param1, param2],
|
|
145
|
+
})
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## React Hooks
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import {
|
|
154
|
+
useActiveAccount,
|
|
155
|
+
useActiveWallet,
|
|
156
|
+
useReadContract,
|
|
157
|
+
useSendTransaction,
|
|
158
|
+
useWalletBalance,
|
|
159
|
+
} from 'thirdweb/react'
|
|
160
|
+
|
|
161
|
+
// Current account
|
|
162
|
+
const account = useActiveAccount()
|
|
163
|
+
|
|
164
|
+
// Read data
|
|
165
|
+
const { data, isLoading } = useReadContract({
|
|
166
|
+
contract,
|
|
167
|
+
method: 'function balanceOf(address) view returns (uint256)',
|
|
168
|
+
params: [account?.address],
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
// Send transaction
|
|
172
|
+
const { mutate: sendTx, isPending } = useSendTransaction()
|
|
173
|
+
sendTx(transaction)
|
|
174
|
+
|
|
175
|
+
// Wallet balance
|
|
176
|
+
const { data: balance } = useWalletBalance({
|
|
177
|
+
client,
|
|
178
|
+
chain: ethereum,
|
|
179
|
+
address: account?.address,
|
|
180
|
+
})
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## thirdweb Engine (Backend)
|
|
186
|
+
|
|
187
|
+
Server-side wallet management and transaction processing.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
// Engine is a self-hosted HTTP server
|
|
191
|
+
// POST /contract/:chain/:address/write
|
|
192
|
+
|
|
193
|
+
const response = await fetch(
|
|
194
|
+
`${ENGINE_URL}/contract/${chainId}/${contractAddress}/write`,
|
|
195
|
+
{
|
|
196
|
+
method: 'POST',
|
|
197
|
+
headers: {
|
|
198
|
+
'Content-Type': 'application/json',
|
|
199
|
+
'Authorization': `Bearer ${ENGINE_ACCESS_TOKEN}`,
|
|
200
|
+
'x-backend-wallet-address': backendWalletAddress,
|
|
201
|
+
},
|
|
202
|
+
body: JSON.stringify({
|
|
203
|
+
functionName: 'transfer',
|
|
204
|
+
args: [toAddress, amount],
|
|
205
|
+
}),
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Engine Features
|
|
211
|
+
| Feature | Description |
|
|
212
|
+
|---------|-------------|
|
|
213
|
+
| **Managed Wallets** | Create and manage wallets server-side |
|
|
214
|
+
| **Nonce Management** | Automatic nonce handling for parallel tx |
|
|
215
|
+
| **Gas Management** | Auto gas estimation and retries |
|
|
216
|
+
| **Webhooks** | Transaction status notifications |
|
|
217
|
+
| **Idempotent Tx** | Prevent duplicate transactions |
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Pay (Onramp + Bridge)
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { PayEmbed } from 'thirdweb/react'
|
|
225
|
+
|
|
226
|
+
// Fiat → Crypto onramp + cross-chain bridge
|
|
227
|
+
<PayEmbed client={client} />
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## thirdweb vs RainbowKit
|
|
233
|
+
|
|
234
|
+
| Feature | thirdweb | RainbowKit |
|
|
235
|
+
|---------|----------|------------|
|
|
236
|
+
| **Wallet UI** | ConnectButton/Embed | ConnectButton |
|
|
237
|
+
| **In-App Wallets** | ✅ Email, passkey, social | ❌ External only |
|
|
238
|
+
| **Account Abstraction** | ✅ Built-in | ❌ Separate |
|
|
239
|
+
| **Contract Deploy** | ✅ CLI + SDK | ❌ |
|
|
240
|
+
| **Backend Engine** | ✅ | ❌ |
|
|
241
|
+
| **Customization** | Moderate | High |
|
|
242
|
+
| **Dependency** | thirdweb only | Wagmi + viem |
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web3-api-providers
|
|
3
|
+
description: Enhanced APIs from Alchemy, Moralis, Infura, and QuickNode. NFT APIs, Token APIs, Webhooks, Streams, and blockchain data services for production DApps.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Web3 API Providers — Enhanced Blockchain Data Services
|
|
7
|
+
|
|
8
|
+
Expert knowledge for leveraging Web3 API provider SDKs and enhanced APIs beyond basic RPC.
|
|
9
|
+
|
|
10
|
+
## Use this skill when
|
|
11
|
+
|
|
12
|
+
- Fetching NFT data (metadata, ownership, transfers)
|
|
13
|
+
- Querying token balances and transfer history
|
|
14
|
+
- Setting up webhooks for real-time blockchain events
|
|
15
|
+
- Using enhanced APIs (asset transfers, trace calls)
|
|
16
|
+
- Choosing between Alchemy, Moralis, Infura, or QuickNode
|
|
17
|
+
|
|
18
|
+
## Do not use this skill when
|
|
19
|
+
|
|
20
|
+
- Optimizing raw RPC calls or Multicall3 (use `rpc-optimization`)
|
|
21
|
+
- Building subgraphs or indexers (use `subgraph-indexing`)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Alchemy SDK
|
|
26
|
+
|
|
27
|
+
### Setup
|
|
28
|
+
```typescript
|
|
29
|
+
import { Alchemy, Network } from 'alchemy-sdk'
|
|
30
|
+
|
|
31
|
+
const alchemy = new Alchemy({
|
|
32
|
+
apiKey: process.env.ALCHEMY_API_KEY,
|
|
33
|
+
network: Network.ETH_MAINNET,
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### NFT API
|
|
38
|
+
```typescript
|
|
39
|
+
// Get all NFTs for an owner
|
|
40
|
+
const nfts = await alchemy.nft.getNftsForOwner('0x...')
|
|
41
|
+
|
|
42
|
+
// Get NFT metadata
|
|
43
|
+
const metadata = await alchemy.nft.getNftMetadata(contractAddress, tokenId)
|
|
44
|
+
|
|
45
|
+
// Get owners of an NFT collection
|
|
46
|
+
const owners = await alchemy.nft.getOwnersForContract(contractAddress)
|
|
47
|
+
|
|
48
|
+
// Get NFTs for a contract
|
|
49
|
+
const contractNfts = await alchemy.nft.getNftsForContract(contractAddress)
|
|
50
|
+
|
|
51
|
+
// Verify NFT ownership
|
|
52
|
+
const isOwner = await alchemy.nft.verifyNftOwnership(ownerAddress, contractAddress)
|
|
53
|
+
|
|
54
|
+
// Get floor price
|
|
55
|
+
const floorPrice = await alchemy.nft.getFloorPrice(contractAddress)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Token API
|
|
59
|
+
```typescript
|
|
60
|
+
// Get all token balances
|
|
61
|
+
const balances = await alchemy.core.getTokenBalances(ownerAddress)
|
|
62
|
+
|
|
63
|
+
// Get token metadata (name, symbol, decimals, logo)
|
|
64
|
+
const metadata = await alchemy.core.getTokenMetadata(tokenAddress)
|
|
65
|
+
|
|
66
|
+
// Get asset transfers (ERC-20, ERC-721, ERC-1155, native)
|
|
67
|
+
const transfers = await alchemy.core.getAssetTransfers({
|
|
68
|
+
fromBlock: '0x0',
|
|
69
|
+
toBlock: 'latest',
|
|
70
|
+
toAddress: '0x...',
|
|
71
|
+
category: ['erc20', 'erc721', 'external'],
|
|
72
|
+
})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Webhooks (Alchemy Notify)
|
|
76
|
+
```typescript
|
|
77
|
+
// Create address activity webhook
|
|
78
|
+
const webhook = await alchemy.notify.createWebhook({
|
|
79
|
+
url: 'https://your-server.com/webhook',
|
|
80
|
+
type: 'ADDRESS_ACTIVITY',
|
|
81
|
+
addresses: ['0x...'],
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// Mined transaction webhook
|
|
85
|
+
const minedWebhook = await alchemy.notify.createWebhook({
|
|
86
|
+
url: 'https://your-server.com/webhook',
|
|
87
|
+
type: 'MINED_TRANSACTION',
|
|
88
|
+
addresses: ['0x...'],
|
|
89
|
+
})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Enhanced WebSockets
|
|
93
|
+
```typescript
|
|
94
|
+
// Subscribe to pending transactions
|
|
95
|
+
alchemy.ws.on({
|
|
96
|
+
method: 'alchemy_pendingTransactions',
|
|
97
|
+
toAddress: contractAddress,
|
|
98
|
+
}, (tx) => {
|
|
99
|
+
console.log('Pending tx:', tx.hash)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// Subscribe to log events
|
|
103
|
+
alchemy.ws.on({
|
|
104
|
+
method: 'eth_subscribe',
|
|
105
|
+
params: ['logs', { address: contractAddress, topics: [] }],
|
|
106
|
+
}, (log) => {
|
|
107
|
+
console.log('New log:', log)
|
|
108
|
+
})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Moralis SDK
|
|
114
|
+
|
|
115
|
+
### Setup
|
|
116
|
+
```typescript
|
|
117
|
+
import Moralis from 'moralis'
|
|
118
|
+
|
|
119
|
+
await Moralis.start({ apiKey: process.env.MORALIS_API_KEY })
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### NFT API
|
|
123
|
+
```typescript
|
|
124
|
+
// Get NFTs by wallet
|
|
125
|
+
const nfts = await Moralis.EvmApi.nft.getWalletNFTs({
|
|
126
|
+
address: '0x...',
|
|
127
|
+
chain: '0x1', // Ethereum
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
// Get NFT metadata
|
|
131
|
+
const metadata = await Moralis.EvmApi.nft.getNFTMetadata({
|
|
132
|
+
address: contractAddress,
|
|
133
|
+
tokenId: '1',
|
|
134
|
+
chain: '0x1',
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
// Get NFT transfers
|
|
138
|
+
const transfers = await Moralis.EvmApi.nft.getNFTTransfers({
|
|
139
|
+
address: contractAddress,
|
|
140
|
+
tokenId: '1',
|
|
141
|
+
chain: '0x1',
|
|
142
|
+
})
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Token API
|
|
146
|
+
```typescript
|
|
147
|
+
// Get ERC-20 balances
|
|
148
|
+
const balances = await Moralis.EvmApi.token.getWalletTokenBalances({
|
|
149
|
+
address: '0x...',
|
|
150
|
+
chain: '0x1',
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
// Get token price
|
|
154
|
+
const price = await Moralis.EvmApi.token.getTokenPrice({
|
|
155
|
+
address: tokenAddress,
|
|
156
|
+
chain: '0x1',
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
// Get token transfers
|
|
160
|
+
const transfers = await Moralis.EvmApi.token.getWalletTokenTransfers({
|
|
161
|
+
address: '0x...',
|
|
162
|
+
chain: '0x1',
|
|
163
|
+
})
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Streams API (Real-Time Webhooks)
|
|
167
|
+
```typescript
|
|
168
|
+
// Create a stream for contract events
|
|
169
|
+
const stream = await Moralis.Streams.add({
|
|
170
|
+
chains: ['0x1'],
|
|
171
|
+
tag: 'my-stream',
|
|
172
|
+
description: 'Track USDC transfers',
|
|
173
|
+
webhookUrl: 'https://your-server.com/moralis-webhook',
|
|
174
|
+
includeContractLogs: true,
|
|
175
|
+
abi: usdcAbi,
|
|
176
|
+
topic0: ['Transfer(address,address,uint256)'],
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
// Add address to stream
|
|
180
|
+
await Moralis.Streams.addAddress({
|
|
181
|
+
id: stream.result.id,
|
|
182
|
+
address: usdcAddress,
|
|
183
|
+
})
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### DeFi API
|
|
187
|
+
```typescript
|
|
188
|
+
// Get DeFi positions
|
|
189
|
+
const positions = await Moralis.EvmApi.defi.getDefiPositionsByProtocol({
|
|
190
|
+
address: '0x...',
|
|
191
|
+
chain: '0x1',
|
|
192
|
+
protocol: 'uniswap-v3',
|
|
193
|
+
})
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Infura
|
|
199
|
+
|
|
200
|
+
### Setup
|
|
201
|
+
```typescript
|
|
202
|
+
import { InfuraProvider } from 'ethers'
|
|
203
|
+
|
|
204
|
+
const provider = new InfuraProvider('mainnet', process.env.INFURA_PROJECT_ID)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### IPFS Gateway
|
|
208
|
+
```typescript
|
|
209
|
+
// Upload to IPFS via Infura
|
|
210
|
+
const response = await fetch('https://ipfs.infura.io:5001/api/v0/add', {
|
|
211
|
+
method: 'POST',
|
|
212
|
+
headers: {
|
|
213
|
+
Authorization: `Basic ${Buffer.from(`${PROJECT_ID}:${PROJECT_SECRET}`).toString('base64')}`,
|
|
214
|
+
},
|
|
215
|
+
body: formData,
|
|
216
|
+
})
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### MetaMask SDK Integration
|
|
220
|
+
```typescript
|
|
221
|
+
import { MetaMaskSDK } from '@metamask/sdk'
|
|
222
|
+
|
|
223
|
+
const MMSDK = new MetaMaskSDK({
|
|
224
|
+
infuraAPIKey: process.env.INFURA_API_KEY,
|
|
225
|
+
dappMetadata: {
|
|
226
|
+
name: 'My DApp',
|
|
227
|
+
url: window.location.href,
|
|
228
|
+
},
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
const ethereum = MMSDK.getProvider()
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## QuickNode
|
|
237
|
+
|
|
238
|
+
### Streams (Real-time)
|
|
239
|
+
```typescript
|
|
240
|
+
// QuickNode Streams — configured via dashboard or API
|
|
241
|
+
// Delivers filtered blockchain data to your endpoint
|
|
242
|
+
|
|
243
|
+
// Stream filter example (QN API):
|
|
244
|
+
const filter = {
|
|
245
|
+
network: 'ethereum-mainnet',
|
|
246
|
+
expression: `
|
|
247
|
+
tx_logs_address == '${contractAddress}' &&
|
|
248
|
+
tx_logs_topic0 == '${transferTopic}'
|
|
249
|
+
`,
|
|
250
|
+
destination: 'https://your-server.com/qn-webhook',
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Functions (Serverless)
|
|
255
|
+
```javascript
|
|
256
|
+
// QuickNode Functions — serverless JS at the edge
|
|
257
|
+
// Triggered by blockchain events or HTTP requests
|
|
258
|
+
export async function main(params) {
|
|
259
|
+
const { data } = params
|
|
260
|
+
// Process blockchain data
|
|
261
|
+
return { statusCode: 200, body: JSON.stringify(result) }
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Provider Selection Guide
|
|
268
|
+
|
|
269
|
+
| Provider | Best For | NFT API | Token API | Webhooks | Free Tier |
|
|
270
|
+
|----------|----------|---------|-----------|----------|-----------|
|
|
271
|
+
| **Alchemy** | Full-stack DApps | ✅ Rich | ✅ Enhanced | ✅ Notify | 300M CU/mo |
|
|
272
|
+
| **Moralis** | Rapid prototyping | ✅ Rich | ✅ + Prices | ✅ Streams | 40K CU/day |
|
|
273
|
+
| **Infura** | MetaMask ecosystem | ❌ Basic | ❌ Basic | ❌ | 100K req/day |
|
|
274
|
+
| **QuickNode** | High-perf infra | ✅ Addon | ✅ Addon | ✅ Streams | 10M credits |
|
|
275
|
+
|
|
276
|
+
### When to Use What
|
|
277
|
+
- **Need NFT/Token data fast?** → Alchemy or Moralis
|
|
278
|
+
- **Need real-time webhooks?** → Moralis Streams or Alchemy Notify
|
|
279
|
+
- **Need MetaMask integration?** → Infura
|
|
280
|
+
- **Need custom streaming + functions?** → QuickNode
|
|
281
|
+
- **Need DeFi positions?** → Moralis
|