Skip to content

Commit 1f5ed0f

Browse files
authored
Simulate Tx : Request Option (#382)
* simulate tx * updated to querystring for simulateTx * updates to fix git changed files * Added a env variable to control data deletion on tx table * simulateTx updated to optional
1 parent af58f1f commit 1f5ed0f

File tree

75 files changed

+631
-54
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+631
-54
lines changed

docker-compose-infra.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ services:
1111
POSTGRES_PASSWORD: postgres
1212
POSTGRES_USER: postgres
1313
POSTGRES_DB: postgres
14+
deploy:
15+
resources:
16+
limits:
17+
cpus: "2"
18+
memory: 2G
19+
reservations:
20+
cpus: "2"
21+
memory: 2G
1422

1523
pgadmin:
1624
container_name: pgadmin4_container

docker-compose.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ services:
77
- db_data:/var/lib/postgresql/data
88
ports:
99
- "5432:5432"
10+
deploy:
11+
resources:
12+
limits:
13+
cpus: "2"
14+
memory: 2G
15+
reservations:
16+
cpus: "2"
17+
memory: 2G
1018

1119
pgadmin:
1220
container_name: pgadmin4_container

src/db/transactions/queueTx.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import type { DeployTransaction, Transaction } from "@thirdweb-dev/sdk";
1+
import type {
2+
DeployTransaction,
3+
Transaction,
4+
TransactionError,
5+
} from "@thirdweb-dev/sdk";
26
import { ERC4337EthersSigner } from "@thirdweb-dev/wallets/dist/declarations/src/evm/connectors/smart-wallet/lib/erc4337-signer";
37
import { BigNumber } from "ethers";
48
import type { ContractExtension } from "../../schema/extension";
@@ -13,6 +17,7 @@ interface QueueTxParams {
1317
// TODO: These shouldn't be in here
1418
deployedContractAddress?: string;
1519
deployedContractType?: string;
20+
simulateTx?: boolean;
1621
}
1722

1823
// TODO: Simulation should be done before this function
@@ -23,6 +28,7 @@ export const queueTx = async ({
2328
extension,
2429
deployedContractAddress,
2530
deployedContractType,
31+
simulateTx = false,
2632
}: QueueTxParams) => {
2733
// TODO: We need a much safer way of detecting if the transaction should be a user operation
2834
const isUserOp = !!(tx.getSigner as ERC4337EthersSigner).erc4337provider;
@@ -54,6 +60,17 @@ export const queueTx = async ({
5460

5561
return queueId;
5662
} else {
63+
try {
64+
if (!deployedContractAddress && simulateTx) {
65+
await tx.simulate();
66+
}
67+
} catch (err: any) {
68+
const errorMessage =
69+
(err as TransactionError)?.reason || (err as any).message || err;
70+
throw new Error(
71+
`Transaction simulation failed with reason: ${errorMessage}`,
72+
);
73+
}
5774
const fromAddress = await tx.getSignerAddress();
5875
const toAddress = tx.getTarget();
5976

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { queueTxRaw } from "../../../db/transactions/queueTxRaw";
1212
import { getContract } from "../../../utils/cache/getContract";
1313
import { getSdk } from "../../../utils/cache/getSdk";
1414
import {
15+
requestQuerystringSchema,
1516
standardResponseSchema,
1617
transactionWritesResponseSchema,
1718
} from "../../schemas/sharedApiSchemas";
@@ -38,6 +39,7 @@ export async function transfer(fastify: FastifyInstance) {
3839
Params: Static<typeof requestSchema>;
3940
Reply: Static<typeof transactionWritesResponseSchema>;
4041
Body: Static<typeof requestBodySchema>;
42+
Querystring: Static<typeof requestQuerystringSchema>;
4143
}>({
4244
method: "POST",
4345
url: "/backend-wallet/:chain/transfer",
@@ -50,6 +52,7 @@ export async function transfer(fastify: FastifyInstance) {
5052
params: requestSchema,
5153
body: requestBodySchema,
5254
headers: Type.Omit(walletAuthSchema, ["x-account-address"]),
55+
querystring: requestQuerystringSchema,
5356
response: {
5457
...standardResponseSchema,
5558
[StatusCodes.OK]: transactionWritesResponseSchema,
@@ -65,7 +68,7 @@ export async function transfer(fastify: FastifyInstance) {
6568

6669
// TODO: Bring Smart Wallet back
6770
// const accountAddress = request.headers["x-account-address"] as string;
68-
71+
const { simulateTx } = request.query;
6972
const chainId = await getChainIdFromChain(chain);
7073
const sdk = await getSdk({ chainId, walletAddress });
7174

@@ -120,7 +123,12 @@ export async function transfer(fastify: FastifyInstance) {
120123
);
121124
const tx = await contract.erc20.transfer.prepare(to, displayValue);
122125

123-
queueId = await queueTx({ tx, chainId, extension: "erc20" });
126+
queueId = await queueTx({
127+
tx,
128+
chainId,
129+
extension: "erc20",
130+
simulateTx,
131+
});
124132
}
125133

126134
reply.status(StatusCodes.OK).send({

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { StatusCodes } from "http-status-codes";
44
import { updateConfiguration } from "../../../../db/configuration/updateConfiguration";
55
import { getConfig } from "../../../../utils/cache/getConfig";
66
import { clearCacheCron } from "../../../../utils/cron/clearCacheCron";
7-
import { isValidCron } from "../../../../utils/cron/isValid";
7+
import { isValidCron } from "../../../../utils/cron/isValidCron";
88
import { standardResponseSchema } from "../../../schemas/sharedApiSchemas";
99
import { ReplySchema } from "./get";
1010

src/server/routes/contract/extensions/account/write/grantAdmin.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { queueTx } from "../../../../../../db/transactions/queueTx";
55
import { getContract } from "../../../../../../utils/cache/getContract";
66
import {
77
contractParamSchema,
8+
requestQuerystringSchema,
89
standardResponseSchema,
910
transactionWritesResponseSchema,
1011
} from "../../../../../schemas/sharedApiSchemas";
@@ -28,6 +29,7 @@ export const grantAdmin = async (fastify: FastifyInstance) => {
2829
Params: Static<typeof contractParamSchema>;
2930
Reply: Static<typeof transactionWritesResponseSchema>;
3031
Body: Static<typeof BodySchema>;
32+
Querystring: Static<typeof requestQuerystringSchema>;
3133
}>({
3234
method: "POST",
3335
url: "/contract/:chain/:contractAddress/account/admins/grant",
@@ -39,13 +41,15 @@ export const grantAdmin = async (fastify: FastifyInstance) => {
3941
headers: walletAuthSchema,
4042
params: contractParamSchema,
4143
body: BodySchema,
44+
querystring: requestQuerystringSchema,
4245
response: {
4346
...standardResponseSchema,
4447
[StatusCodes.OK]: transactionWritesResponseSchema,
4548
},
4649
},
4750
handler: async (request, reply) => {
4851
const { chain, contractAddress } = request.params;
52+
const { simulateTx } = request.query;
4953
const { signerAddress } = request.body;
5054
const walletAddress = request.headers[
5155
"x-backend-wallet-address"
@@ -63,7 +67,12 @@ export const grantAdmin = async (fastify: FastifyInstance) => {
6367
const tx = await contract.account.grantAdminPermissions.prepare(
6468
signerAddress,
6569
);
66-
const queueId = await queueTx({ tx, chainId, extension: "account" });
70+
const queueId = await queueTx({
71+
tx,
72+
chainId,
73+
simulateTx,
74+
extension: "account",
75+
});
6776

6877
reply.status(StatusCodes.OK).send({
6978
result: {

src/server/routes/contract/extensions/account/write/grantSession.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { getContract } from "../../../../../../utils/cache/getContract";
66
import { SessionSchema } from "../../../../../schemas/account";
77
import {
88
contractParamSchema,
9+
requestQuerystringSchema,
910
standardResponseSchema,
1011
transactionWritesResponseSchema,
1112
} from "../../../../../schemas/sharedApiSchemas";
@@ -29,6 +30,7 @@ export const grantSession = async (fastify: FastifyInstance) => {
2930
Params: Static<typeof contractParamSchema>;
3031
Reply: Static<typeof transactionWritesResponseSchema>;
3132
Body: Static<typeof BodySchema>;
33+
Querystring: Static<typeof requestQuerystringSchema>;
3234
}>({
3335
method: "POST",
3436
url: "/contract/:chain/:contractAddress/account/sessions/create",
@@ -40,13 +42,15 @@ export const grantSession = async (fastify: FastifyInstance) => {
4042
params: contractParamSchema,
4143
headers: walletAuthSchema,
4244
body: BodySchema,
45+
querystring: requestQuerystringSchema,
4346
response: {
4447
...standardResponseSchema,
4548
[StatusCodes.OK]: transactionWritesResponseSchema,
4649
},
4750
},
4851
handler: async (request, reply) => {
4952
const { chain, contractAddress } = request.params;
53+
const { simulateTx } = request.query;
5054
const { signerAddress, ...permissions } = request.body;
5155
const walletAddress = request.headers[
5256
"x-backend-wallet-address"
@@ -71,7 +75,12 @@ export const grantSession = async (fastify: FastifyInstance) => {
7175
permissions.nativeTokenLimitPerTransaction,
7276
},
7377
);
74-
const queueId = await queueTx({ tx, chainId, extension: "account" });
78+
const queueId = await queueTx({
79+
tx,
80+
chainId,
81+
simulateTx,
82+
extension: "account",
83+
});
7584

7685
reply.status(StatusCodes.OK).send({
7786
result: {

src/server/routes/contract/extensions/account/write/revokeAdmin.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { queueTx } from "../../../../../../db/transactions/queueTx";
55
import { getContract } from "../../../../../../utils/cache/getContract";
66
import {
77
contractParamSchema,
8+
requestQuerystringSchema,
89
standardResponseSchema,
910
transactionWritesResponseSchema,
1011
} from "../../../../../schemas/sharedApiSchemas";
@@ -27,6 +28,7 @@ export const revokeAdmin = async (fastify: FastifyInstance) => {
2728
fastify.route<{
2829
Params: Static<typeof contractParamSchema>;
2930
Reply: Static<typeof transactionWritesResponseSchema>;
31+
Querystring: Static<typeof requestQuerystringSchema>;
3032
Body: Static<typeof BodySchema>;
3133
}>({
3234
method: "POST",
@@ -39,13 +41,15 @@ export const revokeAdmin = async (fastify: FastifyInstance) => {
3941
headers: walletAuthSchema,
4042
params: contractParamSchema,
4143
body: BodySchema,
44+
querystring: requestQuerystringSchema,
4245
response: {
4346
...standardResponseSchema,
4447
[StatusCodes.OK]: transactionWritesResponseSchema,
4548
},
4649
},
4750
handler: async (request, reply) => {
4851
const { chain, contractAddress } = request.params;
52+
const { simulateTx } = request.query;
4953
const { walletAddress } = request.body;
5054
const backendWalletAddress = request.headers[
5155
"x-backend-wallet-address"
@@ -63,7 +67,12 @@ export const revokeAdmin = async (fastify: FastifyInstance) => {
6367
const tx = await contract.account.revokeAdminPermissions.prepare(
6468
walletAddress,
6569
);
66-
const queueId = await queueTx({ tx, chainId, extension: "account" });
70+
const queueId = await queueTx({
71+
tx,
72+
chainId,
73+
simulateTx,
74+
extension: "account",
75+
});
6776

6877
reply.status(StatusCodes.OK).send({
6978
result: {

src/server/routes/contract/extensions/account/write/revokeSession.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { queueTx } from "../../../../../../db/transactions/queueTx";
55
import { getContract } from "../../../../../../utils/cache/getContract";
66
import {
77
contractParamSchema,
8+
requestQuerystringSchema,
89
standardResponseSchema,
910
transactionWritesResponseSchema,
1011
} from "../../../../../schemas/sharedApiSchemas";
@@ -28,6 +29,7 @@ export const revokeSession = async (fastify: FastifyInstance) => {
2829
Params: Static<typeof contractParamSchema>;
2930
Reply: Static<typeof transactionWritesResponseSchema>;
3031
Body: Static<typeof BodySchema>;
32+
Querystring: Static<typeof requestQuerystringSchema>;
3133
}>({
3234
method: "POST",
3335
url: "/contract/:chain/:contractAddress/account/sessions/revoke",
@@ -39,13 +41,15 @@ export const revokeSession = async (fastify: FastifyInstance) => {
3941
params: contractParamSchema,
4042
headers: walletAuthSchema,
4143
body: BodySchema,
44+
querystring: requestQuerystringSchema,
4245
response: {
4346
...standardResponseSchema,
4447
[StatusCodes.OK]: transactionWritesResponseSchema,
4548
},
4649
},
4750
handler: async (request, reply) => {
4851
const { chain, contractAddress } = request.params;
52+
const { simulateTx } = request.query;
4953
const { walletAddress } = request.body;
5054
const backendWalletAddress = request.headers[
5155
"x-backend-wallet-address"
@@ -60,7 +64,12 @@ export const revokeSession = async (fastify: FastifyInstance) => {
6064
accountAddress,
6165
});
6266
const tx = await contract.account.revokeAccess.prepare(walletAddress);
63-
const queueId = await queueTx({ tx, chainId, extension: "account" });
67+
const queueId = await queueTx({
68+
tx,
69+
chainId,
70+
simulateTx,
71+
extension: "account",
72+
});
6473

6574
reply.status(StatusCodes.OK).send({
6675
result: {

src/server/routes/contract/extensions/account/write/updateSession.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { queueTx } from "../../../../../../db/transactions/queueTx";
55
import { getContract } from "../../../../../../utils/cache/getContract";
66
import {
77
contractParamSchema,
8+
requestQuerystringSchema,
89
standardResponseSchema,
910
transactionWritesResponseSchema,
1011
} from "../../../../../schemas/sharedApiSchemas";
@@ -31,6 +32,7 @@ export const updateSession = async (fastify: FastifyInstance) => {
3132
Params: Static<typeof contractParamSchema>;
3233
Reply: Static<typeof transactionWritesResponseSchema>;
3334
Body: Static<typeof BodySchema>;
35+
Querystring: Static<typeof requestQuerystringSchema>;
3436
}>({
3537
method: "POST",
3638
url: "/contract/:chain/:contractAddress/account/sessions/update",
@@ -42,6 +44,7 @@ export const updateSession = async (fastify: FastifyInstance) => {
4244
params: contractParamSchema,
4345
headers: walletAuthSchema,
4446
body: BodySchema,
47+
querystring: requestQuerystringSchema,
4548
response: {
4649
...standardResponseSchema,
4750
[StatusCodes.OK]: transactionWritesResponseSchema,
@@ -50,6 +53,7 @@ export const updateSession = async (fastify: FastifyInstance) => {
5053
handler: async (request, reply) => {
5154
const { chain, contractAddress } = request.params;
5255
const { signerAddress, ...permissions } = request.body;
56+
const { simulateTx } = request.query;
5357
const walletAddress = request.headers[
5458
"x-backend-wallet-address"
5559
] as string;
@@ -77,7 +81,12 @@ export const updateSession = async (fastify: FastifyInstance) => {
7781
permissions.nativeTokenLimitPerTransaction,
7882
},
7983
);
80-
const queueId = await queueTx({ tx, chainId, extension: "account" });
84+
const queueId = await queueTx({
85+
tx,
86+
chainId,
87+
simulateTx,
88+
extension: "account",
89+
});
8190

8291
reply.status(StatusCodes.OK).send({
8392
result: {

src/server/routes/contract/extensions/accountFactory/write/createAccount.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { getContract } from "../../../../../../utils/cache/getContract";
66
import { prebuiltDeployResponseSchema } from "../../../../../schemas/prebuilts";
77
import {
88
contractParamSchema,
9+
requestQuerystringSchema,
910
standardResponseSchema,
1011
} from "../../../../../schemas/sharedApiSchemas";
1112
import { walletAuthSchema } from "../../../../../schemas/wallet";
@@ -33,6 +34,7 @@ export const createAccount = async (fastify: FastifyInstance) => {
3334
Params: Static<typeof contractParamSchema>;
3435
Reply: Static<typeof prebuiltDeployResponseSchema>;
3536
Body: Static<typeof BodySchema>;
37+
Querystring: Static<typeof requestQuerystringSchema>;
3638
}>({
3739
method: "POST",
3840
url: "/contract/:chain/:contractAddress/account-factory/create-account",
@@ -44,13 +46,15 @@ export const createAccount = async (fastify: FastifyInstance) => {
4446
params: contractParamSchema,
4547
headers: walletAuthSchema,
4648
body: BodySchema,
49+
querystring: requestQuerystringSchema,
4750
response: {
4851
...standardResponseSchema,
4952
[StatusCodes.OK]: prebuiltDeployResponseSchema,
5053
},
5154
},
5255
handler: async (request, reply) => {
5356
const { chain, contractAddress } = request.params;
57+
const { simulateTx } = request.query;
5458
const { adminAddress, extraData } = request.body;
5559
const walletAddress = request.headers[
5660
"x-backend-wallet-address"
@@ -76,6 +80,7 @@ export const createAccount = async (fastify: FastifyInstance) => {
7680
const queueId = await queueTx({
7781
tx,
7882
chainId,
83+
simulateTx,
7984
extension: "account-factory",
8085
deployedContractAddress: deployedAddress,
8186
deployedContractType: "account",

0 commit comments

Comments
 (0)