Development Artifact Cleanup: ✅ BROTHER_NODE REORGANIZATION: Moved development test node to appropriate location - dev/test-nodes/brother_node/: Moved from root directory for better organization - Contains development configuration, test logs, and test chain data - No impact on production systems - purely development/testing artifact ✅ DEVELOPMENT ARTIFACTS IDENTIFIED: - Chain ID: aitbc-brother-chain (test/development chain) - Ports: 8010 (P2P) and 8011 (RPC) - different from production - Environment: .env file with test configuration - Logs: rpc.log and node.log from development testing session (March 15, 2026) ✅ ROOT DIRECTORY CLEANUP: Removed development clutter from production directory - brother_node/ moved to dev/test-nodes/brother_node/ - Root directory now contains only production-ready components - Development artifacts properly organized in dev/ subdirectory DIRECTORY STRUCTURE IMPROVEMENT: 📁 dev/test-nodes/: Development and testing node configurations 🏗️ Root Directory: Clean production structure with only essential components 🧪 Development Isolation: Test environments separated from production BENEFITS: ✅ Clean Production Directory: No development artifacts in root ✅ Better Organization: Development nodes grouped in dev/ subdirectory ✅ Clear Separation: Production vs development environments clearly distinguished ✅ Maintainability: Easier to identify and manage development components RESULT: Successfully moved brother_node development artifact to dev/test-nodes/ subdirectory, cleaning up the root directory while preserving development testing environment for future use.
79 lines
8.9 KiB
TypeScript
Executable File
79 lines
8.9 KiB
TypeScript
Executable File
import { bytesToHex } from '@noble/hashes/utils';
|
|
import { add0x, createDecimal } from '../utils.ts';
|
|
import { addHints, addHook } from './common.ts';
|
|
import { type HintOpt } from './decoder.ts';
|
|
|
|
// prettier-ignore
|
|
const _ABI = [
|
|
{inputs:[{internalType:"address",name:"_factory",type:"address"},{internalType:"address",name:"_WETH9",type:"address"}],stateMutability:"nonpayable",type:"constructor"},{inputs:[],name:"WETH9",outputs:[{internalType:"address",name:"",type:"address"}],stateMutability:"view",type:"function"},{inputs:[{components:[{internalType:"bytes",name:"path",type:"bytes"},{internalType:"address",name:"recipient",type:"address"},{internalType:"uint256",name:"deadline",type:"uint256"},{internalType:"uint256",name:"amountIn",type:"uint256"},{internalType:"uint256",name:"amountOutMinimum",type:"uint256"}],internalType:"struct ISwapRouter.ExactInputParams",name:"params",type:"tuple"}],name:"exactInput",outputs:[{internalType:"uint256",name:"amountOut",type:"uint256"}],stateMutability:"payable",type:"function"},{inputs:[{components:[{internalType:"address",name:"tokenIn",type:"address"},{internalType:"address",name:"tokenOut",type:"address"},{internalType:"uint24",name:"fee",type:"uint24"},{internalType:"address",name:"recipient",type:"address"},{internalType:"uint256",name:"deadline",type:"uint256"},{internalType:"uint256",name:"amountIn",type:"uint256"},{internalType:"uint256",name:"amountOutMinimum",type:"uint256"},{internalType:"uint160",name:"sqrtPriceLimitX96",type:"uint160"}],internalType:"struct ISwapRouter.ExactInputSingleParams",name:"params",type:"tuple"}],name:"exactInputSingle",outputs:[{internalType:"uint256",name:"amountOut",type:"uint256"}],stateMutability:"payable",type:"function"},{inputs:[{components:[{internalType:"bytes",name:"path",type:"bytes"},{internalType:"address",name:"recipient",type:"address"},{internalType:"uint256",name:"deadline",type:"uint256"},{internalType:"uint256",name:"amountOut",type:"uint256"},{internalType:"uint256",name:"amountInMaximum",type:"uint256"}],internalType:"struct ISwapRouter.ExactOutputParams",name:"params",type:"tuple"}],name:"exactOutput",outputs:[{internalType:"uint256",name:"amountIn",type:"uint256"}],stateMutability:"payable",type:"function"},{inputs:[{components:[{internalType:"address",name:"tokenIn",type:"address"},{internalType:"address",name:"tokenOut",type:"address"},{internalType:"uint24",name:"fee",type:"uint24"},{internalType:"address",name:"recipient",type:"address"},{internalType:"uint256",name:"deadline",type:"uint256"},{internalType:"uint256",name:"amountOut",type:"uint256"},{internalType:"uint256",name:"amountInMaximum",type:"uint256"},{internalType:"uint160",name:"sqrtPriceLimitX96",type:"uint160"}],internalType:"struct ISwapRouter.ExactOutputSingleParams",name:"params",type:"tuple"}],name:"exactOutputSingle",outputs:[{internalType:"uint256",name:"amountIn",type:"uint256"}],stateMutability:"payable",type:"function"},{inputs:[],name:"factory",outputs:[{internalType:"address",name:"",type:"address"}],stateMutability:"view",type:"function"},{inputs:[{internalType:"bytes[]",name:"data",type:"bytes[]"}],name:"multicall",outputs:[{internalType:"bytes[]",name:"results",type:"bytes[]"}],stateMutability:"payable",type:"function"},{inputs:[],name:"refundETH",outputs:[],stateMutability:"payable",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"},{internalType:"uint256",name:"value",type:"uint256"},{internalType:"uint256",name:"deadline",type:"uint256"},{internalType:"uint8",name:"v",type:"uint8"},{internalType:"bytes32",name:"r",type:"bytes32"},{internalType:"bytes32",name:"s",type:"bytes32"}],name:"selfPermit",outputs:[],stateMutability:"payable",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"},{internalType:"uint256",name:"nonce",type:"uint256"},{internalType:"uint256",name:"expiry",type:"uint256"},{internalType:"uint8",name:"v",type:"uint8"},{internalType:"bytes32",name:"r",type:"bytes32"},{internalType:"bytes32",name:"s",type:"bytes32"}],name:"selfPermitAllowed",outputs:[],stateMutability:"payable",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"},{internalType:"uint256",name:"nonce",type:"uint256"},{internalType:"uint256",name:"expiry",type:"uint256"},{internalType:"uint8",name:"v",type:"uint8"},{internalType:"bytes32",name:"r",type:"bytes32"},{internalType:"bytes32",name:"s",type:"bytes32"}],name:"selfPermitAllowedIfNecessary",outputs:[],stateMutability:"payable",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"},{internalType:"uint256",name:"value",type:"uint256"},{internalType:"uint256",name:"deadline",type:"uint256"},{internalType:"uint8",name:"v",type:"uint8"},{internalType:"bytes32",name:"r",type:"bytes32"},{internalType:"bytes32",name:"s",type:"bytes32"}],name:"selfPermitIfNecessary",outputs:[],stateMutability:"payable",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"},{internalType:"uint256",name:"amountMinimum",type:"uint256"},{internalType:"address",name:"recipient",type:"address"}],name:"sweepToken",outputs:[],stateMutability:"payable",type:"function"},{inputs:[{internalType:"address",name:"token",type:"address"},{internalType:"uint256",name:"amountMinimum",type:"uint256"},{internalType:"address",name:"recipient",type:"address"},{internalType:"uint256",name:"feeBips",type:"uint256"},{internalType:"address",name:"feeRecipient",type:"address"}],name:"sweepTokenWithFee",outputs:[],stateMutability:"payable",type:"function"},{inputs:[{internalType:"int256",name:"amount0Delta",type:"int256"},{internalType:"int256",name:"amount1Delta",type:"int256"},{internalType:"bytes",name:"_data",type:"bytes"}],name:"uniswapV3SwapCallback",outputs:[],stateMutability:"nonpayable",type:"function"},{inputs:[{internalType:"uint256",name:"amountMinimum",type:"uint256"},{internalType:"address",name:"recipient",type:"address"}],name:"unwrapWETH9",outputs:[],stateMutability:"payable",type:"function"},{inputs:[{internalType:"uint256",name:"amountMinimum",type:"uint256"},{internalType:"address",name:"recipient",type:"address"},{internalType:"uint256",name:"feeBips",type:"uint256"},{internalType:"address",name:"feeRecipient",type:"address"}],name:"unwrapWETH9WithFee",outputs:[],stateMutability:"payable",type:"function"},{stateMutability:"payable",type:"receive"}
|
|
] as const;
|
|
|
|
// Generic multicall hook, maybe move to common?
|
|
const ABI_MULTICALL = /* @__PURE__ */ addHook(_ABI, 'multicall', (d, contract, info, opt) => {
|
|
const decoded = (info.value as any).map((i: any) => d.decode(contract, i, opt));
|
|
info.name = `multicall(${decoded.map((i: any) => i.name).join(', ')})`;
|
|
info.signature = `multicall(${decoded.map((i: any) => i.signature).join(', ')})`;
|
|
info.value = decoded.map((i: any) => i.value);
|
|
let hasHint = false;
|
|
for (let i of decoded) if (i.hint) hasHint = true;
|
|
if (hasHint)
|
|
info.hint = decoded
|
|
.filter((i: any) => i.hint)
|
|
.map((i: any) => i.hint)
|
|
.join(' ');
|
|
return info;
|
|
});
|
|
|
|
const decodePath = (b: Uint8Array) =>
|
|
[b.slice(0, 20), b.slice(-20)].map((i) => add0x(bytesToHex(i)));
|
|
|
|
function uniToken(contract: string, amount: bigint, opt: HintOpt): string | undefined {
|
|
if (!contract || !opt.contracts || !opt.contracts[contract]) return;
|
|
const info = opt.contracts[contract];
|
|
if (!info.decimals || !info.symbol) return;
|
|
return `${createDecimal(info.decimals).encode(amount)} ${info.symbol}`;
|
|
}
|
|
const uniTs = (ts: number) => `Expires at ${new Date(Number(ts) * 1000).toUTCString()}`;
|
|
|
|
const hints = {
|
|
exactInputSingle(v: any, opt: HintOpt) {
|
|
const [from, to] = [
|
|
uniToken(v.tokenIn, v.amountIn, opt),
|
|
uniToken(v.tokenOut, v.amountOutMinimum, opt),
|
|
];
|
|
if (!from || !to) throw new Error('Not enough info');
|
|
return `Swap exact ${from} for at least ${to}. ${uniTs(v.deadline)}`;
|
|
},
|
|
exactOutputSingle(v: any, opt: HintOpt) {
|
|
const [from, to] = [
|
|
uniToken(v.tokenIn, v.amountInMaximum, opt),
|
|
uniToken(v.tokenOut, v.amountOut, opt),
|
|
];
|
|
if (!from || !to) throw new Error('Not enough info');
|
|
return `Swap up to ${from} for exact ${to}. ${uniTs(v.deadline)}`;
|
|
},
|
|
exactInput(v: any, opt: HintOpt) {
|
|
const [tokenIn, tokenOut] = decodePath(v.path);
|
|
const [from, to] = [
|
|
uniToken(tokenIn, v.amountIn, opt),
|
|
uniToken(tokenOut, v.amountOutMinimum, opt),
|
|
];
|
|
if (!from || !to) throw new Error('Not enough info');
|
|
return `Swap exact ${from} for at least ${to}. ${uniTs(v.deadline)}`;
|
|
},
|
|
exactOutput(v: any, opt: HintOpt) {
|
|
const [tokenIn, tokenOut] = decodePath(v.path).reverse();
|
|
const [from, to] = [
|
|
uniToken(tokenIn, v.amountInMaximum, opt),
|
|
uniToken(tokenOut, v.amountOut, opt),
|
|
];
|
|
if (!from || !to) throw new Error('Not enough info');
|
|
return `Swap up to ${from} for exact ${to}. ${uniTs(v.deadline)}`;
|
|
},
|
|
};
|
|
|
|
const ABI = /* @__PURE__ */ addHints(ABI_MULTICALL, hints);
|
|
|
|
export default ABI;
|
|
export const UNISWAP_V3_ROUTER_CONTRACT = '0xe592427a0aece92de3edee1f18e0157c05861564';
|