codec

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Mar 12, 2025 License: MIT Imports: 16 Imported by: 13

Documentation

Overview

Example

Example demonstrates how to use the codec package. It will make use of each Modifier provided in the package, along with their config.

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"math"
	"math/big"
	"time"

	"github.com/smartcontractkit/chainlink-common/pkg/codec"
	"github.com/smartcontractkit/chainlink-common/pkg/types"
)

// This example demonstrates how you can have config for itemTypes with one codec,
// one that is modified before encoding for on-chain and modified after decoding for off-chain
// the other is left unmodified during encoding and decoding.
const (
	anyUnmodifiedTypeName     = "Unmodified"
	anyModifiedStructTypeName = "SecondItem"
	anyExtractorTypeName      = "ExtractProperty"
)

var _ types.RemoteCodec = &ExampleStructJSONCodec{}

type ExampleStructJSONCodec struct{}

func (ExampleStructJSONCodec) Encode(_ context.Context, item any, _ string) ([]byte, error) {
	return json.Marshal(item)
}

func (ExampleStructJSONCodec) GetMaxEncodingSize(_ context.Context, n int, _ string) (int, error) {
	// not used in the example, and not really valid for json.
	return math.MaxInt32, nil
}

func (ExampleStructJSONCodec) Decode(_ context.Context, raw []byte, into any, _ string) error {
	err := json.Unmarshal(raw, into)
	if err != nil {
		return fmt.Errorf("%w: %w", types.ErrInvalidType, err)
	}
	return nil
}

func (ExampleStructJSONCodec) GetMaxDecodingSize(ctx context.Context, n int, _ string) (int, error) {
	// not used in the example, and not really valid for json.
	return math.MaxInt32, nil
}

func (ExampleStructJSONCodec) CreateType(_ string, _ bool) (any, error) {
	// parameters here are unused in the example, but can be used to determine what type to expect.
	// this allows remote execution to know how to decode the incoming message
	// and for [codec.NewModifierCodec] to know what type to expect for intermediate phases.
	return &OnChainStruct{}, nil
}

type ExampleOffChainNestedTestStruct struct {
	X *int
	Y *big.Int
	Z map[string]any
}

type ExampleOffChainTestStruct struct {
	A string
	B ExampleOffChainNestedTestStruct
	C []byte
}

type ExampleOnChainNestedTestStruct struct{}

type ExampleOnChainTestStruct struct {
	A []byte
	B ExampleOnChainNestedTestStruct
	C [32]byte
}

type OnChainStruct struct {
	Aa int64
	Bb string
	Cc bool
	Dd string
	Ee int64
	Ff string
}

const config = `
[
  { "Type" : "drop", "Fields" :  ["Bb"] },
  { "Type" : "hard code", "OnChainValues" : {"Ff" :  "dog", "Bb" : "bb"}, "OffChainValues" : {"Zz" : "foo"}},
  { "Type" : "rename", "Fields" :  {"Aa" :  "Bb"}},
  { "Type" : "extract element", "Extractions" :  {"Dd" :  "middle"}},
  { "Type" : "epoch to time", "Fields" :  ["Ee"]}
]
`
const extractConfig = `[
  { "Type" : "extract property", "FieldName" : "Bb" }
]`

// config converts the OnChainStruct to this structure
type OffChainStruct struct {
	Bb int64
	Cc bool
	Dd []string
	Ee *time.Time
	Zz string
}

// Example demonstrates how to use the codec package.
// It will make use of each [Modifier] provided in the package, along with their config.
func main() {
	mods, err := createModsFromConfig()
	if err != nil {
		fmt.Println(err)
		return
	}

	c, err := codec.NewModifierCodec(&ExampleStructJSONCodec{}, mods)
	if err != nil {
		fmt.Println(err)
		return
	}

	input := &OnChainStruct{
		Aa: 10,
		Bb: "20",
		Cc: true,
		Dd: "great example",
		Ee: 631515600,
		Ff: "dog",
	}

	ctx := context.Background()
	b, err := c.Encode(ctx, input, anyUnmodifiedTypeName)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("Encoded: " + string(b))

	output := &OnChainStruct{}
	if err = c.Decode(ctx, b, output, anyUnmodifiedTypeName); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("Decoded: %+v\n", output)

	anyTimeEpoch := int64(631515600)
	t := time.Unix(anyTimeEpoch, 0)
	modifedInput := &OffChainStruct{
		Bb: 10,
		Cc: true,
		Dd: []string{"terrible example", "great example", "not this one :("},
		Ee: &t,
		Zz: "foo",
	}

	b, err = c.Encode(ctx, modifedInput, anyModifiedStructTypeName)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Encoded with modifications: " + string(b))

	output2 := &OffChainStruct{}
	if err = c.Decode(ctx, b, output2, anyModifiedStructTypeName); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Printf("Decoded with modifications: %+v\n", output2)

	// using Encode for the extractor is a lossy operation and should not be used on writes
	if b, err = c.Encode(ctx, "test", anyExtractorTypeName); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Printf("Encoded for Extraction: %+v\n", string(b))

	var extractedVal string
	if err = c.Decode(ctx, b, &extractedVal, anyExtractorTypeName); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Printf("Decoded to extracted value: %+v\n", extractedVal)
}

func createModsFromConfig() (codec.Modifier, error) {
	modifierConfig := &codec.ModifiersConfig{}
	if err := json.Unmarshal([]byte(config), modifierConfig); err != nil {
		return nil, err
	}

	mod, err := modifierConfig.ToModifier()
	if err != nil {
		return nil, err
	}

	extractorConfig := &codec.ModifiersConfig{}
	if err = json.Unmarshal([]byte(extractConfig), extractorConfig); err != nil {
		return nil, err
	}

	exMod, err := extractorConfig.ToModifier()
	if err != nil {
		return nil, err
	}

	modByItemType := map[string]codec.Modifier{
		anyModifiedStructTypeName: mod,
		anyUnmodifiedTypeName:     codec.MultiModifier{},
		anyExtractorTypeName:      exMod,
	}

	return codec.NewByItemTypeModifier(modByItemType)
}
Output:

Encoded: {"Aa":10,"Bb":"20","Cc":true,"Dd":"great example","Ee":631515600,"Ff":"dog"}
Decoded: &{Aa:10 Bb:20 Cc:true Dd:great example Ee:631515600 Ff:dog}
Encoded with modifications: {"Aa":10,"Bb":"","Cc":true,"Dd":"great example","Ee":631515600,"Ff":"dog"}
Decoded with modifications: &{Bb:10 Cc:true Dd:[great example] Ee:1990-01-05 05:00:00 +0000 UTC Zz:foo}
Encoded for Extraction: {"Aa":0,"Bb":"test","Cc":false,"Dd":"","Ee":0,"Ff":""}
Decoded to extracted value: test

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func BigIntHook

func BigIntHook(_, to reflect.Type, data any) (any, error)

BigIntHook is a mapstructure hook that converts number types to *math/big.Int and vice versa. Float values are cast to an int64 before being converted to a *math/big.Int.

func Convert

func Convert(from, to reflect.Value, hook mapstructure.DecodeHookFunc) error

Convert uses mapstructure and the hook provided to convert from into to. Note that the use of mapstructure is avoided if to and from are the same type, and are both pointers, or if to is a pointer to the type from is. In those cases, to is simply set to from, or to point to it. Arrays and slices are converted by converting each element using mapstructure.

func EpochToTimeHook

func EpochToTimeHook(from reflect.Type, to reflect.Type, data any) (any, error)

EpochToTimeHook is a mapstructure hook that converts a unix epoch to a time.Time and vice versa. To do this, time.Unix and time.Time.Unix are used.

func FitsInNBitsSigned

func FitsInNBitsSigned(n int, bi *big.Int) bool

FitsInNBitsSigned returns if the *math/big.Int can fit in n bits as a signed integer. Namely, if it's in the range [-2^(n-1), 2^(n-1) - 1]

func NewModifierCodec

func NewModifierCodec(codec types.RemoteCodec, modifier Modifier, hooks ...mapstructure.DecodeHookFunc) (types.RemoteCodec, error)

NewModifierCodec returns a codec that calls the modifier before calling codec functions. hooks are applied to the mapstructure decoding when Encode or Decode is called.

func NumberHook

func NumberHook(from reflect.Type, to reflect.Type, val any) (any, error)

func SetValueAtPath added in v0.5.0

func SetValueAtPath(vInto, vField reflect.Value, itemType string) error

func SliceToArrayVerifySizeHook

func SliceToArrayVerifySizeHook(from reflect.Type, to reflect.Type, data any) (any, error)

SliceToArrayVerifySizeHook is a mapstructure hook that verifies if a slice is being assigned to an array, it will have the same number of elements. The default in mapstructure is to allow the slice to be smaller and will zero out the remaining elements in that case.

func ValueForPath added in v0.5.0

func ValueForPath(from reflect.Value, itemType string) (any, error)

Types

type AddressBytesToStringModifierConfig added in v0.4.0

type AddressBytesToStringModifierConfig struct {
	Fields             []string
	EnablePathTraverse bool
	// Modifier is skipped in JSON serialization, will be injected later.
	Modifier AddressModifier `json:"-"`
}

AddressBytesToStringModifierConfig is used to transform address byte fields into string fields. It holds the list of fields that should be modified and the chain-specific logic to do the modifications.

func (*AddressBytesToStringModifierConfig) MarshalJSON added in v0.4.0

func (c *AddressBytesToStringModifierConfig) MarshalJSON() ([]byte, error)

func (*AddressBytesToStringModifierConfig) ToModifier added in v0.4.0

func (c *AddressBytesToStringModifierConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

type AddressModifier added in v0.4.0

type AddressModifier interface {
	// EncodeAddress converts byte array representing an address into its string form using chain-specific logic.
	EncodeAddress([]byte) (string, error)
	// DecodeAddress converts a string representation of an address back into its byte array form using chain-specific logic.
	DecodeAddress(string) ([]byte, error)
	// Length returns the expected byte length of the address for the specific chain.
	Length() int
}

AddressModifier defines the interface for encoding, decoding, and handling addresses. This interface allows for chain-specific logic to be injected into the modifier without modifying the common repository.

type ByteToBooleanModifierConfig added in v0.5.0

type ByteToBooleanModifierConfig struct {
	Fields []string
}

ByteToBooleanModifierConfig converts onchain uint8 fields to offchain bool fields and vice versa.

func (*ByteToBooleanModifierConfig) MarshalJSON added in v0.5.0

func (d *ByteToBooleanModifierConfig) MarshalJSON() ([]byte, error)

func (*ByteToBooleanModifierConfig) ToModifier added in v0.5.0

func (d *ByteToBooleanModifierConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

type ConstrainedBytesToStringModifierConfig added in v0.5.0

type ConstrainedBytesToStringModifierConfig struct {
	Fields             []string
	MaxLen             int
	EnablePathTraverse bool
}

func (*ConstrainedBytesToStringModifierConfig) MarshalJSON added in v0.5.0

func (c *ConstrainedBytesToStringModifierConfig) MarshalJSON() ([]byte, error)

func (*ConstrainedBytesToStringModifierConfig) ToModifier added in v0.5.0

func (c *ConstrainedBytesToStringModifierConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

type DropModifierConfig

type DropModifierConfig struct {
	Fields             []string
	EnablePathTraverse bool
}

DropModifierConfig drops all fields listed. The casing of the first character is ignored to allow compatibility. Note that unused fields are ignored by types.Codec. This is only required if you want to rename a field to an already used name. For example, if a struct has fields A and B, and you want to rename A to B, then you need to either also rename B or drop it.

func (*DropModifierConfig) MarshalJSON

func (d *DropModifierConfig) MarshalJSON() ([]byte, error)

func (*DropModifierConfig) ToModifier

func (d *DropModifierConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

type ElementExtractorFromOnchainModifierConfig added in v0.5.0

type ElementExtractorFromOnchainModifierConfig struct {
	// Key is the name of the field to extract from and the value is which element to extract.
	Extractions map[string]*ElementExtractorLocation
}

ElementExtractorFromOnchainModifierConfig is used to extract an element from an onchain slice or array.

func (*ElementExtractorFromOnchainModifierConfig) MarshalJSON added in v0.5.0

func (*ElementExtractorFromOnchainModifierConfig) ToModifier added in v0.5.0

func (e *ElementExtractorFromOnchainModifierConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

type ElementExtractorLocation

type ElementExtractorLocation int

ElementExtractorLocation is used to determine which element to extract from a slice or array. The default is ElementExtractorLocationMiddle, which will extract the middle element. valid json values are "first", "middle", and "last".

const (
	ElementExtractorLocationFirst ElementExtractorLocation = iota
	ElementExtractorLocationMiddle
	ElementExtractorLocationLast
	ElementExtractorLocationDefault = ElementExtractorLocationMiddle
)

func (ElementExtractorLocation) MarshalJSON

func (e ElementExtractorLocation) MarshalJSON() ([]byte, error)

func (*ElementExtractorLocation) UnmarshalJSON

func (e *ElementExtractorLocation) UnmarshalJSON(b []byte) error

type ElementExtractorModifierConfig

type ElementExtractorModifierConfig struct {
	// Key is the name of the field to extract from and the value is which element to extract.
	Extractions map[string]*ElementExtractorLocation
}

ElementExtractorModifierConfig is used to extract an element from a slice or array

func (*ElementExtractorModifierConfig) MarshalJSON

func (e *ElementExtractorModifierConfig) MarshalJSON() ([]byte, error)

func (*ElementExtractorModifierConfig) ToModifier

func (e *ElementExtractorModifierConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

type EpochToTimeModifierConfig

type EpochToTimeModifierConfig struct {
	Fields             []string
	EnablePathTraverse bool
}

EpochToTimeModifierConfig is used to convert epoch seconds as uint64 fields on-chain to time.Time

func (*EpochToTimeModifierConfig) MarshalJSON

func (e *EpochToTimeModifierConfig) MarshalJSON() ([]byte, error)

func (*EpochToTimeModifierConfig) ToModifier

func (e *EpochToTimeModifierConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

type ExampleAddressModifier added in v0.5.0

type ExampleAddressModifier struct{}

func (*ExampleAddressModifier) DecodeAddress added in v0.5.0

func (m *ExampleAddressModifier) DecodeAddress(str string) ([]byte, error)

func (*ExampleAddressModifier) EncodeAddress added in v0.5.0

func (m *ExampleAddressModifier) EncodeAddress(bts []byte) (string, error)

func (*ExampleAddressModifier) Length added in v0.5.0

func (m *ExampleAddressModifier) Length() int

type HardCodeModifierConfig

type HardCodeModifierConfig struct {
	OnChainValues      map[string]any
	OffChainValues     map[string]any
	EnablePathTraverse bool
}

HardCodeModifierConfig is used to hard code values into the map. Note that hard-coding values will override other values.

func (*HardCodeModifierConfig) MarshalJSON

func (h *HardCodeModifierConfig) MarshalJSON() ([]byte, error)

func (*HardCodeModifierConfig) ToModifier

func (h *HardCodeModifierConfig) ToModifier(onChainHooks ...mapstructure.DecodeHookFunc) (Modifier, error)

type ItemTyper added in v0.5.0

type ItemTyper string

func (ItemTyper) Next added in v0.5.0

func (t ItemTyper) Next() (string, string)

type Modifier

type Modifier interface {
	// RetypeToOffChain will retype the onChainType to its correlated offChainType. The itemType should be empty for an
	// expected whole struct. A dot-separated string can be provided when path traversal is supported on the modifier
	// to retype a nested field.
	//
	// For most modifiers, RetypeToOffChain must be called first with the entire struct to be retyped/modified before
	// any other transformations or path traversal can function.
	RetypeToOffChain(onChainType reflect.Type, itemType string) (reflect.Type, error)

	// TransformToOnChain transforms a type returned from AdjustForInput into the outputType.
	// You may also pass a pointer to the type returned by AdjustForInput to get a pointer to outputType.
	//
	// Modifiers should also optionally provide support for path traversal using itemType. In the case of using path
	// traversal, the offChainValue should be the field value being modified as identified by itemType.
	TransformToOnChain(offChainValue any, itemType string) (any, error)

	// TransformToOffChain is the reverse of TransformForOnChain input.
	// It is used to send back the object after it has been decoded
	//
	// Modifiers should also optionally provide support for path traversal using itemType. In the case of using path
	// traversal, the onChainValue should be the field value being modified as identified by itemType.
	TransformToOffChain(onChainValue any, itemType string) (any, error)
}

Modifier allows you to modify the off-chain type to be used on-chain, and vice-versa. A modifier is set up by retyping the on-chain type to a type used off-chain.

func NewAddressBytesToStringModifier added in v0.4.0

func NewAddressBytesToStringModifier(
	fields []string,
	modifier AddressModifier,
) Modifier

NewAddressBytesToStringModifier creates and returns a new modifier that transforms address byte arrays to their corresponding string representation (or vice versa) based on the provided AddressModifier.

The fields parameter specifies which fields within a struct should be modified. The AddressModifier is injected into the modifier to handle chain-specific logic during the contractReader relayer configuration.

func NewByItemTypeModifier

func NewByItemTypeModifier(modByItemType map[string]Modifier) (Modifier, error)

NewByItemTypeModifier returns a Modifier that uses modByItemType to determine which Modifier to use for a given itemType.

func NewByteToBooleanModifier added in v0.5.0

func NewByteToBooleanModifier(fields []string) Modifier

NewByteToBooleanModifier converts on-chain uint8 to off-chain bool and vice versa.

func NewConstrainedLengthBytesToStringModifier added in v0.5.0

func NewConstrainedLengthBytesToStringModifier(
	fields []string,
	maxLen int,
) Modifier

func NewElementExtractor

func NewElementExtractor(fields map[string]*ElementExtractorLocation) Modifier

NewElementExtractor creates a modifier that extracts an element from a slice or array. fields is used to determine which fields to extract elements from and which element to extract. This modifier is lossy, as TransformToOffChain will always return a slice of length 1 with the single element, so calling TransformToOnChain, then TransformToOffChain will not return the original value, if it has multiple elements.

func NewElementExtractorFromOnchain added in v0.5.0

func NewElementExtractorFromOnchain(fields map[string]*ElementExtractorLocation) Modifier

func NewEpochToTimeModifier

func NewEpochToTimeModifier(fields []string) Modifier

NewEpochToTimeModifier converts all fields from time.Time off-chain to int64.

func NewHardCoder

func NewHardCoder(
	onChain map[string]any,
	offChain map[string]any,
	hooks ...mapstructure.DecodeHookFunc,
) (Modifier, error)

NewHardCoder creates a modifier that will hard-code values for on-chain and off-chain types. The modifier will override any values of the same name, if you need an overwritten value to be used in a different field. NewRenamer must be used before NewHardCoder.

func NewNestableByItemTypeModifier added in v0.5.0

func NewNestableByItemTypeModifier(modByItemType map[string]Modifier) (Modifier, error)

NewNestableByItemTypeModifier returns a Modifier that uses modByItemType to determine which Modifier to use for a given itemType. If itemType is structured as a dot-separated string like 'A.B.C', the first part 'A' will be used to match in the mod map and the remaining list will be provided to the found Modifier 'B.C'.

func NewPathTraverseAddressBytesToStringModifier added in v0.5.0

func NewPathTraverseAddressBytesToStringModifier(
	fields []string,
	modifier AddressModifier,
	enablePathTraverse bool,
) Modifier
Example
package main

import (
	"crypto/rand"
	"fmt"
	"reflect"

	"github.com/smartcontractkit/chainlink-common/pkg/codec"
)

func main() {
	type onChainNested struct {
		X []byte
	}

	type onChain struct {
		A [32]byte
		B onChainNested
	}

	encoder := &codec.ExampleAddressModifier{}
	mod := codec.NewPathTraverseAddressBytesToStringModifier([]string{"B.X"}, encoder, true)

	// call RetypeToOffChain first with empty itemType to set base types
	offChainType, _ := mod.RetypeToOffChain(reflect.TypeOf(&onChain{}), "")

	fmt.Println("offChainType:")
	fmt.Println(offChainType)
	// offChainType:
	// struct { A: string; B: struct { X: string } }

	// calls to transform can transform the entire struct or nested fields specified by itemType
	onChainAddress := [32]byte{}
	_, _ = rand.Read(onChainAddress[:])

	offChainAddress, _ := mod.TransformToOffChain(onChainAddress, "A")

	// the onChainAddress value is modified to the offChainType
	fmt.Println(offChainAddress)
}
Output:

func NewPathTraverseConstrainedLengthBytesToStringModifier added in v0.5.0

func NewPathTraverseConstrainedLengthBytesToStringModifier(
	fields []string,
	maxLen int,
	enablePathTraverse bool,
) Modifier

func NewPathTraverseEpochToTimeModifier added in v0.5.0

func NewPathTraverseEpochToTimeModifier(fields []string, enablePathTraverse bool) Modifier

func NewPathTraverseHardCoder added in v0.5.0

func NewPathTraverseHardCoder(
	onChain map[string]any,
	offChain map[string]any,
	enablePathTraverse bool,
	hooks ...mapstructure.DecodeHookFunc,
) (Modifier, error)

func NewPathTraversePreCodec added in v0.5.0

func NewPathTraversePreCodec(
	fields map[string]string,
	codecs map[string]types.RemoteCodec,
	enablePathTraverse bool,
) (Modifier, error)

NewPathTraversePreCodec creates a PreCodec modifier with itemType path traversal enabled or disabled. The standard constructor. NewPreCodec has path traversal off by default.

func NewPathTraversePropertyExtractor added in v0.5.0

func NewPathTraversePropertyExtractor(fieldName string, enablePathTraverse bool) Modifier

func NewPathTraverseRenamer added in v0.5.0

func NewPathTraverseRenamer(fields map[string]string, enablePathTraverse bool) Modifier

func NewPathTraverseWrapperModifier added in v0.5.0

func NewPathTraverseWrapperModifier(fields map[string]string, enablePathTraverse bool) Modifier

func NewPreCodec added in v0.4.0

func NewPreCodec(
	fields map[string]string,
	codecs map[string]types.RemoteCodec,
) (Modifier, error)

NewPreCodec creates a modifier that will run a preliminary encoding/decoding step. This is useful when wanting to move nested data as generic bytes.

func NewPropertyExtractor

func NewPropertyExtractor(fieldName string) Modifier

NewPropertyExtractor creates a modifier that will extract a single property from a struct. This modifier is lossy, as TransformToOffchain will discard unwanted struct properties and return a single element. Calling TransformToOnchain will result in unset properties. Extracting a field which is nested under a slice of structs will return a slice containing the extracted property for every element of the slice, this is completely lossy and cannot be transformed back.

func NewRenamer

func NewRenamer(fields map[string]string) Modifier

func NewWrapperModifier added in v0.4.0

func NewWrapperModifier(fields map[string]string) Modifier

NewWrapperModifier creates a modifier that will wrap specified on-chain fields in a struct. if key is not provided in the config, the whole value is wrapped with the name of the value from config.

Example
package main

import (
	"log"
	"reflect"

	"github.com/smartcontractkit/chainlink-common/pkg/codec"
)

func main() {
	type nestedOnChain struct {
		C int
	}

	type onChain struct {
		A string
		B nestedOnChain
	}

	// specify the fields to be wrapped and the name of the new field with a map
	fields := map[string]string{"A": "X", "B.C": "Y"}
	wrapper := codec.NewWrapperModifier(fields)

	offChainType, _ := wrapper.RetypeToOffChain(reflect.TypeOf(onChain{}), "")

	// expected off-chain type:
	// struct { A struct { X string }; B struct { C struct { Y int } } }
	//
	// both A and B.C were wrapped in a new struct with the respective specified field names
	log.Println(offChainType)
}
Output:

type ModifierConfig

type ModifierConfig interface {
	ToModifier(onChainHooks ...mapstructure.DecodeHookFunc) (Modifier, error)
}

type ModifierType

type ModifierType string
const (
	ModifierPreCodec                  ModifierType = "precodec"
	ModifierRename                    ModifierType = "rename"
	ModifierDrop                      ModifierType = "drop"
	ModifierHardCode                  ModifierType = "hard code"
	ModifierExtractElement            ModifierType = "extract element"
	ModifierExtractElementFromOnchain ModifierType = "extract element from onchain"
	ModifierByteToBoolean             ModifierType = "byte to boolean"
	ModifierEpochToTime               ModifierType = "epoch to time"
	ModifierExtractProperty           ModifierType = "extract property"
	ModifierAddressToString           ModifierType = "address to string"
	ModifierBytesToString             ModifierType = "constrained bytes to string"
	ModifierWrapper                   ModifierType = "wrapper"
)

type ModifiersConfig

type ModifiersConfig []ModifierConfig

ModifiersConfig unmarshalls as a list of ModifierConfig by using a field called Type The values available for Type are case-insensitive and the config they require are below: - rename -> RenameModifierConfig - drop -> DropModifierConfig - hard code -> HardCodeModifierConfig - extract element -> ElementExtractorModifierConfig - extract element from onchain slice or array -> ElementExtractorFromOnchainModifierConfig - epoch to time -> EpochToTimeModifierConfig - bytes to boolean -> ByteToBooleanModifierConfig - address to string -> AddressBytesToStringModifierConfig - field wrapper -> WrapperModifierConfig - precodec -> PreCodecModifierConfig

func (*ModifiersConfig) ToModifier

func (m *ModifiersConfig) ToModifier(onChainHooks ...mapstructure.DecodeHookFunc) (Modifier, error)

func (*ModifiersConfig) UnmarshalJSON

func (m *ModifiersConfig) UnmarshalJSON(data []byte) error

type MultiModifier

type MultiModifier []Modifier

MultiModifier is a Modifier that applies each element for the slice in-order (reverse order for TransformForOnChain).

func (MultiModifier) RetypeToOffChain

func (c MultiModifier) RetypeToOffChain(onChainType reflect.Type, itemType string) (reflect.Type, error)

func (MultiModifier) TransformToOffChain

func (c MultiModifier) TransformToOffChain(onChainValue any, itemType string) (any, error)

func (MultiModifier) TransformToOnChain

func (c MultiModifier) TransformToOnChain(offChainValue any, itemType string) (any, error)

type Number

type Number string

func (Number) Float64

func (n Number) Float64() (float64, error)

func (Number) Int64

func (n Number) Int64() (int64, error)

func (Number) MarshalCBOR

func (n Number) MarshalCBOR() ([]byte, error)

func (Number) MarshalJSON

func (n Number) MarshalJSON() ([]byte, error)

func (*Number) UnmarshalCBOR

func (n *Number) UnmarshalCBOR(data []byte) error

func (*Number) UnmarshalJSON

func (n *Number) UnmarshalJSON(data []byte) error

type PathMappingError

type PathMappingError struct {
	Err  error
	Path string
}

func (PathMappingError) Cause

func (e PathMappingError) Cause() error

func (PathMappingError) Error

func (e PathMappingError) Error() string

type PreCodecModifierConfig added in v0.4.0

type PreCodecModifierConfig struct {
	// A map of a path of properties to encoding scheme.
	// If the path leads to an array, encoding will occur on every entry.
	//
	// Example: "a.b" -> "uint256 Value"
	Fields             map[string]string
	EnablePathTraverse bool
	// Codecs is skipped in JSON serialization, it will be injected later.
	// The map should be keyed using the value from "Fields" to a corresponding Codec that can encode/decode for it
	// This allows encoding and decoding implementations to be handled outside of the modifier.
	//
	// Example: "uint256 Value" -> a chain specific encoder for "uint256 Value"
	Codecs map[string]types.RemoteCodec `json:"-"`
}

PreCodec creates a modifier that will transform data using a preliminary encoding/decoding step. 'Off-chain' values will be overwritten with the encoded data as a byte array. 'On-chain' values will be typed using the optimistic types from the codec. This is useful when wanting to move the data as generic bytes.

			Example:

			Based on this input struct:
				type example struct {
					A []B
				}

				type B struct {
					C string
					D string
				}

			And the fields config defined as:
		 		{"A": "string C, string D"}

			The codec config gives a map of strings (the values from fields config map) to implementation for encoding/decoding

	           RemoteCodec {
	              func (types.TypeProvider) CreateType(itemType string, forEncoding bool) (any, error)
	              func (types.Decoder) Decode(ctx context.Context, raw []byte, into any, itemType string) error
	              func (types.Encoder) Encode(ctx context.Context, item any, itemType string) ([]byte, error)
	              func (types.Decoder) GetMaxDecodingSize(ctx context.Context, n int, itemType string) (int, error)
	              func (types.Encoder) GetMaxEncodingSize(ctx context.Context, n int, itemType string) (int, error)
	           }

	  		   {"string C, string D": RemoteCodec}

			Result:
				type example struct {
					A [][]bytes
				}

             Where []bytes are the encoded input struct B

func (*PreCodecModifierConfig) MarshalJSON added in v0.4.0

func (c *PreCodecModifierConfig) MarshalJSON() ([]byte, error)

func (*PreCodecModifierConfig) ToModifier added in v0.4.0

func (c *PreCodecModifierConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

type PropertyExtractorConfig

type PropertyExtractorConfig struct {
	FieldName          string
	EnablePathTraverse bool
}

func (*PropertyExtractorConfig) MarshalJSON

func (c *PropertyExtractorConfig) MarshalJSON() ([]byte, error)

func (*PropertyExtractorConfig) ToModifier

func (c *PropertyExtractorConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

type RenameModifierConfig

type RenameModifierConfig struct {
	Fields             map[string]string
	EnablePathTraverse bool
}

RenameModifierConfig renames all fields in the map from the key to the value The casing of the first character is ignored to allow compatibility of go convention for public fields and on-chain names.

func (*RenameModifierConfig) MarshalJSON

func (r *RenameModifierConfig) MarshalJSON() ([]byte, error)

func (*RenameModifierConfig) ToModifier

func (r *RenameModifierConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

type WrapperModifierConfig added in v0.4.0

type WrapperModifierConfig struct {
	// Fields key defines the fields to be wrapped and the name of the wrapper struct.
	// The field becomes a subfield of the wrapper struct where the name of the subfield is map value.
	Fields             map[string]string
	EnablePathTraverse bool
}

WrapperModifierConfig replaces each field based on cfg map keys with a struct containing one field with the value of the original field which has is named based on map values. Wrapper modifier does not maintain the original pointers. Wrapper modifier config shouldn't edit fields that affect each other since the results are not deterministic. To wrap the whole value instead of fields, the config map should only have one entry where the key is an empty string "", and the value is the name of the field that will contain the value.

	Example #1:

	Based on this input struct:
		type example struct {
			A string
		}

	And the wrapper config defined as:
 		{"D": "W"}

	Result:
		type example struct {
			D
		}

	where D is a struct that contains the original value of D under the name W:
		type D struct {
			W string
		}

	Example #2:
	Wrapper modifier works on any type of field, including nested fields or nested fields in slices etc.!

	Based on this input struct:
		type example struct {
			A []B
		}

		type B struct {
			C string
			D string
		}

	And the wrapper config defined as:
 		{"A.C": "E", "A.D": "F"}

	Result:
		type example struct {
			A []B
		}

		type B struct {
			C type struct { E string }
			D type struct { F string }
		}

	Where each element of slice A under fields C.E and D.F retains the values of their respective input slice elements A.C and A.D .

func (*WrapperModifierConfig) MarshalJSON added in v0.4.0

func (r *WrapperModifierConfig) MarshalJSON() ([]byte, error)

func (*WrapperModifierConfig) ToModifier added in v0.4.0

func (r *WrapperModifierConfig) ToModifier(_ ...mapstructure.DecodeHookFunc) (Modifier, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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