From d8fef89917d1fe779d1491b3b1949b224bc0d4bb Mon Sep 17 00:00:00 2001 From: Lauri Junkkari Date: Wed, 28 Apr 2021 15:26:44 +0300 Subject: [PATCH 1/7] WIP encrypt/decrypt --- pkg/keys/simple/encryption.go | 62 +++++++++++++++++++++++++++++++++++ pkg/keys/simple/store.go | 20 ++++++----- 2 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 pkg/keys/simple/encryption.go diff --git a/pkg/keys/simple/encryption.go b/pkg/keys/simple/encryption.go new file mode 100644 index 0000000..09b6c82 --- /dev/null +++ b/pkg/keys/simple/encryption.go @@ -0,0 +1,62 @@ +package simple + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "fmt" + "io" +) + +type SymmetricCrypter struct { + key []byte +} + +func NewCrypter(key []byte) *SymmetricCrypter { + return &SymmetricCrypter{key} +} + +func (s *SymmetricCrypter) Encrypt(original []byte) ([]byte, error) { + c, err := aes.NewCipher(s.key) + if err != nil { + return []byte(""), err + } + + gcm, err := cipher.NewGCM(c) + if err != nil { + return []byte(""), err + } + + nonce := make([]byte, gcm.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return []byte(""), err + } + + return gcm.Seal(nonce, nonce, original, nil), nil +} + +func (s *SymmetricCrypter) Decrypt(original []byte) ([]byte, error) { + c, err := aes.NewCipher(s.key) + if err != nil { + return []byte(""), err + } + + gcm, err := cipher.NewGCM(c) + if err != nil { + return []byte(""), err + } + + nonceSize := gcm.NonceSize() + if len(original) < nonceSize { + return []byte(""), fmt.Errorf("message too short") + } + + nonce, ciphertext := original[:nonceSize], original[nonceSize:] + + plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) + if err != nil { + return []byte(""), err + } + + return plaintext, nil +} diff --git a/pkg/keys/simple/store.go b/pkg/keys/simple/store.go index eec575e..0bcb387 100644 --- a/pkg/keys/simple/store.go +++ b/pkg/keys/simple/store.go @@ -23,7 +23,7 @@ type KeyStore struct { db data.Store serviceAcct data.AccountKey defaultKeyManager string - encryptionKey string + crypter *SymmetricCrypter signAlgo crypto.SignatureAlgorithm hashAlgo crypto.HashAlgorithm } @@ -44,7 +44,7 @@ func NewKeyStore( db, serviceAcct, defaultKeyManager, - encryptionKey, + NewCrypter([]byte(encryptionKey)), crypto.ECDSA_P256, // TODO: config crypto.SHA3_256, // TODO: config }, nil @@ -129,11 +129,12 @@ func (s *KeyStore) Generate(ctx context.Context, keyIndex int, weight int) (keys func (s *KeyStore) Save(key data.AccountKey) error { switch key.Type { case keys.ACCOUNT_KEY_TYPE_LOCAL: - // TODO: encrypt key.Value - if s.encryptionKey != "" { - panic("key encryption not implemented") + encValue, err := s.crypter.Encrypt([]byte(key.Value)) + if err != nil { + return err } - err := s.db.InsertAccountKey(key) + key.Value = string(encValue) + err = s.db.InsertAccountKey(key) return err default: // TODO: google_kms @@ -169,10 +170,11 @@ func (s *KeyStore) MakeAuthorizer(ctx context.Context, fc *client.Client, addres if err != nil { return authorizer, err } - if s.encryptionKey != "" { - // TODO: decrypt accountKey.Value - panic("key decryption not implemented") + decValue, err := s.crypter.Decrypt([]byte(accountKey.Value)) + if err != nil { + return authorizer, err } + accountKey.Value = string(decValue) } flowAcc, err := fc.GetAccount(ctx, flow.HexToAddress(address)) From 5516f973ce553f8a84103663654c42b768577b18 Mon Sep 17 00:00:00 2001 From: Lauri Junkkari Date: Thu, 29 Apr 2021 10:44:37 +0300 Subject: [PATCH 2/7] Big refactor --- api/account.http | 2 +- main.go | 26 +++--- pkg/account/account.go | 11 +-- pkg/account/service.go | 22 +++-- pkg/data/data.go | 24 ----- pkg/data/gorm/accountstore.go | 31 ++----- pkg/data/gorm/{datastore.go => store.go} | 8 +- pkg/data/store.go | 31 ++++++- pkg/handlers/fungible_tokens.go | 6 +- pkg/handlers/transactions.go | 6 +- pkg/keys/manager.go | 38 ++++++++ pkg/keys/simple/encryption.go | 4 + pkg/keys/simple/{store.go => manager.go} | 113 +++++++++++++---------- pkg/keys/store.go | 34 ------- pkg/tokens/non_fungible.go | 6 +- 15 files changed, 187 insertions(+), 175 deletions(-) delete mode 100644 pkg/data/data.go rename pkg/data/gorm/{datastore.go => store.go} (63%) create mode 100644 pkg/keys/manager.go rename pkg/keys/simple/{store.go => manager.go} (70%) delete mode 100644 pkg/keys/store.go diff --git a/api/account.http b/api/account.http index fb82ce1..32d5ddc 100644 --- a/api/account.http +++ b/api/account.http @@ -6,5 +6,5 @@ POST http://localhost:3000/v1/accounts HTTP/1.1 content-type: application/json ### -GET http://localhost:3000/v1/accounts/test HTTP/1.1 +GET http://localhost:3000/v1/accounts/0f7025fa05b578e3 HTTP/1.1 content-type: application/json diff --git a/main.go b/main.go index f073dd1..645dec1 100644 --- a/main.go +++ b/main.go @@ -15,6 +15,7 @@ import ( "github.com/eqlabs/flow-nft-wallet-service/pkg/data" "github.com/eqlabs/flow-nft-wallet-service/pkg/data/gorm" "github.com/eqlabs/flow-nft-wallet-service/pkg/handlers" + "github.com/eqlabs/flow-nft-wallet-service/pkg/keys" "github.com/eqlabs/flow-nft-wallet-service/pkg/keys/simple" "github.com/gorilla/mux" "github.com/joho/godotenv" @@ -69,11 +70,11 @@ func main() { var db data.Store switch cfg.DatabaseType { case data.DB_TYPE_POSTGRESQL: - db, err = gorm.NewDataStore(postgres.Open(cfg.DatabaseDSN)) + db, err = gorm.NewStore(postgres.Open(cfg.DatabaseDSN)) case data.DB_TYPE_MYSQL: - db, err = gorm.NewDataStore(mysql.Open(cfg.DatabaseDSN)) + db, err = gorm.NewStore(mysql.Open(cfg.DatabaseDSN)) case data.DB_TYPE_SQLITE: - db, err = gorm.NewDataStore(sqlite.Open(cfg.DatabaseDSN)) + db, err = gorm.NewStore(sqlite.Open(cfg.DatabaseDSN)) default: err = fmt.Errorf("database type '%s' not supported", cfg.DatabaseType) } @@ -81,13 +82,14 @@ func main() { log.Fatal(err) } - ks, err := simple.NewKeyStore( + km, err := simple.NewKeyManager( db, - data.AccountKey{ - AccountAddress: cfg.ServiceAccountAddress, - Index: cfg.ServiceAccountKeyIndex, - Type: cfg.ServiceAccountKeyType, - Value: cfg.ServiceAccountKeyValue, + fc, + cfg.ServiceAccountAddress, + keys.Key{ + Index: cfg.ServiceAccountKeyIndex, + Type: cfg.ServiceAccountKeyType, + Value: cfg.ServiceAccountKeyValue, }, cfg.DefaultKeyManager, cfg.EncryptionKey, @@ -96,11 +98,11 @@ func main() { log.Fatal(err) } - accountService := account.NewService(l, db, ks, fc) + accountService := account.NewService(l, db, km, fc) accounts := handlers.NewAccounts(l, accountService) - // transactions := handlers.NewTransactions(l, fc, db, ks) - // fungibleTokens := handlers.NewFungibleTokens(l, fc, db, ks) + // transactions := handlers.NewTransactions(l, fc, db, km) + // fungibleTokens := handlers.NewFungibleTokens(l, fc, db, km) r := mux.NewRouter() diff --git a/pkg/account/account.go b/pkg/account/account.go index 6dfded4..bf16aac 100644 --- a/pkg/account/account.go +++ b/pkg/account/account.go @@ -15,13 +15,13 @@ import ( func Create( ctx context.Context, fc *client.Client, - ks keys.Store, + km keys.Manager, ) ( newAccount data.Account, - newAccountKey data.AccountKey, + newKey keys.Key, err error, ) { - serviceAuth, err := ks.ServiceAuthorizer(ctx, fc) + serviceAuth, err := km.AdminAuthorizer() if err != nil { return } @@ -32,12 +32,12 @@ func Create( } // Generate a new key pair - wrapped, err := ks.Generate(ctx, 0, flow.AccountKeyWeightThreshold) + wrapped, err := km.Generate(0, flow.AccountKeyWeightThreshold) if err != nil { return } publicKey := wrapped.FlowKey - newAccountKey = wrapped.AccountKey + newKey = wrapped.AccountKey // Setup a transaction to create an account tx := templates.CreateAccount([]*flow.AccountKey{publicKey}, nil, serviceAuth.Address) @@ -82,7 +82,6 @@ func Create( return } - newAccountKey.AccountAddress = newAddress newAccount.Address = newAddress return diff --git a/pkg/account/service.go b/pkg/account/service.go index 83630e6..8bf2627 100644 --- a/pkg/account/service.go +++ b/pkg/account/service.go @@ -14,7 +14,7 @@ import ( type Service struct { l *log.Logger db data.Store - ks keys.Store + km keys.Manager fc *client.Client chainId flow.ChainID // TODO: how do we want to handle different chains? } @@ -22,9 +22,9 @@ type Service struct { func NewService( l *log.Logger, db data.Store, - ks keys.Store, + km keys.Manager, fc *client.Client) *Service { - return &Service{l, db, ks, fc, flow.Emulator} + return &Service{l, db, km, fc, flow.Emulator} } func (s *Service) List(ctx context.Context) (accounts []data.Account, err error) { @@ -33,18 +33,18 @@ func (s *Service) List(ctx context.Context) (accounts []data.Account, err error) } func (s *Service) Create(ctx context.Context) (account data.Account, err error) { - account, key, err := Create(ctx, s.fc, s.ks) + account, key, err := Create(ctx, s.fc, s.km) if err != nil { return } - // Store the generated key - err = s.ks.Save(key) + accountKey, err := s.km.Save(key) if err != nil { return } + account.Keys = []data.Key{accountKey} - // Store the account + // Store err = s.db.InsertAccount(account) return @@ -55,7 +55,15 @@ func (s *Service) Details(ctx context.Context, address string) (account data.Acc if err != nil { return } + + // keys, err := s.db.AccountKeys(address) + // if err != nil { + // return + // } + account, err = s.db.Account(address) + // account.Keys = keys + return } diff --git a/pkg/data/data.go b/pkg/data/data.go deleted file mode 100644 index deeccc0..0000000 --- a/pkg/data/data.go +++ /dev/null @@ -1,24 +0,0 @@ -package data - -import ( - "time" - - "gorm.io/gorm" -) - -type Account struct { - Address string `json:"address" gorm:"primaryKey"` - CreatedAt time.Time `json:"-"` - UpdatedAt time.Time `json:"-"` - DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` -} - -type AccountKey struct { - AccountAddress string `json:"address" gorm:"primaryKey"` - Index int `json:"index"` - Type string `json:"type"` // local, google_kms - Value string `json:"value"` // local: private key, google_kms: resource id - CreatedAt time.Time `json:"-"` - UpdatedAt time.Time `json:"-"` - DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` -} diff --git a/pkg/data/gorm/accountstore.go b/pkg/data/gorm/accountstore.go index ea95223..10fcfee 100644 --- a/pkg/data/gorm/accountstore.go +++ b/pkg/data/gorm/accountstore.go @@ -10,46 +10,29 @@ type AccountStore struct { } func newAccountStore(db *gorm.DB) *AccountStore { - db.AutoMigrate(&data.Account{}, &data.AccountKey{}) + db.AutoMigrate(&data.Account{}, &data.Key{}) return &AccountStore{db} } // List all accounts func (s *AccountStore) Accounts() (accounts []data.Account, err error) { - result := s.db.Find(&accounts) - err = result.Error + err = s.db.Select("address").Find(&accounts).Error return } // Insert new account func (s *AccountStore) InsertAccount(account data.Account) error { - result := s.db.Create(&account) - return result.Error + return s.db.Create(&account).Error } // Get account details func (s *AccountStore) Account(address string) (account data.Account, err error) { - result := s.db.First(&account, "address = ?", address) - err = result.Error + err = s.db.Preload("Keys").First(&account, "address = ?", address).Error return } -// List all account keys -func (s *AccountStore) AccountKeys() (keys []data.AccountKey, err error) { - result := s.db.Find(&keys) - err = result.Error - return -} - -// Insert new account key -func (s *AccountStore) InsertAccountKey(key data.AccountKey) error { - result := s.db.Create(&key) - return result.Error -} - -// Get account key details -func (s *AccountStore) AccountKey(address string) (key data.AccountKey, err error) { - result := s.db.First(&key, "address = ?", address) - err = result.Error +// Get account key with index +func (s *AccountStore) AccountKey(address string, index int) (key data.Key, err error) { + err = s.db.Where("account_address = ? AND index = ?", address, index).First(&key).Error return } diff --git a/pkg/data/gorm/datastore.go b/pkg/data/gorm/store.go similarity index 63% rename from pkg/data/gorm/datastore.go rename to pkg/data/gorm/store.go index ded0c82..2341797 100644 --- a/pkg/data/gorm/datastore.go +++ b/pkg/data/gorm/store.go @@ -5,16 +5,16 @@ import ( "gorm.io/gorm" ) -type DataStore struct { +type Store struct { data.AccountStore } -func NewDataStore(dialector gorm.Dialector) (*DataStore, error) { +func NewStore(dialector gorm.Dialector) (*Store, error) { db, err := gorm.Open(dialector, &gorm.Config{}) if err != nil { - return &DataStore{}, nil + return &Store{}, err } - return &DataStore{ + return &Store{ AccountStore: newAccountStore(db), }, nil } diff --git a/pkg/data/store.go b/pkg/data/store.go index b872626..2631f6d 100644 --- a/pkg/data/store.go +++ b/pkg/data/store.go @@ -1,5 +1,11 @@ package data +import ( + "time" + + "gorm.io/gorm" +) + const ( DB_TYPE_POSTGRESQL = "psql" DB_TYPE_MYSQL = "mysql" @@ -14,7 +20,26 @@ type AccountStore interface { Accounts() ([]Account, error) InsertAccount(a Account) error Account(address string) (Account, error) - AccountKeys() ([]AccountKey, error) - InsertAccountKey(k AccountKey) error - AccountKey(address string) (AccountKey, error) + AccountKey(address string, index int) (Key, error) +} + +// Storable account +type Account struct { + Address string `json:"address" gorm:"primaryKey"` + Keys []Key `json:"keys" gorm:"foreignKey:AccountAddress;references:Address;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` + CreatedAt time.Time `json:"-"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` +} + +// Storable account key +type Key struct { + ID int `json:"-" gorm:"primaryKey"` + AccountAddress string `json:"-" gorm:"index"` + Index int `json:"index" gorm:"index"` + Type string `json:"type"` + Value []byte `json:"-"` + CreatedAt time.Time `json:"-"` + UpdatedAt time.Time `json:"-"` + DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` } diff --git a/pkg/handlers/fungible_tokens.go b/pkg/handlers/fungible_tokens.go index 46bf83f..e5bad47 100644 --- a/pkg/handlers/fungible_tokens.go +++ b/pkg/handlers/fungible_tokens.go @@ -14,15 +14,15 @@ type FungibleTokens struct { l *log.Logger c *client.Client db data.Store - ks keys.Store + km keys.Manager } func NewFungibleTokens( l *log.Logger, c *client.Client, db data.Store, - ks keys.Store) *FungibleTokens { - return &FungibleTokens{l, c, db, ks} + km keys.Manager) *FungibleTokens { + return &FungibleTokens{l, c, db, km} } func (s *FungibleTokens) Details(rw http.ResponseWriter, r *http.Request) { diff --git a/pkg/handlers/transactions.go b/pkg/handlers/transactions.go index edb0306..eae542a 100644 --- a/pkg/handlers/transactions.go +++ b/pkg/handlers/transactions.go @@ -13,15 +13,15 @@ type Transactions struct { l *log.Logger c *client.Client db data.Store - ks keys.Store + km keys.Manager } func NewTransactions( l *log.Logger, c *client.Client, db data.Store, - ks keys.Store) *Transactions { - return &Transactions{l, c, db, ks} + km keys.Manager) *Transactions { + return &Transactions{l, c, db, km} } func (s *Transactions) List(rw http.ResponseWriter, r *http.Request) { diff --git a/pkg/keys/manager.go b/pkg/keys/manager.go new file mode 100644 index 0000000..9e5ec4e --- /dev/null +++ b/pkg/keys/manager.go @@ -0,0 +1,38 @@ +package keys + +import ( + "github.com/eqlabs/flow-nft-wallet-service/pkg/data" + "github.com/onflow/flow-go-sdk" + "github.com/onflow/flow-go-sdk/crypto" +) + +const ( + ACCOUNT_KEY_TYPE_LOCAL = "local" + ACCOUNT_KEY_TYPE_GOOGLE_KMS = "google_kms" +) + +type Manager interface { + Generate(keyIndex int, weight int) (Wrapped, error) + Save(Key) (data.Key, error) + Load(data.Key) (Key, error) + AdminAuthorizer() (Authorizer, error) + UserAuthorizer(address string) (Authorizer, error) +} + +// "In flight" account key +type Key struct { + Index int `json:"index"` + Type string `json:"type"` + Value string `json:"-"` +} + +type Authorizer struct { + Address flow.Address + Key *flow.AccountKey + Signer crypto.Signer +} + +type Wrapped struct { + FlowKey *flow.AccountKey + AccountKey Key +} diff --git a/pkg/keys/simple/encryption.go b/pkg/keys/simple/encryption.go index 09b6c82..c955e70 100644 --- a/pkg/keys/simple/encryption.go +++ b/pkg/keys/simple/encryption.go @@ -17,11 +17,13 @@ func NewCrypter(key []byte) *SymmetricCrypter { } func (s *SymmetricCrypter) Encrypt(original []byte) ([]byte, error) { + // TODO: research if these could be stored in the struct c, err := aes.NewCipher(s.key) if err != nil { return []byte(""), err } + // TODO: research if these could be stored in the struct gcm, err := cipher.NewGCM(c) if err != nil { return []byte(""), err @@ -36,11 +38,13 @@ func (s *SymmetricCrypter) Encrypt(original []byte) ([]byte, error) { } func (s *SymmetricCrypter) Decrypt(original []byte) ([]byte, error) { + // TODO: research if these could be stored in the struct c, err := aes.NewCipher(s.key) if err != nil { return []byte(""), err } + // TODO: research if these could be stored in the struct gcm, err := cipher.NewGCM(c) if err != nil { return []byte(""), err diff --git a/pkg/keys/simple/store.go b/pkg/keys/simple/manager.go similarity index 70% rename from pkg/keys/simple/store.go rename to pkg/keys/simple/manager.go index 0bcb387..046b362 100644 --- a/pkg/keys/simple/store.go +++ b/pkg/keys/simple/manager.go @@ -19,9 +19,11 @@ import ( kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1" ) -type KeyStore struct { +type KeyManager struct { db data.Store - serviceAcct data.AccountKey + fc *client.Client + serviceAddress string + serviceKey keys.Key defaultKeyManager string crypter *SymmetricCrypter signAlgo crypto.SignatureAlgorithm @@ -34,15 +36,19 @@ type GoogleKMSConfig struct { KeyRingID string } -func NewKeyStore( +func NewKeyManager( db data.Store, - serviceAcct data.AccountKey, + fc *client.Client, + serviceAddress string, + serviceKey keys.Key, defaultKeyManager string, encryptionKey string, -) (*KeyStore, error) { - return &KeyStore{ +) (*KeyManager, error) { + return &KeyManager{ db, - serviceAcct, + fc, + serviceAddress, + serviceKey, defaultKeyManager, NewCrypter([]byte(encryptionKey)), crypto.ECDSA_P256, // TODO: config @@ -50,17 +56,17 @@ func NewKeyStore( }, nil } -func (s *KeyStore) Generate(ctx context.Context, keyIndex int, weight int) (keys.NewKeyWrapper, error) { +func (s *KeyManager) Generate(keyIndex int, weight int) (keys.Wrapped, error) { switch s.defaultKeyManager { case keys.ACCOUNT_KEY_TYPE_LOCAL: seed := make([]byte, crypto.MinSeedLength) _, err := rand.Read(seed) if err != nil { - return keys.NewKeyWrapper{}, err + return keys.Wrapped{}, err } privateKey, err := crypto.GeneratePrivateKey(s.signAlgo, seed) if err != nil { - return keys.NewKeyWrapper{}, err + return keys.Wrapped{}, err } flowKey := flow.NewAccountKey(). @@ -69,12 +75,17 @@ func (s *KeyStore) Generate(ctx context.Context, keyIndex int, weight int) (keys SetWeight(weight) flowKey.Index = keyIndex - accountKey := data.AccountKey{ + encPrivKey, err := s.crypter.Encrypt([]byte(privateKey.String())) + if err != nil { + return keys.Wrapped{}, err + } + + accountKey := keys.Key{ Index: keyIndex, Type: keys.ACCOUNT_KEY_TYPE_LOCAL, - Value: privateKey.String(), + Value: string(encPrivKey), } - return keys.NewKeyWrapper{FlowKey: flowKey, AccountKey: accountKey}, nil + return keys.Wrapped{FlowKey: flowKey, AccountKey: accountKey}, nil case keys.ACCOUNT_KEY_TYPE_GOOGLE_KMS: // TODO: Take this as a param / config instead gkmsConfig := GoogleKMSConfig{ @@ -84,31 +95,33 @@ func (s *KeyStore) Generate(ctx context.Context, keyIndex int, weight int) (keys } keyUUID := uuid.New() + ctx := context.Background() + // Create the new key in Google KMS - createdKey, err := createKeyAsymmetricSign( + createdKey, err := createKeyAsymmetricSigningKey( ctx, fmt.Sprintf("projects/%s/locations/%s/keyRings/%s", gkmsConfig.ProjectID, gkmsConfig.LocationID, gkmsConfig.KeyRingID), fmt.Sprintf("flow-wallet-account-key-%s", keyUUID.String()), ) if err != nil { fmt.Println(err) - return keys.NewKeyWrapper{}, err + return keys.Wrapped{}, err } client, err := cloudkms.NewClient(ctx) if err != nil { fmt.Println(err) - return keys.NewKeyWrapper{}, err + return keys.Wrapped{}, err } // Get the public key (using flow-go-sdk's cloudkms.Client) publicKey, hashAlgorithm, err := client.GetPublicKey(ctx, createdKey) if err != nil { fmt.Println(err) - return keys.NewKeyWrapper{}, err + return keys.Wrapped{}, err } - accountKey := data.AccountKey{ + accountKey := keys.Key{ Index: keyIndex, Type: keys.ACCOUNT_KEY_TYPE_GOOGLE_KMS, Value: createdKey.ResourceID(), @@ -120,64 +133,62 @@ func (s *KeyStore) Generate(ctx context.Context, keyIndex int, weight int) (keys SetWeight(weight) flowKey.Index = keyIndex - return keys.NewKeyWrapper{FlowKey: flowKey, AccountKey: accountKey}, nil + return keys.Wrapped{FlowKey: flowKey, AccountKey: accountKey}, nil default: - return keys.NewKeyWrapper{}, fmt.Errorf("keyStore.Generate() not implmented for %s", s.defaultKeyManager) + return keys.Wrapped{}, fmt.Errorf("keyStore.Generate() not implmented for %s", s.defaultKeyManager) } } -func (s *KeyStore) Save(key data.AccountKey) error { - switch key.Type { - case keys.ACCOUNT_KEY_TYPE_LOCAL: - encValue, err := s.crypter.Encrypt([]byte(key.Value)) - if err != nil { - return err - } - key.Value = string(encValue) - err = s.db.InsertAccountKey(key) - return err - default: - // TODO: google_kms - return fmt.Errorf("keyStore.Save() not implmented for %s", s.defaultKeyManager) +func (s *KeyManager) Save(key keys.Key) (result data.Key, err error) { + encValue, err := s.crypter.Encrypt([]byte(key.Value)) + if err != nil { + return } + result.Index = key.Index + result.Type = key.Type + result.Value = encValue + return } -func (s *KeyStore) Delete(address string, keyIndex int) error { - panic("not implemented") // TODO: implement +func (s *KeyManager) Load(key data.Key) (result keys.Key, err error) { + decValue, err := s.crypter.Decrypt([]byte(key.Value)) + if err != nil { + return + } + result.Index = key.Index + result.Type = key.Type + result.Value = string(decValue) + return } -func (s *KeyStore) ServiceAuthorizer(ctx context.Context, fc *client.Client) (keys.Authorizer, error) { - return s.MakeAuthorizer(ctx, fc, s.serviceAcct.AccountAddress) +func (s *KeyManager) AdminAuthorizer() (keys.Authorizer, error) { + return s.MakeAuthorizer(s.serviceAddress) } -func (s *KeyStore) AccountAuthorizer(ctx context.Context, fc *client.Client, address string) (keys.Authorizer, error) { - return s.MakeAuthorizer(ctx, fc, address) +func (s *KeyManager) UserAuthorizer(address string) (keys.Authorizer, error) { + return s.MakeAuthorizer(address) } -func (s *KeyStore) MakeAuthorizer(ctx context.Context, fc *client.Client, address string) (keys.Authorizer, error) { - var ( - accountKey data.AccountKey - authorizer keys.Authorizer = keys.Authorizer{} - err error - ) +func (s *KeyManager) MakeAuthorizer(address string) (authorizer keys.Authorizer, err error) { + var accountKey keys.Key + ctx := context.Background() authorizer.Address = flow.HexToAddress(address) - if address == s.serviceAcct.AccountAddress { - accountKey = s.serviceAcct + if address == s.serviceAddress { + accountKey = s.serviceKey } else { - accountKey, err = s.db.AccountKey(address) + dbKey, err := s.db.AccountKey(address, 0) if err != nil { return authorizer, err } - decValue, err := s.crypter.Decrypt([]byte(accountKey.Value)) + accountKey, err = s.Load(dbKey) if err != nil { return authorizer, err } - accountKey.Value = string(decValue) } - flowAcc, err := fc.GetAccount(ctx, flow.HexToAddress(address)) + flowAcc, err := s.fc.GetAccount(ctx, flow.HexToAddress(address)) if err != nil { return authorizer, err } diff --git a/pkg/keys/store.go b/pkg/keys/store.go deleted file mode 100644 index 83277fe..0000000 --- a/pkg/keys/store.go +++ /dev/null @@ -1,34 +0,0 @@ -package keys - -import ( - "context" - - "github.com/eqlabs/flow-nft-wallet-service/pkg/data" - "github.com/onflow/flow-go-sdk" - "github.com/onflow/flow-go-sdk/client" - "github.com/onflow/flow-go-sdk/crypto" -) - -const ( - ACCOUNT_KEY_TYPE_LOCAL = "local" - ACCOUNT_KEY_TYPE_GOOGLE_KMS = "google_kms" -) - -type Store interface { - Generate(ctx context.Context, keyIndex int, weight int) (NewKeyWrapper, error) - Save(data.AccountKey) error - Delete(address string, keyIndex int) error - ServiceAuthorizer(ctx context.Context, fc *client.Client) (Authorizer, error) - AccountAuthorizer(ctx context.Context, fc *client.Client, address string) (Authorizer, error) -} - -type Authorizer struct { - Address flow.Address - Key *flow.AccountKey - Signer crypto.Signer -} - -type NewKeyWrapper struct { - FlowKey *flow.AccountKey - AccountKey data.AccountKey -} diff --git a/pkg/tokens/non_fungible.go b/pkg/tokens/non_fungible.go index 9e0bb02..80961f7 100644 --- a/pkg/tokens/non_fungible.go +++ b/pkg/tokens/non_fungible.go @@ -17,13 +17,13 @@ type NftInfo struct { Name string } -func SetupNFT(ctx context.Context, fc *client.Client, ks keys.Store, address string, n NftInfo) (*flow.TransactionResult, error) { - serviceAuth, err := ks.ServiceAuthorizer(ctx, fc) +func SetupNFT(ctx context.Context, fc *client.Client, km keys.Manager, address string, n NftInfo) (*flow.TransactionResult, error) { + serviceAuth, err := km.AdminAuthorizer() if err != nil { return &flow.TransactionResult{}, err } - accountAuth, err := ks.AccountAuthorizer(ctx, fc, address) + accountAuth, err := km.UserAuthorizer(address) if err != nil { return &flow.TransactionResult{}, err } From ccb637da7336a32eb9c7594e5a13a00f1d44dc24 Mon Sep 17 00:00:00 2001 From: Lauri Junkkari Date: Thu, 29 Apr 2021 13:25:24 +0300 Subject: [PATCH 3/7] Update readme --- README.md | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 62205b5..0f431c2 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,24 @@ Run: # edit .env go run main.go +_Note: +The emulator creates new account addresses deterministically. This means that deleting the emulators docker volume will cause the emulator to start from the beginning and give the same addresses as before possibly ending in duplicate key errors in database._ + ## Configuration ### Database -| Config variable | ENV | descrpition | default | examples | -| --------------- | :-----: | ------------------------------------------------------------------------------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| DatabaseType | DB_TYPE | Type of database driver | sqlite | | -| DatabaseDSN | DB_DSN | Data source name ([DSN](https://en.wikipedia.org/wiki/Data_source_name)) for database connection | wallet.db | mysql://john:pass@localhost:3306/my_db

user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local

host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai

For more: https://gorm.io/docs/connecting_to_the_database.html | +| Config variable | ENV | descrpition | default | examples | +| --------------- | :-----: | ------------------------------------------------------------------------------------------------ | --------- | --------- | +| DatabaseType | DB_TYPE | Type of database driver | sqlite | | +| DatabaseDSN | DB_DSN | Data source name ([DSN](https://en.wikipedia.org/wiki/Data_source_name)) for database connection | wallet.db | See below | + +Examples of Database DSN + + mysql://john:pass@localhost:3306/my_db + + user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local + + host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai + +For more: https://gorm.io/docs/connecting_to_the_database.html From 927979c4885a1c61be0bdf09ac9fb1c4a6669e5a Mon Sep 17 00:00:00 2001 From: Lauri Junkkari Date: Thu, 29 Apr 2021 14:31:56 +0300 Subject: [PATCH 4/7] Clean up --- pkg/keys/google/google.go | 58 ++++++++++++++++++++++++ pkg/keys/simple/manager.go | 90 +++++++++----------------------------- 2 files changed, 79 insertions(+), 69 deletions(-) create mode 100644 pkg/keys/google/google.go diff --git a/pkg/keys/google/google.go b/pkg/keys/google/google.go new file mode 100644 index 0000000..1ca932b --- /dev/null +++ b/pkg/keys/google/google.go @@ -0,0 +1,58 @@ +package google + +import ( + "context" + "fmt" + "strings" + + "github.com/onflow/flow-go-sdk/crypto/cloudkms" + + kms "cloud.google.com/go/kms/apiv1" + kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1" +) + +// Creates a new asymmetric signing key in Google KMS and returns a cloudkms.Key (the "raw" result isn't needed) +func AsyncKey(ctx context.Context, parent, id string) (createdKey cloudkms.Key, err error) { + kmsClient, err := kms.NewKeyManagementClient(ctx) + if err != nil { + return + } + + req := &kmspb.CreateCryptoKeyRequest{ + Parent: parent, + CryptoKeyId: id, + CryptoKey: &kmspb.CryptoKey{ + Purpose: kmspb.CryptoKey_ASYMMETRIC_SIGN, + VersionTemplate: &kmspb.CryptoKeyVersionTemplate{ + Algorithm: kmspb.CryptoKeyVersion_EC_SIGN_P256_SHA256, + }, + // TODO: Set relevant labels at creation, update post-creation if necessary + Labels: map[string]string{ + "service": "flow-nft-wallet-service", + "account_address": "", + "chain_id": "", + "environment": "development", + }, + }, + } + + googleKey, err := kmsClient.CreateCryptoKey(ctx, req) + if err != nil { + return + } + + // Append cryptoKeyVersions so that we can utilize the KeyFromResourceID method + createdKey, err = cloudkms.KeyFromResourceID(fmt.Sprintf("%s/cryptoKeyVersions/1", googleKey.Name)) + if err != nil { + fmt.Println("Could not create cloudkms.Key from ResourceId:", googleKey.Name) + return + } + + // Validate key name + if !strings.HasPrefix(createdKey.ResourceID(), googleKey.Name) { + fmt.Println("WARNING: created Google KMS key name does not match the expected", createdKey.ResourceID(), " vs ", googleKey.Name) + // TODO: Handle scenario + } + + return +} diff --git a/pkg/keys/simple/manager.go b/pkg/keys/simple/manager.go index 046b362..ec0535c 100644 --- a/pkg/keys/simple/manager.go +++ b/pkg/keys/simple/manager.go @@ -5,18 +5,16 @@ import ( "crypto/rand" "fmt" "os" - "strings" "github.com/eqlabs/flow-nft-wallet-service/pkg/data" "github.com/eqlabs/flow-nft-wallet-service/pkg/keys" + "github.com/eqlabs/flow-nft-wallet-service/pkg/keys/google" "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/client" "github.com/onflow/flow-go-sdk/crypto" "github.com/onflow/flow-go-sdk/crypto/cloudkms" - kms "cloud.google.com/go/kms/apiv1" "github.com/google/uuid" - kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1" ) type KeyManager struct { @@ -56,17 +54,18 @@ func NewKeyManager( }, nil } -func (s *KeyManager) Generate(keyIndex int, weight int) (keys.Wrapped, error) { +func (s *KeyManager) Generate(keyIndex int, weight int) (result keys.Wrapped, err error) { switch s.defaultKeyManager { case keys.ACCOUNT_KEY_TYPE_LOCAL: seed := make([]byte, crypto.MinSeedLength) _, err := rand.Read(seed) if err != nil { - return keys.Wrapped{}, err + break } + privateKey, err := crypto.GeneratePrivateKey(s.signAlgo, seed) if err != nil { - return keys.Wrapped{}, err + break } flowKey := flow.NewAccountKey(). @@ -75,17 +74,15 @@ func (s *KeyManager) Generate(keyIndex int, weight int) (keys.Wrapped, error) { SetWeight(weight) flowKey.Index = keyIndex - encPrivKey, err := s.crypter.Encrypt([]byte(privateKey.String())) - if err != nil { - return keys.Wrapped{}, err - } - accountKey := keys.Key{ Index: keyIndex, Type: keys.ACCOUNT_KEY_TYPE_LOCAL, - Value: string(encPrivKey), + Value: privateKey.String(), } - return keys.Wrapped{FlowKey: flowKey, AccountKey: accountKey}, nil + + result.AccountKey = accountKey + result.FlowKey = flowKey + case keys.ACCOUNT_KEY_TYPE_GOOGLE_KMS: // TODO: Take this as a param / config instead gkmsConfig := GoogleKMSConfig{ @@ -93,32 +90,30 @@ func (s *KeyManager) Generate(keyIndex int, weight int) (keys.Wrapped, error) { LocationID: os.Getenv("GOOGLE_KMS_LOCATION_ID"), KeyRingID: os.Getenv("GOOGLE_KMS_KEYRING_ID"), } - keyUUID := uuid.New() ctx := context.Background() + keyUUID := uuid.New() + // Create the new key in Google KMS - createdKey, err := createKeyAsymmetricSigningKey( + createdKey, err := google.AsyncKey( ctx, fmt.Sprintf("projects/%s/locations/%s/keyRings/%s", gkmsConfig.ProjectID, gkmsConfig.LocationID, gkmsConfig.KeyRingID), fmt.Sprintf("flow-wallet-account-key-%s", keyUUID.String()), ) if err != nil { - fmt.Println(err) - return keys.Wrapped{}, err + break } client, err := cloudkms.NewClient(ctx) if err != nil { - fmt.Println(err) - return keys.Wrapped{}, err + break } // Get the public key (using flow-go-sdk's cloudkms.Client) publicKey, hashAlgorithm, err := client.GetPublicKey(ctx, createdKey) if err != nil { - fmt.Println(err) - return keys.Wrapped{}, err + break } accountKey := keys.Key{ @@ -133,10 +128,13 @@ func (s *KeyManager) Generate(keyIndex int, weight int) (keys.Wrapped, error) { SetWeight(weight) flowKey.Index = keyIndex - return keys.Wrapped{FlowKey: flowKey, AccountKey: accountKey}, nil + result.AccountKey = accountKey + result.FlowKey = flowKey + default: - return keys.Wrapped{}, fmt.Errorf("keyStore.Generate() not implmented for %s", s.defaultKeyManager) + err = fmt.Errorf("keyStore.Generate() not implmented for %s", s.defaultKeyManager) } + return } func (s *KeyManager) Save(key keys.Key) (result data.Key, err error) { @@ -231,49 +229,3 @@ func (s *KeyManager) MakeAuthorizer(address string) (authorizer keys.Authorizer, return authorizer, nil } - -// Creates a new asymmetric signing key in Google KMS and returns a cloudkms.Key (the "raw" result isn't needed) -func createKeyAsymmetricSigningKey(ctx context.Context, parent, id string) (createdKey cloudkms.Key, err error) { - kmsClient, err := kms.NewKeyManagementClient(ctx) - if err != nil { - return - } - - req := &kmspb.CreateCryptoKeyRequest{ - Parent: parent, - CryptoKeyId: id, - CryptoKey: &kmspb.CryptoKey{ - Purpose: kmspb.CryptoKey_ASYMMETRIC_SIGN, - VersionTemplate: &kmspb.CryptoKeyVersionTemplate{ - Algorithm: kmspb.CryptoKeyVersion_EC_SIGN_P256_SHA256, - }, - // TODO: Set relevant labels at creation, update post-creation if necessary - Labels: map[string]string{ - "service": "flow-nft-wallet-service", - "account_address": "", - "chain_id": "", - "environment": "development", - }, - }, - } - - googleKey, err := kmsClient.CreateCryptoKey(ctx, req) - if err != nil { - return - } - - // Append cryptoKeyVersions so that we can utilize the KeyFromResourceID method - createdKey, err = cloudkms.KeyFromResourceID(fmt.Sprintf("%s/cryptoKeyVersions/1", googleKey.Name)) - if err != nil { - fmt.Println("Could not create cloudkms.Key from ResourceId:", googleKey.Name) - return - } - - // Validate key name - if !strings.HasPrefix(createdKey.ResourceID(), googleKey.Name) { - fmt.Println("WARNING: created Google KMS key name does not match the expected", createdKey.ResourceID(), " vs ", googleKey.Name) - // TODO: Handle scenario - } - - return -} From 55df102a66f82b9a0535fe155ddd4f84e2d33272 Mon Sep 17 00:00:00 2001 From: Lauri Junkkari Date: Thu, 29 Apr 2021 14:37:45 +0300 Subject: [PATCH 5/7] More cleanup --- pkg/keys/simple/manager.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pkg/keys/simple/manager.go b/pkg/keys/simple/manager.go index ec0535c..ea17d8f 100644 --- a/pkg/keys/simple/manager.go +++ b/pkg/keys/simple/manager.go @@ -176,19 +176,20 @@ func (s *KeyManager) MakeAuthorizer(address string) (authorizer keys.Authorizer, if address == s.serviceAddress { accountKey = s.serviceKey } else { - dbKey, err := s.db.AccountKey(address, 0) + var rawKey data.Key + rawKey, err = s.db.AccountKey(address, 0) if err != nil { - return authorizer, err + return } - accountKey, err = s.Load(dbKey) + accountKey, err = s.Load(rawKey) if err != nil { - return authorizer, err + return } } flowAcc, err := s.fc.GetAccount(ctx, flow.HexToAddress(address)) if err != nil { - return authorizer, err + return } authorizer.Key = flowAcc.Keys[accountKey.Index] @@ -199,18 +200,18 @@ func (s *KeyManager) MakeAuthorizer(address string) (authorizer keys.Authorizer, case keys.ACCOUNT_KEY_TYPE_LOCAL: pk, err := crypto.DecodePrivateKeyHex(s.signAlgo, accountKey.Value) if err != nil { - return authorizer, err + break } authorizer.Signer = crypto.NewInMemorySigner(pk, s.hashAlgo) case keys.ACCOUNT_KEY_TYPE_GOOGLE_KMS: kmsClient, err := cloudkms.NewClient(ctx) if err != nil { - return authorizer, err + break } kmsKey, err := cloudkms.KeyFromResourceID(accountKey.Value) if err != nil { - return authorizer, err + break } sig, err := kmsClient.SignerForKey( @@ -219,13 +220,12 @@ func (s *KeyManager) MakeAuthorizer(address string) (authorizer keys.Authorizer, kmsKey, ) if err != nil { - return authorizer, err + break } authorizer.Signer = sig default: - return authorizer, - fmt.Errorf("accountKey.Type not recognised: %s", accountKey.Type) + err = fmt.Errorf("accountKey.Type not recognised: %s", accountKey.Type) } - return authorizer, nil + return } From 7db551859523908a38a641bf63327b3241a5fd92 Mon Sep 17 00:00:00 2001 From: Lauri Junkkari Date: Thu, 29 Apr 2021 14:38:25 +0300 Subject: [PATCH 6/7] Fix typo --- pkg/keys/google/google.go | 2 +- pkg/keys/simple/manager.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/keys/google/google.go b/pkg/keys/google/google.go index 1ca932b..44e0f5b 100644 --- a/pkg/keys/google/google.go +++ b/pkg/keys/google/google.go @@ -12,7 +12,7 @@ import ( ) // Creates a new asymmetric signing key in Google KMS and returns a cloudkms.Key (the "raw" result isn't needed) -func AsyncKey(ctx context.Context, parent, id string) (createdKey cloudkms.Key, err error) { +func AsymKey(ctx context.Context, parent, id string) (createdKey cloudkms.Key, err error) { kmsClient, err := kms.NewKeyManagementClient(ctx) if err != nil { return diff --git a/pkg/keys/simple/manager.go b/pkg/keys/simple/manager.go index ea17d8f..41761ae 100644 --- a/pkg/keys/simple/manager.go +++ b/pkg/keys/simple/manager.go @@ -96,7 +96,7 @@ func (s *KeyManager) Generate(keyIndex int, weight int) (result keys.Wrapped, er keyUUID := uuid.New() // Create the new key in Google KMS - createdKey, err := google.AsyncKey( + createdKey, err := google.AsymKey( ctx, fmt.Sprintf("projects/%s/locations/%s/keyRings/%s", gkmsConfig.ProjectID, gkmsConfig.LocationID, gkmsConfig.KeyRingID), fmt.Sprintf("flow-wallet-account-key-%s", keyUUID.String()), From f1fb1cb6a5634c70dad389f5ce0c7983febc530b Mon Sep 17 00:00:00 2001 From: Lauri Junkkari Date: Thu, 29 Apr 2021 14:41:20 +0300 Subject: [PATCH 7/7] Get rid or pkg folder --- {pkg/account => account}/account.go | 6 +++--- {pkg/account => account}/service.go | 4 ++-- {pkg/data => data}/gorm/accountstore.go | 2 +- {pkg/data => data}/gorm/store.go | 2 +- {pkg/data => data}/store.go | 0 {pkg/flow_helpers => flow_helpers}/flow_helpers.go | 0 {pkg/handlers => handlers}/accounts.go | 2 +- {pkg/handlers => handlers}/fungible_tokens.go | 4 ++-- {pkg/handlers => handlers}/transactions.go | 4 ++-- {pkg/keys => keys}/google/google.go | 0 {pkg/keys => keys}/manager.go | 2 +- {pkg/keys => keys}/simple/encryption.go | 0 {pkg/keys => keys}/simple/manager.go | 6 +++--- main.go | 12 ++++++------ {pkg/tokens => tokens}/fungible.go | 0 {pkg/tokens => tokens}/non_fungible.go | 4 ++-- 16 files changed, 24 insertions(+), 24 deletions(-) rename {pkg/account => account}/account.go (92%) rename {pkg/account => account}/service.go (93%) rename {pkg/data => data}/gorm/accountstore.go (94%) rename {pkg/data => data}/gorm/store.go (84%) rename {pkg/data => data}/store.go (100%) rename {pkg/flow_helpers => flow_helpers}/flow_helpers.go (100%) rename {pkg/handlers => handlers}/accounts.go (96%) rename {pkg/handlers => handlers}/fungible_tokens.go (90%) rename {pkg/handlers => handlers}/transactions.go (86%) rename {pkg/keys => keys}/google/google.go (100%) rename {pkg/keys => keys}/manager.go (93%) rename {pkg/keys => keys}/simple/encryption.go (100%) rename {pkg/keys => keys}/simple/manager.go (96%) rename {pkg/tokens => tokens}/fungible.go (100%) rename {pkg/tokens => tokens}/non_fungible.go (94%) diff --git a/pkg/account/account.go b/account/account.go similarity index 92% rename from pkg/account/account.go rename to account/account.go index bf16aac..7c9824e 100644 --- a/pkg/account/account.go +++ b/account/account.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/eqlabs/flow-nft-wallet-service/pkg/data" - "github.com/eqlabs/flow-nft-wallet-service/pkg/flow_helpers" - "github.com/eqlabs/flow-nft-wallet-service/pkg/keys" + "github.com/eqlabs/flow-nft-wallet-service/data" + "github.com/eqlabs/flow-nft-wallet-service/flow_helpers" + "github.com/eqlabs/flow-nft-wallet-service/keys" "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/client" "github.com/onflow/flow-go-sdk/templates" diff --git a/pkg/account/service.go b/account/service.go similarity index 93% rename from pkg/account/service.go rename to account/service.go index 8bf2627..555c38f 100644 --- a/pkg/account/service.go +++ b/account/service.go @@ -5,8 +5,8 @@ import ( "fmt" "log" - "github.com/eqlabs/flow-nft-wallet-service/pkg/data" - "github.com/eqlabs/flow-nft-wallet-service/pkg/keys" + "github.com/eqlabs/flow-nft-wallet-service/data" + "github.com/eqlabs/flow-nft-wallet-service/keys" "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/client" ) diff --git a/pkg/data/gorm/accountstore.go b/data/gorm/accountstore.go similarity index 94% rename from pkg/data/gorm/accountstore.go rename to data/gorm/accountstore.go index 10fcfee..fcac1d2 100644 --- a/pkg/data/gorm/accountstore.go +++ b/data/gorm/accountstore.go @@ -1,7 +1,7 @@ package gorm import ( - "github.com/eqlabs/flow-nft-wallet-service/pkg/data" + "github.com/eqlabs/flow-nft-wallet-service/data" "gorm.io/gorm" ) diff --git a/pkg/data/gorm/store.go b/data/gorm/store.go similarity index 84% rename from pkg/data/gorm/store.go rename to data/gorm/store.go index 2341797..aa0d0a2 100644 --- a/pkg/data/gorm/store.go +++ b/data/gorm/store.go @@ -1,7 +1,7 @@ package gorm import ( - "github.com/eqlabs/flow-nft-wallet-service/pkg/data" + "github.com/eqlabs/flow-nft-wallet-service/data" "gorm.io/gorm" ) diff --git a/pkg/data/store.go b/data/store.go similarity index 100% rename from pkg/data/store.go rename to data/store.go diff --git a/pkg/flow_helpers/flow_helpers.go b/flow_helpers/flow_helpers.go similarity index 100% rename from pkg/flow_helpers/flow_helpers.go rename to flow_helpers/flow_helpers.go diff --git a/pkg/handlers/accounts.go b/handlers/accounts.go similarity index 96% rename from pkg/handlers/accounts.go rename to handlers/accounts.go index b271318..27413c4 100644 --- a/pkg/handlers/accounts.go +++ b/handlers/accounts.go @@ -6,7 +6,7 @@ import ( "log" "net/http" - "github.com/eqlabs/flow-nft-wallet-service/pkg/account" + "github.com/eqlabs/flow-nft-wallet-service/account" "github.com/gorilla/mux" ) diff --git a/pkg/handlers/fungible_tokens.go b/handlers/fungible_tokens.go similarity index 90% rename from pkg/handlers/fungible_tokens.go rename to handlers/fungible_tokens.go index e5bad47..daf0e0a 100644 --- a/pkg/handlers/fungible_tokens.go +++ b/handlers/fungible_tokens.go @@ -4,8 +4,8 @@ import ( "log" "net/http" - "github.com/eqlabs/flow-nft-wallet-service/pkg/data" - "github.com/eqlabs/flow-nft-wallet-service/pkg/keys" + "github.com/eqlabs/flow-nft-wallet-service/data" + "github.com/eqlabs/flow-nft-wallet-service/keys" "github.com/gorilla/mux" "github.com/onflow/flow-go-sdk/client" ) diff --git a/pkg/handlers/transactions.go b/handlers/transactions.go similarity index 86% rename from pkg/handlers/transactions.go rename to handlers/transactions.go index eae542a..6df2076 100644 --- a/pkg/handlers/transactions.go +++ b/handlers/transactions.go @@ -4,8 +4,8 @@ import ( "log" "net/http" - "github.com/eqlabs/flow-nft-wallet-service/pkg/data" - "github.com/eqlabs/flow-nft-wallet-service/pkg/keys" + "github.com/eqlabs/flow-nft-wallet-service/data" + "github.com/eqlabs/flow-nft-wallet-service/keys" "github.com/onflow/flow-go-sdk/client" ) diff --git a/pkg/keys/google/google.go b/keys/google/google.go similarity index 100% rename from pkg/keys/google/google.go rename to keys/google/google.go diff --git a/pkg/keys/manager.go b/keys/manager.go similarity index 93% rename from pkg/keys/manager.go rename to keys/manager.go index 9e5ec4e..f597d9f 100644 --- a/pkg/keys/manager.go +++ b/keys/manager.go @@ -1,7 +1,7 @@ package keys import ( - "github.com/eqlabs/flow-nft-wallet-service/pkg/data" + "github.com/eqlabs/flow-nft-wallet-service/data" "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/crypto" ) diff --git a/pkg/keys/simple/encryption.go b/keys/simple/encryption.go similarity index 100% rename from pkg/keys/simple/encryption.go rename to keys/simple/encryption.go diff --git a/pkg/keys/simple/manager.go b/keys/simple/manager.go similarity index 96% rename from pkg/keys/simple/manager.go rename to keys/simple/manager.go index 41761ae..c8e3608 100644 --- a/pkg/keys/simple/manager.go +++ b/keys/simple/manager.go @@ -6,9 +6,9 @@ import ( "fmt" "os" - "github.com/eqlabs/flow-nft-wallet-service/pkg/data" - "github.com/eqlabs/flow-nft-wallet-service/pkg/keys" - "github.com/eqlabs/flow-nft-wallet-service/pkg/keys/google" + "github.com/eqlabs/flow-nft-wallet-service/data" + "github.com/eqlabs/flow-nft-wallet-service/keys" + "github.com/eqlabs/flow-nft-wallet-service/keys/google" "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/client" "github.com/onflow/flow-go-sdk/crypto" diff --git a/main.go b/main.go index 645dec1..8735aa0 100644 --- a/main.go +++ b/main.go @@ -11,12 +11,12 @@ import ( "time" "github.com/caarlos0/env/v6" - "github.com/eqlabs/flow-nft-wallet-service/pkg/account" - "github.com/eqlabs/flow-nft-wallet-service/pkg/data" - "github.com/eqlabs/flow-nft-wallet-service/pkg/data/gorm" - "github.com/eqlabs/flow-nft-wallet-service/pkg/handlers" - "github.com/eqlabs/flow-nft-wallet-service/pkg/keys" - "github.com/eqlabs/flow-nft-wallet-service/pkg/keys/simple" + "github.com/eqlabs/flow-nft-wallet-service/account" + "github.com/eqlabs/flow-nft-wallet-service/data" + "github.com/eqlabs/flow-nft-wallet-service/data/gorm" + "github.com/eqlabs/flow-nft-wallet-service/handlers" + "github.com/eqlabs/flow-nft-wallet-service/keys" + "github.com/eqlabs/flow-nft-wallet-service/keys/simple" "github.com/gorilla/mux" "github.com/joho/godotenv" "github.com/onflow/flow-go-sdk/client" diff --git a/pkg/tokens/fungible.go b/tokens/fungible.go similarity index 100% rename from pkg/tokens/fungible.go rename to tokens/fungible.go diff --git a/pkg/tokens/non_fungible.go b/tokens/non_fungible.go similarity index 94% rename from pkg/tokens/non_fungible.go rename to tokens/non_fungible.go index 80961f7..8944dea 100644 --- a/pkg/tokens/non_fungible.go +++ b/tokens/non_fungible.go @@ -5,8 +5,8 @@ import ( "io/ioutil" "strings" - "github.com/eqlabs/flow-nft-wallet-service/pkg/flow_helpers" - "github.com/eqlabs/flow-nft-wallet-service/pkg/keys" + "github.com/eqlabs/flow-nft-wallet-service/flow_helpers" + "github.com/eqlabs/flow-nft-wallet-service/keys" "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/client" )