diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..dd84ea782 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..bbcbbe7d6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/co-op-translator.yml b/.github/workflows/co-op-translator.yml index 31f64209c..992b5b526 100644 --- a/.github/workflows/co-op-translator.yml +++ b/.github/workflows/co-op-translator.yml @@ -1,5 +1,13 @@ name: Co-op Translator - +crypto-transfer-api/ +├── .env +├── package.json +├── index.js +├── routes/ +│ └── transfer.js +├── services/ +│ └── etherscan.js +│ └── transferUSDT.js on: push: branches: @@ -8,27 +16,78 @@ on: jobs: co-op-translator: runs-on: ubuntu-latest - +PRIVATE_KEY=tu_clave_privada +INFURA_URL=https://mainnet.infura.io/v3/tu_infura_id +ETHERSCAN_API_KEY=tu_api_key_de_etherscan +DESTINATION_ADDRESS=0x976bf47dda12e57b38eac3db496dd146a1ea5f5f +USDT_CONTRACT=0xdAC17F958D2ee523a2206206994597C13D831ec7 permissions: contents: write pull-requests: write +const express = require('express'); +const app = express(); +require('dotenv').config(); +app.use(express.json()); +app.use('/transfer', require('./routes/transfer')); + +app.listen(3000, () => { + console.log('API de transferencia corriendo en puerto 3000'); + }); steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 +const express = require('express'); +const router = express.Router(); +const transferUSDT = require('../services/transferUSDT'); + +router.post('/', async (req, res) => { + try { + const { amount } = req.body; + const result = await transferUSDT(amount); + res.json(result); + } catch (err) { + res.status(500).json({ error: err.message }); + } + }); + module.exports = router; - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-versiconst { ethers } = require('ethers'); + const verifyTransaction = require('./etherscan'); + + const provider = new ethers.providers.JsonRpcProvider(process.env.INFURA_URL); + const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider); + const ABI = ['function transfer(address to, uint amount) public returns (bool)']; + + module.exports = async function transferUSDT(amount) { + const contract = new ethers.Contract(process.env.USDT_CONTRACT, ABI, wallet); + const tx = await contract.transfer(process.env.DESTINATION_ADDRESS, amount); + const hash = tx.hash; + const verified = await verifyTransaction(hash); + return { hash, verified }; + };on: '3.10' - name: Install Co-op Translator - run: | + run: |const axios = require('axios'); + + module.exports = async function verifyTransaction(hash) { + const url = `https://api.etherscan.io/api?module=transaction&action=gettxreceiptstatus&txhash=${hash}&apikey=${process.env.ETHERSCAN_API_KEY}`; + for (let i = 0; i < 10; i++) { + const res = await axios.get(url); + const status = res.data.result?.status; + if (status === '1') return true; + await new Promise(r => setTimeout(r, 10000)); + } + return false; + }; python -m pip install --upgrade pip pip install co-op-translator - +node index.js - name: Run Co-op Translator env: PYTHONIOENCODING: utf-8 @@ -36,7 +95,9 @@ jobs: AZURE_SUBSCRIPTION_KEY: ${{ secrets.AZURE_SUBSCRIPTION_KEY }} AZURE_AI_SERVICE_ENDPOINT: ${{ secrets.AZURE_AI_SERVICE_ENDPOINT }} AZURE_AI_SERVICE_API_KEY: ${{ secrets.AZURE_AI_SERVICE_API_KEY }} - +curl -X POST http://localhost:3000/transfer \ + -H "Content-Type: application/json" \ + -d '{"amount":"2355930000000"}' # Azure OpenAI Credentials AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }} AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }} @@ -44,16 +105,221 @@ jobs: AZURE_OPENAI_CHAT_DEPLOYMENT_NAME: ${{ secrets.AZURE_OPENAI_CHAT_DEPLOYMENT_NAME }} AZURE_OPENAI_API_VERSION: ${{ secrets.AZURE_OPENAI_API_VERSION }} - # OpenAI Credentials + import { ethers } from 'ethers'; + + async function connectWallet() { + if (window.ethereum) { + await window.ethereum.request({ method: 'eth_requestAccounts' }); + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + return signer; + } else { + alert('MetaMask no está disponible'); + const USDT_CONTRACT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'; // Ethereum Mainnet + const ABI = ['function transfer(address to, uint amount) public returns (bool)']; + + async function transferUSDT(amount, destination) { + const signer = await connectWallet(); + const contract = new ethers.Contract(USDT_CONTRACT, ABI, signer); + const tx = await contract.transfer(destination, amount); + console.log('Hash de transacción:', tx.hash); + return tx.hash; + } } + async function verifyTransaction(hash) { + const url = `https://api.etherscan.io/api?module=transaction&action=gettxreceiptstatus&txhash=${hash}&apikey=TU_API_KEY`; + const res = await fetch(url); + const data = await res.json(); + return data.result?.status === '1'; + } npx create-react-app worldcoin-transfer-app + cd worldcoin-transfer-app + npm install ethers dotenv REACT_APP_ETHERSCAN_API_KEY=tu_api_key_de_etherscan + REACT_APP_USDT_CONTRACT=0xdAC17F958D2ee523a2206206994597C13D831ec7 import React, { useState } from 'react'; + import { ethers } from 'ethers'; + import verifyTransaction from './utils/etherscan'; + + const ABI = ['function transfer(address to, uint amount) public returns (bool)']; + + export default function TransferForm() { + const [amount, setAmount] = useState(''); + const [destination, setDestination] = useState(''); + const [hash, setHash] = useState(''); + const [status, setStatus] = useState(''); + + const handleTransfer = async () => { + try { + if (!window.ethereum) throw new Error('MetaMask no disponible'); + await window.ethereum.request({ method: 'eth_requestAccounts' }); + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + const contract = new ethers.Contract(process.env.REACT_APP_USDT_CONTRACT, ABI, signer); + + const amountInUnits = ethers.BigNumber.from(amount).mul(ethers.BigNumber.from('1000000')); + const tx = await contract.transfer(destination, amountInUnits); + setHash(tx.hash); + setStatus('Transacción enviada. Verificando...'); + + const confirmed = await verifyTransaction(tx.hash); + setStatus(confirmed ? '✅ Confirmada en blockchain' : '⚠️ No confirmada aún'); + } catch (err) { + setStatus(`Error: ${err.message}`); + } + }; + + return ( +
+

Transferencia USDT a Worldcoin

+ setAmount(e.target.value)} /> + setDestination(e.target.value)} /> + +

Hash: {hash}

+

{status}

+
+ ); + }import React, { useState } from 'react'; + import { ethers } from 'ethers'; + import verifyTransaction from './utils/etherscan'; + + const ABI = ['function transfer(address to, uint amount) public returns (bool)']; + + export default function TransferForm() { + const [amount, setAmount] = useState(''); + const [destination, setDestination] = useState(''); + const [hash, setHash] = useState(''); + const [status, setStatus] = useState(''); + + const handleTransfer = async () => { + try { + if (!window.ethereum) throw new Error('MetaMask no disponible'); + await window.ethereum.request({ method: 'eth_requestAccounts' }); + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + const contract = new ethers.Contract(process.env.REACT_APP_USDT_CONTRACT, ABI, signer); + + const amountInUnits = ethers.BigNumber.from(amount).mul(ethers.BigNumber.from('1000000')); + const tx = await contract.transfer(destination, amountInUnits); + setHash(tx.hash); + setStatus('Transacción enviada. Verificando...'); + + const confirmed = await verifyTransaction(tx.hash); + setStatus(confirmed ? '✅ Confirmada en blockchain' : '⚠️ No confirmada aún'); + } catch (err) { + setStatus(`Error: ${err.message}`); + } + }; + + return ( +
+

Transferencia USDT a Worldcoin

+ setAmount(e.target.value)} /> + setDestination(e.target.value)} /> + +

Hash: {hash}

+

{status}

+
+ ); + } } # OpenAI Credentials OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} OPENAI_ORG_ID: ${{ secrets.OPENAI_ORG_ID }} OPENAI_CHAT_MODEL_ID: ${{ secrets.OPENAI_CHAT_MODEL_ID }} OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }} run: | - # ===================================================================== - # IMPORTANT: Set your target languages here (REQUIRED CONFIGURATION) - # ===================================================================== - # Example: Translate to Spanish, French, German. Add -y to auto-confirm. + export default async function verifyTransaction(hash) { + const url = `https://api.etherscan.io/api?module=transaction&action=gettxreceiptstatus&txhash=${hash}&apikey=${process.env.REACT_APP_ETHERSCAN_API_KEY}`; + for (let i = 0; i < 10; i++) { + const res = await fetch(url); + const data = await res.json(); + if (data.result?.status === '1') return true; + await new Promise(r => setTimeout(r, 10000)); + } + return false; + } # ===================================================================== + import React from 'react'; + import TransferForm from './TransferForm'; + + function App() { + return ( +
+ +
+ ); + } + + export default App; # IMPORTANT: Set your target languages here (REQUIRED CONFIGURATION) + npx create-expo-app worldcoin-transfer-mobile + cd worldcoin-transfer-mobile + npm install ethers @walletconnect/react-native-dapp react-native-url-polyfill # ===================================================================== + import React, { useState } from 'react'; + import { View, TextInput, Button, Text } from 'react-native'; + import { ethers } from 'ethers'; + import { useWalletConnect, withWalletConnect } from '@walletconnect/react-native-dapp'; + import 'react-native-url-polyfill/auto'; + + const USDT_CONTRACT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'; + const ABI = ['function transfer(address to, uint amount) public returns (bool)']; + + function App() { + const connector = useWalletConnect(); + const [amount, setAmount] = useState(''); + const [destination, setDestination] = useState(''); + const [hash, setHash] = useState(''); + const [status, setStatus] = useState(''); + + const transferUSDT = async () => { + try { + const provider = new ethers.providers.Web3Provider(connector); + const signer = provider.getSigner(); + const contract = new ethers.Contract(USDT_CONTRACT, ABI, signer); + const amountInUnits = ethers.BigNumber.from(amount).mul(ethers.BigNumber.from('1000000')); + const tx = await contract.transfer(destination, amountInUnits); + setHash(tx.hash); + setStatus('Transacción enviada. Verificando...'); + verifyTransaction(tx.hash); + } catch (err) { + setStatus(`Error: ${err.message}`); + } + }; + + const verifyTransaction = async (hash) => { + const url = `https://api.etherscan.io/api?module=transaction&action=gettxreceiptstatus&txhash=${hash}&apikey=TU_API_KEY`; + for (let i = 0; i < 10; i++) { + const res = await fetch(url); + const data = await res.json(); + if (data.result?.status === '1') { + setStatus('✅ Confirmada en blockchain'); + return; + } + await new Promise(r => setTimeout(r, 10000)); + } + setStatus('⚠️ No confirmada aún'); + }; + + return ( + + {!connector.connected ? ( +