UNPKG

@reown/appkit-ui

Version:

The full stack toolkit to build onchain app UX.

334 lines • 13.3 kB
import { describe, expect, it } from 'vitest'; import { TransactionUtil } from '../src/utils/TransactionUtil.js'; const nftTransfer = { nft_info: { name: 'Cool NFT', content: { preview: { url: 'nft-url' } }, flags: { is_spam: false } }, direction: 'in', quantity: { numeric: '1' } }; const fungibleTransfer = { fungible_info: { symbol: 'TOK', icon: { url: 'token-url' } }, direction: 'in', quantity: { numeric: '123.4567' } }; const secondFungibleTransfer = { fungible_info: { symbol: 'TOK2', icon: { url: 'token2-url' } }, direction: 'in', quantity: { numeric: '10' } }; describe('TransactionUtil.getTransactionImages', () => { it('returns NFT image for NFT transfer', () => { const images = TransactionUtil.getTransactionImages([nftTransfer]); expect(images[0]?.type).toBe('NFT'); expect(images[0]?.url).toBe('nft-url'); }); it('returns fungible image for fungible transfer', () => { const images = TransactionUtil.getTransactionImages([fungibleTransfer]); expect(images[0]?.type).toBe('FUNGIBLE'); expect(images[0]?.url).toBe('token-url'); }); it('returns images in same order for multiple transfers', () => { const images = TransactionUtil.getTransactionImages([fungibleTransfer, secondFungibleTransfer]); expect(images[0]?.url).toBe('token-url'); expect(images[1]?.url).toBe('token2-url'); }); it('returns all images for multiple transfers', () => { const images = TransactionUtil.getTransactionImages([nftTransfer, fungibleTransfer]); expect(images.length).toBe(2); }); }); describe('TransactionUtil.getTransactionDescriptions', () => { const baseTx = { id: 'tx1', metadata: { operationType: 'receive', status: 'success' }, transfers: [fungibleTransfer] }; it('returns description with + prefix for plusTypes', () => { const desc = TransactionUtil.getTransactionDescriptions(baseTx); expect(desc[0]?.startsWith('+')).toBe(true); expect(desc[0]).toContain('123.457 TOK'); }); it('returns description with - prefix for minusTypes', () => { const tx = { ...baseTx, metadata: { operationType: 'withdraw' } }; const desc = TransactionUtil.getTransactionDescriptions(tx); expect(desc[0]?.startsWith('-')).toBe(true); }); it('returns NFT name for NFT transfer', () => { const tx = { ...baseTx, transfers: [nftTransfer], metadata: { operationType: 'receive' } }; const desc = TransactionUtil.getTransactionDescriptions(tx); expect(desc[0]).toContain('Cool NFT'); }); it('returns descriptions in same order for multiple transfers', () => { const tx = { ...baseTx, transfers: [fungibleTransfer, secondFungibleTransfer], metadata: { operationType: 'receive' } }; const desc = TransactionUtil.getTransactionDescriptions(tx); expect(desc.length).toBe(2); expect(desc[0]).toContain('123.457 TOK'); expect(desc[1]).toContain('10.000 TOK2'); }); it('returns status if no transfers and not send/receive', () => { const tx = { metadata: { operationType: 'burn', status: 'failed' }, transfers: [] }; const desc = TransactionUtil.getTransactionDescriptions(tx); expect(desc[0]).toBe('failed'); }); it('returns return status for send/receive with no transfers', () => { const tx = { metadata: { operationType: 'send', sentFrom: '0x1234567890abcdef', sentTo: '0xfedcba0987654321', status: 'success' }, transfers: [] }; const desc = TransactionUtil.getTransactionDescriptions(tx); expect(desc[0]).toBe('success'); }); }); describe('TransactionUtil.mergeTransfers', () => { const createToken1Transfer = (quantity = '100') => ({ fungible_info: { name: 'Token1', symbol: 'TOK1', icon: { url: 'token1-url' } }, direction: 'in', quantity: { numeric: quantity } }); const createToken2Transfer = (quantity = '200') => ({ fungible_info: { name: 'Token2', symbol: 'TOK2', icon: { url: 'token2-url' } }, direction: 'in', quantity: { numeric: quantity } }); it('returns empty array for empty input', () => { const result = TransactionUtil.mergeTransfers([]); expect(result).toEqual([]); }); it('returns single transfer unchanged', () => { const token1Transfer = createToken1Transfer(); const result = TransactionUtil.mergeTransfers([token1Transfer]); expect(result).toEqual([token1Transfer]); }); it('returns multiple transfers with different names unchanged', () => { const token1Transfer = createToken1Transfer(); const token2Transfer = createToken2Transfer(); const result = TransactionUtil.mergeTransfers([token1Transfer, token2Transfer]); expect(result).toEqual([token1Transfer, token2Transfer]); }); it('merges transfers with same token name', () => { const token1Transfer = createToken1Transfer('100'); const token1Transfer2 = createToken1Transfer('50'); const result = TransactionUtil.mergeTransfers([token1Transfer, token1Transfer2]); expect(result.length).toBe(1); expect(result[0]?.fungible_info?.name).toBe('Token1'); expect(result[0]?.quantity.numeric).toBe('150'); }); it('merges multiple transfers with mixed same and different names', () => { const token1Transfer = createToken1Transfer('100'); const token2Transfer = createToken2Transfer('200'); const token1Transfer2 = createToken1Transfer('50'); const result = TransactionUtil.mergeTransfers([token1Transfer, token2Transfer, token1Transfer2]); expect(result.length).toBe(2); const token1Merged = result.find(t => t?.fungible_info?.name === 'Token1'); expect(token1Merged?.quantity.numeric).toBe('150'); const token2Result = result.find(t => t?.fungible_info?.name === 'Token2'); expect(token2Result?.quantity.numeric).toBe('200'); }); it('handles transfers with undefined fungible_info gracefully', () => { const token1Transfer = createToken1Transfer(); const transferWithoutFungible = { direction: 'in', quantity: { numeric: '100' } }; const result = TransactionUtil.mergeTransfers([token1Transfer, transferWithoutFungible]); expect(result.length).toBe(2); expect(result).toContain(token1Transfer); expect(result).toContain(transferWithoutFungible); }); it('does not merge transfers with undefined fungible_info name', () => { const transferWithoutName = { fungible_info: { symbol: 'TOK1', icon: { url: 'token1-url' } }, direction: 'in', quantity: { numeric: '100' } }; const anotherTransferWithoutName = { fungible_info: { symbol: 'TOK1', icon: { url: 'token1-url' } }, direction: 'in', quantity: { numeric: '50' } }; const result = TransactionUtil.mergeTransfers([transferWithoutName, anotherTransferWithoutName]); expect(result.length).toBe(2); expect(result[0]?.quantity.numeric).toBe('100'); expect(result[1]?.quantity.numeric).toBe('50'); }); it('does not merge transfer with undefined name with named transfer', () => { const namedTransfer = createToken1Transfer('100'); const transferWithoutName = { fungible_info: { symbol: 'TOK1', icon: { url: 'token1-url' } }, direction: 'in', quantity: { numeric: '50' } }; const result = TransactionUtil.mergeTransfers([namedTransfer, transferWithoutName]); expect(result.length).toBe(2); expect(result.find(t => t?.fungible_info?.name === 'Token1')?.quantity.numeric).toBe('100'); expect(result.find(t => !t?.fungible_info?.name)?.quantity.numeric).toBe('50'); }); it('filters out gas fee transfers (small opposite-direction amounts)', () => { const usdcInTransfer = { fungible_info: { name: 'USD Coin', symbol: 'USDC', icon: { url: 'usdc-url' } }, direction: 'in', quantity: { numeric: '0.224784' }, value: 0.2246140943611488 }; const usdcOutTransfer = { fungible_info: { name: 'USD Coin', symbol: 'USDC', icon: { url: 'usdc-url' } }, direction: 'out', quantity: { numeric: '0.005830' }, value: 0.005825593325706 }; const polOutTransfer = { fungible_info: { name: 'Polygon', symbol: 'POL', icon: { url: 'pol-url' } }, direction: 'out', quantity: { numeric: '1.000000000000000000' }, value: 0.2267439626 }; const result = TransactionUtil.mergeTransfers([usdcInTransfer, polOutTransfer, usdcOutTransfer]); expect(result.length).toBe(2); const usdcResult = result.find(t => t?.fungible_info?.name === 'USD Coin'); expect(usdcResult?.direction).toBe('in'); expect(usdcResult?.quantity.numeric).toBe('0.224784'); const polResult = result.find(t => t?.fungible_info?.name === 'Polygon'); expect(polResult?.direction).toBe('out'); expect(polResult?.quantity.numeric).toBe('1.000000000000000000'); }); it('filters out extremely small amounts from multiple transfers of same token', () => { const polInTransfer = { fungible_info: { name: 'Polygon', symbol: 'POL', icon: { url: 'pol-url' } }, direction: 'in', quantity: { numeric: '0.335409423006602078' }, value: 0.09438223449613203 }; const polOutTransfer1 = { fungible_info: { name: 'Polygon', symbol: 'POL', icon: { url: 'pol-url' } }, direction: 'out', quantity: { numeric: '0.03067133025286914' }, value: 0.008630731534866924 }; const polOutTransfer2 = { fungible_info: { name: 'Polygon', symbol: 'POL', icon: { url: 'pol-url' } }, direction: 'out', quantity: { numeric: '0.000000000002869140' }, value: 8.073478275162302e-13 }; const usdcOutTransfer = { fungible_info: { name: 'USD Coin', symbol: 'USDC', icon: { url: 'usdc-url' } }, direction: 'out', quantity: { numeric: '0.095419' }, value: 0.0955182425156652 }; const result = TransactionUtil.mergeTransfers([ polInTransfer, usdcOutTransfer, polOutTransfer1, polOutTransfer2 ]); expect(result.length).toBe(2); const usdcResult = result.find(t => t?.fungible_info?.name === 'USD Coin'); expect(usdcResult?.quantity.numeric).toBe('0.095419'); const polInResult = result.find(t => t?.fungible_info?.name === 'Polygon' && t?.direction === 'in'); expect(polInResult?.quantity.numeric).toBe('0.335409423006602078'); const polOutResult = result.find(t => t?.fungible_info?.name === 'Polygon' && t?.direction === 'out'); expect(polOutResult).toBeUndefined(); const tinyGasFee = result.find(t => t?.quantity.numeric === '0.000000000002869140'); expect(tinyGasFee).toBeUndefined(); }); it('orders transfers with out direction first, then in direction', () => { const inTransfer = { fungible_info: { name: 'USD Coin', symbol: 'USDC', icon: { url: 'usdc-url' } }, direction: 'in', quantity: { numeric: '100' }, value: 100 }; const outTransfer = { fungible_info: { name: 'Ethereum', symbol: 'ETH', icon: { url: 'eth-url' } }, direction: 'out', quantity: { numeric: '0.05' }, value: 120 }; const result = TransactionUtil.mergeTransfers([inTransfer, outTransfer]); expect(result.length).toBe(2); expect(result[0]?.direction).toBe('out'); expect(result[0]?.fungible_info?.symbol).toBe('ETH'); expect(result[1]?.direction).toBe('in'); expect(result[1]?.fungible_info?.symbol).toBe('USDC'); }); }); //# sourceMappingURL=TransactionUtil.test.js.map