diff --git a/routes/dao_coin_exchange.go b/routes/dao_coin_exchange.go index 90ebce44..9b7fe2d6 100644 --- a/routes/dao_coin_exchange.go +++ b/routes/dao_coin_exchange.go @@ -2,6 +2,7 @@ package routes import ( "bytes" + "encoding/hex" "encoding/json" "fmt" "github.com/deso-protocol/core/lib" @@ -18,6 +19,13 @@ import ( type GetDAOCoinLimitOrdersRequest struct { DAOCoin1CreatorPublicKeyBase58Check string `safeForLogging:"true"` DAOCoin2CreatorPublicKeyBase58Check string `safeForLogging:"true"` + + // A list of hex OrderIds that we will fetch + OrderIds []string `safeForLogging:"true"` + // If unset, defaults to TxnStatusUnconfirmed. If set to "unconfirmed" we will + // consider all txns including those in the mempool. If set to "confirmed" then + // we will only consider txns that have been confirmed according to consensus. + TxnStatus TxnStatus `safeForLogging:"true"` } type GetDAOCoinLimitOrdersResponse struct { @@ -63,8 +71,8 @@ func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Re return } - if requestData.DAOCoin1CreatorPublicKeyBase58Check == DESOCoinIdentifierString && - requestData.DAOCoin2CreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(requestData.DAOCoin1CreatorPublicKeyBase58Check) && + IsDesoPkid(requestData.DAOCoin2CreatorPublicKeyBase58Check) { _AddBadRequestError( ww, fmt.Sprint("GetDAOCoinLimitOrders: Must provide either a "+ @@ -74,16 +82,115 @@ func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Re return } + txnStatus := requestData.TxnStatus + if txnStatus == "" { + txnStatus = TxnStatusUnconfirmed + } else if txnStatus != TxnStatusUnconfirmed && + txnStatus != TxnStatusConfirmed { + + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Invalid TxnStatus: %v. Options "+ + "are {unconfirmed, confirmed}.", txnStatus), + ) + return + } + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() if err != nil { _AddInternalServerError(ww, fmt.Sprintf("GetDAOCoinLimitOrders: Problem fetching utxoView: %v", err)) return } + if txnStatus == TxnStatusConfirmed { + utxoView = lib.NewUtxoView( + fes.backendServer.GetBlockchain().DB(), + fes.Params, + nil, + fes.backendServer.GetBlockchain().Snapshot(), + nil) + } + + // If they requested a specific set of OrderIds then fetch them directly + if len(requestData.OrderIds) > 0 { + // Don't allow fetching more than this many orders + maxOrdersToFetch := 10000 + if len(requestData.OrderIds) > maxOrdersToFetch { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Cannot fetch more than %v orders at once", maxOrdersToFetch), + ) + return + } + ordersToReturn := make([]DAOCoinLimitOrderEntryResponse, 0, len(requestData.OrderIds)) + for _, orderIdHex := range requestData.OrderIds { + orderIdBytes, err := hex.DecodeString(orderIdHex) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Invalid OrderId: %v", err), + ) + return + } + if len(orderIdBytes) != 32 { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Block hash has length (%d) but should "+ + "be (%d)", len(orderIdBytes), 32), + ) + return + } + orderId := lib.BlockHash{} + copy(orderId[:], orderIdBytes) + orderEntry, err := utxoView.GetDAOCoinLimitOrderEntry(&orderId) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Error fetching order: %v", err), + ) + return + } + if orderEntry == nil { + continue + } + if orderEntry.IsDeleted() { + continue + } + orderRes, err := buildDAOCoinLimitOrderResponse( + lib.Base58CheckEncode(orderEntry.TransactorPKID[:], false, fes.Params), + lib.Base58CheckEncode(orderEntry.BuyingDAOCoinCreatorPKID[:], false, fes.Params), + lib.Base58CheckEncode(orderEntry.SellingDAOCoinCreatorPKID[:], false, fes.Params), + orderEntry, + ) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Error building order response: %v", err), + ) + return + } + if orderRes == nil { + _AddInternalServerError(ww, "GetDAOCoinLimitOrders: Error building order "+ + "response: nil order response") + return + } + ordersToReturn = append(ordersToReturn, *orderRes) + } + if err = json.NewEncoder(ww).Encode(GetDAOCoinLimitOrdersResponse{ + Orders: ordersToReturn, + }); err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetDAOCoinLimitOrders: Problem encoding response as JSON: %v", err), + ) + return + } + return + } coin1PKID := &lib.ZeroPKID coin2PKID := &lib.ZeroPKID - if requestData.DAOCoin1CreatorPublicKeyBase58Check != DESOCoinIdentifierString { + if !IsDesoPkid(requestData.DAOCoin1CreatorPublicKeyBase58Check) { coin1PKID, err = fes.getPKIDFromPublicKeyBase58Check( utxoView, requestData.DAOCoin1CreatorPublicKeyBase58Check, @@ -97,7 +204,7 @@ func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Re } } - if requestData.DAOCoin2CreatorPublicKeyBase58Check != DESOCoinIdentifierString { + if !IsDesoPkid(requestData.DAOCoin2CreatorPublicKeyBase58Check) { coin2PKID, err = fes.getPKIDFromPublicKeyBase58Check( utxoView, requestData.DAOCoin2CreatorPublicKeyBase58Check, @@ -145,7 +252,12 @@ func (fes *APIServer) GetDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Re } type GetTransactorDAOCoinLimitOrdersRequest struct { - TransactorPublicKeyBase58Check string `safeForLogging:"true"` + TransactorPublicKeyBase58Check string `safeForLogging:"true"` + BuyingCoinPublicKeyBase58Check string `safeForLogging:"true"` + SellingCoinPublicKeyBase58Check string `safeForLogging:"true"` + // Defaults to TxnStatusUnconfirmed. If set to "unconfirmed" we will consider all + // txns including those in the mempool. + TxnStatus TxnStatus `safeForLogging:"true"` } func (fes *APIServer) GetTransactorDAOCoinLimitOrders(ww http.ResponseWriter, req *http.Request) { @@ -159,11 +271,34 @@ func (fes *APIServer) GetTransactorDAOCoinLimitOrders(ww http.ResponseWriter, re return } + txnStatus := requestData.TxnStatus + if txnStatus == "" { + txnStatus = TxnStatusUnconfirmed + } + if txnStatus != TxnStatusUnconfirmed && + txnStatus != TxnStatusConfirmed { + + _AddBadRequestError( + ww, + fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid TxnStatus: %v. Options "+ + "are {unconfirmed, confirmed}.", txnStatus), + ) + return + } + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() if err != nil { _AddInternalServerError(ww, fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Problem fetching utxoView: %v", err)) return } + if txnStatus == TxnStatusConfirmed { + utxoView = lib.NewUtxoView( + fes.backendServer.GetBlockchain().DB(), + fes.Params, + nil, + fes.backendServer.GetBlockchain().Snapshot(), + nil) + } transactorPKID, err := fes.getPKIDFromPublicKeyBase58Check( utxoView, @@ -176,8 +311,45 @@ func (fes *APIServer) GetTransactorDAOCoinLimitOrders(ww http.ResponseWriter, re ) return } + var buyingCoinPkid *lib.PKID + if requestData.BuyingCoinPublicKeyBase58Check != "" { + if IsDesoPkid(requestData.BuyingCoinPublicKeyBase58Check) { + buyingCoinPkid = &lib.ZeroPKID + } else { + buyingCoinPkid, err = fes.getPKIDFromPublicKeyBase58Check( + utxoView, + requestData.BuyingCoinPublicKeyBase58Check, + ) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid BuyingCoinPublicKeyBase58Check: %v", err), + ) + return + } + } + } + var sellingCoinPkid *lib.PKID + if requestData.SellingCoinPublicKeyBase58Check != "" { + if IsDesoPkid(requestData.SellingCoinPublicKeyBase58Check) { + sellingCoinPkid = &lib.ZeroPKID + } else { + sellingCoinPkid, err = fes.getPKIDFromPublicKeyBase58Check( + utxoView, + requestData.SellingCoinPublicKeyBase58Check, + ) + if err != nil { + _AddBadRequestError( + ww, + fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Invalid SellingCoinPublicKeyBase58Check: %v", err), + ) + return + } + } + } - orders, err := utxoView.GetAllDAOCoinLimitOrdersForThisTransactor(transactorPKID) + orders, err := utxoView.GetAllDAOCoinLimitOrdersForThisTransactor( + transactorPKID, buyingCoinPkid, sellingCoinPkid) if err != nil { _AddInternalServerError(ww, fmt.Sprintf("GetTransactorDAOCoinLimitOrders: Error getting limit orders: %v", err)) return @@ -324,6 +496,14 @@ func buildDAOCoinLimitOrderResponse( return nil, err } + // We always want to return the identifier string for DESO coins in the API response + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { + buyingCoinPublicKeyBase58Check = DESOCoinIdentifierString + } + if IsDesoPkid(sellingCoinPublicKeyBase58Check) { + sellingCoinPublicKeyBase58Check = DESOCoinIdentifierString + } + return &DAOCoinLimitOrderEntryResponse{ TransactorPublicKeyBase58Check: transactorPublicKeyBase58Check, @@ -436,10 +616,10 @@ func CalculateScaledExchangeRateFromPriceString( // For DESO <-> DAO coin trades, we scale the calculated exchange rate up or down by 1e9 to account for the // scaling factor difference between DESO nanos and DAO coin base units - if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { // Scale the exchange rate up by 1e9 if the buying coin is DESO rawScaledExchangeRateAsBigInt.Mul(rawScaledExchangeRateAsBigInt, getDESOToDAOCoinBaseUnitsScalingFactor().ToBig()) - } else if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + } else if IsDesoPkid(sellingCoinPublicKeyBase58Check) { // Scale the exchange rate down by 1e9 if the selling coin is DESO if and round the quotient up. // For the same reason as above, we round up the quotient, so it matches with bid orders created using the // same input price @@ -462,7 +642,7 @@ func CalculateScaledExchangeRateFromPriceString( // Beyond this point, we know that the operation type is lib.DAOCoinLimitOrderOperationTypeBID // Scale up the price to account for DAO Coin -> DESO trades - if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { product := uint256.NewInt(0) _, overflow := product.MulOverflow(rawScaledPrice, getDESOToDAOCoinBaseUnitsScalingFactor()) if overflow { @@ -472,7 +652,7 @@ func CalculateScaledExchangeRateFromPriceString( } // Scale down the price to account for DAO Coin -> DESO trades - if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(sellingCoinPublicKeyBase58Check) { // We intentionally want to round the exchange rate down for BID orders so precision loss does not prevent the // order from not getting matched with an ASK order with the same input price quotient := uint256.NewInt(0).Div(rawScaledPrice, getDESOToDAOCoinBaseUnitsScalingFactor()) @@ -512,7 +692,7 @@ func CalculateScaledExchangeRateFromFloat( if rawScaledExchangeRate.IsZero() { return nil, errors.Errorf("The float value %f is too small to produce a scaled exchange rate", exchangeRateCoinsToSellPerCoinToBuy) } - if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { // Buying coin is $DESO product := uint256.NewInt(0) _, overflow := product.MulOverflow(rawScaledExchangeRate, getDESOToDAOCoinBaseUnitsScalingFactor()) @@ -520,7 +700,7 @@ func CalculateScaledExchangeRateFromFloat( return nil, errors.Errorf("Overflow when convering %f to a scaled exchange rate", exchangeRateCoinsToSellPerCoinToBuy) } return product, nil - } else if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + } else if IsDesoPkid(sellingCoinPublicKeyBase58Check) { // Selling coin is $DESO quotient := uint256.NewInt(0).Div(rawScaledExchangeRate, getDESOToDAOCoinBaseUnitsScalingFactor()) if quotient.IsZero() { @@ -543,9 +723,9 @@ func CalculatePriceStringFromScaledExchangeRate( ) (string, error) { scaledExchangeRateAsBigInt := scaledValueExchangeRate.ToBig() - if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { scaledExchangeRateAsBigInt.Div(scaledExchangeRateAsBigInt, getDESOToDAOCoinBaseUnitsScalingFactor().ToBig()) - } else if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + } else if IsDesoPkid(sellingCoinPublicKeyBase58Check) { scaledExchangeRateAsBigInt.Mul(scaledExchangeRateAsBigInt, getDESOToDAOCoinBaseUnitsScalingFactor().ToBig()) } @@ -578,9 +758,9 @@ func CalculateFloatFromScaledExchangeRate( scaledValue *uint256.Int, ) (float64, error) { scaledValueAsBigInt := scaledValue.ToBig() - if buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingCoinPublicKeyBase58Check) { scaledValueAsBigInt.Div(scaledValueAsBigInt, getDESOToDAOCoinBaseUnitsScalingFactor().ToBig()) - } else if sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString { + } else if IsDesoPkid(sellingCoinPublicKeyBase58Check) { scaledValueAsBigInt.Mul(scaledValueAsBigInt, getDESOToDAOCoinBaseUnitsScalingFactor().ToBig()) } @@ -698,6 +878,17 @@ func calculateQuantityToFillAsDESONanos(quantityToFill string) (*uint256.Int, er return scaledQuantity, nil } +var ( + DeSoZeroPkidMainnetBase58 = lib.PkToStringMainnet(lib.ZeroPKID[:]) + DeSoZeroPkidTestnetBase58 = lib.PkToStringTestnet(lib.ZeroPKID[:]) +) + +func IsDesoPkid(pk string) bool { + return (pk == DESOCoinIdentifierString || + pk == DeSoZeroPkidMainnetBase58 || + pk == DeSoZeroPkidTestnetBase58) +} + // given a buying coin, selling coin, and operation type, this determines if the QuantityToFill field // for the coin the quantity field refers to is $DESO. If it's not $DESO, then it's assumed to be a DAO coin func isCoinToFillDESO( @@ -705,8 +896,8 @@ func isCoinToFillDESO( sellingCoinPublicKeyBase58Check string, operationTypeString DAOCoinLimitOrderOperationTypeString, ) bool { - return buyingCoinPublicKeyBase58Check == DESOCoinIdentifierString && operationTypeString == DAOCoinLimitOrderOperationTypeStringBID || - sellingCoinPublicKeyBase58Check == DESOCoinIdentifierString && operationTypeString == DAOCoinLimitOrderOperationTypeStringASK + return IsDesoPkid(buyingCoinPublicKeyBase58Check) && operationTypeString == DAOCoinLimitOrderOperationTypeStringBID || + IsDesoPkid(sellingCoinPublicKeyBase58Check) && operationTypeString == DAOCoinLimitOrderOperationTypeStringASK } // DAOCoinLimitOrderOperationTypeString A convenience type that uses a string to represent BID / ASK side in the API, @@ -856,7 +1047,7 @@ func (fes *APIServer) validateTransactorSellingCoinBalance( // If buying $DESO, the buying PKID is the ZeroPKID. Else it's the DAO coin's PKID. buyingCoinPKID := &lib.ZeroPKID - if buyingDAOCoinCreatorPublicKeyBase58Check != DESOCoinIdentifierString { + if !IsDesoPkid(buyingDAOCoinCreatorPublicKeyBase58Check) { buyingCoinPKID, err = fes.getPKIDFromPublicKeyBase58Check( utxoView, buyingDAOCoinCreatorPublicKeyBase58Check) if err != nil { @@ -870,7 +1061,7 @@ func (fes *APIServer) validateTransactorSellingCoinBalance( // Calculate current balance for transactor. transactorSellingBalanceBaseUnits := uint256.NewInt(0) - if sellingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(sellingDAOCoinCreatorPublicKeyBase58Check) { // Get $DESO balance nanos. desoBalanceNanos, err := utxoView.GetDeSoBalanceNanosForPublicKey(transactorPublicKey) if err != nil { @@ -898,7 +1089,7 @@ func (fes *APIServer) validateTransactorSellingCoinBalance( } // Get open orders for this transactor - orders, err := utxoView.GetAllDAOCoinLimitOrdersForThisTransactor(transactorPKID) + orders, err := utxoView.GetAllDAOCoinLimitOrdersForThisTransactor(transactorPKID, nil, nil) if err != nil { return errors.Errorf("Error getting limit orders: %v", err) } @@ -949,7 +1140,7 @@ func (fes *APIServer) validateDAOCoinOrderTransferRestriction( // If buying $DESO, this never has a transfer restriction. We validate // that you own sufficient of your selling coin elsewhere. - if buyingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingDAOCoinCreatorPublicKeyBase58Check) { return nil } @@ -1020,7 +1211,7 @@ func (fes *APIServer) getDAOCoinLimitOrderSimulatedExecutionResult( if err != nil { return nil, err } - if buyingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(buyingDAOCoinCreatorPublicKeyBase58Check) { // If the buying coin is DESO, then the ending balance change will have the transaction fee subtracted. In order to // isolate the amount of the buying coin bought as a part of this order, we need to add back the transaction fee buyingCoinEndingBalance.Add(buyingCoinEndingBalance, uint256.NewInt(txnFees)) @@ -1030,7 +1221,7 @@ func (fes *APIServer) getDAOCoinLimitOrderSimulatedExecutionResult( if err != nil { return nil, err } - if sellingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(sellingDAOCoinCreatorPublicKeyBase58Check) { // If the selling coin is DESO, then the ending balance will have the network fee subtracted. In order to isolate // the amount of the selling coin sold as a part of this order, we need to add back the transaction fee to the // ending balance @@ -1076,7 +1267,7 @@ func (fes *APIServer) getTransactorDesoOrDaoCoinBalance( return nil, errors.Errorf("Error decoding transactor public key: %v", err) } - if desoOrDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(desoOrDAOCoinCreatorPublicKeyBase58Check) { // Get $DESO balance nanos. desoBalanceNanos, err := utxoView.GetDeSoBalanceNanosForPublicKey(transactorPublicKey) if err != nil { @@ -1099,7 +1290,7 @@ func (fes *APIServer) getTransactorDesoOrDaoCoinBalance( } func getScalingFactorForCoin(coinCreatorPublicKeyBase58Check string) *uint256.Int { - if coinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(coinCreatorPublicKeyBase58Check) { return uint256.NewInt(lib.NanosPerUnit) } return uint256.NewInt(0).Set(lib.BaseUnitsPerCoin) diff --git a/routes/transaction.go b/routes/transaction.go index 7c6e1657..f0626e0b 100644 --- a/routes/transaction.go +++ b/routes/transaction.go @@ -25,9 +25,21 @@ import ( "github.com/pkg/errors" ) +type TxnStatus string + +const ( + TxnStatusUnconfirmed TxnStatus = "unconfirmed" + TxnStatusConfirmed TxnStatus = "confirmed" + // TODO: It would be useful to have one that is "InBlock" or something like that, which + // means we'll consider txns that are in unconfirmed blocks but will *not* consider txns + // that are in the mempool. It's a kindof middle-ground. +) + type GetTxnRequest struct { // TxnHashHex to fetch. TxnHashHex string `safeForLogging:"true"` + // If unset, defaults to TxnStatusUnconfirmed + TxnStatus TxnStatus `safeForLogging:"true"` } type GetTxnResponse struct { @@ -58,10 +70,27 @@ func (fes *APIServer) GetTxn(ww http.ResponseWriter, req *http.Request) { copy(txnHash[:], txnHashBytes) } - txnFound := fes.backendServer.GetMempool().IsTransactionInPool(txnHash) - if !txnFound { + txnFound := false + txnStatus := requestData.TxnStatus + if txnStatus == "" { + txnStatus = TxnStatusUnconfirmed + } + switch txnStatus { + case TxnStatusUnconfirmed: + txnFound = fes.backendServer.GetMempool().IsTransactionInPool(txnHash) + if !txnFound { + txnFound = lib.DbCheckTxnExistence(fes.TXIndex.TXIndexChain.DB(), nil, txnHash) + } + case TxnStatusConfirmed: + // In this case we will not consider a txn until it shows up in txindex, which means that + // it is confirmed. txnFound = lib.DbCheckTxnExistence(fes.TXIndex.TXIndexChain.DB(), nil, txnHash) + default: + _AddBadRequestError(ww, fmt.Sprintf("GetTxn: Invalid TxnStatus: %v. Options are "+ + "{unconfirmed, confirmed}", txnStatus)) + return } + res := &GetTxnResponse{ TxnFound: txnFound, } @@ -3231,8 +3260,8 @@ func (fes *APIServer) getBuyingAndSellingDAOCoinPublicKeys( buyingDAOCoinCreatorPublicKeyBase58Check string, sellingDAOCoinCreatorPublicKeyBase58Check string, ) ([]byte, []byte, error) { - if sellingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString && - buyingDAOCoinCreatorPublicKeyBase58Check == DESOCoinIdentifierString { + if IsDesoPkid(sellingDAOCoinCreatorPublicKeyBase58Check) && + IsDesoPkid(buyingDAOCoinCreatorPublicKeyBase58Check) { return nil, nil, errors.Errorf("'DESO' specified for both the " + "coin to buy and the coin to sell. At least one must specify a valid DAO public key whose coin " + "will be bought or sold") @@ -3243,14 +3272,14 @@ func (fes *APIServer) getBuyingAndSellingDAOCoinPublicKeys( var err error - if buyingDAOCoinCreatorPublicKeyBase58Check != DESOCoinIdentifierString { + if !IsDesoPkid(buyingDAOCoinCreatorPublicKeyBase58Check) { buyingCoinPublicKey, err = GetPubKeyBytesFromBase58Check(buyingDAOCoinCreatorPublicKeyBase58Check) if err != nil { return nil, nil, err } } - if sellingDAOCoinCreatorPublicKeyBase58Check != DESOCoinIdentifierString { + if !IsDesoPkid(sellingDAOCoinCreatorPublicKeyBase58Check) { sellingCoinPublicKey, err = GetPubKeyBytesFromBase58Check(sellingDAOCoinCreatorPublicKeyBase58Check) if err != nil { return nil, nil, err