From ef55cffed6af05164c77b1da148b000dd688e2b2 Mon Sep 17 00:00:00 2001 From: dalechyn Date: Fri, 26 Jul 2024 19:42:54 +0300 Subject: [PATCH] feat: initialize initial state in places where state is not present --- src/frog-base.tsx | 25 ++++++++++++------------- src/utils/getFrameContext.ts | 26 +++++++++++++++++--------- src/utils/getImageContext.ts | 23 ++++++++++++++++------- src/utils/getSignatureContext.ts | 27 ++++++++++++++++++++------- src/utils/getTransactionContext.ts | 27 ++++++++++++++++++++------- 5 files changed, 85 insertions(+), 43 deletions(-) diff --git a/src/frog-base.tsx b/src/frog-base.tsx index b2169cca..d028d11c 100644 --- a/src/frog-base.tsx +++ b/src/frog-base.tsx @@ -593,8 +593,7 @@ export class FrogBase< // @ts-ignore - private this.initialBasePath, ) - - const { context, getState } = getFrameContext({ + const { context, getState } = await getFrameContext({ context: await requestBodyToContext(c, { hub: this.hub || @@ -602,10 +601,8 @@ export class FrogBase< secret: this.secret, verify, }), - initialState: - typeof this._initialState === 'function' - ? await (this._initialState as any)(c) - : this._initialState, + contextHono: c, + initialState: this._initialState, origin, }) @@ -1005,14 +1002,12 @@ export class FrogBase< const origin = this.origin ?? url.origin const assetsUrl = origin + parsePath(this.assetsPath) - const { context } = getImageContext({ + const { context } = await getImageContext({ context: await requestBodyToImageContext(c, { secret: this.secret, }), - initialState: - typeof this._initialState === 'function' - ? await (this._initialState as any)(c) - : this._initialState, + contextHono: c, + initialState: this._initialState, }) const response = await handler(context) @@ -1120,7 +1115,7 @@ export class FrogBase< const { verify = this.verify } = options this.hono.post(parseHonoPath(path), ...middlewares, async (c) => { - const { context } = getTransactionContext({ + const { context } = await getTransactionContext({ context: await requestBodyToContext(c, { hub: this.hub || @@ -1128,6 +1123,8 @@ export class FrogBase< secret: this.secret, verify, }), + contextHono: c, + initialState: this._initialState, req: c.req, }) const response = await handler(context) @@ -1155,7 +1152,7 @@ export class FrogBase< const { verify = this.verify } = options this.hono.post(parseHonoPath(path), ...middlewares, async (c) => { - const { context } = getSignatureContext({ + const { context } = await getSignatureContext({ context: await requestBodyToContext(c, { hub: this.hub || @@ -1163,6 +1160,8 @@ export class FrogBase< secret: this.secret, verify, }), + contextHono: c, + initialState: this._initialState, req: c.req, }) const response = await handler(context) diff --git a/src/utils/getFrameContext.ts b/src/utils/getFrameContext.ts index 7d715823..cc325329 100644 --- a/src/utils/getFrameContext.ts +++ b/src/utils/getFrameContext.ts @@ -1,4 +1,4 @@ -import type { Input } from 'hono' +import type { Input, Context as Context_Hono } from 'hono' import type { Context, FrameContext } from '../types/context.js' import type { Env } from '../types/env.js' import { getIntentState } from './getIntentState.js' @@ -12,7 +12,11 @@ type GetFrameContextParameters< _state = env['State'], > = { context: Context - initialState?: _state + contextHono: Context_Hono + initialState?: + | ((c: Context) => _state | Promise<_state>) + | _state + | undefined origin: string } @@ -22,12 +26,12 @@ type GetFrameContextReturnType< input extends Input = {}, // _state = env['State'], -> = { +> = Promise<{ context: FrameContext getState: () => _state -} +}> -export function getFrameContext< +export async function getFrameContext< env extends Env, path extends string, input extends Input = {}, @@ -36,7 +40,7 @@ export function getFrameContext< >( parameters: GetFrameContextParameters, ): GetFrameContextReturnType { - const { context, origin } = parameters + const { context, contextHono, origin } = parameters const { env, frameData, initialPath, previousButtonValues, req, verified } = context || {} @@ -55,9 +59,13 @@ export function getFrameContext< // initial URL. const url = parsePath(reset ? `${origin}${initialPath}` : context.url) - let previousState = (() => { - if (context.status === 'initial') return parameters.initialState - return context?.previousState || parameters.initialState + let previousState = await (async () => { + if (context.status === 'initial') { + if (typeof parameters.initialState === 'function') + return await (parameters.initialState as any)(contextHono) + return parameters.initialState + } + return context?.previousState })() function deriveState( diff --git a/src/utils/getImageContext.ts b/src/utils/getImageContext.ts index f54d8615..f5b0d91b 100644 --- a/src/utils/getImageContext.ts +++ b/src/utils/getImageContext.ts @@ -1,4 +1,4 @@ -import type { Input } from 'hono' +import type { Input, Context as Context_Hono } from 'hono' import type { Context, ImageContext } from '../types/context.js' import type { Env } from '../types/env.js' @@ -13,7 +13,11 @@ type GetImageContextParameters< Context, 'frameData' | 'verified' | 'status' | 'initialPath' > - initialState?: _state + contextHono: Context_Hono + initialState?: + | ((c: Context) => _state | Promise<_state>) + | _state + | undefined } type GetImageContextReturnType< @@ -22,11 +26,11 @@ type GetImageContextReturnType< input extends Input = {}, // _state = env['State'], -> = { +> = Promise<{ context: ImageContext -} +}> -export function getImageContext< +export async function getImageContext< env extends Env, path extends string, input extends Input = {}, @@ -35,13 +39,18 @@ export function getImageContext< >( parameters: GetImageContextParameters, ): GetImageContextReturnType { - const { context, initialState } = parameters + const { context, contextHono, initialState } = parameters const { env, previousState, req } = context || {} return { context: { env, - previousState: previousState ?? (initialState as _state), + previousState: await (async () => { + if (previousState) return previousState + if (typeof initialState === 'function') + return await (initialState as any)(contextHono) + return initialState + })(), req, res: (data) => ({ data, format: 'image', status: 'success' }), var: context.var, diff --git a/src/utils/getSignatureContext.ts b/src/utils/getSignatureContext.ts index 04f3641e..96f98885 100644 --- a/src/utils/getSignatureContext.ts +++ b/src/utils/getSignatureContext.ts @@ -1,4 +1,4 @@ -import type { HonoRequest, Input } from 'hono' +import type { HonoRequest, Input, Context as Context_Hono } from 'hono' import type { Context, SignatureContext } from '../types/context.js' import type { Env } from '../types/env.js' import type { SignatureResponse } from '../types/signature.js' @@ -12,6 +12,11 @@ type GetSignatureContextParameters< _state = env['State'], > = { context: Context + contextHono: Context_Hono + initialState: + | ((c: Context_Hono) => _state | Promise<_state>) + | _state + | undefined req: HonoRequest } @@ -21,11 +26,11 @@ type GetSignatureContextReturnType< input extends Input = {}, // _state = env['State'], -> = { +> = Promise<{ context: SignatureContext -} +}> -export function getSignatureContext< +export async function getSignatureContext< env extends Env, path extends string, input extends Input, @@ -34,19 +39,27 @@ export function getSignatureContext< >( parameters: GetSignatureContextParameters, ): GetSignatureContextReturnType { - const { context } = parameters + const { context, contextHono } = parameters const { env, frameData, initialPath, previousButtonValues, - previousState, req, status, verified, url, } = context || {} + const previousState = await (async () => { + if (context.status === 'initial') { + if (typeof parameters.initialState === 'function') + return await (parameters.initialState as any)(contextHono) + return parameters.initialState + } + return context?.previousState + })() + const { buttonValue, inputText } = getIntentState({ buttonValues: previousButtonValues || [], frameData, @@ -67,7 +80,7 @@ export function getSignatureContext< initialPath, inputText, previousButtonValues, - previousState, + previousState: previousState as any, req, res(parameters) { const { chainId, method, params } = parameters diff --git a/src/utils/getTransactionContext.ts b/src/utils/getTransactionContext.ts index e3faf743..b9ae1357 100644 --- a/src/utils/getTransactionContext.ts +++ b/src/utils/getTransactionContext.ts @@ -1,4 +1,4 @@ -import type { HonoRequest, Input } from 'hono' +import type { HonoRequest, Input, Context as Context_Hono } from 'hono' import { type Abi, AbiFunctionNotFoundError, @@ -20,6 +20,11 @@ type GetTransactionContextParameters< _state = env['State'], > = { context: Context + contextHono: Context_Hono + initialState: + | ((c: Context_Hono) => _state | Promise<_state>) + | _state + | undefined req: HonoRequest } @@ -29,11 +34,11 @@ type GetTransactionContextReturnType< input extends Input = {}, // _state = env['State'], -> = { +> = Promise<{ context: TransactionContext -} +}> -export function getTransactionContext< +export async function getTransactionContext< env extends Env, path extends string, input extends Input, @@ -42,19 +47,27 @@ export function getTransactionContext< >( parameters: GetTransactionContextParameters, ): GetTransactionContextReturnType { - const { context } = parameters + const { context, contextHono } = parameters const { env, frameData, initialPath, previousButtonValues, - previousState, req, status, verified, url, } = context || {} + const previousState = await (async () => { + if (context.status === 'initial') { + if (typeof parameters.initialState === 'function') + return await (parameters.initialState as any)(contextHono) + return parameters.initialState + } + return context?.previousState + })() + const { buttonValue, inputText } = getIntentState({ buttonValues: previousButtonValues || [], frameData, @@ -112,7 +125,7 @@ export function getTransactionContext< initialPath, inputText, previousButtonValues, - previousState, + previousState: previousState as any, req, res(parameters) { const { attribution, chainId, method, params } = parameters