Skip to content

chore(release): promote dev to staging#268

Open
sallymoc wants to merge 60 commits into
stagingfrom
dev
Open

chore(release): promote dev to staging#268
sallymoc wants to merge 60 commits into
stagingfrom
dev

Conversation

@sallymoc

@sallymoc sallymoc commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

No description provided.

sallymoc and others added 30 commits March 12, 2026 16:18
Replace qli SubmitTransaction and transaction status endpoints with
local PendingTransactionService backed by localStorage. Broadcast
transactions via the live API. Add ApiQueryService for resolving
pending transaction outcomes. Simplify transaction status computation
and use template variable caching for asset transfer lookups.
Use live API endpoints to replace qli dependencies in IPO:
- GET /live/v1/ipos/active replaces GET /ipo/contracts
- GET /live/v1/ipos/{id}/bids replaces GET /Wallet/IpoContracts
- Remove unused getIpoContracts and getSmartContracts from ApiService
- getCurrentIpoBids from qli stays (no replacement yet)
…ents

- Add per-contract bid fetch error tracking with retry UI
- Add global error state with refresh button for failed IPO loading
- Encapsulate currentIpoContracts BehaviorSubject behind setter
- Validate API response parsing with safe parseInt defaults
- Remove dead SmartContract interface from api.model
- Simplify switchMap + of to map in observable chain
- Use nullish coalescing for tickNumber fallback
- Add i18n keys for error states across all 11 locales
- Replace raw address with getAddressDisplayName for consistent formatting
- Link share addresses to explorer instead of copy-to-clipboard
- Remove unused getSeedName method
Replace the old /Wallet/CurrentIpoBids endpoint (qubic.li) with the new
/aggregation/v1/getCurrentIpoBids endpoint on a dedicated aggregation
service. Create ApiAggregationService following the one-service-per-API-tree
convention. Add error handling with localized messages for bids load
failures and simplify the IPO bid status icon to a hardcoded trx-executed
since IPO bids are always SC calls (inputType=1, amount=0).
chore: merge main into dev
…factor/replace-qli-tx-submission

# Conflicts:
#	src/app/constants/qubic.constants.ts
#	src/app/services/api.service.ts
The service had 20 endpoint methods but zero call sites. The only
references were administrative (an unused import in app.component.ts
and a module-level provider entry), both removed.

Superseded by ApiQueryService in 50ec2d0; this was a parallel
implementation that was never wired up.
Cleans up translation keys that have no template references after
the WebSocket bridge / QubicService removal (dcd9c57):

  notifyComponent.qubicLiSync
  notifyComponent.qubicOffline
  notifyComponent.qubicOnline
  settings.general.title ("Web Bridge" header)
  settings.general.webBridge.placeholder
  settings.general.beta.placeholder

Applied uniformly across all 11 language files.
sallymoc and others added 30 commits May 26, 2026 13:14
Defines 3 endpoint methods (getApprovedTransactions, getStatus,
getTxStatus) but no component or service injects it. Only references
were an unused import in app.component.ts and a module-level provider
entry, both removed.

Superseded by the local PendingTransactionService introduced in
1c0369a; this was a parallel implementation that was never wired up.
Four service imports (ApiService, ApiQueryService, ApiLiveService,
ApiStatsService) and two injected constructor params (api, apiQuery)
were never read. The services themselves stay — they're consumed
elsewhere (e.g. updater-service.ts); only the ghost references in
AppComponent were dead.
deviceInfo was assigned in checkSize() but never read anywhere
(no .ts, .html or .scss references). Removed the declaration, the
assignment, and the now-unused DeviceInfo type import. isMobile /
isDesktop (the related fields) stay — they are read by the template
class binding.
After 50ec2d0 migrated transaction/tick fetching from the archiver
service to ApiQueryService, the field names in UpdaterService still
carried archiver vocabulary that no longer matches the source:

  archiverLatestTick        -> lastProcessedTick
  transactionArchiverLoading -> transactionsLoading

The new names align with the API endpoint (getLastProcessedTick) and
the local method of the same name. Only one external consumer
(balance.component.ts) needed updating.
Seven services declared with @Injectable({ providedIn: 'root' }) were
also redundantly listed in the AppModule providers array. The
decorator alone registers them globally as singletons; the duplicate
listing was vestigial pre-Angular 6 boilerplate and prevented
tree-shaking for services that ever go unused (as happened with
ApiArchiveService).

Removed from providers: ApiService, ApiQueryService, ApiLiveService,
ApiStatsService, UpdaterService, EnvironmentService, TransactionService.
The corresponding imports became orphan and were dropped too.

Kept in providers: AuthInterceptor (no providedIn), DecimalPipe,
MAT_DIALOG_DEFAULT_OPTIONS, httpInterceptorProviders, VisibilityService,
TokenService, the WalletService factory. Same singleton behavior at
runtime; pattern now matches ApiAggregationService (already correctly
not listed).
After 8cb059c removed the balanceTick staleness guard, updateBalance
was identical to setBalance except for a trailing saveConfig(false)
call. The current refresh pattern (loop setBalance over results, then
a single savePublic(false) at the end) made updateBalance redundant
and unreferenced. Grep across .ts/.html and string literals confirmed
zero callers.
…aterService

The BalanceComponent had `initialProcessedTick` / `lastProcessedTick`
fields representing the start/end of the tick window being displayed.
After `ce446cf` renamed UpdaterService's BehaviorSubject to
`lastProcessedTick`, both classes had a field of the same name with
different semantics — leading to lines like
`this.lastProcessedTick = this.us.lastProcessedTick.value` where
the identifier means different things on each side.

Renamed the component fields to `viewStartTick` / `viewEndTick`
to reflect what they actually represent: the bounds of the tick
range currently being viewed (which can be a historical epoch in
the "By Epoch" tab, not the chain's latest tick at all).
The remaining 'ApiService' is now a thin qubic.li-only client (auth +
guest login + getOwnedAssets + IPO state store). The generic name
obscured what was happening; renaming makes the qli-specific nature
visible at every call site.

Changes:
- src/app/services/api.service.ts -> src/app/services/apis/qli/api.qli.service.ts
- Class ApiService -> ApiQliService (matches sibling pattern:
  ApiLiveService, ApiQueryService, ApiStatsService, ApiAggregationService)
- Updated 6 consumer files (import + constructor type)
- Removed orphan ApiService import in qearn.service.ts (never used)

api.model.ts stays at services/ root since its types are still shared
with other services.
AuthResponse is the response shape of the qli /Auth/Login endpoint
and has only one consumer (ApiQliService). It lived in the generic
api.model.ts alongside app-domain types (Transaction, QubicAsset,
NetworkBalance, etc) that have no relation to qli.

Moved into the qli service folder next to ApiQliService. The shared
app-domain types in api.model.ts stay where they are.
…ight

Switching epochs or seeds clears transactionsRecord immediately, then
waits on the async getTransfers call to repopulate it. During that
gap, the empty-state message ('Transactions not found') flashed
briefly even when results were about to arrive.

Added a transactionsLoading flag set true before the fetch and
cleared in the subscribe's try/finally (and in the error callback,
which was previously missing entirely). The template now shows the
empty-state message only when the list is empty AND no fetch is in
flight.
Disambiguates from UpdaterService.transactionsLoading (which is a
private polling-cycle lock with different semantics). The component
flag is the in-flight signal for a single getTransfers request that
drives the empty-state template gate; the new name reads more
naturally ("is fetching transactions") and avoids the cross-class
collision a reader could trip on.
If the user rapidly switches seeds or epochs while a getTransfers call
is in flight, late responses would push transactions from the previous
selection into the now-displayed list, mixing data between views. The
stale response's 'finally' could also clear the loading flag while a
newer fetch was still in flight, briefly re-introducing the empty-state
flash that 8287579 set out to eliminate.

Added a monotonic fetchSeq counter — each call increments it and
captures the value at the start. The captured seq is checked at three
points to ensure only the currently-active fetch mutates shared state:

- Top of the success callback: discards stale responses before any
  writes to transactionsArchiver/transactionsRecord.
- Inside the success-path 'finally': clears isFetchingTransactions
  only if seq === fetchSeq. Handles the case where the body's
  'await Promise.all(checkAndParseAssetTransfer)' yielded while a
  new fetch started.
- Top of the error callback: discards stale errors and skips the
  flag clear.

Generalizes over seed switching (publicId change) and epoch navigation
(viewStartTick/viewEndTick change) — anything that triggers a new fetch
invalidates older in-flight ones.
Three small follow-ups noted in the latest code review:

- Drop a dead conjunct in the archiver→record copy guard. transactionsRecord
  was cleared synchronously at the start of the method, so its length is
  always 0 by the time we reach that branch. The check now reads as
  intent: copy when there is anything to copy.
- Add a matching '// stale response — a newer fetch superseded this one'
  comment to the error callback so a reader landing there gets the same
  context as the success callback.
- Make the fetchSeq field type explicit (`: number = 0`) for parity with
  the sibling tick fields (viewStartTick / viewEndTick).
The IPO path in submitIpoTransaction was building a PendingTransaction
without inputHex, losing the bid's price/quantity from local state the
moment the broadcast succeeded. Other contract-call paths (asset
transfers, transfer-rights) already capture inputHex via
storePendingTransaction.

Synthesize the same 16-byte input the chain receives (price int64-LE,
quantity int16-LE, 6 bytes zero padding) and store it hex-encoded on
the pending entry. Layout matches QubicHelper.createIpo. No interface
change — inputHex was already optional on PendingTransaction; the IPO
path was simply omitting it.

Keeps the wallet's pending records protocol-faithful and gives future
UI / retry flows access to the bid details without round-tripping to
the chain.
Promotes the local const IPO_INPUT_TYPE = 1 in transaction.service.ts
to a documented export in src/app/constants/qubic.constants.ts.
Matches how other input-type constants are sourced in this codebase
(via QubicDefinitions for QX_TRANSFER_ASSET_INPUT_TYPE, QUTIL_SENDMANY_INPUT_TYPE).
QubicDefinitions does not currently expose an IPO input type, so we
define it ourselves alongside the wallet's own constants.
The hex-encode chain Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('')
appeared twice: in encodeIpoInputHex (new IPO inputHex path) and in
storePendingTransaction (existing contract-call path). Extracted into
a private bytesToHex helper so the byte-to-hex convention lives in
one place — anyone who ever wants to change it (uppercase, spaced,
faster lookup-table encoding, etc.) has a single point to edit.
Both transaction.service.ts and apis/query/api.query.service.ts had
their own copies of byte-to-hex encoding (the same
Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('')
chain), one wrapped as bytesToHex (private), the other as base64ToHex
(private, with inline duplicated byte loop).

Moved both to a new src/app/utils/hex.utils.ts module, sitting next
to the existing shifted-hex.utils.ts. base64ToHex now delegates to
bytesToHex so the lowercase-hex convention lives in exactly one place.

Net effect: one canonical encoder, both services now consume it via
import. No behavior change.
Match the pattern used by LIVE_API_BASE_PATH and QUERY_API_BASE_PATH,
and drop the duplicated path comment from api.aggregation.model.ts.
Port the explorer's getTransactionTypeDisplayLong helper into
src/app/utils/transaction-type.utils.ts and use it to format the
"Type" cell in the balance table. Display now reads "<label> (N)"
instead of "N Standard|SC (<proc>)" and supports the "Place Bid"
label for shares-auction bids and protocol input-type labels.

Extends QubicStaticService to fetch /v1/general/data/protocol.json
for the transaction-input-type labels and adds sharesAuctionEpoch
to StaticSmartContract.

Adds a per-epoch tick range cache on BalanceComponent so the
tick->epoch lookup driving each row doesn't rebuild a Map and
sort on every change-detection cycle.
feat: replace QLI /Wallet/Assets with aggregation batch endpoint
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants