Fix: relay tx receipts through the server (CSP blocked direct RPC polls)
After a wallet sent a transaction, waitTx polled the public RPC straight from the browser, which connect-src 'self' blocks (Firefox NetworkError, reported by Marty on Activate; the activation itself landed on-chain). New /api/tx/<hash> relays eth_getTransactionReceipt via the server's RPC pool, so the browser only ever talks to us and the mainnet flip needs no CSP changes. Assets v=20260905a. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -49,11 +49,10 @@ window.IAPWallet = (function () {
|
|||||||
return eth().request({ method: 'eth_sendTransaction', params: [tx] });
|
return eth().request({ method: 'eth_sendTransaction', params: [tx] });
|
||||||
}
|
}
|
||||||
async function waitTx(hash) {
|
async function waitTx(hash) {
|
||||||
const c = await IAP.getConfig();
|
// poll our own server (CSP-friendly); it relays the receipt from the RPC
|
||||||
for (let i = 0; i < 60; i++) {
|
for (let i = 0; i < 60; i++) {
|
||||||
const r = await (await fetch(c.rpc, { method: 'POST', headers: { 'Content-Type': 'application/json' },
|
const r = await (await fetch('/api/tx/' + hash)).json();
|
||||||
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_getTransactionReceipt', params: [hash] }) })).json();
|
if (r.found) return { status: r.status, blockNumber: r.blockNumber };
|
||||||
if (r.result) return r.result;
|
|
||||||
await new Promise(res => setTimeout(res, 2500));
|
await new Promise(res => setTimeout(res, 2500));
|
||||||
}
|
}
|
||||||
throw new Error('Timed out waiting for the transaction. Check the explorer.');
|
throw new Error('Timed out waiting for the transaction. Check the explorer.');
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<title>The contract | InstantAdPay</title>
|
<title>The contract | InstantAdPay</title>
|
||||||
<meta name="description" content="Plain-language review of the InstantAdPay settlement contract: what it does, what nobody can change, what the operator can and cannot touch, and how to verify all of it yourself.">
|
<meta name="description" content="Plain-language review of the InstantAdPay settlement contract: what it does, what nobody can change, what the operator can and cannot touch, and how to verify all of it yourself.">
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260904r">
|
<link rel="stylesheet" href="/assets/site.css?v=20260905a">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
@@ -129,8 +129,8 @@
|
|||||||
<div class="small">Advertising services with a performance referral program. Not an investment product; no income guarantees. Crypto transactions are irreversible. Never spend what you cannot afford.</div>
|
<div class="small">Advertising services with a performance referral program. Not an investment product; no income guarantees. Crypto transactions are irreversible. Never spend what you cannot afford.</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
<script src="/assets/common.js?v=20260904r"></script>
|
<script src="/assets/common.js?v=20260905a"></script>
|
||||||
<script src="/assets/contract.js?v=20260904r"></script>
|
<script src="/assets/contract.js?v=20260905a"></script>
|
||||||
<script src="/assets/chat.js?v=20260904r"></script>
|
<script src="/assets/chat.js?v=20260905a"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+5
-5
@@ -5,7 +5,7 @@
|
|||||||
<title>InstantAdPay: advertise and earn, locked in code</title>
|
<title>InstantAdPay: advertise and earn, locked in code</title>
|
||||||
<meta name="description" content="Real ad packages with instant on-chain settlement. Every purchase pays the sponsor line in the same transaction, verifiable by anyone on the live ledger.">
|
<meta name="description" content="Real ad packages with instant on-chain settlement. Every purchase pays the sponsor line in the same transaction, verifiable by anyone on the live ledger.">
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260904r">
|
<link rel="stylesheet" href="/assets/site.css?v=20260905a">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
@@ -398,9 +398,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script src="/assets/common.js?v=20260904r"></script>
|
<script src="/assets/common.js?v=20260905a"></script>
|
||||||
<script src="/assets/wallet.js?v=20260904r"></script>
|
<script src="/assets/wallet.js?v=20260905a"></script>
|
||||||
<script src="/assets/home.js?v=20260904r"></script>
|
<script src="/assets/home.js?v=20260905a"></script>
|
||||||
<script src="/assets/chat.js?v=20260904r"></script>
|
<script src="/assets/chat.js?v=20260905a"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+4
-4
@@ -5,7 +5,7 @@
|
|||||||
<title>Live ledger | InstantAdPay</title>
|
<title>Live ledger | InstantAdPay</title>
|
||||||
<meta name="description" content="Every purchase, payout, and pass-up on InstantAdPay, streamed straight from the blockchain with a verify link on every line.">
|
<meta name="description" content="Every purchase, payout, and pass-up on InstantAdPay, streamed straight from the blockchain with a verify link on every line.">
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260904r">
|
<link rel="stylesheet" href="/assets/site.css?v=20260905a">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
@@ -25,8 +25,8 @@
|
|||||||
<div>InstantAdPay · <a href="/">how it works</a> · <a id="contractLink" href="#" target="_blank" rel="noopener">contract source ↗</a></div>
|
<div>InstantAdPay · <a href="/">how it works</a> · <a id="contractLink" href="#" target="_blank" rel="noopener">contract source ↗</a></div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
<script src="/assets/common.js?v=20260904r"></script>
|
<script src="/assets/common.js?v=20260905a"></script>
|
||||||
<script src="/assets/ledger.js?v=20260904r"></script>
|
<script src="/assets/ledger.js?v=20260905a"></script>
|
||||||
<script src="/assets/chat.js?v=20260904r"></script>
|
<script src="/assets/chat.js?v=20260905a"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+5
-5
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>Member area | InstantAdPay</title>
|
<title>Member area | InstantAdPay</title>
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260904r">
|
<link rel="stylesheet" href="/assets/site.css?v=20260905a">
|
||||||
</head>
|
</head>
|
||||||
<body class="bo-body">
|
<body class="bo-body">
|
||||||
|
|
||||||
@@ -208,9 +208,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/assets/common.js?v=20260904r"></script>
|
<script src="/assets/common.js?v=20260905a"></script>
|
||||||
<script src="/assets/wallet.js?v=20260904r"></script>
|
<script src="/assets/wallet.js?v=20260905a"></script>
|
||||||
<script src="/assets/my.js?v=20260904r"></script>
|
<script src="/assets/my.js?v=20260905a"></script>
|
||||||
<script src="/assets/chat.js?v=20260904r"></script>
|
<script src="/assets/chat.js?v=20260905a"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -173,6 +173,14 @@ const server = http.createServer(async (req, res) => {
|
|||||||
req.on('close', () => feedClients.delete(res));
|
req.on('close', () => feedClients.delete(res));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
m = /^\/api\/tx\/(0x[0-9a-fA-F]{64})$/.exec(p);
|
||||||
|
if (m && req.method === 'GET') {
|
||||||
|
// receipt relay so the browser never talks to the RPC directly (CSP stays 'self')
|
||||||
|
try {
|
||||||
|
const r = await chain.rpc('eth_getTransactionReceipt', [m[1]]);
|
||||||
|
return json(res, 200, r ? { found: true, status: r.status, blockNumber: r.blockNumber } : { found: false });
|
||||||
|
} catch (e) { return json(res, 200, { found: false, rpcError: true }); }
|
||||||
|
}
|
||||||
if (p === '/api/sponsor' && req.method === 'GET') {
|
if (p === '/api/sponsor' && req.method === 'GET') {
|
||||||
const tok = parseCookies(req)['iap.sponsor'] || '';
|
const tok = parseCookies(req)['iap.sponsor'] || '';
|
||||||
const sponsorId = await resolveSponsorToken(tok);
|
const sponsorId = await resolveSponsorToken(tok);
|
||||||
|
|||||||
Reference in New Issue
Block a user