v0.1.0-pre.062
This commit is contained in:
@@ -1,30 +1,94 @@
|
||||
WITH failed_transfer AS (
|
||||
SELECT
|
||||
core.signature,
|
||||
core.slot,
|
||||
core.instruction_path,
|
||||
core.accounts_json
|
||||
FROM kb_sol_ops_processing_ledger AS ledger
|
||||
JOIN kb_sol_core_instructions AS core
|
||||
ON ledger.input_key = core.signature || ':' || core.instruction_path
|
||||
WHERE ledger.stage = 'instruction_decode'
|
||||
AND ledger.status = 'failed'
|
||||
AND ledger.processor_name = 'metadata_metaplex_token_metadata'
|
||||
AND ledger.error_message LIKE 'transfer%'
|
||||
)
|
||||
SELECT
|
||||
failed.signature,
|
||||
failed.slot,
|
||||
failed.instruction_path,
|
||||
account.ordinality - 1 AS position,
|
||||
account.value ->> 'accountKey' AS account_key,
|
||||
(account.value ->> 'accountIndex')::INTEGER AS account_index,
|
||||
keys.signer,
|
||||
keys.writable
|
||||
FROM failed_transfer AS failed
|
||||
CROSS JOIN LATERAL jsonb_array_elements(failed.accounts_json)
|
||||
WITH ORDINALITY AS account(value, ordinality)
|
||||
LEFT JOIN kb_sol_core_account_keys AS keys
|
||||
ON keys.signature = failed.signature
|
||||
AND keys.account_index = (account.value ->> 'accountIndex')::INTEGER
|
||||
ORDER BY account.ordinality;
|
||||
-- file: kb-store/migrations/0001_canonical_transaction_store.sql
|
||||
-- version: 1
|
||||
|
||||
-- Current canonical transaction and acquisition observation store.
|
||||
-- This baseline contains only active tables and uses the current PostgreSQL schema.
|
||||
-- Historical 0.2.x upgrade logic was validated before this baseline was consolidated.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS kb_sol_raw_transactions (
|
||||
id BIGSERIAL,
|
||||
signature TEXT NOT NULL,
|
||||
slot BIGINT NOT NULL,
|
||||
canonical_json JSONB,
|
||||
canonical_json_hash TEXT,
|
||||
canonical_format_version INTEGER NOT NULL DEFAULT 1,
|
||||
retention_state TEXT NOT NULL DEFAULT 'full',
|
||||
processing_state TEXT NOT NULL DEFAULT 'received',
|
||||
lifecycle_reason TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT pk_kb_sol_raw_transactions PRIMARY KEY (id),
|
||||
CONSTRAINT ck_kb_sol_raw_transactions_signature_not_empty CHECK (length(btrim(signature)) > 0),
|
||||
CONSTRAINT ck_kb_sol_raw_transactions_slot_non_negative CHECK (slot >= 0),
|
||||
CONSTRAINT ck_kb_sol_raw_transactions_format_version_positive CHECK (canonical_format_version > 0),
|
||||
CONSTRAINT ck_kb_sol_raw_transactions_retention_state CHECK (retention_state IN ('full', 'compacted', 'archived', 'purged')),
|
||||
CONSTRAINT ck_kb_sol_raw_transactions_processing_state CHECK (processing_state IN ('received', 'core_extracted', 'decoded', 'materialized', 'failed')),
|
||||
CONSTRAINT ck_kb_sol_raw_transactions_full_has_json CHECK (retention_state <> 'full' OR canonical_json IS NOT NULL)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_kb_sol_raw_transactions_signature ON kb_sol_raw_transactions (signature);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_kb_sol_raw_transactions_slot ON kb_sol_raw_transactions (slot);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_kb_sol_raw_transactions_created_at ON kb_sol_raw_transactions (created_at);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_kb_sol_raw_transactions_processing ON kb_sol_raw_transactions (processing_state);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_kb_sol_raw_transactions_canonical_hash ON kb_sol_raw_transactions (canonical_json_hash) WHERE canonical_json_hash IS NOT NULL;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS kb_sol_obs_transaction_observations (
|
||||
id BIGSERIAL,
|
||||
raw_transaction_id BIGINT,
|
||||
observation_key TEXT NOT NULL,
|
||||
signature TEXT,
|
||||
slot BIGINT,
|
||||
provider TEXT NOT NULL,
|
||||
endpoint_code TEXT,
|
||||
protocol TEXT NOT NULL,
|
||||
acquisition_method TEXT NOT NULL,
|
||||
origin TEXT NOT NULL,
|
||||
commitment TEXT,
|
||||
capture_session_id TEXT,
|
||||
filter_code TEXT,
|
||||
detected_at TIMESTAMPTZ,
|
||||
received_at TIMESTAMPTZ NOT NULL,
|
||||
normalized_at TIMESTAMPTZ,
|
||||
persisted_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
payload_size_bytes BIGINT,
|
||||
source_payload_hash TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'received',
|
||||
error_code TEXT,
|
||||
error_message TEXT,
|
||||
CONSTRAINT pk_kb_sol_obs_transaction_observations PRIMARY KEY (id),
|
||||
CONSTRAINT fk_kb_sol_obs_transaction_observations_raw_transaction FOREIGN KEY (raw_transaction_id) REFERENCES kb_sol_raw_transactions(id) ON DELETE SET NULL,
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_key_not_empty CHECK (length(btrim(observation_key)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_signature_not_empty CHECK (signature IS NULL OR length(btrim(signature)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_slot_non_negative CHECK (slot IS NULL OR slot >= 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_provider_not_empty CHECK (length(btrim(provider)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_endpoint_not_empty CHECK (endpoint_code IS NULL OR length(btrim(endpoint_code)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_protocol_not_empty CHECK (length(btrim(protocol)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_method_not_empty CHECK (length(btrim(acquisition_method)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_origin CHECK (origin IN ('live', 'backfill', 'replay', 'repair', 'migration')),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_commitment_not_empty CHECK (commitment IS NULL OR length(btrim(commitment)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_session_not_empty CHECK (capture_session_id IS NULL OR length(btrim(capture_session_id)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_filter_not_empty CHECK (filter_code IS NULL OR length(btrim(filter_code)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_payload_size_non_negative CHECK (payload_size_bytes IS NULL OR payload_size_bytes >= 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_hash_not_empty CHECK (source_payload_hash IS NULL OR length(btrim(source_payload_hash)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_status CHECK (status IN ('detected', 'received', 'normalized', 'persisted', 'failed', 'missing')),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_error_code_not_empty CHECK (error_code IS NULL OR length(btrim(error_code)) > 0),
|
||||
CONSTRAINT ck_kb_sol_obs_transaction_observations_error_message_not_empty CHECK (error_message IS NULL OR length(btrim(error_message)) > 0)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_kb_sol_obs_transaction_observations_key ON kb_sol_obs_transaction_observations (observation_key);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_kb_sol_obs_transaction_observations_signature ON kb_sol_obs_transaction_observations (signature) WHERE signature IS NOT NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_kb_sol_obs_transaction_observations_slot ON kb_sol_obs_transaction_observations (slot) WHERE slot IS NOT NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_kb_sol_obs_transaction_observations_provider_method ON kb_sol_obs_transaction_observations (provider, acquisition_method);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_kb_sol_obs_transaction_observations_received_at ON kb_sol_obs_transaction_observations (received_at);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_kb_sol_obs_transaction_observations_raw_transaction ON kb_sol_obs_transaction_observations (raw_transaction_id) WHERE raw_transaction_id IS NOT NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS ix_kb_sol_obs_transaction_observations_status ON kb_sol_obs_transaction_observations (status);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-store/src/contracts/dto/decode.rs
|
||||
// version: 2
|
||||
// version: 4
|
||||
|
||||
//! Backend-neutral decode, coverage and materialization persistence DTOs.
|
||||
|
||||
@@ -632,7 +632,7 @@ mod tests {
|
||||
#[test]
|
||||
fn materialized_event_filter_is_bounded_and_trims_optional_text() {
|
||||
let result = crate::MaterializedEventFilter::new(
|
||||
std::option::Option::Some(" transaction_annotations ".to_string()),
|
||||
std::option::Option::Some(" materializer.transaction.annotations ".to_string()),
|
||||
std::option::Option::Some(" transaction_annotation ".to_string()),
|
||||
std::option::Option::Some(" signature ".to_string()),
|
||||
crate::MAX_MATERIALIZED_EVENT_QUERY_ROWS,
|
||||
@@ -643,7 +643,7 @@ mod tests {
|
||||
};
|
||||
assert_eq!(
|
||||
filter.processor_name.as_deref(),
|
||||
std::option::Option::Some("transaction_annotations")
|
||||
std::option::Option::Some("materializer.transaction.annotations")
|
||||
);
|
||||
assert_eq!(filter.signature_contains.as_deref(), std::option::Option::Some("signature"));
|
||||
assert!(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-store/src/postgres/query/decode_pipeline_queries.rs
|
||||
// version: 2
|
||||
// version: 4
|
||||
|
||||
//! PostgreSQL queries for contextual decode, coverage and materialization persistence.
|
||||
|
||||
@@ -1055,7 +1055,7 @@ mod tests {
|
||||
processor_name: processor_name.clone(),
|
||||
processor_version: "1".to_string(),
|
||||
program_id: "11111111111111111111111111111111".to_string(),
|
||||
surface_code: std::option::Option::Some("solana_native_system".to_string()),
|
||||
surface_code: std::option::Option::Some("solana.core.system".to_string()),
|
||||
entry_kind: "instruction".to_string(),
|
||||
entry_code: "test".to_string(),
|
||||
discriminator_hex: std::option::Option::None,
|
||||
@@ -1120,7 +1120,7 @@ mod tests {
|
||||
slot: 1,
|
||||
instruction_path: "0".to_string(),
|
||||
program_id: "11111111111111111111111111111111".to_string(),
|
||||
surface_code: std::option::Option::Some("solana_native_system".to_string()),
|
||||
surface_code: std::option::Option::Some("solana.core.system".to_string()),
|
||||
entry_code: std::option::Option::Some("unknown".to_string()),
|
||||
discriminator_hex: std::option::Option::None,
|
||||
status: "unsupported".to_string(),
|
||||
@@ -1175,7 +1175,7 @@ mod tests {
|
||||
};
|
||||
let input_key = unique_processor_name("annotation_query_test");
|
||||
let insert_result = sqlx::query(
|
||||
"INSERT INTO kb_sol_mat_events (processor_name, processor_version, input_key, input_hash, output_key, source_event_key, source_decoder_name, source_decoder_version, source_decode_input_key, signature, slot, materialized_family, payload_jsonb) VALUES ('transaction_annotations', '0.4.3', $1, 'hash', 'annotation', 'memo:0', 'spl_memo', '0.4.3', 'decode-input', $2, 42, 'transaction_annotation', $3)",
|
||||
"INSERT INTO kb_sol_mat_events (processor_name, processor_version, input_key, input_hash, output_key, source_event_key, source_decoder_name, source_decoder_version, source_decode_input_key, signature, slot, materialized_family, payload_jsonb) VALUES ('materializer.transaction.annotations', '0.4.3', $1, 'hash', 'annotation', 'memo:0', 'kb-lib.decoder.spl.memo', '0.4.3', 'decode-input', $2, 42, 'transaction_annotation', $3)",
|
||||
)
|
||||
.bind(input_key.as_str())
|
||||
.bind(input_key.as_str())
|
||||
@@ -1184,7 +1184,7 @@ mod tests {
|
||||
.await;
|
||||
result_or_panic(insert_result);
|
||||
let filter = result_or_panic(crate::MaterializedEventFilter::new(
|
||||
std::option::Option::Some("transaction_annotations".to_string()),
|
||||
std::option::Option::Some("materializer.transaction.annotations".to_string()),
|
||||
std::option::Option::Some("transaction_annotation".to_string()),
|
||||
std::option::Option::Some(input_key.clone()),
|
||||
1,
|
||||
|
||||
Reference in New Issue
Block a user