diff --git a/gqlgen.yml b/gqlgen.yml index f253097f..ed7d3c90 100644 --- a/gqlgen.yml +++ b/gqlgen.yml @@ -90,6 +90,9 @@ models: BigInt: model: - github.com/DIMO-Network/identity-api/graph/types.BigInt + BigDecimal: + model: + - github.com/DIMO-Network/identity-api/graph/types.BigDecimal Bytes: model: github.com/DIMO-Network/identity-api/graph/types.Bytes Manufacturer: diff --git a/graph/generated.go b/graph/generated.go index 7e056be5..f515409e 100644 --- a/graph/generated.go +++ b/graph/generated.go @@ -18,6 +18,7 @@ import ( "github.com/99designs/gqlgen/graphql/introspection" "github.com/DIMO-Network/identity-api/graph/model" "github.com/DIMO-Network/identity-api/graph/types" + "github.com/ericlagergren/decimal" "github.com/ethereum/go-ethereum/common" gqlparser "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" @@ -2934,9 +2935,9 @@ func (ec *executionContext) _AftermarketDeviceEarnings_totalTokens(ctx context.C } return graphql.Null } - res := resTmp.(*big.Int) + res := resTmp.(*decimal.Big) fc.Result = res - return ec.marshalNBigInt2ᚖmathᚋbigᚐInt(ctx, field.Selections, res) + return ec.marshalNBigDecimal2ᚖgithubᚗcomᚋericlagergrenᚋdecimalᚐBig(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_AftermarketDeviceEarnings_totalTokens(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -2946,7 +2947,7 @@ func (ec *executionContext) fieldContext_AftermarketDeviceEarnings_totalTokens(c IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type BigInt does not have child fields") + return nil, errors.New("field of type BigDecimal does not have child fields") }, } return fc, nil @@ -4145,9 +4146,9 @@ func (ec *executionContext) _Earning_streakTokens(ctx context.Context, field gra } return graphql.Null } - res := resTmp.(*big.Int) + res := resTmp.(*decimal.Big) fc.Result = res - return ec.marshalNBigInt2ᚖmathᚋbigᚐInt(ctx, field.Selections, res) + return ec.marshalNBigDecimal2ᚖgithubᚗcomᚋericlagergrenᚋdecimalᚐBig(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Earning_streakTokens(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -4157,7 +4158,7 @@ func (ec *executionContext) fieldContext_Earning_streakTokens(ctx context.Contex IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type BigInt does not have child fields") + return nil, errors.New("field of type BigDecimal does not have child fields") }, } return fc, nil @@ -4262,9 +4263,9 @@ func (ec *executionContext) _Earning_aftermarketDeviceTokens(ctx context.Context } return graphql.Null } - res := resTmp.(*big.Int) + res := resTmp.(*decimal.Big) fc.Result = res - return ec.marshalNBigInt2ᚖmathᚋbigᚐInt(ctx, field.Selections, res) + return ec.marshalNBigDecimal2ᚖgithubᚗcomᚋericlagergrenᚋdecimalᚐBig(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Earning_aftermarketDeviceTokens(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -4274,7 +4275,7 @@ func (ec *executionContext) fieldContext_Earning_aftermarketDeviceTokens(ctx con IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type BigInt does not have child fields") + return nil, errors.New("field of type BigDecimal does not have child fields") }, } return fc, nil @@ -4361,9 +4362,9 @@ func (ec *executionContext) _Earning_syntheticDeviceTokens(ctx context.Context, } return graphql.Null } - res := resTmp.(*big.Int) + res := resTmp.(*decimal.Big) fc.Result = res - return ec.marshalNBigInt2ᚖmathᚋbigᚐInt(ctx, field.Selections, res) + return ec.marshalNBigDecimal2ᚖgithubᚗcomᚋericlagergrenᚋdecimalᚐBig(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Earning_syntheticDeviceTokens(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -4373,7 +4374,7 @@ func (ec *executionContext) fieldContext_Earning_syntheticDeviceTokens(ctx conte IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type BigInt does not have child fields") + return nil, errors.New("field of type BigDecimal does not have child fields") }, } return fc, nil @@ -7229,9 +7230,9 @@ func (ec *executionContext) _UserRewards_totalTokens(ctx context.Context, field } return graphql.Null } - res := resTmp.(*big.Int) + res := resTmp.(*decimal.Big) fc.Result = res - return ec.marshalNBigInt2ᚖmathᚋbigᚐInt(ctx, field.Selections, res) + return ec.marshalNBigDecimal2ᚖgithubᚗcomᚋericlagergrenᚋdecimalᚐBig(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_UserRewards_totalTokens(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -7241,7 +7242,7 @@ func (ec *executionContext) fieldContext_UserRewards_totalTokens(ctx context.Con IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type BigInt does not have child fields") + return nil, errors.New("field of type BigDecimal does not have child fields") }, } return fc, nil @@ -8273,9 +8274,9 @@ func (ec *executionContext) _VehicleEarnings_totalTokens(ctx context.Context, fi } return graphql.Null } - res := resTmp.(*big.Int) + res := resTmp.(*decimal.Big) fc.Result = res - return ec.marshalNBigInt2ᚖmathᚋbigᚐInt(ctx, field.Selections, res) + return ec.marshalNBigDecimal2ᚖgithubᚗcomᚋericlagergrenᚋdecimalᚐBig(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_VehicleEarnings_totalTokens(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -8285,7 +8286,7 @@ func (ec *executionContext) fieldContext_VehicleEarnings_totalTokens(ctx context IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type BigInt does not have child fields") + return nil, errors.New("field of type BigDecimal does not have child fields") }, } return fc, nil @@ -13395,6 +13396,27 @@ func (ec *executionContext) marshalNAftermarketDeviceEdge2ᚖgithubᚗcomᚋDIMO return ec._AftermarketDeviceEdge(ctx, sel, v) } +func (ec *executionContext) unmarshalNBigDecimal2ᚖgithubᚗcomᚋericlagergrenᚋdecimalᚐBig(ctx context.Context, v interface{}) (*decimal.Big, error) { + res, err := types.UnmarshalBigDecimal(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNBigDecimal2ᚖgithubᚗcomᚋericlagergrenᚋdecimalᚐBig(ctx context.Context, sel ast.SelectionSet, v *decimal.Big) 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 + } + res := types.MarshalBigDecimal(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + func (ec *executionContext) unmarshalNBigInt2ᚖmathᚋbigᚐInt(ctx context.Context, v interface{}) (*big.Int, error) { res, err := types.UnmarshalBigInt(v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go index a30dce75..e8edb171 100644 --- a/graph/model/models_gen.go +++ b/graph/model/models_gen.go @@ -6,6 +6,7 @@ import ( "math/big" "time" + "github.com/ericlagergren/decimal" "github.com/ethereum/go-ethereum/common" ) @@ -70,7 +71,7 @@ type AftermarketDeviceConnection struct { } type AftermarketDeviceEarnings struct { - TotalTokens *big.Int `json:"totalTokens"` + TotalTokens *decimal.Big `json:"totalTokens"` History *EarningsConnection `json:"history"` AftermarketDeviceID int `json:"-"` } @@ -161,15 +162,15 @@ type Earning struct { // Consecutive period of which vehicle was connected ConnectionStreak *int `json:"connectionStreak,omitempty"` // Tokens earned for connection period - StreakTokens *big.Int `json:"streakTokens"` + StreakTokens *decimal.Big `json:"streakTokens"` // AftermarketDevice connected to vehicle AftermarketDevice *AftermarketDevice `json:"aftermarketDevice,omitempty"` // Tokens earned by aftermarketDevice - AftermarketDeviceTokens *big.Int `json:"aftermarketDeviceTokens"` + AftermarketDeviceTokens *decimal.Big `json:"aftermarketDeviceTokens"` // SyntheticDevice connected to vehicle SyntheticDevice *SyntheticDevice `json:"syntheticDevice,omitempty"` // Tokens earned by SyntheticDevice - SyntheticDeviceTokens *big.Int `json:"syntheticDeviceTokens"` + SyntheticDeviceTokens *decimal.Big `json:"syntheticDeviceTokens"` // Vehicle reward is assigned to Vehicle *Vehicle `json:"vehicle,omitempty"` // When the token was earned @@ -305,7 +306,7 @@ type SyntheticDevicesFilter struct { } type UserRewards struct { - TotalTokens *big.Int `json:"totalTokens"` + TotalTokens *decimal.Big `json:"totalTokens"` History *EarningsConnection `json:"history"` User common.Address `json:"-"` } @@ -352,7 +353,7 @@ type VehicleConnection struct { } type VehicleEarnings struct { - TotalTokens *big.Int `json:"totalTokens"` + TotalTokens *decimal.Big `json:"totalTokens"` History *EarningsConnection `json:"history"` VehicleID int `json:"-"` } diff --git a/graph/rewards_test.go b/graph/rewards_test.go index 16fb944c..771129c0 100644 --- a/graph/rewards_test.go +++ b/graph/rewards_test.go @@ -206,7 +206,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_FwdPaginate() { "vehicle": { "id": "V_kQE=", "earnings": { - "totalTokens": "177441154036585529047", + "totalTokens": "177.44", "history": { "totalCount": 1, "edges": [ @@ -216,12 +216,12 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_FwdPaginate() { "week": 2, "beneficiary": "%s", "connectionStreak": 20, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=", "tokenId": 1 }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1, "integrationId": 2 @@ -230,7 +230,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_FwdPaginate() { "id": "V_kQE=", "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "sentAt": "%s" } } @@ -382,7 +382,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_FwdPaginate_Firs "vehicle": { "id": "V_kQE=", "earnings": { - "totalTokens": "532323462109756587141", + "totalTokens": "532.32", "history": { "totalCount": 3, "edges": [ @@ -392,12 +392,12 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_FwdPaginate_Firs "week": 3, "beneficiary": "%s", "connectionStreak": 13, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=", "tokenId": 1 }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1, "integrationId": 2 @@ -406,7 +406,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_FwdPaginate_Firs "id": "V_kQE=", "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "sentAt": "%s" } }, @@ -416,12 +416,12 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_FwdPaginate_Firs "week": 2, "beneficiary": "%s", "connectionStreak": 12, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=", "tokenId": 1 }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1, "integrationId": 2 @@ -430,7 +430,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_FwdPaginate_Firs "id": "V_kQE=", "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "sentAt": "%s" } } @@ -587,7 +587,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las "vehicle": { "id": "V_kQE=", "earnings": { - "totalTokens": "532323462109756587141", + "totalTokens": "532.32", "history": { "totalCount": 3, "edges": [ @@ -597,12 +597,12 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las "week": 3, "beneficiary": "%s", "connectionStreak": 13, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=", "tokenId": 1 }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1, "integrationId": 2 @@ -611,7 +611,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las "id": "V_kQE=", "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "sentAt": "%s" } }, @@ -621,12 +621,12 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las "week": 2, "beneficiary": "%s", "connectionStreak": 12, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=", "tokenId": 1 }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1, "integrationId": 2 @@ -635,7 +635,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las "id": "V_kQE=", "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "sentAt": "%s" } } @@ -792,7 +792,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las "vehicle": { "id": "V_kQE=", "earnings": { - "totalTokens": "532323462109756587141", + "totalTokens": "532.32", "history": { "totalCount": 3, "edges": [ @@ -802,12 +802,12 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las "week": 4, "beneficiary": "%s", "connectionStreak": 14, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=", "tokenId": 1 }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1, "integrationId": 2 @@ -816,7 +816,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las "id": "V_kQE=", "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "sentAt": "%s" } }, @@ -826,12 +826,12 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las "week": 3, "beneficiary": "%s", "connectionStreak": 13, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=", "tokenId": 1 }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1, "integrationId": 2 @@ -840,7 +840,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetEarningsByVehicle_BackPaginate_Las "id": "V_kQE=", "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "sentAt": "%s" } } @@ -961,7 +961,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetAftermarketDeviceEarnings_FwdPagin "id": "AD_kQE=", "tokenId": 1, "earnings": { - "totalTokens": "177441154036585529047", + "totalTokens": "177.44", "history": { "totalCount": 1, "pageInfo": { @@ -1104,7 +1104,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_FwdPaginate() { r.JSONEq(fmt.Sprintf(` { "rewards": { - "totalTokens": "532323462109756587141", + "totalTokens": "532.32", "history": { "totalCount": 3, "edges": [ @@ -1113,15 +1113,15 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_FwdPaginate() { "week": 4, "beneficiary": "%s", "connectionStreak": 14, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=" }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "vehicle": { "id": "V_kQE=", "tokenId": 1 @@ -1134,15 +1134,15 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_FwdPaginate() { "week": 3, "beneficiary": "%s", "connectionStreak": 13, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=" }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "vehicle": { "id": "V_kQE=", "tokenId": 1 @@ -1277,7 +1277,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_BackPaginate_LastBefor r.JSONEq(fmt.Sprintf(` { "rewards": { - "totalTokens": "532323462109756587141", + "totalTokens": "532.32", "history": { "totalCount": 3, "edges": [ @@ -1286,15 +1286,15 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_BackPaginate_LastBefor "week": 3, "beneficiary": "%s", "connectionStreak": 13, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=" }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "vehicle": { "id": "V_kQE=", "tokenId": 1 @@ -1307,15 +1307,15 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_BackPaginate_LastBefor "week": 2, "beneficiary": "%s", "connectionStreak": 12, - "streakTokens": "59147051345528509684", + "streakTokens": "59.15", "aftermarketDevice": { "id": "AD_kQE=" }, - "aftermarketDeviceTokens": "59147051345528509681", + "aftermarketDeviceTokens": "59.15", "syntheticDevice": { "tokenId": 1 }, - "syntheticDeviceTokens": "59147051345528509682", + "syntheticDeviceTokens": "59.15", "vehicle": { "id": "V_kQE=", "tokenId": 1 @@ -1348,9 +1348,9 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_NullEarnings() { IssuanceWeek: 3, VehicleID: 1, ConnectionStreak: null.IntFrom(13), - StreakEarnings: dbtypes.IntToDecimal(big.NewInt(1)), + StreakEarnings: dbtypes.IntToDecimal(big.NewInt(1e18)), AftermarketTokenID: null.IntFrom(1), - AftermarketEarnings: dbtypes.IntToDecimal(big.NewInt(1)), + AftermarketEarnings: dbtypes.IntToDecimal(big.NewInt(1e18)), SyntheticTokenID: null.IntFrom(1), SyntheticEarnings: types.Decimal{}, ReceivedByAddress: null.BytesFrom(beneficiary.Bytes()), @@ -1406,7 +1406,7 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_NullEarnings() { r.JSONEq(fmt.Sprintf(` { "rewards": { - "totalTokens": "2", + "totalTokens": "2.00", "history": { "totalCount": 1, "edges": [ @@ -1415,15 +1415,15 @@ func (r *RewardsQueryTestSuite) Test_Query_GetUserRewards_NullEarnings() { "week": 3, "beneficiary": "%s", "connectionStreak": 13, - "streakTokens": "1", + "streakTokens": "1.00", "aftermarketDevice": { "id": "AD_kQE=" }, - "aftermarketDeviceTokens": "1", + "aftermarketDeviceTokens": "1.00", "syntheticDevice": { "tokenId": 1 }, - "syntheticDeviceTokens": "0", + "syntheticDeviceTokens": "0.00", "vehicle": { "id": "V_kQE=", "tokenId": 1 diff --git a/graph/schema/aftermarket.graphqls b/graph/schema/aftermarket.graphqls index 32ad4b2e..ad0a18c7 100644 --- a/graph/schema/aftermarket.graphqls +++ b/graph/schema/aftermarket.graphqls @@ -125,7 +125,7 @@ type AftermarketDeviceEdge { } type AftermarketDeviceEarnings { - totalTokens: BigInt! + totalTokens: BigDecimal! history( first: Int after: String diff --git a/graph/schema/reward.graphqls b/graph/schema/reward.graphqls index 74549b10..9a0e7e39 100644 --- a/graph/schema/reward.graphqls +++ b/graph/schema/reward.graphqls @@ -28,7 +28,7 @@ type Earning { """ Tokens earned for connection period """ - streakTokens: BigInt! + streakTokens: BigDecimal! """ AftermarketDevice connected to vehicle """ @@ -36,7 +36,7 @@ type Earning { """ Tokens earned by aftermarketDevice """ - aftermarketDeviceTokens: BigInt! + aftermarketDeviceTokens: BigDecimal! """ SyntheticDevice connected to vehicle """ @@ -44,7 +44,7 @@ type Earning { """ Tokens earned by SyntheticDevice """ - syntheticDeviceTokens: BigInt! + syntheticDeviceTokens: BigDecimal! """ Vehicle reward is assigned to """ @@ -68,7 +68,7 @@ type EarningsConnection { } type UserRewards { - totalTokens: BigInt! + totalTokens: BigDecimal! history( first: Int after: String diff --git a/graph/schema/schema.graphqls b/graph/schema/schema.graphqls index 4d2aa317..7bd997de 100644 --- a/graph/schema/schema.graphqls +++ b/graph/schema/schema.graphqls @@ -14,6 +14,11 @@ An integer of arbitrary precision, decimal-encoded. Typically a uint256. """ scalar BigInt +""" +BigDecimal decimal floating-point number, per the General Decimal Arithmetic specification. +""" +scalar BigDecimal + """ An array of byte, encoded as a lowercase hex string with 0x prefix. """ diff --git a/graph/schema/vehicle.graphqls b/graph/schema/vehicle.graphqls index b6e36fbf..d9b93ec8 100644 --- a/graph/schema/vehicle.graphqls +++ b/graph/schema/vehicle.graphqls @@ -159,7 +159,7 @@ type VehicleConnection { } type VehicleEarnings { - totalTokens: BigInt! + totalTokens: BigDecimal! history( first: Int after: String diff --git a/graph/types/blockchain.go b/graph/types/blockchain.go index 25b6a13d..beb7faee 100644 --- a/graph/types/blockchain.go +++ b/graph/types/blockchain.go @@ -8,6 +8,7 @@ import ( "strconv" "github.com/99designs/gqlgen/graphql" + "github.com/ericlagergren/decimal" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ) @@ -73,3 +74,23 @@ func UnmarshalBigInt(v any) (*big.Int, error) { return x, nil } + +func MarshalBigDecimal(x *decimal.Big) graphql.Marshaler { + return graphql.WriterFunc(func(w io.Writer) { + _, _ = fmt.Fprintf(w, `"%.2f"`, x) + }) +} + +func UnmarshalBigDecimal(v any) (*decimal.Big, error) { + s, ok := v.(string) + if !ok { + return nil, fmt.Errorf("type %T not a string", v) + } + + x, ok := new(decimal.Big).SetString(s) + if !ok { + return nil, errors.New("not a valid decimal number") + } + + return x, nil +} diff --git a/internal/repositories/reward/rewards.go b/internal/repositories/reward/rewards.go index 29de3e9a..802d4850 100644 --- a/internal/repositories/reward/rewards.go +++ b/internal/repositories/reward/rewards.go @@ -8,6 +8,7 @@ import ( "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/ericlagergren/decimal" "github.com/ethereum/go-ethereum/common" "github.com/volatiletech/null/v8" "github.com/volatiletech/sqlboiler/v4/queries/qm" @@ -15,6 +16,10 @@ import ( "golang.org/x/exp/slices" ) +// weiPerEther is the number of wei in an ether. +// negative scale results in 10^18. +var weiPerEther = decimal.New(1, -18) + type Repository struct { *base.Repository } @@ -32,15 +37,19 @@ type EarningsSummary struct { var rewardsCursorColumns = "(" + models.RewardColumns.IssuanceWeek + ", " + models.RewardColumns.VehicleID + ")" func RewardToAPI(reward models.Reward) gmodel.Earning { + strkEarn := weiToToken(reward.StreakEarnings) + aftrmrktEarn := weiToToken(reward.AftermarketEarnings) + synthEarn := weiToToken(reward.SyntheticEarnings) + return gmodel.Earning{ Week: reward.IssuanceWeek, Beneficiary: common.BytesToAddress(*reward.ReceivedByAddress.Ptr()), ConnectionStreak: reward.ConnectionStreak.Ptr(), - StreakTokens: reward.StreakEarnings.Int(nil), + StreakTokens: strkEarn, AftermarketDeviceID: reward.AftermarketTokenID.Ptr(), - AftermarketDeviceTokens: reward.AftermarketEarnings.Int(nil), + AftermarketDeviceTokens: aftrmrktEarn, SyntheticDeviceID: reward.SyntheticTokenID.Ptr(), - SyntheticDeviceTokens: reward.SyntheticEarnings.Int(nil), + SyntheticDeviceTokens: synthEarn, SentAt: reward.EarnedAt, VehicleID: reward.VehicleID, } @@ -175,7 +184,7 @@ func (r *Repository) GetEarningsByVehicleID(ctx context.Context, tokenID int) (* } return &gmodel.VehicleEarnings{ - TotalTokens: summary.TokenSum.Int(nil), + TotalTokens: weiToToken(summary.TokenSum), History: earningsConn, VehicleID: tokenID, }, nil @@ -212,7 +221,7 @@ func (r *Repository) GetEarningsByAfterMarketDeviceID(ctx context.Context, token } return &gmodel.AftermarketDeviceEarnings{ - TotalTokens: stats.TokenSum.Int(nil), + TotalTokens: weiToToken(stats.TokenSum), History: earningsConn, AftermarketDeviceID: tokenID, }, nil @@ -250,7 +259,7 @@ func (r *Repository) GetEarningsByUserAddress(ctx context.Context, user common.A } return &gmodel.UserRewards{ - TotalTokens: summary.TokenSum.Int(nil), + TotalTokens: weiToToken(summary.TokenSum), History: earningsConn, User: user, }, nil @@ -276,3 +285,8 @@ func (r *Repository) PaginateGetEarningsByUsersDevices(ctx context.Context, user userDeviceEarnings.History.PageInfo = afd.PageInfo return userDeviceEarnings.History, nil } + +// divide by 10^18 to get token value. +func weiToToken(wei types.Decimal) *decimal.Big { + return new(decimal.Big).Quo(wei.Big, weiPerEther) +} diff --git a/internal/repositories/reward/rewards_test.go b/internal/repositories/reward/rewards_test.go index d0818825..49b13393 100644 --- a/internal/repositories/reward/rewards_test.go +++ b/internal/repositories/reward/rewards_test.go @@ -14,6 +14,7 @@ import ( "github.com/DIMO-Network/identity-api/models" "github.com/DIMO-Network/shared/db" "github.com/DIMO-Network/shared/dbtypes" + "github.com/ericlagergren/decimal" "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "github.com/stretchr/testify/suite" @@ -21,6 +22,7 @@ import ( "github.com/volatiletech/null/v8" "github.com/volatiletech/sqlboiler/v4/boil" "github.com/volatiletech/sqlboiler/v4/queries/qm" + "github.com/volatiletech/sqlboiler/v4/types" ) type RewardsRepoTestSuite struct { @@ -277,7 +279,7 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByVehicleID_NoRows() { r.NoError(err) r.Equal(&gmodel.VehicleEarnings{ - TotalTokens: big.NewInt(0), + TotalTokens: decimal.New(0, 18), History: &gmodel.EarningsConnection{ TotalCount: 0, Edges: nil, @@ -288,7 +290,6 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByVehicleID_NoRows() { } func (r *RewardsRepoTestSuite) Test_PaginateVehicleEarningsByID_Disallow_FirstAndLast() { - first := 1 last := 2 _, err := r.repo.PaginateVehicleEarningsByID(r.ctx, &gmodel.VehicleEarnings{}, &first, nil, &last, nil) @@ -377,11 +378,11 @@ func (r *RewardsRepoTestSuite) Test_PaginateVehicleEarningsByID_FwdPagination_Fi Week: 2, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk, - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -484,11 +485,11 @@ func (r *RewardsRepoTestSuite) Test_PaginateVehicleEarningsByID_FwdPagination_Fi Week: 2, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk[0], - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -499,11 +500,11 @@ func (r *RewardsRepoTestSuite) Test_PaginateVehicleEarningsByID_FwdPagination_Fi Week: 1, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk[1], - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -679,11 +680,11 @@ func (r *RewardsRepoTestSuite) Test_PaginateVehicleEarningsByID_BackPagination_L Week: 1, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk, - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -788,11 +789,11 @@ func (r *RewardsRepoTestSuite) Test_PaginateVehicleEarningsByID_BackPagination_L Week: 3, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk[1], - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -803,11 +804,11 @@ func (r *RewardsRepoTestSuite) Test_PaginateVehicleEarningsByID_BackPagination_L Week: 2, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk[0], - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1007,11 +1008,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByAfterMarketDevice_FwdPagination Week: 2, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: rw[1].ConnectionStreak.Ptr(), - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1022,11 +1023,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByAfterMarketDevice_FwdPagination Week: 1, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: rw[0].ConnectionStreak.Ptr(), - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1117,11 +1118,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByAfterMarketDevice_FwdPagination Week: 2, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk[0], - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1132,11 +1133,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByAfterMarketDevice_FwdPagination Week: 1, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk[1], - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1225,11 +1226,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByAfterMarketDevice_BackPaginatio Week: 1, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk, - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1321,11 +1322,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByAfterMarketDevice_BackPaginatio Week: 3, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk[1], - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1336,11 +1337,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByAfterMarketDevice_BackPaginatio Week: 2, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk[0], - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1420,11 +1421,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByUserAddress_FwdPagination_First Week: 2, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: rw[1].ConnectionStreak.Ptr(), - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1435,11 +1436,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByUserAddress_FwdPagination_First Week: 1, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: rw[0].ConnectionStreak.Ptr(), - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1519,11 +1520,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByUserAddress_BackPagination_Last Week: 1, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: &connStrk, - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1617,11 +1618,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByUserAddress_MultipleVehicle_Fwd Week: 3, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: rw[2].ConnectionStreak.Ptr(), - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1632,11 +1633,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByUserAddress_MultipleVehicle_Fwd Week: 1, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: rw[0].ConnectionStreak.Ptr(), - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 11, }, @@ -1647,11 +1648,11 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByUserAddress_MultipleVehicle_Fwd Week: 1, Beneficiary: common.BytesToAddress(beneficiary.Bytes()), ConnectionStreak: rw[1].ConnectionStreak.Ptr(), - StreakTokens: strkEarn, + StreakTokens: bigWeiToToken(strkEarn), AftermarketDeviceID: &aftID, - AftermarketDeviceTokens: aftEarn, + AftermarketDeviceTokens: bigWeiToToken(aftEarn), SyntheticDeviceID: &syntID, - SyntheticDeviceTokens: syntEarn, + SyntheticDeviceTokens: bigWeiToToken(syntEarn), SentAt: currTime, VehicleID: 5, }, @@ -1660,3 +1661,8 @@ func (r *RewardsRepoTestSuite) Test_GetEarningsByUserAddress_MultipleVehicle_Fwd }, paginatedEarnings.Edges) } + +func bigWeiToToken(wei *big.Int) *decimal.Big { + bigDec := new(decimal.Big).SetBigMantScale(wei, 0) + return weiToToken(types.NewDecimal(bigDec)) +}