@mezo-org/passport 0.4.0-dev.5 → 0.4.0-dev.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/dist/src/api/auth.d.ts +36 -59
  2. package/dist/src/api/auth.d.ts.map +1 -1
  3. package/dist/src/api/auth.js +21 -49
  4. package/dist/src/api/auth.js.map +1 -1
  5. package/dist/src/api/client.d.ts +24 -0
  6. package/dist/src/api/client.d.ts.map +1 -0
  7. package/dist/src/api/client.js +54 -0
  8. package/dist/src/api/client.js.map +1 -0
  9. package/dist/src/api/fetch-error.d.ts +5 -0
  10. package/dist/src/api/fetch-error.d.ts.map +1 -0
  11. package/dist/src/api/fetch-error.js +8 -0
  12. package/dist/src/api/fetch-error.js.map +1 -0
  13. package/dist/src/api/index.d.ts +3 -0
  14. package/dist/src/api/index.d.ts.map +1 -0
  15. package/dist/src/api/index.js +3 -0
  16. package/dist/src/api/index.js.map +1 -0
  17. package/dist/src/api/portal.d.ts +32 -0
  18. package/dist/src/api/portal.d.ts.map +1 -0
  19. package/dist/src/api/portal.js +23 -0
  20. package/dist/src/api/portal.js.map +1 -0
  21. package/dist/src/assets/DefaultAvatar.d.ts +5 -0
  22. package/dist/src/assets/DefaultAvatar.d.ts.map +1 -0
  23. package/dist/src/assets/DefaultAvatar.js +21 -0
  24. package/dist/src/assets/DefaultAvatar.js.map +1 -0
  25. package/dist/src/components/Dropdown/AccountAddress.d.ts +8 -0
  26. package/dist/src/components/Dropdown/AccountAddress.d.ts.map +1 -0
  27. package/dist/src/components/Dropdown/AccountAddress.js +58 -0
  28. package/dist/src/components/Dropdown/AccountAddress.js.map +1 -0
  29. package/dist/src/components/Dropdown/AccountAssets.d.ts +14 -0
  30. package/dist/src/components/Dropdown/AccountAssets.d.ts.map +1 -0
  31. package/dist/src/components/Dropdown/AccountAssets.js +44 -0
  32. package/dist/src/components/Dropdown/AccountAssets.js.map +1 -0
  33. package/dist/src/components/Dropdown/AccountBalance.d.ts +7 -0
  34. package/dist/src/components/Dropdown/AccountBalance.d.ts.map +1 -0
  35. package/dist/src/components/Dropdown/AccountBalance.js +18 -0
  36. package/dist/src/components/Dropdown/AccountBalance.js.map +1 -0
  37. package/dist/src/components/Dropdown/ConnectedTrigger.d.ts +7 -0
  38. package/dist/src/components/Dropdown/ConnectedTrigger.d.ts.map +1 -0
  39. package/dist/src/components/Dropdown/ConnectedTrigger.js +30 -0
  40. package/dist/src/components/Dropdown/ConnectedTrigger.js.map +1 -0
  41. package/dist/src/components/Dropdown/Content.d.ts +8 -0
  42. package/dist/src/components/Dropdown/Content.d.ts.map +1 -0
  43. package/dist/src/components/Dropdown/Content.js +65 -0
  44. package/dist/src/components/Dropdown/Content.js.map +1 -0
  45. package/dist/src/components/Dropdown/DisconnectedTrigger.d.ts +7 -0
  46. package/dist/src/components/Dropdown/DisconnectedTrigger.d.ts.map +1 -0
  47. package/dist/src/components/Dropdown/DisconnectedTrigger.js +13 -0
  48. package/dist/src/components/Dropdown/DisconnectedTrigger.js.map +1 -0
  49. package/dist/src/components/Dropdown/Dropdown.d.ts +18 -0
  50. package/dist/src/components/Dropdown/Dropdown.d.ts.map +1 -0
  51. package/dist/src/components/Dropdown/Dropdown.js +42 -0
  52. package/dist/src/components/Dropdown/Dropdown.js.map +1 -0
  53. package/dist/src/components/Dropdown/WelcomeBlock.d.ts +8 -0
  54. package/dist/src/components/Dropdown/WelcomeBlock.d.ts.map +1 -0
  55. package/dist/src/components/Dropdown/WelcomeBlock.js +44 -0
  56. package/dist/src/components/Dropdown/WelcomeBlock.js.map +1 -0
  57. package/dist/src/components/Dropdown/index.d.ts +3 -0
  58. package/dist/src/components/Dropdown/index.d.ts.map +1 -0
  59. package/dist/src/components/Dropdown/index.js +2 -0
  60. package/dist/src/components/Dropdown/index.js.map +1 -0
  61. package/dist/src/components/index.d.ts +2 -0
  62. package/dist/src/components/index.d.ts.map +1 -0
  63. package/dist/src/components/index.js +2 -0
  64. package/dist/src/components/index.js.map +1 -0
  65. package/dist/src/hooks/constants.d.ts +1 -0
  66. package/dist/src/hooks/constants.d.ts.map +1 -1
  67. package/dist/src/hooks/constants.js +1 -0
  68. package/dist/src/hooks/constants.js.map +1 -1
  69. package/dist/src/hooks/index.d.ts +0 -1
  70. package/dist/src/hooks/index.d.ts.map +1 -1
  71. package/dist/src/hooks/index.js +0 -1
  72. package/dist/src/hooks/index.js.map +1 -1
  73. package/dist/src/hooks/useAssetsUSDConversion.d.ts +8 -0
  74. package/dist/src/hooks/useAssetsUSDConversion.d.ts.map +1 -0
  75. package/dist/src/hooks/useAssetsUSDConversion.js +21 -0
  76. package/dist/src/hooks/useAssetsUSDConversion.js.map +1 -0
  77. package/dist/src/hooks/useAuthApiClient.d.ts +1 -1
  78. package/dist/src/hooks/useAuthApiClient.d.ts.map +1 -1
  79. package/dist/src/hooks/useAuthenticateWithWallet.d.ts +12 -102
  80. package/dist/src/hooks/useAuthenticateWithWallet.d.ts.map +1 -1
  81. package/dist/src/hooks/useAuthenticateWithWallet.js +23 -11
  82. package/dist/src/hooks/useAuthenticateWithWallet.js.map +1 -1
  83. package/dist/src/hooks/useCreateAccount.d.ts +23 -173
  84. package/dist/src/hooks/useCreateAccount.d.ts.map +1 -1
  85. package/dist/src/hooks/useCreateAccount.js +7 -4
  86. package/dist/src/hooks/useCreateAccount.js.map +1 -1
  87. package/dist/src/hooks/useCreateSession.d.ts +12 -101
  88. package/dist/src/hooks/useCreateSession.d.ts.map +1 -1
  89. package/dist/src/hooks/useCreateSession.js +10 -8
  90. package/dist/src/hooks/useCreateSession.js.map +1 -1
  91. package/dist/src/hooks/useDropdownData.d.ts +44 -0
  92. package/dist/src/hooks/useDropdownData.d.ts.map +1 -0
  93. package/dist/src/hooks/useDropdownData.js +73 -0
  94. package/dist/src/hooks/useDropdownData.js.map +1 -0
  95. package/dist/src/hooks/useGetAccountByAddress.d.ts +2 -2
  96. package/dist/src/hooks/useGetAccountByAddress.d.ts.map +1 -1
  97. package/dist/src/hooks/useGetAccountByMezoId.d.ts +2 -2
  98. package/dist/src/hooks/useGetAccountByMezoId.d.ts.map +1 -1
  99. package/dist/src/hooks/useGetCurrentAccount.d.ts +16 -2
  100. package/dist/src/hooks/useGetCurrentAccount.d.ts.map +1 -1
  101. package/dist/src/hooks/useGetCurrentAccount.js +25 -3
  102. package/dist/src/hooks/useGetCurrentAccount.js.map +1 -1
  103. package/dist/src/hooks/useGetSession.d.ts +1 -1
  104. package/dist/src/hooks/useGetSession.d.ts.map +1 -1
  105. package/dist/src/hooks/useLinkAccount.d.ts +15 -175
  106. package/dist/src/hooks/useLinkAccount.d.ts.map +1 -1
  107. package/dist/src/hooks/useLinkAccount.js +7 -4
  108. package/dist/src/hooks/useLinkAccount.js.map +1 -1
  109. package/dist/src/hooks/usePortalApiClient.d.ts +2 -0
  110. package/dist/src/hooks/usePortalApiClient.d.ts.map +1 -0
  111. package/dist/src/hooks/usePortalApiClient.js +6 -0
  112. package/dist/src/hooks/usePortalApiClient.js.map +1 -0
  113. package/dist/src/hooks/useSignInWithDiscord.d.ts +12 -100
  114. package/dist/src/hooks/useSignInWithDiscord.d.ts.map +1 -1
  115. package/dist/src/hooks/useSignInWithDiscord.js +6 -3
  116. package/dist/src/hooks/useSignInWithDiscord.js.map +1 -1
  117. package/dist/src/hooks/useSignInWithWallet.d.ts +12 -100
  118. package/dist/src/hooks/useSignInWithWallet.d.ts.map +1 -1
  119. package/dist/src/hooks/useSignInWithWallet.js +2 -2
  120. package/dist/src/hooks/useSignInWithWallet.js.map +1 -1
  121. package/dist/src/hooks/useSignOut.d.ts +12 -28
  122. package/dist/src/hooks/useSignOut.d.ts.map +1 -1
  123. package/dist/src/hooks/useSignOut.js +7 -4
  124. package/dist/src/hooks/useSignOut.js.map +1 -1
  125. package/dist/src/hooks/useSignUpWithWallet.d.ts +12 -100
  126. package/dist/src/hooks/useSignUpWithWallet.d.ts.map +1 -1
  127. package/dist/src/hooks/useSignUpWithWallet.js +2 -2
  128. package/dist/src/hooks/useSignUpWithWallet.js.map +1 -1
  129. package/dist/src/hooks/useUpdateMezoId.d.ts +30 -136
  130. package/dist/src/hooks/useUpdateMezoId.d.ts.map +1 -1
  131. package/dist/src/hooks/useUpdateMezoId.js +7 -4
  132. package/dist/src/hooks/useUpdateMezoId.js.map +1 -1
  133. package/dist/src/hooks/useWalletAccount.d.ts +12 -0
  134. package/dist/src/hooks/useWalletAccount.d.ts.map +1 -0
  135. package/dist/src/hooks/useWalletAccount.js +25 -0
  136. package/dist/src/hooks/useWalletAccount.js.map +1 -0
  137. package/dist/src/index.d.ts +1 -0
  138. package/dist/src/index.d.ts.map +1 -1
  139. package/dist/src/index.js +1 -0
  140. package/dist/src/index.js.map +1 -1
  141. package/dist/src/provider.d.ts +10 -13
  142. package/dist/src/provider.d.ts.map +1 -1
  143. package/dist/src/provider.js +11 -20
  144. package/dist/src/provider.js.map +1 -1
  145. package/dist/src/utils/address.d.ts +15 -0
  146. package/dist/src/utils/address.d.ts.map +1 -0
  147. package/dist/src/utils/address.js +35 -0
  148. package/dist/src/utils/address.js.map +1 -0
  149. package/dist/src/utils/address.test.d.ts +2 -0
  150. package/dist/src/utils/address.test.d.ts.map +1 -0
  151. package/dist/src/utils/address.test.js +37 -0
  152. package/dist/src/utils/address.test.js.map +1 -0
  153. package/dist/src/utils/cryptoAssets.d.ts +28 -0
  154. package/dist/src/utils/cryptoAssets.d.ts.map +1 -0
  155. package/dist/src/utils/cryptoAssets.js +73 -0
  156. package/dist/src/utils/cryptoAssets.js.map +1 -0
  157. package/dist/src/utils/cryptoAssets.test.d.ts +2 -0
  158. package/dist/src/utils/cryptoAssets.test.d.ts.map +1 -0
  159. package/dist/src/utils/cryptoAssets.test.js +49 -0
  160. package/dist/src/utils/cryptoAssets.test.js.map +1 -0
  161. package/dist/src/utils/currency.d.ts +14 -0
  162. package/dist/src/utils/currency.d.ts.map +1 -0
  163. package/dist/src/utils/currency.js +27 -0
  164. package/dist/src/utils/currency.js.map +1 -0
  165. package/dist/src/utils/currency.test.d.ts +2 -0
  166. package/dist/src/utils/currency.test.d.ts.map +1 -0
  167. package/dist/src/utils/currency.test.js +34 -0
  168. package/dist/src/utils/currency.test.js.map +1 -0
  169. package/dist/src/utils/numbers.d.ts +43 -0
  170. package/dist/src/utils/numbers.d.ts.map +1 -0
  171. package/dist/src/utils/numbers.js +81 -0
  172. package/dist/src/utils/numbers.js.map +1 -0
  173. package/dist/src/utils/numbers.test.d.ts +2 -0
  174. package/dist/src/utils/numbers.test.d.ts.map +1 -0
  175. package/dist/src/utils/numbers.test.js +68 -0
  176. package/dist/src/utils/numbers.test.js.map +1 -0
  177. package/package.json +9 -3
  178. package/src/api/auth.ts +72 -129
  179. package/src/api/client.ts +78 -0
  180. package/src/api/fetch-error.ts +8 -0
  181. package/src/api/index.ts +2 -0
  182. package/src/api/portal.ts +56 -0
  183. package/src/assets/DefaultAvatar.tsx +74 -0
  184. package/src/components/Dropdown/AccountAddress.tsx +111 -0
  185. package/src/components/Dropdown/AccountAssets.tsx +110 -0
  186. package/src/components/Dropdown/AccountBalance.tsx +38 -0
  187. package/src/components/Dropdown/ConnectedTrigger.tsx +56 -0
  188. package/src/components/Dropdown/Content.tsx +142 -0
  189. package/src/components/Dropdown/DisconnectedTrigger.tsx +35 -0
  190. package/src/components/Dropdown/Dropdown.tsx +81 -0
  191. package/src/components/Dropdown/README.md +46 -0
  192. package/src/components/Dropdown/WelcomeBlock.tsx +92 -0
  193. package/src/components/Dropdown/index.ts +2 -0
  194. package/src/components/index.ts +1 -0
  195. package/src/hooks/constants.ts +1 -0
  196. package/src/hooks/index.ts +0 -1
  197. package/src/hooks/useAssetsUSDConversion.ts +31 -0
  198. package/src/hooks/useAuthenticateWithWallet.ts +38 -14
  199. package/src/hooks/useCreateAccount.ts +19 -5
  200. package/src/hooks/useCreateSession.ts +22 -9
  201. package/src/hooks/useDropdownData.ts +130 -0
  202. package/src/hooks/useGetAccountByAddress.ts +2 -2
  203. package/src/hooks/useGetAccountByMezoId.ts +2 -2
  204. package/src/hooks/useGetCurrentAccount.ts +46 -6
  205. package/src/hooks/useGetSession.ts +1 -1
  206. package/src/hooks/useLinkAccount.ts +18 -5
  207. package/src/hooks/usePortalApiClient.ts +6 -0
  208. package/src/hooks/useSignInWithDiscord.ts +14 -5
  209. package/src/hooks/useSignInWithWallet.ts +9 -2
  210. package/src/hooks/useSignOut.ts +18 -4
  211. package/src/hooks/useSignUpWithWallet.ts +9 -2
  212. package/src/hooks/useUpdateMezoId.ts +19 -4
  213. package/src/hooks/useWalletAccount.ts +41 -0
  214. package/src/index.ts +1 -0
  215. package/src/provider.ts +30 -37
  216. package/src/utils/address.test.ts +44 -0
  217. package/src/utils/address.ts +43 -0
  218. package/src/utils/cryptoAssets.test.ts +59 -0
  219. package/src/utils/cryptoAssets.ts +93 -0
  220. package/src/utils/currency.test.ts +38 -0
  221. package/src/utils/currency.ts +32 -0
  222. package/src/utils/numbers.test.ts +89 -0
  223. package/src/utils/numbers.ts +110 -0
package/src/api/auth.ts CHANGED
@@ -1,151 +1,88 @@
1
- type RequestHandlerOptions = Omit<RequestInit, "credentials" | "body"> & {
2
- body?: Record<string, unknown>
3
- queryParams?: Record<string, string | undefined>
4
- }
5
- type PassportIdentityProvider = "wallet" | "discord" | "email"
1
+ import { ApiClient } from "./client"
2
+ import { FetchError } from "./fetch-error"
6
3
 
7
- type AccountPublicData = {
8
- mezoId?: string
9
- btcAddress: string
4
+ type AuthProvider = "discord"
5
+
6
+ export type LinkedWalletAccount = {
7
+ type: "wallet"
8
+ btcAddress?: string
10
9
  evmAddress: string
11
10
  }
12
11
 
13
- type AuthUser = {
12
+ export type LinkedProviderAccount = {
13
+ type: AuthProvider
14
+ name: string
14
15
  id: string
15
- app_metadata: {
16
- provider: PassportIdentityProvider
17
- providers: PassportIdentityProvider[]
18
- }
19
- user_metadata: AccountPublicData
16
+ avatarUrl: string
20
17
  }
21
18
 
22
- type AuthProvider = "discord"
23
-
24
- export type LinkedAccount =
25
- | {
26
- type: "wallet"
27
- btcAddress?: string
28
- evmAddress: string
29
- }
30
- | {
31
- type: AuthProvider
32
- name: string
33
- id: string
34
- avatarUrl: string
35
- }
19
+ export type LinkedAccount = LinkedWalletAccount | LinkedProviderAccount
36
20
 
37
21
  type Account = {
38
22
  mezoId: string
39
23
  hasModifiedMezoId: boolean
40
24
  linkedAccounts: LinkedAccount[]
41
- authUser: AuthUser
42
25
  }
43
26
 
44
- type Session = {
27
+ export type Session = {
45
28
  expiresIn: number
46
29
  expiresAt: number
47
30
  sessionLinks: {
48
31
  _links: {
49
- account: "/session/account"
32
+ account: string
50
33
  }
51
34
  }
52
35
  }
53
36
 
54
- type AuthenticationProviderRedirectResponse = {
37
+ export type AuthenticationProviderRedirectResponse = {
55
38
  redirectTo: string
56
39
  }
57
40
 
58
- type WalletAccountCredentials = {
59
- type: "wallet"
41
+ type SignatureData = {
60
42
  message: string
61
43
  signature: string
62
44
  }
63
45
 
46
+ // Request and Response types
47
+ export type GetSessionResponse = Session | { nonce: string }
48
+
64
49
  export type CreateSessionRequest =
65
- | WalletAccountCredentials
50
+ | ({ type: "wallet" } & SignatureData)
66
51
  | { type: "discord" }
52
+ export type CreateSessionResponse =
53
+ | Session
54
+ | AuthenticationProviderRedirectResponse
67
55
 
68
- export type LinkAccountRequest = CreateSessionRequest
69
-
70
- export type CreateAccountRequest = WalletAccountCredentials
71
-
72
- export type GetSessionResponse = Session | { nonce: string }
56
+ export type DeleteSessionResponse = { message: string }
73
57
 
74
58
  export type GetCurrentAccountResponse = Partial<Account> | null
75
59
 
76
60
  export type GetAccountByMezoIdOrAddressResponse = {
77
61
  mezoId?: string
78
- linkedAccounts?: LinkedAccount[]
62
+ linkedAccounts?: Extract<LinkedAccount, { type: "wallet" }>[]
79
63
  }
80
64
 
81
- export const API_ENDPOINTS_BY_ENV = {
82
- mainnet: "https://api.mezo.org",
83
- testnet: "https://api.test.mezo.org",
84
- }
65
+ export type LinkAccountRequest = CreateSessionRequest
66
+ export type LinkAccountResponse =
67
+ | Account
68
+ | AuthenticationProviderRedirectResponse
85
69
 
86
- export class AuthApiClient {
87
- private apiUrl: string
70
+ export type CreateAccountRequest = { type: "wallet" } & SignatureData
71
+ export type CreateAccountResponse = Account
88
72
 
89
- constructor(apiUrl?: string) {
90
- this.apiUrl = apiUrl ?? API_ENDPOINTS_BY_ENV.mainnet
91
- }
73
+ export type UpdateMezoIdResponse = Account
92
74
 
93
- /**
94
- * The request handler for the Passport API. It accepts an API endpoint and
95
- * request options.
96
- * @dev Generic type `D` is a type of returned object from the function
97
- * @dev WARNING: This function hardcodes `credentials: "include"`, meaning
98
- * cookies and authentication headers will be sent with every request. Ensure
99
- * this is safe if you plan to use it in other contexts than auth api worker.
100
- * @param endpoint - The API endpoint to request. Should start with
101
- * forward slash ("/")
102
- * @param options - The request options, the `RequestInit` type with
103
- * additional type-safe properties
104
- * @returns The promise of the API response
105
- */
106
- protected async handleRequest<D>(
107
- endpoint: `/${string}`,
108
- options: RequestHandlerOptions,
109
- ): Promise<D> {
110
- const {
111
- method,
112
- headers,
113
- body,
114
- queryParams = {},
115
- ...restOptions
116
- } = options || {}
117
-
118
- // If last character in apiUrl is forward slash we are removing it
119
- const authApiUrlRoute = this.apiUrl.replace(/\/$/, "")
120
- const url = new URL(`${authApiUrlRoute}${endpoint}`)
121
-
122
- // Removes falsy values (e.g. null, undefined etc.) from query params and
123
- // appends remaining ones to the URL
124
- Object.entries(queryParams)
125
- .filter(([, value]) => value) // Remove falsy values
126
- .forEach(([key, value]) => url.searchParams.append(key, value!))
127
-
128
- const response = await fetch(url, {
129
- method,
130
- credentials: "include",
131
- headers: {
132
- "Content-Type": "application/json",
133
- ...headers,
134
- },
135
- body: body ? JSON.stringify(body) : undefined,
136
- ...restOptions,
137
- })
138
-
139
- const data = await response.json()
140
-
141
- if (!response.ok || data?.error) {
142
- const error =
143
- data?.error ||
144
- `An error occurred when handling API request: ${JSON.stringify(data)}`
145
- throw new Error(`Error [${response.status}]: ${error}`)
146
- }
75
+ export const AUTH_API_ENDPOINTS_BY_ENV = {
76
+ mainnet: "https://api.mezo.org",
77
+ testnet: "https://api.test.mezo.org",
78
+ }
147
79
 
148
- return data as D
80
+ export class AuthApiClient extends ApiClient {
81
+ constructor(
82
+ environment: keyof typeof AUTH_API_ENDPOINTS_BY_ENV = "mainnet",
83
+ apiUrl?: string,
84
+ ) {
85
+ super(apiUrl ?? AUTH_API_ENDPOINTS_BY_ENV[environment])
149
86
  }
150
87
 
151
88
  async getSession(code?: string) {
@@ -158,21 +95,16 @@ export class AuthApiClient {
158
95
  }
159
96
 
160
97
  async createSession(createSessionRequest: CreateSessionRequest) {
161
- const data = await this.handleRequest<Session | { redirectTo: string }>(
162
- "/session",
163
- {
164
- method: "POST",
165
- body: createSessionRequest,
166
- },
167
- )
98
+ const data = await this.handleRequest<CreateSessionResponse>("/session", {
99
+ method: "POST",
100
+ body: createSessionRequest,
101
+ })
168
102
 
169
103
  return data
170
104
  }
171
105
 
172
106
  async deleteSession() {
173
- const data = await this.handleRequest<{
174
- message: string
175
- }>("/session", {
107
+ const data = await this.handleRequest<DeleteSessionResponse>("/session", {
176
108
  method: "DELETE",
177
109
  })
178
110
 
@@ -191,29 +123,40 @@ export class AuthApiClient {
191
123
  }
192
124
 
193
125
  async getAccountByMezoIdOrAddress(mezoIdOrAddress: string) {
194
- const data = await this.handleRequest<GetAccountByMezoIdOrAddressResponse>(
195
- `/accounts/${mezoIdOrAddress}`,
196
- {
197
- method: "GET",
198
- },
199
- )
126
+ let data
127
+ try {
128
+ data = await this.handleRequest<GetAccountByMezoIdOrAddressResponse>(
129
+ `/accounts/${mezoIdOrAddress}`,
130
+ {
131
+ method: "GET",
132
+ },
133
+ )
134
+ } catch (error) {
135
+ // Return null if account is not found instead of throwing an error
136
+ if (error instanceof FetchError && error.status === 404) {
137
+ data = null
138
+ } else {
139
+ throw error
140
+ }
141
+ }
200
142
 
201
143
  return data
202
144
  }
203
145
 
204
146
  async linkAccount(linkAccountRequest: LinkAccountRequest) {
205
- const data = await this.handleRequest<
206
- Account | AuthenticationProviderRedirectResponse
207
- >("/session/account/linked-accounts", {
208
- method: "POST",
209
- body: linkAccountRequest,
210
- })
147
+ const data = await this.handleRequest<LinkAccountResponse>(
148
+ "/session/account/linked-accounts",
149
+ {
150
+ method: "POST",
151
+ body: linkAccountRequest,
152
+ },
153
+ )
211
154
 
212
155
  return data
213
156
  }
214
157
 
215
158
  async createAccount(createAccountRequest: CreateAccountRequest) {
216
- const data = await this.handleRequest<Account>("/accounts", {
159
+ const data = await this.handleRequest<CreateAccountResponse>("/accounts", {
217
160
  method: "POST",
218
161
  body: createAccountRequest,
219
162
  })
@@ -222,7 +165,7 @@ export class AuthApiClient {
222
165
  }
223
166
 
224
167
  async updateMezoId(newMezoId: string) {
225
- const data = await this.handleRequest<Partial<Account> | null>(
168
+ const data = await this.handleRequest<UpdateMezoIdResponse>(
226
169
  "/session/account",
227
170
  {
228
171
  method: "PATCH",
@@ -0,0 +1,78 @@
1
+ import { FetchError } from "./fetch-error"
2
+
3
+ type RequestHandlerOptions = Omit<RequestInit, "credentials" | "body"> & {
4
+ body?: Record<string, unknown>
5
+ queryParams?: Record<string, string | undefined>
6
+ }
7
+
8
+ export abstract class ApiClient {
9
+ private apiUrl: string
10
+
11
+ constructor(apiUrl: string) {
12
+ this.apiUrl = apiUrl
13
+ }
14
+
15
+ /**
16
+ * The request handler for the Passport API. It accepts an API endpoint and
17
+ * request options.
18
+ * @dev Generic type `D` is a type of returned object from the function
19
+ * @dev WARNING: This function hardcodes `credentials: "include"`, meaning
20
+ * cookies and authentication headers will be sent with every request. Ensure
21
+ * this is safe if you plan to use it in other contexts than auth api worker.
22
+ * @param endpoint - The API endpoint to request. Should start with
23
+ * forward slash ("/")
24
+ * @param options - The request options, the `RequestInit` type with
25
+ * additional type-safe properties
26
+ * @returns The promise of the API response
27
+ */
28
+ protected async handleRequest<D>(
29
+ endpoint: `/${string}`,
30
+ options: RequestHandlerOptions = {},
31
+ ): Promise<D> {
32
+ try {
33
+ const { method, body, queryParams = {}, ...restOptions } = options
34
+
35
+ // If last character in apiUrl is forward slash we are removing it
36
+ const authApiUrlRoute = this.apiUrl.replace(/\/$/, "")
37
+ const url = new URL(`${authApiUrlRoute}${endpoint}`)
38
+
39
+ // Removes falsy values (e.g. null, undefined etc.) from query params and
40
+ // appends remaining ones to the URL
41
+ Object.entries(queryParams)
42
+ .filter(([, value]) => value) // Remove falsy values
43
+ .forEach(([key, value]) => url.searchParams.append(key, value!))
44
+
45
+ const response = await fetch(url, {
46
+ method,
47
+ credentials: "include",
48
+ body: body ? JSON.stringify(body) : undefined,
49
+ ...restOptions,
50
+ })
51
+
52
+ const data = await response.json()
53
+
54
+ if (!response.ok || data?.error) {
55
+ const error =
56
+ data?.error ||
57
+ `An error occurred when handling API request: ${JSON.stringify(data)}`
58
+ throw new FetchError(
59
+ response.status,
60
+ `Error [${response.status}]: ${error}`,
61
+ )
62
+ }
63
+
64
+ return data as D
65
+ } catch (error) {
66
+ if (error instanceof FetchError) {
67
+ throw error
68
+ }
69
+
70
+ const errorMessage =
71
+ error instanceof Error ? error.message : JSON.stringify(error)
72
+ throw new FetchError(
73
+ 500,
74
+ `Error [500]: An error occurred when handling API request: ${errorMessage}`,
75
+ )
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,8 @@
1
+ export class FetchError extends Error {
2
+ constructor(
3
+ public status: number,
4
+ message?: string,
5
+ ) {
6
+ super(message)
7
+ }
8
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./auth"
2
+ export * from "./portal"
@@ -0,0 +1,56 @@
1
+ import { ApiClient } from "./client"
2
+
3
+ type PortalStatistics = {
4
+ hodlers: number
5
+ depositedBitcoin: string
6
+ tvl: number
7
+ currentUsdPerBtc: string
8
+ currentUsdPerEth: string
9
+ usdPerBtc24hChange: string
10
+ }
11
+
12
+ type PortalMats = {
13
+ address: string
14
+ totalMats: number
15
+ matsFromDeposits: number
16
+ matsFromReferrals: number
17
+ matsFromSecondaryReferrals: number
18
+ netMatsTransferred: number
19
+ dailyMats: number
20
+ dailyMatsFromDeposits: number
21
+ dailyMatsFromReferrals: number
22
+ dailyMatsFromSecondaryReferrals: number
23
+ }
24
+
25
+ export const PORTAL_API_ENDPOINTS_BY_ENV = {
26
+ mainnet: "https://api.mezo.org/api/v1",
27
+ testnet: "https://api.test.mezo.org/api/v1",
28
+ }
29
+
30
+ export class PortalApiClient extends ApiClient {
31
+ constructor(
32
+ environment: keyof typeof PORTAL_API_ENDPOINTS_BY_ENV = "mainnet",
33
+ apiUrl?: string,
34
+ ) {
35
+ super(apiUrl ?? PORTAL_API_ENDPOINTS_BY_ENV[environment])
36
+ }
37
+
38
+ async getPortalStatistics() {
39
+ const data = await this.handleRequest<PortalStatistics>("/statistics", {
40
+ method: "GET",
41
+ })
42
+
43
+ return data
44
+ }
45
+
46
+ async getPortalMats(address: string) {
47
+ const data = await this.handleRequest<PortalMats>(
48
+ `/accounts/${address}/mats`,
49
+ {
50
+ method: "GET",
51
+ },
52
+ )
53
+
54
+ return data
55
+ }
56
+ }
@@ -0,0 +1,74 @@
1
+ import { Block, BlockProps } from "@mezo-org/mezo-clay"
2
+ import React, { SVGProps } from "react"
3
+
4
+ function DefaultAvatar(props: SVGProps<SVGSVGElement>) {
5
+ return (
6
+ <svg viewBox="0 0 214 214" fill="none" {...props}>
7
+ <rect y="-0.478027" width="166.379" height="81.7091" fill="#FF004D" />
8
+ <rect x="166" y="-0.478027" width="48" height="82" fill="black" />
9
+ <rect
10
+ x="166.379"
11
+ y="81.231"
12
+ width="24.1044"
13
+ height="132.291"
14
+ fill="#DFFF80"
15
+ />
16
+ <rect
17
+ x="118.758"
18
+ y="81.231"
19
+ width="24.1044"
20
+ height="132.291"
21
+ fill="#FF5500"
22
+ />
23
+ <rect
24
+ x="71.1372"
25
+ y="81.231"
26
+ width="24.1044"
27
+ height="132.291"
28
+ fill="#5A59A7"
29
+ />
30
+ <rect
31
+ x="23.5166"
32
+ y="81.231"
33
+ width="24.1044"
34
+ height="132.291"
35
+ fill="#47B5FF"
36
+ />
37
+ <rect y="81.231" width="23.5165" height="132.291" fill="#A3C238" />
38
+ <rect
39
+ x="190.483"
40
+ y="81.231"
41
+ width="23.5165"
42
+ height="132.291"
43
+ fill="#6E6E70"
44
+ />
45
+ <rect
46
+ x="142.863"
47
+ y="81.231"
48
+ width="23.5165"
49
+ height="132.291"
50
+ fill="#0A3C01"
51
+ />
52
+ <rect
53
+ x="95.2417"
54
+ y="81.231"
55
+ width="23.5165"
56
+ height="132.291"
57
+ fill="#F2A91F"
58
+ />
59
+ <rect
60
+ x="47.6211"
61
+ y="81.231"
62
+ width="23.5165"
63
+ height="132.291"
64
+ fill="#6B3D01"
65
+ />
66
+ </svg>
67
+ )
68
+ }
69
+
70
+ function DefaultAvatarComponent(props: BlockProps) {
71
+ return <Block as={DefaultAvatar} {...props} />
72
+ }
73
+
74
+ export default DefaultAvatarComponent
@@ -0,0 +1,111 @@
1
+ import {
2
+ Block,
3
+ Copy03 as CopyIcon,
4
+ LinkExternal02 as LinkIcon,
5
+ ParagraphSmall,
6
+ useStyletron,
7
+ } from "@mezo-org/mezo-clay"
8
+ import React from "react"
9
+ import { useCopyToClipboard } from "usehooks-ts"
10
+ import { usePassportContext } from "../../hooks/usePassportContext"
11
+ import { getAddressExplorerUrl, trimAddress } from "../../utils/address"
12
+ import { getCryptoAsset } from "../../utils/cryptoAssets"
13
+
14
+ type AccountAddressProps = {
15
+ address: string
16
+ type: "bitcoin" | "evm"
17
+ }
18
+
19
+ // TODO: Add visual feedback on copy
20
+
21
+ export default function AccountAddress(props: AccountAddressProps) {
22
+ const { address, type } = props
23
+
24
+ const { environment } = usePassportContext()
25
+ const blockExplorerUrl = getAddressExplorerUrl(
26
+ address,
27
+ type,
28
+ environment === "testnet",
29
+ )
30
+ const trimmedAddress = trimAddress(address)
31
+ const { icon: accountIcon } = getCryptoAsset(
32
+ type === "bitcoin" ? "btc" : "eth",
33
+ )
34
+
35
+ const [, theme] = useStyletron()
36
+
37
+ const [, copy] = useCopyToClipboard()
38
+
39
+ return (
40
+ <Block
41
+ as="button"
42
+ onClick={() => copy(address)}
43
+ display="flex"
44
+ alignItems="center"
45
+ backgroundColor="transparent"
46
+ padding={`${theme.sizing.scale600} ${theme.sizing.scale500}`}
47
+ overrides={{
48
+ Block: {
49
+ style: {
50
+ borderWidth: 0,
51
+ cursor: "pointer",
52
+ ":hover": {
53
+ backgroundColor: theme.colors.backgroundTertiary,
54
+ },
55
+ },
56
+ },
57
+ }}
58
+ >
59
+ <Block as={accountIcon} size={theme.sizing.scale600} />
60
+ <Block
61
+ as="a"
62
+ marginLeft={theme.sizing.scale300}
63
+ href={blockExplorerUrl}
64
+ target="_blank"
65
+ overrides={{
66
+ Block: {
67
+ style: {
68
+ color: "inherit",
69
+ textDecoration: "none",
70
+ ":hover": {
71
+ textDecoration: "underline",
72
+ },
73
+ },
74
+ },
75
+ }}
76
+ >
77
+ <ParagraphSmall
78
+ display="flex"
79
+ alignItems="center"
80
+ margin={0}
81
+ color={theme.colors.gray800}
82
+ >
83
+ {trimmedAddress}
84
+ <LinkIcon
85
+ display="inline"
86
+ size={theme.sizing.scale550}
87
+ overrides={{
88
+ Svg: {
89
+ style: {
90
+ stroke: "currentColor",
91
+ marginLeft: theme.sizing.scale200,
92
+ },
93
+ },
94
+ }}
95
+ />
96
+ </ParagraphSmall>
97
+ </Block>
98
+ <CopyIcon
99
+ size={theme.sizing.scale550}
100
+ overrides={{
101
+ Svg: {
102
+ style: {
103
+ marginLeft: "auto",
104
+ stroke: "currentColor",
105
+ },
106
+ },
107
+ }}
108
+ />
109
+ </Block>
110
+ )
111
+ }