Skip to content

Commit a6cfb53

Browse files
committed
fix: bridge off-chain engagement votes to frontend API queries
Frontend reads from wunderland_sol_posts (on-chain index) but agent browsing votes update wunderland_posts (off-chain). Added LEFT JOIN to merge off-chain engagement counts (likes/downvotes) into all 4 post query paths (getPosts hot/normal/top/controversial, getPostByPda, getThread) using max(COALESCE(wp.likes,0), p.upvotes) to show the higher of off-chain or on-chain counts without double-counting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 639f3ca commit a6cfb53

1 file changed

Lines changed: 20 additions & 12 deletions

File tree

‎backend/src/modules/wunderland/wunderland-sol/wunderland-sol-social.service.ts‎

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,8 @@ export class WunderlandSolSocialService {
468468
p.post_index,
469469
p.content_hash_hex,
470470
p.manifest_hash_hex,
471-
p.upvotes,
472-
p.downvotes,
471+
max(COALESCE(wp.likes, 0), p.upvotes) as upvotes,
472+
max(COALESCE(wp.downvotes, 0), p.downvotes) as downvotes,
473473
p.comment_count,
474474
p.timestamp_sec,
475475
p.created_slot,
@@ -480,6 +480,7 @@ export class WunderlandSolSocialService {
480480
a.traits_json as agent_traits_json
481481
FROM wunderland_sol_posts p
482482
LEFT JOIN wunderland_sol_agents a ON a.agent_pda = p.agent_pda
483+
LEFT JOIN wunderland_posts wp ON wp.sol_post_pda = p.post_pda
483484
${whereSql}
484485
ORDER BY COALESCE(p.created_slot, 0) DESC, p.timestamp_sec DESC
485486
LIMIT ?
@@ -502,15 +503,19 @@ export class WunderlandSolSocialService {
502503
return { posts, total: scored.length, source: 'index' };
503504
}
504505

506+
// Merged vote expressions: prefer off-chain engagement counts over on-chain when available.
507+
const mUp = 'max(COALESCE(wp.likes, 0), p.upvotes)';
508+
const mDown = 'max(COALESCE(wp.downvotes, 0), p.downvotes)';
509+
505510
const orderSql = (() => {
506511
if (sort === 'top') {
507-
return 'ORDER BY (p.upvotes - p.downvotes) DESC, COALESCE(p.created_slot, 0) DESC, p.timestamp_sec DESC';
512+
return `ORDER BY (${mUp} - ${mDown}) DESC, COALESCE(p.created_slot, 0) DESC, p.timestamp_sec DESC`;
508513
}
509514
if (sort === 'controversial') {
510-
const minVotes = '(CASE WHEN p.upvotes < p.downvotes THEN p.upvotes ELSE p.downvotes END)';
511-
const maxVotes = '(CASE WHEN p.upvotes > p.downvotes THEN p.upvotes ELSE p.downvotes END)';
515+
const minVotes = `(CASE WHEN ${mUp} < ${mDown} THEN ${mUp} ELSE ${mDown} END)`;
516+
const maxVotes = `(CASE WHEN ${mUp} > ${mDown} THEN ${mUp} ELSE ${mDown} END)`;
512517
const denom = `(CASE WHEN ${maxVotes} > 0 THEN ${maxVotes} ELSE 1 END)`;
513-
const score = `((${minVotes} * 1.0) / ${denom}) * (p.upvotes + p.downvotes)`;
518+
const score = `((${minVotes} * 1.0) / ${denom}) * (${mUp} + ${mDown})`;
514519
return `ORDER BY ${score} DESC, COALESCE(p.created_slot, 0) DESC, p.timestamp_sec DESC`;
515520
}
516521
// default: new
@@ -528,8 +533,8 @@ export class WunderlandSolSocialService {
528533
p.post_index,
529534
p.content_hash_hex,
530535
p.manifest_hash_hex,
531-
p.upvotes,
532-
p.downvotes,
536+
${mUp} as upvotes,
537+
${mDown} as downvotes,
533538
p.comment_count,
534539
p.timestamp_sec,
535540
p.created_slot,
@@ -540,6 +545,7 @@ export class WunderlandSolSocialService {
540545
a.traits_json as agent_traits_json
541546
FROM wunderland_sol_posts p
542547
LEFT JOIN wunderland_sol_agents a ON a.agent_pda = p.agent_pda
548+
LEFT JOIN wunderland_posts wp ON wp.sol_post_pda = p.post_pda
543549
${whereSql}
544550
${orderSql}
545551
LIMIT ? OFFSET ?
@@ -567,8 +573,8 @@ export class WunderlandSolSocialService {
567573
p.post_index,
568574
p.content_hash_hex,
569575
p.manifest_hash_hex,
570-
p.upvotes,
571-
p.downvotes,
576+
max(COALESCE(wp.likes, 0), p.upvotes) as upvotes,
577+
max(COALESCE(wp.downvotes, 0), p.downvotes) as downvotes,
572578
p.comment_count,
573579
p.timestamp_sec,
574580
p.created_slot,
@@ -579,6 +585,7 @@ export class WunderlandSolSocialService {
579585
a.traits_json as agent_traits_json
580586
FROM wunderland_sol_posts p
581587
LEFT JOIN wunderland_sol_agents a ON a.agent_pda = p.agent_pda
588+
LEFT JOIN wunderland_posts wp ON wp.sol_post_pda = p.post_pda
582589
WHERE p.post_pda = ?
583590
LIMIT 1
584591
`,
@@ -641,8 +648,8 @@ export class WunderlandSolSocialService {
641648
p.post_index,
642649
p.content_hash_hex,
643650
p.manifest_hash_hex,
644-
p.upvotes,
645-
p.downvotes,
651+
max(COALESCE(wp.likes, 0), p.upvotes) as upvotes,
652+
max(COALESCE(wp.downvotes, 0), p.downvotes) as downvotes,
646653
p.comment_count,
647654
p.timestamp_sec,
648655
p.created_slot,
@@ -653,6 +660,7 @@ export class WunderlandSolSocialService {
653660
a.traits_json as agent_traits_json
654661
FROM wunderland_sol_posts p
655662
LEFT JOIN wunderland_sol_agents a ON a.agent_pda = p.agent_pda
663+
LEFT JOIN wunderland_posts wp ON wp.sol_post_pda = p.post_pda
656664
WHERE p.kind = 'comment'
657665
AND p.reply_to IN (${placeholders})
658666
`,

0 commit comments

Comments
 (0)