Closed david-dyn closed 10 months ago
will follow up
Hello! Tokens are smart contracts so in order to do what you are asking for you should leverage the transfer/transferFrom functions from Privateum smart contract https://bscscan.com/address/0xb10be3f4c7e1f870d86ed6cfd412fed6615feb6f#writeContract
As per how to interact with smart contracts, there's no direct way on our SDK but you can do it through web3dart
package, which is a dependency of our SDK.
Here it is an example directly from web3dart
repo https://github.com/xclud/web3dart/blob/10151b108fde49dfa7f4f1a5452e38837639df5f/example/contracts.dart
Here it is an example from Celo academy https://celo.academy/t/interact-with-celo-blockchain-using-web3dart/183
And here it is a really simple example on how to read from a Contract using web3dart
inside of our Web3Modal package https://docs.walletconnect.com/web3modal/flutter/actions#how-to-read-a-contract
I hope this helps for now. We are working on an more user friendly interaction with contracts from our own SDKs!
Thank you for your response and solution that you suggested., But the solution uses private key, it can cause security issues.
How can we avoid using private key? Thanks in advance.
Hello @david-dyn! As of today, the only way to interact with a Smart Contract is through web3dart, which indeed uses private key. We will start soon to work on our own way to interact with Smart Contract without relying on web3dart.
In the meantime you can refer to this Bob's answer here as well https://github.com/WalletConnect/WalletConnectFlutterV2/issues/219#issuecomment-1805780710
Hi, I'll just leave it here
static Future<dynamic> transfer({ required W3MService w3mService, required EthereumAddress contractAddress, required String tokenName, required EthereumAddress to, required BigInt amount, }) async { final ethClient = Web3Client( W3MChainPresets.chains[w3mService.session?.chainId]!.rpcUrl, http.Client(), ); final contract = await ContractDetails.getContract(address: contractAddress, name: tokenName); final transfer = contract.function('transfer'); Credentials credentials = WalletConnectEip155Credentials( signEngine: w3mService.web3App!.signEngine, sessionTopic: w3mService.session!.topic!, chainId: w3mService.selectedChain!.namespace, credentialAddress: EthereumAddress.fromHex(w3mService.session!.address!)); final transaction = Transaction.callContract( contract: contract, function: transfer, parameters: [ to, amount, ], ); final result = ethClient.sendTransaction( credentials, transaction, chainId: int.parse(w3mService.session!.chainId) ); w3mService.launchConnectedWallet(); return result; }
We were helped by Bob's https://gitlab.com/graflr/flutter_web3_demo/-/blob/main/lib/model/wallet_connect_eip155_credential.dart?ref_type=heads
So sorry, but why I can't user WalletConnectEip155Credentials? Can I know what your package is?
I was integrated WalletConnectEip155Credentials in wallet connect example project, and it worked perfectly, web3dart package.
I tried, but it does not direct me to metamask with w3mService.launchConnectedWallet();
I was integrated WalletConnectEip155Credentials in wallet connect example project, and it worked perfectly, web3dart package.
Before transaction you need to connect wallet to your dApp, you can check example project.
I don't see the comment quoted by @Mash-Woo anymore, wasn't it good?
I was delete it, tomorrow I will refactor it, that everyone can understand it 🙃
Before transaction you need to connect the wallet to your dApp, you can check example project.
Thank you. Now, I fixed a bit and it worked with my code, but do you know how to let user automatically change the chain to the chain that deployed the contract. My contract is on Arbitrum but when I click send transaction it often direct user to Ethereum chain
Hello @david-dyn! As of today, the only way to interact with a Smart Contract is through web3dart, which indeed uses private key. We will start soon to work on our own way to interact with Smart Contract without relying on web3dart.
In the meantime you can refer to this Bob's answer here as well #219 (comment)
Hi @quetool , I tried many different ways, but if I use web3dart to send transactions, how can I get user's private key with web3modal, I am seeing that I can't get the user's private key if they use a decentralized wallet such as Metamask
class CustomCredentialsSender extends CustomTransactionSender {
CustomCredentialsSender({
required this.signingEngine,
required this.sessionTopic,
required this.chainId,
required this.credentialsAddress,
});
final ISignEngine signingEngine;
final String sessionTopic;
final String chainId;
final EthereumAddress credentialsAddress;
@override
EthereumAddress get address => credentialsAddress;
@override
Future<String> sendTransaction(Transaction transaction) async {
if (kDebugMode) {
print(
'CustomCredentialsSender: sendTransaction - transaction: ${transaction.prettyPrint}');
}
if (!signingEngine.getActiveSessions().keys.contains(sessionTopic)) {
if (kDebugMode) {
print(
'sendTransaction - called with invalid sessionTopic: $sessionTopic');
}
return 'Internal Error - sendTransaction - called with invalid sessionTopic';
}
SessionRequestParams sessionRequestParams = SessionRequestParams(
method: 'eth_sendTransaction',
params: [
{
'from': transaction.from?.hex ?? credentialsAddress.hex,
'to': transaction.to?.hex,
'data':
(transaction.data != null) ? bytesToHex(transaction.data!) : null,
if (transaction.value != null)
'value':
'0x${transaction.value?.getInWei.toRadixString(16) ?? '0'}',
if (transaction.maxGas != null)
'gas': '0x${transaction.maxGas?.toRadixString(16)}',
if (transaction.gasPrice != null)
'gasPrice': '0x${transaction.gasPrice?.getInWei.toRadixString(16)}',
if (transaction.nonce != null) 'nonce': transaction.nonce,
}
],
);
if (kDebugMode) {
print(
'CustomCredentialsSender: sendTransaction - blockchain $chainId, sessionRequestParams: ${sessionRequestParams.toJson()}');
}
final hash = await signingEngine.request(
topic: sessionTopic,
chainId: chainId,
request: sessionRequestParams,
);
return hash;
}
@override
Future<EthereumAddress> extractAddress() {
// TODO: implement extractAddress
throw UnimplementedError();
}
@override
Future<MsgSignature> signToSignature(Uint8List payload,
{int? chainId, bool isEIP1559 = false}) {
// TODO: implement signToSignature
throw UnimplementedError();
}
@override
MsgSignature signToEcSignature(Uint8List payload,
{int? chainId, bool isEIP1559 = false}) {
// TODO: implement signToEcSignature
throw UnimplementedError();
}
}
You can use this custom credentials class instead of using private key, you need to create this class object in your transfer function like this:
Credentials credentials = CustomCredentialsSender(
signingEngine: w3mService.web3App!.signEngine,
sessionTopic: w3mService.session!.topic!,
chainId: w3mService.selectedChain!.namespace,
credentialsAddress: EthereumAddress.fromHex(w3mService.session!.address!),
);
After it you can use this credentials in your sendTransaction method.
Credentials credentials = CustomCredentialsSender( signEngine: w3mService.web3App!.signEngine, sessionTopic: w3mService.session!.topic!, chainId: w3mService.selectedChain!.namespace, credentialAddress: EthereumAddress.fromHex(w3mService.session!.address!));
Thank you, I tested it, and it can be sent. However, instead of sending my token according to my contract, it sends Eth. And besides that, if the user rejects it, it will cause bugs. Exception has occurred. _$JsonRpcErrorImpl (JsonRpcError(code: 5000, message: User rejected the transaction))
Are you use contract abi, and your custom token contract address? Can you share your transfer method code here?
Are you use contract abi and your custom token contract address? Can you share your transfer method code here?
Yes, I tried to use contract details like you, but it does not work for me, so now I am using this
final scAddress = EthereumAddress.fromHex(dotenv.env['WEB3_SC_ADDRESS']!);
Future<void> transferWalletConnect() async {
String abi = await rootBundle.loadString('backend/contract/namecontract.abi.json');
final contract =
DeployedContract(ContractAbi.fromJson(abi, 'nameToken'), scAddress);
final transfer = contract.function('safeTransferFromFee'); //function from the contract
log('Check contract ${contract.address}');
Credentials credentials = CustomCredentialsSender(
signEngine: w3mService.web3App!.signEngine,
sessionTopic: w3mService.session!.topic!,
chainId: w3mService.selectedChain!.namespace,
credentialAddress:
EthereumAddress.fromHex(w3mService.address!));
final transaction = Transaction.callContract(
contract: contract,
function: transfer,
parameters: [
EthereumAddress.fromHex('$myaddress'),
EthereumAddress.fromHex('$receiveraddress'),
BigInt.parse(authProvider.userData!.profile!.mintId!.toString()),
BigInt.one,
Uint8List.fromList([])
]);
log('Check credentials $credentials');
log('Check transaction $transaction');
final result = ethClient.sendTransaction(credentials, transaction,
chainId: int.parse(w3mService.selectedChain!.chainId));
w3mService.launchConnectedWallet();
w3mService.addListener(() {
result;
});
w3mService.notifyListeners();
}
if your abi is json, use
final contract =
DeployedContract(ContractAbi.fromJson(jsonEncode(abi), 'nameToken'), scAddress);
And try to use w3mService.session!.chainId instead of w3mService.selectedChain!.chainId
if these steps don't help you, please share your contract address of token I will try reproduce it.
if your abi is json, use
final contract = DeployedContract(ContractAbi.fromJson(jsonEncode(abi), 'nameToken'), scAddress);
And try to use w3mService.session!.chainId instead of w3mService.selectedChain!.chainId
if these steps don't help you, please share your contract address of token I will try reproduce it.
Somehow my package only can use w3mService.selectedChain!.chainId or maybe I will set a String such as '42161' the chain id of Arbitrum
if your abi is json, use
final contract = DeployedContract(ContractAbi.fromJson(jsonEncode(abi), 'nameToken'), scAddress);
And try to use w3mService.session!.chainId instead of w3mService.selectedChain!.chainId if these steps don't help you, please share your contract address of token I will try reproduce it.
Somehow my package only can use w3mService.selectedChain!.chainId or maybe I will set a String such as '42161' the chain id of Arbitrum
Where is your ethClient init? And can you share rpcUrl that you use?
if your abi is json, use
final contract = DeployedContract(ContractAbi.fromJson(jsonEncode(abi), 'nameToken'), scAddress);
And try to use w3mService.session!.chainId instead of w3mService.selectedChain!.chainId if these steps don't help you, please share your contract address of token I will try reproduce it.
Somehow my package only can use w3mService.selectedChain!.chainId or maybe I will set a String such as '42161' the chain id of Arbitrum
Where is your ethClient init? And can you share rpcUrl that you use?
I put it in main, my rpcUrl, I am facing this Error
Exception has occurred. _$WalletConnectErrorImpl (WalletConnectError(code: 5100, message: Unsupported chains. The chain eip155:42161 is not supported, data: null))
if your abi is json, use
final contract = DeployedContract(ContractAbi.fromJson(jsonEncode(abi), 'nameToken'), scAddress);
And try to use w3mService.session!.chainId instead of w3mService.selectedChain!.chainId if these steps don't help you, please share your contract address of token I will try reproduce it.
Somehow my package only can use w3mService.selectedChain!.chainId or maybe I will set a String such as '42161' the chain id of Arbitrum
Where is your ethClient init? And can you share rpcUrl that you use?
I put it in main, my rpcUrl, I am facing this Error
Exception has occurred. _$WalletConnectErrorImpl (WalletConnectError(code: 5100, message: Unsupported chains. The chain eip155:42161 is not supported, data: null))
Your chain id is 42161, use it instead of eip155:42161
if your abi is json, use
final contract = DeployedContract(ContractAbi.fromJson(jsonEncode(abi), 'nameToken'), scAddress);
And try to use w3mService.session!.chainId instead of w3mService.selectedChain!.chainId if these steps don't help you, please share your contract address of token I will try reproduce it.
Somehow my package only can use w3mService.selectedChain!.chainId or maybe I will set a String such as '42161' the chain id of Arbitrum
Where is your ethClient init? And can you share rpcUrl that you use?
I put it in main, my rpcUrl, I am facing this Error Exception has occurred. _$WalletConnectErrorImpl (WalletConnectError(code: 5100, message: Unsupported chains. The chain eip155:42161 is not supported, data: null))
Your chain id is 42161, use it instead of eip155:42161
I changed but still facing this problem
@Mash-Woo could you share the contract address and your code where you send the transaction?
@Mash-Woo could you share the contract address and your code where you send the transaction?
This is my set-up config
void initializedW3MService() async {
W3MChainPresets.chains.putIfAbsent(
'eip155:${dotenv.get('CHAIN_ID')}',
() => W3MChainInfo(
chainName: 'Arbitrum Sepolia Testnet',
chainId: dotenv.get('CHAIN_ID'),
namespace: 'eip155:${dotenv.get('CHAIN_ID')}',
tokenName: 'ETH',
rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',
blockExplorer: W3MBlockExplorer(
name: 'Arbitrum Sepolia Testnet',
url: 'https://sepolia.arbiscan.io/',
),
),
);
await w3mService.init();
w3mService.notifyListeners();
}
I just want to add this config and use it, it can work on metamask but not on trust wallet
In Metamask, I am facing this #176
I meant a whole reproducible code, including contract Abi, contract address, and everything that could be useful to test. it's pretty difficult otherwise.
Also, is your custom chain (Arbitrum Sepolia) added in your Wallet? If not, are you requesting wallet_addEthereumChain
?
Also, is your custom chain (Arbitrum Sepolia) added in your Wallet? If not, are you requesting
wallet_addEthereumChain
?
I added it to my wallet
I meant a whole reproducible code, including contract Abi, contract address, and everything that could be useful to test. it's pretty difficult otherwise.
Hmm, actually I completed solving this, and now my bug is Exception has occurred. _$WalletConnectErrorImpl (WalletConnectError(code: 5100, message: Unsupported chains. The chain eip155:421614 is not supported, data: null))
It cause when I work with Trust Wallet, except for Metamask
It means Trust wallet does not support that chain. Try a different wallet or a different chain on Trust.
It means Trust wallet does not support that chain. Try a different wallet or a different chain on Trust.
Thank you, I changed to another network and it worked, but sometime, if user rejected transaction, I will meet this problem Exception has occurred. _$JsonRpcErrorImpl (JsonRpcError(code: 5001, message: User disapproved requested methods))
Indeed that means the user rejected the request
Indeed that means the user rejected the request
Would you happen to have any solution, such as if the user rejects the request, it will redirect to my app?
It's up to the wallet to redirect to your dapp. You can't do anything from your dapp to get back to your dapp from the wallet. All you can do is to catch the error and do whatever you need to do.
In any case I just realized you are implementing Web3Modal and this is WalletConnectFlutterV2 repo so please if you have any other issue open a new one in the proper repository. Thanks!
Hello all! Glad to announce that a new beta is out for WalletConnectFlutterV2 with Smart Contract interaction based on the proposed solution from @bobwith2bees. Thank you Bob! And thank you @Rudo-dyn for bringing this to my attention!
For any issue with this beta please follow up on this new thread
In the PR description you will find how to interact with the new functionality, hopefully it's easy enough.
For the time being, if you are willing to try this with Web3Modal (such as your case @Mash-Woo), you'll need to override walletconnect_flutter_v2
dependency as follows:
dependency_overrides:
walletconnect_flutter_v2: ^2.2.0-beta01
And then make your requests leveraging web3app
instance of w3mService
return w3mService.web3App!.requestWriteContract(.....)
// OR
return w3mService.web3App!.requestReadContract(.....)
Bear in mind that this is a beta release and things might slightly change in the near future. Thanks!
Hello
I need to send transaction with currency other then default in network For example Pri in Binance Smart Chain I need to send 0.001 PRI not 0.001 BNB