Skip to content

Commit

Permalink
add transfer coin
Browse files Browse the repository at this point in the history
add transfer nft
nft-detail-page show data
  • Loading branch information
Yii committed Apr 21, 2022
1 parent 3e58bf4 commit 31ccdc2
Show file tree
Hide file tree
Showing 12 changed files with 377 additions and 220 deletions.
12 changes: 7 additions & 5 deletions lib/core/provider/shared_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ Provider<MetamaskWalletConnectHelper> metamaskWalletConnectHelperProvider = Prov
);

/// 已連結的錢包資訊
final StateNotifierProvider<WalletConnectedNotifier, List<WalletInfo>> walletConnectedProvider =
StateNotifierProvider<WalletConnectedNotifier, List<WalletInfo>>((ref) {
final walletConnectedProvider = StateNotifierProvider<WalletConnectedNotifier, List<WalletInfo>>((ref) {
final Web3Client web3client = ref.read(web3ClientProvider);
return WalletConnectedNotifier(web3client: web3client);
});
Expand Down Expand Up @@ -119,7 +118,7 @@ class LoadCoinDataNotifier extends StateNotifier<LoadCoinState> {
}

// 更新已連結的錢包資料、UI
walletConnectedNotifier.state = walletInfoList;
walletConnectedNotifier.state = [...walletInfoList];
} catch (e) {
state = const LoadCoinState.error(msg: 'loadCoinData() - error');
}
Expand Down Expand Up @@ -229,8 +228,11 @@ Provider<List<Stream_chicken_2>> nftContractListProvider = Provider<List<Stream_
final List<Stream_chicken_2> result = [];
for (String contractAddress in contractAddressList) {
final EthereumAddress ethereumAddress = EthereumAddress.fromHex(contractAddress);
Stream_chicken_2 contract =
Stream_chicken_2(address: ethereumAddress, client: web3client, chainId: Constant.rinkebyChainId);
Stream_chicken_2 contract = Stream_chicken_2(
address: ethereumAddress,
client: web3client,
chainId: Constant.rinkebyChainId,
);
result.add(contract);
}

Expand Down
81 changes: 71 additions & 10 deletions lib/core/util/web3/wallet_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ import 'dart:io';

import 'package:decimal/decimal.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:nft_wallet/core/util/web3/deeplink_util.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:web3dart/web3dart.dart';

import '../../../pages/begin/data/models/crypto_wallet_link.dart';
import '../../../pages/begin/data/models/nft_info.dart';
import '../../../pages/begin/data/models/token_info.dart';
import '../../../pages/begin/data/models/wallet_info.dart';
Expand All @@ -17,6 +14,7 @@ import '../theme.dart';
import 'WalletConnectEthereumCredentials.dart';
import 'abi/erc20.g.dart';
import 'abi/stream_chicken_2.g.dart';
import 'deeplink_util.dart';
import 'eth_conversions.dart';
import 'metamask_wallet_connect_helper.dart';

Expand All @@ -40,6 +38,12 @@ class WalletHelper {
return doubleAmount;
}

Future<EtherAmount> getGasPrice() async {
final Web3Client web3client = ref.read(web3ClientProvider);
final EtherAmount gasPrice = await web3client.getGasPrice();
return gasPrice;
}

Future<List<TokenInfo>> getCoinTokenData({required final String walletAddress}) async {
double etherAmount = await getEtherAmount(walletAddress: walletAddress);
etherAmount = Decimal.parse(etherAmount.toString()).toDouble();
Expand All @@ -57,7 +61,9 @@ class WalletHelper {
final List<Erc20> erc20ContractList = ref.read(coinContractListProvider);
for (Erc20 contract in erc20ContractList) {
final String coinName = await contract.name();
double coinAmount = (await contract.balanceOf(EthereumAddress.fromHex(walletAddress))).toDecimal().toDouble();
BigInt balance = await contract.balanceOf(EthereumAddress.fromHex(walletAddress));
// 轉為正常單位
double coinAmount = EtherAmount.fromUnitAndValue(EtherUnit.wei, balance).getValueInUnit(EtherUnit.ether);
coinAmount = Decimal.parse(coinAmount.toString()).toDouble();

final TokenInfo tokenInfo = TokenInfo(
Expand Down Expand Up @@ -138,6 +144,7 @@ class WalletHelper {
name: collectionName,
tokenName: collectionName,
nftInfoList: nftInfoList,
contract: contract,
);
return collection;
}
Expand All @@ -156,6 +163,7 @@ class WalletHelper {
throw Web3Exception(msg: '錢包有問題,無法進行轉帳');
}

// 錢包位址
late EthereumAddress fromEthereumAddress;
late EthereumAddress toEthereumAddress;
try {
Expand All @@ -168,7 +176,7 @@ class WalletHelper {
BigInt weiBiAmount = EthConversions.ethToWeiBi(amount);

try {
if (tokenInfo == null) {
if (tokenInfo == null || tokenInfo.isEther) {
// 以太幣
if (walletInfo.isFromMetamask) {
// 連結錢包轉帳
Expand All @@ -185,9 +193,10 @@ class WalletHelper {
// 其他貨幣
Erc20? erc20Contract = tokenInfo.contract;
if (erc20Contract != null) {
// 證書,根據不同的匯入方式取得
late Credentials credentials;
if (walletInfo.isFromMetamask) {
// Metamask
// 開啟Metamask app
await DeeplinkUtil.openMetamask();

final MetamaskWalletConnectHelper helper = ref.read(metamaskWalletConnectHelperProvider);
Expand All @@ -197,22 +206,24 @@ class WalletHelper {
credentials = getEthPrivateKeyCredentials(privateKey: walletInfo.privateKey);
}

// 進行交易
EtherAmount gasPrice = await getGasPrice();
transactionHash = await erc20Contract.transfer(
toEthereumAddress,
weiBiAmount,
credentials: credentials,
transaction: Transaction(
from: fromEthereumAddress,
to: toEthereumAddress,
value: EtherAmount.zero(),
gasPrice: gasPrice,
),
);
} else {
throw Web3Exception(msg: '貨幣合約有問題,無法進行轉帳');
}
}
} catch (e) {
throw Web3Exception(msg: '轉帳有問題,請稍候再試試');
throw Web3Exception(msg: '轉帳有問題,請稍候再試');
}

return transactionHash;
Expand All @@ -224,9 +235,13 @@ class WalletHelper {
required BigInt amount,
}) async {
final MetamaskWalletConnectHelper helper = ref.read(metamaskWalletConnectHelperProvider);
WalletConnectEthereumCredentials credentials = helper.getEthereumCredentials();
final WalletConnectEthereumCredentials credentials = helper.getEthereumCredentials();
final Web3Client web3client = ref.read(web3ClientProvider);

// 開啟Metamask app
await DeeplinkUtil.openMetamask();

// 進行交易
Transaction transaction = Transaction(
from: fromEthereumAddress,
to: toEthereumAddress,
Expand All @@ -235,9 +250,55 @@ class WalletHelper {
amount,
),
);
final String transactionHash = await web3client.sendTransaction(credentials, transaction);

return transactionHash;
}

Future<String> transferNFT({
required Stream_chicken_2 contract,
required String toAddress,
required int nftTokenId,
}) async {
final WalletInfo? walletInfo = ref.read(currentWalletProvider);
if (walletInfo == null) {
throw Web3Exception(msg: '錢包有問題,無法進行轉帳');
}

// 錢包位址
late EthereumAddress fromEthereumAddress;
late EthereumAddress toEthereumAddress;
try {
fromEthereumAddress = EthereumAddress.fromHex(walletInfo.address);
toEthereumAddress = EthereumAddress.fromHex(toAddress);
} catch (e) {
throw Web3Exception(msg: '錢包的地址格式有問題,無法進行轉帳');
}

// 開啟Metamask app
await DeeplinkUtil.openMetamask();
final String transactionHash = await web3client.sendTransaction(credentials, transaction);

// 取得錢包證書
final MetamaskWalletConnectHelper helper = ref.read(metamaskWalletConnectHelperProvider);
final WalletConnectEthereumCredentials credentials = helper.getEthereumCredentials();

// 進行交易
String transactionHash = '';
try {
final Transaction transaction = Transaction(
from: fromEthereumAddress,
to: toEthereumAddress,
);
transactionHash = await contract.safeTransferFrom(
fromEthereumAddress,
toEthereumAddress,
BigInt.from(nftTokenId),
credentials: credentials,
transaction: transaction,
);
} catch (e) {
throw Web3Exception(msg: 'NFT轉移有問題,請稍候再試');
}

return transactionHash;
}
Expand Down
8 changes: 8 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fluttertoast/fluttertoast.dart';

import 'core/initialization.dart';
import 'pages/begin/presentation/pages/begin_page.dart';
Expand Down Expand Up @@ -31,3 +32,10 @@ class MyApp extends StatelessWidget {
);
}
}

void showToast({required String msg}) {
Fluttertoast.showToast(
msg: msg,
gravity: ToastGravity.CENTER,
);
}
4 changes: 4 additions & 0 deletions lib/pages/begin/data/models/nft_info.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import 'package:flutter/material.dart';

import '../../../../core/util/web3/abi/stream_chicken_2.g.dart';

class NFTCollection {
final List<NFTInfo> nftInfoList;
final String name;
final String tokenName;
final Stream_chicken_2 contract;

NFTCollection({
required this.nftInfoList,
required this.name,
required this.tokenName,
required this.contract,
});
}

Expand Down
2 changes: 1 addition & 1 deletion lib/pages/begin/data/states/transfer_nft_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ part 'transfer_nft_state.freezed.dart';
class TransferNFTState with _$TransferNFTState {
const factory TransferNFTState.init() = TransferNFTInitial;
const factory TransferNFTState.loading() = TransferNFTLoading;
const factory TransferNFTState.data({required WalletInfo walletInfo}) = TransferNFTData;
const factory TransferNFTState.data() = TransferNFTData;
const factory TransferNFTState.error({required String msg}) = TransferNFTError;
}
Loading

0 comments on commit 31ccdc2

Please sign in to comment.