Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 27 additions & 0 deletions src/types/dbTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Device } from '../models/Device'
import { DeviceState, PushEvent, PushEventState } from './pushTypes'

export interface DeviceRow {
device: Device

updateEvents: (events: PushEvent[]) => Promise<void>
updateState: (state: DeviceState) => Promise<void>
}

export interface PushEventRow {
event: PushEvent

updateState: (state: PushEventState) => Promise<void>
}

export interface DbConnection {
// Background event watchers:
streamAddressBalanceEvents: () => Promise<AsyncIterableIterator<PushEventRow>>
streamPriceEvents: () => Promise<AsyncIterableIterator<PushEventRow>>
streamTxConfirmEvents: () => Promise<AsyncIterableIterator<PushEventRow>>

// Queries:
getDeviceById: (deviceId: string) => Promise<DeviceRow>
getEventsByDeviceId: (deviceId: string) => Promise<PushEventRow[]>
getEventsByLoginId: (loginId: Uint8Array) => Promise<PushEventRow[]>
}
90 changes: 90 additions & 0 deletions src/types/pushTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,93 @@ export interface ApiKey {
admin: boolean
adminsdk?: FirebaseAdminKey
}

/**
* Mutable state on a device object.
*/
export interface DeviceState {
enableLegacyPrices: boolean // For legacy v1 API.
rootLoginIds: Uint8Array[] // asArray(asBase64)
visited: Date
}

/**
* An app installed on a single phone.
*/
export interface Device extends DeviceState {
readonly appId: string
readonly created: Date
readonly deviceId: string
readonly deviceToken: string
}

//
// Events that devices or logins may subscribe to.
//

export interface AddressBalanceTrigger {
readonly type: 'address-balance'
readonly pluginId: string
readonly tokenId?: string
readonly address: string
readonly aboveAmount?: string // Satoshis or Wei or such
readonly belowAmount?: string // Satoshis or Wei or such
}

export interface PriceChangeTrigger {
readonly type: 'price-change'
readonly pluginId: string
readonly tokenId?: string
readonly dailyChange?: number // Percentage
readonly hourlyChange?: number // Percentage
}

export interface PriceLevelTrigger {
readonly type: 'price-level'
readonly currencyPair: string // From our rates server
readonly aboveRate?: number
readonly belowRate?: number
}

export interface TxConfirmTrigger {
readonly type: 'tx-confirm'
readonly pluginId: string
readonly confirmations: number
readonly txid: string
}

export type PushTrigger =
| AddressBalanceTrigger
| PriceChangeTrigger
| PriceLevelTrigger
| TxConfirmTrigger

/**
* Mutable flags that we can toggle on a push event.
*/
export interface PushEventState {
active: boolean // Watch the trigger when true
triggered?: Date
broadcasted?: Date
pushed?: Date
}

/**
* An action to perform once a trigger takes place.
*/
export interface PushEvent extends PushEventState {
readonly eventId?: string
readonly deviceId?: string
readonly loginId?: Uint8Array

readonly broadcast?: Array<{
pluginId: string
rawTx: Uint8Array // asBase64
}>
readonly push?: {
title?: string
body?: string
data: { [key: string]: string } // JSON to push to device
}
readonly trigger: PushTrigger
}
125 changes: 125 additions & 0 deletions src/types/v2Types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
export interface Device {
appId: string
deviceId: string
deviceToken: string
rootLoginIds: Uint8Array[] // asArray(asBase64)
created: Date
visited: Date
}

interface PriceChangeTrigger {
type: 'price-change'
pluginId: string
tokenId?: string
aboveRatio?: number // 1.1 for +10%
belowRatio?: number // 0.9 for -10%
range: 'hourly' | 'daily'
}

interface PriceLevelTrigger {
type: 'price-level'
currencyPair: string // From our rates server
aboveRate?: number
belowRate?: number
}

interface AddressBalanceTrigger {
type: 'address-balance'
pluginId: string
tokenId?: string
address: string
aboveAmount?: string // Satoshis or Wei or such
belowAmount?: string // Satoshis or Wei or such
}

interface TxConfirmTrigger {
type: 'tx-confirm'
pluginId: string
confirmations: number
txid: string
}

export type PushTrigger =
| AddressBalanceTrigger
| PriceChangeTrigger
| PriceLevelTrigger
| TxConfirmTrigger

interface PushEvent {
trigger: PushTrigger
triggered: boolean

// TODO: Check firebase docs
pushMessage?: string
pushPayload?: unknown // JSON to push to device
broadcastTxs?: Array<{
pluginId: string
rawTx: Uint8Array // asBase64
}>
}

export interface PushRequestBody {
// The request payload:
data: unknown

// Who is making the request:
apiKey: string
appId: string
deviceId: string

// For logins:
rootLoginId?: Uint8Array
// rootSecretHash?: Uint8Array
}

/**
* Refreshes the `visited` date on a device and its effects or logins.
* Devices expire after 3 months.
* POST /v2/device/checkin
*/

/**
* Registers / updates a device.
* POST /v2/device/update
*/
export interface UpdateDevicePayload {
rootLoginIds: Uint8Array[] // asArray(asBase64)
events: PushEvent[]
deviceToken: string
}

/**
* Gets a device from the database.
* POST /v2/device
*/
export interface DevicePayload {
deviceId: string
deviceToken: string
events: PushEvent[]
rootLoginIds: Uint8Array[] // asArray(asBase64)
created: Date
visited: Date
}

/**
* Registers / updates a login.
* POST /v2/login/update
*/
export interface UpdateLoginPayload {
events: PushEvent[]

// removeEvents?: string[]
// replaceEvents?: PushEvent[]
// newEvents?: PushEvent[]
}

/**
* Reads a login from the database.
* POST /v2/login
*/
export interface LoginPayload {
deviceIds: string
events: PushEvent[]
created: Date
visited: Date
}