feat(connector)_: impl `personal_sign` endpoint (#5681)
This commit is contained in:
parent
c08dedb77d
commit
be9ba7604b
|
@ -23,10 +23,15 @@ func NewAPI(s *Service) *API {
|
||||||
r := NewCommandRegistry()
|
r := NewCommandRegistry()
|
||||||
c := commands.NewClientSideHandler()
|
c := commands.NewClientSideHandler()
|
||||||
|
|
||||||
|
// Transactions and signing
|
||||||
r.Register("eth_sendTransaction", &commands.SendTransactionCommand{
|
r.Register("eth_sendTransaction", &commands.SendTransactionCommand{
|
||||||
Db: s.db,
|
Db: s.db,
|
||||||
ClientHandler: c,
|
ClientHandler: c,
|
||||||
})
|
})
|
||||||
|
r.Register("personal_sign", &commands.PersonalSignCommand{
|
||||||
|
Db: s.db,
|
||||||
|
ClientHandler: c,
|
||||||
|
})
|
||||||
|
|
||||||
// Accounts query and dapp permissions
|
// Accounts query and dapp permissions
|
||||||
// NOTE: Some dApps expect same behavior for both eth_accounts and eth_requestAccounts
|
// NOTE: Some dApps expect same behavior for both eth_accounts and eth_requestAccounts
|
||||||
|
@ -126,3 +131,11 @@ func (api *API) SendTransactionAccepted(args commands.SendTransactionAcceptedArg
|
||||||
func (api *API) SendTransactionRejected(args commands.RejectedArgs) error {
|
func (api *API) SendTransactionRejected(args commands.RejectedArgs) error {
|
||||||
return api.c.SendTransactionRejected(args)
|
return api.c.SendTransactionRejected(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) PersonalSignAccepted(args commands.PersonalSignAcceptedArgs) error {
|
||||||
|
return api.c.PersonalSignAccepted(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) PersonalSignRejected(args commands.RejectedArgs) error {
|
||||||
|
return api.c.PersonalSignRejected(args)
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ var (
|
||||||
ErrEmptyAccountsShared = fmt.Errorf("empty accounts were shared by wallet")
|
ErrEmptyAccountsShared = fmt.Errorf("empty accounts were shared by wallet")
|
||||||
ErrRequestAccountsRejectedByUser = fmt.Errorf("request accounts was rejected by user")
|
ErrRequestAccountsRejectedByUser = fmt.Errorf("request accounts was rejected by user")
|
||||||
ErrSendTransactionRejectedByUser = fmt.Errorf("send transaction was rejected by user")
|
ErrSendTransactionRejectedByUser = fmt.Errorf("send transaction was rejected by user")
|
||||||
|
ErrPersonalSignRejectedByUser = fmt.Errorf("personal sign was rejected by user")
|
||||||
ErrEmptyRequestID = fmt.Errorf("empty requestID")
|
ErrEmptyRequestID = fmt.Errorf("empty requestID")
|
||||||
ErrAnotherConnectorOperationIsAwaitingFor = fmt.Errorf("another connector operation is awaiting for user input")
|
ErrAnotherConnectorOperationIsAwaitingFor = fmt.Errorf("another connector operation is awaiting for user input")
|
||||||
)
|
)
|
||||||
|
@ -29,6 +30,7 @@ type MessageType int
|
||||||
const (
|
const (
|
||||||
RequestAccountsAccepted MessageType = iota
|
RequestAccountsAccepted MessageType = iota
|
||||||
SendTransactionAccepted
|
SendTransactionAccepted
|
||||||
|
PersonalSignAccepted
|
||||||
Rejected
|
Rejected
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -95,6 +97,20 @@ func (c *ClientSideHandler) RequestShareAccountForDApp(dApp signal.ConnectorDApp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ClientSideHandler) RequestAccountsAccepted(args RequestAccountsAcceptedArgs) error {
|
||||||
|
c.responseChannel <- Message{Type: RequestAccountsAccepted, Data: args}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClientSideHandler) RequestAccountsRejected(args RejectedArgs) error {
|
||||||
|
if args.RequestID == "" {
|
||||||
|
return ErrEmptyRequestID
|
||||||
|
}
|
||||||
|
|
||||||
|
c.responseChannel <- Message{Type: Rejected, Data: args}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ClientSideHandler) RequestSendTransaction(dApp signal.ConnectorDApp, chainID uint64, txArgs *transactions.SendTxArgs) (types.Hash, error) {
|
func (c *ClientSideHandler) RequestSendTransaction(dApp signal.ConnectorDApp, chainID uint64, txArgs *transactions.SendTxArgs) (types.Hash, error) {
|
||||||
if !c.setRequestRunning() {
|
if !c.setRequestRunning() {
|
||||||
return types.Hash{}, ErrAnotherConnectorOperationIsAwaitingFor
|
return types.Hash{}, ErrAnotherConnectorOperationIsAwaitingFor
|
||||||
|
@ -132,20 +148,6 @@ func (c *ClientSideHandler) RequestSendTransaction(dApp signal.ConnectorDApp, ch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientSideHandler) RequestAccountsAccepted(args RequestAccountsAcceptedArgs) error {
|
|
||||||
c.responseChannel <- Message{Type: RequestAccountsAccepted, Data: args}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ClientSideHandler) RequestAccountsRejected(args RejectedArgs) error {
|
|
||||||
if args.RequestID == "" {
|
|
||||||
return ErrEmptyRequestID
|
|
||||||
}
|
|
||||||
|
|
||||||
c.responseChannel <- Message{Type: Rejected, Data: args}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ClientSideHandler) SendTransactionAccepted(args SendTransactionAcceptedArgs) error {
|
func (c *ClientSideHandler) SendTransactionAccepted(args SendTransactionAcceptedArgs) error {
|
||||||
if args.RequestID == "" {
|
if args.RequestID == "" {
|
||||||
return ErrEmptyRequestID
|
return ErrEmptyRequestID
|
||||||
|
@ -163,3 +165,53 @@ func (c *ClientSideHandler) SendTransactionRejected(args RejectedArgs) error {
|
||||||
c.responseChannel <- Message{Type: Rejected, Data: args}
|
c.responseChannel <- Message{Type: Rejected, Data: args}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ClientSideHandler) RequestPersonalSign(dApp signal.ConnectorDApp, challenge, address string) (string, error) {
|
||||||
|
if !c.setRequestRunning() {
|
||||||
|
return "", ErrAnotherConnectorOperationIsAwaitingFor
|
||||||
|
}
|
||||||
|
defer c.clearRequestRunning()
|
||||||
|
|
||||||
|
requestID := c.generateRequestID(dApp)
|
||||||
|
signal.SendConnectorPersonalSign(dApp, requestID, challenge, address)
|
||||||
|
|
||||||
|
timeout := time.After(WalletResponseMaxInterval)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case msg := <-c.responseChannel:
|
||||||
|
switch msg.Type {
|
||||||
|
case PersonalSignAccepted:
|
||||||
|
response := msg.Data.(PersonalSignAcceptedArgs)
|
||||||
|
if response.RequestID == requestID {
|
||||||
|
return response.Signature, nil
|
||||||
|
}
|
||||||
|
case Rejected:
|
||||||
|
response := msg.Data.(RejectedArgs)
|
||||||
|
if response.RequestID == requestID {
|
||||||
|
return "", ErrPersonalSignRejectedByUser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case <-timeout:
|
||||||
|
return "", ErrWalletResponseTimeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClientSideHandler) PersonalSignAccepted(args PersonalSignAcceptedArgs) error {
|
||||||
|
if args.RequestID == "" {
|
||||||
|
return ErrEmptyRequestID
|
||||||
|
}
|
||||||
|
|
||||||
|
c.responseChannel <- Message{Type: PersonalSignAccepted, Data: args}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClientSideHandler) PersonalSignRejected(args RejectedArgs) error {
|
||||||
|
if args.RequestID == "" {
|
||||||
|
return ErrEmptyRequestID
|
||||||
|
}
|
||||||
|
|
||||||
|
c.responseChannel <- Message{Type: Rejected, Data: args}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
persistence "github.com/status-im/status-go/services/connector/database"
|
||||||
|
"github.com/status-im/status-go/signal"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidParamsStructure = errors.New("invalid params structure")
|
||||||
|
)
|
||||||
|
|
||||||
|
type PersonalSignCommand struct {
|
||||||
|
Db *sql.DB
|
||||||
|
ClientHandler ClientSideHandlerInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
type PersonalSignParams struct {
|
||||||
|
Challenge string `json:"challenge"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RPCRequest) getPersonalSignParams() (*PersonalSignParams, error) {
|
||||||
|
if r.Params == nil || len(r.Params) == 0 {
|
||||||
|
return nil, ErrEmptyRPCParams
|
||||||
|
}
|
||||||
|
|
||||||
|
paramMap, ok := r.Params[0].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrInvalidParamsStructure
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the Challenge and Address fields from paramMap
|
||||||
|
challenge, ok := paramMap["challenge"].(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("missing or invalid 'challenge' field")
|
||||||
|
}
|
||||||
|
|
||||||
|
address, ok := paramMap["address"].(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("missing or invalid 'address' field")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and return the PersonalSignParams
|
||||||
|
return &PersonalSignParams{
|
||||||
|
Challenge: challenge,
|
||||||
|
Address: address,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PersonalSignCommand) Execute(request RPCRequest) (interface{}, error) {
|
||||||
|
err := request.Validate()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
params, err := request.getPersonalSignParams()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
dApp, err := persistence.SelectDAppByUrl(c.Db, request.URL)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if dApp == nil {
|
||||||
|
return "", ErrDAppIsNotPermittedByUser
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.ClientHandler.RequestPersonalSign(signal.ConnectorDApp{
|
||||||
|
URL: request.URL,
|
||||||
|
Name: request.Name,
|
||||||
|
IconURL: request.IconURL,
|
||||||
|
}, params.Challenge, params.Address)
|
||||||
|
}
|
|
@ -0,0 +1,183 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/signal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func preparePersonalSignRequest(dApp signal.ConnectorDApp, challenge, address string) (RPCRequest, error) {
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"challenge": challenge,
|
||||||
|
"address": address,
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConstructRPCRequest("personal_sign", []interface{}{params}, &dApp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFailToPersonalSignWithMissingDAppFields(t *testing.T) {
|
||||||
|
db, close := SetupTestDB(t)
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
cmd := &PersonalSignCommand{Db: db}
|
||||||
|
|
||||||
|
// Missing DApp fields
|
||||||
|
request, err := ConstructRPCRequest("personal_sign", []interface{}{}, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
result, err := cmd.Execute(request)
|
||||||
|
assert.Equal(t, ErrRequestMissingDAppData, err)
|
||||||
|
assert.Empty(t, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFailToPersonalSignForUnpermittedDApp(t *testing.T) {
|
||||||
|
db, close := SetupTestDB(t)
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
cmd := &PersonalSignCommand{Db: db}
|
||||||
|
|
||||||
|
request, err := preparePersonalSignRequest(testDAppData,
|
||||||
|
"0x506c65617365207369676e2074686973206d65737361676520746f20636f6e6669726d20796f7572206964656e746974792e",
|
||||||
|
"0x4B0897b0513FdBeEc7C469D9aF4fA6C0752aBea7",
|
||||||
|
)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
result, err := cmd.Execute(request)
|
||||||
|
assert.Equal(t, ErrDAppIsNotPermittedByUser, err)
|
||||||
|
assert.Empty(t, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFailToPersonalSignWithoutParams(t *testing.T) {
|
||||||
|
db, close := SetupTestDB(t)
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
cmd := &PersonalSignCommand{Db: db}
|
||||||
|
|
||||||
|
request, err := ConstructRPCRequest("personal_sign", nil, &testDAppData)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
result, err := cmd.Execute(request)
|
||||||
|
assert.Equal(t, ErrEmptyRPCParams, err)
|
||||||
|
assert.Empty(t, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFailToPersonalSignWithSignalTimout(t *testing.T) {
|
||||||
|
db, close := SetupTestDB(t)
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
clientHandler := NewClientSideHandler()
|
||||||
|
|
||||||
|
cmd := &PersonalSignCommand{
|
||||||
|
Db: db,
|
||||||
|
ClientHandler: clientHandler,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := PersistDAppData(db, testDAppData, types.Address{0x01}, uint64(0x1))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
request, err := preparePersonalSignRequest(testDAppData,
|
||||||
|
"0x506c65617365207369676e2074686973206d65737361676520746f20636f6e6669726d20796f7572206964656e746974792e",
|
||||||
|
"0x4B0897b0513FdBeEc7C469D9aF4fA6C0752aBea7",
|
||||||
|
)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
backupWalletResponseMaxInterval := WalletResponseMaxInterval
|
||||||
|
WalletResponseMaxInterval = 1 * time.Millisecond
|
||||||
|
|
||||||
|
_, err = cmd.Execute(request)
|
||||||
|
assert.Equal(t, ErrWalletResponseTimeout, err)
|
||||||
|
WalletResponseMaxInterval = backupWalletResponseMaxInterval
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPersonalSignWithSignalAccepted(t *testing.T) {
|
||||||
|
db, close := SetupTestDB(t)
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
fakedSignature := "0x051"
|
||||||
|
|
||||||
|
clientHandler := NewClientSideHandler()
|
||||||
|
|
||||||
|
cmd := &PersonalSignCommand{
|
||||||
|
Db: db,
|
||||||
|
ClientHandler: clientHandler,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := PersistDAppData(db, testDAppData, types.Address{0x01}, uint64(0x1))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
challenge := "0x506c65617365207369676e2074686973206d65737361676520746f20636f6e6669726d20796f7572206964656e746974792e"
|
||||||
|
address := "0x4B0897b0513FdBeEc7C469D9aF4fA6C0752aBea7"
|
||||||
|
request, err := preparePersonalSignRequest(testDAppData, challenge, address)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
signal.SetMobileSignalHandler(signal.MobileSignalHandler(func(s []byte) {
|
||||||
|
var evt EventType
|
||||||
|
err := json.Unmarshal(s, &evt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
switch evt.Type {
|
||||||
|
case signal.EventConnectorPersonalSign:
|
||||||
|
var ev signal.ConnectorPersonalSignSignal
|
||||||
|
err := json.Unmarshal(evt.Event, &ev)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, ev.Challenge, challenge)
|
||||||
|
assert.Equal(t, ev.Address, address)
|
||||||
|
|
||||||
|
err = clientHandler.PersonalSignAccepted(PersonalSignAcceptedArgs{
|
||||||
|
Signature: fakedSignature,
|
||||||
|
RequestID: ev.RequestID,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
response, err := cmd.Execute(request)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, response, fakedSignature)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPersonalSignWithSignalRejected(t *testing.T) {
|
||||||
|
db, close := SetupTestDB(t)
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
clientHandler := NewClientSideHandler()
|
||||||
|
|
||||||
|
cmd := &PersonalSignCommand{
|
||||||
|
Db: db,
|
||||||
|
ClientHandler: clientHandler,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := PersistDAppData(db, testDAppData, types.Address{0x01}, uint64(0x1))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
challenge := "0x506c65617365207369676e2074686973206d65737361676520746f20636f6e6669726d20796f7572206964656e746974792e"
|
||||||
|
address := "0x4B0897b0513FdBeEc7C469D9aF4fA6C0752aBea7"
|
||||||
|
request, err := preparePersonalSignRequest(testDAppData, challenge, address)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
signal.SetMobileSignalHandler(signal.MobileSignalHandler(func(s []byte) {
|
||||||
|
var evt EventType
|
||||||
|
err := json.Unmarshal(s, &evt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
switch evt.Type {
|
||||||
|
case signal.EventConnectorPersonalSign:
|
||||||
|
var ev signal.ConnectorPersonalSignSignal
|
||||||
|
err := json.Unmarshal(evt.Event, &ev)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = clientHandler.PersonalSignRejected(RejectedArgs{
|
||||||
|
RequestID: ev.RequestID,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
_, err = cmd.Execute(request)
|
||||||
|
assert.Equal(t, ErrPersonalSignRejectedByUser, err)
|
||||||
|
}
|
|
@ -43,18 +43,27 @@ type SendTransactionAcceptedArgs struct {
|
||||||
Hash types.Hash `json:"hash"`
|
Hash types.Hash `json:"hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PersonalSignAcceptedArgs struct {
|
||||||
|
RequestID string `json:"requestId"`
|
||||||
|
Signature string `json:"signature"`
|
||||||
|
}
|
||||||
|
|
||||||
type RejectedArgs struct {
|
type RejectedArgs struct {
|
||||||
RequestID string `json:"requestId"`
|
RequestID string `json:"requestId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientSideHandlerInterface interface {
|
type ClientSideHandlerInterface interface {
|
||||||
RequestShareAccountForDApp(dApp signal.ConnectorDApp) (types.Address, uint64, error)
|
RequestShareAccountForDApp(dApp signal.ConnectorDApp) (types.Address, uint64, error)
|
||||||
RequestSendTransaction(dApp signal.ConnectorDApp, chainID uint64, txArgs *transactions.SendTxArgs) (types.Hash, error)
|
|
||||||
|
|
||||||
RequestAccountsAccepted(args RequestAccountsAcceptedArgs) error
|
RequestAccountsAccepted(args RequestAccountsAcceptedArgs) error
|
||||||
RequestAccountsRejected(args RejectedArgs) error
|
RequestAccountsRejected(args RejectedArgs) error
|
||||||
|
|
||||||
|
RequestSendTransaction(dApp signal.ConnectorDApp, chainID uint64, txArgs *transactions.SendTxArgs) (types.Hash, error)
|
||||||
SendTransactionAccepted(args SendTransactionAcceptedArgs) error
|
SendTransactionAccepted(args SendTransactionAcceptedArgs) error
|
||||||
SendTransactionRejected(args RejectedArgs) error
|
SendTransactionRejected(args RejectedArgs) error
|
||||||
|
|
||||||
|
RequestPersonalSign(dApp signal.ConnectorDApp, challenge, address string) (string, error)
|
||||||
|
PersonalSignAccepted(args PersonalSignAcceptedArgs) error
|
||||||
|
PersonalSignRejected(args RejectedArgs) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetworkManagerInterface interface {
|
type NetworkManagerInterface interface {
|
||||||
|
|
|
@ -38,6 +38,7 @@ func TestRequestAccountsSwitchChainAndSendTransactionFlow(t *testing.T) {
|
||||||
|
|
||||||
accountAddress := types.BytesToAddress(types.FromHex("0x6d0aa2a774b74bb1d36f97700315adf962c69fcg"))
|
accountAddress := types.BytesToAddress(types.FromHex("0x6d0aa2a774b74bb1d36f97700315adf962c69fcg"))
|
||||||
expectedHash := types.BytesToHash(types.FromHex("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"))
|
expectedHash := types.BytesToHash(types.FromHex("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"))
|
||||||
|
expectedSignature := "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
|
||||||
|
|
||||||
dAppPermissionRevoked := false
|
dAppPermissionRevoked := false
|
||||||
dAppPermissionGranted := false
|
dAppPermissionGranted := false
|
||||||
|
@ -73,6 +74,16 @@ func TestRequestAccountsSwitchChainAndSendTransactionFlow(t *testing.T) {
|
||||||
Hash: expectedHash,
|
Hash: expectedHash,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
case signal.EventConnectorPersonalSign:
|
||||||
|
var ev signal.ConnectorPersonalSignSignal
|
||||||
|
err := json.Unmarshal(evt.Event, &ev)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = api.PersonalSignAccepted(commands.PersonalSignAcceptedArgs{
|
||||||
|
RequestID: ev.RequestID,
|
||||||
|
Signature: expectedSignature,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -110,6 +121,12 @@ func TestRequestAccountsSwitchChainAndSendTransactionFlow(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, expectedHash.Hex(), response)
|
assert.Equal(t, expectedHash.Hex(), response)
|
||||||
|
|
||||||
|
// Personal sign
|
||||||
|
request = "{\"method\": \"personal_sign\", \"params\":[{\"challenge\": \"0x506c65617365207369676e2074686973206d65737361676520746f20636f6e6669726d20796f7572206964656e746974792e\",\"address\":\"0x4B0897b0513FdBeEc7C469D9aF4fA6C0752aBea7\"}], \"url\": \"http://testDAppURL123\", \"name\": \"testDAppName\", \"iconUrl\": \"http://testDAppIconUrl\" }"
|
||||||
|
response, err = api.CallRPC(request)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedSignature, response)
|
||||||
|
|
||||||
// Revoke permissions
|
// Revoke permissions
|
||||||
request = "{\"method\": \"wallet_revokePermissions\", \"params\": [], \"url\": \"http://testDAppURL123\", \"name\": \"testDAppName\", \"iconUrl\": \"http://testDAppIconUrl\" }"
|
request = "{\"method\": \"wallet_revokePermissions\", \"params\": [], \"url\": \"http://testDAppURL123\", \"name\": \"testDAppName\", \"iconUrl\": \"http://testDAppIconUrl\" }"
|
||||||
_, err = api.CallRPC(request)
|
_, err = api.CallRPC(request)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package signal
|
||||||
const (
|
const (
|
||||||
EventConnectorSendRequestAccounts = "connector.sendRequestAccounts"
|
EventConnectorSendRequestAccounts = "connector.sendRequestAccounts"
|
||||||
EventConnectorSendTransaction = "connector.sendTransaction"
|
EventConnectorSendTransaction = "connector.sendTransaction"
|
||||||
|
EventConnectorPersonalSign = "connector.personalSign"
|
||||||
EventConnectorDAppPermissionGranted = "connector.dAppPermissionGranted"
|
EventConnectorDAppPermissionGranted = "connector.dAppPermissionGranted"
|
||||||
EventConnectorDAppPermissionRevoked = "connector.dAppPermissionRevoked"
|
EventConnectorDAppPermissionRevoked = "connector.dAppPermissionRevoked"
|
||||||
)
|
)
|
||||||
|
@ -27,6 +28,13 @@ type ConnectorSendTransactionSignal struct {
|
||||||
TxArgs string `json:"txArgs"`
|
TxArgs string `json:"txArgs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ConnectorPersonalSignSignal struct {
|
||||||
|
ConnectorDApp
|
||||||
|
RequestID string `json:"requestId"`
|
||||||
|
Challenge string `json:"challenge"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
func SendConnectorSendRequestAccounts(dApp ConnectorDApp, requestID string) {
|
func SendConnectorSendRequestAccounts(dApp ConnectorDApp, requestID string) {
|
||||||
send(EventConnectorSendRequestAccounts, ConnectorSendRequestAccountsSignal{
|
send(EventConnectorSendRequestAccounts, ConnectorSendRequestAccountsSignal{
|
||||||
ConnectorDApp: dApp,
|
ConnectorDApp: dApp,
|
||||||
|
@ -43,6 +51,15 @@ func SendConnectorSendTransaction(dApp ConnectorDApp, chainID uint64, txArgs str
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SendConnectorPersonalSign(dApp ConnectorDApp, requestID, challenge, address string) {
|
||||||
|
send(EventConnectorPersonalSign, ConnectorPersonalSignSignal{
|
||||||
|
ConnectorDApp: dApp,
|
||||||
|
RequestID: requestID,
|
||||||
|
Challenge: challenge,
|
||||||
|
Address: address,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func SendConnectorDAppPermissionGranted(dApp ConnectorDApp) {
|
func SendConnectorDAppPermissionGranted(dApp ConnectorDApp) {
|
||||||
send(EventConnectorDAppPermissionGranted, dApp)
|
send(EventConnectorDAppPermissionGranted, dApp)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue