Conversation
|
Commit title is poor. Should be "Add Xgram swap support" |
|
Our workflow is to never merge master into a feature branch. Always rebase your commits on top of master. Please squash this all into one commit for review. |
c5aaf5a to
62d8e3f
Compare
|
cursor review verbose=true |
|
Bugbot request id: serverGenReqId_e478b76d-79f0-4afa-828f-74563cb5b902 |
|
cursor review verbose=true Use all *.md files in the https://github.com/EdgeApp/edge-conventions repo to determine coding and PR commit style. Use any *.md files in each repo to find docs and coding conventions to adhere to when doing reviews. For this repo use this file to determine if the PR adheres to API requirements https://github.com/EdgeApp/edge-exchange-plugins/blob/paul/apiReq/docs/API_REQUIREMENTS.md |
There was a problem hiding this comment.
see all comments. and re-review
https://github.com/EdgeApp/edge-exchange-plugins/blob/paul/apiReq/docs/API_REQUIREMENTS.md
62d8e3f to
c9987a7
Compare
|
@paullinator All API requirements have been taken and fixed in the latest commit. |
paullinator
left a comment
There was a problem hiding this comment.
API Requirements Review
This PR does not yet comply with the API Requirements document. Please address the following before this can be merged:
Section 1: Chain and Token Identification
The current implementation relies on:
- A separate
fetchSupportedAssets()call tolist-currency-optionsendpoint - Currency codes/ticker symbols (
fromCcy,toCcy) for asset identification
Required changes:
- The API must support quoting using chain identifiers (e.g., 'ethereum', 'polygon') and token identifiers (contract addresses) directly
- Remove the need for a pre-fetch call to list supported assets
- For EVM chains, support
chainIdparameter for generic EVM chain identification
What's working well
- Error handling (Section 3) appears compliant - errors are returned in a structured array with proper priority handling for REGION_UNSUPPORTED, CURRENCY_UNSUPPORTED, BELOW_LIMIT, and ABOVE_LIMIT
Please refer to the inline comments for specific lines that need attention.
paullinator
left a comment
There was a problem hiding this comment.
Required Fixes: Data Validation with Cleaners
All network responses must be validated using cleaners, and the cleaned data must be used throughout the code.
Issues Found:
-
Incomplete cleaner definition -
asTemplateQuoteis missingccyAmountFromandexpiresAtfields that are accessed from the API response -
Raw JSON used instead of cleaned data - The code calls
asTemplateQuoteReply()but then accesses fields from the raworderResponseJsoninstead of the validatedquoteReplyresult
Why This Matters:
- Unvalidated API responses can cause runtime crashes if the API changes or returns unexpected data
- Type safety is lost when bypassing cleaners
- This is a standard requirement for all Edge plugins
Please update the cleaner to include all accessed fields, and use the cleaned result for all field access.
98a4a8a to
cd78770
Compare
|
@paullinator
|
cd78770 to
dced8ba
Compare
paullinator
left a comment
There was a problem hiding this comment.
Review Summary
Critical Issues (must fix)
- BSC mapped to wrong chain —
'BSC'→'binance'(BEP2) should be'binancesmartchain'(BSC/BEP20) - Missing Zcash transparent address handling — No
addressTypeMapfor Zcash; shielded addresses will fail on a CEX
Convention Issues (should fix)
- Plugin registration breaks alphabetical order in
src/index.ts - Synchronizer should use shared
loadMappingFile/getMappingFilePathutilities - Cleaners use generic "Template" prefix — rename to
asXgram* - Import
denominationToNative/nativeToDenominationfromutilsnotswapHelpers(per convention)
Cleanup (should fix)
- Dead code:
asOptionalBlank(unused, copy-pasted from changenow) - Dead code:
FlowTypetype (only'fixed'is ever used) - Unused
affiliateIdin init options
API Requirements Compliance (docs/API_REQUIREMENTS.md)
- Sections 1-4: Compliant — chain+contractAddress identification, structured error array, bi-directional quoting, order ID + status page
- EVM
chainIdgap: API uses string network names, not numericchainId. Verify with Xgram team whetherchainIdis supported for automatic new-EVM-chain coverage - Sections 5-8: Not verifiable from plugin code (API/business requirements)
PR Housekeeping
- CHANGELOG checkbox not checked — should be Yes with entry
added: Xgram swap provider - PR description says "none" — should include a brief description of the integration
See inline comments for specific code locations.
0027fa2 to
252358b
Compare
|
Our team will review adding support for using a numeric chainId instead of string network names for new EVM chains. |
paullinator
left a comment
There was a problem hiding this comment.
Re-Review Summary
Great progress — all 10 previous findings (including the 2 critical issues) have been addressed in this commit. The plugin now follows established conventions for chain mappings, synchronizer utilities, cleaner naming, import paths, Zcash address handling, and plugin registration order.
Remaining Issues
depositTag: asStringwill throw on null (Warning) — For non-memo chains, the API may returnnull. UseasOptionalBlank(asString)like ChangeNow does. See inline comment.- Unnecessary optional chaining (Nit) —
request?.quoteForon line 145 still has?.which is unnecessary.
API Requirements Compliance
- Sections 1-4: Compliant (chain+contractAddress identification, structured error array with correct priority order per
CREATING_AN_EXCHANGE_PLUGIN.md, bi-directional quoting, order status page) - EVM
chainIdsupport: Not verifiable from plugin code — verify with Xgram team - Sections 5-8: Server-side requirements, not verifiable from plugin code
What's Working Well
- Error handling follows documented priority (Region → Currency → Limits)
- Clean use of
asMaybe(asXgramLimitError)for limit error extraction - Proper Zcash transparent address handling via
addressTypeMap - Chain mappings correctly map BSC →
binancesmartchain - Synchronizer uses shared
loadMappingFile/getMappingFilePath
See inline comments for specific line references.
We can move forward, but we won't provide any fee advantages until this is implemented. |
46038b1 to
3670edb
Compare
@paullinator Could you please clarify what you mean by “we won't provide any fee advantages”? |
Not that it will have higher exchange fees. It's just that we will not give a priority advantage over other exchanges. |
ee5cd5d to
1696995
Compare
2d0adf4 to
5b1f933
Compare
| export function makeXgramPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin { | ||
| const { io } = opts | ||
|
|
||
| const fetchCors = io.fetch |
There was a problem hiding this comment.
Fetch function ignores CORS-capable fetch variant
Medium Severity
The xgram plugin assigns const fetchCors = io.fetch directly, bypassing io.fetchCors even when it's available. Every other central plugin (changehero, changenow, exolix, godex, letsexchange, swapuz, sideshift) uses const { fetchCors = io.fetch } = io or io.fetchCors ?? io.fetch to prefer the CORS-capable fetch function. This means xgram API calls may fail in browser environments where io.fetchCors is required for cross-origin requests.
|
|
||
| export const xgram = new Map<string, EdgeCurrencyPluginId | null>() | ||
| // WARNING: Not included by the synchronizer synchronization | ||
| xgram.set('ada', 'cardano') |
There was a problem hiding this comment.
Cardano network identifier uses inconsistent lowercase casing
Medium Severity
The Cardano network identifier is 'ada' (lowercase) while every other identifier in the mapping uses uppercase ('BTC', 'ETH', 'BSC', 'ALGO', etc.). If the Xgram API is case-sensitive, Cardano swaps will fail because the API receives 'ada' instead of 'ADA'. The reverse mapping in src/mappings/xgram.ts propagates the same inconsistency.
Additional Locations (1)
|
|
||
| if (!orderResponse.ok) { | ||
| throw new Error('Xgram create order failed') | ||
| } |
There was a problem hiding this comment.
Non-OK HTTP responses bypass structured error handling
Medium Severity
The !orderResponse.ok check throws a generic 'Xgram create order failed' error before the response body is parsed for structured errors (limit, region, currency). If the Xgram API returns structured error bodies (e.g. BELOW_LIMIT, REGION_UNSUPPORTED) with HTTP 4xx status codes — standard REST practice for validation errors — those are discarded and replaced by this generic error. The UI would then be unable to display meaningful messages like minimum amounts or geo-restriction notices. Other plugins like SideShift always parse the body regardless of status code. At minimum, the response body should be parsed and checked for known error structures before falling back to a generic throw.
Additional Locations (1)
|
|
||
| export const xgram = new Map<string, EdgeCurrencyPluginId | null>() | ||
| // WARNING: Not included by the synchronizer synchronization | ||
| xgram.set('ada', 'cardano') |
There was a problem hiding this comment.
Cardano network code uses inconsistent lowercase casing
Medium Severity
The Cardano network code 'ada' is lowercase, while every other network code in the mapping is uppercase ('ALGO', 'ARBITRUM', 'BTC', 'ETH', etc.). This inconsistency is carried through to the auto-generated reverse mapping ('cardano' → 'ada'). If the Xgram API expects uppercase network identifiers — consistent with the convention used for all other 27 chains — Cardano swaps would fail silently at the API level.
Additional Locations (1)
e146195 to
050dd3a
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| export function makeXgramPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin { | ||
| const { io } = opts | ||
|
|
||
| const fetchCors = io.fetch |
There was a problem hiding this comment.
Missing fetchCors fallback breaks browser CORS requests
Medium Severity
const fetchCors = io.fetch always uses io.fetch, ignoring io.fetchCors. Every other central plugin (changehero, changenow, exolix, godex, letsexchange, swapuz) uses const { fetchCors = io.fetch } = io to prefer io.fetchCors when available. In browser environments where io.fetchCors provides CORS proxy support, xgram requests to xgram.io will fail with CORS errors.
|
|
||
| export const xgram = new Map<string, EdgeCurrencyPluginId | null>() | ||
| // WARNING: Not included by the synchronizer synchronization | ||
| xgram.set('ada', 'cardano') |
There was a problem hiding this comment.
Cardano network code uses inconsistent lowercase 'ada'
Medium Severity
The Cardano mapping uses lowercase 'ada' while every other network code in the file is uppercase ('ALGO', 'BTC', 'ETH', etc.). This inconsistency propagates to the reverse mapping in src/mappings/xgram.ts where 'cardano' maps to 'ada'. When the plugin sends fromNetwork or toNetwork to the Xgram API, Cardano will use 'ada' instead of the presumably expected 'ADA', likely causing Cardano swaps to fail.


CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
noneDescription
noneNote
Medium Risk
Adds a new central swap provider that creates real exchange orders via Xgram’s external API and relies on new currency/network mappings, so API contract or mapping issues could break quoting/swaps. CI also changes Jenkins agent selection, which could affect build routing.
Overview
Adds Xgram as a new centralized swap plugin, including quote/order creation against Xgram’s API (with API-key init option), handling region/currency/limit errors, and producing
EdgeSpendInfowith optional memo/tag support.Introduces Xgram currency/network mapping files (script source + auto-generated runtime map) and wires a new
xgramsynchronizer into the mapping update tooling (currently returns no remote chain codes).Updates
Jenkinsfileto run on agents labeledbuildinstead ofany.Written by Cursor Bugbot for commit 0621210. This will update automatically on new commits. Configure here.