@@ -178,6 +178,41 @@ export interface SolConsolidationRecoveryOptions extends MPCConsolidationRecover
178178const HEX_REGEX = / ^ [ 0 - 9 a - f A - F ] + $ / ;
179179const BLIND_SIGNING_TX_TYPES_TO_CHECK = { enabletoken : 'AssociatedTokenAccountInitialization' } ;
180180
181+ /**
182+ * Get amount string corrected for architecture-specific endianness issues.
183+ *
184+ * On s390x (big-endian) architecture, the Solana transaction parser (via @solana/web3.js)
185+ * incorrectly reads little-endian u64 amounts as big-endian, resulting in corrupted values.
186+ *
187+ * This function corrects all amounts on s390x by swapping byte order to undo
188+ * the incorrect byte order that happened during transaction parsing.
189+ *
190+ * @param amount - The amount to check and potentially fix
191+ * @returns The corrected amount as a string
192+ */
193+ function getAmountBasedOnEndianness ( amount : string | number ) : string {
194+ const amountStr = String ( amount ) ;
195+
196+ // Only s390x architecture has this endianness issue
197+ const isS390x = process . arch === 's390x' ;
198+ if ( ! isS390x ) {
199+ return amountStr ;
200+ }
201+
202+ try {
203+ const amountBN = BigInt ( amountStr ) ;
204+ // On s390x, the parser ALWAYS reads u64 as big-endian when it's actually little-endian
205+ // So we ALWAYS need to swap bytes to get the correct value
206+ const buf = Buffer . alloc ( 8 ) ;
207+ buf . writeBigUInt64BE ( amountBN , 0 ) ;
208+ const fixed = buf . readBigUInt64LE ( 0 ) ;
209+ return fixed . toString ( ) ;
210+ } catch ( e ) {
211+ // If conversion fails, return original value
212+ return amountStr ;
213+ }
214+ }
215+
181216export class Sol extends BaseCoin {
182217 protected readonly _staticsCoin : Readonly < StaticsBaseCoin > ;
183218
@@ -371,8 +406,12 @@ export class Sol extends BaseCoin {
371406 const recipientFromTx = filteredOutputs [ index ] ; // This address should be an ATA
372407
373408 // Compare the BigNumber values because amount is (string | number)
374- const userAmount = new BigNumber ( recipientFromUser . amount ) ;
375- const txAmount = new BigNumber ( recipientFromTx . amount ) ;
409+ // Apply s390x endianness fix if needed
410+ const userAmountStr = String ( recipientFromUser . amount ) ;
411+ const txAmountStr = getAmountBasedOnEndianness ( recipientFromTx . amount ) ;
412+
413+ const userAmount = new BigNumber ( userAmountStr ) ;
414+ const txAmount = new BigNumber ( txAmountStr ) ;
376415 if ( ! userAmount . isEqualTo ( txAmount ) ) {
377416 return false ;
378417 }
@@ -459,10 +498,13 @@ export class Sol extends BaseCoin {
459498 const explainedTxTotal : Record < string , BigNumber > = { } ;
460499
461500 for ( const output of explainedTx . outputs ) {
501+ // Apply s390x endianness fix to output amounts before summing
502+ const outputAmountStr = getAmountBasedOnEndianness ( output . amount ) ;
503+
462504 // total output amount based on each token
463505 const assetName = output . tokenName || this . getChain ( ) ;
464506 const amount = explainedTxTotal [ assetName ] || new BigNumber ( 0 ) ;
465- explainedTxTotal [ assetName ] = amount . plus ( output . amount ) ;
507+ explainedTxTotal [ assetName ] = amount . plus ( outputAmountStr ) ;
466508 }
467509
468510 if ( ! _ . isEqual ( explainedTxTotal , totalAmount ) ) {
0 commit comments