forked from stellar/go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
83 lines (69 loc) · 2.44 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package ethereum
import (
"context"
"math/big"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stellar/go/support/errors"
"github.com/stellar/go/support/log"
"github.com/tyler-smith/go-bip32"
)
var (
ten = big.NewInt(10)
eighteen = big.NewInt(18)
// weiInEth = 10^18
weiInEth = new(big.Rat).SetInt(new(big.Int).Exp(ten, eighteen, nil))
)
// Listener listens for transactions using geth RPC. It calls TransactionHandler for each new
// transactions. It will reprocess the block if TransactionHandler returns error. It will
// start from the block number returned from Storage.GetEthereumBlockToProcess or the latest block
// if it returned 0. Transactions can be processed more than once, it's TransactionHandler
// responsibility to ignore duplicates.
// You can run multiple Listeners if Storage is implemented correctly.
// Listener ignores contract creation transactions.
// Listener requires geth 1.7.0.
type Listener struct {
Enabled bool
Client Client `inject:""`
Storage Storage `inject:""`
NetworkID string
TransactionHandler TransactionHandler
log *log.Entry
}
type Client interface {
NetworkID(ctx context.Context) (*big.Int, error)
BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error)
}
// Storage is an interface that must be implemented by an object using
// persistent storage.
type Storage interface {
// GetEthereumBlockToProcess gets the number of Ethereum block to process. `0` means the
// processing should start from the current block.
GetEthereumBlockToProcess() (uint64, error)
// SaveLastProcessedEthereumBlock should update the number of the last processed Ethereum
// block. It should only update the block if block > current block in atomic transaction.
SaveLastProcessedEthereumBlock(block uint64) error
}
type TransactionHandler func(transaction Transaction) error
type Transaction struct {
Hash string
// Value in Wei
ValueWei *big.Int
To string
}
type AddressGenerator struct {
masterPublicKey *bip32.Key
}
func EthToWei(eth string) (*big.Int, error) {
valueRat := new(big.Rat)
_, ok := valueRat.SetString(eth)
if !ok {
return nil, errors.New("Could not convert to *big.Rat")
}
// Calculate value in Wei
valueRat.Mul(valueRat, weiInEth)
// Ensure denominator is equal `1`
if valueRat.Denom().Cmp(big.NewInt(1)) != 0 {
return nil, errors.New("Invalid precision, is value smaller than 1 Wei?")
}
return valueRat.Num(), nil
}