diff --git a/src/services/transactionDecoder.ts b/src/services/transactionDecoder.ts index 406663e..a2f99ff 100644 --- a/src/services/transactionDecoder.ts +++ b/src/services/transactionDecoder.ts @@ -7,6 +7,8 @@ import { generated } from '@runonflux/aa-schnorr-multisig-sdk'; import blockchains from './blockchains'; import log from '../lib/log'; +import { getFromAlchemy } from './tokenServices'; + function getLibId(chain) { return blockchains[chain].libid; } @@ -72,9 +74,16 @@ function decodeEVMTransactionForApproval(rawTx, chain = 'eth') { txInfo.token = decodedData.args[0] as string; // find the token in our token list - const token = blockchains[chain].tokens.find( + let token: any = {}; + + token = blockchains[chain].tokens.find( (t) => t.contract.toLowerCase() === txInfo.token.toLowerCase(), ); + + if (Object.keys(token).length <= 0) { + token = getFromAlchemy(txInfo.token.toLowerCase(), chain.toLowerCase()); + } + if (token) { decimals = token.decimals; } diff --git a/tests/unit/transactionDecoder.spec.ts b/tests/unit/transactionDecoder.spec.ts index 2e0209d..598a548 100644 --- a/tests/unit/transactionDecoder.spec.ts +++ b/tests/unit/transactionDecoder.spec.ts @@ -57,6 +57,58 @@ const rawTxSepolia = { }, }; +const invalidRawTxSepolia = { + id: '0x8b18236447c918b3b217da857a787a7561313b730374430596eaa6f9c2d0ee16', + opHash: '0xc195efc3bf3541c0e4b75591c0a8bf36484fef6ef6feb85f501ed1b4daa4ba68', + userOpRequest: { + sender: '0xd447BA08b0d395fCAd6e480d270529c932289Ce1', + nonce: '0x14', + initCode: '0x', + callData: + '0xb61d27f6000000000000000000000000bbddae4447f0f9712415c7bde2171df3cb8085700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001442eb2c2d600000000000000000000000086b3447d6557c95fc394cc13f22a2b9fc42e9cf0000000000000000000000000b5b3d0e19215fc3a5e996fa54e23a37ad0f91f2d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + callGasLimit: '0x6a02', + verificationGasLimit: '0x13d5a', + preVerificationGas: '0xfa5c', + maxFeePerGas: '0x7309fdd1', + maxPriorityFeePerGas: '0x59682f00', + paymasterAndData: '0x', + signature: + '0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c', + }, + combinedPubKey: + '03b0177e3dbfa2d2460721bc1f32c80576b7adfd7ab4a899c0065879ef95296acb', + publicKeys: { + '0x300429d8ef26b7264fab66d9368958d0e99e3f1f': + '02e10148f9606cfc52d5a3a5d61fb3640d5f135266f32ac0b3dceff438c3f0bd52', + '0x24c752b40767088059fc4d4be4fe4f52facbac57': + '032f320a64727d2d23ccd6caa40af5f2700dc3265143d275beaf04194166b6756e', + }, + publicNonces: { + '0x300429d8ef26b7264fab66d9368958d0e99e3f1f': { + kPublic: + '022f8178611318387a91b287a5942278fb2f66942dfa72f2fdae5a2de4ba2a5e62', + kTwoPublic: + '037a0ba8f0d247907508520ba7df81a31c3f084eb2648f566c8ad902af7a798d63', + }, + '0x24c752b40767088059fc4d4be4fe4f52facbac57': { + kPublic: + '03d0976461943725f33309ff56605784ad7c8d3e2b7a82c45c5df6151d9aed1149', + kTwoPublic: + '03d4f0e6406c080882c5574297c01ffd26aed8ca3f0cad34258592acf74d314650', + }, + }, + signatures: { + '0x300429d8ef26b7264fab66d9368958d0e99e3f1f': { + finalPublicNonce: + '037cde1f949b8c62d815da75d6082718538d0ef68b3819bdde4b7ec3afd5c26c91', + challenge: + '659c5592db35c0b52ec11487d92feb627d7b51d1f0a8fe1451f148726e59871d', + signature: + 'e1f70aa45833fdd10fe3b254d9e5b173988c1c9c4e91c8b6220ad9314a39621e', + }, + }, +}; + describe('Transaction Decoder', function () { describe('Decode Transaction: Correctly verifies action', function () { it('should return error result if raw tx is empty', async function () { @@ -87,6 +139,20 @@ describe('Transaction Decoder', function () { }); }); + it('should return error result if raw tx is invalid for sepolia', async function () { + const response = await transactionDecoder.decodeTransactionForApproval( + JSON.stringify(invalidRawTxSepolia), + 'sepolia', + ); + expect(response).to.deep.equal({ + amount: 'decodingError', + fee: 'decodingError', + receiver: 'decodingError', + sender: 'decodingError', + token: 'decodingError', + }); + }); + it('should return successful result if raw tx is valid for sepolia', async function () { const response = await transactionDecoder.decodeTransactionForApproval( JSON.stringify(rawTxSepolia),