From 7041cf2a273835160410474bf57c2492580827a9 Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Tue, 1 Feb 2022 11:09:42 -0500 Subject: [PATCH 01/10] Support multiple token connectors in a stack, with ERC20/ERC721 Signed-off-by: Peter Broadhurst --- cmd/init.go | 14 +-- internal/core/firefly_config.go | 2 +- internal/stacks/stack_manager.go | 90 ++++++++++-------- internal/stacks/types.go | 35 ++++--- internal/tokens/erc1155/erc1155_provider.go | 26 +++-- internal/tokens/erc20erc721/contracts.go | 39 ++++++++ internal/tokens/erc20erc721/erc20_erc721.go | 95 +++++++++++++++++++ .../tokens/niltokens/niltokens_provider.go | 46 --------- internal/tokens/tokens_provider.go | 6 +- pkg/types/manifest.go | 14 +-- pkg/types/stack.go | 16 +++- 11 files changed, 252 insertions(+), 131 deletions(-) create mode 100644 internal/tokens/erc20erc721/contracts.go create mode 100644 internal/tokens/erc20erc721/erc20_erc721.go delete mode 100644 internal/tokens/niltokens/niltokens_provider.go diff --git a/cmd/init.go b/cmd/init.go index 56736635..cb9cb79c 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -33,7 +33,7 @@ import ( var initOptions stacks.InitOptions var databaseSelection string var blockchainProviderInput string -var tokensProviderSelection string +var tokenProvidersSelection []string var promptNames bool var ffNameValidator = regexp.MustCompile(`^[0-9a-zA-Z]([0-9a-zA-Z._-]{0,62}[0-9a-zA-Z])?$`) @@ -53,7 +53,7 @@ var initCmd = &cobra.Command{ if err := validateBlockchainProvider(blockchainProviderInput); err != nil { return err } - if err := validateTokensProvider(tokensProviderSelection); err != nil { + if err := validateTokensProvider(tokenProvidersSelection); err != nil { return err } @@ -100,7 +100,7 @@ var initCmd = &cobra.Command{ initOptions.Verbose = verbose initOptions.BlockchainProvider, _ = stacks.BlockchainProviderFromString(blockchainProviderInput) initOptions.DatabaseSelection, _ = stacks.DatabaseSelectionFromString(databaseSelection) - initOptions.TokensProvider, _ = stacks.TokensProviderFromString(tokensProviderSelection) + initOptions.TokenProviders, _ = stacks.TokensProviderFromStrings(tokenProvidersSelection) if err := stackManager.InitStack(stackName, memberCount, &initOptions); err != nil { return err @@ -161,14 +161,14 @@ func validateBlockchainProvider(input string) error { // TODO: When we get tokens on Fabric this should change if blockchainSelection == stacks.HyperledgerFabric { - tokensProviderSelection = "none" + tokenProvidersSelection = []string{} } return nil } -func validateTokensProvider(input string) error { - _, err := stacks.TokensProviderFromString(input) +func validateTokensProvider(input []string) error { + _, err := stacks.TokensProviderFromStrings(input) if err != nil { return err } @@ -180,7 +180,7 @@ func init() { initCmd.Flags().IntVarP(&initOptions.ServicesBasePort, "services-base-port", "s", 5100, "Mapped port base of services (100 added for each member)") initCmd.Flags().StringVarP(&databaseSelection, "database", "d", "sqlite3", fmt.Sprintf("Database type to use. Options are: %v", stacks.DBSelectionStrings)) initCmd.Flags().StringVarP(&blockchainProviderInput, "blockchain-provider", "b", "geth", fmt.Sprintf("Blockchain provider to use. Options are: %v", stacks.BlockchainProviderStrings)) - initCmd.Flags().StringVarP(&tokensProviderSelection, "tokens-provider", "t", "erc1155", fmt.Sprintf("Tokens provider to use. Options are: %v", stacks.TokensProviderStrings)) + initCmd.Flags().StringArrayVarP(&tokenProvidersSelection, "token-providers", "t", []string{"erc1155", "erc20erc721"}, fmt.Sprintf("Token providers to use. Options are: %v", stacks.ValidTokenProviders)) initCmd.Flags().IntVarP(&initOptions.ExternalProcesses, "external", "e", 0, "Manage a number of FireFly core processes outside of the docker-compose stack - useful for development and debugging") initCmd.Flags().StringVarP(&initOptions.FireFlyVersion, "release", "r", "latest", "Select the FireFly release version to use") initCmd.Flags().StringVarP(&initOptions.ManifestPath, "manifest", "m", "", "Path to a manifest.json file containing the versions of each FireFly microservice to use. Overrides the --release flag.") diff --git a/internal/core/firefly_config.go b/internal/core/firefly_config.go index b29922f7..c2c5dd72 100644 --- a/internal/core/firefly_config.go +++ b/internal/core/firefly_config.go @@ -149,7 +149,7 @@ type FireflyConfig struct { Database *DatabaseConfig `yaml:"database,omitempty"` P2PFS *PublicStorageConfig `yaml:"publicstorage,omitempty"` DataExchange *DataExchangeConfig `yaml:"dataexchange,omitempty"` - Tokens *TokensConfig `yaml:"tokens,omitempty"` + Tokens TokensConfig `yaml:"tokens,omitempty"` } func NewFireflyConfig(stack *types.Stack, member *types.Member) *FireflyConfig { diff --git a/internal/stacks/stack_manager.go b/internal/stacks/stack_manager.go index 7501614b..86506208 100644 --- a/internal/stacks/stack_manager.go +++ b/internal/stacks/stack_manager.go @@ -41,7 +41,6 @@ import ( "github.com/hyperledger/firefly-cli/internal/docker" "github.com/hyperledger/firefly-cli/internal/tokens" "github.com/hyperledger/firefly-cli/internal/tokens/erc1155" - "github.com/hyperledger/firefly-cli/internal/tokens/niltokens" "github.com/hyperledger/firefly-cli/pkg/types" "golang.org/x/crypto/sha3" @@ -54,7 +53,7 @@ type StackManager struct { Log log.Logger Stack *types.Stack blockchainProvider blockchain.IBlockchainProvider - tokensProvider tokens.ITokensProvider + tokenProviders []tokens.ITokensProvider } type PullOptions struct { @@ -74,7 +73,7 @@ type InitOptions struct { OrgNames []string NodeNames []string BlockchainProvider BlockchainProvider - TokensProvider TokensProvider + TokenProviders types.TokenProviders FireFlyVersion string ManifestPath string } @@ -112,7 +111,7 @@ func (s *StackManager) InitStack(stackName string, memberCount int, options *Ini ExposedBlockchainPort: options.ServicesBasePort, Database: options.DatabaseSelection.String(), BlockchainProvider: options.BlockchainProvider.String(), - TokensProvider: options.TokensProvider.String(), + TokenProviders: options.TokenProviders, } var manifest *types.VersionManifest @@ -140,7 +139,7 @@ func (s *StackManager) InitStack(stackName string, memberCount int, options *Ini s.Stack.VersionManifest = manifest s.blockchainProvider = s.getBlockchainProvider(false) - s.tokensProvider = s.getTokensProvider(false) + s.tokenProviders = s.getITokenProviders(false) for i := 0; i < memberCount; i++ { externalProcess := i < options.ExternalProcesses @@ -148,7 +147,9 @@ func (s *StackManager) InitStack(stackName string, memberCount int, options *Ini } compose := docker.CreateDockerCompose(s.Stack) extraServices := s.blockchainProvider.GetDockerServiceDefinitions() - extraServices = append(extraServices, s.tokensProvider.GetDockerServiceDefinitions()...) + for i, tp := range s.tokenProviders { + extraServices = append(extraServices, tp.GetDockerServiceDefinitions(i)...) + } for _, serviceDefinition := range extraServices { // Add each service definition to the docker compose file @@ -208,7 +209,7 @@ func (s *StackManager) LoadStack(stackName string, verbose bool) error { } s.Stack = stack s.blockchainProvider = s.getBlockchainProvider(verbose) - s.tokensProvider = s.getTokensProvider(verbose) + s.tokenProviders = s.getITokenProviders(verbose) } // For backwards compatability, add a "default" VersionManifest // in memory for stacks that were created with old CLI versions @@ -230,10 +231,14 @@ func (s *StackManager) LoadStack(stackName string, verbose bool) error { Image: "ghcr.io/hyperledger/firefly-dataexchange-https", Tag: "latest", }, - Tokens: &types.ManifestEntry{ + TokensERC1155: &types.ManifestEntry{ Image: "ghcr.io/hyperledger/firefly-tokens-erc1155", Tag: "latest", }, + TokensERC20ERC721: &types.ManifestEntry{ + Image: "ghcr.io/hyperledger/firefly-tokens-erc20-erc721", + Tag: "latest", + }, } } return nil @@ -276,7 +281,9 @@ func (s *StackManager) writeConfigs(verbose bool) error { for _, member := range s.Stack.Members { config := core.NewFireflyConfig(s.Stack, member) config.Blockchain, config.Org = s.blockchainProvider.GetFireflyConfig(member) - config.Tokens = s.tokensProvider.GetFireflyConfig(member) + for iTok, tp := range s.tokenProviders { + config.Tokens = append(config.Tokens, tp.GetFireflyConfig(member, iTok)) + } if err := core.WriteFireflyConfig(config, filepath.Join(stackDir, "configs", fmt.Sprintf("firefly_core_%s.yml", member.ID))); err != nil { return err } @@ -337,7 +344,7 @@ func createMember(id string, index int, options *InitOptions, external bool) *ty encodedAddress := "0x" + hex.EncodeToString(hash.Sum(nil)[12:32]) serviceBase := options.ServicesBasePort + (index * 100) - return &types.Member{ + member := &types.Member{ ID: id, Index: &index, Address: encodedAddress, @@ -350,11 +357,14 @@ func createMember(id string, index int, options *InitOptions, external bool) *ty ExposedDataexchangePort: serviceBase + 5, ExposedIPFSApiPort: serviceBase + 6, ExposedIPFSGWPort: serviceBase + 7, - ExposedTokensPort: serviceBase + 8, External: external, OrgName: options.OrgNames[index], NodeName: options.NodeNames[index], } + for i := range options.TokenProviders { + member.ExposedTokensPorts = append(member.ExposedTokensPorts, 8+i) + } + return member } func (s *StackManager) StartStack(verbose bool, options *StartOptions) error { @@ -425,8 +435,10 @@ func (s *StackManager) PullStack(verbose bool, options *PullOptions) error { } // Iterate over all images used by the tokens provider - for _, service := range s.tokensProvider.GetDockerServiceDefinitions() { - images = append(images, service.Service.Image) + for iTok, tp := range s.tokenProviders { + for _, service := range tp.GetDockerServiceDefinitions(iTok) { + images = append(images, service.Service.Image) + } } // Use docker to pull every image - retry on failure @@ -444,8 +456,10 @@ func (s *StackManager) removeVolumes(verbose bool) { for _, service := range s.blockchainProvider.GetDockerServiceDefinitions() { volumes = append(volumes, service.VolumeNames...) } - for _, service := range s.tokensProvider.GetDockerServiceDefinitions() { - volumes = append(volumes, service.VolumeNames...) + for iTok, tp := range s.tokenProviders { + for _, service := range tp.GetDockerServiceDefinitions(iTok) { + volumes = append(volumes, service.VolumeNames...) + } } for volumeName := range docker.CreateDockerCompose(s.Stack).Volumes { volumes = append(volumes, volumeName) @@ -514,7 +528,7 @@ func (s *StackManager) checkPortsAvailable() error { ports = append(ports, member.ExposedIPFSGWPort) ports = append(ports, member.ExposedPostgresPort) ports = append(ports, member.ExposedUIPort) - ports = append(ports, member.ExposedTokensPort) + ports = append(ports, member.ExposedTokensPorts...) } for _, port := range ports { available, err := checkPortAvailable(port) @@ -595,8 +609,10 @@ func (s *StackManager) runFirstTimeSetup(verbose bool, options *StartOptions) er if err := s.blockchainProvider.DeploySmartContracts(); err != nil { return err } - if err := s.tokensProvider.DeploySmartContracts(); err != nil { - return err + for _, tp := range s.tokenProviders { + if err := tp.DeploySmartContracts(); err != nil { + return err + } } if err := s.patchConfigAndRestartFireflyNodes(verbose); err != nil { @@ -609,8 +625,10 @@ func (s *StackManager) runFirstTimeSetup(verbose bool, options *StartOptions) er } s.Log.Info("initializing token providers") - if err := s.tokensProvider.FirstTimeSetup(); err != nil { - return err + for iTok, tp := range s.tokenProviders { + if err := tp.FirstTimeSetup(iTok); err != nil { + return err + } } return nil } @@ -684,8 +702,8 @@ func (s *StackManager) PrintStackInfo(verbose bool) error { func (s *StackManager) patchConfigAndRestartFireflyNodes(verbose bool) error { for _, member := range s.Stack.Members { s.Log.Info(fmt.Sprintf("applying configuration changes to %s", member.ID)) - configRecordUrl := fmt.Sprintf("http://localhost:%d/admin/api/v1/config/records/admin", member.ExposedFireflyAdminPort) - if err := core.RequestWithRetry("PUT", configRecordUrl, "{\"preInit\": false}", nil); err != nil && err != io.EOF { + configRecordUrl := fmt.Sprintf("http://localhost:%d/admin/api/v1/config/records/admin.preInit", member.ExposedFireflyAdminPort) + if err := core.RequestWithRetry("PUT", configRecordUrl, "false", nil); err != nil && err != io.EOF { return err } resetUrl := fmt.Sprintf("http://localhost:%d/admin/api/v1/config/reset", member.ExposedFireflyAdminPort) @@ -733,21 +751,19 @@ func (s *StackManager) getBlockchainProvider(verbose bool) blockchain.IBlockchai } } -func (s *StackManager) getTokensProvider(verbose bool) tokens.ITokensProvider { - switch s.Stack.TokensProvider { - case NilTokens.String(): - return &niltokens.NilTokensProvider{ - Verbose: verbose, - Log: s.Log, - Stack: s.Stack, - } - case ERC1155.String(): - return &erc1155.ERC1155Provider{ - Verbose: verbose, - Log: s.Log, - Stack: s.Stack, +func (s *StackManager) getITokenProviders(verbose bool) []tokens.ITokensProvider { + tps := make([]tokens.ITokensProvider, len(s.Stack.TokenProviders)) + for i, tp := range s.Stack.TokenProviders { + switch tp { + case ERC1155: + tps[i] = &erc1155.ERC1155Provider{ + Verbose: verbose, + Log: s.Log, + Stack: s.Stack, + } + default: + return nil } - default: - return nil } + return tps } diff --git a/internal/stacks/types.go b/internal/stacks/types.go index cc87fac6..66157c52 100644 --- a/internal/stacks/types.go +++ b/internal/stacks/types.go @@ -19,6 +19,8 @@ package stacks import ( "fmt" "strings" + + "github.com/hyperledger/firefly-cli/pkg/types" ) type DatabaseSelection int @@ -67,24 +69,27 @@ func BlockchainProviderFromString(s string) (BlockchainProvider, error) { return GoEthereum, fmt.Errorf("\"%s\" is not a valid blockchain provider selection. valid options are: %v", s, BlockchainProviderStrings) } -type TokensProvider int - const ( - NilTokens TokensProvider = iota - ERC1155 + NilTokens types.TokenProvider = "none" + ERC1155 types.TokenProvider = "erc1155" + ERC20_ERC721 types.TokenProvider = "erc20_erc721" ) -var TokensProviderStrings = []string{"none", "erc1155"} - -func (tokensProvider TokensProvider) String() string { - return TokensProviderStrings[tokensProvider] -} - -func TokensProviderFromString(s string) (TokensProvider, error) { - for i, tokensProviderSelection := range TokensProviderStrings { - if strings.ToLower(s) == tokensProviderSelection { - return TokensProvider(i), nil +var ValidTokenProviders = []types.TokenProvider{NilTokens, ERC1155, ERC20_ERC721} + +func TokensProviderFromStrings(strTokens []string) (tps types.TokenProviders, err error) { + tps = make([]types.TokenProvider, 0, len(strTokens)) + for _, s := range strTokens { + found := false + for _, tokensProviderSelection := range ValidTokenProviders { + if strings.ToLower(s) == string(tokensProviderSelection) { + found = true + tps = append(tps, tokensProviderSelection) + } + } + if !found { + return nil, fmt.Errorf("\"%s\" is not a valid tokens provider selection. valid options are: %v", s, ValidTokenProviders) } } - return ERC1155, fmt.Errorf("\"%s\" is not a valid tokens provider selection. valid options are: %v", s, TokensProviderStrings) + return tps, nil } diff --git a/internal/tokens/erc1155/erc1155_provider.go b/internal/tokens/erc1155/erc1155_provider.go index 11ee7a8c..86b06bd9 100644 --- a/internal/tokens/erc1155/erc1155_provider.go +++ b/internal/tokens/erc1155/erc1155_provider.go @@ -36,10 +36,10 @@ func (p *ERC1155Provider) DeploySmartContracts() error { return DeployContracts(p.Stack, p.Log, p.Verbose) } -func (p *ERC1155Provider) FirstTimeSetup() error { +func (p *ERC1155Provider) FirstTimeSetup(tokenIdx int) error { for _, member := range p.Stack.Members { p.Log.Info(fmt.Sprintf("initializing tokens on member %s", member.ID)) - tokenInitUrl := fmt.Sprintf("http://localhost:%d/api/v1/init", member.ExposedTokensPort) + tokenInitUrl := fmt.Sprintf("http://localhost:%d/api/v1/init", member.ExposedTokensPorts[tokenIdx]) if err := core.RequestWithRetry("POST", tokenInitUrl, nil, nil); err != nil { return err } @@ -47,15 +47,15 @@ func (p *ERC1155Provider) FirstTimeSetup() error { return nil } -func (p *ERC1155Provider) GetDockerServiceDefinitions() []*docker.ServiceDefinition { +func (p *ERC1155Provider) GetDockerServiceDefinitions(tokenIdx int) []*docker.ServiceDefinition { serviceDefinitions := make([]*docker.ServiceDefinition, 0, len(p.Stack.Members)) for i, member := range p.Stack.Members { serviceDefinitions = append(serviceDefinitions, &docker.ServiceDefinition{ ServiceName: "tokens_" + member.ID, Service: &docker.Service{ - Image: p.Stack.VersionManifest.Tokens.GetDockerImageString(), + Image: p.Stack.VersionManifest.TokensERC1155.GetDockerImageString(), ContainerName: fmt.Sprintf("%s_tokens_%v", p.Stack.Name, i), - Ports: []string{fmt.Sprintf("%d:3000", member.ExposedTokensPort)}, + Ports: []string{fmt.Sprintf("%d:3000", member.ExposedTokensPorts[tokenIdx])}, Environment: map[string]string{ "ETHCONNECT_URL": p.getEthconnectURL(member), "ETHCONNECT_INSTANCE": "/contracts/erc1155", @@ -75,13 +75,11 @@ func (p *ERC1155Provider) GetDockerServiceDefinitions() []*docker.ServiceDefinit return serviceDefinitions } -func (p *ERC1155Provider) GetFireflyConfig(m *types.Member) *core.TokensConfig { - return &core.TokensConfig{ - &core.TokenConnector{ - Plugin: "fftokens", - Name: "erc1155", - URL: p.getTokensURL(m), - }, +func (p *ERC1155Provider) GetFireflyConfig(m *types.Member, tokenIdx int) *core.TokenConnector { + return &core.TokenConnector{ + Plugin: "fftokens", + Name: "erc1155", + URL: p.getTokensURL(m, tokenIdx), } } @@ -89,10 +87,10 @@ func (p *ERC1155Provider) getEthconnectURL(member *types.Member) string { return fmt.Sprintf("http://ethconnect_%s:8080", member.ID) } -func (p *ERC1155Provider) getTokensURL(member *types.Member) string { +func (p *ERC1155Provider) getTokensURL(member *types.Member, tokenIdx int) string { if !member.External { return fmt.Sprintf("http://tokens_%s:3000", member.ID) } else { - return fmt.Sprintf("http://127.0.0.1:%v", member.ExposedTokensPort) + return fmt.Sprintf("http://127.0.0.1:%v", member.ExposedTokensPorts[tokenIdx]) } } diff --git a/internal/tokens/erc20erc721/contracts.go b/internal/tokens/erc20erc721/contracts.go new file mode 100644 index 00000000..f5e1b40e --- /dev/null +++ b/internal/tokens/erc20erc721/contracts.go @@ -0,0 +1,39 @@ +// Copyright © 2021 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package erc20erc721 + +import ( + "github.com/hyperledger/firefly-cli/internal/log" + "github.com/hyperledger/firefly-cli/pkg/types" +) + +func DeployContracts(s *types.Stack, log log.Logger, verbose bool) error { + + // Currently the act of creating and deploying a suitable ERC20 or ERC721 compliant + // contract, or contract factory, is an exercise left to the user. + // + // For users simply experimenting with how tokens work, the ERC1155 standard is recommended + // as a flexbile and fully formed sample implementation of fungible and non-fungible tokens + // with a set of features you would expect. + // + // For users looking to take the next step and create a "proper" coin or NFT collection, + // you really can't bypass the step of investigating the right OpenZeppelin (or other) + // base class and determining the tokenomics (around supply / minting / burning / governance) + // on top of that base class using the examples and standards out there. + + return nil +} diff --git a/internal/tokens/erc20erc721/erc20_erc721.go b/internal/tokens/erc20erc721/erc20_erc721.go new file mode 100644 index 00000000..0569868c --- /dev/null +++ b/internal/tokens/erc20erc721/erc20_erc721.go @@ -0,0 +1,95 @@ +// Copyright © 2021 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package erc20erc721 + +import ( + "fmt" + "strings" + + "github.com/hyperledger/firefly-cli/internal/core" + "github.com/hyperledger/firefly-cli/internal/docker" + "github.com/hyperledger/firefly-cli/internal/log" + "github.com/hyperledger/firefly-cli/pkg/types" +) + +type ERC20ERC721Provider struct { + Log log.Logger + Verbose bool + Stack *types.Stack +} + +func (p *ERC20ERC721Provider) DeploySmartContracts() error { + return DeployContracts(p.Stack, p.Log, p.Verbose) +} + +func (p *ERC20ERC721Provider) FirstTimeSetup(port int) error { + for _, member := range p.Stack.Members { + p.Log.Info(fmt.Sprintf("initializing tokens on member %s", member.ID)) + tokenInitUrl := fmt.Sprintf("http://localhost:%d/api/v1/init", port) + if err := core.RequestWithRetry("POST", tokenInitUrl, nil, nil); err != nil { + return err + } + } + return nil +} + +func (p *ERC20ERC721Provider) GetDockerServiceDefinitions(tokenIdx int) []*docker.ServiceDefinition { + serviceDefinitions := make([]*docker.ServiceDefinition, 0, len(p.Stack.Members)) + for i, member := range p.Stack.Members { + serviceDefinitions = append(serviceDefinitions, &docker.ServiceDefinition{ + ServiceName: "tokens_" + member.ID, + Service: &docker.Service{ + Image: p.Stack.VersionManifest.TokensERC20ERC721.GetDockerImageString(), + ContainerName: fmt.Sprintf("%s_tokens_%v", p.Stack.Name, i), + Ports: []string{fmt.Sprintf("%d:3000", member.ExposedTokensPorts[tokenIdx])}, + Environment: map[string]string{ + "ETHCONNECT_URL": p.getEthconnectURL(member, member.ExposedTokensPorts[tokenIdx]), + "ETHCONNECT_IDENTITY": strings.TrimPrefix(member.Address, "0x"), + "AUTO_INIT": "false", + }, + DependsOn: map[string]map[string]string{ + "ethconnect_" + member.ID: {"condition": "service_started"}, + }, + HealthCheck: &docker.HealthCheck{ + Test: []string{"CMD", "curl", "http://localhost:3000/api"}, + }, + Logging: docker.StandardLogOptions, + }, + }) + } + return serviceDefinitions +} + +func (p *ERC20ERC721Provider) GetFireflyConfig(m *types.Member, tokenIdx int) *core.TokenConnector { + return &core.TokenConnector{ + Plugin: "fftokens", + Name: "erc1155", + URL: p.getTokensURL(m, tokenIdx), + } +} + +func (p *ERC20ERC721Provider) getEthconnectURL(member *types.Member, tokenIdx int) string { + return fmt.Sprintf("http://ethconnect_%s:8080", member.ID) +} + +func (p *ERC20ERC721Provider) getTokensURL(member *types.Member, tokenIdx int) string { + if !member.External { + return fmt.Sprintf("http://tokens_%s:3000", member.ID) + } else { + return fmt.Sprintf("http://127.0.0.1:%v", member.ExposedTokensPorts[tokenIdx]) + } +} diff --git a/internal/tokens/niltokens/niltokens_provider.go b/internal/tokens/niltokens/niltokens_provider.go deleted file mode 100644 index 900ec81d..00000000 --- a/internal/tokens/niltokens/niltokens_provider.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright © 2021 Kaleido, Inc. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package niltokens - -import ( - "github.com/hyperledger/firefly-cli/internal/core" - "github.com/hyperledger/firefly-cli/internal/docker" - "github.com/hyperledger/firefly-cli/internal/log" - "github.com/hyperledger/firefly-cli/pkg/types" -) - -type NilTokensProvider struct { - Log log.Logger - Verbose bool - Stack *types.Stack -} - -func (p *NilTokensProvider) DeploySmartContracts() error { - return nil -} - -func (p *NilTokensProvider) FirstTimeSetup() error { - return nil -} - -func (p *NilTokensProvider) GetDockerServiceDefinitions() []*docker.ServiceDefinition { - return nil -} - -func (p *NilTokensProvider) GetFireflyConfig(m *types.Member) *core.TokensConfig { - return nil -} diff --git a/internal/tokens/tokens_provider.go b/internal/tokens/tokens_provider.go index 342a9a2c..1435fcfe 100644 --- a/internal/tokens/tokens_provider.go +++ b/internal/tokens/tokens_provider.go @@ -24,7 +24,7 @@ import ( type ITokensProvider interface { DeploySmartContracts() error - FirstTimeSetup() error - GetDockerServiceDefinitions() []*docker.ServiceDefinition - GetFireflyConfig(m *types.Member) *core.TokensConfig + FirstTimeSetup(tokenIdx int) error + GetDockerServiceDefinitions(tokenIdx int) []*docker.ServiceDefinition + GetFireflyConfig(m *types.Member, tokenIdx int) *core.TokenConnector } diff --git a/pkg/types/manifest.go b/pkg/types/manifest.go index 0a8d91d5..1320c2d3 100644 --- a/pkg/types/manifest.go +++ b/pkg/types/manifest.go @@ -23,11 +23,12 @@ type GitHubRelease struct { } type VersionManifest struct { - FireFly *ManifestEntry `json:"firefly,omitempty"` - Ethconnect *ManifestEntry `json:"ethconnect"` - Fabconnect *ManifestEntry `json:"fabconnect"` - DataExchange *ManifestEntry `json:"dataexchange-https"` - Tokens *ManifestEntry `json:"tokens-erc1155"` + FireFly *ManifestEntry `json:"firefly,omitempty"` + Ethconnect *ManifestEntry `json:"ethconnect"` + Fabconnect *ManifestEntry `json:"fabconnect"` + DataExchange *ManifestEntry `json:"dataexchange-https"` + TokensERC1155 *ManifestEntry `json:"tokens-erc1155"` + TokensERC20ERC721 *ManifestEntry `json:"tokens-erc20-erc721"` } func (m *VersionManifest) Entries() []*ManifestEntry { @@ -39,7 +40,8 @@ func (m *VersionManifest) Entries() []*ManifestEntry { m.Ethconnect, m.Fabconnect, m.DataExchange, - m.Tokens, + m.TokensERC1155, + m.TokensERC20ERC721, } } diff --git a/pkg/types/stack.go b/pkg/types/stack.go index df70350d..88380f87 100644 --- a/pkg/types/stack.go +++ b/pkg/types/stack.go @@ -23,7 +23,7 @@ type Stack struct { ExposedBlockchainPort int `json:"exposedGethPort,omitempty"` Database string `json:"database"` BlockchainProvider string `json:"blockchainProvider"` - TokensProvider string `json:"tokensProvider"` + TokenProviders TokenProviders `json:"tokenProviders"` VersionManifest *VersionManifest `json:"versionManifest,omitempty"` } @@ -40,8 +40,20 @@ type Member struct { ExposedIPFSApiPort int `json:"exposedIPFSApiPort,omitempty"` ExposedIPFSGWPort int `json:"exposedIPFSGWPort,omitempty"` ExposedUIPort int `json:"exposedUiPort,omitempty"` - ExposedTokensPort int `json:"exposedTokensPort,omitempty"` + ExposedTokensPorts []int `json:"exposedTokensPorts,omitempty"` External bool `json:"external,omitempty"` OrgName string `json:"orgName,omitempty"` NodeName string `json:"nodeName,omitempty"` } + +type TokenProvider string + +type TokenProviders []TokenProvider + +func (tps TokenProviders) Strings() []string { + ret := make([]string, len(tps)) + for i, t := range tps { + ret[i] = string(t) + } + return ret +} From 5ea67c7aa0440c98c82ac35362812dae91bc68b4 Mon Sep 17 00:00:00 2001 From: David Echelberger Date: Tue, 1 Feb 2022 12:08:13 -0500 Subject: [PATCH 02/10] [erc20-erc721] adding missing logic and naming tweaks Signed-off-by: David Echelberger --- cmd/init.go | 2 +- internal/stacks/stack_manager.go | 7 +++++++ internal/tokens/erc20erc721/erc20_erc721.go | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/cmd/init.go b/cmd/init.go index 69d2b946..5c7c85b0 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -180,7 +180,7 @@ func init() { initCmd.Flags().IntVarP(&initOptions.ServicesBasePort, "services-base-port", "s", 5100, "Mapped port base of services (100 added for each member)") initCmd.Flags().StringVarP(&databaseSelection, "database", "d", "sqlite3", fmt.Sprintf("Database type to use. Options are: %v", stacks.DBSelectionStrings)) initCmd.Flags().StringVarP(&blockchainProviderInput, "blockchain-provider", "b", "geth", fmt.Sprintf("Blockchain provider to use. Options are: %v", stacks.BlockchainProviderStrings)) - initCmd.Flags().StringArrayVarP(&tokenProvidersSelection, "token-providers", "t", []string{"erc1155", "erc20erc721"}, fmt.Sprintf("Token providers to use. Options are: %v", stacks.ValidTokenProviders)) + initCmd.Flags().StringArrayVarP(&tokenProvidersSelection, "token-providers", "t", []string{"erc1155", "erc20_erc721"}, fmt.Sprintf("Token providers to use. Options are: %v", stacks.ValidTokenProviders)) initCmd.Flags().IntVarP(&initOptions.ExternalProcesses, "external", "e", 0, "Manage a number of FireFly core processes outside of the docker-compose stack - useful for development and debugging") initCmd.Flags().StringVarP(&initOptions.FireFlyVersion, "release", "r", "latest", "Select the FireFly release version to use") initCmd.Flags().StringVarP(&initOptions.ManifestPath, "manifest", "m", "", "Path to a manifest.json file containing the versions of each FireFly microservice to use. Overrides the --release flag.") diff --git a/internal/stacks/stack_manager.go b/internal/stacks/stack_manager.go index 88118372..537ded8d 100644 --- a/internal/stacks/stack_manager.go +++ b/internal/stacks/stack_manager.go @@ -41,6 +41,7 @@ import ( "github.com/hyperledger/firefly-cli/internal/docker" "github.com/hyperledger/firefly-cli/internal/tokens" "github.com/hyperledger/firefly-cli/internal/tokens/erc1155" + "github.com/hyperledger/firefly-cli/internal/tokens/erc20erc721" "github.com/hyperledger/firefly-cli/pkg/types" "golang.org/x/crypto/sha3" @@ -800,6 +801,12 @@ func (s *StackManager) getITokenProviders(verbose bool) []tokens.ITokensProvider Log: s.Log, Stack: s.Stack, } + case ERC20_ERC721: + tps[i] = &erc20erc721.ERC20ERC721Provider{ + Verbose: verbose, + Log: s.Log, + Stack: s.Stack, + } default: return nil } diff --git a/internal/tokens/erc20erc721/erc20_erc721.go b/internal/tokens/erc20erc721/erc20_erc721.go index 0569868c..84f4d83e 100644 --- a/internal/tokens/erc20erc721/erc20_erc721.go +++ b/internal/tokens/erc20erc721/erc20_erc721.go @@ -77,7 +77,7 @@ func (p *ERC20ERC721Provider) GetDockerServiceDefinitions(tokenIdx int) []*docke func (p *ERC20ERC721Provider) GetFireflyConfig(m *types.Member, tokenIdx int) *core.TokenConnector { return &core.TokenConnector{ Plugin: "fftokens", - Name: "erc1155", + Name: "erc20_erc721", URL: p.getTokensURL(m, tokenIdx), } } From 90f8586593188638153df3a54dce9a5171c3a1a0 Mon Sep 17 00:00:00 2001 From: David Echelberger Date: Tue, 1 Feb 2022 13:50:25 -0500 Subject: [PATCH 03/10] [erc20-erc721] token init url fix Signed-off-by: David Echelberger --- internal/tokens/erc20erc721/erc20_erc721.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/tokens/erc20erc721/erc20_erc721.go b/internal/tokens/erc20erc721/erc20_erc721.go index 84f4d83e..aa466b97 100644 --- a/internal/tokens/erc20erc721/erc20_erc721.go +++ b/internal/tokens/erc20erc721/erc20_erc721.go @@ -36,10 +36,10 @@ func (p *ERC20ERC721Provider) DeploySmartContracts() error { return DeployContracts(p.Stack, p.Log, p.Verbose) } -func (p *ERC20ERC721Provider) FirstTimeSetup(port int) error { +func (p *ERC20ERC721Provider) FirstTimeSetup(tokenIdx int) error { for _, member := range p.Stack.Members { p.Log.Info(fmt.Sprintf("initializing tokens on member %s", member.ID)) - tokenInitUrl := fmt.Sprintf("http://localhost:%d/api/v1/init", port) + tokenInitUrl := fmt.Sprintf("http://localhost:%d/api/v1/init", member.ExposedTokensPorts[tokenIdx]) if err := core.RequestWithRetry("POST", tokenInitUrl, nil, nil); err != nil { return err } From 7d4e210149600b8c87ac0721e93961d6a008ce95 Mon Sep 17 00:00:00 2001 From: David Echelberger Date: Tue, 1 Feb 2022 15:18:58 -0500 Subject: [PATCH 04/10] [erc20-erc721] token image naming convention for multiple connectors Signed-off-by: David Echelberger --- internal/stacks/stack_manager.go | 77 ++++++++++++------- internal/tokens/erc1155/contracts.go | 4 +- internal/tokens/erc1155/erc1155_provider.go | 12 +-- internal/tokens/erc20erc721/contracts.go | 2 +- ...c20_erc721.go => erc20_erc721_provider.go} | 8 +- internal/tokens/tokens_provider.go | 2 +- 6 files changed, 65 insertions(+), 40 deletions(-) rename internal/tokens/erc20erc721/{erc20_erc721.go => erc20_erc721_provider.go} (91%) diff --git a/internal/stacks/stack_manager.go b/internal/stacks/stack_manager.go index 537ded8d..df56aee0 100644 --- a/internal/stacks/stack_manager.go +++ b/internal/stacks/stack_manager.go @@ -27,7 +27,6 @@ import ( "os/exec" "path" "path/filepath" - "strings" "syscall" "time" @@ -122,28 +121,54 @@ func (s *StackManager) InitStack(stackName string, memberCount int, options *Ini s.Stack.ExposedPrometheusPort = options.PrometheusPort } - var manifest *types.VersionManifest - - if options.ManifestPath != "" { - // If a path to a manifest file is set, read the existing file - manifest, err = core.ReadManifestFile(options.ManifestPath) - if err != nil { - return err - } - } else { - // Otherwise, fetch the manifest file from GitHub for the specified version - if options.FireFlyVersion == "" || strings.ToLower(options.FireFlyVersion) == "latest" { - manifest, err = core.GetLatestReleaseManifest() - if err != nil { - return err - } - } else { - manifest, err = core.GetReleaseManifest(options.FireFlyVersion) - if err != nil { - return err - } - } - } + // TODO: Revert before merge + var manifest *types.VersionManifest = &types.VersionManifest{ + FireFly: &types.ManifestEntry{ + Image: "ghcr.io/hyperledger/firefly", + Tag: "latest", + }, + Ethconnect: &types.ManifestEntry{ + Image: "ghcr.io/hyperledger/firefly-ethconnect", + Tag: "latest", + }, + Fabconnect: &types.ManifestEntry{ + Image: "ghcr.io/hyperledger/firefly-fabconnect", + Tag: "latest", + }, + DataExchange: &types.ManifestEntry{ + Image: "ghcr.io/hyperledger/firefly-dataexchange-https", + Tag: "latest", + }, + TokensERC1155: &types.ManifestEntry{ + Image: "ghcr.io/hyperledger/firefly-tokens-erc1155", + Tag: "latest", + }, + TokensERC20ERC721: &types.ManifestEntry{ + Image: "ghcr.io/eberger727/firefly-tokens-erc20-erc721", + Tag: "latest", + }, + } + + // if options.ManifestPath != "" { + // // If a path to a manifest file is set, read the existing file + // manifest, err = core.ReadManifestFile(options.ManifestPath) + // if err != nil { + // return err + // } + // } else { + // // Otherwise, fetch the manifest file from GitHub for the specified version + // if options.FireFlyVersion == "" || strings.ToLower(options.FireFlyVersion) == "latest" { + // manifest, err = core.GetLatestReleaseManifest() + // if err != nil { + // return err + // } + // } else { + // manifest, err = core.GetReleaseManifest(options.FireFlyVersion) + // if err != nil { + // return err + // } + // } + // } s.Stack.VersionManifest = manifest s.blockchainProvider = s.getBlockchainProvider(false) @@ -244,7 +269,7 @@ func (s *StackManager) LoadStack(stackName string, verbose bool) error { Tag: "latest", }, TokensERC20ERC721: &types.ManifestEntry{ - Image: "ghcr.io/hyperledger/firefly-tokens-erc20-erc721", + Image: "ghcr.io/eberger727/firefly-tokens-erc20-erc721", Tag: "latest", }, } @@ -649,8 +674,8 @@ func (s *StackManager) runFirstTimeSetup(verbose bool, options *StartOptions) er if err := s.blockchainProvider.DeploySmartContracts(); err != nil { return err } - for _, tp := range s.tokenProviders { - if err := tp.DeploySmartContracts(); err != nil { + for i, tp := range s.tokenProviders { + if err := tp.DeploySmartContracts(i); err != nil { return err } } diff --git a/internal/tokens/erc1155/contracts.go b/internal/tokens/erc1155/contracts.go index da15ccb0..9bb3b703 100644 --- a/internal/tokens/erc1155/contracts.go +++ b/internal/tokens/erc1155/contracts.go @@ -29,11 +29,11 @@ import ( const TOKEN_URI_PATTERN = "firefly://token/{id}" -func DeployContracts(s *types.Stack, log log.Logger, verbose bool) error { +func DeployContracts(s *types.Stack, log log.Logger, verbose bool, tokenIndex int) error { var containerName string for _, member := range s.Members { if !member.External { - containerName = fmt.Sprintf("%s_tokens_%s", s.Name, member.ID) + containerName = fmt.Sprintf("%s_tokens_%s_%d", s.Name, member.ID, tokenIndex) break } } diff --git a/internal/tokens/erc1155/erc1155_provider.go b/internal/tokens/erc1155/erc1155_provider.go index 6cd110b1..1bfcc540 100644 --- a/internal/tokens/erc1155/erc1155_provider.go +++ b/internal/tokens/erc1155/erc1155_provider.go @@ -31,8 +31,8 @@ type ERC1155Provider struct { Stack *types.Stack } -func (p *ERC1155Provider) DeploySmartContracts() error { - return DeployContracts(p.Stack, p.Log, p.Verbose) +func (p *ERC1155Provider) DeploySmartContracts(tokenIndex int) error { + return DeployContracts(p.Stack, p.Log, p.Verbose, tokenIndex) } func (p *ERC1155Provider) FirstTimeSetup(tokenIdx int) error { @@ -50,13 +50,13 @@ func (p *ERC1155Provider) GetDockerServiceDefinitions(tokenIdx int) []*docker.Se serviceDefinitions := make([]*docker.ServiceDefinition, 0, len(p.Stack.Members)) for i, member := range p.Stack.Members { serviceDefinitions = append(serviceDefinitions, &docker.ServiceDefinition{ - ServiceName: "tokens_" + member.ID, + ServiceName: fmt.Sprintf("tokens_%v_%v", member.ID, tokenIdx), Service: &docker.Service{ Image: p.Stack.VersionManifest.TokensERC1155.GetDockerImageString(), - ContainerName: fmt.Sprintf("%s_tokens_%v", p.Stack.Name, i), + ContainerName: fmt.Sprintf("%s_tokens_%v_%v", p.Stack.Name, i, tokenIdx), Ports: []string{fmt.Sprintf("%d:3000", member.ExposedTokensPorts[tokenIdx])}, Environment: map[string]string{ - "ETHCONNECT_URL": p.getEthconnectURL(member), + "ETHCONNECT_URL": p.getEthconnectURL(member, member.ExposedTokensPorts[tokenIdx]), "ETHCONNECT_INSTANCE": "/contracts/erc1155", "AUTO_INIT": "false", }, @@ -81,7 +81,7 @@ func (p *ERC1155Provider) GetFireflyConfig(m *types.Member, tokenIdx int) *core. } } -func (p *ERC1155Provider) getEthconnectURL(member *types.Member) string { +func (p *ERC1155Provider) getEthconnectURL(member *types.Member, tokenIdx int) string { return fmt.Sprintf("http://ethconnect_%s:8080", member.ID) } diff --git a/internal/tokens/erc20erc721/contracts.go b/internal/tokens/erc20erc721/contracts.go index f5e1b40e..8ac06ada 100644 --- a/internal/tokens/erc20erc721/contracts.go +++ b/internal/tokens/erc20erc721/contracts.go @@ -21,7 +21,7 @@ import ( "github.com/hyperledger/firefly-cli/pkg/types" ) -func DeployContracts(s *types.Stack, log log.Logger, verbose bool) error { +func DeployContracts(s *types.Stack, log log.Logger, verbose bool, tokenIndex int) error { // Currently the act of creating and deploying a suitable ERC20 or ERC721 compliant // contract, or contract factory, is an exercise left to the user. diff --git a/internal/tokens/erc20erc721/erc20_erc721.go b/internal/tokens/erc20erc721/erc20_erc721_provider.go similarity index 91% rename from internal/tokens/erc20erc721/erc20_erc721.go rename to internal/tokens/erc20erc721/erc20_erc721_provider.go index aa466b97..a867c6c2 100644 --- a/internal/tokens/erc20erc721/erc20_erc721.go +++ b/internal/tokens/erc20erc721/erc20_erc721_provider.go @@ -32,8 +32,8 @@ type ERC20ERC721Provider struct { Stack *types.Stack } -func (p *ERC20ERC721Provider) DeploySmartContracts() error { - return DeployContracts(p.Stack, p.Log, p.Verbose) +func (p *ERC20ERC721Provider) DeploySmartContracts(tokenIndex int) error { + return DeployContracts(p.Stack, p.Log, p.Verbose, tokenIndex) } func (p *ERC20ERC721Provider) FirstTimeSetup(tokenIdx int) error { @@ -51,10 +51,10 @@ func (p *ERC20ERC721Provider) GetDockerServiceDefinitions(tokenIdx int) []*docke serviceDefinitions := make([]*docker.ServiceDefinition, 0, len(p.Stack.Members)) for i, member := range p.Stack.Members { serviceDefinitions = append(serviceDefinitions, &docker.ServiceDefinition{ - ServiceName: "tokens_" + member.ID, + ServiceName: fmt.Sprintf("tokens_%v_%v", member.ID, tokenIdx), Service: &docker.Service{ Image: p.Stack.VersionManifest.TokensERC20ERC721.GetDockerImageString(), - ContainerName: fmt.Sprintf("%s_tokens_%v", p.Stack.Name, i), + ContainerName: fmt.Sprintf("%s_tokens_%v_%v", p.Stack.Name, i, tokenIdx), Ports: []string{fmt.Sprintf("%d:3000", member.ExposedTokensPorts[tokenIdx])}, Environment: map[string]string{ "ETHCONNECT_URL": p.getEthconnectURL(member, member.ExposedTokensPorts[tokenIdx]), diff --git a/internal/tokens/tokens_provider.go b/internal/tokens/tokens_provider.go index 1435fcfe..09f835f2 100644 --- a/internal/tokens/tokens_provider.go +++ b/internal/tokens/tokens_provider.go @@ -23,7 +23,7 @@ import ( ) type ITokensProvider interface { - DeploySmartContracts() error + DeploySmartContracts(tokenIndex int) error FirstTimeSetup(tokenIdx int) error GetDockerServiceDefinitions(tokenIdx int) []*docker.ServiceDefinition GetFireflyConfig(m *types.Member, tokenIdx int) *core.TokenConnector From 4fc6248db6ecdb8a06d90690fd20565b5b9d57c1 Mon Sep 17 00:00:00 2001 From: David Echelberger Date: Tue, 1 Feb 2022 15:24:08 -0500 Subject: [PATCH 05/10] [erc20-erc721] tokens url fix Signed-off-by: David Echelberger --- internal/tokens/erc1155/erc1155_provider.go | 2 +- internal/tokens/erc20erc721/erc20_erc721_provider.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/tokens/erc1155/erc1155_provider.go b/internal/tokens/erc1155/erc1155_provider.go index 1bfcc540..825f4569 100644 --- a/internal/tokens/erc1155/erc1155_provider.go +++ b/internal/tokens/erc1155/erc1155_provider.go @@ -87,7 +87,7 @@ func (p *ERC1155Provider) getEthconnectURL(member *types.Member, tokenIdx int) s func (p *ERC1155Provider) getTokensURL(member *types.Member, tokenIdx int) string { if !member.External { - return fmt.Sprintf("http://tokens_%s:3000", member.ID) + return fmt.Sprintf("http://tokens_%s_%d:3000", member.ID, tokenIdx) } else { return fmt.Sprintf("http://127.0.0.1:%v", member.ExposedTokensPorts[tokenIdx]) } diff --git a/internal/tokens/erc20erc721/erc20_erc721_provider.go b/internal/tokens/erc20erc721/erc20_erc721_provider.go index a867c6c2..47c56cf9 100644 --- a/internal/tokens/erc20erc721/erc20_erc721_provider.go +++ b/internal/tokens/erc20erc721/erc20_erc721_provider.go @@ -88,7 +88,7 @@ func (p *ERC20ERC721Provider) getEthconnectURL(member *types.Member, tokenIdx in func (p *ERC20ERC721Provider) getTokensURL(member *types.Member, tokenIdx int) string { if !member.External { - return fmt.Sprintf("http://tokens_%s:3000", member.ID) + return fmt.Sprintf("http://tokens_%s_%d:3000", member.ID, tokenIdx) } else { return fmt.Sprintf("http://127.0.0.1:%v", member.ExposedTokensPorts[tokenIdx]) } From f6a8ac880915f045a26af32306852187075ffb82 Mon Sep 17 00:00:00 2001 From: David Echelberger Date: Tue, 1 Feb 2022 15:49:26 -0500 Subject: [PATCH 06/10] [erc20-erc721] using hyperledger tokens image Signed-off-by: David Echelberger --- internal/stacks/stack_manager.go | 73 +++++++++++--------------------- 1 file changed, 24 insertions(+), 49 deletions(-) diff --git a/internal/stacks/stack_manager.go b/internal/stacks/stack_manager.go index df56aee0..8ed61468 100644 --- a/internal/stacks/stack_manager.go +++ b/internal/stacks/stack_manager.go @@ -27,6 +27,7 @@ import ( "os/exec" "path" "path/filepath" + "strings" "syscall" "time" @@ -121,54 +122,28 @@ func (s *StackManager) InitStack(stackName string, memberCount int, options *Ini s.Stack.ExposedPrometheusPort = options.PrometheusPort } - // TODO: Revert before merge - var manifest *types.VersionManifest = &types.VersionManifest{ - FireFly: &types.ManifestEntry{ - Image: "ghcr.io/hyperledger/firefly", - Tag: "latest", - }, - Ethconnect: &types.ManifestEntry{ - Image: "ghcr.io/hyperledger/firefly-ethconnect", - Tag: "latest", - }, - Fabconnect: &types.ManifestEntry{ - Image: "ghcr.io/hyperledger/firefly-fabconnect", - Tag: "latest", - }, - DataExchange: &types.ManifestEntry{ - Image: "ghcr.io/hyperledger/firefly-dataexchange-https", - Tag: "latest", - }, - TokensERC1155: &types.ManifestEntry{ - Image: "ghcr.io/hyperledger/firefly-tokens-erc1155", - Tag: "latest", - }, - TokensERC20ERC721: &types.ManifestEntry{ - Image: "ghcr.io/eberger727/firefly-tokens-erc20-erc721", - Tag: "latest", - }, - } - - // if options.ManifestPath != "" { - // // If a path to a manifest file is set, read the existing file - // manifest, err = core.ReadManifestFile(options.ManifestPath) - // if err != nil { - // return err - // } - // } else { - // // Otherwise, fetch the manifest file from GitHub for the specified version - // if options.FireFlyVersion == "" || strings.ToLower(options.FireFlyVersion) == "latest" { - // manifest, err = core.GetLatestReleaseManifest() - // if err != nil { - // return err - // } - // } else { - // manifest, err = core.GetReleaseManifest(options.FireFlyVersion) - // if err != nil { - // return err - // } - // } - // } + var manifest *types.VersionManifest + + if options.ManifestPath != "" { + // If a path to a manifest file is set, read the existing file + manifest, err = core.ReadManifestFile(options.ManifestPath) + if err != nil { + return err + } + } else { + // Otherwise, fetch the manifest file from GitHub for the specified version + if options.FireFlyVersion == "" || strings.ToLower(options.FireFlyVersion) == "latest" { + manifest, err = core.GetLatestReleaseManifest() + if err != nil { + return err + } + } else { + manifest, err = core.GetReleaseManifest(options.FireFlyVersion) + if err != nil { + return err + } + } + } s.Stack.VersionManifest = manifest s.blockchainProvider = s.getBlockchainProvider(false) @@ -269,7 +244,7 @@ func (s *StackManager) LoadStack(stackName string, verbose bool) error { Tag: "latest", }, TokensERC20ERC721: &types.ManifestEntry{ - Image: "ghcr.io/eberger727/firefly-tokens-erc20-erc721", + Image: "ghcr.io/hyperledger/firefly-tokens-erc20-erc721", Tag: "latest", }, } From 531408f54dbea1c641e5ef87c5782df3168622c3 Mon Sep 17 00:00:00 2001 From: David Echelberger Date: Tue, 1 Feb 2022 16:25:11 -0500 Subject: [PATCH 07/10] [erc20-erc721] token-provider flag naming Signed-off-by: David Echelberger --- cmd/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/init.go b/cmd/init.go index 5c7c85b0..3873b35a 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -180,7 +180,7 @@ func init() { initCmd.Flags().IntVarP(&initOptions.ServicesBasePort, "services-base-port", "s", 5100, "Mapped port base of services (100 added for each member)") initCmd.Flags().StringVarP(&databaseSelection, "database", "d", "sqlite3", fmt.Sprintf("Database type to use. Options are: %v", stacks.DBSelectionStrings)) initCmd.Flags().StringVarP(&blockchainProviderInput, "blockchain-provider", "b", "geth", fmt.Sprintf("Blockchain provider to use. Options are: %v", stacks.BlockchainProviderStrings)) - initCmd.Flags().StringArrayVarP(&tokenProvidersSelection, "token-providers", "t", []string{"erc1155", "erc20_erc721"}, fmt.Sprintf("Token providers to use. Options are: %v", stacks.ValidTokenProviders)) + initCmd.Flags().StringArrayVarP(&tokenProvidersSelection, "token-provider", "t", []string{"erc1155"}, fmt.Sprintf("Token provider to use. Can specify more than one. Options are: %v", stacks.ValidTokenProviders)) initCmd.Flags().IntVarP(&initOptions.ExternalProcesses, "external", "e", 0, "Manage a number of FireFly core processes outside of the docker-compose stack - useful for development and debugging") initCmd.Flags().StringVarP(&initOptions.FireFlyVersion, "release", "r", "latest", "Select the FireFly release version to use") initCmd.Flags().StringVarP(&initOptions.ManifestPath, "manifest", "m", "", "Path to a manifest.json file containing the versions of each FireFly microservice to use. Overrides the --release flag.") From 559d2fbbf941f1f7bb6c3d4b5d6495dca94849da Mon Sep 17 00:00:00 2001 From: David Echelberger Date: Tue, 1 Feb 2022 17:19:04 -0500 Subject: [PATCH 08/10] [erc20-erc721] TokenProvidersFromStrings naming Signed-off-by: David Echelberger --- cmd/init.go | 4 ++-- internal/stacks/types.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/init.go b/cmd/init.go index 3873b35a..4ac2c3f1 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -100,7 +100,7 @@ var initCmd = &cobra.Command{ initOptions.Verbose = verbose initOptions.BlockchainProvider, _ = stacks.BlockchainProviderFromString(blockchainProviderInput) initOptions.DatabaseSelection, _ = stacks.DatabaseSelectionFromString(databaseSelection) - initOptions.TokenProviders, _ = stacks.TokensProviderFromStrings(tokenProvidersSelection) + initOptions.TokenProviders, _ = stacks.TokenProvidersFromStrings(tokenProvidersSelection) if err := stackManager.InitStack(stackName, memberCount, &initOptions); err != nil { return err @@ -168,7 +168,7 @@ func validateBlockchainProvider(input string) error { } func validateTokensProvider(input []string) error { - _, err := stacks.TokensProviderFromStrings(input) + _, err := stacks.TokenProvidersFromStrings(input) if err != nil { return err } diff --git a/internal/stacks/types.go b/internal/stacks/types.go index 66157c52..2d2f6dfe 100644 --- a/internal/stacks/types.go +++ b/internal/stacks/types.go @@ -77,7 +77,7 @@ const ( var ValidTokenProviders = []types.TokenProvider{NilTokens, ERC1155, ERC20_ERC721} -func TokensProviderFromStrings(strTokens []string) (tps types.TokenProviders, err error) { +func TokenProvidersFromStrings(strTokens []string) (tps types.TokenProviders, err error) { tps = make([]types.TokenProvider, 0, len(strTokens)) for _, s := range strTokens { found := false From e488ad9154c405421b16a93ebfff80d162f82e66 Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Tue, 1 Feb 2022 22:07:55 -0500 Subject: [PATCH 09/10] Make "none" behavior clearer Signed-off-by: Peter Broadhurst --- cmd/init.go | 4 +--- internal/stacks/types.go | 4 +++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/init.go b/cmd/init.go index 69d2b946..f2d5fb4d 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -180,13 +180,11 @@ func init() { initCmd.Flags().IntVarP(&initOptions.ServicesBasePort, "services-base-port", "s", 5100, "Mapped port base of services (100 added for each member)") initCmd.Flags().StringVarP(&databaseSelection, "database", "d", "sqlite3", fmt.Sprintf("Database type to use. Options are: %v", stacks.DBSelectionStrings)) initCmd.Flags().StringVarP(&blockchainProviderInput, "blockchain-provider", "b", "geth", fmt.Sprintf("Blockchain provider to use. Options are: %v", stacks.BlockchainProviderStrings)) - initCmd.Flags().StringArrayVarP(&tokenProvidersSelection, "token-providers", "t", []string{"erc1155", "erc20erc721"}, fmt.Sprintf("Token providers to use. Options are: %v", stacks.ValidTokenProviders)) + initCmd.Flags().StringArrayVarP(&tokenProvidersSelection, "token-providers", "t", []string{"erc1155", "erc20_erc721"}, fmt.Sprintf("Token providers to use. Options are: %v", stacks.ValidTokenProviders)) initCmd.Flags().IntVarP(&initOptions.ExternalProcesses, "external", "e", 0, "Manage a number of FireFly core processes outside of the docker-compose stack - useful for development and debugging") initCmd.Flags().StringVarP(&initOptions.FireFlyVersion, "release", "r", "latest", "Select the FireFly release version to use") initCmd.Flags().StringVarP(&initOptions.ManifestPath, "manifest", "m", "", "Path to a manifest.json file containing the versions of each FireFly microservice to use. Overrides the --release flag.") initCmd.Flags().BoolVar(&promptNames, "prompt-names", false, "Prompt for org and node names instead of using the defaults") - initCmd.Flags().BoolVar(&initOptions.PrometheusEnabled, "prometheus-enabled", false, "Enables Prometheus metrics exposition and aggregation to a shared Prometheus server") - initCmd.Flags().IntVar(&initOptions.PrometheusPort, "prometheus-port", 9090, "Port for the shared Prometheus server") rootCmd.AddCommand(initCmd) } diff --git a/internal/stacks/types.go b/internal/stacks/types.go index 66157c52..fc87dba9 100644 --- a/internal/stacks/types.go +++ b/internal/stacks/types.go @@ -84,7 +84,9 @@ func TokensProviderFromStrings(strTokens []string) (tps types.TokenProviders, er for _, tokensProviderSelection := range ValidTokenProviders { if strings.ToLower(s) == string(tokensProviderSelection) { found = true - tps = append(tps, tokensProviderSelection) + if tokensProviderSelection != NilTokens { + tps = append(tps, tokensProviderSelection) + } } } if !found { From 68f55dee0ad2001bd869c7f1581fb80626e961c9 Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Wed, 2 Feb 2022 09:28:26 -0500 Subject: [PATCH 10/10] ETHCONNECT_IDENTITY is unused env var in either connector Signed-off-by: Peter Broadhurst --- internal/tokens/erc1155/erc1155_provider.go | 5 ++--- internal/tokens/erc20erc721/erc20_erc721_provider.go | 6 ++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/internal/tokens/erc1155/erc1155_provider.go b/internal/tokens/erc1155/erc1155_provider.go index 825f4569..7fe44e91 100644 --- a/internal/tokens/erc1155/erc1155_provider.go +++ b/internal/tokens/erc1155/erc1155_provider.go @@ -56,9 +56,8 @@ func (p *ERC1155Provider) GetDockerServiceDefinitions(tokenIdx int) []*docker.Se ContainerName: fmt.Sprintf("%s_tokens_%v_%v", p.Stack.Name, i, tokenIdx), Ports: []string{fmt.Sprintf("%d:3000", member.ExposedTokensPorts[tokenIdx])}, Environment: map[string]string{ - "ETHCONNECT_URL": p.getEthconnectURL(member, member.ExposedTokensPorts[tokenIdx]), - "ETHCONNECT_INSTANCE": "/contracts/erc1155", - "AUTO_INIT": "false", + "ETHCONNECT_URL": p.getEthconnectURL(member, member.ExposedTokensPorts[tokenIdx]), + "AUTO_INIT": "false", }, DependsOn: map[string]map[string]string{ "ethconnect_" + member.ID: {"condition": "service_started"}, diff --git a/internal/tokens/erc20erc721/erc20_erc721_provider.go b/internal/tokens/erc20erc721/erc20_erc721_provider.go index 47c56cf9..1cec32d0 100644 --- a/internal/tokens/erc20erc721/erc20_erc721_provider.go +++ b/internal/tokens/erc20erc721/erc20_erc721_provider.go @@ -18,7 +18,6 @@ package erc20erc721 import ( "fmt" - "strings" "github.com/hyperledger/firefly-cli/internal/core" "github.com/hyperledger/firefly-cli/internal/docker" @@ -57,9 +56,8 @@ func (p *ERC20ERC721Provider) GetDockerServiceDefinitions(tokenIdx int) []*docke ContainerName: fmt.Sprintf("%s_tokens_%v_%v", p.Stack.Name, i, tokenIdx), Ports: []string{fmt.Sprintf("%d:3000", member.ExposedTokensPorts[tokenIdx])}, Environment: map[string]string{ - "ETHCONNECT_URL": p.getEthconnectURL(member, member.ExposedTokensPorts[tokenIdx]), - "ETHCONNECT_IDENTITY": strings.TrimPrefix(member.Address, "0x"), - "AUTO_INIT": "false", + "ETHCONNECT_URL": p.getEthconnectURL(member, member.ExposedTokensPorts[tokenIdx]), + "AUTO_INIT": "false", }, DependsOn: map[string]map[string]string{ "ethconnect_" + member.ID: {"condition": "service_started"},