Trader Launchpad
Trader Launchpad
TtRPC
Created by Trader Launchpad on 2/14/2024 in #❓-help
Thoughts on how to integrate t3 app, connectkit web3 auth, nextjs middleware, and trpc
I am prototyping an application using t3 app with trpc, connectkit web3 auth. I am wanting to use nextjs middleware to protect routes server side. As part of the connectkit auth flow, I have my application wrapped in a ClientProvider:
// layout.tsx
<body
className={`font-sans ${inter.variable} flex min-h-screen flex-1 items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white`}
>
<TRPCReactProvider headers={headers()}>
<ClientProvider>{children}</ClientProvider>
</TRPCReactProvider>
</body>
// layout.tsx
<body
className={`font-sans ${inter.variable} flex min-h-screen flex-1 items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white`}
>
<TRPCReactProvider headers={headers()}>
<ClientProvider>{children}</ClientProvider>
</TRPCReactProvider>
</body>
Inside ClientProvider I have the web3 providers:
// ClientProvider.tsx
...
return (
<WagmiConfig config={config}>
<SIWEProvider {...siweConfig} onSignIn={() => router.push("/")}>
<ConnectKitProvider>{children}</ConnectKitProvider>
</SIWEProvider>
</WagmiConfig>
);
// ClientProvider.tsx
...
return (
<WagmiConfig config={config}>
<SIWEProvider {...siweConfig} onSignIn={() => router.push("/")}>
<ConnectKitProvider>{children}</ConnectKitProvider>
</SIWEProvider>
</WagmiConfig>
);
and here is const siwiConfig. It calls the /siwe route on initial load and sets a cookie using iron-session with the nonce inside, then updates that same cookie after authentiucation with wallet address and chain:
4 replies
TtRPC
Created by Trader Launchpad on 11/9/2023 in #❓-help
[How To?] Create a record in database on form submission...
I have an application using trpc, Cloudfare D1 database, and trpc. I am trying to use a tamagui form component to insert a record into the database. My trpc route:
export const carsRouter = router({
all: publicProcedure.query(async ({ ctx }) => {
const { db } = ctx
const allCars = await db.select().from(CarTable).all()
return allCars
}),
create: publicProcedure
.input((raw) => parse(CarSchema, raw))
.mutation(async ({ ctx, input }) => {
const { db } = ctx
await db.insert(CarTable).values(input).run()
}),
})
export const carsRouter = router({
all: publicProcedure.query(async ({ ctx }) => {
const { db } = ctx
const allCars = await db.select().from(CarTable).all()
return allCars
}),
create: publicProcedure
.input((raw) => parse(CarSchema, raw))
.mutation(async ({ ctx, input }) => {
const { db } = ctx
await db.insert(CarTable).values(input).run()
}),
})
My drizzle table schema:
export const CarTable = sqliteTable('Car', {
id: integer('id').primaryKey({ autoIncrement: true }),
uuid: binary('uuid', { length: 16 }).default('hex(randomblob(16))').unique(), // Generate a random 16-byte binary string
make: text('make'),
model: text('model'),
year: integer('year'),
color: text('color'),
price: real('price'),
mileage: integer('mileage'),
fuelType: text('fuelType'),
transmission: text('transmission'),
})
export const CarTable = sqliteTable('Car', {
id: integer('id').primaryKey({ autoIncrement: true }),
uuid: binary('uuid', { length: 16 }).default('hex(randomblob(16))').unique(), // Generate a random 16-byte binary string
make: text('make'),
model: text('model'),
year: integer('year'),
color: text('color'),
price: real('price'),
mileage: integer('mileage'),
fuelType: text('fuelType'),
transmission: text('transmission'),
})
My form component:
export const VirtualizedListScreen = (): React.ReactNode => {
const [make, setMake] = useState("");

const createCar = trpc.car.create.useMutation({
onSuccess: () => {
console.log("create post success")
/* router.refresh();
setName(""); */
},
onError: (e) => {
console.log("Error", e)
}
});

return (
<YStack fullscreen f={1}>

<Form
onSubmit={() => {
createCar.mutate({ make, uuid: 123456 });
}}
>
<Input
placeholder="Title"
value={make}
onChangeText={setMake}
/>
<Form.Trigger asChild>

<Button />
</Form.Trigger>
</Form>
{carsListLayout}
</YStack>
)
}
export const VirtualizedListScreen = (): React.ReactNode => {
const [make, setMake] = useState("");

const createCar = trpc.car.create.useMutation({
onSuccess: () => {
console.log("create post success")
/* router.refresh();
setName(""); */
},
onError: (e) => {
console.log("Error", e)
}
});

return (
<YStack fullscreen f={1}>

<Form
onSubmit={() => {
createCar.mutate({ make, uuid: 123456 });
}}
>
<Input
placeholder="Title"
value={make}
onChangeText={setMake}
/>
<Form.Trigger asChild>

<Button />
</Form.Trigger>
</Form>
{carsListLayout}
</YStack>
)
}
When i click the form button, i get a 500 internal error on api/trpc side. Can someone tell me what I am doing wrong, i feel like its obvious but im not getting it.
5 replies
TtRPC
Created by Trader Launchpad on 5/22/2023 in #❓-help
[How To] Properly use trpc UseQuery based on currently selected item
I have a component with a video element and a flatlist. I want to utilize a trpc query to get the videoUri based on the currently selected item. Here is my working component:
import React, { useState, useRef, FC } from "react";
import { StyleSheet } from "react-native";

import { Text } from "../../../design/typography";
import { View } from "../../../design/view";

import { TouchableOpacity } from "../../button";
import { FlashList } from "@shopify/flash-list";
import { Video, ResizeMode } from "expo-av";

interface CourseComponentProps {
data?: DataItem[];
}

type DataItem = {
ID: bigint;
post_title: string;
videoUri?: string;
};

type ItemProps = {
item: DataItem;
onPress: () => void;
};

const Item = ({ item, onPress }: ItemProps) => (
<TouchableOpacity onPress={onPress}>
<Text>{item.post_title}</Text>
</TouchableOpacity>
);

export const CourseComponent: FC<CourseComponentProps> = ({ data }) => {
const video = React.useRef(null);
const [currentItem, setCurrentItem] = React.useState<DataItem>();

const renderItem = ({ item }: { item: DataItem }) => {
return <Item item={item} onPress={() => setCurrentItem(item)} />;
};

return (
<View className="h-screen">
<Video
ref={video}
style={styles.video}
source={{
uri: currentItem?.videoUri || "",
}}
useNativeControls
resizeMode={ResizeMode.CONTAIN}
isLooping
/>
<Text>{currentItem?.post_title}</Text>
<FlashList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.ID.toString()}
/>
</View>
);
};

CourseComponent.defaultProps = {
data: [
{
ID: BigInt(1),
post_title: "Default Post Title 1",
videoUri: "https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4",
},
...
],
};
import React, { useState, useRef, FC } from "react";
import { StyleSheet } from "react-native";

import { Text } from "../../../design/typography";
import { View } from "../../../design/view";

import { TouchableOpacity } from "../../button";
import { FlashList } from "@shopify/flash-list";
import { Video, ResizeMode } from "expo-av";

interface CourseComponentProps {
data?: DataItem[];
}

type DataItem = {
ID: bigint;
post_title: string;
videoUri?: string;
};

type ItemProps = {
item: DataItem;
onPress: () => void;
};

const Item = ({ item, onPress }: ItemProps) => (
<TouchableOpacity onPress={onPress}>
<Text>{item.post_title}</Text>
</TouchableOpacity>
);

export const CourseComponent: FC<CourseComponentProps> = ({ data }) => {
const video = React.useRef(null);
const [currentItem, setCurrentItem] = React.useState<DataItem>();

const renderItem = ({ item }: { item: DataItem }) => {
return <Item item={item} onPress={() => setCurrentItem(item)} />;
};

return (
<View className="h-screen">
<Video
ref={video}
style={styles.video}
source={{
uri: currentItem?.videoUri || "",
}}
useNativeControls
resizeMode={ResizeMode.CONTAIN}
isLooping
/>
<Text>{currentItem?.post_title}</Text>
<FlashList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.ID.toString()}
/>
</View>
);
};

CourseComponent.defaultProps = {
data: [
{
ID: BigInt(1),
post_title: "Default Post Title 1",
videoUri: "https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4",
},
...
],
};
55 replies
TtRPC
Created by Trader Launchpad on 5/11/2023 in #❓-help
[HOW TO?] Call trpc endpoints from vanilla nextJs api routes
Spinoff from an og thread here: https://discordapp.com/channels/867764511159091230/1032301198990135347 HI! I am wanting to do the same thing...call a trpc route from within a nextjs public api endpoint. I am using a fresh t3-turbo-with-clerk project which has trpc in packages/api (@acme/api) here is my apps/nextjs/src/pages/api/post.ts file
import { NextApiRequest, NextApiResponse } from "next";
import { appRouter } from "@acme/api";
import { getHTTPStatusCodeFromError } from "@trpc/server/http";
import { TRPCError } from "@trpc/server";

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const caller = appRouter.createCaller({});

try {
const result = await caller.post.all();
res.status(200).json(result);
} catch (e) {
console.error(e);
const code = e instanceof TRPCError ? getHTTPStatusCodeFromError(e) : 500;
res.status(code).json({ error: e });
}
};

export default handler;
import { NextApiRequest, NextApiResponse } from "next";
import { appRouter } from "@acme/api";
import { getHTTPStatusCodeFromError } from "@trpc/server/http";
import { TRPCError } from "@trpc/server";

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const caller = appRouter.createCaller({});

try {
const result = await caller.post.all();
res.status(200).json(result);
} catch (e) {
console.error(e);
const code = e instanceof TRPCError ? getHTTPStatusCodeFromError(e) : 500;
res.status(code).json({ error: e });
}
};

export default handler;
28 replies