CW-1035: Solana New Fixes(Cont.) (#2206)

* fix: Error while restoring Solana Wallet with PrivateKey * fix: Enhance Solana Error Messages, especially for ATA Creation Errors * - Optimize Solana Transaction History, now more smoother and faster - fix bug with transactions history not being displayed in real time until next reload * fix: Resolve Solana Issue from Github where user transaction showed amount and fee as the same

David Adegoke committed Apr 23, 2025 at 23:57 UTC 1b04619c2a5d39749bab209f3d1473345bc57e06
1 file changed +76 -28
cw_solana/lib/solana_client.dart
+76 -28
@@ -171,37 +171,85 @@ class SolanaWalletClient {
171
172 if (programId == SystemProgramConst.programId) {
173 // For native solana transactions
174 - if (instruction.accounts.length < 2) continue;
175 - final senderIndex = instruction.accounts[0];
176 - final receiverIndex = instruction.accounts[1];
177 -
178 - sender = message.accountKeys[senderIndex].address;
179 - receiver = message.accountKeys[receiverIndex].address;
180 -
181 - final feeForTx = fee / SolanaUtils.lamportsPerSol;
174
183 - final preBalances = meta.preBalances;
184 - final postBalances = meta.postBalances;
185 -
186 - final amountInString =
187 - (((preBalances[senderIndex] - postBalances[senderIndex]) / BigInt.from(1e9))
188 - .toDouble() -
189 - feeForTx)
190 - .toStringAsFixed(6);
175 + if (txResponse.version == TransactionType.legacy) {
176 + // For legacy transfers, the fee payer (index 0) is the sender.
177 + sender = message.accountKeys[0].address;
178 +
179 + final senderPreBalance = meta.preBalances[0];
180 + final senderPostBalance = meta.postBalances[0];
181 + final feeForTx = fee / SolanaUtils.lamportsPerSol;
182 +
183 + // The loss on the sender's account would include both the transfer amount and the fee.
184 + // So we would subtract the fee to calculate the actual amount that was transferred (in lamports).
185 + final transferLamports = (senderPreBalance - senderPostBalance) - BigInt.from(fee);
186 +
187 + // Next, we attempt to find the receiver by comparing the balance changes.
188 + // (The index 0 is for the sender so we skip it.)
189 + bool foundReceiver = false;
190 + for (int i = 1; i < meta.preBalances.length; i++) {
191 + // The increase in balance on the receiver account should correspond to the transfer amount we calculated earlieer.
192 + final pre = meta.preBalances[i];
193 + final post = meta.postBalances[i];
194 + if ((post - pre) == transferLamports) {
195 + receiver = message.accountKeys[i].address;
196 + foundReceiver = true;
197 + break;
198 + }
199 + }
200
192 - final amount = double.parse(amountInString);
201 + if (!foundReceiver) {
202 + // Optionally (and rarely), if no account shows the exact expected change,
203 + // we set the receiver address to unknown.
204 + receiver = "unknown";
205 + }
206
194 - return SolanaTransactionModel(
195 - isOutgoingTx: sender == walletAddress,
196 - from: sender,
197 - to: receiver,
198 - id: signature,
199 - amount: amount.abs(),
200 - programId: SystemProgramConst.programId.address,
201 - tokenSymbol: 'SOL',
202 - blockTimeInInt: blockTime?.toInt() ?? 0,
203 - fee: feeForTx,
204 - );
207 + final amount = transferLamports / BigInt.from(1e9);
208 +
209 + return SolanaTransactionModel(
210 + isOutgoingTx: sender == walletAddress,
211 + from: sender,
212 + to: receiver,
213 + id: signature,
214 + amount: amount.abs(),
215 + programId: SystemProgramConst.programId.address,
216 + tokenSymbol: 'SOL',
217 + blockTimeInInt: blockTime?.toInt() ?? 0,
218 + fee: feeForTx,
219 + );
220 + } else {
221 + if (instruction.accounts.length < 2) continue;
222 + final senderIndex = instruction.accounts[0];
223 + final receiverIndex = instruction.accounts[1];
224 +
225 + sender = message.accountKeys[senderIndex].address;
226 + receiver = message.accountKeys[receiverIndex].address;
227 +
228 + final feeForTx = fee / SolanaUtils.lamportsPerSol;
229 +
230 + final preBalances = meta.preBalances;
231 + final postBalances = meta.postBalances;
232 +
233 + final amountInString =
234 + (((preBalances[senderIndex] - postBalances[senderIndex]) / BigInt.from(1e9))
235 + .toDouble() -
236 + feeForTx)
237 + .toStringAsFixed(6);
238 +
239 + final amount = double.parse(amountInString);
240 +
241 + return SolanaTransactionModel(
242 + isOutgoingTx: sender == walletAddress,
243 + from: sender,
244 + to: receiver,
245 + id: signature,
246 + amount: amount.abs(),
247 + programId: SystemProgramConst.programId.address,
248 + tokenSymbol: 'SOL',
249 + blockTimeInInt: blockTime?.toInt() ?? 0,
250 + fee: feeForTx,
251 + );
252 + }
253 } else if (programId == SPLTokenProgramConst.tokenProgramId) {
254 // For SPL Token transactions
255 if (instruction.accounts.length < 2) continue;