Skip to content

Commit b6f79cf

Browse files
committed
chore: add remote router tx
1 parent a439613 commit b6f79cf

3 files changed

Lines changed: 129 additions & 7 deletions

File tree

typescript/aleo-sdk/src/clients/provider.ts

Lines changed: 116 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ import { AltVM, assert, ensure0x, strip0x } from '@hyperlane-xyz/utils';
1515

1616
import { mailbox } from '../artifacts.js';
1717
import {
18+
ALEO_NULL_ADDRESS,
1819
U128ToString,
1920
formatAddress,
20-
getMessageKey,
21+
splitToU128,
2122
stringToU128,
2223
} from '../utils/helper.js';
2324
import { 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
}

typescript/aleo-sdk/src/clients/signer.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -782,8 +782,18 @@ export class AleoSigner
782782
}
783783

784784
async remoteTransfer(
785-
_req: Omit<AltVM.ReqRemoteTransfer, 'signer'>,
785+
req: Omit<AltVM.ReqRemoteTransfer, 'signer'>,
786786
): Promise<AltVM.ResRemoteTransfer> {
787-
throw new Error(`TODO: implement`);
787+
const tx = await this.getRemoteTransferTransaction({
788+
signer: this.getSignerAddress(),
789+
...req,
790+
});
791+
792+
const txId = await this.programManager.execute(tx);
793+
await this.aleoClient.waitForTransactionConfirmation(txId);
794+
795+
return {
796+
tokenAddress: req.tokenAddress,
797+
};
788798
}
789799
}

typescript/aleo-sdk/src/utils/helper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { strip0x } from '@hyperlane-xyz/utils';
55
export const ALEO_NULL_ADDRESS =
66
'aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc';
77

8-
export function getMessageKey(messageId: string): [U128, U128] {
8+
export function splitToU128(messageId: string): [U128, U128] {
99
const bytes = Buffer.from(strip0x(messageId), 'hex');
1010

1111
// Split into two 128-bit chunks

0 commit comments

Comments
 (0)