Documentation
¶
Overview ¶
Package events provides operations for polling and verifying events from CREC.
Events are blockchain occurrences detected by watchers and signed by the Decentralized Oracle Network (DON). This package enables fetching events from channels, verifying their cryptographic signatures, and decoding the event data into structured Go types.
Usage ¶
Events are typically accessed through the main SDK client:
client, _ := crec.NewClient(
baseURL,
apiKey,
crec.WithOrgID("my-org-id"),
crec.WithEventVerification(3, []string{
"0x5db070ceabcf97e45d96b4f951a1df050ddb5559",
"0xadebb9657c04692275973230b06adfabacc899bc",
"0xc868bbb5d93e97b9d780fc93811a00ca7c016751",
}),
)
events, hasMore, err := client.Events.Poll(ctx, channelID, nil)
For advanced use cases, create the client directly:
eventsClient, err := events.NewClient(&events.Options{
CRECClient: apiClient,
MinRequiredSignatures: 3,
ValidSigners: []string{"0x...", "0x...", "0x..."},
OrgID: "my-org-id", // optional; enables Verify(event) without passing org ID
})
Polling Events ¶
Use Client.Poll to fetch events from a channel:
// Poll with default parameters
events, hasMore, err := client.Events.Poll(ctx, channelID, nil)
// Poll with pagination
params := &apiClient.GetChannelsChannelIdEventsParams{
Limit: ptr(100),
}
events, hasMore, err := client.Events.Poll(ctx, channelID, params)
Verifying Events ¶
CRITICAL: Always verify events before processing. Verification ensures the event was signed by enough trusted DON members and matches the expected workflow.
## Verifying Watcher Events
For single-org use, set OrgID when creating the client (or use crec.WithOrgID) and call Client.Verify:
for _, event := range events {
verified, err := client.Events.Verify(&event)
if err != nil {
// Handle verification error (e.g., ErrOrgIDRequired if no default org configured)
continue
}
if !verified {
// Not enough valid signatures or workflow mismatch, skip this event
continue
}
processEvent(event)
}
For multi-org use, you can either create separate clients (one per org) with OrgID set, or use a single client and call Client.VerifyWithOrgID with an explicit org ID per event:
verified, err := client.Events.VerifyWithOrgID(&event, orgID)
If you have the workflow owner address, use Client.Verify when the client has it as default (Options.WorkflowOwner), or Client.VerifyWithWorkflowOwner with explicit address per event:
verified, err := client.Events.Verify(&event) // or verified, err := client.Events.VerifyWithWorkflowOwner(&event, workflowOwnerAddress)
## Verifying Operation Status Events
Use Client.VerifyOperationStatus when the client has a default OrgID, or Client.VerifyOperationStatusWithOrgID for multi-org with an explicit org ID:
verified, err := client.Events.VerifyOperationStatus(&event) // or verified, err := client.Events.VerifyOperationStatusWithOrgID(&event, orgID)
With a known workflow owner address, use Client.VerifyOperationStatus when the client has it as default, or Client.VerifyOperationStatusWithWorkflowOwner with explicit address per event:
verified, err := client.Events.VerifyOperationStatus(&event) // or verified, err := client.Events.VerifyOperationStatusWithWorkflowOwner(&event, workflowOwnerAddress)
## Deriving Workflow Owner from Org ID
Use Client.WorkflowOwnerFromOrgID to derive the workflow owner Ethereum address from an org ID without performing verification:
ownerAddress, err := client.Events.WorkflowOwnerFromOrgID(orgID)
Decoding Events ¶
Use Client.Decode to unpack event data into a Go struct:
var decodedEvent MyEventStruct err := client.Events.Decode(&event, &decodedEvent)
Or decode to a map for dynamic handling:
var data map[string]interface{}
err := client.Events.Decode(&event, &data)
Decoding Verifiable Events ¶
The event payload contains a base64-encoded VerifiableEvent field with rich event metadata. Use Client.DecodeVerifiableEvent to decode it into a models.VerifiableEvent struct:
import "github.com/smartcontractkit/crec-api-go/models"
// Get the watcher event payload
watcherPayload, err := event.Payload.AsWatcherEventPayload()
if err != nil {
// Handle error
}
// Decode the verifiable event
verifiableEvent, err := client.Events.DecodeVerifiableEvent(&watcherPayload)
if err != nil {
// Handle error
}
// Access event metadata
fmt.Printf("Event: %s at %v\n", verifiableEvent.Name, verifiableEvent.Timestamp)
if verifiableEvent.ChainFamily != nil {
fmt.Printf("Chain Family: %s\n", *verifiableEvent.ChainFamily)
}
// Access chain event details (for EVM chains)
if verifiableEvent.ChainEvent != nil {
evmEvent, err := verifiableEvent.ChainEvent.AsEVMEvent()
if err == nil {
fmt.Printf("Contract: %s, Block: %d\n", evmEvent.Address, evmEvent.BlockNumber)
fmt.Printf("Tx Hash: %s\n", evmEvent.TxHash)
// Access event parameters
if evmEvent.Params != nil {
for key, value := range *evmEvent.Params {
fmt.Printf(" %s: %v\n", key, value)
}
}
}
}
For operation status events, use Client.DecodeOperationStatusVerifiableEvent:
opStatusPayload, _ := event.Payload.AsOperationStatusPayload() verifiableEvent, err := client.Events.DecodeOperationStatusVerifiableEvent(&opStatusPayload)
JSON Serialization ¶
Convert events to JSON for logging or storage:
jsonBytes, err := client.Events.ToJSON(&event)
Event Types ¶
Events can be:
- Watcher events: Blockchain events captured by watchers (verify with Client.Verify)
- Operation status events: Status updates for operations (verify with Client.VerifyOperationStatus)
- Application events: Other status updates for watchers, etc.
Both watcher events and operation status events support cryptographic verification.
Error Handling ¶
All errors can be inspected with errors.Is:
if errors.Is(err, ErrChannelNotFound) {
// Handle missing channel
}
if errors.Is(err, ErrInvalidEventHash) {
// Event data was tampered with
}
if errors.Is(err, ErrOnlyWatcherEventsSupported) {
// Tried to verify a non-watcher event with Verify
}
if errors.Is(err, ErrOnlyOperationStatusSupported) {
// Tried to verify a non-operation-status event with VerifyOperationStatus
}
if errors.Is(err, ErrDecodeVerifiableEvent) {
// Failed to decode base64 verifiable event (invalid base64 or JSON)
}
if errors.Is(err, ErrDeriveWorkflowOwner) {
// Failed to derive workflow owner address from org ID
}
if errors.Is(err, ErrOrgIDOrWorkflowOwnerReq) {
// Called Verify or VerifyOperationStatus without org ID or workflow owner configured
}
if errors.Is(err, ErrWorkflowOwnerRequired) {
// Passed empty workflow owner to VerifyWithWorkflowOwner or VerifyOperationStatusWithWorkflowOwner
}
Index ¶
- Constants
- Variables
- type Client
- func (c *Client) Decode(event *apiClient.Event, payload any) error
- func (c *Client) DecodeOperationStatusVerifiableEvent(payload *apiClient.OperationStatusPayload) (*models.VerifiableEvent, error)
- func (c *Client) DecodeVerifiableEvent(payload *apiClient.WatcherEventPayload) (*models.VerifiableEvent, error)
- func (c *Client) EventHash(event *apiClient.WatcherEventPayload) (common.Hash, error)
- func (c *Client) OperationStatusHash(payload *apiClient.OperationStatusPayload) (common.Hash, error)
- func (c *Client) Poll(ctx context.Context, channelID uuid.UUID, ...) ([]apiClient.Event, bool, error)
- func (c *Client) SearchEvents(ctx context.Context, channelID uuid.UUID, ...) ([]apiClient.Event, bool, error)
- func (c *Client) ToJSON(event apiClient.Event) ([]byte, error)
- func (c *Client) Verify(event *apiClient.Event) (bool, error)
- func (c *Client) VerifyOCRSignatures(ocrReport, ocrContext string, signatures []string) (bool, error)
- func (c *Client) VerifyOperationStatus(event *apiClient.Event) (bool, error)
- func (c *Client) VerifyOperationStatusWithOrgID(event *apiClient.Event, orgID string) (bool, error)
- func (c *Client) VerifyOperationStatusWithWorkflowOwner(event *apiClient.Event, workflowOwner string) (bool, error)
- func (c *Client) VerifyWithOrgID(event *apiClient.Event, orgID string) (bool, error)
- func (c *Client) VerifyWithWorkflowOwner(event *apiClient.Event, workflowOwner string) (bool, error)
- func (c *Client) WorkflowOwnerFromOrgID(orgID string) (string, error)
- type Options
Constants ¶
const (
// CreMainlineTenantID is the CRE mainline tenant ID used as default for workflow owner address derivation.
CreMainlineTenantID = "1"
)
Variables ¶
var ( // ErrChannelIDRequired is returned when the channel ID is nil or missing. ErrChannelIDRequired = errors.New("channel_id is required") // ErrOptionsRequired is returned when the options parameter is nil. ErrOptionsRequired = errors.New("options is required") // ErrCRECClientRequired is returned when the CREC client is nil in options. ErrCRECClientRequired = errors.New("CRECClient is required") // ErrChannelNotFound is returned when the channel does not exist (404 response). ErrChannelNotFound = errors.New("channel not found") // ErrPollEvents is returned when polling events fails. ErrPollEvents = errors.New("failed to poll events") // ErrSearchEvents is returned when searching events fails. ErrSearchEvents = errors.New("failed to search events") // ErrGetEvents is returned when fetching events fails. ErrGetEvents = errors.New("failed to get events") // ErrVerifyEvent is returned when event verification fails. ErrVerifyEvent = errors.New("failed to verify event") // ErrDecodeEvent is returned when decoding an event fails. ErrDecodeEvent = errors.New("failed to decode event") // ErrDecodeVerifiableEvent is returned when decoding the verifiable event payload fails. ErrDecodeVerifiableEvent = errors.New("failed to decode verifiable event") // ErrParseSignature is returned when parsing a signature from hex fails. ErrParseSignature = errors.New("failed to parse signature") // ErrRecoverPubKeyFromSignature is returned when recovering the public key from a signature fails. ErrRecoverPubKeyFromSignature = errors.New("failed to recover public key from signature") // ErrParseOCRReport is returned when parsing the OCR report from hex fails. ErrParseOCRReport = errors.New("failed to parse OCR report") // ErrParseOCRContext is returned when parsing the OCR context from hex fails. ErrParseOCRContext = errors.New("failed to parse OCR context") // ErrParseEventPayload is returned when parsing the event payload fails. ErrParseEventPayload = errors.New("failed to parse event payload") // ErrOnlyWatcherEventsSupported is returned when verifying a non-watcher event type. ErrOnlyWatcherEventsSupported = errors.New("only watcher events are supported for event verification") // ErrOnlyOperationStatusSupported is returned when verifying a non-operation-status event type. ErrOnlyOperationStatusSupported = errors.New("only operation status events are supported for operation status verification") // ErrMarshalEventPayload is returned when marshaling the event payload to JSON fails. ErrMarshalEventPayload = errors.New("failed to marshal event payload") // ErrMarshalEventToJSON is returned when marshaling the event to JSON fails. ErrMarshalEventToJSON = errors.New("failed to marshal event to JSON") // ErrInvalidEventHash is returned when the event hash verification fails. ErrInvalidEventHash = errors.New("event hash verification failed") // ErrNoOCRProofs is returned when the event has no OCR proofs. ErrNoOCRProofs = errors.New("no OCR proofs found") // ErrMultipleOCRProofs is returned when the event has more than one OCR proof. ErrMultipleOCRProofs = errors.New("multiple OCR proofs found but should be 1") // ErrUnexpectedStatusCode is returned when the API returns an unexpected HTTP status code. ErrUnexpectedStatusCode = errors.New("unexpected status code") // ErrNilResponseBody is returned when the API response body is nil. ErrNilResponseBody = errors.New("unexpected nil response body") // ErrBadRequest is returned when the request parameters are invalid. ErrBadRequest = errors.New("invalid request parameters") // ErrOCRReportTooShort is returned when the OCR report is shorter than the minimum required length. ErrOCRReportTooShort = errors.New("OCR report is too short") // ErrVerificationNotConfigured is returned when the client has no valid signers configured. ErrVerificationNotConfigured = errors.New("event verification not configured: no valid signers") // ErrDeriveWorkflowOwner is returned when deriving the workflow owner address from org ID fails. ErrDeriveWorkflowOwner = errors.New("failed to derive workflow owner from org ID") // ErrOrgIDRequired is returned when org ID is required for verification but not set. ErrOrgIDRequired = errors.New("org ID required for verification (set in client options or pass as parameter)") // ErrWorkflowOwnerRequired is returned when workflow owner is required for verification but not set. ErrWorkflowOwnerRequired = errors.New("workflow owner required for verification (set in client options or pass as parameter)") // ErrOrgIDOrWorkflowOwnerReq is returned when neither org ID nor workflow owner is configured for verification. ErrOrgIDOrWorkflowOwnerReq = errors.New("org ID or workflow owner required for verification (set in client options or pass as parameter)") )
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client provides operations for polling and verifying events from CREC.
func NewClient ¶
NewClient creates a new CREC events client with the provided CREC client and options. Returns a pointer to the Client and an error if any issues occur during initialization. If the CREC client or options are nil, it returns an error.
- opts: Options for configuring the CREC events client, see Options for details.
func (*Client) Decode ¶
Decode decodes a verifiable event into a specified payload structure.
- event: The event to decode.
- payload: A pointer to the structure where the decoded event will be stored.
func (*Client) DecodeOperationStatusVerifiableEvent ¶
func (c *Client) DecodeOperationStatusVerifiableEvent(payload *apiClient.OperationStatusPayload) (*models.VerifiableEvent, error)
DecodeOperationStatusVerifiableEvent decodes the base64-encoded VerifiableEvent from an OperationStatusPayload into a models.VerifiableEvent struct.
func (*Client) DecodeVerifiableEvent ¶
func (c *Client) DecodeVerifiableEvent(payload *apiClient.WatcherEventPayload) (*models.VerifiableEvent, error)
DecodeVerifiableEvent decodes the base64-encoded VerifiableEvent from a WatcherEventPayload into a models.VerifiableEvent struct containing the full event data.
func (*Client) EventHash ¶
EventHash computes the Keccak256 hash of the verifiable event string used for signature verification.
func (*Client) OperationStatusHash ¶
func (c *Client) OperationStatusHash(payload *apiClient.OperationStatusPayload) (common.Hash, error)
OperationStatusHash computes the "EventHash" of an OperationStatusPayload used for verification. The hash is computed using the pattern: eventName + "." + base64VerifiableEvent Note: VerifiableEvent must be present and non-empty (should be validated by caller).
func (*Client) Poll ¶
func (c *Client) Poll( ctx context.Context, channelID uuid.UUID, params *apiClient.GetChannelsChannelIdEventsParams, ) ([]apiClient.Event, bool, error)
Poll retrieves events from the CREC service for a specific channel.
- ctx: Context for the request, used for cancellation and timeouts.
- channelID: The UUID of the channel to retrieve events from.
- params: parameters for filtering events, see apiClient.GetChannelsChannelIdEventsParams for details.
func (*Client) SearchEvents ¶
func (c *Client) SearchEvents( ctx context.Context, channelID uuid.UUID, params *apiClient.GetChannelsChannelIdEventsSearchParams, ) ([]apiClient.Event, bool, error)
SearchEvents queries and searches historical events from a channel with filtering capabilities. Use this method for historical queries and searches. For real-time polling, use PollEvents.
- ctx: Context for the request, used for cancellation and timeouts.
- channelID: The UUID of the channel to search events from.
- params: Parameters for filtering events, see client.GetChannelsChannelIdEventsSearchParams for details.
func (*Client) ToJSON ¶
ToJSON converts a verifiable event into its JSON representation.
- event: The event to convert.
func (*Client) Verify ¶
Verify verifies the authenticity of a given watcher event using the default org ID or workflow owner configured on the client. Prefers OrgID when set (derives workflow owner); otherwise uses WorkflowOwner when set. Returns ErrOrgIDOrWorkflowOwnerReq if neither is configured.
- event: The event to verify.
Returns true if the event is valid and signed by enough authorized signers, false otherwise.
func (*Client) VerifyOCRSignatures ¶
func (c *Client) VerifyOCRSignatures(ocrReport, ocrContext string, signatures []string) (bool, error)
VerifyOCRSignatures verifies that the OCR proof contains valid DON signatures. This is a lower-level verification that checks only signatures, without requiring a full Event structure or validating event hash/workflow owner.
Returns true if at least minRequiredSignatures valid signatures are found.
func (*Client) VerifyOperationStatus ¶
VerifyOperationStatus verifies the authenticity of an operation status event using the default org ID or workflow owner configured on the client. Prefers OrgID when set; otherwise uses WorkflowOwner. Returns ErrOrgIDOrWorkflowOwnerReq if neither is configured.
- event: The event to verify.
Returns true if the event is valid and signed by enough authorized signers, false otherwise.
func (*Client) VerifyOperationStatusWithOrgID ¶
VerifyOperationStatusWithOrgID verifies the authenticity of an operation status event using an explicit org ID. It derives the expected workflow owner address and delegates to Client.VerifyOperationStatusWithWorkflowOwner. Use this for multi-org scenarios.
- event: The event to verify.
- orgID: The organization ID used to derive the workflow owner address.
Returns true if the event is valid and signed by enough authorized signers, false otherwise.
func (*Client) VerifyOperationStatusWithWorkflowOwner ¶
func (c *Client) VerifyOperationStatusWithWorkflowOwner(event *apiClient.Event, workflowOwner string) (bool, error)
VerifyOperationStatusWithWorkflowOwner verifies the authenticity of an operation status event using an explicit workflow owner address. Use this for multi-org or per-event workflow owner. For client-default verification, use Client.VerifyOperationStatus.
- event: The event to verify.
- workflowOwner: The workflow owner address (Ethereum address) that deployed the workflow.
Returns true if the event is valid and signed by enough authorized signers, false otherwise.
func (*Client) VerifyWithOrgID ¶
VerifyWithOrgID verifies the authenticity of a given watcher event using an explicit org ID. It derives the expected workflow owner address from the org ID and delegates to the workflow owner verification. Use this for multi-org scenarios where a single client verifies events from different organizations.
- event: The event to verify.
- orgID: The organization ID used to derive the workflow owner address.
Returns true if the event is valid and signed by enough authorized signers, false otherwise.
func (*Client) VerifyWithWorkflowOwner ¶
func (c *Client) VerifyWithWorkflowOwner(event *apiClient.Event, workflowOwner string) (bool, error)
VerifyWithWorkflowOwner verifies the authenticity of a given watcher event using an explicit workflow owner address. Use this for multi-org or when you have the address per event. For client-default verification, use Client.Verify.
- event: The event to verify.
- workflowOwner: The workflow owner address (Ethereum address) that deployed the workflow.
Returns true if the event is valid and signed by enough authorized signers, false otherwise.
func (*Client) WorkflowOwnerFromOrgID ¶ added in v0.6.1
WorkflowOwnerFromOrgID derives the workflow owner Ethereum address from an organization ID. It uses the CRE canonical CREATE2-style address derivation with the client's configured CRE tenant ID.
type Options ¶
type Options struct {
Logger *slog.Logger
CRECClient *apiClient.ClientWithResponses
MinRequiredSignatures int
ValidSigners []string
OrgID string
WorkflowOwner string
CRETenantID string
}
Options holds the configuration options for the CREC events client. It includes options for logging and event retrieval.
- Logger: Optional logger instance.
- CRECClient: A client instance for interacting with the CREC system (required).
- MinRequiredSignatures: Minimum number of valid signatures required to verify an event.
- ValidSigners: List of valid signer addresses (as hex strings).
- OrgID: Optional default organization ID for Client.Verify and Client.VerifyOperationStatus. When set, those methods can be called without passing org ID. For multi-org use, omit and use Client.VerifyWithOrgID or Client.VerifyOperationStatusWithOrgID with explicit org ID.
- WorkflowOwner: Optional default workflow owner address for Client.Verify and Client.VerifyOperationStatus. When set (and OrgID is not), those methods use it. For explicit workflow owner per event, use Client.VerifyWithWorkflowOwner or Client.VerifyOperationStatusWithWorkflowOwner.
- CRETenantID: CRE tenant ID referring to different environments of CRE, used for workflow owner address derivation. Defaults to CreMainlineTenantID ("1") if not provided.