Skip to content
Open
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
163 changes: 106 additions & 57 deletions skel/daemons/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,41 @@ type MarketResponse struct {

// Define currency response data
type CurrencyResponse struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
ParentID string `json:"parent_id"`
Homepage string `json:"homepage"`
Price string `json:"price"`
Type string `json:"type"`
DepositEnabled bool `json:"deposit_enabled"`
WithdrawalEnabled bool `json:"withdrawal_enabled"`
DepositFee string `json:"deposit_fee"`
MinDepositAmount string `json:"min_deposit_amount"`
WithdrawFee string `json:"withdraw_fee"`
MinWithdrawAmount string `json:"min_withdraw_amount"`
WithdrawLimit24h string `json:"withdraw_limit_24h"`
WithdrawLimit72h string `json:"withdraw_limit_72h"`
BaseFactor int64 `json:"base_factor"`
Precision int64 `json:"precision"`
Position int64 `json:"position"`
IconUrl string `json:"icon_url"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Homepage string `json:"homepage"`
Price string `json:"price"`
Status string `json:"status"`
Type string `json:"type"`
Precision uint64 `json:"precision"`
Position uint64 `json:"position"`
IconURL string `json:"icon_url"`
Code string `json:"code"`
Networks []BlockchainCurrencyResponse `json:"networks"`
}

// Define network response data
type BlockchainCurrencyResponse struct {
ID string `json:"id"`
CurrencyID string `json:"currency_id"`
BlockchainKey string `json:"blockchain_key"`
ParentID string `json:"parent_id"`
Status string `json:"status"`
Type string `json:"type"`
DepositEnabled bool `json:"deposit_enabled"`
WithdrawEnabled bool `json:"withdrawal_enabled"`
DepositFee string `json:"deposit_fee"`
MinDepositAmount string `json:"min_deposit_amount"`
WithdrawFee string `json:"withdraw_fee"`
MinWithdrawAmount string `json:"min_withdraw_amount"`
BaseFactor uint64 `json:"base_factor"`
Warning string `json:"warning"`
Description string `json:"description"`
Protocol string `json:"protocol"`
MinConfirmations uint64 `json:"min_confirmations"`
MinCollectionAmount string `json:"min_collection_amount"`
Options map[string]interface{} `json:"options"`
}

type Response struct {
Expand All @@ -66,7 +82,7 @@ func FetchConfigurationPeriodic(peatioClient *peatio.Client, vaultService *vault
for {
platformID, err := getPlatformIDFromVault(vaultService)
if err != nil {
log.Printf("ERR: FetchMarkets: %v", err.Error())
log.Printf("ERR: FetchConfiguration: %v", err.Error())
} else {
if shouldRestart, err := fetchConfiguration(peatioClient, opendaxAddr, platformID); err == nil && shouldRestart {
go setFinexRestart(vaultService, time.Now().Unix())
Expand All @@ -75,16 +91,17 @@ func FetchConfigurationPeriodic(peatioClient *peatio.Client, vaultService *vault
<-time.After(5 * time.Minute)
}
}

func fetchConfiguration(peatioClient *peatio.Client, opendaxAddr, platformID string) (bool, error) {
url := fmt.Sprintf("%s/api/v2/opx/markets", opendaxAddr)
url := fmt.Sprintf("%s/api/v2/opx/config", opendaxAddr)
response, err := getResponse(url, platformID)

if err != nil {
return false, err
}

// Create currencies
createCurrencies(peatioClient, response.Currencies)
// Create currencies and networks
createCurrenciesWithNetworks(peatioClient, response.Currencies)

// Create markets
shouldRestart := createMarkets(peatioClient, response.Markets)
Expand Down Expand Up @@ -142,45 +159,66 @@ func getResponse(url string, platformID string) (*Response, error) {
return response, nil
}

func createCurrencies(peatioClient *peatio.Client, currencies []CurrencyResponse) {
func createCurrenciesWithNetworks(peatioClient *peatio.Client, currencies []CurrencyResponse) {
for _, currency := range currencies {
// Find currency by code, if there is no system will create
res, apiError := peatioClient.GetCurrencyByCode(currency.ID)
// Check result here
if res == nil && apiError != nil {
currencyParams := peatio.CreateCurrencyParams{
Code: currency.ID,
Type: currency.Type,
BaseFactor: currency.BaseFactor,
Position: currency.Position,
DepositFee: currency.DepositFee,
ParentID: currency.ParentID,
MinDepositAmount: currency.MinDepositAmount,
WithdrawFee: currency.WithdrawFee,
MinCollectionAmount: currency.MinDepositAmount,
MinWithdrawAmount: currency.MinWithdrawAmount,
WithdrawLimit24: currency.WithdrawLimit24h,
WithdrawLimit72: currency.WithdrawLimit72h,
DepositEnabled: currency.DepositEnabled,
WithdrawEnabled: currency.WithdrawalEnabled,
Precision: currency.Precision,
Price: currency.Price,
IconURL: currency.IconUrl,
Description: currency.Description,
Homepage: currency.Homepage,
}
if currency.Type == "coin" {
currencyParams.BlockchainKey = "opendax-cloud"
Code: currency.ID,
Type: currency.Type,
Name: currency.Name,
Status: currency.Status,
Precision: int64(currency.Precision),
Price: currency.Price,
IconURL: currency.IconURL,
Description: currency.Description,
Homepage: currency.Homepage,
}

_, apiError := peatioClient.CreateCurrency(currencyParams)
if apiError != nil {
log.Printf("ERROR: createCurrencies: Can't create currency with code %s. Error: %v. Errors: %v", currency.ID, apiError.Error, apiError.Errors)
log.Printf("ERROR: createCurrenciesWithNetworks: Can't create currency with code %s. Error: %v. Errors: %v", currency.ID, apiError.Error, apiError.Errors)
}

// create currency networks
createNetworks(peatioClient, currency)
}
}
}

func createNetworks(peatioClient *peatio.Client, currency CurrencyResponse) {
for _, network := range currency.Networks {
// Find network by currency_id, blockchain_jey, if there is no system will create
res, apiError := peatioClient.GetBlockchainCurrencyByID(network.ID)
// Check result here
if res == nil && apiError != nil {
networkParams := peatio.CreateBlockchainCurrencyParams{
CurrencyID: network.CurrencyID,
BaseFactor: int64(network.BaseFactor),
ParentID: network.ParentID,
DepositFee: network.DepositFee,
MinDepositAmount: network.MinDepositAmount,
MinCollectionAmount: network.MinCollectionAmount,
WithdrawFee: network.WithdrawFee,
MinWithdrawAmount: network.MinWithdrawAmount,
DepositEnabled: network.DepositEnabled,
WithdrawEnabled: network.WithdrawEnabled,
Status: network.Status,
Options: network.Options,
}
if currency.Type == "coin" {
networkParams.BlockchainKey = "opendax-cloud"
}

_, apiError := peatioClient.CreateBlockchainCurrency(networkParams)
if apiError != nil {
log.Printf("ERROR: createCurrenciesWithNetworks: Can't create network with blockchain key %s and currency id %s. Error: %v. Errors: %v", network.BlockchainKey, network.CurrencyID, apiError.Error, apiError.Errors)
}
}
}
}
func createMarkets(peatioClient *peatio.Client, markets []MarketResponse) (shouldRestart bool) {
for _, market := range markets {
// Find market by ID, if there is no system will create
Expand Down Expand Up @@ -282,18 +320,29 @@ func updatePartiallyMatchedWallet(peatioClient *peatio.Client, w *peatio.Wallet,
// For example {"eth": ["eth", "usdt", "link"]}
func divideCurrenciesIntoGroups(currencies []CurrencyResponse) map[string][]string {
res := make(map[string][]string)
// Sort currencies with empty Parent ID first
// It means those currencies should have separate wallet
sort.SliceStable(currencies, func(i, j int) bool {
return currencies[i].ParentID < currencies[j].ParentID
})

blockchainCurrencies := []BlockchainCurrencyResponse{}
for _, currency := range currencies {
if currency.Type == "coin" {
if currency.ParentID == "" {
res[currency.ID] = append(res[currency.ID], currency.ID)
// append only first network
// assume that all networks should have same parent_id
if len(currency.Networks) > 0 {
blockchainCurrencies = append(blockchainCurrencies, currency.Networks[0])
}
}

// Sort networks with empty Parent ID first
// It means those network currencies should have separate wallet
sort.SliceStable(blockchainCurrencies, func(i, j int) bool {
return blockchainCurrencies[i].ParentID < blockchainCurrencies[j].ParentID
})

for _, network := range blockchainCurrencies {
// BlockchainKey is empty in case of fiat currency type
if network.BlockchainKey != "" {
if network.ParentID == "" {
res[network.CurrencyID] = append(res[network.CurrencyID], network.CurrencyID)
} else {
res[currency.ParentID] = append(res[currency.ParentID], currency.ID)
res[network.ParentID] = append(res[network.ParentID], network.CurrencyID)
}
}
}
Expand Down Expand Up @@ -409,7 +458,7 @@ func GetXLNEnabledFromVault(vaultService *vault.Service) (bool, error) {
if err != nil {
return false, err
}

if result == nil {
result = false
}
Expand Down
94 changes: 55 additions & 39 deletions skel/daemons/configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ import (
const peatioManagementURL = "api/v2/peatio/management"

func TestFetchConfigurationSuccess(t *testing.T) {
mockedResponse := []byte(`{"currencies":[{"id":"aave","name":"Aave Token","description":"","parent_id":"","homepage":"","price":"1.0","type":"coin","deposit_enabled":true,"withdrawal_enabled":true,"deposit_fee":"0.0","min_deposit_amount":"0.13764625","withdraw_fee":"0.0","min_withdraw_amount":"0.13764625","withdraw_limit_24h":"0.0","withdraw_limit_72h":"0.0","base_factor":1000000000000000000,"precision":8,"position":1,"icon_url":"https://app.storage.yellow.com/uploads/asset/icon/aave/67ba0cd807.png"}],"markets":[{"id":"omgusdt","name":"OMG/USDT","base_unit":"omg","quote_unit":"usdt","state":"enabled","amount_precision":2,"price_precision":4,"min_price":"0.0037","max_price":"3687.4597","min_amount":"0.01","position":9}]}`)
mockedResponse := []byte(`{"currencies":[{"id":"btc","name":"Bitcoin","description":"","homepage":"","price":"39100.0","status":"enabled","type":"coin","precision":6,"position":4,"icon_url":"","networks":[]}],"markets":[{"id":"omgusdt","name":"OMG/USDT","base_unit":"omg","quote_unit":"usdt","state":"enabled","amount_precision":2,"price_precision":4,"min_price":"0.0037","max_price":"3687.4597","min_amount":"0.01","position":9}]}`)
marketPeatioResponse := []byte(`{"id":"omgusdt","name":"OMG/USDT","base_unit":"omg","quote_unit":"usdt","state":"enabled","amount_precision":2,"price_precision":4,"min_price":"0.0037","max_price":"3687.4597","min_amount":"0.01","position":9}`)
currencyPeatioResponse := []byte(`{"id":"aave","name":"Aave Token","description":null,"homepage":null,"price":"1.0","explorer_transaction":"https://rinkeby.etherscan.io/tx/#{txid}","explorer_address":"https://rinkeby.etherscan.io/address/#{address}","type":"coin","deposit_enabled":true,"withdrawal_enabled":true,"deposit_fee":"0.0","min_deposit_amount":"0.13764625","withdraw_fee":"0.0","min_withdraw_amount":"0.13764625","withdraw_limit_24h":"0.0","withdraw_limit_72h":"0.0","base_factor":1000000000000000000,"precision":8,"position":1,"icon_url":"https://app.storage.yellow.com/uploads/asset/icon/aave/67ba0cd807.png","min_confirmations":6}`)
currencyPeatioResponse := []byte(`{"id":"btc","name":"Bitcoin","description":"","homepage":"","price":"39100.0","status":"enabled","type":"coin","precision":6,"position":4,"icon_url":""}`)
networkPeatioResponse := []byte(`{"blockchain_key":"btc-testnet","currency_id":"btc","deposit_enabled":false,"withdrawal_enabled":true,"deposit_fee":"0.0","min_deposit_amount":"0.0","withdraw_fee":"0.0000000002557544","min_withdraw_amount":"0.0000000025575447","base_factor":1000000000000000000}`)
mux := http.NewServeMux()
mux.HandleFunc("/api/v2/opx/markets", func(res http.ResponseWriter, req *http.Request) {
mux.HandleFunc("/api/v2/opx/config", func(res http.ResponseWriter, req *http.Request) {
res.Write(mockedResponse)
})
mux.HandleFunc("/api/v2/peatio/management/markets/new", func(res http.ResponseWriter, req *http.Request) {
Expand All @@ -28,6 +29,9 @@ func TestFetchConfigurationSuccess(t *testing.T) {
mux.HandleFunc("/api/v2/peatio/management/currencies/create", func(res http.ResponseWriter, req *http.Request) {
res.Write(currencyPeatioResponse)
})
mux.HandleFunc("/api/v2/peatio/management/blockchain_currencies/new", func(res http.ResponseWriter, req *http.Request) {
res.Write(networkPeatioResponse)
})

ts := httptest.NewServer(mux)
defer ts.Close()
Expand All @@ -45,7 +49,7 @@ func TestFetchConfigurationEmptyResponse(t *testing.T) {
mockedResponse := []byte(`{}`)
mux := http.NewServeMux()

mux.HandleFunc("/api/v2/opx/markets", func(res http.ResponseWriter, req *http.Request) {
mux.HandleFunc("/api/v2/opx/config", func(res http.ResponseWriter, req *http.Request) {
res.Write(mockedResponse)
})

Expand Down Expand Up @@ -81,53 +85,65 @@ func TestFetchConfigurationHostError(t *testing.T) {
func TestDivideCurrenciesIntoGroups(t *testing.T) {
response := []CurrencyResponse{
{
ID: "link", Name: "LINK", Description: "", ParentID: "eth", Homepage: "",
Price: "0.0", Type: "coin", DepositEnabled: true, WithdrawalEnabled: true,
DepositFee: "0.0", MinDepositAmount: "0.0", WithdrawFee: "0.0",
MinWithdrawAmount: "0.0", WithdrawLimit24h: "0.0", WithdrawLimit72h: "0.0",
BaseFactor: 8, Precision: 16, Position: 1, IconUrl: "",
ID: "link", Name: "LINK", Description: "", Homepage: "",
Price: "0.0", Type: "coin", Precision: 16, Position: 1, IconURL: "",
Networks: []BlockchainCurrencyResponse{{CurrencyID: "link", BlockchainKey: "eth-rinkeby", ParentID: "eth",
DepositEnabled: true, WithdrawEnabled: true, DepositFee: "0.0", MinDepositAmount: "0.0",
WithdrawFee: "0.0", MinWithdrawAmount: "0.0",
BaseFactor: 8}, {
CurrencyID: "link", BlockchainKey: "eth-rinkeby", ParentID: "",
DepositEnabled: true, WithdrawEnabled: true, DepositFee: "0.0", MinDepositAmount: "0.0",
WithdrawFee: "0.0", MinWithdrawAmount: "0.0",
BaseFactor: 8},
},
},
{
ID: "eth", Name: "ETH", Description: "", ParentID: "", Homepage: "",
Price: "0.0", Type: "coin", DepositEnabled: true, WithdrawalEnabled: true,
DepositFee: "0.0", MinDepositAmount: "0.0", WithdrawFee: "0.0",
MinWithdrawAmount: "0.0", WithdrawLimit24h: "0.0", WithdrawLimit72h: "0.0",
BaseFactor: 8, Precision: 16, Position: 1, IconUrl: "",
ID: "eth", Name: "ETH", Description: "", Homepage: "",
Price: "0.0", Type: "coin", Precision: 16, Position: 1, IconURL: "",
Networks: []BlockchainCurrencyResponse{{CurrencyID: "eth", BlockchainKey: "eth-rinkeby", ParentID: "",
DepositEnabled: true, WithdrawEnabled: true, DepositFee: "0.0", MinDepositAmount: "0.0",
WithdrawFee: "0.0", MinWithdrawAmount: "0.0",
BaseFactor: 8}},
},
{
ID: "usdt", Name: "USDT", Description: "", ParentID: "eth", Homepage: "",
Price: "0.0", Type: "coin", DepositEnabled: true, WithdrawalEnabled: true,
DepositFee: "0.0", MinDepositAmount: "0.0", WithdrawFee: "0.0",
MinWithdrawAmount: "0.0", WithdrawLimit24h: "0.0", WithdrawLimit72h: "0.0",
BaseFactor: 8, Precision: 16, Position: 1, IconUrl: "",
ID: "usdt", Name: "USDT", Description: "", Homepage: "",
Price: "0.0", Type: "coin", Precision: 16, Position: 1, IconURL: "",
Networks: []BlockchainCurrencyResponse{{CurrencyID: "usdt", BlockchainKey: "eth-rinkeby", ParentID: "eth",
DepositEnabled: true, WithdrawEnabled: true, DepositFee: "0.0", MinDepositAmount: "0.0",
WithdrawFee: "0.0", MinWithdrawAmount: "0.0",
BaseFactor: 8}},
},
{
ID: "eur", Name: "EUR", Description: "", ParentID: "", Homepage: "",
Price: "0.0", Type: "fiat", DepositEnabled: true, WithdrawalEnabled: true,
DepositFee: "0.0", MinDepositAmount: "0.0", WithdrawFee: "0.0",
MinWithdrawAmount: "0.0", WithdrawLimit24h: "0.0", WithdrawLimit72h: "0.0",
BaseFactor: 8, Precision: 16, Position: 1, IconUrl: "",
ID: "eur", Name: "EUR", Description: "", Homepage: "",
Price: "0.0", Type: "fiat", Precision: 16, Position: 1, IconURL: "",
Networks: []BlockchainCurrencyResponse{{CurrencyID: "eur", BlockchainKey: "", ParentID: "",
DepositEnabled: true, WithdrawEnabled: true, DepositFee: "0.0", MinDepositAmount: "0.0",
WithdrawFee: "0.0", MinWithdrawAmount: "0.0",
BaseFactor: 8}},
},
{
ID: "tron", Name: "TRON", Description: "", ParentID: "", Homepage: "",
Price: "0.0", Type: "coin", DepositEnabled: true, WithdrawalEnabled: true,
DepositFee: "0.0", MinDepositAmount: "0.0", WithdrawFee: "0.0",
MinWithdrawAmount: "0.0", WithdrawLimit24h: "0.0", WithdrawLimit72h: "0.0",
BaseFactor: 8, Precision: 16, Position: 1, IconUrl: "",
ID: "tron", Name: "TRON", Description: "", Homepage: "",
Price: "0.0", Type: "coin", Precision: 16, Position: 1, IconURL: "",
Networks: []BlockchainCurrencyResponse{{CurrencyID: "tron", BlockchainKey: "tron-testnet", ParentID: "",
DepositEnabled: true, WithdrawEnabled: true, DepositFee: "0.0", MinDepositAmount: "0.0",
WithdrawFee: "0.0", MinWithdrawAmount: "0.0",
BaseFactor: 8}},
},
{
ID: "xrp", Name: "XRP", Description: "", ParentID: "", Homepage: "",
Price: "0.0", Type: "coin", DepositEnabled: true, WithdrawalEnabled: true,
DepositFee: "0.0", MinDepositAmount: "0.0", WithdrawFee: "0.0",
MinWithdrawAmount: "0.0", WithdrawLimit24h: "0.0", WithdrawLimit72h: "0.0",
BaseFactor: 8, Precision: 16, Position: 1, IconUrl: "",
ID: "xrp", Name: "XRP", Description: "", Homepage: "",
Price: "0.0", Type: "coin", Precision: 16, Position: 1, IconURL: "",
Networks: []BlockchainCurrencyResponse{{CurrencyID: "xrp", BlockchainKey: "xrp-testnet", ParentID: "",
DepositEnabled: true, WithdrawEnabled: true, DepositFee: "0.0", MinDepositAmount: "0.0",
WithdrawFee: "0.0", MinWithdrawAmount: "0.0",
BaseFactor: 8}},
},
{
ID: "txrp", Name: "TXRP", Description: "", ParentID: "xrp", Homepage: "",
Price: "0.0", Type: "coin", DepositEnabled: true, WithdrawalEnabled: true,
DepositFee: "0.0", MinDepositAmount: "0.0", WithdrawFee: "0.0",
MinWithdrawAmount: "0.0", WithdrawLimit24h: "0.0", WithdrawLimit72h: "0.0",
BaseFactor: 8, Precision: 16, Position: 1, IconUrl: "",
ID: "txrp", Name: "TXRP", Description: "", Homepage: "",
Price: "0.0", Type: "coin", Precision: 16, Position: 1, IconURL: "",
Networks: []BlockchainCurrencyResponse{{CurrencyID: "txrp", BlockchainKey: "xrp-testnet", ParentID: "xrp",
DepositEnabled: true, WithdrawEnabled: true, DepositFee: "0.0", MinDepositAmount: "0.0",
WithdrawFee: "0.0", MinWithdrawAmount: "0.0",
BaseFactor: 8}},
},
}

Expand Down
Loading