feat(wallet)_: common endpoints added to wallet api
- `SignMessage` - `BuildTransaction` - `SendTransactionWithSignature`
This commit is contained in:
parent
568371e836
commit
dea0b62650
|
@ -2,6 +2,7 @@ package wallet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -524,6 +525,37 @@ func (api *API) GetAddressDetails(ctx context.Context, chainID uint64, address s
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) SignMessage(ctx context.Context, message types.HexBytes, address common.Address, password string) (string, error) {
|
||||||
|
log.Debug("[WalletAPI::SignMessage]", "message", message, "address", address)
|
||||||
|
return api.s.transactionManager.SignMessage(message, address, password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) BuildTransaction(ctx context.Context, chainID uint64, sendTxArgsJSON string) (response *transfer.TxResponse, err error) {
|
||||||
|
log.Debug("[WalletAPI::BuildTransaction]", "chainID", chainID, "sendTxArgsJSON", sendTxArgsJSON)
|
||||||
|
var params transactions.SendTxArgs
|
||||||
|
err = json.Unmarshal([]byte(sendTxArgsJSON), ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return api.s.transactionManager.BuildTransaction(chainID, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) SendTransactionWithSignature(ctx context.Context, chainID uint64, txType transactions.PendingTrxType,
|
||||||
|
sendTxArgsJSON string, signature string) (hash types.Hash, err error) {
|
||||||
|
log.Debug("[WalletAPI::SendTransactionWithSignature]", "chainID", chainID, "txType", txType, "sendTxArgsJSON", sendTxArgsJSON, "signature", signature)
|
||||||
|
sig, err := hex.DecodeString(signature)
|
||||||
|
if err != nil {
|
||||||
|
return hash, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var params transactions.SendTxArgs
|
||||||
|
err = json.Unmarshal([]byte(sendTxArgsJSON), ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return hash, err
|
||||||
|
}
|
||||||
|
return api.s.transactionManager.SendTransactionWithSignature(chainID, txType, params, sig)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) CreateMultiTransaction(ctx context.Context, multiTransactionCommand *transfer.MultiTransactionCommand, data []*bridge.TransactionBridge, password string) (*transfer.MultiTransactionCommandResult, error) {
|
func (api *API) CreateMultiTransaction(ctx context.Context, multiTransactionCommand *transfer.MultiTransactionCommand, data []*bridge.TransactionBridge, password string) (*transfer.MultiTransactionCommandResult, error) {
|
||||||
log.Debug("[WalletAPI:: CreateMultiTransaction] create multi transaction")
|
log.Debug("[WalletAPI:: CreateMultiTransaction] create multi transaction")
|
||||||
return api.s.transactionManager.CreateMultiTransactionFromCommand(ctx, multiTransactionCommand, data, api.router.bridges, password)
|
return api.s.transactionManager.CreateMultiTransactionFromCommand(ctx, multiTransactionCommand, data, api.router.bridges, password)
|
||||||
|
|
|
@ -0,0 +1,225 @@
|
||||||
|
package transfer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
ethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
|
"github.com/status-im/status-go/account"
|
||||||
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||||
|
"github.com/status-im/status-go/params"
|
||||||
|
"github.com/status-im/status-go/services/wallet/bridge"
|
||||||
|
wallet_common "github.com/status-im/status-go/services/wallet/common"
|
||||||
|
"github.com/status-im/status-go/services/wallet/walletevent"
|
||||||
|
"github.com/status-im/status-go/transactions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MultiTransactionIDType int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
NoMultiTransactionID = MultiTransactionIDType(0)
|
||||||
|
|
||||||
|
// EventMTTransactionUpdate is emitted when a multi-transaction is updated (added or deleted)
|
||||||
|
EventMTTransactionUpdate walletevent.EventType = "multi-transaction-update"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SignatureDetails struct {
|
||||||
|
R string `json:"r"`
|
||||||
|
S string `json:"s"`
|
||||||
|
V string `json:"v"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransactionDescription struct {
|
||||||
|
chainID uint64
|
||||||
|
builtTx *ethTypes.Transaction
|
||||||
|
signature []byte
|
||||||
|
unlock transactions.UnlockNonceFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransactionManager struct {
|
||||||
|
db *sql.DB
|
||||||
|
gethManager *account.GethManager
|
||||||
|
transactor *transactions.Transactor
|
||||||
|
config *params.NodeConfig
|
||||||
|
accountsDB *accounts.Database
|
||||||
|
pendingTracker *transactions.PendingTxTracker
|
||||||
|
eventFeed *event.Feed
|
||||||
|
|
||||||
|
multiTransactionForKeycardSigning *MultiTransaction
|
||||||
|
transactionsBridgeData []*bridge.TransactionBridge
|
||||||
|
transactionsForKeycardSingning map[common.Hash]*TransactionDescription
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTransactionManager(
|
||||||
|
db *sql.DB,
|
||||||
|
gethManager *account.GethManager,
|
||||||
|
transactor *transactions.Transactor,
|
||||||
|
config *params.NodeConfig,
|
||||||
|
accountsDB *accounts.Database,
|
||||||
|
pendingTxManager *transactions.PendingTxTracker,
|
||||||
|
eventFeed *event.Feed,
|
||||||
|
) *TransactionManager {
|
||||||
|
return &TransactionManager{
|
||||||
|
db: db,
|
||||||
|
gethManager: gethManager,
|
||||||
|
transactor: transactor,
|
||||||
|
config: config,
|
||||||
|
accountsDB: accountsDB,
|
||||||
|
pendingTracker: pendingTxManager,
|
||||||
|
eventFeed: eventFeed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
emptyHash = common.Hash{}
|
||||||
|
)
|
||||||
|
|
||||||
|
type MultiTransactionType uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
MultiTransactionSend = iota
|
||||||
|
MultiTransactionSwap
|
||||||
|
MultiTransactionBridge
|
||||||
|
)
|
||||||
|
|
||||||
|
type MultiTransaction struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
Timestamp uint64 `json:"timestamp"`
|
||||||
|
FromNetworkID uint64 `json:"fromNetworkID"`
|
||||||
|
ToNetworkID uint64 `json:"toNetworkID"`
|
||||||
|
FromTxHash common.Hash `json:"fromTxHash"`
|
||||||
|
ToTxHash common.Hash `json:"toTxHash"`
|
||||||
|
FromAddress common.Address `json:"fromAddress"`
|
||||||
|
ToAddress common.Address `json:"toAddress"`
|
||||||
|
FromAsset string `json:"fromAsset"`
|
||||||
|
ToAsset string `json:"toAsset"`
|
||||||
|
FromAmount *hexutil.Big `json:"fromAmount"`
|
||||||
|
ToAmount *hexutil.Big `json:"toAmount"`
|
||||||
|
Type MultiTransactionType `json:"type"`
|
||||||
|
CrossTxID string
|
||||||
|
}
|
||||||
|
|
||||||
|
type MultiTransactionCommand struct {
|
||||||
|
FromAddress common.Address `json:"fromAddress"`
|
||||||
|
ToAddress common.Address `json:"toAddress"`
|
||||||
|
FromAsset string `json:"fromAsset"`
|
||||||
|
ToAsset string `json:"toAsset"`
|
||||||
|
FromAmount *hexutil.Big `json:"fromAmount"`
|
||||||
|
Type MultiTransactionType `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MultiTransactionCommandResult struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Hashes map[uint64][]types.Hash `json:"hashes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransactionIdentity struct {
|
||||||
|
ChainID wallet_common.ChainID `json:"chainId"`
|
||||||
|
Hash common.Hash `json:"hash"`
|
||||||
|
Address common.Address `json:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TxResponse struct {
|
||||||
|
KeyUID string `json:"keyUid,omitempty"`
|
||||||
|
Address types.Address `json:"address,omitempty"`
|
||||||
|
AddressPath string `json:"addressPath,omitempty"`
|
||||||
|
SignOnKeycard bool `json:"signOnKeycard,omitempty"`
|
||||||
|
ChainID uint64 `json:"chainId,omitempty"`
|
||||||
|
MesageToSign interface{} `json:"messageToSign,omitempty"`
|
||||||
|
TxArgs transactions.SendTxArgs `json:"txArgs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TransactionManager) SignMessage(message types.HexBytes, address common.Address, password string) (string, error) {
|
||||||
|
selectedAccount, err := tm.gethManager.VerifyAccountPassword(tm.config.KeyStoreDir, address.Hex(), password)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
signature, err := crypto.Sign(message[:], selectedAccount.PrivateKey)
|
||||||
|
|
||||||
|
return types.EncodeHex(signature), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TransactionManager) BuildTransaction(chainID uint64, sendArgs transactions.SendTxArgs) (response *TxResponse, err error) {
|
||||||
|
account, err := tm.accountsDB.GetAccountByAddress(sendArgs.From)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to resolve account: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
kp, err := tm.accountsDB.GetKeypairByKeyUID(account.KeyUID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
txBeingSigned, unlock, err := tm.transactor.ValidateAndBuildTransaction(chainID, sendArgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// We have to unlock the nonce, cause we don't know what will happen on the client side (will user accept/reject) an action.
|
||||||
|
if unlock != nil {
|
||||||
|
defer func() {
|
||||||
|
unlock(false, 0)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set potential missing fields that were added while building the transaction
|
||||||
|
if sendArgs.Value == nil {
|
||||||
|
value := hexutil.Big(*txBeingSigned.Value())
|
||||||
|
sendArgs.Value = &value
|
||||||
|
}
|
||||||
|
if sendArgs.Nonce == nil {
|
||||||
|
nonce := hexutil.Uint64(txBeingSigned.Nonce())
|
||||||
|
sendArgs.Nonce = &nonce
|
||||||
|
}
|
||||||
|
if sendArgs.GasPrice == nil {
|
||||||
|
gasPrice := hexutil.Big(*txBeingSigned.GasPrice())
|
||||||
|
sendArgs.GasPrice = &gasPrice
|
||||||
|
}
|
||||||
|
if sendArgs.MaxPriorityFeePerGas == nil {
|
||||||
|
maxPriorityFeePerGas := hexutil.Big(*txBeingSigned.GasTipCap())
|
||||||
|
sendArgs.MaxPriorityFeePerGas = &maxPriorityFeePerGas
|
||||||
|
}
|
||||||
|
if sendArgs.MaxFeePerGas == nil {
|
||||||
|
maxFeePerGas := hexutil.Big(*txBeingSigned.GasFeeCap())
|
||||||
|
sendArgs.MaxFeePerGas = &maxFeePerGas
|
||||||
|
}
|
||||||
|
|
||||||
|
signer := ethTypes.NewLondonSigner(new(big.Int).SetUint64(chainID))
|
||||||
|
|
||||||
|
return &TxResponse{
|
||||||
|
KeyUID: account.KeyUID,
|
||||||
|
Address: account.Address,
|
||||||
|
AddressPath: account.Path,
|
||||||
|
SignOnKeycard: kp.MigratedToKeycard(),
|
||||||
|
ChainID: chainID,
|
||||||
|
MesageToSign: signer.Hash(txBeingSigned),
|
||||||
|
TxArgs: sendArgs,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TransactionManager) SendTransactionWithSignature(chainID uint64, txType transactions.PendingTrxType, sendArgs transactions.SendTxArgs, signature []byte) (hash types.Hash, err error) {
|
||||||
|
hash, err = tm.transactor.BuildTransactionAndSendWithSignature(chainID, sendArgs, signature)
|
||||||
|
if err != nil {
|
||||||
|
return hash, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tm.pendingTracker.TrackPendingTransaction(
|
||||||
|
wallet_common.ChainID(chainID),
|
||||||
|
common.Hash(hash),
|
||||||
|
common.Address(sendArgs.From),
|
||||||
|
txType,
|
||||||
|
transactions.AutoDelete,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return hash, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash, nil
|
||||||
|
}
|
|
@ -19,8 +19,6 @@ import (
|
||||||
"github.com/status-im/status-go/account"
|
"github.com/status-im/status-go/account"
|
||||||
"github.com/status-im/status-go/eth-node/crypto"
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
|
||||||
"github.com/status-im/status-go/params"
|
|
||||||
"github.com/status-im/status-go/services/wallet/bigint"
|
"github.com/status-im/status-go/services/wallet/bigint"
|
||||||
"github.com/status-im/status-go/services/wallet/bridge"
|
"github.com/status-im/status-go/services/wallet/bridge"
|
||||||
wallet_common "github.com/status-im/status-go/services/wallet/common"
|
wallet_common "github.com/status-im/status-go/services/wallet/common"
|
||||||
|
@ -29,111 +27,6 @@ import (
|
||||||
"github.com/status-im/status-go/transactions"
|
"github.com/status-im/status-go/transactions"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MultiTransactionIDType int64
|
|
||||||
|
|
||||||
const (
|
|
||||||
NoMultiTransactionID = MultiTransactionIDType(0)
|
|
||||||
|
|
||||||
// EventMTTransactionUpdate is emitted when a multi-transaction is updated (added or deleted)
|
|
||||||
EventMTTransactionUpdate walletevent.EventType = "multi-transaction-update"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SignatureDetails struct {
|
|
||||||
R string `json:"r"`
|
|
||||||
S string `json:"s"`
|
|
||||||
V string `json:"v"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TransactionDescription struct {
|
|
||||||
chainID uint64
|
|
||||||
builtTx *ethTypes.Transaction
|
|
||||||
signature []byte
|
|
||||||
unlock transactions.UnlockNonceFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
type TransactionManager struct {
|
|
||||||
db *sql.DB
|
|
||||||
gethManager *account.GethManager
|
|
||||||
transactor *transactions.Transactor
|
|
||||||
config *params.NodeConfig
|
|
||||||
accountsDB *accounts.Database
|
|
||||||
pendingTracker *transactions.PendingTxTracker
|
|
||||||
eventFeed *event.Feed
|
|
||||||
|
|
||||||
multiTransactionForKeycardSigning *MultiTransaction
|
|
||||||
transactionsBridgeData []*bridge.TransactionBridge
|
|
||||||
transactionsForKeycardSingning map[common.Hash]*TransactionDescription
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTransactionManager(
|
|
||||||
db *sql.DB,
|
|
||||||
gethManager *account.GethManager,
|
|
||||||
transactor *transactions.Transactor,
|
|
||||||
config *params.NodeConfig,
|
|
||||||
accountsDB *accounts.Database,
|
|
||||||
pendingTxManager *transactions.PendingTxTracker,
|
|
||||||
eventFeed *event.Feed,
|
|
||||||
) *TransactionManager {
|
|
||||||
return &TransactionManager{
|
|
||||||
db: db,
|
|
||||||
gethManager: gethManager,
|
|
||||||
transactor: transactor,
|
|
||||||
config: config,
|
|
||||||
accountsDB: accountsDB,
|
|
||||||
pendingTracker: pendingTxManager,
|
|
||||||
eventFeed: eventFeed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
emptyHash = common.Hash{}
|
|
||||||
)
|
|
||||||
|
|
||||||
type MultiTransactionType uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
MultiTransactionSend = iota
|
|
||||||
MultiTransactionSwap
|
|
||||||
MultiTransactionBridge
|
|
||||||
)
|
|
||||||
|
|
||||||
type MultiTransaction struct {
|
|
||||||
ID uint `json:"id"`
|
|
||||||
Timestamp uint64 `json:"timestamp"`
|
|
||||||
FromNetworkID uint64 `json:"fromNetworkID"`
|
|
||||||
ToNetworkID uint64 `json:"toNetworkID"`
|
|
||||||
FromTxHash common.Hash `json:"fromTxHash"`
|
|
||||||
ToTxHash common.Hash `json:"toTxHash"`
|
|
||||||
FromAddress common.Address `json:"fromAddress"`
|
|
||||||
ToAddress common.Address `json:"toAddress"`
|
|
||||||
FromAsset string `json:"fromAsset"`
|
|
||||||
ToAsset string `json:"toAsset"`
|
|
||||||
FromAmount *hexutil.Big `json:"fromAmount"`
|
|
||||||
ToAmount *hexutil.Big `json:"toAmount"`
|
|
||||||
Type MultiTransactionType `json:"type"`
|
|
||||||
CrossTxID string
|
|
||||||
}
|
|
||||||
|
|
||||||
type MultiTransactionCommand struct {
|
|
||||||
FromAddress common.Address `json:"fromAddress"`
|
|
||||||
ToAddress common.Address `json:"toAddress"`
|
|
||||||
FromAsset string `json:"fromAsset"`
|
|
||||||
ToAsset string `json:"toAsset"`
|
|
||||||
FromAmount *hexutil.Big `json:"fromAmount"`
|
|
||||||
Type MultiTransactionType `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MultiTransactionCommandResult struct {
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
Hashes map[uint64][]types.Hash `json:"hashes"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TransactionIdentity struct {
|
|
||||||
ChainID wallet_common.ChainID `json:"chainId"`
|
|
||||||
Hash common.Hash `json:"hash"`
|
|
||||||
Address common.Address `json:"address"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const multiTransactionColumns = "from_network_id, from_tx_hash, from_address, from_asset, from_amount, to_network_id, to_tx_hash, to_address, to_asset, to_amount, type, cross_tx_id, timestamp"
|
const multiTransactionColumns = "from_network_id, from_tx_hash, from_address, from_asset, from_amount, to_network_id, to_tx_hash, to_address, to_asset, to_amount, type, cross_tx_id, timestamp"
|
||||||
const selectMultiTransactionColumns = "COALESCE(from_network_id, 0), from_tx_hash, from_address, from_asset, from_amount, COALESCE(to_network_id, 0), to_tx_hash, to_address, to_asset, to_amount, type, cross_tx_id, timestamp"
|
const selectMultiTransactionColumns = "COALESCE(from_network_id, 0), from_tx_hash, from_address, from_asset, from_amount, COALESCE(to_network_id, 0), to_tx_hash, to_address, to_asset, to_amount, type, cross_tx_id, timestamp"
|
||||||
|
|
|
@ -191,7 +191,8 @@ func (t *Transactor) BuildTransactionAndSendWithSignature(chainID uint64, args S
|
||||||
return hash, &ErrBadNonce{tx.Nonce(), expectedNonce}
|
return hash, &ErrBadNonce{tx.Nonce(), expectedNonce}
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.AddSignatureToTransactionAndSend(chainID, tx, sig)
|
hash, err = t.AddSignatureToTransactionAndSend(chainID, tx, sig)
|
||||||
|
return hash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transactor) HashTransaction(args SendTxArgs) (validatedArgs SendTxArgs, hash types.Hash, err error) {
|
func (t *Transactor) HashTransaction(args SendTxArgs) (validatedArgs SendTxArgs, hash types.Hash, err error) {
|
||||||
|
@ -387,10 +388,24 @@ func (t *Transactor) validateAndPropagate(rpcWrapper *rpcWrapper, selectedAccoun
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transactor) buildTransaction(args SendTxArgs) *gethtypes.Transaction {
|
func (t *Transactor) buildTransaction(args SendTxArgs) *gethtypes.Transaction {
|
||||||
nonce := uint64(*args.Nonce)
|
var (
|
||||||
value := (*big.Int)(args.Value)
|
nonce uint64
|
||||||
gas := uint64(*args.Gas)
|
value *big.Int
|
||||||
gasPrice := (*big.Int)(args.GasPrice)
|
gas uint64
|
||||||
|
gasPrice *big.Int
|
||||||
|
)
|
||||||
|
if args.Nonce != nil {
|
||||||
|
nonce = uint64(*args.Nonce)
|
||||||
|
}
|
||||||
|
if args.Value != nil {
|
||||||
|
value = (*big.Int)(args.Value)
|
||||||
|
}
|
||||||
|
if args.Gas != nil {
|
||||||
|
gas = uint64(*args.Gas)
|
||||||
|
}
|
||||||
|
if args.GasPrice != nil {
|
||||||
|
gasPrice = (*big.Int)(args.GasPrice)
|
||||||
|
}
|
||||||
|
|
||||||
return t.buildTransactionWithOverrides(nonce, value, gas, gasPrice, args)
|
return t.buildTransactionWithOverrides(nonce, value, gas, gasPrice, args)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue