diff --git a/CODEOWNERS b/CODEOWNERS index 15caf72..8dab471 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @chasefleming @bjartek \ No newline at end of file +* @chasefleming @bjartek @bthaile \ No newline at end of file diff --git a/README.md b/README.md index 57e6de5..1602b64 100644 --- a/README.md +++ b/README.md @@ -2,22 +2,24 @@ > FlixKit is a Go package that provides functionalities for interacting with Flow Interaction Templates (aka FLIX). Please note that this package is currently in alpha and may undergo significant changes. -The `flixkit` package is a Go module designed to interact with Flow Interaction Templates (FLIX). It allows users to fetch, parse, and handle Flow interaction templates. +The `flixkit` package is a Go module designed to interact with Flow Interaction Templates (FLIX). It allows users to fetch, parse, generate and create binding files for Flow interaction templates aka FLIX, aka Verified Interactions. ## Structures -The package provides a range of structs to represent data fetched from FLIX service: +See FLIP that descibes json structure, [Here](https://github.com/onflow/flips/blob/main/application/20230330-interaction-templates-1.1.0.md) current version is v1.1.0 -- `Network`: Contains information about a specific network like address, contract and pin. -- `Argument`: Represents the arguments that can be given to the contracts. -- `Title`, `Description`: Used for i18n (internationalization) purposes in messages. -- `Messages`: Contains a title and a description. -- `Data`: Provides detailed information about the Flow interaction template like type, interface, messages, dependencies and arguments. -- `FlowInteractionTemplate`: The main struct that contains all the details of a flow interaction template. +This package provides three functionalities. + - Getting network specific Cadence from FLIX + - Generate FLIX from Cadence + - Create binding files based on FLIX (javascript, typescript) The package also defines the following interfaces: - `FlixService`: This interface defines methods to interact with the FLIX service such as fetching raw data or parsed data by template name or template ID. +- `Generator`: This interface generates FLIX json given Cadence, metadata can be provided in two ways: + - prefilled out json + - Cadence docs in the form of a pragma +- `Bindings`: This interface has two implementations for javascript and typescript using fcl ## Usage @@ -25,16 +27,16 @@ The package provides a `FlixService` interface with a constructor function `NewF The `FlixService` interface provides the following methods: -- `GetFlixRaw(ctx context.Context, templateName string) (string, error)`: Fetches a raw Flix template by its name. -- `GetFlix(ctx context.Context, templateName string) (*FlowInteractionTemplate, error)`: Fetches and parses a Flix template by its name. -- `GetFlixByIDRaw(ctx context.Context, templateID string) (string, error)`: Fetches a raw Flix template by its ID. -- `GetFlixByID(ctx context.Context, templateID string) (*FlowInteractionTemplate, error)`: Fetches and parses a Flix template by its ID. +- `GetTemplate(ctx context.Context, templateName string) (string, error)`: Fetches template and returns as a string. +- `GetAndReplaceCadenceImports(ctx context.Context, templateName string, network string) (*FlowInteractionTemplateExecution, error)`: Fetches and parses a Flix template and provides the cadence for the network provided. -Each `FlowInteractionTemplate` instance also provides the following methods: +- Note: `templateName` parameter can be the id or name of a template from the interactive template service. A local file or url to the FLIX json file. + +Result form GetAndReplaceCadenceImports is a `FlowInteractionTemplateExecution` instance also provides the following methods: - `IsScript() bool`: Checks if the template is of type "script". - `IsTransaction() bool`: Checks if the template is of type "transaction". -- `GetAndReplaceCadenceImports(networkName string) (string, error)`: Replaces cadence import statements in the cadence script with their respective network addresses. +- `GetAndReplaceCadenceImports(networkName string) (string, error)`: Replaces cadence import statements in the cadence script or transaction with their respective network addresses. ## Examples @@ -43,7 +45,7 @@ Here is a simple example of creating a new FlixService and fetching a template: ```go flixService := flixkit.NewFlixService(&flixkit.Config{}) -template, err := flixService.GetFlix(context.Background(), "transfer-flow") +template, err := flixService.GetTemplate(context.Background(), "transfer-flow") if err != nil { log.Fatal(err) } @@ -66,14 +68,14 @@ The `bindings` module has two public methods `Generate` and `NewFclJSGenerator`. - `NewFclJSGenerator() *FclJSGenerator` // uses default fcl-js vanilla javascript - - `Generate(flix *flixkit.FlowInteractionTemplate, templateLocation string, isLocal bool) (string, error)` // flix is the hydrated template struct, templateLocation is the file location of the flix json file, isLocal is a flag that indicates if the template is local or on remote server + - `Generate(template string, templateLocation string) (string, error)` // flix is the hydrated template struct, templateLocation is the file location of the flix json file, isLocal is a flag that indicates if the template is local or on remote server ### Example ```go // uses default fcl-js templates -fclJsGen := bindings.NewFclJSGenerator() +fclJsGen := flixkit.NewFclJSGenerator() output, err := fclJsGen.Generate(template, flixQuery, isLocal) if err != nil { @@ -83,4 +85,58 @@ if err != nil { // output is the javascript binding code fmt.Println(output]) -``` \ No newline at end of file +``` + +## Generate + +> Generate creates the newest ratified version of FLIX, as of this update, v1.1 has been passed. Version 1.0.0 will be supported with `FlixService` and `bindings`. + +- `deployedContracts` is an array of v1_1.Contract structs of the contract dependencies the Cadence code depends on, Core contracts are already configured, look in `internal/contracts/core.go` for details + +### Example +```go +generator, err := flixkit.NewGenerator(deployedContracts, logger output.Logger) +// preFilledTemplate is a partially populated flix template with human readable messages +// see FLIX flip for details +prettyJSON, err := generator.Generate(ctx, string(code), preFilledTemplate) + +fmt.Println(prettyJSON) +``` +### Cadence docs pragma + +> Using Cadence pragma the metadata can live with the Cadence code. Therefore a prefilled template isn't necessary + +### Example + +```go +#interaction( + version: "1.1.0", + title: "Transfer Flow", + description: "Transfer Flow to account", + language: "en-US", + parameters: [ + Parameter( + name: "amount", + title: "Amount", + description: "Amount of Flow to transfer" + ), + Parameter( + name: "to", + title: "Reciever", + description: "Destination address to receive Flow Tokens" + ) + ], + ) + + import "FlowToken" + transaction(amount: UFix64, to: Address) { + let vault: @FlowToken.Vault + prepare(signer: AuthAccount) { + ... + } + } +` + +``` + +The pragma describes the transaction parameters and reason for the transaction. \ No newline at end of file diff --git a/bindings/fcl-js.go b/bindings/fcl-js.go deleted file mode 100644 index f2b1f94..0000000 --- a/bindings/fcl-js.go +++ /dev/null @@ -1,135 +0,0 @@ -package bindings - -import ( - "bytes" - "sort" - "text/template" - - "github.com/onflow/flixkit-go" - bindings "github.com/onflow/flixkit-go/bindings/templates" - "github.com/stoewer/go-strcase" -) - -type simpleParameter struct { - Name string - JsType string - Description string - FclType string - CadType string -} - -type templateData struct { - Version string - Parameters []simpleParameter - Title string - Description string - Location string - IsScript bool - IsLocalTemplate bool -} - -type FclJSGenerator struct { - Templates []string -} - -func NewFclJSGenerator() *FclJSGenerator { - templates := []string{ - bindings.GetJsFclMainTemplate(), - bindings.GetJsFclScriptTemplate(), - bindings.GetJsFclTxTemplate(), - } - - return &FclJSGenerator{ - Templates: templates, - } -} - -func (g FclJSGenerator) Generate(flix *flixkit.FlowInteractionTemplate, templateLocation string, isLocal bool) (string, error) { - tmpl, err := parseTemplates(g.Templates) - if err != nil { - return "", err - } - - methodName := strcase.LowerCamelCase(flix.Data.Messages.GetTitleValue("Request")) - description := flix.GetDescription() - data := templateData{ - Version: flix.FVersion, - Parameters: transformArguments(flix.Data.Arguments), - Title: methodName, - Description: description, - Location: templateLocation, - IsScript: flix.IsScript(), - IsLocalTemplate: isLocal, - } - - var buf bytes.Buffer - err = tmpl.Execute(&buf, data) - return buf.String(), err -} - -func transformArguments(args flixkit.Arguments) []simpleParameter { - simpleArgs := []simpleParameter{} - var keys []string - // get keys for sorting - for k := range args { - keys = append(keys, k) - } - - sort.SliceStable(keys, func(i, j int) bool { - return args[keys[i]].Index < args[keys[j]].Index - }) - for _, key := range keys { - arg := args[key] - isArray, cType, jsType := isArrayParameter(arg) - desciption := arg.Messages.GetTitleValue("") - if isArray { - simpleArgs = append(simpleArgs, simpleParameter{Name: key, CadType: cType, JsType: jsType, FclType: "Array(t." + cType + ")", Description: desciption}) - } else { - jsType := convertCadenceTypeToJS(arg.Type) - simpleArgs = append(simpleArgs, simpleParameter{Name: key, CadType: arg.Type, JsType: jsType, FclType: arg.Type, Description: desciption}) - } - } - return simpleArgs -} - -func isArrayParameter(arg flixkit.Argument) (isArray bool, cType string, jsType string) { - if arg.Type == "" || arg.Type[0] != '[' { - return false, "", "" - } - cadenceType := arg.Type[1 : len(arg.Type)-1] - javascriptType := "Array<" + convertCadenceTypeToJS(cadenceType) + ">" - return true, cadenceType, javascriptType -} - -func convertCadenceTypeToJS(cadenceType string) string { - // need to determine js type based on fcl supported types - // looking at fcl types and how arguments work as parameters - // https://github.com/onflow/fcl-js/blob/master/packages/types/src/types.js - switch cadenceType { - case "Bool": - return "boolean" - case "Void": - return "void" - case "Dictionary": - return "object" - case "Struct": - return "object" - case "Enum": - return "object" - default: - return "string" - } -} - -func parseTemplates(templates []string) (*template.Template, error) { - baseTemplate := template.New("base") - - for _, tmplStr := range templates { - _, err := baseTemplate.Parse(tmplStr) - if err != nil { - return nil, err - } - } - - return baseTemplate, nil -} diff --git a/bindings/fcl-js_test.go b/bindings/fcl-js_test.go deleted file mode 100644 index 6b6d5d9..0000000 --- a/bindings/fcl-js_test.go +++ /dev/null @@ -1,251 +0,0 @@ -package bindings - -import ( - "testing" - - "github.com/hexops/autogold/v2" - "github.com/onflow/flixkit-go" - bindings "github.com/onflow/flixkit-go/bindings/templates" - "github.com/stretchr/testify/assert" -) - -var parsedTemplateTX = &flixkit.FlowInteractionTemplate{ - FType: "InteractionTemplate", - FVersion: "1.0.0", - ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", - Data: flixkit.Data{ - Type: "transaction", - Interface: "", - Messages: flixkit.Messages{ - Title: &flixkit.Title{ - I18N: map[string]string{ - "en-US": "Transfer Tokens", - }, - }, - Description: &flixkit.Description{ - I18N: map[string]string{ - "en-US": "Transfer tokens from one account to another", - }, - }, - }, - Cadence: "import FungibleToken from 0xFUNGIBLETOKENADDRESS\ntransaction(amount: UFix64, to: Address) {\nlet vault: @FungibleToken.Vault\nprepare(signer: AuthAccount) {\nself.vault <- signer\n.borrow<&{FungibleToken.Provider}>(from: /storage/flowTokenVault)!\n.withdraw(amount: amount)\n}\nexecute {\ngetAccount(to)\n.getCapability(/public/flowTokenReceiver)!\n.borrow<&{FungibleToken.Receiver}>()!\n.deposit(from: <-self.vault)\n}\n}", - Dependencies: flixkit.Dependencies{ - "0xFUNGIBLETOKENADDRESS": flixkit.Contracts{ - "FungibleToken": flixkit.Networks{ - "mainnet": flixkit.Network{ - Address: "0xf233dcee88fe0abe", - FqAddress: "A.0xf233dcee88fe0abe.FungibleToken", - Contract: "FungibleToken", - Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - PinBlockHeight: 34166296, - }, - "testnet": flixkit.Network{ - Address: "0x9a0766d93b6608b7", - FqAddress: "A.0x9a0766d93b6608b7.FungibleToken", - Contract: "FungibleToken", - Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - PinBlockHeight: 74776482, - }, - }, - }, - }, - Arguments: flixkit.Arguments{ - "amount": flixkit.Argument{ - Index: 0, - Type: "UFix64", - Messages: flixkit.Messages{ - Title: &flixkit.Title{ - I18N: map[string]string{ - "en-US": "The amount of FLOW tokens to send", - }, - }, - }, - Balance: "", - }, - "to": flixkit.Argument{ - Index: 1, - Type: "Address", - Messages: flixkit.Messages{ - Title: &flixkit.Title{ - I18N: map[string]string{ - "en-US": "The Flow account the tokens will go to", - }, - }, - }, - Balance: "", - }, - }, - }, -} - -var parsedTemplateScript = &flixkit.FlowInteractionTemplate{ - FType: "InteractionTemplate", - FVersion: "1.0.0", - ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", - Data: flixkit.Data{ - Type: "script", - Interface: "", - Messages: flixkit.Messages{ - Title: &flixkit.Title{ - I18N: map[string]string{ - "en-US": "Multiply Two Integers", - }, - }, - Description: &flixkit.Description{ - I18N: map[string]string{ - "en-US": "Multiply two numbers to another", - }, - }, - }, - Cadence: "pub fun main(x: Int, y: Int): Int { return x * y }", - Arguments: flixkit.Arguments{ - "x": flixkit.Argument{ - Index: 0, - Type: "Int", - Messages: flixkit.Messages{ - Title: &flixkit.Title{ - I18N: map[string]string{ - "en-US": "number to be multiplied", - }, - }, - }, - Balance: "", - }, - "y": flixkit.Argument{ - Index: 1, - Type: "Int", - Messages: flixkit.Messages{ - Title: &flixkit.Title{ - I18N: map[string]string{ - "en-US": "second number to be multiplied", - }, - }, - }, - Balance: "", - }, - }, - }, -} - -var ArrayTypeScript = &flixkit.FlowInteractionTemplate{ - FType: "InteractionTemplate", - FVersion: "1.0.0", - ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", - Data: flixkit.Data{ - Type: "script", - Interface: "", - Messages: flixkit.Messages{ - Title: &flixkit.Title{ - I18N: map[string]string{ - "en-US": "Multiply Numbers", - }, - }, - Description: &flixkit.Description{ - I18N: map[string]string{ - "en-US": "Multiply numbers in an array", - }, - }, - }, - Cadence: "pub fun main(numbers: [Int]): Int { var total = 1; for x in numbers { total = total * x }; return total }", - Arguments: flixkit.Arguments{ - "numbers": flixkit.Argument{ - Index: 0, - Type: "[Int]", - Messages: flixkit.Messages{ - Title: &flixkit.Title{ - I18N: map[string]string{ - "en-US": "Array of numbers to be multiplied", - }, - }, - }, - Balance: "", - }, - }, - }, -} - -var minimumTemplate = &flixkit.FlowInteractionTemplate{ - FType: "InteractionTemplate", - FVersion: "1.0.0", - ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", - Data: flixkit.Data{ - Type: "script", - Interface: "", - Cadence: "pub fun main(numbers: [Int]): Int { var total = 1; for x in numbers { total = total * x }; return total }", - Arguments: flixkit.Arguments{ - "numbers": flixkit.Argument{ - Index: 0, - Type: "[Int]", - }, - }, - }, -} - -var minimumNoParamTemplate = &flixkit.FlowInteractionTemplate{ - FType: "InteractionTemplate", - FVersion: "1.0.0", - ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", - Data: flixkit.Data{ - Type: "script", - Interface: "", - Cadence: "pub fun main(): Int { return 1 }", - }, -} - -func TestJSGenTransaction(t *testing.T) { - generator := FclJSGenerator{ - Templates: []string{ - bindings.GetJsFclMainTemplate(), - bindings.GetJsFclScriptTemplate(), - bindings.GetJsFclTxTemplate(), - }, - } - got, _ := generator.Generate(parsedTemplateTX, "./transfer_token.json", true) - autogold.ExpectFile(t, got) -} - -func TestJSGenScript(t *testing.T) { - generator := FclJSGenerator{ - Templates: []string{ - bindings.GetJsFclMainTemplate(), - bindings.GetJsFclScriptTemplate(), - bindings.GetJsFclTxTemplate(), - }, - } - assert := assert.New(t) - got, err := generator.Generate(parsedTemplateScript, "./multiply_two_integers.template.json", true) - assert.NoError(err, "ParseTemplate should not return an error") - autogold.ExpectFile(t, got) -} - -func TestJSGenArrayScript(t *testing.T) { - generator := FclJSGenerator{ - Templates: []string{ - bindings.GetJsFclMainTemplate(), - bindings.GetJsFclScriptTemplate(), - bindings.GetJsFclTxTemplate(), - }, - } - assert := assert.New(t) - - out, err := generator.Generate(ArrayTypeScript, "./multiply-numbers.template.json", true) - assert.NoError(err, "ParseTemplate should not return an error") - autogold.ExpectFile(t, out) -} - -func TestJSGenMinScript(t *testing.T) { - generator := NewFclJSGenerator() - assert := assert.New(t) - - out, err := generator.Generate(minimumTemplate, "./min.template.json", true) - assert.NoError(err, "ParseTemplate should not return an error") - autogold.ExpectFile(t, out) -} -func TestJSGenNoParamsScript(t *testing.T) { - generator := NewFclJSGenerator() - assert := assert.New(t) - - out, err := generator.Generate(minimumNoParamTemplate, "./min.template.json", true) - assert.NoError(err, "ParseTemplate should not return an error") - autogold.ExpectFile(t, out) -} diff --git a/flixkit.go b/flixkit.go deleted file mode 100644 index 35084a3..0000000 --- a/flixkit.go +++ /dev/null @@ -1,116 +0,0 @@ -package flixkit - -import ( - "context" - "encoding/json" - "fmt" - "io" - "io/fs" - "log" - "net/http" -) - -type Generator interface { - Generate(ctx context.Context, code string, preFill *FlowInteractionTemplate) (*FlowInteractionTemplate, error) -} - -type FlixService interface { - GetFlixRaw(ctx context.Context, templateName string) (string, error) - GetFlix(ctx context.Context, templateName string) (*FlowInteractionTemplate, error) - GetFlixByIDRaw(ctx context.Context, templateID string) (string, error) - GetFlixByID(ctx context.Context, templateID string) (*FlowInteractionTemplate, error) -} - -type flixServiceImpl struct { - config *Config -} - -var _ FlixService = (*flixServiceImpl)(nil) - -type Config struct { - FlixServerURL string - FileReader fs.ReadFileFS -} - -func NewFlixService(config *Config) FlixService { - if config.FlixServerURL == "" { - config.FlixServerURL = "https://flix.flow.com/v1/templates" - } - - return &flixServiceImpl{ - config: config, - } -} - -func (s *flixServiceImpl) GetFlixRaw(ctx context.Context, templateName string) (string, error) { - url := fmt.Sprintf("%s?name=%s", s.config.FlixServerURL, templateName) - return FetchFlixWithContext(ctx, url) -} - -func (s *flixServiceImpl) GetFlix(ctx context.Context, templateName string) (*FlowInteractionTemplate, error) { - template, err := s.GetFlixRaw(ctx, templateName) - if err != nil { - return nil, err - } - - parsedTemplate, err := ParseFlix(template) - if err != nil { - return nil, err - } - - return parsedTemplate, nil -} - -func (s *flixServiceImpl) GetFlixByIDRaw(ctx context.Context, templateID string) (string, error) { - url := fmt.Sprintf("%s/%s", s.config.FlixServerURL, templateID) - return FetchFlixWithContext(ctx, url) -} - -func (s *flixServiceImpl) GetFlixByID(ctx context.Context, templateID string) (*FlowInteractionTemplate, error) { - template, err := s.GetFlixByIDRaw(ctx, templateID) - if err != nil { - return nil, err - } - - parsedTemplate, err := ParseFlix(template) - if err != nil { - return nil, err - } - - return parsedTemplate, nil -} - -func ParseFlix(template string) (*FlowInteractionTemplate, error) { - var flowTemplate FlowInteractionTemplate - - err := json.Unmarshal([]byte(template), &flowTemplate) - if err != nil { - return nil, err - } - - return &flowTemplate, nil -} - -func FetchFlixWithContext(ctx context.Context, url string) (string, error) { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { - return "", err - } - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return "", err - } - defer func() { - if err := resp.Body.Close(); err != nil { - log.Printf("Warning: error while closing the response body: %v", err) - } - }() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", err - } - - return string(body), nil -} diff --git a/flixkit/fcl_bindings.go b/flixkit/fcl_bindings.go new file mode 100644 index 0000000..535faa1 --- /dev/null +++ b/flixkit/fcl_bindings.go @@ -0,0 +1,258 @@ +package flixkit + +import ( + "bytes" + "fmt" + "sort" + "text/template" + + v1 "github.com/onflow/flixkit-go/flixkit/v1" + v1_1 "github.com/onflow/flixkit-go/flixkit/v1_1" + "github.com/onflow/flixkit-go/internal/templates" + "github.com/stoewer/go-strcase" +) + +func NewFclTSGenerator() *FclGenerator { + t := []string{ + templates.GetTsFclMainTemplate(), + templates.GetTsFclScriptTemplate(), + templates.GetTsFclTxTemplate(), + templates.GetTsFclParamsTemplate(), + templates.GetTsFclInterfaceTemplate(), + } + + return &FclGenerator{ + Templates: t, + } +} + +func NewFclJSGenerator() *FclGenerator { + t := []string{ + templates.GetJsFclMainTemplate(), + templates.GetJsFclScriptTemplate(), + templates.GetJsFclTxTemplate(), + templates.GetJsFclParamsTemplate(), + } + + return &FclGenerator{ + Templates: t, + } +} + +func (g *FclGenerator) Generate(flixString string, templateLocation string) (string, error) { + tmpl, err := parseTemplates(g.Templates) + if err != nil { + return "", err + } + if flixString == "" { + return "", fmt.Errorf("no flix template provided") + } + + ver, err := GetTemplateVersion(flixString) + if err != nil { + return "", fmt.Errorf("invalid flix template version, %w", err) + } + + isLocal := !isUrl(templateLocation) + var data templateData + switch ver { + case "1.0.0": + + flix, err := v1.ParseFlix(flixString) + if err != nil { + return "", err + } + data = getTemplateDataV1_0(flix, templateLocation, isLocal) + case "1.1.0": + flix, err := v1_1.ParseFlix(flixString) + if err != nil { + return "", err + } + data = getTemplateDataV1_1(flix, templateLocation, isLocal) + default: + return "", fmt.Errorf("invalid flix template version: %s", ver) + } + + data.FclVersion = GetFlixFclCompatibility(ver) + var buf bytes.Buffer + err = tmpl.Execute(&buf, data) + return buf.String(), err +} + +type simpleParameter struct { + Name string + JsType string + Description string + FclType string + CadType string +} + +type templateData struct { + FclVersion string + Version string + Parameters []simpleParameter + ParametersPrefixName string + Output simpleParameter + Title string + Description string + Location string + IsScript bool + IsLocalTemplate bool +} + +type FclGenerator struct { + Templates []string +} + +type FlixParameter struct { + Name string + Type string +} + +func GetFlixFclCompatibility(flixVersion string) string { + compatibleVersions := map[string]string{ + "1.0.0": "1.3.0", + "1.1.0": "1.9.0", + // add more versions here + } + v, ok := compatibleVersions[flixVersion] + if !ok { + // default to latest if flix version not configured + return "1.9.0" + } + return v +} + +func getTemplateDataV1_1(flix *v1_1.InteractionTemplate, templateLocation string, isLocal bool) templateData { + var msgs v1_1.InteractionTemplateMessages = flix.Data.Messages + title := msgs.GetTitle("Request") + methodName := strcase.LowerCamelCase(title) + description := msgs.GetDescription("") + result := simpleParameter{} + if flix.Data.Output != nil { + o := transformParameters([]v1_1.Parameter{*flix.Data.Output}) + if len(o) > 0 { + result = o[0] + } + } + data := templateData{ + Version: flix.FVersion, + Parameters: transformParameters(flix.Data.Parameters), + ParametersPrefixName: strcase.UpperCamelCase(title), + Output: result, + Title: methodName, + Description: description, + Location: templateLocation, + IsScript: flix.IsScript(), + IsLocalTemplate: isLocal, + } + return data +} + +func getTemplateDataV1_0(flix *v1.FlowInteractionTemplate, templateLocation string, isLocal bool) templateData { + title := flix.Data.Messages.GetTitleValue("Request") + methodName := strcase.LowerCamelCase(title) + description := flix.GetDescription() + + data := templateData{ + Version: flix.FVersion, + Parameters: transformArguments(flix.Data.Arguments), + ParametersPrefixName: strcase.UpperCamelCase(title), + Title: methodName, + Description: description, + Location: templateLocation, + IsScript: flix.IsScript(), + IsLocalTemplate: isLocal, + } + return data +} + +func convertCadenceTypeToJS(cadenceType string) string { + // need to determine js type based on fcl supported types + // looking at fcl types and how arguments work as parameters + // https://github.com/onflow/fcl-js/blob/master/packages/types/src/types.js + switch cadenceType { + case "Bool": + return "boolean" + case "Void": + return "void" + case "Dictionary": + return "object" + case "Struct": + return "object" + case "Enum": + return "object" + default: + return "string" + } +} + +func parseTemplates(templates []string) (*template.Template, error) { + baseTemplate := template.New("base") + + for _, tmplStr := range templates { + _, err := baseTemplate.Parse(tmplStr) + if err != nil { + return nil, err + } + } + + return baseTemplate, nil +} + +func transformParameters(args []v1_1.Parameter) []simpleParameter { + simpleArgs := []simpleParameter{} + if len(args) == 0 { + return simpleArgs + } + sort.Slice(args, func(i, j int) bool { + return args[i].Index < args[j].Index + }) + + for _, arg := range args { + isArray, cType, jsType := isArrayParameter(FlixParameter{Name: arg.Label, Type: arg.Type}) + var msgs v1_1.InteractionTemplateMessages = arg.Messages + desciption := msgs.GetDescription("") + if isArray { + simpleArgs = append(simpleArgs, simpleParameter{Name: arg.Label, CadType: cType, JsType: jsType, FclType: "Array(t." + cType + ")", Description: desciption}) + } else { + jsType := convertCadenceTypeToJS(arg.Type) + simpleArgs = append(simpleArgs, simpleParameter{Name: arg.Label, CadType: arg.Type, JsType: jsType, FclType: arg.Type, Description: desciption}) + } + } + return simpleArgs +} + +func transformArguments(args v1.Arguments) []simpleParameter { + simpleArgs := []simpleParameter{} + var keys []string + // get keys for sorting + for k := range args { + keys = append(keys, k) + } + + sort.SliceStable(keys, func(i, j int) bool { + return args[keys[i]].Index < args[keys[j]].Index + }) + for _, key := range keys { + arg := args[key] + isArray, cType, jsType := isArrayParameter(FlixParameter{Name: key, Type: arg.Type}) + desciption := arg.Messages.GetTitleValue("") + if isArray { + simpleArgs = append(simpleArgs, simpleParameter{Name: key, CadType: cType, JsType: jsType, FclType: "Array(t." + cType + ")", Description: desciption}) + } else { + jsType := convertCadenceTypeToJS(arg.Type) + simpleArgs = append(simpleArgs, simpleParameter{Name: key, CadType: arg.Type, JsType: jsType, FclType: arg.Type, Description: desciption}) + } + } + return simpleArgs +} + +func isArrayParameter(arg FlixParameter) (isArray bool, cType string, jsType string) { + if arg.Type == "" || arg.Type[0] != '[' { + return false, "", "" + } + cadenceType := arg.Type[1 : len(arg.Type)-1] + javascriptType := "Array<" + convertCadenceTypeToJS(cadenceType) + ">" + return true, cadenceType, javascriptType +} diff --git a/flixkit/fcl_bindings_test.go b/flixkit/fcl_bindings_test.go new file mode 100644 index 0000000..5e5fbed --- /dev/null +++ b/flixkit/fcl_bindings_test.go @@ -0,0 +1,460 @@ +package flixkit + +import ( + "encoding/json" + "testing" + + "github.com/hexops/autogold/v2" + v1 "github.com/onflow/flixkit-go/flixkit/v1" + v1_1 "github.com/onflow/flixkit-go/flixkit/v1_1" + "github.com/onflow/flixkit-go/internal/templates" + "github.com/stretchr/testify/assert" +) + +var parsedTemplateTX = &v1.FlowInteractionTemplate{ + FType: "InteractionTemplate", + FVersion: "1.0.0", + ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", + Data: v1.Data{ + Type: "transaction", + Interface: "", + Messages: v1.Messages{ + Title: &v1.Title{ + I18N: map[string]string{ + "en-US": "Transfer Tokens", + }, + }, + Description: &v1.Description{ + I18N: map[string]string{ + "en-US": "Transfer tokens from one account to another", + }, + }, + }, + Cadence: "import FungibleToken from 0xFUNGIBLETOKENADDRESS\ntransaction(amount: UFix64, to: Address) {\nlet vault: @FungibleToken.Vault\nprepare(signer: AuthAccount) {\nself.vault <- signer\n.borrow<&{FungibleToken.Provider}>(from: /storage/flowTokenVault)!\n.withdraw(amount: amount)\n}\nexecute {\ngetAccount(to)\n.getCapability(/public/flowTokenReceiver)!\n.borrow<&{FungibleToken.Receiver}>()!\n.deposit(from: <-self.vault)\n}\n}", + Dependencies: v1.Dependencies{ + "0xFUNGIBLETOKENADDRESS": v1.Contracts{ + "FungibleToken": v1.Networks{ + "mainnet": v1.Network{ + Address: "0xf233dcee88fe0abe", + FqAddress: "A.0xf233dcee88fe0abe.FungibleToken", + Contract: "FungibleToken", + Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", + PinBlockHeight: 34166296, + }, + "testnet": v1.Network{ + Address: "0x9a0766d93b6608b7", + FqAddress: "A.0x9a0766d93b6608b7.FungibleToken", + Contract: "FungibleToken", + Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", + PinBlockHeight: 74776482, + }, + }, + }, + }, + Arguments: v1.Arguments{ + "amount": v1.Argument{ + Index: 0, + Type: "UFix64", + Messages: v1.Messages{ + Title: &v1.Title{ + I18N: map[string]string{ + "en-US": "The amount of FLOW tokens to send", + }, + }, + }, + Balance: "", + }, + "to": v1.Argument{ + Index: 1, + Type: "Address", + Messages: v1.Messages{ + Title: &v1.Title{ + I18N: map[string]string{ + "en-US": "The Flow account the tokens will go to", + }, + }, + }, + Balance: "", + }, + }, + }, +} + +var parsedTemplateScript = &v1.FlowInteractionTemplate{ + FType: "InteractionTemplate", + FVersion: "1.0.0", + ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", + Data: v1.Data{ + Type: "script", + Interface: "", + Messages: v1.Messages{ + Title: &v1.Title{ + I18N: map[string]string{ + "en-US": "Multiply Two Integers", + }, + }, + Description: &v1.Description{ + I18N: map[string]string{ + "en-US": "Multiply two numbers to another", + }, + }, + }, + Cadence: "pub fun main(x: Int, y: Int): Int { return x * y }", + Arguments: v1.Arguments{ + "x": v1.Argument{ + Index: 0, + Type: "Int", + Messages: v1.Messages{ + Title: &v1.Title{ + I18N: map[string]string{ + "en-US": "number to be multiplied", + }, + }, + }, + Balance: "", + }, + "y": v1.Argument{ + Index: 1, + Type: "Int", + Messages: v1.Messages{ + Title: &v1.Title{ + I18N: map[string]string{ + "en-US": "second number to be multiplied", + }, + }, + }, + Balance: "", + }, + }, + }, +} + +var ArrayTypeScript = &v1.FlowInteractionTemplate{ + FType: "InteractionTemplate", + FVersion: "1.0.0", + ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", + Data: v1.Data{ + Type: "script", + Interface: "", + Messages: v1.Messages{ + Title: &v1.Title{ + I18N: map[string]string{ + "en-US": "Multiply Numbers", + }, + }, + Description: &v1.Description{ + I18N: map[string]string{ + "en-US": "Multiply numbers in an array", + }, + }, + }, + Cadence: "pub fun main(numbers: [Int]): Int { var total = 1; for x in numbers { total = total * x }; return total }", + Arguments: v1.Arguments{ + "numbers": v1.Argument{ + Index: 0, + Type: "[Int]", + Messages: v1.Messages{ + Title: &v1.Title{ + I18N: map[string]string{ + "en-US": "Array of numbers to be multiplied", + }, + }, + }, + Balance: "", + }, + }, + }, +} + +var minimumTemplate = &v1.FlowInteractionTemplate{ + FType: "InteractionTemplate", + FVersion: "1.0.0", + ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", + Data: v1.Data{ + Type: "script", + Interface: "", + Cadence: "pub fun main(numbers: [Int]): Int { var total = 1; for x in numbers { total = total * x }; return total }", + Arguments: v1.Arguments{ + "numbers": v1.Argument{ + Index: 0, + Type: "[Int]", + }, + }, + }, +} + +var minimumNoParamTemplate = &v1.FlowInteractionTemplate{ + FType: "InteractionTemplate", + FVersion: "1.0.0", + ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", + Data: v1.Data{ + Type: "script", + Interface: "", + Cadence: "pub fun main(): Int { return 1 }", + }, +} + +func TestJSGenTransaction(t *testing.T) { + ttemp, err := json.Marshal(parsedTemplateTX) + assert.NoError(t, err, "marshal template to json should not return an error") + generator := FclGenerator{ + Templates: []string{ + templates.GetJsFclMainTemplate(), + templates.GetJsFclScriptTemplate(), + templates.GetJsFclTxTemplate(), + templates.GetJsFclParamsTemplate(), + }, + } + got, _ := generator.Generate(string(ttemp), "./transfer_token.json") + autogold.ExpectFile(t, got) +} + +func TestJSGenScript(t *testing.T) { + ttemp, err := json.Marshal(parsedTemplateScript) + assert.NoError(t, err, "marshal template to json should not return an error") + + generator := FclGenerator{ + Templates: []string{ + templates.GetJsFclMainTemplate(), + templates.GetJsFclScriptTemplate(), + templates.GetJsFclTxTemplate(), + templates.GetJsFclParamsTemplate(), + }, + } + assert := assert.New(t) + got, err := generator.Generate(string(ttemp), "./multiply_two_integers.template.json") + assert.NoError(err, "ParseTemplate should not return an error") + autogold.ExpectFile(t, got) +} + +func TestJSGenArrayScript(t *testing.T) { + ttemp, err := json.Marshal(ArrayTypeScript) + assert.NoError(t, err, "marshal template to json should not return an error") + + generator := FclGenerator{ + Templates: []string{ + templates.GetJsFclMainTemplate(), + templates.GetJsFclScriptTemplate(), + templates.GetJsFclTxTemplate(), + templates.GetJsFclParamsTemplate(), + }, + } + assert := assert.New(t) + + out, err := generator.Generate(string(ttemp), "./multiply-numbers.template.json") + assert.NoError(err, "ParseTemplate should not return an error") + autogold.ExpectFile(t, out) +} + +func TestJSGenMinScript(t *testing.T) { + ttemp, err := json.Marshal(minimumTemplate) + assert.NoError(t, err, "marshal template to json should not return an error") + + generator := NewFclJSGenerator() + assert := assert.New(t) + + out, err := generator.Generate(string(ttemp), "./min.template.json") + assert.NoError(err, "ParseTemplate should not return an error") + autogold.ExpectFile(t, out) +} +func TestJSGenNoParamsScript(t *testing.T) { + ttemp, err := json.Marshal(minimumNoParamTemplate) + assert.NoError(t, err, "marshal template to json should not return an error") + + generator := NewFclJSGenerator() + assert := assert.New(t) + + out, err := generator.Generate(string(ttemp), "./min.template.json") + assert.NoError(err, "ParseTemplate should not return an error") + autogold.ExpectFile(t, out) +} + +var minimumNoParamTemplateTS_SCRIPT = &v1_1.InteractionTemplate{ + FType: "InteractionTemplate", + FVersion: "1.1.0", + ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", + Data: v1_1.Data{ + Type: "script", + Interface: "", + Cadence: v1_1.Cadence{ + Body: "pub fun main(): Int { return 1 }", + NetworkPins: []v1_1.NetworkPin{}, + }, + Output: &v1_1.Parameter{ + Label: "result", + Type: "Int", + Messages: []v1_1.Message{ + { + Key: "description", + I18n: []v1_1.I18n{ + { + Tag: "en-US", + Translation: "Result of some number plus one", + }, + }, + }, + }, + }, + }, +} + +var minimumNoParamTemplateTS_TX = &v1_1.InteractionTemplate{ + FType: "InteractionTemplate", + FVersion: "1.1.0", + ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", + Data: v1_1.Data{ + Type: "transaction", + Interface: "", + Cadence: v1_1.Cadence{ + Body: "import \"HelloWorld\"\n\n#interaction (\n version: \"1.1.0\",\n\ttitle: \"Update Greeting\",\n\tdescription: \"Update the greeting on the HelloWorld contract\",\n\tlanguage: \"en-US\",\n)\ntransaction() {\n\n prepare(acct: AuthAccount) {\n }\n\n execute {\n \n }\n}\n", + NetworkPins: []v1_1.NetworkPin{}, + }, + }, +} + +var minimumParamTemplateTS_SCRIPT = &v1_1.InteractionTemplate{ + FType: "InteractionTemplate", + FVersion: "1.1.0", + ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", + Data: v1_1.Data{ + Type: "script", + Interface: "", + Cadence: v1_1.Cadence{ + Body: "pub fun main(someNumber Int): Int { return 1 + someNumber }", + NetworkPins: []v1_1.NetworkPin{}, + }, + Parameters: []v1_1.Parameter{ + { + Label: "someNumber", + Index: 0, + Type: "Int", + Messages: []v1_1.Message{ + { + Key: "title", + I18n: []v1_1.I18n{ + { + Tag: "en-US", + Translation: "Some Number", + }, + }, + }, + }, + }, + }, + Output: &v1_1.Parameter{ + Label: "result", + Type: "Int", + Messages: []v1_1.Message{ + { + Key: "description", + I18n: []v1_1.I18n{ + { + Tag: "en-US", + Translation: "Result of some number plus one", + }, + }, + }, + }, + }, + }, +} + +var minimumParamTemplateTS_TX = &v1_1.InteractionTemplate{ + FType: "InteractionTemplate", + FVersion: "1.1.0", + ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", + Data: v1_1.Data{ + Type: "transaction", + Interface: "", + Cadence: v1_1.Cadence{ + Body: "import \"HelloWorld\"\n\n#interaction (\n version: \"1.1.0\",\n\ttitle: \"Update Greeting\",\n\tdescription: \"Update the greeting on the HelloWorld contract\",\n\tlanguage: \"en-US\",\n\tparameters: [\n\t\tParameter(\n\t\t\tname: \"greeting\", \n\t\t\ttitle: \"Greeting\", \n\t\t\tdescription: \"The greeting to set on the HelloWorld contract\"\n\t\t)\n\t],\n)\ntransaction(greeting: String) {\n\n prepare(acct: AuthAccount) {\n log(acct.address)\n }\n\n execute {\n HelloWorld.updateGreeting(newGreeting: greeting)\n }\n}\n", + NetworkPins: []v1_1.NetworkPin{}, + }, + Messages: []v1_1.Message{ + { + Key: "title", + I18n: []v1_1.I18n{ + { + Tag: "en-US", + Translation: "Update Greeting", + }, + }, + }, + { + Key: "description", + I18n: []v1_1.I18n{ + { + Tag: "en-US", + Translation: "Update HelloWorld Greeting", + }, + }, + }, + }, + Parameters: []v1_1.Parameter{ + { + Label: "greeting", + Index: 0, + Type: "String", + Messages: []v1_1.Message{ + { + Key: "title", + I18n: []v1_1.I18n{ + { + Tag: "en-US", + Translation: "Greeting", + }, + }, + }, + }, + }, + }, + }, +} + +func TestTSGenNoParamsScript(t *testing.T) { + ttemp, err := json.Marshal(minimumNoParamTemplateTS_SCRIPT) + assert.NoError(t, err, "marshal template to json should not return an error") + + generator := NewFclTSGenerator() + assert := assert.New(t) + + out, err := generator.Generate(string(ttemp), "./min.template.json") + assert.NoError(err, "ParseTemplate should not return an error") + autogold.ExpectFile(t, out) +} + +func TestTSGenNoParamsTx(t *testing.T) { + ttemp, err := json.Marshal(minimumNoParamTemplateTS_TX) + assert.NoError(t, err, "marshal template to json should not return an error") + + generator := NewFclTSGenerator() + assert := assert.New(t) + + out, err := generator.Generate(string(ttemp), "./min.template.json") + assert.NoError(err, "ParseTemplate should not return an error") + autogold.ExpectFile(t, out) +} + +func TestTSGenParamsScript(t *testing.T) { + ttemp, err := json.Marshal(minimumParamTemplateTS_SCRIPT) + assert.NoError(t, err, "marshal template to json should not return an error") + + generator := NewFclTSGenerator() + assert := assert.New(t) + + out, err := generator.Generate(string(ttemp), "./min.template.json") + assert.NoError(err, "ParseTemplate should not return an error") + autogold.ExpectFile(t, out) +} + +func TestTSGenParamsTx(t *testing.T) { + ttemp, err := json.Marshal(minimumParamTemplateTS_TX) + assert.NoError(t, err, "marshal template to json should not return an error") + + generator := NewFclTSGenerator() + assert := assert.New(t) + + out, err := generator.Generate(string(ttemp), "./min.template.json") + assert.NoError(err, "ParseTemplate should not return an error") + autogold.ExpectFile(t, out) +} diff --git a/flixkit/flixkit.go b/flixkit/flixkit.go new file mode 100644 index 0000000..13d2d36 --- /dev/null +++ b/flixkit/flixkit.go @@ -0,0 +1,276 @@ +package flixkit + +import ( + "context" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "net/url" + "os" + + v1 "github.com/onflow/flixkit-go/flixkit/v1" + v1_1 "github.com/onflow/flixkit-go/flixkit/v1_1" +) + +type FlowInteractionTemplateExecution struct { + Network string + Cadence string + IsTransaciton bool + IsScript bool +} + +type FlowInteractionTemplateVersion struct { + FVersion string `json:"f_version"` +} + +type GenerateTemplate interface { + Generate(ctx context.Context, code string, preFill string) (string, error) +} + +type GenerateBinding interface { + Generate(flixString string, templateLocation string) (string, error) +} + +type FlowInteractionTemplateCadence interface { + GetAndReplaceCadenceImports(templateName string) (string, error) + IsTransaction() bool + IsScript() bool +} + +type FlixService interface { + GetTemplate(ctx context.Context, templateName string) (string, error) + GetAndReplaceCadenceImports(ctx context.Context, templateName string, network string) (*FlowInteractionTemplateExecution, error) +} + +type flixServiceImpl struct { + config *Config +} + +var _ FlixService = (*flixServiceImpl)(nil) + +type FileReader interface { + ReadFile(path string) ([]byte, error) +} + +type Config struct { + FlixServerURL string + FileReader FileReader +} + +func NewFlixService(config *Config) FlixService { + if config.FlixServerURL == "" { + config.FlixServerURL = "https://flix.flow.com/v1/templates" + } + + return &flixServiceImpl{ + config: config, + } +} + +func (s *flixServiceImpl) GetFlixRaw(ctx context.Context, templateName string) (string, error) { + url := fmt.Sprintf("%s?name=%s", s.config.FlixServerURL, templateName) + return FetchFlixWithContext(ctx, url) +} + +func (s *flixServiceImpl) GetFlix(ctx context.Context, templateName string) (string, error) { + template, err := s.GetFlixRaw(ctx, templateName) + if err != nil { + return "", err + } + + return template, nil +} + +func (s *flixServiceImpl) GetFlixByIDRaw(ctx context.Context, templateID string) (string, error) { + url := fmt.Sprintf("%s/%s", s.config.FlixServerURL, templateID) + return FetchFlixWithContext(ctx, url) +} + +func (s *flixServiceImpl) GetFlixByID(ctx context.Context, templateID string) (string, error) { + template, err := s.GetFlixByIDRaw(ctx, templateID) + if err != nil { + return "", err + } + return template, nil +} + +func GetTemplateVersion(template string) (string, error) { + var flowTemplate FlowInteractionTemplateVersion + + err := json.Unmarshal([]byte(template), &flowTemplate) + if err != nil { + return "", err + } + + if flowTemplate.FVersion == "" { + return "", fmt.Errorf("version not found") + } + + return flowTemplate.FVersion, nil +} + +func FetchFlixWithContext(ctx context.Context, url string) (string, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + return "", err + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return "", err + } + defer func() { + if err := resp.Body.Close(); err != nil { + log.Printf("Warning: error while closing the response body: %v", err) + } + }() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + return string(body), nil +} + +func (s *flixServiceImpl) GetAndReplaceCadenceImports(ctx context.Context, templateName string, network string) (*FlowInteractionTemplateExecution, error) { + template, err := s.GetTemplate(ctx, templateName) + if err != nil { + return nil, err + } + var execution FlowInteractionTemplateExecution + var cadenceCode string + ver, err := GetTemplateVersion(template) + if err != nil { + return nil, fmt.Errorf("invalid flix template version, %w", err) + } + var replaceableCadence FlowInteractionTemplateCadence + switch ver { + case "1.1.0": + replaceableCadence, err = v1_1.ParseFlix(template) + if err != nil { + return nil, err + } + cadenceCode, err = replaceableCadence.GetAndReplaceCadenceImports(network) + if err != nil { + return nil, err + } + execution.Cadence = cadenceCode + execution.IsScript = replaceableCadence.IsScript() + execution.IsTransaciton = replaceableCadence.IsTransaction() + case "1.0.0": + replaceableCadence, err = v1.ParseFlix(template) + if err != nil { + return nil, err + } + cadenceCode, err = replaceableCadence.GetAndReplaceCadenceImports(network) + if err != nil { + return nil, err + } + execution.Cadence = cadenceCode + execution.IsScript = replaceableCadence.IsScript() + execution.IsTransaciton = replaceableCadence.IsTransaction() + default: + return nil, fmt.Errorf("flix template version: %s not supported", ver) + } + + if execution.Cadence == "" { + return nil, fmt.Errorf("could not parse template, invalid flix template") + } + + return &execution, nil +} + +type flixQueryTypes string + +const ( + flixName flixQueryTypes = "name" + flixPath flixQueryTypes = "path" + flixId flixQueryTypes = "id" + flixUrl flixQueryTypes = "url" + flixJson flixQueryTypes = "json" +) + +func isHex(str string) bool { + if len(str) != 64 { + return false + } + _, err := hex.DecodeString(str) + return err == nil +} + +func isPath(path string) bool { + _, err := os.Stat(path) + return err == nil +} + +func isUrl(str string) bool { + u, err := url.Parse(str) + return err == nil && u.Scheme != "" && u.Host != "" +} + +func isJson(str string) bool { + var js json.RawMessage + return json.Unmarshal([]byte(str), &js) == nil +} + +func getType(s string) flixQueryTypes { + switch { + case isPath(s): + return flixPath + case isHex(s): + return flixId + case isUrl(s): + return flixUrl + case isJson(s): + return flixJson + default: + return flixName + } +} + +func (s *flixServiceImpl) GetTemplate(ctx context.Context, flixQuery string) (string, error) { + var template string + var err error + + switch getType(flixQuery) { + case flixId: + template, err = s.GetFlixByID(ctx, flixQuery) + if err != nil { + return "", fmt.Errorf("could not find flix with id %s: %w", flixQuery, err) + } + + case flixName: + template, err = s.GetFlix(ctx, flixQuery) + if err != nil { + return "", fmt.Errorf("could not find flix with name %s: %w", flixQuery, err) + } + + case flixPath: + if s.config.FileReader == nil { + return "", fmt.Errorf("file reader not provided") + } + file, err := s.config.FileReader.ReadFile(flixQuery) + if err != nil { + return "", fmt.Errorf("could not read flix file %s: %w", flixQuery, err) + } + template = string(file) + if err != nil { + return "", fmt.Errorf("could not parse flix from file %s: %w", flixQuery, err) + } + + case flixUrl: + template, err = FetchFlixWithContext(ctx, flixQuery) + if err != nil { + return "", fmt.Errorf("could not parse flix from url %s: %w", flixQuery, err) + } + + default: + return "", fmt.Errorf("invalid flix query type: %s", flixQuery) + } + + return template, nil +} diff --git a/flixkit_test.go b/flixkit/flixkit_test.go similarity index 76% rename from flixkit_test.go rename to flixkit/flixkit_test.go index 06fb662..6831818 100644 --- a/flixkit_test.go +++ b/flixkit/flixkit_test.go @@ -2,11 +2,11 @@ package flixkit import ( "context" - "io/fs" "net/http" "net/http/httptest" "testing" + v1 "github.com/onflow/flixkit-go/flixkit/v1" "github.com/stretchr/testify/assert" ) @@ -79,37 +79,37 @@ var flix_template = `{ } }` -var parsedTemplate = &FlowInteractionTemplate{ +var parsedTemplate = &v1.FlowInteractionTemplate{ FType: "InteractionTemplate", FVersion: "1.0.0", ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", - Data: Data{ + Data: v1.Data{ Type: "transaction", Interface: "", - Messages: Messages{ - Title: &Title{ + Messages: v1.Messages{ + Title: &v1.Title{ I18N: map[string]string{ "en-US": "Transfer Tokens", }, }, - Description: &Description{ + Description: &v1.Description{ I18N: map[string]string{ "en-US": "Transfer tokens from one account to another", }, }, }, Cadence: "import FungibleToken from 0xFUNGIBLETOKENADDRESS\ntransaction(amount: UFix64, to: Address) {\nlet vault: @FungibleToken.Vault\nprepare(signer: AuthAccount) {\nself.vault <- signer\n.borrow<&{FungibleToken.Provider}>(from: /storage/flowTokenVault)!\n.withdraw(amount: amount)\n}\nexecute {\ngetAccount(to)\n.getCapability(/public/flowTokenReceiver)!\n.borrow<&{FungibleToken.Receiver}>()!\n.deposit(from: <-self.vault)\n}\n}", - Dependencies: Dependencies{ - "0xFUNGIBLETOKENADDRESS": Contracts{ - "FungibleToken": Networks{ - "mainnet": Network{ + Dependencies: v1.Dependencies{ + "0xFUNGIBLETOKENADDRESS": v1.Contracts{ + "FungibleToken": v1.Networks{ + "mainnet": v1.Network{ Address: "0xf233dcee88fe0abe", FqAddress: "A.0xf233dcee88fe0abe.FungibleToken", Contract: "FungibleToken", Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", PinBlockHeight: 34166296, }, - "testnet": Network{ + "testnet": v1.Network{ Address: "0x9a0766d93b6608b7", FqAddress: "A.0x9a0766d93b6608b7.FungibleToken", Contract: "FungibleToken", @@ -119,12 +119,12 @@ var parsedTemplate = &FlowInteractionTemplate{ }, }, }, - Arguments: Arguments{ - "amount": Argument{ + Arguments: v1.Arguments{ + "amount": v1.Argument{ Index: 0, Type: "UFix64", - Messages: Messages{ - Title: &Title{ + Messages: v1.Messages{ + Title: &v1.Title{ I18N: map[string]string{ "en-US": "The amount of FLOW tokens to send", }, @@ -132,11 +132,11 @@ var parsedTemplate = &FlowInteractionTemplate{ }, Balance: "", }, - "to": Argument{ + "to": v1.Argument{ Index: 1, Type: "Address", - Messages: Messages{ - Title: &Title{ + Messages: v1.Messages{ + Title: &v1.Title{ I18N: map[string]string{ "en-US": "The Flow account the tokens will go to", }, @@ -151,7 +151,7 @@ var parsedTemplate = &FlowInteractionTemplate{ func TestParseFlix(t *testing.T) { assert := assert.New(t) - parsedTemplate, err := ParseFlix(flix_template) + parsedTemplate, err := v1.ParseFlix(flix_template) assert.NoError(err, "ParseTemplate should not return an error") assert.NotNil(parsedTemplate, "Parsed template should not be nil") @@ -205,15 +205,15 @@ func TestGetAndReplaceCadenceImports(t *testing.T) { func TestIsScript(t *testing.T) { assert := assert.New(t) - scriptTemplate := &FlowInteractionTemplate{ - Data: Data{ + scriptTemplate := &v1.FlowInteractionTemplate{ + Data: v1.Data{ Type: "script", }, } assert.True(scriptTemplate.IsScript(), "IsScript() should return true") - transactionTemplate := &FlowInteractionTemplate{ - Data: Data{ + transactionTemplate := &v1.FlowInteractionTemplate{ + Data: v1.Data{ Type: "transaction", }, } @@ -223,15 +223,15 @@ func TestIsScript(t *testing.T) { func TestIsTransaction(t *testing.T) { assert := assert.New(t) - scriptTemplate := &FlowInteractionTemplate{ - Data: Data{ + scriptTemplate := &v1.FlowInteractionTemplate{ + Data: v1.Data{ Type: "script", }, } assert.False(scriptTemplate.IsTransaction(), "IsTransaction() should return false") - transactionTemplate := &FlowInteractionTemplate{ - Data: Data{ + transactionTemplate := &v1.FlowInteractionTemplate{ + Data: v1.Data{ Type: "transaction", }, } @@ -252,6 +252,12 @@ func TestFetchFlix(t *testing.T) { assert.Equal("Hello World", body, "GetFlix should return the correct body") } +type DefaultReader struct{} + +func (d DefaultReader) ReadFile(path string) ([]byte, error) { + return []byte(flix_template), nil +} + func TestGetFlixRaw(t *testing.T) { assert := assert.New(t) @@ -261,14 +267,14 @@ func TestGetFlixRaw(t *testing.T) { })) defer server.Close() - flixService := NewFlixService(&Config{FlixServerURL: server.URL}) + flixService := NewFlixService(&Config{FlixServerURL: server.URL, FileReader: DefaultReader{}}) ctx := context.Background() - body, err := flixService.GetFlixRaw(ctx, "templateName") + body, err := flixService.GetTemplate(ctx, "templateName") assert.NoError(err, "GetFlixByName should not return an error") assert.Equal("Hello World", body, "GetFlixByName should return the correct body") } -func TestGetFlix(t *testing.T) { +func TestGetFlixFilename(t *testing.T) { assert := assert.New(t) server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { @@ -276,26 +282,26 @@ func TestGetFlix(t *testing.T) { })) defer server.Close() - flixService := NewFlixService(&Config{FlixServerURL: server.URL}) + flixService := NewFlixService(&Config{FlixServerURL: server.URL, FileReader: DefaultReader{}}) ctx := context.Background() - flix, err := flixService.GetFlix(ctx, "templateName") + flix, err := flixService.GetTemplate(ctx, "./templateFileName") assert.NoError(err, "GetParsedFlixByName should not return an error") assert.NotNil(flix, "GetParsedFlixByName should not return a nil Flix") - assert.Equal(parsedTemplate, flix, "GetParsedFlixByName should return the correct Flix") + assert.Equal(flix_template, flix, "GetParsedFlixByName should return the correct Flix") } func TestGetFlixByIDRaw(t *testing.T) { assert := assert.New(t) server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - assert.Equal("/templateID", req.URL.String(), "GetFlixByID should request the correct path") + assert.Equal("/1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF", req.URL.String(), "GetFlixByID should request the correct path") rw.Write([]byte("Hello World")) })) defer server.Close() flixService := NewFlixService(&Config{FlixServerURL: server.URL}) ctx := context.Background() - body, err := flixService.GetFlixByIDRaw(ctx, "templateID") + body, err := flixService.GetTemplate(ctx, "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF") assert.NoError(err, "GetFlixByID should not return an error") assert.Equal("Hello World", body, "GetFlixByID should return the correct body") } @@ -310,12 +316,52 @@ func TestGetFlixByID(t *testing.T) { flixService := NewFlixService(&Config{FlixServerURL: server.URL}) ctx := context.Background() - flix, err := flixService.GetFlixByID(ctx, "templateID") + flix, err := flixService.GetTemplate(ctx, "templateID") assert.NoError(err, "GetParsedFlixByID should not return an error") assert.NotNil(flix, "GetParsedFlixByID should not return a nil Flix") - assert.Equal(parsedTemplate, flix, "GetParsedFlixByID should return the correct Flix") + assert.Equal(flix_template, flix, "GetParsedFlixByID should return the correct Flix") } -type MapFsReader struct { - FS fs.FS +func TestTemplateVersion(t *testing.T) { + assert := assert.New(t) + + tests := []struct { + templateStr string + version string + wantErr bool + }{ + { + templateStr: `{ + "f_version": "1.0.0" + }`, + version: "1.0.0", + wantErr: false, + }, + { + templateStr: `{ + "f_version": "1.1.0" + }`, + version: "1.1.0", + wantErr: false, + }, + { + templateStr: `{ + "f_ver": "1.x" + }`, + version: "", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.templateStr, func(t *testing.T) { + ver, err := GetTemplateVersion(tt.templateStr) + if tt.wantErr { + assert.Error(err, "TemplateVersion should return an error") + } else { + assert.NoError(err, "TemplateVersion should not return an error") + assert.Equal(tt.version, ver, "TemplateVersion should return the correct version") + } + }) + } } diff --git a/flixkit/generator.go b/flixkit/generator.go new file mode 100644 index 0000000..cc0a609 --- /dev/null +++ b/flixkit/generator.go @@ -0,0 +1,306 @@ +package flixkit + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/onflow/cadence/runtime/ast" + "github.com/onflow/cadence/runtime/cmd" + "github.com/onflow/cadence/runtime/common" + "github.com/onflow/cadence/runtime/parser" + v1_1 "github.com/onflow/flixkit-go/flixkit/v1_1" + "github.com/onflow/flixkit-go/internal/contracts" + "github.com/onflow/flow-cli/flowkit" + "github.com/onflow/flow-cli/flowkit/config" + "github.com/onflow/flow-cli/flowkit/gateway" + "github.com/onflow/flow-cli/flowkit/output" + "github.com/onflow/flow-go-sdk" + "github.com/onflow/flow-go-sdk/crypto" + "github.com/spf13/afero" +) + +/* +Same structure as core contracts, using config network names +*/ +type NetworkAddressMap map[string]string + +/* +Same structure as core contracts, keyed by contract name +*/ +type ContractInfos map[string]NetworkAddressMap + +type Generator struct { + deployedContracts []v1_1.Contract + testnetClient *flowkit.Flowkit + mainnetClient *flowkit.Flowkit + template *v1_1.InteractionTemplate +} + +func NewGenerator(contractInfos ContractInfos, logger output.Logger) (*Generator, error) { + loader := afero.Afero{Fs: afero.NewOsFs()} + + gwt, err := gateway.NewGrpcGateway(config.TestnetNetwork) + if err != nil { + return nil, fmt.Errorf("could not create grpc gateway for testnet %w", err) + } + + gwm, err := gateway.NewGrpcGateway(config.MainnetNetwork) + if err != nil { + return nil, fmt.Errorf("could not create grpc gateway for mainnet %w", err) + } + + state, err := flowkit.Init(loader, crypto.ECDSA_P256, crypto.SHA3_256) + if err != nil { + return nil, fmt.Errorf("could not initialize flowkit state %w", err) + } + testnetClient := flowkit.NewFlowkit(state, config.TestnetNetwork, gwt, logger) + mainnetClient := flowkit.NewFlowkit(state, config.MainnetNetwork, gwm, logger) + // add core contracts to deployed contracts + cc := contracts.GetCoreContracts() + deployedContracts := make([]v1_1.Contract, 0) + for contractName, c := range cc { + contract := v1_1.Contract{ + Contract: contractName, + Networks: []v1_1.Network{ + {Network: config.MainnetNetwork.Name, Address: c[config.MainnetNetwork.Name]}, + {Network: config.TestnetNetwork.Name, Address: c[config.TestnetNetwork.Name]}, + {Network: config.EmulatorNetwork.Name, Address: c[config.EmulatorNetwork.Name]}, + }, + } + deployedContracts = append(deployedContracts, contract) + } + // allow user contracts to override core contracts + for contractInfo, networks := range contractInfos { + contract := v1_1.Contract{ + Contract: contractInfo, + Networks: make([]v1_1.Network, 0), + } + for network, address := range networks { + contract.Networks = append(contract.Networks, v1_1.Network{ + Network: network, + Address: address, + }) + } + deployedContracts = append(deployedContracts, contract) + } + + return &Generator{ + deployedContracts: deployedContracts, + testnetClient: testnetClient, + mainnetClient: mainnetClient, + template: &v1_1.InteractionTemplate{}, + }, nil +} + +func (g Generator) Generate(ctx context.Context, code string, preFill string) (string, error) { + g.template = &v1_1.InteractionTemplate{} + g.template.Init() + if preFill != "" { + t, err := v1_1.ParseFlix(preFill) + if err != nil { + return "", err + } + g.template = t + } + + // make sure imports use new import syntax "string import" + g.template.ProcessImports(code) + program, err := parser.ParseProgram(nil, []byte(g.template.Data.Cadence.Body), parser.Config{}) + if err != nil { + return "", err + } + + err = g.template.DetermineCadenceType(program) + if err != nil { + return "", err + } + + err = g.template.ParsePragma(program) + if err != nil { + return "", err + } + + err = g.template.ProcessParameters(program) + if err != nil { + return "", err + } + + err = g.processDependencies(ctx, program) + if err != nil { + return "", err + } + + // need to process dependencies before calculating network pins + _ = g.calculateNetworkPins(program) + id, _ := v1_1.GenerateFlixID(g.template) + g.template.ID = id + templateJson, err := json.MarshalIndent(g.template, "", " ") + + return string(templateJson), err + +} + +func (g Generator) calculateNetworkPins(program *ast.Program) error { + networksOfInterest := []string{ + config.MainnetNetwork.Name, + config.TestnetNetwork.Name, + } + networkPins := make([]v1_1.NetworkPin, 0) + for _, netName := range networksOfInterest { + cad, err := g.template.GetAndReplaceCadenceImports(netName) + if err != nil { + continue + } + networkPins = append(networkPins, v1_1.NetworkPin{ + Network: netName, + PinSelf: v1_1.ShaHex(cad, ""), + }) + } + g.template.Data.Cadence.NetworkPins = networkPins + return nil +} + +func (g Generator) processDependencies(ctx context.Context, program *ast.Program) error { + imports := program.ImportDeclarations() + + if len(imports) == 0 { + return nil + } + + // fill in dependence information + g.template.Data.Dependencies = make([]v1_1.Dependency, 0) + for _, imp := range imports { + contractName, err := v1_1.ExtractContractName(imp.String()) + if err != nil { + return err + } + networks, err := g.generateDependenceInfo(ctx, contractName) + if err != nil { + return err + } + c := v1_1.Contract{ + Contract: contractName, + Networks: networks, + } + dep := v1_1.Dependency{ + Contracts: []v1_1.Contract{c}, + } + g.template.Data.Dependencies = append(g.template.Data.Dependencies, dep) + } + + return nil +} + +func (g *Generator) generateDependenceInfo(ctx context.Context, contractName string) ([]v1_1.Network, error) { + // only support string import syntax + contractNetworks := g.LookupImportContractInfo(contractName) + if len(contractNetworks) == 0 { + return nil, fmt.Errorf("could not find contract dependency %s", contractName) + } + var networks []v1_1.Network + for _, n := range contractNetworks { + network := v1_1.Network{ + Network: n.Network, + Address: n.Address, + } + var flowkit *flowkit.Flowkit + if n.Network == config.MainnetNetwork.Name && g.mainnetClient != nil { + flowkit = g.mainnetClient + } else if n.Network == config.TestnetNetwork.Name && g.testnetClient != nil { + flowkit = g.testnetClient + } + if n.DependencyPinBlockHeight == 0 && flowkit != nil { + block, _ := flowkit.Gateway().GetLatestBlock() + height := block.Height + + details, err := g.GenerateDepPinDepthFirst(ctx, flowkit, n.Address, contractName, height) + if err != nil { + return nil, err + } + network.DependencyPinBlockHeight = height + network.DependencyPin = details + } + networks = append(networks, network) + } + + return networks, nil +} + +func (g *Generator) LookupImportContractInfo(contractName string) []v1_1.Network { + for _, contract := range g.deployedContracts { + if contractName == contract.Contract { + return contract.Networks + } + } + return nil +} + +func (g *Generator) GenerateDepPinDepthFirst(ctx context.Context, flowkit *flowkit.Flowkit, address string, name string, height uint64) (details *v1_1.PinDetail, err error) { + memoize := make(map[string]v1_1.PinDetail) + networkPinDetail, err := generateDependencyNetworks(ctx, flowkit, address, name, memoize, height) + if err != nil { + return nil, err + } + + return networkPinDetail, nil +} + +func generateDependencyNetworks(ctx context.Context, flowkit *flowkit.Flowkit, address string, name string, cache map[string]v1_1.PinDetail, height uint64) (*v1_1.PinDetail, error) { + identifier := fmt.Sprintf("A.%s.%s", strings.ReplaceAll(address, "0x", ""), name) + pinDetail, ok := cache[identifier] + if ok { + return &pinDetail, nil + } + + account, err := flowkit.GetAccount(ctx, flow.HexToAddress(address)) + if err != nil { + return nil, err + } + code := account.Contracts[name] + if !strings.HasPrefix(address, "0x") { + address = "0x" + address + } + depend := v1_1.PinDetail{ + PinContractName: name, + PinContractAddress: address, + PinSelf: v1_1.ShaHex(code, ""), + } + depend.CalculatePin(height) + pins := []string{depend.PinSelf} + imports := getAddressImports(code, name) + detailImports := make([]v1_1.PinDetail, 0) + for _, imp := range imports { + split := strings.Split(imp, ".") + address, name := split[0], split[1] + dep, err := generateDependencyNetworks(ctx, flowkit, address, name, cache, height) + if err != nil { + return nil, err + } + if dep != nil { + detailImports = append(detailImports, *dep) + cache[identifier] = *dep + } + pins = append(pins, dep.PinSelf) + } + depend.Imports = detailImports + depend.Pin = v1_1.ShaHex(strings.Join(pins, ""), "") + return &depend, nil +} + +func getAddressImports(code []byte, name string) []string { + deps := []string{} + codes := map[common.Location][]byte{} + location := common.StringLocation(name) + program, _ := cmd.PrepareProgram(code, location, codes) + for _, imp := range program.ImportDeclarations() { + address, isAddressImport := imp.Location.(common.AddressLocation) + if isAddressImport { + adr := address.Address.Hex() + impName := imp.Identifiers[0].Identifier + deps = append(deps, fmt.Sprintf("%s.%s", adr, impName)) + } + } + return deps +} diff --git a/flixkit/generator_test.go b/flixkit/generator_test.go new file mode 100644 index 0000000..2fed309 --- /dev/null +++ b/flixkit/generator_test.go @@ -0,0 +1,178 @@ +package flixkit + +import ( + "context" + "testing" + + "github.com/hexops/autogold/v2" + v1_1 "github.com/onflow/flixkit-go/flixkit/v1_1" + "github.com/onflow/flixkit-go/internal/contracts" + "github.com/onflow/flow-cli/flowkit/config" + "github.com/stretchr/testify/assert" +) + +func TestHelloScript(t *testing.T) { + contracts := []v1_1.Contract{ + { + Contract: "HelloWorld", + Networks: []v1_1.Network{ + { + Network: "testnet", + Address: "0xee82856bf20e2aa6", + }, + { + Network: "mainnet", + Address: "0xee82856bf20e2aa6", + }, + { + Network: "emulator", + Address: "0xee82856bf20e2aa6", + }, + }, + }, + } + + generator := Generator{ + deployedContracts: contracts, + testnetClient: nil, + mainnetClient: nil, + } + assert := assert.New(t) + code := ` + #interaction( + version: "1.1.0", + title: "Say Hello", + description: "Read the greeting from the HelloWorld contract", + language: "en-US", + parameters: [], + ) + + import "HelloWorld" + + pub fun main(): String { + return HelloWorld.greeting + } +` + ctx := context.Background() + template, err := generator.Generate(ctx, code, "") + assert.NoError(err, "Generate should not return an error") + autogold.ExpectFile(t, template) + +} + +func TestTransactionValue(t *testing.T) { + contracts := []v1_1.Contract{ + { + Contract: "HelloWorld", + Networks: []v1_1.Network{ + { + Network: "testnet", + Address: "0xee82856bf20e2aa6", + }, + { + Network: "mainnet", + Address: "0xee82856bf20e2aa6", + }, + { + Network: "emulator", + Address: "0xee82856bf20e2aa6", + }, + }, + }, + } + + generator := Generator{ + deployedContracts: contracts, + testnetClient: nil, + mainnetClient: nil, + } + assert := assert.New(t) + code := ` + #interaction( + version: "1.1.0", + title: "Update Greeting", + description: "Update the greeting on the HelloWorld contract", + language: "en-US", + parameters: [ + Parameter( + name: "greeting", + title: "Greeting", + description: "The greeting to set on the HelloWorld contract" + ) + ], + ) + + import "HelloWorld" + transaction(greeting: String) { + + prepare(acct: AuthAccount) { + log(acct.address) + } + + execute { + HelloWorld.updateGreeting(newGreeting: greeting) + } + } +` + ctx := context.Background() + template, err := generator.Generate(ctx, code, "") + assert.NoError(err, "Generate should not return an error") + autogold.ExpectFile(t, template) + +} + +func TestTransferFlowTransaction(t *testing.T) { + cs := []v1_1.Contract{} + cc := contracts.GetCoreContracts() + for contractName, c := range cc { + contract := v1_1.Contract{ + Contract: contractName, + Networks: []v1_1.Network{ + {Network: config.MainnetNetwork.Name, Address: c[config.MainnetNetwork.Name]}, + {Network: config.TestnetNetwork.Name, Address: c[config.TestnetNetwork.Name]}, + {Network: config.EmulatorNetwork.Name, Address: c[config.EmulatorNetwork.Name]}, + }, + } + cs = append(cs, contract) + } + // fill in top level dependencies for the generator + generator := &Generator{ + deployedContracts: cs, + testnetClient: nil, + mainnetClient: nil, + } + assert := assert.New(t) + code := ` + #interaction( + version: "1.1.0", + title: "Transfer Flow", + description: "Transfer Flow to account", + language: "en-US", + parameters: [ + Parameter( + name: "amount", + title: "Amount", + description: "Amount of Flow to transfer" + ), + Parameter( + name: "to", + title: "Reciever", + description: "Destination address to receive Flow Tokens" + ) + ], + ) + + import "FlowToken" + transaction(amount: UFix64, to: Address) { + let vault: @FlowToken.Vault + prepare(signer: AuthAccount) { + + } + } +` + ctx := context.Background() + template, err := generator.Generate(ctx, code, "") + assert.NoError(err, "Generate should not return an error") + autogold.ExpectFile(t, template) + +} diff --git a/flixkit/testdata/TestHelloScript.golden b/flixkit/testdata/TestHelloScript.golden new file mode 100644 index 0000000..3bd53c0 --- /dev/null +++ b/flixkit/testdata/TestHelloScript.golden @@ -0,0 +1,69 @@ +`{ + "f_type": "InteractionTemplate", + "f_version": "1.1.0", + "id": "00ea34585b7351092fe871b23b8e894e339068886058b19d79dcdce168e54a93", + "data": { + "type": "script", + "interface": "", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Say Hello" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Read the greeting from the HelloWorld contract" + } + ] + } + ], + "cadence": { + "body": "\n\t#interaction(\n\t\tversion: \"1.1.0\",\n\t\ttitle: \"Say Hello\",\n\t\tdescription: \"Read the greeting from the HelloWorld contract\",\n\t\tlanguage: \"en-US\",\n\t\tparameters: [],\n\t)\n\t\n\timport \"HelloWorld\"\n\n\tpub fun main(): String {\n\treturn HelloWorld.greeting\n\t}\n", + "network_pins": [ + { + "network": "mainnet", + "pin_self": "57d66cd2e8370ef74feec033e768dc460514091fc82ba1b4c42697b600288048" + }, + { + "network": "testnet", + "pin_self": "57d66cd2e8370ef74feec033e768dc460514091fc82ba1b4c42697b600288048" + } + ] + }, + "dependencies": [ + { + "contracts": [ + { + "contract": "HelloWorld", + "networks": [ + { + "network": "testnet", + "address": "0xee82856bf20e2aa6", + "dependency_pin_block_height": 0 + }, + { + "network": "mainnet", + "address": "0xee82856bf20e2aa6", + "dependency_pin_block_height": 0 + }, + { + "network": "emulator", + "address": "0xee82856bf20e2aa6", + "dependency_pin_block_height": 0 + } + ] + } + ] + } + ], + "parameters": null + } +}` diff --git a/bindings/testdata/TestJSGenArrayScript.golden b/flixkit/testdata/TestJSGenArrayScript.golden similarity index 100% rename from bindings/testdata/TestJSGenArrayScript.golden rename to flixkit/testdata/TestJSGenArrayScript.golden diff --git a/bindings/testdata/TestJSGenMinScript.golden b/flixkit/testdata/TestJSGenMinScript.golden similarity index 100% rename from bindings/testdata/TestJSGenMinScript.golden rename to flixkit/testdata/TestJSGenMinScript.golden diff --git a/bindings/testdata/TestJSGenNoParamsScript.golden b/flixkit/testdata/TestJSGenNoParamsScript.golden similarity index 100% rename from bindings/testdata/TestJSGenNoParamsScript.golden rename to flixkit/testdata/TestJSGenNoParamsScript.golden diff --git a/bindings/testdata/TestJSGenScript.golden b/flixkit/testdata/TestJSGenScript.golden similarity index 100% rename from bindings/testdata/TestJSGenScript.golden rename to flixkit/testdata/TestJSGenScript.golden diff --git a/bindings/testdata/TestJSGenTransaction.golden b/flixkit/testdata/TestJSGenTransaction.golden similarity index 100% rename from bindings/testdata/TestJSGenTransaction.golden rename to flixkit/testdata/TestJSGenTransaction.golden diff --git a/flixkit/testdata/TestTSGenNoParamsScript.golden b/flixkit/testdata/TestTSGenNoParamsScript.golden new file mode 100644 index 0000000..bddb8a0 --- /dev/null +++ b/flixkit/testdata/TestTSGenNoParamsScript.golden @@ -0,0 +1,29 @@ +`/** + This binding file was auto generated based on FLIX template v1.1.0. + Changes to this file might get overwritten. + Note fcl version 1.9.0 or higher is required to use templates. +**/ + +import * as fcl from "@onflow/fcl" +import flixTemplate from "./min.template.json" + + +/** +* request: +* @returns {Promise} - Result of some number plus one +*/ +export async function request(): Promise { + const info = await fcl.query({ + cadence: "", + template: flixTemplate, + + }); + + return info +} + + + + + +` diff --git a/flixkit/testdata/TestTSGenNoParamsTx.golden b/flixkit/testdata/TestTSGenNoParamsTx.golden new file mode 100644 index 0000000..127eda0 --- /dev/null +++ b/flixkit/testdata/TestTSGenNoParamsTx.golden @@ -0,0 +1,27 @@ +`/** + This binding file was auto generated based on FLIX template v1.1.0. + Changes to this file might get overwritten. + Note fcl version 1.9.0 or higher is required to use templates. +**/ + +import * as fcl from "@onflow/fcl" +import flixTemplate from "./min.template.json" + + +/** +* request: +* @returns {Promise} - Returns a promise that resolves to the transaction ID +*/ +export async function request(): Promise { + const transactionId = await fcl.mutate({ + template: flixTemplate, + + }); + + return transactionId +} + + + + +` diff --git a/flixkit/testdata/TestTSGenParamsScript.golden b/flixkit/testdata/TestTSGenParamsScript.golden new file mode 100644 index 0000000..b66c036 --- /dev/null +++ b/flixkit/testdata/TestTSGenParamsScript.golden @@ -0,0 +1,33 @@ +`/** + This binding file was auto generated based on FLIX template v1.1.0. + Changes to this file might get overwritten. + Note fcl version 1.9.0 or higher is required to use templates. +**/ + +import * as fcl from "@onflow/fcl" +import flixTemplate from "./min.template.json" + +interface RequestParams { + someNumber: string; +} + +/** +* request: +* @param string someNumber - +* @returns {Promise} - Result of some number plus one +*/ +export async function request({someNumber}: RequestParams): Promise { + const info = await fcl.query({ + cadence: "", + template: flixTemplate, + args: (arg, t) => [arg(someNumber, t.Int)] + }); + + return info +} + + + + + +` diff --git a/flixkit/testdata/TestTSGenParamsTx.golden b/flixkit/testdata/TestTSGenParamsTx.golden new file mode 100644 index 0000000..eff4484 --- /dev/null +++ b/flixkit/testdata/TestTSGenParamsTx.golden @@ -0,0 +1,31 @@ +`/** + This binding file was auto generated based on FLIX template v1.1.0. + Changes to this file might get overwritten. + Note fcl version 1.9.0 or higher is required to use templates. +**/ + +import * as fcl from "@onflow/fcl" +import flixTemplate from "./min.template.json" + +interface UpdateGreetingParams { + greeting: string; +} + +/** +* updateGreeting: Update HelloWorld Greeting +* @param string greeting - +* @returns {Promise} - Returns a promise that resolves to the transaction ID +*/ +export async function updateGreeting({greeting}: UpdateGreetingParams): Promise { + const transactionId = await fcl.mutate({ + template: flixTemplate, + args: (arg, t) => [arg(greeting, t.String)] + }); + + return transactionId +} + + + + +` diff --git a/flixkit/testdata/TestTransactionValue.golden b/flixkit/testdata/TestTransactionValue.golden new file mode 100644 index 0000000..3dff4f4 --- /dev/null +++ b/flixkit/testdata/TestTransactionValue.golden @@ -0,0 +1,95 @@ +`{ + "f_type": "InteractionTemplate", + "f_version": "1.1.0", + "id": "88d07e6a46150c5e241f637d69b324fcbce1b7f06c130d442638422cff704b58", + "data": { + "type": "transaction", + "interface": "", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Update Greeting" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Update the greeting on the HelloWorld contract" + } + ] + } + ], + "cadence": { + "body": "\n\t#interaction(\n\t\tversion: \"1.1.0\",\n\t\ttitle: \"Update Greeting\",\n\t\tdescription: \"Update the greeting on the HelloWorld contract\",\n\t\tlanguage: \"en-US\",\n\t\tparameters: [\n\t\t\tParameter(\n\t\t\t\tname: \"greeting\", \n\t\t\t\ttitle: \"Greeting\", \n\t\t\t\tdescription: \"The greeting to set on the HelloWorld contract\"\n\t\t\t)\n\t\t],\n\t)\n\t\n\timport \"HelloWorld\"\n\ttransaction(greeting: String) {\n\t\n\t\tprepare(acct: AuthAccount) {\n\t\t\tlog(acct.address)\n\t\t}\n\t\t\n\t\texecute {\n\t\t\tHelloWorld.updateGreeting(newGreeting: greeting)\n\t\t}\n\t}\n", + "network_pins": [ + { + "network": "mainnet", + "pin_self": "0ad0659f79f7b8336a588e24326c26cf6cf7f74af81c0c8a35ee58e190988af2" + }, + { + "network": "testnet", + "pin_self": "0ad0659f79f7b8336a588e24326c26cf6cf7f74af81c0c8a35ee58e190988af2" + } + ] + }, + "dependencies": [ + { + "contracts": [ + { + "contract": "HelloWorld", + "networks": [ + { + "network": "testnet", + "address": "0xee82856bf20e2aa6", + "dependency_pin_block_height": 0 + }, + { + "network": "mainnet", + "address": "0xee82856bf20e2aa6", + "dependency_pin_block_height": 0 + }, + { + "network": "emulator", + "address": "0xee82856bf20e2aa6", + "dependency_pin_block_height": 0 + } + ] + } + ] + } + ], + "parameters": [ + { + "label": "greeting", + "index": 0, + "type": "String", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Greeting" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "The greeting to set on the HelloWorld contract" + } + ] + } + ] + } + ] + } +}` diff --git a/flixkit/testdata/TestTransferFlowTransaction.golden b/flixkit/testdata/TestTransferFlowTransaction.golden new file mode 100644 index 0000000..f153612 --- /dev/null +++ b/flixkit/testdata/TestTransferFlowTransaction.golden @@ -0,0 +1,120 @@ +`{ + "f_type": "InteractionTemplate", + "f_version": "1.1.0", + "id": "2233dc61f9e187efe089977e503a68024a6fd1d35e0971d8f36b1016ba032974", + "data": { + "type": "transaction", + "interface": "", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Transfer Flow" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Transfer Flow to account" + } + ] + } + ], + "cadence": { + "body": "\n\t#interaction(\n\t\tversion: \"1.1.0\",\n\t\ttitle: \"Transfer Flow\",\n\t\tdescription: \"Transfer Flow to account\",\n\t\tlanguage: \"en-US\",\n\t\tparameters: [\n\t\t\tParameter(\n\t\t\t\tname: \"amount\", \n\t\t\t\ttitle: \"Amount\", \n\t\t\t\tdescription: \"Amount of Flow to transfer\"\n\t\t\t),\n\t\t\tParameter(\n\t\t\t\tname: \"to\", \n\t\t\t\ttitle: \"Reciever\", \n\t\t\t\tdescription: \"Destination address to receive Flow Tokens\"\n\t\t\t)\n\t\t],\n\t)\n\t\n\timport \"FlowToken\"\n\ttransaction(amount: UFix64, to: Address) {\n\t\tlet vault: @FlowToken.Vault\n\t\tprepare(signer: AuthAccount) {\n\t\t\n\t\t}\n\t}\n", + "network_pins": [ + { + "network": "mainnet", + "pin_self": "b11213cf3480f71989f7518791b976cfd80d43c7474495a6d5669b17b77e9346" + }, + { + "network": "testnet", + "pin_self": "d7c8bddb94f640478b573871dfc2c4e9d090c706ab2a7b8c3e8223e5f7f737be" + } + ] + }, + "dependencies": [ + { + "contracts": [ + { + "contract": "FlowToken", + "networks": [ + { + "network": "mainnet", + "address": "0x1654653399040a61", + "dependency_pin_block_height": 0 + }, + { + "network": "testnet", + "address": "0x7e60df042a9c0868", + "dependency_pin_block_height": 0 + }, + { + "network": "emulator", + "address": "0x0ae53cb6e3f42a79", + "dependency_pin_block_height": 0 + } + ] + } + ] + } + ], + "parameters": [ + { + "label": "amount", + "index": 0, + "type": "UFix64", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Amount" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Amount of Flow to transfer" + } + ] + } + ] + }, + { + "label": "to", + "index": 1, + "type": "Address", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Reciever" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Destination address to receive Flow Tokens" + } + ] + } + ] + } + ] + } +}` diff --git a/flixkit/v1/types.go b/flixkit/v1/types.go new file mode 100644 index 0000000..ef373c6 --- /dev/null +++ b/flixkit/v1/types.go @@ -0,0 +1,134 @@ +package flixkit + +import ( + "encoding/json" + "fmt" + "regexp" + + "github.com/onflow/flixkit-go/internal/contracts" +) + +type Network struct { + Address string `json:"address"` + FqAddress string `json:"fq_address"` + Contract string `json:"contract"` + Pin string `json:"pin"` + PinBlockHeight uint64 `json:"pin_block_height"` +} + +type Argument struct { + Index int `json:"index"` + Type string `json:"type"` + Messages Messages `json:"messages"` + Balance string `json:"balance"` +} + +type Title struct { + I18N map[string]string `json:"i18n"` +} + +type Description struct { + I18N map[string]string `json:"i18n"` +} + +type Messages struct { + Title *Title `json:"title,omitempty"` + Description *Description `json:"description,omitempty"` +} + +type Dependencies map[string]Contracts +type Contracts map[string]Networks +type Networks map[string]Network +type Arguments map[string]Argument + +type Data struct { + Type string `json:"type"` + Interface string `json:"interface"` + Messages Messages `json:"messages"` + Cadence string `json:"cadence"` + Dependencies Dependencies `json:"dependencies"` + Arguments Arguments `json:"arguments"` +} + +type FlowInteractionTemplate struct { + FType string `json:"f_type"` + FVersion string `json:"f_version"` + ID string `json:"id"` + Data Data `json:"data"` +} + +func (t *FlowInteractionTemplate) IsScript() bool { + return t.Data.Type == "script" +} + +func (t *FlowInteractionTemplate) IsTransaction() bool { + return t.Data.Type == "transaction" +} + +func ParseFlix(template string) (*FlowInteractionTemplate, error) { + var flowTemplate FlowInteractionTemplate + + err := json.Unmarshal([]byte(template), &flowTemplate) + if err != nil { + return nil, err + } + + return &flowTemplate, nil +} + +func (t *FlowInteractionTemplate) GetAndReplaceCadenceImports(networkName string) (string, error) { + var cadence string + + for dependencyAddress, c := range t.Data.Dependencies { + for contractName, networks := range c { + var networkAddress string + network, ok := networks[networkName] + networkAddress = network.Address + if !ok { + coreContractAddress := contracts.GetCoreContractForNetwork(contractName, networkName) + if coreContractAddress == "" { + return "", fmt.Errorf("network %s not found for contract %s in dependencies", networkName, contractName) + } + networkAddress = coreContractAddress + } + + pattern := fmt.Sprintf(`import\s*%s\s*from\s*%s`, contractName, dependencyAddress) + re, err := regexp.Compile(pattern) + if err != nil { + return "", fmt.Errorf("invalid regex pattern: %v", err) + } + + replacement := fmt.Sprintf("import %s from %s", contractName, networkAddress) + cadence = re.ReplaceAllString(t.Data.Cadence, replacement) + } + } + + return cadence, nil +} + +func (t *FlowInteractionTemplate) GetDescription() string { + s := "" + if t.Data.Messages.Description != nil && + t.Data.Messages.Description.I18N != nil { + + // relying on en-US for now, future we need to know what language to use + value, exists := t.Data.Messages.Description.I18N["en-US"] + if exists { + s = value + } + } + return s +} + +func (msgs *Messages) GetTitleValue(placeholder string) string { + s := placeholder + if msgs.Title != nil && + msgs.Title.I18N != nil { + // relying on en-US for now, future we need to know what language to use + value, exists := msgs.Title.I18N["en-US"] + if exists { + s = value + } + } + return s +} diff --git a/flixkit/v1_1/testdata/TestEmptyPragmaWithParameter.golden b/flixkit/v1_1/testdata/TestEmptyPragmaWithParameter.golden new file mode 100644 index 0000000..ce02d09 --- /dev/null +++ b/flixkit/v1_1/testdata/TestEmptyPragmaWithParameter.golden @@ -0,0 +1,23 @@ +`{ + "f_type": "", + "f_version": "", + "id": "", + "data": { + "type": "", + "interface": "", + "messages": null, + "cadence": { + "body": "", + "network_pins": null + }, + "dependencies": null, + "parameters": [ + { + "label": "greeting", + "index": 0, + "type": "String", + "messages": [] + } + ] + } +}` diff --git a/flixkit/v1_1/testdata/TestGenerateParametersScripts.golden b/flixkit/v1_1/testdata/TestGenerateParametersScripts.golden new file mode 100644 index 0000000..a61e0ca --- /dev/null +++ b/flixkit/v1_1/testdata/TestGenerateParametersScripts.golden @@ -0,0 +1,61 @@ +`{ + "f_type": "InteractionTemplate", + "f_version": "1.1.0", + "id": "", + "data": { + "type": "script", + "interface": "", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "User Balance" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Get User Balance" + } + ] + } + ], + "cadence": { + "body": "", + "network_pins": null + }, + "dependencies": [], + "parameters": [ + { + "label": "address", + "index": 0, + "type": "Address", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "User Address" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Get user balance" + } + ] + } + ] + } + ] + } +}` diff --git a/flixkit/v1_1/testdata/TestParsePragma/Empty.golden b/flixkit/v1_1/testdata/TestParsePragma/Empty.golden new file mode 100644 index 0000000..9277e16 --- /dev/null +++ b/flixkit/v1_1/testdata/TestParsePragma/Empty.golden @@ -0,0 +1,16 @@ +`{ + "f_type": "", + "f_version": "", + "id": "", + "data": { + "type": "", + "interface": "", + "messages": null, + "cadence": { + "body": "", + "network_pins": null + }, + "dependencies": null, + "parameters": null + } +}` diff --git a/flixkit/v1_1/testdata/TestParsePragma/Minimum.golden b/flixkit/v1_1/testdata/TestParsePragma/Minimum.golden new file mode 100644 index 0000000..129680c --- /dev/null +++ b/flixkit/v1_1/testdata/TestParsePragma/Minimum.golden @@ -0,0 +1,16 @@ +`{ + "f_type": "", + "f_version": "1.1.0", + "id": "", + "data": { + "type": "", + "interface": "", + "messages": null, + "cadence": { + "body": "", + "network_pins": null + }, + "dependencies": null, + "parameters": null + } +}` diff --git a/flixkit/v1_1/testdata/TestParsePragma/WithParameters.golden b/flixkit/v1_1/testdata/TestParsePragma/WithParameters.golden new file mode 100644 index 0000000..c9bfaee --- /dev/null +++ b/flixkit/v1_1/testdata/TestParsePragma/WithParameters.golden @@ -0,0 +1,86 @@ +`{ + "f_type": "", + "f_version": "1.1.0", + "id": "", + "data": { + "type": "", + "interface": "", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Update Greeting" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Update the greeting on the HelloWorld contract" + } + ] + } + ], + "cadence": { + "body": "", + "network_pins": null + }, + "dependencies": null, + "parameters": [ + { + "label": "greeting", + "index": 0, + "type": "", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Greeting" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "The greeting to set on the HelloWorld contract" + } + ] + } + ] + }, + { + "label": "amount", + "index": 1, + "type": "", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Amount" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "The amount parameter to Test" + } + ] + } + ] + } + ] + } +}` diff --git a/flixkit/v1_1/testdata/TestParsePragma/WithoutParameters.golden b/flixkit/v1_1/testdata/TestParsePragma/WithoutParameters.golden new file mode 100644 index 0000000..eceba88 --- /dev/null +++ b/flixkit/v1_1/testdata/TestParsePragma/WithoutParameters.golden @@ -0,0 +1,35 @@ +`{ + "f_type": "", + "f_version": "1.1.0", + "id": "", + "data": { + "type": "", + "interface": "", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Update Greeting" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Update the greeting on the HelloWorld contract" + } + ] + } + ], + "cadence": { + "body": "", + "network_pins": null + }, + "dependencies": null, + "parameters": null + } +}` diff --git a/flixkit/v1_1/types.go b/flixkit/v1_1/types.go new file mode 100644 index 0000000..0df025d --- /dev/null +++ b/flixkit/v1_1/types.go @@ -0,0 +1,594 @@ +package flixkit + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "encoding/json" + "fmt" + "regexp" + "sort" + "strings" + + "github.com/ethereum/go-ethereum/rlp" + "github.com/onflow/cadence/runtime/ast" + "github.com/onflow/flixkit-go/internal/contracts" + "golang.org/x/crypto/sha3" +) + +type InteractionTemplate struct { + FType string `json:"f_type"` + FVersion string `json:"f_version"` + ID string `json:"id"` + Data Data `json:"data"` +} + +type Data struct { + Type string `json:"type"` + Interface string `json:"interface"` + Messages []Message `json:"messages"` + Cadence Cadence `json:"cadence"` + Dependencies []Dependency `json:"dependencies"` + Parameters []Parameter `json:"parameters"` + Output *Parameter `json:"output,omitempty"` +} + +type Message struct { + Key string `json:"key"` + I18n []I18n `json:"i18n"` +} + +type InteractionTemplateMessages []Message + +func (msgs InteractionTemplateMessages) GetTitle(placeholder string) string { + return msgs.getMessageValue("title", placeholder) +} + +func (msgs InteractionTemplateMessages) GetDescription(placeholder string) string { + return msgs.getMessageValue("description", placeholder) +} + +func (msgs InteractionTemplateMessages) getMessageValue(key string, placeholder string) string { + s := placeholder + for _, msg := range msgs { + if msg.Key == key { + for _, i18n := range msg.I18n { + // set default if en-US not present + s = i18n.Translation + if i18n.Tag == "en-US" { + s = i18n.Translation + break + } + } + } + } + return strings.TrimSpace(s) +} + +type I18n struct { + Tag string `json:"tag"` + Translation string `json:"translation"` +} + +type Cadence struct { + Body string `json:"body"` + NetworkPins []NetworkPin `json:"network_pins"` +} + +type NetworkPin struct { + Network string `json:"network"` + PinSelf string `json:"pin_self"` +} + +type Dependency struct { + Contracts []Contract `json:"contracts"` +} + +type Contract struct { + Contract string `json:"contract"` + Networks []Network `json:"networks"` +} + +type Network struct { + Network string `json:"network"` + Address string `json:"address"` + DependencyPinBlockHeight uint64 `json:"dependency_pin_block_height"` + DependencyPin *PinDetail `json:"dependency_pin,omitempty"` +} + +type PinDetail struct { + Pin string `json:"pin"` + PinSelf string `json:"pin_self"` + PinContractName string `json:"pin_contract_name"` + PinContractAddress string `json:"pin_contract_address"` + Imports []PinDetail `json:"imports"` +} + +func (p *PinDetail) CalculatePin(blockHeight uint64) { + var a []string + a = append(a, ShaHex(p.PinContractAddress, "address")) + a = append(a, ShaHex(p.PinContractName, "address")) + a = append(a, ShaHex(p.PinSelf, "pin_self")) + a = append(a, ShaHex(fmt.Sprint(blockHeight), "pin_block_height")) + hash := ShaHex(strings.Join(a, ""), "calculate_pin") + p.Pin = hash +} + +type Import struct { + Pin string `json:"pin"` + PinSelf string `json:"pin_self"` + PinContractName string `json:"pin_contract_name"` + PinContractAddress string `json:"pin_contract_address"` + Imports []Import `json:"imports"` // Recursive imports, if any +} + +type Parameter struct { + Label string `json:"label"` + Index int `json:"index"` + Type string `json:"type"` + Messages []Message `json:"messages"` +} + +func (t *InteractionTemplate) Init() { + t.FType = "InteractionTemplate" + if t.FVersion == "" { + t.FVersion = "1.1.0" + } +} + +func (t *InteractionTemplate) IsScript() bool { + return t.Data.Type == "script" +} + +func (t *InteractionTemplate) IsTransaction() bool { + return t.Data.Type == "transaction" +} + +func replaceImport(code string, from string, to string) string { + pathRegex := regexp.MustCompile(fmt.Sprintf(`import\s+(\w+)\s+from\s+"%s"`, from)) + identifierRegex := regexp.MustCompile(fmt.Sprintf(`import\s+"(%s)"`, from)) + + replacement := fmt.Sprintf(`import $1 from %s`, to) + code = pathRegex.ReplaceAllString(code, replacement) + code = identifierRegex.ReplaceAllString(code, replacement) + return code +} + +func (t *InteractionTemplate) GetAndReplaceCadenceImports(networkName string) (string, error) { + cadence := t.Data.Cadence.Body + // Compile regular expression to match and capture contract names + re := regexp.MustCompile(`import\s*"([^"]+)"`) + + // Find all matches and their captured groups + matches := re.FindAllStringSubmatch(cadence, -1) + if len(matches) == 0 { + return cadence, nil + } + for _, match := range matches { + contractName := match[1] + var dependencyAddress string + for _, Dependence := range t.Data.Dependencies { + for _, contract := range Dependence.Contracts { + if contract.Contract == contractName { + for _, network := range contract.Networks { + if network.Network == networkName { + dependencyAddress = network.Address + break + } + } + break + } + } + } + + if dependencyAddress == "" { + dependencyAddress = contracts.GetCoreContractForNetwork(contractName, networkName) + if dependencyAddress == "" { + return "", fmt.Errorf("network %s not found for contract %s in dependencies", networkName, contractName) + } + } + cadence = replaceImport(cadence, contractName, dependencyAddress) + } + + return cadence, nil + +} + +func ParseFlix(template string) (*InteractionTemplate, error) { + var flowTemplate InteractionTemplate + err := json.Unmarshal([]byte(template), &flowTemplate) + if err != nil { + return nil, err + } + + return &flowTemplate, nil +} + +type PragmaDeclaration struct { + Expression InteractionExpression `json:"Expression"` +} + +type InteractionExpression struct { + InvokedExpression IdentifierExpression `json:"InvokedExpression"` + Arguments []Argument `json:"Arguments"` + Value string `json:"Value"` // Used for string expressions + Type string `json:"Type"` // Used for string expressions + Values []InteractionExpression `json:"Values"` // Used for array expressions +} + +type IdentifierExpression struct { + Identifier Identifier `json:"Identifier"` +} + +type Identifier struct { + Identifier string `json:"Identifier"` +} + +type Argument struct { + Expression InteractionExpression `json:"Expression"` + Label string `json:"Label"` +} + +func (template *InteractionTemplate) ParsePragma(program *ast.Program) error { + pragmas := program.PragmaDeclarations() + if len(pragmas) == 0 { + return nil + } + + for _, prag := range pragmas { + var pragmaDeclaration PragmaDeclaration + jsonData, err := prag.MarshalJSON() + if err != nil { + return err + } + err = json.Unmarshal([]byte(jsonData), &pragmaDeclaration) + if err != nil { + return err + } + if pragmaDeclaration.Expression.InvokedExpression.Identifier.Identifier == "interaction" { + pragmaInfo := flatten(pragmaDeclaration) + if template.FVersion == "" { + template.FVersion = pragmaInfo.meta["version"] + } + if pragmaInfo.meta["title"] != "" { + template.Data.Messages = append(template.Data.Messages, Message{ + Key: "title", + I18n: []I18n{ + { + Tag: pragmaInfo.meta["language"], + Translation: pragmaInfo.meta["title"], + }, + }, + }) + } + if pragmaInfo.meta["description"] != "" { + template.Data.Messages = append(template.Data.Messages, Message{ + Key: "description", + I18n: []I18n{ + { + Tag: pragmaInfo.meta["language"], + Translation: pragmaInfo.meta["description"], + }, + }, + }) + } + if pragmaInfo.parameters != nil { + for i, paramInfo := range pragmaInfo.parameters { + param := Parameter{ + Label: paramInfo.params["name"], + Index: i, + } + if paramInfo.params["title"] != "" { + param.Messages = append(param.Messages, Message{ + Key: "title", + I18n: []I18n{ + { + Tag: pragmaInfo.meta["language"], + Translation: paramInfo.params["title"], + }, + }, + }) + } + if paramInfo.params["description"] != "" { + param.Messages = append(param.Messages, Message{ + Key: "description", + I18n: []I18n{ + { + Tag: pragmaInfo.meta["language"], + Translation: paramInfo.params["description"], + }, + }, + }) + } + template.Data.Parameters = append(template.Data.Parameters, param) + } + } + } + } + return nil +} + +type parametermetadata struct { + params map[string]string +} +type metadata struct { + meta map[string]string + parameters []parametermetadata +} + +func flatten(pragma PragmaDeclaration) metadata { + var nameValuePairs map[string]string + var parameterPairs []parametermetadata + nameValuePairs = make(map[string]string) + parameterPairs = make([]parametermetadata, 0) + + for _, arg := range pragma.Expression.Arguments { + // For regular arguments + if arg.Expression.Value != "" { + nameValuePairs[arg.Label] = arg.Expression.Value + } + + // For arguments that contain arrays (like parameters) + if len(arg.Expression.Values) > 0 { + for _, param := range arg.Expression.Values { + p := parametermetadata{ + params: make(map[string]string), + } + for _, paramArg := range param.Arguments { + p.params[paramArg.Label] = paramArg.Expression.Value + } + parameterPairs = append(parameterPairs, p) + } + } + } + return metadata{nameValuePairs, parameterPairs} +} + +func (template *InteractionTemplate) ProcessParameters(program *ast.Program) error { + if program == nil { + return fmt.Errorf("no cadence program provided") + } + var parameterList []*ast.Parameter + functionDeclaration := program.FunctionDeclarations() + // only interested in main function of script + for _, d := range functionDeclaration { + if d.Identifier.String() == "main" { + parameterList = d.ParameterList.Parameters + } + } + + if program.SoleTransactionDeclaration() != nil && program.SoleTransactionDeclaration().ParameterList != nil { + parameterList = program.SoleTransactionDeclaration().ParameterList.Parameters + } + + if parameterList != nil && len(template.Data.Parameters) == 0 { + template.Data.Parameters = make([]Parameter, 0) + } + + // use existing parameter of template or create new one + for i, param := range parameterList { + var tempParam *Parameter + if hasValueAtIndex(template.Data.Parameters, i) { + tempParam = &template.Data.Parameters[i] + // verify that the parameter name matches, + // could happen if dev inputted param data incorrectly + if tempParam.Label != param.Identifier.String() { + return fmt.Errorf("parameter name mismatch, expected %s, got %s", tempParam.Label, param.Identifier.String()) + } + tempParam.Type = param.TypeAnnotation.Type.String() + tempParam.Index = i + } else { + tempParam = &Parameter{ + Label: param.Identifier.String(), + Index: i, + Type: param.TypeAnnotation.Type.String(), + Messages: make([]Message, 0), + } + template.Data.Parameters = append(template.Data.Parameters, *tempParam) + } + } + + return nil +} + +func hasValueAtIndex(arr []Parameter, index int) bool { + if len(arr) == 0 { + return false + } + if index >= 0 && index < len(arr) { + return true + } + return false +} + +func (template *InteractionTemplate) DetermineCadenceType(program *ast.Program) error { + funcs := program.FunctionDeclarations() + trans := program.TransactionDeclarations() + var t string + if len(funcs) > 0 { + t = "script" + } else if len(trans) > 0 { + t = "transaction" + template.Data.Output = nil + } else { + return fmt.Errorf("no function or transaction declarations found") + } + template.Data.Type = t + return nil +} + +func (template *InteractionTemplate) ProcessImports(cadenceCode string) { + // Define a regular expression to match the "import ContractName from 0xContractName" pattern + pattern := regexp.MustCompile(`import\s+(\w+)\s+from\s+0x\w+`) + // Replace the matched pattern with "import \"ContractName\"" + replaced := pattern.ReplaceAllString(cadenceCode, `import "$1"`) + template.Data.Cadence.Body = replaced +} + +func messagesToRlp(messages []Message) []interface{} { + values := make([]interface{}, 0) + for _, message := range messages { + var mv []interface{} + mv = append(mv, ShaHex(message.Key, message.Key)) + var templateMessageTranslations []interface{} + for _, v := range message.I18n { + var tagTranslation []interface{} + tagTranslation = append(tagTranslation, ShaHex(v.Tag, v.Tag)) + tagTranslation = append(tagTranslation, ShaHex(v.Translation, v.Translation)) + templateMessageTranslations = append(templateMessageTranslations, tagTranslation) + } + mv = append(mv, templateMessageTranslations) + values = append(values, mv) + } + return values +} + +func parameterToRLP(p Parameter) []interface{} { + var values []interface{} + values = append(values, ShaHex(p.Label, "label")) + + var param []interface{} + param = append(param, ShaHex(fmt.Sprint(p.Index), "index")) + param = append(param, ShaHex(p.Type, "type")) + param = append(param, messagesToRlp(p.Messages)) + values = append(values, param) + + return values +} + +func parametersToRlp(params []Parameter) []interface{} { + values := make([]interface{}, 0) + sort.Slice(params, func(i, j int) bool { + return params[i].Index < params[j].Index + }) + + for _, p := range params { + values = append(values, parameterToRLP(p)) + } + return values +} + +func networksToRlp(Networks []Network) []interface{} { + values := make([]interface{}, 0) + for _, network := range Networks { + var networks []interface{} + networks = append(networks, ShaHex(network.Network, "key")) + if network.DependencyPin != nil { + networks = append(networks, ShaHex(network.DependencyPin.Pin, "networkPin")) + } + values = append(values, networks) + } + return values +} + +func contractsToRlp(Contracts []Contract) []interface{} { + values := make([]interface{}, 0) + for _, contract := range Contracts { + var contracts []interface{} + contracts = append(contracts, ShaHex(contract.Contract, "key")) + contracts = append(contracts, networksToRlp(contract.Networks)) + values = append(values, contracts) + } + return values +} + +func dependenciesToRlp(Dependencies []Dependency) []interface{} { + values := make([]interface{}, 0) + for _, dependency := range Dependencies { + var deps []interface{} + deps = append(deps, contractsToRlp(dependency.Contracts)) + values = append(values, deps) + } + return values +} + +func (flix InteractionTemplate) EncodeRLP() (result string, err error) { + var buffer bytes.Buffer // Create a new buffer + + input := []interface{}{ + ShaHex(flix.FType, ""), + ShaHex(flix.FVersion, ""), + ShaHex(flix.Data.Type, ""), + ShaHex(flix.Data.Interface, ""), + messagesToRlp(flix.Data.Messages), + ShaHex(flix.Data.Cadence, ""), + dependenciesToRlp(flix.Data.Dependencies), + parametersToRlp(flix.Data.Parameters), + } + + // msg := dependenciesToRlp(flix.Data.Dependencies) + //prettyJSON, _ := json.MarshalIndent(input, "", " ") + //fmt.Println(string(prettyJSON)) + + err = rlp.Encode(&buffer, input) + if err != nil { + return "", err + } + hexString := hex.EncodeToString(buffer.Bytes()) + + //fmt.Println("call to hash hex string") + fullyHashed := ShaHex(hexString, "input") + + //fmt.Println("hexString", fullyHashed) + return fullyHashed, nil + +} + +func GenerateFlixID(flix *InteractionTemplate) (string, error) { + rlpOutput, err := flix.EncodeRLP() + if err != nil { + return "", err + } + return string(rlpOutput), nil +} + +func ShaHex(value interface{}, debugKey string) string { + + // Convert the value to a byte array + data, err := convertToBytes(value) + if err != nil { + if debugKey != "" { + fmt.Printf("%30s value=%v hex=%x\n", debugKey, value, err.Error()) + } + return "" + } + + // Calculate the SHA-3 hash + hash := sha3.Sum256(data) + + // Convert the hash to a hexadecimal string + hashHex := hex.EncodeToString(hash[:]) + + return hashHex +} + +func convertToBytes(value interface{}) ([]byte, error) { + switch v := value.(type) { + case []byte: + return v, nil + case string: + return []byte(v), nil + case int: + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, uint32(v)) + return buf, nil + case uint64: + buf := make([]byte, 8) + binary.BigEndian.PutUint64(buf, v) + return buf, nil + default: + return nil, fmt.Errorf("unsupported type %T", v) + } +} + +func ExtractContractName(importStr string) (string, error) { + // Create a regex pattern to find the contract name inside the quotes + pattern := regexp.MustCompile(`import "([^"]+)"`) + matches := pattern.FindStringSubmatch(importStr) + + if len(matches) >= 2 { + return matches[1], nil + } + + return "", fmt.Errorf("no contract name found in string") +} diff --git a/flixkit/v1_1/types_test.go b/flixkit/v1_1/types_test.go new file mode 100644 index 0000000..1bcf41a --- /dev/null +++ b/flixkit/v1_1/types_test.go @@ -0,0 +1,853 @@ +package flixkit + +import ( + "encoding/json" + "testing" + + "github.com/hexops/autogold/v2" + "github.com/onflow/cadence/runtime/parser" + "github.com/stretchr/testify/assert" +) + +var pragmaWithParameters = ` +#interaction( + version: "1.1.0", + title: "Update Greeting", + description: "Update the greeting on the HelloWorld contract", + language: "en-US", + parameters: [ + Parameter( + name: "greeting", + title: "Greeting", + description: "The greeting to set on the HelloWorld contract" + ), + Parameter( + name: "amount", + title: "Amount", + description: "The amount parameter to Test" + ) + ], +) + +import "HelloWorld" +transaction(greeting: String, amount: UFix64) { + + prepare(acct: AuthAccount) { + log(acct.address) + } + + execute { + HelloWorld.updateGreeting(newGreeting: greeting) + } +} +` + +var pragmaWithoutParameters = ` +#interaction( + version: "1.1.0", + title: "Update Greeting", + description: "Update the greeting on the HelloWorld contract", + language: "en-US", +) + +import "HelloWorld" +transaction(greeting: String) { + + prepare(acct: AuthAccount) { + log(acct.address) + } + + execute { + HelloWorld.updateGreeting(newGreeting: greeting) + } +} +` + +var pragmaMinimum = ` +#interaction( + version: "1.1.0", +) + +import "HelloWorld" +transaction(greeting: String) { + + prepare(acct: AuthAccount) { + log(acct.address) + } + + execute { + HelloWorld.updateGreeting(newGreeting: greeting) + } +} +` + +var PragmaEmpty = ` +import "HelloWorld" +transaction(greeting: String) { + + prepare(acct: AuthAccount) { + log(acct.address) + } + + execute { + HelloWorld.updateGreeting(newGreeting: greeting) + } +} +` + +func TestParsePragma(t *testing.T) { + assert := assert.New(t) + + tests := []struct { + name string + wantErr bool + code string + }{ + { + name: "WithParameters", + wantErr: false, + code: pragmaWithParameters, + }, + { + name: "WithoutParameters", + wantErr: false, + code: pragmaWithoutParameters, + }, + { + name: "Minimum", + wantErr: false, + code: pragmaMinimum, + }, + { + name: "Empty", + wantErr: false, + code: PragmaEmpty, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + codeBytes := []byte(tt.code) + program, err := parser.ParseProgram(nil, codeBytes, parser.Config{}) + if err != nil { + t.Fatal(err) + } + var template InteractionTemplate + if err != nil { + t.Fatal(err) + } + + err = template.ParsePragma(program) + if err != nil && !tt.wantErr { + t.Fatal(err) + } + if err != nil { + t.Fatal(err) + } + prettyJSON, err := json.MarshalIndent(template, "", " ") + assert.NoError(err, "marshal template to json should not return an error") + autogold.ExpectFile(t, string(prettyJSON)) + + }) + } +} + +func TestGenerateParametersScripts(t *testing.T) { + templateString := ` + { + "f_type": "InteractionTemplate", + "f_version": "1.1.0", + "id": "", + "data": + { + "type": "script", + "interface": "", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "User Balance" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Get User Balance" + } + ] + }], + "cadence": {}, + "dependencies": [], + "parameters": [ + { + "label": "address", + "index": 0, + "type": "Address", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "User Address" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Get user balance" + } + ] + } + ] + } + ] + } + }` + + cadence := ` + import "FungibleToken" + import "FlowToken" + + pub fun main(address: Address): UFix64 { + let account = getAccount(address) + let vaultRef = account.getCapability(/public/flowTokenBalance) + .borrow<&FlowToken.Vault{FungibleToken.Balance}>() + ?? panic("Could not borrow balance reference to the Vault") + + return vaultRef.balance + } + + ` + + codeBytes := []byte(cadence) + program, err := parser.ParseProgram(nil, codeBytes, parser.Config{}) + if err != nil { + t.Errorf("ParseProgram() err %v", err) + } + + template, err := ParseFlix(templateString) + if err != nil { + t.Errorf("ParseFlix() err %v", err) + } + err = template.ProcessParameters(program) + if err != nil { + t.Errorf("process parameters err %v", err) + } + prettyJSON, err := json.MarshalIndent(template, "", " ") + if err != nil { + t.Errorf("process parameters err %v", err) + } + + autogold.ExpectFile(t, string(prettyJSON)) +} + +func TestGenerateTemplateIdWithDeps(t *testing.T) { + templateId := "fcada4d7a654a0386a4bb048ac4c851ad7de3945e6e835dc4593581b8c8113da" + code := ` + { + "f_type": "InteractionTemplate", + "f_version": "1.1.0", + "id": "", + "data": { + "type": "transaction", + "interface": "", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Update Greeting" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Update the greeting on the HelloWorld contract" + } + ] + } + ], + "cadence": { + "body": "import \"HelloWorld\"\n\n#interaction (\n version: \"1.1.0\",\n\ttitle: \"Update Greeting\",\n\tdescription: \"Update the greeting on the HelloWorld contract\",\n\tlanguage: \"en-US\",\n\tparameters: [\n\t\tParameter(\n\t\t\tname: \"greeting\", \n\t\t\ttitle: \"Greeting\", \n\t\t\tdescription: \"The greeting to set on the HelloWorld contract\"\n\t\t)\n\t],\n)\ntransaction(greeting: String) {\n\n prepare(acct: AuthAccount) {\n log(acct.address)\n }\n\n execute {\n HelloWorld.updateGreeting(newGreeting: greeting)\n }\n}\n", + "network_pins": [ + { + "network": "testnet", + "pin_self": "f61e68b5ba6987aaee393401889d5410b01ffa603a66952307319ea09fd505e7" + } + ] + }, + "dependencies": [ + { + "contracts": [ + { + "contract": "HelloWorld", + "networks": [ + { + "network": "testnet", + "address": "0xe15193734357cf5c", + "dependency_pin_block_height": 139331034, + "dependency_pin": { + "pin": "38b038a23c5975f90a797d6a821f9a8c4e4325a661f92513aedd73fda0e3300c", + "pin_self": "a06b3cd29330a3c22df3ac2383653e89c249c5e773fd4bbee73c45ea10294b97", + "pin_contract_name": "HelloWorld", + "pin_contract_address": "0xe15193734357cf5c", + "imports": [ + { + "pin": "3efc62adadbb1dedab0716ac031066a431cd7d627bc1b9260dd08a5a67b26b55", + "pin_self": "403cd82df774d247bc1fd7471e5ef1fdb7e2e0cb8ec44dce3af5473627179f9a", + "pin_contract_name": "GiveNumber", + "pin_contract_address": "0xe15193734357cf5c", + "imports": [] + } + ] + } + } + ] + } + ] + } + ], + "parameters": [ + { + "label": "greeting", + "index": 0, + "type": "String", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Greeting" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "The greeting to set on the HelloWorld contract" + } + ] + } + ] + } + ] + } + }` + + template, err := ParseFlix(code) + if err != nil { + t.Errorf("ParseFlix() err %v", err) + } + id, err := GenerateFlixID(template) + if err != nil { + t.Errorf("GenerateFlixID err %v", err) + } + + if id != templateId { + t.Errorf("GenerateFlixID got = %v, want %v", id, templateId) + } + +} + +func TestEmptyPragmaWithParameter(t *testing.T) { + codeBytes := []byte(PragmaEmpty) + program, err := parser.ParseProgram(nil, codeBytes, parser.Config{}) + if err != nil { + t.Fatal(err) + } + var template InteractionTemplate + err = template.ProcessParameters(program) + if err != nil { + t.Errorf("process parameters err %v", err) + } + prettyJSON, err := json.MarshalIndent(template, "", " ") + if err != nil { + t.Errorf("process parameters err %v", err) + } + + autogold.ExpectFile(t, string(prettyJSON)) + +} + +const template = ` +{ + "f_type": "InteractionTemplate", + "f_version": "1.1.0", + "id": "a2b2d73def...aabc5472d2", + "data": { + "type": "transaction", + "interface": "asadf23234...fas234234", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Transfer FLOW" + }, + { + "tag": "fr-FR", + "translation": "FLOW de transfert" + }, + { + "tag": "zh-CN", + "translation": "转移流程" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Transfer {amount} FLOW to {to}" + }, + { + "tag": "fr-FR", + "translation": "Transférez {amount} FLOW à {to}" + }, + { + "tag": "zh-CN", + "translation": "将 {amount} FLOW 转移到 {to}" + } + ] + }, + { + "key": "signer", + "i18n": [ + { + "tag": "en-US", + "translation": "Sign this message to transfer FLOW" + }, + { + "tag": "fr-FR", + "translation": "Signez ce message pour transférer FLOW." + }, + { + "tag": "zh-CN", + "translation": "签署此消息以转移FLOW。" + } + ] + } + ], + "cadence": { + "body": "import \"FlowToken\"\n transaction(amount: UFix64, to: Address) {\n let vault: @FungibleToken.Vault\n prepare(signer: AuthAccount) {\n %%self.vault <- signer\n .borrow<&{FungibleToken.Provider}>(from: /storage/flowTokenVault)!\n .withdraw(amount: amount)\n self.vault <- FungibleToken.getVault(signer)\n }\n execute {\n getAccount(to)\n .getCapability(/public/flowTokenReceiver)!\n .borrow<&{FungibleToken.Receiver}>()!\n .deposit(from: <-self.vault)\n }\n }", + "network_pins": [ + { + "network": "mainnet", + "pin_self": "186e262ce6fe06b5075ec6569a0e5482a79c471881182612d8e4a665c2977f3e" + }, + { + "network": "testnet", + "pin_self": "f93977d7a297f559e97259cb2a95fed0f87cfeec46c5257a26adc26a260d6c4c" + } + ] + }, + "dependencies": [ + { + "contracts": [ + { + "contract": "FlowToken", + "networks": [ + { + "network": "mainnet", + "address": "0x1654653399040a61", + "dependency_pin_block_height": 10123123123, + "dependency_pin": { + "pin": "c8cb7cc7a1c2a329de65d83455016bc3a9b53f9668c74ef555032804bac0b25b", + "pin_self": "38d0cca4b74c4e88213df636b4cfc2eb6e86fd8b2b84579d3b9bffab3e0b1fcb", + "pin_contract_name": "FlowToken", + "imports": [ + { + "pin": "b8a3ed26c222ed67016a28021d8fee5603b948533cbc992b3c90f71a61b2b312", + "pin_self": "7bc3056ba5d39d130f45411c2c05bb549db8ce727c11a1cb821136a621be27fb", + "pin_contract_name": "FungibleToken", + "pin_contract_address": "0xf233dcee88fe0abe", + "imports": [] + } + ] + } + }, + { + "network": "testnet", + "address": "0x7e60df042a9c0868", + "dependency_pin_block_height": 10123123123, + "dependency_pin": { + "pin": "c8cb7cc7a1c2a329de65d83455016bc3a9b53f9668c74ef555032804bac0b25b", + "pin_self": "38d0cca4b74c4e88213df636b4cfc2eb6e86fd8b2b84579d3b9bffab3e0b1fcb", + "pin_contract_name": "FlowToken", + "pin_contract_address": "0x7e60df042a9c0868", + "imports": [ + { + "pin": "b8a3ed26c222ed67016a28021d8fee5603b948533cbc992b3c90f71a61b2b312", + "pin_self": "7bc3056ba5d39d130f45411c2c05bb549db8ce727c11a1cb821136a621be27fb", + "pin_contract_name": "FungibleToken", + "pin_contract_address": "0x9a0766d93b6608b7", + "imports": [] + } + ] + } + } + ] + } + ] + } + ], + "parameters": [ + { + "label": "amount", + "index": 0, + "type": "UFix64", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "Amount" + }, + { + "tag": "fr-FR", + "translation": "Montant" + }, + { + "tag": "zh-CN", + "translation": "数量" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Amount of FLOW token to transfer" + }, + { + "tag": "fr-FR", + "translation": "Quantité de token FLOW à transférer" + }, + { + "tag": "zh-CN", + "translation": "要转移的 FLOW 代币数量" + } + ] + } + ], + "balance": "FlowToken" + }, + { + "label": "to", + "index": 1, + "type": "Address", + "messages": [ + { + "key": "title", + "i18n": [ + { + "tag": "en-US", + "translation": "To" + }, + { + "tag": "fr-FR", + "translation": "Pour" + }, + { + "tag": "zh-CN", + "translation": "到" + } + ] + }, + { + "key": "description", + "i18n": [ + { + "tag": "en-US", + "translation": "Amount of FLOW token to transfer" + }, + { + "tag": "fr-FR", + "translation": "Le compte vers lequel transférer les jetons FLOW" + }, + { + "tag": "zh-CN", + "translation": "将 FLOW 代币转移到的帐户" + } + ] + } + ] + } + ] + } + } +` +const templateMultipleImports = ` +{ + "f_type": "InteractionTemplate", + "f_version": "1.1.0", + "id": "29d03aafbbb5a02e0d5f4ffee685c12494915410812305c2858008d3e2902b72", + "data": { + "type": "script", + "interface": "", + "messages": null, + "cadence": { + "body": "import \"FungibleToken\"\nimport \"FlowToken\"\n\npub fun main(address: Address): UFix64 {\n let account = getAccount(address)\n\n let vaultRef = account\n .getCapability(/public/flowTokenBalance)\n .borrow\u003c\u0026FlowToken.Vault{FungibleToken.Balance}\u003e()\n ?? panic(\"Could not borrow balance reference to the Vault\")\n\n return vaultRef.balance\n}\n", + "network_pins": [ + { + "network": "mainnet", + "pin_self": "c9aef2c441b2ff0e1a724fcd72f7a48ae7fbbba3c6e72c530607a90ea0fdf93a" + }, + { + "network": "testnet", + "pin_self": "74331585cf3df9cd60e6570566d079f97b3e28b0e2156a06731e73e492fe120e" + } + ] + }, + "dependencies": [ + { + "contracts": [ + { + "contract": "FungibleToken", + "networks": [ + { + "network": "mainnet", + "address": "0xf233dcee88fe0abe", + "dependency_pin_block_height": 67669170, + "dependency_pin": { + "pin": "ac0208f93d07829ec96584d618ddbec6af3cf4e2866bd5071249e8ec93c7e0dc", + "pin_self": "cdadd5b5897f2dfe35d8b25f4e41fea9f8fca8f40f8a8b506b33701ef5033076", + "pin_contract_name": "FungibleToken", + "pin_contract_address": "0xf233dcee88fe0abe", + "imports": [] + } + }, + { + "network": "testnet", + "address": "0x9a0766d93b6608b7", + "dependency_pin_block_height": 139547221, + "dependency_pin": { + "pin": "ac0208f93d07829ec96584d618ddbec6af3cf4e2866bd5071249e8ec93c7e0dc", + "pin_self": "cdadd5b5897f2dfe35d8b25f4e41fea9f8fca8f40f8a8b506b33701ef5033076", + "pin_contract_name": "FungibleToken", + "pin_contract_address": "0x9a0766d93b6608b7", + "imports": [] + } + }, + { + "network": "emulator", + "address": "0xee82856bf20e2aa6", + "dependency_pin_block_height": 0 + } + ] + } + ] + }, + { + "contracts": [ + { + "contract": "FlowToken", + "networks": [ + { + "network": "mainnet", + "address": "0x1654653399040a61", + "dependency_pin_block_height": 67669170, + "dependency_pin": { + "pin": "a341e772da413bfbcf43b0fc167bd50a20c9f40baf10e12d3dbc2f5181526de9", + "pin_self": "0e932728b73bff3c09dd58922f2529fc7b7fe7477f1dcc61169bc8f46948ad91", + "pin_contract_name": "FlowToken", + "pin_contract_address": "0x1654653399040a61", + "imports": [ + { + "pin": "ac0208f93d07829ec96584d618ddbec6af3cf4e2866bd5071249e8ec93c7e0dc", + "pin_self": "cdadd5b5897f2dfe35d8b25f4e41fea9f8fca8f40f8a8b506b33701ef5033076", + "pin_contract_name": "FungibleToken", + "pin_contract_address": "0xf233dcee88fe0abe", + "imports": [] + } + ] + } + }, + { + "network": "testnet", + "address": "0x7e60df042a9c0868", + "dependency_pin_block_height": 139547221, + "dependency_pin": { + "pin": "9cc21a34a01486ebd6f044e99dbcdd58671850f81fcc345d071181c19f61aaa4", + "pin_self": "6f01c7001e2d6635b667a170d3ccbc13659c40d01bb35e56979fcc7fa2d18646", + "pin_contract_name": "FlowToken", + "pin_contract_address": "0x7e60df042a9c0868", + "imports": [ + { + "pin": "ac0208f93d07829ec96584d618ddbec6af3cf4e2866bd5071249e8ec93c7e0dc", + "pin_self": "cdadd5b5897f2dfe35d8b25f4e41fea9f8fca8f40f8a8b506b33701ef5033076", + "pin_contract_name": "FungibleToken", + "pin_contract_address": "0x9a0766d93b6608b7", + "imports": [] + } + ] + } + }, + { + "network": "emulator", + "address": "0x0ae53cb6e3f42a79", + "dependency_pin_block_height": 0 + } + ] + } + ] + } + ], + "parameters": [ + { + "label": "address", + "index": 0, + "type": "Address", + "messages": [] + } + ] + } +} +` +const templateMultipleCoreImports = ` +{ + "f_type": "InteractionTemplate", + "f_version": "1.1.0", + "id": "29d03aafbbb5a02e0d5f4ffee685c12494915410812305c2858008d3e2902b72", + "data": { + "type": "script", + "interface": "", + "messages": null, + "cadence": { + "body": "import \"FungibleToken\"\nimport \"FlowToken\"\n\npub fun main(address: Address): UFix64 {\n let account = getAccount(address)\n\n let vaultRef = account\n .getCapability(/public/flowTokenBalance)\n .borrow\u003c\u0026FlowToken.Vault{FungibleToken.Balance}\u003e()\n ?? panic(\"Could not borrow balance reference to the Vault\")\n\n return vaultRef.balance\n}\n", + "network_pins": [] + }, + "dependencies": [], + "parameters": [] + } +} +` + +const templateMissing = ` +{ + "f_type": "InteractionTemplate", + "f_version": "1.1.0", + "id": "a2b2d73def...aabc5472d2", + "data": { + "type": "transaction", + "interface": "asadf23234...fas234234", + "messages": [], + "cadence": { + "body": "import \"FlowTokenAA\"\n transaction(amount: UFix64, to: Address) {\n let vault: @FungibleToken.Vault\n prepare(signer: AuthAccount) {\n %%self.vault <- signer\n .borrow<&{FungibleToken.Provider}>(from: /storage/flowTokenVault)!\n .withdraw(amount: amount)\n self.vault <- FungibleToken.getVault(signer)\n }\n execute {\n getAccount(to)\n .getCapability(/public/flowTokenReceiver)!\n .borrow<&{FungibleToken.Receiver}>()!\n .deposit(from: <-self.vault)\n }\n }", + "network_pins": [] + }, + "dependencies": [ + { + "contracts": [], + "parameters": [] + } + ] + } +} +` + +func TestGetAndReplaceCadenceImports(t *testing.T) { + assert := assert.New(t) + + tests := []struct { + name string + network string + wantErr bool + wantImport string + template string + }{ + { + name: "Mainnet", + network: "mainnet", + wantErr: false, + wantImport: "import FlowToken from 0x1654653399040a61", + template: template, + }, + { + name: "Testnet", + network: "testnet", + wantErr: false, + wantImport: "import FlowToken from 0x7e60df042a9c0868", + template: template, + }, + { + name: "MissingNetwork", + network: "missing", + wantErr: true, + template: template, + }, + { + name: "MissingCadence", + network: "mainnet", + wantErr: true, + template: templateMissing, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + parsedTemplate, err := ParseFlix(tt.template) + if err != nil { + t.Fatal(err) + } + + cadenceCode, err := parsedTemplate.GetAndReplaceCadenceImports(tt.network) + if tt.wantErr { + assert.Error(err, tt.name, "GetCadenceWithReplacedImports should return an error") + } else { + assert.NoError(err, "GetCadenceWithReplacedImports should not return an error") + assert.NotEmpty(cadenceCode, tt.name, "Cadence should not be empty") + + assert.Contains(cadenceCode, tt.wantImport, "Cadence should contain the expected import") + } + }) + } +} + +func TestGetAndReplaceCadenceImportsMultipleImports(t *testing.T) { + template, err := ParseFlix(templateMultipleImports) + if err != nil { + t.Fatal(err) + } + cadenceCode, err := template.GetAndReplaceCadenceImports("mainnet") + if err != nil { + t.Fatal(err) + } + assert.Contains(t, cadenceCode, "import FungibleToken from 0xf233dcee88fe0abe", "Cadence should contain the expected FungibleToken import") + assert.Contains(t, cadenceCode, "import FlowToken from 0x1654653399040a61", "Cadence should contain the expected FlowTokenimport") + +} + +func TestGetAndReplaceCadenceImportsMultipleCoreImports(t *testing.T) { + template, err := ParseFlix(templateMultipleCoreImports) + if err != nil { + t.Fatal(err) + } + cadenceCode, err := template.GetAndReplaceCadenceImports("mainnet") + if err != nil { + t.Fatal(err) + } + assert.Contains(t, cadenceCode, "import FungibleToken from 0xf233dcee88fe0abe", "Cadence should contain the expected FungibleToken import") + assert.Contains(t, cadenceCode, "import FlowToken from 0x1654653399040a61", "Cadence should contain the expected FlowTokenimport") + +} diff --git a/generator/core_contracts.go b/generator/core_contracts.go deleted file mode 100644 index 49eddc4..0000000 --- a/generator/core_contracts.go +++ /dev/null @@ -1,101 +0,0 @@ -package generator - -import ( - "github.com/onflow/flixkit-go" -) - -func GetDefaultCoreContracts() flixkit.Contracts { - return flixkit.Contracts{ - "FungibleToken": { - "mainnet": { - Address: "0xf233dcee88fe0abe", - FqAddress: "A.0xf233dcee88fe0abe.FungibleToken", - Contract: "FungibleToken", - Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - PinBlockHeight: 34166296, - }, - "testnet": { - Address: "0x9a0766d93b6608b7", - FqAddress: "A.0x9a0766d93b6608b7.FungibleToken", - Contract: "FungibleToken", - Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - PinBlockHeight: 74776482, - }, - }, - "NonFungibleToken": { - "mainnet": { - Address: "0x1d7e57aa55817448", - FqAddress: "A.0x1d7e57aa55817448.NonFungibleToken", - Contract: "NonFungibleToken", - Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - PinBlockHeight: 47509012, - }, - "testnet": { - Address: "0x631e88ae7f1d7c20", - FqAddress: "A.0x631e88ae7f1d7c20.NonFungibleToken", - Contract: "NonFungibleToken", - Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - PinBlockHeight: 95808228, - }, - }, - "MetadataViews": { - "mainnet": { - Address: "0x1d7e57aa55817448", - FqAddress: "A.0x1d7e57aa55817448.NonFungibleToken", - Contract: "MetadataViews", - Pin: "ba061d95016d5506e9f5d1afda15d82eb066aa8b0552e8b26dc7950fa5714d51", - PinBlockHeight: 47487348, - }, - "testnet": { - Address: "0x631e88ae7f1d7c20", - FqAddress: "A.0x631e88ae7f1d7c20.NonFungibleToken", - Contract: "MetadataViews", - Pin: "ba061d95016d5506e9f5d1afda15d82eb066aa8b0552e8b26dc7950fa5714d51", - PinBlockHeight: 95782517, - }, - }, - "FlowToken": { - "mainnet": { - Address: "0x1654653399040a61", - FqAddress: "A.0x1654653399040a61.FlowToken", - Contract: "FlowToken", - Pin: "0326c320322c4e8dde768ba2975c384184fb7e41765c2c87e79a2040bfc71be8", - PinBlockHeight: 47509023, - }, - "testnet": { - Address: "0x7e60df042a9c0868", - FqAddress: "A.0x7e60df042a9c0868.FlowToken", - Contract: "FlowToken", - Pin: "0326c320322c4e8dde768ba2975c384184fb7e41765c2c87e79a2040bfc71be8", - PinBlockHeight: 95808240, - }, - }, - } -} - -// GetContractInformation returns the contract information for a given contract name -// todo: this information should be generated so it can be updated easily -// todo: this should be moved to a separate package or maybe this inforation already exists somewhere else -func GetContractInformation(contractName string, deployedContracts []flixkit.Contracts, coreContracts flixkit.Contracts) flixkit.Networks { - contracts := make(flixkit.Contracts) - - for contractName, network := range coreContracts { - contracts[contractName] = network - } - - // add deployed contracts to contracts map - for _, contract := range deployedContracts { - for contractName, network := range contract { - contracts[contractName] = network - } - } - - // To lookup a specific entry: - _, exists := contracts[contractName] - if exists { - return contracts[contractName] - } - - return nil - -} diff --git a/generator/core_contracts_test.go b/generator/core_contracts_test.go deleted file mode 100644 index 3cb34d2..0000000 --- a/generator/core_contracts_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package generator - -import "testing" - -func TestContractExist(t *testing.T) { - tests := []struct { - name string - input string - output bool - }{ - { - name: "existing contract", - input: "FungibleToken", - output: true, - }, - { - name: "non-existing contract", - input: "NonExistingContract", - output: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := GetContractInformation(tt.input, nil, GetDefaultCoreContracts()) - if tt.output && got == nil { - t.Errorf("ContractExist() got = %v, want %v", got, tt.output) - } - }) - } -} diff --git a/generator/flixkitv1_0_0/generator.go b/generator/flixkitv1_0_0/generator.go deleted file mode 100644 index cc8e2ba..0000000 --- a/generator/flixkitv1_0_0/generator.go +++ /dev/null @@ -1,157 +0,0 @@ -package flixkitv1_0_0 - -import ( - "context" - "fmt" - - "github.com/onflow/cadence/runtime/ast" - "github.com/onflow/cadence/runtime/parser" - "github.com/onflow/flixkit-go" - "github.com/onflow/flixkit-go/generator" - "github.com/onflow/flow-cli/flowkit" - "github.com/onflow/flow-cli/flowkit/config" - "github.com/onflow/flow-cli/flowkit/gateway" - "github.com/onflow/flow-cli/flowkit/output" - "github.com/onflow/flow-go-sdk/crypto" - "github.com/spf13/afero" -) - -type Generator struct { - deployedContracts []flixkit.Contracts - coreContracts flixkit.Contracts - testnetClient *flowkit.Flowkit - mainnetClient *flowkit.Flowkit -} - -// stubb to pass in parameters -func NewGenerator(deployedContracts []flixkit.Contracts, coreContracts flixkit.Contracts, logger output.Logger) (flixkit.Generator, error) { - loader := afero.Afero{Fs: afero.NewOsFs()} - - gwt, err := gateway.NewGrpcGateway(config.TestnetNetwork) - if err != nil { - return nil, fmt.Errorf("could not create grpc gateway for testnet %w", err) - } - - gwm, err := gateway.NewGrpcGateway(config.MainnetNetwork) - if err != nil { - return nil, fmt.Errorf("could not create grpc gateway for mainnet %w", err) - } - - state, err := flowkit.Init(loader, crypto.ECDSA_P256, crypto.SHA3_256) - if err != nil { - return nil, fmt.Errorf("could not initialize flowkit state %w", err) - } - testnetClient := flowkit.NewFlowkit(state, config.TestnetNetwork, gwt, logger) - mainnetClient := flowkit.NewFlowkit(state, config.MainnetNetwork, gwm, logger) - - if coreContracts == nil { - coreContracts = generator.GetDefaultCoreContracts() - } - - return &Generator{ - deployedContracts: deployedContracts, - coreContracts: coreContracts, - testnetClient: testnetClient, - mainnetClient: mainnetClient, - }, nil -} - -func (g Generator) Generate(ctx context.Context, code string, preFill *flixkit.FlowInteractionTemplate) (*flixkit.FlowInteractionTemplate, error) { - template := &flixkit.FlowInteractionTemplate{} - if preFill != nil { - template = preFill - } - - // make sure imports use new import syntax "string import" - normalizedCode := generator.NormalizeImports(code) - - codeBytes := []byte(normalizedCode) - program, err := parser.ParseProgram(nil, codeBytes, parser.Config{}) - if err != nil { - return nil, err - } - - err = generator.ProcessParameters(program, template) - if err != nil { - return nil, err - } - - // save v1.0.0 cadence code to template, with placeholder imports - template.Data.Cadence = generator.UnNormalizeImports(normalizedCode) - err = g.processDependencies(ctx, program, template) - if err != nil { - return nil, err - } - - // ignore interface type for now - template.FType = "InteractionTemplate" - template.FVersion = "1.0.0" - template.Data.Type = generator.DetermineCadenceType(program) - id, err := flixkit.GenerateFlixID(template) - if err != nil { - return nil, err - } - template.ID = id - - return template, nil -} - -func (g Generator) processDependencies(ctx context.Context, program *ast.Program, template *flixkit.FlowInteractionTemplate) error { - imports := program.ImportDeclarations() - - if len(imports) == 0 { - return nil - } - - // fill in dependence information - deps := make(flixkit.Dependencies, len(imports)) - for _, imp := range imports { - contractName, err := generator.ExtractContractName(imp.String()) - if err != nil { - return err - } - dep, err := g.generateDependenceInfo(ctx, contractName) - if err != nil { - return err - } - for contractName, contract := range dep { - deps[contractName] = contract - } - template.Data.Dependencies = deps - } - - return nil -} - -func (g *Generator) generateDependenceInfo(ctx context.Context, contractName string) (map[string]flixkit.Contracts, error) { - var placeholder string - var info flixkit.Networks - // new import syntax detected, convert to old import syntax, limitation of 1.0.0 - placeholder = "0x" + contractName - info = generator.GetContractInformation(contractName, g.deployedContracts, g.coreContracts) - - for name, network := range info { - var flowkit *flowkit.Flowkit - if name == config.MainnetNetwork.Name && g.mainnetClient != nil { - flowkit = g.mainnetClient - } else if name == config.TestnetNetwork.Name && g.testnetClient != nil { - flowkit = g.testnetClient - } - if network.Pin == "" && flowkit != nil { - hash, height, _ := generator.GeneratePinDebthFirst(ctx, *flowkit, network.Address, network.Contract) - network.Pin = hash - network.PinBlockHeight = height - } - info[name] = network - } - - if info == nil { - return nil, fmt.Errorf("contract %s not found", contractName) - } - - return map[string]flixkit.Contracts{ - placeholder: { - contractName: info, - }, - }, nil -} diff --git a/generator/flixkitv1_0_0/generator_test.go b/generator/flixkitv1_0_0/generator_test.go deleted file mode 100644 index 36e8023..0000000 --- a/generator/flixkitv1_0_0/generator_test.go +++ /dev/null @@ -1,263 +0,0 @@ -package flixkitv1_0_0 - -import ( - "context" - "encoding/json" - "testing" - - "github.com/hexops/autogold/v2" - "github.com/onflow/flixkit-go" - "github.com/onflow/flixkit-go/generator" - "github.com/stretchr/testify/assert" -) - -func TestGenerateWithPrefill(t *testing.T) { - assert := assert.New(t) - templatePreFill := `{ - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "", - "data": { - "type": "transaction", - "interface": "", - "messages": { - "title": { - "i18n": { - "en-US": "Transfer Tokens" - } - }, - "description": { - "i18n": { - "en-US": "Transfer tokens from one account to another" - } - } - }, - "cadence": "", - "dependencies": {}, - "arguments": { - "amount": { - "index": 0, - "type": "UFix64", - "messages": { - "title": { - "i18n": { - "en-US": "Amount " - } - }, - "description": { - "i18n": { - "en-US": "Number of tokens to transfer" - } - } - }, - "balance": "" - }, - "to": { - "index": 1, - "type": "Address", - "messages": { - "title": { - "i18n": { - "en-US": "Account" - } - }, - "description": { - "i18n": { - "en-US": "Destination Account" - } - } - }, - "balance": "" - } - } - } - }` - prefill, _ := flixkit.ParseFlix(templatePreFill) - - code := ` - import FungibleToken from 0xFungibleTokenAddress - import FlowToken from 0xFlowTokenAddress - - transaction(amount: UFix64, to: Address) { - let vault: @FungibleToken.Vault - - prepare(signer: AuthAccount) { - self.vault <- signer - .borrow<&{FungibleToken.Provider}>(from: /storage/flowTokenVault)! - .withdraw(amount: amount) - } - - execute { - getAccount(to) - .getCapability(/public/flowTokenReceiver)! - .borrow<&{FungibleToken.Receiver}>()! - .deposit(from: <-self.vault) - } - } -` - gen := Generator{ - deployedContracts: []flixkit.Contracts{}, - coreContracts: generator.GetDefaultCoreContracts(), - testnetClient: nil, - mainnetClient: nil, - } - ctx := context.Background() - template, err := gen.Generate(ctx, code, prefill) - assert.NoError(err, "Generate should not return an error") - prettyJSON, err := json.MarshalIndent(template, "", " ") - assert.NoError(err, "marshal template to json should not return an error") - autogold.ExpectFile(t, string(prettyJSON)) -} - -func TestSimpleScriptGen(t *testing.T) { - templatePreFill := `{ - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "", - "data": { - "type": "script", - "interface": "", - "messages": { - "title": { - "i18n": { - "en-US": "read Greeting" - } - }, - "description": { - "i18n": { - "en-US": "read greeting of the HelloWorld smart contract" - } - } - }, - "cadence": "", - "dependencies": {}, - "arguments": {} - } - }` - prefill, _ := flixkit.ParseFlix(templatePreFill) - contracts := []flixkit.Contracts{ - { - "HelloWorld": flixkit.Networks{ - "emulator": flixkit.Network{ - Address: "0x01cf0e2f2f715450", - FqAddress: "A.01cf0e2f2f715450.HelloWorld", - Contract: "HelloWorld", - }, - }, - }, - } - generator := Generator{ - deployedContracts: contracts, - testnetClient: nil, - mainnetClient: nil, - } - assert := assert.New(t) - code := ` - import "HelloWorld" - - pub fun main(): String { - return HelloWorld.greeting - } -` - ctx := context.Background() - template, err := generator.Generate(ctx, code, prefill) - assert.NoError(err, "Generate should not return an error") - prettyJSON, err := json.MarshalIndent(template, "", " ") - assert.NoError(err, "marshal template to json should not return an error") - autogold.ExpectFile(t, string(prettyJSON)) - -} - -func TestMinimumValues(t *testing.T) { - contracts := []flixkit.Contracts{ - { - "HelloWorld": flixkit.Networks{ - "emulator": flixkit.Network{ - Address: "0x01cf0e2f2f715450", - FqAddress: "A.01cf0e2f2f715450.HelloWorld", - Contract: "HelloWorld", - Pin: "xxxxxmake-up-data", - PinBlockHeight: 10, - }, - }, - }, - } - generator := Generator{ - deployedContracts: contracts, - testnetClient: nil, - mainnetClient: nil, - } - assert := assert.New(t) - code := ` - import "HelloWorld" - - pub fun main(): String { - return HelloWorld.greeting - } -` - ctx := context.Background() - template, err := generator.Generate(ctx, code, nil) - assert.NoError(err, "Generate should not return an error") - prettyJSON, err := json.MarshalIndent(template, "", " ") - assert.NoError(err, "marshal template to json should not return an error") - autogold.ExpectFile(t, string(prettyJSON)) - -} - -func TestGetDependenceContract(t *testing.T) { - fungi := flixkit.Contracts{ - "LocalContract": { - "mainnet": { - Address: "0xf233dcee88fe0abe", - FqAddress: "A.0xf233dcee88fe0abe.LocalContract", - Contract: "LocalContract", - Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - PinBlockHeight: 34166296, - }, - "testnet": { - Address: "0x9a0766d93b6608b7", - FqAddress: "A.0x9a0766d93b6608b7.LocalContract", - Contract: "LocalContract", - Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - PinBlockHeight: 74776482, - }, - }, - } - genV1 := Generator{ - deployedContracts: []flixkit.Contracts{fungi}, - coreContracts: generator.GetDefaultCoreContracts(), - testnetClient: nil, - mainnetClient: nil, - } - - tests := []struct { - contractName string - want flixkit.Contracts - }{ - { - contractName: `FungibleToken`, - want: fungi, - }, - { - contractName: `LocalContract`, - want: fungi, - }, - } - - for _, tt := range tests { - t.Run(tt.contractName, func(t *testing.T) { - got, err := genV1.generateDependenceInfo(context.Background(), tt.contractName) - if err != nil { - t.Errorf("generateDependenceInfo() err %v", err) - } - if got == nil { - t.Errorf("generateDependenceInfo() got = %v, want %v", got, tt.want) - } - prettyJSON, err := json.MarshalIndent(got, "", " ") - if err != nil { - t.Errorf("generateDependenceInfo() err %v", err) - } - autogold.ExpectFile(t, string(prettyJSON)) - }) - } -} diff --git a/generator/flixkitv1_0_0/testdata/TestGenerateWithPrefill.golden b/generator/flixkitv1_0_0/testdata/TestGenerateWithPrefill.golden deleted file mode 100644 index 9bdef2b..0000000 --- a/generator/flixkitv1_0_0/testdata/TestGenerateWithPrefill.golden +++ /dev/null @@ -1,96 +0,0 @@ -`{ - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "90f71b92526db34818081ea9855484c2230c5b06d0abc2cbd6750631429ce3f0", - "data": { - "type": "transaction", - "interface": "", - "messages": { - "title": { - "i18n": { - "en-US": "Transfer Tokens" - } - }, - "description": { - "i18n": { - "en-US": "Transfer tokens from one account to another" - } - } - }, - "cadence": "\n\timport FungibleToken from 0xFungibleToken\n\timport FlowToken from 0xFlowToken\n\t\n\ttransaction(amount: UFix64, to: Address) {\n\t let vault: @FungibleToken.Vault\n\t\n\t prepare(signer: AuthAccount) {\n\t\tself.vault \u003c- signer\n\t\t .borrow\u003c\u0026{FungibleToken.Provider}\u003e(from: /storage/flowTokenVault)!\n\t\t .withdraw(amount: amount)\n\t }\n\t\n\t execute {\n\t\tgetAccount(to)\n\t\t .getCapability(/public/flowTokenReceiver)!\n\t\t .borrow\u003c\u0026{FungibleToken.Receiver}\u003e()!\n\t\t .deposit(from: \u003c-self.vault)\n\t }\n\t}\n", - "dependencies": { - "0xFlowToken": { - "FlowToken": { - "mainnet": { - "address": "0x1654653399040a61", - "fq_address": "A.0x1654653399040a61.FlowToken", - "contract": "FlowToken", - "pin": "0326c320322c4e8dde768ba2975c384184fb7e41765c2c87e79a2040bfc71be8", - "pin_block_height": 47509023 - }, - "testnet": { - "address": "0x7e60df042a9c0868", - "fq_address": "A.0x7e60df042a9c0868.FlowToken", - "contract": "FlowToken", - "pin": "0326c320322c4e8dde768ba2975c384184fb7e41765c2c87e79a2040bfc71be8", - "pin_block_height": 95808240 - } - } - }, - "0xFungibleToken": { - "FungibleToken": { - "mainnet": { - "address": "0xf233dcee88fe0abe", - "fq_address": "A.0xf233dcee88fe0abe.FungibleToken", - "contract": "FungibleToken", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 34166296 - }, - "testnet": { - "address": "0x9a0766d93b6608b7", - "fq_address": "A.0x9a0766d93b6608b7.FungibleToken", - "contract": "FungibleToken", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 74776482 - } - } - } - }, - "arguments": { - "amount": { - "index": 0, - "type": "UFix64", - "messages": { - "title": { - "i18n": { - "en-US": "Amount " - } - }, - "description": { - "i18n": { - "en-US": "Number of tokens to transfer" - } - } - }, - "balance": "" - }, - "to": { - "index": 1, - "type": "Address", - "messages": { - "title": { - "i18n": { - "en-US": "Account" - } - }, - "description": { - "i18n": { - "en-US": "Destination Account" - } - } - }, - "balance": "" - } - } - } -}` diff --git a/generator/flixkitv1_0_0/testdata/TestGetDependenceContract/FungibleToken.golden b/generator/flixkitv1_0_0/testdata/TestGetDependenceContract/FungibleToken.golden deleted file mode 100644 index 6363804..0000000 --- a/generator/flixkitv1_0_0/testdata/TestGetDependenceContract/FungibleToken.golden +++ /dev/null @@ -1,20 +0,0 @@ -`{ - "0xFungibleToken": { - "FungibleToken": { - "mainnet": { - "address": "0xf233dcee88fe0abe", - "fq_address": "A.0xf233dcee88fe0abe.FungibleToken", - "contract": "FungibleToken", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 34166296 - }, - "testnet": { - "address": "0x9a0766d93b6608b7", - "fq_address": "A.0x9a0766d93b6608b7.FungibleToken", - "contract": "FungibleToken", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 74776482 - } - } - } -}` diff --git a/generator/flixkitv1_0_0/testdata/TestGetDependenceContract/LocalContract.golden b/generator/flixkitv1_0_0/testdata/TestGetDependenceContract/LocalContract.golden deleted file mode 100644 index 9fa60e4..0000000 --- a/generator/flixkitv1_0_0/testdata/TestGetDependenceContract/LocalContract.golden +++ /dev/null @@ -1,20 +0,0 @@ -`{ - "0xLocalContract": { - "LocalContract": { - "mainnet": { - "address": "0xf233dcee88fe0abe", - "fq_address": "A.0xf233dcee88fe0abe.LocalContract", - "contract": "LocalContract", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 34166296 - }, - "testnet": { - "address": "0x9a0766d93b6608b7", - "fq_address": "A.0x9a0766d93b6608b7.LocalContract", - "contract": "LocalContract", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 74776482 - } - } - } -}` diff --git a/generator/flixkitv1_0_0/testdata/TestMinimumValues.golden b/generator/flixkitv1_0_0/testdata/TestMinimumValues.golden deleted file mode 100644 index ed6461c..0000000 --- a/generator/flixkitv1_0_0/testdata/TestMinimumValues.golden +++ /dev/null @@ -1,25 +0,0 @@ -`{ - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "325ce118598e38d5c282415ebe4fab7530a30f26af3d414abf229efb83bab97a", - "data": { - "type": "script", - "interface": "", - "messages": {}, - "cadence": "\n\timport HelloWorld from 0xHelloWorld\n\n\tpub fun main(): String {\n\treturn HelloWorld.greeting\n\t}\n", - "dependencies": { - "0xHelloWorld": { - "HelloWorld": { - "emulator": { - "address": "0x01cf0e2f2f715450", - "fq_address": "A.01cf0e2f2f715450.HelloWorld", - "contract": "HelloWorld", - "pin": "xxxxxmake-up-data", - "pin_block_height": 10 - } - } - } - }, - "arguments": null - } -}` diff --git a/generator/flixkitv1_0_0/testdata/TestSimpleScriptGen.golden b/generator/flixkitv1_0_0/testdata/TestSimpleScriptGen.golden deleted file mode 100644 index 010a314..0000000 --- a/generator/flixkitv1_0_0/testdata/TestSimpleScriptGen.golden +++ /dev/null @@ -1,36 +0,0 @@ -`{ - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "fccf61e27f0fde29fb4ea6e51de36f454297c2e92f6f3ec2f7cece1243737261", - "data": { - "type": "script", - "interface": "", - "messages": { - "title": { - "i18n": { - "en-US": "read Greeting" - } - }, - "description": { - "i18n": { - "en-US": "read greeting of the HelloWorld smart contract" - } - } - }, - "cadence": "\n\timport HelloWorld from 0xHelloWorld\n\n\tpub fun main(): String {\n\treturn HelloWorld.greeting\n\t}\n", - "dependencies": { - "0xHelloWorld": { - "HelloWorld": { - "emulator": { - "address": "0x01cf0e2f2f715450", - "fq_address": "A.01cf0e2f2f715450.HelloWorld", - "contract": "HelloWorld", - "pin": "", - "pin_block_height": 0 - } - } - } - }, - "arguments": {} - } -}` diff --git a/generator/testdata/TestGenerateParameters.golden b/generator/testdata/TestGenerateParameters.golden deleted file mode 100644 index c8f8f90..0000000 --- a/generator/testdata/TestGenerateParameters.golden +++ /dev/null @@ -1,61 +0,0 @@ -`{ - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "", - "data": { - "type": "transaction", - "interface": "", - "messages": { - "title": { - "i18n": { - "en-US": "Transfer Tokens" - } - }, - "description": { - "i18n": { - "en-US": "Transfer tokens from one account to another" - } - } - }, - "cadence": "import FungibleToken from 0xFungibleToken\ntransaction(amount: UFix64, to: Address) {\nlet vault: @FungibleToken.Vault\nprepare(signer: AuthAccount) {\nself.vault \u003c- signer\n.borrow\u003c\u0026{FungibleToken.Provider}\u003e(from: /storage/flowTokenVault)!\n.withdraw(amount: amount)\n}\nexecute {\ngetAccount(to)\n.getCapability(/public/flowTokenReceiver)!\n.borrow\u003c\u0026{FungibleToken.Receiver}\u003e()!\n.deposit(from: \u003c-self.vault)\n}\n}", - "dependencies": { - "0xFungibleToken": { - "FungibleToken": { - "mainnet": { - "address": "0xf233dcee88fe0abe", - "fq_address": "A.0xf233dcee88fe0abe.FungibleToken", - "contract": "FungibleToken", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 34166296 - }, - "testnet": { - "address": "0x9a0766d93b6608b7", - "fq_address": "A.0x9a0766d93b6608b7.FungibleToken", - "contract": "FungibleToken", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 74776482 - } - } - } - }, - "arguments": { - "greeting": { - "index": 0, - "type": "String", - "messages": { - "title": { - "i18n": { - "en-US": "Greeting Update" - } - }, - "description": { - "i18n": { - "en-US": "Update contract greeting message" - } - } - }, - "balance": "" - } - } - } -}` diff --git a/generator/testdata/TestGenerateParametersScripts.golden b/generator/testdata/TestGenerateParametersScripts.golden deleted file mode 100644 index cc8be03..0000000 --- a/generator/testdata/TestGenerateParametersScripts.golden +++ /dev/null @@ -1,42 +0,0 @@ -`{ - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "", - "data": { - "type": "script", - "interface": "", - "messages": { - "title": { - "i18n": { - "en-US": "Get Tokens Balance" - } - }, - "description": { - "i18n": { - "en-US": "Get user token balance" - } - } - }, - "cadence": "", - "dependencies": {}, - "arguments": { - "address": { - "index": 0, - "type": "Address", - "messages": { - "title": { - "i18n": { - "en-US": "User Account" - } - }, - "description": { - "i18n": { - "en-US": "User account address" - } - } - }, - "balance": "" - } - } - } -}` diff --git a/generator/utils.go b/generator/utils.go deleted file mode 100644 index 451fe8c..0000000 --- a/generator/utils.go +++ /dev/null @@ -1,172 +0,0 @@ -package generator - -import ( - "context" - "fmt" - "regexp" - "strings" - - "github.com/onflow/cadence/runtime/ast" - "github.com/onflow/cadence/runtime/cmd" - "github.com/onflow/cadence/runtime/common" - "github.com/onflow/flixkit-go" - "github.com/onflow/flow-cli/flowkit" - "github.com/onflow/flow-go-sdk" -) - -func ProcessParameters(program *ast.Program, template *flixkit.FlowInteractionTemplate) error { - - if program != nil { - var parameterList []*ast.Parameter - functionDeclaration := program.FunctionDeclarations() - // only interested in main function of script - for _, d := range functionDeclaration { - if d.Identifier.String() == "main" { - parameterList = d.ParameterList.Parameters - } - } - - if program.SoleTransactionDeclaration() != nil && program.SoleTransactionDeclaration().ParameterList != nil { - parameterList = program.SoleTransactionDeclaration().ParameterList.Parameters - } - - if parameterList != nil && template.Data.Arguments == nil { - template.Data.Arguments = flixkit.Arguments{} - } - - for i, param := range parameterList { - argMessages := flixkit.Messages{} - if template.Data.Arguments[param.Identifier.String()] != (flixkit.Argument{}) { - argMessages = template.Data.Arguments[param.Identifier.String()].Messages - } - template.Data.Arguments[param.Identifier.String()] = flixkit.Argument{ - Type: param.TypeAnnotation.Type.String(), - Index: i, - Messages: argMessages, - } - } - } - return nil -} - -func RegexpMatch(pattern, text string) (map[string]string, error) { - r := regexp.MustCompile(pattern) - names := r.SubexpNames() - match := r.FindStringSubmatch(text) - if match == nil { - return nil, nil - } - - m := map[string]string{} - for i, n := range match { - m[names[i]] = n - } - - return m, nil -} - -func DetermineCadenceType(program *ast.Program) string { - funcs := program.FunctionDeclarations() - trans := program.TransactionDeclarations() - - if len(funcs) > 0 { - return "script" - } else if len(trans) > 0 { - return "transaction" - } - return "interface" -} - -func NormalizeImports(cadenceCode string) string { - // Define a regular expression to match the "import ContractName from 0xContractName" pattern - pattern := regexp.MustCompile(`import\s+(\w+)\s+from\s+0x\w+`) - // Replace the matched pattern with "import \"ContractName\"" - replaced := pattern.ReplaceAllString(cadenceCode, `import "$1"`) - return replaced -} - -func UnNormalizeImports(cadenceCode string) string { - // Define a regular expression to match the import "ContractName" pattern - pattern := regexp.MustCompile(`import "(.+?)"`) - // Replace the matched pattern with "import ContractName from 0xContractName" - replaced := pattern.ReplaceAllString(cadenceCode, `import $1 from 0x$1`) - return replaced -} - -func ExtractContractName(importStr string) (string, error) { - // Create a regex pattern to find the contract name inside the quotes - pattern := regexp.MustCompile(`import "([^"]+)"`) - matches := pattern.FindStringSubmatch(importStr) - - if len(matches) >= 2 { - return matches[1], nil - } - - return "", fmt.Errorf("no contract name found in string") -} - -/* - Thanks to Overflow, https://github.com/bjartek/overflow/ for all the contract pinning code -*/ -// https://github.com/onflow/fcl-js/blob/master/packages/fcl/src/interaction-template-utils/generate-dependency-pin.js -func generateDependentPin(ctx context.Context, flowkit flowkit.Flowkit, address string, name string, cache map[string][]string) ([]string, error) { - - identifier := fmt.Sprintf("A.%s.%s", strings.ReplaceAll(address, "0x", ""), name) - existingHash, ok := cache[identifier] - if ok { - return existingHash, nil - } - - account, err := flowkit.GetAccount(ctx, flow.HexToAddress(address)) - if err != nil { - return nil, err - } - code := account.Contracts[name] - imports := getAddressImports(code, name) - hashes := []string{flixkit.ShaHex(code, "")} - - for _, imp := range imports { - split := strings.Split(imp, ".") - address, name := split[0], split[1] - dep, err := generateDependentPin(ctx, flowkit, address, name, cache) - if err != nil { - return nil, err - } - hashes = append(hashes, dep...) - } - cache[identifier] = hashes - return hashes, nil -} - -func getAddressImports(code []byte, name string) []string { - deps := []string{} - codes := map[common.Location][]byte{} - location := common.StringLocation(name) - program, _ := cmd.PrepareProgram(code, location, codes) - for _, imp := range program.ImportDeclarations() { - address, isAddressImport := imp.Location.(common.AddressLocation) - if isAddressImport { - adr := address.Address.Hex() - impName := imp.Identifiers[0].Identifier - deps = append(deps, fmt.Sprintf("%s.%s", adr, impName)) - } - } - return deps -} - -// future: use service to get deployed contracts hashes -func GeneratePinDebthFirst(ctx context.Context, flowkit flowkit.Flowkit, address string, name string) (string, uint64, error) { - - memoize := map[string][]string{} - pin, err := generateDependentPin(ctx, flowkit, address, name, memoize) - - if err != nil { - return "", 0, err - } - - block, _ := flowkit.Gateway().GetLatestBlock() - height := block.Height - hash := flixkit.ShaHex(strings.Join(pin, ""), "") - - return hash, height, nil -} diff --git a/generator/utils_test.go b/generator/utils_test.go deleted file mode 100644 index bc50652..0000000 --- a/generator/utils_test.go +++ /dev/null @@ -1,576 +0,0 @@ -package generator - -import ( - "encoding/json" - "testing" - - "github.com/hexops/autogold/v2" - "github.com/onflow/cadence/runtime/parser" - "github.com/onflow/flixkit-go" -) - -func TestDepCheck(t *testing.T) { - tests := []struct { - cadence string - cadenceType string - }{ - { - cadence: `import "FungibleToken" - - pub fun main(accountAddress: Address): UFix64 { - let account = getAccount(accountAddress) - let balanceRef = account.borrow<&FungibleToken.Vault{FungibleToken.Balance}>(from: /public/fungibleTokenBalance) - ?? panic("Could not borrow reference to the account's Vault") - - return balanceRef.balance - } - `, - cadenceType: "script", - }, - { - cadence: `import "FungibleToken" - - transaction(amount: UFix64, recipient: Address) { - - // Reference to the sender's Vault - let tokenVault: @FungibleToken.Vault - - prepare(signer: AuthAccount) { - self.tokenVault = signer.borrow<&FungibleToken.Vault>(from: /storage/fungibleTokenVault) - ?? panic("Could not borrow reference to the owner's Vault") - } - - execute { - let recipient = getAccount(recipient) - let recipientVault = recipient.getCapability(/public/fungibleTokenReceiver) - .borrow<&{FungibleToken.Receiver}>() - ?? panic("Could not borrow receiver reference from the recipient") - - recipientVault.deposit(from: <-self.tokenVault.withdraw(amount: amount)) - } - } - `, - cadenceType: "transaction", - }, { - cadence: ` -/* -Here are some comments and transaction is on start of a line -*/ -transaction(amount: UFix64, recipient: Address) { -// More comments -// Reference to the sender's Vault -prepare(signer: AuthAccount) {} -execute {}} - `, - cadenceType: "transaction", - }, - { - cadence: `import "NonFungibleToken" - - pub fun main(accountAddress: Address, tokenId: UInt64): Bool { - let account = getAccount(accountAddress) - let collectionRef = account.borrow<&NonFungibleToken.Collection{NonFungibleToken.CollectionPublic}>(from: /public/nftCollection) - ?? panic("Could not borrow reference to the NFT Collection") - - return collectionRef.borrowNFT(id: tokenId) != nil - } - `, - cadenceType: "script", - }, - { - cadence: `pub contract interface TokenContract { - - // Returns the total supply of tokens - pub fun totalSupply(): UFix64 - - // Returns the balance of the specified address - pub fun balanceOf(address: Address): UFix64 - - // Transfers tokens from one address to another - pub fun transfer(from: Address, to: Address, amount: UFix64): Bool - } - `, - cadenceType: "interface", - }, - } - - for _, tt := range tests { - t.Run(tt.cadence, func(t *testing.T) { - codeBytes := []byte(tt.cadence) - program, _ := parser.ParseProgram(nil, codeBytes, parser.Config{}) - got := DetermineCadenceType(program) - if got != tt.cadenceType { - t.Errorf("DetermineCadenceType() got = %v, want %v", got, tt.cadenceType) - } - }) - } - -} - -func TestGenerateTemplateId(t *testing.T) { - templateId := "bd10ab0bf472e6b58ecc0398e9b3d1bd58a4205f14a7099c52c0640d9589295f" - code := ` - { - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "", - "data": { - "type": "script", - "interface": "", - "messages": { - "title": { - "i18n": { - "en-US": "Multiply Two Integers" - } - }, - "description": { - "i18n": { - "en-US": "Multiplies two integer arguments together and returns the result." - } - } - }, - "cadence": "pub fun main(x: Int, y: Int): Int { return x * y }", - "dependencies": {}, - "arguments": { - "x": { - "index": 0, - "type": "Int", - "messages": { - "title": { - "i18n": { - "en-US": "Int 1" - } - } - } - }, - "y": { - "index": 1, - "type": "Int", - "messages": { - "title": { - "i18n": { - "en-US": "Int 2" - } - } - } - } - } - } - }` - - template, err := flixkit.ParseFlix(code) - if err != nil { - t.Errorf("ParseFlix() err %v", err) - } - id, err := flixkit.GenerateFlixID(template) - if err != nil { - t.Errorf("call GenerateFlixID err %v", err) - } - - if id != templateId { - t.Errorf("GenerateFlixID got = %v, want %v", id, templateId) - } - -} - -func TestGenerateTemplateIdWithDeps(t *testing.T) { - templateId := "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa" - code := ` - { - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", - "data": { - "type": "transaction", - "interface": "", - "messages": { - "title": { - "i18n": { - "en-US": "Transfer Tokens" - } - }, - "description": { - "i18n": { - "en-US": "Transfer tokens from one account to another" - } - } - }, - "cadence": "import FungibleToken from 0xFUNGIBLETOKENADDRESS\ntransaction(amount: UFix64, to: Address) {\nlet vault: @FungibleToken.Vault\nprepare(signer: AuthAccount) {\nself.vault <- signer\n.borrow<&{FungibleToken.Provider}>(from: /storage/flowTokenVault)!\n.withdraw(amount: amount)\n}\nexecute {\ngetAccount(to)\n.getCapability(/public/flowTokenReceiver)!\n.borrow<&{FungibleToken.Receiver}>()!\n.deposit(from: <-self.vault)\n}\n}", - "dependencies": { - "0xFUNGIBLETOKENADDRESS": { - "FungibleToken": { - "mainnet": { - "address": "0xf233dcee88fe0abe", - "fq_address": "A.0xf233dcee88fe0abe.FungibleToken", - "contract": "FungibleToken", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 34166296 - }, - "testnet": { - "address": "0x9a0766d93b6608b7", - "fq_address": "A.0x9a0766d93b6608b7.FungibleToken", - "contract": "FungibleToken", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 74776482 - } - } - } - }, - "arguments": { - "amount": { - "index": 0, - "type": "UFix64", - "messages": { - "title": { - "i18n": { - "en-US": "The amount of FLOW tokens to send" - } - } - }, - "balance": "" - }, - "to": { - "index": 1, - "type": "Address", - "messages": { - "title": { - "i18n": { - "en-US": "The Flow account the tokens will go to" - } - } - }, - "balance": "" - } - } - } - }` - - template, err := flixkit.ParseFlix(code) - if err != nil { - t.Errorf("ParseFlix() err %v", err) - } - id, err := flixkit.GenerateFlixID(template) - if err != nil { - t.Errorf("GenerateFlixID err %v", err) - } - - if id != templateId { - t.Errorf("GenerateFlixID got = %v, want %v", id, templateId) - } - -} - -func TestGenerateParameters(t *testing.T) { - templateString := ` - { - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "", - "data": - { - "type": "transaction", - "interface": "", - "messages": - { - "title": - { - "i18n": - { - "en-US": "Transfer Tokens" - } - }, - "description": - { - "i18n": - { - "en-US": "Transfer tokens from one account to another" - } - } - }, - "cadence": "import FungibleToken from 0xFungibleToken\ntransaction(amount: UFix64, to: Address) {\nlet vault: @FungibleToken.Vault\nprepare(signer: AuthAccount) {\nself.vault <- signer\n.borrow<&{FungibleToken.Provider}>(from: /storage/flowTokenVault)!\n.withdraw(amount: amount)\n}\nexecute {\ngetAccount(to)\n.getCapability(/public/flowTokenReceiver)!\n.borrow<&{FungibleToken.Receiver}>()!\n.deposit(from: <-self.vault)\n}\n}", - "dependencies": - { - "0xFungibleToken": - { - "FungibleToken": - { - "mainnet": - { - "address": "0xf233dcee88fe0abe", - "fq_address": "A.0xf233dcee88fe0abe.FungibleToken", - "contract": "FungibleToken", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 34166296 - }, - "testnet": - { - "address": "0x9a0766d93b6608b7", - "fq_address": "A.0x9a0766d93b6608b7.FungibleToken", - "contract": "FungibleToken", - "pin": "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", - "pin_block_height": 74776482 - } - } - } - }, - "arguments": - { - "greeting": - { - "messages": - { - "title": - { - "i18n": - { - "en-US": "Greeting Update" - } - }, - "description": - { - "i18n": - { - "en-US": "Update contract greeting message" - } - } - } - } - } - } - }` - cadence := ` - import "HelloWorld" - transaction(greeting: String) { - - prepare(acct: AuthAccount) { - log(acct.address) - } - - execute { - HelloWorld.updateGreeting(newGreeting: greeting) - } - } - -` - codeBytes := []byte(cadence) - program, err := parser.ParseProgram(nil, codeBytes, parser.Config{}) - - template, err := flixkit.ParseFlix(templateString) - if err != nil { - t.Errorf("ParseFlix() err %v", err) - } - err = ProcessParameters(program, template) - if err != nil { - t.Errorf("process parameters err %v", err) - } - prettyJSON, err := json.MarshalIndent(template, "", " ") - - autogold.ExpectFile(t, string(prettyJSON)) -} - -func TestGenerateParametersScripts(t *testing.T) { - templateString := ` - { - "f_type": "InteractionTemplate", - "f_version": "1.0.0", - "id": "", - "data": - { - "type": "script", - "interface": "", - "messages": - { - "title": - { - "i18n": - { - "en-US": "Get Tokens Balance" - } - }, - "description": - { - "i18n": - { - "en-US": "Get user token balance" - } - } - }, - "cadence": "", - "dependencies": {}, - "arguments": - { - "address": - { - "messages": - { - "title": - { - "i18n": - { - "en-US": "User Account" - } - }, - "description": - { - "i18n": - { - "en-US": "User account address" - } - } - } - } - } - } - }` - - cadence := ` - import "FungibleToken" - import "FlowToken" - - pub fun main(address: Address): UFix64 { - let account = getAccount(address) - let vaultRef = account.getCapability(/public/flowTokenBalance) - .borrow<&FlowToken.Vault{FungibleToken.Balance}>() - ?? panic("Could not borrow balance reference to the Vault") - - return vaultRef.balance - } - - ` - - codeBytes := []byte(cadence) - program, err := parser.ParseProgram(nil, codeBytes, parser.Config{}) - if err != nil { - t.Errorf("ParseProgram() err %v", err) - } - - template, err := flixkit.ParseFlix(templateString) - if err != nil { - t.Errorf("ParseFlix() err %v", err) - } - err = ProcessParameters(program, template) - if err != nil { - t.Errorf("process parameters err %v", err) - } - prettyJSON, err := json.MarshalIndent(template, "", " ") - - autogold.ExpectFile(t, string(prettyJSON)) -} - -func TestUnNormalizeCode(t *testing.T) { - tests := []struct { - cadence string - unNormalized string - }{ - { - cadence: `import "FungibleToken" - /* Here is a comment */ - pub fun main(accountAddress: Address): UFix64 { - return balanceRef.balance - } - `, - unNormalized: `import FungibleToken from 0xFungibleToken - /* Here is a comment */ - pub fun main(accountAddress: Address): UFix64 { - return balanceRef.balance - } - `, - }, - { - cadence: `import "NonFungibleToken" - import "FungibleToken" - - transaction(amount: UFix64, recipient: Address) { - /* - Here is a comment - */ - execute { - - } - } - `, - unNormalized: `import NonFungibleToken from 0xNonFungibleToken - import FungibleToken from 0xFungibleToken - - transaction(amount: UFix64, recipient: Address) { - /* - Here is a comment - */ - execute { - - } - } - `, - }, - } - - for _, tt := range tests { - t.Run(tt.cadence, func(t *testing.T) { - got := UnNormalizeImports(tt.cadence) - - if got != tt.unNormalized { - t.Errorf("UnNormalizedImports got = %v, want %v", got, tt.unNormalized) - } - }) - } - -} - -func TestNormalizeCode(t *testing.T) { - tests := []struct { - cadence string - normalized string - }{ - { - cadence: `import FungibleToken from 0xFungibleToken - /* Here is a comment */ - pub fun main(accountAddress: Address): UFix64 { - return balanceRef.balance - } - `, - normalized: `import "FungibleToken" - /* Here is a comment */ - pub fun main(accountAddress: Address): UFix64 { - return balanceRef.balance - } - `, - }, - { - cadence: `import NonFungibleToken from 0xNonFungibleToken - import FungibleToken from 0xFungibleToken - - transaction(amount: UFix64, recipient: Address) { - /* - Here is a comment - */ - execute { - - } - } - `, - normalized: `import "NonFungibleToken" - import "FungibleToken" - - transaction(amount: UFix64, recipient: Address) { - /* - Here is a comment - */ - execute { - - } - } - `, - }, - } - - for _, tt := range tests { - t.Run(tt.cadence, func(t *testing.T) { - got := NormalizeImports(tt.cadence) - - if got != tt.normalized { - t.Errorf("NormalizedImports got = %v, want %v", got, tt.normalized) - } - }) - } - -} diff --git a/go.mod b/go.mod index 35228bc..fc1cd0f 100644 --- a/go.mod +++ b/go.mod @@ -3,34 +3,42 @@ module github.com/onflow/flixkit-go go 1.20 require ( - github.com/ethereum/go-ethereum v1.10.22 + github.com/ethereum/go-ethereum v1.12.0 github.com/hexops/autogold/v2 v2.2.1 - github.com/onflow/cadence v0.42.0 - github.com/onflow/flow-cli/flowkit v1.5.0 - github.com/onflow/flow-go-sdk v0.41.11 + github.com/onflow/cadence v0.42.5 + github.com/onflow/flow-cli/flowkit v1.6.1-0.20231110211255-b41f57a8b8c7 + github.com/onflow/flow-go-sdk v0.41.16 github.com/spf13/afero v1.9.4 github.com/stoewer/go-strcase v1.3.0 github.com/stretchr/testify v1.8.4 - github.com/zeebo/assert v1.3.0 golang.org/x/crypto v0.14.0 ) require ( - cloud.google.com/go/compute v1.21.0 // indirect + cloud.google.com/go/compute v1.23.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.1 // indirect - cloud.google.com/go/kms v1.12.1 // indirect + cloud.google.com/go/kms v1.15.0 // indirect + github.com/DataDog/zstd v1.5.2 // indirect github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 // indirect + github.com/cockroachdb/redact v1.1.3 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect @@ -42,20 +50,25 @@ require ( github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fxamacker/cbor/v2 v2.4.1-0.20230228173756-c0c9f774e40c // indirect github.com/fxamacker/circlehash v0.3.0 // indirect + github.com/getsentry/sentry-go v0.18.0 // indirect github.com/glebarez/go-sqlite v1.21.1 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.1.0 // indirect + github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.4 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/s2a-go v0.1.4 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.11.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/gosuri/uilive v0.0.4 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -65,6 +78,8 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/hexops/valast v1.4.4 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/invopop/jsonschema v0.7.0 // indirect @@ -95,6 +110,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -108,15 +124,16 @@ require ( github.com/multiformats/go-multistream v0.4.1 // indirect github.com/multiformats/go-varint v0.0.7 // indirect github.com/nightlyone/lockfile v1.0.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/onflow/atree v0.6.0 // indirect - github.com/onflow/flow-core-contracts/lib/go/contracts v1.2.4-0.20230703193002-53362441b57d // indirect - github.com/onflow/flow-core-contracts/lib/go/templates v1.2.3 // indirect - github.com/onflow/flow-emulator v0.56.0 // indirect - github.com/onflow/flow-ft/lib/go/contracts v0.7.0 // indirect - github.com/onflow/flow-go v0.32.2-0.20231017202518-0b275f42906c // indirect - github.com/onflow/flow-go/crypto v0.24.9 // indirect + github.com/onflow/flow-core-contracts/lib/go/contracts v1.2.4-0.20231016154253-a00dbf7c061f // indirect + github.com/onflow/flow-core-contracts/lib/go/templates v1.2.4-0.20231016154253-a00dbf7c061f // indirect + github.com/onflow/flow-emulator v0.58.0 // indirect + github.com/onflow/flow-ft/lib/go/contracts v0.7.1-0.20230711213910-baad011d2b13 // indirect + github.com/onflow/flow-go v0.32.4-0.20231115172515-c1ec969fd6f2 // indirect + github.com/onflow/flow-go/crypto v0.24.10 // indirect github.com/onflow/flow-nft/lib/go/contracts v1.1.0 // indirect - github.com/onflow/flow/protobuf/go/flow v0.3.2-0.20231017162044-5d0f9b6dfdb2 // indirect + github.com/onflow/flow/protobuf/go/flow v0.3.2-0.20231018182244-e72527c55c63 // indirect github.com/onflow/nft-storefront/lib/go/contracts v0.0.0-20221222181731-14b90207cead // indirect github.com/onflow/sdks v0.5.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect @@ -136,17 +153,21 @@ require ( github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/zerolog v1.29.0 // indirect github.com/sethvargo/go-retry v0.2.3 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/slok/go-http-metrics v0.10.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.15.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/texttheater/golang-levenshtein/levenshtein v0.0.0-20200805054039-cae8b0eaed6c // indirect + github.com/tklauser/go-sysconf v0.3.9 // indirect + github.com/tklauser/numcpus v0.3.0 // indirect github.com/turbolent/prettier v0.0.0-20220320183459-661cc755135d // indirect - github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v4 v4.3.11 // indirect github.com/vmihailenco/tagparser v0.1.1 // indirect @@ -167,7 +188,7 @@ require ( golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/mod v0.13.0 // indirect golang.org/x/net v0.16.0 // indirect - golang.org/x/oauth2 v0.10.0 // indirect + golang.org/x/oauth2 v0.11.0 // indirect golang.org/x/sync v0.4.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect @@ -176,12 +197,13 @@ require ( gonum.org/v1/gonum v0.13.0 // indirect google.golang.org/api v0.126.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/grpc v1.58.3 // indirect + google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.2.1 // indirect modernc.org/libc v1.22.3 // indirect diff --git a/go.sum b/go.sum index bf2947d..49e16f1 100644 --- a/go.sum +++ b/go.sum @@ -27,15 +27,15 @@ cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aD cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk= +cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= -cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -43,8 +43,8 @@ cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1 cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y= cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= cloud.google.com/go/kms v1.0.0/go.mod h1:nhUehi+w7zht2XrUfvTRNpxrfayBHqP4lu2NSywui/0= -cloud.google.com/go/kms v1.12.1 h1:xZmZuwy2cwzsocmKDOPu4BL7umg8QXagQx6fKVmf45U= -cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= +cloud.google.com/go/kms v1.15.0 h1:xYl5WEaSekKYN5gGRyhjvZKM22GVBBCzegGNVPy+aIs= +cloud.google.com/go/kms v1.15.0/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -56,6 +56,7 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= @@ -71,26 +72,35 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI= github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VictoriaMetrics/fastcache v1.5.3/go.mod h1:+jv9Ckb+za/P1ZRg/sulP5Ni1v49daAVERr0H3CuscE= github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -101,10 +111,10 @@ github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsy github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.2.1 h1:xP60mv8fvp+0khmrN0zTdPC3cNm24rfeE6lh2R/Yv3E= github.com/btcsuite/btcd/btcec/v2 v2.2.1/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -139,27 +149,30 @@ github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= -github.com/cockroachdb/pebble v0.0.0-20230829171545-74d4bb649d92 h1:uGCVnrAKqpaPEyFD8CK50oEy5jBfwgy1ZyfBUwlh1PM= -github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw= -github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= +github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/datadriven v1.0.3-0.20230801171734-e384cf455877 h1:1MLK4YpFtIEo3ZtMA5C795Wtv5VuUnrXX7mQG+aHg6o= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= +github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 h1:T+Np/xtzIjYM/P5NAw0e2Rf1FGvzDau1h54MKvx8G7w= +github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06/go.mod h1:bynZ3gvVyhlvjLI7PT6dmZ7g76xzJ7HpxfjgkzCGz6s= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -169,9 +182,12 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= @@ -184,15 +200,14 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/ef-ds/deque v1.0.4 h1:iFAZNmveMT9WERAkqLJ+oaABF9AcVQ5AjXem/hroniI= github.com/ef-ds/deque v1.0.4/go.mod h1:gXDnTC3yqvBcHbq2lcExjtAcVrOnJCbMcZXmuj8Z4tg= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= -github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -202,20 +217,22 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/go-ethereum v1.9.9/go.mod h1:a9TqabFudpDu1nucId+k9S8R9whYaHnGBLKFouA5EAo= -github.com/ethereum/go-ethereum v1.10.22 h1:HbEgsDo1YTGIf4KB/NNpn+XH+PiNJXUZ9ksRxiqWyMc= -github.com/ethereum/go-ethereum v1.10.22/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= +github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2zljOa0= +github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fxamacker/cbor/v2 v2.2.1-0.20210927235116-3d6d5d1de29b/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= @@ -224,11 +241,19 @@ github.com/fxamacker/cbor/v2 v2.4.1-0.20230228173756-c0c9f774e40c/go.mod h1:TA1x github.com/fxamacker/circlehash v0.1.0/go.mod h1:3aq3OfVvsWtkWMb6A1owjOQFA+TLsD5FgJflnaQwtMM= github.com/fxamacker/circlehash v0.3.0 h1:XKdvTtIJV9t7DDUtsf0RIpC1OcxZtPbmgIH7ekx28WA= github.com/fxamacker/circlehash v0.3.0/go.mod h1:3aq3OfVvsWtkWMb6A1owjOQFA+TLsD5FgJflnaQwtMM= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0y5NY= github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -243,28 +268,36 @@ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-test/deep v1.0.5/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -303,8 +336,10 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -324,7 +359,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -350,8 +386,8 @@ github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -361,9 +397,12 @@ github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0 github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4= github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosuri/uilive v0.0.4 h1:hUEBpQDj8D8jXgtCdBu7sWsy5sbW/5GhuO8KBwJ2jyY= github.com/gosuri/uilive v0.0.4/go.mod h1:V/epo5LjjlDE5RJUcqx8dbw+zc93y5Ya3yg8tfZ74VI= github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= @@ -379,6 +418,7 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -396,13 +436,18 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hexops/valast v1.4.4 h1:rETyycw+/L2ZVJHHNxEBgh8KUn+87WugH9MxcEv9PGs= github.com/hexops/valast v1.4.4/go.mod h1:Jcy1pNH7LNraVaAZDLyv21hHg2WBv9Nf9FL6fGxU7o4= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= +github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= -github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY= +github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= @@ -438,9 +483,12 @@ github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= -github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= +github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= +github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= @@ -449,15 +497,24 @@ github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZl github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= github.com/k0kubun/pp/v3 v3.2.0 h1:h33hNTZ9nVFNP3u2Fsgz8JXiF5JINoZfFq4SvKJwNcs= github.com/k0kubun/pp/v3 v3.2.0/go.mod h1:ODtJQbQcIRfAD3N+theGCV1m/CBxweERz2dapdz1EwA= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= +github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= +github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= +github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= +github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= github.com/kevinburke/go-bindata v3.22.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= github.com/kevinburke/go-bindata v3.23.0+incompatible h1:rqNOXZlqrYhMVVAsQx8wuc+LaA73YcfbQ407wAykyS8= github.com/kevinburke/go-bindata v3.23.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= @@ -465,14 +522,16 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -484,25 +543,20 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/libp2p/go-addr-util v0.1.0 h1:acKsntI33w2bTU7tC9a0SaPimJGfSI0bFKC18ChxeVI= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= -github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-libp2p v0.28.1 h1:YurK+ZAI6cKfASLJBVFkpVBdl3wGhFi6fusOt725ii8= github.com/libp2p/go-libp2p v0.28.1/go.mod h1:s3Xabc9LSwOcnv9UD4nORnXKTsWkPMkIMB/JIGXVnzk= github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= -github.com/libp2p/go-libp2p-kad-dht v0.24.2 h1:zd7myKBKCmtZBhI3I0zm8xBkb28v3gmSEtQfBdAdFwc= github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0= github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo= -github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= -github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= -github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= -github.com/libp2p/go-reuseport v0.3.0 h1:iiZslO5byUYZEg9iCwJGf5h+sf1Agmqx2V2FDjPyvUw= github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= github.com/lmars/go-slip10 v0.0.0-20190606092855-400ba44fee12 h1:qFV7dBLhw5z4hka5gjtIzg1Kq9ie8t8P7Cy0uIxRyAQ= github.com/lmars/go-slip10 v0.0.0-20190606092855-400ba44fee12/go.mod h1:QIsK6U93yCP6TnGsShCv5wl4gcz/mpCHl+aToBsl5Sc= @@ -514,17 +568,21 @@ github.com/logrusorgru/aurora/v4 v4.0.0/go.mod h1:lP0iIa2nrnT/qoFXcOZSrZQpJ1o6n2 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= @@ -539,13 +597,15 @@ github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= @@ -556,6 +616,11 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= @@ -568,7 +633,6 @@ github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= -github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= @@ -585,42 +649,48 @@ github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOEL github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nightlyone/lockfile v1.0.0 h1:RHep2cFKK4PonZJDdEl4GmkabuhbsRMgk/k3uAmxBiA= github.com/nightlyone/lockfile v1.0.0/go.mod h1:rywoIealpdNse2r832aiD9jRk8ErCatROs6LzC841CI= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onflow/atree v0.1.0-beta1.0.20211027184039-559ee654ece9/go.mod h1:+6x071HgCF/0v5hQcaE5qqjc2UqN5gCU8h5Mk6uqpOg= github.com/onflow/atree v0.6.0 h1:j7nQ2r8npznx4NX39zPpBYHmdy45f4xwoi+dm37Jk7c= github.com/onflow/atree v0.6.0/go.mod h1:gBHU0M05qCbv9NN0kijLWMgC47gHVNBIp4KmsVFi0tc= github.com/onflow/cadence v0.20.1/go.mod h1:7mzUvPZUIJztIbr9eTvs+fQjWWHTF8veC+yk4ihcNIA= -github.com/onflow/cadence v0.42.0 h1:XatyCy1pZu10x+JouRU6cZ9A50dF3uM+ubqYUER1/Vk= -github.com/onflow/cadence v0.42.0/go.mod h1:raU8va8QRyTa/eUbhej4mbyW2ETePfSaywoo36MddgE= -github.com/onflow/flow-cli/flowkit v1.5.0 h1:6QnXiT+BwpsgkC6j4QI7vpEaU7as0+B+ZtrCTbhSnig= -github.com/onflow/flow-cli/flowkit v1.5.0/go.mod h1:Z0Ry0nnr8Se3z8/oRWDx0udgJJv5LrGMnBwr9qUIf/c= -github.com/onflow/flow-core-contracts/lib/go/contracts v1.2.4-0.20230703193002-53362441b57d h1:B7PdhdUNkve5MVrekWDuQf84XsGBxNZ/D3x+QQ8XeVs= -github.com/onflow/flow-core-contracts/lib/go/contracts v1.2.4-0.20230703193002-53362441b57d/go.mod h1:xAiV/7TKhw863r6iO3CS5RnQ4F+pBY1TxD272BsILlo= -github.com/onflow/flow-core-contracts/lib/go/templates v1.2.3 h1:X25A1dNajNUtE+KoV76wQ6BR6qI7G65vuuRXxDDqX7E= -github.com/onflow/flow-core-contracts/lib/go/templates v1.2.3/go.mod h1:dqAUVWwg+NlOhsuBHex7bEWmsUjsiExzhe/+t4xNH6A= -github.com/onflow/flow-emulator v0.56.0 h1:rovvMOd3tbfHYPFft+e4d0EO/fVEvHIYkBdKwxuH73I= -github.com/onflow/flow-emulator v0.56.0/go.mod h1:luhvLpxcpaHzfa+mqwgRTFLBYASdu7EorGbKkKKB9SI= -github.com/onflow/flow-ft/lib/go/contracts v0.7.0 h1:XEKE6qJUw3luhsYmIOteXP53gtxNxrwTohgxJXCYqBE= -github.com/onflow/flow-ft/lib/go/contracts v0.7.0/go.mod h1:kTMFIySzEJJeupk+7EmXs0EJ6CBWY/MV9fv9iYQk+RU= -github.com/onflow/flow-go v0.32.2-0.20231017202518-0b275f42906c h1:QJGwyt9t6TbRbIAO7+wl7t2OUOfhaaB/9PC9RCxW5lc= -github.com/onflow/flow-go v0.32.2-0.20231017202518-0b275f42906c/go.mod h1:Jv1NHZrnluiB/eb7GXaZAY3ZBoJOuQ1ClTLG9VyPJRE= +github.com/onflow/cadence v0.42.5 h1:QCilotmJzfRToLd+02o3N62JIioSr8FfN7cujmR/IXQ= +github.com/onflow/cadence v0.42.5/go.mod h1:raU8va8QRyTa/eUbhej4mbyW2ETePfSaywoo36MddgE= +github.com/onflow/flow-cli/flowkit v1.6.1-0.20231110211255-b41f57a8b8c7 h1:EI/XTe2E5U23oHzjaLPIm4TKMLD+v2vI5vHjO1BkRyM= +github.com/onflow/flow-cli/flowkit v1.6.1-0.20231110211255-b41f57a8b8c7/go.mod h1:tPBuuYss8S8carovC49N1YVPIBheF6KD9Vr6Ocg3VpQ= +github.com/onflow/flow-core-contracts/lib/go/contracts v1.2.4-0.20231016154253-a00dbf7c061f h1:S8yIZw9LFXfYD1V5H9BiixihHw3GrXVPrmfplSzYaww= +github.com/onflow/flow-core-contracts/lib/go/contracts v1.2.4-0.20231016154253-a00dbf7c061f/go.mod h1:jM6GMAL+m0hjusUgiYDNrixPQ6b9s8xjoJQoEu5bHQI= +github.com/onflow/flow-core-contracts/lib/go/templates v1.2.4-0.20231016154253-a00dbf7c061f h1:Ep+Mpo2miWMe4pjPGIaEvEzshRep30dvNgxqk+//FrQ= +github.com/onflow/flow-core-contracts/lib/go/templates v1.2.4-0.20231016154253-a00dbf7c061f/go.mod h1:ZeLxwaBkzuSInESGjL8/IPZWezF+YOYsYbMrZlhN+q4= +github.com/onflow/flow-emulator v0.58.0 h1:/Zo+qznjqN2jJNOGQu1mFK2lZT3L6c8V18AmAzXLKZ8= +github.com/onflow/flow-emulator v0.58.0/go.mod h1:pi23Sx7kuj65dJRT7OIlio53XRAhLTUUhf3zV9TN3PA= +github.com/onflow/flow-ft/lib/go/contracts v0.7.1-0.20230711213910-baad011d2b13 h1:B4ll7e3j+MqTJv2122Enq3RtDNzmIGRu9xjV7fo7un0= +github.com/onflow/flow-ft/lib/go/contracts v0.7.1-0.20230711213910-baad011d2b13/go.mod h1:kTMFIySzEJJeupk+7EmXs0EJ6CBWY/MV9fv9iYQk+RU= +github.com/onflow/flow-go v0.32.4-0.20231115172515-c1ec969fd6f2 h1:ujrwrJelTX0R3HtX9kSJRoU7bUtcdvf1Pmpvy31yvNQ= +github.com/onflow/flow-go v0.32.4-0.20231115172515-c1ec969fd6f2/go.mod h1:bKcX2932bIunkyXBKW9qmw8Z0zXpHol+5xCJCumV/H8= github.com/onflow/flow-go-sdk v0.24.0/go.mod h1:IoptMLPyFXWvyd9yYA6/4EmSeeozl6nJoIv4FaEMg74= -github.com/onflow/flow-go-sdk v0.41.11 h1:x1nS91Tn0M4BZbZNSCMU7Vjgx9yjBJfjWWAIOihxDVk= -github.com/onflow/flow-go-sdk v0.41.11/go.mod h1:M6wvgjcpfnmaqM+3IgaVgbHWRCmns3sbg3KfYj4+5MM= +github.com/onflow/flow-go-sdk v0.41.16 h1:HsmHwEVmj+iK+GszHbFseHh7Ii5W3PWOIRNAH/En08Q= +github.com/onflow/flow-go-sdk v0.41.16/go.mod h1:bVrVNoJKiwB6vW5Qbm5tFAfJBQ5we4uSQWnn9gNAFhQ= github.com/onflow/flow-go/crypto v0.21.3/go.mod h1:vI6V4CY3R6c4JKBxdcRiR/AnjBfL8OSD97bJc60cLuQ= -github.com/onflow/flow-go/crypto v0.24.9 h1:0EQp+kSZYJepMIiSypfJVe7tzsPcb6UXOdOtsTCDhBs= -github.com/onflow/flow-go/crypto v0.24.9/go.mod h1:fqCzkIBBMRRkciVrvW21rECKq1oD7Q6u+bCI78lfNX0= +github.com/onflow/flow-go/crypto v0.24.10 h1:nH97tnnC0RaFXO5GuJic5lt/5IEiOuuWa3gaJI2Le3w= +github.com/onflow/flow-go/crypto v0.24.10/go.mod h1:O7jjGhgJEp94t9qXfBWdwW5BArm5L5gYa6XoBJiTdHc= github.com/onflow/flow-nft/lib/go/contracts v1.1.0 h1:rhUDeD27jhLwOqQKI/23008CYfnqXErrJvc4EFRP2a0= github.com/onflow/flow-nft/lib/go/contracts v1.1.0/go.mod h1:YsvzYng4htDgRB9sa9jxdwoTuuhjK8WYWXTyLkIigZY= github.com/onflow/flow/protobuf/go/flow v0.2.2/go.mod h1:gQxYqCfkI8lpnKsmIjwtN2mV/N2PIwc1I+RUK4HPIc8= -github.com/onflow/flow/protobuf/go/flow v0.3.2-0.20231017162044-5d0f9b6dfdb2 h1:PvDTPiMYERXeuEPDSuF67Lm+dG9soy3tMOO6VtRcKwM= -github.com/onflow/flow/protobuf/go/flow v0.3.2-0.20231017162044-5d0f9b6dfdb2/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= +github.com/onflow/flow/protobuf/go/flow v0.3.2-0.20231018182244-e72527c55c63 h1:SX8OhYbyKBExhy4qEDR/Hw6MVTBTzlDb8LfCHfFyte4= +github.com/onflow/flow/protobuf/go/flow v0.3.2-0.20231018182244-e72527c55c63/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= github.com/onflow/nft-storefront/lib/go/contracts v0.0.0-20221222181731-14b90207cead h1:2j1Unqs76Z1b95Gu4C3Y28hzNUHBix7wL490e61SMSw= github.com/onflow/nft-storefront/lib/go/contracts v0.0.0-20221222181731-14b90207cead/go.mod h1:E3ScfQb5XcWJCIAdtIeEnr5i5l2y60GT0BTXeIHseWg= github.com/onflow/sdks v0.5.0 h1:2HCRibwqDaQ1c9oUApnkZtEAhWiNY2GTpRD5+ftdkN8= @@ -628,11 +698,14 @@ github.com/onflow/sdks v0.5.0/go.mod h1:F0dj0EyHC55kknLkeD10js4mo14yTdMotnWMslPi github.com/onflow/wal v0.0.0-20230529184820-bc9f8244608d h1:gAEqYPn3DS83rHIKEpsajnppVD1+zwuYPFyeDVFaQvg= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= -github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= @@ -645,6 +718,8 @@ github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -655,7 +730,6 @@ github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= @@ -674,18 +748,11 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/psiemens/graceland v1.0.0 h1:L580AVV4Q2XLcPpmvxJRH9UpEAYr/eu2jBKmMglhvM8= github.com/psiemens/graceland v1.0.0/go.mod h1:1Tof+vt1LbmcZFE0lzgdwMN0QBymAChG3FRgDx8XisU= github.com/psiemens/sconfig v0.1.0 h1:xfWqW+TRpih7mXZIqKYTmpRhlZLQ1kbxV8EjllPv76s= github.com/psiemens/sconfig v0.1.0/go.mod h1:+MLKqdledP/8G3rOBpknbLh0IclCf4WneJUtS26JB2U= -github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U= -github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E= -github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= -github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU= -github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -698,6 +765,7 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= @@ -710,17 +778,23 @@ github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6us github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/schollz/progressbar/v3 v3.8.3/go.mod h1:pWnVCjSBZsT2X3nx9HfRdnCDrpbevliMeoEVhStwHko= github.com/schollz/progressbar/v3 v3.13.1 h1:o8rySDYiQ59Mwzy2FELeHY5ZARXZTVJC7iHD6PEFUiE= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sethvargo/go-retry v0.2.3 h1:oYlgvIvsju3jNbottWABtbnoLC+GDtLdBHxKWxQm/iU= github.com/sethvargo/go-retry v0.2.3/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/slok/go-http-metrics v0.10.0 h1:rh0LaYEKza5eaYRGDXujKrOln57nHBi4TtVhmNEpbgM= github.com/slok/go-http-metrics v0.10.0/go.mod h1:lFqdaS4kWMfUKCSukjC47PdCeTk+hXDUVm8kLHRqJ38= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.0.1-0.20190317074736-539464a789e9/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -733,8 +807,8 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -771,34 +845,52 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/supranational/blst v0.3.4/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/supranational/blst v0.3.10 h1:CMciDZ/h4pXDDXQASe8ZGTNKUiVNxVVA5hpci2Uuhuk= +github.com/supranational/blst v0.3.11-0.20230406105308-e9dfc5ee724b h1:u49mjRnygnB34h8OKbnNJFVUtWSKIKb1KukdV8bILUM= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/texttheater/golang-levenshtein/levenshtein v0.0.0-20200805054039-cae8b0eaed6c h1:HelZ2kAFadG0La9d+4htN4HzQ68Bm2iM9qKMSMES6xg= github.com/texttheater/golang-levenshtein/levenshtein v0.0.0-20200805054039-cae8b0eaed6c/go.mod h1:JlzghshsemAMDGZLytTFY8C1JQxQPhnatWqNwUXjggo= github.com/thoas/go-funk v0.9.2 h1:oKlNYv0AY5nyf9g+/GhMgS/UO2ces0QRdPKwkhY3VCk= github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo= +github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= +github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/turbolent/prettier v0.0.0-20220320183459-661cc755135d h1:5JInRQbk5UBX8JfUvKh2oYTLMVwj3p6n+wapDDm7hko= github.com/turbolent/prettier v0.0.0-20220320183459-661cc755135d/go.mod h1:Nlx5Y115XQvNcIdIy7dZXaNSUpzwBSge4/Ivk93/Yog= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.11 h1:Q47CePddpNGNhk4GCnAx9DDtASi2rasatE0cd26cZoE= github.com/vmihailenco/msgpack/v4 v4.3.11/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -807,7 +899,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/blake3 v0.2.0/go.mod h1:G9pM4qQwjRzF1/v7+vabMj/c5mWpGZ2Wzo3Eb4z0pb4= github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= @@ -846,8 +937,6 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI= -go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= @@ -870,10 +959,13 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -938,6 +1030,7 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -946,6 +1039,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -956,9 +1050,11 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -970,6 +1066,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= @@ -995,8 +1092,8 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= +golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1032,7 +1129,11 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1050,9 +1151,11 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1067,7 +1170,9 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1077,11 +1182,14 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1123,15 +1231,19 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -1243,6 +1355,7 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1305,12 +1418,13 @@ google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211007155348-82e027067bd4/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1339,8 +1453,8 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1364,8 +1478,13 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= @@ -1379,7 +1498,9 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/contracts/core.go b/internal/contracts/core.go new file mode 100644 index 0000000..66d6054 --- /dev/null +++ b/internal/contracts/core.go @@ -0,0 +1,57 @@ +package contracts + +import ( + "github.com/onflow/flow-cli/flowkit/config" +) + +func GetCoreContracts() map[string]map[string]string { + // TODO: this should be from core contracts module + return map[string]map[string]string{ + "FungibleToken": { + config.MainnetNetwork.Name: "0xf233dcee88fe0abe", + config.TestnetNetwork.Name: "0x9a0766d93b6608b7", + config.EmulatorNetwork.Name: "0xee82856bf20e2aa6", + }, + "NonFungibleToken": { + config.MainnetNetwork.Name: "0x1d7e57aa55817448", + config.TestnetNetwork.Name: "0x631e88ae7f1d7c20", + config.EmulatorNetwork.Name: "0xf8d6e0586b0a20c7", + }, + "MetadataViews": { + config.MainnetNetwork.Name: "0x1d7e57aa55817448", + config.TestnetNetwork.Name: "0x631e88ae7f1d7c20", + config.EmulatorNetwork.Name: "0xf8d6e0586b0a20c7", + }, + "FlowToken": { + config.MainnetNetwork.Name: "0x1654653399040a61", + config.TestnetNetwork.Name: "0x7e60df042a9c0868", + config.EmulatorNetwork.Name: "0x0ae53cb6e3f42a79", + }, + "HybridCustody": { + config.MainnetNetwork.Name: "0xd8a7e05a7ac670c0", + config.TestnetNetwork.Name: "0x294e44e1ec6993c6", + config.EmulatorNetwork.Name: "0xf8d6e0586b0a20c7", + }, + "CapabilityDelegator": { + config.MainnetNetwork.Name: "0xd8a7e05a7ac670c0", + config.TestnetNetwork.Name: "0x294e44e1ec6993c6", + config.EmulatorNetwork.Name: "0xf8d6e0586b0a20c7", + }, + "CapabilityFactory": { + config.MainnetNetwork.Name: "0xd8a7e05a7ac670c0", + config.TestnetNetwork.Name: "0x294e44e1ec6993c6", + config.EmulatorNetwork.Name: "0xf8d6e0586b0a20c7", + }, + "CapabilityFilter": { + config.MainnetNetwork.Name: "0xd8a7e05a7ac670c0", + config.TestnetNetwork.Name: "0x294e44e1ec6993c6", + config.EmulatorNetwork.Name: "0xf8d6e0586b0a20c7", + }, + } +} + +func GetCoreContractForNetwork(contractName string, network string) string { + // TODO: this should be from core contracts module + c := GetCoreContracts() + return c[contractName][network] +} diff --git a/bindings/templates/js_fcl_main.tmpl.go b/internal/templates/js_fcl_main.tmpl.go similarity index 90% rename from bindings/templates/js_fcl_main.tmpl.go rename to internal/templates/js_fcl_main.tmpl.go index c862764..16c31e5 100644 --- a/bindings/templates/js_fcl_main.tmpl.go +++ b/internal/templates/js_fcl_main.tmpl.go @@ -1,10 +1,10 @@ -package bindings +package templates func GetJsFclMainTemplate() string { const template = `/** This binding file was auto generated based on FLIX template v{{.Version}}. Changes to this file might get overwritten. - Note fcl version 1.3.0 or higher is required to use templates. + Note fcl version {{.FclVersion}} or higher is required to use templates. **/ import * as fcl from "@onflow/fcl" @@ -29,7 +29,7 @@ const flixTemplate = "{{.Location}}" {{- "\n"}}*/ {{if .IsScript}} {{- template "script" .}} -{{else}} +{{ else }} {{- template "tx" .}} {{- end}} diff --git a/internal/templates/js_fcl_parameters.go b/internal/templates/js_fcl_parameters.go new file mode 100644 index 0000000..3ab13a0 --- /dev/null +++ b/internal/templates/js_fcl_parameters.go @@ -0,0 +1,17 @@ +package templates + +func GetJsFclParamsTemplate() string { + const template = `{{define "params"}} + {{- if len .Parameters -}} + { + {{- range $index, $ele := .Parameters -}} + {{if $index}}, {{end}}{{.Name}} + {{- end -}} + } + {{- end -}} +{{end}} +` + + return template + +} diff --git a/bindings/templates/js_fcl_script.tmpl.go b/internal/templates/js_fcl_script.tmpl.go similarity index 71% rename from bindings/templates/js_fcl_script.tmpl.go rename to internal/templates/js_fcl_script.tmpl.go index 47143e4..59f442d 100644 --- a/bindings/templates/js_fcl_script.tmpl.go +++ b/internal/templates/js_fcl_script.tmpl.go @@ -1,15 +1,8 @@ -package bindings +package templates func GetJsFclScriptTemplate() string { const template = `{{define "script"}}export async function {{.Title}}( - {{- if len .Parameters -}} - { - {{- range $index, $ele := .Parameters -}} - {{if $index}}, {{end}}{{.Name}} - {{- end -}} - } - {{- end -}} -) { +{{- template "params" .}}) { const info = await fcl.query({ template: flixTemplate, {{ if len .Parameters -}} diff --git a/bindings/templates/js_fcl_tx.tmpl.go b/internal/templates/js_fcl_tx.tmpl.go similarity index 71% rename from bindings/templates/js_fcl_tx.tmpl.go rename to internal/templates/js_fcl_tx.tmpl.go index bb180b7..e803022 100644 --- a/bindings/templates/js_fcl_tx.tmpl.go +++ b/internal/templates/js_fcl_tx.tmpl.go @@ -1,13 +1,8 @@ -package bindings +package templates func GetJsFclTxTemplate() string { - const template = `{{define "tx"}}export async function {{.Title}}({ - {{- if len .Parameters -}} - {{- range $index, $ele := .Parameters -}} - {{if $index}}, {{end}}{{.Name}} - {{- end -}} - {{- end -}} -}) { + const template = `{{define "tx"}}export async function {{.Title}}( + {{- template "params" .}}) { const transactionId = await fcl.mutate({ template: flixTemplate, {{ if len .Parameters -}} diff --git a/internal/templates/ts_fcl_interface.go b/internal/templates/ts_fcl_interface.go new file mode 100644 index 0000000..4ae41a2 --- /dev/null +++ b/internal/templates/ts_fcl_interface.go @@ -0,0 +1,16 @@ +package templates + +func GetTsFclInterfaceTemplate() string { + const template = `{{ define "interface" }} +{{- if len .Parameters -}} +interface {{ .ParametersPrefixName }}Params { +{{- range .Parameters }} + {{ .Name }}: {{ .JsType }}; {{- if .Description }} // {{ .Description }} {{- end }} +{{- end }} +} +{{ end }} +{{ end }} +` + + return template +} diff --git a/internal/templates/ts_fcl_main.tmpl.go b/internal/templates/ts_fcl_main.tmpl.go new file mode 100644 index 0000000..ac86370 --- /dev/null +++ b/internal/templates/ts_fcl_main.tmpl.go @@ -0,0 +1,41 @@ +package templates + +func GetTsFclMainTemplate() string { + const template = `/** + This binding file was auto generated based on FLIX template v{{.Version}}. + Changes to this file might get overwritten. + Note fcl version {{.FclVersion}} or higher is required to use templates. +**/ + +import * as fcl from "@onflow/fcl" +{{- if .IsLocalTemplate }} +import flixTemplate from "{{.Location}}" +{{- else}} +const flixTemplate = "{{.Location}}" +{{- end}} +{{"\n"}} +{{- template "interface" . -}} +/** +* {{.Title}}: {{.Description}} +{{- range $param := .Parameters }} +* @param {{$param.JsType}} {{$param.Name}} - {{$param.Description}} +{{- end }} +{{- if not .IsScript }} +* @returns {Promise} - Returns a promise that resolves to the transaction ID +{{ else }} +* @returns {Promise<{{.Output.JsType}}>} - {{.Output.Description}} +{{ end -}} +*/ +{{if .IsScript}} +{{- template "script" .}} +{{ else }} +{{- template "tx" .}} +{{- end}} + + + + +` + + return template +} diff --git a/internal/templates/ts_fcl_parameters.go b/internal/templates/ts_fcl_parameters.go new file mode 100644 index 0000000..41d23b6 --- /dev/null +++ b/internal/templates/ts_fcl_parameters.go @@ -0,0 +1,18 @@ +package templates + +func GetTsFclParamsTemplate() string { + const template = `{{ define "params" }} +{{- if len .Parameters -}} +{ + {{- range $index, $ele := .Parameters -}} + {{if $index}}, {{end}}{{.Name}} + {{- end -}} + }: {{ .ParametersPrefixName }}Params +{{- end -}} +{{ end }} + +` + + return template + +} diff --git a/internal/templates/ts_fcl_script.tmpl.go b/internal/templates/ts_fcl_script.tmpl.go new file mode 100644 index 0000000..7c190f8 --- /dev/null +++ b/internal/templates/ts_fcl_script.tmpl.go @@ -0,0 +1,24 @@ +package templates + +func GetTsFclScriptTemplate() string { + const template = `{{define "script"}}export async function {{.Title}}( +{{- template "params" .}}): Promise<{{.Output.JsType}}> { + const info = await fcl.query({ + cadence: "", + template: flixTemplate, + {{ if len .Parameters -}} + args: (arg, t) => [ + {{- range $index, $ele := .Parameters -}} + {{if $index}}, {{end}}arg({{.Name}}, t.{{.FclType}}) + {{- end -}} + ] + {{- end }} + }); + + return info +}{{end}} +` + + return template + +} diff --git a/internal/templates/ts_fcl_tx.tmpl.go b/internal/templates/ts_fcl_tx.tmpl.go new file mode 100644 index 0000000..d0a2749 --- /dev/null +++ b/internal/templates/ts_fcl_tx.tmpl.go @@ -0,0 +1,23 @@ +package templates + +func GetTsFclTxTemplate() string { + const template = `{{define "tx"}}export async function {{.Title}}( + {{- template "params" .}}): Promise { + const transactionId = await fcl.mutate({ + template: flixTemplate, + {{ if len .Parameters -}} + args: (arg, t) => [ + {{- range $index, $ele := .Parameters -}} + {{if $index}}, {{end}}arg({{.Name}}, t.{{.FclType}}) + {{- end -}} + ] + {{- end }} + }); + + return transactionId +}{{end}} +` + + return template + +} diff --git a/templateFileName b/templateFileName new file mode 100644 index 0000000..e69de29 diff --git a/types.go b/types.go deleted file mode 100644 index d5a8c5b..0000000 --- a/types.go +++ /dev/null @@ -1,339 +0,0 @@ -package flixkit - -import ( - "bytes" - "encoding/binary" - "encoding/hex" - "fmt" - "regexp" - "sort" - - "github.com/ethereum/go-ethereum/rlp" - "golang.org/x/crypto/sha3" -) - -type Network struct { - Address string `json:"address"` - FqAddress string `json:"fq_address"` - Contract string `json:"contract"` - Pin string `json:"pin"` - PinBlockHeight uint64 `json:"pin_block_height"` -} - -type Argument struct { - Index int `json:"index"` - Type string `json:"type"` - Messages Messages `json:"messages"` - Balance string `json:"balance"` -} - -type Title struct { - I18N map[string]string `json:"i18n"` -} - -type Description struct { - I18N map[string]string `json:"i18n"` -} - -type Messages struct { - Title *Title `json:"title,omitempty"` - Description *Description `json:"description,omitempty"` -} - -type Dependencies map[string]Contracts -type Contracts map[string]Networks -type Networks map[string]Network -type Arguments map[string]Argument - -type Data struct { - Type string `json:"type"` - Interface string `json:"interface"` - Messages Messages `json:"messages"` - Cadence string `json:"cadence"` - Dependencies Dependencies `json:"dependencies"` - Arguments Arguments `json:"arguments"` -} - -type FlowInteractionTemplate struct { - FType string `json:"f_type"` - FVersion string `json:"f_version"` - ID string `json:"id"` - Data Data `json:"data"` -} - -func (t *FlowInteractionTemplate) IsScript() bool { - return t.Data.Type == "script" -} - -func (t *FlowInteractionTemplate) IsTransaction() bool { - return t.Data.Type == "transaction" -} - -func (t *FlowInteractionTemplate) GetAndReplaceCadenceImports(networkName string) (string, error) { - cadence := t.Data.Cadence - - for dependencyAddress, contracts := range t.Data.Dependencies { - for contractName, networks := range contracts { - network, ok := networks[networkName] - if !ok { - return "", fmt.Errorf("network %s not found for contract %s", networkName, contractName) - } - - pattern := fmt.Sprintf(`import\s*%s\s*from\s*%s`, contractName, dependencyAddress) - re, err := regexp.Compile(pattern) - if err != nil { - return "", fmt.Errorf("invalid regex pattern: %v", err) - } - - replacement := fmt.Sprintf("import %s from %s", contractName, network.Address) - cadence = re.ReplaceAllString(cadence, replacement) - } - } - - return cadence, nil -} - -func (t *FlowInteractionTemplate) GetDescription() string { - s := "" - if t.Data.Messages.Description != nil && - t.Data.Messages.Description.I18N != nil { - - // relying on en-US for now, future we need to know what language to use - value, exists := t.Data.Messages.Description.I18N["en-US"] - if exists { - s = value - } - } - return s -} - -func (msgs *Messages) GetTitleValue(placeholder string) string { - s := placeholder - if msgs.Title != nil && - msgs.Title.I18N != nil { - // relying on en-US for now, future we need to know what language to use - value, exists := msgs.Title.I18N["en-US"] - if exists { - s = value - } - } - return s -} - -func messagesToRlp(messages Messages) []interface{} { - values := make([]interface{}, 0) - - if messages.Title != nil { - var titleValue []interface{} - titleValue = append(titleValue, ShaHex("title", "title")) - if messages.Title.I18N != nil { - var langTitle []interface{} - for k, v := range messages.Title.I18N { - var anotherNesting []interface{} - anotherNesting = append(anotherNesting, ShaHex(k, "I18N")) - anotherNesting = append(anotherNesting, ShaHex(v, "I18N")) - langTitle = append(langTitle, anotherNesting) - } - titleValue = append(titleValue, langTitle) - } - values = append(values, titleValue) - } - - if messages.Description != nil { - var descValue []interface{} - descValue = append(descValue, ShaHex("description", "description")) - if messages.Description.I18N != nil { - var langDesc []interface{} - for k, v := range messages.Description.I18N { - var anotherNesting []interface{} - anotherNesting = append(anotherNesting, ShaHex(k, "I18N")) - anotherNesting = append(anotherNesting, ShaHex(v, "I18N")) - langDesc = append(langDesc, anotherNesting) - } - descValue = append(descValue, langDesc) - } - values = append(values, descValue) - } - - return values -} - -func argumentsToRlp(arguments Arguments) []interface{} { - values := make([]interface{}, 0) - sortedArguments := arguments.SortArguments() - for _, argument := range sortedArguments { - - var args []interface{} - args = append(args, ShaHex(argument.Key, "key")) - - var arg []interface{} - arg = append(arg, ShaHex(fmt.Sprint(argument.Index), "index")) - arg = append(arg, ShaHex(argument.Type, "type")) - arg = append(arg, ShaHex(argument.Balance, "balance")) - arg = append(arg, messagesToRlp(argument.Messages)) - args = append(args, arg) - values = append(values, args) - } - return values -} - -func dependenciesToRlp(Dependencies Dependencies) []interface{} { - values := make([]interface{}, 0) - keys := SortMapKeys(Dependencies) - for _, key := range keys { - var deps []interface{} - value := Dependencies[key] - deps = append(deps, ShaHex(key, "key")) - deps = append(deps, contractsToRlp(value)) - values = append(values, deps) - } - return values -} - -func contractsToRlp(Contracts Contracts) []interface{} { - values := make([]interface{}, 0) - keys := SortMapKeys(Contracts) - for _, key := range keys { - value := Contracts[key] - var contracts []interface{} - contracts = append(contracts, ShaHex(key, "key")) - contracts = append(contracts, networksToRlp(value)) - values = append(values, contracts) - } - return values -} - -func networksToRlp(Networks Networks) []interface{} { - values := make([]interface{}, 0) - keys := SortMapKeys(Networks) - for _, key := range keys { - value := Networks[key] - var networks []interface{} - networks = append(networks, ShaHex(key, "key")) - networks = append(networks, networkToRlp(value)) - values = append(values, networks) - } - return values -} - -func networkToRlp(network Network) []interface{} { - values := make([]interface{}, 0) - values = append(values, ShaHex(network.Address, "address")) - values = append(values, ShaHex(network.Contract, "contract")) - values = append(values, ShaHex(network.FqAddress, "fq_address")) - values = append(values, ShaHex(network.Pin, "pin")) - values = append(values, ShaHex(fmt.Sprint(network.PinBlockHeight), "pin_block_height")) - return values -} - -func (flix FlowInteractionTemplate) EncodeRLP() (result string, err error) { - var buffer bytes.Buffer // Create a new buffer - - input := []interface{}{ - ShaHex(flix.FType, "f-type"), - ShaHex(flix.FVersion, "f-version"), - ShaHex(flix.Data.Type, "type"), - ShaHex(flix.Data.Interface, "interface"), - messagesToRlp(flix.Data.Messages), - ShaHex(flix.Data.Cadence, "cadence"), - dependenciesToRlp(flix.Data.Dependencies), - argumentsToRlp(flix.Data.Arguments), - } - - // msg := dependenciesToRlp(flix.Data.Dependencies) - //prettyJSON, _ := json.MarshalIndent(input, "", " ") - //fmt.Println(string(prettyJSON)) - - err = rlp.Encode(&buffer, input) - if err != nil { - return "", err - } - hexString := hex.EncodeToString(buffer.Bytes()) - - //fmt.Println("call to hash hex string") - fullyHashed := ShaHex(hexString, "input") - - //fmt.Println("hexString", fullyHashed) - return fullyHashed, nil - -} - -func GenerateFlixID(flix *FlowInteractionTemplate) (string, error) { - rlpOutput, err := flix.EncodeRLP() - if err != nil { - return "", err - } - return string(rlpOutput), nil -} - -func ShaHex(value interface{}, debugKey string) string { - - // Convert the value to a byte array - data, err := convertToBytes(value) - if err != nil { - if debugKey != "" { - fmt.Printf("%30s value=%v hex=%x\n", debugKey, value, err.Error()) - } - return "" - } - - // Calculate the SHA-3 hash - hash := sha3.Sum256(data) - - // Convert the hash to a hexadecimal string - hashHex := hex.EncodeToString(hash[:]) - - //fmt.Println(value, hashHex) - return hashHex -} - -func convertToBytes(value interface{}) ([]byte, error) { - switch v := value.(type) { - case []byte: - return v, nil - case string: - return []byte(v), nil - case int: - buf := make([]byte, 4) - binary.BigEndian.PutUint32(buf, uint32(v)) - return buf, nil - case uint64: - buf := make([]byte, 8) - binary.BigEndian.PutUint64(buf, v) - return buf, nil - default: - return nil, fmt.Errorf("unsupported type %T", v) - } -} - -type ArgumentKey struct { - Key string - Argument -} - -type ArgumentKeys []ArgumentKey - -func (args Arguments) SortArguments() ArgumentKeys { - keys := make(ArgumentKeys, 0, len(args)) - for key, argument := range args { - keys = append(keys, ArgumentKey{Key: key, Argument: argument}) - } - - // Use sort.Slice instead of sort.Sort - sort.Slice(keys, func(i, j int) bool { - return keys[i].Index < keys[j].Index - }) - - return keys -} - -type MapKeySorter[T any] func(map[string]T) []string - -func SortMapKeys[T any](m map[string]T) []string { - keys := make([]string, 0, len(m)) - for k := range m { - keys = append(keys, k) - } - sort.Strings(keys) - return keys -}