Allow gas and gas input as argument on signing TTXX (#1000)

* Allow gas and gas input as argument on signing TTXX

* Two different bindings ApproveSignRequest and ApproveSignRequestWithArgs
This commit is contained in:
Adrià Cidre 2018-06-06 09:35:32 +02:00 committed by GitHub
parent 2b193de5c1
commit c82d5635b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 274 additions and 41 deletions

View File

@ -175,3 +175,14 @@ func (cs *commandSet) ApproveSignRequest(id, password string) (string, error) {
}
return result.Response.Hex(), nil
}
// ApproveSignRequest instructs API to complete sending of a given transaction.
// gas and gasPrice will be overrided with the given values before signing the
// transaction.
func (cs *commandSet) ApproveSignRequestWithArgs(id, password string, gas, gasPrice int64) (string, error) {
result := cs.statusAPI.ApproveSignRequestWithArgs(id, password, gas, gasPrice)
if result.Error != nil {
return "", result.Error
}
return result.Response.Hex(), nil
}

View File

@ -158,10 +158,17 @@ func (api *StatusAPI) SendTransaction(ctx context.Context, args transactions.Sen
}
// ApproveSignRequest instructs backend to complete sending of a given transaction
func (api *StatusAPI) ApproveSignRequest(id string, password string) sign.Result {
func (api *StatusAPI) ApproveSignRequest(id, password string) sign.Result {
return api.b.ApproveSignRequest(id, password)
}
// ApproveSignRequestWithArgs instructs backend to complete sending of a given transaction
// gas and gasPrice will be overrided with the given values before signing the
// transaction.
func (api *StatusAPI) ApproveSignRequestWithArgs(id, password string, gas, gasPrice int64) sign.Result {
return api.b.ApproveSignRequestWithArgs(id, password, gas, gasPrice)
}
// ApproveSignRequests instructs backend to complete sending of multiple transactions
func (api *StatusAPI) ApproveSignRequests(ids []string, password string) map[string]sign.Result {
return api.b.ApproveSignRequests(ids, password)

View File

@ -251,9 +251,17 @@ func (b *StatusBackend) getVerifiedAccount(password string) (*account.SelectedEx
return selectedAccount, nil
}
// ApproveSignRequest instructs backend to complete sending of a given transaction
func (b *StatusBackend) ApproveSignRequest(id string, password string) sign.Result {
return b.pendingSignRequests.Approve(id, password, b.getVerifiedAccount)
// ApproveSignRequest instructs backend to complete sending of a given transaction.
func (b *StatusBackend) ApproveSignRequest(id, password string) sign.Result {
return b.pendingSignRequests.Approve(id, password, nil, b.getVerifiedAccount)
}
// ApproveSignRequestWithArgs instructs backend to complete sending of a given transaction.
// gas and gasPrice will be overrided with the given values before signing the
// transaction.
func (b *StatusBackend) ApproveSignRequestWithArgs(id, password string, gas, gasPrice int64) sign.Result {
args := prepareTxArgs(gas, gasPrice)
return b.pendingSignRequests.Approve(id, password, &args, b.getVerifiedAccount)
}
// ApproveSignRequests instructs backend to complete sending of multiple transactions

View File

@ -2,10 +2,12 @@ package api
import (
"fmt"
"math/big"
"math/rand"
"sync"
"testing"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/geth/node"
"github.com/status-im/status-go/geth/params"
"github.com/stretchr/testify/assert"
@ -243,4 +245,56 @@ func TestBackendCallRPCConcurrently(t *testing.T) {
wg.Wait()
}
func TestPrepareTxArgs(t *testing.T) {
var flagtests = []struct {
description string
gas int64
gasPrice int64
expectedGas *hexutil.Uint64
expectedGasPrice *hexutil.Big
}{
{
description: "Empty gas and gas price",
gas: 0,
gasPrice: 0,
expectedGas: nil,
expectedGasPrice: nil,
},
{
description: "Non empty gas and gas price",
gas: 1,
gasPrice: 2,
expectedGas: func() *hexutil.Uint64 {
x := hexutil.Uint64(1)
return &x
}(),
expectedGasPrice: (*hexutil.Big)(big.NewInt(2)),
},
{
description: "Empty gas price",
gas: 1,
gasPrice: 0,
expectedGas: func() *hexutil.Uint64 {
x := hexutil.Uint64(1)
return &x
}(),
expectedGasPrice: nil,
},
{
description: "Empty gas",
gas: 0,
gasPrice: 2,
expectedGas: nil,
expectedGasPrice: (*hexutil.Big)(big.NewInt(2)),
},
}
for _, tt := range flagtests {
t.Run(tt.description, func(t *testing.T) {
args := prepareTxArgs(tt.gas, tt.gasPrice)
assert.Equal(t, tt.expectedGas, args.Gas)
assert.Equal(t, tt.expectedGasPrice, args.GasPrice)
})
}
}
// TODO(adam): add concurrent tests for: SendTransaction, ApproveSignRequest, DiscardSignRequest

21
geth/api/txargs.go Normal file
View File

@ -0,0 +1,21 @@
package api
import (
"math/big"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/sign"
)
// prepareTxArgs given gas and gasPrice will prepare a valid sign.TxArgs.
func prepareTxArgs(gas, gasPrice int64) (args sign.TxArgs) {
if gas > 0 {
g := hexutil.Uint64(gas)
args.Gas = &g
}
if gasPrice > 0 {
gp := (*hexutil.Big)(big.NewInt(gasPrice))
args.GasPrice = gp
}
return
}

View File

@ -72,7 +72,8 @@ func (t *Transactor) SendTransaction(ctx context.Context, args SendTxArgs) (geth
ctx = context.Background()
}
completeFunc := func(acc *account.SelectedExtKey, password string) (sign.Response, error) {
completeFunc := func(acc *account.SelectedExtKey, password string, signArgs *sign.TxArgs) (sign.Response, error) {
t.mergeSignTxArgsOntoSendTxArgs(signArgs, &args)
hash, err := t.validateAndPropagate(acc, args)
return sign.Response(hash.Bytes()), err
}
@ -197,8 +198,21 @@ func (t *Transactor) validateAndPropagate(selectedAccount *account.SelectedExtKe
}
ctx, cancel = context.WithTimeout(context.Background(), t.rpcCallTimeout)
defer cancel()
if err := t.sender.SendTransaction(ctx, signedTx); err != nil {
return hash, err
}
return signedTx.Hash(), nil
}
func (t *Transactor) mergeSignTxArgsOntoSendTxArgs(signArgs *sign.TxArgs, args *SendTxArgs) {
if signArgs == nil {
return
}
if signArgs.Gas != nil {
args.Gas = signArgs.Gas
}
if signArgs.GasPrice != nil {
args.GasPrice = signArgs.GasPrice
}
}

View File

@ -76,24 +76,30 @@ func (s *TxQueueTestSuite) TearDownTest() {
}
var (
testGas = hexutil.Uint64(defaultGas + 1)
testGasPrice = (*hexutil.Big)(big.NewInt(10))
testNonce = hexutil.Uint64(10)
testGas = hexutil.Uint64(defaultGas + 1)
testGasPrice = (*hexutil.Big)(big.NewInt(10))
testOverridenGas = hexutil.Uint64(defaultGas + 2)
testOverridenGasPrice = (*hexutil.Big)(big.NewInt(20))
testNonce = hexutil.Uint64(10)
)
func (s *TxQueueTestSuite) setupTransactionPoolAPI(args SendTxArgs, returnNonce, resultNonce hexutil.Uint64, account *account.SelectedExtKey, txErr error) {
func (s *TxQueueTestSuite) setupTransactionPoolAPI(args SendTxArgs, returnNonce, resultNonce hexutil.Uint64, account *account.SelectedExtKey, txErr error, signArgs *sign.TxArgs) {
// Expect calls to gas functions only if there are no user defined values.
// And also set the expected gas and gas price for RLP encoding the expected tx.
var usedGas hexutil.Uint64
var usedGasPrice *big.Int
s.txServiceMock.EXPECT().GetTransactionCount(gomock.Any(), account.Address, gethrpc.PendingBlockNumber).Return(&returnNonce, nil)
if args.GasPrice == nil {
if signArgs != nil && signArgs.GasPrice != nil {
usedGasPrice = (*big.Int)(signArgs.GasPrice)
} else if args.GasPrice == nil {
usedGasPrice = (*big.Int)(testGasPrice)
s.txServiceMock.EXPECT().GasPrice(gomock.Any()).Return(usedGasPrice, nil)
} else {
usedGasPrice = (*big.Int)(args.GasPrice)
}
if args.Gas == nil {
if signArgs != nil && signArgs.Gas != nil {
usedGas = *signArgs.Gas
} else if args.Gas == nil {
s.txServiceMock.EXPECT().EstimateGas(gomock.Any(), gomock.Any()).Return(testGas, nil)
usedGas = testGas
} else {
@ -129,29 +135,80 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
AccountKey: &keystore.Key{PrivateKey: key},
}
testCases := []struct {
name string
gas *hexutil.Uint64
gasPrice *hexutil.Big
name string
gas *hexutil.Uint64
gasPrice *hexutil.Big
signTxArgs *sign.TxArgs
}{
{
"noGasDef",
nil,
nil,
s.defaultSignTxArgs(),
},
{
"gasDefined",
&testGas,
nil,
s.defaultSignTxArgs(),
},
{
"gasPriceDefined",
nil,
testGasPrice,
s.defaultSignTxArgs(),
},
{
"inputPassedInLegacyDataField",
nil,
testGasPrice,
s.defaultSignTxArgs(),
},
{
"overrideGas",
nil,
nil,
&sign.TxArgs{
Gas: &testGas,
},
},
{
"overridePreExistingGas",
&testGas,
nil,
&sign.TxArgs{
Gas: &testOverridenGas,
},
},
{
"overridePreExistingGasPrice",
nil,
testGasPrice,
&sign.TxArgs{
GasPrice: testOverridenGasPrice,
},
},
{
"nilSignTransactionSpecificArgs",
nil,
nil,
nil,
},
{
"overridePreExistingGasWithNil",
&testGas,
nil,
&sign.TxArgs{
Gas: nil,
},
},
{
"overridePreExistingGasPriceWithNil",
nil,
testGasPrice,
&sign.TxArgs{
GasPrice: nil,
},
},
}
@ -164,7 +221,7 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
Gas: testCase.gas,
GasPrice: testCase.gasPrice,
}
s.setupTransactionPoolAPI(args, testNonce, testNonce, selectedAccount, nil)
s.setupTransactionPoolAPI(args, testNonce, testNonce, selectedAccount, nil, testCase.signTxArgs)
w := make(chan struct{})
var sendHash gethcommon.Hash
@ -184,7 +241,7 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
req := s.manager.pendingSignRequests.First()
s.NotNil(req)
approveResult := s.manager.pendingSignRequests.Approve(req.ID, "", simpleVerifyFunc(selectedAccount))
approveResult := s.manager.pendingSignRequests.Approve(req.ID, "", testCase.signTxArgs, simpleVerifyFunc(selectedAccount))
s.NoError(approveResult.Error)
s.NoError(WaitClosed(w, time.Second))
@ -195,6 +252,10 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
}
}
func (s *TxQueueTestSuite) defaultSignTxArgs() *sign.TxArgs {
return &sign.TxArgs{}
}
func (s *TxQueueTestSuite) TestAccountMismatch() {
selectedAccount := &account.SelectedExtKey{
Address: account.FromAddress(TestConfig.Account2.Address),
@ -218,7 +279,7 @@ func (s *TxQueueTestSuite) TestAccountMismatch() {
req := s.manager.pendingSignRequests.First()
s.NotNil(req)
result := s.manager.pendingSignRequests.Approve(req.ID, "", simpleVerifyFunc(selectedAccount))
result := s.manager.pendingSignRequests.Approve(req.ID, "", s.defaultSignTxArgs(), simpleVerifyFunc(selectedAccount))
s.EqualError(result.Error, ErrInvalidCompleteTxSender.Error())
// Transaction should stay in the queue as mismatched accounts
@ -279,7 +340,7 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
if req == nil {
time.Sleep(time.Millisecond)
} else {
s.manager.pendingSignRequests.Approve(req.ID, "", simpleVerifyFunc(selectedAccount)) // nolint: errcheck
s.manager.pendingSignRequests.Approve(req.ID, "", s.defaultSignTxArgs(), simpleVerifyFunc(selectedAccount)) // nolint: errcheck
}
}
}()
@ -289,7 +350,7 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
From: account.FromAddress(TestConfig.Account1.Address),
To: account.ToAddress(TestConfig.Account2.Address),
}
s.setupTransactionPoolAPI(args, nonce, hexutil.Uint64(i), selectedAccount, nil)
s.setupTransactionPoolAPI(args, nonce, hexutil.Uint64(i), selectedAccount, nil, nil)
_, err := s.manager.SendTransaction(context.Background(), args)
s.NoError(err)
@ -303,7 +364,7 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
To: account.ToAddress(TestConfig.Account2.Address),
}
s.setupTransactionPoolAPI(args, nonce, nonce, selectedAccount, nil)
s.setupTransactionPoolAPI(args, nonce, nonce, selectedAccount, nil, nil)
_, err := s.manager.SendTransaction(context.Background(), args)
s.NoError(err)
@ -349,7 +410,7 @@ func (s *TxQueueTestSuite) TestContractCreation() {
if req == nil {
time.Sleep(time.Millisecond)
} else {
s.manager.pendingSignRequests.Approve(req.ID, "", simpleVerifyFunc(selectedAccount)) // nolint: errcheck
s.manager.pendingSignRequests.Approve(req.ID, "", s.defaultSignTxArgs(), simpleVerifyFunc(selectedAccount)) // nolint: errcheck
break
}
}

View File

@ -11,6 +11,7 @@ import (
"github.com/status-im/status-go/geth/params"
"github.com/status-im/status-go/logutils"
"github.com/status-im/status-go/profiling"
"github.com/status-im/status-go/sign"
"gopkg.in/go-playground/validator.v9"
)
@ -206,11 +207,27 @@ func Logout() *C.char {
return makeJSONResponse(err)
}
//ApproveSignRequest instructs backend to complete sending of a given transaction
//ApproveSignRequestWithArgs instructs backend to complete sending of a given transaction.
// gas and gasPrice will be overrided with the given values before signing the
// transaction.
//export ApproveSignRequestWithArgs
func ApproveSignRequestWithArgs(id, password *C.char, gas, gasPrice C.int) *C.char {
result := statusAPI.ApproveSignRequestWithArgs(C.GoString(id), C.GoString(password), int64(gas), int64(gasPrice))
return prepareApproveSignRequestResponse(result, id)
}
//ApproveSignRequest instructs backend to complete sending of a given transaction.
//export ApproveSignRequest
func ApproveSignRequest(id, password *C.char) *C.char {
result := statusAPI.ApproveSignRequest(C.GoString(id), C.GoString(password))
return prepareApproveSignRequestResponse(result, id)
}
// prepareApproveSignRequestResponse based on a sign.Result prepares the binding
// response.
func prepareApproveSignRequestResponse(result sign.Result, id *C.char) *C.char {
errString := ""
if result.Error != nil {
fmt.Fprintln(os.Stderr, result.Error)

View File

@ -88,7 +88,7 @@ func (api *PublicAPI) Sign(context context.Context, rpcParams ...interface{}) (i
}
func (api *PublicAPI) completeFunc(context context.Context, metadata metadata) sign.CompleteFunc {
return func(acc *account.SelectedExtKey, password string) (response sign.Response, err error) {
return func(acc *account.SelectedExtKey, password string, signArgs *sign.TxArgs) (response sign.Response, err error) {
response = sign.EmptyResponse
err = api.validateAccount(metadata, acc)

View File

@ -67,7 +67,7 @@ func (rs *PendingRequests) First() *Request {
}
// Approve a signing request by it's ID. Requires a valid password and a verification function.
func (rs *PendingRequests) Approve(id string, password string, verify verifyFunc) Result {
func (rs *PendingRequests) Approve(id string, password string, args *TxArgs, verify verifyFunc) Result {
rs.log.Info("complete sign request", "id", id)
request, err := rs.tryLock(id)
if err != nil {
@ -81,7 +81,7 @@ func (rs *PendingRequests) Approve(id string, password string, verify verifyFunc
return newErrResult(err)
}
response, err := request.completeFunc(selectedAccount, password)
response, err := request.completeFunc(selectedAccount, password, args)
rs.log.Info("completed sign request ", "id", request.ID, "response", response, "err", err)
rs.complete(request, response, err)

View File

@ -3,12 +3,14 @@ package sign
import (
"context"
"errors"
"math/big"
"sync/atomic"
"testing"
"time"
"github.com/ethereum/go-ethereum/accounts/keystore"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/geth/account"
"github.com/stretchr/testify/suite"
@ -19,6 +21,11 @@ const (
wrongPassword = "password-wrong"
)
var (
overridenGas = hexutil.Uint64(90002)
overridenGasPrice = (*hexutil.Big)(big.NewInt(20))
)
func testVerifyFunc(password string) (*account.SelectedExtKey, error) {
if password == correctPassword {
return nil, nil
@ -40,9 +47,13 @@ func (s *PendingRequestsSuite) SetupTest() {
s.pendingRequests = NewPendingRequests()
}
func (s *PendingRequestsSuite) defaultSignTxArgs() *TxArgs {
return &TxArgs{}
}
func (s *PendingRequestsSuite) defaultCompleteFunc() CompleteFunc {
hash := gethcommon.Hash{1}
return func(acc *account.SelectedExtKey, password string) (Response, error) {
return func(acc *account.SelectedExtKey, password string, args *TxArgs) (Response, error) {
s.Nil(acc, "account should be `nil`")
s.Equal(correctPassword, password)
return hash.Bytes(), nil
@ -51,7 +62,7 @@ func (s *PendingRequestsSuite) defaultCompleteFunc() CompleteFunc {
func (s *PendingRequestsSuite) delayedCompleteFunc() CompleteFunc {
hash := gethcommon.Hash{1}
return func(acc *account.SelectedExtKey, password string) (Response, error) {
return func(acc *account.SelectedExtKey, password string, args *TxArgs) (Response, error) {
time.Sleep(10 * time.Millisecond)
s.Nil(acc, "account should be `nil`")
s.Equal(correctPassword, password)
@ -59,9 +70,20 @@ func (s *PendingRequestsSuite) delayedCompleteFunc() CompleteFunc {
}
}
func (s *PendingRequestsSuite) overridenCompleteFunc() CompleteFunc {
hash := gethcommon.Hash{1}
return func(acc *account.SelectedExtKey, password string, args *TxArgs) (Response, error) {
s.Nil(acc, "account should be `nil`")
s.Equal(correctPassword, password)
s.Equal(&overridenGas, args.Gas)
s.Equal(overridenGasPrice, args.GasPrice)
return hash.Bytes(), nil
}
}
func (s *PendingRequestsSuite) errorCompleteFunc(err error) CompleteFunc {
hash := gethcommon.Hash{1}
return func(acc *account.SelectedExtKey, password string) (Response, error) {
return func(acc *account.SelectedExtKey, password string, args *TxArgs) (Response, error) {
s.Nil(acc, "account should be `nil`")
return hash.Bytes(), err
}
@ -77,13 +99,13 @@ func (s *PendingRequestsSuite) TestGet() {
}
}
func (s *PendingRequestsSuite) testComplete(password string, hash gethcommon.Hash, completeFunc CompleteFunc) (string, error) {
func (s *PendingRequestsSuite) testComplete(password string, hash gethcommon.Hash, completeFunc CompleteFunc, signArgs *TxArgs) (string, error) {
req, err := s.pendingRequests.Add(context.Background(), "", nil, completeFunc)
s.NoError(err)
s.True(s.pendingRequests.Has(req.ID), "sign request should exist")
result := s.pendingRequests.Approve(req.ID, password, testVerifyFunc)
result := s.pendingRequests.Approve(req.ID, password, signArgs, testVerifyFunc)
if s.pendingRequests.Has(req.ID) {
// transient error
@ -96,7 +118,7 @@ func (s *PendingRequestsSuite) testComplete(password string, hash gethcommon.Has
}
func (s *PendingRequestsSuite) TestCompleteSuccess() {
id, err := s.testComplete(correctPassword, gethcommon.Hash{1}, s.defaultCompleteFunc())
id, err := s.testComplete(correctPassword, gethcommon.Hash{1}, s.defaultCompleteFunc(), s.defaultSignTxArgs())
s.NoError(err, "no errors should be there")
s.False(s.pendingRequests.Has(id), "sign request should not exist")
@ -104,7 +126,7 @@ func (s *PendingRequestsSuite) TestCompleteSuccess() {
func (s *PendingRequestsSuite) TestCompleteTransientError() {
hash := gethcommon.Hash{}
id, err := s.testComplete(wrongPassword, hash, s.errorCompleteFunc(keystore.ErrDecrypt))
id, err := s.testComplete(wrongPassword, hash, s.errorCompleteFunc(keystore.ErrDecrypt), s.defaultSignTxArgs())
s.Equal(keystore.ErrDecrypt, err, "error value should be preserved")
s.True(s.pendingRequests.Has(id))
@ -117,7 +139,7 @@ func (s *PendingRequestsSuite) TestCompleteError() {
hash := gethcommon.Hash{1}
expectedError := errors.New("test")
id, err := s.testComplete(correctPassword, hash, s.errorCompleteFunc(expectedError))
id, err := s.testComplete(correctPassword, hash, s.errorCompleteFunc(expectedError), s.defaultSignTxArgs())
s.Equal(expectedError, err, "error value should be preserved")
@ -125,10 +147,10 @@ func (s *PendingRequestsSuite) TestCompleteError() {
}
func (s PendingRequestsSuite) TestMultipleComplete() {
id, err := s.testComplete(correctPassword, gethcommon.Hash{1}, s.defaultCompleteFunc())
id, err := s.testComplete(correctPassword, gethcommon.Hash{1}, s.defaultCompleteFunc(), s.defaultSignTxArgs())
s.NoError(err, "no errors should be there")
result := s.pendingRequests.Approve(id, correctPassword, testVerifyFunc)
result := s.pendingRequests.Approve(id, correctPassword, s.defaultSignTxArgs(), testVerifyFunc)
s.Equal(ErrSignReqNotFound, result.Error)
}
@ -144,7 +166,7 @@ func (s PendingRequestsSuite) TestConcurrentComplete() {
for i := 10; i > 0; i-- {
go func() {
result := s.pendingRequests.Approve(req.ID, correctPassword, testVerifyFunc)
result := s.pendingRequests.Approve(req.ID, correctPassword, s.defaultSignTxArgs(), testVerifyFunc)
if result.Error == nil {
atomic.AddInt32(&approved, 1)
}
@ -167,7 +189,7 @@ func (s PendingRequestsSuite) TestWaitSuccess() {
s.True(s.pendingRequests.Has(req.ID), "sign request should exist")
go func() {
result := s.pendingRequests.Approve(req.ID, correctPassword, testVerifyFunc)
result := s.pendingRequests.Approve(req.ID, correctPassword, s.defaultSignTxArgs(), testVerifyFunc)
s.NoError(result.Error)
}()
@ -201,7 +223,7 @@ func (s PendingRequestsSuite) TestWaitFail() {
s.True(s.pendingRequests.Has(req.ID), "sign request should exist")
go func() {
result := s.pendingRequests.Approve(req.ID, correctPassword, testVerifyFunc)
result := s.pendingRequests.Approve(req.ID, correctPassword, s.defaultSignTxArgs(), testVerifyFunc)
s.Equal(expectedError, result.Error)
}()
@ -218,7 +240,18 @@ func (s PendingRequestsSuite) TestWaitTimeout() {
result := s.pendingRequests.Wait(req.ID, 0*time.Second)
s.Equal(ErrSignReqTimedOut, result.Error)
// Try approving the timeouted request, it will fail
result = s.pendingRequests.Approve(req.ID, correctPassword, testVerifyFunc)
// Try approving the timed out request, it will fail
result = s.pendingRequests.Approve(req.ID, correctPassword, s.defaultSignTxArgs(), testVerifyFunc)
s.NotNil(result.Error)
}
func (s *PendingRequestsSuite) TestCompleteSuccessWithOverridenGas() {
txArgs := TxArgs{
Gas: &overridenGas,
GasPrice: overridenGasPrice,
}
id, err := s.testComplete(correctPassword, gethcommon.Hash{1}, s.overridenCompleteFunc(), &txArgs)
s.NoError(err, "no errors should be there")
s.False(s.pendingRequests.Has(id), "sign request should not exist")
}

View File

@ -3,12 +3,13 @@ package sign
import (
"context"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pborman/uuid"
"github.com/status-im/status-go/geth/account"
)
// CompleteFunc is a function that is called after the sign request is approved.
type CompleteFunc func(account *account.SelectedExtKey, password string) (Response, error)
type CompleteFunc func(account *account.SelectedExtKey, password string, completeArgs *TxArgs) (Response, error)
// Meta represents any metadata that could be attached to a signing request.
// It will be JSON-serialized and used in notifications to the API consumer.
@ -25,6 +26,12 @@ type Request struct {
result chan Result
}
// TxArgs represents the arguments to submit when signing a transaction
type TxArgs struct {
Gas *hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
}
func newRequest(ctx context.Context, method string, meta Meta, completeFunc CompleteFunc) *Request {
return &Request{
ID: uuid.New(),