Skip to content

Conversation

@p2arthur
Copy link
Contributor

@p2arthur p2arthur commented Nov 7, 2025

feat(optional sender) - squashed

This PR replaces the previous one that contained unsigned commits.
I’ve taken the latest version from that branch, squashed all commits into a single signed commit, and reopened it here to maintain a clean history.

Both this PR and the old one have been moved to draft.
I’ll be pushing new commits here to address all review comments and suggestions made earlier today on the previous PR.

Please continue the discussion and review process on this new PR moving forward. 🚀

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Nov 7, 2025

Deploying algokit-lora with  Cloudflare Pages  Cloudflare Pages

Latest commit: cc92c31
Status: ✅  Deploy successful!
Preview URL: https://ae649f33.algokit-lora.pages.dev
Branch Preview URL: https://feat-optional-sender-improve.algokit-lora.pages.dev

View logs

@p2arthur p2arthur requested a review from PatrickDinh November 11, 2025 06:58
@p2arthur p2arthur marked this pull request as ready for review November 14, 2025 03:49
Copy link
Contributor

@PatrickDinh PatrickDinh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @p2arthur for the work. Above are some comments from me. I created this PR too #523 to address some other minor comments.

@@ -0,0 +1,33 @@
import { Nfd } from '@/features/nfd/data/types'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty line

Comment on lines 8 to 16
export type Props = PropsWithChildren<{
address: string | Address
short?: boolean
className?: string
showCopyButton?: boolean
showQRButton?: boolean
nfd?: Nfd
autoPopulated?: boolean
}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be type Props = AddressOrNfdLinkProps & { autoPopulated?: boolean }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better!

Comment on lines 138 to 141
manager: asAddressOrNfd(data.manager.value!),
reserve: asAddressOrNfd(data.reserve.value!),
freeze: asAddressOrNfd(data.freeze.value!),
clawback: asAddressOrNfd(data.clawback.value!),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you use asAddressOrNfd here? If I recall correctly these values can be optional

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, back to optional.

manager: asOptionalAddressOrNfd(data.manager), reserve: asOptionalAddressOrNfd(data.reserve), freeze: asOptionalAddressOrNfd(data.freeze), clawback: asOptionalAddressOrNfd(data.clawback),

Comment on lines 221 to 224
manager: asAddressOrNfd(data.manager.value!),
reserve: asAddressOrNfd(data.reserve.value!),
freeze: asAddressOrNfd(data.freeze.value!),
clawback: asAddressOrNfd(data.clawback.value!),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, why use asAddressOrNfd?

}
}

return {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the sender can't be resolved, the value is set to '', is it intended? Have you checked the behaviour of the transaction wizard when the value is ''?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking for that case like this now

`const val = data?.value ?? ''
const res = data?.resolvedAddress ?? ''

const isEmpty = !val && !res

if (isEmpty) {`

)

const result = await localnet.context.waitForIndexerTransaction(transactionId)
expect(result.transaction.sender).toBe(testAccount.addr.toString())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should compare it with the kmd account (from account manager) because I'm not sure is the testAccount is guarantee to be the same.

"version": "4.1.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.16.tgz",
"integrity": "sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==",
"version": "4.1.17",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we shouldn't update package-lock in this PR. If it needs to be updated, it should be a separate PR that deals with dependencies

<p>Create and send transactions to the selected network using a connected wallet.</p>
<TransactionsBuilder
defaultTransactions={searchParamsTransactions}
key={searchParamsTransactions.transactions.map((t) => t.id).join('|')} // rerender when it gets populated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a good idea, you should wrap this in a loading spinner when it's loading. Have a look at RenderLoadable for inspiration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a PageLoader before rendering the TransactionBuilder. That removes the update based on key change (hacky) approach.

if (errors && errors.length > 0) {
for (const error of errors) {
toast.error(error)
let cancelled = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is cancelled needed here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed together with the unused error handling

import { betanetId, mainnetId, testnetId, fnetId, localnetId } from '@/features/network/data'
import { algorandClient } from '@/features/common/data/algo-client'

export default async function resolveSenderAddress(data?: { value?: string; resolvedAddress?: string }): Promise<TransactionSender> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't pick this up in the previous round, I think we should avoid using export default. We use named export everywhere else in this project.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think data shouldn't be undefined

export default async function resolveSenderAddress(data?: { value?: string; resolvedAddress?: string }): Promise<TransactionSender> {
const { id: networkId } = settingsStore.get(networkConfigAtom)

const val = data?.value ?? ''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can simplify this function by

export async function resolveSenderAddress(data: { value?: string; resolvedAddress?: string }): Promise<TransactionSender> {
    if (data.value) {
        return data
    }

    // The rest
}

Makes the logic simple, if the data has value, just return it.

if (errors && errors.length > 0) {
for (const error of errors) {
toast.error(error)
let mounted = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe I missed something but I don't understand the purpose of the mounted variable. You init it with true and never change the value. Maybe it isn't needed

for (const error of errors) {
toast.error(error)
let mounted = true
const loadTransactions = async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should refactor the async logic inside useEffect. Elsewhere we use jotai atom to deal with loading data. Have a look at the transaction-page.tsx for example. I am aware that it needs to few pieces to setup so if you need a hand, please let me know.

const senderInput = await component.findByLabelText(/Sender/)
fireEvent.input(senderInput, {
target: { value: testAccount.addr },
target: { value: walletAccount.addr },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you change testAccount to walletAccount here? I thought that walletAccount is only used when the sender isn't set. I don't expect the see any changes in this test to be honest. It shouldn't be affected by the optional sender feature you are working on.

@p2arthur p2arthur force-pushed the feat/optional-sender-improved branch from 235900a to cc92c31 Compare November 19, 2025 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants