Skip to content

Commit a77c582

Browse files
authored
Merge branch 'main' into pb/eip-7702
2 parents b8f276c + 8f59c2e commit a77c582

28 files changed

+344
-388
lines changed

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@
6464
"knex": "^3.1.0",
6565
"mnemonist": "^0.39.8",
6666
"node-cron": "^3.0.2",
67-
"ox": "^0.6.9",
67+
"ox": "0.6.9",
6868
"pg": "^8.11.3",
6969
"prisma": "^5.14.0",
7070
"prom-client": "^15.1.3",
7171
"superjson": "^2.2.1",
72-
"thirdweb": "^5.83.0",
72+
"thirdweb": "5.90.0",
7373
"undici": "^6.20.1",
7474
"uuid": "^9.0.1",
75-
"viem": "^2.21.54",
75+
"viem": "2.22.17",
7676
"winston": "^3.14.1",
7777
"zod": "^3.23.8"
7878
},
@@ -103,7 +103,9 @@
103103
"cookie": ">=0.7.0",
104104
"elliptic": ">=6.6.0",
105105
"micromatch": ">=4.0.8",
106+
"ox": "0.6.9",
106107
"secp256k1": ">=4.0.4",
108+
"viem": "2.22.17",
107109
"ws": ">=8.17.1",
108110
"cross-spawn": ">=7.0.6"
109111
},

src/abitype.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
declare module "abitype" {
2+
export interface Config {
3+
AddressType: string;
4+
}
5+
}

src/server/routes/backend-wallet/send-transaction-batch-atomic.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Type, type Static } from "@sinclair/typebox";
22
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
4-
import type { Address, Hex } from "thirdweb";
4+
import { getAddress, type Address, type Hex } from "thirdweb";
55
import { insertTransaction } from "../../../shared/utils/transaction/insert-transaction";
66
import {
77
requestQuerystringSchema,
@@ -29,7 +29,9 @@ const requestBodySchema = Type.Object({
2929
}),
3030
});
3131

32-
export async function sendTransactionBatchAtomicRoute(fastify: FastifyInstance) {
32+
export async function sendTransactionBatchAtomicRoute(
33+
fastify: FastifyInstance,
34+
) {
3335
fastify.route<{
3436
Params: Static<typeof walletChainParamSchema>;
3537
Body: Static<typeof requestBodySchema>;
@@ -113,8 +115,10 @@ export async function sendTransactionBatchAtomicRoute(fastify: FastifyInstance)
113115

114116
const queueId = await insertTransaction({
115117
insertedTransaction: {
118+
...(hasSmartHeaders
119+
? { isUserOp: true, signerAddress: getAddress(fromAddress) }
120+
: { isUserOp: false }),
116121
transactionMode: undefined,
117-
isUserOp: false,
118122
chainId,
119123
from: fromAddress as Address,
120124
accountAddress: maybeAddress(accountAddress, "x-account-address"),

src/server/routes/backend-wallet/sign-transaction.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
import { Type, type Static } from "@sinclair/typebox";
1+
import { type Static, Type } from "@sinclair/typebox";
22
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
4+
import {
5+
type Hex,
6+
prepareTransaction,
7+
toSerializableTransaction,
8+
} from "thirdweb";
49
import { getAccount } from "../../../shared/utils/account";
10+
import { getChain } from "../../../shared/utils/chain";
511
import {
612
getChecksumAddress,
713
maybeBigInt,
@@ -11,12 +17,6 @@ import { thirdwebClient } from "../../../shared/utils/sdk";
1117
import { createCustomError } from "../../middleware/error";
1218
import { standardResponseSchema } from "../../schemas/shared-api-schemas";
1319
import { walletHeaderSchema } from "../../schemas/wallet";
14-
import {
15-
prepareTransaction,
16-
toSerializableTransaction,
17-
type Hex,
18-
} from "thirdweb";
19-
import { getChain } from "../../../shared/utils/chain";
2020

2121
const requestBodySchema = Type.Object({
2222
transaction: Type.Object({
@@ -90,6 +90,11 @@ export async function signTransaction(fastify: FastifyInstance) {
9090
gasPrice: maybeBigInt(transaction.gasPrice),
9191
maxFeePerGas: maybeBigInt(transaction.maxFeePerGas),
9292
maxPriorityFeePerGas: maybeBigInt(transaction.maxPriorityFeePerGas),
93+
type: transaction.type
94+
? transaction.type === 2
95+
? ("eip1559" as const)
96+
: ("legacy" as const)
97+
: undefined,
9398
};
9499

95100
const preparedTransaction = prepareTransaction(prepareTransactionOptions);

src/server/routes/contract/events/get-all-events.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
import { type Static, Type } from "@sinclair/typebox";
22
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
4+
import {
5+
type GetContractEventsResult,
6+
type PreparedEvent,
7+
getContract,
8+
getContractEvents,
9+
} from "thirdweb";
10+
import { getChain } from "../../../../shared/utils/chain";
11+
import { prettifyError } from "../../../../shared/utils/error";
12+
import { thirdwebClient } from "../../../../shared/utils/sdk";
13+
import { createCustomError } from "../../../middleware/error";
414
import {
515
contractEventSchema,
616
eventsQuerystringSchema,
717
} from "../../../schemas/contract";
18+
import { toContractEventV4Schema } from "../../../schemas/event";
819
import {
920
contractParamSchema,
1021
standardResponseSchema,
1122
} from "../../../schemas/shared-api-schemas";
12-
import { thirdwebClient } from "../../../../shared/utils/sdk";
13-
import { getChain } from "../../../../shared/utils/chain";
1423
import { getChainIdFromChain } from "../../../utils/chain";
15-
import { getContract, getContractEvents } from "thirdweb";
16-
import {
17-
type ContractEventV5,
18-
toContractEventV4Schema,
19-
} from "../../../schemas/event";
20-
import { createCustomError } from "../../../middleware/error";
21-
import { prettifyError } from "../../../../shared/utils/error";
2224

2325
const requestSchema = contractParamSchema;
2426

@@ -97,7 +99,7 @@ export async function getAllEvents(fastify: FastifyInstance) {
9799
chain: await getChain(chainId),
98100
});
99101

100-
let eventsV5: ContractEventV5[];
102+
let eventsV5: GetContractEventsResult<PreparedEvent<never>[], true>;
101103
try {
102104
eventsV5 = await getContractEvents({
103105
contract: contract,

src/server/routes/contract/read/read-batch.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Type, type Static } from "@sinclair/typebox";
1+
import { type Static, Type } from "@sinclair/typebox";
22
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
44
import SuperJSON from "superjson";
@@ -10,14 +10,14 @@ import {
1010
resolveMethod,
1111
} from "thirdweb";
1212
import { prepareMethod } from "thirdweb/contract";
13-
import { decodeAbiParameters } from "viem/utils";
1413
import type { AbiFunction } from "viem";
15-
import { createCustomError } from "../../../middleware/error";
16-
import { getChainIdFromChain } from "../../../utils/chain";
17-
import { standardResponseSchema } from "../../../schemas/shared-api-schemas";
14+
import { decodeAbiParameters } from "viem/utils";
1815
import { getChain } from "../../../../shared/utils/chain";
19-
import { thirdwebClient } from "../../../../shared/utils/sdk";
2016
import { prettifyError } from "../../../../shared/utils/error";
17+
import { thirdwebClient } from "../../../../shared/utils/sdk";
18+
import { createCustomError } from "../../../middleware/error";
19+
import { standardResponseSchema } from "../../../schemas/shared-api-schemas";
20+
import { getChainIdFromChain } from "../../../utils/chain";
2121

2222
const MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
2323

@@ -118,7 +118,7 @@ export async function readBatchRoute(fastify: FastifyInstance) {
118118
);
119119

120120
// Get Multicall3 contract
121-
const multicall = await getContract({
121+
const multicall = getContract({
122122
chain,
123123
address: multicallAddress,
124124
client: thirdwebClient,
@@ -132,7 +132,7 @@ export async function readBatchRoute(fastify: FastifyInstance) {
132132
});
133133

134134
// Process results
135-
const processedResults = results.map((result: unknown, i) => {
135+
const processedResults = results.map((result: unknown, i: number) => {
136136
const { success, returnData } = result as {
137137
success: boolean;
138138
returnData: unknown;

src/server/routes/contract/subscriptions/add-contract-subscription.ts

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { type Static, Type } from "@sinclair/typebox";
22
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
44
import { getContract } from "thirdweb";
5-
import { isContractDeployed } from "thirdweb/utils";
5+
import { isContractDeployed, shortenAddress } from "thirdweb/utils";
66
import { upsertChainIndexer } from "../../../../shared/db/chain-indexers/upsert-chain-indexer";
77
import { createContractSubscription } from "../../../../shared/db/contract-subscriptions/create-contract-subscription";
88
import { getContractSubscriptionsUniqueChainIds } from "../../../../shared/db/contract-subscriptions/get-contract-subscriptions";
@@ -21,16 +21,26 @@ import {
2121
import { standardResponseSchema } from "../../../schemas/shared-api-schemas";
2222
import { getChainIdFromChain } from "../../../utils/chain";
2323
import { isValidWebhookUrl } from "../../../utils/validator";
24+
import { getWebhook } from "../../../../shared/db/webhooks/get-webhook";
25+
import type { Webhooks } from "@prisma/client";
2426

2527
const bodySchema = Type.Object({
2628
chain: chainIdOrSlugSchema,
2729
contractAddress: {
2830
...AddressSchema,
2931
description: "The address for the contract.",
3032
},
33+
webhookId: Type.Optional(
34+
Type.Number({
35+
description:
36+
"The ID of an existing webhook to use for this contract subscription. Either `webhookId` or `webhookUrl` must be provided.",
37+
examples: [1],
38+
}),
39+
),
3140
webhookUrl: Type.Optional(
3241
Type.String({
33-
description: "Webhook URL",
42+
description:
43+
"Creates a new webhook to call when new onchain data is detected. Either `webhookId` or `webhookUrl` must be provided.",
3444
examples: ["https://example.com/webhook"],
3545
}),
3646
),
@@ -91,6 +101,7 @@ export async function addContractSubscription(fastify: FastifyInstance) {
91101
const {
92102
chain,
93103
contractAddress,
104+
webhookId,
94105
webhookUrl,
95106
processEventLogs,
96107
filterEvents = [],
@@ -124,6 +135,25 @@ export async function addContractSubscription(fastify: FastifyInstance) {
124135
);
125136
}
126137

138+
// Get an existing webhook or create a new one.
139+
let webhook: Webhooks | null = null;
140+
if (webhookId) {
141+
webhook = await getWebhook(webhookId);
142+
} else if (webhookUrl && isValidWebhookUrl(webhookUrl)) {
143+
webhook = await insertWebhook({
144+
eventType: WebhooksEventTypes.CONTRACT_SUBSCRIPTION,
145+
name: `(Generated) Subscription for ${shortenAddress(contractAddress)}`,
146+
url: webhookUrl,
147+
});
148+
}
149+
if (!webhook) {
150+
throw createCustomError(
151+
'Failed to get or create webhook for contract subscription. Make sure you provide an valid "webhookId" or "webhookUrl".',
152+
StatusCodes.BAD_REQUEST,
153+
"INVALID_WEBHOOK",
154+
);
155+
}
156+
127157
// If not currently indexed, upsert the latest block number.
128158
const subscribedChainIds = await getContractSubscriptionsUniqueChainIds();
129159
if (!subscribedChainIds.includes(chainId)) {
@@ -137,30 +167,11 @@ export async function addContractSubscription(fastify: FastifyInstance) {
137167
}
138168
}
139169

140-
// Create the webhook (if provided).
141-
let webhookId: number | undefined;
142-
if (webhookUrl) {
143-
if (!isValidWebhookUrl(webhookUrl)) {
144-
throw createCustomError(
145-
"Invalid webhook URL. Make sure it starts with 'https://'.",
146-
StatusCodes.BAD_REQUEST,
147-
"BAD_REQUEST",
148-
);
149-
}
150-
151-
const webhook = await insertWebhook({
152-
eventType: WebhooksEventTypes.CONTRACT_SUBSCRIPTION,
153-
name: "(Auto-generated)",
154-
url: webhookUrl,
155-
});
156-
webhookId = webhook.id;
157-
}
158-
159170
// Create the contract subscription.
160171
const contractSubscription = await createContractSubscription({
161172
chainId,
162173
contractAddress: contractAddress.toLowerCase(),
163-
webhookId,
174+
webhookId: webhook.id,
164175
processEventLogs,
165176
filterEvents,
166177
processTransactionReceipts,

src/server/routes/contract/write/write.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { Type, type Static } from "@sinclair/typebox";
1+
import { type Static, Type } from "@sinclair/typebox";
22
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
4+
import type { AbiParameters } from "ox";
45
import { prepareContractCall, resolveMethod } from "thirdweb";
5-
import { parseAbiParams, type AbiFunction } from "thirdweb/utils";
6+
import { type AbiFunction, parseAbiParams } from "thirdweb/utils";
67
import { getContractV5 } from "../../../../shared/utils/cache/get-contractv5";
78
import { prettifyError } from "../../../../shared/utils/error";
89
import { queueTransaction } from "../../../../shared/utils/transaction/queue-transation";
@@ -98,7 +99,7 @@ export async function writeToContract(fastify: FastifyInstance) {
9899
const functionNameOrSignature = sanitizeFunctionName(functionName);
99100
method = await resolveMethod(functionNameOrSignature)(contract);
100101
params = parseAbiParams(
101-
method.inputs.map((i) => i.type),
102+
method.inputs.map((i: AbiParameters.Parameter) => i.type),
102103
args,
103104
);
104105
} catch (e) {

src/server/routes/transaction/blockchain/get-logs.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { Type, type Static } from "@sinclair/typebox";
2-
import type { AbiEvent } from "abitype";
1+
import { type Static, Type } from "@sinclair/typebox";
32
import type { FastifyInstance } from "fastify";
43
import { StatusCodes } from "http-status-codes";
4+
import type { AbiEvent } from "ox";
55
import superjson from "superjson";
66
import {
7+
type Hex,
78
eth_getTransactionReceipt,
89
getContract,
910
getRpcClient,
1011
parseEventLogs,
1112
prepareEvent,
12-
type Hex,
1313
} from "thirdweb";
1414
import { resolveContractAbi } from "thirdweb/contract";
1515
import type { TransactionReceipt } from "thirdweb/transaction";
@@ -204,7 +204,7 @@ export async function getTransactionLogs(fastify: FastifyInstance) {
204204
client: thirdwebClient,
205205
});
206206

207-
const abi: AbiEvent[] = await resolveContractAbi(contract);
207+
const abi: AbiEvent.AbiEvent[] = await resolveContractAbi(contract);
208208
const eventSignatures = abi.filter((item) => item.type === "event");
209209
if (eventSignatures.length === 0) {
210210
throw createCustomError(

0 commit comments

Comments
 (0)