Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Basic Fraction Entity Added #2

Merged
merged 5 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package router
package core

type AlphaRouterParams struct {
}
64 changes: 64 additions & 0 deletions core/alpha-router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package core

import (
"router/core/entities"
"router/core/entities/fractions"
)

type AlphaRouter struct {
portionProvider IPortionProvider
}

func NewAlphaRouter(params AlphaRouterParams) *AlphaRouter {
return &AlphaRouter{}
}

// TODO: 원본 코드에서는 async 함수
// 라우트 한 결과는 SwapRoute
func (a AlphaRouter) route(
amount fractions.CurrencyAmount,
quoteCurrency entities.Currency,
tradeType TradeType,
swapConfig SwapOptions,
) SwapRoute {
//originalAmount := amount
//
//currencyIn, currencyOut := a.determineCurrencyInOutFromTradeType(tradeType, amount, quoteCurrency)
//
//// currencyIn, currencyOut은 Currency 타입이고
//// Currency 타입은 NativeCurrency(GNOT)이거나 Token 타입이다.
//// 아래에서 Token 타입이길 원하는 듯하다.
//tokenIn := currencyIn.Wrapped()
//tokenOut := currencyOut.Wrapped()
//
//// core 패키지를 TradeType 패키지로 변경하면 가독성이 더 좋아질 듯 하다.
//if tradeType == EXACT_OUTPUT {
// // TODO: GetPortionAmount에서 반환 값인 CurrencyAmount을 반환하지 못할 경우가 있을 수도 있다.(높은 확률로)
// portionAmount := a.portionProvider.GetPortionAmount(
// amount,
// tradeType,
// swapConfig,
// )
//
// //result := portionAmount.GreaterThan(0)
// //if result {
// // amount = amount.add(portionAmount)
// //}
//}
//
//swapRoute := SwapRoute{}
//return swapRoute
return SwapRoute{}
}

func (a AlphaRouter) determineCurrencyInOutFromTradeType(
tradeType TradeType,
amount fractions.CurrencyAmount,
quoteCurrency entities.Currency,
) (entities.Currency, entities.Currency) {
if tradeType == EXACT_INPUT {
return amount.Currency, quoteCurrency
} else {
return quoteCurrency, amount.Currency
}
}
File renamed without changes.
29 changes: 29 additions & 0 deletions core/entities/baseCurrency.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package entities

type BaseCurrency struct {
isNative bool
isToken bool

chainId int
decimals int

symbol string
name string
address string
}

func NewBaseCurrency(chainId int, decimals int, symbol string, name string) *BaseCurrency {
return &BaseCurrency{
// 아래 코드는 원문
//invariant(Number.isSafeInteger(chainId), 'CHAIN_ID');
//invariant(
// decimals >= 0 && decimals < 255 && Number.isInteger(decimals),
// 'DECIMALS',
//);

chainId: chainId,
decimals: decimals,
symbol: symbol,
name: name,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ package entities
// Token과 NativeCurrency 모두 BaseCurrency를 상속받는다.
// 하지만 여기서의 Currency는 NativeCurrency와 Token에 포함된다.
type Currency interface {
wrapped() Token
Wrapped() Token
}
16 changes: 16 additions & 0 deletions core/entities/fractions/currencyAmount.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package fractions

import (
"router/core/entities"
)

type CurrencyAmount struct {
Fraction
Currency entities.Currency
}

//func (c CurrencyAmount) add(other CurrencyAmount) CurrencyAmount {
// added := c.Fraction.add(other)
//
// return CurrencyAmount.fromFractionAmount()
//}
119 changes: 119 additions & 0 deletions core/entities/fractions/fraction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package fractions

import (
"errors"
"math/big"
)

type Fraction struct {
Numerator *big.Int
Denominator *big.Int
}

func NewFraction(numerator int64, denominator int64) *Fraction {
return &Fraction{
Numerator: big.NewInt(numerator),
Denominator: big.NewInt(denominator),
}
}

func tryParseFraction(value interface{}) (Fraction, error) {
switch v := value.(type) {
case Fraction:
return v, nil
case *big.Int:
return Fraction{Numerator: v, Denominator: big.NewInt(1)}, nil
case big.Int:
return Fraction{Numerator: &v, Denominator: big.NewInt(1)}, nil
// TODO: int64 등 추가 바람
default:
return Fraction{}, errors.New("not a fraction")
}
}

// ---------------------------
// TODO: 형을 자유롭게 받은 다음 tryParseFraction으로 한 번 거르고 사용하도록 하기
// 덧셈
func (f Fraction) Add(other *Fraction) *Fraction {
numerator1 := new(big.Int).Mul(f.Numerator, other.Denominator)
numerator2 := new(big.Int).Mul(other.Numerator, f.Denominator)
denominator := new(big.Int).Mul(f.Denominator, other.Denominator)
resultNumerator := new(big.Int).Add(numerator1, numerator2)

// TODO: 약분
//g := utils.Gcd(resultNumerator, denominator)

return &Fraction{
Numerator: resultNumerator,
Denominator: denominator,
}
}

// 뺄셈
// TODO: 덧셈 활용해서 코드 단순화 할 수도 있을지도...
func (f Fraction) Sub(other *Fraction) *Fraction {
numerator1 := new(big.Int).Mul(f.Numerator, other.Denominator)
numerator2 := new(big.Int).Mul(other.Numerator, f.Denominator)
denominator := new(big.Int).Mul(f.Denominator, other.Denominator)
resultNumerator := new(big.Int).Sub(numerator1, numerator2)

// TODO: 약분
//g := utils.Gcd(resultNumerator, denominator)

return &Fraction{
Numerator: resultNumerator,
Denominator: denominator,
}
}

func (f Fraction) LessThan(other *Fraction) bool {
leftValue := new(big.Int).Mul(f.Numerator, other.Denominator)
rightValue := new(big.Int).Mul(other.Numerator, f.Denominator)
return leftValue.Cmp(rightValue) < 0
}

func (f Fraction) GreaterThan(other *Fraction) bool {
leftValue := new(big.Int).Mul(f.Numerator, other.Denominator)
rightValue := new(big.Int).Mul(other.Numerator, f.Denominator)
return leftValue.Cmp(rightValue) > 0
}

// 약분이 완료되었다는 가정
// WARN: 약분이 안되었다는 가정이라면 약분하는 로직 추가해야 함
func (f Fraction) Equals(other *Fraction) bool {
return f.Numerator.Cmp(other.Numerator) == 0 &&
f.Denominator.Cmp(other.Denominator) == 0
}

// 몫
func (f Fraction) Quotient() *big.Int {
return new(big.Int).Quo(f.Numerator, f.Denominator)
}

// NOTE: 단순 나머지가 아니라 분수 형태로 표시한다
// 좋은 형태의 함수는 아니라 생각
func (f Fraction) Remainder() Fraction {
return Fraction{
Numerator: new(big.Int).Rem(f.Numerator, f.Denominator),
Denominator: f.Denominator,
}
}

// 역
func (f Fraction) Invert() Fraction {
return Fraction{
Numerator: f.Denominator,
Denominator: f.Numerator,
}
}

//func (f Fraction) GreaterThan(other interface{}) (bool, error) {
// otherParsed, err := tryParseFraction(other)
// if err != nil {
// return false, err
// }
//left := f.Numerator * otherParsed.Denominator
//right := otherParsed.Denominator * f.Numerator
//
// return left > right, nil
//}
39 changes: 39 additions & 0 deletions core/entities/fractions/fraction_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package fractions

import (
"testing"
)

func TestFraction_Add(t *testing.T) {
fraction1 := NewFraction(1, 2)
fraction2 := NewFraction(1, 3)

result := fraction1.Add(fraction2)

expected := NewFraction(5, 6)

if result.Numerator.Cmp(expected.Numerator) != 0 || result.Denominator.Cmp(expected.Denominator) != 0 {
t.Fatalf("Add: expected %v, got %v", expected, result)
}
}

func TestFraction_Sub(t *testing.T) {
fraction1 := NewFraction(1, 2)
fraction2 := NewFraction(1, 3)
result := fraction1.Sub(fraction2)
expected := NewFraction(1, 6)
if result.Numerator.Cmp(expected.Numerator) != 0 || result.Denominator.Cmp(expected.Denominator) != 0 {
t.Fatalf("Sub: expected %v, got %v", expected, result)
}
}

func TestFraction_LessThan(t *testing.T) {
fraction1 := NewFraction(1, 2)
fraction2 := NewFraction(1, 3)
result := fraction1.LessThan(fraction2)
expected := false

if result != expected {
t.Fatalf("LessThan: expected %v, got %v", expected, result)
}
}
21 changes: 21 additions & 0 deletions core/entities/gnot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package entities

type Gnot struct {
NativeCurrency
}

func NewGnot(chainId int) *Gnot {
return &Gnot{
NativeCurrency: NativeCurrency{
BaseCurrency: BaseCurrency{
chainId: chainId,
},
},
}
}

func (g Gnot) Wrapped() Token {
wgnot := WGNOT[g.chainId]
// invariant(!!wgnot, 'WRAPPED')
return wgnot
}
6 changes: 6 additions & 0 deletions core/entities/nativeCurrency.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package entities

// Gnot이 NativeCurrency를 상속한다.
type NativeCurrency struct {
BaseCurrency
}
13 changes: 13 additions & 0 deletions core/entities/token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package entities

type Token struct {
BaseCurrency
}

func NewToken() *Token {
return &Token{}
}

func (t Token) Wrapped() Token {
return t
}
8 changes: 8 additions & 0 deletions core/entities/utils/math.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package utils

import "math/big"

func Gcd(a, b *big.Int) *big.Int {

return a
}
10 changes: 10 additions & 0 deletions core/entities/wgnot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package entities

var WGNOT = map[int]Token{
//1: NewToken(),
//2: NewToken(),
//3: NewToken(),
//4: NewToken(),
//5: NewToken(),
//99: NewToken(),
}
14 changes: 14 additions & 0 deletions core/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package core

type SwapRoute struct {
}

type IRouter interface {
}

// TODO: 원문: type SwapOptions = SwapOptionsUniversalRouter | SwapOptionsSwapRouter02
type SwapOptions struct {
}

type SwapOptionsUniversalRouter struct {
}
13 changes: 13 additions & 0 deletions core/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package core

import (
"router/core/entities/fractions"
)

// interface는 I 접두사를 붙이는 것이 관행인가?
type IPortionProvider interface {
GetPortionAmount(tokenOutAmount fractions.CurrencyAmount, tradeType TradeType, swapConfig SwapOptions) fractions.CurrencyAmount
}

type PortionProvider struct {
}
11 changes: 0 additions & 11 deletions main.go

This file was deleted.

Loading
Loading