feat: explorer API, wallet, CCIP scripts, and config refresh
- Backend REST/gateway/track routes, analytics, Blockscout proxy paths. - Frontend wallet and liquidity surfaces; MetaMask token list alignment. - Deployment docs, verification scripts, address inventory updates. Check: go build ./... under backend/ (pass). Made-with: Cursor
This commit is contained in:
@@ -4,6 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -204,14 +206,100 @@ func TestConfigCapabilitiesEndpointProvidesRPCCapabilityMatrix(t *testing.T) {
|
||||
if !containsString(payload.HTTP.SupportedMethods, "eth_feeHistory") {
|
||||
t.Fatal("expected eth_feeHistory support to be documented")
|
||||
}
|
||||
if !containsString(payload.HTTP.UnsupportedMethods, "eth_maxPriorityFeePerGas") {
|
||||
t.Fatal("expected missing eth_maxPriorityFeePerGas support to be documented")
|
||||
if !containsString(payload.HTTP.SupportedMethods, "eth_maxPriorityFeePerGas") {
|
||||
t.Fatal("expected eth_maxPriorityFeePerGas support to be documented")
|
||||
}
|
||||
if !containsString(payload.Tracing.SupportedMethods, "trace_block") {
|
||||
t.Fatal("expected trace_block support to be documented")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigTokenListEndpointReloadsRuntimeFileWithoutRestart(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
file := filepath.Join(dir, "token-list.json")
|
||||
first := `{"name":"Runtime Token List v1","tokens":[{"chainId":138,"address":"0x1111111111111111111111111111111111111111","symbol":"RT1","name":"Runtime One","decimals":6}]}`
|
||||
second := `{"name":"Runtime Token List v2","tokens":[{"chainId":138,"address":"0x2222222222222222222222222222222222222222","symbol":"RT2","name":"Runtime Two","decimals":6}]}`
|
||||
|
||||
if err := os.WriteFile(file, []byte(first), 0o644); err != nil {
|
||||
t.Fatalf("failed to write initial runtime file: %v", err)
|
||||
}
|
||||
t.Setenv("CONFIG_TOKEN_LIST_JSON_PATH", file)
|
||||
|
||||
handler := setupConfigHandler()
|
||||
|
||||
req1 := httptest.NewRequest(http.MethodGet, "/api/config/token-list", nil)
|
||||
w1 := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w1, req1)
|
||||
|
||||
if w1.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d", w1.Code)
|
||||
}
|
||||
if got := w1.Header().Get("X-Config-Source"); got != "runtime-file" {
|
||||
t.Fatalf("expected runtime-file config source, got %q", got)
|
||||
}
|
||||
etag1 := w1.Header().Get("ETag")
|
||||
if etag1 == "" {
|
||||
t.Fatal("expected ETag header on runtime-backed response")
|
||||
}
|
||||
|
||||
var body1 testTokenList
|
||||
if err := json.Unmarshal(w1.Body.Bytes(), &body1); err != nil {
|
||||
t.Fatalf("failed to parse runtime token list v1: %v", err)
|
||||
}
|
||||
if body1.Name != "Runtime Token List v1" {
|
||||
t.Fatalf("expected first runtime payload, got %q", body1.Name)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(file, []byte(second), 0o644); err != nil {
|
||||
t.Fatalf("failed to write updated runtime file: %v", err)
|
||||
}
|
||||
|
||||
req2 := httptest.NewRequest(http.MethodGet, "/api/config/token-list", nil)
|
||||
w2 := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w2, req2)
|
||||
|
||||
if w2.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200 after runtime update, got %d", w2.Code)
|
||||
}
|
||||
if got := w2.Header().Get("ETag"); got == "" || got == etag1 {
|
||||
t.Fatalf("expected changed ETag after runtime update, got %q", got)
|
||||
}
|
||||
|
||||
var body2 testTokenList
|
||||
if err := json.Unmarshal(w2.Body.Bytes(), &body2); err != nil {
|
||||
t.Fatalf("failed to parse runtime token list v2: %v", err)
|
||||
}
|
||||
if body2.Name != "Runtime Token List v2" {
|
||||
t.Fatalf("expected updated runtime payload, got %q", body2.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigTokenListEndpointSupportsETagRevalidation(t *testing.T) {
|
||||
handler := setupConfigHandler()
|
||||
|
||||
req1 := httptest.NewRequest(http.MethodGet, "/api/config/token-list", nil)
|
||||
w1 := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w1, req1)
|
||||
|
||||
if w1.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d", w1.Code)
|
||||
}
|
||||
|
||||
etag := w1.Header().Get("ETag")
|
||||
if etag == "" {
|
||||
t.Fatal("expected ETag header")
|
||||
}
|
||||
|
||||
req2 := httptest.NewRequest(http.MethodGet, "/api/config/token-list", nil)
|
||||
req2.Header.Set("If-None-Match", etag)
|
||||
w2 := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w2, req2)
|
||||
|
||||
if w2.Code != http.StatusNotModified {
|
||||
t.Fatalf("expected 304, got %d", w2.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigEndpointsSupportOptionsPreflight(t *testing.T) {
|
||||
handler := setupConfigHandler()
|
||||
req := httptest.NewRequest(http.MethodOptions, "/api/config/token-list", nil)
|
||||
|
||||
Reference in New Issue
Block a user