Ad engine v1: banner/text/login campaigns against on-chain credits
Spec 8b types 1-3. Spend accrues per campaign in batches; burns queue for the engine signer (admin runs consume() on-chain, /api/admin/burns). Rates are volume config (adrates.json), rehearsal placeholders until Marty sets the real card. Public slots serve on the ledger page; campaign manager in the members area. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+18
-1
@@ -84,5 +84,22 @@ window.IAP = (function () {
|
||||
+ '<span class="tx"><a target="_blank" rel="noopener" href="' + c.explorer + '/tx/' + ev.tx + '">verify ↗</a></span>';
|
||||
return div;
|
||||
}
|
||||
return { getConfig, fmtPol, fmtUsd, status, renderNav, refreshNavWallet, describeEvent, feedRow, $ };
|
||||
// Render one served ad into #<elId>. Silent if no inventory.
|
||||
async function adSlot(type, elId) {
|
||||
try {
|
||||
const { ad } = await (await fetch('/api/ads/slot?type=' + type)).json();
|
||||
const el = $(elId);
|
||||
if (!ad || !el) return;
|
||||
if (ad.imageUrl) {
|
||||
el.innerHTML = '<a href="' + ad.targetUrl + '" target="_blank" rel="noopener nofollow">'
|
||||
+ '<img src="' + ad.imageUrl + '" alt="advertisement" style="max-width:100%;border-radius:8px"></a>'
|
||||
+ '<div class="small muted">member ad</div>';
|
||||
} else {
|
||||
el.innerHTML = '<a href="' + ad.targetUrl + '" target="_blank" rel="noopener nofollow"><b>' + ad.title + '</b>'
|
||||
+ (ad.body ? ' · ' + ad.body : '') + '</a> <span class="small muted">member ad</span>';
|
||||
}
|
||||
el.hidden = false;
|
||||
} catch (e) {}
|
||||
}
|
||||
return { getConfig, fmtPol, fmtUsd, status, renderNav, refreshNavWallet, describeEvent, feedRow, adSlot, $ };
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user