Skip to content

Commit 391edd6

Browse files
committed
fix: crash on receiving malformed Alchemy input
1 parent 1d00302 commit 391edd6

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

services/wallet/bigint/var_hex_big_int.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ func (b *VarHexBigInt) UnmarshalJSON(input []byte) error {
1717
return err
1818
}
1919

20+
//prevent crash on incorrect input
21+
if len(hexStr) < 2 || hexStr[0:2] != "0x" {
22+
return fmt.Errorf("hex string too short (len=%d): %q", len(hexStr), hexStr)
23+
}
24+
2025
var ok bool
2126
b.Int, ok = new(big.Int).SetString(hexStr[2:], 16)
2227
if !ok {

services/wallet/thirdparty/activity/alchemy/types.go

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package alchemy
22

33
import (
4+
"encoding/json"
45
"fmt"
6+
"math/big"
57
"time"
68

79
"github.com/ethereum/go-ethereum/common"
@@ -14,6 +16,35 @@ import (
1416
const getAssetTransfersMethod = "alchemy_getAssetTransfers"
1517
const MaxAssetTransfersCount = 1000
1618

19+
// AlchemyBigInt wraps VarHexBigInt to handle Alchemy API inconsistency
20+
// it sometimes returns plain decimal numbers instead of hexadecimal
21+
type AlchemyBigInt struct {
22+
*bigint.VarHexBigInt
23+
}
24+
25+
func (a *AlchemyBigInt) UnmarshalJSON(data []byte) error {
26+
var str string
27+
if err := json.Unmarshal(data, &str); err != nil {
28+
return err
29+
}
30+
31+
// alchemy sometimes returns plain numbers like "0" or "1" without "0x" prefix
32+
// so we need to take this into account
33+
if len(str) >= 2 && str[0:2] == "0x" {
34+
// hex string case
35+
a.VarHexBigInt = &bigint.VarHexBigInt{}
36+
return a.VarHexBigInt.UnmarshalJSON(data)
37+
} else {
38+
// plain decimal number
39+
val := new(big.Int)
40+
if _, ok := val.SetString(str, 10); !ok {
41+
return fmt.Errorf("invalid decimal number: %s", str)
42+
}
43+
a.VarHexBigInt = &bigint.VarHexBigInt{Int: val}
44+
return nil
45+
}
46+
}
47+
1748
type TransferCategory string
1849

1950
const (
@@ -58,7 +89,7 @@ type Transfer struct {
5889
ToAddress *common.Address `json:"to,omitempty"`
5990
Value float64 `json:"value,omitempty"`
6091
Erc1155Metadata []Erc1155Metadata `json:"erc1155Metadata,omitempty"`
61-
TokenID *bigint.VarHexBigInt `json:"tokenId"`
92+
TokenID *AlchemyBigInt `json:"tokenId"`
6293
Asset string `json:"asset"`
6394
UniqueID string `json:"uniqueId"`
6495
Hash common.Hash `json:"hash"`
@@ -79,7 +110,7 @@ func (t Transfer) IsIncoming(accountAddress common.Address) bool {
79110
}
80111

81112
type Erc1155Metadata struct {
82-
TokenID *bigint.VarHexBigInt `json:"tokenId"`
113+
TokenID *AlchemyBigInt `json:"tokenId"`
83114
Value *bigint.VarHexBigInt `json:"value"`
84115
}
85116

0 commit comments

Comments
 (0)