Extract domain logic from `src/blockchain/oracle/services/submitter.service.ts` (620 lines)
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
- Issue type
- Refactor
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- nodejs, typescript
- Domain
- backend, blockchain
Research direction
Start with the retry loop in src/blockchain/oracle/services/submitter.service.ts (around lines 235-241) and the matching loop with the payloadRepository.findOne check in submission-batch.service.ts (around lines 216-219). Check src/common/utils/ for an existing helper and read payload-signing.service.spec.ts for the test style. Done when a shared retry helper is used, the idempotency check runs once per payload, and a spec shows a fail-then-succeed submission produces exactly one transaction, with npx tsc --noEmit and npm test passing.
Written by the indexing model from the issue text.
Description
Problem
src/blockchain/oracle/services/submitter.service.ts is 620 lines — the second-largest file in the repository. It handles gas estimation, submission retry, and payload lifecycle in one service. The retry loop at lines 235-241 shows several concerns interleaved:
for (let attempt = 1; attempt <= this.maxRetries + 1; attempt++) {
const gasEstimate = await this.estimateGas(payload);
const gasLimit = BigInt(
Math.ceil(Number(gasEstimate) * this.gasLimitMultiplier),
);
...
}
Gas estimation, retry/backoff policy, and transaction submission are three distinct concerns being driven from one loop. There is a related submission-batch.service.ts (656 lines) with a structurally similar retry loop at line 216, so the retry policy is duplicated across both files.
Why it matters
This is the on-chain submission path — the README's "critical outcomes are signed and auditable" boundary. Two files implementing retry policy independently will drift, and a drift here means duplicate or dropped on-chain submissions. The duplicated idempotency check at submission-batch.service.ts:219 (payloadRepository.findOne({ where: { id: payloadId } })) runs on every retry attempt, so the retry cost includes a database round-trip per attempt that the batch service may already have done.
Suggested Direction
- Extract a shared retry utility. Both loops implement the same shape. Put a small
retry(fn, { maxAttempts, backoff, shouldRetry })helper somewhere shared — checksrc/common/utils/for where similar utilities already live. - Separate the concerns in
submitter.service.ts:gas-estimation.service.ts— wrapsestimateGasand the multiplier mathsubmission-retry.service.ts— the retry/backoff policy- keep
SubmitterServiceas the orchestrator
- Move the idempotency check out of the retry loop. Fetch the payload once before the loop instead of re-querying per attempt (this also has a performance benefit — see the retry-loop performance issue).
- Add colocated specs. There is
src/blockchain/oracle/services/payload-signing.service.spec.tsalready, so signing is covered — submission is not.
Constraints
- Idempotency is critical. A retry must never produce a duplicate on-chain transaction. Preserve or strengthen the idempotency guarantee; do not remove the check to save a query.
- Retry counts, backoff intervals, and the gas multiplier are operational tuning parameters — keep them externally configurable.
submission-batch.service.tsshould get the same treatment, but consider doing it in a follow-up PR so each is reviewable.
Acceptance Criteria
- A shared retry helper exists and is used by
submitter.service.ts. -
submitter.service.tsno longer exceeds ~350 lines. - The idempotency check is not executed redundantly per retry attempt.
- A test asserts a failing-then-succeeding submission produces exactly one on-chain transaction.
-
npx tsc --noEmitandnpm testpass.
- Dominant language
- TypeScript
- Stars
- 7
- Forks
- 55
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 5
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from SourceXXL/alian_structure-api
-
good first issue help wanted security
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SourceXXL/alian_structure-api#266 ·
-
Parallelize the cache-warming loop in `cache-warming.service.ts` — warmers run strictly sequentiallyPossibly taken @syntaxsuuvam-spec claimed this 6 days ago. Opengood first issue performance
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SourceXXL/alian_structure-api#240 ·
-
documentation help wanted intermediate refactor
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
SourceXXL/alian_structure-api#215 ·
-
good first issue refactor tooling
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
SourceXXL/alian_structure-api#199 ·
-
help wanted intermediate refactor
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
SourceXXL/alian_structure-api#196 ·
All issues in SourceXXL/alian_structure-api
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Chocobozzz/PeerTube#7832 ·
Maintainers usually reply within 3 days
-
Pay to use?Open
Difficulty 1/5 Under an hour Newbie friendliness 66/100
darkreader/darkreader#16108 · 1 comment ·
Maintainers usually reply within 2 days
-
Add: Dak Nong TV SDOpencheck:passed streams:add
Difficulty 1/5 Under an hour Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
bug engine
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
frostney/GocciaScript#1746 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
agilepathway/label-checker#739 · 4 comments ·
Maintainers usually reply within 1 day