Conversation
Deploying algokit-lora with
|
| Latest commit: |
c5675a2
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://7bb95edf.algokit-lora.pages.dev |
| Branch Preview URL: | https://feat-optional-sender-improve.algokit-lora.pages.dev |
| @@ -0,0 +1,33 @@ | |||
| import { Nfd } from '@/features/nfd/data/types' | |||
|
|
|||
| export type Props = PropsWithChildren<{ | ||
| address: string | Address | ||
| short?: boolean | ||
| className?: string | ||
| showCopyButton?: boolean | ||
| showQRButton?: boolean | ||
| nfd?: Nfd | ||
| autoPopulated?: boolean | ||
| }> |
There was a problem hiding this comment.
this should be type Props = AddressOrNfdLinkProps & { autoPopulated?: boolean }
| manager: asAddressOrNfd(data.manager.value!), | ||
| reserve: asAddressOrNfd(data.reserve.value!), | ||
| freeze: asAddressOrNfd(data.freeze.value!), | ||
| clawback: asAddressOrNfd(data.clawback.value!), |
There was a problem hiding this comment.
why do you use asAddressOrNfd here? If I recall correctly these values can be optional
There was a problem hiding this comment.
You're right, back to optional.
manager: asOptionalAddressOrNfd(data.manager), reserve: asOptionalAddressOrNfd(data.reserve), freeze: asOptionalAddressOrNfd(data.freeze), clawback: asOptionalAddressOrNfd(data.clawback),
| manager: asAddressOrNfd(data.manager.value!), | ||
| reserve: asAddressOrNfd(data.reserve.value!), | ||
| freeze: asAddressOrNfd(data.freeze.value!), | ||
| clawback: asAddressOrNfd(data.clawback.value!), |
There was a problem hiding this comment.
same here, why use asAddressOrNfd?
| } | ||
| } | ||
|
|
||
| return { |
There was a problem hiding this comment.
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 ''?
There was a problem hiding this comment.
Checking for that case like this now
`const val = data?.value ?? ''
const res = data?.resolvedAddress ?? ''
const isEmpty = !val && !res
if (isEmpty) {`
There was a problem hiding this comment.
I think we could
return data
if we can't populate the address
| ) | ||
|
|
||
| const result = await localnet.context.waitForIndexerTransaction(transactionId) | ||
| expect(result.transaction.sender).toBe(testAccount.addr.toString()) |
There was a problem hiding this comment.
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.
package-lock.json
Outdated
| "version": "4.1.16", | ||
| "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.16.tgz", | ||
| "integrity": "sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==", | ||
| "version": "4.1.17", |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Added a PageLoader before rendering the TransactionBuilder. That removes the update based on key change (hacky) approach.
src/features/transaction-wizard/utils/use-transaction-search-params-builder.ts
Outdated
Show resolved
Hide resolved
| if (errors && errors.length > 0) { | ||
| for (const error of errors) { | ||
| toast.error(error) | ||
| let cancelled = false |
There was a problem hiding this comment.
why is cancelled needed here?
There was a problem hiding this comment.
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> { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 ?? '' |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
No need data? because data can't be undefined
| if (errors && errors.length > 0) { | ||
| for (const error of errors) { | ||
| toast.error(error) | ||
| let mounted = true |
There was a problem hiding this comment.
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 () => { |
There was a problem hiding this comment.
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 }, |
There was a problem hiding this comment.
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.
…e unsigned commits
…params transaction builder
…estWallet + address PR comments
… fields that got required
235900a to
cc92c31
Compare
| const val = data?.value ?? '' | ||
| const res = data?.resolvedAddress ?? '' | ||
|
|
||
| const isEmpty = !val && !res |
There was a problem hiding this comment.
This is to account for the "" case
…plify the function and make it named export
…o use jotai for async auto population
…o use case wallet variables instead of test suite walletAddress
| type: BuildableTransactionType.AssetReconfigure, | ||
| asset: data.asset, | ||
| sender: data.sender, | ||
|
|
There was a problem hiding this comment.
remove this empty line
| const receiverLabel = 'Receiver' | ||
|
|
||
| export const paymentFormSchema = z.object({ | ||
| sender: optionalAddressFieldSchema, |
There was a problem hiding this comment.
I think moving the sender above ...commonSchema can caused unwanted bahaviour because this will be overwritten by commonSchema
There was a problem hiding this comment.
I agree. Even though there aren't any properties that would overlap, setting the sender: optionalAddress afterwards makes a lot more sense.
| return { | ||
| sender: transaction.sender.resolvedAddress, | ||
| receiver: transaction.receiver ? transaction.receiver.resolvedAddress : transaction.sender.resolvedAddress, | ||
| receiver: transaction.receiver ? transaction.receiver.resolvedAddress : (transaction.sender?.resolvedAddress ?? 'LOL IDK'), |
There was a problem hiding this comment.
I don't think you need to do this, the sender can't be undefined
| import { betanetId, mainnetId, testnetId, fnetId, localnetId } from '@/features/network/data' | ||
| import { algorandClient } from '@/features/common/data/algo-client' | ||
|
|
||
| export async function resolveSenderAddress(data: { value?: string; resolvedAddress?: string }): Promise<TransactionSender> { |
There was a problem hiding this comment.
let's rename to resolveTransactionSender to match the returned type
| export default async function resolveSenderAddress(data?: { value?: string; resolvedAddress?: string }): Promise<TransactionSender> { | ||
| const { id: networkId } = settingsStore.get(networkConfigAtom) | ||
|
|
||
| const val = data?.value ?? '' |
There was a problem hiding this comment.
No need data? because data can't be undefined
| }) | ||
|
|
||
| it.each([ | ||
| // Missing required field cases |
There was a problem hiding this comment.
You should remove these comments too if you removed the test case
| expect(await screen.findByText(assetId)).toBeInTheDocument() | ||
| // Find the yellow sender link (auto-populated) | ||
| const senderLinks = await screen.findAllByText(localnetDispenderAccount.addr.toString()) | ||
| expect(senderLinks.some((link) => link.className.includes('text-yellow-500'))).toBe(true) |
There was a problem hiding this comment.
Not sure if we need to go this far in the test to be honest, it's just the visual effect. In the future, if we need to change the color, we will need to update all the tests
| useEffect(() => { | ||
| setTransactions(defaultTransactions ?? []) | ||
| }, [defaultTransactions]) |
There was a problem hiding this comment.
can you confirm if the useEffect is needed. This component isn't rendered until the loadable atom resolves data
There was a problem hiding this comment.
Not needed. Removed it
| return groupedParams.filter((entry) => Object.keys(entry).length > 0) | ||
| } | ||
|
|
||
| const autopopulateAddress = atomFamily((searchParamsString: string) => { |
There was a problem hiding this comment.
can you review the names in this file? They don't match with the purpose.
There was a problem hiding this comment.
You don't need an atomFamily here, please refer to the implementation of the useLoadableTransactionAtom. If you have questions, please reach out to me.
.vscode/settings.json
Outdated
| "editor.defaultFormatter": "esbenp.prettier-vscode" | ||
| } | ||
| }, | ||
| "postman.settings.dotenv-detection-notification-visibility": false |
chore: refactor the search params transactions hook
… improve optional sender handling
| return { | ||
| value: val, | ||
| resolvedAddress: res, | ||
| } |
There was a problem hiding this comment.
if (val) { return data as TransactionSender }
| } | ||
| } | ||
|
|
||
| return { |
There was a problem hiding this comment.
I think we could
return data
if we can't populate the address
| }) | ||
|
|
||
| it('should render payment transaction without sender - auto populate sender with localnet address', async () => { | ||
| const localnetDispenderAccount = await localnet.algorand.account.localNetDispenser() |
There was a problem hiding this comment.
| const localnetDispenderAccount = await localnet.algorand.account.localNetDispenser() | |
| const localnetDispenserAccount = await localnet.algorand.account.localNetDispenser() |
| }) | ||
|
|
||
| it('should render asset create transaction without sender - auto populate sender with localnet address', async () => { | ||
| const localnetDispenderAccount = await localnet.algorand.account.localNetDispenser() |
There was a problem hiding this comment.
fix spelling for all localnetDispenderAccount
| expect(await screen.findByText(`0 ${unitName}`)).toBeInTheDocument() | ||
| }) | ||
|
|
||
| it('should render asset opt-in transaction without sender auto-populated', async () => { |
There was a problem hiding this comment.
| it('should render asset opt-in transaction without sender auto-populated', async () => { | |
| it('should render asset opt-in transaction without sender - auto populate sender with localnet address', async () => { |
Let's make it consistent with the rest
| }), | ||
| }) | ||
|
|
||
| await waitFor( |
There was a problem hiding this comment.
why does this test has waitFor but the opt-in test doesn't? Should you use findAllByText here as well to avoid waitFor?
There was a problem hiding this comment.
Changed all tests that use waitFor to use await findAllByText instead. Much better!
| return { | ||
| sender: transaction.sender.resolvedAddress, | ||
| receiver: transaction.receiver ? transaction.receiver.resolvedAddress : transaction.sender.resolvedAddress, | ||
| receiver: transaction.receiver ? transaction.receiver.resolvedAddress : transaction.sender?.resolvedAddress, |
There was a problem hiding this comment.
| receiver: transaction.receiver ? transaction.receiver.resolvedAddress : transaction.sender?.resolvedAddress, | |
| receiver: transaction.receiver ? transaction.receiver.resolvedAddress : transaction.sender.resolvedAddress, |
- throw error when can't resolve sender - clean up the tests
…gorandfoundation/algokit-lora into feat/optional-sender-improved
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. 🚀