index3.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <template>
  2. <view class="content">
  3. <view class="content-text">1.连接钱包</view>
  4. <button class="content-button" @click="modal.open()">Open Connect Modal</button>
  5. <button class="content-button" @click="modal.open({ view: 'Networks' })">Open Network Modal</button>
  6. <button class="content-button" @click="disconnect()">断开连接</button>
  7. <view class="content-text">2.获取钱包信息</view>
  8. <view class="content-text2">address:{{ address }}</view>
  9. <view class="content-text2">chainId:{{ chainId }}</view>
  10. <view class="content-text">3.签名</view>
  11. <button class="content-button" @click="sign()">sign message</button>
  12. <view class="content-text">4.查询 Match 余额</view>
  13. <view class="content-text2">MAT: {{balance && formatUnits(balance.value,18)}}</view>
  14. <view class="content-text2">TOX: {{usdtBalance && formatUnits(usdtBalance,18)}}</view>
  15. <view class="content-text">5.转账</view>
  16. <!-- <input v-model="inputValue" @input="fun" type="text" /> -->
  17. <button class="content-button" @click="transfer()">transfer</button>
  18. <view class="content-text">6.查询 授权合约额度</view>
  19. <view class="content-text2"> allowance: {{allowance && formatUnits(allowance,18)}}</view>
  20. <button class="content-button" @click="signLogin()">Login</button>
  21. </view>
  22. </template>
  23. <script>
  24. import {
  25. toRefs,
  26. toRaw,
  27. ref,
  28. defineModel,
  29. reactive
  30. } from 'vue';
  31. import {
  32. arbitrum,
  33. mainnet
  34. } from '@wagmi/core/chains'
  35. import {
  36. createWeb3Modal,
  37. useWeb3Modal,
  38. useWeb3ModalEvents,
  39. useWeb3ModalState,
  40. useWeb3ModalTheme
  41. } from '@web3modal/wagmi/vue'
  42. import {
  43. chains,
  44. projectId,
  45. wagmiConfig
  46. } from "../unit/config.js";
  47. import {
  48. useAccount,
  49. useBalance,
  50. useDisconnect,
  51. useReadContract,
  52. useSignMessage,
  53. useWriteContract
  54. } from "@wagmi/vue";
  55. import ERC20 from '../contract/abi/ERC20.json'
  56. import {
  57. ChainId,
  58. USDT_ADDRESS
  59. } from "@/contract/address";
  60. import {
  61. formatUnits,
  62. parseUnits
  63. } from "viem";
  64. // 3. Create modal
  65. createWeb3Modal({
  66. wagmiConfig,
  67. projectId,
  68. chains,
  69. themeMode: 'light'
  70. })
  71. export default {
  72. setup() {
  73. const {
  74. signMessageAsync
  75. } = useSignMessage()
  76. const {
  77. disconnect
  78. } = useDisconnect()
  79. // 4. Use modal composable 。
  80. // 注意在使用“useWeb3Mode”compositable之前,请调用“createWeb3Model”
  81. const modal = useWeb3Modal()
  82. const {
  83. address,
  84. chainId,
  85. isConnected
  86. } = useAccount()
  87. const {
  88. data: balance
  89. } = useBalance({
  90. address: address?.value
  91. })
  92. const balanceData = balance.value;
  93. if (balanceData) {
  94. console.log("Balance value:", formatUnits(balanceData.value, 18));
  95. console.log("Balance object:", balanceData);
  96. const balanceFormatted = balanceData?.formatted || 'undefined';
  97. const balanceSymbol = balanceData?.symbol || 'undefined';
  98. const balanceValue = formatUnits(balanceData.value, 18);
  99. console.log("Balance formatted:", balanceFormatted);
  100. console.log("Balance symbol:", balanceSymbol);
  101. console.log("Balance value:", balanceValue);
  102. } else {
  103. console.log("Balance data is not available.");
  104. }
  105. //签名
  106. async function sign() {
  107. const signature = await signMessageAsync({
  108. message: `Login request from ${address.value}`//'gm wagmi frens'
  109. })
  110. console.log(signature)
  111. }
  112. //测试签名登录
  113. async function signLogin() {
  114. if (!address) {
  115. await modal.open();
  116. }
  117. console.log("Connected address:", address);
  118. const userAddress = address.value;
  119. console.log("userAddress:", userAddress)
  120. const message = `Login request from ${userAddress}`;
  121. const signature = await signMessageAsync({
  122. message
  123. });
  124. // Send signature and account to backend
  125. // const response = await axios.post('http://192.168.0.113:30001/ms_dev/program/getLoginToken', {
  126. // address: address,
  127. // signature: signature,
  128. // message: message
  129. // });
  130. const params = {
  131. address: userAddress,
  132. signature: signature,
  133. message: message
  134. }
  135. uni.request({
  136. url: "http://127.0.0.1:30001/ms_dev/program/getLoginToken",
  137. data: params,
  138. method: "POST",
  139. header: {
  140. "Content-Type": "application/json",
  141. },
  142. success: function(res) {
  143. if (res.statusCode == 200) {
  144. let data = res.data;
  145. console.log("res:", data);
  146. const token = data.token;
  147. console.log(token)
  148. } else {
  149. console.error("Error:", res)
  150. }
  151. },
  152. fail: function(e) {
  153. console.error("Failed:", e)
  154. }
  155. })
  156. }
  157. // 获取 USDT 余额
  158. const {
  159. data: usdtBalance
  160. } = useReadContract({
  161. abi: ERC20,
  162. address: USDT_ADDRESS[ChainId.MATCH],
  163. functionName: 'balanceOf',
  164. args: [address],
  165. })
  166. // 获取 USDT授权某个合约额度 直接转账transfer不需要授权 调用合约扣除自己代币的需要先授权
  167. // 授权方法 approve 参数 合约地址 数量(一般MaxUint256)具体看 abi erc20
  168. // export const MaxUint256: bigint = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
  169. const {
  170. data: allowance
  171. } = useReadContract({
  172. abi: ERC20,
  173. address: USDT_ADDRESS[ChainId.MATCH],
  174. functionName: 'allowance',
  175. //自己地址 合约地址
  176. args: [address, address],
  177. })
  178. const {
  179. writeContractAsync
  180. } = useWriteContract()
  181. const state = reactive({
  182. inputValue: '',
  183. })
  184. // 输入处理函数
  185. let fun = (event) => {
  186. console.log(event);
  187. state.inputValue = event.target.value;
  188. }
  189. async function transfer() {
  190. //转给谁
  191. const to =
  192. "0xB91ee630d4BaF83bBfc32d99a6536344d63cCA87"; // "0xa5f99C0E7D0C7A35D27b6F8E9881F2c9E32A937D"
  193. //转多少 这里以 1 个 USDT 举例 因为区块链没有小数 USDT 的代币精度是 18 1个 USDT 在区块链上表示为 1*10**18
  194. const value = parseUnits("0.01", 18) //库封装了方法
  195. const res = await writeContractAsync({
  196. abi: ERC20,
  197. address: USDT_ADDRESS[ChainId.MATCH],
  198. functionName: 'transfer',
  199. args: [
  200. to,
  201. value
  202. ],
  203. })
  204. console.log(res)
  205. }
  206. return {
  207. modal,
  208. address,
  209. chainId,
  210. balance,
  211. usdtBalance,
  212. allowance,
  213. formatUnits,
  214. disconnect,
  215. sign,
  216. transfer,
  217. signLogin
  218. }
  219. },
  220. data() {
  221. return {
  222. }
  223. },
  224. methods: {
  225. }
  226. }
  227. </script>
  228. <style>
  229. .content {
  230. display: flex;
  231. flex-direction: column;
  232. align-items: center;
  233. justify-content: center;
  234. background-color: aqua;
  235. }
  236. .content-text {
  237. text-align: left;
  238. width: 400rpx;
  239. height: 60rpx;
  240. font-weight: bold;
  241. margin: 20rpx 0;
  242. }
  243. .content-text2 {
  244. text-align: left;
  245. width: 400rpx;
  246. height: 80rpx;
  247. line-height: 80rpx;
  248. /* border: 1rpx solid red; */
  249. /* word-wrap: break-word; */
  250. /* font-weight: bold; */
  251. }
  252. .content-input {}
  253. .content-button {
  254. /* width: 400rpx; */
  255. /* height: 60rpx; */
  256. margin: 10rpx 0;
  257. }
  258. </style>