Skip to content

Commit 9fb2316

Browse files
committed
Fixes
1 parent abfc99c commit 9fb2316

File tree

17 files changed

+499
-132
lines changed

17 files changed

+499
-132
lines changed

arch-indexer-microservices/api-server/src/api/handlers.rs

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use crate::{db::models::{Block, Transaction, BlockWithTransactions}, indexer::Bl
2121
use crate::arch_rpc::ArchRpcClient;
2222
use std::collections::HashSet;
2323
use axum::http::StatusCode as AxStatusCode;
24-
use sqlx::Row as _;
2524

2625
#[derive(serde::Serialize)]
2726
pub struct TokenListRow {
@@ -322,45 +321,6 @@ pub async fn get_token_detail(
322321
Ok(Json(json!({"error":"not_found"})))
323322
}
324323

325-
// Backfill token_metadata for existing mints by scanning token_mints and decoding on-chain metadata PDAs when available.
326-
// For now, we opportunistically copy name/symbol/uri from any existing token_metadata rows or leave nulls if not present.
327-
pub async fn backfill_token_metadata(
328-
State(pool): State<Arc<PgPool>>,
329-
) -> Result<Json<serde_json::Value>, ApiError> {
330-
// If tables are missing, exit gracefully
331-
let has_mints: bool = sqlx::query_scalar("SELECT to_regclass('public.token_mints') IS NOT NULL")
332-
.fetch_one(&*pool).await.unwrap_or(false);
333-
let has_metadata: bool = sqlx::query_scalar("SELECT to_regclass('public.token_metadata') IS NOT NULL")
334-
.fetch_one(&*pool).await.unwrap_or(false);
335-
if !has_mints || !has_metadata {
336-
return Ok(Json(json!({"updated": 0, "skipped": true})));
337-
}
338-
339-
// Upsert metadata rows for all known mints with placeholders where needed
340-
let mints: Vec<(String, Option<String>)> = sqlx::query(
341-
r#"
342-
SELECT tm.mint_address, md.mint_address AS has_md
343-
FROM token_mints tm
344-
LEFT JOIN token_metadata md ON md.mint_address = tm.mint_address
345-
"#
346-
)
347-
.fetch_all(&*pool)
348-
.await
349-
.map(|rows| rows.into_iter().map(|r| (r.get::<String, _>("mint_address"), r.try_get::<Option<String>, _>("has_md").ok().flatten())).collect())
350-
.unwrap_or_default();
351-
352-
let mut updated: i64 = 0;
353-
for (mint, has_md) in mints {
354-
if has_md.is_some() { continue; }
355-
let _ = sqlx::query("SELECT upsert_token_metadata($1, COALESCE((SELECT program_id FROM token_mints WHERE mint_address = $1), ''), NULL, NULL, NULL, NULL)")
356-
.bind(&mint)
357-
.execute(&*pool)
358-
.await;
359-
updated += 1;
360-
}
361-
Ok(Json(json!({"updated": updated})))
362-
}
363-
364324
fn key_to_bytes(v: &serde_json::Value) -> Option<Vec<u8>> {
365325
if let Some(arr) = v.as_array() {
366326
return Some(arr.iter().filter_map(|x| x.as_i64().map(|n| n as u8)).collect());
@@ -484,6 +444,7 @@ fn fallback_program_name_from_b58(b58: &str) -> Option<String> {
484444
"ComputeBudget111111111111111111111111111111" => Some("Compute Budget Program".to_string()),
485445
"AplToken111111111111111111111111" => Some("APL Token Program".to_string()),
486446
"AssociatedTokenAccount1111111111" => Some("APL Associated Token Account Program".to_string()),
447+
"ArchTokenMetadata111111111111111" => Some("APL Token Metadata Program".to_string()),
487448

488449
// Accept legacy/base58 forms for friendly label
489450
"7ZMyUmgbNckx7G5BCrdmX2XUasjDAk5uhcMpDbUDxHQ3" => Some("APL Token".to_string()),
@@ -512,6 +473,7 @@ fn fallback_program_name_from_hex(hex_id: &str) -> Option<String> {
512473
"ComputeBudget111111111111111111111111111111" => return Some("Compute Budget Program".to_string()),
513474
"AplToken111111111111111111111111" => return Some("APL Token Program".to_string()),
514475
"AssociatedTokenAccount1111111111" => return Some("APL Associated Token Account Program".to_string()),
476+
"ArchTokenMetadata111111111111111" => return Some("APL Token Metadata Program".to_string()),
515477
_ => {}
516478
}
517479
}

arch-indexer-microservices/api-server/src/api/program_ids.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub const COMPUTE_BUDGET: &str = "ComputeBudget111111111111111111111111111111";
1111
// Arch token programs (fixed canonical IDs)
1212
pub const APL_TOKEN_PROGRAM: &str = "AplToken111111111111111111111111";
1313
pub const APL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM: &str = "AssociatedTokenAccount1111111111";
14+
pub const APL_TOKEN_METADATA_PROGRAM: &str = "ArchTokenMetadata111111111111111";
1415

1516
// Legacy Solana program IDs we may still see in historical/interop data
1617
pub const SOL_LOADER: &str = "Loader1111111111111111111111111111111";
@@ -50,7 +51,26 @@ pub fn get_program_name(base58_id: &str) -> Option<&'static str> {
5051
APL_TOKEN_PROGRAM_BASE58 => Some("APL Token Program"),
5152
APL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_BASE58 => Some("APL Associated Token Account Program"),
5253

53-
_ => None,
54+
_ => {
55+
// Fallback: some Arch program IDs are ASCII labels padded to 32 bytes and then base58-encoded.
56+
// Decode and recognize those labels here without having to precompute base58 constants.
57+
if let Ok(bytes) = bs58::decode(base58_id).into_vec() {
58+
if let Ok(label) = std::str::from_utf8(&bytes) {
59+
return match label {
60+
"VoteProgram111111111111111111111" => Some("Vote Program"),
61+
"StakeProgram11111111111111111111" => Some("Stake Program"),
62+
"BpfLoader11111111111111111111111" => Some("BPF Loader"),
63+
"NativeLoader11111111111111111111" => Some("Native Loader"),
64+
"ComputeBudget111111111111111111111111111111" => Some("Compute Budget Program"),
65+
"AplToken111111111111111111111111" => Some("APL Token Program"),
66+
"AssociatedTokenAccount1111111111" => Some("APL Associated Token Account Program"),
67+
"ArchTokenMetadata111111111111111" => Some("APL Token Metadata Program"),
68+
_ => None,
69+
};
70+
}
71+
}
72+
None
73+
},
5474
}
5575
}
5676

arch-indexer-microservices/api-server/src/api/routes.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ pub fn create_router(pool: Arc<PgPool>) -> Router {
6868
"/api/tokens/leaderboard",
6969
get(handlers::get_token_leaderboard),
7070
)
71-
.route("/api/tokens/backfill-metadata", get(handlers::backfill_token_metadata))
7271
.route("/api/tokens", get(handlers::list_tokens))
7372
.route("/api/tokens/:mint", get(handlers::get_token_detail))
7473
// Accounts

arch-indexer-microservices/db-init/22_canonical_program_id.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ BEGIN
4242
RETURN normalize_program_id('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
4343
ELSIF label LIKE 'apl-token%' OR label LIKE 'apl_token%' THEN
4444
RETURN normalize_program_id('AplToken111111111111111111111111');
45+
ELSIF label LIKE 'apl-token-metadata%' OR label LIKE 'apl_token_metadata%' OR label LIKE 'arch-token-metadata%' OR label LIKE 'arch_token_metadata%' THEN
46+
RETURN normalize_program_id('ArchTokenMetadata111111111111111');
4547
ELSIF label LIKE 'spl-associated-token-account%' OR label LIKE 'spl_associated_token_account%' THEN
4648
RETURN normalize_program_id('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL');
4749
ELSIF label LIKE 'apl-associated-token-account%' OR label LIKE 'apl_associated_token_account%' THEN

arch-indexer-microservices/frontend/pages/programs/[id].tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const MAPPED: Record<string, string> = {
2424
// base58 -> mapped label used in routes
2525
'AplToken111111111111111111111111': 'AplToken111111111111111111111111',
2626
'AplAssociatedTokenAccount11111111111111111': 'AplAssociatedTokenAccount11111111111111111',
27+
'ArchTokenMetadata111111111111111': 'ArchTokenMetadata111111111111111',
2728
};
2829

2930
export default function ProgramDetailPage() {

0 commit comments

Comments
 (0)