Skip to content

Commit 309a3a0

Browse files
authored
fix: bug with foreign assets and some layout fixes
1 parent 2c2f340 commit 309a3a0

File tree

9 files changed

+99
-22
lines changed

9 files changed

+99
-22
lines changed

src/features/transactions/components/app-call-transaction-info.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export function AppCallTransactionInfo({ transaction }: Props) {
9898
)
9999

100100
return (
101-
<>
101+
<div className={cn('space-y-2')}>
102102
<DescriptionList items={items} />
103103

104104
<Tabs defaultValue={applicationArgsTabId}>
@@ -114,52 +114,54 @@ export function AppCallTransactionInfo({ transaction }: Props) {
114114
))}
115115
</TabsList>
116116
{tabs.map((tab) => (
117-
<TabsContent key={tab.id} value={tab.id} className={cn('border-solid border-2 border-border p-4')}>
118-
{tab.children}
117+
<TabsContent key={tab.id} value={tab.id} className={cn('border-solid border-2 border-border')}>
118+
<div className="grid">
119+
<div className="overflow-auto p-4">{tab.children}</div>
120+
</div>
119121
</TabsContent>
120122
))}
121123
</Tabs>
122-
</>
124+
</div>
123125
)
124126
}
125127

126128
function ApplicationArgs({ transaction }: Props) {
127129
return (
128-
<div>
130+
<>
129131
{transaction.applicationArgs.map((data, index) => (
130132
<div key={index}>{data}</div>
131133
))}
132-
</div>
134+
</>
133135
)
134136
}
135137

136138
function ForeignAccounts({ transaction }: Props) {
137139
return (
138-
<div>
140+
<>
139141
{transaction.applicationAccounts.map((data, index) => (
140142
<div key={index}>{data}</div>
141143
))}
142-
</div>
144+
</>
143145
)
144146
}
145147

146148
function ForeignApplications({ transaction }: Props) {
147149
return (
148-
<div>
150+
<>
149151
{transaction.foreignApps.map((data, index) => (
150152
<div key={index}>{data}</div>
151153
))}
152-
</div>
154+
</>
153155
)
154156
}
155157

156158
function ForeignAssets({ transaction }: Props) {
157159
return (
158-
<div>
160+
<>
159161
{transaction.foreignAssets.map((data, index) => (
160162
<div key={index}>{data}</div>
161163
))}
162-
</div>
164+
</>
163165
)
164166
}
165167

src/features/transactions/components/app-call-transaction-logs.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ export function AppCallTransactionLogs({ logs }: Props) {
3030
{textLogsTabLabel}
3131
</TabsTrigger>
3232
</TabsList>
33-
<TabsContent value={base64LogTabId} className={cn('border-solid border-2 border-border h-60 p-4')}>
33+
<TabsContent value={base64LogTabId} className={cn('border-solid border-2 p-4')}>
3434
{logs.map((log, index) => (
3535
<div key={index}>{log}</div>
3636
))}
3737
</TabsContent>
38-
<TabsContent value={textLogTabId} className={cn('border-solid border-2 border-border h-60 p-4')}>
38+
<TabsContent value={textLogTabId} className={cn('border-solid border-2 p-4')}>
3939
{texts.map((text, index) => (
4040
<div key={index}>{text}</div>
4141
))}

src/features/transactions/data/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { JotaiStore } from '@/features/common/data/types'
1313
import { asTransactionModel } from '../mappers/transaction-mappers'
1414
import { getAssetAtomBuilder, getAssetsAtomBuilder } from '@/features/assets/data'
1515
import { InnerTransactionModel, TransactionModel, TransactionType as TransactionTypeModel } from '../models'
16+
import { getAssetIdsForTransaction } from '../utils/get-asset-ids-for-app-call-transaction'
1617

1718
// TODO: Size should be capped at some limit, so memory usage doesn't grow indefinitely
1819
export const transactionsAtom = atom<Map<TransactionId, TransactionResult>>(new Map())
@@ -67,7 +68,7 @@ export const fetchTransactionsModelAtomBuilder = (
6768
}
6869
}
6970
if (txn['tx-type'] === TransactionType.appl && txn['application-transaction']) {
70-
const assetIds = txn['application-transaction']['foreign-assets'] ?? []
71+
const assetIds = getAssetIdsForTransaction(txn)
7172
assetIds.forEach((assetId) => {
7273
if (!acc.has(assetId)) {
7374
acc.add(assetId)

src/features/transactions/mappers/app-call-transaction-mappers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const mapCommonAppCallTransactionProperties = (
3636
transactionResult['inner-txns']?.map((innerTransaction, index) => {
3737
// Generate a unique id for the inner transaction
3838
const innerId = indexPrefix ? `${indexPrefix}-${index + 1}` : `${index + 1}`
39-
return asInnerTransactionMode(networkTransactionId, innerId, innerTransaction, assets)
39+
return asInnerTransactionModel(networkTransactionId, innerId, innerTransaction, assets)
4040
}) ?? [],
4141
onCompletion: asAppCallOnComplete(transactionResult['application-transaction']['on-completion']),
4242
action: transactionResult['application-transaction']['application-id'] ? 'Call' : 'Create',
@@ -82,7 +82,7 @@ const asAppCallOnComplete = (indexerEnum: ApplicationOnComplete): AppCallOnCompl
8282
}
8383
}
8484

85-
const asInnerTransactionMode = (networkTransactionId: string, index: string, transactionResult: TransactionResult, assets: Asset[]) => {
85+
const asInnerTransactionModel = (networkTransactionId: string, index: string, transactionResult: TransactionResult, assets: Asset[]) => {
8686
if (transactionResult['tx-type'] === AlgoSdkTransactionType.pay) {
8787
return asInnerPaymentTransaction(networkTransactionId, index, transactionResult)
8888
}

src/features/transactions/mappers/transaction-mappers.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { asAssetTransferTransaction } from './asset-transfer-transaction-mappers
88
import { asPaymentTransaction } from './payment-transaction-mappers'
99
import { asPlaceholderTransaction } from './placeholder-transaction-mappers'
1010
import { Asset } from '@/features/assets/models'
11+
import { getAssetIdsForTransaction } from '../utils/get-asset-ids-for-app-call-transaction'
1112

1213
export const asTransactionModel = async (
1314
transactionResult: TransactionResult,
@@ -24,9 +25,8 @@ export const asTransactionModel = async (
2425
}
2526
case algosdk.TransactionType.appl: {
2627
invariant(transactionResult['application-transaction'], 'application-transaction is not set')
27-
const assetIds = transactionResult['application-transaction']['foreign-assets'] ?? []
28-
const uniqueAssetIds = Array.from(new Set(assetIds))
29-
const assets = await Promise.all(uniqueAssetIds.map((assetId) => assetResolver(assetId)))
28+
const assetIds = Array.from(new Set(getAssetIdsForTransaction(transactionResult)))
29+
const assets = await Promise.all(assetIds.map((assetId) => assetResolver(assetId)))
3030
return asAppCallTransaction(transactionResult, assets)
3131
}
3232
default:

src/features/transactions/pages/transaction-page.test.tsx

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import { base64LogsTabLabel, logsLabel, textLogsTabLabel } from '../components/a
5959
import { InnerTransactionPage } from './inner-transaction-page'
6060
import { base64ToUtf8 } from '@/utils/base64-to-utf8'
6161
import { textListAssertion } from '@/tests/assertions/text-list-assertion'
62+
import { AssetResult } from '@algorandfoundation/algokit-utils/types/indexer'
6263

6364
describe('transaction-page', () => {
6465
describe('when rendering a transaction with an invalid id', () => {
@@ -688,7 +689,10 @@ describe('transaction-page', () => {
688689
vi.mocked(useParams).mockImplementation(() => ({ transactionId: transaction.id, innerTransactionId: '2' }))
689690
const myStore = createStore()
690691
myStore.set(transactionsAtom, new Map([[transaction.id, transaction]]))
691-
myStore.set(assetsAtom, new Map(assets.map((a) => [a.index, a])))
692+
myStore.set(
693+
assetsAtom,
694+
new Map([[algoAssetResult.index, algoAssetResult], ...assets.map<[number, AssetResult]>((a) => [a.index, a])])
695+
)
692696

693697
return executeComponentTest(
694698
() => {
@@ -797,4 +801,37 @@ describe('transaction-page', () => {
797801
)
798802
})
799803
})
804+
805+
describe('when rendering an app call transaction that has no foreign assets but has an inner asset transfer transaction', () => {
806+
const asset = assetResultMother['mainnet-312769']().build()
807+
const innerAssetTransferTransaction = transactionResultMother.transfer(asset).build()
808+
const transaction = transactionResultMother.appCall()['withInner-txns']([innerAssetTransferTransaction]).build()
809+
810+
it('should be rendered without error', () => {
811+
vi.mocked(useParams).mockImplementation(() => ({ transactionId: transaction.id }))
812+
const myStore = createStore()
813+
myStore.set(transactionsAtom, new Map([[transaction.id, transaction]]))
814+
myStore.set(
815+
assetsAtom,
816+
new Map([
817+
[algoAssetResult.index, algoAssetResult],
818+
[asset.index, asset],
819+
])
820+
)
821+
822+
return executeComponentTest(
823+
() => {
824+
return render(<TransactionPage />, undefined, myStore)
825+
},
826+
async (component) => {
827+
await waitFor(() => {
828+
descriptionListAssertion({
829+
container: component.container,
830+
items: [{ term: transactionIdLabel, description: transaction.id }],
831+
})
832+
})
833+
}
834+
)
835+
})
836+
})
800837
})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import algosdk from 'algosdk'
2+
import { TransactionResult } from '@algorandfoundation/algokit-utils/types/indexer'
3+
import { invariant } from '@/utils/invariant'
4+
5+
export const getAssetIdsForTransaction = (transaction: TransactionResult): number[] => {
6+
// TODO: as we add more transaction types, we have to add more cases here
7+
if (transaction['tx-type'] === algosdk.TransactionType.axfer) {
8+
invariant(transaction['asset-transfer-transaction'], 'asset-transfer-transaction is not set')
9+
10+
return [transaction['asset-transfer-transaction']['asset-id']]
11+
}
12+
if (transaction['tx-type'] === algosdk.TransactionType.appl) {
13+
invariant(transaction['application-transaction'], 'application-transaction is not set')
14+
15+
const innerTransactions = transaction['inner-txns'] ?? []
16+
return innerTransactions.reduce(
17+
(acc, innerTxn) => {
18+
const innerResult = getAssetIdsForTransaction(innerTxn)
19+
return acc.concat(innerResult)
20+
},
21+
transaction['application-transaction']['foreign-assets'] ?? ([] as number[])
22+
)
23+
}
24+
25+
return []
26+
}

src/tests/builders/transaction-result-builder.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
randomDateBetween,
88
randomNumberBetween,
99
} from '@makerx/ts-dossier'
10-
import { AssetResult, TransactionResult } from '@algorandfoundation/algokit-utils/types/indexer'
10+
import { ApplicationTransactionResult, AssetResult, TransactionResult } from '@algorandfoundation/algokit-utils/types/indexer'
1111
import algosdk from 'algosdk'
1212

1313
export class TransactionResultBuilder extends DataBuilder<TransactionResult> {
@@ -51,6 +51,14 @@ export class TransactionResultBuilder extends DataBuilder<TransactionResult> {
5151
}
5252
return this
5353
}
54+
55+
public appCallTransaction() {
56+
this.thing['tx-type'] = algosdk.TransactionType.appl
57+
this.thing['application-transaction'] = {
58+
'application-id': randomNumber(),
59+
} as ApplicationTransactionResult
60+
return this
61+
}
5462
}
5563

5664
export const transactionResultBuilder = dossierProxy<TransactionResultBuilder, TransactionResult>(TransactionResultBuilder)

src/tests/object-mother/transaction-result.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export const transactionResultMother = {
99
transfer: (asset: AssetResult) => {
1010
return transactionResultBuilder().transferTransaction(asset)
1111
},
12+
appCall: () => {
13+
return transactionResultBuilder().appCallTransaction()
14+
},
1215
multisig: () => {
1316
return transactionResultBuilder()
1417
.paymentTransaction()

0 commit comments

Comments
 (0)