Skip to content

Conversation

@yrong
Copy link
Contributor

@yrong yrong commented Nov 14, 2025

Context

Adds support for multiple-asset transfers in the P→E direction, along with some refactoring and cleanup. For now, since PNA is not yet widely adopted in production, this implementation supports only multiple ERC-20 assets. We can extend it in a future PR if necessary.

Resolves: https://linear.app/snowfork/issue/SNO-1637

@yrong yrong force-pushed the ron/multi-assets-transfer branch from f9d6a6c to ea1f2dd Compare November 16, 2025 15:50
@yrong yrong marked this pull request as ready for review November 17, 2025 04:04
@yrong yrong requested a review from claravanstaden November 17, 2025 04:04
@yrong yrong force-pushed the ron/multi-assets-transfer branch from b77bc39 to 1af53a2 Compare November 17, 2025 04:08
Copy link
Contributor

@claravanstaden claravanstaden left a comment

Choose a reason for hiding this comment

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

Nice! 👏🏻

Comment on lines +114 to +119
export type AggregatedAsset = {
tokenErcMetadata: ERC20Metadata
ahAssetMetadata: Asset
sourceAssetMetadata: Asset
amount: bigint
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that we don't want to change the SDK interface too often, can we add a field to distinguish if an asset is an ERC-20 or PNA, so we don't have to change the interface later? Or does this type already support this?

We don't have to add PNA support right now, but the interface should be defined with PNA in mind so we don't need to make unnecessary changes later.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

An Asset with a non-nil location field is treated as PNA; otherwise, it’s ENA.
It’s a bit implicit, though — we might consider adding an explicit flag to make this clearer.

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 a flag would be cool yeah! :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines 734 to 750
if (isNativeBalance && fee.totalFeeInNative) {
if (amount + fee.totalFeeInNative > tokenBalance) {
logs.push({
kind: ValidationKind.Error,
reason: ValidationReason.InsufficientTokenBalance,
message: "Insufficient token balance to submit transaction.",
})
}
} else {
if (amount > tokenBalance) {
logs.push({
kind: ValidationKind.Error,
reason: ValidationReason.InsufficientTokenBalance,
message: "Insufficient token balance to submit transaction.",
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we not leave these basic token balances checks? Dry run doesn't always give a clear error to the user.

Copy link
Contributor Author

@yrong yrong Nov 21, 2025

Choose a reason for hiding this comment

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

I’d prefer to remove it for simplicity. It can be detected by a dry run, and the result should already include the error code, for example:

error: {
          Module: {
            index: 31
            error: 0x1c000900
          }
        }

I assume this can then be further decoded into a more detailed error description.

@alistair-singh What's your take on this?

Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to remove them for simplicity. However the UI is driven by these errors. We use them for many cases such as for NeuroWeb, when the API returns InsufficientTokenBalance we pop up a pre transfer step which allows the user to wrap/unwrap.

https://github.com/Snowfork/snowbridge-app/blob/8d9efcd5c843ca9b467f85c80822741242703789/utils/sendToken.ts#L55-L64

We do similar for ETH. So I would only support it if we can get the same kind of granularity.

Copy link
Contributor Author

@yrong yrong Nov 26, 2025

Choose a reason for hiding this comment

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

8706c10 for InsufficientTokenBalance and 74ec9f1 for InsufficientDotFee

const sourceParachainImpl = await paraImplementation(parachain)
const { tokenErcMetadata, sourceParachain, ahAssetMetadata, sourceAssetMetadata } =
resolveInputs(registry, tokenAddress, sourceParachainImpl.parachainId)
resolveInputs(registry, tokens[0].address, sourceParachainImpl.parachainId)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should add a check if tokens.length > 1, throw an error that only 1 PNA is supported at this time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yrong yrong requested a review from alistair-singh November 21, 2025 05:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants