From 48a08d4b3b9a031368c136bed2b01e447603a7e0 Mon Sep 17 00:00:00 2001 From: Mocha Dcaf Date: Tue, 31 Jan 2023 20:03:41 -0500 Subject: [PATCH 1/8] chore: update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9ab870d..2aad05e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ generated/ +.idea/ \ No newline at end of file From 316335685796d1fd11512ce788bd3318edfe54e2 Mon Sep 17 00:00:00 2001 From: Mocha Dcaf Date: Tue, 31 Jan 2023 20:04:34 -0500 Subject: [PATCH 2/8] chore: go mod tidy --- go.mod | 2 -- go.sum | 3 --- 2 files changed, 5 deletions(-) diff --git a/go.mod b/go.mod index 4d5024b..01c5964 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect github.com/gagliardetto/binary v0.7.6 - github.com/gagliardetto/gofuzz v1.2.2 github.com/gagliardetto/solana-go v1.5.0 - github.com/gagliardetto/treeout v0.1.4 github.com/gagliardetto/utilz v0.1.1 github.com/stretchr/testify v1.7.0 golang.org/x/mod v0.4.2 diff --git a/go.sum b/go.sum index a757e4c..4f4674d 100644 --- a/go.sum +++ b/go.sum @@ -90,11 +90,8 @@ github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gagliardetto/binary v0.6.1/go.mod h1:aOfYkc20U0deHaHn/LVZXiqlkDbFAX0FpTlDhsXa0S0= -github.com/gagliardetto/binary v0.7.1 h1:6ggDQ26vR+4xEvl/S13NcdLK3MUCi4oSy73pS9aI1cI= -github.com/gagliardetto/binary v0.7.1/go.mod h1:aOfYkc20U0deHaHn/LVZXiqlkDbFAX0FpTlDhsXa0S0= github.com/gagliardetto/binary v0.7.6 h1:8K3ZB9cEffv6XVqybOR7WxFTTsB1FDWHkv28Pg2tTPc= github.com/gagliardetto/binary v0.7.6/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= -github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= github.com/gagliardetto/hashsearch v0.0.0-20191005111333-09dd671e19f9/go.mod h1:513DXpQPzeRo7d4dsCP3xO3XI8hgvruMl9njxyQeraQ= github.com/gagliardetto/solana-go v1.5.0 h1:FOMgNZyZ6Qwk0gSunfZGFpCOiZzob9KdMTRm007WHK4= From 006ba67260a17530f6082e19a5845522e1b11583 Mon Sep 17 00:00:00 2001 From: Mocha Dcaf Date: Tue, 31 Jan 2023 21:38:46 -0500 Subject: [PATCH 3/8] feat: generate instruction account structs --- generator.go | 24 ++++++++++++++++++++++++ main.go | 11 ++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/generator.go b/generator.go index df5c1a2..6c9685a 100644 --- a/generator.go +++ b/generator.go @@ -86,6 +86,30 @@ func genField(field IdlField, pointer bool) Code { return st } +func genAccountField(field IdlAccountItem) Code { + st := newStatement() + if field.IdlAccount != nil { + st.Id(ToCamel(field.IdlAccount.Name)). + Add(typeStringToType(IdlTypePublicKey)). + Add(func() Code { + if field.IdlAccount.Optional { + return Tag(map[string]string{ + "bin": "optional", + }) + } + return nil + }()) + } + if field.IdlAccounts != nil { + st.Id(field.IdlAccounts.Name).StructFunc(func(group *Group) { + for _, idlAccountItem := range field.IdlAccounts.Accounts { + group.Add(genAccountField(idlAccountItem)) + } + }) + } + return st +} + func genTypeName(idlTypeEnv IdlType) Code { st := newStatement() switch { diff --git a/main.go b/main.go index f09a589..43b1799 100644 --- a/main.go +++ b/main.go @@ -302,7 +302,7 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { for _, instruction := range idl.Instructions { file := NewGoFile(idl.Name, true) insExportedName := ToCamel(instruction.Name) - + insAccountsExportedName := ToCamel(fmt.Sprintf("%s_accounts", instruction.Name)) // fmt.Println(RedBG(instruction.Name)) { @@ -398,6 +398,15 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { }) }) + code.Line().Line() + + // Generate Instruction Account Struct + code.Type().Id(insAccountsExportedName).StructFunc(func(fieldsGroup *Group) { + for _, accountItem := range instruction.Accounts { + fieldsGroup.Add(genAccountField(accountItem)) + } + }) + file.Add(code.Line()) } From 9aa27e8a02cd6cfb2a790af89ff91cbd97e04b83 Mon Sep 17 00:00:00 2001 From: Mocha Dcaf Date: Tue, 31 Jan 2023 22:18:18 -0500 Subject: [PATCH 4/8] feat: generate helper to create accounts struct --- generator.go | 2 +- main.go | 30 +++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/generator.go b/generator.go index 6c9685a..997dbe7 100644 --- a/generator.go +++ b/generator.go @@ -101,7 +101,7 @@ func genAccountField(field IdlAccountItem) Code { }()) } if field.IdlAccounts != nil { - st.Id(field.IdlAccounts.Name).StructFunc(func(group *Group) { + st.Id(ToCamel(field.IdlAccounts.Name)).StructFunc(func(group *Group) { for _, idlAccountItem := range field.IdlAccounts.Accounts { group.Add(genAccountField(idlAccountItem)) } diff --git a/main.go b/main.go index 43b1799..c7bea42 100644 --- a/main.go +++ b/main.go @@ -399,7 +399,7 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { }) code.Line().Line() - + // Generate Instruction Account Struct code.Type().Id(insAccountsExportedName).StructFunc(func(fieldsGroup *Group) { for _, accountItem := range instruction.Accounts { @@ -456,6 +456,29 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { file.Add(code.Line()) } + { + // Declare method to get Account struct form AccountMetasSlice + code := Empty().Line().Line() + code. + Func(). + Params(Id("inst").Op("*").Id(insExportedName)). + Id("Get" + insAccountsExportedName).Params().Op("*").Id(insAccountsExportedName). + BlockFunc(func(body *Group) { + body.Id("res").Op(":=").Op("&").Id(insAccountsExportedName).Block() + instruction.Accounts.Walk("", nil, nil, func(parentGroupPath string, index int, parentGroup *IdlAccounts, account *IdlAccount) bool { + field := body.Id("res") + if parentGroupPath != "" { + field = field.Dot(ToCamel(parentGroupPath)) + } + field = field.Dot(ToCamel(account.Name)).Op("=").Add(Id("inst").Dot("AccountMetaSlice").Index(Lit(index)).Dot("PublicKey")) + return true + }) + body.Return().Op("res") + }) + + file.Add(code.Line().Line()) + } + { // Declare methods that set the parameters of the instruction: code := Empty() @@ -499,6 +522,7 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { file.Add(code.Line()) } + { // Declare methods that set/get accounts for the instruction: code := Empty() @@ -597,6 +621,7 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { file.Add(code.Line()) } + { // Declare `Build` method on instruction: code := Empty() @@ -673,6 +698,7 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { }) file.Add(code.Line()) } + { // Declare `ValidateAndBuild` method on instruction: code := Empty() @@ -710,6 +736,7 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { }) file.Add(code.Line()) } + { // Declare `Validate` method on instruction: code := Empty() @@ -775,6 +802,7 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { }) file.Add(code.Line()) } + { // Declare `EncodeToTree(parent treeout.Branches)` method in instruction: code := Empty() From f6fff6abb6d8cd6b5f4b4d6d0742fe9fb0ebae70 Mon Sep 17 00:00:00 2001 From: Mocha Dcaf Date: Tue, 31 Jan 2023 22:22:34 -0500 Subject: [PATCH 5/8] chore: spelling mistake --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index c7bea42..6c00764 100644 --- a/main.go +++ b/main.go @@ -457,7 +457,7 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { } { - // Declare method to get Account struct form AccountMetasSlice + // Declare method to get Account struct from AccountMetasSlice code := Empty().Line().Line() code. Func(). From 445406275ff5498cc430c60eb59a7ea526c2eeca Mon Sep 17 00:00:00 2001 From: Mocha Dcaf Date: Tue, 31 Jan 2023 22:36:22 -0500 Subject: [PATCH 6/8] feat: add tests for genAccountField --- generator_test.go | 82 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/generator_test.go b/generator_test.go index 2b64c39..bcdaa7f 100644 --- a/generator_test.go +++ b/generator_test.go @@ -6,10 +6,15 @@ import ( . "github.com/dave/jennifer/jen" "github.com/davecgh/go-spew/spew" - "github.com/stretchr/testify/require" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +type jsonToSource struct { + from string + expected string +} + func Test_genTypeName(t *testing.T) { type jsonToSource struct { from string @@ -155,10 +160,6 @@ func Test_genTypeName(t *testing.T) { } func Test_genField(t *testing.T) { - type jsonToSource struct { - from string - expected string - } tests := []jsonToSource{ { @@ -186,6 +187,77 @@ func Test_genField(t *testing.T) { } } +func Test_genAccountField(t *testing.T) { + basicTest := `{ + "name": "authorityBefore", + "isMut": false, + "isSigner": true + }` + optionalTest := `{ + "name": "authorityBefore", + "isMut": false, + "isSigner": true, + "optional": true + }` + compositeTest := `{ + "name": "marketGroup", + "accounts": [ + { + "name": "marketMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "foo", + "isMut": true, + "isSigner": false + }, + { + "name": "subMarket", + "accounts": [ + { + "name": "subMarketMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "openOrders", + "isMut": true, + "isSigner": false + } + ] + } + ] + }` + + tests := []jsonToSource{ + { + basicTest, + "var thing struct {\n\tAuthorityBefore solanago.PublicKey\n}", + }, + { + optionalTest, + "var thing struct {\n\tAuthorityBefore solanago.PublicKey `bin:\"optional\"`\n}", + }, + { + compositeTest, + "var thing struct {\n\tMarketGroup struct {\n\t\tMarketMarket solanago.PublicKey\n\t\tFoo solanago.PublicKey\n\t\tSubMarket struct {\n\t\t\tSubMarketMarket solanago.PublicKey\n\t\t\tOpenOrders solanago.PublicKey\n\t\t}\n\t}\n}", + }, + } + { + for _, scenario := range tests { + var target IdlAccountItem + err := json.Unmarshal([]byte(scenario.from), &target) + require.NoError(t, err) + code := Var().Id("thing").Struct( + genAccountField(target), + ) + got := codeToString(code) + require.Equal(t, scenario.expected, got) + } + } +} + func Test_IdlAccountItemSlice_Walk(t *testing.T) { data := `[ { From 235cca9e248fb8880eb7f8f4b46ae7e90bcf533c Mon Sep 17 00:00:00 2001 From: Mocha Dcaf Date: Tue, 31 Jan 2023 22:51:12 -0500 Subject: [PATCH 7/8] fix: mod --- go.mod | 2 ++ go.sum | 1 + 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index 01c5964..4d5024b 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,9 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect github.com/gagliardetto/binary v0.7.6 + github.com/gagliardetto/gofuzz v1.2.2 github.com/gagliardetto/solana-go v1.5.0 + github.com/gagliardetto/treeout v0.1.4 github.com/gagliardetto/utilz v0.1.1 github.com/stretchr/testify v1.7.0 golang.org/x/mod v0.4.2 diff --git a/go.sum b/go.sum index 4f4674d..202190b 100644 --- a/go.sum +++ b/go.sum @@ -92,6 +92,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/gagliardetto/binary v0.6.1/go.mod h1:aOfYkc20U0deHaHn/LVZXiqlkDbFAX0FpTlDhsXa0S0= github.com/gagliardetto/binary v0.7.6 h1:8K3ZB9cEffv6XVqybOR7WxFTTsB1FDWHkv28Pg2tTPc= github.com/gagliardetto/binary v0.7.6/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= +github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= github.com/gagliardetto/hashsearch v0.0.0-20191005111333-09dd671e19f9/go.mod h1:513DXpQPzeRo7d4dsCP3xO3XI8hgvruMl9njxyQeraQ= github.com/gagliardetto/solana-go v1.5.0 h1:FOMgNZyZ6Qwk0gSunfZGFpCOiZzob9KdMTRm007WHK4= From f77f9aaa05596017b78357080f3f3ab480b634c3 Mon Sep 17 00:00:00 2001 From: Mocha Dcaf Date: Wed, 1 Feb 2023 21:16:05 -0500 Subject: [PATCH 8/8] fix: add nil check in codgen fn --- main.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/main.go b/main.go index 6c00764..fc0fc96 100644 --- a/main.go +++ b/main.go @@ -466,11 +466,14 @@ func GenerateClientFromProgramIDL(idl IDL) ([]*FileWrapper, error) { BlockFunc(func(body *Group) { body.Id("res").Op(":=").Op("&").Id(insAccountsExportedName).Block() instruction.Accounts.Walk("", nil, nil, func(parentGroupPath string, index int, parentGroup *IdlAccounts, account *IdlAccount) bool { - field := body.Id("res") - if parentGroupPath != "" { - field = field.Dot(ToCamel(parentGroupPath)) - } - field = field.Dot(ToCamel(account.Name)).Op("=").Add(Id("inst").Dot("AccountMetaSlice").Index(Lit(index)).Dot("PublicKey")) + // check if not nil before accessing "PublicKey" + body.If(Id("inst").Dot("AccountMetaSlice").Index(Lit(index)).Op("!=").Nil()).BlockFunc(func(group *Group) { + field := group.Id("res") + if parentGroupPath != "" { + field = field.Dot(ToCamel(parentGroupPath)) + } + field.Dot(ToCamel(account.Name)).Op("=").Add(Id("inst").Dot("AccountMetaSlice").Index(Lit(index)).Dot("PublicKey")) + }) return true }) body.Return().Op("res")