Skip to content

Commit fd7bb27

Browse files
committed
feat: helper function to convert TransactionOutput(s) to PlutusData
Fixes #1100 Signed-off-by: Aurora Gaffney <[email protected]>
1 parent 1e678d1 commit fd7bb27

File tree

8 files changed

+429
-0
lines changed

8 files changed

+429
-0
lines changed

ledger/alonzo/alonzo.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ package alonzo
1717
import (
1818
"encoding/json"
1919
"fmt"
20+
"math/big"
2021

2122
"github.com/blinklabs-io/gouroboros/cbor"
2223
"github.com/blinklabs-io/gouroboros/ledger/common"
2324
"github.com/blinklabs-io/gouroboros/ledger/mary"
2425
"github.com/blinklabs-io/gouroboros/ledger/shelley"
26+
"github.com/blinklabs-io/plutigo/pkg/data"
2527
utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano"
2628
)
2729

@@ -332,6 +334,49 @@ func (o AlonzoTransactionOutput) MarshalJSON() ([]byte, error) {
332334
return json.Marshal(&tmpObj)
333335
}
334336

337+
func (o AlonzoTransactionOutput) ToPlutusData() data.PlutusData {
338+
var valueData [][2]data.PlutusData
339+
if o.OutputAmount.Amount > 0 {
340+
valueData = append(
341+
valueData,
342+
[2]data.PlutusData{
343+
data.NewByteString(nil),
344+
data.NewMap(
345+
[][2]data.PlutusData{
346+
{
347+
data.NewByteString(nil),
348+
data.NewInteger(big.NewInt(int64(o.OutputAmount.Amount))),
349+
},
350+
},
351+
),
352+
},
353+
)
354+
}
355+
if o.OutputAmount.Assets != nil {
356+
assetData := o.OutputAmount.Assets.ToPlutusData()
357+
assetDataMap, ok := assetData.(*data.Map)
358+
if !ok {
359+
return nil
360+
}
361+
valueData = append(
362+
valueData,
363+
assetDataMap.Pairs...,
364+
)
365+
}
366+
tmpData := data.NewConstr(
367+
0,
368+
o.OutputAddress.ToPlutusData(),
369+
data.NewMap(valueData),
370+
// Empty datum option
371+
// TODO: implement this
372+
data.NewConstr(0),
373+
// Empty script ref
374+
// TODO: implement this
375+
data.NewConstr(1),
376+
)
377+
return tmpData
378+
}
379+
335380
func (o AlonzoTransactionOutput) Address() common.Address {
336381
return o.OutputAddress
337382
}

ledger/alonzo/alonzo_test.go

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright 2025 Blink Labs Software
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package alonzo
16+
17+
import (
18+
"math/big"
19+
"reflect"
20+
"testing"
21+
22+
"github.com/blinklabs-io/gouroboros/cbor"
23+
"github.com/blinklabs-io/gouroboros/internal/test"
24+
"github.com/blinklabs-io/gouroboros/ledger/common"
25+
"github.com/blinklabs-io/gouroboros/ledger/mary"
26+
"github.com/blinklabs-io/plutigo/pkg/data"
27+
)
28+
29+
func TestAlonzoTransactionOutputToPlutusDataCoinOnly(t *testing.T) {
30+
testAddr := "addr_test1vqg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygxrcya6"
31+
var testAmount uint64 = 123_456_789
32+
testTxOut := AlonzoTransactionOutput{
33+
OutputAddress: func() common.Address { foo, _ := common.NewAddress(testAddr); return foo }(),
34+
OutputAmount: mary.MaryTransactionOutputValue{
35+
Amount: testAmount,
36+
},
37+
}
38+
expectedData := data.NewConstr(
39+
0,
40+
// Address
41+
data.NewConstr(
42+
0,
43+
data.NewConstr(
44+
0,
45+
data.NewConstr(
46+
0,
47+
data.NewByteString(
48+
[]byte{
49+
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
50+
},
51+
),
52+
),
53+
),
54+
data.NewConstr(
55+
1,
56+
),
57+
),
58+
// Value
59+
data.NewMap(
60+
[][2]data.PlutusData{
61+
{
62+
data.NewByteString(nil),
63+
data.NewMap(
64+
[][2]data.PlutusData{
65+
{
66+
data.NewByteString(nil),
67+
data.NewInteger(big.NewInt(int64(testAmount))),
68+
},
69+
},
70+
),
71+
},
72+
},
73+
),
74+
// TODO: empty datum option
75+
data.NewConstr(0),
76+
// TODO: empty script ref
77+
data.NewConstr(1),
78+
)
79+
tmpData := testTxOut.ToPlutusData()
80+
if !reflect.DeepEqual(tmpData, expectedData) {
81+
t.Fatalf("did not get expected PlutusData\n got: %#v\n wanted: %#v", tmpData, expectedData)
82+
}
83+
}
84+
85+
func TestAlonzoTransactionOutputToPlutusDataCoinAssets(t *testing.T) {
86+
testAddr := "addr_test1vqg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygxrcya6"
87+
var testAmount uint64 = 123_456_789
88+
testAssets := common.NewMultiAsset[common.MultiAssetTypeOutput](
89+
map[common.Blake2b224]map[cbor.ByteString]common.MultiAssetTypeOutput{
90+
common.NewBlake2b224(test.DecodeHexString("29a8fb8318718bd756124f0c144f56d4b4579dc5edf2dd42d669ac61")): {
91+
cbor.NewByteString(test.DecodeHexString("6675726e697368613239686e")): 123456,
92+
},
93+
common.NewBlake2b224(test.DecodeHexString("eaf8042c1d8203b1c585822f54ec32c4c1bb4d3914603e2cca20bbd5")): {
94+
cbor.NewByteString(test.DecodeHexString("426f7764757261436f6e63657074733638")): 234567,
95+
},
96+
},
97+
)
98+
testTxOut := AlonzoTransactionOutput{
99+
OutputAddress: func() common.Address { foo, _ := common.NewAddress(testAddr); return foo }(),
100+
OutputAmount: mary.MaryTransactionOutputValue{
101+
Amount: testAmount,
102+
Assets: &testAssets,
103+
},
104+
}
105+
expectedData := data.NewConstr(
106+
0,
107+
// Address
108+
data.NewConstr(
109+
0,
110+
data.NewConstr(
111+
0,
112+
data.NewConstr(
113+
0,
114+
data.NewByteString(
115+
[]byte{
116+
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
117+
},
118+
),
119+
),
120+
),
121+
data.NewConstr(
122+
1,
123+
),
124+
),
125+
// Value
126+
data.NewMap(
127+
[][2]data.PlutusData{
128+
{
129+
data.NewByteString(nil),
130+
data.NewMap(
131+
[][2]data.PlutusData{
132+
{
133+
data.NewByteString(nil),
134+
data.NewInteger(big.NewInt(int64(testAmount))),
135+
},
136+
},
137+
),
138+
},
139+
{
140+
data.NewByteString(test.DecodeHexString("29a8fb8318718bd756124f0c144f56d4b4579dc5edf2dd42d669ac61")),
141+
data.NewMap(
142+
[][2]data.PlutusData{
143+
{
144+
data.NewByteString(test.DecodeHexString("6675726e697368613239686e")),
145+
data.NewInteger(big.NewInt(123456)),
146+
},
147+
},
148+
),
149+
},
150+
{
151+
data.NewByteString(test.DecodeHexString("eaf8042c1d8203b1c585822f54ec32c4c1bb4d3914603e2cca20bbd5")),
152+
data.NewMap(
153+
[][2]data.PlutusData{
154+
{
155+
data.NewByteString(test.DecodeHexString("426f7764757261436f6e63657074733638")),
156+
data.NewInteger(big.NewInt(234567)),
157+
},
158+
},
159+
),
160+
},
161+
},
162+
),
163+
// Empty datum option
164+
data.NewConstr(0),
165+
// Empty script ref
166+
data.NewConstr(1),
167+
)
168+
tmpData := testTxOut.ToPlutusData()
169+
if !reflect.DeepEqual(tmpData, expectedData) {
170+
t.Fatalf("did not get expected PlutusData\n got: %#v\n wanted: %#v", tmpData, expectedData)
171+
}
172+
}

ledger/babbage/babbage.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ import (
1818
"encoding/json"
1919
"errors"
2020
"fmt"
21+
"math/big"
2122

2223
"github.com/blinklabs-io/gouroboros/cbor"
2324
"github.com/blinklabs-io/gouroboros/ledger/alonzo"
2425
"github.com/blinklabs-io/gouroboros/ledger/common"
2526
"github.com/blinklabs-io/gouroboros/ledger/mary"
2627
"github.com/blinklabs-io/gouroboros/ledger/shelley"
28+
"github.com/blinklabs-io/plutigo/pkg/data"
2729
utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano"
2830
)
2931

@@ -487,6 +489,49 @@ func (o BabbageTransactionOutput) MarshalJSON() ([]byte, error) {
487489
return json.Marshal(&tmpObj)
488490
}
489491

492+
func (o BabbageTransactionOutput) ToPlutusData() data.PlutusData {
493+
var valueData [][2]data.PlutusData
494+
if o.OutputAmount.Amount > 0 {
495+
valueData = append(
496+
valueData,
497+
[2]data.PlutusData{
498+
data.NewByteString(nil),
499+
data.NewMap(
500+
[][2]data.PlutusData{
501+
{
502+
data.NewByteString(nil),
503+
data.NewInteger(big.NewInt(int64(o.OutputAmount.Amount))),
504+
},
505+
},
506+
),
507+
},
508+
)
509+
}
510+
if o.OutputAmount.Assets != nil {
511+
assetData := o.OutputAmount.Assets.ToPlutusData()
512+
assetDataMap, ok := assetData.(*data.Map)
513+
if !ok {
514+
return nil
515+
}
516+
valueData = append(
517+
valueData,
518+
assetDataMap.Pairs...,
519+
)
520+
}
521+
tmpData := data.NewConstr(
522+
0,
523+
o.OutputAddress.ToPlutusData(),
524+
data.NewMap(valueData),
525+
// Empty datum option
526+
// TODO: implement this
527+
data.NewConstr(0),
528+
// Empty script ref
529+
// TODO: implement this
530+
data.NewConstr(1),
531+
)
532+
return tmpData
533+
}
534+
490535
func (o BabbageTransactionOutput) Address() common.Address {
491536
return o.OutputAddress
492537
}

0 commit comments

Comments
 (0)