Search Apps Documentation Source Content File Folder Download Copy Actions Download

packet.gno

3.49 Kb · 139 lines
  1package transfer
  2
  3import (
  4	"strings"
  5
  6	"gno.land/p/aib/encoding/proto"
  7	"gno.land/p/nt/ufmt/v0"
  8	"gno.land/p/onbloc/int256"
  9)
 10
 11// FungibleTokenPacketData defines a struct for the packet payload
 12// See FungibleTokenPacketData spec:
 13// https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer#data-structures
 14type FungibleTokenPacketData struct {
 15	// the token denomination to be transferred
 16	Denom string
 17	// the token amount to be transferred
 18	Amount string
 19	// the sender address
 20	Sender string
 21	// the recipient address on the destination chain
 22	Receiver string
 23	// optional memo
 24	Memo string
 25}
 26
 27// NewFungibleTokenPacketData constructs a new FungibleTokenPacketData instance
 28func NewFungibleTokenPacketData(
 29	denom string, amount string,
 30	sender, receiver string,
 31	memo string,
 32) FungibleTokenPacketData {
 33	return FungibleTokenPacketData{
 34		Denom:    denom,
 35		Amount:   amount,
 36		Sender:   sender,
 37		Receiver: receiver,
 38		Memo:     memo,
 39	}
 40}
 41
 42// ProtoMarshal returns the protobuf encoding of f.
 43//
 44//	message FungibleTokenPacketData {
 45//		string denom = 1;
 46//		string amount = 2;
 47//		string sender = 3;
 48//		string receiver = 4;
 49//		string memo = 5;
 50//	}
 51func (f *FungibleTokenPacketData) ProtoMarshal() (buf []byte) {
 52	// Field 1: denom (length-delimited)
 53	buf = proto.AppendLengthDelimited(buf, 1, []byte(f.Denom))
 54
 55	// Field 2: amount (length-delimited)
 56	buf = proto.AppendLengthDelimited(buf, 2, []byte(f.Amount))
 57
 58	// Field 3: sender (length-delimited)
 59	buf = proto.AppendLengthDelimited(buf, 3, []byte(f.Sender))
 60
 61	// Field 4: receiver (length-delimited)
 62	buf = proto.AppendLengthDelimited(buf, 4, []byte(f.Receiver))
 63
 64	// Field 5: memo (length-delimited)
 65	buf = proto.AppendLengthDelimited(buf, 5, []byte(f.Memo))
 66
 67	return
 68}
 69
 70// ProtoUnmarshal reads the protobuf encoded bz into f.
 71//
 72//	message FungibleTokenPacketData {
 73//		string denom = 1;
 74//		string amount = 2;
 75//		string sender = 3;
 76//		string receiver = 4;
 77//		string memo = 5;
 78//	}
 79func (f *FungibleTokenPacketData) ProtoUnmarshal(bz []byte) error {
 80	var pos int
 81	for pos < len(bz) {
 82		// Read field tag (key)
 83		key, newPos, err := proto.DecodeVarint(bz, pos)
 84		if err != nil {
 85			return ufmt.Errorf("error reading field tag: %v", err)
 86		}
 87		pos = newPos
 88
 89		fieldNum := key >> 3
 90		wireType := key & 0x07
 91
 92		if wireType != 2 { // All fields are strings (wire type 2)
 93			return ufmt.Errorf("unexpected wire type %d for field %d", wireType, fieldNum)
 94		}
 95
 96		// Read string value
 97		value, newPos, err := proto.DecodeString(bz, pos)
 98		if err != nil {
 99			return ufmt.Errorf("error reading string value: %v", err)
100		}
101		pos = newPos
102
103		// Assign to appropriate field
104		switch fieldNum {
105		case 1:
106			f.Denom = value
107		case 2:
108			f.Amount = value
109		case 3:
110			f.Sender = value
111		case 4:
112			f.Receiver = value
113		case 5:
114			f.Memo = value
115		default:
116			return ufmt.Errorf("unknown field aren't authorized in FungibleTokenPacketData")
117		}
118	}
119	return nil
120}
121
122// ValidateBasic is used for validating the token transfer.
123func (f FungibleTokenPacketData) ValidateBasic() error {
124	amount, err := int256.FromDecimal(f.Amount)
125	if err != nil {
126		return ufmt.Errorf("unable to parse transfer amount %q: %v", f.Amount, err)
127	}
128	if amount.Sign() != 1 {
129		return ufmt.Errorf("amount must be strictly positive: got %s", amount)
130	}
131	if strings.TrimSpace(f.Sender) == "" {
132		return ufmt.Errorf("sender address cannot be blank")
133	}
134	if strings.TrimSpace(f.Receiver) == "" {
135		return ufmt.Errorf("receiver address cannot be blank")
136	}
137	denom := ExtractDenomFromPath(f.Denom)
138	return denom.ValidateBasic()
139}