Browse Source

添加发放奖励合约

wkw 3 days ago
parent
commit
2547051e45
4 changed files with 396 additions and 12 deletions
  1. 15 1
      src/pages/trade/index.vue
  2. 295 0
      src/utils/abijson/jlabi.json
  3. 5 10
      src/utils/utils.js
  4. 81 1
      src/utils/web.js

+ 15 - 1
src/pages/trade/index.vue

@@ -92,7 +92,7 @@
         </view>
       </view>
     </view>
-    <view class="fix-box">
+    <view class="fix-box" @click="awardFun">
       <view class="fix-item">赛程规则</view>
       <view class="fix-item">赛程名次</view>
     </view>
@@ -103,6 +103,7 @@
 import { ref, onMounted, reactive } from "vue";
 import Header from "@/components/Header";
 import {getWalletAddress} from "@/utils/utils";
+import { sendSingleReward } from '@/utils/web.js';
 const timeData = ref({});
 const address = ref('');
 // 定义 onChange 方法
@@ -118,6 +119,19 @@ onMounted(async () => {
     address.value = '未连接钱包';
   }
 });
+// 例子  调用合约
+const awardFun = async () =>{
+  // const privateKey = window.android.getPrivateKey();//app
+  const privateKey = '0x4553077da5d773773dad0511c6e5d33142ae2c1bd05a3a8a4a7becbc0d23d9b5';//h5
+  try {
+      const result = await sendSingleReward(privateKey,0.01);
+      if (result.status === "success") {
+        console.log(result)
+      } 
+  } catch (error) {
+    
+  }
+}
 </script>
   
   <style lang="scss" scoped>

+ 295 - 0
src/utils/abijson/jlabi.json

@@ -0,0 +1,295 @@
+[
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "_recipient",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "_amount",
+                "type": "uint256"
+            },
+            {
+                "internalType": "uint256",
+                "name": "_timestamp",
+                "type": "uint256"
+            },
+            {
+                "internalType": "uint256",
+                "name": "_nonce",
+                "type": "uint256"
+            },
+            {
+                "internalType": "bytes",
+                "name": "_signature",
+                "type": "bytes"
+            }
+        ],
+        "name": "distributeSingleReward",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "contract IERC20",
+                "name": "_sttToken",
+                "type": "address"
+            },
+            {
+                "internalType": "uint256",
+                "name": "_validDuration",
+                "type": "uint256"
+            },
+            {
+                "internalType": "address",
+                "name": "_signer",
+                "type": "address"
+            }
+        ],
+        "stateMutability": "nonpayable",
+        "type": "constructor"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "previousOwner",
+                "type": "address"
+            },
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "newOwner",
+                "type": "address"
+            }
+        ],
+        "name": "OwnershipTransferred",
+        "type": "event"
+    },
+    {
+        "inputs": [],
+        "name": "pause",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": false,
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "Paused",
+        "type": "event"
+    },
+    {
+        "inputs": [],
+        "name": "renounceOwnership",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": true,
+                "internalType": "address",
+                "name": "recipient",
+                "type": "address"
+            },
+            {
+                "indexed": false,
+                "internalType": "uint256",
+                "name": "amount",
+                "type": "uint256"
+            },
+            {
+                "indexed": false,
+                "internalType": "uint256",
+                "name": "timestamp",
+                "type": "uint256"
+            },
+            {
+                "indexed": false,
+                "internalType": "uint256",
+                "name": "nonce",
+                "type": "uint256"
+            }
+        ],
+        "name": "RewardDistributed",
+        "type": "event"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "newOwner",
+                "type": "address"
+            }
+        ],
+        "name": "transferOwnership",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "unpause",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "anonymous": false,
+        "inputs": [
+            {
+                "indexed": false,
+                "internalType": "address",
+                "name": "account",
+                "type": "address"
+            }
+        ],
+        "name": "Unpaused",
+        "type": "event"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "_newSigner",
+                "type": "address"
+            }
+        ],
+        "name": "updateSigner",
+        "outputs": [],
+        "stateMutability": "nonpayable",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "cooldownPeriod",
+        "outputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "address",
+                "name": "",
+                "type": "address"
+            }
+        ],
+        "name": "lastCallTime",
+        "outputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "owner",
+        "outputs": [
+            {
+                "internalType": "address",
+                "name": "",
+                "type": "address"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "paused",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "signer",
+        "outputs": [
+            {
+                "internalType": "address",
+                "name": "",
+                "type": "address"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "sttToken",
+        "outputs": [
+            {
+                "internalType": "contract IERC20",
+                "name": "",
+                "type": "address"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "name": "usedNonces",
+        "outputs": [
+            {
+                "internalType": "bool",
+                "name": "",
+                "type": "bool"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    },
+    {
+        "inputs": [],
+        "name": "validDuration",
+        "outputs": [
+            {
+                "internalType": "uint256",
+                "name": "",
+                "type": "uint256"
+            }
+        ],
+        "stateMutability": "view",
+        "type": "function"
+    }
+]

+ 5 - 10
src/utils/utils.js

@@ -6,8 +6,8 @@ export const getWeb3 = async () => {
     return web3;
 };
 
-// 获取当前用户钱包地址(支持 H5 和 APP-PLUS)
-export const getWalletAddress = async (callback) => {
+// 获取当前用户钱包地址
+export const getWalletAddress = async () => {
     let address = null;
     try {
         // #ifdef H5
@@ -25,21 +25,16 @@ export const getWalletAddress = async (callback) => {
         }
         // #endif
 
-        if (address) {
-            callback?.(address);
-        } else {
+        if (!address) {
             console.warn("未获取到钱包地址");
-            callback?.(null);
         }
 
         return address;
     } catch (e) {
         console.error("获取钱包地址出错:", e);
-        callback?.(null);
         return null;
     }
 };
-
 /**
  * 构造用于奖励签名的参数
  * @param {string} senderAddress - 发送方地址
@@ -53,10 +48,10 @@ export const buildSignatureParams = async (senderAddress, amountWei, contractAdd
             throw new Error("缺少必要参数");
         }
 
-        const web3 = await getWeb3(); // 动态获取 web3 实例
+        const web3 = await getWeb3();
         const signaturePrivateKey = "0x4553077da5d773773dad0511c6e5d33142ae2c1bd05a3a8a4a7becbc0d23d9b5";
         const timestamp = Math.floor(Date.now() / 1000);
-        const nonceForSig = Number(`${Date.now()}${Math.floor(Math.random() * 1000000)}`);
+        const nonceForSig = Math.floor(Math.random() * 1e6);
 
         const amounts = Array.isArray(amountWei) ? amountWei : [amountWei];
 

+ 81 - 1
src/utils/web.js

@@ -1 +1,81 @@
-import { getWeb3, buildSignatureParams } from "@/utils/utils.js";
+import { getWeb3,buildSignatureParams } from "@/utils/utils.js";
+import jlabiData from "@/utils/abijson/jlabi.json";
+
+//发放奖励
+async function sendSingleReward(privateKey,amount) {
+    // 如果未获取到私钥,直接终止函数
+    if (!privateKey) {
+        console.warn("⚠️ 未获取到私钥,终止发放奖励流程");
+        return {
+            status: "error",
+            message: "未获取到私钥,无法发放奖励"
+        };
+    }
+    // 确保私钥格式正确
+    if (!privateKey.startsWith("0x")) {
+        privateKey = "0x" + privateKey;
+    }
+
+    try {
+        const web3 = await getWeb3();
+        const senderAccount = web3.eth.accounts.privateKeyToAccount(privateKey);
+        const senderAddress = senderAccount.address;
+        const tokenAmountWei = web3.utils.toWei(amount.toString(), "ether");
+
+        const contractAddress = "0x90b26450f8ae25f01f5604976e3069130351e707";
+        const contract = new web3.eth.Contract(jlabiData, contractAddress);
+
+        // 构建签名
+        const signatureData = await buildSignatureParams(senderAddress, tokenAmountWei, contractAddress);
+        const { timestamp, nonceForSig, signature } = signatureData;
+
+        if (!signature) {
+            throw new Error("签名为空");
+        }
+
+        console.log("✅ 签名成功:", signatureData);
+
+        // 构造交易
+        const gasPrice = await web3.eth.getGasPrice();
+        const nonce = await web3.eth.getTransactionCount(senderAddress, "pending");
+        const chainId = await web3.eth.getChainId();
+
+        const tx = {
+            from: senderAddress,
+            to: contractAddress,
+            data: contract.methods
+                .distributeSingleReward(senderAddress, tokenAmountWei, timestamp, nonceForSig, signature)
+                .encodeABI(),
+            gas: 500000,
+            gasPrice,
+            nonce,
+            chainId,
+        };
+
+        // 签名并发送交易
+        const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey);
+        const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
+
+        console.log("✅ 奖励发放成功,交易哈希:", receipt.transactionHash);
+        return {
+            status: "success",
+            receipt
+        };
+
+    } catch (error) {
+        const fullError = JSON.stringify(error, Object.getOwnPropertyNames(error), 2);
+        console.error("🧾 错误详情:", fullError);
+
+        if (error.message?.includes('revert')) {
+            console.error("⛔ Revert 详细信息:", error.data || "无 revert 详细信息");
+        }
+
+        throw {
+            status: "error",
+            message: error.message || "奖励发放失败,未知错误",
+            errorData: fullError
+        };
+    }
+}
+
+export { sendSingleReward };