@xspswap/smart-order-router
Version:
XSwap Protocol V3 Smart Order Router
96 lines • 9.99 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TokenValidatorProvider = exports.TokenValidationResult = void 0;
const sdk_core_1 = require("@x-swap-protocol/sdk-core");
const lodash_1 = __importDefault(require("lodash"));
const ITokenValidator__factory_1 = require("../types/other/factories/ITokenValidator__factory");
const util_1 = require("../util");
const DEFAULT_ALLOWLIST = new Set([
// RYOSHI. Does not allow transfers between contracts so fails validation.
'0x777E2ae845272a2F540ebf6a3D03734A5a8f618e'.toLowerCase(),
]);
var TokenValidationResult;
(function (TokenValidationResult) {
TokenValidationResult[TokenValidationResult["UNKN"] = 0] = "UNKN";
TokenValidationResult[TokenValidationResult["FOT"] = 1] = "FOT";
TokenValidationResult[TokenValidationResult["STF"] = 2] = "STF";
})(TokenValidationResult = exports.TokenValidationResult || (exports.TokenValidationResult = {}));
const TOKEN_VALIDATOR_ADDRESS = '0x13E9fA07eBf6d019B5be08b3C450FacaA6Dd1AFe';
const AMOUNT_TO_FLASH_BORROW = '1000';
const GAS_LIMIT_PER_VALIDATE = 1000000;
class TokenValidatorProvider {
constructor(chainId, multicall2Provider, tokenValidationCache, tokenValidatorAddress = TOKEN_VALIDATOR_ADDRESS, gasLimitPerCall = GAS_LIMIT_PER_VALIDATE, amountToFlashBorrow = AMOUNT_TO_FLASH_BORROW, allowList = DEFAULT_ALLOWLIST) {
this.chainId = chainId;
this.multicall2Provider = multicall2Provider;
this.tokenValidationCache = tokenValidationCache;
this.tokenValidatorAddress = tokenValidatorAddress;
this.gasLimitPerCall = gasLimitPerCall;
this.amountToFlashBorrow = amountToFlashBorrow;
this.allowList = allowList;
this.CACHE_KEY = (chainId, address) => `token-${chainId}-${address}`;
this.BASES = [sdk_core_1.WETH9[this.chainId].address];
}
async validateTokens(tokens, providerConfig) {
const tokenAddressToToken = lodash_1.default.keyBy(tokens, 'address');
const addressesRaw = (0, lodash_1.default)(tokens)
.map((token) => token.address)
.uniq()
.value();
const addresses = [];
const tokenToResult = {};
// Check if we have cached token validation results for any tokens.
for (const address of addressesRaw) {
if (await this.tokenValidationCache.has(this.CACHE_KEY(this.chainId, address))) {
tokenToResult[address.toLowerCase()] =
(await this.tokenValidationCache.get(this.CACHE_KEY(this.chainId, address)));
}
else {
addresses.push(address);
}
}
util_1.log.info(`Got token validation results for ${addressesRaw.length - addresses.length} tokens from cache. Getting ${addresses.length} on-chain.`);
const functionParams = (0, lodash_1.default)(addresses)
.map((address) => [address, this.BASES, this.amountToFlashBorrow])
.value();
// We use the validate function instead of batchValidate to avoid poison pill problem.
// One token that consumes too much gas could cause the entire batch to fail.
const multicallResult = await this.multicall2Provider.callSameFunctionOnContractWithMultipleParams({
address: this.tokenValidatorAddress,
contractInterface: ITokenValidator__factory_1.ITokenValidator__factory.createInterface(),
functionName: 'validate',
functionParams: functionParams,
providerConfig,
additionalConfig: {
gasLimitPerCallOverride: this.gasLimitPerCall,
},
});
for (let i = 0; i < multicallResult.results.length; i++) {
const resultWrapper = multicallResult.results[i];
const tokenAddress = addresses[i];
const token = tokenAddressToToken[tokenAddress];
if (this.allowList.has(token.address.toLowerCase())) {
tokenToResult[token.address.toLowerCase()] = TokenValidationResult.UNKN;
await this.tokenValidationCache.set(this.CACHE_KEY(this.chainId, token.address.toLowerCase()), tokenToResult[token.address.toLowerCase()]);
continue;
}
// Could happen if the tokens transfer consumes too much gas so we revert. Just
// drop the token in that case.
if (!resultWrapper.success) {
util_1.log.info({ result: resultWrapper }, `Failed to validate token ${token.symbol}`);
continue;
}
const validationResult = resultWrapper.result[0];
tokenToResult[token.address.toLowerCase()] =
validationResult;
await this.tokenValidationCache.set(this.CACHE_KEY(this.chainId, token.address.toLowerCase()), tokenToResult[token.address.toLowerCase()]);
}
return {
getValidationByToken: (token) => tokenToResult[token.address.toLowerCase()],
};
}
}
exports.TokenValidatorProvider = TokenValidatorProvider;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tdmFsaWRhdG9yLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy90b2tlbi12YWxpZGF0b3ItcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsd0RBQWtFO0FBQ2xFLG9EQUF1QjtBQUV2QixnR0FBNkY7QUFDN0Ysa0NBQThCO0FBTTlCLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLENBQVM7SUFDeEMsMEVBQTBFO0lBQzFFLDRDQUE0QyxDQUFDLFdBQVcsRUFBRTtDQUMzRCxDQUFDLENBQUM7QUFFSCxJQUFZLHFCQUlYO0FBSkQsV0FBWSxxQkFBcUI7SUFDL0IsaUVBQVEsQ0FBQTtJQUNSLCtEQUFPLENBQUE7SUFDUCwrREFBTyxDQUFBO0FBQ1QsQ0FBQyxFQUpXLHFCQUFxQixHQUFyQiw2QkFBcUIsS0FBckIsNkJBQXFCLFFBSWhDO0FBTUQsTUFBTSx1QkFBdUIsR0FBRyw0Q0FBNEMsQ0FBQztBQUM3RSxNQUFNLHNCQUFzQixHQUFHLE1BQU0sQ0FBQztBQUN0QyxNQUFNLHNCQUFzQixHQUFHLE9BQVMsQ0FBQztBQXNCekMsTUFBYSxzQkFBc0I7SUFNakMsWUFDWSxPQUFnQixFQUNoQixrQkFBc0MsRUFDeEMsb0JBQW1ELEVBQ25ELHdCQUF3Qix1QkFBdUIsRUFDL0Msa0JBQWtCLHNCQUFzQixFQUN4QyxzQkFBc0Isc0JBQXNCLEVBQzVDLFlBQVksaUJBQWlCO1FBTjNCLFlBQU8sR0FBUCxPQUFPLENBQVM7UUFDaEIsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtRQUN4Qyx5QkFBb0IsR0FBcEIsb0JBQW9CLENBQStCO1FBQ25ELDBCQUFxQixHQUFyQixxQkFBcUIsQ0FBMEI7UUFDL0Msb0JBQWUsR0FBZixlQUFlLENBQXlCO1FBQ3hDLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBeUI7UUFDNUMsY0FBUyxHQUFULFNBQVMsQ0FBb0I7UUFaL0IsY0FB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