import { ApiClient } from "./client" import { FetchError } from "./fetch-error" type AuthProvider = "discord" export type LinkedWalletAccount = { type: "wallet" btcAddress?: string evmAddress: string } export type LinkedProviderAccount = { type: AuthProvider name: string id: string avatarUrl: string } export type LinkedAccount = LinkedWalletAccount | LinkedProviderAccount type UserDocumentStatus = { acceptedVersion?: string acceptedAt?: string isCurrentVersionAccepted: boolean } export type DocumentType = "termsOfUse" | "privacyPolicy" type Account = { mezoId: string hasModifiedMezoId: boolean linkedAccounts: LinkedAccount[] documents?: Record email?: string telegram?: string } export type Session = { expiresIn: number expiresAt: number sessionLinks: { _links: { account: string } } } export type AuthenticationProviderRedirectResponse = { redirectTo: string } export type SignatureData = { message: string signature: string } // Request and Response types export type GetSessionResponse = Session | { nonce: string } export type CreateSessionRequest = | ({ type: "wallet" } & SignatureData) | { type: "discord" } export type CreateSessionResponse = | Session | AuthenticationProviderRedirectResponse export type DeleteSessionResponse = { message: string } export type GetCurrentAccountResponse = Partial | null export type GetAccountByMezoIdOrAddressResponse = { mezoId?: string linkedAccounts?: Extract[] } export type LinkAccountRequest = CreateAccountRequest | { type: "discord" } export type LinkAccountResponse = | Account | AuthenticationProviderRedirectResponse export type CreateAccountRequest = { type: "wallet" } & SignatureData & { bitcoinPublicKey?: string } export type CreateAccountResponse = Account export type UpdateMezoIdResponse = Account export type AcceptDocumentsResponse = Account export type GetDocumentVersionsResponse = Record< DocumentType, { version: string | null } > export type AcceptDocumentsRequest = Partial< Record > export type UpdateAccountRequest = { mezoId?: string email?: string telegram?: string } export type UpdateAccountResponse = Account export const AUTH_API_ENDPOINTS_BY_ENV = { mainnet: "https://api.mezo.org", testnet: "https://api.test.mezo.org", } export class AuthApiClient extends ApiClient { constructor( environment: keyof typeof AUTH_API_ENDPOINTS_BY_ENV = "mainnet", apiUrl?: string, ) { super({ apiUrl: apiUrl ?? AUTH_API_ENDPOINTS_BY_ENV[environment], }) } async getSession(code?: string) { const data = await this.handleRequest("/session", { method: "GET", queryParams: { code }, }) return data } async createSession(createSessionRequest: CreateSessionRequest) { const data = await this.handleRequest("/session", { method: "POST", body: createSessionRequest, }) return data } async deleteSession() { const data = await this.handleRequest("/session", { method: "DELETE", }) return data } async getCurrentAccount() { const data = await this.handleRequest( "/session/account", { method: "GET", }, ) return data } async getAccountByMezoIdOrAddress(mezoIdOrAddress: string) { let data try { data = await this.handleRequest( `/accounts/${mezoIdOrAddress}`, { method: "GET", }, ) } catch (error) { // Return null if account is not found instead of throwing an error if (error instanceof FetchError && error.status === 404) { data = null } else { throw error } } return data } async linkAccount(linkAccountRequest: LinkAccountRequest) { const data = await this.handleRequest( "/session/account/linked-accounts", { method: "POST", body: linkAccountRequest, }, ) return data } async createAccount(createAccountRequest: CreateAccountRequest) { const data = await this.handleRequest("/accounts", { method: "POST", body: createAccountRequest, }) return data } async updateMezoId(newMezoId: string) { const data = await this.handleRequest( "/session/account", { method: "PATCH", body: { mezoId: newMezoId }, }, ) return data } async acceptDocuments(payload: AcceptDocumentsRequest) { const data = await this.handleRequest( "/session/account", { method: "PATCH", body: { documents: payload }, }, ) return data } async getDocumentVersions() { const data = await this.handleRequest( "/documents", { method: "GET", }, ) return data } async updateAccount(updates: UpdateAccountRequest) { const data = await this.handleRequest( "/session/account", { method: "PATCH", body: updates, }, ) return data } }