Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,10 @@ func IDLTypeKind_ToTypeDeclCode(ts idltype.IdlType) *Statement {
stat.Qual(PkgBinary, "Uint128")
case *idltype.I128:
stat.Qual(PkgBinary, "Int128")
case *idltype.U256:
stat.Index(Lit(32)).Byte()
case *idltype.I256:
stat.Index(Lit(32)).Byte()
case *idltype.Bytes:
stat.Index().Byte()
case *idltype.String:
Expand Down
70 changes: 51 additions & 19 deletions cmd/generate-bindings/solana/anchor-go/generator/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,25 +174,57 @@ func (g *Generator) gen_constants() (*OutputFile, error) {
Return(Id("val")),
).Call()
code.Line()
case *idltype.I128:
_ = ty
// "value":"-100_000_000"
cleanValue := strings.ReplaceAll(co.Value, "_", "")
bigInt := new(big.Int)
_, ok := bigInt.SetString(cleanValue, 10)
if !ok {
return nil, fmt.Errorf("failed to parse i128 constants[%d] %s: invalid format", coi, spew.Sdump(co))
}
// Generate code that creates a big.Int from string
code.Var().Id(co.Name).Op("=").Func().Params().Op("*").Qual("math/big", "Int").Block(
Id("val").Op(",").Id("ok").Op(":=").New(Qual("math/big", "Int")).Dot("SetString").Call(Lit(cleanValue), Lit(10)),
If(Op("!").Id("ok")).Block(
Panic(Lit(fmt.Sprintf("invalid i128 constant %s", co.Name))),
),
Return(Id("val")),
).Call()
code.Line()
case *idltype.F32:
case *idltype.I128:
_ = ty
// "value":"-100_000_000"
cleanValue := strings.ReplaceAll(co.Value, "_", "")
bigInt := new(big.Int)
_, ok := bigInt.SetString(cleanValue, 10)
if !ok {
return nil, fmt.Errorf("failed to parse i128 constants[%d] %s: invalid format", coi, spew.Sdump(co))
}
// Generate code that creates a big.Int from string
code.Var().Id(co.Name).Op("=").Func().Params().Op("*").Qual("math/big", "Int").Block(
Id("val").Op(",").Id("ok").Op(":=").New(Qual("math/big", "Int")).Dot("SetString").Call(Lit(cleanValue), Lit(10)),
If(Op("!").Id("ok")).Block(
Panic(Lit(fmt.Sprintf("invalid i128 constant %s", co.Name))),
),
Return(Id("val")),
).Call()
code.Line()
case *idltype.U256:
_ = ty
cleanValue := strings.ReplaceAll(co.Value, "_", "")
bigInt := new(big.Int)
_, ok := bigInt.SetString(cleanValue, 10)
if !ok {
return nil, fmt.Errorf("failed to parse u256 constants[%d] %s: invalid format", coi, spew.Sdump(co))
}
code.Var().Id(co.Name).Op("=").Func().Params().Op("*").Qual("math/big", "Int").Block(
Id("val").Op(",").Id("ok").Op(":=").New(Qual("math/big", "Int")).Dot("SetString").Call(Lit(cleanValue), Lit(10)),
If(Op("!").Id("ok")).Block(
Panic(Lit(fmt.Sprintf("invalid u256 constant %s", co.Name))),
),
Return(Id("val")),
).Call()
code.Line()
case *idltype.I256:
_ = ty
cleanValue := strings.ReplaceAll(co.Value, "_", "")
bigInt := new(big.Int)
_, ok := bigInt.SetString(cleanValue, 10)
if !ok {
return nil, fmt.Errorf("failed to parse i256 constants[%d] %s: invalid format", coi, spew.Sdump(co))
}
code.Var().Id(co.Name).Op("=").Func().Params().Op("*").Qual("math/big", "Int").Block(
Id("val").Op(",").Id("ok").Op(":=").New(Qual("math/big", "Int")).Dot("SetString").Call(Lit(cleanValue), Lit(10)),
If(Op("!").Id("ok")).Block(
Panic(Lit(fmt.Sprintf("invalid i256 constant %s", co.Name))),
),
Return(Id("val")),
).Call()
code.Line()
case *idltype.F32:
_ = ty
// "value":"3.14"
cleanValue := strings.ReplaceAll(co.Value, "_", "")
Expand Down
148 changes: 148 additions & 0 deletions cmd/generate-bindings/solana/anchor-go/generator/u256_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
//nolint:all // Forked from anchor-go generator, maintaining original code structure
package generator

import (
"testing"

"github.com/gagliardetto/anchor-go/idl"
"github.com/gagliardetto/anchor-go/idl/idltype"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestIDLTypeKind_ToTypeDeclCode_U256(t *testing.T) {
assert.NotPanics(t, func() {
result := IDLTypeKind_ToTypeDeclCode(&idltype.U256{})
assert.NotNil(t, result)
})
}

func TestIDLTypeKind_ToTypeDeclCode_I256(t *testing.T) {
assert.NotPanics(t, func() {
result := IDLTypeKind_ToTypeDeclCode(&idltype.I256{})
assert.NotNil(t, result)
})
}

func TestGenTypeName_U256(t *testing.T) {
assert.NotPanics(t, func() {
result := genTypeName(&idltype.U256{})
assert.NotNil(t, result)
})
}

func TestGenTypeName_I256(t *testing.T) {
assert.NotPanics(t, func() {
result := genTypeName(&idltype.I256{})
assert.NotNil(t, result)
})
}

func TestGenConstants_U256(t *testing.T) {
idlData := &idl.Idl{
Constants: []idl.IdlConst{
{
Name: "MAX_SUPPLY",
Ty: &idltype.U256{},
Value: "115792089237316195423570985008687907853269984665640564039457584007913129639935",
},
},
}
gen := &Generator{
idl: idlData,
options: &GeneratorOptions{Package: "test"},
}

outputFile, err := gen.gen_constants()
require.NoError(t, err)

generatedCode := outputFile.File.GoString()
assert.Contains(t, generatedCode, "var MAX_SUPPLY = func() *big.Int")
assert.Contains(t, generatedCode, ".SetString(\"115792089237316195423570985008687907853269984665640564039457584007913129639935\", 10)")
}

func TestGenConstants_I256(t *testing.T) {
idlData := &idl.Idl{
Constants: []idl.IdlConst{
{
Name: "MIN_VALUE",
Ty: &idltype.I256{},
Value: "-57896044618658097711785492504343953926634992332820282019728792003956564819968",
},
},
}
gen := &Generator{
idl: idlData,
options: &GeneratorOptions{Package: "test"},
}

outputFile, err := gen.gen_constants()
require.NoError(t, err)

generatedCode := outputFile.File.GoString()
assert.Contains(t, generatedCode, "var MIN_VALUE = func() *big.Int")
assert.Contains(t, generatedCode, ".SetString(\"-57896044618658097711785492504343953926634992332820282019728792003956564819968\", 10)")
}

func TestGenConstants_U256_Invalid(t *testing.T) {
idlData := &idl.Idl{
Constants: []idl.IdlConst{
{
Name: "INVALID_U256",
Ty: &idltype.U256{},
Value: "not_a_number",
},
},
}
gen := &Generator{
idl: idlData,
options: &GeneratorOptions{Package: "test"},
}

_, err := gen.gen_constants()
require.Error(t, err)
assert.Contains(t, err.Error(), "failed to parse u256")
}

func TestGenConstants_I256_Invalid(t *testing.T) {
idlData := &idl.Idl{
Constants: []idl.IdlConst{
{
Name: "INVALID_I256",
Ty: &idltype.I256{},
Value: "not_a_number",
},
},
}
gen := &Generator{
idl: idlData,
options: &GeneratorOptions{Package: "test"},
}

_, err := gen.gen_constants()
require.Error(t, err)
assert.Contains(t, err.Error(), "failed to parse i256")
}

func TestGenConstants_U256_WithUnderscores(t *testing.T) {
idlData := &idl.Idl{
Constants: []idl.IdlConst{
{
Name: "LARGE_U256",
Ty: &idltype.U256{},
Value: "1_000_000_000_000_000_000_000_000_000",
},
},
}
gen := &Generator{
idl: idlData,
options: &GeneratorOptions{Package: "test"},
}

outputFile, err := gen.gen_constants()
require.NoError(t, err)

generatedCode := outputFile.File.GoString()
assert.Contains(t, generatedCode, "var LARGE_U256 = func() *big.Int")
assert.Contains(t, generatedCode, ".SetString(\"1000000000000000000000000000\", 10)")
}
Loading