mirror of
https://github.com/luxfi/utxo.git
synced 2026-10-30 15:13:57 +00:00
Completes the fx wire for the two application fx families so xvm can go struct-is-wire (LP-023): TypeKindNFT=0x08, TypeKindProperty=0x09; shapes NFTMintOutput=0x10, NFTTransferOutput=0x11, NFTMintOperation=0x13, NFTTransferOp=0x14, OwnedOutput=0x15, BurnOperation=0x16 (appended; bare- owners property MintOutput + credentials reuse the shared shapes). fx-side Bytes()/Wrap* per type in nftfx/wire.go + propertyfx/wire.go following the secp256k1fx/wire.go template. NEW wire.NextEnvelope: the ONE packed-envelope walker (SignedTx creds / XVMBaseTx outs-ins / nft mint owners all use the same split rule). Round-trip + cross-shape-confusion tests green. Co-authored-by: Hanzo Dev <[email protected]>
88 lines
2.8 KiB
Go
88 lines
2.8 KiB
Go
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package nftfx
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/utxo/secp256k1fx"
|
|
"github.com/luxfi/utxo/wire"
|
|
)
|
|
|
|
func TestWireRoundTrips(t *testing.T) {
|
|
require := require.New(t)
|
|
addr := ids.ShortID{0x01, 0x02, 0x03}
|
|
|
|
mintOut := &MintOutput{
|
|
GroupID: 7,
|
|
OutputOwners: secp256k1fx.OutputOwners{
|
|
Locktime: 99,
|
|
Threshold: 1,
|
|
Addrs: []ids.ShortID{addr},
|
|
},
|
|
}
|
|
gotMintOut, err := WrapMintOutput(mintOut.Bytes())
|
|
require.NoError(err)
|
|
require.Equal(mintOut.GroupID, gotMintOut.GroupID)
|
|
require.Equal(mintOut.OutputOwners.Locktime, gotMintOut.OutputOwners.Locktime)
|
|
require.Equal(mintOut.OutputOwners.Threshold, gotMintOut.OutputOwners.Threshold)
|
|
require.Equal(mintOut.OutputOwners.Addrs, gotMintOut.OutputOwners.Addrs)
|
|
|
|
xferOut := &TransferOutput{
|
|
GroupID: 3,
|
|
Payload: []byte("nft payload"),
|
|
OutputOwners: secp256k1fx.OutputOwners{
|
|
Locktime: 5,
|
|
Threshold: 2,
|
|
Addrs: []ids.ShortID{addr, {0xaa}},
|
|
},
|
|
}
|
|
gotXferOut, err := WrapTransferOutput(xferOut.Bytes())
|
|
require.NoError(err)
|
|
require.Equal(xferOut.GroupID, gotXferOut.GroupID)
|
|
require.Equal([]byte(xferOut.Payload), []byte(gotXferOut.Payload))
|
|
require.Equal(xferOut.OutputOwners.Addrs, gotXferOut.OutputOwners.Addrs)
|
|
|
|
mintOp := &MintOperation{
|
|
MintInput: secp256k1fx.Input{SigIndices: []uint32{0, 2}},
|
|
GroupID: 9,
|
|
Payload: []byte("mint me"),
|
|
Outputs: []*secp256k1fx.OutputOwners{
|
|
{Locktime: 1, Threshold: 1, Addrs: []ids.ShortID{addr}},
|
|
{Locktime: 2, Threshold: 1, Addrs: []ids.ShortID{{0xbb}}},
|
|
},
|
|
}
|
|
gotMintOp, err := WrapMintOperation(mintOp.Bytes())
|
|
require.NoError(err)
|
|
require.Equal(mintOp.MintInput.SigIndices, gotMintOp.MintInput.SigIndices)
|
|
require.Equal(mintOp.GroupID, gotMintOp.GroupID)
|
|
require.Equal([]byte(mintOp.Payload), []byte(gotMintOp.Payload))
|
|
require.Len(gotMintOp.Outputs, 2)
|
|
require.Equal(mintOp.Outputs[0].Addrs, gotMintOp.Outputs[0].Addrs)
|
|
require.Equal(mintOp.Outputs[1].Locktime, gotMintOp.Outputs[1].Locktime)
|
|
|
|
xferOp := &TransferOperation{
|
|
Input: secp256k1fx.Input{SigIndices: []uint32{1}},
|
|
Output: *xferOut,
|
|
}
|
|
gotXferOp, err := WrapTransferOperation(xferOp.Bytes())
|
|
require.NoError(err)
|
|
require.Equal(xferOp.Input.SigIndices, gotXferOp.Input.SigIndices)
|
|
require.Equal(xferOp.Output.GroupID, gotXferOp.Output.GroupID)
|
|
require.Equal([]byte(xferOp.Output.Payload), []byte(gotXferOp.Output.Payload))
|
|
|
|
cred := &Credential{}
|
|
cred.Sigs = [][65]byte{{0x11}, {0x22}}
|
|
gotCred, err := WrapCredential(cred.Bytes())
|
|
require.NoError(err)
|
|
require.Equal(cred.Sigs, gotCred.Sigs)
|
|
|
|
// cross-fx confusion: an nft envelope must not wrap as secp mint output.
|
|
_, err = secp256k1fx.WrapMintOutput(mintOut.Bytes())
|
|
require.ErrorIs(err, wire.ErrWrongShapeKind)
|
|
}
|