@@ -5,6 +5,7 @@ import type {
5
5
AutomaticTokenBridge ,
6
6
ChainContext ,
7
7
Signer ,
8
+ NativeAddress ,
8
9
TokenId ,
9
10
TokenTransferDetails ,
10
11
TransactionId ,
@@ -14,6 +15,7 @@ import type {
14
15
} from "@wormhole-foundation/sdk-definitions" ;
15
16
import {
16
17
TokenBridge ,
18
+ UniversalAddress ,
17
19
deserialize ,
18
20
isNative ,
19
21
isTokenId ,
@@ -501,7 +503,6 @@ export namespace TokenTransfer {
501
503
dstChain : ChainContext < N , DC > ,
502
504
token : TokenId < SC > ,
503
505
) : Promise < TokenId < DC > > {
504
- // that will be minted when the transfer is redeemed
505
506
let lookup : TokenId ;
506
507
const tb = await srcChain . getTokenBridge ( ) ;
507
508
if ( isNative ( token . address ) ) {
@@ -514,20 +515,37 @@ export namespace TokenTransfer {
514
515
} else {
515
516
try {
516
517
// otherwise, check to see if it is a wrapped token locally
517
- lookup = await tb . getOriginalAsset ( token . address ) ;
518
- } catch ( e ) {
518
+ let address : NativeAddress < SC > ;
519
+ if ( UniversalAddress . instanceof ( token . address ) ) {
520
+ address = ( await tb . getWrappedAsset ( token ) ) as NativeAddress < SC > ;
521
+ } else {
522
+ address = token . address ;
523
+ }
524
+ lookup = await tb . getOriginalAsset ( address ) ;
525
+ } catch ( e : any ) {
526
+ if ( ! e . message . includes ( "not a wrapped asset" ) ) throw e ;
519
527
// not a from-chain native wormhole-wrapped one
520
- lookup = { chain : token . chain , address : await tb . getTokenUniversalAddress ( token . address ) } ;
528
+ let address : NativeAddress < SC > ;
529
+ if ( UniversalAddress . instanceof ( token . address ) ) {
530
+ address = await tb . getTokenNativeAddress ( srcChain . chain , token . address ) ;
531
+ } else {
532
+ address = token . address ;
533
+ }
534
+ lookup = { chain : token . chain , address : await tb . getTokenUniversalAddress ( address ) } ;
521
535
}
522
536
}
523
537
524
538
// if the token id is actually native to the destination, return it
539
+ const dstTb = await dstChain . getTokenBridge ( ) ;
525
540
if ( lookup . chain === dstChain . chain ) {
526
- return lookup as TokenId < DC > ;
541
+ const nativeAddress = await dstTb . getTokenNativeAddress (
542
+ lookup . chain ,
543
+ lookup . address as UniversalAddress ,
544
+ ) ;
545
+ return { chain : dstChain . chain , address : nativeAddress } ;
527
546
}
528
547
529
548
// otherwise, figure out what the token address representing the wormhole-wrapped token we're transferring
530
- const dstTb = await dstChain . getTokenBridge ( ) ;
531
549
const dstAddress = await dstTb . getWrappedAsset ( lookup ) ;
532
550
return { chain : dstChain . chain , address : dstAddress } ;
533
551
}
@@ -627,14 +645,27 @@ export namespace TokenTransfer {
627
645
dstChain : ChainContext < N , Chain > ,
628
646
transfer : Omit < TokenTransferDetails , "from" | "to" > ,
629
647
) : Promise < TransferQuote > {
630
- const srcDecimals = await srcChain . getDecimals ( transfer . token . address ) ;
648
+ const srcTb = await srcChain . getTokenBridge ( ) ;
649
+ let srcToken : NativeAddress < Chain > ;
650
+ if ( isNative ( transfer . token . address ) ) {
651
+ srcToken = await srcTb . getWrappedNative ( ) ;
652
+ } else if ( UniversalAddress . instanceof ( transfer . token . address ) ) {
653
+ try {
654
+ srcToken = ( await srcTb . getWrappedAsset ( transfer . token ) ) as NativeAddress < Chain > ;
655
+ } catch ( e : any ) {
656
+ if ( ! e . message . includes ( "not a wrapped asset" ) ) throw e ;
657
+ srcToken = await srcTb . getTokenNativeAddress ( srcChain . chain , transfer . token . address ) ;
658
+ }
659
+ } else {
660
+ srcToken = transfer . token . address ;
661
+ }
662
+ // @ts -ignore: TS2339
663
+ const srcTokenId = Wormhole . tokenId ( srcChain . chain , srcToken . toString ( ) ) ;
664
+
665
+ const srcDecimals = await srcChain . getDecimals ( srcToken ) ;
631
666
const srcAmount = amount . fromBaseUnits ( transfer . amount , srcDecimals ) ;
632
667
const srcAmountTruncated = amount . truncate ( srcAmount , TokenTransfer . MAX_DECIMALS ) ;
633
668
634
- const srcToken = isNative ( transfer . token . address )
635
- ? await srcChain . getNativeWrappedTokenId ( )
636
- : transfer . token ;
637
-
638
669
// Ensure the transfer would not violate governor transfer limits
639
670
const [ tokens , limits ] = await Promise . all ( [
640
671
getGovernedTokens ( wh . config . api ) ,
@@ -643,13 +674,11 @@ export namespace TokenTransfer {
643
674
644
675
const warnings : QuoteWarning [ ] = [ ] ;
645
676
if ( limits !== null && srcChain . chain in limits && tokens !== null ) {
646
- const srcTb = await srcChain . getTokenBridge ( ) ;
647
-
648
677
let origAsset : TokenId ;
649
678
if ( isNative ( transfer . token . address ) ) {
650
679
origAsset = {
651
680
chain : srcChain . chain ,
652
- address : await srcTb . getTokenUniversalAddress ( srcToken . address ) ,
681
+ address : await srcTb . getTokenUniversalAddress ( srcToken ) ,
653
682
} ;
654
683
} else {
655
684
try {
@@ -658,7 +687,7 @@ export namespace TokenTransfer {
658
687
if ( ! e . message . includes ( "not a wrapped asset" ) ) throw e ;
659
688
origAsset = {
660
689
chain : srcChain . chain ,
661
- address : await srcTb . getTokenUniversalAddress ( srcToken . address ) ,
690
+ address : await srcTb . getTokenUniversalAddress ( srcToken ) ,
662
691
} ;
663
692
}
664
693
}
@@ -685,26 +714,16 @@ export namespace TokenTransfer {
685
714
}
686
715
687
716
const dstToken = await TokenTransfer . lookupDestinationToken ( srcChain , dstChain , transfer . token ) ;
688
- // TODO: this is a hack to get the aptos native gas token decimals
689
- // which requires us to pass in a token address in canonical form
690
- // but the `dstToken.address` here is in universal form
691
- if ( dstChain . chain === "Aptos" && dstToken . chain === "Aptos" ) {
692
- const dstTb = await dstChain . getTokenBridge ( ) ;
693
- const wrappedNative = await dstTb . getWrappedNative ( ) ;
694
- if (
695
- dstToken . address . toString ( ) ===
696
- ( await dstTb . getTokenUniversalAddress ( wrappedNative ) ) . toString ( )
697
- ) {
698
- dstToken . address = wrappedNative ;
699
- }
700
- }
701
717
const dstDecimals = await dstChain . getDecimals ( dstToken . address ) ;
702
718
const dstAmountReceivable = amount . scale ( srcAmountTruncated , dstDecimals ) ;
703
719
704
720
const eta = finality . estimateFinalityTime ( srcChain . chain ) ;
705
721
if ( ! transfer . automatic ) {
706
722
return {
707
- sourceToken : { token : srcToken , amount : amount . units ( srcAmountTruncated ) } ,
723
+ sourceToken : {
724
+ token : srcTokenId ,
725
+ amount : amount . units ( srcAmountTruncated ) ,
726
+ } ,
708
727
destinationToken : { token : dstToken , amount : amount . units ( dstAmountReceivable ) } ,
709
728
warnings : warnings . length > 0 ? warnings : undefined ,
710
729
eta,
@@ -716,7 +735,7 @@ export namespace TokenTransfer {
716
735
// The fee is removed from the amount transferred
717
736
// quoted on the source chain
718
737
const stb = await srcChain . getAutomaticTokenBridge ( ) ;
719
- const fee = await stb . getRelayerFee ( dstChain . chain , srcToken . address ) ;
738
+ const fee = await stb . getRelayerFee ( dstChain . chain , srcToken ) ;
720
739
const feeAmountDest = amount . scale (
721
740
amount . truncate ( amount . fromBaseUnits ( fee , srcDecimals ) , TokenTransfer . MAX_DECIMALS ) ,
722
741
dstDecimals ,
@@ -791,11 +810,11 @@ export namespace TokenTransfer {
791
810
792
811
return {
793
812
sourceToken : {
794
- token : srcToken ,
813
+ token : srcTokenId ,
795
814
amount : amount . units ( srcAmountTruncated ) ,
796
815
} ,
797
816
destinationToken : { token : dstToken , amount : destAmountLessFee } ,
798
- relayFee : { token : srcToken , amount : fee } ,
817
+ relayFee : { token : srcTokenId , amount : fee } ,
799
818
destinationNativeGas,
800
819
warnings : warnings . length > 0 ? warnings : undefined ,
801
820
eta,
0 commit comments