@arcana/ca-sdk
Version:
Arcana Network's chain abstraction SDK for unified balance in Web3 apps
105 lines (104 loc) • 4.25 kB
JavaScript
import { bn, CHAIN_IDS } from "fuels";
import { encodeFunctionData } from "viem";
import ERC20ABI from "../abi/erc20";
import { ZERO_ADDRESS } from "../constants";
import { getLogger } from "../logger";
import { convertIntent, equalFold, mulDecimals } from "../utils";
const logger = getLogger();
class TransferQuery {
constructor(input, init, switchChain, createEVMHandler, createFuelHandler, evmAddress, chainList, fuelAccount) {
this.input = input;
this.init = init;
this.switchChain = switchChain;
this.createEVMHandler = createEVMHandler;
this.createFuelHandler = createFuelHandler;
this.evmAddress = evmAddress;
this.chainList = chainList;
this.fuelAccount = fuelAccount;
this.handlerResponse = null;
this.exec = async () => {
if (!this.handlerResponse?.handler) {
throw new Error("ca not applicable");
}
await this.handlerResponse.handler.process();
logger.debug("TransferQuery:Exec", {
state: "processing completed, going to processTx()",
});
return this.handlerResponse.processTx();
};
this.simulate = async () => {
if (!this.handlerResponse?.handler) {
throw new Error("ca not applicable");
}
const response = await this.handlerResponse.handler.buildIntent();
if (!response) {
throw new Error("ca not applicable");
}
return {
intent: convertIntent(response.intent, response.token, this.chainList),
token: response.token,
};
};
}
async initHandler() {
if (!this.handlerResponse) {
const input = this.input;
await this.init();
logger.debug("SendQueryBuilder.exec", {
c: input.chainID,
p: input,
});
if (input.to &&
input.amount !== undefined &&
input.token &&
input.chainID) {
const tokenInfo = this.chainList.getTokenInfoBySymbol(input.chainID, input.token);
if (!tokenInfo) {
throw new Error("Token not supported on this chain.");
}
const amount = mulDecimals(input.amount, tokenInfo.decimals);
logger.debug("transfer:2", { amount, tokenInfo });
if (input.chainID === CHAIN_IDS.fuel.mainnet) {
if (this.fuelAccount) {
const tx = await this.fuelAccount.createTransfer(input.to, bn(amount.toString()), tokenInfo.contractAddress);
this.handlerResponse = await this.createFuelHandler(tx, {
bridge: false,
gas: 0n,
skipTx: false,
});
}
else {
throw new Error("Fuel connector is not set");
}
}
else {
await this.switchChain(input.chainID);
const isNative = equalFold(tokenInfo.contractAddress, ZERO_ADDRESS);
const p = {
from: this.evmAddress,
to: input.to,
};
if (isNative) {
p.value = `0x${amount.toString(16)}`;
}
else {
p.to = tokenInfo.contractAddress;
p.data = encodeFunctionData({
abi: ERC20ABI,
args: [input.to, amount],
functionName: "transfer",
});
}
this.handlerResponse = await this.createEVMHandler(p, {
bridge: false,
gas: 0n,
skipTx: false,
});
}
return;
}
throw new Error("transfer: missing params");
}
}
}
export { TransferQuery };