Skip to content

Commit 0ba2550

Browse files
arcoravenfarhanW3d4mr
authored
[WIP] Transaction workers to Redis (#554)
* wip * WIP: transaction workers in Redis * webhooks and usage tracking * wip * remove prepare worker * multiple transaction hashes * updates to allow all POST end-point to work with new flow * transaction db updates * purge worker * db update * add queued txs * UserOps Updates * build fixes * Error Handling update * updates for errors * simplify purge logic * wip * add getChain * support get all tx by wallet * fix sent redis * updated error handling * wip * separate helper funcs for userOps * typing... * remove env debug * update ttl seconds * fix build, add nonce helpers * update: added implementation to retrieve the contract-address * updates for deployedContractAddress * fixed createAccount build issue * unused nonces worker * unused nonces * send-transaction userOp update * add pretty error message back * Add openapi.json to gitignore * remove debug line * unused nonce * reuse rpc request * remove simulation in send eoa transaction * update sdk, undo rpc client caching * remove unused env var * cleanup and comments * log released nonces * handle resend rpc errors * explicitly list attempts/backoff * fix mine worker bug * better handle rpc error * prune transaction lists and details * prune tx by count * wip * explicit worker init step * add basic auth to queues management * migrate postgres tx * add migration worker * updates for value override, simulation + send Tx/UserOps using data * tx details debug endpoint * Remove debug line * fix example * fix: bullboard not working in prod * move cron init workers * bugfix: account created from ethers signer need provider * Add test suite * bugfix: remove hardcoded anvil chain * fix: only connect provider to aws signer * fix: removed logs * fix: remove debug test values * fix: pass wallet label in test * Updates: Removed logs + queuedAt indexed * Fk/extend ph worker (#595) * Update: Added nonce rebase with blockchain logic * removed logs * updates * AWS & GCP KMS provider fix * updated rebaseNonce * feat: take file as arg * chore: update anvil installation instructions in e2e README * Updates: v2 Nonce (#597) * Updates * updates * cleaned logs * updates * updated recycleNonce to check if isNan * comments updated * chore: expose NonceResyncQueue to bullboard * Convert nonce-recycled to set and add nonce-sent set helpers * fix: handle removing from sent nonces in fail handler * chore: Remove commented out code in setup.ts file * Update nonceResyncWorker to use stricter wildcard pattern for redis keys * Add isSentNonce helper function for checking if a nonce is in the sent nonces set * refactor and solve nonce resynchronization logic bugs and nits in nonceResyncWorker * chore: Refactor cancelRecycledNoncesWorker to use SMEMBERS instead of LRANGE for retrieving unused nonces * treat `ReplacementGasFeeTowLow` as `NonceAlreadyUsed` * updated logs & removeSentNonce --------- Co-authored-by: Prithvish Baidya <deformercoding@gmail.com> * yarn lock * queue latency metrics * use v5 for local wallets on EOA * handle rpc errors better * fix: batch ioredis operations * updated isReplacementGasFeeTooLow check * graceful shutdown, use multi instead of lua script * add backoff on SendTransactionQueue * fix: default REDIS_MAXMEMORY = 0 * lua script default to 0 * fix queued tx cancel * default concurrency 200 * updated wallet_address -> walletAddress, erc20 balance-of * reverting changes. will move it to a breaking updates PR * checksum addresses to RPC * fix build * use checksumAddress * Make effective gas price optional * set onchainStatus for userop * allow replaying failed txs * always query latest block tag for tx count * fix: regex address validation * Updates: Claim-to using v5 SDK (#618) * Updates: Claim-to using v5 SDK * updates * removed caching for getContractV5 --------- Co-authored-by: farhanW3 <farhan@thirdweb.com> Co-authored-by: Prithvish Baidya <deformercoding@gmail.com> Co-authored-by: Farhan Khwaja <132962163+farhanW3@users.noreply.github.com>
1 parent 019a78e commit 0ba2550

File tree

164 files changed

+5339
-3947
lines changed

Some content is hidden

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

164 files changed

+5339
-3947
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ yarn-error.log
134134
.yarn/install-state.gz
135135
.pnp.*
136136

137+
# yalc cache
138+
.yalc
139+
yalc.lock
140+
137141
swagger.yml
138142
worker/distWorker/
139143
.DS_Store
@@ -144,3 +148,6 @@ credentials
144148

145149
# SSL Local Certs folder
146150
https
151+
152+
# Auto generated OpenAPI file
153+
openapi.json

docker-compose.yml

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,14 @@ services:
3030
restart: always
3131
ports:
3232
- 6379:6379
33+
deploy:
34+
resources:
35+
limits:
36+
cpus: "1"
37+
memory: 1024M
3338
volumes:
3439
- redis_data:/data
3540

36-
bullboard:
37-
container_name: bullboard
38-
image: deadly0/bull-board:3.2.6
39-
restart: always
40-
ports:
41-
- 3333:3000
42-
environment:
43-
REDIS_HOST: redis
44-
REDIS_PORT: 6379
45-
REDIS_USE_TLS: "false"
46-
BULL_PREFIX: bull
47-
depends_on:
48-
- redis
49-
5041
engine:
5142
profiles:
5243
- engine

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@
2727
},
2828
"dependencies": {
2929
"@aws-sdk/client-kms": "^3.398.0",
30+
"@bull-board/fastify": "^5.21.1",
31+
"@fastify/basic-auth": "^5.1.1",
3032
"@fastify/cookie": "^8.3.0",
3133
"@fastify/express": "^2.3.0",
3234
"@fastify/swagger": "^8.9.0",
3335
"@fastify/type-provider-typebox": "^3.2.0",
3436
"@fastify/websocket": "^8.2.0",
3537
"@google-cloud/kms": "^4.4.0",
36-
"@prisma/client": "^5.14.0",
38+
"@prisma/client": "5.17.0",
3739
"@sinclair/typebox": "^0.31.28",
3840
"@t3-oss/env-core": "^0.6.0",
3941
"@thirdweb-dev/auth": "^4.1.87",
@@ -43,7 +45,7 @@
4345
"@types/base-64": "^1.0.2",
4446
"base-64": "^1.0.0",
4547
"body-parser": "^1.20.2",
46-
"bullmq": "^5.7.8",
48+
"bullmq": "^5.11.0",
4749
"cookie": "^0.5.0",
4850
"cookie-parser": "^1.4.6",
4951
"copyfiles": "^2.4.1",
@@ -68,7 +70,6 @@
6870
"superjson": "^2.2.1",
6971
"thirdweb": "^5.45.1",
7072
"uuid": "^9.0.1",
71-
"viem": "^1.14.0",
7273
"winston": "^3.14.1",
7374
"zod": "^3.23.8"
7475
},

src/db/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const knex = pg({
2222
acquireConnectionTimeout: 30000,
2323
} as Knex.Config);
2424

25-
export const isDatabaseHealthy = async (): Promise<boolean> => {
25+
export const isDatabaseReachable = async () => {
2626
try {
2727
await prisma.walletDetails.findFirst();
2828
return true;

src/db/configuration/getConfiguration.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import { Configuration } from "@prisma/client";
2+
import { Static } from "@sinclair/typebox";
23
import { LocalWallet } from "@thirdweb-dev/wallets";
34
import { ethers } from "ethers";
4-
import { Config } from "../../schema/config";
5+
import { Chain } from "thirdweb";
6+
import { ParsedConfig } from "../../schema/config";
57
import { WalletType } from "../../schema/wallet";
68
import { mandatoryAllowedCorsUrls } from "../../server/utils/cors-urls";
9+
import { networkResponseSchema } from "../../utils/cache/getSdk";
710
import { decrypt } from "../../utils/crypto";
811
import { env } from "../../utils/env";
912
import { logger } from "../../utils/logger";
1013
import { prisma } from "../client";
1114
import { updateConfiguration } from "./updateConfiguration";
1215

13-
const withWalletConfig = async (config: Configuration): Promise<Config> => {
16+
const toParsedConfig = async (config: Configuration): Promise<ParsedConfig> => {
1417
// We destructure the config to omit wallet related fields to prevent direct access
1518
const {
1619
awsAccessKeyId,
@@ -25,6 +28,31 @@ const withWalletConfig = async (config: Configuration): Promise<Config> => {
2528
...restConfig
2629
} = config;
2730

31+
// Parse "chainOverrides" JSON to an array of Chain[] items.
32+
let chainOverridesParsed: Chain[] = [];
33+
if (config.chainOverrides) {
34+
try {
35+
const parsed: Static<typeof networkResponseSchema>[] = JSON.parse(
36+
config.chainOverrides,
37+
);
38+
chainOverridesParsed = parsed.map(
39+
(chain): Chain => ({
40+
id: chain.chainId,
41+
name: chain.name,
42+
rpc: chain.rpc[0],
43+
nativeCurrency: chain.nativeCurrency,
44+
testnet: chain.testnet ? true : undefined,
45+
}),
46+
);
47+
} catch (e) {
48+
logger({
49+
service: "server",
50+
level: "error",
51+
message: `Failed parsing chainOverrides: ${e}`,
52+
});
53+
}
54+
}
55+
2856
// TODO: Remove backwards compatibility with next breaking change
2957
if (awsAccessKeyId && awsSecretAccessKey && awsRegion) {
3058
// First try to load the aws secret using the encryption password
@@ -61,6 +89,7 @@ const withWalletConfig = async (config: Configuration): Promise<Config> => {
6189
...restConfig,
6290
contractSubscriptionsRequeryDelaySeconds:
6391
contractSubscriptionsRetryDelaySeconds,
92+
chainOverridesParsed,
6493
walletConfiguration: {
6594
type: WalletType.awsKms,
6695
awsRegion,
@@ -109,6 +138,7 @@ const withWalletConfig = async (config: Configuration): Promise<Config> => {
109138
...restConfig,
110139
contractSubscriptionsRequeryDelaySeconds:
111140
contractSubscriptionsRetryDelaySeconds,
141+
chainOverridesParsed,
112142
walletConfiguration: {
113143
type: WalletType.gcpKms,
114144
gcpApplicationProjectId,
@@ -124,6 +154,7 @@ const withWalletConfig = async (config: Configuration): Promise<Config> => {
124154
...restConfig,
125155
contractSubscriptionsRequeryDelaySeconds:
126156
contractSubscriptionsRetryDelaySeconds,
157+
chainOverridesParsed,
127158
walletConfiguration: {
128159
type: WalletType.local,
129160
},
@@ -139,7 +170,7 @@ const createAuthWalletEncryptedJson = async () => {
139170
});
140171
};
141172

142-
export const getConfiguration = async (): Promise<Config> => {
173+
export const getConfiguration = async (): Promise<ParsedConfig> => {
143174
let config = await prisma.configuration.findUnique({
144175
where: {
145176
id: "default",
@@ -193,5 +224,6 @@ export const getConfiguration = async (): Promise<Config> => {
193224
});
194225
}
195226

196-
return withWalletConfig(config);
227+
const result = await toParsedConfig(config);
228+
return result;
197229
};

src/db/transactions/cleanTxs.ts

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)