11import { AleoProvider , AleoTransaction } from '@hyperlane-xyz/aleo-sdk' ;
2- import { Address , Numberish , assert } from '@hyperlane-xyz/utils' ;
2+ import {
3+ Address ,
4+ Domain ,
5+ Numberish ,
6+ addressToBytes32 ,
7+ assert ,
8+ strip0x ,
9+ } from '@hyperlane-xyz/utils' ;
310
411import { BaseAleoAdapter } from '../../app/MultiProtocolApp.js' ;
512import { MultiProtocolProvider } from '../../providers/MultiProtocolProvider.js' ;
613import { ChainName } from '../../types.js' ;
714import { TokenMetadata } from '../types.js' ;
815
9- import { ITokenAdapter , TransferParams } from './ITokenAdapter.js' ;
16+ import {
17+ IHypTokenAdapter ,
18+ ITokenAdapter ,
19+ InterchainGasQuote ,
20+ QuoteTransferRemoteParams ,
21+ TransferParams ,
22+ TransferRemoteParams ,
23+ } from './ITokenAdapter.js' ;
1024
1125export class AleoTokenAdapter
1226 extends BaseAleoAdapter
@@ -15,6 +29,10 @@ export class AleoTokenAdapter
1529 protected provider : AleoProvider ;
1630 protected tokenAddress : string ;
1731
32+ protected async getDenom ( ) : Promise < string > {
33+ return this . tokenAddress ;
34+ }
35+
1836 constructor (
1937 public readonly chainName : ChainName ,
2038 public readonly multiProvider : MultiProtocolProvider ,
@@ -27,20 +45,35 @@ export class AleoTokenAdapter
2745 }
2846
2947 async getBalance ( address : Address ) : Promise < bigint > {
48+ const denom = await this . getDenom ( ) ;
3049 return this . provider . getBalance ( {
3150 address,
51+ denom,
3252 } ) ;
3353 }
3454
3555 async getMetadata ( ) : Promise < TokenMetadata > {
36- const nativeToken = await this . provider . getToken ( {
56+ const { name , symbol , decimals } = await this . provider . getToken ( {
3757 tokenAddress : this . tokenAddress ,
3858 } ) ;
3959
60+ assert (
61+ name !== undefined ,
62+ `name on radix token ${ this . tokenAddress } is undefined` ,
63+ ) ;
64+ assert (
65+ symbol !== undefined ,
66+ `symbol on radix token ${ this . tokenAddress } is undefined` ,
67+ ) ;
68+ assert (
69+ decimals !== undefined ,
70+ `divisibility on radix token ${ this . tokenAddress } is undefined` ,
71+ ) ;
72+
4073 return {
41- name : nativeToken . name ,
42- symbol : nativeToken . symbol ,
43- decimals : nativeToken . decimals ,
74+ name,
75+ symbol,
76+ decimals,
4477 } ;
4578 }
4679
@@ -70,18 +103,167 @@ export class AleoTokenAdapter
70103 async populateTransferTx (
71104 transferParams : TransferParams ,
72105 ) : Promise < AleoTransaction > {
106+ const denom = await this . getDenom ( ) ;
107+
73108 assert ( transferParams . fromAccountOwner , `no sender in transfer params` ) ;
74109
75110 return this . provider . getTransferTransaction ( {
76111 signer : transferParams . fromAccountOwner ,
77112 recipient : transferParams . recipient ,
78- denom : '' ,
113+ denom,
79114 amount : transferParams . weiAmountOrId . toString ( ) ,
80115 } ) ;
81116 }
82117
83118 async getTotalSupply ( ) : Promise < bigint | undefined > {
84- // Not implemented, native tokens don't have an accessible total supply
85- return undefined ;
119+ const denom = await this . getDenom ( ) ;
120+ return this . provider . getTotalSupply ( {
121+ denom,
122+ } ) ;
123+ }
124+ }
125+
126+ export class AleoNativeTokenAdapter
127+ extends AleoTokenAdapter
128+ implements ITokenAdapter < AleoTransaction >
129+ {
130+ override async getMetadata ( ) : Promise < TokenMetadata > {
131+ const { nativeToken } = this . multiProvider . getChainMetadata ( this . chainName ) ;
132+ assert (
133+ nativeToken ,
134+ `Native token data is required for ${ AleoNativeTokenAdapter . name } ` ,
135+ ) ;
136+
137+ return {
138+ name : nativeToken . name ,
139+ symbol : nativeToken . symbol ,
140+ decimals : nativeToken . decimals ,
141+ } ;
86142 }
87143}
144+
145+ export class AleoHypCollateralAdapter
146+ extends AleoTokenAdapter
147+ implements IHypTokenAdapter < AleoTransaction >
148+ {
149+ constructor (
150+ public readonly chainName : ChainName ,
151+ public readonly multiProvider : MultiProtocolProvider ,
152+ public readonly addresses : { token : Address } ,
153+ ) {
154+ super ( chainName , multiProvider , addresses ) ;
155+ }
156+
157+ protected async getResourceAddress ( ) : Promise < string > {
158+ const { denom } = await this . provider . getToken ( {
159+ tokenAddress : this . tokenAddress ,
160+ } ) ;
161+ return denom ;
162+ }
163+
164+ async getDomains ( ) : Promise < Domain [ ] > {
165+ const { remoteRouters } = await this . provider . getRemoteRouters ( {
166+ tokenAddress : this . tokenAddress ,
167+ } ) ;
168+
169+ return remoteRouters . map ( ( router ) => router . receiverDomainId ) ;
170+ }
171+
172+ async getRouterAddress ( domain : Domain ) : Promise < Buffer > {
173+ const { remoteRouters } = await this . provider . getRemoteRouters ( {
174+ tokenAddress : this . tokenAddress ,
175+ } ) ;
176+
177+ const router = remoteRouters . find (
178+ ( router ) => router . receiverDomainId === domain ,
179+ ) ;
180+
181+ if ( ! router ) {
182+ throw new Error ( `Router with domain "${ domain } " not found` ) ;
183+ }
184+
185+ return Buffer . from ( strip0x ( router . receiverAddress ) , 'hex' ) ;
186+ }
187+
188+ async getAllRouters ( ) : Promise < Array < { domain : Domain ; address : Buffer } > > {
189+ const { remoteRouters } = await this . provider . getRemoteRouters ( {
190+ tokenAddress : this . tokenAddress ,
191+ } ) ;
192+
193+ return remoteRouters . map ( ( router ) => ( {
194+ domain : router . receiverDomainId ,
195+ address : Buffer . from ( strip0x ( router . receiverAddress ) , 'hex' ) ,
196+ } ) ) ;
197+ }
198+
199+ async getBridgedSupply ( ) : Promise < bigint | undefined > {
200+ return this . provider . getBridgedSupply ( {
201+ tokenAddress : this . tokenAddress ,
202+ } ) ;
203+ }
204+
205+ async quoteTransferRemoteGas ( {
206+ destination,
207+ } : QuoteTransferRemoteParams ) : Promise < InterchainGasQuote > {
208+ const { denom : addressOrDenom , amount } =
209+ await this . provider . quoteRemoteTransfer ( {
210+ tokenAddress : this . tokenAddress ,
211+ destinationDomainId : destination ,
212+ } ) ;
213+
214+ return {
215+ igpQuote : {
216+ addressOrDenom,
217+ amount,
218+ } ,
219+ } ;
220+ }
221+
222+ async populateTransferRemoteTx (
223+ params : TransferRemoteParams ,
224+ ) : Promise < AleoTransaction > {
225+ assert ( params . fromAccountOwner , `no sender in remote transfer params` ) ;
226+
227+ if ( ! params . interchainGas ) {
228+ params . interchainGas = await this . quoteTransferRemoteGas ( {
229+ destination : params . destination ,
230+ } ) ;
231+ }
232+
233+ const { remoteRouters } = await this . provider . getRemoteRouters ( {
234+ tokenAddress : this . tokenAddress ,
235+ } ) ;
236+
237+ const router = remoteRouters . find (
238+ ( router ) => router . receiverDomainId === params . destination ,
239+ ) ;
240+
241+ if ( ! router ) {
242+ throw new Error (
243+ `Failed to find remote router for token id and destination: ${ this . tokenAddress } ,${ params . destination } ` ,
244+ ) ;
245+ }
246+
247+ if ( ! params . interchainGas . igpQuote ?. addressOrDenom ) {
248+ throw new Error (
249+ `Require denom for max fee, didn't receive and denom in the interchainGas quote` ,
250+ ) ;
251+ }
252+
253+ return this . provider . getRemoteTransferTransaction ( {
254+ signer : params . fromAccountOwner ! ,
255+ tokenAddress : this . tokenAddress ,
256+ destinationDomainId : params . destination ,
257+ recipient : strip0x ( addressToBytes32 ( params . recipient ) ) ,
258+ amount : params . weiAmountOrId . toString ( ) ,
259+ customHookAddress : params . customHook ,
260+ gasLimit : router . gas ,
261+ maxFee : {
262+ denom : params . interchainGas . igpQuote ?. addressOrDenom ,
263+ amount : params . interchainGas . igpQuote ?. amount . toString ( ) ,
264+ } ,
265+ } ) ;
266+ }
267+ }
268+
269+ export class AleoHypSyntheticAdapter extends AleoHypCollateralAdapter { }
0 commit comments