Skip to content

Commit 8d547f9

Browse files
authored
Merge pull request #292 from blinklabs-io/feat/ledger-multi-asset
feat: better handling of Mary MultiAsset value
2 parents 8095cee + e96fff1 commit 8d547f9

File tree

8 files changed

+87
-14
lines changed

8 files changed

+87
-14
lines changed

cmd/block-fetch/main.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,19 @@ func main() {
9898
for _, output := range tx.Outputs() {
9999
fmt.Printf(" Address: %x\n", output.Address())
100100
fmt.Printf(" Amount: %d\n", output.Amount())
101-
fmt.Printf(" Assets: %#v\n", output.Assets())
101+
assets := output.Assets()
102+
if assets != nil {
103+
fmt.Printf(" Assets:\n")
104+
for _, policyId := range assets.Policies() {
105+
fmt.Printf(" Policy Id: %s\n", policyId)
106+
fmt.Printf(" Policy assets:\n")
107+
for _, assetName := range assets.Assets(policyId) {
108+
fmt.Printf(" Asset name: %s\n", assetName)
109+
fmt.Printf(" Amount: %d\n", assets.Asset(policyId, assetName))
110+
fmt.Println("")
111+
}
112+
}
113+
}
102114
fmt.Println("")
103115
}
104116
}

ledger/alonzo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func (o AlonzoTransactionOutput) Amount() uint64 {
128128
return o.OutputAmount.Amount
129129
}
130130

131-
func (o AlonzoTransactionOutput) Assets() interface{} {
131+
func (o AlonzoTransactionOutput) Assets() *MultiAsset[uint64] {
132132
return o.OutputAmount.Assets
133133
}
134134

ledger/babbage.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ func (o BabbageTransactionOutput) Amount() uint64 {
173173
return o.OutputAmount.Amount
174174
}
175175

176-
func (o BabbageTransactionOutput) Assets() interface{} {
176+
func (o BabbageTransactionOutput) Assets() *MultiAsset[uint64] {
177177
return o.OutputAmount.Assets
178178
}
179179

ledger/common.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2023 Blink Labs, LLC.
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 ledger
16+
17+
import (
18+
"github.com/blinklabs-io/gouroboros/cbor"
19+
)
20+
21+
// MultiAsset represents a collection of policies, assets, and quantities. It's used for
22+
// TX outputs (uint64) and TX asset minting (int64 to allow for negative values for burning)
23+
type MultiAsset[T int64 | uint64] struct {
24+
data map[Blake2b224]map[cbor.ByteString]T
25+
}
26+
27+
func (m *MultiAsset[T]) UnmarshalCBOR(data []byte) error {
28+
_, err := cbor.Decode(data, &(m.data))
29+
return err
30+
}
31+
32+
func (m *MultiAsset[T]) MarshalCBOR() ([]byte, error) {
33+
return cbor.Encode(&(m.data))
34+
}
35+
36+
func (m *MultiAsset[T]) Policies() []Blake2b224 {
37+
var ret []Blake2b224
38+
for policyId := range m.data {
39+
ret = append(ret, policyId)
40+
}
41+
return ret
42+
}
43+
44+
func (m *MultiAsset[T]) Assets(policyId Blake2b224) [][]byte {
45+
assets, ok := m.data[policyId]
46+
if !ok {
47+
return nil
48+
}
49+
var ret [][]byte
50+
for assetName := range assets {
51+
ret = append(ret, assetName.Bytes())
52+
}
53+
return ret
54+
}
55+
56+
func (m *MultiAsset[T]) Asset(policyId Blake2b224, assetName []byte) T {
57+
policy, ok := m.data[policyId]
58+
if !ok {
59+
return 0
60+
}
61+
return policy[cbor.ByteString(assetName)]
62+
}

ledger/mary.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ func (h *MaryBlockHeader) Era() Era {
8080
type MaryTransactionBody struct {
8181
AllegraTransactionBody
8282
TxOutputs []MaryTransactionOutput `cbor:"1,keyasint,omitempty"`
83-
// TODO: further parsing of this field
84-
Mint cbor.Value `cbor:"9,keyasint,omitempty"`
83+
Mint MultiAsset[int64] `cbor:"9,keyasint,omitempty"`
8584
}
8685

8786
func (b *MaryTransactionBody) UnmarshalCBOR(cborData []byte) error {
@@ -117,14 +116,15 @@ func (o MaryTransactionOutput) Amount() uint64 {
117116
return o.OutputAmount.Amount
118117
}
119118

120-
func (o MaryTransactionOutput) Assets() interface{} {
119+
func (o MaryTransactionOutput) Assets() *MultiAsset[uint64] {
121120
return o.OutputAmount.Assets
122121
}
123122

124123
type MaryTransactionOutputValue struct {
125124
cbor.StructAsArray
126125
Amount uint64
127-
Assets map[Blake2b224]map[cbor.ByteString]uint64
126+
// We use a pointer here to allow it to be nil
127+
Assets *MultiAsset[uint64]
128128
}
129129

130130
func (v *MaryTransactionOutputValue) UnmarshalCBOR(data []byte) error {

ledger/mary_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ import (
2323
"github.com/blinklabs-io/gouroboros/internal/test"
2424
)
2525

26-
func createMaryTransactionOutputValueAssets(policyId []byte, assetName []byte, amount uint64) map[Blake2b224]map[cbor.ByteString]uint64 {
27-
ret := map[Blake2b224]map[cbor.ByteString]uint64{}
26+
func createMaryTransactionOutputValueAssets(policyId []byte, assetName []byte, amount uint64) *MultiAsset[uint64] {
27+
data := map[Blake2b224]map[cbor.ByteString]uint64{}
2828
policyIdKey := Blake2b224{}
2929
copy(policyIdKey[:], policyId)
3030
assetKey := cbor.ByteString(assetName)
31-
ret[policyIdKey] = map[cbor.ByteString]uint64{
31+
data[policyIdKey] = map[cbor.ByteString]uint64{
3232
assetKey: amount,
3333
}
34-
return ret
34+
return &MultiAsset[uint64]{data: data}
3535
}
3636

3737
func TestMaryTransactionOutputValueEncodeDecode(t *testing.T) {

ledger/shelley.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ func (o ShelleyTransactionOutput) Amount() uint64 {
193193
return o.OutputAmount
194194
}
195195

196-
func (o ShelleyTransactionOutput) Assets() interface{} {
196+
func (o ShelleyTransactionOutput) Assets() *MultiAsset[uint64] {
197197
return nil
198198
}
199199

ledger/tx.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ type TransactionInput interface {
3636
type TransactionOutput interface {
3737
Address() []byte
3838
Amount() uint64
39-
// TODO: create more specific type/interface for assets
40-
Assets() interface{}
39+
Assets() *MultiAsset[uint64]
4140
}
4241

4342
func NewTransactionFromCbor(txType uint, data []byte) (interface{}, error) {

0 commit comments

Comments
 (0)