2024-07-18 17:30:10 +02:00
|
|
|
package commands
|
|
|
|
|
|
|
|
import (
|
2024-09-19 20:24:06 +02:00
|
|
|
"context"
|
2024-07-18 17:30:10 +02:00
|
|
|
"database/sql"
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
2024-09-19 20:24:06 +02:00
|
|
|
"math/big"
|
2024-07-18 17:30:10 +02:00
|
|
|
|
2024-09-19 20:24:06 +02:00
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
|
|
"github.com/status-im/status-go/rpc"
|
2024-07-18 17:30:10 +02:00
|
|
|
persistence "github.com/status-im/status-go/services/connector/database"
|
2024-09-19 20:24:06 +02:00
|
|
|
"github.com/status-im/status-go/services/wallet/router/fees"
|
2024-11-05 22:28:24 +01:00
|
|
|
"github.com/status-im/status-go/services/wallet/wallettypes"
|
2024-07-18 17:30:10 +02:00
|
|
|
"github.com/status-im/status-go/signal"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ErrParamsFromAddressIsNotShared = errors.New("from parameter address is not dApp's shared account")
|
|
|
|
ErrNoTransactionParamsFound = errors.New("no transaction in params found")
|
2024-09-19 20:24:06 +02:00
|
|
|
ErrSendingParamsInvalid = errors.New("sending params are invalid")
|
2024-07-18 17:30:10 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type SendTransactionCommand struct {
|
2024-09-19 20:24:06 +02:00
|
|
|
RpcClient rpc.ClientInterface
|
2024-07-18 17:30:10 +02:00
|
|
|
Db *sql.DB
|
|
|
|
ClientHandler ClientSideHandlerInterface
|
|
|
|
}
|
|
|
|
|
2024-11-05 22:28:24 +01:00
|
|
|
func (r *RPCRequest) getSendTransactionParams() (*wallettypes.SendTxArgs, error) {
|
2024-07-18 17:30:10 +02:00
|
|
|
if r.Params == nil || len(r.Params) == 0 {
|
|
|
|
return nil, ErrEmptyRPCParams
|
|
|
|
}
|
|
|
|
|
|
|
|
paramMap, ok := r.Params[0].(map[string]interface{})
|
|
|
|
if !ok {
|
|
|
|
return nil, ErrNoTransactionParamsFound
|
|
|
|
}
|
|
|
|
|
|
|
|
paramBytes, err := json.Marshal(paramMap)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error marshalling first transaction param: %v", err)
|
|
|
|
}
|
|
|
|
|
2024-11-05 22:28:24 +01:00
|
|
|
var sendTxArgs wallettypes.SendTxArgs
|
2024-07-18 17:30:10 +02:00
|
|
|
err = json.Unmarshal(paramBytes, &sendTxArgs)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error unmarshalling first transaction param to SendTxArgs: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &sendTxArgs, nil
|
|
|
|
}
|
|
|
|
|
2024-09-19 20:24:06 +02:00
|
|
|
func (c *SendTransactionCommand) Execute(ctx context.Context, request RPCRequest) (interface{}, error) {
|
2024-07-18 17:30:10 +02:00
|
|
|
err := request.Validate()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
dApp, err := persistence.SelectDAppByUrl(c.Db, request.URL)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if dApp == nil {
|
|
|
|
return "", ErrDAppIsNotPermittedByUser
|
|
|
|
}
|
|
|
|
|
|
|
|
params, err := request.getSendTransactionParams()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2024-09-19 20:24:06 +02:00
|
|
|
if !params.Valid() {
|
|
|
|
return "", ErrSendingParamsInvalid
|
|
|
|
}
|
|
|
|
|
2024-07-18 17:30:10 +02:00
|
|
|
if params.From != dApp.SharedAccount {
|
|
|
|
return "", ErrParamsFromAddressIsNotShared
|
|
|
|
}
|
|
|
|
|
2024-09-19 20:24:06 +02:00
|
|
|
if params.Value == nil {
|
|
|
|
params.Value = (*hexutil.Big)(big.NewInt(0))
|
|
|
|
}
|
|
|
|
|
|
|
|
if params.GasPrice == nil || (params.MaxFeePerGas == nil && params.MaxPriorityFeePerGas == nil) {
|
|
|
|
feeManager := &fees.FeeManager{
|
|
|
|
RPCClient: c.RpcClient,
|
|
|
|
}
|
|
|
|
fetchedFees, err := feeManager.SuggestedFees(ctx, dApp.ChainID)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !fetchedFees.EIP1559Enabled {
|
|
|
|
params.GasPrice = (*hexutil.Big)(fetchedFees.GasPrice)
|
|
|
|
} else {
|
2025-01-29 00:34:23 +01:00
|
|
|
maxFees, priorityFee, err := fetchedFees.FeeFor(fees.GasFeeMedium)
|
feat(wallet)!: allowing client to set custom values for fees, nonce, gas
Removed properties from `Path` type:
- `MaxFeesPerGas`, based on the sending flow progress appropriate new properties (`TxMaxFeesPerGas`, `ApprovalMaxFeesPerGas`) should be used
Added new properties to `Path` type:
- `RouterInputParamsUuid`, used to identify from which router input params this path was created
- `TxNonce`, used to set nonce for the tx
- `TxMaxFeesPerGas`, used to set max fees per gas for the tx
- `TxEstimatedTime`, used to estimate time for executing the tx
- `ApprovalTxNonce`, used to set nonce for the approval tx
- `ApprovalTxMaxFeesPerGas`, used to set max fees per gas for the approval tx
- `ApprovalTxEstimatedTime`, used to estimate time for executing the approval tx
New request types added:
- `PathTxCustomParams`, used to pass tx custom params from the client
- `PathTxIdentity`, used to uniquely identify path (tx) to which the custom params need to be applied
New endpoints added:
- `SetFeeMode` used to set fee mode (`GasFeeLow`, `GasFeeMedium` or `GasFeeHigh`)
- `SetCustomTxDetails` used to set custom fee mode (`SetCustomTxDetails`), if this mode is set, client needs to provide:
- Max fees per gas
- Max priority fee
- Nonce
- Gas amount
2024-11-26 12:29:00 +01:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
params.MaxFeePerGas = (*hexutil.Big)(maxFees)
|
2025-01-29 00:34:23 +01:00
|
|
|
params.MaxPriorityFeePerGas = (*hexutil.Big)(priorityFee)
|
2024-09-19 20:24:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if params.Nonce == nil {
|
|
|
|
ethClient, err := c.RpcClient.EthClient(dApp.ChainID)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
nonce, err := ethClient.PendingNonceAt(ctx, common.Address(dApp.SharedAccount))
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
params.Nonce = (*hexutil.Uint64)(&nonce)
|
|
|
|
}
|
|
|
|
|
2024-07-18 17:30:10 +02:00
|
|
|
hash, err := c.ClientHandler.RequestSendTransaction(signal.ConnectorDApp{
|
|
|
|
URL: request.URL,
|
|
|
|
Name: request.Name,
|
|
|
|
IconURL: request.IconURL,
|
|
|
|
}, dApp.ChainID, params)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return hash.String(), nil
|
|
|
|
}
|