Files
proxmox/scripts/deployment/protocolink-swap-to-gas.cjs
defiQUG 3f76bc9507
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
docs: update master documentation and push to Gitea (2026-03-06)
- MASTER_INDEX: Last Updated 2026-03-06; status 59/59 contracts; add NEXT_STEPS_LIST, CONTRACT_NEXT_STEPS_LIST
- docs/README, NEXT_STEPS_INDEX, 06-besu/MASTER_INDEX: Last Updated 2026-03-06
- Contract check script: 59 addresses (PMM, vault/reserve, CompliantFiatTokens); canonical CCIP/router
- New docs: EXECUTION_CHECKLIST, NEXT_STEPS_LIST, DOTENV_AUDIT, ADDITIONAL_PATHS, deployer gas runbook, WEMIX_ACQUISITION_TABLED, etc.
- Config: deployer-gas-routes, cro-wemix-swap-routes, routing-registry, token-mapping
- Scripts: check-contracts-on-chain-138, check-pmm-pool-balances-chain138, deployer-gas-auto-route, acquire-cro-and-wemix-gas
- Operator rule: operator-lan-access-check.mdc

Made-with: Cursor
2026-03-06 19:11:25 -08:00

176 lines
6.8 KiB
JavaScript

#!/usr/bin/env node
/**
* Protocolink path for deployer gas auto-route: get quote and build tx data for
* swapping ERC-20 (USDT, USDC, LINK) to native gas (or WETH) on Protocolink-supported chains.
*
* Usage:
* node scripts/deployment/protocolink-swap-to-gas.cjs --chain-id 1 [--token USDC] [--amount-raw 1000000] [--no-execute]
* PROTOCOLINK_API_URL=https://api.protocolink.com node scripts/deployment/protocolink-swap-to-gas.cjs --chain-id 137
*
* Requires: Node 18+ (fetch), config/deployer-gas-routes.json for chain list.
* Output: JSON with quote and tx building instructions; no private key or signing in script.
*/
const fs = require('fs');
const path = require('path');
const PROJECT_ROOT = path.resolve(__dirname, '../..');
const CONFIG_PATH = path.join(PROJECT_ROOT, 'config/deployer-gas-routes.json');
const API_BASE = process.env.PROTOCOLINK_API_URL || 'https://api.protocolink.com';
const PROTOCOL_ID = process.env.PROTOCOLINK_PROTOCOL || 'paraswap-v5';
const LOGIC_ID = 'swap-token';
const SLIPPAGE_BPS = parseInt(process.env.SLIPPAGE_BPS || '150', 10);
// Common token addresses per chain (mainnet; extend as needed)
const NATIVE_OR_WETH = {
1: { address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', decimals: 18, symbol: 'WETH' },
56: { address: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', decimals: 18, symbol: 'WBNB' },
137: { address: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', decimals: 18, symbol: 'WMATIC' },
100: { address: '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d', decimals: 18, symbol: 'WXDAI' },
10: { address: '0x4200000000000000000000000000000000000006', decimals: 18, symbol: 'WETH' },
42161: { address: '0x82aF49447D8a07e3bd95BD0d56f35241523fBb1', decimals: 18, symbol: 'WETH' },
8453: { address: '0x4200000000000000000000000000000000000006', decimals: 18, symbol: 'WETH' },
43114: { address: '0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7', decimals: 18, symbol: 'WAVAX' },
25: { address: '0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23', decimals: 18, symbol: 'WCRO' },
};
const USDT = {
1: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
56: '0x55d398326f99059fF775485246999027B3197955',
137: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
100: '0x4ECaBa5870353805a9F068101A40E0f32ed605C6',
10: '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58',
42161: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',
8453: '0x0000000000000000000000000000000000000000', // TBD
43114: '0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7',
25: '0x66e428c3f67a68878562e79A0234c1F83c208770',
};
const USDC = {
1: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
56: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',
137: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',
100: '0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83',
10: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
42161: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
8453: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
43114: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
25: '0xc21223249CA28397B4B6541dfFaEcC539BfF0c59',
};
const LINK = {
1: '0x514910771AF9Ca656af840dff83E8264EcF986CA',
56: '0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD',
137: '0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39',
100: '0xE2e73A1c69ecF83F464CECE147577d37BCf26298',
10: '0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6',
42161: '0xf97f4df75117a78c1A5a0DBb814Af92458539FB4',
8453: '0x0000000000000000000000000000000000000000', // TBD
43114: '0x5947BB275c521040051D82396192181b413227A3',
25: '0xE7d7D8374CF6a8e3F656c433F6B0f0C81F6d06F5',
};
function getTokenIn(chainId, symbol) {
const s = (symbol || 'USDC').toUpperCase();
let addr;
if (s === 'USDT') addr = USDT[chainId];
else if (s === 'USDC') addr = USDC[chainId];
else if (s === 'LINK') addr = LINK[chainId];
else return null;
if (!addr || addr === '0x0000000000000000000000000000000000000000') return null;
const decimals = s === 'LINK' ? 18 : 6;
return { chainId, address: addr, decimals, symbol: s, name: s };
}
function getTokenOut(chainId) {
const t = NATIVE_OR_WETH[chainId];
if (!t) return null;
return { chainId, address: t.address, decimals: t.decimals, symbol: t.symbol, name: t.symbol };
}
function parseArgs() {
const args = process.argv.slice(2);
let chainId, tokenIn = 'USDC', amountRaw, noExecute = false;
for (let i = 0; i < args.length; i++) {
if (args[i] === '--chain-id' && args[i + 1]) chainId = parseInt(args[i + 1], 10);
if (args[i] === '--token' && args[i + 1]) tokenIn = args[i + 1];
if (args[i] === '--amount-raw' && args[i + 1]) amountRaw = args[i + 1];
if (args[i] === '--no-execute') noExecute = true;
}
return { chainId, tokenIn, amountRaw: amountRaw || '1000000', noExecute };
}
async function requestQuote(chainId, tokenInObj, tokenOutObj, amountRaw) {
const url = `${API_BASE}/v1/protocols/${chainId}/${PROTOCOL_ID}/${LOGIC_ID}/quote`;
const body = {
input: {
token: tokenInObj,
amount: amountRaw,
},
tokenOut: tokenOutObj,
slippage: SLIPPAGE_BPS,
};
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Protocolink quote failed ${res.status}: ${text}`);
}
return res.json();
}
function loadConfig() {
if (!fs.existsSync(CONFIG_PATH)) return null;
return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
}
async function main() {
const { chainId, tokenIn: tokenSymbol, amountRaw, noExecute } = parseArgs();
if (!chainId) {
console.error('Usage: node protocolink-swap-to-gas.cjs --chain-id <chainId> [--token USDC|USDT|LINK] [--amount-raw <raw>] [--no-execute]');
process.exit(1);
}
const tokenInObj = getTokenIn(chainId, tokenSymbol);
const tokenOutObj = getTokenOut(chainId);
if (!tokenInObj || !tokenOutObj) {
console.error(JSON.stringify({
error: 'Unsupported chain or token',
chainId,
tokenIn: tokenSymbol,
message: 'Add token addresses for this chain in protocolink-swap-to-gas.cjs or use a supported chain (1, 56, 137, 100, 10, 42161, 8453, 43114, 25).',
}, null, 2));
process.exit(1);
}
try {
const quote = await requestQuote(chainId, tokenInObj, tokenOutObj, amountRaw);
const output = {
chainId,
protocolId: PROTOCOL_ID,
logicId: LOGIC_ID,
quote,
tokenIn: tokenInObj,
tokenOut: tokenOutObj,
amountInRaw: amountRaw,
slippageBps: SLIPPAGE_BPS,
nextStep: 'Use Protocolink API "build transaction" or SDK to build tx; sign with deployer key and submit. See https://docs.protocolink.com/protocolink-api/overview.',
noExecute: true,
};
console.log(JSON.stringify(output, null, 2));
} catch (err) {
console.error(JSON.stringify({
error: err.message,
chainId,
tokenIn: tokenSymbol,
}, null, 2));
process.exit(1);
}
}
main();