cloudevent

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 1, 2025 License: Apache-2.0 Imports: 10 Imported by: 12

README

DIMO CloudEvent

GitHub license GoDoc Go Report Card

A Go library for working with CloudEvents in the DIMO ecosystem, with specialized support for Decentralized Identifiers (DIDs).

Overview

DIMO CloudEvent is designed for developers building applications within the DIMO ecosystem who need to:

  • Work with standardized event data following the CloudEvents specification
  • Process events with blockchain-based identifiers (DIDs)
  • Build event-driven applications with persistent, well-structured event data

This library implements a DIMO-specific profile of the CloudEvents specification, extending the standard with additional features for decentralized identifiers and blockchain data structures while maintaining compatibility with the core specification.

CloudEvent Format

CloudEvents Specification

DIMO CloudEvents are a derived standard from the official CloudEvents specification v1.0. While maintaining full compatibility with the base standard, DIMO CloudEvents include additional fields and conventions specific to the DIMO ecosystem.

The core structure is:

type CloudEvent[A any] struct {
    CloudEventHeader
    Data A `json:"data"`
}
Example CloudEvent JSON

When working with DIMO services, your CloudEvent payload should follow this format:

{
  "id": "unique-event-identifier",
  "source": "0xEthereumAddress",
  "producer": "did:erc721:1:0xbA5738a18d83D41847dfFbDC6101d37C69c9B0cF:42",
  "specversion": "1.0",
  "subject": "did:erc721:1:0x123456789abcdef0123456789abcdef012345678:42",
  "time": "2025-03-04T12:00:00Z",
  "type": "dimo.status",
  "datacontenttype": "application/json",
  "dataversion": "default/v1.0",
  "data": {
    "signals": [
      {
        "name": "powertrainTransmissionTravelledDistance",
        "timestamp": "2025-03-04T12:00:00Z",
        "value": 12345.67
      },
      {
        "name": "speed",
        "timestamp": "2025-03-04T12:01:00Z",
        "value": 55
      },
      {
        "name": "powertrainType",
        "timestamp": "2025-03-04T12:03:00Z",
        "value": "COMBUSTION"
      }
    ],
    "vin": "1GGCM82633A123456"
  }
}
CloudEvent Headers

Each CloudEvent contains the following header fields:

Field Description
ID A unique identifier for the event. The combination of ID and Source must be unique.
Source Typically an Ethereum address. In many DIMO services
Producer The DID of the entity that produced the payload. Ex. did:erc721:<chainId>:<contractAddress>:<tokenId>.
SpecVersion The version of CloudEvents specification used. This is always hardcoded as "1.0".
Subject The DID which denotes the subject of the event. Ex. did:erc721:<chainId>:<contractAddress>:<tokenId>.
Time The time at which the event occurred. Format as RFC3339 timestamp.
Type Describes the type of event - must be one of the predefined DIMO types.
DataContentType The MIME type for the data field. When using JSON (the most common case), this should be "application/json".
DataSchema URI pointing to a schema for the data field.
DataVersion An optional way for the data provider to specify the version of the data structure in the payload (e.g., "default/v1.0").
Extras Additional custom fields.

The DIMO-specific extensions to the CloudEvents specification include:

  • Producer: Provides additional context about the specific instance, process, or device that created the event
  • DataVersion: A DIMO-specific extension that is unique to each source. This can be used by a source to determine the shape of the data field, enabling version-based data processing
Event Uniqueness

A CloudEvent is uniquely identified by the combination of the following fields:

  • Subject
  • Time
  • Type
  • Source
  • ID

This combination forms the "index key" for the event and is used for deduplication and retrieval purposes.

DIMO Event Types

The library defines several DIMO-specific event types:

  • dimo.status: Used for status updates
  • dimo.fingerprint: Used for fingerprint updates
  • dimo.verifiablecredential: Used for verifiable credentials
  • dimo.unknown: Used for unknown events

DIMO services expect the Type field to be one of these predefined types. Using custom or undefined types may result in events being improperly processed or rejected by DIMO services.

Decentralized Identifier (DID) Formats

The library provides support for two types of DIDs:

ERC721 DID

The ERC721 DID format is used to identify ERC721 tokens on a blockchain:

did:erc721:<chainID>:<contractAddress>:<tokenID>

Example: did:erc721:137:0xbA5738a18d83D41847dfFbDC6101d37C69c9B0cF:123

  • chainID: The blockchain network ID (e.g., 1 for Ethereum mainnet, 137 for Polygon)
  • contractAddress: Ethereum hex address of the NFT contract
  • tokenID: The numeric token ID
Ethereum DID

The Ethereum DID format is used to identify Ethereum accounts or contracts:

did:ethr:<chainID>:<address>

Example: did:ethr:1:0xbA5738a18d83D41847dfFbDC6101d37C69c9B0cF

  • chainID: The blockchain network ID
  • address: Ethereum hex address

Usage Examples

Creating a CloudEvent
event := cloudevent.CloudEvent[MyDataType]{
    CloudEventHeader: cloudevent.CloudEventHeader{
        ID:             "unique-id",
        Source:         "0xConnectionLicenseAddress",
        Producer:       cloudevent.ERC721DID{
          ChainID: 1,
          ContractAddress: "0x123456789abcdef0123456789abcdef012345678",
          TokenID: big.NewInt(123),
        }.String(),
        Subject:         cloudevent.ERC721DID{
          ChainID: 1,
          ContractAddress: "0x123456789abcdef0123456789abcdef012345678",
          TokenID: big.NewInt(123),
        }.String(),
        Time:           time.Now().UTC(),
        Type:           cloudevent.TypeStatus,
        DataContentType: "application/json",
        DataVersion:    "default/v1.0",
    },
    Data: MyDataType{
        // Your data fields
    },
}
Working with DIDs
// Parse an ERC721 DID
erc721DID, err := cloudevent.DecodeERC721DID("did:erc721:137:0xbA5738a18d83D41847dfFbDC6101d37C69c9B0cF:123")
if err != nil {
    // Handle error
}

// Convert back to string
didString := erc721DID.String()

Development

Use make to manage the project building, testing, and linting.

> make help

Specify a subcommand:

  build                Build the code
  clean                Clean the project binaries
  tidy                 tidy the go modules
  test                 Run the all tests
  lint                 Run the linter
  format               Run the linter with fix
  migration            Generate migration file specify name with name=your_migration_name
  tools                Install all tools
  tools-golangci-lint  Install golangci-lint
  tools-migration      Install migration tool

License

Apache 2.0

Documentation

Overview

Package cloudevent provides types for working with CloudEvents.

Index

Constants

View Source
const (
	// TypeStatus is the event type for status updates.
	TypeStatus = "dimo.status"

	// TypeFingerprint is the event type for fingerprint updates.
	TypeFingerprint = "dimo.fingerprint"

	// TypeVerifableCredential is the event type for verifiable credentials.
	TypeVerifableCredential = "dimo.verifiablecredential" //nolint:gosec // This is not a credential.

	// TypeAttestation is the event type for 3rd party attestations
	TypeAttestation = "dimo.attestation"

	// TypeUnknown is the event type for unknown events.
	TypeUnknown = "dimo.unknown"

	// TypeEvent is the event type for vehicle events
	TypeEvent = "dimo.event"
)
View Source
const (
	// ERC721DIDMethod is the method for a ERC721 NFT DID.
	ERC721DIDMethod = "erc721"
	// EthrDIDMethod is the method for a Ethereum Address DID.
	EthrDIDMethod = "ethr"
	// ERC20DIDMethod is the method for a ERC20 token DID.
	ERC20DIDMethod = "erc20"
)
View Source
const SpecVersion = "1.0"

SpecVersion is the version of the CloudEvents spec.

Variables

This section is empty.

Functions

func EncodeLegacyNFTDID added in v0.1.0

func EncodeLegacyNFTDID(chainID uint64, contractAddress common.Address, tokenID *big.Int) string

EncodeLegacyNFTDID is a legacy encoder for NFT DIDs that use the format "did:nft:1:0xbA5738a18d83D41847dfFbDC6101d37C69c9B0cF_1".

Types

type CloudEvent

type CloudEvent[A any] struct {
	CloudEventHeader
	// Data contains domain-specific information about the event.
	Data A `json:"data"`
}

CloudEvent represents an event according to the CloudEvents spec. To Add extra headers to the CloudEvent, add them to the Extras map. See https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md

func (CloudEvent[A]) MarshalJSON

func (c CloudEvent[A]) MarshalJSON() ([]byte, error)

MarshalJSON implements custom JSON marshaling for CloudEventHeader.

func (*CloudEvent[A]) UnmarshalJSON

func (c *CloudEvent[A]) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshaling for CloudEvent.

type CloudEventHeader

type CloudEventHeader struct {
	// ID is an identifier for the event. The combination of ID and Source must
	// be unique.
	ID string `json:"id"`

	// Source is the context in which the event happened. In a distributed system it might consist of multiple Producers.
	Source string `json:"source"`

	// Producer is a specific instance, process or device that creates the data structure describing the CloudEvent.
	Producer string `json:"producer"`

	// SpecVersion is the version of CloudEvents specification used.
	// This is always hardcoded "1.0".
	SpecVersion string `json:"specversion"`

	// Subject is an optional field identifying the subject of the event within
	// the context of the event producer. In practice, we always set this.
	Subject string `json:"subject"`

	// Time is an optional field giving the time at which the event occurred. In
	// practice, we always set this.
	Time time.Time `json:"time"`

	// Type describes the type of event. It should generally be a reverse-DNS
	// name.
	Type string `json:"type"`

	// DataContentType is an optional MIME type for the data field. We almost
	// always serialize to JSON and in that case this field is implicitly
	// "application/json".
	DataContentType string `json:"datacontenttype,omitempty"`

	// DataSchema is an optional URI pointing to a schema for the data field.
	DataSchema string `json:"dataschema,omitempty"`

	// DataVersion is the version of the data type.
	DataVersion string `json:"dataversion,omitempty"`

	// Signature hold the signature of the a cloudevent's data field.
	Signature string `json:"signature,omitempty" cloudevent:"leaveInExtras"`

	// Extras contains any additional fields that are not part of the CloudEvent excluding the data field.
	Extras map[string]any `json:"-"`
}

CloudEventHeader contains the metadata for any CloudEvent. To add extra headers to the CloudEvent, add them to the Extras map.

func (*CloudEventHeader) Equals

func (c *CloudEventHeader) Equals(other CloudEventHeader) bool

Equals returns true if the two CloudEventHeaders share the same IndexKey.

func (CloudEventHeader) Key added in v0.0.3

func (c CloudEventHeader) Key() string

Key returns the unique identifier for the CloudEvent.

func (CloudEventHeader) MarshalJSON

func (c CloudEventHeader) MarshalJSON() ([]byte, error)

MarshalJSON implements custom JSON marshaling for CloudEventHeader.

func (*CloudEventHeader) UnmarshalJSON

func (c *CloudEventHeader) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshaling for CloudEventHeader.

type ERC20DID added in v0.1.0

type ERC20DID struct {
	ChainID         uint64         `json:"chainId"`
	ContractAddress common.Address `json:"contract"`
}

ERC20DID is a Decentralized Identifier for an ERC20 token.

func DecodeERC20DID added in v0.1.0

func DecodeERC20DID(did string) (ERC20DID, error)

DecodeERC20DID decodes a ERC20 DID string into a DID struct.

func (ERC20DID) MarshalText added in v0.1.1

func (e ERC20DID) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler

func (ERC20DID) String added in v0.1.0

func (e ERC20DID) String() string

String returns the string representation of the ERC20DID.

func (*ERC20DID) UnmarshalText added in v0.1.1

func (e *ERC20DID) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler

type ERC721DID added in v0.1.0

type ERC721DID struct {
	ChainID         uint64         `json:"chainId"`
	ContractAddress common.Address `json:"contract"`
	TokenID         *big.Int       `json:"tokenId"`
}

ERC721DID is a Decentralized Identifier for a ERC721 NFT.

func DecodeERC721DID added in v0.1.0

func DecodeERC721DID(did string) (ERC721DID, error)

DecodeERC721DID decodes a DID string into a DID struct.

func DecodeERC721orNFTDID added in v0.1.0

func DecodeERC721orNFTDID(did string) (ERC721DID, error)

DecodeERC721orNFTDID is a decoder that attempts to decode a DID string into an ERC721DID or a legacy NFT DID.

func DecodeLegacyNFTDID added in v0.1.0

func DecodeLegacyNFTDID(did string) (ERC721DID, error)

DecodeLegacyNFTDID is a legacy decoder for NFT DIDs that use the format "did:nft:1:0xbA5738a18d83D41847dfFbDC6101d37C69c9B0cF_1" You most likely want to use DecodeERC721DID instead.

func (ERC721DID) MarshalText added in v0.1.1

func (e ERC721DID) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler

func (ERC721DID) String added in v0.1.0

func (e ERC721DID) String() string

String returns the string representation of the NFTDID.

func (*ERC721DID) UnmarshalText added in v0.1.1

func (e *ERC721DID) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler

type EthrDID

type EthrDID struct {
	ChainID         uint64         `json:"chainId"`
	ContractAddress common.Address `json:"contract"`
}

EthrDID is a Decentralized Identifier for an Ethereum contract.

func DecodeEthrDID

func DecodeEthrDID(did string) (EthrDID, error)

DecodeEthrDID decodes a Ethr DID string into a DID struct.

func (EthrDID) MarshalText added in v0.1.1

func (e EthrDID) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler

func (EthrDID) String

func (e EthrDID) String() string

String returns the string representation of the EthrDID.

func (*EthrDID) UnmarshalText added in v0.1.1

func (e *EthrDID) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler

type Fingerprint

type Fingerprint struct {
	VIN string `json:"vin"`
}

Fingerprint represents a fingerprint message which holds a vehicle's VIN.

type FingerprintEvent

type FingerprintEvent = CloudEvent[Fingerprint]

FingerprintEvent is a CloudEvent for a fingerprint message.

type RawEvent

type RawEvent = CloudEvent[json.RawMessage]

RawEvent is a cloudevent with a json.RawMessage data field.

Directories

Path Synopsis
cmd
migrations command
pkg
clickhouse/eventrepo
Package eventrepo contains service code for gettting and managing cloudevent objects.
Package eventrepo contains service code for gettting and managing cloudevent objects.
clickhouse/migrations
Code generated by "clickhouse-infra" DO NOT EDIT.
Code generated by "clickhouse-infra" DO NOT EDIT.
codegen command
Package main provides a code generator for CloudEventHeader field accessors.
Package main provides a code generator for CloudEventHeader field accessors.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL