You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The current architecture is tightly coupled to the ChainId dependency and its a poor architecture.
Fix Dependency Injection for the sdks
SDK-Core Addresses and mappings are a mess ()
There's code duplication in other sdks and no single source of truth (WETH addresses, and Quoter addresses are overridden and duplicated in smart-order-router, router-sdk, universal-router sdk)
Adding a new chain requires redeployment and synchronization of multiple sdks.
V2-SDK does not allow InitHash injection
At this point you're pretty tied into this poor architecture however you can do the following.
A: Inject all dependencies into all dependent classes, this a big headache since the pool and route dependencies will need to take in the factory and init hashes.
This would be an extreme refactor and cause a lot of existing third party code to break as a cause of the update
B: Static configuration Injection (Overall is a hack as the SDK should not be statically dependent however currently you don't support configurations per chain so it shouldn't be an issue.)
1. Add a class to statically initialize the chain configuration but fallback to the existing chains so people aren't forced to call the chain initializer
// ChainAddressConfig.ts
import { ChainAddresses } from "./addresses";
export type ChainAddressesMap = Record<number, ChainAddresses>;
const GLOBAL_CHAIN_ADDRESSES_KEY = '__GLOBAL_CHAIN_ADDRESSES_CONFIG__';
export class ChainAddressConfig {
private addressesMap: ChainAddressesMap = {};
private constructor() { }
private static get instance(): ChainAddressConfig {
if (!(globalThis as any)[GLOBAL_CHAIN_ADDRESSES_KEY]) {
(globalThis as any)[GLOBAL_CHAIN_ADDRESSES_KEY] = new ChainAddressConfig();
}
return (globalThis as any)[GLOBAL_CHAIN_ADDRESSES_KEY];
}
public static initialize(addressesMap: ChainAddressesMap, allowMerge = false): void {
if (!allowMerge && Object.keys(this.instance.addressesMap).length > 0) {
throw new Error('ChainAddressConfig already initialized. To merge, set allowMerge=true.');
}
this.instance.addressesMap = allowMerge
? { ...this.instance.addressesMap, ...addressesMap }
: addressesMap;
}
public static getAddresses(chainId: number): ChainAddresses | undefined {
return this.instance.addressesMap[chainId];
}
public static getAddress(
chainId: number,
key: Exclude<keyof ChainAddresses, 'weth'>
): string | undefined {
const addresses = this.getAddresses(chainId);
if (!addresses) {
return undefined;
}
return addresses[key];
}
public static getChainIds(): number[] {
return Object.keys(this.instance.addressesMap).map(Number);
}
}
Create a proxy to override the existing chain maps to dynamically support the static configuration: (Note: I created a fallback proxy provider which can be used in the smart-order router since you again decided to override some properties and dynamically create address maps e.g quoterV2Addresses)
export function createAddressProxy(propertyName: keyof ChainAddresses): AddressMap {
return new Proxy({}, {
get(_, chainId: string) {
const numericChainId = Number(chainId);
return CHAIN_TO_ADDRESSES_MAP[numericChainId]?.[propertyName];
},
ownKeys() {
return Object.keys(CHAIN_TO_ADDRESSES_MAP).filter((chainId) => {
return CHAIN_TO_ADDRESSES_MAP[Number(chainId)]?.[propertyName];
});
},
getOwnPropertyDescriptor(_, chainId: string) {
const numericChainId = Number(chainId);
if (CHAIN_TO_ADDRESSES_MAP[numericChainId]?.[propertyName]) {
return { enumerable: true, configurable: true };
}
return undefined;
},
has(_, chainId: string) {
const numericChainId = Number(chainId);
return CHAIN_TO_ADDRESSES_MAP[numericChainId]?.[propertyName] !== undefined;
},
});
}
export function createDynamicAddressMapProxyWithFallback(
property: string,
fallbackProperty: keyof ChainAddresses,
propertyOverrides: Record<number, string>
): AddressMap {
return new Proxy({}, {
get(_, chainId: string) {
const numericChainId = Number(chainId);
const chainConfig = CHAIN_TO_ADDRESSES_MAP[numericChainId];
return (
(chainConfig as any)?.[property] ??
propertyOverrides[numericChainId] ??
chainConfig?.[fallbackProperty]
);
},
has(_, chainId: string) {
const numericChainId = Number(chainId);
const chainConfig = CHAIN_TO_ADDRESSES_MAP[numericChainId];
return (
(chainConfig as any)?.[property] !== undefined ||
propertyOverrides[numericChainId] !== undefined ||
chainConfig?.[fallbackProperty] !== undefined
);
},
ownKeys() {
const chainIds = new Set<number>();
// Include any chain with a matching primary or fallback property
for (const [idStr, config] of Object.entries(CHAIN_TO_ADDRESSES_MAP)) {
const id = Number(idStr);
if ((config as any)?.[property] || config?.[fallbackProperty]) {
chainIds.add(id);
}
}
// Include overrides if the property/fallback is not already present
for (const idStr of Object.keys(propertyOverrides)) {
const id = Number(idStr);
const config = CHAIN_TO_ADDRESSES_MAP[id];
if (!(config as any)?.[property] && !config?.[fallbackProperty]) {
chainIds.add(id);
}
}
return Array.from(chainIds).map(String);
},
getOwnPropertyDescriptor(_, chainId: string) {
const numericChainId = Number(chainId);
const config = CHAIN_TO_ADDRESSES_MAP[numericChainId];
const value = (
(config as any)?.[property] ??
propertyOverrides[numericChainId] ??
config?.[fallbackProperty]
);
if (value !== undefined) {
return { enumerable: true, configurable: true };
}
return undefined;
}
});
}
Depricate old chain map and reference static chain configuration and build properties for the addtional address map
The current architecture is tightly coupled to the ChainId dependency and its a poor architecture.
Fix Dependency Injection for the sdks
At this point you're pretty tied into this poor architecture however you can do the following.
A: Inject all dependencies into all dependent classes, this a big headache since the pool and route dependencies will need to take in the factory and init hashes.
This would be an extreme refactor and cause a lot of existing third party code to break as a cause of the update
B: Static configuration Injection (Overall is a hack as the SDK should not be statically dependent however currently you don't support configurations per chain so it shouldn't be an issue.)
The text was updated successfully, but these errors were encountered: