Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add utility library for easier environment and contract interaction #9

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
94e0c94
Add chain enum and extension for information
y-pakorn Sep 13, 2021
77da3e3
Add makerdao's multicall support
y-pakorn Sep 13, 2021
bc16778
Move ERC20 Contract to utils and add option use to multicall
y-pakorn Sep 13, 2021
ebd4a1d
Add and seperate utils library
y-pakorn Sep 13, 2021
9f3b80a
Add Fragment and ParamType
y-pakorn Sep 13, 2021
3889896
Add encode/decode data from interface function
y-pakorn Sep 13, 2021
d26ed74
Add more MulticallPayload factory constructor
y-pakorn Sep 13, 2021
444664d
Add chain information
y-pakorn Sep 14, 2021
ab88697
docs: Fix dartdoc warning
y-pakorn Sep 14, 2021
0444d57
package: publish 2.2.0-pre.1
y-pakorn Sep 14, 2021
17f8136
Add ERC1155 contract
y-pakorn Sep 14, 2021
56e8549
Add multicall support for contract
y-pakorn Sep 15, 2021
3093c89
feat: add fragment inherited class and refactor
y-pakorn Sep 16, 2021
dead6c6
feat: add interface function related to specific fragment
y-pakorn Sep 16, 2021
90ee453
Merge branch 'main' into utils
y-pakorn Sep 17, 2021
953d559
feat: add ethereum chain extension
y-pakorn Oct 1, 2021
2630e4d
feat: add extension to export
y-pakorn Oct 1, 2021
ea3659d
Merge branch 'main' into utils
y-pakorn Oct 2, 2021
ae4604c
feat: add erc20 multicall function
y-pakorn Oct 3, 2021
d4faa8b
feat: export erc1155
y-pakorn Oct 12, 2021
3165be8
feat: add custom abi constructor and more method
y-pakorn Oct 12, 2021
fa8029f
feat: add erc1155 extension contract
y-pakorn Oct 12, 2021
6132b68
pacakge: merge branch main and publish 2.2.0-pre.4
y-pakorn Oct 12, 2021
df7e8b0
docs: correct removed property
y-pakorn Oct 12, 2021
3a5bb4f
fix: correct function arg and return types
y-pakorn Nov 5, 2021
dfc8ef9
fix: overwrite format function to supress ethers error
y-pakorn Nov 5, 2021
300c756
fix: correct events and functions getter return types
y-pakorn Nov 5, 2021
566f367
package: publish 2.2.0-pre.5
y-pakorn Nov 5, 2021
4b161c7
feat: add js package injection support
y-pakorn Nov 14, 2021
89c080e
package: update package dep
y-pakorn Nov 14, 2021
f5c90bb
fix: correct EthereumException inheritance
y-pakorn Nov 14, 2021
1173f21
fix: append error catching to other method in Signer
y-pakorn Nov 14, 2021
c9b6ee1
package: merge and publish 2.2.0-pre.6
y-pakorn Nov 14, 2021
0f78aff
package: include injector usage to README
y-pakorn Nov 14, 2021
5259f9e
package: merge and publish 2.2.0-pre.7
y-pakorn Feb 7, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.2.0-pre.7

- Pre-release for utils

## 2.1.9

- Add `toList` for list case of argument (#38)
Expand All @@ -23,7 +27,7 @@

## 2.1.3

- Add provider call error catching
- Add provider call error catching
- Fix ethereum error not thrown properly
- Add documentation for getFeeData

Expand Down
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,19 @@ To use Ethers JS and Wallet Connect Provider, we need to include script to JS pa

```html
<!--Ethers-->
<script src="https://cdn.ethers.io/lib/ethers-5.4.umd.min.js" type="application/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/ethers@latest/dist/ethers.umd.min.js" type="application/javascript"></script>
<!--Wallet Connect-->
<script src="https://cdn.jsdelivr.net/npm/@walletconnect/[email protected]/dist/umd/index.min.js" type="application/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/@walletconnect/web3-provider@latest/dist/umd/index.min.js" type="application/javascript"></script>
```

Optinally, use injector by asynchronous calling `inject` or `injectAll` before `runApp`.

```dart
void main() async {
await FlutterWeb3.injectAll();

runApp(MyApp());
}
```

---
Expand Down
80 changes: 75 additions & 5 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
amdjs:
dependency: transitive
description:
name: amdjs
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.6.1"
version: "2.8.1"
boolean_selector:
dependency: transitive
description:
Expand All @@ -28,7 +42,7 @@ packages:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.1"
clock:
dependency: transitive
description:
Expand All @@ -50,6 +64,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
dom_tools:
dependency: transitive
description:
name: dom_tools
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
enum_to_string:
dependency: transitive
description:
name: enum_to_string
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
fake_async:
dependency: transitive
description:
Expand All @@ -73,21 +101,49 @@ packages:
path: ".."
relative: true
source: path
version: "2.0.0-pre.6"
version: "2.2.0-pre.5"
get:
dependency: "direct main"
description:
name: get
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.4"
html_unescape:
dependency: transitive
description:
name: html_unescape
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
intl:
dependency: transitive
description:
name: intl
url: "https://pub.dartlang.org"
source: hosted
version: "0.17.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
json_object_mapper:
dependency: transitive
description:
name: json_object_mapper
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
markdown:
dependency: transitive
description:
name: markdown
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
matcher:
dependency: transitive
description:
Expand All @@ -101,14 +157,21 @@ packages:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
version: "1.7.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
resource_portable:
dependency: transitive
description:
name: resource_portable
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
sky_engine:
dependency: transitive
description: flutter
Expand Down Expand Up @@ -142,6 +205,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
swiss_knife:
dependency: transitive
description:
name: swiss_knife
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.8"
term_glyph:
dependency: transitive
description:
Expand All @@ -155,7 +225,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.0"
version: "0.4.2"
typed_data:
dependency: transitive
description:
Expand Down
1 change: 0 additions & 1 deletion lib/ethers.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export 'src/ethers/constant.dart';
export 'src/ethers/ethers.dart';
export 'src/ethers/exception.dart';
export 'src/ethers/utils.dart';
73 changes: 73 additions & 0 deletions lib/flutter_web3.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,77 @@
import 'package:amdjs/amdjs.dart';

export './ethereum.dart';
export './ethers.dart';
export './src/constant.dart';
export './utils.dart';
export './wallet_connect.dart';

/// Static class for injecting required js module.
class FlutterWeb3 {
/// Inject js module that required by this package by [injectionType]. Optinally [version] can be provided, otherwise `latest` is used.
///
/// ---
///
/// ```dart
/// void main() async {
/// await FlutterWeb3.inject(FlutterWeb3InjectionTypes.ethers);
///
/// runApp(MyApp());
/// }
/// ```
static Future<void> inject(FlutterWeb3InjectionTypes injectionType,
[String version = 'latest']) async {
AMDJS.verbose = false;

await AMDJS.require(
injectionType.module,
jsFullPath: injectionType.path.replaceFirst(r'latest', version),
globalJSVariableName: injectionType.variable,
);
}

/// Inject all js module that required by this package at `latest` version.
///
/// ---
///
/// ```dart
/// void main() async {
/// await FlutterWeb3.injectAll();
///
/// runApp(MyApp());
/// }
/// ```
static Future<void> injectAll() async {
AMDJS.verbose = false;
await Future.wait(FlutterWeb3InjectionTypes.values.map((e) => inject(e)));
}
}

/// Available module to inject, used in [FlutterWeb3.inject].
enum FlutterWeb3InjectionTypes {
ethers,
walletConnect,
}

extension _InjectionInformation on FlutterWeb3InjectionTypes {
static const _info = {
FlutterWeb3InjectionTypes.ethers: {
'module': 'ethers',
'variable': 'ethers',
'path':
'https://cdn.jsdelivr.net/npm/ethers@latest/dist/ethers.umd.min.js'
},
FlutterWeb3InjectionTypes.walletConnect: {
'module': 'WalletConnectProvider',
'variable': 'WalletConnectProvider',
'path':
'https://cdn.jsdelivr.net/npm/@walletconnect/web3-provider@latest/dist/umd/index.min.js'
}
};

String get module => _info[this]!['module']!;

String get variable => _info[this]!['variable']!;

String get path => _info[this]!['path']!;
}
33 changes: 19 additions & 14 deletions lib/src/ethereum/exception.dart
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
class EthereumUnrecognizedChainException implements Exception {
final int chainId;
class EthereumException implements Exception {
final int code;
final String message;
final dynamic data;

EthereumUnrecognizedChainException(this.chainId);
const EthereumException(this.code, this.message, this.data);

@override
String toString() =>
'EthereumUnrecognizedChainException: Chain $chainId is not recognized, please add the chain using `walletAddChain` first';
String toString() => 'EthereumException: $code $message';
}

class EthereumUserRejected implements Exception {
class EthereumUnrecognizedChainException extends EthereumException {
final int chainId;

const EthereumUnrecognizedChainException(this.chainId,
[int code = 4902, String message = ''])
: super(code, message, null);

@override
String toString() => 'EthereumUserRejected: User rejected the request';
String toString() =>
'EthereumUnrecognizedChainException: Chain $chainId is not recognized, please add the chain using `walletAddChain` first';
}

class EthereumException implements Exception {
final int code;
final String message;
final dynamic data;

EthereumException(this.code, this.message, this.data);
class EthereumUserRejected extends EthereumException {
const EthereumUserRejected([int code = 4001, String message = ''])
: super(code, message, null);

@override
String toString() => 'EthereumException: $code $message';
String toString() => 'EthereumUserRejected: User rejected the request';
}
54 changes: 46 additions & 8 deletions lib/src/ethers/contract.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ class Contract extends Interop<_ContractImpl> {
Future<T> call<T>(String method, [List<dynamic> args = const []]) =>
_call<T>(method, args);

/// Returns a new instance of the [Contract] attached to [addressOrName].
///
/// This is useful if there are multiple similar or identical copies of a Contract on the network and you wish to interact with each of them.
Contract attach(String addressOrName) {
assert(EthUtils.isAddress(addressOrName), 'addressOrName must be valid');

return Contract._(impl.attach(addressOrName));
}

///Returns a new instance of the [Contract], but connected to [Provider] or [Signer].
///
///By passing in a [Provider], this will return a downgraded Contract which only has read-only access (i.e. constant calls).
Expand Down Expand Up @@ -115,16 +124,45 @@ class Contract extends Interop<_ContractImpl> {
List listeners(Object event) =>
impl.listeners(event is EventFilter ? event.impl : event);

/// Multicall read-only constant [method] with [args]. `May not` be at the same block.
/// Multicall read-only constant [method] with [args]. Will use multiple https call unless [multicall] is provided.
///
/// If [eagerError] is `true`, returns the error immediately on the first error found.
Future<List<T>> multicall<T>(String method, List<List<dynamic>> args,
[bool eagerError = false]) =>
Future.wait(
Iterable<int>.generate(args.length).map(
(e) => _call<T>(method, args[e]),
),
eagerError: eagerError);
Future<List<T>> multicall<T>(
String method,
List<List<dynamic>> args, [
Multicall? multicall,
bool eagerError = false,
]) async {
if (multicall != null) {
final res = await multicall.aggregate(
args
.map(
(e) => MulticallPayload.fromInterfaceFunction(
address, interface, method, e),
)
.toList(),
);
final decoded = res.returnData
.map((e) => interface.decodeFunctionResult(method, e))
.toList();
switch (T) {
case List:
return decoded as List<T>;
case BigInt:
return decoded.map((e) => BigInt.parse(e[0].toString())).toList()
as List<T>;
default:
return decoded.map((e) => e[0]).toList() as List<T>;
}
} else {
return Future.wait(
Iterable<int>.generate(args.length).map(
(e) => _call<T>(method, args[e]),
),
eagerError: eagerError,
);
}
}

/// Remove a [listener] for the [event]. If no [listener] is provided, all listeners for [event] are removed.
off(dynamic event, [Function? listener]) => callMethod(
Expand Down
Loading