diff --git a/plutusencoder/plutus.go b/plutusencoder/plutus.go index 18d7ef3..b38f53d 100644 --- a/plutusencoder/plutus.go +++ b/plutusencoder/plutus.go @@ -98,6 +98,25 @@ func MarshalPlutus(v interface{}) (*PlutusData.PlutusData, error) { overallContainer = append(overallContainer.(PlutusData.PlutusDefArray), pdi) } } + case "StringBytes": + if values.Field(i).Kind() != reflect.String { + return nil, fmt.Errorf("error: StringBytes field is not string") + } + pdsb := PlutusData.PlutusData{ + PlutusDataType: PlutusData.PlutusBytes, + Value: []byte(values.Field(i).Interface().(string)), + TagNr: constr, + } + if isMap { + nameBytes := serialization.CustomBytes{Value: name} + overallContainer.(map[serialization.CustomBytes]PlutusData.PlutusData)[nameBytes] = pdsb + } else { + if isIndef { + overallContainer = append(overallContainer.(PlutusData.PlutusIndefArray), pdsb) + } else { + overallContainer = append(overallContainer.(PlutusData.PlutusDefArray), pdsb) + } + } default: pd, err := MarshalPlutus(values.Field(i).Interface()) if err != nil { diff --git a/plutusencoder/plutusencoder_test.go b/plutusencoder/plutusencoder_test.go index 1df193f..ae02412 100644 --- a/plutusencoder/plutusencoder_test.go +++ b/plutusencoder/plutusencoder_test.go @@ -15,16 +15,18 @@ type BuyerDatum struct { Skh []byte `plutusType:"Bytes"` } type Datum struct { - _ struct{} `plutusType:"IndefList" plutusConstr:"1"` - Pkh []byte `plutusType:"Bytes"` - Amount int64 `plutusType:"Int"` - Buyer BuyerDatum + _ struct{} `plutusType:"IndefList" plutusConstr:"1"` + Pkh []byte `plutusType:"Bytes"` + RandomText string `plutusType:"StringBytes"` + Amount int64 `plutusType:"Int"` + Buyer BuyerDatum } func TestPlutusMarshal(t *testing.T) { d := Datum{ - Pkh: []byte{0x01, 0x02, 0x03, 0x04}, - Amount: 1000000, + Pkh: []byte{0x01, 0x02, 0x03, 0x04}, + Amount: 1000000, + RandomText: "Hello World", Buyer: BuyerDatum{ Pkh: []byte{0x01, 0x02, 0x03, 0x04}, Amount: 1000000, @@ -36,7 +38,7 @@ func TestPlutusMarshal(t *testing.T) { t.Error(err) } encoded, err := cbor.Marshal(marshaled) - if hex.EncodeToString(encoded) != "d87a9f44010203041a000f4240d87b8344010203041a000f42404401020304ff" { + if hex.EncodeToString(encoded) != "d87a9f44010203044b48656c6c6f20576f726c641a000f4240d87b8344010203041a000f42404401020304ff" { t.Error("encoding error") } } diff --git a/plutusencoder/readme.md b/plutusencoder/readme.md index dbece66..7b963bf 100644 --- a/plutusencoder/readme.md +++ b/plutusencoder/readme.md @@ -1,7 +1,7 @@ Plutus Struct tags: plutusConstr: int -> Defines the constructor - for no constructor -plutusType: Bytes || Int || Map || IndefList || DefList +plutusType: Bytes || Int || Map || IndefList || DefList || StringBytes diff --git a/serialization/Value/Value.go b/serialization/Value/Value.go index 77946fb..bc86bcc 100644 --- a/serialization/Value/Value.go +++ b/serialization/Value/Value.go @@ -23,7 +23,9 @@ type AlonzoValue struct { HasAssets bool } -/** +/* +* + UnmarshalCBOR deserializes CBOr-encoded data into an AlonzoValue. Params: @@ -50,7 +52,9 @@ func (val *AlonzoValue) UnmarshalCBOR(value []byte) error { return nil } -/** +/* +* + MarshalCBOR serializes the AlonzoValue into an CBOr-encoded data. Returns: @@ -68,11 +72,13 @@ func (alVal *AlonzoValue) MarshalCBOR() ([]byte, error) { if alVal.Coin < 0 { return nil, errors.New("invalid coin value") } - return cbor.Marshal([]any{alVal.Coin, map[any]any{}}) + return cbor.Marshal(alVal.Coin) } } -/** +/* +* + Clone creates a copy of the AlonzoValue, including its assets. Returns: @@ -86,7 +92,9 @@ func (alVal AlonzoValue) Clone() AlonzoValue { } } -/** +/* +* + ToAlonzoValue converts a Value object to an AlonzoValue, preserving its attributes. Returns: @@ -100,7 +108,9 @@ func (val Value) ToAlonzoValue() AlonzoValue { } } -/** +/* +* + ToValue converts an AlonzoValue to a Value object, preserving its attributes. Returns: @@ -114,7 +124,9 @@ func (alVal AlonzoValue) ToValue() Value { } } -/** +/* +* + RemoveZeroAssets removes assets with zero values from a Value. Returns: @@ -128,7 +140,9 @@ func (val Value) RemoveZeroAssets() Value { return res } -/** +/* +* + Clone creates a copy of the Value, including its assets. Returns: @@ -142,10 +156,12 @@ func (val Value) Clone() Value { } } -/** +/* +* + AddAssets adds MultiAsset assets to a Value. - Params: + Params: other (MultiAsset.MultiAsset[int64]): the MultiAssets assets to be added. */ func (val *Value) AddAssets(other MultiAsset.MultiAsset[int64]) { @@ -159,13 +175,15 @@ func (val *Value) AddAssets(other MultiAsset.MultiAsset[int64]) { } } -/** +/* +* + SimpleValue creates a Value object with a specified coin value and a MultiAssets. Params: coin (int64): The coin value. assets (MultiAsset.MultiAsset[int64]): the assets. - + Returns: Value: A Value object. */ @@ -184,7 +202,9 @@ func SimpleValue(coin int64, assets MultiAsset.MultiAsset[int64]) Value { } } -/** +/* +* + SubLovelace subtracts a specified amount of Lovelace (coin) from the Value. In case that there aren't any assets, then it subtracts from the Coin field, otherwise from the AlonzoAmount's Coin field. @@ -200,7 +220,9 @@ func (val *Value) SubLovelace(amount int64) { } } -/** +/* +* + AddLovelace adds a specified amount of Lovelace (coin) from the Value. In case that there aren't any assets, then it adds to the Coin field, otherwise to the AlonzoAmount's Coin field. @@ -216,7 +238,9 @@ func (val *Value) AddLovelace(amount int64) { } } -/** +/* +* + SetLovelace sets a specified amount of Lovelace (coin) in the Value. In case that there aren't any assets, then it sets the Coin field, otherwise it sets the AlonzoAmount's Coin field. @@ -232,7 +256,9 @@ func (val *Value) SetLovelace(amount int64) { } } -/** +/* +* + SetMultiAsset sets the MultiAsset in the Value. Params: @@ -245,7 +271,9 @@ func (val *Value) SetMultiAsset(amount MultiAsset.MultiAsset[int64]) { val.Am.Value = amount } -/** +/* +* + GetCoin returns the amount of Lovelace (coin) in the Value. Returns: @@ -258,7 +286,9 @@ func (val Value) GetCoin() int64 { return val.Coin } -/** +/* +* + GetAssets returns the MultiAsset assets in the Value. Returns: @@ -271,7 +301,9 @@ func (val Value) GetAssets() MultiAsset.MultiAsset[int64] { return nil } -/** +/* +* + Add function adds another Value to the current Value. Params: @@ -300,7 +332,9 @@ func (val Value) Add(other Value) Value { return res } -/** +/* +* + Sub function subtracts another Value to the current Value. Params: @@ -327,7 +361,9 @@ func (val Value) Sub(other Value) Value { return res } -/** +/* +* + Less checks if the current Value is less than another Value. Params: @@ -340,7 +376,9 @@ func (val Value) Less(other Value) bool { return val.GetCoin() <= other.GetCoin() && val.GetAssets().Less(other.GetAssets()) } -/** +/* +* + Equal checks if the current Value is equal to another Value. Params: @@ -353,7 +391,9 @@ func (val Value) Equal(other Value) bool { return val.HasAssets == other.HasAssets && val.Coin == other.Coin && val.Am.Equal(other.Am) } -/** +/* +* + LessOrEqual checks if the current Value is less than or equal to another Value. Params: @@ -366,7 +406,9 @@ func (val Value) LessOrEqual(other Value) bool { return val.Equal(other) || val.Less(other) } -/** +/* +* + Greater checks if the current Value is greater than another Value. Params: @@ -380,7 +422,9 @@ func (val Value) Greater(other Value) bool { } -/** +/* +* + GreaterOrEqual checks if the current Value is greater than or equal to another Value. Params: @@ -393,7 +437,9 @@ func (val Value) GreaterOrEqual(other Value) bool { return val.Greater(other) || val.Equal(other) } -/** +/* +* + String reutnrs a string representation of teh Value. Returns: @@ -407,16 +453,18 @@ func (val Value) String() string { } } -/** - UnmarshalCBOR unmarshals a CBOR-encoded byte slice into the Value, - which decoed either a uint64 inot the Coin field or a CBOR-encoded Amount - into the AlonzoAmount field. +/* +* - Params: - value ([]byte): The CBOR-encoded byte slice to unmarshal. - - Returns: - error: An error if unmarshaling fails. + UnmarshalCBOR unmarshals a CBOR-encoded byte slice into the Value, + which decoed either a uint64 inot the Coin field or a CBOR-encoded Amount + into the AlonzoAmount field. + + Params: + value ([]byte): The CBOR-encoded byte slice to unmarshal. + + Returns: + error: An error if unmarshaling fails. */ func (val *Value) UnmarshalCBOR(value []byte) error { var rec any @@ -436,11 +484,13 @@ func (val *Value) UnmarshalCBOR(value []byte) error { return nil } -/** +/* +* + MarshalCBOR marshals the Value into a CBOR-encoded byte slice. If the Value has assets, then it encodes the AlonzoAmount using CBOR, otherwise it encodes the Coin field directly. - + Returns: []byte: The CBOR-encoded byte slice. error: An error if marshaling fails. @@ -460,15 +510,17 @@ func (val *Value) MarshalCBOR() ([]byte, error) { } } -/** - PureLovelaceValue creates a Value with only a specified amount - of Lovelace (coin) and no assets. +/* +* - Params: - coin (int64): The amount of Lovelace (coin) to set in the Value. + PureLovelaceValue creates a Value with only a specified amount + of Lovelace (coin) and no assets. - Returns: - Value: The Value with the specified amount of Lovelace and no assets. + Params: + coin (int64): The amount of Lovelace (coin) to set in the Value. + + Returns: + Value: The Value with the specified amount of Lovelace and no assets. */ func PureLovelaceValue(coin int64) Value { return Value{Coin: coin, HasAssets: false} diff --git a/tests/serialization/TransactionOutput/TransactionOutput_test.go b/tests/serialization/TransactionOutput/TransactionOutput_test.go index 807b5dd..8cc13c5 100644 --- a/tests/serialization/TransactionOutput/TransactionOutput_test.go +++ b/tests/serialization/TransactionOutput/TransactionOutput_test.go @@ -6,7 +6,11 @@ import ( "testing" "github.com/Salvionied/apollo/serialization/Address" + "github.com/Salvionied/apollo/serialization/Asset" + "github.com/Salvionied/apollo/serialization/AssetName" + "github.com/Salvionied/apollo/serialization/MultiAsset" "github.com/Salvionied/apollo/serialization/PlutusData" + "github.com/Salvionied/apollo/serialization/Policy" "github.com/Salvionied/apollo/serialization/Transaction" "github.com/Salvionied/apollo/serialization/TransactionOutput" "github.com/Salvionied/apollo/serialization/Value" @@ -44,7 +48,7 @@ func TestPostAlonzo(t *testing.T) { txO.PostAlonzo.Amount = Value.PureLovelaceValue(1000000).ToAlonzoValue() d := PlutusData.DatumOptionInline(&pd) txO.PostAlonzo.Datum = &d - resultHex := "a300581d712618e94cdb06792f05ae9b1ec78b0231f4b7f4215b1b4cf52e6342de01821a000f4240a0028201d81858e8d8799fd8799fd8799f581c37dce7298152979f0d0ff71fb2d0c759b298ac6fa7bc56b928ffc1bcffd8799fd8799fd8799f581cf68864a338ae8ed81f61114d857cb6a215c8e685aa5c43bc1f879cceffffffffd8799fd8799f581c37dce7298152979f0d0ff71fb2d0c759b298ac6fa7bc56b928ffc1bcffd8799fd8799fd8799f581cf68864a338ae8ed81f61114d857cb6a215c8e685aa5c43bc1f879cceffffffffd87a80d8799fd8799f581c25f0fc240e91bd95dcdaebd2ba7713fc5168ac77234a3d79449fc20c47534f4349455459ff1b00002cc16be02b37ff1a001e84801a001e8480ff" + resultHex := "a300581d712618e94cdb06792f05ae9b1ec78b0231f4b7f4215b1b4cf52e6342de011a000f4240028201d81858e8d8799fd8799fd8799f581c37dce7298152979f0d0ff71fb2d0c759b298ac6fa7bc56b928ffc1bcffd8799fd8799fd8799f581cf68864a338ae8ed81f61114d857cb6a215c8e685aa5c43bc1f879cceffffffffd8799fd8799f581c37dce7298152979f0d0ff71fb2d0c759b298ac6fa7bc56b928ffc1bcffd8799fd8799fd8799f581cf68864a338ae8ed81f61114d857cb6a215c8e685aa5c43bc1f879cceffffffffd87a80d8799fd8799f581c25f0fc240e91bd95dcdaebd2ba7713fc5168ac77234a3d79449fc20c47534f4349455459ff1b00002cc16be02b37ff1a001e84801a001e8480ff" cborred, _ := cbor.Marshal(txO) if hex.EncodeToString(cborred) != resultHex { fmt.Println(hex.EncodeToString(cborred)) @@ -73,3 +77,34 @@ func TestDeSerializeTxWithPostAlonzoOut(t *testing.T) { } } + +func TestValueSerialization(t *testing.T) { + ShelleyValueWithNoAssets := Value.PureLovelaceValue(1000000) + ShelleyValueWithAssets := Value.SimpleValue(1_000_000, MultiAsset.MultiAsset[int64]{ + Policy.PolicyId{"115a3b670ea8b6b99d1c3d1d8041d7da9bd0b45532c24481cdbd9818"}: Asset.Asset[int64]{ + AssetName.NewAssetNameFromString("Token1"): 1, + }, + }) + AlonzoValueWithNoAssets := Value.PureLovelaceValue(1000000).ToAlonzoValue() + AlonzoValueWithAssets := Value.SimpleValue(1_000_000, MultiAsset.MultiAsset[int64]{ + Policy.PolicyId{"115a3b670ea8b6b99d1c3d1d8041d7da9bd0b45532c24481cdbd9818"}: Asset.Asset[int64]{ + AssetName.NewAssetNameFromString("Token1"): 1, + }, + }).ToAlonzoValue() + ShelleyValueWithNoAssetsBytes, _ := cbor.Marshal(ShelleyValueWithNoAssets) + ShelleyValueWithAssetsBytes, _ := cbor.Marshal(ShelleyValueWithAssets) + AlonzoValueWithNoAssetsBytes, _ := cbor.Marshal(AlonzoValueWithNoAssets) + AlonzoValueWithAssetsBytes, _ := cbor.Marshal(AlonzoValueWithAssets) + if hex.EncodeToString(ShelleyValueWithNoAssetsBytes) != "1a000f4240" { + t.Error("ShelleyValueWithNoAssetsBytes") + } + if hex.EncodeToString(AlonzoValueWithNoAssetsBytes) != "1a000f4240" { + t.Error("AlonzoValueWithNoAssetsBytes") + } + if hex.EncodeToString(ShelleyValueWithAssetsBytes) != "821a000f4240a1581c115a3b670ea8b6b99d1c3d1d8041d7da9bd0b45532c24481cdbd9818a146546f6b656e3101" { + t.Error("ShelleyValueWithAssetsBytes") + } + if hex.EncodeToString(AlonzoValueWithAssetsBytes) != "821a000f4240a1581c115a3b670ea8b6b99d1c3d1d8041d7da9bd0b45532c24481cdbd9818a146546f6b656e3101" { + t.Error("AlonzoValueWithAssetsBytes") + } +}