1// Referral capture: remember who sent you here until there is a player to 2// credit. 3// 4// The gap this closes is a timing one. A referral code arrives on a URL â a 5// share card link, a Telegram deep link â but the person it belongs to does 6// not exist as a player yet: they have no wallet session, no Telegram 7// identity, nothing the server can attach a credit to. That only happens later, 8// on their first recorded run. So the code has to survive the walk from 9// landing page to first game over. 10// 11// Stored, not sent immediately. Sending it on arrival would mean crediting a 12// visit, and a visit is worth nothing â the server credits on a first PLAY, 13// which is the first moment somebody actually turned up. 14(() => { 15 const KEY = 'webcade-ref'; 16 17 // Same closed alphabet the codes are minted from. Anything else is either a 18 // typo or somebody poking at the query string, and neither should be stored. 19 const clean = v => String(v || '').toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 5); 20 21 function read() { 22 try { return clean(localStorage.getItem(KEY)); } catch (_) { return ''; } 23 } 24 25 function remember(code) { 26 const c = clean(code); 27 if (c.length !== 5) return; 28 try { 29 // First one wins. Someone who arrives on A's link, wanders off and comes 30 // back on B's was recruited by A â letting the newer code overwrite would 31 // hand every recruit to whoever shared last. 32 if (!read()) localStorage.setItem(KEY, c); 33 } catch (_) { /* private mode: the referral is lost, the game is not */ } 34 } 35 36 // ?ref=CODE on any page, and Telegram's start_param, which is how a deep 37 // link carries anything at all. A duel id also arrives that way, so only a 38 // ref-shaped value is taken. 39 try { 40 const q = new URLSearchParams(location.search).get('ref'); 41 if (q) remember(q); 42 } catch (_) {} 43 try { 44 const sp = (window.ARCADE_TG || {}).startParam; 45 if (sp && /^ref[-_]?[A-Za-z0-9]{5}$/.test(String(sp))) remember(String(sp).slice(-5)); 46 } catch (_) {} 47 48 window.ARCADE_REF = { 49 get code() { return read(); }, 50 remember, 51 // Folded into a request body by whoever is about to submit a run. Empty 52 // when there is nothing to say, so it never adds a key for no reason. 53 tag(body) { 54 const c = read(); 55 return c ? { ...body, ref: c } : body; 56 }, 57 // Once credited the code has done its job; keeping it would re-send it on 58 // every future run for no purpose. 59 clear() { try { localStorage.removeItem(KEY); } catch (_) {} }, 60 }; 61})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.