import fs from 'node:fs';
import { PrivyClient } from '@privy-io/server-auth';
import { createWalletClient, createPublicClient, http, erc20Abi, formatUnits, encodeFunctionData, recoverAddress } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { polygon } from 'viem/chains';
const env = {};
for (const l of fs.readFileSync(new URL('../.env.privy', import.meta.url), 'utf8').split('\n')) { const t = l.trim(); if (!t || t.startsWith('#')) continue; const i = t.indexOf('='); if (i > 0) env[t.slice(0, i).trim()] = t.slice(i + 1).trim(); }
const privy = new PrivyClient(env.PRIVY_APP_ID, env.PRIVY_APP_SECRET, { walletApi: { authorizationPrivateKey: env.PRIVY_AUTHORIZATION_KEY } });
const users = await privy.getUsers();
let EOA = null;
for (const u of users) for (const a of u.linkedAccounts || []) if (a.type === 'wallet' && a.walletClientType === 'privy') EOA = a.address;
console.log('Rick Privy EOA (Safe owner):', EOA);
let PK = '';
for (const l of fs.readFileSync('/home/app/polymarket-weather-bot/.env', 'utf8').split('\n')) { const t = l.trim(); if (t.startsWith('PRIVATE_KEY=')) PK = t.slice(12).trim(); }
if (!PK.startsWith('0x')) PK = '0x' + PK;
const gasPayer = privateKeyToAccount(PK);
const RPC = 'https://polygon.drpc.org';
const pub = createPublicClient({ chain: polygon, transport: http(RPC) });
const wal = createWalletClient({ account: gasPayer, chain: polygon, transport: http(RPC) });
const PUSD = '0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB';
const SAFE = '0x7570210eACa5F3783577997fF74e8FEbe9B9E1f4';
const DW = '0x50A8061e9448EB1e5d5e7aF07BE4E4F63C6F24Ff';
const Z = '0x0000000000000000000000000000000000000000';
const SAFE_ABI = [
{ name: 'nonce', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
{ name: 'isOwner', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }], outputs: [{ type: 'bool' }] },
{ name: 'getTransactionHash', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }, { type: 'uint256' }, { type: 'bytes' }, { type: 'uint8' }, { type: 'uint256' }, { type: 'uint256' }, { type: 'uint256' }, { type: 'address' }, { type: 'address' }, { type: 'uint256' }], outputs: [{ type: 'bytes32' }] },
{ name: 'execTransaction', type: 'function', stateMutability: 'payable', inputs: [{ type: 'address' }, { type: 'uint256' }, { type: 'bytes' }, { type: 'uint8' }, { type: 'uint256' }, { type: 'uint256' }, { type: 'uint256' }, { type: 'address' }, { type: 'address' }, { type: 'bytes' }], outputs: [{ type: 'bool' }] },
];
console.log('isOwner(Rick):', await pub.readContract({ address: SAFE, abi: SAFE_ABI, functionName: 'isOwner', args: [EOA] }));
const bal = await pub.readContract({ address: PUSD, abi: erc20Abi, functionName: 'balanceOf', args: [SAFE] });
console.log('Rick Safe pUSD:', formatUnits(bal, 6));
if (bal === 0n) { console.log('nothing'); process.exit(0); }
const data = encodeFunctionData({ abi: erc20Abi, functionName: 'transfer', args: [DW, bal] });
const nonce = await pub.readContract({ address: SAFE, abi: SAFE_ABI, functionName: 'nonce' });
const args = [PUSD, 0n, data, 0, 0n, 0n, 0n, Z, Z];
const safeTxHash = await pub.readContract({ address: SAFE, abi: SAFE_ABI, functionName: 'getTransactionHash', args: [...args, nonce] });
const typedData = {
domain: { chainId: 137, verifyingContract: SAFE },
types: { SafeTx: [ { name: 'to', type: 'address' }, { name: 'value', type: 'uint256' }, { name: 'data', type: 'bytes' }, { name: 'operation', type: 'uint8' }, { name: 'safeTxGas', type: 'uint256' }, { name: 'baseGas', type: 'uint256' }, { name: 'gasPrice', type: 'uint256' }, { name: 'gasToken', type: 'address' }, { name: 'refundReceiver', type: 'address' }, { name: 'nonce', type: 'uint256' } ] },
primaryType: 'SafeTx',
message: { to: PUSD, value: '0', data, operation: 0, safeTxGas: '0', baseGas: '0', gasPrice: '0', gasToken: Z, refundReceiver: Z, nonce: nonce.toString() },
};
const { signature } = await privy.walletApi.ethereum.signTypedData({ address: EOA, chainType: 'ethereum', typedData });
const recovered = await recoverAddress({ hash: safeTxHash, signature });
console.log('sig recovers to:', recovered, recovered.toLowerCase() === EOA.toLowerCase() ? 'OK matches owner' : 'MISMATCH abort');
if (recovered.toLowerCase() !== EOA.toLowerCase()) process.exit(1);
const hash = await wal.writeContract({ address: SAFE, abi: SAFE_ABI, functionName: 'execTransaction', args: [...args, signature] });
console.log('tx:', hash, 'waiting');
const rc = await pub.waitForTransactionReceipt({ hash, timeout: 120000 });
console.log('status:', rc.status);
console.log('DW pUSD now:', formatUnits(await pub.readContract({ address: PUSD, abi: erc20Abi, functionName: 'balanceOf', args: [DW] }), 6));