77 * the runtime parser, binary search and renderer pipeline are all exercised
88 * end-to-end against rendered DOM.
99 */
10- import { ClipboardService } from '@airgap/angular-core'
10+ import { ClipboardService , ProtocolService } from '@airgap/angular-core'
1111import { HttpClient } from '@angular/common/http'
1212import { ComponentFixture , TestBed } from '@angular/core/testing'
1313import { IonicModule } from '@ionic/angular'
1414import { TranslateModule , TranslateService } from '@ngx-translate/core'
15- import { IAirGapTransaction , MainProtocolSymbols } from '@airgap/coinlib-core'
15+ import { IAirGapTransaction , MainProtocolSymbols , SubProtocolSymbols } from '@airgap/coinlib-core'
1616import { of } from 'rxjs'
1717
1818import { ContactsService } from '../../services/contacts/contacts.service'
19+ import { EvmTransactionRendererService } from '../../services/evm/transaction-renderer.service'
1920import { EvmTransactionDisplayComponent } from '../evm-transaction-display/evm-transaction-display.component'
2021import { TransactionWarningComponent } from '../transaction-warning/transaction-warning.component'
2122import enJson from '../../../assets/i18n/en.json'
@@ -114,6 +115,7 @@ describe('TransactionComponent — EVM decoder (e2e)', () => {
114115 let component : TransactionComponent
115116 let fixture : ComponentFixture < TransactionComponent >
116117 const contactsSpy = jasmine . createSpyObj ( 'ContactsService' , [ 'isBookEnabled' , 'getContactName' ] )
118+ const protocolSpy = jasmine . createSpyObj ( 'ProtocolService' , [ 'getProtocol' ] )
117119
118120 beforeEach ( async ( ) => {
119121 contactsSpy . isBookEnabled . and . returnValue ( Promise . resolve ( false ) )
@@ -124,7 +126,8 @@ describe('TransactionComponent — EVM decoder (e2e)', () => {
124126 providers : [
125127 { provide : HttpClient , useClass : FakeHttpClient } ,
126128 { provide : ContactsService , useValue : contactsSpy } ,
127- { provide : ClipboardService , useValue : jasmine . createSpyObj ( 'ClipboardService' , [ 'copyAndShowToast' ] ) }
129+ { provide : ClipboardService , useValue : jasmine . createSpyObj ( 'ClipboardService' , [ 'copyAndShowToast' ] ) } ,
130+ { provide : ProtocolService , useValue : protocolSpy }
128131 ]
129132 } )
130133 // Schemas: the real TransactionComponent template uses pipes (amountConverter / feeConverter)
@@ -169,6 +172,34 @@ describe('TransactionComponent — EVM decoder (e2e)', () => {
169172 expect ( text ) . toContain ( '0xd8da6bf26964af9d7eed9e03e53415d37aa96045' )
170173 } )
171174
175+ it ( 'uses the token contract, not the recipient in `to`, for ERC-20 sub-protocols' , async ( ) => {
176+ protocolSpy . getProtocol . and . returnValue (
177+ Promise . resolve ( { getContractAddress : ( ) => Promise . resolve ( '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ) } )
178+ )
179+ await runWith ( [
180+ evmTx ( {
181+ // coinlib's ERC20 protocol reports the token recipient as `to`
182+ to : '0xd8da6bf26964af9d7eed9e03e53415d37aa96045' ,
183+ protocolIdentifier : SubProtocolSymbols . ETH_ERC20 ,
184+ data :
185+ '0xa9059cbb' +
186+ '000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045' +
187+ '00000000000000000000000000000000000000000000000000000000000f4240'
188+ } )
189+ ] )
190+ const text = ( fixture . nativeElement as HTMLElement ) . textContent || ''
191+ expect ( text ) . toContain ( '1 USDC' )
192+ expect ( text ) . toContain ( '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' )
193+ } )
194+
195+ it ( 'renders raw calldata with a warning when decoding throws' , async ( ) => {
196+ const renderer = TestBed . inject ( EvmTransactionRendererService )
197+ spyOn ( renderer , 'render' ) . and . throwError ( 'boom' )
198+ await runWith ( [ evmTx ( { to : '0xabcabcabcabcabcabcabcabcabcabcabcabcabca' , data : '0x12345678' } ) ] )
199+ const text = ( fixture . nativeElement as HTMLElement ) . textContent || ''
200+ expect ( text ) . toContain ( 'Could not decode' )
201+ } )
202+
172203 it ( 'renders an unlimited approval in warning style' , async ( ) => {
173204 await runWith ( [
174205 evmTx ( {
0 commit comments