Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/endpoint routes #10

Merged
merged 37 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d02ac68
Fixing bugs
violog Feb 26, 2024
7553fb1
Fix ranking for a single balance
violog Feb 26, 2024
2c324ca
Fix pagination on leaderboard
violog Feb 27, 2024
0511498
Fix pagination on events and withdrawals lists
violog Feb 27, 2024
a01596b
Fix SBT checker stop on expiration, also drop disabled events
violog Feb 27, 2024
3a6be4f
Logging improvements, small fixes
violog Feb 27, 2024
4c184e7
Use Errorf for formatted strings
violog Feb 28, 2024
e82541f
Index-based referral code derivation
violog Feb 29, 2024
db385be
Add table for referral codes, vastly optimize indexes
violog Mar 1, 2024
8db5b49
Intermediate changes for balance creation logic
violog Mar 1, 2024
5539c9f
Private referrer creation with arbitrary number of ref codes
violog Mar 1, 2024
d01a0c7
Allow addition and invalidation of referral codes in the same endpoint
violog Mar 1, 2024
121f352
Add constraint that a referral link can be used only once
violog Mar 1, 2024
1a6470b
Add passport_scan event and dynamic reward depend on shared fields
Zaptoss Mar 1, 2024
6731a03
Remove excessive db request in claim_events, reduce variable name, ch…
Zaptoss Mar 1, 2024
694249f
Add validation for shared_data, code style
Zaptoss Mar 1, 2024
e005dc1
Add validation for shared_data, code style
Zaptoss Mar 1, 2024
7e4326e
Merge remote-tracking branch 'origin/feature/referral-otc' into work/…
Zaptoss Mar 4, 2024
b9d4e62
Add new referral system
Zaptoss Mar 4, 2024
a2162cf
Put metadata into fulfilled referral event
violog Mar 4, 2024
f5f67ff
Logic for disabled balances with null referred_by value
violog Mar 4, 2024
993ddf6
Small fixes of DB schema and handlers
violog Mar 4, 2024
2c4a04d
Logic for disabled balances with null referred_by value
violog Mar 4, 2024
61b8cc6
Create function newBalanceResponse which return response with referra…
Zaptoss Mar 4, 2024
6b62c4f
Add filters in GetBalance query: whether to return the rank and wheth…
Zaptoss Mar 5, 2024
f35d01a
Remove main binary
Zaptoss Mar 5, 2024
07ef0fd
Replace getRankedBalance function by if-else; Remove GetBalanceFilter…
Zaptoss Mar 5, 2024
aee3521
Comments
Zaptoss Mar 5, 2024
8009256
Change endpoint routes in router.go
violog Mar 6, 2024
aabfbeb
Change endpoint routes in docs
violog Mar 7, 2024
e9db94c
Filter not started and expired events in list endpoint
violog Mar 11, 2024
7e5be12
Update balance creation doc for the future implementation change
violog Mar 5, 2024
513c1ed
fix cookie auth
olegfomenko Mar 11, 2024
8a74c49
Fix edit referrals request validation
violog Mar 11, 2024
0b05327
Merge pull request #9 from rarimo/fix/cookie-auth
olegfomenko Mar 11, 2024
f8ad0e6
Fix referral ID generation function, add unit tests
violog Mar 11, 2024
e4e230d
Return referrals list and use request body in edit_referrals
violog Mar 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ db:
url: postgres://points:points@localhost:5432/points?sslmode=disable

listener:
addr: :8000

cop:
disabled: true
endpoint: "http://..."
upstream: "http://..."
service_name: rarime-points-svc
service_port: 80
addr: localhost:8000

event_types:
passport_rewards:
age: 20
nationality: 50
types:
- name: passport_scan
title: Points for passport scan
reward: 200
description: Get points for scan passport and share data
frequency: one-time
- name: get_poh
title: Get PoH credential
reward: 50
Expand Down Expand Up @@ -56,7 +57,7 @@ auth:
addr: http://rarime-auth

broadcaster:
addr: "http://broadcaster"
addr: broadcaster
sender_account: "rarimo15hcd6tv7pe8hk2re7hu0zg0aphqdm2dtjrs0ds"

withdrawal:
Expand Down
19 changes: 14 additions & 5 deletions docs/spec/components/schemas/Balance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ allOf:
type: object
required:
- amount
- referral_id
- is_verified
- is_disabled
- created_at
- updated_at
properties:
Expand All @@ -18,14 +18,17 @@ allOf:
format: int64
description: Amount of points
example: 580
referral_id:
type: string
description: Referral ID used to build a referral link and send it to friends
example: "zgsScguZ"
is_verified:
type: boolean
description: Whether the user has scanned passport
example: true
is_disabled:
type: boolean
description: |
Whether the user was not referred by anybody, but the balance with some
events was reserved. It happens when the user fulfills some event
before the balance creation.
example: false
created_at:
type: integer
description: Unix timestamp of balance creation
Expand All @@ -39,3 +42,9 @@ allOf:
format: int
description: Rank of the user in the full leaderboard. Returned only for the single user.
example: 294
referral_codes:
type: array
description: Referral codes used to build a referral link and send it to friends. Required if a balance is created
example: ["zgsScguZ", "jerUsmac"]
items:
type: string
5 changes: 4 additions & 1 deletion docs/spec/components/schemas/CreateBalance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ allOf:
- $ref: '#/components/schemas/CreateBalanceKey'
- type: object
x-go-is-request: true
required:
- attributes
properties:
attributes:
type: object
Expand All @@ -10,5 +12,6 @@ allOf:
properties:
referred_by:
type: string
description: ID of the referrer from the link
description: referrer code from the link
example: "rCx18MZ4"

4 changes: 4 additions & 0 deletions docs/spec/components/schemas/WithdrawKey.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ required:
- id
- type
properties:
id:
type: string
description: DID of the points owner
example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV"
type:
type: string
enum: [ withdraw ]
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ post:
- Points balance
summary: Create points balance
description: |
Create an empty balance for authorized user who makes the request. Rank is included.
Create an empty balance for authorized user who makes the request. Rank is included
in response.

This operation might be time-consuming, because `open` events should be added for
the new account synchronously (to display them right after the request).

If balance already exists, but it is disabled (it was not referred by another user,
but has fulfilled some event), you should use this endpoint as well.
operationId: createPointsBalance
requestBody:
content:
Expand Down Expand Up @@ -68,5 +73,11 @@ get:
$ref: '#/components/schemas/Balance'
400:
$ref: '#/components/responses/invalidParameter'
409:
description: Balance already exists and it is not disabled
content:
application/vnd.api+json:
schema:
$ref: '#/components/schemas/Errors'
500:
$ref: '#/components/responses/internalError'
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ get:
operationId: getPointsBalance
parameters:
- $ref: '#/components/parameters/pathDID'
- in: query
name: 'rank'
description: 'Specifies whether to return the rank'
required: false
schema:
type: boolean
example: true
- in: query
name: 'referral_codes'
description: 'Specifies whether to return the referral codes'
required: false
schema:
type: booleand
example: true
responses:
200:
description: Success
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ require (
github.com/go-chi/chi v4.1.2+incompatible
github.com/go-co-op/gocron/v2 v2.2.2
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
github.com/google/jsonapi v1.0.0
github.com/iden3/go-iden3-core/v2 v2.0.4
github.com/rarimo/auth-svc v1.0.0-rc2
github.com/rarimo/auth-svc v1.0.0-rc2.0.20240311143312-de1e2258f175
github.com/rarimo/saver-grpc-lib v1.0.0
github.com/rubenv/sql-migrate v1.6.1
gitlab.com/distributed_lab/ape v1.7.1
Expand Down Expand Up @@ -79,7 +80,6 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/jsonapi v1.0.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1217,8 +1217,8 @@ github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJf
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
github.com/rarimo/auth-svc v1.0.0-rc2 h1:6w+T8xFZwi5gc2x8FlObnfMEij2zlNQZDNSdaBLY2iw=
github.com/rarimo/auth-svc v1.0.0-rc2/go.mod h1:XtPIuJABJ3QNmhcpmJRlQrxuagPfpIWwFbY0j5SakFg=
github.com/rarimo/auth-svc v1.0.0-rc2.0.20240311143312-de1e2258f175 h1:LWfw+633hf9J0unWMA528CEf+taYdzhhoqJVFj3po6Y=
github.com/rarimo/auth-svc v1.0.0-rc2.0.20240311143312-de1e2258f175/go.mod h1:XtPIuJABJ3QNmhcpmJRlQrxuagPfpIWwFbY0j5SakFg=
github.com/rarimo/broadcaster-svc v1.0.2 h1:ExQcjjWCRP5+POLDlZHrTD1ffUsBH+Dgv5FAgcP3BXc=
github.com/rarimo/broadcaster-svc v1.0.2/go.mod h1:lYIHy+X4IqQt4eBdtMN/V352H3EV0/gO8G+32SFwUWI=
github.com/rarimo/cosmos-sdk v0.46.7 h1:jU2PiWzc+19SF02cXM0O0puKPeH1C6Q6t2lzJ9s1ejc=
Expand Down
24 changes: 17 additions & 7 deletions internal/assets/migrations/001_initial.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,29 @@ CREATE TABLE IF NOT EXISTS balances
amount bigint NOT NULL default 0,
created_at integer NOT NULL default EXTRACT('EPOCH' FROM NOW()),
updated_at integer NOT NULL default EXTRACT('EPOCH' FROM NOW()),
referral_id text UNIQUE NOT NULL,
referred_by text REFERENCES balances (referral_id),
referred_by text UNIQUE,
passport_hash text UNIQUE,
passport_expires timestamp without time zone
);

CREATE INDEX IF NOT EXISTS balances_amount_index ON balances using btree (amount);
CREATE INDEX IF NOT EXISTS balances_page_index ON balances (amount, updated_at) WHERE referred_by IS NOT NULL;

CREATE TRIGGER set_updated_at
BEFORE UPDATE
ON balances
FOR EACH ROW
EXECUTE FUNCTION trigger_set_updated_at();

CREATE TABLE IF NOT EXISTS referrals
(
id text PRIMARY KEY,
user_did text NOT NULL REFERENCES balances (did),
is_consumed boolean NOT NULL default false
);

ALTER TABLE balances ADD CONSTRAINT referred_by_fk FOREIGN KEY (referred_by) REFERENCES referrals (id);
CREATE INDEX IF NOT EXISTS referrals_user_did_index ON referrals (user_did);

CREATE TYPE event_status AS ENUM ('open', 'fulfilled', 'claimed');

CREATE TABLE IF NOT EXISTS events
Expand All @@ -39,9 +48,7 @@ CREATE TABLE IF NOT EXISTS events
CONSTRAINT unique_external_id UNIQUE (user_did, type, external_id)
);

CREATE INDEX IF NOT EXISTS events_user_did_index ON events using btree (user_did);
CREATE INDEX IF NOT EXISTS events_type_index ON events using btree (type);
CREATE INDEX IF NOT EXISTS events_updated_at_index ON events using btree (updated_at);
CREATE INDEX IF NOT EXISTS events_page_index ON events (user_did, updated_at);

CREATE TRIGGER set_updated_at
BEFORE UPDATE
Expand All @@ -58,11 +65,14 @@ CREATE TABLE IF NOT EXISTS withdrawals
created_at integer NOT NULL default EXTRACT('EPOCH' FROM NOW())
);

CREATE INDEX IF NOT EXISTS withdrawals_user_did_index ON withdrawals using btree (user_did);
CREATE INDEX IF NOT EXISTS withdrawals_page_index ON withdrawals (user_did, created_at);

-- +migrate Down
DROP TABLE IF EXISTS withdrawals;
DROP TABLE IF EXISTS events;

ALTER TABLE balances DROP CONSTRAINT referred_by_fk;
DROP TABLE IF EXISTS referrals;
DROP TABLE IF EXISTS balances;

DROP TYPE IF EXISTS event_status;
Expand Down
7 changes: 4 additions & 3 deletions internal/data/balances.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ type Balance struct {
Amount int64 `db:"amount"`
CreatedAt int32 `db:"created_at"`
UpdatedAt int32 `db:"updated_at"`
ReferralID string `db:"referral_id"`
ReferredBy sql.NullString `db:"referred_by"`
PassportHash sql.NullString `db:"passport_hash"`
PassportExpires sql.NullTime `db:"passport_expires"`
Expand All @@ -24,12 +23,14 @@ type BalancesQ interface {
Insert(Balance) error
UpdateAmountBy(points int64) error
SetPassport(hash string, exp time.Time) error
SetReferredBy(referralCode string) error

Page(*pgdb.OffsetPageParams) BalancesQ
Select() ([]Balance, error)
Get() (*Balance, error)
// GetWithRank returns balance with rank, filtered by DID. No other filters can be applied.
GetWithRank(did string) (*Balance, error)

WithRank() BalancesQ
FilterByDID(string) BalancesQ
FilterByReferralID(string) BalancesQ
FilterDisabled() BalancesQ
}
1 change: 1 addition & 0 deletions internal/data/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,5 @@ type EventsQ interface {
FilterByType(...string) EventsQ
FilterByUpdatedAtBefore(int64) EventsQ
FilterByExternalID(string) EventsQ
FilterInactiveNotClaimed(types ...string) EventsQ
}
19 changes: 17 additions & 2 deletions internal/data/evtypes/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ func NewConfig(getter kv.Getter) EventTypeser {
func (c *config) EventTypes() Types {
return c.once.Do(func() interface{} {
var raw struct {
Types []EventConfig `fig:"types,required"`
Types []EventConfig `fig:"types,required"`
PassportRewards map[string]int `fig:"passport_rewards"`
}

err := figure.Out(&raw).
Expand All @@ -42,7 +43,21 @@ func (c *config) EventTypes() Types {
m[t.Name] = t
}

return Types{m, raw.Types}
if _, ok := m[TypePassportScan]; !ok {
if len(raw.PassportRewards) != 0 {
panic(fmt.Errorf("rewards exists, but event PassportScan not exists"))
}
return Types{m, raw.Types, raw.PassportRewards}
}

if _, ok := raw.PassportRewards[PassportRewardAge]; !ok {
panic(fmt.Errorf("absent required field: %s", PassportRewardAge))
}
if _, ok := raw.PassportRewards[PassportRewardNationality]; !ok {
panic(fmt.Errorf("absent required field: %s", PassportRewardNationality))
}

return Types{m, raw.Types, raw.PassportRewards}
}).(Types)
}

Expand Down
22 changes: 20 additions & 2 deletions internal/data/evtypes/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ const (
TypeFreeWeekly = "free_weekly"
TypeBeReferred = "be_referred"
TypeReferralSpecific = "referral_specific"
TypePassportScan = "passport_scan"
)

const (
PassportRewardAge = "age"
PassportRewardNationality = "nationality"
)

type EventConfig struct {
Expand All @@ -50,8 +56,9 @@ func (e EventConfig) Resource() resources.EventStaticMeta {
}

type Types struct {
m map[string]EventConfig
list []EventConfig
m map[string]EventConfig
list []EventConfig
passportRewards map[string]int
}

func (t Types) Get(name string, filters ...filter) *EventConfig {
Expand Down Expand Up @@ -118,3 +125,14 @@ func (t Types) ensureInitialized() {
panic("event types are not correctly initialized")
}
}

func (t Types) CalculatePassportScanReward(sharedFields ...string) (reward int64, success bool) {
for _, field := range sharedFields {
val, ok := t.passportRewards[field]
if !ok {
return 0, false
}
reward += int64(val)
}
return reward, true
}
Loading
Loading