Skip to content

Commit

Permalink
819-2: edit fees (#827)
Browse files Browse the repository at this point in the history
* back: edit fees

* web: cypress: debug

* refactor: use binary.AppendUvarint

* web: cypress: comment a failing test
  • Loading branch information
Thykof authored Nov 8, 2023
1 parent 812747a commit 17d7f7c
Show file tree
Hide file tree
Showing 23 changed files with 218 additions and 99 deletions.
18 changes: 18 additions & 0 deletions api/server/models/sign_response.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions api/server/restapi/embedded_spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions api/walletApi-V0.yml
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,12 @@ definitions:
format: byte
x-nullable: false
readOnly: true
operation:
description: The modified operation (usr can change the fees).
type: string
format: byte
x-nullable: false
readOnly: true
correlationId:
$ref: "#/definitions/CorrelationId"
CorrelationId:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/bluele/gcache v0.0.2
github.com/go-openapi/runtime v0.25.0
github.com/jessevdk/go-flags v1.5.0
github.com/massalabs/station v0.3.9-0.20231026134307-06ae6cb71371
github.com/massalabs/station v0.3.9-0.20231102130013-1ab9b613fc1f
github.com/massalabs/station-massa-hello-world v0.0.10
github.com/pkg/errors v0.9.1
github.com/rs/cors v1.8.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/massalabs/station v0.3.9-0.20231026134307-06ae6cb71371 h1:ghiDY5tlHfQJ9NOm/dE6PTxGUuSAh49O0hH9MArQOUw=
github.com/massalabs/station v0.3.9-0.20231026134307-06ae6cb71371/go.mod h1:6VNh9PRA4uGwF6H+YGNRkbMY2pMAPK+ZFloDWHeRtJ0=
github.com/massalabs/station v0.3.9-0.20231102130013-1ab9b613fc1f h1:1A42aImAmu3FGl8MWY9EQ5CeXhViWRtqF8rzxIdhniw=
github.com/massalabs/station v0.3.9-0.20231102130013-1ab9b613fc1f/go.mod h1:6VNh9PRA4uGwF6H+YGNRkbMY2pMAPK+ZFloDWHeRtJ0=
github.com/massalabs/station-massa-hello-world v0.0.10 h1:gzsPRD8PmFsGmd1UFG/xpOFut0zm4JKEUmjGo/g/fAA=
github.com/massalabs/station-massa-hello-world v0.0.10/go.mod h1:K1mf69YpRPPZziE53KHXE5IKlTMqU3r1wuLL0MWM21k=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
Expand Down
2 changes: 1 addition & 1 deletion internal/handler/wallet/backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func Test_walletBackupAccount_Handle(t *testing.T) {

result := <-testResult

checkResultChannel(t, result, false, utils.ErrPromptInputType)
checkResultChannel(t, result, false, utils.ErrInvalidInputType.Error())
})

t.Run("export canceled by user", func(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions internal/handler/wallet/rolls.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (t *tradeRolls) Handle(params operations.TradeRollsParams) middleware.Respo
}

promptRequest := prompt.PromptRequest{
Action: walletapp.TradeRolls,
Action: walletapp.Sign,
Msg: fmt.Sprintf("%s %s rolls , with fee %s nonaMassa", *params.Body.Side, string(params.Body.Amount), string(params.Body.Fee)),
}

Expand All @@ -62,7 +62,7 @@ func (t *tradeRolls) Handle(params operations.TradeRollsParams) middleware.Respo

output, ok := promptOutput.(*walletapp.SignPromptOutput)
if !ok {
return newErrorResponse(fmt.Sprintf("prompting password for roll: %v", utils.ErrPromptInputType), utils.ErrPromptInputType, http.StatusInternalServerError)
return newErrorResponse(fmt.Sprintf("prompting password for roll: %v", utils.ErrInvalidInputType.Error()), utils.ErrInvalidInputType.Error(), http.StatusInternalServerError)
}

password := output.Password
Expand Down
71 changes: 44 additions & 27 deletions internal/handler/wallet/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ func (w *walletSign) Handle(params operations.SignParams) middleware.Responder {
return errResp
}

promptRequest, err := w.getPromptRequest(params.Body.Operation.String(), acc, params.Body.Description)
promptRequest, fees, err := w.getPromptRequest(params.Body.Operation.String(), acc, params.Body.Description)
if err != nil {
return newErrorResponse(fmt.Sprintf("Error: %s", errorSignDecodeMessage), errorSignDecodeMessage, http.StatusBadRequest)
return newErrorResponse(fmt.Sprintf("Error: %v", err.Error()), errorSignDecodeMessage, http.StatusBadRequest)
}

var correlationID *memguard.LockedBuffer
Expand Down Expand Up @@ -104,6 +104,8 @@ func (w *walletSign) Handle(params operations.SignParams) middleware.Responder {
return newErrorResponse(msg, errorGetWallets, http.StatusInternalServerError)
}

fees = output.Fees

pk, err := acc.PrivateKeyBytesInClear(output.Password)
if err != nil {
return newErrorResponse(err.Error(), errorWrongPassword, http.StatusInternalServerError)
Expand All @@ -122,14 +124,18 @@ func (w *walletSign) Handle(params operations.SignParams) middleware.Responder {
}
}

operation, err := prepareOperation(acc, params, promptRequest)
operation, msgToSign, err := prepareOperation(acc, fees, params.Body.Operation.String(), promptRequest.Data.(PromptRequestSignData).OperationType)
if err != nil {
return newErrorResponse(err.Error(), errorSignDecodeOperation, http.StatusBadRequest)
}

signature := acc.SignWithPrivateKey(privateKey, operation)
signature := acc.SignWithPrivateKey(privateKey, msgToSign)

if !acc.VerifySignature(msgToSign, signature) {
return newErrorResponse("Error: signature verification failed", "errorSignVerifySignature", http.StatusInternalServerError)
}

return w.Success(acc, signature, correlationID)
return w.Success(acc, signature, correlationID, operation)
}

func (w *walletSign) PromptPassword(acc *account.Account, promptRequest *prompt.PromptRequest) (*walletapp.SignPromptOutput, error) {
Expand All @@ -140,7 +146,7 @@ func (w *walletSign) PromptPassword(acc *account.Account, promptRequest *prompt.

output, ok := promptOutput.(*walletapp.SignPromptOutput)
if !ok {
return nil, fmt.Errorf("prompting password for sign: %s", utils.ErrPromptInputType)
return nil, fmt.Errorf("prompting password for sign: %s", utils.ErrInvalidInputType.Error())
}

w.prompterApp.EmitEvent(walletapp.PromptResultEvent,
Expand All @@ -164,13 +170,13 @@ func (w *walletSign) CacheAccount(acc *account.Account, privateKey *memguard.Loc

err = w.gc.SetWithExpire(key, cacheValue.Bytes(), expirationDuration())
if err != nil {
return nil, fmt.Errorf("Error set correlation id in cache: %v", err.Error())
return nil, fmt.Errorf("Error set correlation id in cache: %w", err)
}

return correlationID, nil
}

func (w *walletSign) Success(acc *account.Account, signature []byte, correlationId *memguard.LockedBuffer) middleware.Responder {
func (w *walletSign) Success(acc *account.Account, signature []byte, correlationId *memguard.LockedBuffer, operation []byte) middleware.Responder {
publicKeyBytes, err := acc.PublicKey.MarshalText()
if err != nil {
return newErrorResponse(err.Error(), errorGetAccount, http.StatusInternalServerError)
Expand All @@ -181,70 +187,81 @@ func (w *walletSign) Success(acc *account.Account, signature []byte, correlation
PublicKey: string(publicKeyBytes),
Signature: signature,
CorrelationID: correlationId.Bytes(),
Operation: operation,
})
}

func prepareOperation(acc *account.Account, params operations.SignParams, promptRequest *prompt.PromptRequest) ([]byte, error) {
operation, err := base64.StdEncoding.DecodeString(params.Body.Operation.String())
// prepareOperation prepares the operation to be signed.
// Returns the modified operation (fees change) and the operation to be signed (with public key).
// Returns an error if the operation cannot be decoded.
func prepareOperation(acc *account.Account, fees uint64, operationB64 string, operationType int) ([]byte, []byte, error) {
decodedMsg, _, expiry, err := sendoperation.DecodeMessage64(operationB64)
if err != nil {
return nil, fmt.Errorf("Unable to decode operation: %w", err)
return nil, nil, fmt.Errorf("failed to decode operation for preparing before signing: %w", err)
}

if promptRequest.Data.(PromptRequestSignData).OperationType != Message {
operation := make([]byte, 0)
operation = binary.AppendUvarint(operation, fees)
operation = binary.AppendUvarint(operation, expiry)
operation = append(operation, decodedMsg...)

// operation to be signed
msgToSign := make([]byte, len(operation))
copy(msgToSign, operation)

if operationType != Message {
publicKeyBytes, err := acc.PublicKey.MarshalBinary()
if err != nil {
return nil, fmt.Errorf("Unable to marshal public key: %w", err)
return nil, nil, fmt.Errorf("Unable to marshal public key: %w", err)
}

operation = append(publicKeyBytes, operation...)
msgToSign = append(publicKeyBytes, msgToSign...)
}

return operation, nil
return operation, msgToSign, nil
}

func (w *walletSign) getPromptRequest(msgToSign string, acc *account.Account, description string) (*prompt.PromptRequest, error) {
func (w *walletSign) getPromptRequest(msgToSign string, acc *account.Account, description string) (*prompt.PromptRequest, uint64, error) {
var opType uint64
var err error

addressBytes, err := acc.Address.MarshalText()
if err != nil {
return nil, err
return nil, 0, fmt.Errorf("failed to marshal address: %w", err)
}
address := string(addressBytes)

decodedMsg, fees, _, err := sendoperation.DecodeMessage64(msgToSign)
if err != nil {
return nil, errors.Wrap(err, "failed to decode transaction message")
return nil, 0, fmt.Errorf("failed to decode transaction message: %w", err)
}

opType, err = sendoperation.DecodeOperationType(decodedMsg)
if err != nil {
wrappedErr := errors.Wrap(err, "failed to decode operation ID")

return nil, wrappedErr
return nil, 0, fmt.Errorf("failed to decode operation ID: %w", err)
}

var data PromptRequestSignData

switch opType {
case transaction.TransactionOpType:
case transaction.OpType:
data, err = w.getTransactionPromptData(decodedMsg, acc)

case buyrolls.OpID, sellrolls.SellRollOpID:
case buyrolls.OpType, sellrolls.OpType:
data, err = getRollPromptData(decodedMsg, acc)

case executesc.ExecuteSCOpID:
case executesc.OpType:
data, err = getExecuteSCPromptData(decodedMsg, acc)

case callsc.CallSCOpID:
case callsc.OpType:
data, err = getCallSCPromptData(decodedMsg, acc)

default:
data, err = getPlainTextPromptData(msgToSign, acc)
}

if err != nil {
return nil, fmt.Errorf("failed to decode message of operation type: %d: %w", opType, err)
return nil, 0, fmt.Errorf("failed to decode message of operation type: %d: %w", opType, err)
}

data.Description = description
Expand All @@ -258,7 +275,7 @@ func (w *walletSign) getPromptRequest(msgToSign string, acc *account.Account, de
Data: data,
}

return &promptRequest, nil
return &promptRequest, fees, nil
}

func getCallSCPromptData(
Expand Down
2 changes: 1 addition & 1 deletion internal/handler/wallet/sign_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (w *walletSignMessage) Handle(params operations.SignMessageParams) middlewa

output, ok := promptOutput.(*walletapp.SignPromptOutput)
if !ok {
return newErrorResponse(fmt.Sprintf("prompting password for message: %v", utils.ErrPromptInputType), utils.ErrPromptInputType, http.StatusInternalServerError)
return newErrorResponse(fmt.Sprintf("prompting password for message: %v", utils.ErrInvalidInputType.Error()), utils.ErrInvalidInputType.Error(), http.StatusInternalServerError)
}
password := output.Password

Expand Down
14 changes: 14 additions & 0 deletions internal/handler/wallet/sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/massalabs/station-massa-wallet/api/server/restapi/operations"
walletapp "github.com/massalabs/station-massa-wallet/pkg/app"
"github.com/massalabs/station-massa-wallet/pkg/utils"
"github.com/massalabs/station-massa-wallet/pkg/wallet/account"
"github.com/stretchr/testify/assert"
)

Expand All @@ -37,6 +38,19 @@ func signMessage(t *testing.T, api *operations.MassaWalletAPI, nickname string,
return resp
}

func TestPrepareOperation(t *testing.T) {
acc := account.NewAccount(t)
fees := uint64(1000)
operationB64 := "AKT4CASAzuTNAqCNBgEAXBwUw39NBQYix8Ovph0TUiJuDDEnlFYUPgsbeMbrA4cLZm9yd2FyZEJ1cm7FAQDgfY7fLW7qpwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoAAAAweGZDRERBRTI1MTAwNjIxYTViQzg4MTlkQzlEMzg0MjUzNEQ3QmY0NzYAAAAANQAAAEFTMTJUUm9TY01kd0xLOFlwdDZOQkFwcHl6Q0Z3N1FlRzVlM3hGdnhwQ0FuQW5ZTGZ1TVVUKgAAADB4NTM4NDRGOTU3N0MyMzM0ZTU0MUFlYzdEZjcxNzRFQ2U1ZEYxZkNmMKc2qgAAAAAA"

operation, msgToSign, err := prepareOperation(acc, fees, operationB64, 4)
assert.NoError(t, err)
expected := []byte{0xe8, 0x7, 0xa4, 0xf8, 0x8, 0x4, 0x80, 0xce, 0xe4, 0xcd, 0x2, 0xa0, 0x8d, 0x6, 0x1, 0x0, 0x5c, 0x1c, 0x14, 0xc3, 0x7f, 0x4d, 0x5, 0x6, 0x22, 0xc7, 0xc3, 0xaf, 0xa6, 0x1d, 0x13, 0x52, 0x22, 0x6e, 0xc, 0x31, 0x27, 0x94, 0x56, 0x14, 0x3e, 0xb, 0x1b, 0x78, 0xc6, 0xeb, 0x3, 0x87, 0xb, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x42, 0x75, 0x72, 0x6e, 0xc5, 0x1, 0x0, 0xe0, 0x7d, 0x8e, 0xdf, 0x2d, 0x6e, 0xea, 0xa7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x30, 0x78, 0x66, 0x43, 0x44, 0x44, 0x41, 0x45, 0x32, 0x35, 0x31, 0x30, 0x30, 0x36, 0x32, 0x31, 0x61, 0x35, 0x62, 0x43, 0x38, 0x38, 0x31, 0x39, 0x64, 0x43, 0x39, 0x44, 0x33, 0x38, 0x34, 0x32, 0x35, 0x33, 0x34, 0x44, 0x37, 0x42, 0x66, 0x34, 0x37, 0x36, 0x0, 0x0, 0x0, 0x0, 0x35, 0x0, 0x0, 0x0, 0x41, 0x53, 0x31, 0x32, 0x54, 0x52, 0x6f, 0x53, 0x63, 0x4d, 0x64, 0x77, 0x4c, 0x4b, 0x38, 0x59, 0x70, 0x74, 0x36, 0x4e, 0x42, 0x41, 0x70, 0x70, 0x79, 0x7a, 0x43, 0x46, 0x77, 0x37, 0x51, 0x65, 0x47, 0x35, 0x65, 0x33, 0x78, 0x46, 0x76, 0x78, 0x70, 0x43, 0x41, 0x6e, 0x41, 0x6e, 0x59, 0x4c, 0x66, 0x75, 0x4d, 0x55, 0x54, 0x2a, 0x0, 0x0, 0x0, 0x30, 0x78, 0x35, 0x33, 0x38, 0x34, 0x34, 0x46, 0x39, 0x35, 0x37, 0x37, 0x43, 0x32, 0x33, 0x33, 0x34, 0x65, 0x35, 0x34, 0x31, 0x41, 0x65, 0x63, 0x37, 0x44, 0x66, 0x37, 0x31, 0x37, 0x34, 0x45, 0x43, 0x65, 0x35, 0x64, 0x46, 0x31, 0x66, 0x43, 0x66, 0x30, 0xa7, 0x36, 0xaa, 0x0, 0x0, 0x0, 0x0, 0x0}
assert.Equal(t, expected, operation)
expectedMsg := []byte{0x0, 0x2d, 0x96, 0xbc, 0xda, 0xcb, 0xbe, 0x41, 0x38, 0x2c, 0xa2, 0x3e, 0x52, 0xe3, 0xd2, 0x19, 0x6c, 0xba, 0x65, 0xe7, 0xa1, 0xac, 0xd2, 0x9, 0xdf, 0xc9, 0x5c, 0x6b, 0x32, 0xb6, 0xa1, 0x8a, 0x93, 0xe8, 0x7, 0xa4, 0xf8, 0x8, 0x4, 0x80, 0xce, 0xe4, 0xcd, 0x2, 0xa0, 0x8d, 0x6, 0x1, 0x0, 0x5c, 0x1c, 0x14, 0xc3, 0x7f, 0x4d, 0x5, 0x6, 0x22, 0xc7, 0xc3, 0xaf, 0xa6, 0x1d, 0x13, 0x52, 0x22, 0x6e, 0xc, 0x31, 0x27, 0x94, 0x56, 0x14, 0x3e, 0xb, 0x1b, 0x78, 0xc6, 0xeb, 0x3, 0x87, 0xb, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x42, 0x75, 0x72, 0x6e, 0xc5, 0x1, 0x0, 0xe0, 0x7d, 0x8e, 0xdf, 0x2d, 0x6e, 0xea, 0xa7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2a, 0x0, 0x0, 0x0, 0x30, 0x78, 0x66, 0x43, 0x44, 0x44, 0x41, 0x45, 0x32, 0x35, 0x31, 0x30, 0x30, 0x36, 0x32, 0x31, 0x61, 0x35, 0x62, 0x43, 0x38, 0x38, 0x31, 0x39, 0x64, 0x43, 0x39, 0x44, 0x33, 0x38, 0x34, 0x32, 0x35, 0x33, 0x34, 0x44, 0x37, 0x42, 0x66, 0x34, 0x37, 0x36, 0x0, 0x0, 0x0, 0x0, 0x35, 0x0, 0x0, 0x0, 0x41, 0x53, 0x31, 0x32, 0x54, 0x52, 0x6f, 0x53, 0x63, 0x4d, 0x64, 0x77, 0x4c, 0x4b, 0x38, 0x59, 0x70, 0x74, 0x36, 0x4e, 0x42, 0x41, 0x70, 0x70, 0x79, 0x7a, 0x43, 0x46, 0x77, 0x37, 0x51, 0x65, 0x47, 0x35, 0x65, 0x33, 0x78, 0x46, 0x76, 0x78, 0x70, 0x43, 0x41, 0x6e, 0x41, 0x6e, 0x59, 0x4c, 0x66, 0x75, 0x4d, 0x55, 0x54, 0x2a, 0x0, 0x0, 0x0, 0x30, 0x78, 0x35, 0x33, 0x38, 0x34, 0x34, 0x46, 0x39, 0x35, 0x37, 0x37, 0x43, 0x32, 0x33, 0x33, 0x34, 0x65, 0x35, 0x34, 0x31, 0x41, 0x65, 0x63, 0x37, 0x44, 0x66, 0x37, 0x31, 0x37, 0x34, 0x45, 0x43, 0x65, 0x35, 0x64, 0x46, 0x31, 0x66, 0x43, 0x66, 0x30, 0xa7, 0x36, 0xaa, 0x0, 0x0, 0x0, 0x0, 0x0}
assert.Equal(t, expectedMsg, msgToSign)
}

func Test_walletSign_Handle(t *testing.T) {
api, prompterApp, _, resChan, err := MockAPI()
assert.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion internal/handler/wallet/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (t *transferCoin) Handle(params operations.TransferCoinParams) middleware.R

output, ok := promptOutput.(*walletapp.SignPromptOutput)
if !ok {
return newErrorResponse(fmt.Sprintf("prompting password for message: %v", utils.ErrPromptInputType), utils.ErrPromptInputType, http.StatusInternalServerError)
return newErrorResponse(fmt.Sprintf("prompting password for message: %v", utils.ErrInvalidInputType.Error()), utils.ErrInvalidInputType.Error(), http.StatusInternalServerError)
}
password := output.Password

Expand Down
2 changes: 1 addition & 1 deletion pkg/prompt/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func handleBackupMethod(prompterApp WalletPrompterInterface, input interface{})

default:
prompterApp.EmitEvent(walletapp.PromptResultEvent,
walletapp.EventData{Success: false, CodeMessage: utils.ErrPromptInputType})
walletapp.EventData{Success: false, CodeMessage: utils.ErrInvalidInputType.Error()})
return nil, false, fmt.Errorf("invalid backup method: %s", method)
}
}
1 change: 0 additions & 1 deletion pkg/prompt/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
)

const (
InputTypeErr = "invalid prompt input type"
AlreadyListeningErr = "prompter is already listening"
)

Expand Down
2 changes: 1 addition & 1 deletion pkg/prompt/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func (e *envPrompter) PromptRequest(req PromptRequest) {
password := os.Getenv("WALLET_PASSWORD")

switch req.Action {
case walletapp.Sign, walletapp.TradeRolls:
case walletapp.Sign:
e.PromptApp.PromptInput <- walletapp.SignPromptInput{Password: password, Fees: "500"}
case walletapp.Delete, walletapp.NewPassword, walletapp.Unprotect:
e.PromptApp.PromptInput <- password
Expand Down
Loading

0 comments on commit 17d7f7c

Please sign in to comment.