forked from Kava-Labs/kava
-
Notifications
You must be signed in to change notification settings - Fork 0
/
swap.go
169 lines (153 loc) · 5.96 KB
/
swap.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package types
import (
"encoding/hex"
"errors"
"fmt"
"strings"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// NewAtomicSwap returns a new AtomicSwap
func NewAtomicSwap(amount sdk.Coins, randomNumberHash tmbytes.HexBytes, expireHeight uint64, timestamp int64,
sender, recipient sdk.AccAddress, senderOtherChain, recipientOtherChain string, closedBlock int64,
status SwapStatus, crossChain bool, direction SwapDirection,
) AtomicSwap {
return AtomicSwap{
Amount: amount,
RandomNumberHash: randomNumberHash,
ExpireHeight: expireHeight,
Timestamp: timestamp,
Sender: sender,
Recipient: recipient,
SenderOtherChain: senderOtherChain,
RecipientOtherChain: recipientOtherChain,
ClosedBlock: closedBlock,
Status: status,
CrossChain: crossChain,
Direction: direction,
}
}
// GetSwapID calculates the ID of an atomic swap
func (a AtomicSwap) GetSwapID() tmbytes.HexBytes {
return CalculateSwapID(a.RandomNumberHash, a.Sender, a.SenderOtherChain)
}
// GetCoins returns the swap's amount as sdk.Coins
func (a AtomicSwap) GetCoins() sdk.Coins {
return sdk.NewCoins(a.Amount...)
}
// Validate performs a basic validation of an atomic swap fields.
func (a AtomicSwap) Validate() error {
if !a.Amount.IsValid() {
return fmt.Errorf("invalid amount: %s", a.Amount)
}
if !a.Amount.IsAllPositive() {
return fmt.Errorf("the swapped out coin must be positive: %s", a.Amount)
}
if len(a.RandomNumberHash) != RandomNumberHashLength {
return fmt.Errorf("the length of random number hash should be %d", RandomNumberHashLength)
}
if a.ExpireHeight == 0 {
return errors.New("expire height cannot be 0")
}
if a.Timestamp == 0 {
return errors.New("timestamp cannot be 0")
}
if a.Sender.Empty() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender cannot be empty")
}
if a.Recipient.Empty() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "recipient cannot be empty")
}
// NOTE: These adresses may not have a bech32 prefix.
if strings.TrimSpace(a.SenderOtherChain) == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender other chain cannot be blank")
}
if strings.TrimSpace(a.RecipientOtherChain) == "" {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "recipient other chain cannot be blank")
}
if a.Status == SWAP_STATUS_COMPLETED && a.ClosedBlock == 0 {
return errors.New("closed block cannot be 0")
}
if a.Status == SWAP_STATUS_UNSPECIFIED || a.Status > 3 {
return errors.New("invalid swap status")
}
if a.Direction == SWAP_DIRECTION_UNSPECIFIED || a.Direction > 2 {
return errors.New("invalid swap direction")
}
return nil
}
// AtomicSwaps is a slice of AtomicSwap
type AtomicSwaps []AtomicSwap
// NewSwapStatusFromString converts string to SwapStatus type
func NewSwapStatusFromString(str string) SwapStatus {
switch str {
case "Open", "open":
return SWAP_STATUS_OPEN
case "Completed", "completed":
return SWAP_STATUS_COMPLETED
case "Expired", "expired":
return SWAP_STATUS_EXPIRED
default:
return SWAP_STATUS_UNSPECIFIED
}
}
// IsValid returns true if the swap status is valid and false otherwise.
func (status SwapStatus) IsValid() bool {
return status == SWAP_STATUS_OPEN ||
status == SWAP_STATUS_COMPLETED ||
status == SWAP_STATUS_EXPIRED
}
// NewSwapDirectionFromString converts string to SwapDirection type
func NewSwapDirectionFromString(str string) SwapDirection {
switch str {
case "Incoming", "incoming", "inc", "I", "i":
return SWAP_DIRECTION_INCOMING
case "Outgoing", "outgoing", "out", "O", "o":
return SWAP_DIRECTION_OUTGOING
default:
return SWAP_DIRECTION_UNSPECIFIED
}
}
// IsValid returns true if the swap direction is valid and false otherwise.
func (direction SwapDirection) IsValid() bool {
return direction == SWAP_DIRECTION_INCOMING ||
direction == SWAP_DIRECTION_OUTGOING
}
// LegacyAugmentedAtomicSwap defines an ID and AtomicSwap fields on the top level.
// This should be removed when legacy REST endpoints are removed.
type LegacyAugmentedAtomicSwap struct {
ID string `json:"id" yaml:"id"`
// Embed AtomicSwap fields explicity in order to output as top level JSON fields
// This prevents breaking changes for clients using REST API
Amount sdk.Coins `json:"amount" yaml:"amount"`
RandomNumberHash tmbytes.HexBytes `json:"random_number_hash" yaml:"random_number_hash"`
ExpireHeight uint64 `json:"expire_height" yaml:"expire_height"`
Timestamp int64 `json:"timestamp" yaml:"timestamp"`
Sender sdk.AccAddress `json:"sender" yaml:"sender"`
Recipient sdk.AccAddress `json:"recipient" yaml:"recipient"`
SenderOtherChain string `json:"sender_other_chain" yaml:"sender_other_chain"`
RecipientOtherChain string `json:"recipient_other_chain" yaml:"recipient_other_chain"`
ClosedBlock int64 `json:"closed_block" yaml:"closed_block"`
Status SwapStatus `json:"status" yaml:"status"`
CrossChain bool `json:"cross_chain" yaml:"cross_chain"`
Direction SwapDirection `json:"direction" yaml:"direction"`
}
func NewLegacyAugmentedAtomicSwap(swap AtomicSwap) LegacyAugmentedAtomicSwap {
return LegacyAugmentedAtomicSwap{
ID: hex.EncodeToString(swap.GetSwapID()),
Amount: swap.Amount,
RandomNumberHash: swap.RandomNumberHash,
ExpireHeight: swap.ExpireHeight,
Timestamp: swap.Timestamp,
Sender: swap.Sender,
Recipient: swap.Recipient,
SenderOtherChain: swap.SenderOtherChain,
RecipientOtherChain: swap.RecipientOtherChain,
ClosedBlock: swap.ClosedBlock,
Status: swap.Status,
CrossChain: swap.CrossChain,
Direction: swap.Direction,
}
}
type LegacyAugmentedAtomicSwaps []LegacyAugmentedAtomicSwap