diff --git a/app/backend/src/ingestion/event-schema.js b/app/backend/src/ingestion/event-schema.js index a214c8e3..ee5c9601 100644 --- a/app/backend/src/ingestion/event-schema.js +++ b/app/backend/src/ingestion/event-schema.js @@ -12,6 +12,7 @@ exports.RustAcademy_EVENT_TOPICS = { // payloadKeys are sorted alphabetically. // "ledger_sequence" ('l') sorts after 'f*' / 'e*' keys and before 'p*' / 'r*' / 's*' keys. exports.RustAcademy_EVENT_SCHEMA_CONTRACTS = { + // ── Escrow events ─────────────────────────────────────────────────────── EscrowDeposited: { topic: exports.RustAcademy_EVENT_TOPICS.escrow, eventName: "EscrowDeposited", @@ -44,6 +45,86 @@ exports.RustAcademy_EVENT_SCHEMA_CONTRACTS = { schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [1, exports.RustAcademy_EVENT_SCHEMA_VERSION], }, + EscrowDisputed: { + topic: exports.RustAcademy_EVENT_TOPICS.escrow, + eventName: "EscrowDisputed", + indexedFields: ["escrow_id", "arbiter"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + EscrowFinalized: { + topic: exports.RustAcademy_EVENT_TOPICS.escrow, + eventName: "EscrowFinalized", + indexedFields: ["escrow_id", "owner"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp", "token", "total_amount"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + PartialPayment: { + topic: exports.RustAcademy_EVENT_TOPICS.escrow, + eventName: "PartialPayment", + indexedFields: ["escrow_id", "payer"], + payloadKeys: [ + "amount_due", + "amount_paid", + "ledger_sequence", + "payment_amount", + "schema_version", + "timestamp", + "token", + ], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + // ── Dispute events ────────────────────────────────────────────────────── + ArbiterVoteCast: { + topic: exports.RustAcademy_EVENT_TOPICS.dispute, + eventName: "ArbiterVoteCast", + indexedFields: ["escrow_id", "arbiter"], + payloadKeys: [ + "ledger_sequence", + "resolve_for_owner", + "schema_version", + "threshold", + "timestamp", + "vote_count", + ], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + DisputeResolved: { + topic: exports.RustAcademy_EVENT_TOPICS.dispute, + eventName: "DisputeResolved", + indexedFields: ["escrow_id", "resolved_for_owner"], + payloadKeys: [ + "amount", + "ledger_sequence", + "schema_version", + "threshold", + "timestamp", + "total_votes", + ], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + DisputeTimeoutSet: { + topic: exports.RustAcademy_EVENT_TOPICS.dispute, + eventName: "DisputeTimeoutSet", + indexedFields: ["escrow_id"], + payloadKeys: ["action", "expires_at", "ledger_sequence", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + DisputeAutoResolved: { + topic: exports.RustAcademy_EVENT_TOPICS.dispute, + eventName: "DisputeAutoResolved", + indexedFields: ["escrow_id", "action"], + payloadKeys: ["amount", "ledger_sequence", "recipient", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + // ── Privacy events ────────────────────────────────────────────────────── PrivacyToggled: { topic: exports.RustAcademy_EVENT_TOPICS.privacy, eventName: "PrivacyToggled", @@ -52,14 +133,32 @@ exports.RustAcademy_EVENT_SCHEMA_CONTRACTS = { schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [1, exports.RustAcademy_EVENT_SCHEMA_VERSION], }, - ContractPaused: { - topic: exports.RustAcademy_EVENT_TOPICS.admin, - eventName: "ContractPaused", - indexedFields: ["admin"], - payloadKeys: ["ledger_sequence", "paused", "schema_version", "timestamp"], + // ── Stealth events ────────────────────────────────────────────────────── + EphemeralKeyRegistered: { + topic: exports.RustAcademy_EVENT_TOPICS.stealth, + eventName: "EphemeralKeyRegistered", + indexedFields: ["stealth_address", "eph_pub"], + payloadKeys: [ + "amount_due", + "amount_paid", + "expires_at", + "ledger_sequence", + "schema_version", + "timestamp", + "token", + ], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + StealthWithdrawn: { + topic: exports.RustAcademy_EVENT_TOPICS.stealth, + eventName: "StealthWithdrawn", + indexedFields: ["stealth_address", "recipient"], + payloadKeys: ["amount", "ledger_sequence", "schema_version", "timestamp", "token"], schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], }, + // ── Admin events ──────────────────────────────────────────────────────── AdminChanged: { topic: exports.RustAcademy_EVENT_TOPICS.admin, eventName: "AdminChanged", @@ -68,6 +167,37 @@ exports.RustAcademy_EVENT_SCHEMA_CONTRACTS = { schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [1, exports.RustAcademy_EVENT_SCHEMA_VERSION], }, + ContractInitialized: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "ContractInitialized", + indexedFields: ["admin"], + payloadKeys: [ + "contract_version", + "event_schema_version", + "ledger_sequence", + "paused", + "schema_version", + "timestamp", + ], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + ContractMigrated: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "ContractMigrated", + indexedFields: ["admin"], + payloadKeys: ["from_version", "ledger_sequence", "schema_version", "timestamp", "to_version"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + ContractPaused: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "ContractPaused", + indexedFields: ["admin"], + payloadKeys: ["ledger_sequence", "paused", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, ContractUpgraded: { topic: exports.RustAcademy_EVENT_TOPICS.admin, eventName: "ContractUpgraded", @@ -76,27 +206,116 @@ exports.RustAcademy_EVENT_SCHEMA_CONTRACTS = { schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], }, - EphemeralKeyRegistered: { - topic: exports.RustAcademy_EVENT_TOPICS.stealth, - eventName: "EphemeralKeyRegistered", - indexedFields: ["stealth_address", "eph_pub"], + DisputeExpiryActionSet: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "DisputeExpiryActionSet", + indexedFields: [], + payloadKeys: ["action", "ledger_sequence", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + DisputeTimeoutConfigSet: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "DisputeTimeoutConfigSet", + indexedFields: [], + payloadKeys: ["ledger_sequence", "schema_version", "timeout_secs", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + EmergencyModeActivated: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "EmergencyModeActivated", + indexedFields: ["admin"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + FeeCollectorRotated: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "FeeCollectorRotated", + indexedFields: ["new_collector"], + payloadKeys: ["ledger_sequence", "rotation_index", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + FeeConfigChanged: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "FeeConfigChanged", + indexedFields: [], + payloadKeys: ["fee_bps", "ledger_sequence", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + HookRegistered: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "HookRegistered", + indexedFields: ["hook_contract"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + HookUnregistered: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "HookUnregistered", + indexedFields: ["hook_contract"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + PauseFlagsChanged: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "PauseFlagsChanged", + indexedFields: ["admin"], + payloadKeys: ["flags_disabled", "flags_enabled", "ledger_sequence", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + PerAssetFeeSet: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "PerAssetFeeSet", + indexedFields: ["token"], + payloadKeys: ["arbiter_bps", "fee_bps", "ledger_sequence", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + PlatformWalletChanged: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "PlatformWalletChanged", + indexedFields: ["wallet"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + UpgradeCompleted: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "UpgradeCompleted", + indexedFields: ["admin"], + payloadKeys: ["ledger_sequence", "new_version", "old_version", "schema_version", "timestamp"], + schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], + }, + UpgradeStarted: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "UpgradeStarted", + indexedFields: ["admin"], payloadKeys: [ - "amount_due", - "amount_paid", - "expires_at", "ledger_sequence", + "new_version", + "new_wasm_hash", + "old_version", "schema_version", "timestamp", - "token", + "window_end", + "window_start", ], schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], }, - StealthWithdrawn: { - topic: exports.RustAcademy_EVENT_TOPICS.stealth, - eventName: "StealthWithdrawn", - indexedFields: ["stealth_address", "recipient"], - payloadKeys: ["amount", "ledger_sequence", "schema_version", "timestamp", "token"], + UpgradeWindowSet: { + topic: exports.RustAcademy_EVENT_TOPICS.admin, + eventName: "UpgradeWindowSet", + indexedFields: ["admin"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp", "window_end", "window_start"], schemaVersion: exports.RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [exports.RustAcademy_EVENT_SCHEMA_VERSION], }, diff --git a/app/backend/src/ingestion/event-schema.ts b/app/backend/src/ingestion/event-schema.ts index f649d2ea..a2d58502 100644 --- a/app/backend/src/ingestion/event-schema.ts +++ b/app/backend/src/ingestion/event-schema.ts @@ -23,6 +23,7 @@ export interface EventSchemaContract { // payloadKeys are sorted alphabetically. // "ledger_sequence" ('l') sorts after 'f*' / 'e*' keys and before 'p*' / 'r*' / 's*' keys. export const RustAcademy_EVENT_SCHEMA_CONTRACTS = { + // ── Escrow events ─────────────────────────────────────────────────────── EscrowDeposited: { topic: RustAcademy_EVENT_TOPICS.escrow, eventName: "EscrowDeposited", @@ -55,6 +56,86 @@ export const RustAcademy_EVENT_SCHEMA_CONTRACTS = { schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [1, RustAcademy_EVENT_SCHEMA_VERSION], }, + EscrowDisputed: { + topic: RustAcademy_EVENT_TOPICS.escrow, + eventName: "EscrowDisputed", + indexedFields: ["escrow_id", "arbiter"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + EscrowFinalized: { + topic: RustAcademy_EVENT_TOPICS.escrow, + eventName: "EscrowFinalized", + indexedFields: ["escrow_id", "owner"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp", "token", "total_amount"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + PartialPayment: { + topic: RustAcademy_EVENT_TOPICS.escrow, + eventName: "PartialPayment", + indexedFields: ["escrow_id", "payer"], + payloadKeys: [ + "amount_due", + "amount_paid", + "ledger_sequence", + "payment_amount", + "schema_version", + "timestamp", + "token", + ], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + // ── Dispute events ────────────────────────────────────────────────────── + ArbiterVoteCast: { + topic: RustAcademy_EVENT_TOPICS.dispute, + eventName: "ArbiterVoteCast", + indexedFields: ["escrow_id", "arbiter"], + payloadKeys: [ + "ledger_sequence", + "resolve_for_owner", + "schema_version", + "threshold", + "timestamp", + "vote_count", + ], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + DisputeResolved: { + topic: RustAcademy_EVENT_TOPICS.dispute, + eventName: "DisputeResolved", + indexedFields: ["escrow_id", "resolved_for_owner"], + payloadKeys: [ + "amount", + "ledger_sequence", + "schema_version", + "threshold", + "timestamp", + "total_votes", + ], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + DisputeTimeoutSet: { + topic: RustAcademy_EVENT_TOPICS.dispute, + eventName: "DisputeTimeoutSet", + indexedFields: ["escrow_id"], + payloadKeys: ["action", "expires_at", "ledger_sequence", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + DisputeAutoResolved: { + topic: RustAcademy_EVENT_TOPICS.dispute, + eventName: "DisputeAutoResolved", + indexedFields: ["escrow_id", "action"], + payloadKeys: ["amount", "ledger_sequence", "recipient", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + // ── Privacy events ────────────────────────────────────────────────────── PrivacyToggled: { topic: RustAcademy_EVENT_TOPICS.privacy, eventName: "PrivacyToggled", @@ -63,14 +144,32 @@ export const RustAcademy_EVENT_SCHEMA_CONTRACTS = { schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [1, RustAcademy_EVENT_SCHEMA_VERSION], }, - ContractPaused: { - topic: RustAcademy_EVENT_TOPICS.admin, - eventName: "ContractPaused", - indexedFields: ["admin"], - payloadKeys: ["ledger_sequence", "paused", "schema_version", "timestamp"], + // ── Stealth events ────────────────────────────────────────────────────── + EphemeralKeyRegistered: { + topic: RustAcademy_EVENT_TOPICS.stealth, + eventName: "EphemeralKeyRegistered", + indexedFields: ["stealth_address", "eph_pub"], + payloadKeys: [ + "amount_due", + "amount_paid", + "expires_at", + "ledger_sequence", + "schema_version", + "timestamp", + "token", + ], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + StealthWithdrawn: { + topic: RustAcademy_EVENT_TOPICS.stealth, + eventName: "StealthWithdrawn", + indexedFields: ["stealth_address", "recipient"], + payloadKeys: ["amount", "ledger_sequence", "schema_version", "timestamp", "token"], schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], }, + // ── Admin events ──────────────────────────────────────────────────────── AdminChanged: { topic: RustAcademy_EVENT_TOPICS.admin, eventName: "AdminChanged", @@ -79,6 +178,37 @@ export const RustAcademy_EVENT_SCHEMA_CONTRACTS = { schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [1, RustAcademy_EVENT_SCHEMA_VERSION], }, + ContractInitialized: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "ContractInitialized", + indexedFields: ["admin"], + payloadKeys: [ + "contract_version", + "event_schema_version", + "ledger_sequence", + "paused", + "schema_version", + "timestamp", + ], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + ContractMigrated: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "ContractMigrated", + indexedFields: ["admin"], + payloadKeys: ["from_version", "ledger_sequence", "schema_version", "timestamp", "to_version"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + ContractPaused: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "ContractPaused", + indexedFields: ["admin"], + payloadKeys: ["ledger_sequence", "paused", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, ContractUpgraded: { topic: RustAcademy_EVENT_TOPICS.admin, eventName: "ContractUpgraded", @@ -87,27 +217,116 @@ export const RustAcademy_EVENT_SCHEMA_CONTRACTS = { schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], }, - EphemeralKeyRegistered: { - topic: RustAcademy_EVENT_TOPICS.stealth, - eventName: "EphemeralKeyRegistered", - indexedFields: ["stealth_address", "eph_pub"], + DisputeExpiryActionSet: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "DisputeExpiryActionSet", + indexedFields: [], + payloadKeys: ["action", "ledger_sequence", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + DisputeTimeoutConfigSet: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "DisputeTimeoutConfigSet", + indexedFields: [], + payloadKeys: ["ledger_sequence", "schema_version", "timeout_secs", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + EmergencyModeActivated: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "EmergencyModeActivated", + indexedFields: ["admin"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + FeeCollectorRotated: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "FeeCollectorRotated", + indexedFields: ["new_collector"], + payloadKeys: ["ledger_sequence", "rotation_index", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + FeeConfigChanged: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "FeeConfigChanged", + indexedFields: [], + payloadKeys: ["fee_bps", "ledger_sequence", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + HookRegistered: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "HookRegistered", + indexedFields: ["hook_contract"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + HookUnregistered: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "HookUnregistered", + indexedFields: ["hook_contract"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + PauseFlagsChanged: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "PauseFlagsChanged", + indexedFields: ["admin"], + payloadKeys: ["flags_disabled", "flags_enabled", "ledger_sequence", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + PerAssetFeeSet: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "PerAssetFeeSet", + indexedFields: ["token"], + payloadKeys: ["arbiter_bps", "fee_bps", "ledger_sequence", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + PlatformWalletChanged: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "PlatformWalletChanged", + indexedFields: ["wallet"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + UpgradeCompleted: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "UpgradeCompleted", + indexedFields: ["admin"], + payloadKeys: ["ledger_sequence", "new_version", "old_version", "schema_version", "timestamp"], + schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, + compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], + }, + UpgradeStarted: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "UpgradeStarted", + indexedFields: ["admin"], payloadKeys: [ - "amount_due", - "amount_paid", - "expires_at", "ledger_sequence", + "new_version", + "new_wasm_hash", + "old_version", "schema_version", "timestamp", - "token", + "window_end", + "window_start", ], schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], }, - StealthWithdrawn: { - topic: RustAcademy_EVENT_TOPICS.stealth, - eventName: "StealthWithdrawn", - indexedFields: ["stealth_address", "recipient"], - payloadKeys: ["amount", "ledger_sequence", "schema_version", "timestamp", "token"], + UpgradeWindowSet: { + topic: RustAcademy_EVENT_TOPICS.admin, + eventName: "UpgradeWindowSet", + indexedFields: ["admin"], + payloadKeys: ["ledger_sequence", "schema_version", "timestamp", "window_end", "window_start"], schemaVersion: RustAcademy_EVENT_SCHEMA_VERSION, compatibleVersions: [RustAcademy_EVENT_SCHEMA_VERSION], }, diff --git a/app/backend/src/ingestion/soroban-event.parser.js b/app/backend/src/ingestion/soroban-event.parser.js index 1b3e9602..e069c5c1 100644 --- a/app/backend/src/ingestion/soroban-event.parser.js +++ b/app/backend/src/ingestion/soroban-event.parser.js @@ -83,18 +83,62 @@ var SorobanEventParser = /** @class */ (function () { return this.parseEscrowWithdrawn(topics, dataVal, base, layout.indexedOffset); case "EscrowRefunded": return this.parseEscrowRefunded(topics, dataVal, base, layout.indexedOffset); + case "EscrowDisputed": + return this.parseEscrowDisputed(topics, dataVal, base, layout.indexedOffset); + case "EscrowFinalized": + return this.parseEscrowFinalized(topics, dataVal, base, layout.indexedOffset); + case "PartialPayment": + return this.parsePartialPayment(topics, dataVal, base, layout.indexedOffset); + case "ArbiterVoteCast": + return this.parseArbiterVoteCast(topics, dataVal, base, layout.indexedOffset); + case "DisputeResolved": + return this.parseDisputeResolved(topics, dataVal, base, layout.indexedOffset); + case "DisputeTimeoutSet": + return this.parseDisputeTimeoutSet(topics, dataVal, base, layout.indexedOffset); + case "DisputeAutoResolved": + return this.parseDisputeAutoResolved(topics, dataVal, base, layout.indexedOffset); case "PrivacyToggled": return this.parsePrivacyToggled(topics, dataVal, base, layout.indexedOffset); - case "ContractPaused": - return this.parseContractPaused(topics, dataVal, base, layout.indexedOffset); - case "AdminChanged": - return this.parseAdminChanged(topics, dataVal, base, layout.indexedOffset); - case "ContractUpgraded": - return this.parseContractUpgraded(topics, dataVal, base, layout.indexedOffset); case "EphemeralKeyRegistered": return this.parseEphemeralKeyRegistered(topics, dataVal, base, layout.indexedOffset); case "StealthWithdrawn": return this.parseStealthWithdrawn(topics, dataVal, base, layout.indexedOffset); + case "AdminChanged": + return this.parseAdminChanged(topics, dataVal, base, layout.indexedOffset); + case "ContractInitialized": + return this.parseContractInitialized(topics, dataVal, base, layout.indexedOffset); + case "ContractMigrated": + return this.parseContractMigrated(topics, dataVal, base, layout.indexedOffset); + case "ContractPaused": + return this.parseContractPaused(topics, dataVal, base, layout.indexedOffset); + case "ContractUpgraded": + return this.parseContractUpgraded(topics, dataVal, base, layout.indexedOffset); + case "DisputeExpiryActionSet": + return this.parseDisputeExpiryActionSet(topics, dataVal, base, layout.indexedOffset); + case "DisputeTimeoutConfigSet": + return this.parseDisputeTimeoutConfigSet(topics, dataVal, base, layout.indexedOffset); + case "EmergencyModeActivated": + return this.parseEmergencyModeActivated(topics, dataVal, base, layout.indexedOffset); + case "FeeCollectorRotated": + return this.parseFeeCollectorRotated(topics, dataVal, base, layout.indexedOffset); + case "FeeConfigChanged": + return this.parseFeeConfigChanged(topics, dataVal, base, layout.indexedOffset); + case "HookRegistered": + return this.parseHookRegistered(topics, dataVal, base, layout.indexedOffset); + case "HookUnregistered": + return this.parseHookUnregistered(topics, dataVal, base, layout.indexedOffset); + case "PauseFlagsChanged": + return this.parsePauseFlagsChanged(topics, dataVal, base, layout.indexedOffset); + case "PerAssetFeeSet": + return this.parsePerAssetFeeSet(topics, dataVal, base, layout.indexedOffset); + case "PlatformWalletChanged": + return this.parsePlatformWalletChanged(topics, dataVal, base, layout.indexedOffset); + case "UpgradeCompleted": + return this.parseUpgradeCompleted(topics, dataVal, base, layout.indexedOffset); + case "UpgradeStarted": + return this.parseUpgradeStarted(topics, dataVal, base, layout.indexedOffset); + case "UpgradeWindowSet": + return this.parseUpgradeWindowSet(topics, dataVal, base, layout.indexedOffset); default: this.logger.debug("Unrecognised event name: ".concat(layout.eventName)); return null; @@ -127,6 +171,51 @@ var SorobanEventParser = /** @class */ (function () { var map = this.dataToMap(data); return __assign(__assign({ eventType: "EscrowRefunded" }, base), { commitment: commitment, owner: owner, token: this.decodeAddress(map["token"]), amount: BigInt((0, stellar_sdk_1.scValToNative)(map["amount"])) }); }; + SorobanEventParser.prototype.parseEscrowDisputed = function (topics, data, base, indexedOffset) { + var commitment = this.decodeBytes32Hex(topics[indexedOffset]); + var arbiter = this.decodeAddress(topics[indexedOffset + 1]); + return __assign(__assign({ eventType: "EscrowDisputed" }, base), { commitment: commitment, arbiter: arbiter }); + }; + SorobanEventParser.prototype.parseEscrowFinalized = function (topics, data, base, indexedOffset) { + var commitment = this.decodeBytes32Hex(topics[indexedOffset]); + var owner = this.decodeAddress(topics[indexedOffset + 1]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "EscrowFinalized" }, base), { commitment: commitment, owner: owner, token: this.decodeAddress(map["token"]), totalAmount: BigInt((0, stellar_sdk_1.scValToNative)(map["total_amount"])) }); + }; + SorobanEventParser.prototype.parsePartialPayment = function (topics, data, base, indexedOffset) { + var commitment = this.decodeBytes32Hex(topics[indexedOffset]); + var payer = this.decodeAddress(topics[indexedOffset + 1]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "PartialPayment" }, base), { commitment: commitment, payer: payer, token: this.decodeAddress(map["token"]), paymentAmount: BigInt((0, stellar_sdk_1.scValToNative)(map["payment_amount"])), amountPaid: BigInt((0, stellar_sdk_1.scValToNative)(map["amount_paid"])), amountDue: BigInt((0, stellar_sdk_1.scValToNative)(map["amount_due"])) }); + }; + // --------------------------------------------------------------------------- + // Dispute event parsers + // --------------------------------------------------------------------------- + SorobanEventParser.prototype.parseArbiterVoteCast = function (topics, data, base, indexedOffset) { + var commitment = this.decodeBytes32Hex(topics[indexedOffset]); + var arbiter = this.decodeAddress(topics[indexedOffset + 1]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "ArbiterVoteCast" }, base), { commitment: commitment, arbiter: arbiter, resolveForOwner: Boolean((0, stellar_sdk_1.scValToNative)(map["resolve_for_owner"])), voteCount: Number((0, stellar_sdk_1.scValToNative)(map["vote_count"])), threshold: Number((0, stellar_sdk_1.scValToNative)(map["threshold"])) }); + }; + SorobanEventParser.prototype.parseDisputeResolved = function (topics, data, base, indexedOffset) { + var commitment = this.decodeBytes32Hex(topics[indexedOffset]); + var resolvedForOwner = Boolean((0, stellar_sdk_1.scValToNative)(topics[indexedOffset + 1])); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "DisputeResolved" }, base), { commitment: commitment, resolvedForOwner: resolvedForOwner, totalVotes: Number((0, stellar_sdk_1.scValToNative)(map["total_votes"])), threshold: Number((0, stellar_sdk_1.scValToNative)(map["threshold"])), amount: BigInt((0, stellar_sdk_1.scValToNative)(map["amount"])) }); + }; + SorobanEventParser.prototype.parseDisputeTimeoutSet = function (topics, data, base, indexedOffset) { + var _a; + var commitment = this.decodeBytes32Hex(topics[indexedOffset]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "DisputeTimeoutSet" }, base), { commitment: commitment, action: (_a = this.decodeSymbol(map["action"])) !== null && _a !== void 0 ? _a : "", expiresAt: BigInt((0, stellar_sdk_1.scValToNative)(map["expires_at"])) }); + }; + SorobanEventParser.prototype.parseDisputeAutoResolved = function (topics, data, base, indexedOffset) { + var _a; + var commitment = this.decodeBytes32Hex(topics[indexedOffset]); + var action = (_a = this.decodeSymbol(topics[indexedOffset + 1])) !== null && _a !== void 0 ? _a : ""; + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "DisputeAutoResolved" }, base), { commitment: commitment, action: action, recipient: this.decodeAddress(map["recipient"]), amount: BigInt((0, stellar_sdk_1.scValToNative)(map["amount"])) }); + }; // --------------------------------------------------------------------------- // Admin / Privacy event parsers // --------------------------------------------------------------------------- @@ -150,6 +239,75 @@ var SorobanEventParser = /** @class */ (function () { var admin = this.decodeAddress(topics[indexedOffset + 1]); return __assign(__assign({ eventType: "ContractUpgraded" }, base), { newWasmHash: newWasmHash, admin: admin }); }; + SorobanEventParser.prototype.parseContractInitialized = function (topics, data, base, indexedOffset) { + var admin = this.decodeAddress(topics[indexedOffset]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "ContractInitialized" }, base), { admin: admin, contractVersion: Number((0, stellar_sdk_1.scValToNative)(map["contract_version"])), eventSchemaVersion: Number((0, stellar_sdk_1.scValToNative)(map["event_schema_version"])), paused: Boolean((0, stellar_sdk_1.scValToNative)(map["paused"])) }); + }; + SorobanEventParser.prototype.parseContractMigrated = function (topics, data, base, indexedOffset) { + var admin = this.decodeAddress(topics[indexedOffset]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "ContractMigrated" }, base), { admin: admin, fromVersion: Number((0, stellar_sdk_1.scValToNative)(map["from_version"])), toVersion: Number((0, stellar_sdk_1.scValToNative)(map["to_version"])) }); + }; + SorobanEventParser.prototype.parseDisputeExpiryActionSet = function (topics, data, base, _indexedOffset) { + var _a; + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "DisputeExpiryActionSet" }, base), { action: (_a = this.decodeSymbol(map["action"])) !== null && _a !== void 0 ? _a : "" }); + }; + SorobanEventParser.prototype.parseDisputeTimeoutConfigSet = function (topics, data, base, _indexedOffset) { + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "DisputeTimeoutConfigSet" }, base), { timeoutSecs: BigInt((0, stellar_sdk_1.scValToNative)(map["timeout_secs"])) }); + }; + SorobanEventParser.prototype.parseEmergencyModeActivated = function (topics, data, base, indexedOffset) { + var admin = this.decodeAddress(topics[indexedOffset]); + return __assign(__assign({ eventType: "EmergencyModeActivated" }, base), { admin: admin }); + }; + SorobanEventParser.prototype.parseFeeCollectorRotated = function (topics, data, base, indexedOffset) { + var newCollector = this.decodeAddress(topics[indexedOffset]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "FeeCollectorRotated" }, base), { newCollector: newCollector, rotationIndex: Number((0, stellar_sdk_1.scValToNative)(map["rotation_index"])) }); + }; + SorobanEventParser.prototype.parseFeeConfigChanged = function (topics, data, base, _indexedOffset) { + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "FeeConfigChanged" }, base), { feeBps: Number((0, stellar_sdk_1.scValToNative)(map["fee_bps"])) }); + }; + SorobanEventParser.prototype.parseHookRegistered = function (topics, data, base, indexedOffset) { + var hookContract = this.decodeAddress(topics[indexedOffset]); + return __assign(__assign({ eventType: "HookRegistered" }, base), { hookContract: hookContract }); + }; + SorobanEventParser.prototype.parseHookUnregistered = function (topics, data, base, indexedOffset) { + var hookContract = this.decodeAddress(topics[indexedOffset]); + return __assign(__assign({ eventType: "HookUnregistered" }, base), { hookContract: hookContract }); + }; + SorobanEventParser.prototype.parsePauseFlagsChanged = function (topics, data, base, indexedOffset) { + var admin = this.decodeAddress(topics[indexedOffset]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "PauseFlagsChanged" }, base), { admin: admin, flagsEnabled: BigInt((0, stellar_sdk_1.scValToNative)(map["flags_enabled"])), flagsDisabled: BigInt((0, stellar_sdk_1.scValToNative)(map["flags_disabled"])) }); + }; + SorobanEventParser.prototype.parsePerAssetFeeSet = function (topics, data, base, indexedOffset) { + var token = this.decodeAddress(topics[indexedOffset]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "PerAssetFeeSet" }, base), { token: token, feeBps: Number((0, stellar_sdk_1.scValToNative)(map["fee_bps"])), arbiterBps: Number((0, stellar_sdk_1.scValToNative)(map["arbiter_bps"])) }); + }; + SorobanEventParser.prototype.parsePlatformWalletChanged = function (topics, data, base, indexedOffset) { + var wallet = this.decodeAddress(topics[indexedOffset]); + return __assign(__assign({ eventType: "PlatformWalletChanged" }, base), { wallet: wallet }); + }; + SorobanEventParser.prototype.parseUpgradeCompleted = function (topics, data, base, indexedOffset) { + var admin = this.decodeAddress(topics[indexedOffset]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "UpgradeCompleted" }, base), { admin: admin, oldVersion: Number((0, stellar_sdk_1.scValToNative)(map["old_version"])), newVersion: Number((0, stellar_sdk_1.scValToNative)(map["new_version"])) }); + }; + SorobanEventParser.prototype.parseUpgradeStarted = function (topics, data, base, indexedOffset) { + var admin = this.decodeAddress(topics[indexedOffset]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "UpgradeStarted" }, base), { admin: admin, oldVersion: Number((0, stellar_sdk_1.scValToNative)(map["old_version"])), newVersion: Number((0, stellar_sdk_1.scValToNative)(map["new_version"])), newWasmHash: this.decodeBytes32HexFromMap(map["new_wasm_hash"]), windowStart: BigInt((0, stellar_sdk_1.scValToNative)(map["window_start"])), windowEnd: BigInt((0, stellar_sdk_1.scValToNative)(map["window_end"])) }); + }; + SorobanEventParser.prototype.parseUpgradeWindowSet = function (topics, data, base, indexedOffset) { + var admin = this.decodeAddress(topics[indexedOffset]); + var map = this.dataToMap(data); + return __assign(__assign({ eventType: "UpgradeWindowSet" }, base), { admin: admin, windowStart: BigInt((0, stellar_sdk_1.scValToNative)(map["window_start"])), windowEnd: BigInt((0, stellar_sdk_1.scValToNative)(map["window_end"])) }); + }; // --------------------------------------------------------------------------- // Stealth address event parsers (Privacy v2 – Issue #157) // --------------------------------------------------------------------------- @@ -219,6 +377,10 @@ var SorobanEventParser = /** @class */ (function () { var bytes = (0, stellar_sdk_1.scValToNative)(val); return bytes.toString("hex"); }; + SorobanEventParser.prototype.decodeBytes32HexFromMap = function (val) { + var bytes = (0, stellar_sdk_1.scValToNative)(val); + return bytes.toString("hex"); + }; /** * Converts a Soroban map ScVal into a plain JS Record keyed by field name. */ diff --git a/app/backend/src/ingestion/soroban-event.parser.ts b/app/backend/src/ingestion/soroban-event.parser.ts index 7f55f0d6..a9222d6a 100644 --- a/app/backend/src/ingestion/soroban-event.parser.ts +++ b/app/backend/src/ingestion/soroban-event.parser.ts @@ -7,10 +7,32 @@ import type { EscrowDepositedEvent, EscrowWithdrawnEvent, EscrowRefundedEvent, + EscrowDisputedEvent, + EscrowFinalizedEvent, + PartialPaymentEvent, + ArbiterVoteCastEvent, + DisputeResolvedEvent, + DisputeTimeoutSetEvent, + DisputeAutoResolvedEvent, PrivacyToggledEvent, ContractPausedEvent, AdminChangedEvent, ContractUpgradedEvent, + ContractInitializedEvent, + ContractMigratedEvent, + DisputeExpiryActionSetEvent, + DisputeTimeoutConfigSetEvent, + EmergencyModeActivatedEvent, + FeeCollectorRotatedEvent, + FeeConfigChangedEvent, + HookRegisteredEvent, + HookUnregisteredEvent, + PauseFlagsChangedEvent, + PerAssetFeeSetEvent, + PlatformWalletChangedEvent, + UpgradeCompletedEvent, + UpgradeStartedEvent, + UpgradeWindowSetEvent, EphemeralKeyRegisteredEvent, StealthWithdrawnEvent, } from "./types/contract-event.types"; @@ -130,68 +152,67 @@ export class SorobanEventParser { switch (layout.eventName) { case "EscrowDeposited": - return this.parseEscrowDeposited( - topics, - dataVal, - base, - layout.indexedOffset, - ); + return this.parseEscrowDeposited(topics, dataVal, base, layout.indexedOffset); case "EscrowWithdrawn": - return this.parseEscrowWithdrawn( - topics, - dataVal, - base, - layout.indexedOffset, - ); + return this.parseEscrowWithdrawn(topics, dataVal, base, layout.indexedOffset); case "EscrowRefunded": - return this.parseEscrowRefunded( - topics, - dataVal, - base, - layout.indexedOffset, - ); + return this.parseEscrowRefunded(topics, dataVal, base, layout.indexedOffset); + case "EscrowDisputed": + return this.parseEscrowDisputed(topics, dataVal, base, layout.indexedOffset); + case "EscrowFinalized": + return this.parseEscrowFinalized(topics, dataVal, base, layout.indexedOffset); + case "PartialPayment": + return this.parsePartialPayment(topics, dataVal, base, layout.indexedOffset); + case "ArbiterVoteCast": + return this.parseArbiterVoteCast(topics, dataVal, base, layout.indexedOffset); + case "DisputeResolved": + return this.parseDisputeResolved(topics, dataVal, base, layout.indexedOffset); + case "DisputeTimeoutSet": + return this.parseDisputeTimeoutSet(topics, dataVal, base, layout.indexedOffset); + case "DisputeAutoResolved": + return this.parseDisputeAutoResolved(topics, dataVal, base, layout.indexedOffset); case "PrivacyToggled": - return this.parsePrivacyToggled( - topics, - dataVal, - base, - layout.indexedOffset, - ); - case "ContractPaused": - return this.parseContractPaused( - topics, - dataVal, - base, - layout.indexedOffset, - ); - case "AdminChanged": - return this.parseAdminChanged( - topics, - dataVal, - base, - layout.indexedOffset, - ); - case "ContractUpgraded": - return this.parseContractUpgraded( - topics, - dataVal, - base, - layout.indexedOffset, - ); + return this.parsePrivacyToggled(topics, dataVal, base, layout.indexedOffset); case "EphemeralKeyRegistered": - return this.parseEphemeralKeyRegistered( - topics, - dataVal, - base, - layout.indexedOffset, - ); + return this.parseEphemeralKeyRegistered(topics, dataVal, base, layout.indexedOffset); case "StealthWithdrawn": - return this.parseStealthWithdrawn( - topics, - dataVal, - base, - layout.indexedOffset, - ); + return this.parseStealthWithdrawn(topics, dataVal, base, layout.indexedOffset); + case "AdminChanged": + return this.parseAdminChanged(topics, dataVal, base, layout.indexedOffset); + case "ContractInitialized": + return this.parseContractInitialized(topics, dataVal, base, layout.indexedOffset); + case "ContractMigrated": + return this.parseContractMigrated(topics, dataVal, base, layout.indexedOffset); + case "ContractPaused": + return this.parseContractPaused(topics, dataVal, base, layout.indexedOffset); + case "ContractUpgraded": + return this.parseContractUpgraded(topics, dataVal, base, layout.indexedOffset); + case "DisputeExpiryActionSet": + return this.parseDisputeExpiryActionSet(topics, dataVal, base, layout.indexedOffset); + case "DisputeTimeoutConfigSet": + return this.parseDisputeTimeoutConfigSet(topics, dataVal, base, layout.indexedOffset); + case "EmergencyModeActivated": + return this.parseEmergencyModeActivated(topics, dataVal, base, layout.indexedOffset); + case "FeeCollectorRotated": + return this.parseFeeCollectorRotated(topics, dataVal, base, layout.indexedOffset); + case "FeeConfigChanged": + return this.parseFeeConfigChanged(topics, dataVal, base, layout.indexedOffset); + case "HookRegistered": + return this.parseHookRegistered(topics, dataVal, base, layout.indexedOffset); + case "HookUnregistered": + return this.parseHookUnregistered(topics, dataVal, base, layout.indexedOffset); + case "PauseFlagsChanged": + return this.parsePauseFlagsChanged(topics, dataVal, base, layout.indexedOffset); + case "PerAssetFeeSet": + return this.parsePerAssetFeeSet(topics, dataVal, base, layout.indexedOffset); + case "PlatformWalletChanged": + return this.parsePlatformWalletChanged(topics, dataVal, base, layout.indexedOffset); + case "UpgradeCompleted": + return this.parseUpgradeCompleted(topics, dataVal, base, layout.indexedOffset); + case "UpgradeStarted": + return this.parseUpgradeStarted(topics, dataVal, base, layout.indexedOffset); + case "UpgradeWindowSet": + return this.parseUpgradeWindowSet(topics, dataVal, base, layout.indexedOffset); default: this.logger.debug(`Unrecognised event name: ${layout.eventName}`); return null; @@ -211,16 +232,7 @@ export class SorobanEventParser { private parseEscrowDeposited( topics: xdr.ScVal[], data: xdr.ScVal, - base: Omit< - EscrowDepositedEvent, - | "eventType" - | "commitment" - | "owner" - | "token" - | "amount" - | "amountPaid" - | "expiresAt" - >, + base: Omit, indexedOffset: number, ): EscrowDepositedEvent { const commitment = this.decodeBytes32Hex(topics[indexedOffset]); @@ -242,10 +254,7 @@ export class SorobanEventParser { private parseEscrowWithdrawn( topics: xdr.ScVal[], data: xdr.ScVal, - base: Omit< - EscrowWithdrawnEvent, - "eventType" | "commitment" | "owner" | "token" | "amount" - >, + base: Omit, indexedOffset: number, ): EscrowWithdrawnEvent { const commitment = this.decodeBytes32Hex(topics[indexedOffset]); @@ -265,10 +274,7 @@ export class SorobanEventParser { private parseEscrowRefunded( topics: xdr.ScVal[], data: xdr.ScVal, - base: Omit< - EscrowRefundedEvent, - "eventType" | "commitment" | "owner" | "token" | "amount" - >, + base: Omit, indexedOffset: number, ): EscrowRefundedEvent { const commitment = this.decodeBytes32Hex(topics[indexedOffset]); @@ -285,75 +291,162 @@ export class SorobanEventParser { }; } + private parseEscrowDisputed( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): EscrowDisputedEvent { + const commitment = this.decodeBytes32Hex(topics[indexedOffset]); + const arbiter = this.decodeAddress(topics[indexedOffset + 1]); + + return { eventType: "EscrowDisputed", ...base, commitment, arbiter }; + } + + private parseEscrowFinalized( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): EscrowFinalizedEvent { + const commitment = this.decodeBytes32Hex(topics[indexedOffset]); + const owner = this.decodeAddress(topics[indexedOffset + 1]); + const map = this.dataToMap(data); + + return { + eventType: "EscrowFinalized", + ...base, + commitment, + owner, + token: this.decodeAddress(map["token"]), + totalAmount: BigInt(scValToNative(map["total_amount"])), + }; + } + + private parsePartialPayment( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): PartialPaymentEvent { + const commitment = this.decodeBytes32Hex(topics[indexedOffset]); + const payer = this.decodeAddress(topics[indexedOffset + 1]); + const map = this.dataToMap(data); + + return { + eventType: "PartialPayment", + ...base, + commitment, + payer, + token: this.decodeAddress(map["token"]), + paymentAmount: BigInt(scValToNative(map["payment_amount"])), + amountPaid: BigInt(scValToNative(map["amount_paid"])), + amountDue: BigInt(scValToNative(map["amount_due"])), + }; + } + // --------------------------------------------------------------------------- - // Admin / Privacy event parsers + // Dispute event parsers // --------------------------------------------------------------------------- - private parsePrivacyToggled( + private parseArbiterVoteCast( topics: xdr.ScVal[], data: xdr.ScVal, - base: Omit, + base: Omit, indexedOffset: number, - ): PrivacyToggledEvent { - const owner = this.decodeAddress(topics[indexedOffset]); + ): ArbiterVoteCastEvent { + const commitment = this.decodeBytes32Hex(topics[indexedOffset]); + const arbiter = this.decodeAddress(topics[indexedOffset + 1]); const map = this.dataToMap(data); return { - eventType: "PrivacyToggled", + eventType: "ArbiterVoteCast", ...base, - owner, - enabled: Boolean(scValToNative(map["enabled"])), + commitment, + arbiter, + resolveForOwner: Boolean(scValToNative(map["resolve_for_owner"])), + voteCount: Number(scValToNative(map["vote_count"])), + threshold: Number(scValToNative(map["threshold"])), }; } - private parseContractPaused( + private parseDisputeResolved( topics: xdr.ScVal[], data: xdr.ScVal, - base: Omit, + base: Omit, indexedOffset: number, - ): ContractPausedEvent { - const admin = this.decodeAddress(topics[indexedOffset]); + ): DisputeResolvedEvent { + const commitment = this.decodeBytes32Hex(topics[indexedOffset]); + const resolvedForOwner = Boolean(scValToNative(topics[indexedOffset + 1])); const map = this.dataToMap(data); return { - eventType: "ContractPaused", + eventType: "DisputeResolved", ...base, - admin, - paused: Boolean(scValToNative(map["paused"])), + commitment, + resolvedForOwner, + totalVotes: Number(scValToNative(map["total_votes"])), + threshold: Number(scValToNative(map["threshold"])), + amount: BigInt(scValToNative(map["amount"])), }; } - private parseAdminChanged( + private parseDisputeTimeoutSet( topics: xdr.ScVal[], data: xdr.ScVal, - base: Omit, + base: Omit, indexedOffset: number, - ): AdminChangedEvent { - const oldAdmin = this.decodeAddress(topics[indexedOffset]); - const newAdmin = this.decodeAddress(topics[indexedOffset + 1]); + ): DisputeTimeoutSetEvent { + const commitment = this.decodeBytes32Hex(topics[indexedOffset]); + const map = this.dataToMap(data); return { - eventType: "AdminChanged", + eventType: "DisputeTimeoutSet", ...base, - oldAdmin, - newAdmin, + commitment, + action: this.decodeSymbol(map["action"]) ?? "", + expiresAt: BigInt(scValToNative(map["expires_at"])), }; } - private parseContractUpgraded( + private parseDisputeAutoResolved( topics: xdr.ScVal[], data: xdr.ScVal, - base: Omit, + base: Omit, indexedOffset: number, - ): ContractUpgradedEvent { - const newWasmHash = this.decodeBytes32Hex(topics[indexedOffset]); - const admin = this.decodeAddress(topics[indexedOffset + 1]); + ): DisputeAutoResolvedEvent { + const commitment = this.decodeBytes32Hex(topics[indexedOffset]); + const action = this.decodeSymbol(topics[indexedOffset + 1]) ?? ""; + const map = this.dataToMap(data); return { - eventType: "ContractUpgraded", + eventType: "DisputeAutoResolved", ...base, - newWasmHash, - admin, + commitment, + action, + recipient: this.decodeAddress(map["recipient"]), + amount: BigInt(scValToNative(map["amount"])), + }; + } + + // --------------------------------------------------------------------------- + // Privacy event parsers + // --------------------------------------------------------------------------- + + private parsePrivacyToggled( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): PrivacyToggledEvent { + const owner = this.decodeAddress(topics[indexedOffset]); + const map = this.dataToMap(data); + + return { + eventType: "PrivacyToggled", + ...base, + owner, + enabled: Boolean(scValToNative(map["enabled"])), }; } @@ -364,15 +457,7 @@ export class SorobanEventParser { private parseEphemeralKeyRegistered( topics: xdr.ScVal[], data: xdr.ScVal, - base: Omit< - EphemeralKeyRegisteredEvent, - | "eventType" - | "stealthAddress" - | "ephPub" - | "token" - | "amount" - | "expiresAt" - >, + base: Omit, indexedOffset: number, ): EphemeralKeyRegisteredEvent { const stealthAddress = this.decodeBytes32Hex(topics[indexedOffset]); @@ -393,10 +478,7 @@ export class SorobanEventParser { private parseStealthWithdrawn( topics: xdr.ScVal[], data: xdr.ScVal, - base: Omit< - StealthWithdrawnEvent, - "eventType" | "stealthAddress" | "recipient" | "token" | "amount" - >, + base: Omit, indexedOffset: number, ): StealthWithdrawnEvent { const stealthAddress = this.decodeBytes32Hex(topics[indexedOffset]); @@ -413,6 +495,290 @@ export class SorobanEventParser { }; } + // --------------------------------------------------------------------------- + // Admin event parsers + // --------------------------------------------------------------------------- + + private parseAdminChanged( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): AdminChangedEvent { + const oldAdmin = this.decodeAddress(topics[indexedOffset]); + const newAdmin = this.decodeAddress(topics[indexedOffset + 1]); + + return { eventType: "AdminChanged", ...base, oldAdmin, newAdmin }; + } + + private parseContractInitialized( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): ContractInitializedEvent { + const admin = this.decodeAddress(topics[indexedOffset]); + const map = this.dataToMap(data); + + return { + eventType: "ContractInitialized", + ...base, + admin, + contractVersion: Number(scValToNative(map["contract_version"])), + eventSchemaVersion: Number(scValToNative(map["event_schema_version"])), + paused: Boolean(scValToNative(map["paused"])), + }; + } + + private parseContractMigrated( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): ContractMigratedEvent { + const admin = this.decodeAddress(topics[indexedOffset]); + const map = this.dataToMap(data); + + return { + eventType: "ContractMigrated", + ...base, + admin, + fromVersion: Number(scValToNative(map["from_version"])), + toVersion: Number(scValToNative(map["to_version"])), + }; + } + + private parseContractPaused( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): ContractPausedEvent { + const admin = this.decodeAddress(topics[indexedOffset]); + const map = this.dataToMap(data); + + return { + eventType: "ContractPaused", + ...base, + admin, + paused: Boolean(scValToNative(map["paused"])), + }; + } + + private parseContractUpgraded( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): ContractUpgradedEvent { + const newWasmHash = this.decodeBytes32Hex(topics[indexedOffset]); + const admin = this.decodeAddress(topics[indexedOffset + 1]); + + return { eventType: "ContractUpgraded", ...base, newWasmHash, admin }; + } + + private parseDisputeExpiryActionSet( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _indexedOffset: number, + ): DisputeExpiryActionSetEvent { + const map = this.dataToMap(data); + + return { + eventType: "DisputeExpiryActionSet", + ...base, + action: this.decodeSymbol(map["action"]) ?? "", + }; + } + + private parseDisputeTimeoutConfigSet( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _indexedOffset: number, + ): DisputeTimeoutConfigSetEvent { + const map = this.dataToMap(data); + + return { + eventType: "DisputeTimeoutConfigSet", + ...base, + timeoutSecs: BigInt(scValToNative(map["timeout_secs"])), + }; + } + + private parseEmergencyModeActivated( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): EmergencyModeActivatedEvent { + const admin = this.decodeAddress(topics[indexedOffset]); + + return { eventType: "EmergencyModeActivated", ...base, admin }; + } + + private parseFeeCollectorRotated( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): FeeCollectorRotatedEvent { + const newCollector = this.decodeAddress(topics[indexedOffset]); + const map = this.dataToMap(data); + + return { + eventType: "FeeCollectorRotated", + ...base, + newCollector, + rotationIndex: Number(scValToNative(map["rotation_index"])), + }; + } + + private parseFeeConfigChanged( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _indexedOffset: number, + ): FeeConfigChangedEvent { + const map = this.dataToMap(data); + + return { + eventType: "FeeConfigChanged", + ...base, + feeBps: Number(scValToNative(map["fee_bps"])), + }; + } + + private parseHookRegistered( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): HookRegisteredEvent { + const hookContract = this.decodeAddress(topics[indexedOffset]); + + return { eventType: "HookRegistered", ...base, hookContract }; + } + + private parseHookUnregistered( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): HookUnregisteredEvent { + const hookContract = this.decodeAddress(topics[indexedOffset]); + + return { eventType: "HookUnregistered", ...base, hookContract }; + } + + private parsePauseFlagsChanged( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): PauseFlagsChangedEvent { + const admin = this.decodeAddress(topics[indexedOffset]); + const map = this.dataToMap(data); + + return { + eventType: "PauseFlagsChanged", + ...base, + admin, + flagsEnabled: BigInt(scValToNative(map["flags_enabled"])), + flagsDisabled: BigInt(scValToNative(map["flags_disabled"])), + }; + } + + private parsePerAssetFeeSet( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): PerAssetFeeSetEvent { + const token = this.decodeAddress(topics[indexedOffset]); + const map = this.dataToMap(data); + + return { + eventType: "PerAssetFeeSet", + ...base, + token, + feeBps: Number(scValToNative(map["fee_bps"])), + arbiterBps: Number(scValToNative(map["arbiter_bps"])), + }; + } + + private parsePlatformWalletChanged( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): PlatformWalletChangedEvent { + const wallet = this.decodeAddress(topics[indexedOffset]); + + return { eventType: "PlatformWalletChanged", ...base, wallet }; + } + + private parseUpgradeCompleted( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): UpgradeCompletedEvent { + const admin = this.decodeAddress(topics[indexedOffset]); + const map = this.dataToMap(data); + + return { + eventType: "UpgradeCompleted", + ...base, + admin, + oldVersion: Number(scValToNative(map["old_version"])), + newVersion: Number(scValToNative(map["new_version"])), + }; + } + + private parseUpgradeStarted( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): UpgradeStartedEvent { + const admin = this.decodeAddress(topics[indexedOffset]); + const map = this.dataToMap(data); + + return { + eventType: "UpgradeStarted", + ...base, + admin, + oldVersion: Number(scValToNative(map["old_version"])), + newVersion: Number(scValToNative(map["new_version"])), + newWasmHash: this.decodeBytes32HexFromMap(map["new_wasm_hash"]), + windowStart: BigInt(scValToNative(map["window_start"])), + windowEnd: BigInt(scValToNative(map["window_end"])), + }; + } + + private parseUpgradeWindowSet( + topics: xdr.ScVal[], + data: xdr.ScVal, + base: Omit, + indexedOffset: number, + ): UpgradeWindowSetEvent { + const admin = this.decodeAddress(topics[indexedOffset]); + const map = this.dataToMap(data); + + return { + eventType: "UpgradeWindowSet", + ...base, + admin, + windowStart: BigInt(scValToNative(map["window_start"])), + windowEnd: BigInt(scValToNative(map["window_end"])), + }; + } + // --------------------------------------------------------------------------- // XDR decode helpers // --------------------------------------------------------------------------- @@ -478,7 +844,6 @@ export class SorobanEventParser { private decodeAddress(val: xdr.ScVal): string { const native = scValToNative(val); if (typeof native === "string") return native; - // It may already be an Address object return Address.fromScVal(val).toString(); } @@ -487,6 +852,11 @@ export class SorobanEventParser { return bytes.toString("hex"); } + private decodeBytes32HexFromMap(val: xdr.ScVal): string { + const bytes: Buffer = scValToNative(val); + return bytes.toString("hex"); + } + /** * Converts a Soroban map ScVal into a plain JS Record keyed by field name. */ diff --git a/app/backend/src/ingestion/types/contract-event.types.ts b/app/backend/src/ingestion/types/contract-event.types.ts index d5941d47..e27614ef 100644 --- a/app/backend/src/ingestion/types/contract-event.types.ts +++ b/app/backend/src/ingestion/types/contract-event.types.ts @@ -7,12 +7,34 @@ export type SorobanEventType = | "EscrowDeposited" | "EscrowWithdrawn" | "EscrowRefunded" + | "EscrowDisputed" + | "EscrowFinalized" + | "PartialPayment" + | "ArbiterVoteCast" + | "DisputeResolved" + | "DisputeTimeoutSet" + | "DisputeAutoResolved" | "PrivacyToggled" - | "ContractPaused" + | "EphemeralKeyRegistered" + | "StealthWithdrawn" | "AdminChanged" + | "ContractInitialized" + | "ContractMigrated" + | "ContractPaused" | "ContractUpgraded" - | "EphemeralKeyRegistered" - | "StealthWithdrawn"; + | "DisputeExpiryActionSet" + | "DisputeTimeoutConfigSet" + | "EmergencyModeActivated" + | "FeeCollectorRotated" + | "FeeConfigChanged" + | "HookRegistered" + | "HookUnregistered" + | "PauseFlagsChanged" + | "PerAssetFeeSet" + | "PlatformWalletChanged" + | "UpgradeCompleted" + | "UpgradeStarted" + | "UpgradeWindowSet"; export interface BaseContractEvent { eventType: SorobanEventType; @@ -33,6 +55,8 @@ export interface BaseContractEvent { contractLedgerSequence?: number; } +// ── Escrow events ───────────────────────────────────────────────────────────── + export interface EscrowDepositedEvent extends BaseContractEvent { eventType: "EscrowDeposited"; commitment: string; // hex @@ -59,30 +83,75 @@ export interface EscrowRefundedEvent extends BaseContractEvent { amount: bigint; } -export interface PrivacyToggledEvent extends BaseContractEvent { - eventType: "PrivacyToggled"; +export interface EscrowDisputedEvent extends BaseContractEvent { + eventType: "EscrowDisputed"; + commitment: string; + arbiter: string; +} + +export interface EscrowFinalizedEvent extends BaseContractEvent { + eventType: "EscrowFinalized"; + commitment: string; owner: string; - enabled: boolean; + token: string; + totalAmount: bigint; } -export interface ContractPausedEvent extends BaseContractEvent { - eventType: "ContractPaused"; - admin: string; - paused: boolean; +export interface PartialPaymentEvent extends BaseContractEvent { + eventType: "PartialPayment"; + commitment: string; + payer: string; + token: string; + paymentAmount: bigint; + amountPaid: bigint; + amountDue: bigint; } -export interface AdminChangedEvent extends BaseContractEvent { - eventType: "AdminChanged"; - oldAdmin: string; - newAdmin: string; +// ── Dispute events ──────────────────────────────────────────────────────────── + +export interface ArbiterVoteCastEvent extends BaseContractEvent { + eventType: "ArbiterVoteCast"; + commitment: string; + arbiter: string; + resolveForOwner: boolean; + voteCount: number; + threshold: number; } -export interface ContractUpgradedEvent extends BaseContractEvent { - eventType: "ContractUpgraded"; - newWasmHash: string; - admin: string; +export interface DisputeResolvedEvent extends BaseContractEvent { + eventType: "DisputeResolved"; + commitment: string; + resolvedForOwner: boolean; + totalVotes: number; + threshold: number; + amount: bigint; +} + +export interface DisputeTimeoutSetEvent extends BaseContractEvent { + eventType: "DisputeTimeoutSet"; + commitment: string; + action: string; + expiresAt: bigint; +} + +export interface DisputeAutoResolvedEvent extends BaseContractEvent { + eventType: "DisputeAutoResolved"; + commitment: string; + action: string; + recipient: string; + amount: bigint; +} + +// ── Privacy events ──────────────────────────────────────────────────────────── + +export interface PrivacyToggledEvent extends BaseContractEvent { + eventType: "PrivacyToggled"; + owner: string; + enabled: boolean; } +// ── Stealth events ──────────────────────────────────────────────────────────── + /** Emitted when a sender registers an ephemeral public key and locks funds for a stealth recipient. */ export interface EphemeralKeyRegisteredEvent extends BaseContractEvent { eventType: "EphemeralKeyRegistered"; @@ -106,16 +175,154 @@ export interface StealthWithdrawnEvent extends BaseContractEvent { amount: bigint; } +// ── Admin events ────────────────────────────────────────────────────────────── + +export interface AdminChangedEvent extends BaseContractEvent { + eventType: "AdminChanged"; + oldAdmin: string; + newAdmin: string; +} + +export interface ContractInitializedEvent extends BaseContractEvent { + eventType: "ContractInitialized"; + admin: string; + contractVersion: number; + eventSchemaVersion: number; + paused: boolean; +} + +export interface ContractMigratedEvent extends BaseContractEvent { + eventType: "ContractMigrated"; + admin: string; + fromVersion: number; + toVersion: number; +} + +export interface ContractPausedEvent extends BaseContractEvent { + eventType: "ContractPaused"; + admin: string; + paused: boolean; +} + +export interface ContractUpgradedEvent extends BaseContractEvent { + eventType: "ContractUpgraded"; + newWasmHash: string; + admin: string; +} + +export interface DisputeExpiryActionSetEvent extends BaseContractEvent { + eventType: "DisputeExpiryActionSet"; + action: string; +} + +export interface DisputeTimeoutConfigSetEvent extends BaseContractEvent { + eventType: "DisputeTimeoutConfigSet"; + timeoutSecs: bigint; +} + +export interface EmergencyModeActivatedEvent extends BaseContractEvent { + eventType: "EmergencyModeActivated"; + admin: string; +} + +export interface FeeCollectorRotatedEvent extends BaseContractEvent { + eventType: "FeeCollectorRotated"; + newCollector: string; + rotationIndex: number; +} + +export interface FeeConfigChangedEvent extends BaseContractEvent { + eventType: "FeeConfigChanged"; + feeBps: number; +} + +export interface HookRegisteredEvent extends BaseContractEvent { + eventType: "HookRegistered"; + hookContract: string; +} + +export interface HookUnregisteredEvent extends BaseContractEvent { + eventType: "HookUnregistered"; + hookContract: string; +} + +export interface PauseFlagsChangedEvent extends BaseContractEvent { + eventType: "PauseFlagsChanged"; + admin: string; + flagsEnabled: bigint; + flagsDisabled: bigint; +} + +export interface PerAssetFeeSetEvent extends BaseContractEvent { + eventType: "PerAssetFeeSet"; + token: string; + feeBps: number; + arbiterBps: number; +} + +export interface PlatformWalletChangedEvent extends BaseContractEvent { + eventType: "PlatformWalletChanged"; + wallet: string; +} + +export interface UpgradeCompletedEvent extends BaseContractEvent { + eventType: "UpgradeCompleted"; + admin: string; + oldVersion: number; + newVersion: number; +} + +export interface UpgradeStartedEvent extends BaseContractEvent { + eventType: "UpgradeStarted"; + admin: string; + oldVersion: number; + newVersion: number; + newWasmHash: string; + windowStart: bigint; + windowEnd: bigint; +} + +export interface UpgradeWindowSetEvent extends BaseContractEvent { + eventType: "UpgradeWindowSet"; + admin: string; + windowStart: bigint; + windowEnd: bigint; +} + +// ── Union types ─────────────────────────────────────────────────────────────── + export type RustAcademyContractEvent = | EscrowDepositedEvent | EscrowWithdrawnEvent | EscrowRefundedEvent + | EscrowDisputedEvent + | EscrowFinalizedEvent + | PartialPaymentEvent + | ArbiterVoteCastEvent + | DisputeResolvedEvent + | DisputeTimeoutSetEvent + | DisputeAutoResolvedEvent | PrivacyToggledEvent - | ContractPausedEvent + | EphemeralKeyRegisteredEvent + | StealthWithdrawnEvent | AdminChangedEvent + | ContractInitializedEvent + | ContractMigratedEvent + | ContractPausedEvent | ContractUpgradedEvent - | EphemeralKeyRegisteredEvent - | StealthWithdrawnEvent; + | DisputeExpiryActionSetEvent + | DisputeTimeoutConfigSetEvent + | EmergencyModeActivatedEvent + | FeeCollectorRotatedEvent + | FeeConfigChangedEvent + | HookRegisteredEvent + | HookUnregisteredEvent + | PauseFlagsChangedEvent + | PerAssetFeeSetEvent + | PlatformWalletChangedEvent + | UpgradeCompletedEvent + | UpgradeStartedEvent + | UpgradeWindowSetEvent; export type EscrowEvent = | EscrowDepositedEvent @@ -125,6 +332,27 @@ export type EscrowEvent = export type AdminEvent = | ContractPausedEvent | AdminChangedEvent - | ContractUpgradedEvent; + | ContractUpgradedEvent + | ContractInitializedEvent + | ContractMigratedEvent + | EmergencyModeActivatedEvent + | FeeCollectorRotatedEvent + | FeeConfigChangedEvent + | HookRegisteredEvent + | HookUnregisteredEvent + | PauseFlagsChangedEvent + | PerAssetFeeSetEvent + | PlatformWalletChangedEvent + | UpgradeCompletedEvent + | UpgradeStartedEvent + | UpgradeWindowSetEvent + | DisputeExpiryActionSetEvent + | DisputeTimeoutConfigSetEvent; export type StealthEvent = EphemeralKeyRegisteredEvent | StealthWithdrawnEvent; + +export type DisputeEvent = + | ArbiterVoteCastEvent + | DisputeResolvedEvent + | DisputeTimeoutSetEvent + | DisputeAutoResolvedEvent;