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

OCT-2263: Community onboarding through Sablier #600

Open
wants to merge 22 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c2ab48a
OCT-2264: Change the sablier winning endpoint
kgarbacinski Dec 19, 2024
a39c88a
refactor: blackify
kgarbacinski Dec 19, 2024
daa00a0
Merge remote-tracking branch 'origin/develop' into kacper/feat/oct-22…
kgarbacinski Jan 7, 2025
491f1e0
oct-2264: sablier ui update
jmikolajczyk Jan 8, 2025
5c06820
OCT-2264: UI support for the GLM giveaways receivers (#617)
aziolek Jan 15, 2025
b40d187
Merge branch 'develop' into kacper/feat/oct-2263-community-onboarding…
aziolek Jan 15, 2025
4ec7119
[CI/CD] Update uat.env contracts
housekeeper-bot Jan 15, 2025
fab258a
Merge branch 'develop' into kacper/feat/oct-2263-community-onboarding…
aziolek Jan 15, 2025
4845e2d
Merge branch 'develop' of github.com:golemfoundation/octant into kacp…
kgarbacinski Jan 15, 2025
ceea925
fix: fix ci
kgarbacinski Jan 15, 2025
5510d77
Merge remote-tracking branch 'origin/develop' into HEAD
kgarbacinski Jan 15, 2025
1c33e5d
[CI/CD] Update uat.env contracts
housekeeper-bot Jan 15, 2025
5fa6528
Merge branch 'develop' into kacper/feat/oct-2263-community-onboarding…
aziolek Jan 16, 2025
54597ee
oct-2263: sablier ui update
jmikolajczyk Jan 16, 2025
beb5f26
oct-2263: final sablier ui update
jmikolajczyk Jan 16, 2025
723c06d
oct-2263: badge fix
jmikolajczyk Jan 17, 2025
85ce715
Merge branch 'develop' into kacper/feat/oct-2263-community-onboarding…
aziolek Jan 20, 2025
e6d0dc4
Merge branch 'develop' into kacper/feat/oct-2263-community-onboarding…
aziolek Jan 24, 2025
bc7d67f
[CI/CD] Update uat.env contracts
housekeeper-bot Jan 26, 2025
00ffdd9
chore: update contracts addresses
kgarbacinski Jan 27, 2025
fb61b28
Merge branch 'kacper/feat/oct-2263-community-onboarding-through-sabli…
kgarbacinski Jan 27, 2025
1f0b306
[CI/CD] Update uat.env contracts
housekeeper-bot Jan 28, 2025
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
54 changes: 33 additions & 21 deletions backend/app/infrastructure/routes/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
post_user_terms_of_service_consent,
get_user_terms_of_service_consent_status,
)
from app.modules.user.winnings.controller import get_user_winnings
from app.modules.user.sablier_streams.controller import get_sablier_streams
from app.settings import config

ns = Namespace("user", description="Octant user settings")
Expand Down Expand Up @@ -98,27 +98,35 @@
},
)

user_winning_model = api.model(
"UserWinning",
user_stream_model = api.model(
"UserStream",
{
"amount": fields.String(
required=True,
description="Amount in WEI",
),
"dateAvailableForWithdrawal": fields.String(
required=True,
description="Date when winning is available for withdrawal as unix timestamp",
description="Date when stream is available for withdrawal as unix timestamp",
),
"isCancelled": fields.Boolean(
required=True,
description="Flag indicating whether stream is cancelled",
),
"remainingAmount": fields.String(
required=True,
description="Remaining amount in WEI",
),
},
)

user_winnings_model = api.model(
"UserWinnings",
user_streams_model = api.model(
"SablierStreams",
{
"winnings": fields.List(
fields.Nested(user_winning_model),
"sablierStreams": fields.List(
fields.Nested(user_stream_model),
required=True,
description="User winnings",
description="User's sablier streams",
),
},
)
Expand Down Expand Up @@ -344,29 +352,33 @@ def get(self, epoch: int):
}


@ns.route("/<string:user_address>/raffle/winnings")
@ns.route("/<string:user_address>/sablier-streams")
@ns.doc(
params={
"user_address": "User ethereum address in hexadecimal format (case-insensitive, prefixed with 0x)",
}
)
class UserWinnings(OctantResource):
class SablierStreams(OctantResource):
@ns.doc(
description="Returns an array of user's winnings with amounts and availability dates",
description="Returns an array of user's streams from Sablier with amounts, availability dates, remainingAmount and isCancelled flag.",
)
@ns.marshal_with(user_winnings_model)
@ns.response(200, "User's winnings retrieved successfully")
@ns.marshal_with(user_streams_model)
@ns.response(200, "User's streams from Sablier retrieved successfully")
def get(self, user_address: str):
app.logger.debug(f"Getting winnings for user {user_address}.")
winnings = get_user_winnings(user_address)
app.logger.debug(f"Retrieved {len(winnings)} winnings for user {user_address}.")
app.logger.debug(f"Getting sablier streams for user {user_address}.")
sablier_streams = get_sablier_streams(user_address)
app.logger.debug(
f"Retrieved {len(sablier_streams)} sablier streams for user {user_address}."
)

return {
"winnings": [
"sablierStreams": [
{
"amount": winning.amount,
"dateAvailableForWithdrawal": winning.date_available_for_withdrawal,
"amount": stream.amount,
"dateAvailableForWithdrawal": stream.date_available_for_withdrawal,
"isCancelled": stream.is_cancelled,
"remainingAmount": stream.remaining_amount,
}
for winning in winnings
for stream in sablier_streams
]
}
56 changes: 16 additions & 40 deletions backend/app/infrastructure/sablier/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,9 @@ class SablierStream(TypedDict):
id: str
actions: List[SablierAction]
intactAmount: str


class SablierStreamForTrackingWinner(TypedDict):
id: str
canceled: bool
endTime: str
depositAmount: str
intactAmount: str


def fetch_streams(query: str, variables: Dict) -> List[SablierStream]:
Expand All @@ -55,8 +51,18 @@ def fetch_streams(query: str, variables: Dict) -> List[SablierStream]:
for stream in streams:
actions = stream.get("actions", [])
final_intact_amount = stream.get("intactAmount", 0)
is_cancelled = stream["canceled"]
end_time = stream["endTime"]
deposit_amount = stream["depositAmount"]

all_streams.append(
SablierStream(actions=actions, intactAmount=final_intact_amount)
SablierStream(
actions=actions,
intactAmount=final_intact_amount,
canceled=is_cancelled,
endTime=end_time,
depositAmount=deposit_amount,
)
)

if len(streams) < limit:
Expand All @@ -70,6 +76,7 @@ def fetch_streams(query: str, variables: Dict) -> List[SablierStream]:
def get_user_events_history(user_address: str) -> List[SablierStream]:
"""
Get all the locks and unlocks for a user.
Query used for computing user's effective deposit and getting all sablier streams from an endpoint.
"""
query = """
query GetEvents($sender: String!, $recipient: String!, $tokenAddress: String!, $limit: Int!, $skip: Int!) {
Expand All @@ -86,6 +93,9 @@ def get_user_events_history(user_address: str) -> List[SablierStream]:
) {
id
intactAmount
canceled
endTime
depositAmount
actions(where: {category_in: [Cancel, Withdraw, Create]}, orderBy: timestamp) {
category
addressA
Expand Down Expand Up @@ -146,40 +156,6 @@ def get_all_streams_history() -> List[SablierStream]:
return fetch_streams(query, variables)


def get_streams_with_create_events_to_user(
user_address: str,
) -> List[SablierStreamForTrackingWinner]:
"""
Get all the create events for a user.
"""
query = """
query GetCreateEvents($sender: String!, $recipient: String!, $tokenAddress: String!) {
streams(
where: {
sender: $sender
recipient: $recipient
asset_: {address: $tokenAddress}
transferable: false
}
orderBy: timestamp
) {
id
intactAmount
endTime
depositAmount
}
}
"""
variables = {
"sender": _get_sender(),
"recipient": user_address,
"tokenAddress": _get_token_address(),
}

result = gql_sablier_factory.build().execute(gql(query), variable_values=variables)
return result.get("streams", [])


def _get_sender():
chain_id = app.config["CHAIN_ID"]
sender = (
Expand Down
10 changes: 6 additions & 4 deletions backend/app/modules/modules_factory/current.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from app.modules.history.service.full import FullHistory
from app.modules.modules_factory.protocols import (
OctantRewards,
WinningsService,
UserEffectiveDeposits,
TotalEffectiveDeposits,
HistoryService,
Expand All @@ -17,6 +16,7 @@
ScoreDelegation,
UniquenessQuotients,
ProjectsDetailsService,
SablierStreamsService,
)
from app.modules.modules_factory.protocols import SimulatePendingSnapshots
from app.modules.multisig_signatures.service.offchain import OffchainMultisigSignatures
Expand Down Expand Up @@ -55,7 +55,9 @@
from app.modules.projects.details.service.projects_details import (
StaticProjectsDetailsService,
)
from app.modules.user.winnings.service.raffle import RaffleWinningsService
from app.modules.user.sablier_streams.service.sablier_streams import (
UserSablierStreamsService,
)


class CurrentUserDeposits(UserEffectiveDeposits, TotalEffectiveDeposits, Protocol):
Expand All @@ -68,7 +70,7 @@ class CurrentServices(Model):
user_tos_service: UserTos
user_antisybil_service: GitcoinPassportAntisybil
octant_rewards_service: OctantRewards
user_winnings_service: WinningsService
sablier_streams_service: SablierStreamsService
history_service: HistoryService
simulated_pending_snapshot_service: SimulatePendingSnapshots
multisig_signatures_service: MultisigSignatures
Expand Down Expand Up @@ -160,7 +162,7 @@ def create(chain_id: int) -> "CurrentServices":
multisig_signatures_service=multisig_signatures,
user_tos_service=user_tos,
user_antisybil_service=user_antisybil_service,
user_winnings_service=RaffleWinningsService(),
sablier_streams_service=UserSablierStreamsService(),
projects_metadata_service=StaticProjectsMetadataService(),
projects_details_service=StaticProjectsDetailsService(),
user_budgets_service=user_budgets,
Expand Down
10 changes: 6 additions & 4 deletions backend/app/modules/modules_factory/pre_pending.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
AllUserEffectiveDeposits,
OctantRewards,
PendingSnapshots,
WinningsService,
SablierStreamsService,
UserEffectiveDeposits,
SavedProjectRewardsService,
ProjectsMetadataService,
Expand All @@ -29,7 +29,9 @@
from app.modules.projects.details.service.projects_details import (
StaticProjectsDetailsService,
)
from app.modules.user.winnings.service.raffle import RaffleWinningsService
from app.modules.user.sablier_streams.service.sablier_streams import (
UserSablierStreamsService,
)


class PrePendingUserDeposits(UserEffectiveDeposits, AllUserEffectiveDeposits, Protocol):
Expand All @@ -43,7 +45,7 @@ class PrePendingServices(Model):
project_rewards_service: SavedProjectRewardsService
projects_metadata_service: ProjectsMetadataService
projects_details_service: ProjectsDetailsService
user_winnings_service: WinningsService
user_winnings_service: SablierStreamsService

@staticmethod
def create(chain_id: int) -> "PrePendingServices":
Expand Down Expand Up @@ -72,5 +74,5 @@ def create(chain_id: int) -> "PrePendingServices":
project_rewards_service=SavedProjectRewards(),
projects_metadata_service=StaticProjectsMetadataService(),
projects_details_service=StaticProjectsDetailsService(),
user_winnings_service=RaffleWinningsService(),
user_winnings_service=UserSablierStreamsService(),
)
8 changes: 4 additions & 4 deletions backend/app/modules/modules_factory/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from app.modules.history.dto import UserHistoryDTO
from app.modules.multisig_signatures.dto import Signature
from app.modules.projects.details.service.projects_details import ProjectsDetailsDTO
from app.modules.user.winnings.service.raffle import UserWinningDTO
from app.modules.user.sablier_streams.service.sablier_streams import UserStreamsDTO


@runtime_checkable
Expand Down Expand Up @@ -127,10 +127,10 @@ def get_unused_rewards(self, context: Context) -> Dict[str, int]:


@runtime_checkable
class WinningsService(Protocol):
def get_user_winnings(
class SablierStreamsService(Protocol):
def get_sablier_streams(
self, context: Context, user_address: str
) -> List[UserWinningDTO]:
) -> List[UserStreamsDTO]:
...


Expand Down
16 changes: 16 additions & 0 deletions backend/app/modules/user/sablier_streams/controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import List

from app.context.manager import state_context
from app.modules.registry import get_services
from app.modules.modules_factory.protocols import SablierStreamsService
from app.modules.user.sablier_streams.service.sablier_streams import UserStreamsDTO
from app.context.epoch_state import EpochState


def get_sablier_streams(user_address: str) -> List[UserStreamsDTO]:
context = state_context(EpochState.CURRENT)
service: SablierStreamsService = get_services(
context.epoch_state
).sablier_streams_service

return service.get_sablier_streams(context, user_address)
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from app.pydantic import Model
from typing import List
from dataclasses import dataclass

from app.infrastructure.sablier.events import get_user_events_history
from app.context.manager import Context


@dataclass
class UserStreamsDTO:
amount: str
date_available_for_withdrawal: str
is_cancelled: bool
remaining_amount: str


class UserSablierStreamsService(Model):
def get_sablier_streams(
self, _: Context, user_address: str
) -> List[UserStreamsDTO]:
user_streams = get_user_events_history(
user_address
) # in practice: we should assume a user only has always one stream (one create event)

user_streams_details = []
for user_stream in user_streams:
date_available_for_withdrawal = user_stream["endTime"]
amount = user_stream["depositAmount"]
is_cancelled = user_stream["canceled"]
remaining_amount = user_stream["intactAmount"]

user_streams_details.append(
UserStreamsDTO(
amount=amount,
date_available_for_withdrawal=date_available_for_withdrawal,
is_cancelled=is_cancelled,
remaining_amount=remaining_amount,
)
)

return user_streams_details
14 changes: 0 additions & 14 deletions backend/app/modules/user/winnings/controller.py

This file was deleted.

Loading
Loading