Skip to content

Commit 61f577d

Browse files
web3blindclaude
andcommitted
Discover other players on fresh device for chronicle/blessing list
Three changes to fix empty player list on new devices: 1. state-engine: remember target/to accounts from guild invites, item transfers, etc. — not just the action sender 2. chronicle: collect accounts from all guild rosters and guild listings, not just the current user's guild 3. app: after recovering user's own chain, traverse VM chains of discovered accounts to rebuild guild rosters and social state Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0e4aee1 commit 61f577d

3 files changed

Lines changed: 116 additions & 7 deletions

File tree

app/js/engine/state-engine.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,12 @@ var StateEngine = (function() {
346346
break;
347347
}
348348

349-
// Add to recent actions
349+
// Add to recent actions — remember sender and any target accounts
350350
_rememberAccount(sender);
351+
if (action.data) {
352+
if (action.data.target) _rememberAccount(action.data.target);
353+
if (action.data.to) _rememberAccount(action.data.to);
354+
}
351355

352356
worldState.recentActions.push({
353357
type: action.type,

app/js/ui/app.js

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -336,12 +336,14 @@ var App = (function() {
336336

337337
function processNext() {
338338
if (idx >= historicalBlocks.length) {
339-
// Save checkpoint after full recovery
340-
StateEngine.saveCheckpoint(function() {
341-
console.log('App: Chain history recovery complete,', historicalBlocks.length, 'blocks processed');
342-
_chainRecoveryDone = true;
343-
_chainRecoveryBusy = false;
344-
callback();
339+
// After user's own chain is recovered, discover other players
340+
_recoverKnownAccountsChains(recentWindowStart, function() {
341+
StateEngine.saveCheckpoint(function() {
342+
console.log('App: Chain history recovery complete,', historicalBlocks.length, 'blocks processed');
343+
_chainRecoveryDone = true;
344+
_chainRecoveryBusy = false;
345+
callback();
346+
});
345347
});
346348
return;
347349
}
@@ -371,6 +373,91 @@ var App = (function() {
371373
});
372374
}
373375

376+
/**
377+
* After recovering the current user's chain, traverse VM chains of
378+
* other accounts discovered during replay (guild invite targets,
379+
* item transfer recipients, etc.) to rebuild guild rosters,
380+
* marketplace listings, and the social feed account list.
381+
* Processes up to 100 actions per account, only blocks older than
382+
* the 24h window (to avoid overlap with normal polling).
383+
*/
384+
function _recoverKnownAccountsChains(recentWindowStart, callback) {
385+
var state = StateEngine.getState();
386+
var user = VizAccount.getCurrentUser();
387+
var others = [];
388+
389+
// Collect accounts discovered during user's chain replay
390+
if (state.social && state.social.knownAccounts) {
391+
for (var i = 0; i < state.social.knownAccounts.length; i++) {
392+
var acct = state.social.knownAccounts[i];
393+
if (acct && acct !== user) others.push(acct);
394+
}
395+
}
396+
397+
if (others.length === 0) {
398+
console.log('App: No other accounts discovered, skipping secondary recovery');
399+
callback();
400+
return;
401+
}
402+
403+
console.log('App: Recovering chains for', others.length, 'discovered accounts');
404+
var acctIdx = 0;
405+
406+
function nextAccount() {
407+
if (acctIdx >= others.length) {
408+
console.log('App: Secondary account recovery complete');
409+
callback();
410+
return;
411+
}
412+
413+
var account = others[acctIdx++];
414+
_updateSyncStatus(80 + (acctIdx / others.length) * 15, true); // 80-95%
415+
416+
VMProtocol.traverseChain(account, 100, function(err, actions) {
417+
if (err || !actions || actions.length === 0) {
418+
nextAccount();
419+
return;
420+
}
421+
422+
// Collect historical blocks for this account
423+
var blocks = [];
424+
for (var i = 0; i < actions.length; i++) {
425+
if (actions[i].blockNum < recentWindowStart) {
426+
blocks.push(actions[i].blockNum);
427+
}
428+
}
429+
430+
if (blocks.length === 0) {
431+
nextAccount();
432+
return;
433+
}
434+
435+
blocks.sort(function(a, b) { return a - b; });
436+
var bIdx = 0;
437+
438+
function nextBlock() {
439+
if (bIdx >= blocks.length) {
440+
nextAccount();
441+
return;
442+
}
443+
444+
viz.api.getBlock(blocks[bIdx], function(bErr, block) {
445+
if (!bErr && block) {
446+
var processed = BlockProcessor.processBlock(block, blocks[bIdx]);
447+
StateEngine.processBlock(processed);
448+
}
449+
bIdx++;
450+
setTimeout(nextBlock, 10);
451+
});
452+
}
453+
454+
nextBlock();
455+
});
456+
}
457+
458+
nextAccount();
459+
}
460+
374461
function _startBlockPolling() {
375462
if (_pollTimer) return;
376463

app/js/ui/screens/chronicle.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,24 @@ var ChronicleScreen = (function() {
163163
}
164164
}
165165

166+
// Discover accounts from guild listings (visible even on fresh devices)
167+
if (state && state.guildListings) {
168+
for (var gl = 0; gl < state.guildListings.length; gl++) {
169+
if (state.guildListings[gl].sender) add(state.guildListings[gl].sender);
170+
}
171+
}
172+
173+
// Discover accounts from all known guilds' member rosters
174+
if (state && state.guilds) {
175+
for (var gid in state.guilds) {
176+
if (state.guilds.hasOwnProperty(gid) && state.guilds[gid].members) {
177+
for (var gm in state.guilds[gid].members) {
178+
if (state.guilds[gid].members.hasOwnProperty(gm)) add(gm);
179+
}
180+
}
181+
}
182+
}
183+
166184
return accounts;
167185
}
168186

0 commit comments

Comments
 (0)