mirror of
https://github.com/luxfi/graph.git
synced 2026-09-24 00:26:07 +00:00
indexer: full ERC-3643 + ONCHAINID event ingestion
Adds the missing topic0 signatures + handlers so the resolvers under
resolvers/securities/ + resolvers/identity/ are actually fed live data:
events.go (new constants):
- IToken: AddressFrozen, TokensFrozen, TokensUnfrozen, Paused, Unpaused,
RecoverySuccess, UpdatedTokenInformation,
IdentityRegistryAdded, ComplianceAdded
- IdentityRegistry / IdentityRegistryStorage:
IdentityRegistered/Removed/Updated, CountryUpdated, IdentityStored
- ONCHAINID (ERC-734/735):
ClaimAdded/Removed/Changed, KeyAdded/Removed,
Approved (exec), Executed (exec)
- TrustedIssuersRegistry / ClaimTopicsRegistry:
TrustedIssuerAdded/Removed, ClaimTopicsUpdated,
ClaimTopicAdded/Removed
- ModularCompliance + IModule:
ModuleAdded/Removed, TokenBound/Unbound, ModuleInteraction
- SecuritiesTopics() returns the full set, appended into knownTopics().
indexer_securities.go (new):
- Per-event handlers writing structured entities through Store.SetEntity.
- Entity types match the resolver expectations:
SecurityTransfer, TransferAgentAction, FrozenAccount, FrozenTokens,
IdentityRegistryAction, OnchainIdClaim, OnchainIdKey, ComplianceAction,
TrustedIssuerAction, ClaimTopicAction, SecuritiesEvent.
- Decoders for indexed bool / uint256 / address topics.
indexer.go (processLog dispatch):
- Adds case branches for each new topic0 to the appropriate handler.
Result: any deployed @luxfi/contracts SecurityToken (T-REX), IdentityRegistry,
ONCHAINID, TrustedIssuersRegistry, ClaimTopicsRegistry, or ModularCompliance
contract is now indexed by `graph` out of the box, queryable via the existing
GraphQL resolvers — no per-deployment manifest needed.
Build: go build ./indexer/... → exit 0
This commit is contained in:
@@ -48,6 +48,114 @@ const (
|
||||
SigFlash = "0xbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca633"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// ERC-3643 (T-REX) `IToken` events
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const (
|
||||
// AddressFrozen(address indexed user, bool indexed isFrozen, address indexed owner)
|
||||
SigAddressFrozen = "0x7fa523c84ab8d7fc5b72f08b9e46dbbf10c39e119a075b3e317002d14bc9f436"
|
||||
|
||||
// TokensFrozen(address indexed user, uint256 amount)
|
||||
SigTokensFrozen = "0xa065e63c631c86f1b9f66a4a2f63f2093bf1c2168d23290259dbd969e0222a45"
|
||||
|
||||
// TokensUnfrozen(address indexed user, uint256 amount)
|
||||
SigTokensUnfrozen = "0x9bed35cb62ad0dba04f9d5bfee4b5bc91443e77da8a65c4c84834c51bb08b0d6"
|
||||
|
||||
// Paused(address user) — T-REX token pause
|
||||
SigSecurityPaused = "0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258"
|
||||
|
||||
// Unpaused(address user)
|
||||
SigSecurityUnpaused = "0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa"
|
||||
|
||||
// RecoverySuccess(address indexed lostWallet, address indexed newWallet, address indexed investorOnchainID)
|
||||
SigRecoverySuccess = "0xf0c9129a94f30f1caaceb63e44b9811d0a3edf1d6c23757f346093af5553fed0"
|
||||
|
||||
// UpdatedTokenInformation(string indexed name, string indexed symbol, uint8 decimals, string version, address indexed onchainID)
|
||||
SigUpdatedTokenInformation = "0x6a1105ac8148a3c319adbc369f9072573e8a11d3a3d195e067e7c40767ec54d1"
|
||||
|
||||
// IdentityRegistryAdded(address indexed identityRegistry)
|
||||
SigIdentityRegistryAdded = "0xd2be862d755bca7e0d39772b2cab3a5578da9c285f69199f4c063c2294a7f36c"
|
||||
|
||||
// ComplianceAdded(address indexed compliance)
|
||||
SigComplianceAdded = "0x7f3a888862559648ec01d97deb7b5012bff86dc91e654a1de397170db40e35b6"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// ERC-3643 IdentityRegistry / IdentityRegistryStorage
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const (
|
||||
SigIdentityRegistered = "0x6ae73635c50d24a45af6fbd5e016ac4bed179addbc8bf24e04ff0fcc6d33af19"
|
||||
SigIdentityRemoved = "0x59d6590e225b81befe259af056324092801080acbb7feab310eb34678871f327"
|
||||
SigIdentityUpdated = "0xe98082932c8056a0f514da9104e4a66bc2cbaef102ad59d90c4b24220ebf6010"
|
||||
SigCountryUpdated = "0x04ed3b726495c2dca1ff1215d9ca54e1a4030abb5e82b0f6ce55702416cee853"
|
||||
SigIdentityStored = "0x0030dea7e9c9afaa2e3c9810f2fc9b5181f1bad74ca5a8db85f746a33585e747"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// ONCHAINID — ERC-734 (key mgmt) + ERC-735 (claims)
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const (
|
||||
// ClaimAdded/Removed/Changed(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri)
|
||||
SigClaimAdded = "0x46149b18aa084502c3f12bc75e19eda8bda8d102b82cce8474677a6d0d5f43c5"
|
||||
SigClaimRemoved = "0x3cf57863a89432c61c4a27073c6ee39e8a764bff5a05aebfbcdcdc80b2e6130a"
|
||||
SigClaimChanged = "0x3bab293fc00db832d7619a9299914251b8747c036867ec056cbd506f60135b13"
|
||||
|
||||
// KeyAdded/Removed(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType)
|
||||
SigKeyAdded = "0x480000bb1edad8ca1470381cc334b1917fbd51c6531f3a623ea8e0ec7e38a6e9"
|
||||
SigKeyRemoved = "0x585a4aef50f8267a92b32412b331b20f7f8b96f2245b253b9cc50dcc621d3397"
|
||||
|
||||
// Approved(uint256 indexed executionId, bool approved)
|
||||
SigOnchainIdApproved = "0xb3932da477fe5d6c8ff2eafef050c0f3a1af18fc07121001482600f36f3715d8"
|
||||
|
||||
// Executed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data)
|
||||
SigOnchainIdExecuted = "0x1f920dbda597d7bf95035464170fa58d0a4b57f13a1c315ace6793b9f63688b8"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// ERC-3643 TrustedIssuersRegistry / ClaimTopicsRegistry
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const (
|
||||
SigTrustedIssuerAdded = "0xfedc33fd34859594822c0ff6f3f4f9fc279cc6d5cae53068f706a088e4500872"
|
||||
SigTrustedIssuerRemoved = "0x2214ded40113cc3fb63fc206cafee88270b0a903dac7245d54efdde30ebb0321"
|
||||
SigClaimTopicsUpdated = "0xec753cfc52044f61676f18a11e500093a9f2b1cd5e4942bc476f2b0438159bcf"
|
||||
SigClaimTopicAdded = "0x01c928b7f7ade2949e92366aa9454dbef3a416b731cf6ec786ba9595bbd814d6"
|
||||
SigClaimTopicRemoved = "0x0b1381093c776453c1bbe54fd68be1b235c65db61d099cb50d194b2991e0eec5"
|
||||
)
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// ERC-3643 ModularCompliance + IModule
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const (
|
||||
SigModuleAdded = "0xead6a006345da1073a106d5f32372d2d2204f46cb0b4bca8f5ebafcbbed12b8a"
|
||||
SigModuleRemoved = "0x0a1ee69f55c33d8467c69ca59ce2007a737a88603d75392972520bf67cb513b8"
|
||||
SigTokenBound = "0x2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b"
|
||||
SigTokenUnbound = "0x28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a"
|
||||
SigModuleInteraction = "0x20d79de70adcc6e9353d8a9a5646b46dc352710d0a310b1ad1f67faeca7ef891"
|
||||
)
|
||||
|
||||
// SecuritiesTopics returns every topic0 indexed by the securities resolvers.
|
||||
// Use this when constructing eth_getLogs filters or extending knownTopics().
|
||||
func SecuritiesTopics() []string {
|
||||
return []string{
|
||||
// IToken
|
||||
SigAddressFrozen, SigTokensFrozen, SigTokensUnfrozen,
|
||||
SigSecurityPaused, SigSecurityUnpaused, SigRecoverySuccess,
|
||||
SigUpdatedTokenInformation, SigIdentityRegistryAdded, SigComplianceAdded,
|
||||
// IdentityRegistry / Storage
|
||||
SigIdentityRegistered, SigIdentityRemoved, SigIdentityUpdated,
|
||||
SigCountryUpdated, SigIdentityStored,
|
||||
// ONCHAINID
|
||||
SigClaimAdded, SigClaimRemoved, SigClaimChanged,
|
||||
SigKeyAdded, SigKeyRemoved,
|
||||
SigOnchainIdApproved, SigOnchainIdExecuted,
|
||||
// Trusted issuers / topics registries
|
||||
SigTrustedIssuerAdded, SigTrustedIssuerRemoved, SigClaimTopicsUpdated,
|
||||
SigClaimTopicAdded, SigClaimTopicRemoved,
|
||||
// ModularCompliance + IModule
|
||||
SigModuleAdded, SigModuleRemoved, SigTokenBound, SigTokenUnbound, SigModuleInteraction,
|
||||
}
|
||||
}
|
||||
|
||||
// V4 events (PoolManager singleton pattern)
|
||||
const (
|
||||
// Initialize(bytes32 indexed id, address indexed currency0, address indexed currency1, uint24 fee, int24 tickSpacing, address hooks, uint160 sqrtPriceX96, int24 tick)
|
||||
|
||||
+68
-1
@@ -134,12 +134,15 @@ func parseHexUint64(s string) (uint64, error) {
|
||||
|
||||
// knownTopics returns all event topic0s we want to filter for.
|
||||
func knownTopics() []string {
|
||||
return []string{
|
||||
topics := []string{
|
||||
// AMM (V2/V3/V4)
|
||||
SigPairCreated, SigSwapV2, SigMintV2, SigBurnV2, SigSync, SigTransfer,
|
||||
SigPoolCreated, SigInitialize, SigSwapV3, SigMintV3, SigBurnV3,
|
||||
SigCollect, SigFlash,
|
||||
SigInitializeV4, SigModifyLiquidity, SigSwapV4,
|
||||
}
|
||||
// Securities — full ERC-3643 + ONCHAINID surface.
|
||||
return append(topics, SecuritiesTopics()...)
|
||||
}
|
||||
|
||||
// logEntry is a decoded eth_getLogs result entry.
|
||||
@@ -240,6 +243,70 @@ func (idx *Indexer) processLog(l *logEntry) {
|
||||
SigCollect, SigFlash, SigInitialize,
|
||||
SigInitializeV4, SigModifyLiquidity, SigSwapV4:
|
||||
// Recognized but storage for these types not yet wired
|
||||
|
||||
// ── ERC-3643 IToken ───────────────────────────────────────────────
|
||||
case SigAddressFrozen:
|
||||
idx.handleAddressFrozen(l, blockNum, txHash, logIdx)
|
||||
case SigTokensFrozen:
|
||||
idx.handleTokensFrozen(l, blockNum, txHash, logIdx, true)
|
||||
case SigTokensUnfrozen:
|
||||
idx.handleTokensFrozen(l, blockNum, txHash, logIdx, false)
|
||||
case SigSecurityPaused:
|
||||
idx.handleSecurityPause(l, blockNum, txHash, logIdx, true)
|
||||
case SigSecurityUnpaused:
|
||||
idx.handleSecurityPause(l, blockNum, txHash, logIdx, false)
|
||||
case SigRecoverySuccess:
|
||||
idx.handleRecoverySuccess(l, blockNum, txHash, logIdx)
|
||||
case SigUpdatedTokenInformation:
|
||||
idx.handleSimpleSecuritiesEvent(l, blockNum, txHash, logIdx, "UpdatedTokenInformation")
|
||||
case SigIdentityRegistryAdded:
|
||||
idx.handleSimpleSecuritiesEvent(l, blockNum, txHash, logIdx, "IdentityRegistryAdded")
|
||||
case SigComplianceAdded:
|
||||
idx.handleSimpleSecuritiesEvent(l, blockNum, txHash, logIdx, "ComplianceAdded")
|
||||
|
||||
// ── IdentityRegistry / Storage ────────────────────────────────────
|
||||
case SigIdentityRegistered:
|
||||
idx.handleIdentityRegistryAction(l, blockNum, txHash, logIdx, "IdentityRegistered")
|
||||
case SigIdentityRemoved:
|
||||
idx.handleIdentityRegistryAction(l, blockNum, txHash, logIdx, "IdentityRemoved")
|
||||
case SigIdentityUpdated:
|
||||
idx.handleIdentityRegistryAction(l, blockNum, txHash, logIdx, "IdentityUpdated")
|
||||
case SigCountryUpdated:
|
||||
idx.handleIdentityRegistryAction(l, blockNum, txHash, logIdx, "CountryUpdated")
|
||||
case SigIdentityStored:
|
||||
idx.handleIdentityRegistryAction(l, blockNum, txHash, logIdx, "IdentityStored")
|
||||
|
||||
// ── ONCHAINID (ERC-734 / ERC-735) ─────────────────────────────────
|
||||
case SigClaimAdded:
|
||||
idx.handleClaim(l, blockNum, txHash, logIdx, "ClaimAdded")
|
||||
case SigClaimRemoved:
|
||||
idx.handleClaim(l, blockNum, txHash, logIdx, "ClaimRemoved")
|
||||
case SigClaimChanged:
|
||||
idx.handleClaim(l, blockNum, txHash, logIdx, "ClaimChanged")
|
||||
case SigKeyAdded:
|
||||
idx.handleKey(l, blockNum, txHash, logIdx, "KeyAdded")
|
||||
case SigKeyRemoved:
|
||||
idx.handleKey(l, blockNum, txHash, logIdx, "KeyRemoved")
|
||||
case SigOnchainIdApproved:
|
||||
idx.handleSimpleSecuritiesEvent(l, blockNum, txHash, logIdx, "OnchainIdApproved")
|
||||
case SigOnchainIdExecuted:
|
||||
idx.handleSimpleSecuritiesEvent(l, blockNum, txHash, logIdx, "OnchainIdExecuted")
|
||||
|
||||
// ── TrustedIssuersRegistry / ClaimTopicsRegistry ──────────────────
|
||||
case SigTrustedIssuerAdded:
|
||||
idx.handleTrustedIssuer(l, blockNum, txHash, logIdx, "TrustedIssuerAdded")
|
||||
case SigTrustedIssuerRemoved:
|
||||
idx.handleTrustedIssuer(l, blockNum, txHash, logIdx, "TrustedIssuerRemoved")
|
||||
case SigClaimTopicsUpdated:
|
||||
idx.handleTrustedIssuer(l, blockNum, txHash, logIdx, "ClaimTopicsUpdated")
|
||||
case SigClaimTopicAdded:
|
||||
idx.handleClaimTopic(l, blockNum, txHash, logIdx, "ClaimTopicAdded")
|
||||
case SigClaimTopicRemoved:
|
||||
idx.handleClaimTopic(l, blockNum, txHash, logIdx, "ClaimTopicRemoved")
|
||||
|
||||
// ── ModularCompliance / IModule ───────────────────────────────────
|
||||
case SigModuleAdded, SigModuleRemoved, SigTokenBound, SigTokenUnbound, SigModuleInteraction:
|
||||
idx.handleComplianceEvent(l, blockNum, txHash, logIdx, topic0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
package indexer
|
||||
|
||||
// ERC-3643 + ONCHAINID event handlers.
|
||||
//
|
||||
// Each handler decodes the relevant log topics/data and writes a structured
|
||||
// entity through the storage layer. Resolvers in resolvers/securities/ read
|
||||
// these entities back.
|
||||
//
|
||||
// Entity types written here (read by resolvers/securities/securities.go):
|
||||
// - SecurityTransfer (already handled by handleTransfer for IToken Transfer)
|
||||
// - TransferAgentAction (AddressFrozen / TokensFrozen / TokensUnfrozen / RecoverySuccess / Paused / Unpaused)
|
||||
// - FrozenAccount (current AddressFrozen state per (token, user))
|
||||
// - FrozenTokens (current per-(token, user) partial-freeze amount)
|
||||
// - IdentityRegistryAction (IdentityRegistered/Removed/Updated/Stored, CountryUpdated)
|
||||
// - OnchainIdClaim (ClaimAdded/Removed/Changed)
|
||||
// - OnchainIdKey (KeyAdded/Removed)
|
||||
// - OnchainIdApproval (Approved/Executed)
|
||||
// - TrustedIssuerAction (TrustedIssuerAdded/Removed, ClaimTopicsUpdated)
|
||||
// - ClaimTopicAction (ClaimTopicAdded/Removed)
|
||||
// - ComplianceAction (ModuleAdded/Removed, TokenBound/Unbound, ModuleInteraction)
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// topicBool decodes a bool indexed topic (`bytes32(0)` = false, anything else = true).
|
||||
func topicBool(topic string) bool {
|
||||
t := strings.TrimPrefix(topic, "0x")
|
||||
for i := 0; i < len(t); i++ {
|
||||
if t[i] != '0' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// decodeUint256Topic decodes a uint256 from an indexed topic (32-byte word).
|
||||
func decodeUint256Topic(topic string) *big.Int {
|
||||
n := new(big.Int)
|
||||
n.SetString(strings.TrimPrefix(topic, "0x"), 16)
|
||||
return n
|
||||
}
|
||||
|
||||
// decodeAddress reads a 32-byte word at wordIndex and returns the low 20 bytes as a 0x-prefixed address.
|
||||
func decodeAddress(data string, wordIndex int) string {
|
||||
d := strings.TrimPrefix(data, "0x")
|
||||
start := wordIndex * 64
|
||||
if start+64 > len(d) {
|
||||
return "0x0000000000000000000000000000000000000000"
|
||||
}
|
||||
return "0x" + d[start+24:start+64]
|
||||
}
|
||||
|
||||
// id makes a stable per-log entity id: <token>:<txHash>:<logIdx>.
|
||||
func entityID(addr, txHash, logIdx string) string {
|
||||
return fmt.Sprintf("%s:%s:%s", addr, txHash, logIdx)
|
||||
}
|
||||
|
||||
// ── ERC-3643 IToken ──────────────────────────────────────────────────────────
|
||||
|
||||
// AddressFrozen(address indexed user, bool indexed isFrozen, address indexed owner)
|
||||
func (idx *Indexer) handleAddressFrozen(l *logEntry, blockNum uint64, txHash, logIdx string) {
|
||||
if len(l.Topics) < 4 {
|
||||
return
|
||||
}
|
||||
user := topicAddr(l.Topics[1])
|
||||
isFrozen := topicBool(l.Topics[2])
|
||||
owner := topicAddr(l.Topics[3])
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
|
||||
idx.store.SetEntity("TransferAgentAction", id, map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": "AddressFrozen",
|
||||
"token": l.Address,
|
||||
"user": user,
|
||||
"isFrozen": isFrozen,
|
||||
"owner": owner,
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
})
|
||||
// Live snapshot
|
||||
snapID := fmt.Sprintf("%s:%s", l.Address, user)
|
||||
idx.store.SetEntity("FrozenAccount", snapID, map[string]interface{}{
|
||||
"id": snapID,
|
||||
"token": l.Address,
|
||||
"user": user,
|
||||
"frozen": isFrozen,
|
||||
"updated": blockNum,
|
||||
})
|
||||
}
|
||||
|
||||
// TokensFrozen / TokensUnfrozen(address indexed user, uint256 amount)
|
||||
func (idx *Indexer) handleTokensFrozen(l *logEntry, blockNum uint64, txHash, logIdx string, freezing bool) {
|
||||
if len(l.Topics) < 2 {
|
||||
return
|
||||
}
|
||||
user := topicAddr(l.Topics[1])
|
||||
amount := decodeUint256(l.Data, 0)
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
kind := "TokensFrozen"
|
||||
if !freezing {
|
||||
kind = "TokensUnfrozen"
|
||||
}
|
||||
|
||||
idx.store.SetEntity("TransferAgentAction", id, map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": kind,
|
||||
"token": l.Address,
|
||||
"user": user,
|
||||
"amount": amount.String(),
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
})
|
||||
snapID := fmt.Sprintf("%s:%s", l.Address, user)
|
||||
// We don't track the running total without a read-modify cycle; just record the latest delta.
|
||||
idx.store.SetEntity("FrozenTokens", snapID, map[string]interface{}{
|
||||
"id": snapID,
|
||||
"token": l.Address,
|
||||
"user": user,
|
||||
"delta": amount.String(),
|
||||
"kind": kind,
|
||||
"updated": blockNum,
|
||||
})
|
||||
}
|
||||
|
||||
// Paused/Unpaused(address user)
|
||||
func (idx *Indexer) handleSecurityPause(l *logEntry, blockNum uint64, txHash, logIdx string, paused bool) {
|
||||
user := decodeAddress(l.Data, 0)
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
kind := "Paused"
|
||||
if !paused {
|
||||
kind = "Unpaused"
|
||||
}
|
||||
idx.store.SetEntity("TransferAgentAction", id, map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": kind,
|
||||
"token": l.Address,
|
||||
"user": user,
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
})
|
||||
}
|
||||
|
||||
// RecoverySuccess(address indexed lostWallet, address indexed newWallet, address indexed investorOnchainID)
|
||||
func (idx *Indexer) handleRecoverySuccess(l *logEntry, blockNum uint64, txHash, logIdx string) {
|
||||
if len(l.Topics) < 4 {
|
||||
return
|
||||
}
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
idx.store.SetEntity("TransferAgentAction", id, map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": "RecoverySuccess",
|
||||
"token": l.Address,
|
||||
"lostWallet": topicAddr(l.Topics[1]),
|
||||
"newWallet": topicAddr(l.Topics[2]),
|
||||
"investorOnchainID": topicAddr(l.Topics[3]),
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
})
|
||||
}
|
||||
|
||||
// ── IdentityRegistry / IdentityRegistryStorage ──────────────────────────────
|
||||
|
||||
// IdentityRegistered(address indexed user, IIdentity indexed identity)
|
||||
// IdentityRemoved(address indexed user, IIdentity indexed identity)
|
||||
// IdentityUpdated(IIdentity indexed oldIdentity, IIdentity indexed newIdentity)
|
||||
// IdentityStored(address indexed user, IIdentity indexed identity)
|
||||
// CountryUpdated(address indexed user, uint16 indexed country)
|
||||
func (idx *Indexer) handleIdentityRegistryAction(l *logEntry, blockNum uint64, txHash, logIdx, kind string) {
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
entity := map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": kind,
|
||||
"registry": l.Address,
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
}
|
||||
if len(l.Topics) >= 2 {
|
||||
entity["topic1"] = l.Topics[1]
|
||||
}
|
||||
if len(l.Topics) >= 3 {
|
||||
entity["topic2"] = l.Topics[2]
|
||||
}
|
||||
idx.store.SetEntity("IdentityRegistryAction", id, entity)
|
||||
}
|
||||
|
||||
// ── ONCHAINID ────────────────────────────────────────────────────────────────
|
||||
|
||||
// ClaimAdded/Removed/Changed(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri)
|
||||
func (idx *Indexer) handleClaim(l *logEntry, blockNum uint64, txHash, logIdx, kind string) {
|
||||
if len(l.Topics) < 4 {
|
||||
return
|
||||
}
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
idx.store.SetEntity("OnchainIdClaim", id, map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": kind,
|
||||
"identity": l.Address,
|
||||
"claimId": l.Topics[1],
|
||||
"topic": decodeUint256Topic(l.Topics[2]).String(),
|
||||
"issuer": topicAddr(l.Topics[3]),
|
||||
"data": l.Data,
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
})
|
||||
}
|
||||
|
||||
// KeyAdded/Removed(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType)
|
||||
func (idx *Indexer) handleKey(l *logEntry, blockNum uint64, txHash, logIdx, kind string) {
|
||||
if len(l.Topics) < 4 {
|
||||
return
|
||||
}
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
idx.store.SetEntity("OnchainIdKey", id, map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": kind,
|
||||
"identity": l.Address,
|
||||
"key": l.Topics[1],
|
||||
"purpose": decodeUint256Topic(l.Topics[2]).String(),
|
||||
"keyType": decodeUint256Topic(l.Topics[3]).String(),
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
})
|
||||
}
|
||||
|
||||
// ── TrustedIssuersRegistry / ClaimTopicsRegistry ────────────────────────────
|
||||
|
||||
func (idx *Indexer) handleTrustedIssuer(l *logEntry, blockNum uint64, txHash, logIdx, kind string) {
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
entity := map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": kind,
|
||||
"registry": l.Address,
|
||||
"data": l.Data,
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
}
|
||||
if len(l.Topics) >= 2 {
|
||||
entity["issuer"] = topicAddr(l.Topics[1])
|
||||
}
|
||||
idx.store.SetEntity("TrustedIssuerAction", id, entity)
|
||||
}
|
||||
|
||||
func (idx *Indexer) handleClaimTopic(l *logEntry, blockNum uint64, txHash, logIdx, kind string) {
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
entity := map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": kind,
|
||||
"registry": l.Address,
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
}
|
||||
if len(l.Topics) >= 2 {
|
||||
entity["topic"] = decodeUint256Topic(l.Topics[1]).String()
|
||||
}
|
||||
idx.store.SetEntity("ClaimTopicAction", id, entity)
|
||||
}
|
||||
|
||||
// ── ModularCompliance / IModule ─────────────────────────────────────────────
|
||||
|
||||
func (idx *Indexer) handleComplianceEvent(l *logEntry, blockNum uint64, txHash, logIdx, topic0 string) {
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
kind := "ComplianceEvent"
|
||||
switch topic0 {
|
||||
case SigModuleAdded:
|
||||
kind = "ModuleAdded"
|
||||
case SigModuleRemoved:
|
||||
kind = "ModuleRemoved"
|
||||
case SigTokenBound:
|
||||
kind = "TokenBound"
|
||||
case SigTokenUnbound:
|
||||
kind = "TokenUnbound"
|
||||
case SigModuleInteraction:
|
||||
kind = "ModuleInteraction"
|
||||
}
|
||||
entity := map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": kind,
|
||||
"compliance": l.Address,
|
||||
"data": l.Data,
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
}
|
||||
if len(l.Topics) >= 2 {
|
||||
entity["target"] = topicAddr(l.Topics[1])
|
||||
}
|
||||
idx.store.SetEntity("ComplianceAction", id, entity)
|
||||
}
|
||||
|
||||
// ── Catch-all for events we record but don't decode in detail ───────────────
|
||||
|
||||
func (idx *Indexer) handleSimpleSecuritiesEvent(l *logEntry, blockNum uint64, txHash, logIdx, kind string) {
|
||||
id := entityID(l.Address, txHash, logIdx)
|
||||
idx.store.SetEntity("SecuritiesEvent", id, map[string]interface{}{
|
||||
"id": id,
|
||||
"kind": kind,
|
||||
"contract": l.Address,
|
||||
"topics": l.Topics,
|
||||
"data": l.Data,
|
||||
"blockNumber": blockNum,
|
||||
"txHash": txHash,
|
||||
"logIndex": logIdx,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user