Skip to content

Commit c4235a9

Browse files
committed
feat: helper function to convert MultiAsset to PlutusData
Fixes #1101 Signed-off-by: Aurora Gaffney <[email protected]>
1 parent 3dcd8a2 commit c4235a9

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

ledger/common/common.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@
1515
package common
1616

1717
import (
18+
"bytes"
1819
"encoding/hex"
1920
"encoding/json"
2021
"fmt"
22+
"maps"
23+
"math/big"
24+
"slices"
2125

2226
"github.com/blinklabs-io/gouroboros/cbor"
2327
"github.com/blinklabs-io/plutigo/pkg/data"
@@ -199,6 +203,38 @@ func (m MultiAsset[T]) MarshalJSON() ([]byte, error) {
199203
return json.Marshal(&tmpAssets)
200204
}
201205

206+
func (m *MultiAsset[T]) ToPlutusData() data.PlutusData {
207+
tmpData := make([][2]data.PlutusData, 0, len(m.data))
208+
// Sort policy IDs
209+
policyKeys := slices.Collect(maps.Keys(m.data))
210+
slices.SortFunc(policyKeys, func(a, b Blake2b224) int { return bytes.Compare(a.Bytes(), b.Bytes()) })
211+
for _, policyId := range policyKeys {
212+
policyData := m.data[policyId]
213+
tmpPolicyData := make([][2]data.PlutusData, 0, len(policyData))
214+
// Sort asset names
215+
assetKeys := slices.Collect(maps.Keys(policyData))
216+
slices.SortFunc(assetKeys, func(a, b cbor.ByteString) int { return bytes.Compare(a.Bytes(), b.Bytes()) })
217+
for _, assetName := range assetKeys {
218+
amount := policyData[assetName]
219+
tmpPolicyData = append(
220+
tmpPolicyData,
221+
[2]data.PlutusData{
222+
data.NewByteString(assetName.Bytes()),
223+
data.NewInteger(big.NewInt(int64(amount))),
224+
},
225+
)
226+
}
227+
tmpData = append(
228+
tmpData,
229+
[2]data.PlutusData{
230+
data.NewByteString(policyId.Bytes()),
231+
data.NewMap(tmpPolicyData),
232+
},
233+
)
234+
}
235+
return data.NewMap(tmpData)
236+
}
237+
202238
func (m *MultiAsset[T]) Policies() []Blake2b224 {
203239
ret := []Blake2b224{}
204240
for policyId := range m.data {

ledger/common/common_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package common
1717
import (
1818
"encoding/hex"
1919
"encoding/json"
20+
"math/big"
2021
"reflect"
2122
"testing"
2223

@@ -128,6 +129,90 @@ func TestMultiAssetJson(t *testing.T) {
128129
}
129130
}
130131

132+
func TestMultiAssetToPlutusData(t *testing.T) {
133+
testDefs := []struct {
134+
multiAssetObj any
135+
expectedData data.PlutusData
136+
}{
137+
{
138+
multiAssetObj: MultiAsset[MultiAssetTypeOutput]{
139+
data: map[Blake2b224]map[cbor.ByteString]MultiAssetTypeOutput{
140+
NewBlake2b224(test.DecodeHexString("29a8fb8318718bd756124f0c144f56d4b4579dc5edf2dd42d669ac61")): {
141+
cbor.NewByteString(test.DecodeHexString("6675726e697368613239686e")): 123456,
142+
},
143+
},
144+
},
145+
expectedData: data.NewMap(
146+
[][2]data.PlutusData{
147+
{
148+
data.NewByteString(test.DecodeHexString("29a8fb8318718bd756124f0c144f56d4b4579dc5edf2dd42d669ac61")),
149+
data.NewMap(
150+
[][2]data.PlutusData{
151+
{
152+
data.NewByteString(test.DecodeHexString("6675726e697368613239686e")),
153+
data.NewInteger(big.NewInt(123456)),
154+
},
155+
},
156+
),
157+
},
158+
},
159+
),
160+
},
161+
{
162+
multiAssetObj: MultiAsset[MultiAssetTypeOutput]{
163+
data: map[Blake2b224]map[cbor.ByteString]MultiAssetTypeOutput{
164+
NewBlake2b224(test.DecodeHexString("29a8fb8318718bd756124f0c144f56d4b4579dc5edf2dd42d669ac61")): {
165+
cbor.NewByteString(test.DecodeHexString("6675726e697368613239686e")): 123456,
166+
},
167+
NewBlake2b224(test.DecodeHexString("eaf8042c1d8203b1c585822f54ec32c4c1bb4d3914603e2cca20bbd5")): {
168+
cbor.NewByteString(test.DecodeHexString("426f7764757261436f6e63657074733638")): 234567,
169+
},
170+
},
171+
},
172+
expectedData: data.NewMap(
173+
[][2]data.PlutusData{
174+
{
175+
data.NewByteString(test.DecodeHexString("29a8fb8318718bd756124f0c144f56d4b4579dc5edf2dd42d669ac61")),
176+
data.NewMap(
177+
[][2]data.PlutusData{
178+
{
179+
data.NewByteString(test.DecodeHexString("6675726e697368613239686e")),
180+
data.NewInteger(big.NewInt(123456)),
181+
},
182+
},
183+
),
184+
},
185+
{
186+
data.NewByteString(test.DecodeHexString("eaf8042c1d8203b1c585822f54ec32c4c1bb4d3914603e2cca20bbd5")),
187+
data.NewMap(
188+
[][2]data.PlutusData{
189+
{
190+
data.NewByteString(test.DecodeHexString("426f7764757261436f6e63657074733638")),
191+
data.NewInteger(big.NewInt(234567)),
192+
},
193+
},
194+
),
195+
},
196+
},
197+
),
198+
},
199+
}
200+
for _, testDef := range testDefs {
201+
var tmpData data.PlutusData
202+
switch v := testDef.multiAssetObj.(type) {
203+
case MultiAsset[MultiAssetTypeOutput]:
204+
tmpData = v.ToPlutusData()
205+
case MultiAsset[MultiAssetTypeMint]:
206+
tmpData = v.ToPlutusData()
207+
default:
208+
t.Fatalf("test def multi-asset object was not expected type: %T", v)
209+
}
210+
if !reflect.DeepEqual(tmpData, testDef.expectedData) {
211+
t.Fatalf("did not get expected PlutusData\n got: %#v\n wanted: %#v", tmpData, testDef.expectedData)
212+
}
213+
}
214+
}
215+
131216
func TestMultiAssetCompare(t *testing.T) {
132217
testDefs := []struct {
133218
asset1 *MultiAsset[MultiAssetTypeOutput]

0 commit comments

Comments
 (0)