> For the complete documentation index, see [llms.txt](https://snowball-mns.gitbook.io/snowball/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://snowball-mns.gitbook.io/snowball/decentralized-identity-layer/technical-documentation/events-documentation.md).

# Events Documentation

### Events Overview

Events in DiD Protocol provide real-time updates about changes to names, ownership, addresses, and other state changes in the system. This allows integrators to maintain accurate, up-to-date indexes of the naming system.

### Core Events

#### Registration Events

**RegisterNameEvent**

Emitted when a name (domain or subdomain) is registered.

```move
struct RegisterNameEvent has drop, store {
    owner: address,
    domain_name: String,
    domain_suffix: Option<String>,
    subdomain_name: Option<String>,
    registration_fee_octas: u64,
    expiration_time_secs: u64,
    registration_duration_secs: u64
}
```

* `owner`: Address of the new name owner
* `domain_name`: The registered domain name
* `domain_suffix`: Optional domain suffix (e.g., "move")
* `subdomain_name`: Optional subdomain name if registering a subdomain
* `registration_fee_octas`: Registration fee paid in Octas
* `expiration_time_secs`: Unix timestamp when the registration expires
* `registration_duration_secs`: Duration of the registration in seconds

**RenewNameEvent**

Emitted when a name's registration is renewed.

```move
struct RenewNameEvent has drop, store {
    domain_name: String,
    domain_suffix: Option<String>,
    subdomain_name: Option<String>,
    renewal_fee_octas: u64,
    expiration_time_secs: u64,
    renewal_duration_secs: u64,
    target_address: Option<address>,
    is_primary_name: bool
}
```

* `domain_name`: The renewed domain name
* `domain_suffix`: Optional domain suffix
* `subdomain_name`: Optional subdomain name
* `renewal_fee_octas`: Renewal fee paid in Octas
* `expiration_time_secs`: New expiration timestamp
* `renewal_duration_secs`: Duration of renewal in seconds
* `target_address`: Current target address of the name
* `is_primary_name`: Whether this name is set as primary name for its target address

#### Transfer Events

**TransferNameEvent**

Emitted when a name is transferred to a new owner.

```move
struct TransferNameEvent has drop, store {
    domain_name: String,
    domain_suffix: Option<String>, 
    subdomain_name: Option<String>,
    from_addr: address,
    to_addr: address
}
```

* `domain_name`: The transferred domain name
* `domain_suffix`: Optional domain suffix
* `subdomain_name`: Optional subdomain name
* `from_addr`: Previous owner's address
* `to_addr`: New owner's address

#### Address Resolution Events

**SetTargetAddressEvent**

Emitted when a name's target address is updated.

```move
struct SetTargetAddressEvent has drop, store {
    domain_name: String,
    domain_suffix: Option<String>,
    subdomain_name: Option<String>,
    expiration_time_secs: u64,
    new_address: Option<address>
}
```

* `domain_name`: The domain name
* `domain_suffix`: Optional domain suffix
* `subdomain_name`: Optional subdomain name
* `expiration_time_secs`: Current expiration timestamp
* `new_address`: New target address (None if cleared)

**SetTargetAddressByCAIPEvent**

Emitted when a cross-chain address is set for a name.

```move
struct SetTargetAddressByCAIPEvent has drop, store {
    domain_name: String,
    domain_suffix: Option<String>,
    subdomain_name: Option<String>,
    new_address: Option<String>,
    caip: String
}
```

* `domain_name`: The domain name
* `domain_suffix`: Optional domain suffix
* `subdomain_name`: Optional subdomain name
* `new_address`: New target address in string format
* `caip`: CAIP identifier for the chain

#### Reverse Resolution Events

**SetReverseLookupEvent**

Emitted when a reverse lookup (primary name) is set or cleared for an address.

```move
struct SetReverseLookupEvent has drop, store {
    account_addr: address,
    prev_domain_name: Option<String>,
    prev_domain_suffix: Option<String>, 
    prev_subdomain_name: Option<String>,
    prev_expiration_time_secs: Option<u64>,
    curr_domain_name: Option<String>,
    curr_domain_suffix: Option<String>,
    curr_subdomain_name: Option<String>,
    curr_expiration_time_secs: Option<u64>
}
```

* `account_addr`: Address whose primary name is being set/cleared
* `prev_*`: Previous name details (if any)
* `curr_*`: New name details (None if clearing)

#### Metadata Events

**SetAvatarUrlEvent**

Emitted when an avatar URL is set for a name.

```move
struct SetAvatarUrlEvent has drop, store {
    domain_name: String,
    domain_suffix: Option<String>,
    subdomain_name: Option<String>,
    avatar_ipfs_hash: Option<String>
}
```

* `domain_name`: The domain name
* `domain_suffix`: Optional domain suffix
* `subdomain_name`: Optional subdomain name
* `avatar_ipfs_hash`: IPFS hash of the avatar (None if cleared)

**SetKeyValueRecordEvent**

Emitted when a key-value record is set for a name.

```move
struct SetKeyValueRecordEvent has drop, store {
    domain_name: String,
    domain_suffix: Option<String>,
    subdomain_name: Option<String>,
    key: String,
    value: Option<String>
}
```

* `domain_name`: The domain name
* `domain_suffix`: Optional domain suffix
* `subdomain_name`: Optional subdomain name
* `key`: Record key
* `value`: Record value (None if cleared)

#### Marketplace Events

**ListDomainForSaleEvent**

Emitted when a domain is listed for sale.

```move
struct ListDomainForSaleEvent has drop, store {
    domain_name: String,
    domain_suffix: Option<String>,
    price: u64,
    duration_secs: u64,
    expiration_time: u64,
    seller: address
}
```

* `domain_name`: The listed domain name
* `domain_suffix`: Optional domain suffix
* `price`: Listing price in Octas
* `duration_secs`: Duration of the listing
* `expiration_time`: When the listing expires
* `seller`: Address of the seller

**ListingUpdatedEvent**

Emitted when a domain listing is updated.

```move
struct ListingUpdatedEvent has drop, store {
    domain_name: String,
    domain_suffix: Option<String>,
    old_price: u64,
    new_price: u64,
    old_expiration_time: u64,
    new_expiration_time: u64,
    duration_secs: u64,
    seller: address
}
```

**ListingBuyEvent**

Emitted when a listed domain is purchased.

```move
struct ListingBuyEvent has drop, store {
    domain_name: String,
    domain_suffix: Option<String>,
    price: u64,
    seller: address,
    buyer: address
}
```

**ListingCancelledEvent**

Emitted when a domain listing is cancelled.

```move
struct ListingCancelledEvent has drop, store {
    domain_name: String,
    domain_suffix: Option<String>,
    price: u64,
    seller: address
}
```

### Best Practices for Indexing

1. **Handle Reorgs**: Always be prepared for blockchain reorganizations by implementing proper reorg handling in your indexer.
2. **Process Events in Order**: Events should be processed in the order they appear in blocks to maintain consistency.
3. **State Validation**: Periodically validate your indexed state against on-chain data to ensure accuracy.
4. **Handle Missing Events**: Implement retry logic for missed events and periodic state reconciliation.
5. **Track Event Versions**: If the event structure changes in future updates, maintain version compatibility in your indexer.

### Technical Considerations

* All timestamps are in Unix seconds
* Fees and prices are in Octas (1 APT = 100000000 Octas)
* String values for names should be stored as normalized lowercase
* CAIP IDs follow the CAIP-2 specification for chain identification
* Handle Option types appropriately - they may be None/null
