mirror of
https://github.com/galacticship/terra.git
synced 2024-11-09 01:37:51 +00:00
142 lines
3.1 KiB
Go
142 lines
3.1 KiB
Go
package terra
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/galacticship/terra/cosmos"
|
|
"github.com/pkg/errors"
|
|
"github.com/shopspring/decimal"
|
|
)
|
|
|
|
type RoutePair struct {
|
|
Pair Pair
|
|
IsToken1First bool
|
|
}
|
|
|
|
func NewRoutePair(pair Pair, token1first bool) RoutePair {
|
|
return RoutePair{
|
|
Pair: pair,
|
|
IsToken1First: token1first,
|
|
}
|
|
}
|
|
|
|
func (p RoutePair) FirstToken() Token {
|
|
if p.IsToken1First {
|
|
return p.Pair.Token1()
|
|
} else {
|
|
return p.Pair.Token2()
|
|
}
|
|
}
|
|
|
|
func (p RoutePair) SecondToken() Token {
|
|
if p.IsToken1First {
|
|
return p.Pair.Token2()
|
|
} else {
|
|
return p.Pair.Token1()
|
|
}
|
|
}
|
|
|
|
type Route []RoutePair
|
|
|
|
func NewRoute(pairs ...RoutePair) Route {
|
|
return Route(pairs)
|
|
}
|
|
|
|
func (r Route) Last() RoutePair {
|
|
return r[len(r)-1]
|
|
}
|
|
func (r Route) First() RoutePair {
|
|
return r[0]
|
|
}
|
|
|
|
func (r Route) Contains(pair Pair) bool {
|
|
for _, t := range r {
|
|
if t.Pair.Equals(pair) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (r Route) Copy() Route {
|
|
res := make(Route, len(r))
|
|
copy(res, r)
|
|
return res
|
|
}
|
|
|
|
func (r Route) String() string {
|
|
var res string
|
|
for _, pair := range r {
|
|
if pair.IsToken1First {
|
|
res += fmt.Sprintf("[%s-%s] ", pair.Pair.Token1().Symbol(), pair.Pair.Token2().Symbol())
|
|
} else {
|
|
res += fmt.Sprintf("[%s-%s] ", pair.Pair.Token2().Symbol(), pair.Pair.Token1().Symbol())
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (r Route) OfferToken() Token {
|
|
if r.First().IsToken1First {
|
|
return r.First().Pair.Token1()
|
|
} else {
|
|
return r.First().Pair.Token2()
|
|
}
|
|
}
|
|
|
|
func (r Route) AskToken() Token {
|
|
if r.Last().IsToken1First {
|
|
return r.Last().Pair.Token2()
|
|
} else {
|
|
return r.Last().Pair.Token1()
|
|
}
|
|
}
|
|
|
|
func (r Route) CopyAndAdd(pair RoutePair) Route {
|
|
return append(r.Copy(), pair)
|
|
}
|
|
|
|
func (r Route) SimulateSwap(offerAmount decimal.Decimal, pools map[Pair]PoolInfo) decimal.Decimal {
|
|
current := r.OfferToken().ValueToTerra(offerAmount)
|
|
for _, pair := range r {
|
|
pool := pools[pair.Pair]
|
|
ra, _, _, _ := ComputeConstantProductSwap(pair.FirstToken().ValueToTerra(pool[pair.FirstToken().Id()]), pair.SecondToken().ValueToTerra(pool[pair.SecondToken().Id()]), current, pair.Pair.CommissionRate())
|
|
current = ra
|
|
}
|
|
return r.AskToken().ValueFromTerra(current)
|
|
}
|
|
|
|
func (r Route) GenerateArbitrageMessages(sender cosmos.AccAddress, offerAmount decimal.Decimal, pools map[Pair]PoolInfo) ([]cosmos.Msg, error) {
|
|
current := r.OfferToken().ValueToTerra(offerAmount)
|
|
var msgs []cosmos.Msg
|
|
for _, pair := range r {
|
|
pool := pools[pair.Pair]
|
|
ra, _, _, bp := ComputeConstantProductSwap(pair.FirstToken().ValueToTerra(pool[pair.FirstToken().Id()]), pair.SecondToken().ValueToTerra(pool[pair.SecondToken().Id()]), current, pair.Pair.CommissionRate())
|
|
newmsg, err := pair.Pair.NewSwapMessage(sender, pair.FirstToken(), current, "0.0", bp)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "generating message for pair %s", pair.Pair)
|
|
}
|
|
msgs = append(msgs, newmsg)
|
|
current = ra
|
|
}
|
|
return msgs, nil
|
|
}
|
|
|
|
func (r Route) Pairs() []Pair {
|
|
var res []Pair
|
|
for _, pair := range r {
|
|
contains := false
|
|
for _, re := range res {
|
|
if re.Equals(pair.Pair) {
|
|
contains = true
|
|
break
|
|
}
|
|
}
|
|
if contains {
|
|
continue
|
|
}
|
|
res = append(res, pair.Pair)
|
|
}
|
|
return res
|
|
}
|