Skip to content

Commit f102ee3

Browse files
committed
tested transactions
1 parent ee8c926 commit f102ee3

File tree

13 files changed

+559
-19
lines changed

13 files changed

+559
-19
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"knex": "^3.1.0",
6565
"mnemonist": "^0.39.8",
6666
"node-cron": "^3.0.2",
67+
"ox": "^0.6.9",
6768
"pg": "^8.11.3",
6869
"prisma": "^5.14.0",
6970
"prom-client": "^15.1.3",
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
-- AlterTable
2+
ALTER TABLE "configuration" ADD COLUMN "walletProviderConfigs" JSONB NOT NULL DEFAULT '{}';
3+
4+
-- AlterTable
5+
ALTER TABLE "wallet_details" ADD COLUMN "credentialId" TEXT,
6+
ADD COLUMN "platformIdentifiers" JSONB;
7+
8+
-- CreateTable
9+
CREATE TABLE "wallet_credentials" (
10+
"id" TEXT NOT NULL,
11+
"type" TEXT NOT NULL,
12+
"label" TEXT NOT NULL,
13+
"data" JSONB NOT NULL,
14+
"isDefault" BOOLEAN NOT NULL DEFAULT false,
15+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
16+
"updatedAt" TIMESTAMP(3) NOT NULL,
17+
"deletedAt" TIMESTAMP(3),
18+
19+
CONSTRAINT "wallet_credentials_pkey" PRIMARY KEY ("id")
20+
);
21+
22+
-- CreateIndex
23+
CREATE INDEX "wallet_credentials_type_idx" ON "wallet_credentials"("type");
24+
25+
-- CreateIndex
26+
CREATE UNIQUE INDEX "wallet_credentials_type_is_default_key" ON "wallet_credentials"("type", "isDefault");
27+
28+
-- AddForeignKey
29+
ALTER TABLE "wallet_details" ADD CONSTRAINT "wallet_details_credentialId_fkey" FOREIGN KEY ("credentialId") REFERENCES "wallet_credentials"("id") ON DELETE SET NULL ON UPDATE CASCADE;

src/server/routes/backend-wallet/create.ts

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import {
66
DEFAULT_ACCOUNT_FACTORY_V0_7,
77
ENTRYPOINT_ADDRESS_v0_7,
88
} from "thirdweb/wallets/smart";
9-
import { WalletType } from "../../../shared/schemas/wallet";
9+
import {
10+
LegacyWalletType,
11+
WalletType,
12+
CircleWalletType,
13+
} from "../../../shared/schemas/wallet";
1014
import { getConfig } from "../../../shared/utils/cache/get-config";
1115
import { createCustomError } from "../../middleware/error";
1216
import { AddressSchema } from "../../schemas/address";
@@ -25,16 +29,26 @@ import {
2529
createSmartGcpWalletDetails,
2630
createSmartLocalWalletDetails,
2731
} from "../../utils/wallets/create-smart-wallet";
32+
import {
33+
CircleWalletError,
34+
createCircleWalletDetails,
35+
} from "../../utils/wallets/circle";
2836

29-
const requestBodySchema = Type.Object({
30-
label: Type.Optional(Type.String()),
31-
type: Type.Optional(
32-
Type.Enum(WalletType, {
33-
description:
34-
"Type of new wallet to create. It is recommended to always provide this value. If not provided, the default wallet type will be used.",
35-
}),
36-
),
37-
});
37+
const requestBodySchema = Type.Union([
38+
// Base schema for non-circle wallet types
39+
Type.Object({
40+
label: Type.Optional(Type.String()),
41+
type: Type.Optional(Type.Union([Type.Enum(LegacyWalletType)])),
42+
}),
43+
44+
// Schema for circle and smart:circle wallet types
45+
Type.Object({
46+
label: Type.Optional(Type.String()),
47+
type: Type.Union([Type.Enum(CircleWalletType)]),
48+
credentialId: Type.String(),
49+
walletSetId: Type.Optional(Type.String()),
50+
}),
51+
]);
3852

3953
const responseSchema = Type.Object({
4054
result: Type.Object({
@@ -73,7 +87,7 @@ export const createBackendWallet = async (fastify: FastifyInstance) => {
7387
handler: async (req, reply) => {
7488
const { label } = req.body;
7589

76-
let walletAddress: string;
90+
let walletAddress: string | undefined = undefined;
7791
const config = await getConfig();
7892

7993
const walletType =
@@ -112,6 +126,66 @@ export const createBackendWallet = async (fastify: FastifyInstance) => {
112126
throw e;
113127
}
114128
break;
129+
case CircleWalletType.circle:
130+
{
131+
// we need this if here for typescript to statically type the credentialId and walletSetId
132+
if (req.body.type !== "circle")
133+
throw new Error("Invalid Circle wallet type"); // invariant
134+
135+
const { credentialId, walletSetId } = req.body;
136+
137+
try {
138+
const wallet = await createCircleWalletDetails({
139+
label,
140+
isSmart: false,
141+
credentialId,
142+
walletSetId,
143+
});
144+
145+
walletAddress = getAddress(wallet.address);
146+
} catch (e) {
147+
if (e instanceof CircleWalletError) {
148+
throw createCustomError(
149+
e.message,
150+
StatusCodes.BAD_REQUEST,
151+
"CREATE_CIRCLE_WALLET_ERROR",
152+
);
153+
}
154+
throw e;
155+
}
156+
}
157+
break;
158+
159+
case CircleWalletType.smartCircle:
160+
{
161+
// we need this if here for typescript to statically type the credentialId and walletSetId
162+
if (req.body.type !== "smart:circle")
163+
throw new Error("Invalid Circle wallet type"); // invariant
164+
165+
const { credentialId, walletSetId } = req.body;
166+
167+
try {
168+
const wallet = await createCircleWalletDetails({
169+
label,
170+
isSmart: true,
171+
credentialId,
172+
walletSetId,
173+
});
174+
175+
walletAddress = getAddress(wallet.address);
176+
} catch (e) {
177+
if (e instanceof CircleWalletError) {
178+
throw createCustomError(
179+
e.message,
180+
StatusCodes.BAD_REQUEST,
181+
"CREATE_CIRCLE_WALLET_ERROR",
182+
);
183+
}
184+
throw e;
185+
}
186+
}
187+
break;
188+
115189
case WalletType.smartAwsKms:
116190
try {
117191
const smartAwsWallet = await createSmartAwsWalletDetails({
@@ -163,10 +237,14 @@ export const createBackendWallet = async (fastify: FastifyInstance) => {
163237
break;
164238
}
165239

240+
if (!walletAddress) {
241+
throw new Error("Invalid state"); // invariant, typescript cannot exhaustive check because enums
242+
}
243+
166244
reply.status(StatusCodes.OK).send({
167245
result: {
168246
walletAddress,
169-
type: walletType,
247+
type: walletType as WalletType,
170248
status: "success",
171249
},
172250
});

src/server/routes/configuration/wallets/update.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ const requestBodySchema = Type.Union([
2121
gcpApplicationCredentialEmail: Type.String(),
2222
gcpApplicationCredentialPrivateKey: Type.String(),
2323
}),
24+
Type.Object({
25+
awsAccessKeyId: Type.String(),
26+
awsSecretAccessKey: Type.String(),
27+
awsRegion: Type.String(),
28+
}),
29+
Type.Object({
30+
circleApiKey: Type.String(),
31+
}),
2432
]);
2533

2634
requestBodySchema.examples = [
@@ -107,6 +115,16 @@ export async function updateWalletsConfiguration(fastify: FastifyInstance) {
107115
});
108116
}
109117

118+
if ("circleApiKey" in req.body) {
119+
await updateConfiguration({
120+
walletProviderConfigs: {
121+
circle: {
122+
apiKey: req.body.circleApiKey,
123+
},
124+
},
125+
});
126+
}
127+
110128
const config = await getConfig(false);
111129

112130
const { legacyWalletType_removeInNextBreakingChange, aws, gcp } =

src/server/routes/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ import { revokeWebhook } from "./webhooks/revoke";
113113
import { testWebhookRoute } from "./webhooks/test";
114114
import { readBatchRoute } from "./contract/read/read-batch";
115115
import { sendTransactionBatchAtomicRoute } from "./backend-wallet/send-transaction-batch-atomic";
116+
import { createWalletCredentialRoute } from "./wallet-credentials/create";
117+
import { getWalletCredentialRoute } from "./wallet-credentials/get";
118+
import { getAllWalletCredentialsRoute } from "./wallet-credentials/get-all";
116119

117120
export async function withRoutes(fastify: FastifyInstance) {
118121
// Backend Wallets
@@ -137,6 +140,11 @@ export async function withRoutes(fastify: FastifyInstance) {
137140
await fastify.register(getBackendWalletNonce);
138141
await fastify.register(simulateTransaction);
139142

143+
// Credentials
144+
await fastify.register(createWalletCredentialRoute);
145+
await fastify.register(getWalletCredentialRoute);
146+
await fastify.register(getAllWalletCredentialsRoute);
147+
140148
// Configuration
141149
await fastify.register(getWalletsConfiguration);
142150
await fastify.register(updateWalletsConfiguration);

src/server/routes/wallet-credentials/get-all.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ responseSchema.example = {
4747
],
4848
};
4949

50-
export async function getAllWalletCredentialsEndpoint(fastify: FastifyInstance) {
50+
export async function getAllWalletCredentialsRoute(fastify: FastifyInstance) {
5151
fastify.route<{
5252
Querystring: Static<typeof QuerySchema>;
5353
Reply: Static<typeof responseSchema>;

src/server/routes/wallet-credentials/get.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ responseSchema.example = {
3535
},
3636
};
3737

38-
export async function getWalletCredentialEndpoint(fastify: FastifyInstance) {
38+
export async function getWalletCredentialRoute(fastify: FastifyInstance) {
3939
fastify.route<{
4040
Params: Static<typeof ParamsSchema>;
4141
Reply: Static<typeof responseSchema>;

0 commit comments

Comments
 (0)