@@ -3,6 +3,7 @@ package main
3
3
import (
4
4
"errors"
5
5
"fmt"
6
+ "strconv"
6
7
"time"
7
8
8
9
"github.com/ethereum/go-ethereum/cmd/utils"
@@ -15,13 +16,19 @@ import (
15
16
"github.com/ethereum/go-ethereum/rpc"
16
17
"github.com/ethereum/go-ethereum/xeth"
17
18
"github.com/robertkrimen/otto"
19
+ "gopkg.in/fatih/set.v0"
18
20
)
19
21
20
22
/*
21
23
node admin bindings
22
24
*/
23
25
24
26
func (js * jsre ) adminBindings () {
27
+ ethO , _ := js .re .Get ("eth" )
28
+ eth := ethO .Object ()
29
+ eth .Set ("pendingTransactions" , js .pendingTransactions )
30
+ eth .Set ("resend" , js .resend )
31
+
25
32
js .re .Set ("admin" , struct {}{})
26
33
t , _ := js .re .Get ("admin" )
27
34
admin := t .Object ()
@@ -74,6 +81,70 @@ func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
74
81
return nil , errors .New ("requires block number or block hash as argument" )
75
82
}
76
83
84
+ func (js * jsre ) pendingTransactions (call otto.FunctionCall ) otto.Value {
85
+ txs := js .ethereum .TxPool ().GetTransactions ()
86
+
87
+ // grab the accounts from the account manager. This will help with determening which
88
+ // transactions should be returned.
89
+ accounts , err := js .ethereum .AccountManager ().Accounts ()
90
+ if err != nil {
91
+ fmt .Println (err )
92
+ return otto .UndefinedValue ()
93
+ }
94
+
95
+ // Add the accouns to a new set
96
+ accountSet := set .New ()
97
+ for _ , account := range accounts {
98
+ accountSet .Add (common .BytesToAddress (account .Address ))
99
+ }
100
+
101
+ //ltxs := make([]*tx, len(txs))
102
+ var ltxs []* tx
103
+ for _ , tx := range txs {
104
+ // no need to check err
105
+ if from , _ := tx .From (); accountSet .Has (from ) {
106
+ ltxs = append (ltxs , newTx (tx ))
107
+ }
108
+ }
109
+
110
+ return js .re .ToVal (ltxs )
111
+ }
112
+
113
+ func (js * jsre ) resend (call otto.FunctionCall ) otto.Value {
114
+ if len (call .ArgumentList ) == 0 {
115
+ fmt .Println ("first argument must be a transaction" )
116
+ return otto .FalseValue ()
117
+ }
118
+
119
+ v , err := call .Argument (0 ).Export ()
120
+ if err != nil {
121
+ fmt .Println (err )
122
+ return otto .FalseValue ()
123
+ }
124
+
125
+ if tx , ok := v .(* tx ); ok {
126
+ gl , gp := tx .GasLimit , tx .GasPrice
127
+ if len (call .ArgumentList ) > 1 {
128
+ gp = call .Argument (1 ).String ()
129
+ }
130
+ if len (call .ArgumentList ) > 2 {
131
+ gl = call .Argument (2 ).String ()
132
+ }
133
+
134
+ ret , err := js .xeth .Transact (tx .From , tx .To , tx .Nonce , tx .Value , gl , gp , tx .Data )
135
+ if err != nil {
136
+ fmt .Println (err )
137
+ return otto .FalseValue ()
138
+ }
139
+ js .ethereum .TxPool ().RemoveTransactions (types.Transactions {tx .tx })
140
+
141
+ return js .re .ToVal (ret )
142
+ }
143
+
144
+ fmt .Println ("first argument must be a transaction" )
145
+ return otto .FalseValue ()
146
+ }
147
+
77
148
func (js * jsre ) debugBlock (call otto.FunctionCall ) otto.Value {
78
149
block , err := js .getBlock (call )
79
150
if err != nil {
@@ -421,3 +492,35 @@ func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
421
492
return js .re .ToVal (dump )
422
493
423
494
}
495
+
496
+ // internal transaction type which will allow us to resend transactions using `eth.resend`
497
+ type tx struct {
498
+ tx * types.Transaction
499
+
500
+ To string
501
+ From string
502
+ Nonce string
503
+ Value string
504
+ Data string
505
+ GasLimit string
506
+ GasPrice string
507
+ }
508
+
509
+ func newTx (t * types.Transaction ) * tx {
510
+ from , _ := t .From ()
511
+ var to string
512
+ if t := t .To (); t != nil {
513
+ to = t .Hex ()
514
+ }
515
+
516
+ return & tx {
517
+ tx : t ,
518
+ To : to ,
519
+ From : from .Hex (),
520
+ Value : t .Amount .String (),
521
+ Nonce : strconv .Itoa (int (t .Nonce ())),
522
+ Data : "0x" + common .Bytes2Hex (t .Data ()),
523
+ GasLimit : t .GasLimit .String (),
524
+ GasPrice : t .GasPrice ().String (),
525
+ }
526
+ }
0 commit comments