chore(walletconnect)_: various improvements applied
- `WalletConnectTransfer` identified as a new transfer type - Wallet-related endpoints that logically belong to the wallet moved from the wallet connect service - Wallet connect service now receives `transfer.TransactionManager` instead of `transactions.Transactor` - Deadlock issue when trying to send the tx with the wrong nonce fixed
This commit is contained in:
parent
04873ef880
commit
cfa542378d
|
@ -541,6 +541,23 @@ func (api *API) BuildTransaction(ctx context.Context, chainID uint64, sendTxArgs
|
||||||
return api.s.transactionManager.BuildTransaction(chainID, params)
|
return api.s.transactionManager.BuildTransaction(chainID, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) BuildRawTransaction(ctx context.Context, chainID uint64, sendTxArgsJSON string, signature string) (response *transfer.TxResponse, err error) {
|
||||||
|
log.Debug("[WalletAPI::BuildRawTransaction]", "chainID", chainID, "sendTxArgsJSON", sendTxArgsJSON, "signature", signature)
|
||||||
|
|
||||||
|
sig, err := hex.DecodeString(signature)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var params transactions.SendTxArgs
|
||||||
|
err = json.Unmarshal([]byte(sendTxArgsJSON), ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return api.s.transactionManager.BuildRawTransaction(chainID, params, sig)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) SendTransactionWithSignature(ctx context.Context, chainID uint64, txType transactions.PendingTrxType,
|
func (api *API) SendTransactionWithSignature(ctx context.Context, chainID uint64, txType transactions.PendingTrxType,
|
||||||
sendTxArgsJSON string, signature string) (hash types.Hash, err error) {
|
sendTxArgsJSON string, signature string) (hash types.Hash, err error) {
|
||||||
log.Debug("[WalletAPI::SendTransactionWithSignature]", "chainID", chainID, "txType", txType, "sendTxArgsJSON", sendTxArgsJSON, "signature", signature)
|
log.Debug("[WalletAPI::SendTransactionWithSignature]", "chainID", chainID, "txType", txType, "sendTxArgsJSON", sendTxArgsJSON, "signature", signature)
|
||||||
|
@ -641,34 +658,6 @@ func (api *API) FetchChainIDForURL(ctx context.Context, rpcURL string) (*big.Int
|
||||||
return client.ChainID(ctx)
|
return client.ChainID(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WCSignMessage signs a message for the passed address using the provided password and returns the signature
|
|
||||||
func (api *API) WCSignMessage(ctx context.Context, message types.HexBytes, address common.Address, password string) (string, error) {
|
|
||||||
log.Debug("wallet.api.wc.SignMessage", "message", message, "address", address, "password", password)
|
|
||||||
|
|
||||||
return api.s.walletConnect.SignMessage(message, address, password)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WCBuildRawTransaction builds raw transaction using the provided signature and returns the RLP-encoded transaction object
|
|
||||||
func (api *API) WCBuildRawTransaction(signature string) (string, error) {
|
|
||||||
log.Debug("wallet.api.wc.BuildRawTransaction", "signature", signature)
|
|
||||||
|
|
||||||
return api.s.walletConnect.BuildRawTransaction(signature)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WCSendRawTransaction sends provided raw transaction and returns the transaction hash
|
|
||||||
func (api *API) WCSendRawTransaction(rawTx string) (string, error) {
|
|
||||||
log.Debug("wallet.api.wc.SendRawTransaction", "rawTx", rawTx)
|
|
||||||
|
|
||||||
return api.s.walletConnect.SendRawTransaction(rawTx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WCSendTransactionWithSignature sends transaction with the provided signature and returns the transaction hash
|
|
||||||
func (api *API) WCSendTransactionWithSignature(signature string) (string, error) {
|
|
||||||
log.Debug("wallet.api.wc.SendTransactionWithSignature", "signature", signature)
|
|
||||||
|
|
||||||
return api.s.walletConnect.SendTransactionWithSignature(signature)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WCPairSessionProposal responds to "session_proposal" event
|
// WCPairSessionProposal responds to "session_proposal" event
|
||||||
func (api *API) WCPairSessionProposal(ctx context.Context, sessionProposalJSON string) (*wc.PairSessionResponse, error) {
|
func (api *API) WCPairSessionProposal(ctx context.Context, sessionProposalJSON string) (*wc.PairSessionResponse, error) {
|
||||||
log.Debug("wallet.api.wc.PairSessionProposal", "proposal.len", len(sessionProposalJSON))
|
log.Debug("wallet.api.wc.PairSessionProposal", "proposal.len", len(sessionProposalJSON))
|
||||||
|
@ -709,7 +698,7 @@ func (api *API) WCHasActivePairings(ctx context.Context) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WCSessionRequest responds to "session_request" event
|
// WCSessionRequest responds to "session_request" event
|
||||||
func (api *API) WCSessionRequest(ctx context.Context, sessionRequestJSON string) (*wc.SessionRequestResponse, error) {
|
func (api *API) WCSessionRequest(ctx context.Context, sessionRequestJSON string) (*transfer.TxResponse, error) {
|
||||||
log.Debug("wallet.api.wc.SessionRequest", "request.len", len(sessionRequestJSON))
|
log.Debug("wallet.api.wc.SessionRequest", "request.len", len(sessionRequestJSON))
|
||||||
|
|
||||||
var request wc.SessionRequest
|
var request wc.SessionRequest
|
||||||
|
|
|
@ -144,7 +144,7 @@ func NewService(
|
||||||
|
|
||||||
activity := activity.NewService(db, tokenManager, collectiblesManager, feed)
|
activity := activity.NewService(db, tokenManager, collectiblesManager, feed)
|
||||||
|
|
||||||
walletconnect := walletconnect.NewService(db, rpcClient.NetworkManager, accountsDB, transactor, gethManager, feed, config)
|
walletconnect := walletconnect.NewService(db, rpcClient.NetworkManager, accountsDB, transactionManager, gethManager, feed, config)
|
||||||
|
|
||||||
return &Service{
|
return &Service{
|
||||||
db: db,
|
db: db,
|
||||||
|
|
|
@ -132,8 +132,10 @@ type TxResponse struct {
|
||||||
AddressPath string `json:"addressPath,omitempty"`
|
AddressPath string `json:"addressPath,omitempty"`
|
||||||
SignOnKeycard bool `json:"signOnKeycard,omitempty"`
|
SignOnKeycard bool `json:"signOnKeycard,omitempty"`
|
||||||
ChainID uint64 `json:"chainId,omitempty"`
|
ChainID uint64 `json:"chainId,omitempty"`
|
||||||
MesageToSign interface{} `json:"messageToSign,omitempty"`
|
MessageToSign interface{} `json:"messageToSign,omitempty"`
|
||||||
TxArgs transactions.SendTxArgs `json:"txArgs,omitempty"`
|
TxArgs transactions.SendTxArgs `json:"txArgs,omitempty"`
|
||||||
|
RawTx string `json:"rawTx,omitempty"`
|
||||||
|
TxHash common.Hash `json:"txHash,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *TransactionManager) SignMessage(message types.HexBytes, address common.Address, password string) (string, error) {
|
func (tm *TransactionManager) SignMessage(message types.HexBytes, address common.Address, password string) (string, error) {
|
||||||
|
@ -159,15 +161,15 @@ func (tm *TransactionManager) BuildTransaction(chainID uint64, sendArgs transact
|
||||||
}
|
}
|
||||||
|
|
||||||
txBeingSigned, unlock, err := tm.transactor.ValidateAndBuildTransaction(chainID, sendArgs)
|
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.
|
// 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 {
|
if unlock != nil {
|
||||||
defer func() {
|
defer func() {
|
||||||
unlock(false, 0)
|
unlock(false, 0)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Set potential missing fields that were added while building the transaction
|
// Set potential missing fields that were added while building the transaction
|
||||||
if sendArgs.Value == nil {
|
if sendArgs.Value == nil {
|
||||||
|
@ -178,17 +180,24 @@ func (tm *TransactionManager) BuildTransaction(chainID uint64, sendArgs transact
|
||||||
nonce := hexutil.Uint64(txBeingSigned.Nonce())
|
nonce := hexutil.Uint64(txBeingSigned.Nonce())
|
||||||
sendArgs.Nonce = &nonce
|
sendArgs.Nonce = &nonce
|
||||||
}
|
}
|
||||||
|
if sendArgs.Gas == nil {
|
||||||
|
gas := hexutil.Uint64(txBeingSigned.Gas())
|
||||||
|
sendArgs.Gas = &gas
|
||||||
|
}
|
||||||
if sendArgs.GasPrice == nil {
|
if sendArgs.GasPrice == nil {
|
||||||
gasPrice := hexutil.Big(*txBeingSigned.GasPrice())
|
gasPrice := hexutil.Big(*txBeingSigned.GasPrice())
|
||||||
sendArgs.GasPrice = &gasPrice
|
sendArgs.GasPrice = &gasPrice
|
||||||
}
|
}
|
||||||
if sendArgs.MaxPriorityFeePerGas == nil {
|
|
||||||
maxPriorityFeePerGas := hexutil.Big(*txBeingSigned.GasTipCap())
|
if sendArgs.IsDynamicFeeTx() {
|
||||||
sendArgs.MaxPriorityFeePerGas = &maxPriorityFeePerGas
|
if sendArgs.MaxPriorityFeePerGas == nil {
|
||||||
}
|
maxPriorityFeePerGas := hexutil.Big(*txBeingSigned.GasTipCap())
|
||||||
if sendArgs.MaxFeePerGas == nil {
|
sendArgs.MaxPriorityFeePerGas = &maxPriorityFeePerGas
|
||||||
maxFeePerGas := hexutil.Big(*txBeingSigned.GasFeeCap())
|
}
|
||||||
sendArgs.MaxFeePerGas = &maxFeePerGas
|
if sendArgs.MaxFeePerGas == nil {
|
||||||
|
maxFeePerGas := hexutil.Big(*txBeingSigned.GasFeeCap())
|
||||||
|
sendArgs.MaxFeePerGas = &maxFeePerGas
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signer := ethTypes.NewLondonSigner(new(big.Int).SetUint64(chainID))
|
signer := ethTypes.NewLondonSigner(new(big.Int).SetUint64(chainID))
|
||||||
|
@ -199,11 +208,36 @@ func (tm *TransactionManager) BuildTransaction(chainID uint64, sendArgs transact
|
||||||
AddressPath: account.Path,
|
AddressPath: account.Path,
|
||||||
SignOnKeycard: kp.MigratedToKeycard(),
|
SignOnKeycard: kp.MigratedToKeycard(),
|
||||||
ChainID: chainID,
|
ChainID: chainID,
|
||||||
MesageToSign: signer.Hash(txBeingSigned),
|
MessageToSign: signer.Hash(txBeingSigned),
|
||||||
TxArgs: sendArgs,
|
TxArgs: sendArgs,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tm *TransactionManager) BuildRawTransaction(chainID uint64, sendArgs transactions.SendTxArgs, signature []byte) (response *TxResponse, err error) {
|
||||||
|
tx, unlock, err := tm.transactor.BuildTransactionWithSignature(chainID, sendArgs, signature)
|
||||||
|
// 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)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := tx.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &TxResponse{
|
||||||
|
ChainID: chainID,
|
||||||
|
TxArgs: sendArgs,
|
||||||
|
RawTx: types.EncodeHex(data),
|
||||||
|
TxHash: tx.Hash(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (tm *TransactionManager) SendTransactionWithSignature(chainID uint64, txType transactions.PendingTrxType, sendArgs transactions.SendTxArgs, signature []byte) (hash types.Hash, err error) {
|
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)
|
hash, err = tm.transactor.BuildTransactionAndSendWithSignature(chainID, sendArgs, signature)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
package walletconnect
|
package walletconnect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
ethTypes "github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"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/services/wallet/transfer"
|
||||||
"github.com/status-im/status-go/transactions"
|
"github.com/status-im/status-go/transactions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -65,7 +61,7 @@ func (n *sendTransactionParams) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(n.SendTxArgs)
|
return json.Marshal(n.SendTxArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) buildTransaction(request SessionRequest) (response *SessionRequestResponse, err error) {
|
func (s *Service) buildTransaction(request SessionRequest) (response *transfer.TxResponse, err error) {
|
||||||
if len(request.Params.Request.Params) != 1 {
|
if len(request.Params.Request.Params) != 1 {
|
||||||
return nil, ErrorInvalidParamsCount
|
return nil, ErrorInvalidParamsCount
|
||||||
}
|
}
|
||||||
|
@ -75,62 +71,16 @@ func (s *Service) buildTransaction(request SessionRequest) (response *SessionReq
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
account, err := s.accountsDB.GetAccountByAddress(params.From)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to get active account: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
kp, err := s.accountsDB.GetKeypairByKeyUID(account.KeyUID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, chainID, err := parseCaip2ChainID(request.Params.ChainID)
|
_, chainID, err := parseCaip2ChainID(request.Params.ChainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this case we can ignore `unlock` function received from `ValidateAndBuildTransaction` cause `Nonce`
|
return s.transactionManager.BuildTransaction(chainID, params.SendTxArgs)
|
||||||
// will be always set by the initiator of this transaction (by the dapp).
|
|
||||||
// Though we will need sort out completely that part since Nonce kept in the local cache is not the most recent one,
|
|
||||||
// instead of that we should always ask network what's the most recent known Nonce for the account.
|
|
||||||
// Logged issue to handle that: https://github.com/status-im/status-go/issues/4335
|
|
||||||
txBeingSigned, _, err := s.transactor.ValidateAndBuildTransaction(chainID, params.SendTxArgs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.txSignDetails = &txSigningDetails{
|
|
||||||
from: common.Address(account.Address),
|
|
||||||
chainID: chainID,
|
|
||||||
txBeingSigned: txBeingSigned,
|
|
||||||
}
|
|
||||||
|
|
||||||
signer := ethTypes.NewLondonSigner(new(big.Int).SetUint64(chainID))
|
|
||||||
return &SessionRequestResponse{
|
|
||||||
KeyUID: account.KeyUID,
|
|
||||||
Address: account.Address,
|
|
||||||
AddressPath: account.Path,
|
|
||||||
SignOnKeycard: kp.MigratedToKeycard(),
|
|
||||||
MessageToSign: signer.Hash(txBeingSigned),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) addSignatureToTransaction(signature string) (*ethTypes.Transaction, error) {
|
|
||||||
if s.txSignDetails.txBeingSigned == nil {
|
|
||||||
return nil, errors.New("no tx to sign")
|
|
||||||
}
|
|
||||||
|
|
||||||
signatureBytes, err := hex.DecodeString(signature)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.transactor.AddSignatureToTransaction(s.txSignDetails.chainID, s.txSignDetails.txBeingSigned, signatureBytes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) buildMessage(request SessionRequest, addressIndex int, messageIndex int,
|
func (s *Service) buildMessage(request SessionRequest, addressIndex int, messageIndex int,
|
||||||
handleTypedData bool) (response *SessionRequestResponse, err error) {
|
handleTypedData bool) (response *transfer.TxResponse, err error) {
|
||||||
if len(request.Params.Request.Params) != 2 {
|
if len(request.Params.Request.Params) != 2 {
|
||||||
return nil, ErrorInvalidParamsCount
|
return nil, ErrorInvalidParamsCount
|
||||||
}
|
}
|
||||||
|
@ -178,7 +128,7 @@ func (s *Service) buildMessage(request SessionRequest, addressIndex int, message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &SessionRequestResponse{
|
return &transfer.TxResponse{
|
||||||
KeyUID: account.KeyUID,
|
KeyUID: account.KeyUID,
|
||||||
Address: account.Address,
|
Address: account.Address,
|
||||||
AddressPath: account.Path,
|
AddressPath: account.Path,
|
||||||
|
|
|
@ -6,102 +6,42 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
ethTypes "github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
||||||
"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/types"
|
|
||||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||||
"github.com/status-im/status-go/params"
|
"github.com/status-im/status-go/params"
|
||||||
"github.com/status-im/status-go/rpc/network"
|
"github.com/status-im/status-go/rpc/network"
|
||||||
"github.com/status-im/status-go/transactions"
|
"github.com/status-im/status-go/services/wallet/transfer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type txSigningDetails struct {
|
|
||||||
chainID uint64
|
|
||||||
from common.Address
|
|
||||||
txBeingSigned *ethTypes.Transaction
|
|
||||||
txHash common.Hash
|
|
||||||
}
|
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
networkManager *network.Manager
|
networkManager *network.Manager
|
||||||
accountsDB *accounts.Database
|
accountsDB *accounts.Database
|
||||||
eventFeed *event.Feed
|
eventFeed *event.Feed
|
||||||
|
|
||||||
transactor *transactions.Transactor
|
transactionManager *transfer.TransactionManager
|
||||||
gethManager *account.GethManager
|
gethManager *account.GethManager
|
||||||
|
|
||||||
config *params.NodeConfig
|
config *params.NodeConfig
|
||||||
txSignDetails *txSigningDetails
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(db *sql.DB, networkManager *network.Manager, accountsDB *accounts.Database, transactor *transactions.Transactor, gethManager *account.GethManager, eventFeed *event.Feed, config *params.NodeConfig) *Service {
|
func NewService(db *sql.DB, networkManager *network.Manager, accountsDB *accounts.Database,
|
||||||
|
transactionManager *transfer.TransactionManager, gethManager *account.GethManager, eventFeed *event.Feed,
|
||||||
|
config *params.NodeConfig) *Service {
|
||||||
return &Service{
|
return &Service{
|
||||||
db: db,
|
db: db,
|
||||||
networkManager: networkManager,
|
networkManager: networkManager,
|
||||||
accountsDB: accountsDB,
|
accountsDB: accountsDB,
|
||||||
eventFeed: eventFeed,
|
eventFeed: eventFeed,
|
||||||
transactor: transactor,
|
transactionManager: transactionManager,
|
||||||
gethManager: gethManager,
|
gethManager: gethManager,
|
||||||
config: config,
|
config: config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) SignMessage(message types.HexBytes, address common.Address, password string) (string, error) {
|
|
||||||
selectedAccount, err := s.gethManager.VerifyAccountPassword(s.config.KeyStoreDir, address.Hex(), password)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
signature, err := crypto.Sign(message[:], selectedAccount.PrivateKey)
|
|
||||||
|
|
||||||
return types.EncodeHex(signature), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) BuildRawTransaction(signature string) (string, error) {
|
|
||||||
txWithSignature, err := s.addSignatureToTransaction(signature)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := txWithSignature.MarshalBinary()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.txSignDetails.txHash = txWithSignature.Hash()
|
|
||||||
|
|
||||||
return types.EncodeHex(data), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) SendRawTransaction(rawTx string) (string, error) {
|
|
||||||
err := s.transactor.SendRawTransaction(s.txSignDetails.chainID, rawTx)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.txSignDetails.txHash.Hex(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) SendTransactionWithSignature(signature string) (string, error) {
|
|
||||||
txWithSignature, err := s.addSignatureToTransaction(signature)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
hash, err := s.transactor.SendTransactionWithSignature(txWithSignature)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash.Hex(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) PairSessionProposal(proposal SessionProposal) (*PairSessionResponse, error) {
|
func (s *Service) PairSessionProposal(proposal SessionProposal) (*PairSessionResponse, error) {
|
||||||
if !proposal.Valid() {
|
if !proposal.Valid() {
|
||||||
return nil, ErrorInvalidSessionProposal
|
return nil, ErrorInvalidSessionProposal
|
||||||
|
@ -208,7 +148,7 @@ func (s *Service) HasActivePairings() (bool, error) {
|
||||||
return HasActivePairings(s.db, time.Now().Unix())
|
return HasActivePairings(s.db, time.Now().Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) SessionRequest(request SessionRequest) (response *SessionRequestResponse, err error) {
|
func (s *Service) SessionRequest(request SessionRequest) (response *transfer.TxResponse, err error) {
|
||||||
// TODO #12434: should we check topic for validity? It might make sense if we
|
// TODO #12434: should we check topic for validity? It might make sense if we
|
||||||
// want to cache the paired sessions
|
// want to cache the paired sessions
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
|
||||||
"github.com/status-im/status-go/eth-node/types"
|
|
||||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||||
"github.com/status-im/status-go/services/wallet/walletevent"
|
"github.com/status-im/status-go/services/wallet/walletevent"
|
||||||
)
|
)
|
||||||
|
@ -102,14 +101,6 @@ type SessionDelete struct {
|
||||||
Topic Topic `json:"topic"`
|
Topic Topic `json:"topic"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SessionRequestResponse struct {
|
|
||||||
KeyUID string `json:"keyUid,omitempty"`
|
|
||||||
Address types.Address `json:"address,omitempty"`
|
|
||||||
AddressPath string `json:"addressPath,omitempty"`
|
|
||||||
SignOnKeycard bool `json:"signOnKeycard,omitempty"`
|
|
||||||
MessageToSign interface{} `json:"messageToSign,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid namespace
|
// Valid namespace
|
||||||
func (n *Namespace) Valid(namespaceName string, chainID *uint64) bool {
|
func (n *Namespace) Valid(namespaceName string, chainID *uint64) bool {
|
||||||
if chainID == nil {
|
if chainID == nil {
|
||||||
|
|
|
@ -359,6 +359,7 @@ const (
|
||||||
BurnCommunityToken PendingTrxType = "BurnCommunityToken"
|
BurnCommunityToken PendingTrxType = "BurnCommunityToken"
|
||||||
DeployOwnerToken PendingTrxType = "DeployOwnerToken"
|
DeployOwnerToken PendingTrxType = "DeployOwnerToken"
|
||||||
SetSignerPublicKey PendingTrxType = "SetSignerPublicKey"
|
SetSignerPublicKey PendingTrxType = "SetSignerPublicKey"
|
||||||
|
WalletConnectTransfer PendingTrxType = "WalletConnectTransfer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PendingTransaction struct {
|
type PendingTransaction struct {
|
||||||
|
|
|
@ -167,32 +167,50 @@ func (t *Transactor) AddSignatureToTransactionAndSend(chainID uint64, tx *gethty
|
||||||
// It's different from eth_sendRawTransaction because it receives a signature and not a serialized transaction with signature.
|
// It's different from eth_sendRawTransaction because it receives a signature and not a serialized transaction with signature.
|
||||||
// Since the transactions is already signed, we assume it was validated and used the right nonce.
|
// Since the transactions is already signed, we assume it was validated and used the right nonce.
|
||||||
func (t *Transactor) BuildTransactionAndSendWithSignature(chainID uint64, args SendTxArgs, sig []byte) (hash types.Hash, err error) {
|
func (t *Transactor) BuildTransactionAndSendWithSignature(chainID uint64, args SendTxArgs, sig []byte) (hash types.Hash, err error) {
|
||||||
|
txWithSignature, unlock, err := t.BuildTransactionWithSignature(chainID, args, sig)
|
||||||
|
if unlock != nil {
|
||||||
|
defer func() {
|
||||||
|
var nonce uint64
|
||||||
|
if txWithSignature != nil {
|
||||||
|
nonce = txWithSignature.Nonce()
|
||||||
|
}
|
||||||
|
unlock(err == nil, nonce)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return hash, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, err = t.SendTransactionWithSignature(txWithSignature)
|
||||||
|
return hash, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Transactor) BuildTransactionWithSignature(chainID uint64, args SendTxArgs, sig []byte) (*gethtypes.Transaction, UnlockNonceFunc, error) {
|
||||||
if !args.Valid() {
|
if !args.Valid() {
|
||||||
return hash, ErrInvalidSendTxArgs
|
return nil, nil, ErrInvalidSendTxArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(sig) != ValidSignatureSize {
|
if len(sig) != ValidSignatureSize {
|
||||||
return hash, ErrInvalidSignatureSize
|
return nil, nil, ErrInvalidSignatureSize
|
||||||
}
|
}
|
||||||
|
|
||||||
tx := t.buildTransaction(args)
|
tx := t.buildTransaction(args)
|
||||||
rpcWrapper := newRPCWrapper(t.rpcWrapper.RPCClient, chainID)
|
rpcWrapper := newRPCWrapper(t.rpcWrapper.RPCClient, chainID)
|
||||||
expectedNonce, unlock, err := t.nonce.Next(rpcWrapper, args.From)
|
expectedNonce, unlock, err := t.nonce.Next(rpcWrapper, args.From)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hash, err
|
return nil, nil, err
|
||||||
}
|
|
||||||
if unlock != nil {
|
|
||||||
defer func() {
|
|
||||||
unlock(err == nil, expectedNonce)
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if tx.Nonce() != expectedNonce {
|
if tx.Nonce() != expectedNonce {
|
||||||
return hash, &ErrBadNonce{tx.Nonce(), expectedNonce}
|
return nil, unlock, &ErrBadNonce{tx.Nonce(), expectedNonce}
|
||||||
}
|
}
|
||||||
|
|
||||||
hash, err = t.AddSignatureToTransactionAndSend(chainID, tx, sig)
|
txWithSignature, err := t.AddSignatureToTransaction(chainID, tx, sig)
|
||||||
return hash, err
|
if err != nil {
|
||||||
|
return nil, unlock, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return txWithSignature, unlock, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
Loading…
Reference in New Issue