-
Notifications
You must be signed in to change notification settings - Fork 204
/
parser.go
115 lines (97 loc) · 3.42 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package types
import (
"encoding/json"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
)
type RawPacketMetadata struct {
Autopilot *struct {
Receiver string `json:"receiver"`
Stakeibc *StakeibcPacketMetadata `json:"stakeibc,omitempty"`
Claim *ClaimPacketMetadata `json:"claim,omitempty"`
} `json:"autopilot"`
}
type PacketForwardMetadata struct {
Receiver string
RoutingInfo ModuleRoutingInfo
}
type ModuleRoutingInfo interface {
Validate() error
}
// Packet metadata info specific to Stakeibc (e.g. 1-click liquid staking)
type StakeibcPacketMetadata struct {
Action string `json:"action"`
StrideAddress string
}
// Packet metadata info specific to Claim (e.g. airdrops for non-118 coins)
type ClaimPacketMetadata struct {
StrideAddress string
}
// Validate stakeibc packet metadata fields
// including the stride address and action type
func (m StakeibcPacketMetadata) Validate() error {
_, err := sdk.AccAddressFromBech32(m.StrideAddress)
if err != nil {
return err
}
if m.Action != "LiquidStake" {
return errorsmod.Wrapf(ErrUnsupportedStakeibcAction, "action %s is not supported", m.Action)
}
return nil
}
// Validate claim packet metadata includes the stride address
func (m ClaimPacketMetadata) Validate() error {
_, err := sdk.AccAddressFromBech32(m.StrideAddress)
if err != nil {
return err
}
return nil
}
// Parse packet metadata intended for autopilot
// In the ICS-20 packet, the metadata can optionally indicate a module to route to (e.g. stakeibc)
// The PacketForwardMetadata returned from this function contains attributes for each autopilot supported module
// It can only be forward to one module per packet
// Returns nil if there was no metadata found
func ParsePacketMetadata(metadata string) (*PacketForwardMetadata, error) {
// If we can't unmarshal the metadata into a PacketMetadata struct,
// assume packet forwarding was no used and pass back nil so that autopilot is ignored
var raw RawPacketMetadata
if err := json.Unmarshal([]byte(metadata), &raw); err != nil {
return nil, nil
}
// If no forwarding logic was used for autopilot, return the metadata with each disabled
if raw.Autopilot == nil {
return nil, nil
}
// Confirm a receiver address was supplied
if _, err := sdk.AccAddressFromBech32(raw.Autopilot.Receiver); err != nil {
return nil, errorsmod.Wrapf(ErrInvalidPacketMetadata, ErrInvalidReceiverAddress.Error())
}
// Parse the packet info into the specific module type
// We increment the module count to ensure only one module type was provided
moduleCount := 0
var routingInfo ModuleRoutingInfo
if raw.Autopilot.Stakeibc != nil {
// override the stride address with the receiver address
raw.Autopilot.Stakeibc.StrideAddress = raw.Autopilot.Receiver
moduleCount++
routingInfo = *raw.Autopilot.Stakeibc
}
if raw.Autopilot.Claim != nil {
// override the stride address with the receiver address
raw.Autopilot.Claim.StrideAddress = raw.Autopilot.Receiver
moduleCount++
routingInfo = *raw.Autopilot.Claim
}
if moduleCount != 1 {
return nil, errorsmod.Wrapf(ErrInvalidPacketMetadata, ErrInvalidModuleRoutes.Error())
}
// Validate the packet info according to the specific module type
if err := routingInfo.Validate(); err != nil {
return nil, errorsmod.Wrapf(err, ErrInvalidPacketMetadata.Error())
}
return &PacketForwardMetadata{
Receiver: raw.Autopilot.Receiver,
RoutingInfo: routingInfo,
}, nil
}