tapimo 0.5.2 → 0.6.0
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.
- package/dist/App.d.ts +13987 -5755
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js.map +1 -1
- package/dist/admin/App.d.ts +910 -412
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +4 -0
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/early-access.d.ts +148 -0
- package/dist/admin/apps/early-access.d.ts.map +1 -0
- package/dist/admin/apps/early-access.js +133 -0
- package/dist/admin/apps/early-access.js.map +1 -0
- package/dist/admin/apps/verified-tokens.d.ts +643 -118
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +214 -1
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +45 -33
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/apps/data/App.d.ts +3733 -2428
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +11 -6
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.d.ts +34 -1
- package/dist/apps/data/FundingQuoteProviders.d.ts.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.js +193 -2
- package/dist/apps/data/FundingQuoteProviders.js.map +1 -1
- package/dist/apps/data/FxOracle.d.ts +71 -0
- package/dist/apps/data/FxOracle.d.ts.map +1 -0
- package/dist/apps/data/FxOracle.js +97 -0
- package/dist/apps/data/FxOracle.js.map +1 -0
- package/dist/apps/data/index.d.ts +1 -0
- package/dist/apps/data/index.d.ts.map +1 -1
- package/dist/apps/data/index.js +1 -0
- package/dist/apps/data/index.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +3575 -1358
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +230 -88
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +963 -342
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/addresses.js +11 -9
- package/dist/apps/data/routes/addresses.js.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +108 -57
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +88 -45
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +169 -169
- package/dist/apps/data/routes/exchanges.d.ts +952 -201
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +518 -76
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +24 -24
- package/dist/apps/data/routes/funding.d.ts +8 -2
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +32 -6
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +5 -5
- package/dist/apps/data/routes/receipts.d.ts +392 -315
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +152 -77
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +166 -173
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +14 -12
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +277 -536
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +96 -77
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +82 -17
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +70 -13
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +307 -0
- package/dist/apps/data/routes/valuation.d.ts.map +1 -0
- package/dist/apps/data/routes/valuation.js +292 -0
- package/dist/apps/data/routes/valuation.js.map +1 -0
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/verified-tokens.js +7 -5
- package/dist/apps/data/routes/verified-tokens.js.map +1 -1
- package/dist/apps/data/routes/webhooks.d.ts +459 -479
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +124 -25
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/index.d.ts +1 -1
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +1 -1
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/management/App.d.ts +8606 -1681
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +12 -1
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +23 -0
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +5 -3
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +88 -48
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +10 -2
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +218 -0
- package/dist/apps/management/routes/faucet.d.ts.map +1 -0
- package/dist/apps/management/routes/faucet.js +139 -0
- package/dist/apps/management/routes/faucet.js.map +1 -0
- package/dist/apps/management/routes/invitations.d.ts +121 -121
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +3 -0
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +197 -168
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
- package/dist/apps/management/routes/invite-links.js +26 -1
- package/dist/apps/management/routes/invite-links.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +2 -0
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +4 -0
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +49 -49
- package/dist/apps/management/routes/orgs.d.ts +91 -91
- package/dist/apps/management/routes/projects.d.ts +115 -115
- package/dist/apps/management/routes/usage.d.ts +35 -32
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +4 -0
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +697 -0
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -0
- package/dist/apps/management/routes/verified-token-requests.js +271 -0
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -0
- package/dist/apps/management/routes/webhooks.d.ts +6977 -0
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -0
- package/dist/apps/management/routes/webhooks.js +573 -0
- package/dist/apps/management/routes/webhooks.js.map +1 -0
- package/dist/apps/mcp.d.ts +9 -2
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +9 -4
- package/dist/apps/mcp.js.map +1 -1
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +7 -2
- package/dist/cli/Cli.js.map +1 -1
- package/dist/db/Db.d.ts +4 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +83 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +41 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +45 -0
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earlyAccess.d.ts +50 -0
- package/dist/db/tables/earlyAccess.d.ts.map +1 -0
- package/dist/db/tables/earlyAccess.js +63 -0
- package/dist/db/tables/earlyAccess.js.map +1 -0
- package/dist/db/tables/invitations.d.ts +12 -1
- package/dist/db/tables/invitations.d.ts.map +1 -1
- package/dist/db/tables/invitations.js +23 -0
- package/dist/db/tables/invitations.js.map +1 -1
- package/dist/db/tables/inviteLinks.d.ts +10 -2
- package/dist/db/tables/inviteLinks.d.ts.map +1 -1
- package/dist/db/tables/inviteLinks.js +10 -1
- package/dist/db/tables/inviteLinks.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +2 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +2 -0
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.d.ts +94 -0
- package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -0
- package/dist/db/tables/verifiedTokenRequests.js +120 -0
- package/dist/db/tables/verifiedTokenRequests.js.map +1 -0
- package/dist/db/tables/webhookSubscriptions.d.ts +14 -0
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +16 -0
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/internal/Auth.d.ts +43 -2
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +60 -45
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/FundingQuotes.d.ts +69 -15
- package/dist/internal/FundingQuotes.d.ts.map +1 -1
- package/dist/internal/FundingQuotes.js +74 -25
- package/dist/internal/FundingQuotes.js.map +1 -1
- package/dist/internal/Log.d.ts +19 -1
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +2 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +9 -0
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +2 -2
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +3 -0
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Schema.d.ts +14 -5
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +23 -5
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Value.d.ts +18 -0
- package/dist/internal/Value.d.ts.map +1 -1
- package/dist/internal/Value.js +11 -1
- package/dist/internal/Value.js.map +1 -1
- package/dist/internal/VerifiedTokens.d.ts.map +1 -1
- package/dist/internal/VerifiedTokens.js +10 -1
- package/dist/internal/VerifiedTokens.js.map +1 -1
- package/dist/internal/Viem.d.ts +1 -1
- package/dist/internal/Webhooks.d.ts +24 -3
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +34 -8
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +2 -2
- package/src/App.ts +9 -1
- package/src/Client.test-d.ts +638 -6
- package/src/admin/App.ts +4 -0
- package/src/admin/apps/early-access.test.ts +125 -0
- package/src/admin/apps/early-access.ts +175 -0
- package/src/admin/apps/verified-tokens.test.ts +201 -0
- package/src/admin/apps/verified-tokens.ts +532 -286
- package/src/admin/ui/plugin.ts +2 -1
- package/src/admin/ui/src/lib/early-access.ts +63 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +79 -0
- package/src/admin/ui/src/routeTree.gen.ts +33 -2
- package/src/admin/ui/src/routes/__root.tsx +2 -1
- package/src/admin/ui/src/routes/early-access.tsx +157 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +230 -19
- package/src/admin/ui.generated.ts +48 -33
- package/src/apps/data/App.ts +22 -14
- package/src/apps/data/FundingQuoteProviders.test.ts +298 -0
- package/src/apps/data/FundingQuoteProviders.ts +257 -4
- package/src/apps/data/FxOracle.test.ts +118 -0
- package/src/apps/data/FxOracle.ts +153 -0
- package/src/apps/data/index.ts +1 -0
- package/src/apps/data/routes/activities.test.ts +173 -3
- package/src/apps/data/routes/activities.ts +403 -132
- package/src/apps/data/routes/addresses.ts +19 -9
- package/src/apps/data/routes/balances.test.ts +144 -11
- package/src/apps/data/routes/balances.ts +140 -51
- package/src/apps/data/routes/exchanges.test.ts +540 -9
- package/src/apps/data/routes/exchanges.ts +690 -103
- package/src/apps/data/routes/funding.test.ts +84 -0
- package/src/apps/data/routes/funding.ts +38 -6
- package/src/apps/data/routes/receipts.test.ts +125 -23
- package/src/apps/data/routes/receipts.ts +205 -100
- package/src/apps/data/routes/tokens.test.ts +43 -0
- package/src/apps/data/routes/tokens.ts +27 -12
- package/src/apps/data/routes/transactions.test.ts +72 -19
- package/src/apps/data/routes/transactions.ts +162 -92
- package/src/apps/data/routes/transfers.test.ts +146 -4
- package/src/apps/data/routes/transfers.ts +91 -13
- package/src/apps/data/routes/valuation.test.ts +422 -0
- package/src/apps/data/routes/valuation.ts +423 -0
- package/src/apps/data/routes/verified-tokens.ts +14 -2
- package/src/apps/data/routes/webhooks.test.ts +56 -8
- package/src/apps/data/routes/webhooks.ts +144 -27
- package/src/apps/index.ts +1 -1
- package/src/apps/management/App.ts +13 -0
- package/src/apps/management/routes/api-keys.test.ts +87 -0
- package/src/apps/management/routes/api-keys.ts +4 -3
- package/src/apps/management/routes/billing.test.ts +112 -1
- package/src/apps/management/routes/billing.ts +7 -2
- package/src/apps/management/routes/faucet.test.ts +79 -0
- package/src/apps/management/routes/faucet.ts +185 -0
- package/src/apps/management/routes/invitations.test.ts +172 -0
- package/src/apps/management/routes/invitations.ts +3 -0
- package/src/apps/management/routes/invite-links.test.ts +117 -0
- package/src/apps/management/routes/invite-links.ts +43 -1
- package/src/apps/management/routes/me.test.ts +140 -88
- package/src/apps/management/routes/me.ts +6 -0
- package/src/apps/management/routes/usage.test.ts +6 -0
- package/src/apps/management/routes/usage.ts +7 -0
- package/src/apps/management/routes/verified-token-requests.test.ts +377 -0
- package/src/apps/management/routes/verified-token-requests.ts +397 -0
- package/src/apps/management/routes/webhooks.test.ts +426 -0
- package/src/apps/management/routes/webhooks.ts +672 -0
- package/src/apps/mcp.test.ts +13 -0
- package/src/apps/mcp.ts +18 -5
- package/src/cli/Cli.test.ts +36 -0
- package/src/cli/Cli.ts +7 -2
- package/src/db/Db.test.ts +19 -0
- package/src/db/Db.ts +95 -0
- package/src/db/Schema.ts +53 -0
- package/src/db/tables/earlyAccess.ts +86 -0
- package/src/db/tables/invitations.ts +26 -1
- package/src/db/tables/inviteLinks.ts +22 -3
- package/src/db/tables/sponsoredTransactions.ts +4 -0
- package/src/db/tables/verifiedTokenRequests.test.ts +200 -0
- package/src/db/tables/verifiedTokenRequests.ts +182 -0
- package/src/db/tables/webhookSubscriptions.ts +31 -0
- package/src/internal/Auth.ts +73 -45
- package/src/internal/FundingQuotes.test.ts +143 -1
- package/src/internal/FundingQuotes.ts +95 -28
- package/src/internal/Log.test-d.ts +21 -0
- package/src/internal/Log.test.ts +50 -0
- package/src/internal/Log.ts +24 -1
- package/src/internal/MetricSink.test.ts +160 -0
- package/src/internal/MetricSink.ts +10 -0
- package/src/internal/OpenApi.ts +3 -0
- package/src/internal/Schema.ts +50 -5
- package/src/internal/Value.test.ts +20 -0
- package/src/internal/Value.ts +24 -1
- package/src/internal/VerifiedTokens.ts +9 -1
- package/src/internal/Webhooks.test.ts +140 -0
- package/src/internal/Webhooks.ts +53 -9
package/src/admin/ui/plugin.ts
CHANGED
|
@@ -23,7 +23,8 @@ const outFile = path.join(here, '..', 'ui.generated.ts')
|
|
|
23
23
|
// Total gzipped budget for the whole UI; the React + TanStack + Regen baseline
|
|
24
24
|
// is heavier than a hand-rolled SPA, so fail loudly before it bloats the
|
|
25
25
|
// package. Raise deliberately (and revisit code-splitting) if it trips.
|
|
26
|
-
|
|
26
|
+
// Raised from 405 KB for the early-access page.
|
|
27
|
+
const maxGzipBytes = 415_000
|
|
27
28
|
|
|
28
29
|
const contentTypes: Record<string, string> = {
|
|
29
30
|
'.css': 'text/css; charset=utf-8',
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as ReactQuery from '@tanstack/react-query'
|
|
2
|
+
import type { InferResponseType } from 'hono/client'
|
|
3
|
+
|
|
4
|
+
import { client } from './client'
|
|
5
|
+
|
|
6
|
+
/** A stored allowlist entry (domain or exact email) from the list endpoint. */
|
|
7
|
+
export type Entry = InferResponseType<(typeof client)['early-access']['$get'], 200>['data'][number]
|
|
8
|
+
|
|
9
|
+
/** List early-access allowlist entries. */
|
|
10
|
+
export namespace list {
|
|
11
|
+
export const key = ['early-access'] as const
|
|
12
|
+
export async function fn() {
|
|
13
|
+
const response = await client['early-access'].$get()
|
|
14
|
+
if (!response.ok) throw new Error('Failed to load entries.')
|
|
15
|
+
return response.json()
|
|
16
|
+
}
|
|
17
|
+
export function options() {
|
|
18
|
+
return ReactQuery.queryOptions({ queryFn: fn, queryKey: key, staleTime: 30_000 })
|
|
19
|
+
}
|
|
20
|
+
export function useQuery() {
|
|
21
|
+
return ReactQuery.useQuery(options())
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Add an allowlist entry: a bare domain or a full email. */
|
|
26
|
+
export namespace add {
|
|
27
|
+
export type Input = { entry: string }
|
|
28
|
+
export async function fn(input: Input) {
|
|
29
|
+
const response = await client['early-access'].$post({ json: input })
|
|
30
|
+
if (!response.ok) throw new Error(await errorMessage(response, 'Failed to add entry.'))
|
|
31
|
+
return response.json()
|
|
32
|
+
}
|
|
33
|
+
export function useMutation() {
|
|
34
|
+
const queryClient = ReactQuery.useQueryClient()
|
|
35
|
+
return ReactQuery.useMutation({
|
|
36
|
+
mutationFn: fn,
|
|
37
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: list.key }),
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Remove an allowlist entry. */
|
|
43
|
+
export namespace remove {
|
|
44
|
+
export type Input = { entry: string }
|
|
45
|
+
export async function fn({ entry }: Input) {
|
|
46
|
+
const response = await client['early-access'].$delete({ json: { entry } })
|
|
47
|
+
if (!response.ok) throw new Error(await errorMessage(response, 'Failed to remove entry.'))
|
|
48
|
+
return response.json()
|
|
49
|
+
}
|
|
50
|
+
export function useMutation() {
|
|
51
|
+
const queryClient = ReactQuery.useQueryClient()
|
|
52
|
+
return ReactQuery.useMutation({
|
|
53
|
+
mutationFn: fn,
|
|
54
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: list.key }),
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Server error-envelope message, with a fallback for non-JSON bodies. */
|
|
60
|
+
async function errorMessage(response: { json(): Promise<unknown> }, fallback: string) {
|
|
61
|
+
const body = (await response.json().catch(() => null)) as { error?: { message?: string } } | null
|
|
62
|
+
return body?.error?.message ?? fallback
|
|
63
|
+
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import * as ReactQuery from '@tanstack/react-query'
|
|
2
2
|
import type { InferRequestType, InferResponseType } from 'hono/client'
|
|
3
|
+
import * as z from 'zod/mini'
|
|
3
4
|
|
|
4
5
|
import { client } from './client'
|
|
5
6
|
|
|
7
|
+
/** Route search: the active page tab. */
|
|
8
|
+
export const search = z.object({
|
|
9
|
+
tab: z.catch(z.optional(z.enum(['pending', 'verified'])), undefined),
|
|
10
|
+
})
|
|
11
|
+
|
|
6
12
|
/** The verified-token list endpoint's success body. */
|
|
7
13
|
type ListResponse = InferResponseType<(typeof client)['verified-tokens']['$get'], 200>
|
|
8
14
|
|
|
@@ -67,6 +73,79 @@ export namespace create {
|
|
|
67
73
|
}
|
|
68
74
|
}
|
|
69
75
|
|
|
76
|
+
/** Review queue over organization verification requests. */
|
|
77
|
+
export namespace requests {
|
|
78
|
+
/** A verification request record from the queue endpoint. */
|
|
79
|
+
export type VerifiedTokenRequest = InferResponseType<
|
|
80
|
+
(typeof client)['verified-tokens']['requests']['$get'],
|
|
81
|
+
200
|
|
82
|
+
>['data'][number]
|
|
83
|
+
|
|
84
|
+
export namespace list {
|
|
85
|
+
export function key() {
|
|
86
|
+
return ['verified-token-requests'] as const
|
|
87
|
+
}
|
|
88
|
+
export async function fn() {
|
|
89
|
+
const response = await client['verified-tokens'].requests.$get({ query: {} })
|
|
90
|
+
if (!response.ok) throw new Error('Failed to load requests.')
|
|
91
|
+
return response.json()
|
|
92
|
+
}
|
|
93
|
+
export function options() {
|
|
94
|
+
return ReactQuery.queryOptions({ queryFn: fn, queryKey: key(), staleTime: 30_000 })
|
|
95
|
+
}
|
|
96
|
+
export function useQuery() {
|
|
97
|
+
return ReactQuery.useQuery(options())
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export namespace approve {
|
|
102
|
+
export type Input = { chainId: number; requestId: string }
|
|
103
|
+
export async function fn({ requestId }: Input) {
|
|
104
|
+
const response = await client['verified-tokens'].requests[':requestId'].approve.$post({
|
|
105
|
+
param: { requestId },
|
|
106
|
+
})
|
|
107
|
+
if (!response.ok) throw new Error(await errorMessage(response, 'Failed to approve request.'))
|
|
108
|
+
return response.json()
|
|
109
|
+
}
|
|
110
|
+
export function useMutation() {
|
|
111
|
+
const queryClient = ReactQuery.useQueryClient()
|
|
112
|
+
return ReactQuery.useMutation({
|
|
113
|
+
mutationFn: fn,
|
|
114
|
+
onSuccess: (_data, input) => {
|
|
115
|
+
void queryClient.invalidateQueries({ queryKey: list.key() })
|
|
116
|
+
// Approval publishes the token onto the chain's verified list.
|
|
117
|
+
void queryClient.invalidateQueries({ queryKey: get.key({ chainId: input.chainId }) })
|
|
118
|
+
},
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export namespace deny {
|
|
124
|
+
export type Input = { requestId: string; reviewNote?: string }
|
|
125
|
+
export async function fn({ requestId, reviewNote }: Input) {
|
|
126
|
+
const response = await client['verified-tokens'].requests[':requestId'].deny.$post({
|
|
127
|
+
json: reviewNote ? { reviewNote } : {},
|
|
128
|
+
param: { requestId },
|
|
129
|
+
})
|
|
130
|
+
if (!response.ok) throw new Error(await errorMessage(response, 'Failed to deny request.'))
|
|
131
|
+
return response.json()
|
|
132
|
+
}
|
|
133
|
+
export function useMutation() {
|
|
134
|
+
const queryClient = ReactQuery.useQueryClient()
|
|
135
|
+
return ReactQuery.useMutation({
|
|
136
|
+
mutationFn: fn,
|
|
137
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: list.key() }),
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Server error-envelope message, with a fallback for non-JSON bodies. */
|
|
144
|
+
async function errorMessage(response: { json(): Promise<unknown> }, fallback: string) {
|
|
145
|
+
const body = (await response.json().catch(() => null)) as { error?: { message?: string } } | null
|
|
146
|
+
return body?.error?.message ?? fallback
|
|
147
|
+
}
|
|
148
|
+
|
|
70
149
|
/** Remove a verified token from a chain. */
|
|
71
150
|
export namespace remove {
|
|
72
151
|
export type Input = { address: `0x${string}`; chainId: number }
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { Route as rootRouteImport } from './routes/__root'
|
|
12
12
|
import { Route as VerifiedTokensRouteImport } from './routes/verified-tokens'
|
|
13
13
|
import { Route as OrganizationsRouteImport } from './routes/organizations'
|
|
14
|
+
import { Route as EarlyAccessRouteImport } from './routes/early-access'
|
|
14
15
|
import { Route as ApiKeysRouteImport } from './routes/api-keys'
|
|
15
16
|
import { Route as IndexRouteImport } from './routes/index'
|
|
16
17
|
import { Route as OrganizationsOrgIdRouteImport } from './routes/organizations_.$orgId'
|
|
@@ -25,6 +26,11 @@ const OrganizationsRoute = OrganizationsRouteImport.update({
|
|
|
25
26
|
path: '/organizations',
|
|
26
27
|
getParentRoute: () => rootRouteImport,
|
|
27
28
|
} as any)
|
|
29
|
+
const EarlyAccessRoute = EarlyAccessRouteImport.update({
|
|
30
|
+
id: '/early-access',
|
|
31
|
+
path: '/early-access',
|
|
32
|
+
getParentRoute: () => rootRouteImport,
|
|
33
|
+
} as any)
|
|
28
34
|
const ApiKeysRoute = ApiKeysRouteImport.update({
|
|
29
35
|
id: '/api-keys',
|
|
30
36
|
path: '/api-keys',
|
|
@@ -44,6 +50,7 @@ const OrganizationsOrgIdRoute = OrganizationsOrgIdRouteImport.update({
|
|
|
44
50
|
export interface FileRoutesByFullPath {
|
|
45
51
|
'/': typeof IndexRoute
|
|
46
52
|
'/api-keys': typeof ApiKeysRoute
|
|
53
|
+
'/early-access': typeof EarlyAccessRoute
|
|
47
54
|
'/organizations': typeof OrganizationsRoute
|
|
48
55
|
'/verified-tokens': typeof VerifiedTokensRoute
|
|
49
56
|
'/organizations/$orgId': typeof OrganizationsOrgIdRoute
|
|
@@ -51,6 +58,7 @@ export interface FileRoutesByFullPath {
|
|
|
51
58
|
export interface FileRoutesByTo {
|
|
52
59
|
'/': typeof IndexRoute
|
|
53
60
|
'/api-keys': typeof ApiKeysRoute
|
|
61
|
+
'/early-access': typeof EarlyAccessRoute
|
|
54
62
|
'/organizations': typeof OrganizationsRoute
|
|
55
63
|
'/verified-tokens': typeof VerifiedTokensRoute
|
|
56
64
|
'/organizations/$orgId': typeof OrganizationsOrgIdRoute
|
|
@@ -59,19 +67,33 @@ export interface FileRoutesById {
|
|
|
59
67
|
__root__: typeof rootRouteImport
|
|
60
68
|
'/': typeof IndexRoute
|
|
61
69
|
'/api-keys': typeof ApiKeysRoute
|
|
70
|
+
'/early-access': typeof EarlyAccessRoute
|
|
62
71
|
'/organizations': typeof OrganizationsRoute
|
|
63
72
|
'/verified-tokens': typeof VerifiedTokensRoute
|
|
64
73
|
'/organizations_/$orgId': typeof OrganizationsOrgIdRoute
|
|
65
74
|
}
|
|
66
75
|
export interface FileRouteTypes {
|
|
67
76
|
fileRoutesByFullPath: FileRoutesByFullPath
|
|
68
|
-
fullPaths:
|
|
77
|
+
fullPaths:
|
|
78
|
+
| '/'
|
|
79
|
+
| '/api-keys'
|
|
80
|
+
| '/early-access'
|
|
81
|
+
| '/organizations'
|
|
82
|
+
| '/verified-tokens'
|
|
83
|
+
| '/organizations/$orgId'
|
|
69
84
|
fileRoutesByTo: FileRoutesByTo
|
|
70
|
-
to:
|
|
85
|
+
to:
|
|
86
|
+
| '/'
|
|
87
|
+
| '/api-keys'
|
|
88
|
+
| '/early-access'
|
|
89
|
+
| '/organizations'
|
|
90
|
+
| '/verified-tokens'
|
|
91
|
+
| '/organizations/$orgId'
|
|
71
92
|
id:
|
|
72
93
|
| '__root__'
|
|
73
94
|
| '/'
|
|
74
95
|
| '/api-keys'
|
|
96
|
+
| '/early-access'
|
|
75
97
|
| '/organizations'
|
|
76
98
|
| '/verified-tokens'
|
|
77
99
|
| '/organizations_/$orgId'
|
|
@@ -80,6 +102,7 @@ export interface FileRouteTypes {
|
|
|
80
102
|
export interface RootRouteChildren {
|
|
81
103
|
IndexRoute: typeof IndexRoute
|
|
82
104
|
ApiKeysRoute: typeof ApiKeysRoute
|
|
105
|
+
EarlyAccessRoute: typeof EarlyAccessRoute
|
|
83
106
|
OrganizationsRoute: typeof OrganizationsRoute
|
|
84
107
|
VerifiedTokensRoute: typeof VerifiedTokensRoute
|
|
85
108
|
OrganizationsOrgIdRoute: typeof OrganizationsOrgIdRoute
|
|
@@ -101,6 +124,13 @@ declare module '@tanstack/react-router' {
|
|
|
101
124
|
preLoaderRoute: typeof OrganizationsRouteImport
|
|
102
125
|
parentRoute: typeof rootRouteImport
|
|
103
126
|
}
|
|
127
|
+
'/early-access': {
|
|
128
|
+
id: '/early-access'
|
|
129
|
+
path: '/early-access'
|
|
130
|
+
fullPath: '/early-access'
|
|
131
|
+
preLoaderRoute: typeof EarlyAccessRouteImport
|
|
132
|
+
parentRoute: typeof rootRouteImport
|
|
133
|
+
}
|
|
104
134
|
'/api-keys': {
|
|
105
135
|
id: '/api-keys'
|
|
106
136
|
path: '/api-keys'
|
|
@@ -128,6 +158,7 @@ declare module '@tanstack/react-router' {
|
|
|
128
158
|
const rootRouteChildren: RootRouteChildren = {
|
|
129
159
|
IndexRoute: IndexRoute,
|
|
130
160
|
ApiKeysRoute: ApiKeysRoute,
|
|
161
|
+
EarlyAccessRoute: EarlyAccessRoute,
|
|
131
162
|
OrganizationsRoute: OrganizationsRoute,
|
|
132
163
|
VerifiedTokensRoute: VerifiedTokensRoute,
|
|
133
164
|
OrganizationsOrgIdRoute: OrganizationsOrgIdRoute,
|
|
@@ -10,7 +10,7 @@ import type { QueryClient } from '@tanstack/react-query'
|
|
|
10
10
|
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
|
|
11
11
|
import { type ComponentType } from 'react'
|
|
12
12
|
import { Button, Identicon } from 'regen-ui'
|
|
13
|
-
import { BadgeCheck, Building2, KeyRound, LogOut } from 'lucide-react'
|
|
13
|
+
import { BadgeCheck, Building2, KeyRound, LogOut, Ticket } from 'lucide-react'
|
|
14
14
|
import { WagmiProvider } from 'wagmi'
|
|
15
15
|
|
|
16
16
|
import appCss from '../styles.css?url'
|
|
@@ -115,6 +115,7 @@ const nav = [
|
|
|
115
115
|
{ exact: false, href: '/organizations', icon: Building2, label: 'Organizations' },
|
|
116
116
|
{ exact: false, href: '/api-keys', icon: KeyRound, label: 'API Keys' },
|
|
117
117
|
{ exact: false, href: '/verified-tokens', icon: BadgeCheck, label: 'Verified Tokens' },
|
|
118
|
+
{ exact: false, href: '/early-access', icon: Ticket, label: 'Early Access' },
|
|
118
119
|
] as const
|
|
119
120
|
|
|
120
121
|
function Sidebar(props: { email: string; logoutUrl?: string }) {
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
2
|
+
import { useState } from 'react'
|
|
3
|
+
import { Button, Fields, Input } from 'regen-ui'
|
|
4
|
+
import { Plus, Trash2 } from 'lucide-react'
|
|
5
|
+
|
|
6
|
+
import { Card, Notice, Page } from '../components/Page'
|
|
7
|
+
import { Dialog } from '../components/Dialog'
|
|
8
|
+
import * as EarlyAccess from '../lib/early-access'
|
|
9
|
+
|
|
10
|
+
export const Route = createFileRoute('/early-access')({
|
|
11
|
+
loader: ({ context }) => context.queryClient.prefetchQuery(EarlyAccess.list.options()),
|
|
12
|
+
component: RouteComponent,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
function RouteComponent() {
|
|
16
|
+
const [open, setOpen] = useState(false)
|
|
17
|
+
const entries = EarlyAccess.list.useQuery()
|
|
18
|
+
const add = EarlyAccess.add.useMutation()
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Dialog.Root onOpenChange={setOpen} open={open}>
|
|
22
|
+
<Page
|
|
23
|
+
title="Early Access"
|
|
24
|
+
description="Manage which accounts have early access"
|
|
25
|
+
action={
|
|
26
|
+
<Dialog.Trigger
|
|
27
|
+
render={
|
|
28
|
+
<Button variant="primary">
|
|
29
|
+
<Plus className="size-4" />
|
|
30
|
+
Add entry
|
|
31
|
+
</Button>
|
|
32
|
+
}
|
|
33
|
+
/>
|
|
34
|
+
}
|
|
35
|
+
>
|
|
36
|
+
<EntryList
|
|
37
|
+
entries={entries.data?.data ?? []}
|
|
38
|
+
error={entries.error}
|
|
39
|
+
loading={entries.isPending}
|
|
40
|
+
/>
|
|
41
|
+
<Dialog.Popup>
|
|
42
|
+
<AddEntryForm
|
|
43
|
+
onSubmit={(input) =>
|
|
44
|
+
add.mutate(input, {
|
|
45
|
+
onError: (error) => alert(error.message),
|
|
46
|
+
onSuccess: () => setOpen(false),
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
pending={add.isPending}
|
|
50
|
+
/>
|
|
51
|
+
</Dialog.Popup>
|
|
52
|
+
</Page>
|
|
53
|
+
</Dialog.Root>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function AddEntryForm(props: {
|
|
58
|
+
onSubmit: (input: EarlyAccess.add.Input) => void
|
|
59
|
+
pending: boolean
|
|
60
|
+
}) {
|
|
61
|
+
function onSubmit(event: React.FormEvent<HTMLFormElement>) {
|
|
62
|
+
event.preventDefault()
|
|
63
|
+
const entry = new FormData(event.currentTarget).get('entry')
|
|
64
|
+
if (typeof entry !== 'string' || !entry.trim()) return
|
|
65
|
+
props.onSubmit({ entry: entry.trim() })
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<>
|
|
70
|
+
<Dialog.Title>Add Entry</Dialog.Title>
|
|
71
|
+
<Dialog.Description>
|
|
72
|
+
Grant early access to a whole domain or a single email
|
|
73
|
+
</Dialog.Description>
|
|
74
|
+
<form className="mt-6 flex flex-col gap-8" onSubmit={onSubmit}>
|
|
75
|
+
<Fields className="gap-6" variant="default">
|
|
76
|
+
<Input
|
|
77
|
+
autoComplete="off"
|
|
78
|
+
label="Domain or email"
|
|
79
|
+
name="entry"
|
|
80
|
+
placeholder="example.org or user@example.org"
|
|
81
|
+
required
|
|
82
|
+
spellCheck={false}
|
|
83
|
+
/>
|
|
84
|
+
</Fields>
|
|
85
|
+
<div className="flex justify-end gap-2">
|
|
86
|
+
<Dialog.Close render={<Button type="button">Cancel</Button>} />
|
|
87
|
+
<Button loading={props.pending} type="submit" variant="primary">
|
|
88
|
+
Add entry
|
|
89
|
+
</Button>
|
|
90
|
+
</div>
|
|
91
|
+
</form>
|
|
92
|
+
</>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function EntryList(props: {
|
|
97
|
+
entries: readonly EarlyAccess.Entry[]
|
|
98
|
+
error: Error | null
|
|
99
|
+
loading: boolean
|
|
100
|
+
}) {
|
|
101
|
+
return (
|
|
102
|
+
<Card>
|
|
103
|
+
{props.loading ? (
|
|
104
|
+
<Notice>Loading entries…</Notice>
|
|
105
|
+
) : props.error ? (
|
|
106
|
+
<Notice>{props.error.message}</Notice>
|
|
107
|
+
) : props.entries.length === 0 ? (
|
|
108
|
+
<Notice>No entries yet.</Notice>
|
|
109
|
+
) : (
|
|
110
|
+
<ul className="divide-y divide-border">
|
|
111
|
+
{props.entries.map((entry) => (
|
|
112
|
+
<EntryRow entry={entry} key={entry.entry} />
|
|
113
|
+
))}
|
|
114
|
+
</ul>
|
|
115
|
+
)}
|
|
116
|
+
</Card>
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function EntryRow(props: { entry: EarlyAccess.Entry }) {
|
|
121
|
+
const { entry } = props
|
|
122
|
+
const remove = EarlyAccess.remove.useMutation()
|
|
123
|
+
|
|
124
|
+
function onRemove() {
|
|
125
|
+
if (!confirm(`Remove ${entry.entry}? Matching users lose early access.`)) return
|
|
126
|
+
remove.mutate({ entry: entry.entry }, { onError: (error) => alert(error.message) })
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<li className="flex items-center justify-between gap-4 px-5 py-2.5">
|
|
131
|
+
<div className="flex min-w-0 flex-col gap-1">
|
|
132
|
+
<span className="truncate text-label-14 text-foreground">{entry.entry}</span>
|
|
133
|
+
<span className="text-label-12 text-foreground-secondary">
|
|
134
|
+
Added by {entry.createdBy} · {formatDate(entry.createdAt)}
|
|
135
|
+
</span>
|
|
136
|
+
</div>
|
|
137
|
+
<Button.Icon
|
|
138
|
+
className="text-foreground-secondary hover:text-negative"
|
|
139
|
+
disabled={remove.isPending}
|
|
140
|
+
onClick={onRemove}
|
|
141
|
+
size="lg"
|
|
142
|
+
title="Remove entry"
|
|
143
|
+
variant="plain"
|
|
144
|
+
>
|
|
145
|
+
<Trash2 />
|
|
146
|
+
</Button.Icon>
|
|
147
|
+
</li>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function formatDate(iso: string) {
|
|
152
|
+
return new Date(iso).toLocaleDateString(undefined, {
|
|
153
|
+
day: 'numeric',
|
|
154
|
+
month: 'short',
|
|
155
|
+
year: 'numeric',
|
|
156
|
+
})
|
|
157
|
+
}
|