Skip to content

Commit 3aef7d5

Browse files
committed
axelar transceiver
1 parent f571b64 commit 3aef7d5

File tree

7 files changed

+160
-52
lines changed

7 files changed

+160
-52
lines changed

evm/ts/src/axelar.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export async function getAxelarGasFee(
1818
destinationChain: Chain,
1919
gasLimit: bigint
2020
): Promise<bigint> {
21-
const axelarQueryApi = new AxelarQueryAPI({
21+
const api = new AxelarQueryAPI({
2222
environment:
2323
network === "Mainnet" ? Environment.MAINNET : Environment.TESTNET,
2424
});
@@ -33,7 +33,7 @@ export async function getAxelarGasFee(
3333
throw new Error(`Unsupported destination chain: ${destinationChain}`);
3434
}
3535

36-
const response = await axelarQueryApi.estimateGasFee(
36+
const response = await api.estimateGasFee(
3737
axelarSourceChain,
3838
axelarDestinationChain,
3939
gasLimit

evm/ts/src/multiTokenNtt.ts

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,9 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
173173
}
174174
}
175175

176-
async getSendTransceivers(destinationChain: Chain) {
176+
async getSendTransceivers(
177+
destinationChain: Chain
178+
): Promise<Ntt.TransceiverMeta[]> {
177179
const sendTransceivers =
178180
await this.gmpManager.getSendTransceiversWithIndicesForChain(
179181
toChainId(destinationChain)
@@ -191,7 +193,9 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
191193
);
192194
}
193195

194-
async getReceiveTransceivers(sourceChain: Chain) {
196+
async getReceiveTransceivers(
197+
sourceChain: Chain
198+
): Promise<Ntt.TransceiverMeta[]> {
195199
const receiveTransceivers =
196200
await this.gmpManager.getReceiveTransceiversWithIndicesForChain(
197201
toChainId(sourceChain)
@@ -235,36 +239,44 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
235239

236240
const instructions: Ntt.TransceiverInstruction[] = await Promise.all(
237241
sendTransceivers.map(async (transceiver) => {
238-
if (transceiver.type.toLowerCase() === "wormhole") {
239-
return {
240-
index: transceiver.index,
241-
payload: new Uint8Array([1]), // skipRelay = true
242-
};
243-
} else if (transceiver.type.toLowerCase() === "axelar") {
244-
// If we fail to fetch the axelar gas fee, then use 0 as a fallback
245-
// The user will need to manually top up the axelar gas fee later
246-
let gasFee = 0n;
247-
try {
248-
gasFee = await getAxelarGasFee(
249-
this.network,
250-
this.chain,
251-
dstChain,
252-
gasLimit
242+
switch (transceiver.type.toLowerCase()) {
243+
case "wormhole":
244+
return {
245+
index: transceiver.index,
246+
payload: new Uint8Array([1]), // skipRelay = true
247+
};
248+
case "axelar": {
249+
let gasFee = 0n;
250+
try {
251+
gasFee = await getAxelarGasFee(
252+
this.network,
253+
this.chain,
254+
dstChain,
255+
gasLimit
256+
);
257+
} catch (e) {
258+
// If we fail to fetch the gas fee, then use 0 as a fallback.
259+
// The Axelar relay should fail and the track() method will
260+
// surface a RelayFailedError that a UI can use to inform the user.
261+
// We don't want to block the transfer entirely just because
262+
// of a failure to fetch the gas fee.
263+
gasFee = 100000000000000n; // 0.0001 ETH
264+
console.error(`Failed to fetch axelar gas fee: ${e}`);
265+
}
266+
return {
267+
index: transceiver.index,
268+
payload: encoding.bignum.toBytes(gasFee, 32),
269+
};
270+
}
271+
default:
272+
throw new Error(
273+
`Unsupported transceiver type: ${transceiver.type} at index ${transceiver.index}`
253274
);
254-
} catch {}
255-
return {
256-
index: transceiver.index,
257-
payload: encoding.bignum.toBytes(gasFee, 32),
258-
};
259-
} else {
260-
throw new Error(
261-
`Unsupported transceiver type: ${transceiver.type} at index ${transceiver.index}`
262-
);
263275
}
264276
})
265277
);
266278

267-
// the contract expects the instructions to be sorted by transceiver index
279+
// The contract expects the instructions to be sorted by transceiver index.
268280
instructions.sort((a, b) => a.index - b.index);
269281

270282
return instructions;
@@ -378,12 +390,12 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
378390
);
379391
}
380392

381-
// TODO: this only supports redeeming with a Wormhole transceiver for now
382393
async *redeem(attestation: MultiTokenNtt.Attestation) {
383394
const transceivers = await this.getReceiveTransceivers(
384395
attestation.emitterChain
385396
);
386397

398+
// TODO: support other transceiver types
387399
const wormholeTransceiver = transceivers.find((t) => t.type === "wormhole");
388400
if (!wormholeTransceiver) {
389401
throw new Error("No Wormhole transceiver registered for this chain");
@@ -514,8 +526,7 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
514526

515527
async *completeInboundQueuedTransfer(
516528
fromChain: Chain,
517-
transceiverMessage: MultiTokenNtt.Message,
518-
payer?: AccountAddress<C>
529+
transceiverMessage: MultiTokenNtt.Message
519530
) {
520531
const tx =
521532
await this.manager.completeInboundQueuedTransfer.populateTransaction(
@@ -540,7 +551,7 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
540551
};
541552
}
542553

543-
// This will return null if the token is not yet created
554+
// This will return null if the token doesn't exist
544555
async getLocalToken(
545556
originalToken: MultiTokenNtt.OriginalTokenId
546557
): Promise<TokenId | null> {
@@ -559,6 +570,7 @@ export class EvmMultiTokenNtt<N extends Network, C extends EvmChains>
559570
return { chain: this.chain, address: toNative(this.chain, wethAddress) };
560571
}
561572

573+
// If the local token doesn't exist yet, this will return the address where it will be deployed
562574
async calculateLocalTokenAddress(
563575
originalToken: MultiTokenNtt.OriginalTokenId,
564576
tokenMeta: MultiTokenNtt.TokenMeta

sdk/definitions/src/multiTokenNtt.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ export namespace MultiTokenNtt {
5252
>
5353
>;
5454

55-
export type TransferOptions = {};
56-
5755
export type OriginalTokenId<C extends Chain = Chain> = {
5856
chain: C;
5957
address: UniversalAddress;
@@ -86,6 +84,10 @@ export namespace MultiTokenNtt {
8684
export interface MultiTokenNtt<N extends Network, C extends Chain> {
8785
isPaused(): Promise<boolean>;
8886

87+
getSendTransceivers(dstChain: Chain): Promise<Ntt.TransceiverMeta[]>;
88+
89+
getReceiveTransceivers(srcChain: Chain): Promise<Ntt.TransceiverMeta[]>;
90+
8991
createTransceiverInstructions(
9092
dstChain: Chain,
9193
gasLimit: bigint
@@ -140,8 +142,7 @@ export interface MultiTokenNtt<N extends Network, C extends Chain> {
140142

141143
completeInboundQueuedTransfer(
142144
fromChain: Chain,
143-
transceiverMessage: MultiTokenNtt.Message,
144-
payer?: AccountAddress<C>
145+
transceiverMessage: MultiTokenNtt.Message
145146
): AsyncGenerator<UnsignedTransaction<N, C>>;
146147

147148
getOriginalToken(localToken: TokenId): Promise<MultiTokenNtt.OriginalTokenId>;

sdk/definitions/src/ntt.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ export namespace Ntt {
8888
payload: Uint8Array;
8989
};
9090

91+
export type TransceiverMeta = {
92+
address: string;
93+
index: number;
94+
type: string;
95+
};
96+
9197
export type Peer<C extends Chain> = {
9298
address: ChainAddress<C>;
9399
tokenDecimals: number;

sdk/route/src/executor/multiToken.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -780,11 +780,9 @@ export class MultiTokenNttExecutorRoute<N extends Network>
780780
const destinationNtt = await toChain.getProtocol("MultiTokenNtt", {
781781
multiTokenNtt: receipt.params.normalizedParams.destinationContracts,
782782
});
783-
const sender = Wormhole.chainAddress(signer.chain(), signer.address());
784783
const completeTransfer = destinationNtt.completeInboundQueuedTransfer(
785784
receipt.from,
786-
vaa.payload.nttManagerPayload,
787-
sender.address
785+
vaa.payload.nttManagerPayload
788786
);
789787
const finalizeTxs = await signSendWait(toChain, completeTransfer, signer);
790788
return {

0 commit comments

Comments
 (0)