diff --git a/README.md b/README.md index 9f0d2425..6b253234 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Add a migrations: ## Generate SQLBoiler `docker-compose up -d db` Starts a Postgres database. -`make tools-boil` Installs the correct version of sqlboiler. +`make tools-sqlboiler` Installs the correct version of sqlboiler. `make migrate` Runs unapplied database migrations. `make boil` Regenerates the SQLBoiler models. diff --git a/charts/identity-api/values.yaml b/charts/identity-api/values.yaml index 5e9685e4..a5e35fc5 100644 --- a/charts/identity-api/values.yaml +++ b/charts/identity-api/values.yaml @@ -51,6 +51,7 @@ env: STAKING_ADDR: '0xA010a42DE263592E631d3DCDC621ae7BFfCca338' CONNECTION_ADDR: '0x41799E9Dc893722844E771a1C1cAf3BBc2876132' STORAGE_NODE_ADDR: '0xf76eEBa34B19aDb7eEa9E4Eea05243D7E5a30123' + TEMPLATE_ADDR: '0x0000000000000000000000000000000000000000' service: type: ClusterIP ports: diff --git a/graph/generated.go b/graph/generated.go index 149f5a05..1534b5fc 100644 --- a/graph/generated.go +++ b/graph/generated.go @@ -295,6 +295,8 @@ type ComplexityRoot struct { Stakes func(childComplexity int, first *int, after *string, last *int, before *string, filterBy *model.StakeFilterBy) int SyntheticDevice func(childComplexity int, by model.SyntheticDeviceBy) int SyntheticDevices func(childComplexity int, first *int, last *int, after *string, before *string, filterBy *model.SyntheticDevicesFilter) int + Template func(childComplexity int, by model.TemplateBy) int + Templates func(childComplexity int, first *int, after *string, last *int, before *string) int Vehicle func(childComplexity int, tokenID *int, tokenDid *string) int Vehicles func(childComplexity int, first *int, after *string, last *int, before *string, filterBy *model.VehiclesFilter) int } @@ -412,6 +414,27 @@ type ComplexityRoot struct { Node func(childComplexity int) int } + Template struct { + Asset func(childComplexity int) int + Cid func(childComplexity int) int + CreatedAt func(childComplexity int) int + Creator func(childComplexity int) int + Permissions func(childComplexity int) int + TokenID func(childComplexity int) int + } + + TemplateConnection struct { + Edges func(childComplexity int) int + Nodes func(childComplexity int) int + PageInfo func(childComplexity int) int + TotalCount func(childComplexity int) int + } + + TemplateEdge struct { + Cursor func(childComplexity int) int + Node func(childComplexity int) int + } + UserRewards struct { History func(childComplexity int, first *int, after *string, last *int, before *string) int TotalTokens func(childComplexity int) int @@ -502,6 +525,8 @@ type QueryResolver interface { Stakes(ctx context.Context, first *int, after *string, last *int, before *string, filterBy *model.StakeFilterBy) (*model.StakeConnection, error) SyntheticDevice(ctx context.Context, by model.SyntheticDeviceBy) (*model.SyntheticDevice, error) SyntheticDevices(ctx context.Context, first *int, last *int, after *string, before *string, filterBy *model.SyntheticDevicesFilter) (*model.SyntheticDeviceConnection, error) + Template(ctx context.Context, by model.TemplateBy) (*model.Template, error) + Templates(ctx context.Context, first *int, after *string, last *int, before *string) (*model.TemplateConnection, error) Vehicle(ctx context.Context, tokenID *int, tokenDid *string) (*model.Vehicle, error) Vehicles(ctx context.Context, first *int, after *string, last *int, before *string, filterBy *model.VehiclesFilter) (*model.VehicleConnection, error) } @@ -1691,6 +1716,30 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.Query.SyntheticDevices(childComplexity, args["first"].(*int), args["last"].(*int), args["after"].(*string), args["before"].(*string), args["filterBy"].(*model.SyntheticDevicesFilter)), true + case "Query.template": + if e.complexity.Query.Template == nil { + break + } + + args, err := ec.field_Query_template_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Template(childComplexity, args["by"].(model.TemplateBy)), true + + case "Query.templates": + if e.complexity.Query.Templates == nil { + break + } + + args, err := ec.field_Query_templates_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Templates(childComplexity, args["first"].(*int), args["after"].(*string), args["last"].(*int), args["before"].(*string)), true + case "Query.vehicle": if e.complexity.Query.Vehicle == nil { break @@ -2170,6 +2219,90 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.SyntheticDeviceEdge.Node(childComplexity), true + case "Template.asset": + if e.complexity.Template.Asset == nil { + break + } + + return e.complexity.Template.Asset(childComplexity), true + + case "Template.cid": + if e.complexity.Template.Cid == nil { + break + } + + return e.complexity.Template.Cid(childComplexity), true + + case "Template.createdAt": + if e.complexity.Template.CreatedAt == nil { + break + } + + return e.complexity.Template.CreatedAt(childComplexity), true + + case "Template.creator": + if e.complexity.Template.Creator == nil { + break + } + + return e.complexity.Template.Creator(childComplexity), true + + case "Template.permissions": + if e.complexity.Template.Permissions == nil { + break + } + + return e.complexity.Template.Permissions(childComplexity), true + + case "Template.tokenId": + if e.complexity.Template.TokenID == nil { + break + } + + return e.complexity.Template.TokenID(childComplexity), true + + case "TemplateConnection.edges": + if e.complexity.TemplateConnection.Edges == nil { + break + } + + return e.complexity.TemplateConnection.Edges(childComplexity), true + + case "TemplateConnection.nodes": + if e.complexity.TemplateConnection.Nodes == nil { + break + } + + return e.complexity.TemplateConnection.Nodes(childComplexity), true + + case "TemplateConnection.pageInfo": + if e.complexity.TemplateConnection.PageInfo == nil { + break + } + + return e.complexity.TemplateConnection.PageInfo(childComplexity), true + + case "TemplateConnection.totalCount": + if e.complexity.TemplateConnection.TotalCount == nil { + break + } + + return e.complexity.TemplateConnection.TotalCount(childComplexity), true + + case "TemplateEdge.cursor": + if e.complexity.TemplateEdge.Cursor == nil { + break + } + + return e.complexity.TemplateEdge.Cursor(childComplexity), true + + case "TemplateEdge.node": + if e.complexity.TemplateEdge.Node == nil { + break + } + + return e.complexity.TemplateEdge.Node(childComplexity), true + case "UserRewards.history": if e.complexity.UserRewards.History == nil { break @@ -2415,6 +2548,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputStakeFilterBy, ec.unmarshalInputSyntheticDeviceBy, ec.unmarshalInputSyntheticDevicesFilter, + ec.unmarshalInputTemplateBy, ec.unmarshalInputVehiclesFilter, ) first := true @@ -2497,7 +2631,7 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } -//go:embed "schema/aftermarket.graphqls" "schema/connection.graphqls" "schema/dcn.graphqls" "schema/developerlicense.graphqls" "schema/devicedefinition.graphqls" "schema/manufacturer.graphqls" "schema/privilege.graphqls" "schema/reward.graphqls" "schema/sacd.graphqls" "schema/schema.graphqls" "schema/stakes.graphqls" "schema/storagenode.graphqls" "schema/synthetic.graphqls" "schema/vehicle.graphqls" +//go:embed "schema/aftermarket.graphqls" "schema/connection.graphqls" "schema/dcn.graphqls" "schema/developerlicense.graphqls" "schema/devicedefinition.graphqls" "schema/manufacturer.graphqls" "schema/privilege.graphqls" "schema/reward.graphqls" "schema/sacd.graphqls" "schema/schema.graphqls" "schema/stakes.graphqls" "schema/storagenode.graphqls" "schema/synthetic.graphqls" "schema/template.graphqls" "schema/vehicle.graphqls" var sourcesFS embed.FS func sourceData(filename string) string { @@ -2522,6 +2656,7 @@ var sources = []*ast.Source{ {Name: "schema/stakes.graphqls", Input: sourceData("schema/stakes.graphqls"), BuiltIn: false}, {Name: "schema/storagenode.graphqls", Input: sourceData("schema/storagenode.graphqls"), BuiltIn: false}, {Name: "schema/synthetic.graphqls", Input: sourceData("schema/synthetic.graphqls"), BuiltIn: false}, + {Name: "schema/template.graphqls", Input: sourceData("schema/template.graphqls"), BuiltIn: false}, {Name: "schema/vehicle.graphqls", Input: sourceData("schema/vehicle.graphqls"), BuiltIn: false}, } var parsedSchema = gqlparser.MustLoadSchema(sources...) @@ -2961,6 +3096,43 @@ func (ec *executionContext) field_Query_syntheticDevices_args(ctx context.Contex return args, nil } +func (ec *executionContext) field_Query_template_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "by", ec.unmarshalNTemplateBy2githubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateBy) + if err != nil { + return nil, err + } + args["by"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_templates_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "first", ec.unmarshalOInt2ᚖint) + if err != nil { + return nil, err + } + args["first"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "after", ec.unmarshalOString2ᚖstring) + if err != nil { + return nil, err + } + args["after"] = arg1 + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "last", ec.unmarshalOInt2ᚖint) + if err != nil { + return nil, err + } + args["last"] = arg2 + arg3, err := graphql.ProcessArgField(ctx, rawArgs, "before", ec.unmarshalOString2ᚖstring) + if err != nil { + return nil, err + } + args["before"] = arg3 + return args, nil +} + func (ec *executionContext) field_Query_vehicle_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { var err error args := map[string]any{} @@ -10766,6 +10938,140 @@ func (ec *executionContext) fieldContext_Query_syntheticDevices(ctx context.Cont return fc, nil } +func (ec *executionContext) _Query_template(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_template(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Template(rctx, fc.Args["by"].(model.TemplateBy)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Template) + fc.Result = res + return ec.marshalNTemplate2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplate(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_template(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "tokenId": + return ec.fieldContext_Template_tokenId(ctx, field) + case "creator": + return ec.fieldContext_Template_creator(ctx, field) + case "asset": + return ec.fieldContext_Template_asset(ctx, field) + case "permissions": + return ec.fieldContext_Template_permissions(ctx, field) + case "cid": + return ec.fieldContext_Template_cid(ctx, field) + case "createdAt": + return ec.fieldContext_Template_createdAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Template", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_template_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_templates(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_templates(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Templates(rctx, fc.Args["first"].(*int), fc.Args["after"].(*string), fc.Args["last"].(*int), fc.Args["before"].(*string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.TemplateConnection) + fc.Result = res + return ec.marshalNTemplateConnection2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateConnection(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_templates(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "totalCount": + return ec.fieldContext_TemplateConnection_totalCount(ctx, field) + case "edges": + return ec.fieldContext_TemplateConnection_edges(ctx, field) + case "nodes": + return ec.fieldContext_TemplateConnection_nodes(ctx, field) + case "pageInfo": + return ec.fieldContext_TemplateConnection_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type TemplateConnection", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_templates_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_vehicle(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_vehicle(ctx, field) if err != nil { @@ -14217,8 +14523,8 @@ func (ec *executionContext) fieldContext_SyntheticDeviceEdge_node(_ context.Cont return fc, nil } -func (ec *executionContext) _UserRewards_totalTokens(ctx context.Context, field graphql.CollectedField, obj *model.UserRewards) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_UserRewards_totalTokens(ctx, field) +func (ec *executionContext) _Template_tokenId(ctx context.Context, field graphql.CollectedField, obj *model.Template) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Template_tokenId(ctx, field) if err != nil { return graphql.Null } @@ -14231,7 +14537,7 @@ func (ec *executionContext) _UserRewards_totalTokens(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return obj.TotalTokens, nil + return obj.TokenID, nil }) if err != nil { ec.Error(ctx, err) @@ -14243,26 +14549,26 @@ func (ec *executionContext) _UserRewards_totalTokens(ctx context.Context, field } return graphql.Null } - res := resTmp.(*decimal.Big) + res := resTmp.(*big.Int) fc.Result = res - return ec.marshalNBigDecimal2ᚖgithubᚗcomᚋericlagergrenᚋdecimalᚐBig(ctx, field.Selections, res) + return ec.marshalNBigInt2ᚖmathᚋbigᚐInt(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserRewards_totalTokens(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Template_tokenId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "UserRewards", + Object: "Template", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type BigDecimal does not have child fields") + return nil, errors.New("field of type BigInt does not have child fields") }, } return fc, nil } -func (ec *executionContext) _UserRewards_history(ctx context.Context, field graphql.CollectedField, obj *model.UserRewards) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_UserRewards_history(ctx, field) +func (ec *executionContext) _Template_creator(ctx context.Context, field graphql.CollectedField, obj *model.Template) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Template_creator(ctx, field) if err != nil { return graphql.Null } @@ -14275,7 +14581,7 @@ func (ec *executionContext) _UserRewards_history(ctx context.Context, field grap }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.UserRewards().History(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*string), fc.Args["last"].(*int), fc.Args["before"].(*string)) + return obj.Creator, nil }) if err != nil { ec.Error(ctx, err) @@ -14287,32 +14593,604 @@ func (ec *executionContext) _UserRewards_history(ctx context.Context, field grap } return graphql.Null } - res := resTmp.(*model.EarningsConnection) + res := resTmp.(common.Address) fc.Result = res - return ec.marshalNEarningsConnection2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐEarningsConnection(ctx, field.Selections, res) + return ec.marshalNAddress2githubᚗcomᚋethereumᚋgoᚑethereumᚋcommonᚐAddress(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_UserRewards_history(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Template_creator(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "UserRewards", + Object: "Template", Field: field, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "totalCount": - return ec.fieldContext_EarningsConnection_totalCount(ctx, field) - case "edges": - return ec.fieldContext_EarningsConnection_edges(ctx, field) - case "nodes": - return ec.fieldContext_EarningsConnection_nodes(ctx, field) - case "pageInfo": - return ec.fieldContext_EarningsConnection_pageInfo(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type EarningsConnection", field.Name) + return nil, errors.New("field of type Address does not have child fields") }, } - defer func() { + return fc, nil +} + +func (ec *executionContext) _Template_asset(ctx context.Context, field graphql.CollectedField, obj *model.Template) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Template_asset(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Asset, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(common.Address) + fc.Result = res + return ec.marshalNAddress2githubᚗcomᚋethereumᚋgoᚑethereumᚋcommonᚐAddress(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Template_asset(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Template", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Address does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Template_permissions(ctx context.Context, field graphql.CollectedField, obj *model.Template) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Template_permissions(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Permissions, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Template_permissions(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Template", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Template_cid(ctx context.Context, field graphql.CollectedField, obj *model.Template) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Template_cid(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Cid, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Template_cid(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Template", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Template_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.Template) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Template_createdAt(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(time.Time) + fc.Result = res + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Template_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Template", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _TemplateConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *model.TemplateConnection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TemplateConnection_totalCount(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.TotalCount, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TemplateConnection_totalCount(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TemplateConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _TemplateConnection_edges(ctx context.Context, field graphql.CollectedField, obj *model.TemplateConnection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TemplateConnection_edges(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Edges, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.TemplateEdge) + fc.Result = res + return ec.marshalNTemplateEdge2ᚕᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateEdgeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TemplateConnection_edges(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TemplateConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "node": + return ec.fieldContext_TemplateEdge_node(ctx, field) + case "cursor": + return ec.fieldContext_TemplateEdge_cursor(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type TemplateEdge", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _TemplateConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *model.TemplateConnection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TemplateConnection_nodes(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Nodes, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.Template) + fc.Result = res + return ec.marshalNTemplate2ᚕᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TemplateConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TemplateConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "tokenId": + return ec.fieldContext_Template_tokenId(ctx, field) + case "creator": + return ec.fieldContext_Template_creator(ctx, field) + case "asset": + return ec.fieldContext_Template_asset(ctx, field) + case "permissions": + return ec.fieldContext_Template_permissions(ctx, field) + case "cid": + return ec.fieldContext_Template_cid(ctx, field) + case "createdAt": + return ec.fieldContext_Template_createdAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Template", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _TemplateConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.TemplateConnection) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TemplateConnection_pageInfo(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.PageInfo, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.PageInfo) + fc.Result = res + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TemplateConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TemplateConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "startCursor": + return ec.fieldContext_PageInfo_startCursor(ctx, field) + case "endCursor": + return ec.fieldContext_PageInfo_endCursor(ctx, field) + case "hasPreviousPage": + return ec.fieldContext_PageInfo_hasPreviousPage(ctx, field) + case "hasNextPage": + return ec.fieldContext_PageInfo_hasNextPage(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _TemplateEdge_node(ctx context.Context, field graphql.CollectedField, obj *model.TemplateEdge) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TemplateEdge_node(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Node, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Template) + fc.Result = res + return ec.marshalNTemplate2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplate(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TemplateEdge_node(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TemplateEdge", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "tokenId": + return ec.fieldContext_Template_tokenId(ctx, field) + case "creator": + return ec.fieldContext_Template_creator(ctx, field) + case "asset": + return ec.fieldContext_Template_asset(ctx, field) + case "permissions": + return ec.fieldContext_Template_permissions(ctx, field) + case "cid": + return ec.fieldContext_Template_cid(ctx, field) + case "createdAt": + return ec.fieldContext_Template_createdAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Template", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _TemplateEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *model.TemplateEdge) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TemplateEdge_cursor(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Cursor, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TemplateEdge_cursor(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TemplateEdge", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _UserRewards_totalTokens(ctx context.Context, field graphql.CollectedField, obj *model.UserRewards) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_UserRewards_totalTokens(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.TotalTokens, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*decimal.Big) + fc.Result = res + return ec.marshalNBigDecimal2ᚖgithubᚗcomᚋericlagergrenᚋdecimalᚐBig(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_UserRewards_totalTokens(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "UserRewards", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type BigDecimal does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _UserRewards_history(ctx context.Context, field graphql.CollectedField, obj *model.UserRewards) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_UserRewards_history(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.UserRewards().History(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*string), fc.Args["last"].(*int), fc.Args["before"].(*string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.EarningsConnection) + fc.Result = res + return ec.marshalNEarningsConnection2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐEarningsConnection(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_UserRewards_history(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "UserRewards", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "totalCount": + return ec.fieldContext_EarningsConnection_totalCount(ctx, field) + case "edges": + return ec.fieldContext_EarningsConnection_edges(ctx, field) + case "nodes": + return ec.fieldContext_EarningsConnection_nodes(ctx, field) + case "pageInfo": + return ec.fieldContext_EarningsConnection_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type EarningsConnection", field.Name) + }, + } + defer func() { if r := recover(); r != nil { err = ec.Recover(ctx, r) ec.Error(ctx, err) @@ -18308,6 +19186,40 @@ func (ec *executionContext) unmarshalInputSyntheticDevicesFilter(ctx context.Con return it, nil } +func (ec *executionContext) unmarshalInputTemplateBy(ctx context.Context, obj any) (model.TemplateBy, error) { + var it model.TemplateBy + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"tokenId", "cid"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "tokenId": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("tokenId")) + data, err := ec.unmarshalOBigInt2ᚖmathᚋbigᚐInt(ctx, v) + if err != nil { + return it, err + } + it.TokenID = data + case "cid": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("cid")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.Cid = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputVehiclesFilter(ctx context.Context, obj any) (model.VehiclesFilter, error) { var it model.VehiclesFilter asMap := map[string]any{} @@ -20640,7 +21552,51 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_stakes(ctx, field) + res = ec._Query_stakes(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "syntheticDevice": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_syntheticDevice(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "syntheticDevices": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_syntheticDevices(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -20653,7 +21609,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "syntheticDevice": + case "template": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -20662,7 +21618,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_syntheticDevice(ctx, field) + res = ec._Query_template(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -20675,7 +21631,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "syntheticDevices": + case "templates": field := field innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { @@ -20684,7 +21640,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Query_syntheticDevices(ctx, field) + res = ec._Query_templates(ctx, field) if res == graphql.Null { atomic.AddUint32(&fs.Invalids, 1) } @@ -21759,6 +22715,168 @@ func (ec *executionContext) _SyntheticDeviceEdge(ctx context.Context, sel ast.Se return out } +var templateImplementors = []string{"Template"} + +func (ec *executionContext) _Template(ctx context.Context, sel ast.SelectionSet, obj *model.Template) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, templateImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Template") + case "tokenId": + out.Values[i] = ec._Template_tokenId(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "creator": + out.Values[i] = ec._Template_creator(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "asset": + out.Values[i] = ec._Template_asset(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "permissions": + out.Values[i] = ec._Template_permissions(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "cid": + out.Values[i] = ec._Template_cid(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "createdAt": + out.Values[i] = ec._Template_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var templateConnectionImplementors = []string{"TemplateConnection"} + +func (ec *executionContext) _TemplateConnection(ctx context.Context, sel ast.SelectionSet, obj *model.TemplateConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, templateConnectionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("TemplateConnection") + case "totalCount": + out.Values[i] = ec._TemplateConnection_totalCount(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "edges": + out.Values[i] = ec._TemplateConnection_edges(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "nodes": + out.Values[i] = ec._TemplateConnection_nodes(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._TemplateConnection_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var templateEdgeImplementors = []string{"TemplateEdge"} + +func (ec *executionContext) _TemplateEdge(ctx context.Context, sel ast.SelectionSet, obj *model.TemplateEdge) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, templateEdgeImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("TemplateEdge") + case "node": + out.Values[i] = ec._TemplateEdge_node(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "cursor": + out.Values[i] = ec._TemplateEdge_cursor(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var userRewardsImplementors = []string{"UserRewards"} func (ec *executionContext) _UserRewards(ctx context.Context, sel ast.SelectionSet, obj *model.UserRewards) graphql.Marshaler { @@ -24588,6 +25706,137 @@ func (ec *executionContext) marshalNSyntheticDeviceEdge2ᚖgithubᚗcomᚋDIMO return ec._SyntheticDeviceEdge(ctx, sel, v) } +func (ec *executionContext) marshalNTemplate2githubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplate(ctx context.Context, sel ast.SelectionSet, v model.Template) graphql.Marshaler { + return ec._Template(ctx, sel, &v) +} + +func (ec *executionContext) marshalNTemplate2ᚕᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Template) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNTemplate2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplate(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNTemplate2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplate(ctx context.Context, sel ast.SelectionSet, v *model.Template) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._Template(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNTemplateBy2githubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateBy(ctx context.Context, v any) (model.TemplateBy, error) { + res, err := ec.unmarshalInputTemplateBy(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNTemplateConnection2githubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateConnection(ctx context.Context, sel ast.SelectionSet, v model.TemplateConnection) graphql.Marshaler { + return ec._TemplateConnection(ctx, sel, &v) +} + +func (ec *executionContext) marshalNTemplateConnection2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateConnection(ctx context.Context, sel ast.SelectionSet, v *model.TemplateConnection) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._TemplateConnection(ctx, sel, v) +} + +func (ec *executionContext) marshalNTemplateEdge2ᚕᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateEdgeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.TemplateEdge) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNTemplateEdge2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateEdge(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNTemplateEdge2ᚖgithubᚗcomᚋDIMOᚑNetworkᚋidentityᚑapiᚋgraphᚋmodelᚐTemplateEdge(ctx context.Context, sel ast.SelectionSet, v *model.TemplateEdge) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._TemplateEdge(ctx, sel, v) +} + func (ec *executionContext) unmarshalNTime2timeᚐTime(ctx context.Context, v any) (time.Time, error) { res, err := graphql.UnmarshalTime(v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/graph/mock_template_test.go b/graph/mock_template_test.go new file mode 100644 index 00000000..c6e4d0d6 --- /dev/null +++ b/graph/mock_template_test.go @@ -0,0 +1,72 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/DIMO-Network/identity-api/graph (interfaces: TemplateRepository) +// +// Generated by this command: +// +// mockgen -destination=./mock_template_test.go -package=graph github.com/DIMO-Network/identity-api/graph TemplateRepository +// + +// Package graph is a generated GoMock package. +package graph + +import ( + context "context" + reflect "reflect" + + model "github.com/DIMO-Network/identity-api/graph/model" + gomock "go.uber.org/mock/gomock" +) + +// MockTemplateRepository is a mock of TemplateRepository interface. +type MockTemplateRepository struct { + ctrl *gomock.Controller + recorder *MockTemplateRepositoryMockRecorder + isgomock struct{} +} + +// MockTemplateRepositoryMockRecorder is the mock recorder for MockTemplateRepository. +type MockTemplateRepositoryMockRecorder struct { + mock *MockTemplateRepository +} + +// NewMockTemplateRepository creates a new mock instance. +func NewMockTemplateRepository(ctrl *gomock.Controller) *MockTemplateRepository { + mock := &MockTemplateRepository{ctrl: ctrl} + mock.recorder = &MockTemplateRepositoryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockTemplateRepository) EXPECT() *MockTemplateRepositoryMockRecorder { + return m.recorder +} + +// GetTemplate mocks base method. +func (m *MockTemplateRepository) GetTemplate(ctx context.Context, by model.ConnectionBy) (*model.Template, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTemplate", ctx, by) + ret0, _ := ret[0].(*model.Template) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTemplate indicates an expected call of GetTemplate. +func (mr *MockTemplateRepositoryMockRecorder) GetTemplate(ctx, by any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTemplate", reflect.TypeOf((*MockTemplateRepository)(nil).GetTemplate), ctx, by) +} + +// GetTemplates mocks base method. +func (m *MockTemplateRepository) GetTemplates(ctx context.Context, first *int, after *string, last *int, before *string) (*model.TemplateConnection, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTemplates", ctx, first, after, last, before) + ret0, _ := ret[0].(*model.TemplateConnection) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTemplates indicates an expected call of GetTemplates. +func (mr *MockTemplateRepositoryMockRecorder) GetTemplates(ctx, first, after, last, before any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTemplates", reflect.TypeOf((*MockTemplateRepository)(nil).GetTemplates), ctx, first, after, last, before) +} diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index da6a1544..8d7a12af 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -627,6 +627,36 @@ type SyntheticDevicesFilter struct { IntegrationID *int `json:"integrationId,omitempty"` } +type Template struct { + // The token id of the template as an NFT + TokenID *big.Int `json:"tokenId"` + // Creator of the template + Creator common.Address `json:"creator"` + Asset common.Address `json:"asset"` + // Hex string of permissions + Permissions string `json:"permissions"` + Cid string `json:"cid"` + // The block timestamp at which this template was created + CreatedAt time.Time `json:"createdAt"` +} + +type TemplateBy struct { + TokenID *big.Int `json:"tokenId,omitempty"` + Cid *string `json:"cid,omitempty"` +} + +type TemplateConnection struct { + TotalCount int `json:"totalCount"` + Edges []*TemplateEdge `json:"edges"` + Nodes []*Template `json:"nodes"` + PageInfo *PageInfo `json:"pageInfo"` +} + +type TemplateEdge struct { + Node *Template `json:"node"` + Cursor string `json:"cursor"` +} + type UserRewards struct { TotalTokens *decimal.Big `json:"totalTokens"` History *EarningsConnection `json:"history"` diff --git a/graph/resolver.go b/graph/resolver.go index c2cfac4a..8835834f 100644 --- a/graph/resolver.go +++ b/graph/resolver.go @@ -14,6 +14,7 @@ import ( "github.com/DIMO-Network/identity-api/internal/repositories/reward" "github.com/DIMO-Network/identity-api/internal/repositories/stake" "github.com/DIMO-Network/identity-api/internal/repositories/synthetic" + "github.com/DIMO-Network/identity-api/internal/repositories/template" "github.com/DIMO-Network/identity-api/internal/repositories/vehicle" "github.com/DIMO-Network/identity-api/internal/repositories/vehicleprivilege" "github.com/DIMO-Network/identity-api/internal/repositories/vehiclesacd" @@ -103,6 +104,14 @@ type ConnectionRepository interface { GetConnection(ctx context.Context, by model.ConnectionBy) (*model.Connection, error) } +// Template interface for mocking template.Repository. +// +//go:generate mockgen -destination=./mock_template_test.go -package=graph github.com/DIMO-Network/identity-api/graph TemplateRepository +type TemplateRepository interface { + GetTemplates(ctx context.Context, first *int, after *string, last *int, before *string) (*model.TemplateConnection, error) + GetTemplate(ctx context.Context, by model.TemplateBy) (*model.Template, error) +} + // Resolver holds the repositories for the graph resolvers. type Resolver struct { aftermarket AftermarketDeviceRepository @@ -117,6 +126,7 @@ type Resolver struct { developerLicense DeveloperLicenseRepository stake StakeRepository connection ConnectionRepository + template TemplateRepository } // NewResolver creates a new Resolver with allocated repositories. @@ -136,5 +146,6 @@ func NewResolver(baseRepo *base.Repository) *Resolver { developerLicense: developerlicense.New(baseRepo), stake: stake.New(baseRepo), connection: connection.New(baseRepo), + template: template.New(baseRepo), } } diff --git a/graph/schema/template.graphqls b/graph/schema/template.graphqls new file mode 100644 index 00000000..05c34bb0 --- /dev/null +++ b/graph/schema/template.graphqls @@ -0,0 +1,56 @@ +# Template Types + +type Template { + """ + The token id of the template as an NFT + """ + tokenId: BigInt! + """ + Creator of the template + """ + creator: Address! + asset: Address! + """ + Hex string of permissions + """ + permissions: String! + cid: String! + """ + The block timestamp at which this template was created + """ + createdAt: Time! +} + +extend type Query { + """ + Retrieve a particular template. + """ + template(by: TemplateBy!): Template! + + """ + List templates. Sorts by minting time, descending. + """ + templates( + first: Int, + after: String, + last: Int, + before: String + ): TemplateConnection! +} + +type TemplateConnection { + totalCount: Int! + edges: [TemplateEdge!]! + nodes: [Template!]! + pageInfo: PageInfo! +} + +type TemplateEdge { + node: Template! + cursor: String! +} + +input TemplateBy { + tokenId: BigInt + cid: String +} \ No newline at end of file diff --git a/graph/template.resolvers.go b/graph/template.resolvers.go new file mode 100644 index 00000000..5f5cfc9d --- /dev/null +++ b/graph/template.resolvers.go @@ -0,0 +1,21 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.78 + +import ( + "context" + + "github.com/DIMO-Network/identity-api/graph/model" +) + +// Template is the resolver for the template field. +func (r *queryResolver) Template(ctx context.Context, by model.TemplateBy) (*model.Template, error) { + return r.template.GetTemplate(ctx, by) +} + +// Templates is the resolver for the templates field. +func (r *queryResolver) Templates(ctx context.Context, first *int, after *string, last *int, before *string) (*model.TemplateConnection, error) { + return r.template.GetTemplates(ctx, first, after, last, before) +} diff --git a/internal/config/settings.go b/internal/config/settings.go index c380f4b7..8d93a6c7 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -28,4 +28,5 @@ type Settings struct { StakingAddr string `yaml:"STAKING_ADDR"` ConnectionAddr string `yaml:"CONNECTION_ADDR"` StorageNodeAddr string `yaml:"STORAGE_NODE_ADDR"` + TemplateAddr string `yaml:"TEMPLATE_ADDR"` } diff --git a/internal/helpers/helpers.go b/internal/helpers/helpers.go index 1c644530..e577a0e7 100644 --- a/internal/helpers/helpers.go +++ b/internal/helpers/helpers.go @@ -7,6 +7,8 @@ import ( "math/big" "strconv" + + "github.com/ethereum/go-ethereum/crypto" ) func CursorToID(cur string) (int, error) { @@ -58,3 +60,9 @@ func ConvertTokenIDToID(tokenID *big.Int) ([]byte, error) { return tb32, nil } + +// Equivalent of uint256(keccak256(bytes(input))) +func StringToUint256Hash(input string) *big.Int { + hash := crypto.Keccak256([]byte(input)) + return new(big.Int).SetBytes(hash) +} diff --git a/internal/repositories/storagenode/repo.go b/internal/repositories/storagenode/repo.go index ab102752..8230a943 100644 --- a/internal/repositories/storagenode/repo.go +++ b/internal/repositories/storagenode/repo.go @@ -16,7 +16,7 @@ type Repository struct { contractAddress common.Address } -// New creates a new connection repository. +// New creates a new storage node repository. func New(baseRepo *base.Repository) *Repository { return &Repository{ Repository: baseRepo, diff --git a/internal/repositories/template/template.go b/internal/repositories/template/template.go new file mode 100644 index 00000000..311080d4 --- /dev/null +++ b/internal/repositories/template/template.go @@ -0,0 +1,201 @@ +package template + +import ( + "context" + "database/sql" + "errors" + "fmt" + "math/big" + "slices" + "time" + + "github.com/DIMO-Network/identity-api/graph/model" + "github.com/DIMO-Network/identity-api/internal/helpers" + "github.com/DIMO-Network/identity-api/internal/repositories" + "github.com/DIMO-Network/identity-api/internal/repositories/base" + "github.com/DIMO-Network/identity-api/models" + "github.com/aarondl/sqlboiler/v4/queries/qm" + "github.com/ethereum/go-ethereum/common" + "github.com/vektah/gqlparser/v2/gqlerror" +) + +type Repository struct { + *base.Repository + chainID uint64 + contractAddress common.Address +} + +type Cursor struct { + CreatedAt time.Time + TokenID []byte +} + +var pageHelper = helpers.PaginationHelper[Cursor]{} + +// New creates a new template repository. +func New(db *base.Repository) *Repository { + return &Repository{ + Repository: db, + chainID: uint64(db.Settings.DIMORegistryChainID), + contractAddress: common.HexToAddress(db.Settings.ConnectionAddr), + } +} + +func (r *Repository) ToAPI(template *models.Template) *model.Template { + tokenID := new(big.Int).SetBytes(template.ID) + + return &model.Template{ + TokenID: tokenID, + Creator: common.BytesToAddress(template.Creator), + Asset: common.BytesToAddress(template.Asset), + Permissions: template.Permissions, + Cid: template.Cid, + CreatedAt: template.CreatedAt, + } +} + +func (r *Repository) GetTemplates(ctx context.Context, first *int, after *string, last *int, before *string) (*model.TemplateConnection, error) { + limit, err := helpers.ValidateFirstLast(first, last, base.MaxPageSize) + if err != nil { + return nil, err + } + + // None now, but making room. + var queryMods []qm.QueryMod + + totalCount, err := models.Templates().Count(ctx, r.PDB.DBS().Reader) + if err != nil { + return nil, err + } + + if after != nil { + afterCur, err := pageHelper.DecodeCursor(*after) + if err != nil { + return nil, err + } + + queryMods = append(queryMods, qm.Expr( + models.TemplateWhere.CreatedAt.EQ(afterCur.CreatedAt), + models.TemplateWhere.ID.GT(afterCur.TokenID), + qm.Or2(models.TemplateWhere.CreatedAt.LT(afterCur.CreatedAt)), + )) + } + + if before != nil { + beforeCur, err := pageHelper.DecodeCursor(*before) + if err != nil { + return nil, err + } + + queryMods = append(queryMods, qm.Expr( + models.TemplateWhere.CreatedAt.EQ(beforeCur.CreatedAt), + models.TemplateWhere.ID.LT(beforeCur.TokenID), + qm.Or2(models.TemplateWhere.CreatedAt.GT(beforeCur.CreatedAt)), + )) + } + + orderBy := fmt.Sprintf("%s DESC, %s ASC", models.TemplateColumns.CreatedAt, models.TemplateColumns.ID) + if last != nil { + orderBy = fmt.Sprintf("%s ASC, %s DESC", models.TemplateColumns.CreatedAt, models.TemplateColumns.ID) + } + + queryMods = append(queryMods, + // Use limit + 1 here to check if there's another page. + qm.Limit(limit+1), + qm.OrderBy(orderBy), + ) + + all, err := models.Templates(queryMods...).All(ctx, r.PDB.DBS().Reader) + if err != nil { + return nil, err + } + + // We assume that cursors come from real elements. + hasNext := before != nil + hasPrevious := after != nil + + if first != nil && len(all) == limit+1 { + hasNext = true + all = all[:limit] + } else if last != nil && len(all) == limit+1 { + hasPrevious = true + all = all[:limit] + } + + if last != nil { + slices.Reverse(all) + } + + nodes := make([]*model.Template, len(all)) + edges := make([]*model.TemplateEdge, len(all)) + + for i, dv := range all { + dlv := r.ToAPI(dv) + + nodes[i] = dlv + + crsr, err := pageHelper.EncodeCursor(Cursor{ + CreatedAt: dv.CreatedAt, + TokenID: dv.ID, + }) + if err != nil { + return nil, err + } + + edges[i] = &model.TemplateEdge{ + Node: dlv, + Cursor: crsr, + } + } + + var endCur, startCur *string + + if len(edges) != 0 { + startCur = &edges[0].Cursor + endCur = &edges[len(edges)-1].Cursor + } + + res := &model.TemplateConnection{ + Edges: edges, + Nodes: nodes, + PageInfo: &model.PageInfo{ + EndCursor: endCur, + HasNextPage: hasNext, + HasPreviousPage: hasPrevious, + StartCursor: startCur, + }, + TotalCount: int(totalCount), + } + + return res, nil +} + +func (r *Repository) GetTemplate(ctx context.Context, by model.TemplateBy) (*model.Template, error) { + if base.CountTrue(by.TokenID != nil, by.Cid != nil) != 1 { + return nil, gqlerror.Errorf("must specify exactly one of `TokenID` or `Cid`") + } + + var mod qm.QueryMod + + switch { + case by.TokenID != nil: + id, err := helpers.ConvertTokenIDToID(by.TokenID) + if err != nil { + return nil, err + } + + mod = models.TemplateWhere.ID.EQ(id) + case by.Cid != nil: + mod = models.TemplateWhere.Cid.EQ(*by.Cid) + } + + dl, err := models.Templates(mod).One(ctx, r.PDB.DBS().Reader) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, repositories.ErrNotFound + } + return nil, err + } + + return r.ToAPI(dl), nil +} diff --git a/internal/repositories/template/template_test.go b/internal/repositories/template/template_test.go new file mode 100644 index 00000000..1037d01b --- /dev/null +++ b/internal/repositories/template/template_test.go @@ -0,0 +1,130 @@ +package template + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/DIMO-Network/identity-api/graph/model" + "github.com/DIMO-Network/identity-api/internal/config" + "github.com/DIMO-Network/identity-api/internal/helpers" + "github.com/DIMO-Network/identity-api/internal/repositories/base" + "github.com/DIMO-Network/identity-api/models" + "github.com/DIMO-Network/shared/pkg/db" + "github.com/aarondl/sqlboiler/v4/boil" + "github.com/ethereum/go-ethereum/common" + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" +) + +const migrationsDir = "../../../migrations" + +func TestGetTemplate(t *testing.T) { + ctx := context.Background() + pdb, _ := helpers.StartContainerDatabase(ctx, t, migrationsDir) + + tokenIds, creators, assets, permissions, cids := createTemplates(t, ctx, pdb) + + logger := zerolog.Nop() + controller := New(base.NewRepository(pdb, config.Settings{}, &logger)) + for i := range 3 { + res, err := controller.GetTemplate(ctx, model.TemplateBy{TokenID: tokenIds[i]}) + assert.NoError(t, err) + assert.Equal(t, res.TokenID, tokenIds[i]) + assert.Equal(t, res.Creator, creators[i]) + assert.Equal(t, res.Asset, assets[i]) + assert.Equal(t, res.Permissions, permissions) + assert.Equal(t, res.Cid, cids[i]) + + res, err = controller.GetTemplate(ctx, model.TemplateBy{Cid: &cids[i]}) + assert.NoError(t, err) + assert.Equal(t, res.TokenID, tokenIds[i]) + assert.Equal(t, res.Creator, creators[i]) + assert.Equal(t, res.Asset, assets[i]) + assert.Equal(t, res.Permissions, permissions) + assert.Equal(t, res.Cid, cids[i]) + } +} + +func TestGetTemplates(t *testing.T) { + ctx := context.Background() + pdb, _ := helpers.StartContainerDatabase(ctx, t, migrationsDir) + + tokenIds, creators, assets, permissions, cids := createTemplates(t, ctx, pdb) + + logger := zerolog.Nop() + controller := New(base.NewRepository(pdb, config.Settings{}, &logger)) + + first := 100 + res, err := controller.GetTemplates(ctx, &first, nil, nil, nil) + assert.NoError(t, err) + + totalTemplates := len(tokenIds) + + assert.Len(t, res.Nodes, totalTemplates) + assert.Equal(t, res.TotalCount, totalTemplates) + assert.Equal(t, res.PageInfo.HasNextPage, false) + assert.Equal(t, res.PageInfo.HasPreviousPage, false) + assert.Len(t, res.Edges, totalTemplates) + for i := range totalTemplates { + // GetTemplates returns descending order + reverseIndex := totalTemplates - 1 - i + + assert.Equal(t, res.Nodes[i].TokenID, tokenIds[reverseIndex]) + assert.Equal(t, res.Nodes[i].Creator, creators[reverseIndex]) + assert.Equal(t, res.Nodes[i].Asset, assets[reverseIndex]) + assert.Equal(t, res.Nodes[i].Permissions, permissions) + assert.Equal(t, res.Nodes[i].Cid, cids[reverseIndex]) + + assert.Equal(t, res.Edges[i].Node.TokenID, tokenIds[reverseIndex]) + assert.Equal(t, res.Edges[i].Node.Creator, creators[reverseIndex]) + assert.Equal(t, res.Edges[i].Node.Asset, assets[reverseIndex]) + assert.Equal(t, res.Edges[i].Node.Permissions, permissions) + assert.Equal(t, res.Edges[i].Node.Cid, cids[reverseIndex]) + } +} + +func createTemplates(t *testing.T, ctx context.Context, pdb db.Store) ([]*big.Int, []common.Address, []common.Address, string, []string) { + size := 3 + + tokenIds := make([]*big.Int, size) + creators := []common.Address{ + common.HexToAddress("1111111111111111111111111111111111111111"), + common.HexToAddress("2222222222222222222222222222222222222222"), + common.HexToAddress("3333333333333333333333333333333333333333"), + } + assets := []common.Address{ + common.HexToAddress("5555555555555555555555555555555555555555"), + common.HexToAddress("6666666666666666666666666666666666666666"), + common.HexToAddress("7777777777777777777777777777777777777777"), + } + permissions := new(big.Int).SetUint64(3888).Text(2) // 11 11 00 11 00 00 + cids := []string{ + "QmTkDGhbhABxgHde1Go2vcarW3NxQYkaSHFBYCdiUo79d9", + "QmdYe42GrGU9TCtN4rq1K1bsa5naaiZUhBV93PrF4JtYaE", + "QmYoWDRp6yXc53rZBaWrz56XEaDm7heoDNx6s5ttESiXHX", + } + + for i := range size { + tokenId := helpers.StringToUint256Hash(cids[i]) + tokenIds[i] = tokenId + + tokenIdBytes, err := helpers.ConvertTokenIDToID(tokenId) + assert.NoError(t, err) + + m := models.Template{ + ID: tokenIdBytes, + Creator: creators[i].Bytes(), + Asset: assets[i].Bytes(), + Permissions: permissions, + CreatedAt: time.Now(), + Cid: cids[i], + } + + err = m.Insert(ctx, pdb.DBS().Writer, boil.Infer()) + assert.NoError(t, err) + } + + return tokenIds, creators, assets, permissions, cids +} diff --git a/internal/services/contract_events_consumer_test.go b/internal/services/contract_events_consumer_test.go index 087a2bab..b1518995 100644 --- a/internal/services/contract_events_consumer_test.go +++ b/internal/services/contract_events_consumer_test.go @@ -29,6 +29,7 @@ const ( aftermarketDeviceAddr = "0xcf9af64522162da85164a714c23a7705e6e466b3" syntheticDeviceAddr = "0x85226A67FF1b3Ec6cb033162f7df5038a6C3bAB2" rewardContractAddr = "0x375885164266d48C48abbbb439Be98864Ae62bBE" + templateAddr = "0xf369532e2144034E34Be08DBaA3A589C87dBbE3A" ) var ( @@ -1685,3 +1686,54 @@ func TestHandleAftermarketDeviceAddressResetEvent(t *testing.T) { assert.Equal(t, eventData.AftermarketDeviceAddress, common.BytesToAddress(updatedAmd.Address)) } + +func TestHandleTemplateCreatedEvent(t *testing.T) { + ctx := context.Background() + logger := zerolog.New(os.Stdout).With().Timestamp().Str("app", helpers.DBSettings.Name).Logger() + contractEventData.EventName = "TemplateCreated" + contractEventData.Contract = common.HexToAddress(templateAddr) + + _, wallet, err := helpers.GenerateWallet() + assert.NoError(t, err) + + // uint256(keccak256(bytes("QmYA2fn8cMbVWo4v95RwcwJVyQsNtnEwHerfWR8UNtEwoE"))) + templateIdStr := "39432737238797479986393736422353506685818102154178527542856781838379111614015" + templateId := new(big.Int) + templateId.SetString(templateIdStr, 10) + + var templateCreatedData = TemplateCreatedData{ + TemplateId: templateId, + Creator: *wallet, + Asset: common.HexToAddress("0xc6e7DF5E7b4f2A278906862b61205850344D4e7d"), + Permissions: big.NewInt(3888), // 11 11 00 11 00 00 + Cid: "QmYA2fn8cMbVWo4v95RwcwJVyQsNtnEwHerfWR8UNtEwoE", + } + + settings := config.Settings{ + DIMORegistryAddr: "0x4de1bcf2b7e851e31216fc07989caa902a604784", // Different from template address + DIMORegistryChainID: contractEventData.ChainID, + TemplateAddr: templateAddr, + } + + pdb, _ := helpers.StartContainerDatabase(ctx, t, migrationsDirRelPath) + contractEventConsumer := NewContractsEventsConsumer(pdb, &logger, &settings) + e := prepareEvent(t, contractEventData, templateCreatedData) + + err = contractEventConsumer.Process(ctx, &e) + assert.NoError(t, err) + + expectedTemplateID, err := helpers.ConvertTokenIDToID(templateCreatedData.TemplateId) + assert.NoError(t, err) + + template, err := models.Templates( + models.TemplateWhere.ID.EQ(expectedTemplateID), + ).One(ctx, pdb.DBS().Reader) + assert.NoError(t, err) + + assert.Equal(t, expectedTemplateID, template.ID) + assert.Equal(t, templateCreatedData.Creator.Bytes(), template.Creator) + assert.Equal(t, templateCreatedData.Asset.Bytes(), template.Asset) + assert.Equal(t, templateCreatedData.Permissions.Text(2), template.Permissions) + assert.Equal(t, templateCreatedData.Cid, template.Cid) + assert.Equal(t, contractEventData.Block.Time.UTC(), template.CreatedAt) +} diff --git a/internal/services/contracts_events_consumer.go b/internal/services/contracts_events_consumer.go index bd6c7c60..e7053a4a 100644 --- a/internal/services/contracts_events_consumer.go +++ b/internal/services/contracts_events_consumer.go @@ -50,6 +50,9 @@ const ( // SACD. PermissionsSetEvent EventName = "PermissionsSet" + // Template. + TemplateCreatedEvent EventName = "TemplateCreated" + // Manufacturers. ManufacturerNodeMinted EventName = "ManufacturerNodeMinted" DeviceDefinitionTableCreated EventName = "DeviceDefinitionTableCreated" @@ -137,6 +140,7 @@ func (c *ContractsEventsConsumer) Process(ctx context.Context, event *cloudevent connAddr := common.HexToAddress(c.settings.ConnectionAddr) manufacturerAddr := common.HexToAddress(c.settings.ManufacturerNFTAddr) storageNodeAddr := common.HexToAddress(c.settings.StorageNodeAddr) + templateAddr := common.HexToAddress(c.settings.TemplateAddr) var data cmodels.ContractEventData if err := json.Unmarshal(event.Data, &data); err != nil { @@ -200,6 +204,11 @@ func (c *ContractsEventsConsumer) Process(ctx context.Context, event *cloudevent case PermissionsSetEvent: return c.handlePermissionsSetEvent(ctx, &data) } + case templateAddr: + switch eventName { + case TemplateCreatedEvent: + return c.handleTemplateCreatedEvent(ctx, &data) + } case aftermarketDeviceAddr: switch eventName { case Transfer: @@ -630,6 +639,38 @@ func (c *ContractsEventsConsumer) handlePermissionsSetEvent(ctx context.Context, return nil } +func (c *ContractsEventsConsumer) handleTemplateCreatedEvent(ctx context.Context, e *cmodels.ContractEventData) error { + logger := c.log.With().Str("EventName", TemplateCreatedEvent.String()).Logger() + + var args TemplateCreatedData + if err := json.Unmarshal(e.Arguments, &args); err != nil { + return fmt.Errorf("error unmarshaling TemplateCreated inputs: %w", err) + } + + // This is the result of uint256(keccak256(bytes(cid))). + templateID, err := helpers.ConvertTokenIDToID(args.TemplateId) + if err != nil { + return err + } + + template := models.Template{ + ID: templateID, + Creator: args.Creator.Bytes(), + Asset: args.Asset.Bytes(), + Permissions: args.Permissions.Text(2), + Cid: args.Cid, + CreatedAt: e.Block.Time, + } + + logger.Info(). + Int64("templateId", args.TemplateId.Int64()). + Str("creator", args.Creator.Hex()). + Str("asset", args.Asset.Hex()). + Msg("Template created successfully.") + + return template.Insert(ctx, c.dbs.DBS().Writer, boil.Infer()) +} + func (c *ContractsEventsConsumer) handlePrivilegeSetEvent(ctx context.Context, e *cmodels.ContractEventData) error { logger := c.log.With().Str("EventName", PrivilegeSet.String()).Logger() diff --git a/internal/services/event_data_models.go b/internal/services/event_data_models.go index 65d992bb..7ecad70d 100644 --- a/internal/services/event_data_models.go +++ b/internal/services/event_data_models.go @@ -161,6 +161,14 @@ type PermissionsSetData struct { Source string } +type TemplateCreatedData struct { + TemplateId *big.Int + Creator common.Address + Asset common.Address + Permissions *big.Int + Cid string +} + type VehicleStorageNodeIdSetData struct { VehicleId *big.Int StorageNodeId *big.Int diff --git a/migrations/00046_create_template.sql b/migrations/00046_create_template.sql new file mode 100644 index 00000000..cb872933 --- /dev/null +++ b/migrations/00046_create_template.sql @@ -0,0 +1,18 @@ +-- +goose Up +-- +goose StatementBegin + +-- Create templates table for the new TemplateCreated event +CREATE TABLE templates ( + id bytea PRIMARY KEY CHECK (length(id) = 32), -- This is the keccak256 of cid. + creator bytea NOT NULL CHECK (length(creator) = 20), + asset bytea NOT NULL CHECK (length(asset) = 20), + permissions bit varying(256) NOT NULL, + cid TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL +); +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +DROP TABLE templates; +-- +goose StatementEnd diff --git a/models/boil_table_names.go b/models/boil_table_names.go index 73539cfd..b0f8d1eb 100644 --- a/models/boil_table_names.go +++ b/models/boil_table_names.go @@ -16,6 +16,7 @@ var TableNames = struct { Stakes string StorageNodes string SyntheticDevices string + Templates string VehicleSacds string Vehicles string }{ @@ -31,6 +32,7 @@ var TableNames = struct { Stakes: "stakes", StorageNodes: "storage_nodes", SyntheticDevices: "synthetic_devices", + Templates: "templates", VehicleSacds: "vehicle_sacds", Vehicles: "vehicles", } diff --git a/models/templates.go b/models/templates.go new file mode 100644 index 00000000..daf79749 --- /dev/null +++ b/models/templates.go @@ -0,0 +1,1244 @@ +// Code generated by SQLBoiler 4.19.5 (https://github.com/aarondl/sqlboiler). DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. + +package models + +import ( + "context" + "database/sql" + "fmt" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/aarondl/sqlboiler/v4/boil" + "github.com/aarondl/sqlboiler/v4/queries" + "github.com/aarondl/sqlboiler/v4/queries/qm" + "github.com/aarondl/sqlboiler/v4/queries/qmhelper" + "github.com/aarondl/strmangle" + "github.com/friendsofgo/errors" +) + +// Template is an object representing the database table. +type Template struct { + ID []byte `boil:"id" json:"id" toml:"id" yaml:"id"` + Creator []byte `boil:"creator" json:"creator" toml:"creator" yaml:"creator"` + Asset []byte `boil:"asset" json:"asset" toml:"asset" yaml:"asset"` + Permissions string `boil:"permissions" json:"permissions" toml:"permissions" yaml:"permissions"` + Cid string `boil:"cid" json:"cid" toml:"cid" yaml:"cid"` + CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` + + R *templateR `boil:"-" json:"-" toml:"-" yaml:"-"` + L templateL `boil:"-" json:"-" toml:"-" yaml:"-"` +} + +var TemplateColumns = struct { + ID string + Creator string + Asset string + Permissions string + Cid string + CreatedAt string +}{ + ID: "id", + Creator: "creator", + Asset: "asset", + Permissions: "permissions", + Cid: "cid", + CreatedAt: "created_at", +} + +var TemplateTableColumns = struct { + ID string + Creator string + Asset string + Permissions string + Cid string + CreatedAt string +}{ + ID: "templates.id", + Creator: "templates.creator", + Asset: "templates.asset", + Permissions: "templates.permissions", + Cid: "templates.cid", + CreatedAt: "templates.created_at", +} + +// Generated where + +var TemplateWhere = struct { + ID whereHelper__byte + Creator whereHelper__byte + Asset whereHelper__byte + Permissions whereHelperstring + Cid whereHelperstring + CreatedAt whereHelpertime_Time +}{ + ID: whereHelper__byte{field: "\"identity_api\".\"templates\".\"id\""}, + Creator: whereHelper__byte{field: "\"identity_api\".\"templates\".\"creator\""}, + Asset: whereHelper__byte{field: "\"identity_api\".\"templates\".\"asset\""}, + Permissions: whereHelperstring{field: "\"identity_api\".\"templates\".\"permissions\""}, + Cid: whereHelperstring{field: "\"identity_api\".\"templates\".\"cid\""}, + CreatedAt: whereHelpertime_Time{field: "\"identity_api\".\"templates\".\"created_at\""}, +} + +// TemplateRels is where relationship names are stored. +var TemplateRels = struct { + VehicleSacds string +}{ + VehicleSacds: "VehicleSacds", +} + +// templateR is where relationships are stored. +type templateR struct { + VehicleSacds VehicleSacdSlice `boil:"VehicleSacds" json:"VehicleSacds" toml:"VehicleSacds" yaml:"VehicleSacds"` +} + +// NewStruct creates a new relationship struct +func (*templateR) NewStruct() *templateR { + return &templateR{} +} + +func (o *Template) GetVehicleSacds() VehicleSacdSlice { + if o == nil { + return nil + } + + return o.R.GetVehicleSacds() +} + +func (r *templateR) GetVehicleSacds() VehicleSacdSlice { + if r == nil { + return nil + } + + return r.VehicleSacds +} + +// templateL is where Load methods for each relationship are stored. +type templateL struct{} + +var ( + templateAllColumns = []string{"id", "creator", "asset", "permissions", "cid", "created_at"} + templateColumnsWithoutDefault = []string{"id", "creator", "asset", "permissions", "cid", "created_at"} + templateColumnsWithDefault = []string{} + templatePrimaryKeyColumns = []string{"id"} + templateGeneratedColumns = []string{} +) + +type ( + // TemplateSlice is an alias for a slice of pointers to Template. + // This should almost always be used instead of []Template. + TemplateSlice []*Template + // TemplateHook is the signature for custom Template hook methods + TemplateHook func(context.Context, boil.ContextExecutor, *Template) error + + templateQuery struct { + *queries.Query + } +) + +// Cache for insert, update and upsert +var ( + templateType = reflect.TypeOf(&Template{}) + templateMapping = queries.MakeStructMapping(templateType) + templatePrimaryKeyMapping, _ = queries.BindMapping(templateType, templateMapping, templatePrimaryKeyColumns) + templateInsertCacheMut sync.RWMutex + templateInsertCache = make(map[string]insertCache) + templateUpdateCacheMut sync.RWMutex + templateUpdateCache = make(map[string]updateCache) + templateUpsertCacheMut sync.RWMutex + templateUpsertCache = make(map[string]insertCache) +) + +var ( + // Force time package dependency for automated UpdatedAt/CreatedAt. + _ = time.Second + // Force qmhelper dependency for where clause generation (which doesn't + // always happen) + _ = qmhelper.Where +) + +var templateAfterSelectMu sync.Mutex +var templateAfterSelectHooks []TemplateHook + +var templateBeforeInsertMu sync.Mutex +var templateBeforeInsertHooks []TemplateHook +var templateAfterInsertMu sync.Mutex +var templateAfterInsertHooks []TemplateHook + +var templateBeforeUpdateMu sync.Mutex +var templateBeforeUpdateHooks []TemplateHook +var templateAfterUpdateMu sync.Mutex +var templateAfterUpdateHooks []TemplateHook + +var templateBeforeDeleteMu sync.Mutex +var templateBeforeDeleteHooks []TemplateHook +var templateAfterDeleteMu sync.Mutex +var templateAfterDeleteHooks []TemplateHook + +var templateBeforeUpsertMu sync.Mutex +var templateBeforeUpsertHooks []TemplateHook +var templateAfterUpsertMu sync.Mutex +var templateAfterUpsertHooks []TemplateHook + +// doAfterSelectHooks executes all "after Select" hooks. +func (o *Template) doAfterSelectHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range templateAfterSelectHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeInsertHooks executes all "before insert" hooks. +func (o *Template) doBeforeInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range templateBeforeInsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterInsertHooks executes all "after Insert" hooks. +func (o *Template) doAfterInsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range templateAfterInsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeUpdateHooks executes all "before Update" hooks. +func (o *Template) doBeforeUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range templateBeforeUpdateHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterUpdateHooks executes all "after Update" hooks. +func (o *Template) doAfterUpdateHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range templateAfterUpdateHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeDeleteHooks executes all "before Delete" hooks. +func (o *Template) doBeforeDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range templateBeforeDeleteHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterDeleteHooks executes all "after Delete" hooks. +func (o *Template) doAfterDeleteHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range templateAfterDeleteHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doBeforeUpsertHooks executes all "before Upsert" hooks. +func (o *Template) doBeforeUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range templateBeforeUpsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// doAfterUpsertHooks executes all "after Upsert" hooks. +func (o *Template) doAfterUpsertHooks(ctx context.Context, exec boil.ContextExecutor) (err error) { + if boil.HooksAreSkipped(ctx) { + return nil + } + + for _, hook := range templateAfterUpsertHooks { + if err := hook(ctx, exec, o); err != nil { + return err + } + } + + return nil +} + +// AddTemplateHook registers your hook function for all future operations. +func AddTemplateHook(hookPoint boil.HookPoint, templateHook TemplateHook) { + switch hookPoint { + case boil.AfterSelectHook: + templateAfterSelectMu.Lock() + templateAfterSelectHooks = append(templateAfterSelectHooks, templateHook) + templateAfterSelectMu.Unlock() + case boil.BeforeInsertHook: + templateBeforeInsertMu.Lock() + templateBeforeInsertHooks = append(templateBeforeInsertHooks, templateHook) + templateBeforeInsertMu.Unlock() + case boil.AfterInsertHook: + templateAfterInsertMu.Lock() + templateAfterInsertHooks = append(templateAfterInsertHooks, templateHook) + templateAfterInsertMu.Unlock() + case boil.BeforeUpdateHook: + templateBeforeUpdateMu.Lock() + templateBeforeUpdateHooks = append(templateBeforeUpdateHooks, templateHook) + templateBeforeUpdateMu.Unlock() + case boil.AfterUpdateHook: + templateAfterUpdateMu.Lock() + templateAfterUpdateHooks = append(templateAfterUpdateHooks, templateHook) + templateAfterUpdateMu.Unlock() + case boil.BeforeDeleteHook: + templateBeforeDeleteMu.Lock() + templateBeforeDeleteHooks = append(templateBeforeDeleteHooks, templateHook) + templateBeforeDeleteMu.Unlock() + case boil.AfterDeleteHook: + templateAfterDeleteMu.Lock() + templateAfterDeleteHooks = append(templateAfterDeleteHooks, templateHook) + templateAfterDeleteMu.Unlock() + case boil.BeforeUpsertHook: + templateBeforeUpsertMu.Lock() + templateBeforeUpsertHooks = append(templateBeforeUpsertHooks, templateHook) + templateBeforeUpsertMu.Unlock() + case boil.AfterUpsertHook: + templateAfterUpsertMu.Lock() + templateAfterUpsertHooks = append(templateAfterUpsertHooks, templateHook) + templateAfterUpsertMu.Unlock() + } +} + +// One returns a single template record from the query. +func (q templateQuery) One(ctx context.Context, exec boil.ContextExecutor) (*Template, error) { + o := &Template{} + + queries.SetLimit(q.Query, 1) + + err := q.Bind(ctx, exec, o) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "models: failed to execute a one query for templates") + } + + if err := o.doAfterSelectHooks(ctx, exec); err != nil { + return o, err + } + + return o, nil +} + +// All returns all Template records from the query. +func (q templateQuery) All(ctx context.Context, exec boil.ContextExecutor) (TemplateSlice, error) { + var o []*Template + + err := q.Bind(ctx, exec, &o) + if err != nil { + return nil, errors.Wrap(err, "models: failed to assign all query results to Template slice") + } + + if len(templateAfterSelectHooks) != 0 { + for _, obj := range o { + if err := obj.doAfterSelectHooks(ctx, exec); err != nil { + return o, err + } + } + } + + return o, nil +} + +// Count returns the count of all Template records in the query. +func (q templateQuery) Count(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + + err := q.Query.QueryRowContext(ctx, exec).Scan(&count) + if err != nil { + return 0, errors.Wrap(err, "models: failed to count templates rows") + } + + return count, nil +} + +// Exists checks if the row exists in the table. +func (q templateQuery) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, error) { + var count int64 + + queries.SetSelect(q.Query, nil) + queries.SetCount(q.Query) + queries.SetLimit(q.Query, 1) + + err := q.Query.QueryRowContext(ctx, exec).Scan(&count) + if err != nil { + return false, errors.Wrap(err, "models: failed to check if templates exists") + } + + return count > 0, nil +} + +// VehicleSacds retrieves all the vehicle_sacd's VehicleSacds with an executor. +func (o *Template) VehicleSacds(mods ...qm.QueryMod) vehicleSacdQuery { + var queryMods []qm.QueryMod + if len(mods) != 0 { + queryMods = append(queryMods, mods...) + } + + queryMods = append(queryMods, + qm.Where("\"identity_api\".\"vehicle_sacds\".\"template_id\"=?", o.ID), + ) + + return VehicleSacds(queryMods...) +} + +// LoadVehicleSacds allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for a 1-M or N-M relationship. +func (templateL) LoadVehicleSacds(ctx context.Context, e boil.ContextExecutor, singular bool, maybeTemplate interface{}, mods queries.Applicator) error { + var slice []*Template + var object *Template + + if singular { + var ok bool + object, ok = maybeTemplate.(*Template) + if !ok { + object = new(Template) + ok = queries.SetFromEmbeddedStruct(&object, &maybeTemplate) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybeTemplate)) + } + } + } else { + s, ok := maybeTemplate.(*[]*Template) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybeTemplate) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybeTemplate)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &templateR{} + } + args[object.ID] = struct{}{} + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &templateR{} + } + args[obj.ID] = struct{}{} + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`identity_api.vehicle_sacds`), + qm.WhereIn(`identity_api.vehicle_sacds.template_id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load vehicle_sacds") + } + + var resultSlice []*VehicleSacd + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice vehicle_sacds") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results in eager load on vehicle_sacds") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for vehicle_sacds") + } + + if len(vehicleSacdAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + if singular { + object.R.VehicleSacds = resultSlice + for _, foreign := range resultSlice { + if foreign.R == nil { + foreign.R = &vehicleSacdR{} + } + foreign.R.Template = object + } + return nil + } + + for _, foreign := range resultSlice { + for _, local := range slice { + if queries.Equal(local.ID, foreign.TemplateID) { + local.R.VehicleSacds = append(local.R.VehicleSacds, foreign) + if foreign.R == nil { + foreign.R = &vehicleSacdR{} + } + foreign.R.Template = local + break + } + } + } + + return nil +} + +// AddVehicleSacds adds the given related objects to the existing relationships +// of the template, optionally inserting them as new records. +// Appends related to o.R.VehicleSacds. +// Sets related.R.Template appropriately. +func (o *Template) AddVehicleSacds(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*VehicleSacd) error { + var err error + for _, rel := range related { + if insert { + queries.Assign(&rel.TemplateID, o.ID) + if err = rel.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } else { + updateQuery := fmt.Sprintf( + "UPDATE \"identity_api\".\"vehicle_sacds\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"template_id"}), + strmangle.WhereClause("\"", "\"", 2, vehicleSacdPrimaryKeyColumns), + ) + values := []interface{}{o.ID, rel.VehicleID, rel.Grantee} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update foreign table") + } + + queries.Assign(&rel.TemplateID, o.ID) + } + } + + if o.R == nil { + o.R = &templateR{ + VehicleSacds: related, + } + } else { + o.R.VehicleSacds = append(o.R.VehicleSacds, related...) + } + + for _, rel := range related { + if rel.R == nil { + rel.R = &vehicleSacdR{ + Template: o, + } + } else { + rel.R.Template = o + } + } + return nil +} + +// SetVehicleSacds removes all previously related items of the +// template replacing them completely with the passed +// in related items, optionally inserting them as new records. +// Sets o.R.Template's VehicleSacds accordingly. +// Replaces o.R.VehicleSacds with related. +// Sets related.R.Template's VehicleSacds accordingly. +func (o *Template) SetVehicleSacds(ctx context.Context, exec boil.ContextExecutor, insert bool, related ...*VehicleSacd) error { + query := "update \"identity_api\".\"vehicle_sacds\" set \"template_id\" = null where \"template_id\" = $1" + values := []interface{}{o.ID} + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, query) + fmt.Fprintln(writer, values) + } + _, err := exec.ExecContext(ctx, query, values...) + if err != nil { + return errors.Wrap(err, "failed to remove relationships before set") + } + + if o.R != nil { + for _, rel := range o.R.VehicleSacds { + queries.SetScanner(&rel.TemplateID, nil) + if rel.R == nil { + continue + } + + rel.R.Template = nil + } + o.R.VehicleSacds = nil + } + + return o.AddVehicleSacds(ctx, exec, insert, related...) +} + +// RemoveVehicleSacds relationships from objects passed in. +// Removes related items from R.VehicleSacds (uses pointer comparison, removal does not keep order) +// Sets related.R.Template. +func (o *Template) RemoveVehicleSacds(ctx context.Context, exec boil.ContextExecutor, related ...*VehicleSacd) error { + if len(related) == 0 { + return nil + } + + var err error + for _, rel := range related { + queries.SetScanner(&rel.TemplateID, nil) + if rel.R != nil { + rel.R.Template = nil + } + if _, err = rel.Update(ctx, exec, boil.Whitelist("template_id")); err != nil { + return err + } + } + if o.R == nil { + return nil + } + + for _, rel := range related { + for i, ri := range o.R.VehicleSacds { + if rel != ri { + continue + } + + ln := len(o.R.VehicleSacds) + if ln > 1 && i < ln-1 { + o.R.VehicleSacds[i] = o.R.VehicleSacds[ln-1] + } + o.R.VehicleSacds = o.R.VehicleSacds[:ln-1] + break + } + } + + return nil +} + +// Templates retrieves all the records using an executor. +func Templates(mods ...qm.QueryMod) templateQuery { + mods = append(mods, qm.From("\"identity_api\".\"templates\"")) + q := NewQuery(mods...) + if len(queries.GetSelect(q)) == 0 { + queries.SetSelect(q, []string{"\"identity_api\".\"templates\".*"}) + } + + return templateQuery{q} +} + +// FindTemplate retrieves a single record by ID with an executor. +// If selectCols is empty Find will return all columns. +func FindTemplate(ctx context.Context, exec boil.ContextExecutor, iD []byte, selectCols ...string) (*Template, error) { + templateObj := &Template{} + + sel := "*" + if len(selectCols) > 0 { + sel = strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, selectCols), ",") + } + query := fmt.Sprintf( + "select %s from \"identity_api\".\"templates\" where \"id\"=$1", sel, + ) + + q := queries.Raw(query, iD) + + err := q.Bind(ctx, exec, templateObj) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, sql.ErrNoRows + } + return nil, errors.Wrap(err, "models: unable to select from templates") + } + + if err = templateObj.doAfterSelectHooks(ctx, exec); err != nil { + return templateObj, err + } + + return templateObj, nil +} + +// Insert a single record using an executor. +// See boil.Columns.InsertColumnSet documentation to understand column list inference for inserts. +func (o *Template) Insert(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) error { + if o == nil { + return errors.New("models: no templates provided for insertion") + } + + var err error + if !boil.TimestampsAreSkipped(ctx) { + currTime := time.Now().In(boil.GetLocation()) + + if o.CreatedAt.IsZero() { + o.CreatedAt = currTime + } + } + + if err := o.doBeforeInsertHooks(ctx, exec); err != nil { + return err + } + + nzDefaults := queries.NonZeroDefaultSet(templateColumnsWithDefault, o) + + key := makeCacheKey(columns, nzDefaults) + templateInsertCacheMut.RLock() + cache, cached := templateInsertCache[key] + templateInsertCacheMut.RUnlock() + + if !cached { + wl, returnColumns := columns.InsertColumnSet( + templateAllColumns, + templateColumnsWithDefault, + templateColumnsWithoutDefault, + nzDefaults, + ) + + cache.valueMapping, err = queries.BindMapping(templateType, templateMapping, wl) + if err != nil { + return err + } + cache.retMapping, err = queries.BindMapping(templateType, templateMapping, returnColumns) + if err != nil { + return err + } + if len(wl) != 0 { + cache.query = fmt.Sprintf("INSERT INTO \"identity_api\".\"templates\" (\"%s\") %%sVALUES (%s)%%s", strings.Join(wl, "\",\""), strmangle.Placeholders(dialect.UseIndexPlaceholders, len(wl), 1, 1)) + } else { + cache.query = "INSERT INTO \"identity_api\".\"templates\" %sDEFAULT VALUES%s" + } + + var queryOutput, queryReturning string + + if len(cache.retMapping) != 0 { + queryReturning = fmt.Sprintf(" RETURNING \"%s\"", strings.Join(returnColumns, "\",\"")) + } + + cache.query = fmt.Sprintf(cache.query, queryOutput, queryReturning) + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, cache.query) + fmt.Fprintln(writer, vals) + } + + if len(cache.retMapping) != 0 { + err = exec.QueryRowContext(ctx, cache.query, vals...).Scan(queries.PtrsFromMapping(value, cache.retMapping)...) + } else { + _, err = exec.ExecContext(ctx, cache.query, vals...) + } + + if err != nil { + return errors.Wrap(err, "models: unable to insert into templates") + } + + if !cached { + templateInsertCacheMut.Lock() + templateInsertCache[key] = cache + templateInsertCacheMut.Unlock() + } + + return o.doAfterInsertHooks(ctx, exec) +} + +// Update uses an executor to update the Template. +// See boil.Columns.UpdateColumnSet documentation to understand column list inference for updates. +// Update does not automatically update the record in case of default values. Use .Reload() to refresh the records. +func (o *Template) Update(ctx context.Context, exec boil.ContextExecutor, columns boil.Columns) (int64, error) { + var err error + if err = o.doBeforeUpdateHooks(ctx, exec); err != nil { + return 0, err + } + key := makeCacheKey(columns, nil) + templateUpdateCacheMut.RLock() + cache, cached := templateUpdateCache[key] + templateUpdateCacheMut.RUnlock() + + if !cached { + wl := columns.UpdateColumnSet( + templateAllColumns, + templatePrimaryKeyColumns, + ) + + if !columns.IsWhitelist() { + wl = strmangle.SetComplement(wl, []string{"created_at"}) + } + if len(wl) == 0 { + return 0, errors.New("models: unable to update templates, could not build whitelist") + } + + cache.query = fmt.Sprintf("UPDATE \"identity_api\".\"templates\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, wl), + strmangle.WhereClause("\"", "\"", len(wl)+1, templatePrimaryKeyColumns), + ) + cache.valueMapping, err = queries.BindMapping(templateType, templateMapping, append(wl, templatePrimaryKeyColumns...)) + if err != nil { + return 0, err + } + } + + values := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), cache.valueMapping) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, cache.query) + fmt.Fprintln(writer, values) + } + var result sql.Result + result, err = exec.ExecContext(ctx, cache.query, values...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to update templates row") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by update for templates") + } + + if !cached { + templateUpdateCacheMut.Lock() + templateUpdateCache[key] = cache + templateUpdateCacheMut.Unlock() + } + + return rowsAff, o.doAfterUpdateHooks(ctx, exec) +} + +// UpdateAll updates all rows with the specified column values. +func (q templateQuery) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) { + queries.SetUpdate(q.Query, cols) + + result, err := q.Query.ExecContext(ctx, exec) + if err != nil { + return 0, errors.Wrap(err, "models: unable to update all for templates") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: unable to retrieve rows affected for templates") + } + + return rowsAff, nil +} + +// UpdateAll updates all rows with the specified column values, using an executor. +func (o TemplateSlice) UpdateAll(ctx context.Context, exec boil.ContextExecutor, cols M) (int64, error) { + ln := int64(len(o)) + if ln == 0 { + return 0, nil + } + + if len(cols) == 0 { + return 0, errors.New("models: update all requires at least one column argument") + } + + colNames := make([]string, len(cols)) + args := make([]interface{}, len(cols)) + + i := 0 + for name, value := range cols { + colNames[i] = name + args[i] = value + i++ + } + + // Append all of the primary key values for each column + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), templatePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := fmt.Sprintf("UPDATE \"identity_api\".\"templates\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, colNames), + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), len(colNames)+1, templatePrimaryKeyColumns, len(o))) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, args...) + } + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to update all in template slice") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: unable to retrieve rows affected all in update all template") + } + return rowsAff, nil +} + +// Upsert attempts an insert using an executor, and does an update or ignore on conflict. +// See boil.Columns documentation for how to properly use updateColumns and insertColumns. +func (o *Template) Upsert(ctx context.Context, exec boil.ContextExecutor, updateOnConflict bool, conflictColumns []string, updateColumns, insertColumns boil.Columns, opts ...UpsertOptionFunc) error { + if o == nil { + return errors.New("models: no templates provided for upsert") + } + if !boil.TimestampsAreSkipped(ctx) { + currTime := time.Now().In(boil.GetLocation()) + + if o.CreatedAt.IsZero() { + o.CreatedAt = currTime + } + } + + if err := o.doBeforeUpsertHooks(ctx, exec); err != nil { + return err + } + + nzDefaults := queries.NonZeroDefaultSet(templateColumnsWithDefault, o) + + // Build cache key in-line uglily - mysql vs psql problems + buf := strmangle.GetBuffer() + if updateOnConflict { + buf.WriteByte('t') + } else { + buf.WriteByte('f') + } + buf.WriteByte('.') + for _, c := range conflictColumns { + buf.WriteString(c) + } + buf.WriteByte('.') + buf.WriteString(strconv.Itoa(updateColumns.Kind)) + for _, c := range updateColumns.Cols { + buf.WriteString(c) + } + buf.WriteByte('.') + buf.WriteString(strconv.Itoa(insertColumns.Kind)) + for _, c := range insertColumns.Cols { + buf.WriteString(c) + } + buf.WriteByte('.') + for _, c := range nzDefaults { + buf.WriteString(c) + } + key := buf.String() + strmangle.PutBuffer(buf) + + templateUpsertCacheMut.RLock() + cache, cached := templateUpsertCache[key] + templateUpsertCacheMut.RUnlock() + + var err error + + if !cached { + insert, _ := insertColumns.InsertColumnSet( + templateAllColumns, + templateColumnsWithDefault, + templateColumnsWithoutDefault, + nzDefaults, + ) + + update := updateColumns.UpdateColumnSet( + templateAllColumns, + templatePrimaryKeyColumns, + ) + + if updateOnConflict && len(update) == 0 { + return errors.New("models: unable to upsert templates, could not build update column list") + } + + ret := strmangle.SetComplement(templateAllColumns, strmangle.SetIntersect(insert, update)) + + conflict := conflictColumns + if len(conflict) == 0 && updateOnConflict && len(update) != 0 { + if len(templatePrimaryKeyColumns) == 0 { + return errors.New("models: unable to upsert templates, could not build conflict column list") + } + + conflict = make([]string, len(templatePrimaryKeyColumns)) + copy(conflict, templatePrimaryKeyColumns) + } + cache.query = buildUpsertQueryPostgres(dialect, "\"identity_api\".\"templates\"", updateOnConflict, ret, update, conflict, insert, opts...) + + cache.valueMapping, err = queries.BindMapping(templateType, templateMapping, insert) + if err != nil { + return err + } + if len(ret) != 0 { + cache.retMapping, err = queries.BindMapping(templateType, templateMapping, ret) + if err != nil { + return err + } + } + } + + value := reflect.Indirect(reflect.ValueOf(o)) + vals := queries.ValuesFromMapping(value, cache.valueMapping) + var returns []interface{} + if len(cache.retMapping) != 0 { + returns = queries.PtrsFromMapping(value, cache.retMapping) + } + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, cache.query) + fmt.Fprintln(writer, vals) + } + if len(cache.retMapping) != 0 { + err = exec.QueryRowContext(ctx, cache.query, vals...).Scan(returns...) + if errors.Is(err, sql.ErrNoRows) { + err = nil // Postgres doesn't return anything when there's no update + } + } else { + _, err = exec.ExecContext(ctx, cache.query, vals...) + } + if err != nil { + return errors.Wrap(err, "models: unable to upsert templates") + } + + if !cached { + templateUpsertCacheMut.Lock() + templateUpsertCache[key] = cache + templateUpsertCacheMut.Unlock() + } + + return o.doAfterUpsertHooks(ctx, exec) +} + +// Delete deletes a single Template record with an executor. +// Delete will match against the primary key column to find the record to delete. +func (o *Template) Delete(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if o == nil { + return 0, errors.New("models: no Template provided for delete") + } + + if err := o.doBeforeDeleteHooks(ctx, exec); err != nil { + return 0, err + } + + args := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(o)), templatePrimaryKeyMapping) + sql := "DELETE FROM \"identity_api\".\"templates\" WHERE \"id\"=$1" + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, args...) + } + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to delete from templates") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by delete for templates") + } + + if err := o.doAfterDeleteHooks(ctx, exec); err != nil { + return 0, err + } + + return rowsAff, nil +} + +// DeleteAll deletes all matching rows. +func (q templateQuery) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if q.Query == nil { + return 0, errors.New("models: no templateQuery provided for delete all") + } + + queries.SetDelete(q.Query) + + result, err := q.Query.ExecContext(ctx, exec) + if err != nil { + return 0, errors.Wrap(err, "models: unable to delete all from templates") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by deleteall for templates") + } + + return rowsAff, nil +} + +// DeleteAll deletes all rows in the slice, using an executor. +func (o TemplateSlice) DeleteAll(ctx context.Context, exec boil.ContextExecutor) (int64, error) { + if len(o) == 0 { + return 0, nil + } + + if len(templateBeforeDeleteHooks) != 0 { + for _, obj := range o { + if err := obj.doBeforeDeleteHooks(ctx, exec); err != nil { + return 0, err + } + } + } + + var args []interface{} + for _, obj := range o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), templatePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "DELETE FROM \"identity_api\".\"templates\" WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 1, templatePrimaryKeyColumns, len(o)) + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, args) + } + result, err := exec.ExecContext(ctx, sql, args...) + if err != nil { + return 0, errors.Wrap(err, "models: unable to delete all from template slice") + } + + rowsAff, err := result.RowsAffected() + if err != nil { + return 0, errors.Wrap(err, "models: failed to get rows affected by deleteall for templates") + } + + if len(templateAfterDeleteHooks) != 0 { + for _, obj := range o { + if err := obj.doAfterDeleteHooks(ctx, exec); err != nil { + return 0, err + } + } + } + + return rowsAff, nil +} + +// Reload refetches the object from the database +// using the primary keys with an executor. +func (o *Template) Reload(ctx context.Context, exec boil.ContextExecutor) error { + ret, err := FindTemplate(ctx, exec, o.ID) + if err != nil { + return err + } + + *o = *ret + return nil +} + +// ReloadAll refetches every row with matching primary key column values +// and overwrites the original object slice with the newly updated slice. +func (o *TemplateSlice) ReloadAll(ctx context.Context, exec boil.ContextExecutor) error { + if o == nil || len(*o) == 0 { + return nil + } + + slice := TemplateSlice{} + var args []interface{} + for _, obj := range *o { + pkeyArgs := queries.ValuesFromMapping(reflect.Indirect(reflect.ValueOf(obj)), templatePrimaryKeyMapping) + args = append(args, pkeyArgs...) + } + + sql := "SELECT \"identity_api\".\"templates\".* FROM \"identity_api\".\"templates\" WHERE " + + strmangle.WhereClauseRepeated(string(dialect.LQ), string(dialect.RQ), 1, templatePrimaryKeyColumns, len(*o)) + + q := queries.Raw(sql, args...) + + err := q.Bind(ctx, exec, &slice) + if err != nil { + return errors.Wrap(err, "models: unable to reload all in TemplateSlice") + } + + *o = slice + + return nil +} + +// TemplateExists checks if the Template row exists. +func TemplateExists(ctx context.Context, exec boil.ContextExecutor, iD []byte) (bool, error) { + var exists bool + sql := "select exists(select 1 from \"identity_api\".\"templates\" where \"id\"=$1 limit 1)" + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, sql) + fmt.Fprintln(writer, iD) + } + row := exec.QueryRowContext(ctx, sql, iD) + + err := row.Scan(&exists) + if err != nil { + return false, errors.Wrap(err, "models: unable to check if templates exists") + } + + return exists, nil +} + +// Exists checks if the Template row exists. +func (o *Template) Exists(ctx context.Context, exec boil.ContextExecutor) (bool, error) { + return TemplateExists(ctx, exec, o.ID) +} diff --git a/models/vehicle_sacds.go b/models/vehicle_sacds.go index f2a912a1..5d4c7028 100644 --- a/models/vehicle_sacds.go +++ b/models/vehicle_sacds.go @@ -13,6 +13,7 @@ import ( "sync" "time" + "github.com/aarondl/null/v8" "github.com/aarondl/sqlboiler/v4/boil" "github.com/aarondl/sqlboiler/v4/queries" "github.com/aarondl/sqlboiler/v4/queries/qm" @@ -23,12 +24,13 @@ import ( // VehicleSacd is an object representing the database table. type VehicleSacd struct { - VehicleID int `boil:"vehicle_id" json:"vehicle_id" toml:"vehicle_id" yaml:"vehicle_id"` - Grantee []byte `boil:"grantee" json:"grantee" toml:"grantee" yaml:"grantee"` - Permissions string `boil:"permissions" json:"permissions" toml:"permissions" yaml:"permissions"` - Source string `boil:"source" json:"source" toml:"source" yaml:"source"` - CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` - ExpiresAt time.Time `boil:"expires_at" json:"expires_at" toml:"expires_at" yaml:"expires_at"` + VehicleID int `boil:"vehicle_id" json:"vehicle_id" toml:"vehicle_id" yaml:"vehicle_id"` + Grantee []byte `boil:"grantee" json:"grantee" toml:"grantee" yaml:"grantee"` + Permissions string `boil:"permissions" json:"permissions" toml:"permissions" yaml:"permissions"` + Source string `boil:"source" json:"source" toml:"source" yaml:"source"` + CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` + ExpiresAt time.Time `boil:"expires_at" json:"expires_at" toml:"expires_at" yaml:"expires_at"` + TemplateID null.Bytes `boil:"template_id" json:"template_id,omitempty" toml:"template_id" yaml:"template_id,omitempty"` R *vehicleSacdR `boil:"-" json:"-" toml:"-" yaml:"-"` L vehicleSacdL `boil:"-" json:"-" toml:"-" yaml:"-"` @@ -41,6 +43,7 @@ var VehicleSacdColumns = struct { Source string CreatedAt string ExpiresAt string + TemplateID string }{ VehicleID: "vehicle_id", Grantee: "grantee", @@ -48,6 +51,7 @@ var VehicleSacdColumns = struct { Source: "source", CreatedAt: "created_at", ExpiresAt: "expires_at", + TemplateID: "template_id", } var VehicleSacdTableColumns = struct { @@ -57,6 +61,7 @@ var VehicleSacdTableColumns = struct { Source string CreatedAt string ExpiresAt string + TemplateID string }{ VehicleID: "vehicle_sacds.vehicle_id", Grantee: "vehicle_sacds.grantee", @@ -64,6 +69,7 @@ var VehicleSacdTableColumns = struct { Source: "vehicle_sacds.source", CreatedAt: "vehicle_sacds.created_at", ExpiresAt: "vehicle_sacds.expires_at", + TemplateID: "vehicle_sacds.template_id", } // Generated where @@ -75,6 +81,7 @@ var VehicleSacdWhere = struct { Source whereHelperstring CreatedAt whereHelpertime_Time ExpiresAt whereHelpertime_Time + TemplateID whereHelpernull_Bytes }{ VehicleID: whereHelperint{field: "\"identity_api\".\"vehicle_sacds\".\"vehicle_id\""}, Grantee: whereHelper__byte{field: "\"identity_api\".\"vehicle_sacds\".\"grantee\""}, @@ -82,18 +89,22 @@ var VehicleSacdWhere = struct { Source: whereHelperstring{field: "\"identity_api\".\"vehicle_sacds\".\"source\""}, CreatedAt: whereHelpertime_Time{field: "\"identity_api\".\"vehicle_sacds\".\"created_at\""}, ExpiresAt: whereHelpertime_Time{field: "\"identity_api\".\"vehicle_sacds\".\"expires_at\""}, + TemplateID: whereHelpernull_Bytes{field: "\"identity_api\".\"vehicle_sacds\".\"template_id\""}, } // VehicleSacdRels is where relationship names are stored. var VehicleSacdRels = struct { - Vehicle string + Template string + Vehicle string }{ - Vehicle: "Vehicle", + Template: "Template", + Vehicle: "Vehicle", } // vehicleSacdR is where relationships are stored. type vehicleSacdR struct { - Vehicle *Vehicle `boil:"Vehicle" json:"Vehicle" toml:"Vehicle" yaml:"Vehicle"` + Template *Template `boil:"Template" json:"Template" toml:"Template" yaml:"Template"` + Vehicle *Vehicle `boil:"Vehicle" json:"Vehicle" toml:"Vehicle" yaml:"Vehicle"` } // NewStruct creates a new relationship struct @@ -101,6 +112,22 @@ func (*vehicleSacdR) NewStruct() *vehicleSacdR { return &vehicleSacdR{} } +func (o *VehicleSacd) GetTemplate() *Template { + if o == nil { + return nil + } + + return o.R.GetTemplate() +} + +func (r *vehicleSacdR) GetTemplate() *Template { + if r == nil { + return nil + } + + return r.Template +} + func (o *VehicleSacd) GetVehicle() *Vehicle { if o == nil { return nil @@ -121,9 +148,9 @@ func (r *vehicleSacdR) GetVehicle() *Vehicle { type vehicleSacdL struct{} var ( - vehicleSacdAllColumns = []string{"vehicle_id", "grantee", "permissions", "source", "created_at", "expires_at"} + vehicleSacdAllColumns = []string{"vehicle_id", "grantee", "permissions", "source", "created_at", "expires_at", "template_id"} vehicleSacdColumnsWithoutDefault = []string{"vehicle_id", "grantee", "permissions", "source", "created_at", "expires_at"} - vehicleSacdColumnsWithDefault = []string{} + vehicleSacdColumnsWithDefault = []string{"template_id"} vehicleSacdPrimaryKeyColumns = []string{"vehicle_id", "grantee"} vehicleSacdGeneratedColumns = []string{} ) @@ -433,6 +460,17 @@ func (q vehicleSacdQuery) Exists(ctx context.Context, exec boil.ContextExecutor) return count > 0, nil } +// Template pointed to by the foreign key. +func (o *VehicleSacd) Template(mods ...qm.QueryMod) templateQuery { + queryMods := []qm.QueryMod{ + qm.Where("\"id\" = ?", o.TemplateID), + } + + queryMods = append(queryMods, mods...) + + return Templates(queryMods...) +} + // Vehicle pointed to by the foreign key. func (o *VehicleSacd) Vehicle(mods ...qm.QueryMod) vehicleQuery { queryMods := []qm.QueryMod{ @@ -444,6 +482,130 @@ func (o *VehicleSacd) Vehicle(mods ...qm.QueryMod) vehicleQuery { return Vehicles(queryMods...) } +// LoadTemplate allows an eager lookup of values, cached into the +// loaded structs of the objects. This is for an N-1 relationship. +func (vehicleSacdL) LoadTemplate(ctx context.Context, e boil.ContextExecutor, singular bool, maybeVehicleSacd interface{}, mods queries.Applicator) error { + var slice []*VehicleSacd + var object *VehicleSacd + + if singular { + var ok bool + object, ok = maybeVehicleSacd.(*VehicleSacd) + if !ok { + object = new(VehicleSacd) + ok = queries.SetFromEmbeddedStruct(&object, &maybeVehicleSacd) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", object, maybeVehicleSacd)) + } + } + } else { + s, ok := maybeVehicleSacd.(*[]*VehicleSacd) + if ok { + slice = *s + } else { + ok = queries.SetFromEmbeddedStruct(&slice, maybeVehicleSacd) + if !ok { + return errors.New(fmt.Sprintf("failed to set %T from embedded struct %T", slice, maybeVehicleSacd)) + } + } + } + + args := make(map[interface{}]struct{}) + if singular { + if object.R == nil { + object.R = &vehicleSacdR{} + } + if !queries.IsNil(object.TemplateID) { + args[object.TemplateID] = struct{}{} + } + + } else { + for _, obj := range slice { + if obj.R == nil { + obj.R = &vehicleSacdR{} + } + + if !queries.IsNil(obj.TemplateID) { + args[obj.TemplateID] = struct{}{} + } + + } + } + + if len(args) == 0 { + return nil + } + + argsSlice := make([]interface{}, len(args)) + i := 0 + for arg := range args { + argsSlice[i] = arg + i++ + } + + query := NewQuery( + qm.From(`identity_api.templates`), + qm.WhereIn(`identity_api.templates.id in ?`, argsSlice...), + ) + if mods != nil { + mods.Apply(query) + } + + results, err := query.QueryContext(ctx, e) + if err != nil { + return errors.Wrap(err, "failed to eager load Template") + } + + var resultSlice []*Template + if err = queries.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice Template") + } + + if err = results.Close(); err != nil { + return errors.Wrap(err, "failed to close results of eager load for templates") + } + if err = results.Err(); err != nil { + return errors.Wrap(err, "error occurred during iteration of eager loaded relations for templates") + } + + if len(templateAfterSelectHooks) != 0 { + for _, obj := range resultSlice { + if err := obj.doAfterSelectHooks(ctx, e); err != nil { + return err + } + } + } + + if len(resultSlice) == 0 { + return nil + } + + if singular { + foreign := resultSlice[0] + object.R.Template = foreign + if foreign.R == nil { + foreign.R = &templateR{} + } + foreign.R.VehicleSacds = append(foreign.R.VehicleSacds, object) + return nil + } + + for _, local := range slice { + for _, foreign := range resultSlice { + if queries.Equal(local.TemplateID, foreign.ID) { + local.R.Template = foreign + if foreign.R == nil { + foreign.R = &templateR{} + } + foreign.R.VehicleSacds = append(foreign.R.VehicleSacds, local) + break + } + } + } + + return nil +} + // LoadVehicle allows an eager lookup of values, cached into the // loaded structs of the objects. This is for an N-1 relationship. func (vehicleSacdL) LoadVehicle(ctx context.Context, e boil.ContextExecutor, singular bool, maybeVehicleSacd interface{}, mods queries.Applicator) error { @@ -564,6 +726,86 @@ func (vehicleSacdL) LoadVehicle(ctx context.Context, e boil.ContextExecutor, sin return nil } +// SetTemplate of the vehicleSacd to the related item. +// Sets o.R.Template to related. +// Adds o to related.R.VehicleSacds. +func (o *VehicleSacd) SetTemplate(ctx context.Context, exec boil.ContextExecutor, insert bool, related *Template) error { + var err error + if insert { + if err = related.Insert(ctx, exec, boil.Infer()); err != nil { + return errors.Wrap(err, "failed to insert into foreign table") + } + } + + updateQuery := fmt.Sprintf( + "UPDATE \"identity_api\".\"vehicle_sacds\" SET %s WHERE %s", + strmangle.SetParamNames("\"", "\"", 1, []string{"template_id"}), + strmangle.WhereClause("\"", "\"", 2, vehicleSacdPrimaryKeyColumns), + ) + values := []interface{}{related.ID, o.VehicleID, o.Grantee} + + if boil.IsDebug(ctx) { + writer := boil.DebugWriterFrom(ctx) + fmt.Fprintln(writer, updateQuery) + fmt.Fprintln(writer, values) + } + if _, err = exec.ExecContext(ctx, updateQuery, values...); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + queries.Assign(&o.TemplateID, related.ID) + if o.R == nil { + o.R = &vehicleSacdR{ + Template: related, + } + } else { + o.R.Template = related + } + + if related.R == nil { + related.R = &templateR{ + VehicleSacds: VehicleSacdSlice{o}, + } + } else { + related.R.VehicleSacds = append(related.R.VehicleSacds, o) + } + + return nil +} + +// RemoveTemplate relationship. +// Sets o.R.Template to nil. +// Removes o from all passed in related items' relationships struct. +func (o *VehicleSacd) RemoveTemplate(ctx context.Context, exec boil.ContextExecutor, related *Template) error { + var err error + + queries.SetScanner(&o.TemplateID, nil) + if _, err = o.Update(ctx, exec, boil.Whitelist("template_id")); err != nil { + return errors.Wrap(err, "failed to update local table") + } + + if o.R != nil { + o.R.Template = nil + } + if related == nil || related.R == nil { + return nil + } + + for i, ri := range related.R.VehicleSacds { + if queries.Equal(o.TemplateID, ri.TemplateID) { + continue + } + + ln := len(related.R.VehicleSacds) + if ln > 1 && i < ln-1 { + related.R.VehicleSacds[i] = related.R.VehicleSacds[ln-1] + } + related.R.VehicleSacds = related.R.VehicleSacds[:ln-1] + break + } + return nil +} + // SetVehicle of the vehicleSacd to the related item. // Sets o.R.Vehicle to related. // Adds o to related.R.VehicleSacds. diff --git a/settings.sample.yaml b/settings.sample.yaml index 27c48d12..80bc3cae 100644 --- a/settings.sample.yaml +++ b/settings.sample.yaml @@ -16,6 +16,7 @@ DIMO_VEHICLE_NFT_ADDR: "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d" AFTERMARKET_DEVICE_CONTRACT_ADDRESS: "0xcf9af64522162da85164a714c23a7705e6e466b3" SYNTHETIC_DEVICE_CONTRACT_ADDRESS: "0x85226A67FF1b3Ec6cb033162f7df5038a6C3bAB2" REWARDS_CONTRACT_ADDRESS: "0x375885164266d48C48abbbb439Be98864Ae62bBE" +TEMPLATE_ADDR: "0x0000000000000000000000000000000000000000" BASE_IMAGE_URL: "https://devices-api.dev.dimo.zone/v1/" TABLELAND_API_GATEWAY: "https://testnets.tableland.network/" ETHEREUM_RPC_URL: "http://127.0.0.1:8545" \ No newline at end of file