@arcana/ca-sdk
Version:
Arcana Network's chain abstraction SDK for unified balance in Web3 apps
95 lines (94 loc) • 3.84 kB
JavaScript
import { Universe } from "@arcana/ca-common";
import { Account, Address, bn, BN, Provider as FuelProvider, hexlify, OutputType, randomBytes, UTXO_ID_LEN, } from "fuels";
import { FUEL_BASE_ASSET_ID, FUEL_NETWORK_URL } from "../../constants";
import { getLogger } from "../../logger";
import { equalFold, mulDecimals } from "../../utils";
const logger = getLogger();
const getFuelProvider = (getBalances, address, chain) => {
return new (class Provider extends FuelProvider {
constructor(url, options) {
super(url, { ...options, resourceCacheTTL: -1 });
}
async assembleTx(params) {
const { request } = params;
logger.debug("ffProvider", {
request,
});
const addr = new Address(address);
const balances = await getBalances();
const assetIdsOnFuel = chain.custom.knownTokens.map((c) => c.contractAddress);
const outputAssetList = request.outputs.filter((o) => o.type === OutputType.Coin);
const allAssetSupported = outputAssetList.every((a) => assetIdsOnFuel.includes(hexlify(a.assetId)));
logger.debug("FuelProvide:1", {
allAssetSupported,
assetIdsOnFuel,
outputAssetList,
});
if (!allAssetSupported) {
return super.assembleTx({
...params,
feePayerAccount: new Account(addr),
request,
});
}
const al = [];
for (const a of assetIdsOnFuel) {
if (!outputAssetList.map((al) => al.assetId).includes(a) &&
a !== FUEL_BASE_ASSET_ID) {
continue;
}
const asset = balances.find((asset) => asset.breakdown.find((b) => equalFold(b.contractAddress, hexlify(a)) &&
b.universe === Universe.FUEL));
const chainAsset = asset?.breakdown.find((b) => equalFold(b.contractAddress, hexlify(a)) &&
b.universe === Universe.FUEL);
logger.debug("FuelProvider:2", {
asset,
chainAsset,
});
if (asset && chainAsset) {
const decimals = equalFold(FUEL_BASE_ASSET_ID, chainAsset.contractAddress)
? 9
: asset.decimals;
const amount = new BN(mulDecimals(asset.balance, decimals).toString());
logger.debug("FuelProvider:3", {
amount,
assetId: hexlify(a),
});
al.push({
amount,
assetId: hexlify(a),
});
}
}
request.addResources(generateFakeResources(al, new Address(address)));
const { accountCoinQuantities, ...rest } = params;
logger.debug("FuelProvider:4", {
accountCoinQuantities,
params: { ...params },
request,
rest,
});
const response = await super.assembleTx({
...rest,
request,
});
logger.debug("FuelProvider:4", {
accountCoinQuantities,
params: { ...params },
request,
response,
});
return response;
}
})(FUEL_NETWORK_URL);
};
const generateFakeResources = (coins, address) => {
return coins.map((coin) => ({
blockCreated: bn(1),
id: hexlify(randomBytes(UTXO_ID_LEN)),
owner: address,
txCreatedIdx: bn(1),
...coin,
}));
};
export { getFuelProvider };