Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- 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
176 lines
6.8 KiB
JavaScript
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();
|