From 4cd1f5aaa115e83edb660d7c8da7edda81533cdd Mon Sep 17 00:00:00 2001 From: tolelom Date: Wed, 28 Aug 2024 15:56:03 +0900 Subject: [PATCH 1/2] refactor: change function params --- core/alpha-router.go | 8 +- core/currency/base_currency.go | 36 ++++ core/currency/currency.go | 6 + core/currency/native_currency.go | 5 + core/currency/token.go | 5 + core/entities/baseCurrency.go | 29 ---- core/entities/currency.go | 8 - core/entities/fractions/currencyAmount.go | 10 ++ core/entities/gnot.go | 6 +- core/entities/nativeCurrency.go | 6 - core/entities/token.go | 13 -- core/entities/wgnot.go | 4 +- core/math/fraction.go | 151 +++++++++++++++++ core/math/fraction_test.go | 195 ++++++++++++++++++++++ core/math/math.go | 15 ++ core/math/math_test.go | 32 ++++ 16 files changed, 466 insertions(+), 63 deletions(-) create mode 100644 core/currency/base_currency.go create mode 100644 core/currency/currency.go create mode 100644 core/currency/native_currency.go create mode 100644 core/currency/token.go delete mode 100644 core/entities/baseCurrency.go delete mode 100644 core/entities/currency.go delete mode 100644 core/entities/nativeCurrency.go delete mode 100644 core/entities/token.go create mode 100644 core/math/fraction.go create mode 100644 core/math/fraction_test.go create mode 100644 core/math/math.go create mode 100644 core/math/math_test.go diff --git a/core/alpha-router.go b/core/alpha-router.go index 89b25ec..51c2368 100644 --- a/core/alpha-router.go +++ b/core/alpha-router.go @@ -1,7 +1,7 @@ package core import ( - "router/core/entities" + "router/core/currency" "router/core/entities/fractions" ) @@ -17,7 +17,7 @@ func NewAlphaRouter(params AlphaRouterParams) *AlphaRouter { // 라우트 한 결과는 SwapRoute func (a AlphaRouter) route( amount fractions.CurrencyAmount, - quoteCurrency entities.Currency, + quoteCurrency currency.Currency, tradeType TradeType, swapConfig SwapOptions, ) SwapRoute { @@ -54,8 +54,8 @@ func (a AlphaRouter) route( func (a AlphaRouter) determineCurrencyInOutFromTradeType( tradeType TradeType, amount fractions.CurrencyAmount, - quoteCurrency entities.Currency, -) (entities.Currency, entities.Currency) { + quoteCurrency currency.Currency, +) (currency.Currency, currency.Currency) { if tradeType == EXACT_INPUT { return amount.Currency, quoteCurrency } else { diff --git a/core/currency/base_currency.go b/core/currency/base_currency.go new file mode 100644 index 0000000..31df962 --- /dev/null +++ b/core/currency/base_currency.go @@ -0,0 +1,36 @@ +package currency + +type BaseCurrency struct { + // The chain ID on which this currency resides + chainId int + // The decimals used in representing currency amounts + decimals int + + // 이 아래 필드는 옵션 + // The symbol of the currency, i.e. a short textual non-unique identifier + symbol string + // The name of the currency, i.e. a descriptive textual non-unique identifier + name string + address string +} + +func NewBaseCurrency(chainId int, decimals int, symbol string, name string) *BaseCurrency { + // 아래 코드는 원문 + //invariant(Number.isSafeInteger(chainId), 'CHAIN_ID'); + //invariant( + // decimals >= 0 && decimals < 255 && Number.isInteger(decimals), + // 'DECIMALS', + //); + + // 이 제약이 걸린 이유는 아직 알지 못한다. + if decimals < 0 || 255 < decimals { + panic("decimals must be between 0 and 255") + } + + return &BaseCurrency{ + chainId: chainId, + decimals: decimals, + symbol: symbol, + name: name, + } +} diff --git a/core/currency/currency.go b/core/currency/currency.go new file mode 100644 index 0000000..2079b96 --- /dev/null +++ b/core/currency/currency.go @@ -0,0 +1,6 @@ +package currency + +// Currency는 Token | NativeCurrency +type Currency interface { + Wrapped() Token +} diff --git a/core/currency/native_currency.go b/core/currency/native_currency.go new file mode 100644 index 0000000..746310b --- /dev/null +++ b/core/currency/native_currency.go @@ -0,0 +1,5 @@ +package currency + +type NativeCurrency struct { + BaseCurrency +} diff --git a/core/currency/token.go b/core/currency/token.go new file mode 100644 index 0000000..bee6c6f --- /dev/null +++ b/core/currency/token.go @@ -0,0 +1,5 @@ +package currency + +type Token struct { + BaseCurrency +} diff --git a/core/entities/baseCurrency.go b/core/entities/baseCurrency.go deleted file mode 100644 index ba333a4..0000000 --- a/core/entities/baseCurrency.go +++ /dev/null @@ -1,29 +0,0 @@ -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, - } -} diff --git a/core/entities/currency.go b/core/entities/currency.go deleted file mode 100644 index bebeb9a..0000000 --- a/core/entities/currency.go +++ /dev/null @@ -1,8 +0,0 @@ -package entities - -// 원문에서는 Currency는 Token | NativeCurrency 이고 -// Token과 NativeCurrency 모두 BaseCurrency를 상속받는다. -// 하지만 여기서의 Currency는 NativeCurrency와 Token에 포함된다. -type Currency interface { - Wrapped() Token -} diff --git a/core/entities/fractions/currencyAmount.go b/core/entities/fractions/currencyAmount.go index 4fe107a..6c6f38e 100644 --- a/core/entities/fractions/currencyAmount.go +++ b/core/entities/fractions/currencyAmount.go @@ -1,12 +1,22 @@ package fractions import ( +<<<<<<< Updated upstream:core/entities/fractions/currencyAmount.go "router/core/entities" ) type CurrencyAmount struct { Fraction Currency entities.Currency +======= + "router/core/currency" + "router/core/math" +) + +type CurrencyAmount struct { + math.Fraction + Currency currency.Currency +>>>>>>> Stashed changes:core/entities/fractions/currency_amount.go } //func (c CurrencyAmount) add(other CurrencyAmount) CurrencyAmount { diff --git a/core/entities/gnot.go b/core/entities/gnot.go index 2db7dbb..c96b287 100644 --- a/core/entities/gnot.go +++ b/core/entities/gnot.go @@ -1,5 +1,7 @@ package entities +import "router/core/currency" + type Gnot struct { NativeCurrency } @@ -7,14 +9,14 @@ type Gnot struct { func NewGnot(chainId int) *Gnot { return &Gnot{ NativeCurrency: NativeCurrency{ - BaseCurrency: BaseCurrency{ + currency.BaseCurrency: currency.BaseCurrency{ chainId: chainId, }, }, } } -func (g Gnot) Wrapped() Token { +func (g Gnot) Wrapped() currency.Token { wgnot := WGNOT[g.chainId] // invariant(!!wgnot, 'WRAPPED') return wgnot diff --git a/core/entities/nativeCurrency.go b/core/entities/nativeCurrency.go deleted file mode 100644 index aa2862d..0000000 --- a/core/entities/nativeCurrency.go +++ /dev/null @@ -1,6 +0,0 @@ -package entities - -// Gnot이 NativeCurrency를 상속한다. -type NativeCurrency struct { - BaseCurrency -} diff --git a/core/entities/token.go b/core/entities/token.go deleted file mode 100644 index af61500..0000000 --- a/core/entities/token.go +++ /dev/null @@ -1,13 +0,0 @@ -package entities - -type Token struct { - BaseCurrency -} - -func NewToken() *Token { - return &Token{} -} - -func (t Token) Wrapped() Token { - return t -} diff --git a/core/entities/wgnot.go b/core/entities/wgnot.go index 2740d5c..6e88818 100644 --- a/core/entities/wgnot.go +++ b/core/entities/wgnot.go @@ -1,6 +1,8 @@ package entities -var WGNOT = map[int]Token{ +import "router/core/currency" + +var WGNOT = map[int]currency.Token{ //1: NewToken(), //2: NewToken(), //3: NewToken(), diff --git a/core/math/fraction.go b/core/math/fraction.go new file mode 100644 index 0000000..44b8f5d --- /dev/null +++ b/core/math/fraction.go @@ -0,0 +1,151 @@ +package math + +import ( + "errors" + "math/big" +) + +type Fraction struct { + Numerator *big.Int + Denominator *big.Int +} + +func NewFraction(numerator int64, denominator int64) *Fraction { + if denominator == 0 { + panic(errors.New("denominator cannot be zero")) + } + + // 분모는 양수만 + if denominator < 0 { + numerator = -numerator + denominator = -denominator + } + + fraction := &Fraction{ + Numerator: big.NewInt(numerator), + Denominator: big.NewInt(denominator), + } + + g := GCD(fraction.Numerator, fraction.Denominator) + fraction.Numerator = fraction.Numerator.Div(fraction.Numerator, g) + fraction.Denominator = fraction.Denominator.Div(fraction.Denominator, g) + + return fraction +} + +func (f *Fraction) Add(o *Fraction) *Fraction { + numerator1 := new(big.Int).Mul(f.Numerator, o.Denominator) + numerator2 := new(big.Int).Mul(o.Numerator, f.Denominator) + denominator := new(big.Int).Mul(f.Denominator, o.Denominator) + resultNumerator := new(big.Int).Add(numerator1, numerator2) + + g := GCD(resultNumerator, denominator) + + return &Fraction{ + Numerator: new(big.Int).Div(resultNumerator, g), + Denominator: new(big.Int).Div(denominator, g), + } +} + +func (f *Fraction) Sub(o *Fraction) *Fraction { + numerator1 := new(big.Int).Mul(f.Numerator, o.Denominator) + numerator2 := new(big.Int).Mul(o.Numerator, f.Denominator) + denominator := new(big.Int).Mul(f.Denominator, o.Denominator) + resultNumerator := new(big.Int).Sub(numerator1, numerator2) + + g := GCD(resultNumerator, denominator) + + return &Fraction{ + Numerator: new(big.Int).Div(resultNumerator, g), + Denominator: new(big.Int).Div(denominator, g), + } +} + +func (f *Fraction) Mul(other *Fraction) *Fraction { + numerator := new(big.Int).Mul(f.Numerator, other.Numerator) + denominator := new(big.Int).Mul(f.Denominator, other.Denominator) + + if numerator.Sign() == -1 && denominator.Sign() == -1 { + numerator.Neg(numerator) + denominator.Neg(denominator) + } + + g := GCD(numerator, denominator) + + return &Fraction{ + Numerator: new(big.Int).Div(numerator, g), + Denominator: new(big.Int).Div(denominator, g), + } +} + +func (f *Fraction) Div(other *Fraction) *Fraction { + numerator := new(big.Int).Mul(f.Numerator, other.Denominator) + denominator := new(big.Int).Mul(f.Denominator, other.Numerator) + + if numerator.Sign() == -1 && denominator.Sign() == -1 { + numerator.Neg(numerator) + denominator.Neg(denominator) + } + + g := GCD(numerator, denominator) + + return &Fraction{ + Numerator: new(big.Int).Div(numerator, g), + Denominator: new(big.Int).Div(denominator, g), + } +} + +//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 +//} +// +//// 약분이 완료되었다는 가정 +//func (f *Fraction) Equals(other *Fraction) bool { +// return f.Numerator.Cmp(other.Numerator) == 0 && +// f.Denominator.Cmp(other.Denominator) == 0 +//} +// +//// 역 +//func (f *Fraction) Invert() *Fraction { +// return &Fraction{ +// Numerator: f.Denominator, +// Denominator: f.Numerator, +// } +//} + +// 몫 +//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) 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 +//} + +// 구현 안 한 함수들 +// toSignificant() {} +// toFixed() {} diff --git a/core/math/fraction_test.go b/core/math/fraction_test.go new file mode 100644 index 0000000..49d25c4 --- /dev/null +++ b/core/math/fraction_test.go @@ -0,0 +1,195 @@ +package math + +import ( + "testing" +) + +func TestNewFraction(t *testing.T) { + tests := []struct { + numerator, denominator int64 + expectedNumerator, expectedDenominator int64 + expectedError bool + }{ + {1, 1, 1, 1, false}, + {2, 2, 1, 1, false}, + {1, 3, 1, 3, false}, + {1, 0, 0, 0, true}, + {6, 3, 2, 1, false}, + {12, 3, 4, 1, false}, + {-16, 2, -8, 1, false}, + {16, -2, 8, -1, false}, + {16, -2, -8, 1, false}, + } + + for _, test := range tests { + t.Run("", func(t *testing.T) { + defer func() { + if r := recover(); r != nil { + if !test.expectedError { + t.Fatalf("NewFraction: unexpected panic: %v", r) + } + } + }() + fraction := NewFraction(test.numerator, test.denominator) + expectedFraction := NewFraction(test.expectedNumerator, test.expectedDenominator) + + if expectedFraction.Numerator.Cmp(fraction.Numerator) != 0 || expectedFraction.Denominator.Cmp(fraction.Denominator) != 0 { + t.Fatalf("NewFraction: expected %v, got %v", expectedFraction, fraction) + } + }) + } +} + +func TestFraction_Add(t *testing.T) { + t.Parallel() + tests := []struct { + name string + numerator1, denominator1 int64 + numerator2, denominator2 int64 + expectedNumerator, expectedDenominator int64 + }{ + {"1/2 + 1/2", 1, 2, 1, 2, 1, 1}, + {"1/2 + 1/3", 1, 2, 1, 3, 5, 6}, + {"0/1 + 1/1", 0, 1, 1, 1, 1, 1}, + {"-1/2 + 1/2", -1, 2, 1, 2, 0, 1}, + {"1/-2 + 1/-3", 1, -2, 1, -3, -5, 6}, + {"2/1 + 15/7", 2, 1, 15, 7, 29, 7}, + {"2/1 + -15/7", 2, 1, -15, 7, -1, 7}, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + fraction1 := NewFraction(tt.numerator1, tt.denominator1) + fraction2 := NewFraction(tt.numerator2, tt.denominator2) + result := fraction1.Add(fraction2) + expected := NewFraction(tt.expectedNumerator, tt.expectedDenominator) + + 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) { + t.Parallel() + + tests := []struct { + numerator1, denominator1 int64 + numerator2, denominator2 int64 + expectedNumerator, expectedDenominator int64 + }{ + {1, 2, 1, 3, 1, 6}, + {-1, 2, 1, 3, -5, 6}, + {0, 1, 16, 2, 8, -1}, + {1, 2, 1, 2, 0, 1}, + } + + for _, tt := range tests { + tt := tt + t.Run("", func(t *testing.T) { + fraction1 := NewFraction(tt.numerator1, tt.denominator1) + fraction2 := NewFraction(tt.numerator2, tt.denominator2) + result := fraction1.Sub(fraction2) + expected := NewFraction(tt.expectedNumerator, tt.expectedDenominator) + + if result.Numerator.Cmp(expected.Numerator) != 0 || result.Denominator.Cmp(expected.Denominator) != 0 { + t.Fatalf("Sub: expected %v, got %v", expected, result) + } + }) + } +} + +func TestFraction_Mul(t *testing.T) { + tests := []struct { + numerator1, denominator1 int64 + numerator2, denominator2 int64 + expectedNumerator, expectedDenominator int64 + }{ + {1, 2, 1, 3, 1, 6}, + {-100, 10, 256, -10, 256, 1}, + } + + for _, tt := range tests { + t.Run("", func(t *testing.T) { + fraction1 := NewFraction(tt.numerator1, tt.denominator1) + fraction2 := NewFraction(tt.numerator2, tt.denominator2) + result := fraction1.Mul(fraction2) + expected := NewFraction(tt.expectedNumerator, tt.expectedDenominator) + + if result.Numerator.Cmp(expected.Numerator) != 0 || result.Denominator.Cmp(expected.Denominator) != 0 { + t.Fatalf("Mul: expected %v, got %v", expected, result) + } + }) + } +} + +func TestFraction_Div(t *testing.T) { + tests := []struct { + numerator1, denominator1 int64 + numerator2, denominator2 int64 + expectedNumerator, expectedDenominator int64 + }{ + {1, 2, 1, 3, 3, 2}, + {-100, 10, 256, -10, 100, 256}, + } + + for _, tt := range tests { + t.Run("", func(t *testing.T) { + fraction1 := NewFraction(tt.numerator1, tt.denominator1) + fraction2 := NewFraction(tt.numerator2, tt.denominator2) + result := fraction1.Div(fraction2) + expected := NewFraction(tt.expectedNumerator, tt.expectedDenominator) + + if result.Numerator.Cmp(expected.Numerator) != 0 || result.Denominator.Cmp(expected.Denominator) != 0 { + t.Fatalf("Div: 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) +// } +//} +// +//func TestFraction_GreaterThan(t *testing.T) { +// fraction1 := NewFraction(1, 2) +// fraction2 := NewFraction(1, 3) +// result := fraction1.GreaterThan(fraction2) +// expected := true +// +// if result != expected { +// t.Fatalf("GreaterThan: expected %v, got %v", expected, result) +// } +//} +// +//func TestFraction_Equals(t *testing.T) { +// fraction1 := NewFraction(1, 2) +// fraction2 := NewFraction(1, 3) +// result := fraction1.Equals(fraction2) +// expected := false +// +// if result != expected { +// t.Fatalf("Equals: expected %v, got %v", expected, result) +// } +//} +// + +// +//func TestFraction_Invert(t *testing.T) { +// fraction1 := NewFraction(1, 2) +// result := fraction1.Invert() +// expected := NewFraction(2, 1) +// +// if result.Numerator.Cmp(expected.Numerator) != 0 || result.Denominator.Cmp(expected.Denominator) != 0 { +// t.Fatalf("Invert: expected %v, got %v", expected, result) +// } +//} diff --git a/core/math/math.go b/core/math/math.go new file mode 100644 index 0000000..1d10ea9 --- /dev/null +++ b/core/math/math.go @@ -0,0 +1,15 @@ +package math + +import "math/big" + +func GCD(a, b *big.Int) *big.Int { + zero := big.NewInt(0) + + aAbs := new(big.Int).Abs(a) + bAbs := new(big.Int).Abs(b) + + for bAbs.Cmp(zero) != 0 { + aAbs, bAbs = bAbs, new(big.Int).Mod(aAbs, bAbs) + } + return aAbs +} diff --git a/core/math/math_test.go b/core/math/math_test.go new file mode 100644 index 0000000..9cdda4c --- /dev/null +++ b/core/math/math_test.go @@ -0,0 +1,32 @@ +package math + +import ( + "math/big" + "testing" +) + +func TestGCD(t *testing.T) { + tests := []struct { + a, b, expected int64 + }{ + {1, 1, 1}, + {48, 18, 6}, + {101, 10, 1}, + {0, 5, 5}, + {5, 0, 5}, + {-48, 18, 6}, + {48, -18, 6}, + {-48, -18, 6}, + {16, -2, 2}, + } + + for _, test := range tests { + t.Run("", func(t *testing.T) { + result := GCD(big.NewInt(test.a), big.NewInt(test.b)) + + if result.Cmp(big.NewInt(test.expected)) != 0 { + t.Fatalf("GCD: expected %v, got %v", test.expected, result) + } + }) + } +} From c7028de62d2dd38423b7b8e0087f5d11e43b85b1 Mon Sep 17 00:00:00 2001 From: tolelom Date: Wed, 28 Aug 2024 16:01:09 +0900 Subject: [PATCH 2/2] fix --- core/alpha-router.go | 64 ---------- core/alpha_router.go | 64 ++++++++++ ...outer-params.go => alpha_router_params.go} | 0 core/entities/fractions/currencyAmount.go | 26 ---- core/entities/fractions/fraction.go | 119 ------------------ core/entities/fractions/fraction_test.go | 39 ------ core/entities/gnot.go | 23 ---- core/entities/utils/math.go | 8 -- core/entities/wgnot.go | 12 -- core/types.go | 2 +- 10 files changed, 65 insertions(+), 292 deletions(-) delete mode 100644 core/alpha-router.go create mode 100644 core/alpha_router.go rename core/{alpha-router-params.go => alpha_router_params.go} (100%) delete mode 100644 core/entities/fractions/currencyAmount.go delete mode 100644 core/entities/fractions/fraction.go delete mode 100644 core/entities/fractions/fraction_test.go delete mode 100644 core/entities/gnot.go delete mode 100644 core/entities/utils/math.go delete mode 100644 core/entities/wgnot.go diff --git a/core/alpha-router.go b/core/alpha-router.go deleted file mode 100644 index 51c2368..0000000 --- a/core/alpha-router.go +++ /dev/null @@ -1,64 +0,0 @@ -package core - -import ( - "router/core/currency" - "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 currency.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 currency.Currency, -) (currency.Currency, currency.Currency) { - if tradeType == EXACT_INPUT { - return amount.Currency, quoteCurrency - } else { - return quoteCurrency, amount.Currency - } -} diff --git a/core/alpha_router.go b/core/alpha_router.go new file mode 100644 index 0000000..681ca5d --- /dev/null +++ b/core/alpha_router.go @@ -0,0 +1,64 @@ +package core + +//import ( +// "router/core/coins/fractions" +// "router/core/currency" +//) +// +//type AlphaRouter struct { +// portionProvider IPortionProvider +//} +// +//func NewAlphaRouter(params AlphaRouterParams) *AlphaRouter { +// return &AlphaRouter{} +//} +// +//// TODO: 원본 코드에서는 async 함수 +//// 라우트 한 결과는 SwapRoute +//func (a AlphaRouter) route( +// amount fractions.CurrencyAmount, +// quoteCurrency currency.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 currency.Currency, +//) (currency.Currency, currency.Currency) { +// if tradeType == EXACT_INPUT { +// return amount.Currency, quoteCurrency +// } else { +// return quoteCurrency, amount.Currency +// } +//} diff --git a/core/alpha-router-params.go b/core/alpha_router_params.go similarity index 100% rename from core/alpha-router-params.go rename to core/alpha_router_params.go diff --git a/core/entities/fractions/currencyAmount.go b/core/entities/fractions/currencyAmount.go deleted file mode 100644 index 6c6f38e..0000000 --- a/core/entities/fractions/currencyAmount.go +++ /dev/null @@ -1,26 +0,0 @@ -package fractions - -import ( -<<<<<<< Updated upstream:core/entities/fractions/currencyAmount.go - "router/core/entities" -) - -type CurrencyAmount struct { - Fraction - Currency entities.Currency -======= - "router/core/currency" - "router/core/math" -) - -type CurrencyAmount struct { - math.Fraction - Currency currency.Currency ->>>>>>> Stashed changes:core/entities/fractions/currency_amount.go -} - -//func (c CurrencyAmount) add(other CurrencyAmount) CurrencyAmount { -// added := c.Fraction.add(other) -// -// return CurrencyAmount.fromFractionAmount() -//} diff --git a/core/entities/fractions/fraction.go b/core/entities/fractions/fraction.go deleted file mode 100644 index 4a72349..0000000 --- a/core/entities/fractions/fraction.go +++ /dev/null @@ -1,119 +0,0 @@ -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 -//} diff --git a/core/entities/fractions/fraction_test.go b/core/entities/fractions/fraction_test.go deleted file mode 100644 index 6a1ab85..0000000 --- a/core/entities/fractions/fraction_test.go +++ /dev/null @@ -1,39 +0,0 @@ -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) - } -} diff --git a/core/entities/gnot.go b/core/entities/gnot.go deleted file mode 100644 index c96b287..0000000 --- a/core/entities/gnot.go +++ /dev/null @@ -1,23 +0,0 @@ -package entities - -import "router/core/currency" - -type Gnot struct { - NativeCurrency -} - -func NewGnot(chainId int) *Gnot { - return &Gnot{ - NativeCurrency: NativeCurrency{ - currency.BaseCurrency: currency.BaseCurrency{ - chainId: chainId, - }, - }, - } -} - -func (g Gnot) Wrapped() currency.Token { - wgnot := WGNOT[g.chainId] - // invariant(!!wgnot, 'WRAPPED') - return wgnot -} diff --git a/core/entities/utils/math.go b/core/entities/utils/math.go deleted file mode 100644 index 0b6bd44..0000000 --- a/core/entities/utils/math.go +++ /dev/null @@ -1,8 +0,0 @@ -package utils - -import "math/big" - -func Gcd(a, b *big.Int) *big.Int { - - return a -} diff --git a/core/entities/wgnot.go b/core/entities/wgnot.go deleted file mode 100644 index 6e88818..0000000 --- a/core/entities/wgnot.go +++ /dev/null @@ -1,12 +0,0 @@ -package entities - -import "router/core/currency" - -var WGNOT = map[int]currency.Token{ - //1: NewToken(), - //2: NewToken(), - //3: NewToken(), - //4: NewToken(), - //5: NewToken(), - //99: NewToken(), -} diff --git a/core/types.go b/core/types.go index f80a40a..0ec0c51 100644 --- a/core/types.go +++ b/core/types.go @@ -1,7 +1,7 @@ package core import ( - "router/core/entities/fractions" + "router/core/coins/fractions" ) // interface는 I 접두사를 붙이는 것이 관행인가?