abc-scaffold 1.0.1 → 1.0.2
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/package.json
CHANGED
package/src/scaffold.js
CHANGED
|
@@ -68,28 +68,28 @@ Fill in your values in \`.env\`:
|
|
|
68
68
|
### 3. Compile contracts
|
|
69
69
|
|
|
70
70
|
\`\`\`bash
|
|
71
|
-
|
|
71
|
+
npx hardhat compile
|
|
72
72
|
\`\`\`
|
|
73
73
|
|
|
74
74
|
### 4. Run tests
|
|
75
75
|
|
|
76
76
|
\`\`\`bash
|
|
77
|
-
|
|
77
|
+
npx hardhat test
|
|
78
78
|
\`\`\`
|
|
79
79
|
|
|
80
|
-
### 5.
|
|
80
|
+
### 5. Deploy contracts locally
|
|
81
|
+
|
|
82
|
+
Open two terminals:
|
|
81
83
|
|
|
82
84
|
\`\`\`bash
|
|
85
|
+
# Terminal 1 — start a local node
|
|
83
86
|
npx hardhat node
|
|
84
|
-
\`\`\`
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
\`\`\`bash
|
|
88
|
+
# Terminal 2 — deploy your contracts
|
|
89
89
|
npx hardhat run scripts/deploy.js --network localhost
|
|
90
90
|
\`\`\`
|
|
91
91
|
|
|
92
|
-
###
|
|
92
|
+
### 6. Start the frontend
|
|
93
93
|
|
|
94
94
|
\`\`\`bash
|
|
95
95
|
cd frontend
|
|
@@ -337,7 +337,7 @@ export async function scaffold(initialName) {
|
|
|
337
337
|
console.log(chalk.cyan(` cd ${projectName}`));
|
|
338
338
|
console.log(chalk.cyan(' npm install') + chalk.gray(' # install root dependencies'));
|
|
339
339
|
console.log(chalk.cyan(' cp .env.example .env') + chalk.gray(' # fill in your keys'));
|
|
340
|
-
console.log(chalk.cyan('
|
|
340
|
+
console.log(chalk.cyan(' npx hardhat compile') + chalk.gray(' # compile contracts'));
|
|
341
341
|
console.log(chalk.cyan(' cd frontend && npm install') + chalk.gray(' # install frontend dependencies'));
|
|
342
342
|
console.log(chalk.cyan(' npm run dev') + chalk.gray(' # start the UI'));
|
|
343
343
|
console.log('');
|
|
@@ -19,75 +19,63 @@ body {
|
|
|
19
19
|
flex-direction: column;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/* ──
|
|
22
|
+
/* ── Centered content ── */
|
|
23
23
|
.main {
|
|
24
24
|
flex: 1;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
width: 100%;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/* ── Hero ── */
|
|
32
|
-
.hero {
|
|
33
|
-
text-align: center;
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
justify-content: center;
|
|
34
28
|
}
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
/* ── Connect button ── */
|
|
31
|
+
.connect-btn {
|
|
32
|
+
background-color: #e94560;
|
|
39
33
|
color: #ffffff;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.subtitle {
|
|
34
|
+
border: none;
|
|
35
|
+
border-radius: 10px;
|
|
36
|
+
padding: 1rem 2.5rem;
|
|
45
37
|
font-size: 1.1rem;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
font-weight: 700;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
transition: background-color 0.18s ease, transform 0.12s ease;
|
|
41
|
+
letter-spacing: 0.3px;
|
|
49
42
|
}
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
55
|
-
gap: 1.5rem;
|
|
56
|
-
margin-top: 1rem;
|
|
44
|
+
.connect-btn:hover:not(:disabled) {
|
|
45
|
+
background-color: #c73652;
|
|
46
|
+
transform: translateY(-2px);
|
|
57
47
|
}
|
|
58
48
|
|
|
59
|
-
.
|
|
60
|
-
|
|
61
|
-
border: 1px solid #2a2a4a;
|
|
62
|
-
border-radius: 12px;
|
|
63
|
-
padding: 1.75rem 1.5rem;
|
|
64
|
-
text-align: left;
|
|
65
|
-
transition: border-color 0.2s ease, transform 0.2s ease;
|
|
49
|
+
.connect-btn:active:not(:disabled) {
|
|
50
|
+
transform: translateY(0);
|
|
66
51
|
}
|
|
67
52
|
|
|
68
|
-
.
|
|
69
|
-
|
|
70
|
-
|
|
53
|
+
.connect-btn:disabled {
|
|
54
|
+
background-color: #555566;
|
|
55
|
+
cursor: not-allowed;
|
|
71
56
|
}
|
|
72
57
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
58
|
+
/* ── Connected state ── */
|
|
59
|
+
.connected {
|
|
60
|
+
display: flex;
|
|
61
|
+
align-items: center;
|
|
62
|
+
gap: 0.6rem;
|
|
63
|
+
background-color: #1a1a2e;
|
|
64
|
+
border: 1px solid #e94560;
|
|
65
|
+
border-radius: 10px;
|
|
66
|
+
padding: 0.75rem 1.5rem;
|
|
78
67
|
}
|
|
79
68
|
|
|
80
|
-
.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
69
|
+
.wallet-dot {
|
|
70
|
+
width: 10px;
|
|
71
|
+
height: 10px;
|
|
72
|
+
background-color: #4caf50;
|
|
73
|
+
border-radius: 50%;
|
|
74
|
+
flex-shrink: 0;
|
|
84
75
|
}
|
|
85
76
|
|
|
86
|
-
.
|
|
87
|
-
background-color: #0d0d1a;
|
|
88
|
-
color: #e94560;
|
|
89
|
-
padding: 0.1rem 0.4rem;
|
|
90
|
-
border-radius: 4px;
|
|
91
|
-
font-size: 0.85rem;
|
|
77
|
+
.wallet-address {
|
|
92
78
|
font-family: 'Fira Code', 'Cascadia Code', monospace;
|
|
79
|
+
font-size: 1rem;
|
|
80
|
+
color: #e2e2e2;
|
|
93
81
|
}
|
|
@@ -1,34 +1,52 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { BrowserProvider } from 'ethers';
|
|
1
3
|
import Navbar from './components/Navbar.jsx';
|
|
2
4
|
import './App.css';
|
|
3
5
|
|
|
4
6
|
function App() {
|
|
7
|
+
const [account, setAccount] = useState(null);
|
|
8
|
+
const [connecting, setConnecting] = useState(false);
|
|
9
|
+
|
|
10
|
+
async function connectWallet() {
|
|
11
|
+
if (!window.ethereum) {
|
|
12
|
+
alert('MetaMask is not installed. Please install it at https://metamask.io');
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
setConnecting(true);
|
|
17
|
+
try {
|
|
18
|
+
const provider = new BrowserProvider(window.ethereum);
|
|
19
|
+
const accounts = await provider.send('eth_requestAccounts', []);
|
|
20
|
+
setAccount(accounts[0]);
|
|
21
|
+
} catch (err) {
|
|
22
|
+
console.error('Wallet connection rejected:', err);
|
|
23
|
+
} finally {
|
|
24
|
+
setConnecting(false);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function truncate(addr) {
|
|
29
|
+
return `${addr.slice(0, 6)}…${addr.slice(-4)}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
5
32
|
return (
|
|
6
33
|
<div className="app">
|
|
7
34
|
<Navbar />
|
|
8
35
|
<main className="main">
|
|
9
|
-
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<div className="cards">
|
|
14
|
-
<div className="card">
|
|
15
|
-
<h3>📄 Write Contracts</h3>
|
|
16
|
-
<p>Add your Solidity files to <code>contracts/</code></p>
|
|
17
|
-
</div>
|
|
18
|
-
<div className="card">
|
|
19
|
-
<h3>⚙️ Compile</h3>
|
|
20
|
-
<p>Run <code>npm run compile</code> in the project root</p>
|
|
21
|
-
</div>
|
|
22
|
-
<div className="card">
|
|
23
|
-
<h3>🚀 Deploy</h3>
|
|
24
|
-
<p>Add a script to <code>scripts/</code> and run it with Hardhat</p>
|
|
25
|
-
</div>
|
|
26
|
-
<div className="card">
|
|
27
|
-
<h3>🔗 Connect</h3>
|
|
28
|
-
<p>Use the wallet button above to connect MetaMask, then interact with your contracts</p>
|
|
29
|
-
</div>
|
|
36
|
+
{account ? (
|
|
37
|
+
<div className="connected">
|
|
38
|
+
<span className="wallet-dot" />
|
|
39
|
+
<span className="wallet-address">{truncate(account)}</span>
|
|
30
40
|
</div>
|
|
31
|
-
|
|
41
|
+
) : (
|
|
42
|
+
<button
|
|
43
|
+
className="connect-btn"
|
|
44
|
+
onClick={connectWallet}
|
|
45
|
+
disabled={connecting}
|
|
46
|
+
>
|
|
47
|
+
{connecting ? 'Connecting…' : 'Connect Wallet'}
|
|
48
|
+
</button>
|
|
49
|
+
)}
|
|
32
50
|
</main>
|
|
33
51
|
</div>
|
|
34
52
|
);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
.navbar {
|
|
2
2
|
display: flex;
|
|
3
3
|
align-items: center;
|
|
4
|
-
justify-content: space-between;
|
|
5
4
|
padding: 1rem 2rem;
|
|
6
5
|
background-color: #1a1a2e;
|
|
7
6
|
border-bottom: 1px solid #2a2a4a;
|
|
@@ -10,12 +9,10 @@
|
|
|
10
9
|
z-index: 100;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
/* ── Brand ── */
|
|
14
12
|
.navbar-brand {
|
|
15
13
|
display: flex;
|
|
16
14
|
align-items: center;
|
|
17
15
|
gap: 0.6rem;
|
|
18
|
-
text-decoration: none;
|
|
19
16
|
}
|
|
20
17
|
|
|
21
18
|
.navbar-logo {
|
|
@@ -29,62 +26,3 @@
|
|
|
29
26
|
color: #e94560;
|
|
30
27
|
letter-spacing: 0.3px;
|
|
31
28
|
}
|
|
32
|
-
|
|
33
|
-
/* ── Actions ── */
|
|
34
|
-
.navbar-actions {
|
|
35
|
-
display: flex;
|
|
36
|
-
align-items: center;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/* Connect button */
|
|
40
|
-
.connect-btn {
|
|
41
|
-
background-color: #e94560;
|
|
42
|
-
color: #ffffff;
|
|
43
|
-
border: none;
|
|
44
|
-
border-radius: 8px;
|
|
45
|
-
padding: 0.55rem 1.3rem;
|
|
46
|
-
font-size: 0.9rem;
|
|
47
|
-
font-weight: 600;
|
|
48
|
-
cursor: pointer;
|
|
49
|
-
transition: background-color 0.18s ease, transform 0.12s ease;
|
|
50
|
-
white-space: nowrap;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.connect-btn:hover:not(:disabled) {
|
|
54
|
-
background-color: #c73652;
|
|
55
|
-
transform: translateY(-1px);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.connect-btn:active:not(:disabled) {
|
|
59
|
-
transform: translateY(0);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.connect-btn:disabled {
|
|
63
|
-
background-color: #555566;
|
|
64
|
-
cursor: not-allowed;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/* Connected badge */
|
|
68
|
-
.wallet-badge {
|
|
69
|
-
display: flex;
|
|
70
|
-
align-items: center;
|
|
71
|
-
gap: 0.5rem;
|
|
72
|
-
background-color: #0f3460;
|
|
73
|
-
border: 1px solid #e94560;
|
|
74
|
-
border-radius: 8px;
|
|
75
|
-
padding: 0.45rem 1rem;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.wallet-dot {
|
|
79
|
-
width: 8px;
|
|
80
|
-
height: 8px;
|
|
81
|
-
background-color: #4caf50;
|
|
82
|
-
border-radius: 50%;
|
|
83
|
-
flex-shrink: 0;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.wallet-address {
|
|
87
|
-
color: #e2e2e2;
|
|
88
|
-
font-family: 'Fira Code', 'Cascadia Code', monospace;
|
|
89
|
-
font-size: 0.875rem;
|
|
90
|
-
}
|
|
@@ -1,56 +1,12 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
import { BrowserProvider } from 'ethers';
|
|
3
1
|
import './Navbar.css';
|
|
4
2
|
|
|
5
3
|
export default function Navbar() {
|
|
6
|
-
const [account, setAccount] = useState(null);
|
|
7
|
-
const [connecting, setConnecting] = useState(false);
|
|
8
|
-
|
|
9
|
-
async function connectWallet() {
|
|
10
|
-
if (!window.ethereum) {
|
|
11
|
-
alert('MetaMask is not installed. Please install it at https://metamask.io');
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
setConnecting(true);
|
|
16
|
-
try {
|
|
17
|
-
const provider = new BrowserProvider(window.ethereum);
|
|
18
|
-
const accounts = await provider.send('eth_requestAccounts', []);
|
|
19
|
-
setAccount(accounts[0]);
|
|
20
|
-
} catch (err) {
|
|
21
|
-
console.error('Wallet connection rejected:', err);
|
|
22
|
-
} finally {
|
|
23
|
-
setConnecting(false);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function truncate(addr) {
|
|
28
|
-
return `${addr.slice(0, 6)}…${addr.slice(-4)}`;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
4
|
return (
|
|
32
5
|
<nav className="navbar">
|
|
33
6
|
<div className="navbar-brand">
|
|
34
7
|
<span className="navbar-logo">🔗</span>
|
|
35
8
|
<span className="navbar-title">Africa's Blockchain Club</span>
|
|
36
9
|
</div>
|
|
37
|
-
|
|
38
|
-
<div className="navbar-actions">
|
|
39
|
-
{account ? (
|
|
40
|
-
<div className="wallet-badge">
|
|
41
|
-
<span className="wallet-dot" />
|
|
42
|
-
<span className="wallet-address">{truncate(account)}</span>
|
|
43
|
-
</div>
|
|
44
|
-
) : (
|
|
45
|
-
<button
|
|
46
|
-
className="connect-btn"
|
|
47
|
-
onClick={connectWallet}
|
|
48
|
-
disabled={connecting}
|
|
49
|
-
>
|
|
50
|
-
{connecting ? 'Connecting…' : 'Connect Wallet'}
|
|
51
|
-
</button>
|
|
52
|
-
)}
|
|
53
|
-
</div>
|
|
54
10
|
</nav>
|
|
55
11
|
);
|
|
56
12
|
}
|