Repository navigation
Expand file tree
/
Copy pathdeploy-v2.html
More file actions
102 lines (94 loc) · 5.57 KB
/
Copy pathdeploy-v2.html
File metadata and controls
102 lines (94 loc) · 5.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex">
<title>Deploy TBlock hook V2</title>
<style>
:root{--fond:#04090c;--carte:#0b1c22;--ligne:#16323c;--texte:#f2fbff;--doux:#9cc3cf;--accent:#35d3f0;--ok:#3ddc97;--ko:#ff6b6b}
body{margin:0;background:var(--fond);color:var(--texte);font:15px/1.5 system-ui,-apple-system,Segoe UI,sans-serif}
main{max-width:640px;margin:0 auto;padding:24px 16px}
h1{font-size:20px;margin:0 0 6px}
.carte{background:var(--carte);border:1px solid var(--ligne);border-radius:14px;padding:16px;margin:14px 0}
.ligne{display:flex;gap:10px;align-items:baseline;margin:6px 0}
.ligne b{min-width:18px}
code{font-size:12.5px;word-break:break-all;color:var(--doux)}
button{font:inherit;font-weight:700;padding:12px 18px;border-radius:12px;border:0;cursor:pointer;background:var(--accent);color:#012}
button[disabled]{opacity:.45;cursor:not-allowed}
.ok{color:var(--ok)} .ko{color:var(--ko)} .doux{color:var(--doux)}
</style>
</head>
<body>
<main>
<h1>Deploy the TBlock hook V2</h1>
<p class="doux">One transaction, signed by <b>your</b> wallet. This page never sees a key. The contract has no owner and
lands at the same address whoever sends it — the address depends only on its code.</p>
<div class="carte">
<div class="ligne"><b id="c1">…</b><span>Base mainnet reachable, hook address still empty</span></div>
<div class="ligne"><b id="c2">…</b><span>Dry run on Base returns the expected hook address</span></div>
<div class="ligne"><b id="c3">…</b><span>Wallet connected on Base</span></div>
<p class="doux" style="margin:10px 0 0">Expected hook: <code id="attendu"></code></p>
</div>
<div class="carte">
<button id="connecter" type="button">Connect wallet</button>
<button id="deployer" type="button" disabled>Deploy — sign in your wallet</button>
<p id="etat" class="doux" style="margin:12px 0 0"></p>
</div>
</main>
<script type="module">
/* ⛔ PAGE DE DEPLOIEMENT DU HOOK V2 (2026-09-19). Phil ne pouvait pas importer sa cle dans cast (copier-coller refuse).
* Le contrat est deploye par le deployeur CREATE2 standard : l adresse ne depend QUE du code (aucun proprietaire), donc
* n importe quel wallet peut l envoyer. La page VERIFIE avant d autoriser la signature :
* 1. aucun code a l adresse attendue ; 2. un eth_call de la transaction rend exactement cette adresse ;
* 3. wallet sur Base. Elle ne touche a aucune cle ; c est le wallet de l utilisateur qui signe. */
import { envoyerDepuisWallet } from './envoi.js';
const $ = (s) => document.querySelector(s);
const RPC = 'https://mainnet.base.org';
const rpc = async (method, params) => {
const r = await fetch(RPC, { method: 'POST', headers: { 'content-type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }) }).then((x) => x.json());
if (r.error) throw new Error(r.error.message || 'rpc error');
return r.result;
};
const marque = (id, ok, texte) => { const e = $(id); e.textContent = ok ? '✓' : '✗'; e.className = ok ? 'ok' : 'ko'; if (texte) e.title = texte; };
let tx = null, compte = null, pret = { vide: false, simu: false };
async function verifier() {
tx = await fetch('./deploy-v2.json', { cache: 'no-store' }).then((r) => r.json());
$('#attendu').textContent = tx.hook;
const code = await rpc('eth_getCode', [tx.hook, 'latest']);
pret.vide = code === '0x';
marque('#c1', pret.vide);
if (!pret.vide) { $('#etat').innerHTML = '<span class="ok">The hook V2 is already deployed at this address. Nothing to do.</span>'; return; }
const r = await rpc('eth_call', [{ to: tx.deployeur, data: tx.data, gas: '0x4c4b40' }, 'latest']);
pret.simu = ('0x' + String(r).slice(-40)).toLowerCase() === tx.hook.toLowerCase();
marque('#c2', pret.simu);
majBouton();
}
function majBouton() { $('#deployer').disabled = !(pret.vide && pret.simu && compte); }
$('#connecter').addEventListener('click', async () => {
if (!window.ethereum) { $('#etat').textContent = 'No wallet found in this browser.'; return; }
try {
const comptes = await window.ethereum.request({ method: 'eth_requestAccounts' });
compte = comptes && comptes[0];
try { await window.ethereum.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: '0x2105' }] }); } catch (_) {}
const chaine = await window.ethereum.request({ method: 'eth_chainId' });
marque('#c3', !!compte && Number(chaine) === 8453);
if (Number(chaine) !== 8453) compte = null;
} catch (e) { $('#etat').textContent = 'Connection refused: ' + (e.message || e); }
majBouton();
});
$('#deployer').addEventListener('click', async () => {
$('#deployer').disabled = true;
$('#etat').textContent = 'Opening your wallet — check it shows Base and a contract call, then sign.';
const r = await envoyerDepuisWallet({ eth: window.ethereum, rpc, chaineAttendue: 8453, compte, to: tx.deployeur, data: tx.data, value: '0x0' });
if (r.etat !== 'CONFIRME') { $('#etat').innerHTML = '<span class="ko">Not done: ' + (r.pourquoi || r.etat) + '</span>'; majBouton(); return; }
const code = await rpc('eth_getCode', [tx.hook, 'latest']);
$('#etat').innerHTML = code !== '0x'
? '<span class="ok">Deployed. Hook V2 is live at ' + tx.hook + '.</span> Transaction: <code>' + r.hash + '</code>'
: '<span class="ko">Transaction confirmed but no code at the address yet — send me the hash: </span><code>' + r.hash + '</code>';
});
verifier().catch((e) => { $('#etat').textContent = 'Could not read Base right now: ' + (e.message || e); });
</script>
</body>
</html>