Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/nar 1656 refactor devtool to support staging env #303

Merged
Merged
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
46 changes: 26 additions & 20 deletions apps/devtool/src/app/_components/HealthcheckStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
'use client'

import { useEffect, useState } from 'react'
import useAuthServerApi from '../_hooks/useAuthServerApi'
import useDataStoreApi from '../_hooks/useDataStoreApi'
import useEngineApi from '../_hooks/useEngineApi'
import useVaultApi from '../_hooks/useVaultApi'
import { classNames } from '../_lib/utils'

const HealthcheckStatus = () => {
const [status, setStatus] = useState({
armoryConnection: false,
engineConnection: false,
engineDataStore: false,
vaultConnection: false,
entityDataUrl: false,
policyDataUrl: false,
vaultConnection: false
policyDataUrl: false
})

const { ping: pingEngine, sync } = useEngineApi()
const { getEntityStore, getPolicyStore } = useDataStoreApi()
const { ping: pingArmory } = useAuthServerApi()
const { ping: pingEngine } = useEngineApi()
const { ping: pingVault } = useVaultApi()

const { getEntityStore, getPolicyStore } = useDataStoreApi()

const checkEntityDataConnection = async () => {
try {
await getEntityStore()
Expand All @@ -37,21 +40,21 @@ const HealthcheckStatus = () => {
}
}

const checkEngineConnection = async () => {
const checkArmoryConnection = async () => {
try {
await pingEngine()
setStatus((prev) => ({ ...prev, engineConnection: true }))
await pingArmory()
setStatus((prev) => ({ ...prev, armoryConnection: true }))
} catch (e) {
setStatus((prev) => ({ ...prev, engineConnection: false }))
setStatus((prev) => ({ ...prev, armoryConnection: false }))
}
}

const checkEngineDataStore = async () => {
const checkEngineConnection = async () => {
try {
await sync()
setStatus((prev) => ({ ...prev, engineDataStore: true }))
await pingEngine()
setStatus((prev) => ({ ...prev, engineConnection: true }))
} catch (e) {
setStatus((prev) => ({ ...prev, engineDataStore: false }))
setStatus((prev) => ({ ...prev, engineConnection: false }))
}
}

Expand All @@ -67,8 +70,8 @@ const HealthcheckStatus = () => {
useEffect(() => {
checkEntityDataConnection()
checkPolicyDataConnection()
checkArmoryConnection()
checkEngineConnection()
checkEngineDataStore()
checkVaultConnection()
}, [])

Expand Down Expand Up @@ -104,29 +107,32 @@ const HealthcheckStatus = () => {
</div>
</div>
<div className="flex flex-col gap-4">
<div className="text-nv-xl">Policy Engine</div>
<div className="text-nv-xl">Auth Server</div>
<div className="flex flex-col gap-2">
<div className="text-nv-md underline">Connection</div>
<div className="flex items-center gap-4">
<div
className={classNames(
'h-3 w-3 rounded-full',
status.engineConnection ? 'bg-nv-green-500' : 'bg-nv-red-500'
status.armoryConnection ? 'bg-nv-green-500' : 'bg-nv-red-500'
)}
></div>
<div>{status.engineConnection ? 'Connected' : 'Disconnected'}</div>
<div>{status.armoryConnection ? 'Connected' : 'Disconnected'}</div>
</div>
</div>
</div>
<div className="flex flex-col gap-4">
<div className="text-nv-xl">Policy Engine</div>
<div className="flex flex-col gap-2">
<div className="text-nv-md underline">Data Store</div>
<div className="text-nv-md underline">Connection</div>
<div className="flex items-center gap-4">
<div
className={classNames(
'h-3 w-3 rounded-full',
status.engineDataStore ? 'bg-nv-green-500' : 'bg-nv-red-500'
status.engineConnection ? 'bg-nv-green-500' : 'bg-nv-red-500'
)}
></div>
<div>{status.engineDataStore ? 'Synced' : 'Unsynced'}</div>
<div>{status.engineConnection ? 'Connected' : 'Disconnected'}</div>
</div>
</div>
</div>
Expand Down
72 changes: 28 additions & 44 deletions apps/devtool/src/app/_components/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,17 @@

import { faArrowsRotate, faFileSignature } from '@fortawesome/pro-regular-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
AuthorizationRequest,
DeriveWalletRequest,
DeriveWalletResponse,
GenerateKeyRequest,
GenerateKeyResponse,
ImportPrivateKeyRequest,
ImportPrivateKeyResponse,
ImportSeedRequest,
ImportSeedResponse,
SendEvaluationResponse,
SignatureRequest,
SignatureResponse
} from '@narval/armory-sdk'
import { AuthorizationRequest, SendEvaluationResponse, SignatureRequest } from '@narval/armory-sdk'
import { EvaluationRequest, hexSchema } from '@narval/policy-engine-shared'
import { FC, useEffect, useState } from 'react'
import { FC, ReactNode, useEffect, useState } from 'react'
import NarButton from '../_design-system/NarButton'
import useStore from '../_hooks/useStore'
import useVaultApi from '../_hooks/useVaultApi'
import { erc20, grantPermission, spendingLimits } from '../_lib/request'
import CodeEditor from './CodeEditor'
import ValueWithCopy from './ValueWithCopy'
import CreateWalletModal from './modals/CreateWalletModal'
import ImportWalletModal from './modals/ImportWalletModal'
import PlaygroundConfigModal from './modals/PlaygroundConfigModal'

enum Template {
ERC20 = 'ERC20',
Expand All @@ -35,32 +22,25 @@ enum Template {

interface PlaygroundProps {
title: string
configModal: ReactNode
response?: string
errors?: string | undefined
authorize?: (req: EvaluationRequest) => Promise<AuthorizationRequest | undefined> | undefined
evaluate?: (req: EvaluationRequest) => Promise<SendEvaluationResponse> | undefined
sign?: (req: SignatureRequest) => Promise<SignatureResponse> | undefined
importPrivateKey?: (req: ImportPrivateKeyRequest) => Promise<ImportPrivateKeyResponse> | undefined
importSeedPhrase?: (req: ImportSeedRequest) => Promise<ImportSeedResponse> | undefined
generateKey?: (req: GenerateKeyRequest) => Promise<GenerateKeyResponse> | undefined
deriveWallet?: (req: DeriveWalletRequest) => Promise<DeriveWalletResponse> | undefined
validateResponse: (res: any) => Promise<SignatureRequest | undefined>
}

const Playground: FC<PlaygroundProps> = ({
title,
response,
configModal,
errors,
response,
authorize,
evaluate,
sign,
importPrivateKey,
importSeedPhrase,
generateKey,
deriveWallet,
validateResponse
}) => {
const { authClientId, vaultClientId, vaultAccessToken, setVaultAccessToken } = useStore()
const { errors: vaultErrors, sign, importPk, importSeedPhrase, generateWalletKeys, deriveWalletKey } = useVaultApi()
const { authClientId, engineClientId, vaultClientId, vaultAccessToken, setVaultAccessToken } = useStore()
const [requestEditor, setRequestEditor] = useState<string>()
const [responseEditor, setResponseEditor] = useState<string>()
const [isProcessing, setIsProcessing] = useState(false)
Expand All @@ -85,8 +65,10 @@ const Playground: FC<PlaygroundProps> = ({
useEffect(() => {
if (errors) {
setResponseEditor(`{ errors: ${errors} }`)
} else if (vaultErrors) {
setResponseEditor(`{ errors: ${vaultErrors} }`)
}
}, [errors])
}, [errors, vaultErrors])

const updateTemplate = async (template: Template) => {
switch (template) {
Expand Down Expand Up @@ -155,7 +137,7 @@ const Playground: FC<PlaygroundProps> = ({
try {
setIsProcessing(true)
setResponseEditor(undefined)
const response = sign && (await sign(signatureReq))
const response = await sign(signatureReq)
if (response) setResponseEditor(JSON.stringify(response, null, 2))
} finally {
setIsProcessing(false)
Expand All @@ -167,9 +149,7 @@ const Playground: FC<PlaygroundProps> = ({
setIsProcessing(true)
setResponseEditor(undefined)

const response =
importPrivateKey &&
(await importPrivateKey({ privateKey: hexSchema.parse(pk), accessToken: { value: accessToken } }))
const response = await importPk({ privateKey: hexSchema.parse(pk), accessToken: { value: accessToken } })

if (response) {
setResponseEditor(JSON.stringify(response, null, 2))
Expand All @@ -186,7 +166,7 @@ const Playground: FC<PlaygroundProps> = ({
setIsProcessing(true)
setResponseEditor(undefined)

const response = importSeedPhrase && (await importSeedPhrase({ seed, accessToken: { value: accessToken } }))
const response = await importSeedPhrase({ seed, accessToken: { value: accessToken } })

if (response) {
setResponseEditor(JSON.stringify(response, null, 2))
Expand All @@ -203,7 +183,7 @@ const Playground: FC<PlaygroundProps> = ({
setIsProcessing(true)
setResponseEditor(undefined)

const response = generateKey && (await generateKey({ keyId, accessToken: { value: accessToken } }))
const response = await generateWalletKeys({ keyId, accessToken: { value: accessToken } })

if (response) {
setResponseEditor(JSON.stringify(response, null, 2))
Expand All @@ -220,8 +200,7 @@ const Playground: FC<PlaygroundProps> = ({
setIsProcessing(true)
setResponseEditor(undefined)

const response =
deriveWallet && (await deriveWallet({ keyId, derivationPaths: ['next'], accessToken: { value: accessToken } }))
const response = await deriveWalletKey({ keyId, derivationPaths: ['next'], accessToken: { value: accessToken } })

if (response) {
setResponseEditor(JSON.stringify(response, null, 2))
Expand All @@ -239,51 +218,56 @@ const Playground: FC<PlaygroundProps> = ({
<div className="flex items-center">
<div className="text-nv-2xl grow">{title}</div>
<div className="flex items-center gap-[8px]">
{authorize && authClientId && (
{authClientId && authorize && (
<NarButton
label="Authorize"
leftIcon={<FontAwesomeIcon icon={faArrowsRotate} />}
onClick={handleAuthorization}
disabled={isProcessing}
/>
)}
{evaluate && (
{engineClientId && evaluate && (
<NarButton
label="Evaluate"
leftIcon={<FontAwesomeIcon icon={faArrowsRotate} />}
onClick={handleEvaluation}
disabled={isProcessing}
/>
)}
{sign && vaultClientId && (
{vaultClientId && (
<NarButton
label="Sign"
leftIcon={<FontAwesomeIcon icon={faFileSignature} />}
onClick={handleSign}
disabled={isProcessing}
/>
)}
{(generateKey || deriveWallet) && vaultClientId && (
{vaultClientId && (
<CreateWalletModal
accessToken={vaultAccessToken}
generateKey={handleGenerateKey}
deriveWallet={handleDeriveWallet}
/>
)}
{(importPrivateKey || importSeedPhrase) && vaultClientId && (
{vaultClientId && (
<ImportWalletModal
accessToken={vaultAccessToken}
importPrivateKey={handlePrivateKeyImport}
importSeedPhrase={handleSeedImport}
/>
)}
<PlaygroundConfigModal displayAuthServerUrl={Boolean(authorize)} />
{configModal}
</div>
</div>
<div className="flex items-start">
<div className="grow">
<div className="flex flex-col gap-[8px]">
<ValueWithCopy layout="horizontal" label="Auth Client ID" value={authClientId} />
{authClientId && authorize && (
<ValueWithCopy layout="horizontal" label="Auth Client ID" value={authClientId} />
)}
{engineClientId && evaluate && (
<ValueWithCopy layout="horizontal" label="Engine Client ID" value={engineClientId} />
)}
<ValueWithCopy layout="horizontal" label="Vault Client ID" value={vaultClientId} />
</div>
</div>
Expand Down
Loading
Loading