mirror of
https://github.com/planetmint/planetmint-go.git
synced 2025-03-30 15:08:28 +00:00
291 lines
6.9 KiB
Go
291 lines
6.9 KiB
Go
package trustwallet
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"strconv"
|
|
"sync"
|
|
)
|
|
|
|
const (
|
|
NoDataReturned = "no data returned"
|
|
NoPublicKeyReturned = "no public key returned"
|
|
NoSignatureReturned = "no signature returned"
|
|
)
|
|
|
|
var (
|
|
keys *PlanetMintKeys
|
|
)
|
|
|
|
type Connector struct {
|
|
oscSender *OSCMessageSender
|
|
mu sync.Mutex
|
|
}
|
|
|
|
func NewTrustWalletConnector(portName string) (*Connector, error) {
|
|
sender, err := NewOSCMessageSender(portName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Connector{
|
|
oscSender: sender,
|
|
}, nil
|
|
}
|
|
|
|
func (t *Connector) sendOSCMessage(address string, args ...interface{}) (OSCResponse, error) {
|
|
t.mu.Lock()
|
|
defer t.mu.Unlock()
|
|
|
|
message, err := encodeOSCMessage(address, args...)
|
|
if err != nil {
|
|
return OSCResponse{}, err
|
|
}
|
|
|
|
return t.oscSender.SendMessage(message)
|
|
}
|
|
|
|
func (t *Connector) ValiseGet() (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw + "/getSeed")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New(NoDataReturned)
|
|
}
|
|
|
|
func (t *Connector) CreateMnemonic() (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/mnemonicToSeed", int32(1))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New(NoDataReturned)
|
|
}
|
|
|
|
func (t *Connector) InjectPlanetminkeyToSE050(slot int) (bool, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/se050InjectSECPKeys", int32(slot))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1] == "0", nil
|
|
}
|
|
return false, errors.New(NoDataReturned)
|
|
}
|
|
|
|
func (t *Connector) RecoverFromMnemonic(mnemonic string) (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/mnemonicToSeed", int32(1), mnemonic)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New(NoDataReturned)
|
|
}
|
|
|
|
func (t *Connector) GetPlanetmintKeys() (*PlanetMintKeys, error) {
|
|
if keys == nil {
|
|
response, err := t.sendOSCMessage(PrefixIhw + "/getPlntmntKeys")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(response.Data) < 4 {
|
|
return nil, errors.New("trust wallet not initialized. Please initialize the wallet")
|
|
}
|
|
|
|
keys = &PlanetMintKeys{
|
|
PlanetmintAddress: response.Data[1],
|
|
ExtendedLiquidPubkey: response.Data[2],
|
|
ExtendedPlanetmintPubkey: response.Data[3],
|
|
RawPlanetmintPubkey: response.Data[4],
|
|
}
|
|
}
|
|
return keys, nil
|
|
}
|
|
|
|
func (t *Connector) GetSeedSE050() (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw + "/se050GetSeed")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New(NoDataReturned)
|
|
}
|
|
|
|
func (t *Connector) SignHashWithPlanetmint(dataToSign string) (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/ecdsaSignPlmnt", dataToSign)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New(NoSignatureReturned)
|
|
}
|
|
|
|
func (t *Connector) SignHashWithRDDL(dataToSign string) (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/ecdsaSignRddl", dataToSign)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New(NoSignatureReturned)
|
|
}
|
|
|
|
func (t *Connector) CreateOptegaKeypair(ctx int) (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/optigaTrustXCreateSecret", int32(ctx), "")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New(NoPublicKeyReturned)
|
|
}
|
|
|
|
func (t *Connector) SignWithOptega(ctx int, dataToSign, pubkey string) (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/optigaTrustXSignMessage", int32(ctx), dataToSign, pubkey, "")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New(NoSignatureReturned)
|
|
}
|
|
|
|
func (t *Connector) UnwrapPublicKey(publicKey string) (bool, string) {
|
|
length := len(publicKey)
|
|
if length == 136 || length == 130 {
|
|
return true, publicKey[len(publicKey)-128:]
|
|
} else if length == 128 {
|
|
return true, publicKey
|
|
}
|
|
return false, publicKey
|
|
}
|
|
|
|
func (t *Connector) CalculateHash(dataToSign string) (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/se050CalculateHash", dataToSign)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New("no hash returned")
|
|
}
|
|
|
|
func (t *Connector) CreateSE050KeypairNIST(ctx int) (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/se050CreateKeyPair", int32(ctx), int32(1))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New(NoPublicKeyReturned)
|
|
}
|
|
|
|
func (t *Connector) GetPublicKeyFromSE050(ctx int) (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/se050GetPublicKey", int32(ctx))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
valid, pubKey := t.UnwrapPublicKey(response.Data[1])
|
|
if !valid {
|
|
return "", errors.New("inject PlanetMintKey failed: No key found")
|
|
}
|
|
return pubKey, nil
|
|
}
|
|
return "", errors.New(NoPublicKeyReturned)
|
|
}
|
|
|
|
func (t *Connector) SignWithSE050(dataToSign string, ctx int) (string, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/se050SignData", dataToSign, int32(ctx))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return response.Data[1], nil
|
|
}
|
|
return "", errors.New(NoSignatureReturned)
|
|
}
|
|
|
|
func (t *Connector) VerifySE050Signature(dataToSign, signature string, ctx int) (bool, error) {
|
|
response, err := t.sendOSCMessage(PrefixIhw+"/se050VerifySignature", dataToSign, signature, int32(ctx))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if len(response.Data) > 1 {
|
|
return strconv.ParseBool(response.Data[1])
|
|
}
|
|
return false, errors.New("no verification result returned")
|
|
}
|
|
|
|
func encodeOSCMessage(address string, args ...interface{}) (returnBytes []byte, err error) {
|
|
var buffer bytes.Buffer
|
|
|
|
// Write address
|
|
buffer.WriteString(address)
|
|
buffer.WriteByte(0)
|
|
alignBuffer(&buffer)
|
|
|
|
// Write type tags
|
|
buffer.WriteByte(',')
|
|
for _, arg := range args {
|
|
switch arg.(type) {
|
|
case int32:
|
|
err = buffer.WriteByte('i')
|
|
case float32:
|
|
err = buffer.WriteByte('f')
|
|
case string:
|
|
err = buffer.WriteByte('s')
|
|
}
|
|
if err != nil {
|
|
return buffer.Bytes(), err
|
|
}
|
|
}
|
|
|
|
buffer.WriteByte(0)
|
|
alignBuffer(&buffer)
|
|
|
|
// Write arguments
|
|
for _, arg := range args {
|
|
switch v := arg.(type) {
|
|
case int32:
|
|
err = binary.Write(&buffer, binary.BigEndian, v)
|
|
case float32:
|
|
err = binary.Write(&buffer, binary.BigEndian, v)
|
|
case string:
|
|
_, err = buffer.WriteString(v)
|
|
if err != nil {
|
|
return buffer.Bytes(), err
|
|
}
|
|
err = buffer.WriteByte(0)
|
|
alignBuffer(&buffer)
|
|
}
|
|
if err != nil {
|
|
return buffer.Bytes(), err
|
|
}
|
|
}
|
|
|
|
return buffer.Bytes(), nil
|
|
}
|
|
|
|
func alignBuffer(buffer *bytes.Buffer) {
|
|
for buffer.Len()%4 != 0 {
|
|
buffer.WriteByte(0)
|
|
}
|
|
}
|