Skip to content

Commit

Permalink
feat(platform): set and get App Data
Browse files Browse the repository at this point in the history
  • Loading branch information
poolsar42 committed May 12, 2023
1 parent f636de7 commit 61294b6
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import type { ActionFunction } from '@remix-run/cloudflare'
import { redirect } from '@remix-run/cloudflare'
import { getValidatedSessionContext } from '~/session.server'

import { getAccessClient } from '~/platform.server'
import { getAccessClient, getAddressClient } from '~/platform.server'

import { getFlashSession, commitFlashSession } from '~/session.server'
import { BadRequestError } from '@proofzero/errors'
import { AddressURNSpace } from '@proofzero/urns/address'
import { generateHashedIDRef } from '@proofzero/urns/idref'
import { CryptoAddressType, NodeType } from '@proofzero/types/address'

export const action: ActionFunction = async ({ request, params, context }) => {
const session = await getFlashSession(request, context.env)
Expand All @@ -26,6 +29,43 @@ export const action: ActionFunction = async ({ request, params, context }) => {
try {
const accessClient = getAccessClient(context.env, context.traceSpan, jwt)

const appData = await accessClient.getAppData.query({
clientId,
})

if (appData?.smartWalletSessionKeys?.length) {
await Promise.all(
appData.smartWalletSessionKeys.map(async (sessionKeyAddresses) => {
const addressURN = AddressURNSpace.componentizedUrn(
generateHashedIDRef(
CryptoAddressType.Wallet,
sessionKeyAddresses.smartContractWalletAddress
),
{
node_type: NodeType.Crypto,
addr_type: CryptoAddressType.Wallet,
},
{
alias: sessionKeyAddresses.smartContractWalletAddress,
hidden: 'true',
}
)
const baseAddressURN = AddressURNSpace.getBaseURN(addressURN)
const addressClient = getAddressClient(
baseAddressURN,
context.env,
context.traceSpan
)

addressClient.revokeWalletSessionKey.mutate({
clientId,
projectId: '',
sessionPublicKey: sessionKeyAddresses.devEthereumAddress,
})
})
)
}

await accessClient.revokeAppAuthorization.mutate({ clientId })

session.flash(
Expand Down
11 changes: 11 additions & 0 deletions packages/types/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,14 @@ export enum AuthorizationControlSelection {
export const AuthorizationControlSelectionEnum = z.nativeEnum(
AuthorizationControlSelection
)

export const AppData = z.object({
smartWalletSessionKeys: z.array(
z.object({
smartContractWalletAddress: z.string(),
devEthereumAddress: z.string(),
})
),
})

export type AppDataType = z.infer<typeof AppData>
45 changes: 45 additions & 0 deletions platform/access/src/jsonrpc/methods/getAppData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { z } from 'zod'

import { BadRequestError } from '@proofzero/errors'
import { AccountURNSpace } from '@proofzero/urns/account'

import { Context } from '../../context'
import { initAccessNodeByName } from '../../nodes'
import { AppData } from '@proofzero/types/application'
import type { AppDataType } from '@proofzero/types/application'
import type { AccountURN } from '@proofzero/urns/account'

export const GetAppDataInput = z.object({
clientId: z.string(),
})

export const GetAppDataOutput = AppData

export const getAppDataMethod = async ({
input,
ctx,
}: {
input: z.infer<typeof GetAppDataInput>
ctx: Context
}): Promise<z.infer<typeof GetAppDataOutput>> => {
const accountUrn = ctx.accountURN as AccountURN
const { clientId } = input

if (!clientId)
throw new BadRequestError({
message: 'missing client id',
})

if (!AccountURNSpace.is(accountUrn))
throw new BadRequestError({
message: 'missing account',
})

const name = `${AccountURNSpace.decode(accountUrn)}@${clientId}`
const accessNode = await initAccessNodeByName(name, ctx.Access)

const appData =
(await accessNode.storage.get<AppDataType>('appData')) ||
({} as AppDataType)
return appData
}
41 changes: 41 additions & 0 deletions platform/access/src/jsonrpc/methods/setAppData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { z } from 'zod'

import { BadRequestError } from '@proofzero/errors'
import { AccountURNSpace } from '@proofzero/urns/account'

import { Context } from '../../context'
import { initAccessNodeByName } from '../../nodes'
import { AppData } from '@proofzero/types/application'
import type { AppDataType } from '@proofzero/types/application'
import type { AccountURN } from '@proofzero/urns/account'

export const SetAppDataInput = z.object({
clientId: z.string(),
appData: AppData,
})

export const setAppDataMethod = async ({
input,
ctx,
}: {
input: z.infer<typeof SetAppDataInput>
ctx: Context
}) => {
const accountUrn = ctx.accountURN as AccountURN
const { clientId } = input

if (!clientId)
throw new BadRequestError({
message: 'missing client id',
})

if (!AccountURNSpace.is(accountUrn))
throw new BadRequestError({
message: 'missing account',
})

const name = `${AccountURNSpace.decode(accountUrn)}@${clientId}`
const accessNode = await initAccessNodeByName(name, ctx.Access)

await accessNode.storage.put<AppDataType>({ appData: input.appData })
}
21 changes: 21 additions & 0 deletions platform/access/src/jsonrpc/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ import {
PreAuthorizeMethodInput,
PreAuthorizeMethodOutput,
} from './methods/preauthorize'
import { SetAppDataInput, setAppDataMethod } from './methods/setAppData'
import {
GetAppDataInput,
getAppDataMethod,
GetAppDataOutput,
} from './methods/getAppData'

const t = initTRPC.context<Context>().create({ errorFormatter })

Expand Down Expand Up @@ -161,4 +167,19 @@ export const appRouter = t.router({
.use(Analytics)
.output(GetJWKSMethodOutput)
.query(getJWKSMethod),
getAppData: t.procedure
.use(AuthorizationTokenFromHeader)
.use(ValidateJWT)
.use(LogUsage)
.use(Analytics)
.input(GetAppDataInput)
.output(GetAppDataOutput)
.query(getAppDataMethod),
setAppData: t.procedure
.use(AuthorizationTokenFromHeader)
.use(ValidateJWT)
.use(LogUsage)
.use(Analytics)
.input(SetAppDataInput)
.mutation(setAppDataMethod),
})
22 changes: 5 additions & 17 deletions platform/address/src/jsonrpc/methods/revokeWalletSessionKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import {
revokeSessionKey,
} from '@zerodevapp/sdk'
import { Context } from '../../context'
import { CryptoAddressType, NodeType } from '@proofzero/types/address'
import { AddressURNSpace } from '@proofzero/urns/address'
import { generateHashedIDRef } from '@proofzero/urns/idref'
import { initAddressNodeByName } from '../../nodes'
import { BadRequestError } from '@proofzero/errors'

import type { AddressURN } from '@proofzero/urns/address'

export const RevokeWalletSessionKeyInput = z.object({
smartContractWalletAddress: z.string(),
clientId: z.string(),
sessionPublicKey: z.string(),
projectId: z.string(),
Expand All @@ -27,20 +25,9 @@ export const revokeWalletSessionKeyMethod = async ({
}: {
input: RevokeWalletSessionKeyParams
ctx: Context
}) => {
const { smartContractWalletAddress } = input
const addressURN = AddressURNSpace.componentizedUrn(
generateHashedIDRef(CryptoAddressType.Wallet, smartContractWalletAddress),
{
node_type: NodeType.Crypto,
addr_type: CryptoAddressType.Wallet,
},
{ alias: smartContractWalletAddress, hidden: 'true' }
)

const baseAddressURN = AddressURNSpace.getBaseURN(addressURN)
}): Promise<void> => {
const smartContractWalletNode = initAddressNodeByName(
baseAddressURN,
ctx.address3RN as AddressURN,
ctx.Address
)

Expand All @@ -57,5 +44,6 @@ export const revokeWalletSessionKeyMethod = async ({
owner: getPrivateKeyOwner(ownerPrivateKey),
})

// this is a transaction on chain => requires to pay gas fees
await revokeSessionKey(zdSigner, input.sessionPublicKey)
}
10 changes: 10 additions & 0 deletions platform/address/src/jsonrpc/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ import {
RegisterSessionKeyInput,
RegisterSessionKeyOutput,
} from './methods/registerSessionKey'
import {
RevokeWalletSessionKeyInput,
revokeWalletSessionKeyMethod,
} from './methods/revokeWalletSessionKey'

const t = initTRPC.context<Context>().create({ errorFormatter })

Expand Down Expand Up @@ -120,6 +124,12 @@ export const appRouter = t.router({
.input(RegisterSessionKeyInput)
.output(RegisterSessionKeyOutput)
.mutation(registerSessionKeyMethod),
revokeWalletSessionKey: t.procedure
.use(LogUsage)
.use(Analytics)
.use(parse3RN)
.input(RevokeWalletSessionKeyInput)
.mutation(revokeWalletSessionKeyMethod),
setAccount: t.procedure
.use(LogUsage)
.use(parse3RN)
Expand Down
18 changes: 18 additions & 0 deletions platform/galaxy/src/schema/resolvers/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,24 @@ const addressResolvers: Resolvers = {
sessionPublicKey,
})

const appData = await accessClient.getAppData.query({
clientId,
})

const smartWalletSessionKeys = appData?.smartWalletSessionKeys || []

smartWalletSessionKeys.push({
smartContractWalletAddress,
devEthereumAddress: sessionPublicKey,
})

await accessClient.setAppData.mutate({
clientId,
appData: {
smartWalletSessionKeys,
},
})

return sessionKey
} catch (e) {
throw new GraphQLError('Failed to register session key.')
Expand Down

0 comments on commit 61294b6

Please sign in to comment.