From f4606402b03629014cd60b06a095fad421d9d772 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Thu, 19 Sep 2024 21:58:01 -0700 Subject: [PATCH 01/20] Generalize generator interface --- cadence/contracts/Foobar.cdc | 4 + cadence/scripts/Baz.cdc | 4 + cadence/tests/Foobar_test.cdc | 13 + foo.cdc | 3 + internal/super/generate.go | 327 +----------------- internal/super/generator/contract_template.go | 76 ++++ internal/super/generator/generator.go | 160 +++++++++ .../generator_test.go} | 128 +++---- internal/super/generator/mocks/generator.go | 51 +++ internal/super/generator/script_template.go | 44 +++ internal/super/generator/test_template.go | 43 +++ .../super/generator/transaction_template.go | 44 +++ internal/super/setup.go | 40 +-- 13 files changed, 531 insertions(+), 406 deletions(-) create mode 100644 cadence/contracts/Foobar.cdc create mode 100644 cadence/scripts/Baz.cdc create mode 100644 cadence/tests/Foobar_test.cdc create mode 100644 foo.cdc create mode 100644 internal/super/generator/contract_template.go create mode 100644 internal/super/generator/generator.go rename internal/super/{generate_test.go => generator/generator_test.go} (61%) create mode 100644 internal/super/generator/mocks/generator.go create mode 100644 internal/super/generator/script_template.go create mode 100644 internal/super/generator/test_template.go create mode 100644 internal/super/generator/transaction_template.go diff --git a/cadence/contracts/Foobar.cdc b/cadence/contracts/Foobar.cdc new file mode 100644 index 000000000..cef88c8ef --- /dev/null +++ b/cadence/contracts/Foobar.cdc @@ -0,0 +1,4 @@ +access(all) +contract Foobar { + init() {} +} \ No newline at end of file diff --git a/cadence/scripts/Baz.cdc b/cadence/scripts/Baz.cdc new file mode 100644 index 000000000..191f77c5d --- /dev/null +++ b/cadence/scripts/Baz.cdc @@ -0,0 +1,4 @@ +access(all) +fun main() { + // Script details here +} \ No newline at end of file diff --git a/cadence/tests/Foobar_test.cdc b/cadence/tests/Foobar_test.cdc new file mode 100644 index 000000000..bee7499af --- /dev/null +++ b/cadence/tests/Foobar_test.cdc @@ -0,0 +1,13 @@ +import Test + +access(all) let account = Test.createAccount() + +access(all) fun testContract() { + let err = Test.deployContract( + name: "Foobar", + path: "../contracts/Foobar.cdc", + arguments: [], + ) + + Test.expect(err, Test.beNil()) +} \ No newline at end of file diff --git a/foo.cdc b/foo.cdc new file mode 100644 index 000000000..d0b279e78 --- /dev/null +++ b/foo.cdc @@ -0,0 +1,3 @@ +access(all) fun main() { + +} \ No newline at end of file diff --git a/internal/super/generate.go b/internal/super/generate.go index 5a16047d4..7a6ab4f0c 100644 --- a/internal/super/generate.go +++ b/internal/super/generate.go @@ -19,15 +19,9 @@ package super import ( - "bytes" "embed" - "fmt" - "path/filepath" - "text/template" - - flowsdk "github.com/onflow/flow-go-sdk" - "github.com/onflow/flowkit/v2/config" + "github.com/onflow/flow-cli/internal/super/generator" "github.com/onflow/flow-cli/internal/util" "github.com/onflow/flowkit/v2" @@ -36,6 +30,7 @@ import ( "github.com/onflow/flow-cli/internal/command" + "github.com/spf13/afero" "github.com/spf13/cobra" ) @@ -109,9 +104,9 @@ func generateContract( _ flowkit.Services, state *flowkit.State, ) (result command.Result, err error) { - generator := NewGenerator("", state, logger, false, true) - contract := Contract{Name: args[0], Account: ""} - err = generator.Create(TemplateMap{ContractType: []TemplateItem{contract}}) + g := generator.NewGenerator(getTemplateFs(), "", state, logger, false, true) + name := util.StripCDCExtension(args[0]) + err = g.Create(generator.ContractTemplate{Name: name}) return nil, err } @@ -122,9 +117,9 @@ func generateTransaction( _ flowkit.Services, state *flowkit.State, ) (result command.Result, err error) { - generator := NewGenerator("", state, logger, false, true) - transaction := ScriptTemplate{Name: args[0]} - err = generator.Create(TemplateMap{TransactionType: []TemplateItem{transaction}}) + g := generator.NewGenerator(getTemplateFs(), "", state, logger, false, true) + name := util.StripCDCExtension(args[0]) + err = g.Create(generator.TransactionTemplate{Name: name}) return nil, err } @@ -135,307 +130,13 @@ func generateScript( _ flowkit.Services, state *flowkit.State, ) (result command.Result, err error) { - generator := NewGenerator("", state, logger, false, true) - script := ScriptTemplate{Name: args[0]} - err = generator.Create(TemplateMap{ScriptType: []TemplateItem{script}}) + g := generator.NewGenerator(getTemplateFs(), "", state, logger, false, true) + name := util.StripCDCExtension(args[0]) + err = g.Create(generator.ScriptTemplate{Name: name}) return nil, err } -// TemplateItem is an interface for different template types -type TemplateItem interface { - GetName() string - GetTemplate() string - GetAccount() string - GetData() map[string]interface{} -} - -// Contract contains properties for contracts -type Contract struct { - Name string - Template string - Account string - Data map[string]interface{} -} - -// GetName returns the name of the contract -func (c Contract) GetName() string { - return c.Name -} - -// GetTemplate returns the template of the contract -func (c Contract) GetTemplate() string { - if c.Template == "" { - return "contract_init" - } - - return c.Template -} - -// GetAccount returns the account of the contract -func (c Contract) GetAccount() string { - return c.Account -} - -// GetData returns the data of the contract -func (c Contract) GetData() map[string]interface{} { - return c.Data -} - -// ScriptTemplate contains only a name property for scripts and transactions -type ScriptTemplate struct { - Name string - Template string - Data map[string]interface{} -} - -// GetName returns the name of the script or transaction -func (o ScriptTemplate) GetName() string { - return o.Name -} - -// GetTemplate returns an empty string for scripts and transactions -func (o ScriptTemplate) GetTemplate() string { - if o.Template == "" { - return "script_init" - } - - return o.Template -} - -// GetAccount returns an empty string for scripts and transactions -func (o ScriptTemplate) GetAccount() string { - return "" -} - -// GetData returns the data of the script or transaction -func (o ScriptTemplate) GetData() map[string]interface{} { - return o.Data -} - -// TransactionTemplate contains only a name property for scripts and transactions -type TransactionTemplate struct { - Name string - Template string - Data map[string]interface{} -} - -// GetName returns the name of the script or transaction -func (o TransactionTemplate) GetName() string { - return o.Name -} - -// GetTemplate returns an empty string for scripts and transactions -func (o TransactionTemplate) GetTemplate() string { - if o.Template == "" { - return "transaction_init" - } - - return o.Template -} - -// GetAccount returns an empty string for scripts and transactions -func (o TransactionTemplate) GetAccount() string { - return "" -} - -// GetData returns the data of the script or transaction -func (o TransactionTemplate) GetData() map[string]interface{} { - return o.Data -} - -// TemplateMap holds all templates with flexibility -type TemplateMap map[string][]TemplateItem - -type Generator struct { - directory string - state *flowkit.State - logger output.Logger - disableLogs bool - saveState bool -} - -func NewGenerator(directory string, state *flowkit.State, logger output.Logger, disableLogs, saveState bool) *Generator { - return &Generator{ - directory: directory, - state: state, - logger: logger, - disableLogs: disableLogs, - saveState: saveState, - } -} - -func (g *Generator) Create(typeNames TemplateMap) error { - for templateType, items := range typeNames { - for _, item := range items { - err := g.generate(templateType, item.GetTemplate(), item.GetName(), item.GetAccount(), item.GetData()) - if err != nil { - return err - } - } - } - return nil -} - -func (g *Generator) generate(templateType, templateName, name, account string, data map[string]interface{}) error { - - name = util.StripCDCExtension(name) - filename := util.AddCDCExtension(name) - - var fileToWrite string - var testFileToWrite string - var rootDir string - var basePath string - var testsBasePath = filepath.Join(DefaultCadenceDirectory, "tests") - var err error - - if g.directory != "" { - rootDir = g.directory - } - - templatePath := fmt.Sprintf("templates/%s.cdc.tmpl", templateName) - - switch templateType { - case ContractType: - basePath = filepath.Join(DefaultCadenceDirectory, "contracts") - fileData := map[string]interface{}{"Name": name} - for k, v := range data { - fileData[k] = v - } - fileToWrite, err = processTemplate(templatePath, fileData) - if err != nil { - return fmt.Errorf("error generating contract template: %w", err) - } - - testFileToWrite, err = processTemplate("templates/contract_init_test.cdc.tmpl", fileData) - if err != nil { - return fmt.Errorf("error generating contract test template: %w", err) - } - case ScriptType: - basePath = filepath.Join(DefaultCadenceDirectory, "scripts") - fileData := map[string]interface{}{} - for k, v := range data { - fileData[k] = v - } - fileToWrite, err = processTemplate(templatePath, fileData) - if err != nil { - return fmt.Errorf("error generating script template: %w", err) - } - case TransactionType: - basePath = filepath.Join(DefaultCadenceDirectory, "transactions") - fileData := map[string]interface{}{} - for k, v := range data { - fileData[k] = v - } - fileToWrite, err = processTemplate(templatePath, fileData) - if err != nil { - return fmt.Errorf("error generating transaction template: %w", err) - } - default: - return fmt.Errorf("invalid template type: %s", templateType) - } - - directoryWithBasePath := filepath.Join(rootDir, basePath, account) - filenameWithBasePath := filepath.Join(rootDir, basePath, account, filename) - relativeFilenameWithBasePath := filepath.Join(basePath, account, filename) - - // Check file existence - if _, err := g.state.ReaderWriter().ReadFile(filenameWithBasePath); err == nil { - return fmt.Errorf("file already exists: %s", filenameWithBasePath) - } - - // Ensure the directory exists - if err := g.state.ReaderWriter().MkdirAll(directoryWithBasePath, 0755); err != nil { - return fmt.Errorf("error creating directories: %w", err) - } - - // Write files - err = g.state.ReaderWriter().WriteFile(filenameWithBasePath, []byte(fileToWrite), 0644) - if err != nil { - return fmt.Errorf("error writing file: %w", err) - } - - if !g.disableLogs { - g.logger.Info(fmt.Sprintf("Generated new %s: %s at %s", templateType, name, filenameWithBasePath)) - } - - if generateFlags.SkipTests != true && templateType == ContractType { - testDirectoryWithBasePath := filepath.Join(rootDir, testsBasePath) - testFilenameWithBasePath := filepath.Join(rootDir, testsBasePath, util.AddCDCExtension(fmt.Sprintf("%s_test", name))) - - if _, err := g.state.ReaderWriter().ReadFile(testFilenameWithBasePath); err == nil { - return fmt.Errorf("file already exists: %s", testFilenameWithBasePath) - } - - if err := g.state.ReaderWriter().MkdirAll(testDirectoryWithBasePath, 0755); err != nil { - return fmt.Errorf("error creating test directory: %w", err) - } - - err := g.state.ReaderWriter().WriteFile(testFilenameWithBasePath, []byte(testFileToWrite), 0644) - if err != nil { - return fmt.Errorf("error writing test file: %w", err) - } - - if !g.disableLogs { - g.logger.Info(fmt.Sprintf("Generated new test file: %s at %s", name, testFilenameWithBasePath)) - } - } - - if templateType == ContractType { - err := g.updateContractsState(name, relativeFilenameWithBasePath) - if err != nil { - return err - } - } - - return nil -} - -func (g *Generator) updateContractsState(name, location string) error { - var aliases config.Aliases - - if generateFlags.SkipTests != true { - aliases = config.Aliases{{ - Network: config.TestingNetwork.Name, - Address: flowsdk.HexToAddress("0x0000000000000007"), - }} - } - - contract := config.Contract{ - Name: name, - Location: location, - Aliases: aliases, - } - - g.state.Contracts().AddOrUpdate(contract) - - if g.saveState { - err := g.state.SaveDefault() // TODO: Support adding a target project directory - if err != nil { - return fmt.Errorf("error saving to flow.json: %w", err) - } - } - - return nil -} - -// processTemplate reads a template file from the embedded filesystem and processes it with the provided data -// If you don't need to provide data, pass nil -func processTemplate(templatePath string, data map[string]interface{}) (string, error) { - templateData, err := templatesFS.ReadFile(templatePath) - if err != nil { - return "", fmt.Errorf("failed to read template file: %w", err) - } - - tmpl, err := template.New("template").Parse(string(templateData)) - if err != nil { - return "", fmt.Errorf("failed to parse template: %w", err) - } - - var executedTemplate bytes.Buffer - // Execute the template with the provided data or nil if no data is needed - if err = tmpl.Execute(&executedTemplate, data); err != nil { - return "", fmt.Errorf("failed to execute template: %w", err) - } - - return executedTemplate.String(), nil +func getTemplateFs() *afero.Afero { + fs := afero.Afero{Fs: afero.FromIOFS{FS: templatesFS}} + return &afero.Afero{Fs: afero.NewBasePathFs(fs, "templates")} } diff --git a/internal/super/generator/contract_template.go b/internal/super/generator/contract_template.go new file mode 100644 index 000000000..3c319192d --- /dev/null +++ b/internal/super/generator/contract_template.go @@ -0,0 +1,76 @@ +package generator + +import ( + "fmt" + "path/filepath" + + "github.com/onflow/flow-cli/internal/util" + flowsdk "github.com/onflow/flow-go-sdk" + "github.com/onflow/flowkit/v2" + "github.com/onflow/flowkit/v2/config" +) + +// Contract contains properties for contracts +type ContractTemplate struct { + Name string + Account string + TemplatePath string + Data map[string]interface{} + skipTests bool + saveState bool +} + +var _ TemplateItem = ContractTemplate{} + +// GetTemplate returns the template of the contract +func (c ContractTemplate) GetTemplatePath() string { + if c.TemplatePath == "" { + return "contract_init.cdc.tmpl" + } + + return c.TemplatePath +} + +// GetData returns the data of the contract +func (c ContractTemplate) GetData() map[string]interface{} { + data := map[string]interface{}{ + "Name": c.Name, + } + + for k, v := range c.Data { + data[k] = v + } + return data +} + +func (c ContractTemplate) GetTargetPath() string { + return filepath.Join(DefaultCadenceDirectory, "contracts", c.Account, util.AddCDCExtension(c.Name)) +} + +func (c ContractTemplate) UpdateState(state *flowkit.State) error { + var aliases config.Aliases + + if c.skipTests != true { + aliases = config.Aliases{{ + Network: config.TestingNetwork.Name, + Address: flowsdk.HexToAddress("0x0000000000000007"), + }} + } + + contract := config.Contract{ + Name: c.Name, + Location: c.GetTargetPath(), + Aliases: aliases, + } + + state.Contracts().AddOrUpdate(contract) + + if c.saveState { + err := state.SaveDefault() // TODO: Support adding a target project directory + if err != nil { + return fmt.Errorf("error saving to flow.json: %w", err) + } + } + + return nil +} diff --git a/internal/super/generator/generator.go b/internal/super/generator/generator.go new file mode 100644 index 000000000..968ca1ed4 --- /dev/null +++ b/internal/super/generator/generator.go @@ -0,0 +1,160 @@ +/* + * Flow CLI + * + * Copyright Flow Foundation + * + * 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 generator + +import ( + "bytes" + "fmt" + "path/filepath" + "text/template" + + "github.com/onflow/flowkit/v2" + "github.com/spf13/afero" + + "github.com/onflow/flowkit/v2/output" +) + +const ( + DefaultCadenceDirectory = "cadence" +) + +// TemplateItem is an interface for different template types +type TemplateItem interface { + GetTemplatePath() string + GetData() map[string]interface{} + GetTargetPath() string + UpdateState(state *flowkit.State) error +} + +//go:generate mockery --name Generator --case underscore +type Generator interface { + // Create generates files from the provided template items + Create(items ...TemplateItem) error +} + +type GeneratorImpl struct { + templateFs *afero.Afero + directory string + state *flowkit.State + logger output.Logger + disableLogs bool + saveState bool +} + +func NewGenerator( + templateFs *afero.Afero, + directory string, + state *flowkit.State, + logger output.Logger, + disableLogs, + saveState bool, +) *GeneratorImpl { + return &GeneratorImpl{ + templateFs: templateFs, + directory: directory, + state: state, + logger: logger, + disableLogs: disableLogs, + saveState: saveState, + } +} + +func (g *GeneratorImpl) Create(items ...TemplateItem) error { + for _, item := range items { + err := g.generate(item) + if err != nil { + return err + } + } + + return nil +} + +func (g *GeneratorImpl) generate(item TemplateItem) error { + rootDir := g.directory + + targetRelativeToRoot := item.GetTargetPath() + templatePath := item.GetTemplatePath() + data := item.GetData() + + fileData := map[string]interface{}{} + for k, v := range data { + fileData[k] = v + } + + outputContent, err := g.processTemplate(templatePath, fileData) + if err != nil { + // TODO, better error based on template type + return fmt.Errorf("error generating template: %w", err) + } + + targetPath := filepath.Join(rootDir, targetRelativeToRoot) + targetDirectory := filepath.Dir(targetPath) + + // Check file existence + if _, err := g.state.ReaderWriter().ReadFile(targetPath); err == nil { + return fmt.Errorf("file already exists: %s", targetPath) + } + + // Ensure the directory exists + if err := g.state.ReaderWriter().MkdirAll(targetDirectory, 0755); err != nil { + return fmt.Errorf("error creating directories: %w", err) + } + + // Write files + err = g.state.ReaderWriter().WriteFile(targetPath, []byte(outputContent), 0644) + if err != nil { + return fmt.Errorf("error writing file: %w", err) + } + + if !g.disableLogs { + // TODO: Add more detailed logging + g.logger.Info(fmt.Sprintf("Generated %s", targetPath)) + } + + // Call template state update function if it exists + err = item.UpdateState(g.state) + if err != nil { + return err + } + + return nil +} + +// processTemplate reads a template file from the embedded filesystem and processes it with the provided data +// If you don't need to provide data, pass nil +func (g *GeneratorImpl) processTemplate(templatePath string, data map[string]interface{}) (string, error) { + templateData, err := g.templateFs.ReadFile(templatePath) + if err != nil { + return "", fmt.Errorf("failed to read template file: %w", err) + } + + tmpl, err := template.New("template").Parse(string(templateData)) + if err != nil { + return "", fmt.Errorf("failed to parse template: %w", err) + } + + var executedTemplate bytes.Buffer + // Execute the template with the provided data or nil if no data is needed + if err = tmpl.Execute(&executedTemplate, data); err != nil { + return "", fmt.Errorf("failed to execute template: %w", err) + } + + return executedTemplate.String(), nil +} diff --git a/internal/super/generate_test.go b/internal/super/generator/generator_test.go similarity index 61% rename from internal/super/generate_test.go rename to internal/super/generator/generator_test.go index 3e368f07d..c6d6719ee 100644 --- a/internal/super/generate_test.go +++ b/internal/super/generator/generator_test.go @@ -16,64 +16,54 @@ * limitations under the License. */ -package super +package generator import ( + "embed" "fmt" "path/filepath" "testing" "github.com/onflow/flow-cli/internal/util" + "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/onflow/flowkit/v2/output" ) +// go:embed ../templates/*.tmpl +var templateFs embed.FS + +func getTemplateFS() *afero.Afero { + return &afero.Afero{Fs: afero.FromIOFS{FS: templateFs}} +} + func TestGenerateNewContract(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - generator := NewGenerator("", state, logger, false, true) + g := NewGenerator(getTemplateFS(), "", state, logger, false, true) // Test contract generation - err := generator.Create(TemplateMap{"contract": []TemplateItem{Contract{Name: "TestContract", Account: ""}}}) + err := g.Create(ContractTemplate{Name: "TestContract"}) assert.NoError(t, err, "Failed to generate contract") fileContent, err := state.ReaderWriter().ReadFile(filepath.FromSlash("cadence/contracts/TestContract.cdc")) assert.NoError(t, err, "Failed to read generated file") assert.NotNil(t, fileContent) - testContent, err := state.ReaderWriter().ReadFile(filepath.FromSlash("cadence/tests/TestContract_test.cdc")) - assert.NoError(t, err, "Failed to read generated file") - assert.NotNil(t, testContent) - // Check content is correct expectedContent := `access(all) contract TestContract { init() {} }` - expectedTestContent := `import Test - -access(all) let account = Test.createAccount() - -access(all) fun testContract() { - let err = Test.deployContract( - name: "TestContract", - path: "../contracts/TestContract.cdc", - arguments: [], - ) - - Test.expect(err, Test.beNil()) -}` - assert.Equal(t, expectedContent, util.NormalizeLineEndings(string(fileContent))) - assert.Equal(t, expectedTestContent, util.NormalizeLineEndings(string(testContent))) // Test file already exists scenario - generatorTwo := NewGenerator("", state, logger, false, true) - err = generatorTwo.Create(TemplateMap{"contract": []TemplateItem{Contract{Name: "TestContract", Account: ""}}}) + generatorTwo := NewGenerator(getTemplateFS(), "", state, logger, false, true) + err = generatorTwo.Create(ContractTemplate{Name: "TestContract"}) assert.Error(t, err) expectedError := fmt.Sprintf("file already exists: %s", filepath.FromSlash("cadence/contracts/TestContract.cdc")) assert.Equal(t, expectedError, err.Error()) @@ -83,34 +73,25 @@ func TestGenerateContractWithAccount(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - generator := NewGenerator("", state, logger, false, true) + g := NewGenerator(getTemplateFS(), "", state, logger, false, true) // Test contract generation - err := generator.Create(TemplateMap{"contract": []TemplateItem{Contract{Name: "TestContract", Account: "example-account"}}}) + err := g.Create(ContractTemplate{Name: "TestContract", Account: "example-account"}) assert.NoError(t, err, "Failed to generate contract") fileContent, err := state.ReaderWriter().ReadFile(filepath.FromSlash("cadence/contracts/example-account/TestContract.cdc")) assert.NoError(t, err, "Failed to read generated file") assert.NotNil(t, fileContent) - - testContent, err := state.ReaderWriter().ReadFile(filepath.FromSlash("cadence/tests/TestContract_test.cdc")) - assert.NoError(t, err, "Failed to read generated file") - assert.NotNil(t, testContent) } func TestGenerateNewContractSkipTests(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - generateFlags.SkipTests = true - - generator := NewGenerator("", state, logger, false, true) - t.Cleanup(func() { - generateFlags.SkipTests = false - }) + g := NewGenerator(getTemplateFS(), "", state, logger, false, true) // Test contract generation - err := generator.Create(TemplateMap{"contract": []TemplateItem{Contract{Name: "TestContract", Account: ""}}}) + err := g.Create(ContractTemplate{Name: "TestContract", Account: "", skipTests: true}) assert.NoError(t, err, "Failed to generate contract") fileContent, err := state.ReaderWriter().ReadFile(filepath.FromSlash("cadence/contracts/TestContract.cdc")) @@ -122,31 +103,13 @@ func TestGenerateNewContractSkipTests(t *testing.T) { assert.Nil(t, testContent) } -func TestGenerateNewContractWithCDCExtension(t *testing.T) { - logger := output.NewStdoutLogger(output.NoneLog) - _, state, _ := util.TestMocks(t) - - // Test contract generation - generator := NewGenerator("", state, logger, false, true) - err := generator.Create(TemplateMap{"contract": []TemplateItem{Contract{Name: "Tester.cdc", Account: ""}}}) - assert.NoError(t, err, "Failed to generate contract") - - fileContent, err := state.ReaderWriter().ReadFile(filepath.FromSlash("cadence/contracts/Tester.cdc")) - assert.NoError(t, err, "Failed to read generated file") - assert.NotNil(t, fileContent) - - testContent, err := state.ReaderWriter().ReadFile(filepath.FromSlash("cadence/tests/Tester_test.cdc")) - assert.NoError(t, err, "Failed to read generated file") - assert.NotNil(t, testContent) -} - func TestGenerateNewContractFileAlreadyExists(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) // Test contract generation - generator := NewGenerator("", state, logger, false, true) - err := generator.Create(TemplateMap{"contract": []TemplateItem{Contract{Name: "TestContract", Account: ""}}}) + g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + err := g.Create(ContractTemplate{Name: "TestContract", Account: ""}) assert.NoError(t, err, "Failed to generate contract") //// Check if the file exists in the correct directory @@ -155,8 +118,8 @@ func TestGenerateNewContractFileAlreadyExists(t *testing.T) { assert.NotNil(t, content) // Test file already exists scenario - generatorTwo := NewGenerator("", state, logger, false, true) - err = generatorTwo.Create(TemplateMap{"contract": []TemplateItem{Contract{Name: "TestContract", Account: ""}}}) + generatorTwo := NewGenerator(getTemplateFS(), "", state, logger, false, true) + err = generatorTwo.Create(ContractTemplate{Name: "TestContract", Account: ""}) assert.Error(t, err) expectedError := fmt.Sprintf("file already exists: %s", filepath.FromSlash("cadence/contracts/TestContract.cdc")) assert.Equal(t, expectedError, err.Error()) @@ -166,8 +129,8 @@ func TestGenerateNewContractWithFileExtension(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - generator := NewGenerator("", state, logger, false, true) - err := generator.Create(TemplateMap{"contract": []TemplateItem{Contract{Name: "TestContract.cdc", Account: ""}}}) + g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + err := g.Create(ContractTemplate{Name: "TestContract.cdc", Account: ""}) assert.NoError(t, err, "Failed to generate contract") // Check file exists @@ -180,8 +143,8 @@ func TestGenerateNewScript(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - generator := NewGenerator("", state, logger, false, true) - err := generator.Create(TemplateMap{"script": []TemplateItem{ScriptTemplate{Name: "TestScript"}}}) + g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + err := g.Create(ScriptTemplate{Name: "TestScript"}) assert.NoError(t, err, "Failed to generate contract") content, err := state.ReaderWriter().ReadFile(filepath.FromSlash("cadence/scripts/TestScript.cdc")) @@ -199,8 +162,8 @@ func TestGenerateNewTransaction(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - generator := NewGenerator("", state, logger, false, true) - err := generator.Create(TemplateMap{"transaction": []TemplateItem{TransactionTemplate{Name: "TestTransaction"}}}) + g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + err := g.Create(TransactionTemplate{Name: "TestTransaction"}) assert.NoError(t, err, "Failed to generate contract") content, err := state.ReaderWriter().ReadFile(filepath.FromSlash("cadence/transactions/TestTransaction.cdc")) @@ -219,21 +182,44 @@ func TestGenerateNewWithDirFlag(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - generator := NewGenerator("customDir", state, logger, false, true) - err := generator.Create(TemplateMap{"contract": []TemplateItem{Contract{Name: "TestContract", Account: ""}}}) + g := NewGenerator(getTemplateFS(), "customDir", state, logger, false, true) + err := g.Create(ContractTemplate{Name: "TestContract", Account: ""}) assert.NoError(t, err, "Failed to generate contract") content, err := state.ReaderWriter().ReadFile(filepath.FromSlash("customDir/cadence/contracts/TestContract.cdc")) assert.NoError(t, err, "Failed to read generated file") assert.NotNil(t, content) - testContent, err := state.ReaderWriter().ReadFile(filepath.FromSlash("customDir/cadence/tests/TestContract_test.cdc")) - assert.NoError(t, err, "Failed to read generated file") - assert.NotNil(t, testContent) - expectedContent := `access(all) contract TestContract { init() {} }` assert.Equal(t, expectedContent, util.NormalizeLineEndings(string(content))) } + +func TestGenerateTestTemplate(t *testing.T) { + logger := output.NewStdoutLogger(output.NoneLog) + _, state, _ := util.TestMocks(t) + + // Create a mock template file + tmplFs := afero.Afero{Fs: afero.NewMemMapFs()} + err := tmplFs.WriteFile("file.tmpl", []byte("{{.content}}"), 0644) + assert.NoError(t, err, "Failed to create template file") + + g := NewGenerator(&tmplFs, "", state, logger, false, true) + err = g.Create(TestTemplate{ + Name: "FooBar_test", + TemplatePath: "file.tmpl", + Data: map[string]interface{}{ + "content": "test template", + }}, + ) + assert.NoError(t, err, "Failed to generate file") + + content, err := state.ReaderWriter().ReadFile(filepath.FromSlash("cadence/tests/FooBar_test.cdc")) + assert.NoError(t, err, "Failed to read generated file") + assert.NotNil(t, content) + + expectedContent := `test template` + assert.Equal(t, expectedContent, util.NormalizeLineEndings(string(content))) +} diff --git a/internal/super/generator/mocks/generator.go b/internal/super/generator/mocks/generator.go new file mode 100644 index 000000000..c4e4e4a6e --- /dev/null +++ b/internal/super/generator/mocks/generator.go @@ -0,0 +1,51 @@ +// Code generated by mockery v2.40.3. DO NOT EDIT. + +package mocks + +import ( + generator "github.com/onflow/flow-cli/internal/super/generator" + mock "github.com/stretchr/testify/mock" +) + +// Generator is an autogenerated mock type for the Generator type +type Generator struct { + mock.Mock +} + +// Create provides a mock function with given fields: items +func (_m *Generator) Create(items ...generator.TemplateItem) error { + _va := make([]interface{}, len(items)) + for _i := range items { + _va[_i] = items[_i] + } + var _ca []interface{} + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Create") + } + + var r0 error + if rf, ok := ret.Get(0).(func(...generator.TemplateItem) error); ok { + r0 = rf(items...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// NewGenerator creates a new instance of Generator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewGenerator(t interface { + mock.TestingT + Cleanup(func()) +}) *Generator { + mock := &Generator{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/super/generator/script_template.go b/internal/super/generator/script_template.go new file mode 100644 index 000000000..7f13b55aa --- /dev/null +++ b/internal/super/generator/script_template.go @@ -0,0 +1,44 @@ +package generator + +import ( + "path/filepath" + + "github.com/onflow/flow-cli/internal/util" + "github.com/onflow/flowkit/v2" +) + +// ScriptTemplate contains only a name property for scripts and transactions +type ScriptTemplate struct { + Name string + TemplatePath string + Data map[string]interface{} +} + +var _ TemplateItem = ScriptTemplate{} + +// GetName returns the name of the script or transaction +func (o ScriptTemplate) GetName() string { + return o.Name +} + +// GetTemplate returns an empty string for scripts and transactions +func (o ScriptTemplate) GetTemplatePath() string { + if o.TemplatePath == "" { + return "script_init.cdc.tmpl" + } + + return o.TemplatePath +} + +// GetData returns the data of the script or transaction +func (o ScriptTemplate) GetData() map[string]interface{} { + return o.Data +} + +func (o ScriptTemplate) GetTargetPath() string { + return filepath.Join(DefaultCadenceDirectory, "scripts", util.AddCDCExtension(o.Name)) +} + +func (o ScriptTemplate) UpdateState(state *flowkit.State) error { + return nil +} diff --git a/internal/super/generator/test_template.go b/internal/super/generator/test_template.go new file mode 100644 index 000000000..f0207e187 --- /dev/null +++ b/internal/super/generator/test_template.go @@ -0,0 +1,43 @@ +package generator + +import ( + "path/filepath" + + "github.com/onflow/flow-cli/internal/util" + "github.com/onflow/flowkit/v2" +) + +type TestTemplate struct { + Name string + TemplatePath string + Data map[string]interface{} +} + +var _ TemplateItem = TestTemplate{} + +// GetName returns the name of the script or transaction +func (o TestTemplate) GetName() string { + return o.Name +} + +// GetTemplate returns an empty string for scripts and transactions +func (o TestTemplate) GetTemplatePath() string { + if o.TemplatePath == "" { + return "test_init" + } + + return o.TemplatePath +} + +// GetData returns the data of the script or transaction +func (o TestTemplate) GetData() map[string]interface{} { + return o.Data +} + +func (o TestTemplate) GetTargetPath() string { + return filepath.Join(DefaultCadenceDirectory, "tests", util.AddCDCExtension(o.Name)) +} + +func (o TestTemplate) UpdateState(state *flowkit.State) error { + return nil +} diff --git a/internal/super/generator/transaction_template.go b/internal/super/generator/transaction_template.go new file mode 100644 index 000000000..d90ba3cce --- /dev/null +++ b/internal/super/generator/transaction_template.go @@ -0,0 +1,44 @@ +package generator + +import ( + "path/filepath" + + "github.com/onflow/flow-cli/internal/util" + "github.com/onflow/flowkit/v2" +) + +// TransactionTemplate contains only a name property for scripts and transactions +type TransactionTemplate struct { + Name string + TemplatePath string + Data map[string]interface{} +} + +var _ TemplateItem = TransactionTemplate{} + +// GetName returns the name of the script or transaction +func (o TransactionTemplate) GetName() string { + return o.Name +} + +// GetTemplate returns an empty string for scripts and transactions +func (o TransactionTemplate) GetTemplatePath() string { + if o.TemplatePath == "" { + return "transaction_init.cdc.tmpl" + } + + return o.TemplatePath +} + +// GetData returns the data of the script or transaction +func (o TransactionTemplate) GetData() map[string]interface{} { + return o.Data +} + +func (o TransactionTemplate) GetTargetPath() string { + return filepath.Join(DefaultCadenceDirectory, "transactions", util.AddCDCExtension(o.Name)) +} + +func (o TransactionTemplate) UpdateState(state *flowkit.State) error { + return nil +} diff --git a/internal/super/setup.go b/internal/super/setup.go index 8af247cd0..7cb4a4bb0 100644 --- a/internal/super/setup.go +++ b/internal/super/setup.go @@ -32,6 +32,7 @@ import ( "golang.org/x/exp/slices" "github.com/onflow/flow-cli/internal/dependencymanager" + "github.com/onflow/flow-cli/internal/super/generator" "github.com/onflow/flow-cli/internal/util" "github.com/spf13/afero" @@ -207,38 +208,33 @@ func startInteractiveSetup( return "", fmt.Errorf("failed to initialize configuration: %w", err) } - // Generate standard cadence files + // Generate standard cadence files & README.md // cadence/contracts/DefaultContract.cdc // cadence/scripts/DefaultScript.cdc // cadence/transactions/DefaultTransaction.cdc // cadence/tests/DefaultContract_test.cdc + // README.md - templates := TemplateMap{ - "contract": []TemplateItem{ - Contract{ - Name: "Counter", - Template: "contract_counter", - Account: "", - }, + templates := []generator.TemplateItem{ + generator.ContractTemplate{ + Name: "Counter", + TemplatePath: "contract_counter.cdc.tmpl", + Account: "", }, - "script": []TemplateItem{ - ScriptTemplate{ - Name: "GetCounter", - Template: "script_counter", - Data: map[string]interface{}{"ContractName": "Counter"}, - }, + generator.ScriptTemplate{ + Name: "GetCounter", + TemplatePath: "script_counter.cdc.tmpl", + Data: map[string]interface{}{"ContractName": "Counter"}, }, - "transaction": []TemplateItem{ - TransactionTemplate{ - Name: "IncrementCounter", - Template: "transaction_counter", - Data: map[string]interface{}{"ContractName": "Counter"}, - }, + generator.TransactionTemplate{ + Name: "IncrementCounter", + TemplatePath: "transaction_counter.cdc.tmpl", + Data: map[string]interface{}{"ContractName": "Counter"}, }, } - generator := NewGenerator(tempDir, state, logger, true, false) - err = generator.Create(templates) + g := generator.NewGenerator(getTemplateFs(), tempDir, state, logger, true, false) + err = g.Create(templates...) if err != nil { return "", err } From 1a43e5bbcb5e7008422caf6cdc9293668c7823bb Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Thu, 19 Sep 2024 22:30:17 -0700 Subject: [PATCH 02/20] Add README --- internal/super/generator/file_template.go | 44 +++++++ internal/super/generator/generator_test.go | 27 ++++ internal/super/setup.go | 7 ++ internal/super/templates/README.md | 137 +++++++++++++++++++++ 4 files changed, 215 insertions(+) create mode 100644 internal/super/generator/file_template.go create mode 100644 internal/super/templates/README.md diff --git a/internal/super/generator/file_template.go b/internal/super/generator/file_template.go new file mode 100644 index 000000000..5fdf8716a --- /dev/null +++ b/internal/super/generator/file_template.go @@ -0,0 +1,44 @@ +package generator + +import ( + "github.com/onflow/flowkit/v2" +) + +// FileTemplate is a template for raw +type FileTemplate struct { + TemplatePath string + TargetPath string + Data map[string]interface{} +} + +func NewFileTemplate( + templatePath string, + targetPath string, + data map[string]interface{}, +) FileTemplate { + return FileTemplate{ + TemplatePath: templatePath, + TargetPath: targetPath, + Data: data, + } +} + +var _ TemplateItem = FileTemplate{} + +// GetTemplate returns the template of the contract +func (c FileTemplate) GetTemplatePath() string { + return c.TemplatePath +} + +// GetData returns the data of the contract +func (c FileTemplate) GetData() map[string]interface{} { + return c.Data +} + +func (c FileTemplate) GetTargetPath() string { + return c.TargetPath +} + +func (c FileTemplate) UpdateState(state *flowkit.State) error { + return nil +} diff --git a/internal/super/generator/generator_test.go b/internal/super/generator/generator_test.go index c6d6719ee..454263460 100644 --- a/internal/super/generator/generator_test.go +++ b/internal/super/generator/generator_test.go @@ -223,3 +223,30 @@ func TestGenerateTestTemplate(t *testing.T) { expectedContent := `test template` assert.Equal(t, expectedContent, util.NormalizeLineEndings(string(content))) } + +func TestGenerateFileTemplate(t *testing.T) { + logger := output.NewStdoutLogger(output.NoneLog) + _, state, _ := util.TestMocks(t) + + // Create a mock template file + tmplFs := afero.Afero{Fs: afero.NewMemMapFs()} + err := tmplFs.WriteFile("file.tmpl", []byte("{{.content}}"), 0644) + assert.NoError(t, err, "Failed to create template file") + + g := NewGenerator(&tmplFs, "", state, logger, false, true) + err = g.Create(FileTemplate{ + TargetPath: "TestFile", + TemplatePath: "file.tmpl", + Data: map[string]interface{}{ + "content": "test template", + }}, + ) + assert.NoError(t, err, "Failed to generate file") + + content, err := state.ReaderWriter().ReadFile(filepath.FromSlash("TestFile")) + assert.NoError(t, err, "Failed to read generated file") + assert.NotNil(t, content) + + expectedContent := `test template` + assert.Equal(t, expectedContent, util.NormalizeLineEndings(string(content))) +} diff --git a/internal/super/setup.go b/internal/super/setup.go index 7cb4a4bb0..8cfc6a153 100644 --- a/internal/super/setup.go +++ b/internal/super/setup.go @@ -231,6 +231,13 @@ func startInteractiveSetup( TemplatePath: "transaction_counter.cdc.tmpl", Data: map[string]interface{}{"ContractName": "Counter"}, }, + generator.FileTemplate{ + TemplatePath: "README.md.tmpl", + TargetPath: "README.md", + Data: map[string]interface{}{ + "ProjectName": filepath.Base(targetDir), + }, + }, } g := generator.NewGenerator(getTemplateFs(), tempDir, state, logger, true, false) diff --git a/internal/super/templates/README.md b/internal/super/templates/README.md new file mode 100644 index 000000000..a51c44b2b --- /dev/null +++ b/internal/super/templates/README.md @@ -0,0 +1,137 @@ +## ๐Ÿ‘‹ Welcome Flow Developer! +Welcome to your new {{ .ProjectType }} project. This project is a starting point for you to develop smart contracts on the Flow blockchain. It comes with a few example contracts and scripts to help you get started. + +## ๐Ÿ”จ Getting started +Getting started can feel overwhelming, but we are here for you. Depending on how accustomed you are to Flow here's a list of resources you might find useful: +- **[Cadence documentation](https://developers.flow.com/cadence/language)**: here you will find language reference for Cadence, which will be the language in which you develop your smart contracts, +- **[Visual Studio Code](https://code.visualstudio.com/?wt.mc_id=DX_841432)** and **[Cadence extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)**: we suggest using Visual Studio Code IDE for writing Cadence with the Cadence extension installed, that will give you nice syntax highlitning and additional smart features, +- **[SDKs](https://developers.flow.com/tools#sdks)**: here you will find a list of SDKs you can use to ease the interaction with Flow network (sending transactions, fetching accounts etc), +- **[Tools](https://developers.flow.com/tools#development-tools)**: development tools you can use to make your development easier, [Flowser](https://docs.flowser.dev/) can be super handy to see what's going on the blockchain while you develop +{{ if .IsNFTProject }} + +NFT Resources: +- **[flow-nft](https://github.com/onflow/flow-nft)**: home of the Flow NFT standards, contains utility contracts, examples, and documentation +- **[nft-storefront](https://github.com/onflow/nft-storefront/)**: NFT Storefront is an open marketplace contract used by most Flow NFT marketplaces +{{ end }} +{{ if .IsFungibleProject }} + +Fungible Token Resources: +- **[flow-ft](https://github.com/onflow/flow-ft)**: home of the Flow Fungible Token standards, contains utility contracts, examples, and documentation +{{ end }} + + +## ๐Ÿ“ฆ Project Structure +Your project comes with some standard folders which have a special purpose: +- `flow.json` configuration file for your project, you can think of it as package.json. It has been initialized with a basic configuration{{ if len .Dependecies }} and some Core Contract dependencies{{ end }}. +- `/cadence` inside here is where your Cadence smart contracts code lives + +Your project is set up with the following dependencies: +{{ range .Dependecies }} + - `{{ .Name }}` +{{ end }} + +Inside `cadence` folder you will find: +- `/contracts` location for Cadence contracts go in this folder +{{ range .Contracts }} + - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` contract +{{ end }} +- `/scripts` location for Cadence scripts goes here +{{ range .Scripts }} + - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` script +{{ end }} +- `/transactions` location for Cadence transactions goes in this folder +{{ range .Transactions }} + - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` transaction +{{ end }} +- `/tests` location for Cadence tests goes in this folder +{{ range .Tests }} + - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` test +{{ end }} + +## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing + +### Creating a new contract +To add a new contract to your project you can use the following command: + +```shell +> flow generate contract +``` + +This command will create a new contract file and add it to the `flow.json` configuration file. + +### Creating a new script + +To add a new script to your project you can use the following command: + +```shell +> flow generate script +``` + +This command will create a new script file and add it to the `flow.json` configuration file. + +You can import any of your own contracts or installed dependencies in your script file using the `import` keyword. For example: + +```cadence +import Counter from "Counter" +``` + +### Creating a new transaction + +To add a new transaction to your project you can use the following command: + +```shell +> flow generate transaction +``` + +This command will create a new transaction file and add it to the `flow.json` configuration file. You can import any dependencies as you would in a script file. + +### Installing external dependencies + +If you want to use external contract dependencies (like NonFungibleToken, FlowToken, FungibleToken,..) you can install them using Cadence dependency manager: https://developers.flow.com/tools/flow-cli/dependency-manager + +Use [ContractBrowser](https://contractbrowser.com/) to explore available 3rd party contracts in the Flow ecosystem. + +## ๐Ÿงช Testing +To verify that your project is working as expected you can run the tests using the following command: +```shell +> flow test +``` + +This command will run all the tests in the `cadence/tests` folder. You can add more tests to this folder as you develop your project. + +To learn more about testing in Cadence, check out the [Cadence testing documentation](https://cadence-lang.org/docs/testing-framework). + +## ๐Ÿš€ Deploying + +### Deploying to the Flow Emulator + +To deploy your project to the Flow Emulator you can use the following command: +```shell +> flow emulator --start +``` + +This command will start the Flow Emulator and deploy your project to it. You can then interact with your project using the Flow Emulator. + +### Deploying to the Flow Testnet + +To deploy your project to the Flow Testnet you can use the following command: +```shell +> flow project deploy --network=testnet +``` + +This command will deploy your project to the Flow Testnet. You can then interact with your project using the Flow Testnet. + +### Deploying to the Flow Mainnet + +To deploy your project to the Flow Mainnet you can use the following command: +```shell +> flow project deploy --network=mainnet +``` + +This command will deploy your project to the Flow Mainnet. You can then interact with your project using the Flow Mainnet. + +## Further Reading + +- Cadence Language Reference https://cadence-lang.org/docs/language +- Flow Smart Contract Project Development Standards https://cadence-lang.org/docs/project-development-tips +- Cadence anti-patterns https://cadence-lang.org/docs/anti-patterns \ No newline at end of file From 07887f1a861d5692124d871ba1286ab7c10750f8 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 24 Sep 2024 15:24:02 -0700 Subject: [PATCH 03/20] Remove FS abstraction --- internal/super/generate.go | 17 ++-------- internal/super/generator/generator.go | 10 +++--- internal/super/generator/generator_test.go | 32 +++++++------------ .../super/{ => generator}/templates/README.md | 0 .../templates/contract_counter.cdc.tmpl | 0 .../templates/contract_init.cdc.tmpl | 0 .../templates/contract_init_test.cdc.tmpl | 0 .../templates/script_counter.cdc.tmpl | 0 .../templates/script_init.cdc.tmpl | 0 .../templates/transaction_counter.cdc.tmpl | 0 .../templates/transaction_init.cdc.tmpl | 0 internal/super/setup.go | 2 +- 12 files changed, 21 insertions(+), 40 deletions(-) rename internal/super/{ => generator}/templates/README.md (100%) rename internal/super/{ => generator}/templates/contract_counter.cdc.tmpl (100%) rename internal/super/{ => generator}/templates/contract_init.cdc.tmpl (100%) rename internal/super/{ => generator}/templates/contract_init_test.cdc.tmpl (100%) rename internal/super/{ => generator}/templates/script_counter.cdc.tmpl (100%) rename internal/super/{ => generator}/templates/script_init.cdc.tmpl (100%) rename internal/super/{ => generator}/templates/transaction_counter.cdc.tmpl (100%) rename internal/super/{ => generator}/templates/transaction_init.cdc.tmpl (100%) diff --git a/internal/super/generate.go b/internal/super/generate.go index 7a6ab4f0c..6b1ec27ec 100644 --- a/internal/super/generate.go +++ b/internal/super/generate.go @@ -19,8 +19,6 @@ package super import ( - "embed" - "github.com/onflow/flow-cli/internal/super/generator" "github.com/onflow/flow-cli/internal/util" @@ -30,13 +28,9 @@ import ( "github.com/onflow/flow-cli/internal/command" - "github.com/spf13/afero" "github.com/spf13/cobra" ) -//go:embed templates/*.tmpl -var templatesFS embed.FS - type generateFlagsDef struct { Directory string `default:"" flag:"dir" info:"Directory to generate files in"` SkipTests bool `default:"false" flag:"skip-tests" info:"Skip generating test files"` @@ -104,7 +98,7 @@ func generateContract( _ flowkit.Services, state *flowkit.State, ) (result command.Result, err error) { - g := generator.NewGenerator(getTemplateFs(), "", state, logger, false, true) + g := generator.NewGenerator("", state, logger, false, true) name := util.StripCDCExtension(args[0]) err = g.Create(generator.ContractTemplate{Name: name}) return nil, err @@ -117,7 +111,7 @@ func generateTransaction( _ flowkit.Services, state *flowkit.State, ) (result command.Result, err error) { - g := generator.NewGenerator(getTemplateFs(), "", state, logger, false, true) + g := generator.NewGenerator("", state, logger, false, true) name := util.StripCDCExtension(args[0]) err = g.Create(generator.TransactionTemplate{Name: name}) return nil, err @@ -130,13 +124,8 @@ func generateScript( _ flowkit.Services, state *flowkit.State, ) (result command.Result, err error) { - g := generator.NewGenerator(getTemplateFs(), "", state, logger, false, true) + g := generator.NewGenerator("", state, logger, false, true) name := util.StripCDCExtension(args[0]) err = g.Create(generator.ScriptTemplate{Name: name}) return nil, err } - -func getTemplateFs() *afero.Afero { - fs := afero.Afero{Fs: afero.FromIOFS{FS: templatesFS}} - return &afero.Afero{Fs: afero.NewBasePathFs(fs, "templates")} -} diff --git a/internal/super/generator/generator.go b/internal/super/generator/generator.go index 968ca1ed4..901b29650 100644 --- a/internal/super/generator/generator.go +++ b/internal/super/generator/generator.go @@ -20,12 +20,12 @@ package generator import ( "bytes" + "embed" "fmt" "path/filepath" "text/template" "github.com/onflow/flowkit/v2" - "github.com/spf13/afero" "github.com/onflow/flowkit/v2/output" ) @@ -34,6 +34,9 @@ const ( DefaultCadenceDirectory = "cadence" ) +//go:embed templates/*.tmpl +var templatesFS embed.FS + // TemplateItem is an interface for different template types type TemplateItem interface { GetTemplatePath() string @@ -49,7 +52,6 @@ type Generator interface { } type GeneratorImpl struct { - templateFs *afero.Afero directory string state *flowkit.State logger output.Logger @@ -58,7 +60,6 @@ type GeneratorImpl struct { } func NewGenerator( - templateFs *afero.Afero, directory string, state *flowkit.State, logger output.Logger, @@ -66,7 +67,6 @@ func NewGenerator( saveState bool, ) *GeneratorImpl { return &GeneratorImpl{ - templateFs: templateFs, directory: directory, state: state, logger: logger, @@ -140,7 +140,7 @@ func (g *GeneratorImpl) generate(item TemplateItem) error { // processTemplate reads a template file from the embedded filesystem and processes it with the provided data // If you don't need to provide data, pass nil func (g *GeneratorImpl) processTemplate(templatePath string, data map[string]interface{}) (string, error) { - templateData, err := g.templateFs.ReadFile(templatePath) + templateData, err := templatesFS.ReadFile(templatePath) if err != nil { return "", fmt.Errorf("failed to read template file: %w", err) } diff --git a/internal/super/generator/generator_test.go b/internal/super/generator/generator_test.go index 454263460..6c0309019 100644 --- a/internal/super/generator/generator_test.go +++ b/internal/super/generator/generator_test.go @@ -19,7 +19,6 @@ package generator import ( - "embed" "fmt" "path/filepath" "testing" @@ -32,18 +31,11 @@ import ( "github.com/onflow/flowkit/v2/output" ) -// go:embed ../templates/*.tmpl -var templateFs embed.FS - -func getTemplateFS() *afero.Afero { - return &afero.Afero{Fs: afero.FromIOFS{FS: templateFs}} -} - func TestGenerateNewContract(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + g := NewGenerator("", state, logger, false, true) // Test contract generation err := g.Create(ContractTemplate{Name: "TestContract"}) @@ -62,7 +54,7 @@ contract TestContract { assert.Equal(t, expectedContent, util.NormalizeLineEndings(string(fileContent))) // Test file already exists scenario - generatorTwo := NewGenerator(getTemplateFS(), "", state, logger, false, true) + generatorTwo := NewGenerator("", state, logger, false, true) err = generatorTwo.Create(ContractTemplate{Name: "TestContract"}) assert.Error(t, err) expectedError := fmt.Sprintf("file already exists: %s", filepath.FromSlash("cadence/contracts/TestContract.cdc")) @@ -73,7 +65,7 @@ func TestGenerateContractWithAccount(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + g := NewGenerator("", state, logger, false, true) // Test contract generation err := g.Create(ContractTemplate{Name: "TestContract", Account: "example-account"}) @@ -88,7 +80,7 @@ func TestGenerateNewContractSkipTests(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + g := NewGenerator("", state, logger, false, true) // Test contract generation err := g.Create(ContractTemplate{Name: "TestContract", Account: "", skipTests: true}) @@ -108,7 +100,7 @@ func TestGenerateNewContractFileAlreadyExists(t *testing.T) { _, state, _ := util.TestMocks(t) // Test contract generation - g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + g := NewGenerator("", state, logger, false, true) err := g.Create(ContractTemplate{Name: "TestContract", Account: ""}) assert.NoError(t, err, "Failed to generate contract") @@ -118,7 +110,7 @@ func TestGenerateNewContractFileAlreadyExists(t *testing.T) { assert.NotNil(t, content) // Test file already exists scenario - generatorTwo := NewGenerator(getTemplateFS(), "", state, logger, false, true) + generatorTwo := NewGenerator("", state, logger, false, true) err = generatorTwo.Create(ContractTemplate{Name: "TestContract", Account: ""}) assert.Error(t, err) expectedError := fmt.Sprintf("file already exists: %s", filepath.FromSlash("cadence/contracts/TestContract.cdc")) @@ -129,7 +121,7 @@ func TestGenerateNewContractWithFileExtension(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + g := NewGenerator("", state, logger, false, true) err := g.Create(ContractTemplate{Name: "TestContract.cdc", Account: ""}) assert.NoError(t, err, "Failed to generate contract") @@ -143,7 +135,7 @@ func TestGenerateNewScript(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + g := NewGenerator("", state, logger, false, true) err := g.Create(ScriptTemplate{Name: "TestScript"}) assert.NoError(t, err, "Failed to generate contract") @@ -162,7 +154,7 @@ func TestGenerateNewTransaction(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - g := NewGenerator(getTemplateFS(), "", state, logger, false, true) + g := NewGenerator("", state, logger, false, true) err := g.Create(TransactionTemplate{Name: "TestTransaction"}) assert.NoError(t, err, "Failed to generate contract") @@ -182,7 +174,7 @@ func TestGenerateNewWithDirFlag(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) - g := NewGenerator(getTemplateFS(), "customDir", state, logger, false, true) + g := NewGenerator("customDir", state, logger, false, true) err := g.Create(ContractTemplate{Name: "TestContract", Account: ""}) assert.NoError(t, err, "Failed to generate contract") @@ -206,7 +198,7 @@ func TestGenerateTestTemplate(t *testing.T) { err := tmplFs.WriteFile("file.tmpl", []byte("{{.content}}"), 0644) assert.NoError(t, err, "Failed to create template file") - g := NewGenerator(&tmplFs, "", state, logger, false, true) + g := NewGenerator("", state, logger, false, true) err = g.Create(TestTemplate{ Name: "FooBar_test", TemplatePath: "file.tmpl", @@ -233,7 +225,7 @@ func TestGenerateFileTemplate(t *testing.T) { err := tmplFs.WriteFile("file.tmpl", []byte("{{.content}}"), 0644) assert.NoError(t, err, "Failed to create template file") - g := NewGenerator(&tmplFs, "", state, logger, false, true) + g := NewGenerator("", state, logger, false, true) err = g.Create(FileTemplate{ TargetPath: "TestFile", TemplatePath: "file.tmpl", diff --git a/internal/super/templates/README.md b/internal/super/generator/templates/README.md similarity index 100% rename from internal/super/templates/README.md rename to internal/super/generator/templates/README.md diff --git a/internal/super/templates/contract_counter.cdc.tmpl b/internal/super/generator/templates/contract_counter.cdc.tmpl similarity index 100% rename from internal/super/templates/contract_counter.cdc.tmpl rename to internal/super/generator/templates/contract_counter.cdc.tmpl diff --git a/internal/super/templates/contract_init.cdc.tmpl b/internal/super/generator/templates/contract_init.cdc.tmpl similarity index 100% rename from internal/super/templates/contract_init.cdc.tmpl rename to internal/super/generator/templates/contract_init.cdc.tmpl diff --git a/internal/super/templates/contract_init_test.cdc.tmpl b/internal/super/generator/templates/contract_init_test.cdc.tmpl similarity index 100% rename from internal/super/templates/contract_init_test.cdc.tmpl rename to internal/super/generator/templates/contract_init_test.cdc.tmpl diff --git a/internal/super/templates/script_counter.cdc.tmpl b/internal/super/generator/templates/script_counter.cdc.tmpl similarity index 100% rename from internal/super/templates/script_counter.cdc.tmpl rename to internal/super/generator/templates/script_counter.cdc.tmpl diff --git a/internal/super/templates/script_init.cdc.tmpl b/internal/super/generator/templates/script_init.cdc.tmpl similarity index 100% rename from internal/super/templates/script_init.cdc.tmpl rename to internal/super/generator/templates/script_init.cdc.tmpl diff --git a/internal/super/templates/transaction_counter.cdc.tmpl b/internal/super/generator/templates/transaction_counter.cdc.tmpl similarity index 100% rename from internal/super/templates/transaction_counter.cdc.tmpl rename to internal/super/generator/templates/transaction_counter.cdc.tmpl diff --git a/internal/super/templates/transaction_init.cdc.tmpl b/internal/super/generator/templates/transaction_init.cdc.tmpl similarity index 100% rename from internal/super/templates/transaction_init.cdc.tmpl rename to internal/super/generator/templates/transaction_init.cdc.tmpl diff --git a/internal/super/setup.go b/internal/super/setup.go index 8cfc6a153..904661479 100644 --- a/internal/super/setup.go +++ b/internal/super/setup.go @@ -240,7 +240,7 @@ func startInteractiveSetup( }, } - g := generator.NewGenerator(getTemplateFs(), tempDir, state, logger, true, false) + g := generator.NewGenerator(tempDir, state, logger, true, false) err = g.Create(templates...) if err != nil { return "", err From cf002ba9a973e715cd3fd22519c24cb1892c626c Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 24 Sep 2024 15:53:27 -0700 Subject: [PATCH 04/20] stash --- foo/foobar/.gitignore | 4 +++ foo/foobar/cadence/contracts/Counter.cdc | 31 +++++++++++++++++++ foo/foobar/cadence/scripts/GetCounter.cdc | 6 ++++ foo/foobar/cadence/tests/Counter_test.cdc | 13 ++++++++ .../cadence/transactions/IncrementCounter.cdc | 16 ++++++++++ .../templates/transaction_counter.cdc.tmpl | 4 +-- 6 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 foo/foobar/.gitignore create mode 100644 foo/foobar/cadence/contracts/Counter.cdc create mode 100644 foo/foobar/cadence/scripts/GetCounter.cdc create mode 100644 foo/foobar/cadence/tests/Counter_test.cdc create mode 100644 foo/foobar/cadence/transactions/IncrementCounter.cdc diff --git a/foo/foobar/.gitignore b/foo/foobar/.gitignore new file mode 100644 index 000000000..763a4cc20 --- /dev/null +++ b/foo/foobar/.gitignore @@ -0,0 +1,4 @@ + +# flow +emulator-account.pkey +imports diff --git a/foo/foobar/cadence/contracts/Counter.cdc b/foo/foobar/cadence/contracts/Counter.cdc new file mode 100644 index 000000000..98309a807 --- /dev/null +++ b/foo/foobar/cadence/contracts/Counter.cdc @@ -0,0 +1,31 @@ +access(all) contract Counter { + + access(all) var count: Int + + // Event to be emitted when the counter is incremented + access(all) event CounterIncremented(newCount: Int) + + // Event to be emitted when the counter is decremented + access(all) event CounterDecremented(newCount: Int) + + init() { + self.count = 0 + } + + // Public function to increment the counter + access(all) fun increment() { + self.count = self.count + 1 + emit CounterIncremented(newCount: self.count) + } + + // Public function to decrement the counter + access(all) fun decrement() { + self.count = self.count - 1 + emit CounterDecremented(newCount: self.count) + } + + // Public function to get the current count + view access(all) fun getCount(): Int { + return self.count + } +} \ No newline at end of file diff --git a/foo/foobar/cadence/scripts/GetCounter.cdc b/foo/foobar/cadence/scripts/GetCounter.cdc new file mode 100644 index 000000000..8d965ac1d --- /dev/null +++ b/foo/foobar/cadence/scripts/GetCounter.cdc @@ -0,0 +1,6 @@ +import "Counter" + +access(all) +fun main(): String { + return Counter.greeting +} \ No newline at end of file diff --git a/foo/foobar/cadence/tests/Counter_test.cdc b/foo/foobar/cadence/tests/Counter_test.cdc new file mode 100644 index 000000000..060cddeb6 --- /dev/null +++ b/foo/foobar/cadence/tests/Counter_test.cdc @@ -0,0 +1,13 @@ +import Test + +access(all) let account = Test.createAccount() + +access(all) fun testContract() { + let err = Test.deployContract( + name: "Counter", + path: "../contracts/Counter.cdc", + arguments: [], + ) + + Test.expect(err, Test.beNil()) +} \ No newline at end of file diff --git a/foo/foobar/cadence/transactions/IncrementCounter.cdc b/foo/foobar/cadence/transactions/IncrementCounter.cdc new file mode 100644 index 000000000..4504bf253 --- /dev/null +++ b/foo/foobar/cadence/transactions/IncrementCounter.cdc @@ -0,0 +1,16 @@ +import "Counter" + +transaction { + prepare(signer: auth(BorrowValue) &Account) { + // Borrow a reference to the contract's public capability + let counterRef = signer.storage.borrow<&Counter>(from: /storage/counter) + ?? panic("Could not borrow reference to the counter") + + // Call the increment function on the Counter contract + counterRef.increment() + } + + execute { + log("Counter incremented successfully") + } +} \ No newline at end of file diff --git a/internal/super/generator/templates/transaction_counter.cdc.tmpl b/internal/super/generator/templates/transaction_counter.cdc.tmpl index ee2e10a46..b120a843c 100644 --- a/internal/super/generator/templates/transaction_counter.cdc.tmpl +++ b/internal/super/generator/templates/transaction_counter.cdc.tmpl @@ -1,8 +1,8 @@ import "{{ .ContractName }}" transaction { - prepare(signer: auth(Account) &Account) { - // Borrow a reference to the {{ .Name }} contract's public capability + prepare(signer: auth(BorrowValue) &Account) { + // Borrow a reference to the {{ .ContractName }} contract's public capability let counterRef = signer.borrow<&{{ .ContractName }}>(from: /storage/counter) ?? panic("Could not borrow reference to the counter") From 3b69fbf92acba394e445360766f216113a66c223 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 24 Sep 2024 16:39:17 -0700 Subject: [PATCH 05/20] cleanup --- cadence/contracts/Foobar.cdc | 4 --- cadence/scripts/Baz.cdc | 4 --- cadence/tests/Foobar_test.cdc | 13 -------- foo.cdc | 3 -- foo/foobar/.gitignore | 4 --- foo/foobar/cadence/contracts/Counter.cdc | 31 ------------------- foo/foobar/cadence/scripts/GetCounter.cdc | 6 ---- foo/foobar/cadence/tests/Counter_test.cdc | 13 -------- .../cadence/transactions/IncrementCounter.cdc | 16 ---------- internal/super/generate.go | 5 ++- internal/super/generator/generator.go | 2 +- .../templates/{README.md => README.md.tmpl} | 0 .../templates/contract_init_test.cdc.tmpl | 4 +-- internal/super/generator/test_template.go | 2 +- internal/super/setup.go | 9 ++++-- 15 files changed, 14 insertions(+), 102 deletions(-) delete mode 100644 cadence/contracts/Foobar.cdc delete mode 100644 cadence/scripts/Baz.cdc delete mode 100644 cadence/tests/Foobar_test.cdc delete mode 100644 foo.cdc delete mode 100644 foo/foobar/.gitignore delete mode 100644 foo/foobar/cadence/contracts/Counter.cdc delete mode 100644 foo/foobar/cadence/scripts/GetCounter.cdc delete mode 100644 foo/foobar/cadence/tests/Counter_test.cdc delete mode 100644 foo/foobar/cadence/transactions/IncrementCounter.cdc rename internal/super/generator/templates/{README.md => README.md.tmpl} (100%) diff --git a/cadence/contracts/Foobar.cdc b/cadence/contracts/Foobar.cdc deleted file mode 100644 index cef88c8ef..000000000 --- a/cadence/contracts/Foobar.cdc +++ /dev/null @@ -1,4 +0,0 @@ -access(all) -contract Foobar { - init() {} -} \ No newline at end of file diff --git a/cadence/scripts/Baz.cdc b/cadence/scripts/Baz.cdc deleted file mode 100644 index 191f77c5d..000000000 --- a/cadence/scripts/Baz.cdc +++ /dev/null @@ -1,4 +0,0 @@ -access(all) -fun main() { - // Script details here -} \ No newline at end of file diff --git a/cadence/tests/Foobar_test.cdc b/cadence/tests/Foobar_test.cdc deleted file mode 100644 index bee7499af..000000000 --- a/cadence/tests/Foobar_test.cdc +++ /dev/null @@ -1,13 +0,0 @@ -import Test - -access(all) let account = Test.createAccount() - -access(all) fun testContract() { - let err = Test.deployContract( - name: "Foobar", - path: "../contracts/Foobar.cdc", - arguments: [], - ) - - Test.expect(err, Test.beNil()) -} \ No newline at end of file diff --git a/foo.cdc b/foo.cdc deleted file mode 100644 index d0b279e78..000000000 --- a/foo.cdc +++ /dev/null @@ -1,3 +0,0 @@ -access(all) fun main() { - -} \ No newline at end of file diff --git a/foo/foobar/.gitignore b/foo/foobar/.gitignore deleted file mode 100644 index 763a4cc20..000000000 --- a/foo/foobar/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ - -# flow -emulator-account.pkey -imports diff --git a/foo/foobar/cadence/contracts/Counter.cdc b/foo/foobar/cadence/contracts/Counter.cdc deleted file mode 100644 index 98309a807..000000000 --- a/foo/foobar/cadence/contracts/Counter.cdc +++ /dev/null @@ -1,31 +0,0 @@ -access(all) contract Counter { - - access(all) var count: Int - - // Event to be emitted when the counter is incremented - access(all) event CounterIncremented(newCount: Int) - - // Event to be emitted when the counter is decremented - access(all) event CounterDecremented(newCount: Int) - - init() { - self.count = 0 - } - - // Public function to increment the counter - access(all) fun increment() { - self.count = self.count + 1 - emit CounterIncremented(newCount: self.count) - } - - // Public function to decrement the counter - access(all) fun decrement() { - self.count = self.count - 1 - emit CounterDecremented(newCount: self.count) - } - - // Public function to get the current count - view access(all) fun getCount(): Int { - return self.count - } -} \ No newline at end of file diff --git a/foo/foobar/cadence/scripts/GetCounter.cdc b/foo/foobar/cadence/scripts/GetCounter.cdc deleted file mode 100644 index 8d965ac1d..000000000 --- a/foo/foobar/cadence/scripts/GetCounter.cdc +++ /dev/null @@ -1,6 +0,0 @@ -import "Counter" - -access(all) -fun main(): String { - return Counter.greeting -} \ No newline at end of file diff --git a/foo/foobar/cadence/tests/Counter_test.cdc b/foo/foobar/cadence/tests/Counter_test.cdc deleted file mode 100644 index 060cddeb6..000000000 --- a/foo/foobar/cadence/tests/Counter_test.cdc +++ /dev/null @@ -1,13 +0,0 @@ -import Test - -access(all) let account = Test.createAccount() - -access(all) fun testContract() { - let err = Test.deployContract( - name: "Counter", - path: "../contracts/Counter.cdc", - arguments: [], - ) - - Test.expect(err, Test.beNil()) -} \ No newline at end of file diff --git a/foo/foobar/cadence/transactions/IncrementCounter.cdc b/foo/foobar/cadence/transactions/IncrementCounter.cdc deleted file mode 100644 index 4504bf253..000000000 --- a/foo/foobar/cadence/transactions/IncrementCounter.cdc +++ /dev/null @@ -1,16 +0,0 @@ -import "Counter" - -transaction { - prepare(signer: auth(BorrowValue) &Account) { - // Borrow a reference to the contract's public capability - let counterRef = signer.storage.borrow<&Counter>(from: /storage/counter) - ?? panic("Could not borrow reference to the counter") - - // Call the increment function on the Counter contract - counterRef.increment() - } - - execute { - log("Counter incremented successfully") - } -} \ No newline at end of file diff --git a/internal/super/generate.go b/internal/super/generate.go index 6b1ec27ec..82d2b473e 100644 --- a/internal/super/generate.go +++ b/internal/super/generate.go @@ -100,7 +100,10 @@ func generateContract( ) (result command.Result, err error) { g := generator.NewGenerator("", state, logger, false, true) name := util.StripCDCExtension(args[0]) - err = g.Create(generator.ContractTemplate{Name: name}) + err = g.Create( + generator.ContractTemplate{Name: name}, + generator.TestTemplate{Name: name}, + ) return nil, err } diff --git a/internal/super/generator/generator.go b/internal/super/generator/generator.go index 901b29650..9d71367d2 100644 --- a/internal/super/generator/generator.go +++ b/internal/super/generator/generator.go @@ -140,7 +140,7 @@ func (g *GeneratorImpl) generate(item TemplateItem) error { // processTemplate reads a template file from the embedded filesystem and processes it with the provided data // If you don't need to provide data, pass nil func (g *GeneratorImpl) processTemplate(templatePath string, data map[string]interface{}) (string, error) { - templateData, err := templatesFS.ReadFile(templatePath) + templateData, err := templatesFS.ReadFile(filepath.Join("templates", templatePath)) if err != nil { return "", fmt.Errorf("failed to read template file: %w", err) } diff --git a/internal/super/generator/templates/README.md b/internal/super/generator/templates/README.md.tmpl similarity index 100% rename from internal/super/generator/templates/README.md rename to internal/super/generator/templates/README.md.tmpl diff --git a/internal/super/generator/templates/contract_init_test.cdc.tmpl b/internal/super/generator/templates/contract_init_test.cdc.tmpl index dc8cc25fb..89a8985d5 100644 --- a/internal/super/generator/templates/contract_init_test.cdc.tmpl +++ b/internal/super/generator/templates/contract_init_test.cdc.tmpl @@ -4,8 +4,8 @@ access(all) let account = Test.createAccount() access(all) fun testContract() { let err = Test.deployContract( - name: "{{ .Name }}", - path: "../contracts/{{ .Name }}.cdc", + name: "{{ .ContractName }}", + path: "../contracts/{{ .ContractName }}.cdc", arguments: [], ) diff --git a/internal/super/generator/test_template.go b/internal/super/generator/test_template.go index f0207e187..a3e32a5c3 100644 --- a/internal/super/generator/test_template.go +++ b/internal/super/generator/test_template.go @@ -23,7 +23,7 @@ func (o TestTemplate) GetName() string { // GetTemplate returns an empty string for scripts and transactions func (o TestTemplate) GetTemplatePath() string { if o.TemplatePath == "" { - return "test_init" + return "contract_init_test.cdc.tmpl" } return o.TemplatePath diff --git a/internal/super/setup.go b/internal/super/setup.go index 904661479..44283f7f0 100644 --- a/internal/super/setup.go +++ b/internal/super/setup.go @@ -219,7 +219,6 @@ func startInteractiveSetup( generator.ContractTemplate{ Name: "Counter", TemplatePath: "contract_counter.cdc.tmpl", - Account: "", }, generator.ScriptTemplate{ Name: "GetCounter", @@ -231,13 +230,17 @@ func startInteractiveSetup( TemplatePath: "transaction_counter.cdc.tmpl", Data: map[string]interface{}{"ContractName": "Counter"}, }, - generator.FileTemplate{ + generator.TestTemplate{ + Name: "Counter_test", + Data: map[string]interface{}{"ContractName": "Counter"}, + }, + /*generator.FileTemplate{ TemplatePath: "README.md.tmpl", TargetPath: "README.md", Data: map[string]interface{}{ "ProjectName": filepath.Base(targetDir), }, - }, + },*/ } g := generator.NewGenerator(tempDir, state, logger, true, false) From 1d8c5b6480b4ed7dc022f375f929ab044f65756a Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 24 Sep 2024 16:43:47 -0700 Subject: [PATCH 06/20] fix generate --- internal/super/generate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/super/generate.go b/internal/super/generate.go index 82d2b473e..00f074fc8 100644 --- a/internal/super/generate.go +++ b/internal/super/generate.go @@ -102,7 +102,7 @@ func generateContract( name := util.StripCDCExtension(args[0]) err = g.Create( generator.ContractTemplate{Name: name}, - generator.TestTemplate{Name: name}, + generator.TestTemplate{Name: name + "_test", Data: map[string]interface{}{"ContractName": "Counter"}}, ) return nil, err } From a37be85dd336ab91622c923996790866f1240d01 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 24 Sep 2024 16:45:50 -0700 Subject: [PATCH 07/20] fixup --- internal/super/generate.go | 13 +++++++++---- internal/super/generator/contract_template.go | 8 ++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/internal/super/generate.go b/internal/super/generate.go index 00f074fc8..24cd0e2d3 100644 --- a/internal/super/generate.go +++ b/internal/super/generate.go @@ -100,10 +100,15 @@ func generateContract( ) (result command.Result, err error) { g := generator.NewGenerator("", state, logger, false, true) name := util.StripCDCExtension(args[0]) - err = g.Create( - generator.ContractTemplate{Name: name}, - generator.TestTemplate{Name: name + "_test", Data: map[string]interface{}{"ContractName": "Counter"}}, - ) + + templates := []generator.TemplateItem{ + generator.ContractTemplate{Name: name, SkipTests: generateFlags.SkipTests, SaveState: true}, + } + if !generateFlags.SkipTests { + templates = append(templates, generator.TestTemplate{Name: name + "_test", Data: map[string]interface{}{"ContractName": "Counter"}}) + } + + err = g.Create() return nil, err } diff --git a/internal/super/generator/contract_template.go b/internal/super/generator/contract_template.go index 3c319192d..783e9952a 100644 --- a/internal/super/generator/contract_template.go +++ b/internal/super/generator/contract_template.go @@ -16,8 +16,8 @@ type ContractTemplate struct { Account string TemplatePath string Data map[string]interface{} - skipTests bool - saveState bool + SkipTests bool + SaveState bool } var _ TemplateItem = ContractTemplate{} @@ -50,7 +50,7 @@ func (c ContractTemplate) GetTargetPath() string { func (c ContractTemplate) UpdateState(state *flowkit.State) error { var aliases config.Aliases - if c.skipTests != true { + if c.SkipTests != true { aliases = config.Aliases{{ Network: config.TestingNetwork.Name, Address: flowsdk.HexToAddress("0x0000000000000007"), @@ -65,7 +65,7 @@ func (c ContractTemplate) UpdateState(state *flowkit.State) error { state.Contracts().AddOrUpdate(contract) - if c.saveState { + if c.SaveState { err := state.SaveDefault() // TODO: Support adding a target project directory if err != nil { return fmt.Errorf("error saving to flow.json: %w", err) From e68033533c3906dbacd14950a8fd391c74b7d4e1 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Sat, 5 Oct 2024 13:01:14 -0700 Subject: [PATCH 08/20] fix tests --- internal/super/generator/file_template.go | 6 +++++- internal/super/setup.go | 4 ---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/super/generator/file_template.go b/internal/super/generator/file_template.go index 5fdf8716a..8a9969973 100644 --- a/internal/super/generator/file_template.go +++ b/internal/super/generator/file_template.go @@ -25,7 +25,11 @@ func NewFileTemplate( var _ TemplateItem = FileTemplate{} -// GetTemplate returns the template of the contract +// GetType returns the type of the contract +func (c FileTemplate) GetType() string { + return "file" +} + func (c FileTemplate) GetTemplatePath() string { return c.TemplatePath } diff --git a/internal/super/setup.go b/internal/super/setup.go index 2fc439d48..d12985336 100644 --- a/internal/super/setup.go +++ b/internal/super/setup.go @@ -25,10 +25,6 @@ import ( "os" "path/filepath" - "github.com/onflow/flow-cli/internal/dependencymanager" - "github.com/onflow/flow-cli/internal/super/generator" - "github.com/onflow/flow-cli/internal/util" - "github.com/spf13/afero" "github.com/onflow/flow-cli/internal/prompt" From 81c08306637d81228655253e299272fa47f9d875 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Sat, 5 Oct 2024 18:50:09 -0700 Subject: [PATCH 09/20] update README --- .../super/generator/templates/README.md.tmpl | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/internal/super/generator/templates/README.md.tmpl b/internal/super/generator/templates/README.md.tmpl index a51c44b2b..9d81f2f6c 100644 --- a/internal/super/generator/templates/README.md.tmpl +++ b/internal/super/generator/templates/README.md.tmpl @@ -3,10 +3,12 @@ Welcome to your new {{ .ProjectType }} project. This project is a starting point ## ๐Ÿ”จ Getting started Getting started can feel overwhelming, but we are here for you. Depending on how accustomed you are to Flow here's a list of resources you might find useful: -- **[Cadence documentation](https://developers.flow.com/cadence/language)**: here you will find language reference for Cadence, which will be the language in which you develop your smart contracts, -- **[Visual Studio Code](https://code.visualstudio.com/?wt.mc_id=DX_841432)** and **[Cadence extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)**: we suggest using Visual Studio Code IDE for writing Cadence with the Cadence extension installed, that will give you nice syntax highlitning and additional smart features, -- **[SDKs](https://developers.flow.com/tools#sdks)**: here you will find a list of SDKs you can use to ease the interaction with Flow network (sending transactions, fetching accounts etc), -- **[Tools](https://developers.flow.com/tools#development-tools)**: development tools you can use to make your development easier, [Flowser](https://docs.flowser.dev/) can be super handy to see what's going on the blockchain while you develop +- **[Cadence documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for Flow blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. +- **[Visual Studio Code](https://code.visualstudio.com/?wt.mc_id=DX_841432)** and **[Cadence extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. +- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow documentation is a great resource for learning about the Flow blockchain and its features. +- **[Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the blockchain. +- **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore the Flow blockchain. You can use them to view transactions, accounts, and other data on the blockchain. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. + {{ if .IsNFTProject }} NFT Resources: @@ -21,7 +23,7 @@ Fungible Token Resources: ## ๐Ÿ“ฆ Project Structure -Your project comes with some standard folders which have a special purpose: +Your project has been set up with the following structure: - `flow.json` configuration file for your project, you can think of it as package.json. It has been initialized with a basic configuration{{ if len .Dependecies }} and some Core Contract dependencies{{ end }}. - `/cadence` inside here is where your Cadence smart contracts code lives @@ -51,7 +53,7 @@ Inside `cadence` folder you will find: ## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing ### Creating a new contract -To add a new contract to your project you can use the following command: +To add a new contract to your project, run the following command: ```shell > flow generate contract @@ -61,7 +63,7 @@ This command will create a new contract file and add it to the `flow.json` confi ### Creating a new script -To add a new script to your project you can use the following command: +To add a new script to your project, run the following command: ```shell > flow generate script @@ -92,6 +94,7 @@ If you want to use external contract dependencies (like NonFungibleToken, FlowTo Use [ContractBrowser](https://contractbrowser.com/) to explore available 3rd party contracts in the Flow ecosystem. ## ๐Ÿงช Testing + To verify that your project is working as expected you can run the tests using the following command: ```shell > flow test From 51eb26518291075d31b7c60bcdc857f314e4b8e0 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Sat, 5 Oct 2024 20:57:33 -0700 Subject: [PATCH 10/20] improvements --- .../super/generator/templates/README.md.tmpl | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/internal/super/generator/templates/README.md.tmpl b/internal/super/generator/templates/README.md.tmpl index 9d81f2f6c..be44d3861 100644 --- a/internal/super/generator/templates/README.md.tmpl +++ b/internal/super/generator/templates/README.md.tmpl @@ -1,30 +1,20 @@ ## ๐Ÿ‘‹ Welcome Flow Developer! -Welcome to your new {{ .ProjectType }} project. This project is a starting point for you to develop smart contracts on the Flow blockchain. It comes with a few example contracts and scripts to help you get started. +Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow blockchain. It comes with a few example contracts and scripts to help you get started. ## ๐Ÿ”จ Getting started -Getting started can feel overwhelming, but we are here for you. Depending on how accustomed you are to Flow here's a list of resources you might find useful: -- **[Cadence documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for Flow blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. + +Here are some essential resources to help you hit the ground running: + +- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for Flow blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. - **[Visual Studio Code](https://code.visualstudio.com/?wt.mc_id=DX_841432)** and **[Cadence extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. - **[Flow Documentation](https://docs.onflow.org/)** - The official Flow documentation is a great resource for learning about the Flow blockchain and its features. - **[Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the blockchain. - **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore the Flow blockchain. You can use them to view transactions, accounts, and other data on the blockchain. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. -{{ if .IsNFTProject }} - -NFT Resources: -- **[flow-nft](https://github.com/onflow/flow-nft)**: home of the Flow NFT standards, contains utility contracts, examples, and documentation -- **[nft-storefront](https://github.com/onflow/nft-storefront/)**: NFT Storefront is an open marketplace contract used by most Flow NFT marketplaces -{{ end }} -{{ if .IsFungibleProject }} - -Fungible Token Resources: -- **[flow-ft](https://github.com/onflow/flow-ft)**: home of the Flow Fungible Token standards, contains utility contracts, examples, and documentation -{{ end }} - - ## ๐Ÿ“ฆ Project Structure Your project has been set up with the following structure: -- `flow.json` configuration file for your project, you can think of it as package.json. It has been initialized with a basic configuration{{ if len .Dependecies }} and some Core Contract dependencies{{ end }}. + +- `flow.json` configuration file for your project, analagous to a `package.json` file for NPM. It has been initialized with a basic configuration{{ if len .Dependecies }} and some Core Contract dependencies{{ end }}. - `/cadence` inside here is where your Cadence smart contracts code lives Your project is set up with the following dependencies: @@ -136,5 +126,4 @@ This command will deploy your project to the Flow Mainnet. You can then interact ## Further Reading - Cadence Language Reference https://cadence-lang.org/docs/language -- Flow Smart Contract Project Development Standards https://cadence-lang.org/docs/project-development-tips -- Cadence anti-patterns https://cadence-lang.org/docs/anti-patterns \ No newline at end of file +- Flow Smart Contract Project Development Standards https://cadence-lang.org/docs/project-development-tips \ No newline at end of file From 6ca33546a38606f99d6afef5b004670dca44053f Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Sat, 5 Oct 2024 22:30:20 -0700 Subject: [PATCH 11/20] fix test --- internal/super/generator/file_template.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/internal/super/generator/file_template.go b/internal/super/generator/file_template.go index 8a9969973..a6f5f03ad 100644 --- a/internal/super/generator/file_template.go +++ b/internal/super/generator/file_template.go @@ -1,3 +1,21 @@ +/* + * Flow CLI + * + * Copyright Flow Foundation + * + * 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 generator import ( From 5bc7a56ae5ca1d8e5e7be91380a46f717a3e9e0a Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Mon, 7 Oct 2024 21:39:31 -0700 Subject: [PATCH 12/20] fixup (no deps vsn is what you want) --- .../generator/fixtures/README_no_deps copy.md | 129 +++++++++++++ .../generator/fixtures/README_no_deps.md | 178 ++++++++++++++++++ internal/super/generator/mocks/generator.go | 51 ----- .../super/generator/templates/README.md.tmpl | 4 +- 4 files changed, 309 insertions(+), 53 deletions(-) create mode 100644 internal/super/generator/fixtures/README_no_deps copy.md create mode 100644 internal/super/generator/fixtures/README_no_deps.md delete mode 100644 internal/super/generator/mocks/generator.go diff --git a/internal/super/generator/fixtures/README_no_deps copy.md b/internal/super/generator/fixtures/README_no_deps copy.md new file mode 100644 index 000000000..be44d3861 --- /dev/null +++ b/internal/super/generator/fixtures/README_no_deps copy.md @@ -0,0 +1,129 @@ +## ๐Ÿ‘‹ Welcome Flow Developer! +Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow blockchain. It comes with a few example contracts and scripts to help you get started. + +## ๐Ÿ”จ Getting started + +Here are some essential resources to help you hit the ground running: + +- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for Flow blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. +- **[Visual Studio Code](https://code.visualstudio.com/?wt.mc_id=DX_841432)** and **[Cadence extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. +- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow documentation is a great resource for learning about the Flow blockchain and its features. +- **[Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the blockchain. +- **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore the Flow blockchain. You can use them to view transactions, accounts, and other data on the blockchain. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. + +## ๐Ÿ“ฆ Project Structure +Your project has been set up with the following structure: + +- `flow.json` configuration file for your project, analagous to a `package.json` file for NPM. It has been initialized with a basic configuration{{ if len .Dependecies }} and some Core Contract dependencies{{ end }}. +- `/cadence` inside here is where your Cadence smart contracts code lives + +Your project is set up with the following dependencies: +{{ range .Dependecies }} + - `{{ .Name }}` +{{ end }} + +Inside `cadence` folder you will find: +- `/contracts` location for Cadence contracts go in this folder +{{ range .Contracts }} + - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` contract +{{ end }} +- `/scripts` location for Cadence scripts goes here +{{ range .Scripts }} + - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` script +{{ end }} +- `/transactions` location for Cadence transactions goes in this folder +{{ range .Transactions }} + - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` transaction +{{ end }} +- `/tests` location for Cadence tests goes in this folder +{{ range .Tests }} + - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` test +{{ end }} + +## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing + +### Creating a new contract +To add a new contract to your project, run the following command: + +```shell +> flow generate contract +``` + +This command will create a new contract file and add it to the `flow.json` configuration file. + +### Creating a new script + +To add a new script to your project, run the following command: + +```shell +> flow generate script +``` + +This command will create a new script file and add it to the `flow.json` configuration file. + +You can import any of your own contracts or installed dependencies in your script file using the `import` keyword. For example: + +```cadence +import Counter from "Counter" +``` + +### Creating a new transaction + +To add a new transaction to your project you can use the following command: + +```shell +> flow generate transaction +``` + +This command will create a new transaction file and add it to the `flow.json` configuration file. You can import any dependencies as you would in a script file. + +### Installing external dependencies + +If you want to use external contract dependencies (like NonFungibleToken, FlowToken, FungibleToken,..) you can install them using Cadence dependency manager: https://developers.flow.com/tools/flow-cli/dependency-manager + +Use [ContractBrowser](https://contractbrowser.com/) to explore available 3rd party contracts in the Flow ecosystem. + +## ๐Ÿงช Testing + +To verify that your project is working as expected you can run the tests using the following command: +```shell +> flow test +``` + +This command will run all the tests in the `cadence/tests` folder. You can add more tests to this folder as you develop your project. + +To learn more about testing in Cadence, check out the [Cadence testing documentation](https://cadence-lang.org/docs/testing-framework). + +## ๐Ÿš€ Deploying + +### Deploying to the Flow Emulator + +To deploy your project to the Flow Emulator you can use the following command: +```shell +> flow emulator --start +``` + +This command will start the Flow Emulator and deploy your project to it. You can then interact with your project using the Flow Emulator. + +### Deploying to the Flow Testnet + +To deploy your project to the Flow Testnet you can use the following command: +```shell +> flow project deploy --network=testnet +``` + +This command will deploy your project to the Flow Testnet. You can then interact with your project using the Flow Testnet. + +### Deploying to the Flow Mainnet + +To deploy your project to the Flow Mainnet you can use the following command: +```shell +> flow project deploy --network=mainnet +``` + +This command will deploy your project to the Flow Mainnet. You can then interact with your project using the Flow Mainnet. + +## Further Reading + +- Cadence Language Reference https://cadence-lang.org/docs/language +- Flow Smart Contract Project Development Standards https://cadence-lang.org/docs/project-development-tips \ No newline at end of file diff --git a/internal/super/generator/fixtures/README_no_deps.md b/internal/super/generator/fixtures/README_no_deps.md new file mode 100644 index 000000000..6e5b8f162 --- /dev/null +++ b/internal/super/generator/fixtures/README_no_deps.md @@ -0,0 +1,178 @@ +## ๐Ÿ‘‹ Welcome Flow Developer! + +Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow Blockchain. It comes with example contracts, scripts, transactions, and tests to help you get started. + +## ๐Ÿ”จ Getting started + +Here are some essential resources to help you hit the ground running: + +- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow Documentation is a great starting point to begin learn about [building](https://developers.flow.com/build/flow) on Flow. +- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. +- **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. +- **[Flow Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow Blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the network. +- **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore on-chain data. You can use them to view transactions, accounts, events, and other information. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. + +## ๐Ÿ“ฆ Project Structure +Your project has been set up with the following structure: + +- `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration{{ if len .Dependencies }} and your selected Core Contract dependencies{{ end }} to get started. + +{{ if len .Dependencies }} + Your project has also been configured with the following dependencies. You can add more dependencies using the `flow deps add` command: + {{ range .Dependencies }} + - `{{ .Name }}` + {{ end }} +{{ end }} + +- `/cadence` - This is where your Cadence smart contracts code lives + +Inside `cadence` folder you will find: +- `/contracts` - This folder contains your Cadence contracts (these are deployed to the network and contain the business logic for your application) +{{ range .Contracts }} + - `{{ .Name }}.cdc` +{{ end }} +- `/scripts` - This folder contains your Cadence scripts (read-only operations) +{{ range .Scripts }} + - `{{ .Name }}.cdc` +{{ end }} +- `/transactions` - This folder contains your Cadence transactions (state-changing operations) +{{ range .Transactions }} + - `{{ .Name }}.cdc` +{{ end }} +- `/tests` - This folder contains your Cadence tests (integration tests for your contracts, scripts, and transactions to verify they behave as expected) +{{ range .Tests }} + - `{{ .Name }}.cdc` +{{ end }} + +## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing + +### Creating a new contract + +To add a new contract to your project, run the following command: + +```shell +flow generate contract +``` + +This command will create a new contract file and add it to the `flow.json` configuration file. + +### Creating a new script + +To add a new script to your project, run the following command: + +```shell +flow generate script +``` + +This command will create a new script file. Scripts are used to read data from the blockchain and do not modify state (i.e. get the current balance of an account, get a user's NFTs, etc). + +You can import any of your own contracts or installed dependencies in your script file using the `import` keyword. For example: + +```cadence +import "Counter" +``` + +### Creating a new transaction + +To add a new transaction to your project you can use the following command: + +```shell +flow generate transaction +``` + +This command will create a new transaction file. Transactions are used to modify the state of the blockchain (i.e purchase an NFT, transfer tokens, etc). + +You can import any dependencies as you would in a script file. + +### Creating a new test + +To add a new test to your project you can use the following command: + +```shell +flow generate test +``` + +This command will create a new test file. Tests are used to verify that your contracts, scripts, and transactions are working as expected. + +### Installing external dependencies + +If you want to use external contract dependencies (such as NonFungibleToken, FlowToken, FungibleToken, etc.) you can install them using [Flow CLI Dependency Manager](https://developers.flow.com/tools/flow-cli/dependency-manager). + +For example, to install the NonFungibleToken contract you can use the following command: + +```shell +flow deps add mainnet://1d7e57aa55817448.NonFungibleToken +``` + +Contracts can be found using [ContractBrowser](https://contractbrowser.com/), but be sure to verify the authenticity before using third-party contracts in your project. + +## ๐Ÿงช Testing + +To verify that your project is working as expected you can run the tests using the following command: + +```shell +flow test +``` + +This command will run all tests with the `_test.cdc` suffix (these can be found in the `cadence/tests` folder). You can add more tests here using the `flow generate test` command (or by creating them manually). + +To learn more about testing in Cadence, check out the [Cadence Test Framework Documentation](https://cadence-lang.org/docs/testing-framework). + +## ๐Ÿš€ Deploying your project + +To deploy your project to the Flow network, you must first have a Flow account and have configured your deployment targets in the `flow.json` configuration file. + +You can create a new Flow account using the following command: + +```shell +flow accounts create +``` + +Learn more about setting up deployment targets in the [Flow CLI documentation](https://developers.flow.com/tools/flow-cli/deployment/project-contracts). + +### Deploying to the Flow Emulator + +To deploy your project to the Flow Emulator, start the emulator using the following command: + +```shell +flow emulator --start +``` + +To deploy your project, run the following command: + +```shell +flow project deploy --network=emulator +``` + +This command will start the Flow Emulator and deploy your project to it. You can now interact with your smart contracts using the Flow CLI or any other Flow client. + +### Deploying to Flow Testnet + +To deploy your project to Flow Testnet you can use the following command: + +```shell +flow project deploy --network=testnet +``` + +This command will deploy your project to Flow Testnet. You can now interact with your project using the Flow Testnet. + +### Deploying to Flow Mainnet + +To deploy your project to Flow Mainnet you can use the following command: + +```shell +flow project deploy --network=mainnet +``` + +This command will deploy your project to Flow Mainnet. You now then interact with your project using the Flow Mainnet. + +## ๐Ÿ“š Other Resources + +- [Cadence Design Patterns](https://cadence-lang.org/docs/design-patterns) +- [Cadence Anti-Patterns](https://cadence-lang.org/docs/anti-patterns) +- [Flow Core Contracts](https://developers.flow.com/build/core-contracts) + +## ๐Ÿค Community +- [Flow Community Forum](https://forum.onflow.org/) +- [Flow Discord](https://discord.gg/flow) +- [Flow Twitter](https://x.com/flow_blockchain) diff --git a/internal/super/generator/mocks/generator.go b/internal/super/generator/mocks/generator.go deleted file mode 100644 index c4e4e4a6e..000000000 --- a/internal/super/generator/mocks/generator.go +++ /dev/null @@ -1,51 +0,0 @@ -// Code generated by mockery v2.40.3. DO NOT EDIT. - -package mocks - -import ( - generator "github.com/onflow/flow-cli/internal/super/generator" - mock "github.com/stretchr/testify/mock" -) - -// Generator is an autogenerated mock type for the Generator type -type Generator struct { - mock.Mock -} - -// Create provides a mock function with given fields: items -func (_m *Generator) Create(items ...generator.TemplateItem) error { - _va := make([]interface{}, len(items)) - for _i := range items { - _va[_i] = items[_i] - } - var _ca []interface{} - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for Create") - } - - var r0 error - if rf, ok := ret.Get(0).(func(...generator.TemplateItem) error); ok { - r0 = rf(items...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// NewGenerator creates a new instance of Generator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewGenerator(t interface { - mock.TestingT - Cleanup(func()) -}) *Generator { - mock := &Generator{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/internal/super/generator/templates/README.md.tmpl b/internal/super/generator/templates/README.md.tmpl index be44d3861..7a73b3e07 100644 --- a/internal/super/generator/templates/README.md.tmpl +++ b/internal/super/generator/templates/README.md.tmpl @@ -14,11 +14,11 @@ Here are some essential resources to help you hit the ground running: ## ๐Ÿ“ฆ Project Structure Your project has been set up with the following structure: -- `flow.json` configuration file for your project, analagous to a `package.json` file for NPM. It has been initialized with a basic configuration{{ if len .Dependecies }} and some Core Contract dependencies{{ end }}. +- `flow.json` configuration file for your project, analagous to a `package.json` file for NPM. It has been initialized with a basic configuration{{ if len .Dependencies }} and some Core Contract dependencies{{ end }}. - `/cadence` inside here is where your Cadence smart contracts code lives Your project is set up with the following dependencies: -{{ range .Dependecies }} +{{ range .Dependencies }} - `{{ .Name }}` {{ end }} From bf5a988e22455b84f623b7044f118dcb4467d58a Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Fri, 18 Oct 2024 12:57:32 -0700 Subject: [PATCH 13/20] update --- .../generator/fixtures/README_no_deps copy.md | 146 +++++++++++------- .../generator/fixtures/README_no_deps.md | 26 +--- internal/super/generator/generator_test.go | 75 +++++++++ .../super/generator/templates/README.md.tmpl | 139 +++++++++++------ 4 files changed, 266 insertions(+), 120 deletions(-) diff --git a/internal/super/generator/fixtures/README_no_deps copy.md b/internal/super/generator/fixtures/README_no_deps copy.md index be44d3861..6a68aab64 100644 --- a/internal/super/generator/fixtures/README_no_deps copy.md +++ b/internal/super/generator/fixtures/README_no_deps copy.md @@ -1,52 +1,46 @@ ## ๐Ÿ‘‹ Welcome Flow Developer! -Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow blockchain. It comes with a few example contracts and scripts to help you get started. + +Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow Blockchain. It comes with example contracts, scripts, transactions, and tests to help you get started. ## ๐Ÿ”จ Getting started Here are some essential resources to help you hit the ground running: -- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for Flow blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. -- **[Visual Studio Code](https://code.visualstudio.com/?wt.mc_id=DX_841432)** and **[Cadence extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. -- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow documentation is a great resource for learning about the Flow blockchain and its features. -- **[Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the blockchain. -- **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore the Flow blockchain. You can use them to view transactions, accounts, and other data on the blockchain. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. +- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow Documentation is a great starting point to begin learn about [building](https://developers.flow.com/build/flow) on Flow. +- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. +- **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. +- **[Flow Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow Blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the network. +- **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore on-chain data. You can use them to view transactions, accounts, events, and other information. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. ## ๐Ÿ“ฆ Project Structure Your project has been set up with the following structure: -- `flow.json` configuration file for your project, analagous to a `package.json` file for NPM. It has been initialized with a basic configuration{{ if len .Dependecies }} and some Core Contract dependencies{{ end }}. -- `/cadence` inside here is where your Cadence smart contracts code lives +- `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration and your selected Core Contract dependencies to get started. + + Your project has also been configured with the following dependencies. You can add more dependencies using the `flow deps add` command: + - `FlowToken` + - `FungibleToken` -Your project is set up with the following dependencies: -{{ range .Dependecies }} - - `{{ .Name }}` -{{ end }} +- `/cadence` - This is where your Cadence smart contracts code lives Inside `cadence` folder you will find: -- `/contracts` location for Cadence contracts go in this folder -{{ range .Contracts }} - - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` contract -{{ end }} -- `/scripts` location for Cadence scripts goes here -{{ range .Scripts }} - - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` script -{{ end }} -- `/transactions` location for Cadence transactions goes in this folder -{{ range .Transactions }} - - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` transaction -{{ end }} -- `/tests` location for Cadence tests goes in this folder -{{ range .Tests }} - - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` test -{{ end }} +- `/contracts` - This folder contains your Cadence contracts (these are deployed to the network and contain the business logic for your application) + - `ExampleContract.cdc` +- `/scripts` - This folder contains your Cadence scripts (read-only operations) + - `ExampleScript.cdc` +- `/transactions` - This folder contains your Cadence transactions (state-changing operations) + - `ExampleTransaction.cdc` +- `/tests` - This folder contains your Cadence tests (integration tests for your contracts, scripts, and transactions to verify they behave as expected) + - `ExampleTest.cdc` ## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing ### Creating a new contract + To add a new contract to your project, run the following command: ```shell -> flow generate contract +flow generate contract ``` This command will create a new contract file and add it to the `flow.json` configuration file. @@ -56,15 +50,15 @@ This command will create a new contract file and add it to the `flow.json` confi To add a new script to your project, run the following command: ```shell -> flow generate script +flow generate script ``` -This command will create a new script file and add it to the `flow.json` configuration file. +This command will create a new script file. Scripts are used to read data from the blockchain and do not modify state (i.e. get the current balance of an account, get a user's NFTs, etc). You can import any of your own contracts or installed dependencies in your script file using the `import` keyword. For example: ```cadence -import Counter from "Counter" +import "Counter" ``` ### Creating a new transaction @@ -72,58 +66,102 @@ import Counter from "Counter" To add a new transaction to your project you can use the following command: ```shell -> flow generate transaction +flow generate transaction ``` -This command will create a new transaction file and add it to the `flow.json` configuration file. You can import any dependencies as you would in a script file. +This command will create a new transaction file. Transactions are used to modify the state of the blockchain (i.e purchase an NFT, transfer tokens, etc). + +You can import any dependencies as you would in a script file. + +### Creating a new test + +To add a new test to your project you can use the following command: + +```shell +flow generate test +``` + +This command will create a new test file. Tests are used to verify that your contracts, scripts, and transactions are working as expected. ### Installing external dependencies -If you want to use external contract dependencies (like NonFungibleToken, FlowToken, FungibleToken,..) you can install them using Cadence dependency manager: https://developers.flow.com/tools/flow-cli/dependency-manager +If you want to use external contract dependencies (such as NonFungibleToken, FlowToken, FungibleToken, etc.) you can install them using [Flow CLI Dependency Manager](https://developers.flow.com/tools/flow-cli/dependency-manager). -Use [ContractBrowser](https://contractbrowser.com/) to explore available 3rd party contracts in the Flow ecosystem. +For example, to install the NonFungibleToken contract you can use the following command: + +```shell +flow deps add mainnet://1d7e57aa55817448.NonFungibleToken +``` + +Contracts can be found using [ContractBrowser](https://contractbrowser.com/), but be sure to verify the authenticity before using third-party contracts in your project. ## ๐Ÿงช Testing To verify that your project is working as expected you can run the tests using the following command: + ```shell -> flow test +flow test ``` -This command will run all the tests in the `cadence/tests` folder. You can add more tests to this folder as you develop your project. +This command will run all tests with the `_test.cdc` suffix (these can be found in the `cadence/tests` folder). You can add more tests here using the `flow generate test` command (or by creating them manually). -To learn more about testing in Cadence, check out the [Cadence testing documentation](https://cadence-lang.org/docs/testing-framework). +To learn more about testing in Cadence, check out the [Cadence Test Framework Documentation](https://cadence-lang.org/docs/testing-framework). -## ๐Ÿš€ Deploying +## ๐Ÿš€ Deploying your project + +To deploy your project to the Flow network, you must first have a Flow account and have configured your deployment targets in the `flow.json` configuration file. + +You can create a new Flow account using the following command: + +```shell +flow accounts create +``` + +Learn more about setting up deployment targets in the [Flow CLI documentation](https://developers.flow.com/tools/flow-cli/deployment/project-contracts). ### Deploying to the Flow Emulator -To deploy your project to the Flow Emulator you can use the following command: +To deploy your project to the Flow Emulator, start the emulator using the following command: + ```shell -> flow emulator --start +flow emulator --start ``` -This command will start the Flow Emulator and deploy your project to it. You can then interact with your project using the Flow Emulator. +To deploy your project, run the following command: -### Deploying to the Flow Testnet +```shell +flow project deploy --network=emulator +``` + +This command will start the Flow Emulator and deploy your project to it. You can now interact with your smart contracts using the Flow CLI or any other Flow client. + +### Deploying to Flow Testnet + +To deploy your project to Flow Testnet you can use the following command: -To deploy your project to the Flow Testnet you can use the following command: ```shell -> flow project deploy --network=testnet +flow project deploy --network=testnet ``` -This command will deploy your project to the Flow Testnet. You can then interact with your project using the Flow Testnet. +This command will deploy your project to Flow Testnet. You can now interact with your project using the Flow Testnet. + +### Deploying to Flow Mainnet -### Deploying to the Flow Mainnet +To deploy your project to Flow Mainnet you can use the following command: -To deploy your project to the Flow Mainnet you can use the following command: ```shell -> flow project deploy --network=mainnet +flow project deploy --network=mainnet ``` -This command will deploy your project to the Flow Mainnet. You can then interact with your project using the Flow Mainnet. +This command will deploy your project to Flow Mainnet. You now then interact with your project using the Flow Mainnet. + +## ๐Ÿ“š Other Resources -## Further Reading +- [Cadence Design Patterns](https://cadence-lang.org/docs/design-patterns) +- [Cadence Anti-Patterns](https://cadence-lang.org/docs/anti-patterns) +- [Flow Core Contracts](https://developers.flow.com/build/core-contracts) -- Cadence Language Reference https://cadence-lang.org/docs/language -- Flow Smart Contract Project Development Standards https://cadence-lang.org/docs/project-development-tips \ No newline at end of file +## ๐Ÿค Community +- [Flow Community Forum](https://forum.onflow.org/) +- [Flow Discord](https://discord.gg/flow) +- [Flow Twitter](https://x.com/flow_blockchain) diff --git a/internal/super/generator/fixtures/README_no_deps.md b/internal/super/generator/fixtures/README_no_deps.md index 6e5b8f162..4199e4b2c 100644 --- a/internal/super/generator/fixtures/README_no_deps.md +++ b/internal/super/generator/fixtures/README_no_deps.md @@ -15,34 +15,18 @@ Here are some essential resources to help you hit the ground running: ## ๐Ÿ“ฆ Project Structure Your project has been set up with the following structure: -- `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration{{ if len .Dependencies }} and your selected Core Contract dependencies{{ end }} to get started. - -{{ if len .Dependencies }} - Your project has also been configured with the following dependencies. You can add more dependencies using the `flow deps add` command: - {{ range .Dependencies }} - - `{{ .Name }}` - {{ end }} -{{ end }} - +- `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration to get started. - `/cadence` - This is where your Cadence smart contracts code lives Inside `cadence` folder you will find: - `/contracts` - This folder contains your Cadence contracts (these are deployed to the network and contain the business logic for your application) -{{ range .Contracts }} - - `{{ .Name }}.cdc` -{{ end }} + - `ExampleContract.cdc` - `/scripts` - This folder contains your Cadence scripts (read-only operations) -{{ range .Scripts }} - - `{{ .Name }}.cdc` -{{ end }} + - `ExampleScript.cdc` - `/transactions` - This folder contains your Cadence transactions (state-changing operations) -{{ range .Transactions }} - - `{{ .Name }}.cdc` -{{ end }} + - `ExampleTransaction.cdc` - `/tests` - This folder contains your Cadence tests (integration tests for your contracts, scripts, and transactions to verify they behave as expected) -{{ range .Tests }} - - `{{ .Name }}.cdc` -{{ end }} + - `ExampleTest.cdc` ## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing diff --git a/internal/super/generator/generator_test.go b/internal/super/generator/generator_test.go index f4fca000c..2673f7d82 100644 --- a/internal/super/generator/generator_test.go +++ b/internal/super/generator/generator_test.go @@ -30,6 +30,12 @@ import ( "github.com/onflow/flow-cli/internal/util" ) +// go:embed fixtures/README_no_deps.md +var readmeNoDepsFixture string + +// go:embed fixtures/README_with_deps.md +var readmeWithDepsFixture string + func TestGenerateNewContract(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) _, state, _ := util.TestMocks(t) @@ -221,3 +227,72 @@ access(all) fun testContract() { }` assert.Equal(t, expectedContent, util.NormalizeLineEndings(string(content))) } + +func TestGenerateReadmeNoDeps(t *testing.T) { + logger := output.NewStdoutLogger(output.NoneLog) + _, state, _ := util.TestMocks(t) + + g := NewGenerator("", state, logger, false, true) + err := g.Create(FileTemplate{ + TemplatePath: "README.md.tmpl", + TargetPath: "README.md", + Data: map[string]interface{}{ + "Dependencies": []map[string]interface{}{}, + "Contracts": []map[string]interface{}{ + {"Name": "ExampleContract"}, + }, + "Transactions": []map[string]interface{}{ + {"Name": "ExampleTransaction"}, + }, + "Scripts": []map[string]interface{}{ + {"Name": "ExampleScript"}, + }, + "Tests": []map[string]interface{}{ + {"Name": "ExampleTest"}, + }, + }, + }) + assert.NoError(t, err, "Failed to generate file") + + content, err := state.ReaderWriter().ReadFile(filepath.FromSlash("README.md")) + assert.NoError(t, err, "Failed to read generated file") + assert.NotNil(t, content) + + assert.Equal(t, readmeNoDepsFixture, string(content)) +} + +func TestGenerateReadmeWithDeps(t *testing.T) { + logger := output.NewStdoutLogger(output.NoneLog) + _, state, _ := util.TestMocks(t) + + g := NewGenerator("", state, logger, false, true) + err := g.Create(FileTemplate{ + TemplatePath: "README.md.tmpl", + TargetPath: "README.md", + Data: map[string]interface{}{ + "Dependencies": []map[string]interface{}{ + {"Name": "FlowToken"}, + {"Name": "FungibleToken"}, + }, + "Contracts": []map[string]interface{}{ + {"Name": "ExampleContract"}, + }, + "Transactions": []map[string]interface{}{ + {"Name": "ExampleTransaction"}, + }, + "Scripts": []map[string]interface{}{ + {"Name": "ExampleScript"}, + }, + "Tests": []map[string]interface{}{ + {"Name": "ExampleTest"}, + }, + }, + }) + assert.NoError(t, err, "Failed to generate file") + + content, err := state.ReaderWriter().ReadFile(filepath.FromSlash("README.md")) + assert.NoError(t, err, "Failed to read generated file") + assert.NotNil(t, content) + + assert.Equal(t, readmeWithDepsFixture, string(content)) +} diff --git a/internal/super/generator/templates/README.md.tmpl b/internal/super/generator/templates/README.md.tmpl index 7a73b3e07..3d7d11d57 100644 --- a/internal/super/generator/templates/README.md.tmpl +++ b/internal/super/generator/templates/README.md.tmpl @@ -1,52 +1,57 @@ ## ๐Ÿ‘‹ Welcome Flow Developer! -Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow blockchain. It comes with a few example contracts and scripts to help you get started. + +Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow Blockchain. It comes with example contracts, scripts, transactions, and tests to help you get started. ## ๐Ÿ”จ Getting started Here are some essential resources to help you hit the ground running: -- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for Flow blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. -- **[Visual Studio Code](https://code.visualstudio.com/?wt.mc_id=DX_841432)** and **[Cadence extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. -- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow documentation is a great resource for learning about the Flow blockchain and its features. -- **[Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the blockchain. -- **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore the Flow blockchain. You can use them to view transactions, accounts, and other data on the blockchain. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. +- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow Documentation is a great starting point to begin learn about [building](https://developers.flow.com/build/flow) on Flow. +- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. +- **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. +- **[Flow Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow Blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the network. +- **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore on-chain data. You can use them to view transactions, accounts, events, and other information. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. ## ๐Ÿ“ฆ Project Structure Your project has been set up with the following structure: -- `flow.json` configuration file for your project, analagous to a `package.json` file for NPM. It has been initialized with a basic configuration{{ if len .Dependencies }} and some Core Contract dependencies{{ end }}. -- `/cadence` inside here is where your Cadence smart contracts code lives +- `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration{{ if len .Dependencies }} and your selected Core Contract dependencies{{ end }} to get started. +{{ if len .Dependencies }} + + Your project has also been configured with the following dependencies. You can add more dependencies using the `flow deps add` command: + {{ range .Dependencies }} + - `{{ .Name }}` + {{ end }} -Your project is set up with the following dependencies: -{{ range .Dependencies }} - - `{{ .Name }}` {{ end }} +- `/cadence` - This is where your Cadence smart contracts code lives Inside `cadence` folder you will find: -- `/contracts` location for Cadence contracts go in this folder +- `/contracts` - This folder contains your Cadence contracts (these are deployed to the network and contain the business logic for your application) {{ range .Contracts }} - - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` contract + - `{{ .Name }}.cdc` {{ end }} -- `/scripts` location for Cadence scripts goes here +- `/scripts` - This folder contains your Cadence scripts (read-only operations) {{ range .Scripts }} - - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` script + - `{{ .Name }}.cdc` {{ end }} -- `/transactions` location for Cadence transactions goes in this folder +- `/transactions` - This folder contains your Cadence transactions (state-changing operations) {{ range .Transactions }} - - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` transaction + - `{{ .Name }}.cdc` {{ end }} -- `/tests` location for Cadence tests goes in this folder +- `/tests` - This folder contains your Cadence tests (integration tests for your contracts, scripts, and transactions to verify they behave as expected) {{ range .Tests }} - - `{{ .Name }}.cdc` is the file for the `{{ .Name }}` test + - `{{ .Name }}.cdc` {{ end }} ## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing ### Creating a new contract + To add a new contract to your project, run the following command: ```shell -> flow generate contract +flow generate contract ``` This command will create a new contract file and add it to the `flow.json` configuration file. @@ -56,15 +61,15 @@ This command will create a new contract file and add it to the `flow.json` confi To add a new script to your project, run the following command: ```shell -> flow generate script +flow generate script ``` -This command will create a new script file and add it to the `flow.json` configuration file. +This command will create a new script file. Scripts are used to read data from the blockchain and do not modify state (i.e. get the current balance of an account, get a user's NFTs, etc). You can import any of your own contracts or installed dependencies in your script file using the `import` keyword. For example: ```cadence -import Counter from "Counter" +import "Counter" ``` ### Creating a new transaction @@ -72,58 +77,102 @@ import Counter from "Counter" To add a new transaction to your project you can use the following command: ```shell -> flow generate transaction +flow generate transaction ``` -This command will create a new transaction file and add it to the `flow.json` configuration file. You can import any dependencies as you would in a script file. +This command will create a new transaction file. Transactions are used to modify the state of the blockchain (i.e purchase an NFT, transfer tokens, etc). + +You can import any dependencies as you would in a script file. + +### Creating a new test + +To add a new test to your project you can use the following command: + +```shell +flow generate test +``` + +This command will create a new test file. Tests are used to verify that your contracts, scripts, and transactions are working as expected. ### Installing external dependencies -If you want to use external contract dependencies (like NonFungibleToken, FlowToken, FungibleToken,..) you can install them using Cadence dependency manager: https://developers.flow.com/tools/flow-cli/dependency-manager +If you want to use external contract dependencies (such as NonFungibleToken, FlowToken, FungibleToken, etc.) you can install them using [Flow CLI Dependency Manager](https://developers.flow.com/tools/flow-cli/dependency-manager). -Use [ContractBrowser](https://contractbrowser.com/) to explore available 3rd party contracts in the Flow ecosystem. +For example, to install the NonFungibleToken contract you can use the following command: + +```shell +flow deps add mainnet://1d7e57aa55817448.NonFungibleToken +``` + +Contracts can be found using [ContractBrowser](https://contractbrowser.com/), but be sure to verify the authenticity before using third-party contracts in your project. ## ๐Ÿงช Testing To verify that your project is working as expected you can run the tests using the following command: + ```shell -> flow test +flow test ``` -This command will run all the tests in the `cadence/tests` folder. You can add more tests to this folder as you develop your project. +This command will run all tests with the `_test.cdc` suffix (these can be found in the `cadence/tests` folder). You can add more tests here using the `flow generate test` command (or by creating them manually). -To learn more about testing in Cadence, check out the [Cadence testing documentation](https://cadence-lang.org/docs/testing-framework). +To learn more about testing in Cadence, check out the [Cadence Test Framework Documentation](https://cadence-lang.org/docs/testing-framework). -## ๐Ÿš€ Deploying +## ๐Ÿš€ Deploying your project + +To deploy your project to the Flow network, you must first have a Flow account and have configured your deployment targets in the `flow.json` configuration file. + +You can create a new Flow account using the following command: + +```shell +flow accounts create +``` + +Learn more about setting up deployment targets in the [Flow CLI documentation](https://developers.flow.com/tools/flow-cli/deployment/project-contracts). ### Deploying to the Flow Emulator -To deploy your project to the Flow Emulator you can use the following command: +To deploy your project to the Flow Emulator, start the emulator using the following command: + ```shell -> flow emulator --start +flow emulator --start ``` -This command will start the Flow Emulator and deploy your project to it. You can then interact with your project using the Flow Emulator. +To deploy your project, run the following command: -### Deploying to the Flow Testnet +```shell +flow project deploy --network=emulator +``` + +This command will start the Flow Emulator and deploy your project to it. You can now interact with your smart contracts using the Flow CLI or any other Flow client. + +### Deploying to Flow Testnet + +To deploy your project to Flow Testnet you can use the following command: -To deploy your project to the Flow Testnet you can use the following command: ```shell -> flow project deploy --network=testnet +flow project deploy --network=testnet ``` -This command will deploy your project to the Flow Testnet. You can then interact with your project using the Flow Testnet. +This command will deploy your project to Flow Testnet. You can now interact with your project using the Flow Testnet. + +### Deploying to Flow Mainnet -### Deploying to the Flow Mainnet +To deploy your project to Flow Mainnet you can use the following command: -To deploy your project to the Flow Mainnet you can use the following command: ```shell -> flow project deploy --network=mainnet +flow project deploy --network=mainnet ``` -This command will deploy your project to the Flow Mainnet. You can then interact with your project using the Flow Mainnet. +This command will deploy your project to Flow Mainnet. You now then interact with your project using the Flow Mainnet. + +## ๐Ÿ“š Other Resources -## Further Reading +- [Cadence Design Patterns](https://cadence-lang.org/docs/design-patterns) +- [Cadence Anti-Patterns](https://cadence-lang.org/docs/anti-patterns) +- [Flow Core Contracts](https://developers.flow.com/build/core-contracts) -- Cadence Language Reference https://cadence-lang.org/docs/language -- Flow Smart Contract Project Development Standards https://cadence-lang.org/docs/project-development-tips \ No newline at end of file +## ๐Ÿค Community +- [Flow Community Forum](https://forum.onflow.org/) +- [Flow Discord](https://discord.gg/flow) +- [Flow Twitter](https://x.com/flow_blockchain) From 9d17ec576f1cd53d2521961ff56573e9caad43a0 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Fri, 18 Oct 2024 13:24:55 -0700 Subject: [PATCH 14/20] fixup --- ...ME_no_deps copy.md => README_with_deps.md} | 0 .../super/generator/templates/README.md.tmpl | 34 +++++---------- internal/super/setup.go | 42 +++++++++++++------ 3 files changed, 40 insertions(+), 36 deletions(-) rename internal/super/generator/fixtures/{README_no_deps copy.md => README_with_deps.md} (100%) diff --git a/internal/super/generator/fixtures/README_no_deps copy.md b/internal/super/generator/fixtures/README_with_deps.md similarity index 100% rename from internal/super/generator/fixtures/README_no_deps copy.md rename to internal/super/generator/fixtures/README_with_deps.md diff --git a/internal/super/generator/templates/README.md.tmpl b/internal/super/generator/templates/README.md.tmpl index 3d7d11d57..65c1e23dd 100644 --- a/internal/super/generator/templates/README.md.tmpl +++ b/internal/super/generator/templates/README.md.tmpl @@ -15,34 +15,22 @@ Here are some essential resources to help you hit the ground running: ## ๐Ÿ“ฆ Project Structure Your project has been set up with the following structure: -- `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration{{ if len .Dependencies }} and your selected Core Contract dependencies{{ end }} to get started. -{{ if len .Dependencies }} - - Your project has also been configured with the following dependencies. You can add more dependencies using the `flow deps add` command: - {{ range .Dependencies }} - - `{{ .Name }}` - {{ end }} +- `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration{{ if len .Dependencies }} and your selected Core Contract dependencies{{ end }} to get started.{{ if len .Dependencies }} + Your project has also been configured with the following dependencies. You can add more dependencies using the `flow deps add` command:{{ range .Dependencies }} + - `{{ .Name }}`{{ end }} {{ end }} - `/cadence` - This is where your Cadence smart contracts code lives Inside `cadence` folder you will find: -- `/contracts` - This folder contains your Cadence contracts (these are deployed to the network and contain the business logic for your application) -{{ range .Contracts }} - - `{{ .Name }}.cdc` -{{ end }} -- `/scripts` - This folder contains your Cadence scripts (read-only operations) -{{ range .Scripts }} - - `{{ .Name }}.cdc` -{{ end }} -- `/transactions` - This folder contains your Cadence transactions (state-changing operations) -{{ range .Transactions }} - - `{{ .Name }}.cdc` -{{ end }} -- `/tests` - This folder contains your Cadence tests (integration tests for your contracts, scripts, and transactions to verify they behave as expected) -{{ range .Tests }} - - `{{ .Name }}.cdc` -{{ end }} +- `/contracts` - This folder contains your Cadence contracts (these are deployed to the network and contain the business logic for your application){{ range .Contracts }} + - `{{ .Name }}.cdc`{{ end }} +- `/scripts` - This folder contains your Cadence scripts (read-only operations){{ range .Scripts }} + - `{{ .Name }}.cdc`{{ end }} +- `/transactions` - This folder contains your Cadence transactions (state-changing operations){{ range .Transactions }} + - `{{ .Name }}.cdc`{{ end }} +- `/tests` - This folder contains your Cadence tests (integration tests for your contracts, scripts, and transactions to verify they behave as expected){{ range .Tests }} + - `{{ .Name }}.cdc`{{ end }} ## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing diff --git a/internal/super/setup.go b/internal/super/setup.go index d12985336..7868dba5b 100644 --- a/internal/super/setup.go +++ b/internal/super/setup.go @@ -200,6 +200,14 @@ func startInteractiveSetup( return "", fmt.Errorf("failed to initialize configuration: %w", err) } + msg := "Would you like to install any core contracts and their dependencies?" + if prompt.GenericBoolPrompt(msg) { + err := dependencymanager.PromptInstallCoreContracts(logger, state, tempDir, nil) + if err != nil { + return "", err + } + } + // Generate standard cadence files & README.md // cadence/contracts/DefaultContract.cdc // cadence/scripts/DefaultScript.cdc @@ -222,15 +230,31 @@ func startInteractiveSetup( TemplatePath: "transaction_counter.cdc.tmpl", Data: map[string]interface{}{"ContractName": "Counter"}, }, - generator.TestTemplate{ - Name: "Counter_test", - Data: map[string]interface{}{"ContractName": "Counter"}, - }, generator.FileTemplate{ TemplatePath: "README.md.tmpl", TargetPath: "README.md", Data: map[string]interface{}{ - "ProjectName": filepath.Base(targetDir), + "Dependencies": (func() []map[string]interface{} { + contracts := []map[string]interface{}{} + for _, dep := range *state.Dependencies() { + contracts = append(contracts, map[string]interface{}{ + "Name": dep.Name, + }) + } + return contracts + })(), + "Contracts": []map[string]interface{}{ + {"Name": "Counter"}, + }, + "Scripts": []map[string]interface{}{ + {"Name": "GetCounter"}, + }, + "Transactions": []map[string]interface{}{ + {"Name": "IncrementCounter"}, + }, + "Tests": []map[string]interface{}{ + {"Name": "Counter_test"}, + }, }, }, } @@ -241,14 +265,6 @@ func startInteractiveSetup( return "", err } - msg := "Would you like to install any core contracts and their dependencies?" - if prompt.GenericBoolPrompt(msg) { - err := dependencymanager.PromptInstallCoreContracts(logger, state, tempDir, nil) - if err != nil { - return "", err - } - } - err = state.Save(filepath.Join(tempDir, "flow.json")) if err != nil { return "", err From cd91ebcb0f5d99ce4860f524b13de5b9342cf778 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Fri, 18 Oct 2024 13:47:40 -0700 Subject: [PATCH 15/20] Fix tests --- internal/super/generator/generator_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/super/generator/generator_test.go b/internal/super/generator/generator_test.go index 2673f7d82..adcb63de2 100644 --- a/internal/super/generator/generator_test.go +++ b/internal/super/generator/generator_test.go @@ -19,6 +19,7 @@ package generator import ( + "embed" "fmt" "path/filepath" "testing" @@ -30,11 +31,8 @@ import ( "github.com/onflow/flow-cli/internal/util" ) -// go:embed fixtures/README_no_deps.md -var readmeNoDepsFixture string - -// go:embed fixtures/README_with_deps.md -var readmeWithDepsFixture string +//go:embed fixtures/*.* +var fixturesFS embed.FS func TestGenerateNewContract(t *testing.T) { logger := output.NewStdoutLogger(output.NoneLog) @@ -258,7 +256,8 @@ func TestGenerateReadmeNoDeps(t *testing.T) { assert.NoError(t, err, "Failed to read generated file") assert.NotNil(t, content) - assert.Equal(t, readmeNoDepsFixture, string(content)) + readmeNoDepsFixture, _ := fixturesFS.ReadFile("fixtures/README_no_deps.md") + assert.Equal(t, string(readmeNoDepsFixture), string(content)) } func TestGenerateReadmeWithDeps(t *testing.T) { @@ -294,5 +293,6 @@ func TestGenerateReadmeWithDeps(t *testing.T) { assert.NoError(t, err, "Failed to read generated file") assert.NotNil(t, content) - assert.Equal(t, readmeWithDepsFixture, string(content)) + readmeWithDepsFixture, _ := fixturesFS.ReadFile("fixtures/README_with_deps.md") + assert.Equal(t, string(readmeWithDepsFixture), string(content)) } From 0367edf6cd725c3738ae148fbfa817995591c95d Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Fri, 18 Oct 2024 13:59:58 -0700 Subject: [PATCH 16/20] Grammatical changes --- .../super/generator/fixtures/README_no_deps.md | 14 +++++++------- .../super/generator/fixtures/README_with_deps.md | 14 +++++++------- internal/super/generator/templates/README.md.tmpl | 14 +++++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/internal/super/generator/fixtures/README_no_deps.md b/internal/super/generator/fixtures/README_no_deps.md index 4199e4b2c..a8e5000dd 100644 --- a/internal/super/generator/fixtures/README_no_deps.md +++ b/internal/super/generator/fixtures/README_no_deps.md @@ -6,9 +6,9 @@ Welcome to your new Flow project. This project is a starting point for you to de Here are some essential resources to help you hit the ground running: -- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow Documentation is a great starting point to begin learn about [building](https://developers.flow.com/build/flow) on Flow. -- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. -- **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. +- **[Flow Documentation](https://developers.onflow.org/)** - The official Flow Documentation is a great starting point to start learning about about [building](https://developers.flow.com/build/flow) on Flow. +- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain. It is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. +- **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will provide syntax highlighting, code completion, and other features to support Cadence development. - **[Flow Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow Blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the network. - **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore on-chain data. You can use them to view transactions, accounts, events, and other information. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. @@ -18,7 +18,7 @@ Your project has been set up with the following structure: - `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration to get started. - `/cadence` - This is where your Cadence smart contracts code lives -Inside `cadence` folder you will find: +Inside the `cadence` folder you will find: - `/contracts` - This folder contains your Cadence contracts (these are deployed to the network and contain the business logic for your application) - `ExampleContract.cdc` - `/scripts` - This folder contains your Cadence scripts (read-only operations) @@ -128,7 +128,7 @@ To deploy your project, run the following command: flow project deploy --network=emulator ``` -This command will start the Flow Emulator and deploy your project to it. You can now interact with your smart contracts using the Flow CLI or any other Flow client. +This command will start the Flow Emulator and deploy your project to it. You can now interact with your project using the Flow CLI or alternate [client](https://developers.flow.com/tools/clients). ### Deploying to Flow Testnet @@ -138,7 +138,7 @@ To deploy your project to Flow Testnet you can use the following command: flow project deploy --network=testnet ``` -This command will deploy your project to Flow Testnet. You can now interact with your project using the Flow Testnet. +This command will deploy your project to Flow Testnet. You can now interact with your project on this network using the Flow CLI or any other Flow client. ### Deploying to Flow Mainnet @@ -148,7 +148,7 @@ To deploy your project to Flow Mainnet you can use the following command: flow project deploy --network=mainnet ``` -This command will deploy your project to Flow Mainnet. You now then interact with your project using the Flow Mainnet. +This command will deploy your project to Flow Mainnet. You can now interact with your project using the Flow CLI or alternate [client](https://developers.flow.com/tools/clients). ## ๐Ÿ“š Other Resources diff --git a/internal/super/generator/fixtures/README_with_deps.md b/internal/super/generator/fixtures/README_with_deps.md index 6a68aab64..9b3aaedb3 100644 --- a/internal/super/generator/fixtures/README_with_deps.md +++ b/internal/super/generator/fixtures/README_with_deps.md @@ -6,9 +6,9 @@ Welcome to your new Flow project. This project is a starting point for you to de Here are some essential resources to help you hit the ground running: -- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow Documentation is a great starting point to begin learn about [building](https://developers.flow.com/build/flow) on Flow. -- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. -- **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. +- **[Flow Documentation](https://developers.onflow.org/)** - The official Flow Documentation is a great starting point to start learning about about [building](https://developers.flow.com/build/flow) on Flow. +- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain. It is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. +- **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will provide syntax highlighting, code completion, and other features to support Cadence development. - **[Flow Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow Blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the network. - **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore on-chain data. You can use them to view transactions, accounts, events, and other information. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. @@ -23,7 +23,7 @@ Your project has been set up with the following structure: - `/cadence` - This is where your Cadence smart contracts code lives -Inside `cadence` folder you will find: +Inside the `cadence` folder you will find: - `/contracts` - This folder contains your Cadence contracts (these are deployed to the network and contain the business logic for your application) - `ExampleContract.cdc` - `/scripts` - This folder contains your Cadence scripts (read-only operations) @@ -133,7 +133,7 @@ To deploy your project, run the following command: flow project deploy --network=emulator ``` -This command will start the Flow Emulator and deploy your project to it. You can now interact with your smart contracts using the Flow CLI or any other Flow client. +This command will start the Flow Emulator and deploy your project to it. You can now interact with your project using the Flow CLI or alternate [client](https://developers.flow.com/tools/clients). ### Deploying to Flow Testnet @@ -143,7 +143,7 @@ To deploy your project to Flow Testnet you can use the following command: flow project deploy --network=testnet ``` -This command will deploy your project to Flow Testnet. You can now interact with your project using the Flow Testnet. +This command will deploy your project to Flow Testnet. You can now interact with your project on this network using the Flow CLI or any other Flow client. ### Deploying to Flow Mainnet @@ -153,7 +153,7 @@ To deploy your project to Flow Mainnet you can use the following command: flow project deploy --network=mainnet ``` -This command will deploy your project to Flow Mainnet. You now then interact with your project using the Flow Mainnet. +This command will deploy your project to Flow Mainnet. You can now interact with your project using the Flow CLI or alternate [client](https://developers.flow.com/tools/clients). ## ๐Ÿ“š Other Resources diff --git a/internal/super/generator/templates/README.md.tmpl b/internal/super/generator/templates/README.md.tmpl index 65c1e23dd..c32a37eea 100644 --- a/internal/super/generator/templates/README.md.tmpl +++ b/internal/super/generator/templates/README.md.tmpl @@ -6,9 +6,9 @@ Welcome to your new Flow project. This project is a starting point for you to de Here are some essential resources to help you hit the ground running: -- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow Documentation is a great starting point to begin learn about [building](https://developers.flow.com/build/flow) on Flow. -- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. -- **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. +- **[Flow Documentation](https://developers.onflow.org/)** - The official Flow Documentation is a great starting point to start learning about about [building](https://developers.flow.com/build/flow) on Flow. +- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain. It is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. +- **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will provide syntax highlighting, code completion, and other features to support Cadence development. - **[Flow Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow Blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the network. - **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore on-chain data. You can use them to view transactions, accounts, events, and other information. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. @@ -22,7 +22,7 @@ Your project has been set up with the following structure: {{ end }} - `/cadence` - This is where your Cadence smart contracts code lives -Inside `cadence` folder you will find: +Inside the `cadence` folder you will find: - `/contracts` - This folder contains your Cadence contracts (these are deployed to the network and contain the business logic for your application){{ range .Contracts }} - `{{ .Name }}.cdc`{{ end }} - `/scripts` - This folder contains your Cadence scripts (read-only operations){{ range .Scripts }} @@ -132,7 +132,7 @@ To deploy your project, run the following command: flow project deploy --network=emulator ``` -This command will start the Flow Emulator and deploy your project to it. You can now interact with your smart contracts using the Flow CLI or any other Flow client. +This command will start the Flow Emulator and deploy your project to it. You can now interact with your project using the Flow CLI or alternate [client](https://developers.flow.com/tools/clients). ### Deploying to Flow Testnet @@ -142,7 +142,7 @@ To deploy your project to Flow Testnet you can use the following command: flow project deploy --network=testnet ``` -This command will deploy your project to Flow Testnet. You can now interact with your project using the Flow Testnet. +This command will deploy your project to Flow Testnet. You can now interact with your project on this network using the Flow CLI or any other Flow client. ### Deploying to Flow Mainnet @@ -152,7 +152,7 @@ To deploy your project to Flow Mainnet you can use the following command: flow project deploy --network=mainnet ``` -This command will deploy your project to Flow Mainnet. You now then interact with your project using the Flow Mainnet. +This command will deploy your project to Flow Mainnet. You can now interact with your project using the Flow CLI or alternate [client](https://developers.flow.com/tools/clients). ## ๐Ÿ“š Other Resources From e48d793b643ceb40b0eb2916cafe1dc57f2c9394 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink <17958158+jribbink@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:17:20 -0700 Subject: [PATCH 17/20] Update internal/super/generator/fixtures/README_no_deps.md Co-authored-by: Greg Santos --- internal/super/generator/fixtures/README_no_deps.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/super/generator/fixtures/README_no_deps.md b/internal/super/generator/fixtures/README_no_deps.md index a8e5000dd..d231e1a79 100644 --- a/internal/super/generator/fixtures/README_no_deps.md +++ b/internal/super/generator/fixtures/README_no_deps.md @@ -6,7 +6,7 @@ Welcome to your new Flow project. This project is a starting point for you to de Here are some essential resources to help you hit the ground running: -- **[Flow Documentation](https://developers.onflow.org/)** - The official Flow Documentation is a great starting point to start learning about about [building](https://developers.flow.com/build/flow) on Flow. +- **[Flow Documentation](https://developers.flow.com/)** - The official Flow Documentation is a great starting point to start learning about about [building](https://developers.flow.com/build/flow) on Flow. - **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain. It is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. - **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will provide syntax highlighting, code completion, and other features to support Cadence development. - **[Flow Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow Blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the network. From cf65e4cd1aed29d1463bcaa4920faf03bbf274f2 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink <17958158+jribbink@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:17:26 -0700 Subject: [PATCH 18/20] Update internal/super/generator/fixtures/README_with_deps.md Co-authored-by: Greg Santos --- internal/super/generator/fixtures/README_with_deps.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/super/generator/fixtures/README_with_deps.md b/internal/super/generator/fixtures/README_with_deps.md index 9b3aaedb3..39a7e1215 100644 --- a/internal/super/generator/fixtures/README_with_deps.md +++ b/internal/super/generator/fixtures/README_with_deps.md @@ -6,7 +6,7 @@ Welcome to your new Flow project. This project is a starting point for you to de Here are some essential resources to help you hit the ground running: -- **[Flow Documentation](https://developers.onflow.org/)** - The official Flow Documentation is a great starting point to start learning about about [building](https://developers.flow.com/build/flow) on Flow. +- **[Flow Documentation](https://developers.flow.com/)** - The official Flow Documentation is a great starting point to start learning about about [building](https://developers.flow.com/build/flow) on Flow. - **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain. It is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. - **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will provide syntax highlighting, code completion, and other features to support Cadence development. - **[Flow Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow Blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the network. From fae96cdd4301bf365d9101c7d10e38ec836a099a Mon Sep 17 00:00:00 2001 From: Jordan Ribbink <17958158+jribbink@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:17:34 -0700 Subject: [PATCH 19/20] Update internal/super/generator/templates/README.md.tmpl Co-authored-by: Greg Santos --- internal/super/generator/templates/README.md.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/super/generator/templates/README.md.tmpl b/internal/super/generator/templates/README.md.tmpl index c32a37eea..3696270de 100644 --- a/internal/super/generator/templates/README.md.tmpl +++ b/internal/super/generator/templates/README.md.tmpl @@ -6,7 +6,7 @@ Welcome to your new Flow project. This project is a starting point for you to de Here are some essential resources to help you hit the ground running: -- **[Flow Documentation](https://developers.onflow.org/)** - The official Flow Documentation is a great starting point to start learning about about [building](https://developers.flow.com/build/flow) on Flow. +- **[Flow Documentation](https://developers.flow.com/)** - The official Flow Documentation is a great starting point to start learning about about [building](https://developers.flow.com/build/flow) on Flow. - **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain. It is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. - **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will provide syntax highlighting, code completion, and other features to support Cadence development. - **[Flow Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow Blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the network. From 8f9efc452695eefd010e08f517051ffd39ff9feb Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Fri, 18 Oct 2024 14:54:39 -0700 Subject: [PATCH 20/20] Fix casing --- .../generator/fixtures/README_no_deps.md | 15 +- .../generator/fixtures/README_with_deps.md | 15 +- .../super/generator/templates/README.md.tmpl | 15 +- testing/better/README.md | 172 ++++++++++++++++++ 4 files changed, 196 insertions(+), 21 deletions(-) create mode 100644 testing/better/README.md diff --git a/internal/super/generator/fixtures/README_no_deps.md b/internal/super/generator/fixtures/README_no_deps.md index d231e1a79..d44869cca 100644 --- a/internal/super/generator/fixtures/README_no_deps.md +++ b/internal/super/generator/fixtures/README_no_deps.md @@ -2,7 +2,7 @@ Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow Blockchain. It comes with example contracts, scripts, transactions, and tests to help you get started. -## ๐Ÿ”จ Getting started +## ๐Ÿ”จ Getting Started Here are some essential resources to help you hit the ground running: @@ -13,6 +13,7 @@ Here are some essential resources to help you hit the ground running: - **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore on-chain data. You can use them to view transactions, accounts, events, and other information. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. ## ๐Ÿ“ฆ Project Structure + Your project has been set up with the following structure: - `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration to get started. @@ -30,7 +31,7 @@ Inside the `cadence` folder you will find: ## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing -### Creating a new contract +### Creating a New Contract To add a new contract to your project, run the following command: @@ -40,7 +41,7 @@ flow generate contract This command will create a new contract file and add it to the `flow.json` configuration file. -### Creating a new script +### Creating a New Script To add a new script to your project, run the following command: @@ -56,7 +57,7 @@ You can import any of your own contracts or installed dependencies in your scrip import "Counter" ``` -### Creating a new transaction +### Creating a New Transaction To add a new transaction to your project you can use the following command: @@ -68,7 +69,7 @@ This command will create a new transaction file. Transactions are used to modif You can import any dependencies as you would in a script file. -### Creating a new test +### Creating a New Test To add a new test to your project you can use the following command: @@ -78,7 +79,7 @@ flow generate test This command will create a new test file. Tests are used to verify that your contracts, scripts, and transactions are working as expected. -### Installing external dependencies +### Installing External Dependencies If you want to use external contract dependencies (such as NonFungibleToken, FlowToken, FungibleToken, etc.) you can install them using [Flow CLI Dependency Manager](https://developers.flow.com/tools/flow-cli/dependency-manager). @@ -102,7 +103,7 @@ This command will run all tests with the `_test.cdc` suffix (these can be found To learn more about testing in Cadence, check out the [Cadence Test Framework Documentation](https://cadence-lang.org/docs/testing-framework). -## ๐Ÿš€ Deploying your project +## ๐Ÿš€ Deploying Your Project To deploy your project to the Flow network, you must first have a Flow account and have configured your deployment targets in the `flow.json` configuration file. diff --git a/internal/super/generator/fixtures/README_with_deps.md b/internal/super/generator/fixtures/README_with_deps.md index 39a7e1215..c1c2bfc9f 100644 --- a/internal/super/generator/fixtures/README_with_deps.md +++ b/internal/super/generator/fixtures/README_with_deps.md @@ -2,7 +2,7 @@ Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow Blockchain. It comes with example contracts, scripts, transactions, and tests to help you get started. -## ๐Ÿ”จ Getting started +## ๐Ÿ”จ Getting Started Here are some essential resources to help you hit the ground running: @@ -13,6 +13,7 @@ Here are some essential resources to help you hit the ground running: - **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore on-chain data. You can use them to view transactions, accounts, events, and other information. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. ## ๐Ÿ“ฆ Project Structure + Your project has been set up with the following structure: - `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration and your selected Core Contract dependencies to get started. @@ -35,7 +36,7 @@ Inside the `cadence` folder you will find: ## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing -### Creating a new contract +### Creating a New Contract To add a new contract to your project, run the following command: @@ -45,7 +46,7 @@ flow generate contract This command will create a new contract file and add it to the `flow.json` configuration file. -### Creating a new script +### Creating a New Script To add a new script to your project, run the following command: @@ -61,7 +62,7 @@ You can import any of your own contracts or installed dependencies in your scrip import "Counter" ``` -### Creating a new transaction +### Creating a New Transaction To add a new transaction to your project you can use the following command: @@ -73,7 +74,7 @@ This command will create a new transaction file. Transactions are used to modif You can import any dependencies as you would in a script file. -### Creating a new test +### Creating a New Test To add a new test to your project you can use the following command: @@ -83,7 +84,7 @@ flow generate test This command will create a new test file. Tests are used to verify that your contracts, scripts, and transactions are working as expected. -### Installing external dependencies +### Installing External Dependencies If you want to use external contract dependencies (such as NonFungibleToken, FlowToken, FungibleToken, etc.) you can install them using [Flow CLI Dependency Manager](https://developers.flow.com/tools/flow-cli/dependency-manager). @@ -107,7 +108,7 @@ This command will run all tests with the `_test.cdc` suffix (these can be found To learn more about testing in Cadence, check out the [Cadence Test Framework Documentation](https://cadence-lang.org/docs/testing-framework). -## ๐Ÿš€ Deploying your project +## ๐Ÿš€ Deploying Your Project To deploy your project to the Flow network, you must first have a Flow account and have configured your deployment targets in the `flow.json` configuration file. diff --git a/internal/super/generator/templates/README.md.tmpl b/internal/super/generator/templates/README.md.tmpl index 3696270de..1e3d61cfb 100644 --- a/internal/super/generator/templates/README.md.tmpl +++ b/internal/super/generator/templates/README.md.tmpl @@ -2,7 +2,7 @@ Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow Blockchain. It comes with example contracts, scripts, transactions, and tests to help you get started. -## ๐Ÿ”จ Getting started +## ๐Ÿ”จ Getting Started Here are some essential resources to help you hit the ground running: @@ -13,6 +13,7 @@ Here are some essential resources to help you hit the ground running: - **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore on-chain data. You can use them to view transactions, accounts, events, and other information. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. ## ๐Ÿ“ฆ Project Structure + Your project has been set up with the following structure: - `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration{{ if len .Dependencies }} and your selected Core Contract dependencies{{ end }} to get started.{{ if len .Dependencies }} @@ -34,7 +35,7 @@ Inside the `cadence` folder you will find: ## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing -### Creating a new contract +### Creating a New Contract To add a new contract to your project, run the following command: @@ -44,7 +45,7 @@ flow generate contract This command will create a new contract file and add it to the `flow.json` configuration file. -### Creating a new script +### Creating a New Script To add a new script to your project, run the following command: @@ -60,7 +61,7 @@ You can import any of your own contracts or installed dependencies in your scrip import "Counter" ``` -### Creating a new transaction +### Creating a New Transaction To add a new transaction to your project you can use the following command: @@ -72,7 +73,7 @@ This command will create a new transaction file. Transactions are used to modif You can import any dependencies as you would in a script file. -### Creating a new test +### Creating a New Test To add a new test to your project you can use the following command: @@ -82,7 +83,7 @@ flow generate test This command will create a new test file. Tests are used to verify that your contracts, scripts, and transactions are working as expected. -### Installing external dependencies +### Installing External Dependencies If you want to use external contract dependencies (such as NonFungibleToken, FlowToken, FungibleToken, etc.) you can install them using [Flow CLI Dependency Manager](https://developers.flow.com/tools/flow-cli/dependency-manager). @@ -106,7 +107,7 @@ This command will run all tests with the `_test.cdc` suffix (these can be found To learn more about testing in Cadence, check out the [Cadence Test Framework Documentation](https://cadence-lang.org/docs/testing-framework). -## ๐Ÿš€ Deploying your project +## ๐Ÿš€ Deploying Your Project To deploy your project to the Flow network, you must first have a Flow account and have configured your deployment targets in the `flow.json` configuration file. diff --git a/testing/better/README.md b/testing/better/README.md new file mode 100644 index 000000000..2502ef6de --- /dev/null +++ b/testing/better/README.md @@ -0,0 +1,172 @@ +## ๐Ÿ‘‹ Welcome Flow Developer! + +Welcome to your new Flow project. This project is a starting point for you to develop smart contracts on the Flow Blockchain. It comes with example contracts, scripts, transactions, and tests to help you get started. + +## ๐Ÿ”จ Getting started + +Here are some essential resources to help you hit the ground running: + +- **[Flow Documentation](https://docs.onflow.org/)** - The official Flow Documentation is a great starting point to begin learn about [building](https://developers.flow.com/build/flow) on Flow. +- **[Cadence Documentation](https://cadence-lang.org/docs/language)** - Cadence is the native language for the Flow Blockchain, it is a resource-oriented programming language that is designed for developing smart contracts. The documentation is a great place to start learning about the language. +- **[Visual Studio Code](https://code.visualstudio.com/)** and the **[Cadence Extension](https://marketplace.visualstudio.com/items?itemName=onflow.cadence)** - It is recommended to use the Visual Studio Code IDE with the Cadence extension installed. This will include syntax highlighting, code completion, and other features to support Cadence development. +- **[Flow Clients](https://developers.flow.com/tools/clients)** - There are clients available in multiple languages to interact with the Flow Blockchain. You can use these clients to interact with your smart contracts, run transactions, and query data from the network. +- **[Block Explorers](https://developers.flow.com/ecosystem/block-explorers)** - Block explorers are tools that allow you to explore on-chain data. You can use them to view transactions, accounts, events, and other information. [Flowser](https://flowser.dev/) is a powerful block explorer for local development on the Flow Emulator. + +## ๐Ÿ“ฆ Project Structure +Your project has been set up with the following structure: + +- `flow.json` - This is the configuration file for your project (analogous to a `package.json` file for NPM). It has been initialized with a basic configuration and your selected Core Contract dependencies to get started. + + Your project has also been configured with the following dependencies. You can add more dependencies using the `flow deps add` command: + - `Burner` + +- `/cadence` - This is where your Cadence smart contracts code lives + +Inside `cadence` folder you will find: +- `/contracts` - This folder contains your Cadence contracts (these are deployed to the network and contain the business logic for your application) + + - `Counter.cdc` + +- `/scripts` - This folder contains your Cadence scripts (read-only operations) + + - `GetCounter.cdc` + +- `/transactions` - This folder contains your Cadence transactions (state-changing operations) + + - `IncrementCounter.cdc` + +- `/tests` - This folder contains your Cadence tests (integration tests for your contracts, scripts, and transactions to verify they behave as expected) + - `Counter_test.cdc` + +## ๐Ÿ‘จโ€๐Ÿ’ป Start Developing + +### Creating a New Contract + +To add a new contract to your project, run the following command: + +```shell +flow generate contract +``` + +This command will create a new contract file and add it to the `flow.json` configuration file. + +### Creating a New Script + +To add a new script to your project, run the following command: + +```shell +flow generate script +``` + +This command will create a new script file. Scripts are used to read data from the blockchain and do not modify state (i.e. get the current balance of an account, get a user's NFTs, etc). + +You can import any of your own contracts or installed dependencies in your script file using the `import` keyword. For example: + +```cadence +import "Counter" +``` + +### Creating a New Transaction + +To add a new transaction to your project you can use the following command: + +```shell +flow generate transaction +``` + +This command will create a new transaction file. Transactions are used to modify the state of the blockchain (i.e purchase an NFT, transfer tokens, etc). + +You can import any dependencies as you would in a script file. + +### Creating a New test + +To add a new test to your project you can use the following command: + +```shell +flow generate test +``` + +This command will create a new test file. Tests are used to verify that your contracts, scripts, and transactions are working as expected. + +### Installing external dependencies + +If you want to use external contract dependencies (such as NonFungibleToken, FlowToken, FungibleToken, etc.) you can install them using [Flow CLI Dependency Manager](https://developers.flow.com/tools/flow-cli/dependency-manager). + +For example, to install the NonFungibleToken contract you can use the following command: + +```shell +flow deps add mainnet://1d7e57aa55817448.NonFungibleToken +``` + +Contracts can be found using [ContractBrowser](https://contractbrowser.com/), but be sure to verify the authenticity before using third-party contracts in your project. + +## ๐Ÿงช Testing + +To verify that your project is working as expected you can run the tests using the following command: + +```shell +flow test +``` + +This command will run all tests with the `_test.cdc` suffix (these can be found in the `cadence/tests` folder). You can add more tests here using the `flow generate test` command (or by creating them manually). + +To learn more about testing in Cadence, check out the [Cadence Test Framework Documentation](https://cadence-lang.org/docs/testing-framework). + +## ๐Ÿš€ Deploying your project + +To deploy your project to the Flow network, you must first have a Flow account and have configured your deployment targets in the `flow.json` configuration file. + +You can create a new Flow account using the following command: + +```shell +flow accounts create +``` + +Learn more about setting up deployment targets in the [Flow CLI documentation](https://developers.flow.com/tools/flow-cli/deployment/project-contracts). + +### Deploying to the Flow Emulator + +To deploy your project to the Flow Emulator, start the emulator using the following command: + +```shell +flow emulator --start +``` + +To deploy your project, run the following command: + +```shell +flow project deploy --network=emulator +``` + +This command will start the Flow Emulator and deploy your project to it. You can now interact with your smart contracts using the Flow CLI or any other Flow client. + +### Deploying to Flow Testnet + +To deploy your project to Flow Testnet you can use the following command: + +```shell +flow project deploy --network=testnet +``` + +This command will deploy your project to Flow Testnet. You can now interact with your project using the Flow Testnet. + +### Deploying to Flow Mainnet + +To deploy your project to Flow Mainnet you can use the following command: + +```shell +flow project deploy --network=mainnet +``` + +This command will deploy your project to Flow Mainnet. You now then interact with your project using the Flow Mainnet. + +## ๐Ÿ“š Other Resources + +- [Cadence Design Patterns](https://cadence-lang.org/docs/design-patterns) +- [Cadence Anti-Patterns](https://cadence-lang.org/docs/anti-patterns) +- [Flow Core Contracts](https://developers.flow.com/build/core-contracts) + +## ๐Ÿค Community +- [Flow Community Forum](https://forum.onflow.org/) +- [Flow Discord](https://discord.gg/flow) +- [Flow Twitter](https://x.com/flow_blockchain)