-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add binding gen js for remote and local #12
Merged
Merged
Changes from 13 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
a2c8c05
init check in for generating binding files based on flix
bthaile 6f03fb0
add sub templates for js files, gen binding file in same dir as templ…
bthaile 389069b
organization of files and ignores
bthaile 7451e2a
ignore built file
bthaile 4ab973f
ignore template files
bthaile 016c059
ignore template files
bthaile 5a50239
add file reader to config for unit testing
bthaile 50d5bcb
verify that remote templates can gen js files
bthaile 1b9b440
fix git ignore file
bthaile 37a9f3d
ignore cmd dir and all .DS_Store files
bthaile 6c242b7
remove .DS_Store files
bthaile f9d4bf4
add testing gen js binding with remote flix
bthaile d15e7ca
support array of simple types
bthaile d4848cf
first batch of changes based on feedback
bthaile 2098974
collapse files and keep everything in flixkit package
bthaile 530a385
clean up
bthaile b7a142c
add js docs to provide types for typescript
bthaile 870b6ff
do not rely on message to be there and that us-en exists, update temp…
bthaile 805a993
fix consistency for testing
bthaile dac9742
simplify conversion to js types, fcl uses strings for all numbers
bthaile 4a9cf9a
add golden for unit tests
bthaile bd1a7a9
pass in generator method to generate code
bthaile 5aef7f0
use interface and set specific port for testing remote and use golden…
bthaile e7cd1bc
fixed arguments key sorting issue, that was causing test failures
bthaile 4932623
fix case typo in generator name
bthaile 64e11a5
remove need to read from disk to get template
bthaile aa66b9f
tidy
bthaile 9d27901
move js generator to bindings module and rename js generator to fcl j…
bthaile 8c19379
formatting
bthaile 0593679
pass in template directory to be more flexible
bthaile 5a9f441
add comment that fcl version 1.3.0 or greater is needed to use templates
bthaile 8857770
add helper func to create fcl js code generator
bthaile 9cd4a66
removed todo: added named return values from method
bthaile 5ad7e6a
update readme to include bindings module
bthaile 6619788
use filepath.Walk to get files from template dir
bthaile File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Ignore cmd directory | ||
cmd/ | ||
|
||
# ignore all .DS_Store files | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package bindings | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
js "github.com/onflow/flixkit-go/bindings/js" | ||
"github.com/onflow/flixkit-go/common" | ||
) | ||
|
||
func Generate(lang string, flix *common.FlowInteractionTemplate, templateLocation string) (string, error) { | ||
var contents string | ||
var err error | ||
switch lang { | ||
case "javascript", "js": | ||
contents, err = js.GenerateJavaScript(flix, templateLocation) | ||
default: | ||
return "", fmt.Errorf("language %s not supported", lang) | ||
} | ||
|
||
if err != nil { | ||
log.Fatalf("Error generating JavaScript: %v", err) | ||
} | ||
|
||
return contents, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package js | ||
|
||
import ( | ||
"bytes" | ||
"embed" | ||
_ "embed" | ||
"fmt" | ||
"net/url" | ||
"path" | ||
"text/template" | ||
|
||
"github.com/onflow/flixkit-go/common" | ||
) | ||
|
||
type SimpleParameter struct { | ||
Name string | ||
Type string | ||
} | ||
|
||
type TemplateData struct { | ||
Version string | ||
Parameters []SimpleParameter | ||
Title string | ||
Location string | ||
IsScript bool | ||
IsLocalTemplate bool | ||
bthaile marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
//go:embed templates/*.tmpl | ||
var templateFiles embed.FS | ||
|
||
func GenerateJavaScript(flix *common.FlowInteractionTemplate, templateLocation string) (string, error) { | ||
tmpl, err := template.ParseFS(templateFiles, "templates/*.tmpl") | ||
if err != nil { | ||
fmt.Println("Error executing template:", err) | ||
return "", err | ||
} | ||
|
||
templatePath, IsLocal, _ := GetTemplateReference(templateLocation) | ||
methodName := common.TitleToMethodName(flix.Data.Messages.Title.I18N["en-US"]) | ||
data := TemplateData{ | ||
Version: flix.FVersion, | ||
Parameters: TransformArguments(flix.Data.Arguments), | ||
Title: methodName, | ||
Location: templatePath, | ||
IsScript: flix.IsScript(), | ||
IsLocalTemplate: IsLocal, | ||
} | ||
|
||
var buf bytes.Buffer | ||
err = tmpl.Execute(&buf, data) | ||
return buf.String(), err | ||
} | ||
|
||
|
||
func TransformArguments(args common.Arguments) []SimpleParameter { | ||
simpleArgs := []SimpleParameter{} | ||
for name, arg := range args { | ||
isArray, arrayType := IsArrayParameter(arg) | ||
if (isArray) { | ||
simpleArgs = append(simpleArgs, SimpleParameter{Name: name, Type: "Array(t." + arrayType + ")"}) | ||
} else { | ||
simpleArgs = append(simpleArgs, SimpleParameter{Name: name, Type: arg.Type}) | ||
} | ||
} | ||
return simpleArgs | ||
} | ||
|
||
|
||
func IsArrayParameter(arg common.Argument) (bool, string) { | ||
isArray := arg.Type[0] == '[' && arg.Type[len(arg.Type)-1] == ']' | ||
if (!isArray) { | ||
bthaile marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return isArray, "" | ||
} | ||
return isArray, arg.Type[1 : len(arg.Type)-1] | ||
} | ||
|
||
func GetTemplateReference(templateLocation string) (string, bool, error) { | ||
var err error | ||
templatePath := templateLocation | ||
IsLocal := common.IsLocalTemplate(templateLocation) | ||
bthaile marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (IsLocal) { | ||
bthaile marked this conversation as resolved.
Show resolved
Hide resolved
|
||
parsedURL, err := url.Parse(templateLocation) | ||
if err != nil { | ||
return templatePath, IsLocal, err | ||
} | ||
templatePath = "./" + path.Base(parsedURL.Path) | ||
} | ||
return templatePath, IsLocal, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
package js | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
|
||
"github.com/onflow/flixkit-go/common" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
|
||
var parsedTemplateTX = &common.FlowInteractionTemplate{ | ||
FType: "InteractionTemplate", | ||
FVersion: "1.0.0", | ||
ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", | ||
Data: common.Data{ | ||
Type: "transaction", | ||
Interface: "", | ||
Messages: common.Messages{ | ||
Title: &common.Title{ | ||
I18N: map[string]string{ | ||
"en-US": "Transfer Tokens", | ||
}, | ||
}, | ||
Description: &common.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: common.Dependencies{ | ||
"0xFUNGIBLETOKENADDRESS": common.Contracts{ | ||
"FungibleToken": common.Networks{ | ||
"mainnet": common.Network{ | ||
Address: "0xf233dcee88fe0abe", | ||
FqAddress: "A.0xf233dcee88fe0abe.FungibleToken", | ||
Contract: "FungibleToken", | ||
Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", | ||
PinBlockHeight: 34166296, | ||
}, | ||
"testnet": common.Network{ | ||
Address: "0x9a0766d93b6608b7", | ||
FqAddress: "A.0x9a0766d93b6608b7.FungibleToken", | ||
Contract: "FungibleToken", | ||
Pin: "83c9e3d61d3b5ebf24356a9f17b5b57b12d6d56547abc73e05f820a0ae7d9cf5", | ||
PinBlockHeight: 74776482, | ||
}, | ||
}, | ||
}, | ||
}, | ||
Arguments: common.Arguments{ | ||
"amount": common.Argument{ | ||
Index: 0, | ||
Type: "UFix64", | ||
Messages: common.Messages{ | ||
Title: &common.Title{ | ||
I18N: map[string]string{ | ||
"en-US": "The amount of FLOW tokens to send", | ||
}, | ||
}, | ||
}, | ||
Balance: "", | ||
}, | ||
"to": common.Argument{ | ||
Index: 1, | ||
Type: "Address", | ||
Messages: common.Messages{ | ||
Title: &common.Title{ | ||
I18N: map[string]string{ | ||
"en-US": "The Flow account the tokens will go to", | ||
}, | ||
}, | ||
}, | ||
Balance: "", | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
|
||
var parsedTemplateScript = &common.FlowInteractionTemplate{ | ||
FType: "InteractionTemplate", | ||
FVersion: "1.0.0", | ||
ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", | ||
Data: common.Data{ | ||
Type: "script", | ||
Interface: "", | ||
Messages: common.Messages{ | ||
Title: &common.Title{ | ||
I18N: map[string]string{ | ||
"en-US": "Transfer Tokens", | ||
}, | ||
}, | ||
Description: &common.Description{ | ||
I18N: map[string]string{ | ||
"en-US": "Transfer tokens from one account to another", | ||
}, | ||
}, | ||
}, | ||
Cadence: "pub fun main(x: Int, y: Int): Int { return x * y }", | ||
Arguments: common.Arguments{ | ||
"x": common.Argument{ | ||
Index: 0, | ||
Type: "Int", | ||
Messages: common.Messages{ | ||
Title: &common.Title{ | ||
I18N: map[string]string{ | ||
"en-US": "number to be multiplied", | ||
}, | ||
}, | ||
}, | ||
Balance: "", | ||
}, | ||
"y": common.Argument{ | ||
Index: 1, | ||
Type: "Int", | ||
Messages: common.Messages{ | ||
Title: &common.Title{ | ||
I18N: map[string]string{ | ||
"en-US": "second number to be multiplied", | ||
}, | ||
}, | ||
}, | ||
Balance: "", | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
|
||
var ArrayTypeScript = &common.FlowInteractionTemplate{ | ||
FType: "InteractionTemplate", | ||
FVersion: "1.0.0", | ||
ID: "290b6b6222b2a77b16db896a80ddf29ebd1fa3038c9e6625a933fa213fce51fa", | ||
Data: common.Data{ | ||
Type: "script", | ||
Interface: "", | ||
Messages: common.Messages{ | ||
Title: &common.Title{ | ||
I18N: map[string]string{ | ||
"en-US": "Multiply Numbers", | ||
}, | ||
}, | ||
Description: &common.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: common.Arguments{ | ||
"numbers": common.Argument{ | ||
Index: 0, | ||
Type: "[Int]", | ||
Messages: common.Messages{ | ||
Title: &common.Title{ | ||
I18N: map[string]string{ | ||
"en-US": "Array of numbers to be multiplied", | ||
}, | ||
}, | ||
}, | ||
Balance: "", | ||
}, | ||
}, | ||
}, | ||
} | ||
func TestJSGenTransaction(t *testing.T) { | ||
assert := assert.New(t) | ||
|
||
contents, err := GenerateJavaScript(parsedTemplateTX, "./transfer_token.json") | ||
assert.NoError(err, "ParseTemplate should not return an error") | ||
assert.NotNil(contents, "Parsed template should not be nil") | ||
assert.True(strings.Contains(contents, "await fcl.mutate("), "Expected '%s'", "await fcl.mutate(") | ||
println(contents) | ||
|
||
} | ||
|
||
|
||
func TestJSGenScript(t *testing.T) { | ||
assert := assert.New(t) | ||
|
||
contents, err := GenerateJavaScript(parsedTemplateScript, "./transfer_token.json") | ||
assert.NoError(err, "ParseTemplate should not return an error") | ||
assert.NotNil(contents, "Parsed template should not be nil") | ||
assert.True(strings.Contains(contents, "await fcl.query("), "Expected '%s'", "await fcl.query(") | ||
println(contents) | ||
|
||
} | ||
|
||
|
||
|
||
func TestJSGenArrayScript(t *testing.T) { | ||
assert := assert.New(t) | ||
|
||
contents, err := GenerateJavaScript(ArrayTypeScript, "./multiply-numbers.template.json") | ||
assert.NoError(err, "ParseTemplate should not return an error") | ||
assert.NotNil(contents, "Parsed template should not be nil") | ||
assert.True(strings.Contains(contents, "await fcl.query("), "Expected '%s'", "await fcl.query(") | ||
assert.True(strings.Contains(contents, `args: (arg, t) => ([ args(numbers, t.Array(t.Int))])`), "Expected '%s'", `args([ fcl.arg(numbers, t.Array(t.Int)) ])`) | ||
println(contents) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/** | ||
This binding file was auto generated based on FLIX template v{{.Version}}. | ||
Changes to this file might get overwritten | ||
**/ | ||
|
||
import * as fcl from "@onflow/fcl" | ||
chasefleming marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{{- if .IsLocalTemplate }} | ||
import flixTemplate from "{{.Location}}" | ||
{{- else}} | ||
const flixTemplate = "{{.Location}}" | ||
{{- end}} | ||
|
||
const parameterNames = [ | ||
{{- range $index, $ele := .Parameters -}} | ||
{{if $index}}, {{end}}"{{$ele.Name}}" | ||
{{- end -}} | ||
]; | ||
|
||
{{if .IsScript}} | ||
{{- template "script.tmpl" .}} | ||
{{else}} | ||
{{- template "tx.tmpl" .}} | ||
{{end}} | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
export async function {{.Title}}({ | ||
{{- if len .Parameters -}} | ||
{{- range $index, $ele := .Parameters -}} | ||
{{if $index}}, {{end}}{{.Name}} | ||
{{- end -}} | ||
{{- end -}} | ||
}) { | ||
const info = await fcl.query({ | ||
template: flixTemplate, | ||
{{ if len .Parameters -}} | ||
args: (arg, t) => [ | ||
{{- range $index, $ele := .Parameters -}} | ||
{{if $index}}, {{end}}arg({{.Name}}, t.{{.Type}}) | ||
{{- end -}} | ||
] | ||
{{- end }} | ||
}); | ||
|
||
return info | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
export async function {{.Title}}({ | ||
{{- if len .Parameters -}} | ||
{{- range $index, $ele := .Parameters -}} | ||
{{if $index}}, {{end}}{{.Name}} | ||
{{- end -}} | ||
{{- end -}} | ||
}) { | ||
const transactionId = await fcl.mutate({ | ||
template: flixTemplate, | ||
{{ if len .Parameters -}} | ||
args: (arg, t) => [ | ||
{{- range $index, $ele := .Parameters -}} | ||
{{if $index}}, {{end}}arg({{.Name}}, t.{{.Type}}) | ||
{{- end -}} | ||
] | ||
{{- end }} | ||
}); | ||
|
||
return transactionId | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the goal is to run this from Flow CLI I don't think this makes sense to be here. It should instead pull the file and get the command using the CLI and then call the fundings it needs to which occur inside the case statements. That's what happens here in the Flow CLI for running FLIX: https://github.com/onflow/flow-cli/blob/master/internal/super/flix.go#L104
Then you can also use Cobra in the CLI which will handle all this better and remove the need for the cmd folder.