Skip to content

Commit 654bdee

Browse files
author
miko
committed
Check result from CU.
Split USDC tip checking to multiple functions Minor possibly temp changes to detecting tip type
1 parent a858f3e commit 654bdee

File tree

1 file changed

+158
-59
lines changed

1 file changed

+158
-59
lines changed

server/services/v1/comments/create.go

+158-59
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ var specialLogFile *os.File
4848
// Temp variable to allow testing
4949
var useOldTipAmountChecks bool
5050

51+
// Not sure where to put this
52+
var wUsdcPid = "7zH9dlMNoxprab9loshv3Y7WG45DOny_Vrq9KrXObdQ"
53+
5154
func init() {
5255
var err error
5356
specialLogFile, err = os.OpenFile("special.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
@@ -89,22 +92,25 @@ func create(_ *http.Request, args *commentapi.CreateArgs, reply *commentapi.Crea
8992
useOldTipAmountChecks = args.Amount == nil
9093

9194
var frequencyCheck = checkFrequency
92-
if args.SupportTxID != nil || args.PaymentIntentID != nil || args.Currency != nil {
95+
if args.SupportTxID != nil || args.PaymentIntentID != nil {
9396
if args.DryRun {
9497
if args.Amount != nil {
9598
if args.PaymentIntentID != nil {
9699
cents := uint64(*args.Amount * 100)
97100
request.comment.Amount.SetValid(cents)
98-
} else if args.SupportTxID != nil {
99-
lbc, err := btcutil.NewAmount(*args.Amount)
100-
if err != nil {
101-
return errors.Err(err)
101+
} else if args.SupportTxID != nil && args.Currency != nil {
102+
switch *args.Currency {
103+
case "USDC":
104+
cents := uint64(*args.Amount * 100)
105+
request.comment.Amount.SetValid(cents)
106+
request.comment.Currency.SetValid(*args.Currency)
107+
case "LBC":
108+
lbc, err := btcutil.NewAmount(*args.Amount)
109+
if err != nil {
110+
return errors.Err(err)
111+
}
112+
request.comment.Amount.SetValid(uint64(lbc.ToUnit(btcutil.AmountSatoshi)))
102113
}
103-
request.comment.Amount.SetValid(uint64(lbc.ToUnit(btcutil.AmountSatoshi)))
104-
} else if *args.Currency == "USDC" {
105-
cents := uint64(*args.Amount * 100)
106-
request.comment.Amount.SetValid(cents)
107-
request.comment.Currency.SetValid(*args.Currency)
108114
}
109115
}
110116
} else {
@@ -633,7 +639,7 @@ func checkSettings(settings *m.CreatorSetting, request *createRequest) error {
633639
}
634640
} else {
635641
if !request.comment.Amount.IsZero() {
636-
if request.args.PaymentIntentID == nil && request.args.Currency == nil {
642+
if request.args.PaymentIntentID == nil && (request.args.Currency == nil || *request.args.Currency != "USDC") {
637643
err = checkMinTipAmountSuperChat(settings, request)
638644
} else {
639645
err = checkMinUsdcTipAmountSuperChat(settings, request)
@@ -646,7 +652,7 @@ func checkSettings(settings *m.CreatorSetting, request *createRequest) error {
646652
if request.comment.Amount.IsZero() {
647653
return api.StatusError{Err: errors.Err("you must include tip in order to comment as required by creator"), Status: http.StatusBadRequest}
648654
}
649-
if request.args.PaymentIntentID == nil && request.args.Currency == nil {
655+
if request.args.PaymentIntentID == nil && (request.args.Currency == nil || *request.args.Currency != "USDC") {
650656
err = checkMinTipAmountComment(settings, request)
651657
} else {
652658
err = checkMinUsdcTipAmountComment(settings, request)
@@ -751,7 +757,85 @@ func getCounter(key string, expiration time.Duration) (*counter.Counter, error)
751757
return creatorCounter, nil
752758
}
753759

754-
func handleUsdcTip(request *createRequest) {
760+
type tag struct {
761+
Name string `json:"name"`
762+
Value string `json:"value"`
763+
}
764+
765+
type cuResultResponse struct {
766+
Messages []struct {
767+
Data string `json:"Data"`
768+
Target string `json:"Target "`
769+
Anchor string `json:"Anchor "`
770+
Tags []tag `json:"Tags"`
771+
Sags []tag `json:"Sags"`
772+
} `json:"Messages"`
773+
Assignments []struct{} `json:"Assignments"`
774+
Spawns []struct{} `json:"Spawns"`
775+
Output []struct{} `json:"Output"`
776+
GasUsed int `json:"GasUsed"`
777+
}
778+
779+
func getResultFromCu(txID, pID string, timeout int) (cuResultResponse, error) {
780+
cuEndPoint := fmt.Sprintf(`https://cu.ao-testnet.xyz/result/%s?process-id=%s`, txID, pID)
781+
var cuResp cuResultResponse
782+
783+
client := &http.Client{
784+
Timeout: time.Duration(timeout) * time.Second,
785+
}
786+
resp, err := client.Get(cuEndPoint)
787+
if err != nil {
788+
return cuResp, errors.Err("request failed: %w", err)
789+
}
790+
791+
defer helper.CloseBody(resp.Body)
792+
793+
if resp.StatusCode != http.StatusOK {
794+
return cuResp, errors.Err("Request failed with status %s", resp.Status)
795+
}
796+
797+
if err := json.NewDecoder(resp.Body).Decode(&cuResp); err != nil {
798+
return cuResp, errors.Err("failed to decode response: %w", err)
799+
}
800+
801+
return cuResp, nil
802+
}
803+
804+
func checkCuResult(result cuResultResponse) error {
805+
tagFound := false
806+
if len(result.Messages) == 0 {
807+
return errors.Err("No result messages")
808+
}
809+
message := result.Messages[0]
810+
for _, v := range message.Tags {
811+
if v.Value == "Debit-Notice" || v.Value == "Credit-Notice" {
812+
tagFound = true
813+
break
814+
}
815+
}
816+
if !tagFound {
817+
return errors.Err("Credit-Notice or Depit-Notice tag not found in first result message")
818+
}
819+
820+
return nil
821+
}
822+
823+
type graphQLRespData struct {
824+
Transactions struct {
825+
Edges []struct {
826+
Node struct {
827+
ID string `json:"id"`
828+
Recipient string `json:"recipient"`
829+
Owner struct {
830+
Address string `json:"address"`
831+
} `json:"owner"`
832+
Tags []tag `json:"Tags"`
833+
} `json:"node"`
834+
} `json:"edges"`
835+
} `json:"transactions"`
836+
}
837+
838+
func getSupportTxFromGraphQL(request *createRequest) (graphQLRespData, error) {
755839
client := graphql.NewClient("https://arweave.net/graphql")
756840

757841
query := `
@@ -776,40 +860,16 @@ func handleUsdcTip(request *createRequest) {
776860
}
777861
`
778862

779-
req := graphql.NewRequest(query)
780-
781-
if request.args.SupportTxID == nil {
782-
logrus.Error(fmt.Sprintf("Can't verify the tip, support txid not given. CommentID: %s", request.comment.CommentID))
783-
return
784-
}
785-
defaultErrorInfo := fmt.Sprintf("TxID: %s CommentID: %s", *request.args.SupportTxID, request.comment.CommentID)
863+
var respData graphQLRespData
786864

787865
err := checkForDuplicateTxID(*request.args.SupportTxID)
788866
if err != nil {
789-
logrus.Error(fmt.Sprintf("%v %s", err.Error(), defaultErrorInfo))
867+
return respData, errors.Err("%v", err.Error())
790868
}
791869

870+
req := graphql.NewRequest(query)
792871
req.Var("ids", []string{*request.args.SupportTxID})
793872

794-
var respData struct {
795-
Transactions struct {
796-
Edges []struct {
797-
Node struct {
798-
ID string `json:"id"`
799-
Recipient string `json:"recipient"`
800-
Owner struct {
801-
Address string `json:"address"`
802-
} `json:"owner"`
803-
Tags []struct {
804-
Name string `json:"name"`
805-
Value string `json:"value"`
806-
} `json:"Tags"`
807-
} `json:"node"`
808-
} `json:"edges"`
809-
} `json:"transactions"`
810-
}
811-
812-
amount := request.comment.Amount.Uint64
813873
triesLeft := 2
814874
for triesLeft > 0 {
815875
triesLeft--
@@ -822,30 +882,32 @@ func handleUsdcTip(request *createRequest) {
822882
if len(respData.Transactions.Edges) == 0 {
823883
logrus.Error(fmt.Sprintf("Tx for id %s not found", *request.args.SupportTxID))
824884
}
825-
// If tx can't be found let it pass (assume a delay with gateway indexing)
826-
request.comment.Amount.SetValid(amount)
827-
request.comment.Currency.SetValid(*request.args.Currency)
828-
return
885+
return respData, nil
829886
}
830887
time.Sleep(3 * time.Second)
831888
}
832889

890+
return respData, nil
891+
}
892+
893+
func checkSupportTxAndGetAmount(request *createRequest, respData *graphQLRespData) (uint64, error) {
894+
amount := request.comment.Amount.Uint64
895+
833896
if len(respData.Transactions.Edges[0].Node.Tags) == 0 {
834-
logrus.Error(fmt.Sprintf("No tags found. %s", defaultErrorInfo))
897+
return amount, errors.Err("No tags found. %s")
835898
}
836899

837-
wUsdcPid := "7zH9dlMNoxprab9loshv3Y7WG45DOny_Vrq9KrXObdQ"
838900
if respData.Transactions.Edges[0].Node.Recipient != wUsdcPid {
839-
logrus.Error(fmt.Sprintf("Expected recipient %s, got %s. %s", wUsdcPid, respData.Transactions.Edges[0].Node.Recipient, defaultErrorInfo))
901+
return amount, errors.Err("Expected recipient %s, got %s. %s", wUsdcPid, respData.Transactions.Edges[0].Node.Recipient)
840902
}
841903

842904
if request.args.Owner != nil {
843905
foundOwner := respData.Transactions.Edges[0].Node.Owner.Address
844906
if foundOwner != *request.args.Owner {
845-
logrus.Error(fmt.Sprintf("Expected Owner %s, got %s. %s", *request.args.Owner, foundOwner, defaultErrorInfo))
907+
return amount, errors.Err("Expected Owner %s, got %s. %s", *request.args.Owner, foundOwner)
846908
}
847909
} else {
848-
logrus.Error(fmt.Sprintf("Given nil Owner. %s", defaultErrorInfo))
910+
return amount, errors.Err("Given nil Owner. %s")
849911
}
850912

851913
tagsLeftToCheck := []string{"Action", "Quantity", "Recipient", "TimeStamp", "Signature", "SignatureTS"}
@@ -856,36 +918,36 @@ func handleUsdcTip(request *createRequest) {
856918
switch tag.Name {
857919
case "Action":
858920
if tag.Value != "Transfer" {
859-
logrus.Error(fmt.Sprintf("Action not Transfer. %s", defaultErrorInfo))
921+
return amount, errors.Err("Action not Transfer. %s")
860922
}
861923
case "Quantity":
862924
quantity, err := strconv.Atoi(tag.Value)
863925
if err != nil {
864-
logrus.Error(fmt.Sprintf("Failed to parse Quantity %v. %s", err.Error(), defaultErrorInfo))
926+
return amount, errors.Err("Failed to parse Quantity %v. %s", err.Error())
865927
}
866928
quantityCents := uint64(quantity / 10000)
867929
amount = quantityCents
868930
if quantityCents != request.comment.Amount.Uint64 {
869-
logrus.Error(fmt.Sprintf("Quantity amount mismatch. Expected %d, got %d. %s", request.comment.Amount.Uint64, quantityCents, defaultErrorInfo))
931+
return amount, errors.Err("Quantity amount mismatch. Expected %d, got %d. %s", request.comment.Amount.Uint64, quantityCents)
870932
}
871933
case "Recipient":
872934
if request.args.Recipient != nil {
873935
if tag.Value != *request.args.Recipient {
874-
logrus.Error(fmt.Sprintf("Transfer recipient mismatch. Expected %s, got %s. %s", *request.args.Recipient, tag.Value, defaultErrorInfo))
936+
return amount, errors.Err("Transfer recipient mismatch. Expected %s, got %s. %s", *request.args.Recipient, tag.Value)
875937
}
876938
} else {
877-
logrus.Error(fmt.Sprintf("Given nil Transfer Recipient. %s", defaultErrorInfo))
939+
return amount, errors.Err("Given nil Transfer Recipient. %s")
878940
}
879941
case "TimeStamp":
880942
allowedTimeDifference, _ := time.ParseDuration("5m")
881943
timeStamp, err := strconv.Atoi(tag.Value)
882944
if err != nil {
883-
logrus.Error(fmt.Sprintf("Failed to parse timestamp %v. %s", err.Error(), defaultErrorInfo))
945+
return amount, errors.Err("Failed to parse timestamp %v. %s", err.Error())
884946
}
885947
deltaMs := math.Abs(float64(int64(timeStamp) - time.Now().UnixMilli()))
886948
if int64(deltaMs) > allowedTimeDifference.Milliseconds() {
887949
parsedDelta, _ := time.ParseDuration(fmt.Sprintf("%dms", int64(deltaMs)))
888-
logrus.Error(fmt.Sprintf("Timestamp %d over allowed difference of %dm, difference %dm. %s", timeStamp, int64(allowedTimeDifference.Minutes()), int64(parsedDelta.Minutes()), defaultErrorInfo))
950+
return amount, errors.Err("Timestamp %d over allowed difference of %dm, difference %dm. %s", timeStamp, int64(allowedTimeDifference.Minutes()), int64(parsedDelta.Minutes()))
889951
}
890952
case "Signature":
891953
signature = tag.Value
@@ -900,13 +962,50 @@ func handleUsdcTip(request *createRequest) {
900962
}
901963
}
902964

903-
err = lbry.ValidateSignatureAndTS(request.args.ChannelID, signature, signatureTS, request.args.ChannelName)
965+
err := lbry.ValidateSignatureAndTS(request.args.ChannelID, signature, signatureTS, request.args.ChannelName)
904966
if err != nil {
905-
logrus.Error(fmt.Sprintf("%v %s", errors.Prefix("could not authenticate channel signature:", err), defaultErrorInfo))
967+
return amount, errors.Err("%v %s", errors.Prefix("could not authenticate channel signature:", err))
906968
}
907969

908970
if len(tagsLeftToCheck) != 0 {
909-
logrus.Error(fmt.Sprintf("Didn't found tags %v from the tx. %s", tagsLeftToCheck, defaultErrorInfo))
971+
return amount, errors.Err("Didn't found tags %v from the tx. %s", tagsLeftToCheck)
972+
}
973+
974+
return amount, nil
975+
976+
}
977+
978+
func handleUsdcTip(request *createRequest) {
979+
if request.args.SupportTxID == nil {
980+
logrus.Error(fmt.Sprintf("Can't verify the tip, support txid not given. CommentID: %s", request.comment.CommentID))
981+
return
982+
}
983+
defaultErrorInfo := fmt.Sprintf("TxID: %s CommentID: %s", *request.args.SupportTxID, request.comment.CommentID)
984+
985+
respData, err := getSupportTxFromGraphQL(request)
986+
if err != nil {
987+
logrus.Error(fmt.Sprintf("%v %s", err, defaultErrorInfo))
988+
}
989+
if len(respData.Transactions.Edges) == 0 {
990+
// If tx can't be found let it pass (assume a delay with gateway indexing)
991+
request.comment.Amount.SetValid(request.comment.Amount.Uint64)
992+
request.comment.Currency.SetValid(*request.args.Currency)
993+
return
994+
}
995+
996+
amount, err := checkSupportTxAndGetAmount(request, &respData)
997+
if err != nil {
998+
logrus.Error(fmt.Sprintf("%v %s", err, defaultErrorInfo))
999+
}
1000+
1001+
timeout := 2
1002+
result, err := getResultFromCu(*request.args.SupportTxID, wUsdcPid, timeout)
1003+
if err != nil {
1004+
logrus.Error(fmt.Sprintf("%v %s", err, defaultErrorInfo))
1005+
}
1006+
err = checkCuResult(result)
1007+
if err != nil {
1008+
logrus.Error(fmt.Sprintf("%v %s", err, defaultErrorInfo))
9101009
}
9111010

9121011
request.comment.Amount.SetValid(amount)

0 commit comments

Comments
 (0)