Skip to content

Commit

Permalink
Make ERC-20 the default token connector
Browse files Browse the repository at this point in the history
Signed-off-by: Nicko Guyer <nicko.guyer@kaleido.io>
  • Loading branch information
nguyer committed Apr 25, 2022
1 parent 6d7064c commit 54ef823
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 40 deletions.
2 changes: 1 addition & 1 deletion cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,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", types.DBSelectionStrings))
initCmd.Flags().StringVarP(&blockchainProviderInput, "blockchain-provider", "b", "geth", fmt.Sprintf("Blockchain provider to use. Options are: %v", types.BlockchainProviderStrings))
initCmd.Flags().StringArrayVarP(&tokenProvidersSelection, "token-providers", "t", []string{"erc1155"}, fmt.Sprintf("Token providers to use. Options are: %v", types.ValidTokenProviders))
initCmd.Flags().StringArrayVarP(&tokenProvidersSelection, "token-providers", "t", []string{"erc20_erc721"}, fmt.Sprintf("Token providers to use. Options are: %v", types.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.")
Expand Down
2 changes: 1 addition & 1 deletion internal/blockchain/ethereum/besu/besu_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func (p *BesuProvider) Reset() error {
}

func (p *BesuProvider) GetContracts(filename string, extraArgs []string) ([]string, error) {
contracts, err := ethereum.ReadCombinedABIJSON(filename)
contracts, err := ethereum.ReadContractJSON(filename)
if err != nil {
return []string{}, err
}
Expand Down
27 changes: 22 additions & 5 deletions internal/blockchain/ethereum/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ type CompiledContract struct {
}

type truffleCompiledContract struct {
ABI interface{} `json:"abi"`
Bytecode string `json:"bytecode"`
ABI interface{} `json:"abi"`
Bytecode string `json:"bytecode"`
ContractName string `json:"contractName"`
}

func ReadTruffleCompiledContract(filePath string) (*CompiledContract, error) {
func ReadTruffleCompiledContract(filePath string) (*CompiledContracts, error) {
d, _ := ioutil.ReadFile(filePath)
var truffleCompiledContract *truffleCompiledContract
err := json.Unmarshal(d, &truffleCompiledContract)
Expand All @@ -48,10 +49,15 @@ func ReadTruffleCompiledContract(filePath string) (*CompiledContract, error) {
ABI: truffleCompiledContract.ABI,
Bytecode: truffleCompiledContract.Bytecode,
}
return contract, nil
contracts := &CompiledContracts{
Contracts: map[string]*CompiledContract{
truffleCompiledContract.ContractName: contract,
},
}
return contracts, nil
}

func ReadCombinedABIJSON(filePath string) (*CompiledContracts, error) {
func ReadSolcCompiledContract(filePath string) (*CompiledContracts, error) {
d, _ := ioutil.ReadFile(filePath)
var contracts *CompiledContracts
err := json.Unmarshal(d, &contracts)
Expand All @@ -61,6 +67,17 @@ func ReadCombinedABIJSON(filePath string) (*CompiledContracts, error) {
return contracts, nil
}

func ReadContractJSON(filePath string) (*CompiledContracts, error) {
contracts, err := ReadSolcCompiledContract(filePath)
if err != nil {
return nil, err
}
if len(contracts.Contracts) > 0 {
return contracts, nil
}
return ReadTruffleCompiledContract(filePath)
}

func ExtractContracts(containerName, sourceDir, destinationDir string, verbose bool) error {
if err := docker.RunDockerCommand(destinationDir, verbose, verbose, "cp", containerName+":"+sourceDir, destinationDir); err != nil {
return err
Expand Down
12 changes: 7 additions & 5 deletions internal/blockchain/ethereum/ethconnect/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,15 +301,17 @@ func DeployFireFlyContract(s *types.Stack, log log.Logger, verbose bool) (*core.
return nil, err
}

contracts, err := ethereum.ReadCombinedABIJSON(filepath.Join(s.RuntimeDir, "contracts", "Firefly.json"))
var fireflyContract *ethereum.CompiledContract
contracts, err := ethereum.ReadContractJSON(filepath.Join(s.RuntimeDir, "contracts", "Firefly.json"))
if err != nil {
return nil, err
}

fireflyContract, ok := contracts.Contracts["Firefly.sol:Firefly"]
if !ok {
fireflyContract, err = ethereum.ReadTruffleCompiledContract(filepath.Join(s.RuntimeDir, "contracts", "Firefly.json"))
if err != nil {
return nil, err
fireflyContract, ok = contracts.Contracts["Firefly"]
if !ok {
return nil, fmt.Errorf("unable to find compiled FireFly contract")
}
}

Expand All @@ -328,7 +330,7 @@ func DeployFireFlyContract(s *types.Stack, log log.Logger, verbose bool) (*core.
}

func DeployCustomContract(member *types.Member, filename, contractName string) (string, error) {
contracts, err := ethereum.ReadCombinedABIJSON(filename)
contracts, err := ethereum.ReadContractJSON(filename)
if err != nil {
return "", nil
}
Expand Down
2 changes: 1 addition & 1 deletion internal/blockchain/ethereum/geth/geth_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func (p *GethProvider) Reset() error {
}

func (p *GethProvider) GetContracts(filename string, extraArgs []string) ([]string, error) {
contracts, err := ethereum.ReadCombinedABIJSON(filename)
contracts, err := ethereum.ReadContractJSON(filename)
if err != nil {
return []string{}, err
}
Expand Down
10 changes: 9 additions & 1 deletion internal/stacks/stack_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -775,9 +775,17 @@ func (s *StackManager) runFirstTimeSetup(verbose bool, options *types.StartOptio
}

for i, tp := range s.tokenProviders {
if err := tp.DeploySmartContracts(i); err != nil {
result, err := tp.DeploySmartContracts(i)
if err != nil {
return err
}
if result != nil {
msg := result.GetTokenDeploymentMessage()
if msg != "" {
// TODO: move this to the end somehow
fmt.Println(msg)
}
}
}

if s.Stack.ContractAddress == "" {
Expand Down
38 changes: 30 additions & 8 deletions internal/tokens/erc1155/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,26 @@ import (
"github.com/hyperledger/firefly-cli/internal/blockchain/ethereum"
"github.com/hyperledger/firefly-cli/internal/blockchain/ethereum/ethconnect"
"github.com/hyperledger/firefly-cli/internal/log"
"github.com/hyperledger/firefly-cli/internal/tokens"
"github.com/hyperledger/firefly-cli/pkg/types"
)

const TOKEN_URI_PATTERN = "firefly://token/{id}"

func DeployContracts(s *types.Stack, log log.Logger, verbose bool, tokenIndex int) error {
type TokenDeploymentResult struct {
Message string
Result interface{}
}

func (t *TokenDeploymentResult) GetTokenDeploymentMessage() string {
return t.Message
}

func (t *TokenDeploymentResult) GetTokenDeploymentResult() interface{} {
return t.Result
}

func DeployContracts(s *types.Stack, log log.Logger, verbose bool, tokenIndex int) (tokens.ITokenDeploymentResult, error) {
var containerName string
for _, member := range s.Members {
if !member.External {
Expand All @@ -38,17 +52,21 @@ func DeployContracts(s *types.Stack, log log.Logger, verbose bool, tokenIndex in
}
}
if containerName == "" {
return errors.New("unable to extract contracts from container - no valid tokens containers found in stack")
return nil, errors.New("unable to extract contracts from container - no valid tokens containers found in stack")
}
log.Info("extracting smart contracts")

if err := ethereum.ExtractContracts(containerName, "/root/contracts", s.RuntimeDir, verbose); err != nil {
return err
return nil, err
}

tokenContract, err := ethereum.ReadTruffleCompiledContract(filepath.Join(s.RuntimeDir, "contracts", "ERC1155MixedFungible.json"))
contracts, err := ethereum.ReadTruffleCompiledContract(filepath.Join(s.RuntimeDir, "contracts", "ERC1155MixedFungible.json"))
if err != nil {
return err
return nil, err
}
tokenContract, ok := contracts.Contracts["ERC1155MixedFungible"]
if !ok {
return nil, fmt.Errorf("unable to find ERC1155MixedFungible in compiled contracts")
}

var tokenContractAddress string
Expand All @@ -58,16 +76,20 @@ func DeployContracts(s *types.Stack, log log.Logger, verbose bool, tokenIndex in
log.Info(fmt.Sprintf("deploying ERC1155 contract on '%s'", member.ID))
tokenContractAddress, err = ethconnect.DeprecatedDeployContract(member, tokenContract, "erc1155", map[string]string{"uri": TOKEN_URI_PATTERN})
if err != nil {
return err
return nil, err
}
} else {
log.Info(fmt.Sprintf("registering ERC1155 contract on '%s'", member.ID))
err = ethconnect.DeprecatedRegisterContract(member, tokenContract, tokenContractAddress, "erc1155", map[string]string{"uri": TOKEN_URI_PATTERN})
if err != nil {
return err
return nil, err
}
}
}

return nil
result := &TokenDeploymentResult{
Message: "i deployed an ERC1155 contract",
}

return result, nil
}
3 changes: 2 additions & 1 deletion internal/tokens/erc1155/erc1155_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ 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/internal/tokens"
"github.com/hyperledger/firefly-cli/pkg/types"
)

Expand All @@ -31,7 +32,7 @@ type ERC1155Provider struct {
Stack *types.Stack
}

func (p *ERC1155Provider) DeploySmartContracts(tokenIndex int) error {
func (p *ERC1155Provider) DeploySmartContracts(tokenIndex int) (tokens.ITokenDeploymentResult, error) {
return DeployContracts(p.Stack, p.Log, p.Verbose, tokenIndex)
}

Expand Down
75 changes: 60 additions & 15 deletions internal/tokens/erc20erc721/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,67 @@ package erc20erc721

import (
"github.com/hyperledger/firefly-cli/internal/log"
"github.com/hyperledger/firefly-cli/internal/tokens"
"github.com/hyperledger/firefly-cli/pkg/types"
)

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.
//
// 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
type TokenDeploymentResult struct {
Message string
Result interface{}
}

func (t *TokenDeploymentResult) GetTokenDeploymentMessage() string {
return t.Message
}

func (t *TokenDeploymentResult) GetTokenDeploymentResult() interface{} {
return t.Result
}

func DeployContracts(s *types.Stack, log log.Logger, verbose bool, tokenIndex int) (tokens.ITokenDeploymentResult, error) {
// var containerName string
// for _, member := range s.Members {
// if !member.External {
// containerName = fmt.Sprintf("%s_tokens_%s_%d", s.Name, member.ID, tokenIndex)
// break
// }
// }
// if containerName == "" {
// return nil, errors.New("unable to extract contracts from container - no valid tokens containers found in stack")
// }
// log.Info("extracting smart contracts")

// if err := ethereum.ExtractContracts(containerName, "/root/contracts", s.RuntimeDir, verbose); err != nil {
// return nil, err
// }

// tokenContract, err := ethereum.ReadSolcCompiledContract(filepath.Join(s.RuntimeDir, "contracts", "TokenFactory.json"))
// if err != nil {
// return nil, err
// }

// var tokenContractAddress string
// for _, member := range s.Members {
// // TODO: move to address based contract deployment, once ERC-1155 connector is updated to not require an EthConnect REST API registration
// if tokenContractAddress == "" {
// log.Info(fmt.Sprintf("deploying ERC1155 contract on '%s'", member.ID))
// tokenContractAddress, err = ethconnect.DeprecatedDeployContract(member, tokenContract, "ERC20WithData", map[string]string{"uri": TOKEN_URI_PATTERN})
// if err != nil {
// return nil, err
// }
// } else {
// log.Info(fmt.Sprintf("registering ERC1155 contract on '%s'", member.ID))
// err = ethconnect.DeprecatedRegisterContract(member, tokenContract, tokenContractAddress, "erc1155", map[string]string{"uri": TOKEN_URI_PATTERN})
// if err != nil {
// return nil, err
// }
// }
// }

// deploymentResult := &TokenDeploymentResult{
// Message: "hey, I deployed a contract!",
// }

// return deploymentResult, nil
return nil, nil
}
3 changes: 2 additions & 1 deletion internal/tokens/erc20erc721/erc20_erc721_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ 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/internal/tokens"
"github.com/hyperledger/firefly-cli/pkg/types"
)

Expand All @@ -31,7 +32,7 @@ type ERC20ERC721Provider struct {
Stack *types.Stack
}

func (p *ERC20ERC721Provider) DeploySmartContracts(tokenIndex int) error {
func (p *ERC20ERC721Provider) DeploySmartContracts(tokenIndex int) (tokens.ITokenDeploymentResult, error) {
return DeployContracts(p.Stack, p.Log, p.Verbose, tokenIndex)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/tokens/tokens_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
)

type ITokensProvider interface {
DeploySmartContracts(tokenIndex int) error
DeploySmartContracts(tokenIndex int) (ITokenDeploymentResult, error)
FirstTimeSetup(tokenIdx int) error
GetDockerServiceDefinitions(tokenIdx int) []*docker.ServiceDefinition
GetFireflyConfig(m *types.Member, tokenIdx int) *core.TokenConnector
Expand Down
22 changes: 22 additions & 0 deletions internal/tokens/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright © 2022 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 tokens

type ITokenDeploymentResult interface {
GetTokenDeploymentMessage() string
GetTokenDeploymentResult() interface{}
}

0 comments on commit 54ef823

Please sign in to comment.