-
Notifications
You must be signed in to change notification settings - Fork 68
Closed
Description
class WalletConnectServiceV2 extends WalletConnectService {
WalletConnectServiceV2();
late wc.Web3Wallet wcClient;
late Web3Client ethClient;
// final ethClient = Web3Client(
// 'https://mainnet.infura.io/v3/51716d2096df4e73bec298680a51f0c5',
// Client());
late Function(bool) _onConnectionStatus;
late Function(SessionProposal p1) _onSessionProposal;
late Function(String topic) _onSessionDelete;
late Function(Session session) _onSessionSettle;
late Future<String> Function(
String to,
String from,
String amount,
BigInt gasPriceInGwei,
Uint8List data,
int nounce) _onSignTransactionRequest;
late String _privateAddress;
// late String _rpcUrl;
@override
Future<void> approveRequest(String topic, String requestId, String result) {
// TODO: implement approveRequest
throw UnimplementedError();
}
@override
Future<void> approveSession(SessionProposal session, String address) async {
await wcClient.approveSession(
id: int.parse(session.id),
namespaces: session.namespaces.map(
(key, value) => MapEntry(
key,
wc.Namespace(
methods: value.methods,
events: value.events,
accounts: value.chains!,
),
),
),
);
}
@override
Future<void> connect() async {
_onConnectionStatus(true);
}
@override
Future<void> deleteSession(String topic) async {
// await wcClient.core.pairing.disconnect(topic: topic);
await wcClient.disconnectSession(
topic: topic,
reason: const wc.WalletConnectError(
code: -1, message: 'Session deleted', data: ''));
}
@override
Future<void> disconnect() async {}
@override
Future<void> disconnectWallet() async {}
@override
void dispose() {
// TODO: implement dispose
}
@override
Future<List<Session>> getActveSessions() async {
final sessions = wcClient.getActiveSessions();
return sessions.values
.map((e) => Session(
topic: e.pairingTopic,
peer: AppMetadata(
name: e.peer.metadata.name,
url: e.peer.metadata.url,
description: e.peer.metadata.description,
icons: e.peer.metadata.icons),
expiration: DateTime.fromMillisecondsSinceEpoch(e.expiry),
namespaces: e.namespaces.map((key, value) => MapEntry(
key,
SessionNamespace(
accounts: value.accounts,
methods: value.methods,
events: value.events)))))
.toList();
}
@override
Future<void> initWallet(String publicAddress) async {
wcClient = wc.Web3Wallet(
core: wc.Core(
projectId: PROJECT_ID,
logLevel: wc.LogLevel.error,
),
metadata: const wc.PairingMetadata(
name: 'Example Wallet',
description: 'Example Wallet',
url: 'https://walletconnect.com/',
icons: [
'https://github.com/WalletConnect/Web3ModalFlutter/blob/master/assets/png/logo_wc.png'
],
redirect: wc.Redirect(
native: 'myflutterwallet://',
universal: 'https://walletconnect.com',
),
),
);
wcClient.onSessionProposal.subscribe((sessionProposal) {
debugPrint(':: onSessionProposal: $sessionProposal');
final id = sessionProposal!.id.toString();
final metadata = sessionProposal.params.proposer.metadata;
final namespaces = sessionProposal.params.generatedNamespaces;
_onSessionProposal(
SessionProposal(
id: id,
proposer: AppMetadata(
name: metadata.name,
url: metadata.url,
description: metadata.description,
icons: metadata.icons,
),
namespaces: namespaces!.map(
(key, value) => MapEntry(
key,
ProposalNamespace(
methods: value.methods,
events: value.events,
chains: value.accounts,
),
),
),
),
);
});
for (final network in SupportedCovalentChain.supportedNetworks) {
wcClient.registerEventEmitter(
chainId: 'eip155:${network.chainId}',
event: 'accountsChanged',
);
wcClient.registerEventEmitter(
chainId: 'eip155:${network.chainId}',
event: 'chainChanged',
);
wcClient.registerAccount(
chainId: 'eip155:${network.chainId}',
accountAddress: publicAddress,
);
Map<String, dynamic Function(String, dynamic)> methodsHandlers = {
'personal_sign': (String topic, dynamic parameter) {
debugPrint(':: personal_sign: $topic, $parameter');
},
'eth_sign': (String topic, dynamic parameter) {
debugPrint(':: eth_sign: $topic, $parameter');
},
'eth_signTransaction': (String topic, dynamic parameter) async {
debugPrint(':: eth_signTransaction: $topic, $parameter');
final signedMessage = await ethSignTransaction(topic, parameter);
return signedMessage;
},
'eth_signTypedData': (String topic, dynamic parameter) {
debugPrint(':: eth_signTypedData: $topic, $parameter');
},
'eth_sendTransaction': (String topic, dynamic parameter) async {
debugPrint(':: eth_sendTransaction: $topic, $parameter');
final signedMessage = await ethSignTransaction(topic, parameter);
return signedMessage;
// final response = wc.JsonRpcResponse(result: signedMessage, id: 432);
// try {
// await wcClient.respondSessionRequest(
// topic: topic, response: response);
// } catch (e) {
// debugPrint(':: onSessionRequest error: $e');
// print(e);
// }
// return {"jsonrpc": "2.0", "id": 1, "result": signedMessage};
// return signedMessage;
},
// add whatever method/handler you want to support
// 'eth_signTypedData_v4': ethSignTypedDataV4,
};
for (var method in methodsHandlers.keys) {
wcClient.registerRequestHandler(
chainId: 'eip155:${network.chainId}',
method: method,
handler: methodsHandlers[method]!,
);
}
wcClient.registerEventEmitter(
chainId: 'eip155:${network.chainId}',
event: 'chainChanged',
);
}
wcClient.onSessionProposalError.subscribe((args) {
debugPrint(':: onSessionProposalError: $args');
});
wcClient.core.pairing.onPairingInvalid.subscribe((args) {
debugPrint(':: onPairingInvalid: $args');
});
wcClient.core.pairing.onPairingCreate.subscribe((args) {
debugPrint(':: onPairingCreate: $args');
});
wcClient.pairings.onSync.subscribe((args) {
debugPrint(':: onSync: $args');
});
wcClient.onSessionProposalError.subscribe((args) {
debugPrint(':: onSessionProposalError: $args');
});
wcClient.onSessionConnect.subscribe((args) {
debugPrint(':: onSessionConnect: $args');
_onSessionSettle(
Session(
topic: args!.session.pairingTopic,
peer: AppMetadata(
name: args.session.peer.metadata.name,
url: args.session.peer.metadata.url,
description: args.session.peer.metadata.description,
icons: args.session.peer.metadata.icons),
expiration: DateTime.fromMillisecondsSinceEpoch(args.session.expiry),
namespaces: args.session.namespaces.map(
(key, value) => MapEntry(
key,
SessionNamespace(
accounts: value.accounts,
events: value.events,
methods: value.methods,
),
),
),
),
);
});
wcClient.onSessionRequest.subscribe((args) async {
debugPrint(':: onSessionRequest: $args');
// final id = args?.id;
// final topic = args?.topic;
// final params = args?.params;
// final message = params[0]['data'];
// final credentials = EthPrivateKey.fromHex(_privateAddress);
// final String? signedMessage = await ethSignTransaction(topic!, params);
// print(signedMessage);
// final response = {'id': id, 'result': signedMessage, 'jsonrpc': '2.0'};
// final r = wc.JsonRpcResponse.fromJson(response);
// print(r);
// try {
// await wcClient.respondSessionRequest(topic: topic, response: r);
// } catch (e) {
// print(e);
// }
});
wcClient.onAuthRequest.subscribe((args) {
debugPrint(':: onAuthRequest: $args');
});
wcClient.core.relayClient.onRelayClientError
.subscribe((args) => debugPrint(':: onRelayClientError: $args'));
wcClient.core.pairing.onPairingDelete.subscribe((args) {
debugPrint(':: onPairingDelete: $args');
});
wcClient.pairings.onDelete.subscribe((args) {
debugPrint(':: onDelete: $args');
_onSessionDelete(args!.value.topic);
});
await wcClient.init();
}
Future<String?> ethSignTransaction(String topic, dynamic parameters) async {
final Credentials credentials = EthPrivateKey.fromHex(_privateAddress);
EthereumTransaction ethTransaction =
EthereumTransaction.fromJson(parameters[0]);
final gasFee = ethTransaction.gas != null
? BigInt.tryParse(ethTransaction.gas!, radix: 16) ?? BigInt.zero
: BigInt.zero;
final transaction = Transaction(
from: EthereumAddress.fromHex(ethTransaction.from),
to: EthereumAddress.fromHex(ethTransaction.to),
value: ethTransaction.value == null
? null
: EtherAmount.fromBigInt(
EtherUnit.wei,
BigInt.parse(ethTransaction.value!.substring(2), radix: 16),
),
gasPrice: ethTransaction.gas != null
? EtherAmount.fromBigInt(EtherUnit.wei, gasFee)
: null,
maxFeePerGas: EtherAmount.fromBigInt(
EtherUnit.wei, gasFee + gasFee * BigInt.from(10)),
data: (ethTransaction.data != null && ethTransaction.data != '0x')
? Uint8List.fromList(hex.decode(ethTransaction.data!.substring(2)))
: null,
);
try {
final Uint8List sig = await ethClient.signTransaction(
credentials,
transaction,
);
final String signedTx = hex.encode(sig);
// zero hash
// final String zerohash = '0x' + '0' * 64;
// return zerohash;
// Return the signed transaction as a hexadecimal string
return '0x$signedTx';
} catch (e) {
print(e);
return 'Failed';
}
// Sign the transaction
// final tx = await _onSignTransactionRequest(
// ethTransaction.to,
// ethTransaction.from,
// amount.toString(),
// BigInt.two,
// ethTransaction.data != null && ethTransaction.data != '0x'
// ? Uint8List.fromList(hex.decode(ethTransaction.data!.substring(2)))
// : Uint8List(0),
// int.tryParse(ethTransaction.nonce ?? '') ?? 0,
// );
// return tx;
// final transaction = Transaction(
// from: EthereumAddress.fromHex(ethTransaction.from),
// to: EthereumAddress.fromHex(ethTransaction.to),
// value: EtherAmount.fromBigInt(
// EtherUnit.wei,
// BigInt.tryParse(ethTransaction.value) ?? BigInt.zero,
// ),
// gasPrice: ethTransaction.gasPrice != null
// ? EtherAmount.fromBigInt(
// EtherUnit.wei,
// BigInt.tryParse(ethTransaction.gasPrice!) ?? BigInt.zero,
// )
// : null,
// maxFeePerGas: ethTransaction.maxFeePerGas != null
// ? EtherAmount.fromBigInt(
// EtherUnit.wei,
// BigInt.tryParse(ethTransaction.maxFeePerGas!) ?? BigInt.zero,
// )
// : null,
// maxPriorityFeePerGas: ethTransaction.maxPriorityFeePerGas != null
// ? EtherAmount.fromBigInt(
// EtherUnit.wei,
// BigInt.tryParse(ethTransaction.maxPriorityFeePerGas!) ??
// BigInt.zero,
// )
// : null,
// maxGas: int.tryParse(ethTransaction.gasLimit ?? ''),
// nonce: int.tryParse(ethTransaction.nonce ?? ''),
// data: (ethTransaction.data != null && ethTransaction.data != '0x')
// ? Uint8List.fromList(hex.decode(ethTransaction.data!))
// : null,
// );
// try {
// final Uint8List sig = await ethClient.signTransaction(
// credentials,
// transaction,
// );
// // Sign the transaction
// final String signedTx = hex.encode(sig);
// // Return the signed transaction as a hexadecimal string
// return '0x$signedTx';
// } catch (e) {
// print(e);
// return 'Failed';
// }
}
@override
set onConnectionStatus(Function(bool p1) onConnectionStatus) {
_onConnectionStatus = onConnectionStatus;
}
@override
set onEventError(Function(String p1, String p2) onEventError) {
// TODO: implement onEventError
}
@override
set onSessionDelete(Function(String p1) onSessionDelete) {
_onSessionDelete = onSessionDelete;
}
@override
set onSessionProposal(Function(SessionProposal p1) onSessionProposal) {
_onSessionProposal = onSessionProposal;
}
@override
set onSessionRejection(Function(String p1) onSessionRejection) {
// TODO: implement onSessionRejection
}
@override
set onSessionRequest(Function(SessionRequest p1) onSessionRequest) {
// TODO: implement onSessionRequest
}
@override
set onSessionResponse(Function(SessionResponse p1) onSessionResponse) {
// TODO: implement onSessionResponse
}
@override
set onSessionSettle(Function(Session p1) onSessionSettle) {
_onSessionSettle = onSessionSettle;
}
@override
set onSessionUpdate(Function(String p1) onSessionUpdate) {
// TODO: implement onSessionUpdate
}
@override
Future<void> pair(String uri) async {
Uri qrUri = Uri.parse(uri);
final wc.PairingInfo pairing = await wcClient.pair(uri: qrUri);
}
@override
Future<void> refreshToken() {
// TODO: implement refreshToken
throw UnimplementedError();
}
@override
Future<void> rejectRequest(String topic, String requestId) {
// TODO: implement rejectRequest
throw UnimplementedError();
}
@override
Future<void> rejectSession(String topic) {
// TODO: implement rejectSession
throw UnimplementedError();
}
@override
void privateAddress(String privateAddress) {
_privateAddress = privateAddress;
}
@override
set onSignTransactionRequest(
Future<String> Function(String to, String from, String amount,
BigInt gasPriceInGwei, Uint8List data, int nounce)
onSignTransactionRequest) {
_onSignTransactionRequest = onSignTransactionRequest;
}
@override
set rpcUrl(String rpcUrl) {
// _rpcUrl = rpcUrl;
ethClient = Web3Client(rpcUrl, Client());
}
}
class EthUtils {
static String getUtf8Message(String maybeHex) {
if (maybeHex.startsWith('0x')) {
final List<int> decoded = hex.decode(
maybeHex.substring(2),
);
return utf8.decode(decoded);
}
return maybeHex;
}
}
class EthereumTransaction {
final String from;
final String to;
final String? gas;
final String? data;
final String? value;
EthereumTransaction({
required this.from,
required this.to,
this.gas,
this.data,
this.value,
});
factory EthereumTransaction.fromJson(Map<String, dynamic> json) {
return EthereumTransaction(
from: json['from'] as String,
to: json['to'] as String,
gas: json['gas'] as String?,
data: json['data'] as String?,
value: json['value'] as String?,
);
}
}
This is the service I have written.
Wallet connects with D-App successfully, but when I try to swap tokens using uniswap, "eth_sendTransaction" function gets called, where I am signing the transaction. I get a new hash in response of signing it, but after that it fails on uniswap app.
Can you tell me what am I doing wrong here?
Metadata
Metadata
Assignees
Labels
No labels