Documentation
¶
Index ¶
- Variables
- func SendContactJoinedFlipcashPush(ctx context.Context, pusher Pusher, joinedPhone *commonpb.PhoneNumber, ...) error
- func SendFlipcashCurrencyBoughtPush(ctx context.Context, pusher Pusher, user *commonpb.UserId, ...) error
- func SendFlipcashCurrencyDepositedPush(ctx context.Context, pusher Pusher, user *commonpb.UserId, ...) error
- func SendFlipcashCurrencyGainPush(ctx context.Context, pusher Pusher, user *commonpb.UserId, ...) error
- func SendFlipcashCurrencySoldPush(ctx context.Context, pusher Pusher, user *commonpb.UserId, ...) error
- func SendUsdfDepositProcessingPush(ctx context.Context, pusher Pusher, user *commonpb.UserId, ...) error
- func SendUsdfDepositedPush(ctx context.Context, pusher Pusher, user *commonpb.UserId, ...) error
- type BadgeCounts
- type BadgeResolver
- type ChatMessagePush
- func BuildContactDmPush(ctx context.Context, ocpData ocp_data.Provider, chatId *commonpb.ChatId, ...) (*ChatMessagePush, error)
- func BuildDmPush(ctx context.Context, ocpData ocp_data.Provider, chatId *commonpb.ChatId, ...) (*ChatMessagePush, error)
- func BuildGroupChatPush(ctx context.Context, ocpData ocp_data.Provider, chatId *commonpb.ChatId, ...) (*ChatMessagePush, error)
- type ChatRecipients
- type CurrencyState
- type CurrencyStateStore
- type FCMClient
- type FCMPusher
- type NoOpPusher
- type Pusher
- type Server
- type Store
- type Token
- type TokenStore
Constants ¶
This section is empty.
Variables ¶
var ErrCurrencyStateNotFound = errors.New("currency state not found")
ErrCurrencyStateNotFound is returned when no push state exists for a mint.
Functions ¶
func SendContactJoinedFlipcashPush ¶ added in v1.11.0
func SendFlipcashCurrencyBoughtPush ¶ added in v0.4.0
func SendFlipcashCurrencyDepositedPush ¶ added in v0.4.0
func SendFlipcashCurrencyGainPush ¶ added in v1.1.0
func SendFlipcashCurrencySoldPush ¶ added in v0.4.0
func SendUsdfDepositProcessingPush ¶ added in v1.9.0
Types ¶
type BadgeCounts ¶ added in v1.30.0
BadgeCounts maps a user (keyed by string(userID.Value)) to the app-icon badge to display alongside a push. A user absent from the map gets no badge.
type BadgeResolver ¶ added in v1.30.0
BadgeResolver produces the badge count to display for each of the given users. A pusher invokes it with only the users who own at least one iOS device — APNs is the only platform with a server-settable numeric badge — so any per-user work behind it (e.g. bumping a stored count) is skipped for users who could never display the result.
A resolver may return a partial map alongside an error: the counts it did produce are still carried on the push, and the error is reported after the push is sent.
type ChatMessagePush ¶ added in v1.32.0
type ChatMessagePush struct {
// contains filtered or unexported fields
}
ChatMessagePush is a chat message's notification, rendered once and sent to any number of recipient pages (see Send). Rendering is the part of a push that is the same for every recipient — the title, the body, the payload, and for cash content a currency-name lookup — so a fan-out that walks a large group's roster in pages builds it once per message rather than once per page. A nil *ChatMessagePush from a builder means the message's content earns no push (an unsupported content type, or a sender missing what the title needs), which is not an error.
func BuildContactDmPush ¶ added in v1.32.0
func BuildContactDmPush(ctx context.Context, ocpData ocp_data.Provider, chatId *commonpb.ChatId, message *messagingpb.Message, senderID *commonpb.UserId, senderContact *commonpb.PhoneNumber) (*ChatMessagePush, error)
BuildContactDmPush renders a new message in a contact DM. The title is a contact substitution on the sender's phone number, which the recipient's client resolves against their address book.
func BuildDmPush ¶ added in v1.33.0
func BuildDmPush(ctx context.Context, ocpData ocp_data.Provider, chatId *commonpb.ChatId, message *messagingpb.Message, senderID *commonpb.UserId, senderDisplayName string) (*ChatMessagePush, error)
BuildDmPush renders a new message in a DM (ChatType_DM). The sender is typically not in the recipient's contacts, so the title carries the sender's display name directly rather than a contact substitution — and never the sender's phone number, which is private outside contact DMs.
func BuildGroupChatPush ¶ added in v1.32.0
func BuildGroupChatPush(ctx context.Context, ocpData ocp_data.Provider, chatId *commonpb.ChatId, message *messagingpb.Message, senderID *commonpb.UserId, senderDisplayName, chatTitle string) (*ChatMessagePush, error)
BuildGroupChatPush renders a new message in a group chat. The notification is titled by the group ("Untitled Group" when it has none), with the sender identified by display name in the body ("Alice: hello"; "Alice sent a message" for encrypted content, see renderGroupChatMessagePushBody). Like a DM, a group push never carries the sender's phone number, which is private outside contact DMs.
func (*ChatMessagePush) Send ¶ added in v1.32.0
func (p *ChatMessagePush) Send(ctx context.Context, pusher Pusher, badges badge.Store, recipients ChatRecipients) error
Send delivers the push to both halves of one page of its audience: the unmuted half with each recipient's badge bumped and the new total carried on the notification, so a recipient's icon updates with the same push that announces the message rather than a second, badge-only push per recipient; the muted half flagged, unbadged, as a copy of the same payload, to Android devices only. Either half may be empty and costs nothing then. The two sends are independent, and a failure in one is reported alongside the other's. Send may be called once per page of a large audience; each call is its own token lookup, badge batch and FCM send, so what a call holds is bounded by its page.
type ChatRecipients ¶ added in v1.32.0
ChatRecipients is a chat push's audience, split by whether each recipient has the chat muted. The unmuted half receives the alert with a badge bump. The muted half receives the same payload flagged (ChatMetadata.muted) and without a badge bump, since a muted chat must not move the app icon's count — and only on Android, where the client can deliver the message quietly; the FCMPusher drops a muted recipient's iOS devices, which could not suppress the alert, so an iOS user hears nothing from a chat they muted. Which half a recipient lands in is the sender's best-effort call at send time; the client's own copy of its mute is the last word.
type CurrencyState ¶ added in v1.19.0
type CurrencyState struct {
Mint *commonpb.PublicKey
AllTimeHighSupply uint64
AllTimeHighSlot uint64
LastGainPushAt *time.Time // nil if a gain push has never been granted for the mint
}
CurrencyState captures per-currency state used to gate push notifications.
AllTimeHighSupply tracks the circulating supply (in quarks) observed at the last granted gain push, NOT a true high-water mark: it only advances when a gain push is actually granted (see CurrencyStateStore.ClaimGainPush).
type CurrencyStateStore ¶ added in v1.19.0
type CurrencyStateStore interface {
// ClaimGainPush atomically gates a "currency gain" push wave for a mint.
//
// granted is true only when both conditions hold against the currently stored
// state: (1) supply is strictly greater than the stored all-time high, and
// (2) at least cooldown has elapsed since the last granted gain push (or none
// has ever been granted). When granted, the stored all-time high (supply,
// slot) and last-gain-push timestamp are advanced to the provided values / now.
// When not granted, the stored state is left unchanged — in particular a new
// high observed during cooldown is NOT recorded.
//
// Whenever err is nil, the returned CurrencyState reflects the resulting stored
// state — the freshly written values when granted, or the existing values when
// not — so callers can populate a local cache regardless of the outcome.
ClaimGainPush(ctx context.Context, mint *commonpb.PublicKey, supply, slot uint64, cooldown time.Duration) (granted bool, state *CurrencyState, err error)
// GetCurrencyState returns the stored push state for a mint, or
// ErrCurrencyStateNotFound if none has been recorded yet.
GetCurrencyState(ctx context.Context, mint *commonpb.PublicKey) (*CurrencyState, error)
}
type FCMClient ¶
type FCMClient interface {
SendEach(ctx context.Context, messages []*messaging.Message) (*messaging.BatchResponse, error)
}
FCMClient is the subset of *messaging.Client the pusher depends on. SendEach takes one fully independent message per device, which is what lets each recipient carry its own badge; the SDK fans it out one request per message over a worker pool, exactly as it does for a multicast.
type FCMPusher ¶
type FCMPusher struct {
// contains filtered or unexported fields
}
func NewFCMPusher ¶
func NewFCMPusher(log *zap.Logger, tokens TokenStore, client FCMClient) *FCMPusher
func (*FCMPusher) SendPushes ¶ added in v0.7.0
type NoOpPusher ¶
type NoOpPusher struct{}
func (*NoOpPusher) SendPushes ¶ added in v0.7.0
func (*NoOpPusher) SendPushesWithBadges ¶ added in v1.30.0
func (n *NoOpPusher) SendPushesWithBadges(_ context.Context, _, _ string, _ *pushpb.Payload, _ BadgeResolver, _ ...*commonpb.UserId) error
type Pusher ¶
type Pusher interface {
// SendPushes sends the same notification to every device of the given users.
SendPushes(ctx context.Context, title, body string, customPayload *pushpb.Payload, users ...*commonpb.UserId) error
// SendPushesWithBadges is SendPushes with a per-user app-icon badge carried
// on the notification itself, resolved on demand for the recipients whose
// devices can display one (see BadgeResolver).
SendPushesWithBadges(ctx context.Context, title, body string, customPayload *pushpb.Payload, resolveBadges BadgeResolver, users ...*commonpb.UserId) error
}
func NewNoOpPusher ¶
func NewNoOpPusher() Pusher
type Server ¶
type Server struct {
pushpb.UnimplementedPushServer
// contains filtered or unexported fields
}
func NewServer ¶
func NewServer(log *zap.Logger, authz auth.Authorizer, tokens TokenStore) *Server
func (*Server) AddToken ¶
func (s *Server) AddToken(ctx context.Context, req *pushpb.AddTokenRequest) (*pushpb.AddTokenResponse, error)
func (*Server) DeleteTokens ¶
func (s *Server) DeleteTokens(ctx context.Context, req *pushpb.DeleteTokensRequest) (*pushpb.DeleteTokensResponse, error)
type Store ¶ added in v1.19.0
type Store interface {
TokenStore
CurrencyStateStore
}
Store is the combined push persistence surface, implemented by each backend.
type Token ¶
type Token struct {
UserID *commonpb.UserId
Type pushpb.TokenType
Token string
AppInstallID string
}
Token represents a push notification token.
Tokens are bound to a (user, device) pair, identified by the AppInstallID.
type TokenStore ¶
type TokenStore interface {
// GetTokens returns all tokens for a user.
GetTokens(ctx context.Context, userID *commonpb.UserId) ([]Token, error)
// GetTokensBatch returns all tokens for a batch of users.
GetTokensBatch(ctx context.Context, userIDs ...*commonpb.UserId) ([]Token, error)
// AddToken adds a token for a user.
//
// If the token already exists for the same user and device, it will be updated.
AddToken(ctx context.Context, userID *commonpb.UserId, appInstallID *commonpb.AppInstallId, tokenType pushpb.TokenType, token string) error
// DeleteToken deletes a token for a user.
DeleteToken(ctx context.Context, tokenType pushpb.TokenType, token string) error
// DeleteTokens deletes every given (type, token) pair in one operation. It
// exists for the pusher's cleanup of tokens FCM reports as unregistered,
// which a large send can surface many of at once. A pair that no longer
// exists is skipped, not an error.
DeleteTokens(ctx context.Context, tokens ...Token) error
// FilterUsersWithTokens returns the subset of user IDs that have at least one push token.
FilterUsersWithTokens(ctx context.Context, userIDs ...*commonpb.UserId) ([]*commonpb.UserId, error)
}