feat: merge tt utils#123
Conversation
WalkthroughConsolidates external utility re-exports into local implementations, adds analytics and gas-station utilities with tests, expands supportedChains and chain metadata, centralizes verification error messages and fragment handling, adds extensive verifier-response fixtures, and updates TypeScript types for gtag. Changes
Sequence Diagram(s)sequenceDiagram
participant App as Application
participant Analytics as Analytics Module
participant Gtag as window.gtag
participant Console as Console
App->>Analytics: gaPageView(event, gaId)
Analytics->>Analytics: validateGtag()
alt gtag present
Analytics->>Analytics: validatePageViewEvent(event)
alt valid
Analytics->>Gtag: gtag('event','page_view', {..., send_to: gaId})
else invalid
Analytics->>Console: console.error("invalid page view")
end
else gtag missing
Analytics->>Console: console.warn("gtag not initialised")
end
sequenceDiagram
participant Test as Test Suite
participant Factory as gasStation(url)
participant Fetch as fetch
participant Parser as safeParseUnits
participant Caller as Caller
Test->>Factory: create with URL
Factory-->>Test: fetcherFn
Test->>fetcherFn: invoke
fetcherFn->>Fetch: fetch(url)
alt success
Fetch-->>fetcherFn: JSON
fetcherFn->>Parser: parse fee strings
Parser-->>fetcherFn: BigNumber values
fetcherFn-->>Caller: {maxPriorityFeePerGas, maxFeePerGas}
else error
fetcherFn-->>Caller: throw "Failed to fetch gas station"
end
sequenceDiagram
participant Fragments as VerificationFragments
participant Handler as errorMessageHandling()
participant Logic as interpretFragments / OAErrorMessageHandling
participant Out as ErrorCodes[]
Fragments->>Handler: fragments[]
Handler->>Logic: interpretFragments(fragments)
Logic->>Logic: check integrity (HASH), issuance (ISSUED/REVOKED), identity (DNS/DID)
alt all valid
Logic-->>Out: [ISSUED]
else revoked
Logic-->>Out: [REVOKED,...]
else mixed issues
Logic-->>Out: aggregated error codes
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (21)
src/utils/static/icons.ts (1)
1-8: Consider using proper MIME types for image data URLs.
iconEthereumandiconPolygonusedata:image/octet-stream;base64whileiconStabilityandiconAstronusedata:image/png;base64. Using the correct MIME type improves browser compatibility and ensures proper rendering.Based on the base64 headers:
iconEthereumappears to be WebP format (UklGR= RIFF header)iconPolygonalso appears to be WebP formatexport const iconEthereum = - 'data:image/octet-stream;base64,UklGRhgNAABXRUJQ... + 'data:image/webp;base64,UklGRhgNAABXRUJQ... export const iconPolygon = - 'data:image/octet-stream;base64,UklGRuIDAABXRUJQ... + 'data:image/webp;base64,UklGRuIDAABXRUJQ...src/utils/fragment/index.ts (3)
18-22: Rename interface to follow PascalCase convention.The interface name
interpretFragmentsReturnTypesshould follow TypeScript naming conventions using PascalCase.-interface interpretFragmentsReturnTypes { +interface InterpretFragmentsReturnTypes { hashValid: boolean; issuedValid: boolean; identityValid: boolean; }Also update the return type on line 47:
export const interpretFragments = ( fragments: VerificationFragment[], -): interpretFragmentsReturnTypes => { +): InterpretFragmentsReturnTypes => {
54-90: Consider adding explicit type annotation for the errors array.The
errorsarray is implicitly typed. Adding an explicit type annotation improves readability and catches potential type errors early.export const OAErrorMessageHandling = (fragments: VerificationFragment[]): string[] => { const { hashValid, issuedValid, identityValid } = interpretFragments(fragments); - const errors = []; + const errors: string[] = [];
114-141: Consider adding explicit type annotation for consistency.Similar to
OAErrorMessageHandling, theerrorsarray should have an explicit type annotation for consistency.const errorMessageHandling = (fragments: VerificationFragment[]): string[] => { const { hashValid, issuedValid, identityValid } = interpretFragments(fragments); - const errors = []; + const errors: string[] = [];src/utils/gasStation/index.ts (3)
1-2: Remove commented-out code.These commented import lines should be removed as they serve no purpose and add noise. Per static analysis.
-// export { gasStation, calculateMaxFee, scaleBigNumber } from '@tradetrust-tt/tradetrust-utils'; -// export type { GasStationFunction, GasStationFeeData } from '@tradetrust-tt/tradetrust-utils'; import { BigNumber, ethers } from 'ethers';
71-72: Simplify undefined checks (optional).Per static analysis, prefer direct comparison with
undefinedinstead oftypeof. This applies to lines 71, 86, and 89.- if (wei === null || typeof wei === 'undefined') { + if (wei === null || wei === undefined) { throw new Error('Wei not specified'); }
31-33: Consider preserving the original error context.The catch block discards the original error, making debugging harder. Consider including the original error message or at least logging it.
- } catch { - throw new Error('Failed to fetch gas station'); + } catch (error) { + throw new Error(`Failed to fetch gas station: ${error instanceof Error ? error.message : String(error)}`); }src/utils/gasStation/index.test.ts (1)
1-87: Good test coverage forgasStation, but missing tests for other exports.The tests adequately cover the
gasStationfunction. However,scaleBigNumberandcalculateMaxFeeare also exported but have no test coverage in this file. Consider adding tests for these functions, especially edge cases like:
scaleBigNumberwith null/undefined inputcalculateMaxFeewith scale = 1 (fast path) and scale != 1- Values near precision boundaries
src/token-registry-functions/utils.ts (1)
3-4: Remove commented-out import.The commented import on line 3 should be removed. Per static analysis.
-// import { CHAIN_ID, SUPPORTED_CHAINS } from '@tradetrust-tt/tradetrust-utils'; import { CHAIN_ID, SUPPORTED_CHAINS } from '../utils';src/__tests__/token-registry-functions/returnToken.test.ts (1)
7-7: Consider standardizing CHAIN_ID import paths across test files.This file imports CHAIN_ID from
../../utils/supportedChains, while other test files (e.g., mint.test.ts) import from../../utils/index.js. Both paths may work if properly re-exported, but using a consistent import path through the barrel export (../../utils/index.jsor../../utils) improves maintainability.src/__tests__/token-registry-functions/rejectTransfers.test.ts (1)
6-6: Consider standardizing CHAIN_ID import paths across test files.This file imports CHAIN_ID from
../../utils/supportedChains, while other test files import from../../utils/index.js. Using a consistent import path through the barrel export improves maintainability.src/__tests__/token-registry-functions/transfers.test.ts (1)
7-7: Local SUPPORTED_CHAINS usage looks good; consider cleaning up commented dynamic importsSwitching to the local
CHAIN_ID/SUPPORTED_CHAINSimport is consistent with the new utils module, and the pattern of overridingSUPPORTED_CHAINS[mockChainId].gasStationthen restoring it is correct for these tests.You can safely remove the now-redundant commented dynamic-import blocks for
SUPPORTED_CHAINS(Lines 172–174, 361–363, 543, 719) to reduce noise and avoid future confusion.Also applies to: 169-203, 350-392, 542-574, 708-748
src/utils/fragment/fragments.test.ts (1)
1-158: Comprehensive coverage for fragment interpretation and error aggregationThe test scenarios for
interpretFragmentsanderrorMessageHandlingare well structured and cover the main combinations of hash/issued/identity validity plus the various error codes (HASH, IDENTITY, ISSUED, REVOKED, ADDRESS_INVALID, CONTRACT_NOT_FOUND, SERVER_ERROR, ETHERS_UNHANDLED_ERROR).If you want to reduce duplication later, you could import the centralised error constants (e.g., via
errorMessages) instead of hardcoding the string literals, but the current tests are already clear and effective.src/utils/errorMessages/index.ts (1)
1-8: Tighten up local CONSTANTS wiring and remove dead commented importThe move to a local
VerificationErrorMessagessource looks fine, and assigning the module namespace toerrorMessages: ErrorMessageswill work as long as that module exposes the expectedTYPES/MESSAGESshape.Two small cleanups:
- Remove the commented external import to satisfy the Sonar warning and avoid confusion.
- (Optional) Make the mapping explicit, which also better documents the contract:
-import * as CONSTANTS from './VerificationErrorMessages'; +import { TYPES, MESSAGES } from './VerificationErrorMessages'; ... -// Re-export with proper typing -export const errorMessages: ErrorMessages = CONSTANTS; +// Re-export with proper typing +export const errorMessages: ErrorMessages = { TYPES, MESSAGES };src/utils/network/index.ts (1)
1-21: Local network types look good; drop obsolete commented re-exportDefining
networksas a readonly tuple and derivingnetworkNameplus the explicitnetworkType/networkCurrencyunions is a clean replacement for the previous external re-export.You can safely delete the commented
export * from '@tradetrust-tt/tradetrust-utils/constants/network';line now that the local definitions are in place, which will also address the Sonar warning.src/utils/analytics/analytics.ts (1)
1-54: Consider making validators gate event dispatch, not just logThe core GA helpers are structurally sound:
validateGtagsafely checks forgtagand avoids runtime errors.gaPageView/gaEventcorrectly construct page_view and generic event payloads.Right now,
validatePageViewEventandvalidateGaEventonly log errors but don’t prevent sending malformed events (e.g., missing category/action or wrong value type) —gaPageView/gaEventproceed regardless.If you want validation to be effective rather than advisory, consider having validators return a boolean (or throw) and short‑circuit on failure, e.g.:
export const validateGaEvent = (gaEvent: GaEventProps): boolean => { let valid = true; if (!gaEvent.category) { console.error('Category is required'); valid = false; } if (!gaEvent.action) { console.error('Action is required'); valid = false; } if (gaEvent.label != null && typeof gaEvent.label !== 'string') { console.error('Label must be a string'); valid = false; } if (gaEvent.value != null && typeof gaEvent.value !== 'number') { console.error('Value must be a number'); valid = false; } return valid; }; export const gaEvent = (gaEvent: GaEventProps): void => { if (!validateGtag()) return; if (!validateGaEvent(gaEvent)) return; ... };This keeps the API the same but avoids emitting obviously invalid analytics data.
src/utils/analytics/analytics.test.ts (2)
1-29: Simplify console spying and align “gtag not present” test with its setupA couple of small testing improvements:
- You don’t need to
vi.spyOn(console, 'error'/'warn')both at the top level and again inbeforeEach. Initialising the spies inbeforeEach(and using those references in expectations) is enough and avoids any risk of double‑spying confusion.- In the
gaEventsuite, the test"does not fail if gtag is not present"currently runs withgtaginitialised in the suitebeforeEach. Either rename this test to reflect that it’s a generic smoke test, or clearglobalThis.gtag/window.gtaginside that test before callinggaEventso it truly covers the “not present” scenario.These are test-only changes but will make intent clearer and more robust.
Also applies to: 31-37
48-59: UseglobalThisinstead ofwindowfor gtag in tests to satisfy Sonar and be environment-agnosticSonar’s suggestions to prefer
globalThisoverwindowhere are reasonable and easy to adopt, and they’ll also make the tests less dependent on a DOM-like environment.You can simplify the setup/teardown by only touching
globalThis.gtagand asserting on it, e.g.:beforeEach(() => { - // Ensure both global gtag (used by code) and window.gtag (used by assertions) are set - (globalThis as any).gtag = vi.fn(); - window.gtag = (globalThis as any).gtag; + (globalThis as any).gtag = vi.fn(); }); afterEach(() => { - window.gtag = undefined as any; - (globalThis as any).gtag = undefined; + (globalThis as any).gtag = undefined; }); ... - expect(window.gtag).toHaveBeenCalledTimes(1); - expect(window.gtag).toHaveBeenCalledWith('event', 'TEST_ACTION', { ... }); + expect((globalThis as any).gtag).toHaveBeenCalledTimes(1); + expect((globalThis as any).gtag).toHaveBeenCalledWith('event', 'TEST_ACTION', { ... });This will also remove the “unnecessary assertion” warning on the
as anycast.Also applies to: 60-80, 129-139, 141-163
src/utils/supportedChains/index.ts (2)
1-1: Remove commented-out code.Dead code clutters the codebase. If this export is no longer needed, delete the line entirely rather than leaving it commented.
-// export * from '@tradetrust-tt/tradetrust-utils/constants/supportedChains';
60-60: Consider validating environment variables at startup.Environment variables like
INFURA_API_KEY,OKLINK_API_KEY, andSTABILITY_*_API_KEYare interpolated directly into URLs. If any are undefined, you'll get malformed URLs likehttps://mainnet.infura.io/v3/undefined. Consider adding validation or fallback handling for required env vars.Also applies to: 70-70, 87-87, 103-103, 148-148, 164-164
src/utils/errorMessages/VerificationErrorMessages.ts (1)
1-18: Consider usingas constfor stricter type inference.Adding
as constto theTYPESobject enables TypeScript to infer literal types for the values, which can improve type safety when used as discriminants.export const TYPES = { REVOKED: 'REVOKED', SUSPENDED: 'SUSPENDED', ISSUED: 'ISSUED', HASH: 'HASH', IDENTITY: 'IDENTITY', INVALID: 'INVALID', ADDRESS_INVALID: 'ADDRESS_INVALID', NETWORK_INVALID: 'NETWORK_INVALID', NETWORK_MISMATCH_MAINNET: 'NETWORK_MISMATCH_MAINNET', NETWORK_MISMATCH_TESTNET: 'NETWORK_MISMATCH_TESTNET', CONTRACT_NOT_FOUND: 'CONTRACT_NOT_FOUND', INVALID_ARGUMENT: 'INVALID_ARGUMENT', SERVER_ERROR: 'SERVER_ERROR', ETHERS_UNHANDLED_ERROR: 'ETHERS_UNHANDLED_ERROR', CLIENT_NETWORK_ERROR: 'CLIENT_NETWORK_ERROR', VERIFICATION_ERROR: 'VERIFICATION_ERROR', -}; +} as const;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (29)
package.json(2 hunks)src/__tests__/e2e/token-registry-functions/rejectTransfer.e2e.test.ts(1 hunks)src/__tests__/e2e/token-registry-functions/returnToken.e2e.test.ts(1 hunks)src/__tests__/e2e/token-registry-functions/transfer.e2e.test.ts(1 hunks)src/__tests__/fixtures/verifier-response.ts(1 hunks)src/__tests__/token-registry-functions/mint.test.ts(1 hunks)src/__tests__/token-registry-functions/ownerOf.test.ts(1 hunks)src/__tests__/token-registry-functions/rejectTransfers.test.ts(1 hunks)src/__tests__/token-registry-functions/returnToken.test.ts(1 hunks)src/__tests__/token-registry-functions/transfers.test.ts(5 hunks)src/__tests__/utils/fragment/errorMessageHandling.test.ts(1 hunks)src/token-registry-functions/types.ts(1 hunks)src/token-registry-functions/utils.ts(1 hunks)src/utils/analytics/analytics.test.ts(1 hunks)src/utils/analytics/analytics.ts(1 hunks)src/utils/analytics/index.ts(1 hunks)src/utils/errorMessages/VerificationErrorMessages.ts(1 hunks)src/utils/errorMessages/index.ts(1 hunks)src/utils/fragment/fragments.test.ts(1 hunks)src/utils/fragment/index.ts(2 hunks)src/utils/gasStation/index.test.ts(1 hunks)src/utils/gasStation/index.ts(1 hunks)src/utils/index.ts(1 hunks)src/utils/network/index.ts(1 hunks)src/utils/static/icons.ts(1 hunks)src/utils/supportedChains/index.ts(1 hunks)src/utils/supportedChains/supportedChains.test.ts(1 hunks)tsconfig.build.json(1 hunks)tsconfig.json(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
src/utils/supportedChains/supportedChains.test.ts (1)
src/utils/supportedChains/index.ts (1)
SUPPORTED_CHAINS(41-204)
src/utils/gasStation/index.test.ts (1)
src/utils/gasStation/index.ts (1)
gasStation(21-34)
src/utils/fragment/index.ts (2)
src/verify/verify.ts (3)
VerificationFragment(99-99)utils(86-86)isValid(78-78)src/utils/errorMessages/VerificationErrorMessages.ts (1)
TYPES(1-18)
src/utils/analytics/analytics.test.ts (1)
src/utils/analytics/analytics.ts (5)
validateGtag(14-18)validatePageViewEvent(20-24)gaPageView(26-34)validateGaEvent(36-42)gaEvent(44-54)
🪛 GitHub Check: SonarCloud Code Analysis
src/utils/network/index.ts
[warning] 1-1: Remove this commented out code.
src/utils/fragment/index.ts
[warning] 18-18: Rename interface "interpretFragmentsReturnTypes" to match the regular expression ^[A-Z][a-zA-Z0-9]*$.
[warning] 1-5: Remove this commented out code.
src/utils/supportedChains/index.ts
[warning] 1-1: Remove this commented out code.
src/utils/analytics/analytics.test.ts
[warning] 149-149: Prefer globalThis over window.
[warning] 148-148: Prefer globalThis over window.
[warning] 52-52: Prefer globalThis over window.
[warning] 137-137: Prefer globalThis over window.
[warning] 56-56: Prefer globalThis over window.
[warning] 67-67: Prefer globalThis over window.
[warning] 68-68: Prefer globalThis over window.
[warning] 133-133: Prefer globalThis over window.
[warning] 133-133: This assertion is unnecessary since it does not change the type of the expression.
src/token-registry-functions/utils.ts
[warning] 3-3: Remove this commented out code.
src/utils/gasStation/index.ts
[warning] 71-71: Compare with undefined directly instead of using typeof.
[warning] 86-86: Compare with undefined directly instead of using typeof.
[warning] 38-38: Use the "RegExp.exec()" method instead.
[warning] 59-59: Use the "RegExp.exec()" method instead.
[warning] 89-89: Compare with undefined directly instead of using typeof.
[warning] 1-2: Remove this commented out code.
src/utils/errorMessages/index.ts
[warning] 1-1: Remove this commented out code.
🔇 Additional comments (21)
package.json (1)
133-133: Appropriate choice of node-fetch v2.x for dual module support.Using node-fetch v2.x is correct since v3.x is ESM-only and would break the CommonJS build output. The type definitions at line 152 align properly.
tsconfig.json (1)
8-8: LGTM!Adding
gtag.jsto the types array properly enables ambient type definitions for the new analytics utilities.tsconfig.build.json (1)
7-7: LGTM!Build configuration properly includes gtag types, consistent with the base tsconfig.json.
src/utils/fragment/index.ts (3)
31-38: LGTM!The helper correctly extracts the DID-signed document status fragment and checks for the
DOCUMENT_REVOKEDstatus code. The documentation clearly explains why this project-level check is necessary.
45-52: LGTM!The function properly aggregates fragment results using the
isValidhelper from@tradetrust-tt/tt-verifywith the correct verification types.
143-143: LGTM!The export statement correctly exposes
errorMessageHandling,w3cCredentialStatusRevoked, andw3cCredentialStatusSuspendedas the public API surface.src/__tests__/e2e/token-registry-functions/transfer.e2e.test.ts (1)
4-4: LGTM!Import path correctly updated to use local utilities, consistent with the PR objective to consolidate TT-utils.
src/__tests__/e2e/token-registry-functions/rejectTransfer.e2e.test.ts (1)
6-6: LGTM!Import path correctly updated to use local utilities, consistent with other test files in this PR.
src/utils/analytics/index.ts (1)
1-1: LGTM!Standard barrel export pattern for the analytics module.
src/utils/index.ts (1)
9-9: LGTM!The analytics module is properly added to the public API through the barrel export, consistent with the existing export pattern.
src/__tests__/token-registry-functions/ownerOf.test.ts (1)
6-6: LGTM!Correctly imports CHAIN_ID through the barrel export at
../../utils/index.js, which is the preferred pattern for accessing utilities.src/__tests__/e2e/token-registry-functions/returnToken.e2e.test.ts (1)
3-3: LGTM!Correctly imports CHAIN_ID through the barrel export with the appropriate relative path for the e2e test directory structure.
src/__tests__/token-registry-functions/mint.test.ts (1)
19-19: CHAIN_ID is correctly exported from the local utils module.The import path change from the external package to
'../../utils/index.js'is valid. The local utils module properly re-exportsCHAIN_IDfrom thesupportedChainssubmodule via its index file, maintaining the same interface.src/token-registry-functions/types.ts (1)
1-1: No type compatibility issues found with CHAIN_ID import.The import path is correctly configured and properly resolves through the utils barrel export.
CHAIN_IDis defined as a string enum insrc/utils/supportedChains/index.tsand is re-exported viasrc/utils/index.ts, making it available at the../utilsimport location. TheTransactionOptionsinterface correctly uses the optionalchainId?: CHAIN_IDproperty, maintaining type safety for the public API.src/__tests__/utils/fragment/errorMessageHandling.test.ts (1)
2-3: Wiring to local errorMessages/fragment utilities looks correctImporting
errorMessagesasCONSTANTSanderrorMessageHandlingfrom the local utils path preserves the previous behavior while decoupling from the external package. The tests remain clear and correctly assert againstCONSTANTS.TYPES.src/utils/supportedChains/supportedChains.test.ts (1)
1-108: Chain metadata tests align with SUPPORTED_CHAINS configurationThese tests correctly mirror the
SUPPORTED_CHAINSentries (id, name, type, currency, explorer URL, and Amoy RPC prefix). The import path to../supportedChainswill resolve to the index module as intended.src/utils/supportedChains/index.ts (2)
7-19: LGTM!The
CHAIN_IDenum provides a clean, type-safe way to reference chain identifiers across the codebase.
21-37: LGTM!The
chainInfotype is well-structured with appropriate optional fields for chain-specific features likegasStationandnativeCurrency.src/utils/errorMessages/VerificationErrorMessages.ts (1)
20-112: LGTM!The
MESSAGESmapping provides comprehensive, user-friendly error messages for all verification scenarios. The structure is consistent and the messages are clear and actionable.src/__tests__/fixtures/verifier-response.ts (2)
1-105: LGTM!Comprehensive test fixtures covering various document verification scenarios. The data structures accurately represent OpenAttestation verification fragments.
276-289: Good use of composition for derived fixtures.Reusing
whenDocumentValidAndIssuedByDnsand filtering by type to create the tampered hash scenario reduces duplication and ensures consistency across related test cases.
| // Too many decimals and some non-zero ending, take the ceiling | ||
| if (comps[1].length > 9 && !comps[1].substring(9).match(/^0+$/)) { | ||
| comps[1] = BigNumber.from(comps[1].substring(0, 9)).add(BigNumber.from(1)).toString(); | ||
| } | ||
|
|
||
| return ethers.utils.parseUnits(`${comps[0]}.${comps[1]}`, decimals); |
There was a problem hiding this comment.
Hardcoded 9 should use decimals parameter, and ceiling logic may overflow.
Two issues in this block:
- Line 59 uses hardcoded
9instead of thedecimalsparameter - Line 60: Adding 1 to the fractional part can cause overflow (e.g., "999999999" + 1 = "1000000000"), which would then cause
parseUnitsto fail or produce incorrect results
- if (comps[1].length > 9 && !comps[1].substring(9).match(/^0+$/)) {
- comps[1] = BigNumber.from(comps[1].substring(0, 9)).add(BigNumber.from(1)).toString();
+ if (comps[1].length > decimals && !comps[1].substring(decimals).match(/^0+$/)) {
+ const fractional = BigNumber.from(comps[1].substring(0, decimals)).add(BigNumber.from(1));
+ const fractionalStr = fractional.toString();
+ // Handle carry-over to whole part
+ if (fractionalStr.length > decimals) {
+ comps[0] = BigNumber.from(comps[0]).add(1).toString();
+ comps[1] = '0'.repeat(decimals);
+ } else {
+ comps[1] = fractionalStr.padStart(decimals, '0');
+ }
+ } else {
+ comps[1] = comps[1].substring(0, decimals);
}🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis
[warning] 59-59: Use the "RegExp.exec()" method instead.
🤖 Prompt for AI Agents
In src/utils/gasStation/index.ts around lines 58 to 63, the code currently uses
a hardcoded "9" for fractional trimming and naively adds 1 to the fractional
substring which can overflow; change the hardcoded 9 to the function's decimals
parameter, and when rounding up handle carry: compute the fractional substring
of length decimals, if the truncated tail contains any non-zero digit then add
one to the fractional part using BigNumber; if that addition increases the
fractional string length (e.g., "999" + 1 -> "1000") roll the carry into the
integer part (increment comps[0]) and set the fractional string to zeros of
length decimals; finally left-pad or right-pad the fractional string to exactly
decimals before calling ethers.utils.parseUnits so parseUnits receives a valid
fixed-length fraction.
| currency: 'MATIC', | ||
| iconImage: iconPolygon, | ||
| explorerUrl: 'https://www.oklink.com/amoy', | ||
| explorerApiUrl: `https://www.oklink.com/${process.env.OKLINK_API_KEY}`, |
There was a problem hiding this comment.
🧩 Analysis chain
OKLink API authentication format documentation
<web_search_result>
OKLink private REST requests — required headers and signing
-
Required headers:
- OK-ACCESS-KEY: your APIKey. [1]
- OK-ACCESS-SIGN: Base64-encoded HMAC-SHA256 signature. [1]
- OK-ACCESS-TIMESTAMP: UTC timestamp in ISO 8601 with milliseconds (e.g. 2022-10-07T07:03:54.726Z). [1]
- OK-ACCESS-PASSPHRASE: passphrase chosen when creating the APIKey. [1]
-
Signature generation:
- Build the prehash string: timestamp + HTTP_METHOD(UPPERCASE) + requestPath + body (body omitted for GET). Query parameters for GET count as part of requestPath. [1]
- Compute HMAC-SHA256 of the prehash string using your SecretKey. [1]
- Base64-encode the HMAC result and put it in OK-ACCESS-SIGN. [1]
-
Request notes:
- Request body must be application/json. [1]
- requestPath is the API path (e.g. /api/v5/asset/balances). [1]
Source: OKLink API docs. [1] https://www.oklink.com/docs/trust_en/
</web_search_result>
OKLink explorer API public endpoint authentication
<web_search_result>
Short answer — it depends:
-
Public/read-only explorer endpoints (e.g., basic chain/query endpoints) are typically unauthenticated and can be called without an API key. See example explorer endpoints in the docs. [1]
-
Actions that change state or access protected data (broadcasting txs, contract verification, rate‑limited/paid endpoints) require API credentials and signed headers (OK-ACCESS-KEY / OK-ACCESS-SIGN / passphrase style auth). See the API key / signing instructions. [2][3]
-
Note: OKLink announced suspension of the Explorer API service effective May 20, 2025; if you plan integration verify current service status with OKLink before building. [4]
Sources:
[1] OKLink explorer API examples/docs. [2] OKLink API authentication / APIKey & signing headers. [3] OKLink explorer endpoint example (v5). [4] OKLink announcement: suspension of Explorer API (May 20, 2025).
</web_search_result>
Script executed:
rg -n "explorerApiUrl" --type ts --type js -B 3 -A 3Repository: TrustVC/trustvc
<shell_result>
Repository: TrustVC/trustvc
Exit code: 0
stdout:
src/utils/supportedChains/index.ts-26- currency: networkCurrency;
src/utils/supportedChains/index.ts-27- iconImage: string;
src/utils/supportedChains/index.ts-28- explorerUrl: string;
src/utils/supportedChains/index.ts:29: explorerApiUrl?: string;
src/utils/supportedChains/index.ts-30- rpcUrl?: string;
src/utils/supportedChains/index.ts-31- gasStation?: () => Promise<GasStationFeeData | undefined>;
src/utils/supportedChains/index.ts-32- nativeCurrency?: {
--
src/utils/supportedChains/index.ts-83- currency: 'MATIC',
src/utils/supportedChains/index.ts-84- iconImage: iconPolygon,
src/utils/supportedChains/index.ts-85- explorerUrl: 'https://www.oklink.com/amoy',
src/utils/supportedChains/index.ts:86: explorerApiUrl: `https://www.oklink.com/${process.env.OKLINK_API_KEY}`,
src/utils/supportedChains/index.ts-87- rpcUrl: `https://polygon-amoy.infura.io/v3/${process.env.INFURA_API_KEY}`,
src/utils/supportedChains/index.ts-88- gasStation: gasStation('https://gasstation-testnet.polygon.technology/amoy'),
src/utils/supportedChains/index.ts-89- nativeCurrency: {
</shell_result>
Script executed:
rg -n "explorerApiUrl" --type ts --type jsRepository: TrustVC/trustvc
<shell_result>
Repository: TrustVC/trustvc
Exit code: 0
stdout:
src/utils/supportedChains/index.ts:29: explorerApiUrl?: string;
src/utils/supportedChains/index.ts:86: explorerApiUrl: `https://www.oklink.com/${process.env.OKLINK_API_KEY}`,
</shell_result>
Remove the API key from the URL path and use proper OKLink authentication headers instead.
OKLink API authentication requires headers (OK-ACCESS-KEY, OK-ACCESS-SIGN, OK-ACCESS-TIMESTAMP, OK-ACCESS-PASSPHRASE) for protected endpoints, not API keys embedded in the URL path. Public/read-only explorer endpoints are typically unauthenticated and require no API key at all. The current format exposes the key in logs, URLs, and referrer headers, which is a security anti-pattern.
Additionally, OKLink has announced suspension of the Explorer API effective May 20, 2025—verify current service status before relying on this integration.
🤖 Prompt for AI Agents
In src/utils/supportedChains/index.ts around line 86, the explorerApiUrl is
embedding the OKLink API key into the URL path which leaks secrets and is wrong
for OKLink (their protected endpoints require authentication via headers, or
public explorer endpoints require no key). Remove the API key from the URL and
set explorerApiUrl to the base public endpoint only; implement/expect OKLink
auth to be provided via request headers (OK-ACCESS-KEY, OK-ACCESS-SIGN,
OK-ACCESS-TIMESTAMP, OK-ACCESS-PASSPHRASE) when calling protected endpoints, and
ensure the key is read from env and used only in header construction (not
concatenated into URLs), also add a note or conditional to verify the Explorer
API availability given the May 20, 2025 suspension notice.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
src/utils/analytics/analytics.test.ts (1)
133-133: Remove redundant type assertion.The type assertion
as anyafter(globalThis as any).gtagis redundant since the expression is already typed asany.Apply this diff:
- window.gtag = (globalThis as any).gtag as any; + window.gtag = (globalThis as any).gtag;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/utils/analytics/analytics.test.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/utils/analytics/analytics.test.ts (1)
src/utils/analytics/analytics.ts (5)
validateGtag(14-18)validatePageViewEvent(20-24)gaPageView(26-34)validateGaEvent(36-42)gaEvent(44-54)
🪛 GitHub Check: SonarCloud Code Analysis
src/utils/analytics/analytics.test.ts
[warning] 133-133: This assertion is unnecessary since it does not change the type of the expression.
[warning] 56-56: Prefer globalThis over window.
[warning] 148-148: Prefer globalThis over window.
[warning] 133-133: Prefer globalThis over window.
[warning] 67-67: Prefer globalThis over window.
[warning] 68-68: Prefer globalThis over window.
[warning] 149-149: Prefer globalThis over window.
[warning] 52-52: Prefer globalThis over window.
[warning] 137-137: Prefer globalThis over window.
🔇 Additional comments (3)
src/utils/analytics/analytics.test.ts (3)
1-19: LGTM!The test setup is well-structured with appropriate vitest configuration, console spies, and mock data.
21-29: LGTM!The beforeEach and afterEach hooks properly manage mock state between tests.
31-37: LGTM!The test correctly verifies that a warning is logged when gtag is not initialized.
| }); | ||
| }); | ||
|
|
||
| describe('validateGaPageView', () => { |
There was a problem hiding this comment.
Fix the describe block name.
The describe block name "validateGaPageView" doesn't match the function name "validatePageViewEvent".
Apply this diff:
-describe('validateGaPageView', () => {
+describe('validatePageViewEvent', () => {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| describe('validateGaPageView', () => { | |
| describe('validatePageViewEvent', () => { |
🤖 Prompt for AI Agents
In src/utils/analytics/analytics.test.ts around line 39, the describe block is
named "validateGaPageView" but the test targets the function
validatePageViewEvent; update the describe block name to "validatePageViewEvent"
so it matches the function under test, keeping surrounding test code intact.
| it('errors if there is a validation error', () => { | ||
| const mockGaEventError = { action: 123 }; | ||
| // @ts-expect-error the mock does not match the signature | ||
| gaPageView(mockGaEventError); | ||
| expect(consoleError).toHaveBeenCalledTimes(1); | ||
| expect(consoleError).toHaveBeenCalledWith('Action must be a string'); | ||
| }); |
There was a problem hiding this comment.
Missing required parameter in function call.
The gaPageView function requires two parameters (gaEvent and gaId), but line 76 only provides one. This means the test doesn't properly exercise the validation error path.
Apply this diff:
const mockGaEventError = { action: 123 };
// @ts-expect-error the mock does not match the signature
- gaPageView(mockGaEventError);
+ gaPageView(mockGaEventError, GA_MEASUREMENT_ID);
expect(consoleError).toHaveBeenCalledTimes(1);
expect(consoleError).toHaveBeenCalledWith('Action must be a string');🤖 Prompt for AI Agents
In src/utils/analytics/analytics.test.ts around lines 73 to 79, the test calls
gaPageView with only the gaEvent argument which omits the required gaId and
prevents the test from hitting the intended validation path; update the function
call to include a valid dummy GA id (e.g. 'GA-TEST') as the second argument so
the validation runs against the malformed gaEvent.action and the existing
assertions remain valid.
| it('passes for minimum values', () => { | ||
| validateGaEvent({ | ||
| category: 'foobar', | ||
| action: 'foobar_start', | ||
| label: undefined, | ||
| value: undefined, | ||
| }); | ||
| expect(true).toBe(true); | ||
| }); | ||
|
|
||
| it('passes for all values', () => { | ||
| validateGaEvent({ | ||
| category: 'foobar', | ||
| action: 'foobar_start', | ||
| label: 'Start Foobar', | ||
| value: 2, | ||
| }); | ||
| expect(true).toBe(true); | ||
| }); |
There was a problem hiding this comment.
Replace meaningless assertions.
Lines 115 and 125 use expect(true).toBe(true), which doesn't verify anything meaningful. Consider asserting that consoleError was NOT called instead.
Apply this diff:
it('passes for minimum values', () => {
validateGaEvent({
category: 'foobar',
action: 'foobar_start',
label: undefined,
value: undefined,
});
- expect(true).toBe(true);
+ expect(consoleError).not.toHaveBeenCalled();
});
it('passes for all values', () => {
validateGaEvent({
category: 'foobar',
action: 'foobar_start',
label: 'Start Foobar',
value: 2,
});
- expect(true).toBe(true);
+ expect(consoleError).not.toHaveBeenCalled();
});Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/utils/analytics/analytics.test.ts around lines 108 to 126, the tests use
meaningless assertions expect(true).toBe(true); replace them with assertions
that console error was not invoked: set up a spy (or mock) for console.error (or
the existing consoleError mock if present) before calling validateGaEvent, call
validateGaEvent with the same payloads, then assert that the spy was not called
(e.g., expect(consoleError).not.toHaveBeenCalled()), and finally restore/clear
the spy to avoid test pollution.
| it('does not fail if gtag is not present', () => { | ||
| gaEvent(mockGaEvent as any); | ||
| expect(true).toBe(true); | ||
| }); |
There was a problem hiding this comment.
Test doesn't verify the intended condition.
This test claims to verify behavior "if gtag is not present", but the beforeEach hook on lines 130-133 always sets up gtag. The test doesn't actually exercise the code path when gtag is absent.
Apply this diff to properly test the absence of gtag:
it('does not fail if gtag is not present', () => {
+ // Remove gtag to test the not-present case
+ window.gtag = undefined as any;
+ (globalThis as any).gtag = undefined;
gaEvent(mockGaEvent as any);
expect(true).toBe(true);
});Alternatively, consider moving this test outside the describe block so it doesn't run the beforeEach hook that sets up gtag.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| it('does not fail if gtag is not present', () => { | |
| gaEvent(mockGaEvent as any); | |
| expect(true).toBe(true); | |
| }); | |
| it('does not fail if gtag is not present', () => { | |
| // Remove gtag to test the not-present case | |
| window.gtag = undefined as any; | |
| (globalThis as any).gtag = undefined; | |
| gaEvent(mockGaEvent as any); | |
| expect(true).toBe(true); | |
| }); |
🤖 Prompt for AI Agents
In src/utils/analytics/analytics.test.ts around lines 141 to 144, the test "does
not fail if gtag is not present" is invalid because the describe-level
beforeEach always sets window.gtag; update the test to remove or stub out gtag
before invoking gaEvent (e.g., delete (window as any).gtag or set it to
undefined) or move this test outside the describe that installs gtag so it
actually exercises the absent-gtag path, then assert that gaEvent does not throw
and that no global gtag calls were attempted (e.g., wrap gaEvent call in
expect(() => gaEvent(...)).not.toThrow() and verify any spy on global gtag is
not called).
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/utils/gasStation/index.ts (1)
34-62: Hardcoded9should usedecimalsparameter, and ceiling logic may overflow.This is the same issue flagged in the previous review. Two problems persist:
- Line 57: Uses hardcoded
9instead of thedecimalsparameter- Lines 58-59: Adding 1 to the fractional part can overflow (e.g., "999999999" + 1 = "1000000000"), producing an invalid string for
parseUnitsAdditionally, after line 59, if the fractional part is shorter than
decimals, it needs proper padding or truncation before callingparseUnits.Apply this diff to fix:
- // Pad the fraction to 9 decimal places + // Pad the fraction to the specified decimal places while (comps[1].length < decimals) { comps[1] += '0'; } // Too many decimals and some non-zero ending, take the ceiling - if (comps[1].length > 9 && !comps[1].substring(9).match(/^0+$/)) { - comps[1] = BigNumber.from(comps[1].substring(0, 9)).add(BigNumber.from(1)).toString(); + if (comps[1].length > decimals && !comps[1].substring(decimals).match(/^0+$/)) { + const fractional = BigNumber.from(comps[1].substring(0, decimals)).add(BigNumber.from(1)); + const fractionalStr = fractional.toString(); + // Handle carry-over to whole part + if (fractionalStr.length > decimals) { + comps[0] = BigNumber.from(comps[0]).add(1).toString(); + comps[1] = '0'.repeat(decimals); + } else { + comps[1] = fractionalStr.padStart(decimals, '0'); + } + } else { + comps[1] = comps[1].substring(0, decimals); }src/utils/supportedChains/index.ts (1)
85-86: Remove the API key from the URL path and use proper OKLink authentication headers instead.This is the same security issue flagged in the previous review. OKLink API authentication requires headers (
OK-ACCESS-KEY,OK-ACCESS-SIGN,OK-ACCESS-TIMESTAMP,OK-ACCESS-PASSPHRASE) for protected endpoints, not API keys embedded in the URL path. Public/read-only explorer endpoints typically require no authentication at all.Embedding the key in the URL:
- Exposes secrets in logs, URLs, and referrer headers
- Uses the wrong authentication method for OKLink
- May not work at all given OKLink announced suspension of Explorer API effective May 20, 2025
Apply this diff:
explorerUrl: 'https://www.oklink.com/amoy', - explorerApiUrl: `https://www.oklink.com/${process.env.OKLINK_API_KEY}`, + explorerApiUrl: 'https://www.oklink.com/amoy',Implement OKLink authentication via request headers (when calling protected endpoints) rather than URL construction. Also verify the Explorer API availability given the suspension notice.
🧹 Nitpick comments (7)
src/utils/fragment/index.ts (3)
13-17: Rename interface to PascalCase.Per TypeScript conventions, interface names should use PascalCase.
-interface interpretFragmentsReturnTypes { +interface InterpretFragmentsReturnTypes { hashValid: boolean; issuedValid: boolean; identityValid: boolean; }Also update the return type annotation on line 42:
): InterpretFragmentsReturnTypes => {
49-52: Add explicit type annotation toerrorsarray.Without a type annotation, TypeScript may infer
never[]in strict mode, which would cause type errors onpushcalls.export const OAErrorMessageHandling = (fragments: VerificationFragment[]): string[] => { const { hashValid, issuedValid, identityValid } = interpretFragments(fragments); - const errors = []; + const errors: string[] = [];
109-111: Add explicit type annotation toerrorsarray.Same issue as in
OAErrorMessageHandling- the array needs an explicit type annotation.const errorMessageHandling = (fragments: VerificationFragment[]): string[] => { const { hashValid, issuedValid, identityValid } = interpretFragments(fragments); - const errors = []; + const errors: string[] = [];src/utils/gasStation/index.ts (3)
19-32: Consider returningundefinedon error for consistency with the return type.The function's return type is
Promise<GasStationFeeData | undefined>, but the catch block throws an error rather than returningundefined. This creates inconsistent behavior—callers expectingundefinedon failure will instead receive an unhandled promise rejection.Apply this diff to return
undefinedconsistently:} catch { - throw new Error('Failed to fetch gas station'); + return undefined; }Alternatively, if throwing is intentional, update the return type to remove
| undefined.
64-77: Consider directundefinedcomparison for consistency.The function correctly handles null/undefined inputs. Static analysis suggests comparing with
undefineddirectly rather than usingtypeof, which is a common modern TypeScript pattern.Apply this diff if you prefer the modern style:
- if (wei === null || typeof wei === 'undefined') { + if (wei === null || wei === undefined) { throw new Error('Wei not specified'); }
79-96: Consider directundefinedcomparison for consistency.The function logic is correct, including the fast-path optimization when
scale === 1. Static analysis suggests comparing withundefineddirectly rather than usingtypeof, which aligns with modern TypeScript conventions.Apply this diff if you prefer the modern style:
- if (maxFee === null || typeof maxFee === 'undefined') { + if (maxFee === null || maxFee === undefined) { throw new Error('Max Fee not specified'); } - if (priorityFee === null || typeof priorityFee === 'undefined') { + if (priorityFee === null || priorityFee === undefined) { throw new Error('Priority Fee not specified'); }src/utils/supportedChains/index.ts (1)
59-203: Consider validating environment variables to prevent runtime errors.Multiple chain configurations use environment variables in template strings (e.g.,
INFURA_API_KEY,STABILITY_API_KEY,OKLINK_API_KEY) without validation. If any of these variables are undefined, the resulting URLs will contain the string"undefined", causing runtime failures when the RPC or API endpoints are accessed.Consider adding validation either:
- At module initialization (throw early if required vars are missing)
- At runtime (return undefined or throw descriptive errors when constructing URLs)
Example validation at module level:
const requiredEnvVars = ['INFURA_API_KEY', 'STABILITY_API_KEY', 'STABILITY_TESTNET_API_KEY']; for (const varName of requiredEnvVars) { if (!process.env[varName]) { console.warn(`Environment variable ${varName} is not set. Some chain configurations may fail.`); } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/token-registry-functions/utils.ts(1 hunks)src/utils/errorMessages/index.ts(1 hunks)src/utils/fragment/index.ts(2 hunks)src/utils/gasStation/index.ts(1 hunks)src/utils/network/index.ts(1 hunks)src/utils/supportedChains/index.ts(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/token-registry-functions/utils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/utils/errorMessages/index.ts
🧰 Additional context used
🧬 Code graph analysis (2)
src/utils/supportedChains/index.ts (3)
src/utils/network/index.ts (3)
networkName(16-16)networkType(18-18)networkCurrency(20-20)src/utils/gasStation/index.ts (2)
GasStationFeeData(7-10)gasStation(19-32)src/utils/static/icons.ts (5)
iconEthereum(1-2)iconPolygon(4-5)iconXDC(7-8)iconStability(10-11)iconAstron(13-14)
src/utils/fragment/index.ts (1)
src/utils/errorMessages/VerificationErrorMessages.ts (1)
TYPES(1-18)
🪛 GitHub Check: SonarCloud Code Analysis
src/utils/fragment/index.ts
[warning] 13-13: Rename interface "interpretFragmentsReturnTypes" to match the regular expression ^[A-Z][a-zA-Z0-9]*$.
src/utils/gasStation/index.ts
[warning] 84-84: Compare with undefined directly instead of using typeof.
[warning] 69-69: Compare with undefined directly instead of using typeof.
[warning] 57-57: Use the "RegExp.exec()" method instead.
[warning] 36-36: Use the "RegExp.exec()" method instead.
[warning] 87-87: Compare with undefined directly instead of using typeof.
🔇 Additional comments (7)
src/utils/fragment/index.ts (5)
1-11: Imports are clean and well-organized.The previously commented-out import block has been removed as suggested in prior review. All imports are now in use.
19-33: Well-documented internal helper.Good JSDoc explaining why this project-level helper exists rather than relying on the upstream library. The implementation correctly checks the DID-signed fragment for revocation status.
35-47: Clean aggregation helper.The function correctly delegates to
isValidfor each verification category and returns a well-structured result object.
87-107: W3C status helper functions are correctly implemented.The functions properly handle the various credential status codes including the combined
REVOKED_AND_SUSPENDEDstate.
138-138: Export statement aligns with public API.The named exports correctly expose the intended public interface while keeping internal helpers private.
src/utils/network/index.ts (1)
1-20: LGTM! Clean type definitions.The network constants and type aliases are well-structured. Using
as constfor the networks array provides type safety, and the derived type aliases are appropriate.src/utils/supportedChains/index.ts (1)
6-38: LGTM! Well-structured type definitions.The
CHAIN_IDenum andchainInfotype are clearly defined with appropriate field types. The optional fields (explorerApiUrl?,rpcUrl?,gasStation?,nativeCurrency?) provide flexibility for different chain configurations.
| @@ -1 +1,203 @@ | |||
| export * from '@tradetrust-tt/tradetrust-utils/constants/supportedChains'; | |||
| import 'dotenv/config'; | |||
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Move dotenv/config import to the application entry point.
Importing dotenv/config in a utility module creates side effects and can lead to initialization-order issues. The conventional practice is to import it once at the application's entry point (e.g., index.ts or server.ts) before any other modules are loaded.
Remove the import from this file:
-import 'dotenv/config';And ensure dotenv/config is imported at the top of your application's entry file.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import 'dotenv/config'; |
🤖 Prompt for AI Agents
In src/utils/supportedChains/index.ts lines 1-1 the file currently imports
'dotenv/config' causing side effects and potential initialization-order issues;
remove that import from this module and instead add a single import
'dotenv/config' at the very top of your application's entry point (e.g.,
src/index.ts or src/server.ts) before any other imports so environment variables
are loaded once at startup.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/__tests__/token-registry-functions/mint.test.ts (1)
18-19: Local utils imports look good; optional consistency tweakSwitching
getEthersContractFromProviderto../../utils/ethersandCHAIN_IDto the local../../utilskeeps these tests aligned with the new TT-utils consolidation and should be behaviorally equivalent. IfCHAIN_IDis ultimately sourced fromsupportedChains, you could optionally import it from../../utils/supportedChains(like intransfers.test.ts) to make the source of chain metadata consistent across tests, but this is purely a style/nitpick point.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/__tests__/token-registry-functions/mint.test.ts(1 hunks)src/__tests__/token-registry-functions/ownerOf.test.ts(1 hunks)src/__tests__/token-registry-functions/transfers.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/tests/token-registry-functions/ownerOf.test.ts
🔇 Additional comments (1)
src/__tests__/token-registry-functions/transfers.test.ts (1)
7-7: Migration to local supportedChains is consistent and safeImporting
CHAIN_IDandSUPPORTED_CHAINSfrom../../utils/supportedChainskeeps these transfer tests tied to the same chain metadata used in the app, and the gas-station tests still correctly override and restoreSUPPORTED_CHAINS[mockChainId].gasStation, so behavior should remain unchanged.
|
## [2.5.0](v2.4.2...v2.5.0) (2025-11-27) ### Features * merge tt utils ([#123](#123)) ([5b997fc](5b997fc))
|
🎉 This PR is included in version 2.5.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |


Summary
Merge TT-utils in trustvc
Summary by CodeRabbit
New Features
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.