From 9f7d56b68aabf301077ec99e8ef43f0ae26d691d Mon Sep 17 00:00:00 2001 From: solipsis Date: Fri, 16 Feb 2018 09:54:36 -0700 Subject: [PATCH] more refactoring --- pkg/ethereum/ethereum.go => ethereum.go | 13 +- jsonTest.go | 253 ++++++++++++++ main.go | 441 ++++-------------------- 3 files changed, 324 insertions(+), 383 deletions(-) rename pkg/ethereum/ethereum.go => ethereum.go (80%) create mode 100644 jsonTest.go diff --git a/pkg/ethereum/ethereum.go b/ethereum.go similarity index 80% rename from pkg/ethereum/ethereum.go rename to ethereum.go index f32bbf3..ae2e838 100644 --- a/pkg/ethereum/ethereum.go +++ b/ethereum.go @@ -1,11 +1,10 @@ -package ethereum +package gokeepkey import "math/big" -import kk "github.com/solipsis/go-keepkey" import kkProto "github.com/solipsis/go-keepkey/internal" // should take interface -func EthTxAsProto(tx *kk.EthereumTx, nodePath []uint32) *kkProto.EthereumSignTx { +func EthTxAsProto(tx *EthereumTx, nodePath []uint32) *kkProto.EthereumSignTx { est := &kkProto.EthereumSignTx{ AddressN: nodePath, @@ -39,13 +38,13 @@ func emptyOrVal(val *big.Int) []byte { return val.Bytes() } -func NewTransaction(nonce uint64, recipient string, amount, gasLimit, gasPrice *big.Int, data []byte) *kk.EthereumTx { +func NewTransaction(nonce uint64, recipient string, amount, gasLimit, gasPrice *big.Int, data []byte) *EthereumTx { if len(data) > 0 { cp := make([]byte, len(data)) copy(cp, data) data = cp } - tx := kk.EthereumTx{ + tx := EthereumTx{ Nonce: nonce, Recipient: recipient, Amount: new(big.Int), @@ -69,8 +68,8 @@ func NewTransaction(nonce uint64, recipient string, amount, gasLimit, gasPrice * return &tx } -func NewTokenTransaction(tx *kk.EthereumTx, tShortcut, tRecipient string, tValue *big.Int) *kk.TokenTx { - tokenTx := &kk.TokenTx{ +func NewTokenTransaction(tx *EthereumTx, tShortcut, tRecipient string, tValue *big.Int) *TokenTx { + tokenTx := &TokenTx{ EthereumTx: tx, TokenShortcut: tShortcut, TokenTo: tRecipient, diff --git a/jsonTest.go b/jsonTest.go new file mode 100644 index 0000000..26d6181 --- /dev/null +++ b/jsonTest.go @@ -0,0 +1,253 @@ +package gokeepkey + +import ( + "encoding/hex" + "log" + "strconv" + + kkProto "github.com/solipsis/go-keepkey/internal" +) + +type EthSignTxJSON struct { + AddressN []uint32 `json:"address_n"` + Nonce string `json:"nonce,omitempty"` + GasPrice string `json:"gas_price,omitempty"` + GasLimit string `json:"gas_limit,omitempty"` + To string `json:"to,omitempty"` + Value string `json:"value,omitempty"` + DataInitialChunk string `json:"data_initial_chunk,omitempty"` + DataLength uint32 `json:"data_length,omitempty"` + ToAddressN []uint32 `json:"to_address_n,omitempty"` + AddressType string `json:"address_type,omitempty"` + ChainID uint32 `json:"chain_id,omitempty"` + TokenValue string `json:"token_value,omitempty"` + TokenTo string `json:"token_to,omitempty"` + TokenShortcut string `json:"token_shortcut,omitempty"` + TypeName string `json:"typeName,omitempty"` + ExchangeType ExchangeType `json:"exchange_type,omitempty"` +} + +type ExchangeAddress struct { + CoinType string `json:"coin_type,omitempty"` + Address string `json:"address,omitempty"` + DestTag interface{} `json:"dest_tag,omitempty"` + RsAddress interface{} `json:"rs_address,omitempty"` +} + +type ExchangeType struct { + SignedExchangeResponse struct { + Response interface{} `json:"response"` + Signature string `json:"signature"` + ResponseV2 struct { + DepositAddress ExchangeAddress `json:"deposit_address"` + DepositAmount string `json:"deposit_amount"` + Expiration string `json:"expiration"` + QuotedRate string `json:"quoted_rate"` + WithdrawalAddress ExchangeAddress `json:"withdrawal_address"` + WithdrawalAmount string `json:"withdrawal_amount"` + ReturnAddress ExchangeAddress `json:"return_address"` + APIKey string `json:"api_key"` + MinerFee string `json:"miner_fee"` + OrderID string `json:"order_id"` + } `json:"responseV2"` + } `json:"signed_exchange_response"` + WithdrawalCoinName string `json:"withdrawal_coin_name"` + WithdrawalAddressN []uint32 `json:"withdrawal_address_n"` + ReturnAddressN []uint32 `json:"return_address_n"` +} + +func exchangeAddressFromJSON(a ExchangeAddress) *kkProto.ExchangeAddress { + return &kkProto.ExchangeAddress{ + CoinType: &a.CoinType, + Address: &a.Address, + } +} + +func mustDecode(s string) []byte { + h, err := hex.DecodeString(s) + if err != nil { + log.Fatal(err) + } + return h +} + +func ethSignProtoFromJSON(e EthSignTxJSON) *kkProto.EthereumSignTx { + addrType := kkProto.OutputAddressType(kkProto.OutputAddressType_value[e.AddressType]) + ret := &kkProto.EthereumSignTx{ + AddressN: e.AddressN, + Nonce: mustDecode(e.Nonce), + GasPrice: mustDecode(e.GasPrice), + GasLimit: mustDecode(e.GasLimit), + To: mustDecode(e.To), + Value: mustDecode(e.Value), + //DataInitialChunk: mustDecode(e.DataInitialChunk), + //DataLength: &e.DataLength, + ToAddressN: e.ToAddressN, + AddressType: &addrType, + ExchangeType: exchangeProtoFromJSON(e.ExchangeType), + ChainId: &e.ChainID, + //TokenValue: mustDecode(e.TokenValue), + //TokenTo: mustDecode(e.TokenTo), + //TokenShortcut: &e.TokenShortcut, + } + if e.TokenValue != "" { + ret.TokenValue = mustDecode(e.TokenValue) + } + if e.TokenTo != "" { + ret.TokenTo = mustDecode(e.TokenTo) + } + if e.TokenShortcut != "" { + ret.TokenShortcut = &e.TokenShortcut + } + return ret +} + +func exchangeProtoFromJSON(e ExchangeType) *kkProto.ExchangeType { + resp := e.SignedExchangeResponse + v2 := resp.ResponseV2 + exp, _ := strconv.ParseInt(v2.Expiration, 10, 64) + retV2 := kkProto.ExchangeResponseV2{ + DepositAddress: exchangeAddressFromJSON(v2.DepositAddress), + DepositAmount: mustDecode(v2.DepositAmount), + Expiration: &exp, + QuotedRate: mustDecode(v2.QuotedRate), + WithdrawalAddress: exchangeAddressFromJSON(v2.WithdrawalAddress), + WithdrawalAmount: mustDecode(v2.WithdrawalAmount), + ReturnAddress: exchangeAddressFromJSON(v2.ReturnAddress), + ApiKey: mustDecode(v2.APIKey), + MinerFee: mustDecode(v2.MinerFee), + OrderId: mustDecode(v2.OrderID), + } + signedExchangeResponse := kkProto.SignedExchangeResponse{ + ResponseV2: &retV2, + Signature: mustDecode(resp.Signature), + } + return &kkProto.ExchangeType{ + SignedExchangeResponse: &signedExchangeResponse, + WithdrawalCoinName: &e.WithdrawalCoinName, + WithdrawalAddressN: e.WithdrawalAddressN, + ReturnAddressN: e.ReturnAddressN, + } +} + +// TODO: can i get this reflectively from proto file? +var sampleEthSign = `{ + "address_n": [ + 2147483692, + 2147483708, + 2147483648, + 0, + 0 + ], + "nonce": "25", + "gas_price": "05d21dba00", + "gas_limit": "0124f8", + "to": null, + "value": "", + "data_initial_chunk": null, + "data_length": null, + "to_address_n": [], + "address_type": "EXCHANGE", + "exchange_type": { + "signed_exchange_response": { + "response": null, + "signature": "20c1856c630ec481ca597a1f2f6075ab8f05fcbcb9e3298ea8e2a127eacc76ec820acbeaa31d72e0f3bef2e87dd9e8e6ff56d19db0b0a0795a505f370273a73568", + "responseV2": { + "deposit_address": { + "coin_type": "salt", + "address": "0x0081b2ed70c6dfb50d87a072a1ca5dd63b226f96", + "dest_tag": null, + "rs_address": null + }, + "deposit_amount": "989680", + "expiration": "1518034541638", + "quoted_rate": "18587729fb", + "withdrawal_address": { + "coin_type": "doge", + "address": "DRJdizwQLfZMGz886cnr9U9iHuEBLuJjcR", + "dest_tag": null, + "rs_address": null + }, + "withdrawal_amount": "0263535bcc", + "return_address": { + "coin_type": "salt", + "address": "0x6b67c94fc31510707f9c0f1281aad5ec9a2eeff0", + "dest_tag": null, + "rs_address": null + }, + "api_key": "6ad5831b778484bb849da45180ac35047848e5cac0fa666454f4ff78b8c7399fea6a8ce2c7ee6287bcd78db6610ca3f538d6b3e90ca80c8e6368b6021445950b", + "miner_fee": "0bebc200", + "order_id": "44e5533e9b10462d882b8f2690825a73" + } + }, + "withdrawal_coin_name": "Dogecoin", + "withdrawal_address_n": [ + 2147483692, + 2147483651, + 2147483648, + 0, + 0 + ], + "return_address_n": [ + 2147483692, + 2147483708, + 2147483648, + 0, + 0 + ] + }, + "chain_id": null, + "token_value": "989680", + "token_to": null, + "token_shortcut": "SALT", + "typeName": "EthereumSignTx" +}` + +var sampleExchangeResp = `{ + "signed_exchange_response": { + "response": null, + "signature": "20c1856c630ec481ca597a1f2f6075ab8f05fcbcb9e3298ea8e2a127eacc76ec820acbeaa31d72e0f3bef2e87dd9e8e6ff56d19db0b0a0795a505f370273a73568", + "responseV2": { + "deposit_address": { + "coin_type": "salt", + "address": "0x0081b2ed70c6dfb50d87a072a1ca5dd63b226f96", + "dest_tag": null, + "rs_address": null + }, + "deposit_amount": "989680", + "expiration": "1518034541638", + "quoted_rate": "18587729fb", + "withdrawal_address": { + "coin_type": "doge", + "address": "DRJdizwQLfZMGz886cnr9U9iHuEBLuJjcR", + "dest_tag": null, + "rs_address": null + }, + "withdrawal_amount": "0263535bcc", + "return_address": { + "coin_type": "salt", + "address": "0x6b67c94fc31510707f9c0f1281aad5ec9a2eeff0", + "dest_tag": null, + "rs_address": null + }, + "api_key": "6ad5831b778484bb849da45180ac35047848e5cac0fa666454f4ff78b8c7399fea6a8ce2c7ee6287bcd78db6610ca3f538d6b3e90ca80c8e6368b6021445950b", + "miner_fee": "0bebc200", + "order_id": "44e5533e9b10462d882b8f2690825a73" + } + }, + "withdrawal_coin_name": "Dogecoin", + "withdrawal_address_n": [ + 2147483692, + 2147483651, + 2147483648, + 0, + 0 + ], + "return_address_n": [ + 2147483692, + 2147483708, + 2147483648, + 0, + 0 + ] + }` diff --git a/main.go b/main.go index 2d8fd56..f0ba4e5 100644 --- a/main.go +++ b/main.go @@ -5,14 +5,11 @@ import ( "crypto/sha256" "encoding/binary" "encoding/hex" - "encoding/json" "errors" "fmt" "io" "io/ioutil" - "log" "math/big" - "strconv" "strings" "github.com/golang/protobuf/proto" @@ -191,142 +188,78 @@ func (kk *Keepkey) UploadFirmware(path string) (int, error) { return len(data), nil } -func (kk *Keepkey) EthereumSignTxFromJSON(b []byte) *kkProto.EthereumTxRequest { +func (kk *Keepkey) EthereumSignTx(derivationPath []uint32, tx *EthereumTx) (*kkProto.EthereumTxRequest, error) { - data := make([]byte, 0) - estJSON := EthSignTxJSON{} - json.Unmarshal(b, &estJSON) - - est := ethSignProtoFromJSON(estJSON) - //fmt.Println(est.GasLimit) - /* - if length > 1024 { - est.DataInitialChunk, data = data[:1024], data[1024:] - } else { - est.DataInitialChunk, data = data, nil - } - */ - fmt.Println(est) - response := new(kkProto.EthereumTxRequest) - fmt.Println("**************************************") - if _, err := kk.keepkeyExchange(est, response); err != nil { - fmt.Println("error sending initial sign request") - fmt.Println(err) - //log.Fatal(err) + // Convert Address to hex + to := tx.Recipient + if strings.HasPrefix(to, "0x") || strings.HasPrefix(to, "0X") { + to = to[2:] + } + toBuf := make([]byte, 20) + if _, err := hex.Decode(toBuf, []byte(to)); err != nil { + return nil, err } - // stream until a signature is returned - for response.DataLength != nil && int(*response.DataLength) <= len(data) { - chunk := data[:*response.DataLength] - fmt.Println("chunk", chunk) - data = data[*response.DataLength:] - fmt.Println("data", data) - // acknowledge that we got a chunk and ask for the next one - if _, err := kk.keepkeyExchange(&kkProto.EthereumTxAck{DataChunk: chunk}, response); err != nil { - fmt.Println("error streaming response") - fmt.Println(err) - //log.Fatal(err) - } + // Create request + est := &kkProto.EthereumSignTx{ + AddressN: derivationPath, + Nonce: big.NewInt(int64(tx.Nonce)).Bytes(), + To: toBuf, } - signature := append(append(response.GetSignatureR(), response.GetSignatureS()...), byte(response.GetSignatureV())) - v := make([]byte, 4) - binary.LittleEndian.PutUint32(v, response.GetSignatureV()) - fmt.Println("signature:", hex.EncodeToString(signature)) - fmt.Println("v:", hex.EncodeToString(v)) - fmt.Println("r:", hex.EncodeToString(response.GetSignatureR())) - fmt.Println("s:", hex.EncodeToString(response.GetSignatureS())) - fmt.Println("hash:", hex.EncodeToString(response.Hash)) - fmt.Println(response) - return response + // For proper rlp encoding when the value of the parameter is zero, + // the device expects an empty byte array instead of + // a byte array with a value of zero + if tx.Amount != nil { + est.Value = emptyOrVal(tx.Amount) + } + if tx.GasLimit != nil { + est.GasLimit = emptyOrVal(tx.GasLimit) + } + if tx.GasPrice != nil { + est.GasPrice = emptyOrVal(tx.GasPrice) + } + return kk.ethereumSignTx(est) } -func (kk *Keepkey) EthereumSignJSONTest(arr []byte) *kkProto.EthereumTxRequest { +func (kk *Keepkey) ethereumSignTx(est *kkProto.EthereumSignTx) (*kkProto.EthereumTxRequest, error) { data := make([]byte, 0) - //estJSON := EthSignTxJSON{} - //json.Unmarshal(b, &estJSON) - - est := new(kkProto.EthereumSignTx) - json.Unmarshal(arr, est) - //est := ethSignProtoFromJSON(estJSON) - //fmt.Println(est.GasLimit) + //test := []byte("6b67c94fc31510707F9c0f1281AaD5ec9a2EEFF0") + //tokenTo := make([]byte, 20) + //hex.Decode(tokenTo, test) + //tokenValue := make([]byte, 32) + //tokenBig := big.NewInt(1337) + //copy(tokenValue[32-len(tokenBig.Bytes()):], tokenBig.Bytes()) /* - if length > 1024 { - est.DataInitialChunk, data = data[:1024], data[1024:] - } else { - est.DataInitialChunk, data = data, nil + empty := make([]byte, 0) + fmt.Println(empty) + addressType := kkProto.OutputAddressType_EXCHANGE + resp := ExchangeType{} + json.Unmarshal([]byte(sampleExchangeResp), &resp) + exchangeType := exchangeProtoFromJSON(resp) + fmt.Println(exchangeType) + est := &kkProto.EthereumSignTx{ + AddressN: derivationPath, + AddressType: &addressType, + Nonce: big.NewInt(int64(nonce)).Bytes(), + GasPrice: big.NewInt(22000000000).Bytes(), + GasLimit: big.NewInt(70000).Bytes(), + ExchangeType: exchangeType, + //GasLimit: big.NewInt(1000).Bytes(), + //Value: empty, + //Value: big.NewInt(1).Bytes(), + + // DataLength: &length, + //To: empty, + //ToAddressN: toTest, + TokenValue: tokenValue, + //TokenValue: big.NewInt(6).Bytes(), + TokenShortcut: &tokenShortcut, + TokenTo: tokenTo, + //ChainId: &chainId, + + //To: []byte("32Be343B94f860124dC4fEe278FDCBD38C102D88"), } */ - fmt.Println(est) - response := new(kkProto.EthereumTxRequest) - fmt.Println("**************************************") - if _, err := kk.keepkeyExchange(est, response); err != nil { - fmt.Println("error sending initial sign request") - log.Fatal(err) - } - - // stream until a signature is returned - for response.DataLength != nil && int(*response.DataLength) <= len(data) { - chunk := data[:*response.DataLength] - fmt.Println("chunk", chunk) - data = data[*response.DataLength:] - fmt.Println("data", data) - // acknowledge that we got a chunk and ask for the next one - if _, err := kk.keepkeyExchange(&kkProto.EthereumTxAck{DataChunk: chunk}, response); err != nil { - fmt.Println("error streaming response") - log.Fatal(err) - } - } - signature := append(append(response.GetSignatureR(), response.GetSignatureS()...), byte(response.GetSignatureV())) - v := make([]byte, 4) - binary.LittleEndian.PutUint32(v, response.GetSignatureV()) - fmt.Println("signature:", hex.EncodeToString(signature)) - fmt.Println("v:", hex.EncodeToString(v)) - fmt.Println("r:", hex.EncodeToString(response.GetSignatureR())) - fmt.Println("s:", hex.EncodeToString(response.GetSignatureS())) - fmt.Println("hash:", hex.EncodeToString(response.Hash)) - fmt.Println(response) - return response - -} - -func (kk *Keepkey) EthereumSignTx(derivationPath []uint32, nonce uint64, tokenShortcut string) *kkProto.EthereumTxRequest { - data := make([]byte, 0) - test := []byte("6b67c94fc31510707F9c0f1281AaD5ec9a2EEFF0") - tokenTo := make([]byte, 20) - hex.Decode(tokenTo, test) - tokenValue := make([]byte, 32) - tokenBig := big.NewInt(1337) - copy(tokenValue[32-len(tokenBig.Bytes()):], tokenBig.Bytes()) - - empty := make([]byte, 0) - fmt.Println(empty) - addressType := kkProto.OutputAddressType_EXCHANGE - resp := ExchangeType{} - json.Unmarshal([]byte(sampleExchangeResp), &resp) - exchangeType := exchangeProtoFromJSON(resp) - fmt.Println(exchangeType) - est := &kkProto.EthereumSignTx{ - AddressN: derivationPath, - AddressType: &addressType, - Nonce: big.NewInt(int64(nonce)).Bytes(), - GasPrice: big.NewInt(22000000000).Bytes(), - GasLimit: big.NewInt(70000).Bytes(), - ExchangeType: exchangeType, - //GasLimit: big.NewInt(1000).Bytes(), - //Value: empty, - //Value: big.NewInt(1).Bytes(), - - // DataLength: &length, - //To: empty, - //ToAddressN: toTest, - TokenValue: tokenValue, - //TokenValue: big.NewInt(6).Bytes(), - TokenShortcut: &tokenShortcut, - TokenTo: tokenTo, - //ChainId: &chainId, - - //To: []byte("32Be343B94f860124dC4fEe278FDCBD38C102D88"), - } //fmt.Println(est.GasLimit) /* if length > 1024 { @@ -344,7 +277,7 @@ func (kk *Keepkey) EthereumSignTx(derivationPath []uint32, nonce uint64, tokenSh fmt.Println("**************************************") if _, err := kk.keepkeyExchange(est, response); err != nil { fmt.Println("error sending initial sign request") - log.Fatal(err) + return nil, err } // stream until a signature is returned @@ -356,7 +289,7 @@ func (kk *Keepkey) EthereumSignTx(derivationPath []uint32, nonce uint64, tokenSh // acknowledge that we got a chunk and ask for the next one if _, err := kk.keepkeyExchange(&kkProto.EthereumTxAck{DataChunk: chunk}, response); err != nil { fmt.Println("error streaming response") - log.Fatal(err) + return nil, err } } signature := append(append(response.GetSignatureR(), response.GetSignatureS()...), byte(response.GetSignatureV())) @@ -368,7 +301,7 @@ func (kk *Keepkey) EthereumSignTx(derivationPath []uint32, nonce uint64, tokenSh fmt.Println("s:", hex.EncodeToString(response.GetSignatureS())) fmt.Println("hash:", hex.EncodeToString(response.Hash)) fmt.Println(response) - return response + return response, nil //fmt.Println(response) /* @@ -391,250 +324,6 @@ func (kk *Keepkey) EthereumSignTx(derivationPath []uint32, nonce uint64, tokenSh // TODO: } -func exchangeAddressFromJSON(a ExchangeAddress) *kkProto.ExchangeAddress { - return &kkProto.ExchangeAddress{ - CoinType: &a.CoinType, - Address: &a.Address, - } -} - -func mustDecode(s string) []byte { - h, err := hex.DecodeString(s) - if err != nil { - log.Fatal(err) - } - return h -} - -func exchangeProtoFromJSON(e ExchangeType) *kkProto.ExchangeType { - resp := e.SignedExchangeResponse - v2 := resp.ResponseV2 - exp, _ := strconv.ParseInt(v2.Expiration, 10, 64) - retV2 := kkProto.ExchangeResponseV2{ - DepositAddress: exchangeAddressFromJSON(v2.DepositAddress), - DepositAmount: mustDecode(v2.DepositAmount), - Expiration: &exp, - QuotedRate: mustDecode(v2.QuotedRate), - WithdrawalAddress: exchangeAddressFromJSON(v2.WithdrawalAddress), - WithdrawalAmount: mustDecode(v2.WithdrawalAmount), - ReturnAddress: exchangeAddressFromJSON(v2.ReturnAddress), - ApiKey: mustDecode(v2.APIKey), - MinerFee: mustDecode(v2.MinerFee), - OrderId: mustDecode(v2.OrderID), - } - signedExchangeResponse := kkProto.SignedExchangeResponse{ - ResponseV2: &retV2, - Signature: mustDecode(resp.Signature), - } - return &kkProto.ExchangeType{ - SignedExchangeResponse: &signedExchangeResponse, - WithdrawalCoinName: &e.WithdrawalCoinName, - WithdrawalAddressN: e.WithdrawalAddressN, - ReturnAddressN: e.ReturnAddressN, - } -} - -func ethSignProtoFromJSON(e EthSignTxJSON) *kkProto.EthereumSignTx { - addrType := kkProto.OutputAddressType(kkProto.OutputAddressType_value[e.AddressType]) - ret := &kkProto.EthereumSignTx{ - AddressN: e.AddressN, - Nonce: mustDecode(e.Nonce), - GasPrice: mustDecode(e.GasPrice), - GasLimit: mustDecode(e.GasLimit), - To: mustDecode(e.To), - Value: mustDecode(e.Value), - //DataInitialChunk: mustDecode(e.DataInitialChunk), - //DataLength: &e.DataLength, - ToAddressN: e.ToAddressN, - AddressType: &addrType, - ExchangeType: exchangeProtoFromJSON(e.ExchangeType), - ChainId: &e.ChainID, - //TokenValue: mustDecode(e.TokenValue), - //TokenTo: mustDecode(e.TokenTo), - //TokenShortcut: &e.TokenShortcut, - } - if e.TokenValue != "" { - ret.TokenValue = mustDecode(e.TokenValue) - } - if e.TokenTo != "" { - ret.TokenTo = mustDecode(e.TokenTo) - } - if e.TokenShortcut != "" { - ret.TokenShortcut = &e.TokenShortcut - } - return ret -} - -type EthSignTxJSON struct { - AddressN []uint32 `json:"address_n"` - Nonce string `json:"nonce,omitempty"` - GasPrice string `json:"gas_price,omitempty"` - GasLimit string `json:"gas_limit,omitempty"` - To string `json:"to,omitempty"` - Value string `json:"value,omitempty"` - DataInitialChunk string `json:"data_initial_chunk,omitempty"` - DataLength uint32 `json:"data_length,omitempty"` - ToAddressN []uint32 `json:"to_address_n,omitempty"` - AddressType string `json:"address_type,omitempty"` - ChainID uint32 `json:"chain_id,omitempty"` - TokenValue string `json:"token_value,omitempty"` - TokenTo string `json:"token_to,omitempty"` - TokenShortcut string `json:"token_shortcut,omitempty"` - TypeName string `json:"typeName,omitempty"` - ExchangeType ExchangeType `json:"exchange_type,omitempty"` -} - -type ExchangeAddress struct { - CoinType string `json:"coin_type,omitempty"` - Address string `json:"address,omitempty"` - DestTag interface{} `json:"dest_tag,omitempty"` - RsAddress interface{} `json:"rs_address,omitempty"` -} - -type ExchangeType struct { - SignedExchangeResponse struct { - Response interface{} `json:"response"` - Signature string `json:"signature"` - ResponseV2 struct { - DepositAddress ExchangeAddress `json:"deposit_address"` - DepositAmount string `json:"deposit_amount"` - Expiration string `json:"expiration"` - QuotedRate string `json:"quoted_rate"` - WithdrawalAddress ExchangeAddress `json:"withdrawal_address"` - WithdrawalAmount string `json:"withdrawal_amount"` - ReturnAddress ExchangeAddress `json:"return_address"` - APIKey string `json:"api_key"` - MinerFee string `json:"miner_fee"` - OrderID string `json:"order_id"` - } `json:"responseV2"` - } `json:"signed_exchange_response"` - WithdrawalCoinName string `json:"withdrawal_coin_name"` - WithdrawalAddressN []uint32 `json:"withdrawal_address_n"` - ReturnAddressN []uint32 `json:"return_address_n"` -} - -var sampleEthSign = `{ - "address_n": [ - 2147483692, - 2147483708, - 2147483648, - 0, - 0 - ], - "nonce": "25", - "gas_price": "05d21dba00", - "gas_limit": "0124f8", - "to": null, - "value": "", - "data_initial_chunk": null, - "data_length": null, - "to_address_n": [], - "address_type": "EXCHANGE", - "exchange_type": { - "signed_exchange_response": { - "response": null, - "signature": "20c1856c630ec481ca597a1f2f6075ab8f05fcbcb9e3298ea8e2a127eacc76ec820acbeaa31d72e0f3bef2e87dd9e8e6ff56d19db0b0a0795a505f370273a73568", - "responseV2": { - "deposit_address": { - "coin_type": "salt", - "address": "0x0081b2ed70c6dfb50d87a072a1ca5dd63b226f96", - "dest_tag": null, - "rs_address": null - }, - "deposit_amount": "989680", - "expiration": "1518034541638", - "quoted_rate": "18587729fb", - "withdrawal_address": { - "coin_type": "doge", - "address": "DRJdizwQLfZMGz886cnr9U9iHuEBLuJjcR", - "dest_tag": null, - "rs_address": null - }, - "withdrawal_amount": "0263535bcc", - "return_address": { - "coin_type": "salt", - "address": "0x6b67c94fc31510707f9c0f1281aad5ec9a2eeff0", - "dest_tag": null, - "rs_address": null - }, - "api_key": "6ad5831b778484bb849da45180ac35047848e5cac0fa666454f4ff78b8c7399fea6a8ce2c7ee6287bcd78db6610ca3f538d6b3e90ca80c8e6368b6021445950b", - "miner_fee": "0bebc200", - "order_id": "44e5533e9b10462d882b8f2690825a73" - } - }, - "withdrawal_coin_name": "Dogecoin", - "withdrawal_address_n": [ - 2147483692, - 2147483651, - 2147483648, - 0, - 0 - ], - "return_address_n": [ - 2147483692, - 2147483708, - 2147483648, - 0, - 0 - ] - }, - "chain_id": null, - "token_value": "989680", - "token_to": null, - "token_shortcut": "SALT", - "typeName": "EthereumSignTx" -}` - -var sampleExchangeResp = `{ - "signed_exchange_response": { - "response": null, - "signature": "20c1856c630ec481ca597a1f2f6075ab8f05fcbcb9e3298ea8e2a127eacc76ec820acbeaa31d72e0f3bef2e87dd9e8e6ff56d19db0b0a0795a505f370273a73568", - "responseV2": { - "deposit_address": { - "coin_type": "salt", - "address": "0x0081b2ed70c6dfb50d87a072a1ca5dd63b226f96", - "dest_tag": null, - "rs_address": null - }, - "deposit_amount": "989680", - "expiration": "1518034541638", - "quoted_rate": "18587729fb", - "withdrawal_address": { - "coin_type": "doge", - "address": "DRJdizwQLfZMGz886cnr9U9iHuEBLuJjcR", - "dest_tag": null, - "rs_address": null - }, - "withdrawal_amount": "0263535bcc", - "return_address": { - "coin_type": "salt", - "address": "0x6b67c94fc31510707f9c0f1281aad5ec9a2eeff0", - "dest_tag": null, - "rs_address": null - }, - "api_key": "6ad5831b778484bb849da45180ac35047848e5cac0fa666454f4ff78b8c7399fea6a8ce2c7ee6287bcd78db6610ca3f538d6b3e90ca80c8e6368b6021445950b", - "miner_fee": "0bebc200", - "order_id": "44e5533e9b10462d882b8f2690825a73" - } - }, - "withdrawal_coin_name": "Dogecoin", - "withdrawal_address_n": [ - 2147483692, - 2147483651, - 2147483648, - 0, - 0 - ], - "return_address_n": [ - 2147483692, - 2147483708, - 2147483648, - 0, - 0 - ] - }` - -// TODO: can i get this reflectively from proto file? func isDebugMessage(req interface{}) bool { switch req.(type) { case *kkProto.DebugLinkDecision, *kkProto.DebugLinkFillConfig, *kkProto.DebugLinkGetState: