> ## Documentation Index
> Fetch the complete documentation index at: https://core.anylayer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Identity SBT Events

> Complete reference for all Identity SBT contract events

## Overview

The ZKScore Identity SBT contract emits events for all significant state changes. These events are essential for tracking identity lifecycle, monitoring contract activity, and building off-chain applications.

<Tip>
  Events are stored in the blockchain and can be queried by indexers. They provide a reliable way to track contract state changes and build real-time applications.
</Tip>

## Standard ERC-721 Events

### Transfer

Emitted when a token is transferred from one address to another.

```solidity theme={null}
event Transfer(
    address indexed from,
    address indexed to,
    uint256 indexed tokenId
);
```

**Parameters:**

* `from` (address indexed): The previous owner of the token
* `to` (address indexed): The new owner of the token
* `tokenId` (uint256 indexed): The ID of the token

**When Emitted:**

* When a token is minted (`from` is zero address)
* When a token is transferred between addresses
* When a token is burned (`to` is zero address)

**Note:** This event is not emitted for activated (soulbound) tokens since they cannot be transferred.

**Example Usage:**

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Listen for all transfer events
  contract.on('Transfer', (from, to, tokenId, event) => {
    console.log(`Token ${tokenId} transferred from ${from} to ${to}`);
  });

  // Filter for specific transfers
  const filter = contract.filters.Transfer(null, '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
  contract.on(filter, (from, to, tokenId, event) => {
    console.log(`Token ${tokenId} transferred to alice`);
  });

  // Get historical transfers
  async function getTransfers(tokenId) {
    const filter = contract.filters.Transfer(null, null, tokenId);
    const events = await contract.queryFilter(filter);
    return events;
  }
  ```

  ```python Python theme={null}
  # Listen for transfer events
  def handle_transfer(event):
      from_addr = event['args']['from']
      to_addr = event['args']['to']
      token_id = event['args']['tokenId']
      print(f"Token {token_id} transferred from {from_addr} to {to_addr}")

  # Set up event listener
  contract.events.Transfer().on('data', handle_transfer)

  # Filter for specific transfers
  filter = contract.events.Transfer.createFilter(
      fromBlock='latest',
      argument_filters={'to': '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'}
  )

  # Get historical transfers
  def get_transfers(token_id):
      filter = contract.events.Transfer.createFilter(
          fromBlock=0,
          argument_filters={'tokenId': token_id}
      )
      events = filter.get_all_entries()
      return events
  ```
</CodeGroup>

### Approval

Emitted when an address is approved to transfer a specific token.

```solidity theme={null}
event Approval(
    address indexed owner,
    address indexed approved,
    uint256 indexed tokenId
);
```

**Parameters:**

* `owner` (address indexed): The owner of the token
* `approved` (address indexed): The approved address
* `tokenId` (uint256 indexed): The ID of the token

**When Emitted:**

* When `approve()` is called
* When approval is revoked (approved address is zero)

**Note:** This event is not emitted for activated (soulbound) tokens since they cannot be transferred.

### ApprovalForAll

Emitted when an operator is approved or revoked for all tokens.

```solidity theme={null}
event ApprovalForAll(
    address indexed owner,
    address indexed operator,
    bool approved
);
```

**Parameters:**

* `owner` (address indexed): The owner of the tokens
* `operator` (address indexed): The operator address
* `approved` (bool): True if approved, false if revoked

**When Emitted:**

* When `setApprovalForAll()` is called

## Soulbound Token Events

### IdentityMinted

Emitted when a new identity token is minted.

```solidity theme={null}
event IdentityMinted(
    address indexed to,
    uint256 indexed tokenId,
    string name
);
```

**Parameters:**

* `to` (address indexed): The address the token was minted to
* `tokenId` (uint256 indexed): The ID of the minted token
* `name` (string): The ZKS ID name

**When Emitted:**

* When `mint()` is called successfully

**Example Usage:**

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Listen for identity minting events
  contract.on('IdentityMinted', (to, tokenId, name, event) => {
    console.log(`New identity minted: ${name} (ID: ${tokenId}) to ${to}`);
  });

  // Filter for specific user
  const filter = contract.filters.IdentityMinted('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
  contract.on(filter, (to, tokenId, name, event) => {
    console.log(`Alice's identity minted: ${name} (ID: ${tokenId})`);
  });

  // Get all minted identities
  async function getAllMintedIdentities() {
    const filter = contract.filters.IdentityMinted();
    const events = await contract.queryFilter(filter);
    return events.map(event => ({
      to: event.args.to,
      tokenId: event.args.tokenId,
      name: event.args.name,
      blockNumber: event.blockNumber,
      transactionHash: event.transactionHash
    }));
  }
  ```

  ```python Python theme={null}
  # Listen for identity minting events
  def handle_identity_minted(event):
      to = event['args']['to']
      token_id = event['args']['tokenId']
      name = event['args']['name']
      print(f"New identity minted: {name} (ID: {token_id}) to {to}")

  # Set up event listener
  contract.events.IdentityMinted().on('data', handle_identity_minted)

  # Filter for specific user
  filter = contract.events.IdentityMinted.createFilter(
      fromBlock='latest',
      argument_filters={'to': '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'}
  )

  # Get all minted identities
  def get_all_minted_identities():
      filter = contract.events.IdentityMinted.createFilter(fromBlock=0)
      events = filter.get_all_entries()
      return [{
          'to': event['args']['to'],
          'tokenId': event['args']['tokenId'],
          'name': event['args']['name'],
          'blockNumber': event['blockNumber'],
          'transactionHash': event['transactionHash']
      } for event in events]
  ```
</CodeGroup>

### IdentityActivated

Emitted when an identity token is activated (made soulbound).

```solidity theme={null}
event IdentityActivated(
    uint256 indexed tokenId,
    address indexed owner
);
```

**Parameters:**

* `tokenId` (uint256 indexed): The ID of the activated token
* `owner` (address indexed): The owner of the token

**When Emitted:**

* When `activate()` is called successfully

**Example Usage:**

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Listen for activation events
  contract.on('IdentityActivated', (tokenId, owner, event) => {
    console.log(`Identity ${tokenId} activated by ${owner}`);
  });

  // Filter for specific token
  const filter = contract.filters.IdentityActivated(123);
  contract.on(filter, (tokenId, owner, event) => {
    console.log(`Token 123 activated by ${owner}`);
  });

  // Get activation history
  async function getActivationHistory(tokenId) {
    const filter = contract.filters.IdentityActivated(tokenId);
    const events = await contract.queryFilter(filter);
    return events;
  }
  ```

  ```python Python theme={null}
  # Listen for activation events
  def handle_identity_activated(event):
      token_id = event['args']['tokenId']
      owner = event['args']['owner']
      print(f"Identity {token_id} activated by {owner}")

  # Set up event listener
  contract.events.IdentityActivated().on('data', handle_identity_activated)

  # Filter for specific token
  filter = contract.events.IdentityActivated.createFilter(
      fromBlock='latest',
      argument_filters={'tokenId': 123}
  )

  # Get activation history
  def get_activation_history(token_id):
      filter = contract.events.IdentityActivated.createFilter(
          fromBlock=0,
          argument_filters={'tokenId': token_id}
      )
      events = filter.get_all_entries()
      return events
  ```
</CodeGroup>

### MetadataUpdated

Emitted when a token's metadata URI is updated.

```solidity theme={null}
event MetadataUpdated(
    uint256 indexed tokenId,
    string newURI
);
```

**Parameters:**

* `tokenId` (uint256 indexed): The ID of the token
* `newURI` (string): The new metadata URI

**When Emitted:**

* When `setTokenURI()` is called successfully

**Note:** This event is not emitted for activated tokens since their metadata is immutable.

### SoulboundStatusChanged

Emitted when a token's soulbound status changes.

```solidity theme={null}
event SoulboundStatusChanged(
    uint256 indexed tokenId,
    bool isSoulbound
);
```

**Parameters:**

* `tokenId` (uint256 indexed): The ID of the token
* `isSoulbound` (bool): True if the token is now soulbound, false otherwise

**When Emitted:**

* When `activate()` is called (isSoulbound becomes true)
* When soulbound status is changed by admin (rare)

## Event Indexing

### Indexed Parameters

Events have up to 3 indexed parameters that can be filtered efficiently:

```solidity theme={null}
event IdentityMinted(
    address indexed to,        // Indexed - can filter by address
    uint256 indexed tokenId,   // Indexed - can filter by token ID
    string name                // Not indexed - cannot filter efficiently
);
```

### Filtering Examples

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Filter by indexed parameters
  const filter1 = contract.filters.IdentityMinted('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
  const filter2 = contract.filters.IdentityMinted(null, 123);
  const filter3 = contract.filters.IdentityMinted('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 123);

  // Filter by block range
  async function getEventsInRange(startBlock, endBlock) {
    const filter = contract.filters.IdentityMinted();
    const events = await contract.queryFilter(filter, startBlock, endBlock);
    return events;
  }

  // Filter by multiple criteria
  async function getRecentMints(limit = 10) {
    const currentBlock = await provider.getBlockNumber();
    const startBlock = currentBlock - 1000; // Last 1000 blocks
    
    const filter = contract.filters.IdentityMinted();
    const events = await contract.queryFilter(filter, startBlock, currentBlock);
    
    return events.slice(-limit); // Last 10 events
  }
  ```

  ```python Python theme={null}
  # Filter by indexed parameters
  filter1 = contract.events.IdentityMinted.createFilter(
      argument_filters={'to': '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'}
  )
  filter2 = contract.events.IdentityMinted.createFilter(
      argument_filters={'tokenId': 123}
  )
  filter3 = contract.events.IdentityMinted.createFilter(
      argument_filters={'to': '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 'tokenId': 123}
  )

  # Filter by block range
  def get_events_in_range(start_block, end_block):
      filter = contract.events.IdentityMinted.createFilter(
          fromBlock=start_block,
          toBlock=end_block
      )
      events = filter.get_all_entries()
      return events

  # Filter by multiple criteria
  def get_recent_mints(limit=10):
      current_block = w3.eth.block_number
      start_block = current_block - 1000  # Last 1000 blocks
      
      filter = contract.events.IdentityMinted.createFilter(
          fromBlock=start_block,
          toBlock=current_block
      )
      events = filter.get_all_entries()
      
      return events[-limit:]  # Last 10 events
  ```
</CodeGroup>

## Event Monitoring

### Real-time Monitoring

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Set up real-time event monitoring
  class IdentityEventMonitor {
    constructor(contract) {
      this.contract = contract;
      this.listeners = new Map();
    }
    
    startMonitoring() {
      // Monitor all identity events
      this.contract.on('IdentityMinted', (to, tokenId, name, event) => {
        this.handleEvent('IdentityMinted', {
          to,
          tokenId,
          name,
          blockNumber: event.blockNumber,
          transactionHash: event.transactionHash
        });
      });
      
      this.contract.on('IdentityActivated', (tokenId, owner, event) => {
        this.handleEvent('IdentityActivated', {
          tokenId,
          owner,
          blockNumber: event.blockNumber,
          transactionHash: event.transactionHash
        });
      });
    }
    
    handleEvent(eventType, data) {
      console.log(`Event: ${eventType}`, data);
      
      // Notify listeners
      if (this.listeners.has(eventType)) {
        this.listeners.get(eventType).forEach(callback => {
          callback(data);
        });
      }
    }
    
    on(eventType, callback) {
      if (!this.listeners.has(eventType)) {
        this.listeners.set(eventType, []);
      }
      this.listeners.get(eventType).push(callback);
    }
    
    off(eventType, callback) {
      if (this.listeners.has(eventType)) {
        const callbacks = this.listeners.get(eventType);
        const index = callbacks.indexOf(callback);
        if (index > -1) {
          callbacks.splice(index, 1);
        }
      }
    }
  }

  // Usage
  const monitor = new IdentityEventMonitor(contract);
  monitor.startMonitoring();

  monitor.on('IdentityMinted', (data) => {
    console.log('New identity minted:', data);
  });

  monitor.on('IdentityActivated', (data) => {
    console.log('Identity activated:', data);
  });
  ```

  ```python Python theme={null}
  # Set up real-time event monitoring
  class IdentityEventMonitor:
      def __init__(self, contract):
          self.contract = contract
          self.listeners = {}
      
      def start_monitoring(self):
          # Monitor all identity events
          self.contract.events.IdentityMinted().on('data', self.handle_identity_minted)
          self.contract.events.IdentityActivated().on('data', self.handle_identity_activated)
      
      def handle_identity_minted(self, event):
          data = {
              'to': event['args']['to'],
              'tokenId': event['args']['tokenId'],
              'name': event['args']['name'],
              'blockNumber': event['blockNumber'],
              'transactionHash': event['transactionHash']
          }
          self.handle_event('IdentityMinted', data)
      
      def handle_identity_activated(self, event):
          data = {
              'tokenId': event['args']['tokenId'],
              'owner': event['args']['owner'],
              'blockNumber': event['blockNumber'],
              'transactionHash': event['transactionHash']
          }
          self.handle_event('IdentityActivated', data)
      
      def handle_event(self, event_type, data):
          print(f"Event: {event_type}", data)
          
          # Notify listeners
          if event_type in self.listeners:
              for callback in self.listeners[event_type]:
                  callback(data)
      
      def on(self, event_type, callback):
          if event_type not in self.listeners:
              self.listeners[event_type] = []
          self.listeners[event_type].append(callback)
      
      def off(self, event_type, callback):
          if event_type in self.listeners:
              if callback in self.listeners[event_type]:
                  self.listeners[event_type].remove(callback)

  # Usage
  monitor = IdentityEventMonitor(contract)
  monitor.start_monitoring()

  def on_identity_minted(data):
      print('New identity minted:', data)

  def on_identity_activated(data):
      print('Identity activated:', data)

  monitor.on('IdentityMinted', on_identity_minted)
  monitor.on('IdentityActivated', on_identity_activated)
  ```
</CodeGroup>

### Historical Event Queries

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Get all events for a specific token
  async function getTokenEvents(tokenId) {
    const events = {
      minted: await contract.queryFilter(contract.filters.IdentityMinted(null, tokenId)),
      activated: await contract.queryFilter(contract.filters.IdentityActivated(tokenId)),
      transfers: await contract.queryFilter(contract.filters.Transfer(null, null, tokenId))
    };
    
    return events;
  }

  // Get events by block range
  async function getEventsByBlockRange(startBlock, endBlock) {
    const filter = contract.filters.IdentityMinted();
    const events = await contract.queryFilter(filter, startBlock, endBlock);
    
    return events.map(event => ({
      type: 'IdentityMinted',
      to: event.args.to,
      tokenId: event.args.tokenId,
      name: event.args.name,
      blockNumber: event.blockNumber,
      transactionHash: event.transactionHash
    }));
  }

  // Get recent events
  async function getRecentEvents(limit = 100) {
    const currentBlock = await provider.getBlockNumber();
    const startBlock = currentBlock - 10000; // Last 10,000 blocks
    
    const filter = contract.filters.IdentityMinted();
    const events = await contract.queryFilter(filter, startBlock, currentBlock);
    
    return events.slice(-limit);
  }
  ```

  ```python Python theme={null}
  # Get all events for a specific token
  def get_token_events(token_id):
      events = {
          'minted': contract.events.IdentityMinted.createFilter(
              argument_filters={'tokenId': token_id}
          ).get_all_entries(),
          'activated': contract.events.IdentityActivated.createFilter(
              argument_filters={'tokenId': token_id}
          ).get_all_entries(),
          'transfers': contract.events.Transfer.createFilter(
              argument_filters={'tokenId': token_id}
          ).get_all_entries()
      }
      return events

  # Get events by block range
  def get_events_by_block_range(start_block, end_block):
      filter = contract.events.IdentityMinted.createFilter(
          fromBlock=start_block,
          toBlock=end_block
      )
      events = filter.get_all_entries()
      
      return [{
          'type': 'IdentityMinted',
          'to': event['args']['to'],
          'tokenId': event['args']['tokenId'],
          'name': event['args']['name'],
          'blockNumber': event['blockNumber'],
          'transactionHash': event['transactionHash']
      } for event in events]

  # Get recent events
  def get_recent_events(limit=100):
      current_block = w3.eth.block_number
      start_block = current_block - 10000  # Last 10,000 blocks
      
      filter = contract.events.IdentityMinted.createFilter(
          fromBlock=start_block,
          toBlock=current_block
      )
      events = filter.get_all_entries()
      
      return events[-limit:]
  ```
</CodeGroup>

## Event Analytics

### Event Statistics

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Analyze event patterns
  async function analyzeEvents() {
    const currentBlock = await provider.getBlockNumber();
    const startBlock = currentBlock - 100000; // Last 100,000 blocks
    
    const filter = contract.filters.IdentityMinted();
    const events = await contract.queryFilter(filter, startBlock, currentBlock);
    
    const stats = {
      totalMints: events.length,
      uniqueUsers: new Set(events.map(e => e.args.to)).size,
      averageMintsPerBlock: events.length / 100000,
      mostActiveUser: getMostActiveUser(events),
      mintingTrend: getMintingTrend(events)
    };
    
    return stats;
  }

  function getMostActiveUser(events) {
    const userCounts = {};
    events.forEach(event => {
      const user = event.args.to;
      userCounts[user] = (userCounts[user] || 0) + 1;
    });
    
    return Object.entries(userCounts)
      .sort(([,a], [,b]) => b - a)[0];
  }

  function getMintingTrend(events) {
    const blockCounts = {};
    events.forEach(event => {
      const block = event.blockNumber;
      blockCounts[block] = (blockCounts[block] || 0) + 1;
    });
    
    return Object.entries(blockCounts)
      .sort(([a], [b]) => a - b)
      .map(([block, count]) => ({ block: parseInt(block), count }));
  }
  ```

  ```python Python theme={null}
  # Analyze event patterns
  def analyze_events():
      current_block = w3.eth.block_number
      start_block = current_block - 100000  # Last 100,000 blocks
      
      filter = contract.events.IdentityMinted.createFilter(
          fromBlock=start_block,
          toBlock=current_block
      )
      events = filter.get_all_entries()
      
      stats = {
          'totalMints': len(events),
          'uniqueUsers': len(set(event['args']['to'] for event in events)),
          'averageMintsPerBlock': len(events) / 100000,
          'mostActiveUser': get_most_active_user(events),
          'mintingTrend': get_minting_trend(events)
      }
      
      return stats

  def get_most_active_user(events):
      user_counts = {}
      for event in events:
          user = event['args']['to']
          user_counts[user] = user_counts.get(user, 0) + 1
      
      return max(user_counts.items(), key=lambda x: x[1])

  def get_minting_trend(events):
      block_counts = {}
      for event in events:
          block = event['blockNumber']
          block_counts[block] = block_counts.get(block, 0) + 1
      
      return sorted(block_counts.items(), key=lambda x: x[0])
  ```
</CodeGroup>

## Best Practices

### Event Handling

1. **Always handle errors**: Event listeners can fail, implement proper error handling
2. **Use filters efficiently**: Filter events by indexed parameters when possible
3. **Monitor gas costs**: Event queries can be expensive for large ranges
4. **Implement rate limiting**: Don't overwhelm your application with too many events
5. **Store event data**: Consider storing important event data in a database

### Performance Optimization

1. **Use indexed parameters**: Filter by indexed parameters for better performance
2. **Limit block ranges**: Query smaller block ranges to avoid timeouts
3. **Cache results**: Cache frequently accessed event data
4. **Use pagination**: Implement pagination for large event datasets
5. **Monitor memory usage**: Large event queries can consume significant memory

## Related Documentation

* [Contract Overview](/contracts/identity-sbt/overview) - Contract architecture and features
* [Functions Reference](/contracts/identity-sbt/functions) - Complete function documentation
* [Integration Guide](/contracts/identity-sbt/integration) - Integration examples
* [Security Guide](/contracts/identity-sbt/security) - Security considerations
* [Deployment Guide](/contracts/identity-sbt/deployment) - Deployment instructions
