diff --git a/pkg/serialization/codec/codec.go b/pkg/serialization/codec/codec.go
index d994723..11c424a 100644
--- a/pkg/serialization/codec/codec.go
+++ b/pkg/serialization/codec/codec.go
@@ -2,5 +2,7 @@ package codec
 
 type Codec interface {
 	Marshal(v interface{}) ([]byte, error)
+	MarshalGeneral(x uint64) ([]byte, error)
 	Unmarshal(data []byte, v interface{}) error
+	UnmarshalGeneral(data []byte, v *uint64) error
 }
diff --git a/pkg/serialization/codec/jam/errors.go b/pkg/serialization/codec/jam/errors.go
new file mode 100644
index 0000000..addb023
--- /dev/null
+++ b/pkg/serialization/codec/jam/errors.go
@@ -0,0 +1,8 @@
+package jam
+
+import "errors"
+
+var (
+	// errFirstByteNineByteSerialization is returned when the first byte has wrong value in 9-byte serialization
+	errFirstByteNineByteSerialization = errors.New("expected first byte to be 255 for 9-byte serialization")
+)
diff --git a/pkg/serialization/codec/jam/general_natural.go b/pkg/serialization/codec/jam/general_natural.go
new file mode 100644
index 0000000..8860601
--- /dev/null
+++ b/pkg/serialization/codec/jam/general_natural.go
@@ -0,0 +1,65 @@
+package jam
+
+import (
+	"encoding/binary"
+	"math"
+	"math/bits"
+)
+
+// GeneralNatural implements the formula (275: able to encode naturals of up to 2^64)
+type GeneralNatural struct{}
+
+func (j *GeneralNatural) SerializeUint64(x uint64) []byte {
+	var l uint8
+	// Determine the length needed to represent the value
+	for l = 0; l < 8; l++ {
+		if x < (1 << (7 * (l + 1))) {
+			break
+		}
+	}
+	bytes := make([]byte, 0)
+	if l < 8 {
+		// Calculate the prefix byte, ensure it stays within uint8 range
+		prefix := uint8((256 - (1 << (8 - l))) + (x>>(8*l))&math.MaxUint8)
+		bytes = append(bytes, prefix)
+	} else {
+		bytes = append(bytes, math.MaxUint8)
+	}
+	// Serialize the integer in little-endian order
+	for i := 0; i < int(l); i++ {
+		byteVal := uint8((x >> (8 * i)) & math.MaxUint8)
+		bytes = append(bytes, byteVal)
+	}
+	return bytes
+}
+
+// DeserializeUint64 deserializes a byte slice into a uint64 value.
+func (j *GeneralNatural) DeserializeUint64(serialized []byte, u *uint64) error {
+	*u = 0
+
+	n := len(serialized)
+	if n == 0 {
+		return nil
+	}
+
+	if n > 8 {
+		if serialized[0] != math.MaxUint8 {
+			return errFirstByteNineByteSerialization
+		}
+		*u = binary.LittleEndian.Uint64(serialized[1:9])
+		return nil
+	}
+
+	prefix := serialized[0]
+	l := uint8(bits.LeadingZeros8(^prefix))
+
+	// Deserialize the first `l` bytes
+	for i := uint8(0); i < l; i++ {
+		*u |= uint64(serialized[i+1]) << (8 * i)
+	}
+
+	// Combine the remaining part of the prefix
+	*u |= uint64(prefix&(math.MaxUint8>>l)) << (8 * l)
+
+	return nil
+}
diff --git a/pkg/serialization/codec/jam/general_natural_test.go b/pkg/serialization/codec/jam/general_natural_test.go
new file mode 100644
index 0000000..1ab6df9
--- /dev/null
+++ b/pkg/serialization/codec/jam/general_natural_test.go
@@ -0,0 +1,71 @@
+package jam
+
+import (
+	"fmt"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+	"math"
+	"testing"
+)
+
+func TestEncodeDecodeUint64(t *testing.T) {
+	testCases := []struct {
+		input    uint64
+		expected []byte
+	}{
+		// l = 0
+		{0, []byte{0}},
+		{1, []byte{1}},
+		{math.MaxInt8, []byte{127}}, // 127
+		// l = 1
+		{1 << 7, []byte{128, 128}},        // 128
+		{math.MaxUint8, []byte{128, 255}}, // 255
+		{1 << 8, []byte{129, 0}},          // 256
+		{(1 << 10) - 1, []byte{131, 255}}, // 1023
+		{1 << 10, []byte{132, 0}},         // 1024
+		{(1 << 14) - 1, []byte{191, 255}}, // 16383
+		//l = 2
+		{1 << 14, []byte{192, 0, 64}},           // 16384
+		{math.MaxUint16, []byte{192, 255, 255}}, // 65535
+		{1 << 16, []byte{193, 0, 0}},            // 65536
+		{(1 << 21) - 1, []byte{223, 255, 255}},  // 2097151
+		//l = 3
+		{1 << 21, []byte{224, 0, 0, 32}},            // 2097152
+		{(1 << 28) - 1, []byte{239, 255, 255, 255}}, // 268435455
+		//l = 4
+		{1 << 28, []byte{240, 0, 0, 0, 16}},              // 268435456
+		{(1 << 35) - 1, []byte{247, 255, 255, 255, 255}}, // 34359738367
+		//l = 5
+		{1 << 35, []byte{248, 0, 0, 0, 0, 8}},                 // 34359738368
+		{(1 << 42) - 1, []byte{251, 255, 255, 255, 255, 255}}, // 4398046511103
+		//l = 6
+		{1 << 42, []byte{252, 0, 0, 0, 0, 0, 4}},                   // 4398046511104
+		{(1 << 49) - 1, []byte{253, 255, 255, 255, 255, 255, 255}}, // 562949953421311
+		//l = 7
+		{1 << 49, []byte{254, 0, 0, 0, 0, 0, 0, 2}},                     // 562949953421312
+		{(1 << 56) - 1, []byte{254, 255, 255, 255, 255, 255, 255, 255}}, // 72057594037927935
+		// l = 8
+		{1 << 56, []byte{255, 0, 0, 0, 0, 0, 0, 0, 1}},   // 72057594037927936
+		{1 << 63, []byte{255, 0, 0, 0, 0, 0, 0, 0, 128}}, // 9223372036854775808
+	}
+
+	gn := GeneralNatural{}
+
+	for _, tc := range testCases {
+		t.Run(fmt.Sprintf("uint64(%d)", tc.input), func(t *testing.T) {
+			// Marshal the input value
+			serialized := gn.SerializeUint64(tc.input)
+
+			// Check if the serialized output matches the expected output
+			assert.Equal(t, tc.expected, serialized, "serialized output mismatch for input %d", tc.input)
+
+			// Unmarshal the serialized data back into a uint64
+			var deserialized uint64
+			err := gn.DeserializeUint64(serialized, &deserialized)
+			require.NoError(t, err, "unmarshal(%v) returned an unexpected error", serialized)
+
+			// Check if the deserialized value matches the original input
+			assert.Equal(t, tc.input, deserialized, "deserialized value mismatch for input %d", tc.input)
+		})
+	}
+}
diff --git a/pkg/serialization/codec/jam_codec.go b/pkg/serialization/codec/jam_codec.go
new file mode 100644
index 0000000..b44f017
--- /dev/null
+++ b/pkg/serialization/codec/jam_codec.go
@@ -0,0 +1,34 @@
+package codec
+
+import (
+	"errors"
+	"github.com/eigerco/strawberry/pkg/serialization/codec/jam"
+)
+
+// JAMCodec implements the Codec interface for JSON encoding and decoding.
+type JAMCodec struct {
+	gn jam.GeneralNatural
+}
+
+// NewJamCodec initializes an instance of Jam codec
+func NewJamCodec() *JAMCodec {
+	return &JAMCodec{gn: jam.GeneralNatural{}}
+}
+
+func (j *JAMCodec) Marshal(v interface{}) ([]byte, error) {
+	// TODO
+	return nil, errors.New("not implemented")
+}
+
+func (j *JAMCodec) MarshalGeneral(v uint64) ([]byte, error) {
+	return j.gn.SerializeUint64(v), nil
+}
+
+func (j *JAMCodec) Unmarshal(data []byte, v interface{}) error {
+	// TODO
+	return errors.New("not implemented")
+}
+
+func (j *JAMCodec) UnmarshalGeneral(data []byte, v *uint64) error {
+	return j.gn.DeserializeUint64(data, v)
+}
diff --git a/pkg/serialization/codec/json_codec.go b/pkg/serialization/codec/json_codec.go
index fb5e78f..e2f9bdd 100644
--- a/pkg/serialization/codec/json_codec.go
+++ b/pkg/serialization/codec/json_codec.go
@@ -11,6 +11,14 @@ func (j *JSONCodec) Marshal(v interface{}) ([]byte, error) {
 	return json.Marshal(v)
 }
 
+func (j *JSONCodec) MarshalGeneral(v uint64) ([]byte, error) {
+	return json.Marshal(v)
+}
+
 func (j *JSONCodec) Unmarshal(data []byte, v interface{}) error {
 	return json.Unmarshal(data, v)
 }
+
+func (j *JSONCodec) UnmarshalGeneral(data []byte, v *uint64) error {
+	return json.Unmarshal(data, v)
+}
diff --git a/pkg/serialization/codec/scale_codec.go b/pkg/serialization/codec/scale_codec.go
index e9e101a..0a3b2a3 100644
--- a/pkg/serialization/codec/scale_codec.go
+++ b/pkg/serialization/codec/scale_codec.go
@@ -9,6 +9,14 @@ func (s *SCALECodec) Marshal(v interface{}) ([]byte, error) {
 	return scale.Marshal(v)
 }
 
+func (j *SCALECodec) MarshalGeneral(v uint64) ([]byte, error) {
+	return scale.Marshal(v)
+}
+
 func (s *SCALECodec) Unmarshal(data []byte, v interface{}) error {
 	return scale.Unmarshal(data, v)
 }
+
+func (s *SCALECodec) UnmarshalGeneral(data []byte, v *uint64) error {
+	return scale.Unmarshal(data, v)
+}
diff --git a/pkg/serialization/serializer.go b/pkg/serialization/serializer.go
index 41f2982..e0aa7bf 100644
--- a/pkg/serialization/serializer.go
+++ b/pkg/serialization/serializer.go
@@ -17,7 +17,17 @@ func (s *Serializer) Encode(v interface{}) ([]byte, error) {
 	return s.codec.Marshal(v)
 }
 
+// EncodeGeneral is specific encoding for natural numbers up to 2^64
+func (s *Serializer) EncodeGeneral(v uint64) ([]byte, error) {
+	return s.codec.MarshalGeneral(v)
+}
+
 // Decode deserializes the given data into the specified value using the codec.
 func (s *Serializer) Decode(data []byte, v interface{}) error {
 	return s.codec.Unmarshal(data, v)
 }
+
+// DecodeGeneral is specific decoding for natural numbers up to 2^64
+func (s *Serializer) DecodeGeneral(data []byte, v *uint64) error {
+	return s.codec.UnmarshalGeneral(data, v)
+}
diff --git a/pkg/serialization/serializer_test.go b/pkg/serialization/serializer_test.go
index 6bf1865..b066682 100644
--- a/pkg/serialization/serializer_test.go
+++ b/pkg/serialization/serializer_test.go
@@ -50,3 +50,20 @@ func TestSCALESerializer(t *testing.T) {
 	require.NoError(t, err)
 	assert.Equal(t, example, decoded)
 }
+
+func TestGeneralSerializer(t *testing.T) {
+	jamCodec := codec.NewJamCodec()
+	serializer := serialization.NewSerializer(jamCodec)
+
+	// Test Encoding
+	v := uint64(127)
+	encoded, err := serializer.EncodeGeneral(v)
+	require.NoError(t, err)
+	require.Equal(t, []byte{127}, encoded)
+
+	// Test Decoding
+	var decoded uint64
+	err = serializer.DecodeGeneral(encoded, &decoded)
+	require.NoError(t, err)
+	assert.Equal(t, v, decoded)
+}