Closed lukassgramm closed 6 months ago
To be reviewed Error where there are @JS:
The '@JS' annotation
of 'dart:js_interop' can only be used for static interop, through extension types or '@staticInterop' classes.
Try making this class an extension type or marking it as '@staticInterop'.
ViewPort class {
Removing @anonymous
should work and you should add in the @JS the name of what you use in the .js file
@lukassgramm have you finished yet?
I'm not finished. There is no way to test if it works. Every time I have to run flutter build web --wasm. I didn't have time to finish. I can't test it locally the package with an existing flutter project, I dont know
It's OK, let me continue doing it
@hnvn If you want to continue, go ahead but review what I changed, I am having problems in other packages with this migration as well
It's tough than I thought 😬
Hmm, I need to rewrite all of JS interop codes, so it makes me consider that it is time to switch to different JS library
If it helps you @hnvn these are the changes I made to a project where you connect the wallet with Solana. Leaving out the Solana talk you can see what I changed.
JS example:
const init = () => {
const Web3Modal = window.Web3Modal.default;
const WalletConnectProvider = window.WalletConnectProvider.default;
const ethers = window.ethers;
let web3Modal;
let provider;
const providerOptions = {
walletconnect: {
package: WalletConnectProvider,
},
};
async function fetchAccountData() {
const wallet = new ethers.providers.Web3Provider(provider);
const network = await wallet.getNetwork();
const signer = wallet.getSigner();
const selectedAccount = await signer.getAddress();
const balance = await signer.getBalance();
const res = {
"address": selectedAccount
}
return JSON.stringify(res);
}
async function refreshAccountData() {
await fetchAccountData();
}
const onConnect = async () => {
try {
provider = await web3Modal.connect();
} catch (e) {
console.log("Could not get a wallet connection", e);
return;
}
provider.on("accountsChanged", (accounts) => {
fetchAccountData();
});
provider.on("chainChanged", (chainId) => {
fetchAccountData();
});
provider.on("networkChanged", (networkId) => {
fetchAccountData();
});
await refreshAccountData();
}
window._onConnect = onConnect;
window._fetchAccountData = fetchAccountData;
window._refreshAccountData = refreshAccountData;
}
window.onload = () => {
init();
}
Flutter with js package:
@JS()
library js_interop;
import 'package:js/js.dart';
import 'dart:js_util';
@JS()
external _onConnect();
@JS()
external _fetchAccountData();
class WalletInteropService {
onConnect() async {
final promise = await _onConnect();
final data = await promiseToFuture(promise);
}
fetchAccountData() async {
final promise = await _fetchAccountData();
final data = await promiseToFuture(promise);
return data;
}
}
Migration
Flutter with dart:js_interop
I made a wrap of the class that was previously in dart and put it in the javascript file, so the code would be more organized
import 'dart:js_interop';
@JS('window.WalletManager.onConnect')
external JSPromise onConnect();
@JS('window.WalletManager.fetchAccountData')
external JSPromise<JSString> fetchAccountData();
To use these functions on flutter I had to port all types from js to dart:
final res = await onConnect().toDart;
final fetch_account = await fetchAccountData().toDart;
setState(() {
wallet = jsonDecode(fetch_account.toDart);
// wallet['address']
});
new js file (I had also managed to implement the stream):
const init = () => {
const Web3Modal = window.Web3Modal.default;
const WalletConnectProvider = window.WalletConnectProvider.default;
const ethers = window.ethers;
let web3Modal;
let provider;
const providerOptions = {
walletconnect: {
package: WalletConnectProvider,
},
};
window.WalletManager = {
onConnect: async () => {
try {
provider = await web3Modal.connect();
const wallet = new ethers.providers.Web3Provider(provider);
const signer = wallet.getSigner();
provider.on("accountsChanged", (accounts) => {
console.log("accountsChanged", accounts);
window.postMessage(JSON.stringify({ type: 'accountsChanged', address: accounts[0] }), "*");
});
provider.on("chainChanged", (chainId) => {
window.postMessage(JSON.stringify({ type: 'chainChanged', chainId: chainId }), "*");
});
provider.on("networkChanged", (networkId) => {
window.postMessage(JSON.stringify({ type: 'networkChanged', networkId: networkId }), "*");
});
} catch (e) {
console.log("Could not get a wallet connection", e);
window.postMessage(JSON.stringify({ type: 'error', message: e.message }), "*");
}
},
fetchAccountData: async () => {
const wallet = new ethers.providers.Web3Provider(provider);
const network = await wallet.getNetwork();
const signer = wallet.getSigner();
const selectedAccount = await signer.getAddress();
const balance = await signer.getBalance();
const res = {
"address": selectedAccount,
"balance": balance.toString()
};
return JSON.stringify(res);
},
refreshAccountData: async () => {
return await WalletManager.fetchAccountData();
}
};
}
window.onload = init;
This is listening to the stream in dart if it helps you:
import 'package:web/web.dart' as web;
//...
void startListening() {
web.window.onMessage.listen((event) {
try {
if (event.data == null) return;
if (event.data.toString() == "[object Object]") return;
final data = json.decode(event.data.toString());
if (data['type'] == "accountsChanged") {
setState(() {
wallet['address'] = data['address'];
print("Wallet Address: >${wallet['address']}<");
});
} else{
print("Data: $data");
}
} catch (e) {
print("Errore Listen: $e");
}
});
}
With flutter 3.22 it is possible to build with
--wasm
. Also, many packages conflict with older versions of js. Therefore I created a fork that migrates js to interop_js and dart:html to web. It seems to workLinks: