From 79c2f513c314c15c8978f2237e662012998e3c28 Mon Sep 17 00:00:00 2001 From: Jonny Spicer Date: Mon, 16 Feb 2026 17:29:13 +1300 Subject: [PATCH] feat: add resolution fields to Answer struct Add Resolution, ResolutionTime, ResolutionProbability, and ResolverId fields to the Answer struct so callers can determine whether individual answers in multi-choice markets have been resolved. Fixes #11 Co-Authored-By: Claude Opus 4.6 --- api_test.go | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++ market.go | 6 ++- 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/api_test.go b/api_test.go index 468444a..a913aa3 100644 --- a/api_test.go +++ b/api_test.go @@ -696,6 +696,159 @@ func TestAwardBounty(t *testing.T) { } } +func TestAnswerResolutionFields(t *testing.T) { + t.Run("with resolution fields", func(t *testing.T) { + data := `{ + "id": "ans1", + "username": "testuser", + "name": "Test User", + "userId": "user1", + "createdTime": 1700000000000, + "avatarUrl": "https://example.com/avatar.png", + "number": 1, + "contractId": "contract1", + "text": "Answer text", + "probability": 0.5, + "resolution": "CANCEL", + "resolutionTime": 1700763039000, + "resolutionProbability": 0.764, + "resolverId": "abc123" + }` + + var answer Answer + if err := json.Unmarshal([]byte(data), &answer); err != nil { + t.Fatalf("failed to unmarshal: %v", err) + } + + if answer.Resolution != "CANCEL" { + t.Errorf("expected resolution 'CANCEL', got '%s'", answer.Resolution) + } + if answer.ResolutionTime != 1700763039000 { + t.Errorf("expected resolutionTime 1700763039000, got %d", answer.ResolutionTime) + } + if answer.ResolutionProbability != 0.764 { + t.Errorf("expected resolutionProbability 0.764, got %f", answer.ResolutionProbability) + } + if answer.ResolverId != "abc123" { + t.Errorf("expected resolverId 'abc123', got '%s'", answer.ResolverId) + } + }) + + t.Run("without resolution fields", func(t *testing.T) { + data := `{ + "id": "ans2", + "username": "testuser", + "name": "Test User", + "userId": "user1", + "createdTime": 1700000000000, + "avatarUrl": "https://example.com/avatar.png", + "number": 2, + "contractId": "contract1", + "text": "Unresolved answer", + "probability": 0.3 + }` + + var answer Answer + if err := json.Unmarshal([]byte(data), &answer); err != nil { + t.Fatalf("failed to unmarshal: %v", err) + } + + if answer.Resolution != "" { + t.Errorf("expected empty resolution, got '%s'", answer.Resolution) + } + if answer.ResolutionTime != 0 { + t.Errorf("expected zero resolutionTime, got %d", answer.ResolutionTime) + } + if answer.ResolutionProbability != 0 { + t.Errorf("expected zero resolutionProbability, got %f", answer.ResolutionProbability) + } + if answer.ResolverId != "" { + t.Errorf("expected empty resolverId, got '%s'", answer.ResolverId) + } + }) +} + +func TestFullMarketWithResolvedAnswers(t *testing.T) { + expected := FullMarket{ + Id: "market1", + Question: "Multi-choice market?", + OutcomeType: MultipleChoice, + Mechanism: "cpmm-multi-1", + Answers: []Answer{ + { + Id: "ans1", + Username: "resolver", + Name: "Resolver User", + UserId: "resolver1", + CreatedTime: 1700000000000, + AvatarUrl: "https://example.com/avatar.png", + Number: 1, + ContractId: "market1", + Text: "Option A", + Probability: 0.0, + Resolution: "YES", + ResolutionTime: 1700763039000, + ResolutionProbability: 1.0, + ResolverId: "resolver1", + }, + { + Id: "ans2", + Username: "resolver", + Name: "Resolver User", + UserId: "resolver1", + CreatedTime: 1700000000000, + AvatarUrl: "https://example.com/avatar.png", + Number: 2, + ContractId: "market1", + Text: "Option B", + Probability: 0.5, + }, + }, + } + + handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(expected) + }) + + server := httptest.NewServer(handler) + defer server.Close() + + mc := ClientInstance(server.Client(), &server.URL, &testKey) + defer mc.Destroy() + + result, err := mc.GetMarketByID("market1") + if err != nil { + t.Fatalf("error getting market: %v", err) + } + + if len(result.Answers) != 2 { + t.Fatalf("expected 2 answers, got %d", len(result.Answers)) + } + + resolved := result.Answers[0] + if resolved.Resolution != "YES" { + t.Errorf("expected resolution 'YES', got '%s'", resolved.Resolution) + } + if resolved.ResolutionTime != 1700763039000 { + t.Errorf("expected resolutionTime 1700763039000, got %d", resolved.ResolutionTime) + } + if resolved.ResolutionProbability != 1.0 { + t.Errorf("expected resolutionProbability 1.0, got %f", resolved.ResolutionProbability) + } + if resolved.ResolverId != "resolver1" { + t.Errorf("expected resolverId 'resolver1', got '%s'", resolved.ResolverId) + } + + unresolved := result.Answers[1] + if unresolved.Resolution != "" { + t.Errorf("expected empty resolution on unresolved answer, got '%s'", unresolved.Resolution) + } + if unresolved.ResolutionTime != 0 { + t.Errorf("expected zero resolutionTime on unresolved answer, got %d", unresolved.ResolutionTime) + } +} + func TestGetLeagues(t *testing.T) { expected := []LeagueEntry{ {UserId: "user1", Season: 1, Division: 3, ManaEarned: 500}, diff --git a/market.go b/market.go index 5c589b1..8815001 100644 --- a/market.go +++ b/market.go @@ -32,7 +32,11 @@ type Answer struct { Number int64 `json:"number"` ContractId string `json:"contractId"` Text string `json:"text"` - Probability float64 `json:"probability"` + Probability float64 `json:"probability"` + Resolution string `json:"resolution,omitempty"` + ResolutionTime int64 `json:"resolutionTime,omitempty"` + ResolutionProbability float64 `json:"resolutionProbability,omitempty"` + ResolverId string `json:"resolverId,omitempty"` } // GetMarketsRequest represents the optional parameters that can be supplied to