@@ -15,9 +15,10 @@ import { AltVM, assert, ensure0x, strip0x } from '@hyperlane-xyz/utils';
1515
1616import { mailbox } from '../artifacts.js' ;
1717import {
18+ ALEO_NULL_ADDRESS ,
1819 U128ToString ,
1920 formatAddress ,
20- getMessageKey ,
21+ splitToU128 ,
2122 stringToU128 ,
2223} from '../utils/helper.js' ;
2324import { AleoTransaction } from '../utils/types.js' ;
@@ -171,7 +172,7 @@ export class AleoProvider implements AltVM.IProvider {
171172 async isMessageDelivered ( req : AltVM . ReqIsMessageDelivered ) : Promise < boolean > {
172173 try {
173174 // Message key needs to be separated into [u128, u128] using Little Endian.
174- const messageKey = getMessageKey ( req . messageId ) ;
175+ const messageKey = splitToU128 ( req . messageId ) ;
175176
176177 const res = await this . aleoClient . getProgramMappingPlaintext (
177178 req . mailboxAddress ,
@@ -1094,8 +1095,119 @@ export class AleoProvider implements AltVM.IProvider {
10941095 }
10951096
10961097 async getRemoteTransferTransaction (
1097- _req : AltVM . ReqRemoteTransfer ,
1098+ req : AltVM . ReqRemoteTransfer ,
10981099 ) : Promise < AleoTransaction > {
1099- throw new Error ( `TODO: implement` ) ;
1100+ const { mailboxAddress } = await this . getToken ( {
1101+ tokenAddress : req . tokenAddress ,
1102+ } ) ;
1103+
1104+ const tokenMetadataValue = await this . aleoClient . getProgramMappingValue (
1105+ req . tokenAddress ,
1106+ 'token_metadata' ,
1107+ 'true' ,
1108+ ) ;
1109+
1110+ if ( ! tokenMetadataValue ) {
1111+ throw new Error ( `found no token metadata for ${ req . tokenAddress } ` ) ;
1112+ }
1113+
1114+ const mailbox = await this . getMailbox ( {
1115+ mailboxAddress : mailboxAddress ,
1116+ } ) ;
1117+
1118+ const remoteRouterValue = await this . aleoClient . getProgramMappingValue (
1119+ req . tokenAddress ,
1120+ 'remote_routers' ,
1121+ `${ req . destinationDomainId } u32` ,
1122+ ) ;
1123+
1124+ if ( ! remoteRouterValue ) {
1125+ throw new Error (
1126+ `found no remote router for destination domain id ${ req . destinationDomainId } ` ,
1127+ ) ;
1128+ }
1129+
1130+ const recipient = `[${ splitToU128 ( req . recipient )
1131+ . map ( ( u ) => u . toString ( ) )
1132+ . join ( ',' ) } ]`;
1133+
1134+ const creditAllowance = Array ( 4 ) . fill (
1135+ `{spender:${ ALEO_NULL_ADDRESS } ,amount:0u8}` ,
1136+ ) ;
1137+
1138+ const gasLimit = new BigNumber ( req . gasLimit ) ;
1139+ const hooks = [
1140+ req . customHookAddress || mailbox . defaultHook ,
1141+ mailbox . requiredHook ,
1142+ ] ;
1143+
1144+ for ( let i = 0 ; i < hooks . length ; i ++ ) {
1145+ try {
1146+ const igp = await this . getInterchainGasPaymasterHook ( {
1147+ hookAddress : hooks [ i ] ,
1148+ } ) ;
1149+
1150+ const config = igp . destinationGasConfigs [ req . destinationDomainId ] ;
1151+
1152+ if ( ! config ) {
1153+ continue ;
1154+ }
1155+
1156+ const quote = gasLimit
1157+ . plus ( config . gasOverhead )
1158+ . multipliedBy ( config . gasOracle . gasPrice )
1159+ . multipliedBy ( config . gasOracle . tokenExchangeRate )
1160+ . dividedToIntegerBy ( new BigNumber ( 10 ) . exponentiatedBy ( 10 ) )
1161+ . toFixed ( 0 ) ;
1162+
1163+ creditAllowance [ i ] = `{spender:${ hooks [ i ] } ,amount:${ quote } u8}` ;
1164+ } catch {
1165+ continue ;
1166+ }
1167+ }
1168+
1169+ if ( req . customHookAddress ) {
1170+ const hookMetadata = Array ( 256 ) . fill ( `0u8` ) ;
1171+
1172+ if ( req . customHookMetadata ) {
1173+ Buffer . from ( req . customHookMetadata , 'hex' ) . forEach ( ( b , i ) => {
1174+ hookMetadata [ i ] = `${ b } u8` ;
1175+ } ) ;
1176+ }
1177+
1178+ return {
1179+ programName : req . tokenAddress ,
1180+ functionName : 'transfer_remote' ,
1181+ priorityFee : 0 ,
1182+ privateFee : false ,
1183+ inputs : [
1184+ tokenMetadataValue ,
1185+ `{default_ism:${ mailbox . defaultIsm || ALEO_NULL_ADDRESS } ,default_hook:${ mailbox . defaultHook || ALEO_NULL_ADDRESS } ,required_hook:${ mailbox . requiredHook || ALEO_NULL_ADDRESS } }` ,
1186+ remoteRouterValue ,
1187+ `${ req . destinationDomainId } u8` ,
1188+ recipient ,
1189+ `${ req . amount } u128` ,
1190+ JSON . stringify ( creditAllowance ) . replaceAll ( '"' , '' ) ,
1191+ req . customHookAddress ,
1192+ JSON . stringify ( hookMetadata ) . replaceAll ( '"' , '' ) ,
1193+ ] ,
1194+ } ;
1195+ }
1196+
1197+ return {
1198+ programName : req . tokenAddress ,
1199+ functionName : 'transfer_remote' ,
1200+ priorityFee : 0 ,
1201+ privateFee : false ,
1202+ inputs : [
1203+ tokenMetadataValue ,
1204+ `{default_ism:${ mailbox . defaultIsm || ALEO_NULL_ADDRESS } ,default_hook:${ mailbox . defaultHook || ALEO_NULL_ADDRESS } ,required_hook:${ mailbox . requiredHook || ALEO_NULL_ADDRESS } }` ,
1205+ remoteRouterValue ,
1206+ `${ req . destinationDomainId } u8` ,
1207+ recipient ,
1208+ `${ req . amount } u128` ,
1209+ JSON . stringify ( creditAllowance ) . replaceAll ( '"' , '' ) ,
1210+ ] ,
1211+ } ;
11001212 }
11011213}
0 commit comments