Compare commits
4 Commits
loginpage-
...
frontend-f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b228d9b57 | ||
|
|
08bc3e1ea2 | ||
|
|
a091d39c08 | ||
|
|
35699a41bd |
@@ -19,11 +19,13 @@ const (
|
|||||||
rpcTimeoutMS = 30000
|
rpcTimeoutMS = 30000
|
||||||
rpcMaxRetries = 3
|
rpcMaxRetries = 3
|
||||||
rpcRetryBaseMS = 2000
|
rpcRetryBaseMS = 2000
|
||||||
|
rpcMinIntervalMS = 1000
|
||||||
)
|
)
|
||||||
|
|
||||||
type JsonRpcEthereum struct {
|
type JsonRpcEthereum struct {
|
||||||
rpcURL string
|
rpcURL string
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
lastCallAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJsonRpcEthereum(rpcURL string) (*JsonRpcEthereum, error) {
|
func NewJsonRpcEthereum(rpcURL string) (*JsonRpcEthereum, error) {
|
||||||
@@ -58,6 +60,8 @@ type rpcError struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (j *JsonRpcEthereum) callRPC(ctx context.Context, method string, params ...interface{}) (json.RawMessage, error) {
|
func (j *JsonRpcEthereum) callRPC(ctx context.Context, method string, params ...interface{}) (json.RawMessage, error) {
|
||||||
|
j.throttle(ctx)
|
||||||
|
|
||||||
if params == nil {
|
if params == nil {
|
||||||
params = []interface{}{}
|
params = []interface{}{}
|
||||||
}
|
}
|
||||||
@@ -72,7 +76,25 @@ func (j *JsonRpcEthereum) callRPC(ctx context.Context, method string, params ...
|
|||||||
return nil, fmt.Errorf("marshal RPC request: %w", err)
|
return nil, fmt.Errorf("marshal RPC request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return j.callWithRetry(ctx, method, body)
|
result, callErr := j.callWithRetry(ctx, method, body)
|
||||||
|
j.lastCallAt = time.Now()
|
||||||
|
|
||||||
|
return result, callErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JsonRpcEthereum) throttle(ctx context.Context) {
|
||||||
|
if j.lastCallAt.IsZero() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
minInterval := time.Duration(rpcMinIntervalMS) * time.Millisecond
|
||||||
|
elapsed := time.Since(j.lastCallAt)
|
||||||
|
if elapsed >= minInterval {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-time.After(minInterval - elapsed):
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// callWithRetry executes a JSON-RPC POST with exponential backoff on transient errors.
|
// callWithRetry executes a JSON-RPC POST with exponential backoff on transient errors.
|
||||||
|
|||||||
BIN
backend/poller
Executable file
BIN
backend/poller
Executable file
Binary file not shown.
@@ -79,6 +79,18 @@
|
|||||||
animation-delay: 3s;
|
animation-delay: 3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login-tagline {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
max-width: 630px;
|
||||||
|
margin: 5rem auto 0;
|
||||||
|
padding-left: 2rem;
|
||||||
|
font-style: italic;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
.login-interactive-fadein {
|
.login-interactive-fadein {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
animation: fadeIn 2s ease-in-out forwards;
|
animation: fadeIn 2s ease-in-out forwards;
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ export default function Login() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p className="login-tagline login-card-fadein">
|
||||||
|
A lightweight, on-chain monitoring system giving users real-time
|
||||||
|
situational awareness over blockchain addresses.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user