@sei-js/create-sei 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +12 -0
- package/README.md +16 -25
- package/biome.json +8 -0
- package/dist/main.js +10 -60
- package/dist/templates/next-template/.eslintrc.json +3 -0
- package/dist/templates/next-template/package.json +30 -0
- package/dist/templates/next-template/src/app/components/Homepage/Examples.tsx +257 -0
- package/dist/templates/next-template/src/app/components/Homepage/Homepage.css +154 -0
- package/dist/templates/{next-wagmi-template → next-template}/src/app/components/Homepage/Homepage.tsx +10 -36
- package/{templates/next-wagmi-template → dist/templates/next-template}/src/app/components/Web3Provider.tsx +29 -28
- package/dist/templates/next-template/src/app/components/index.ts +2 -0
- package/dist/templates/{next-wagmi-template → next-template}/src/app/constants/chain.ts +2 -2
- package/dist/templates/next-template/src/app/constants/index.ts +1 -0
- package/dist/templates/next-template/src/app/index.css +184 -0
- package/dist/templates/next-template/src/app/layout.tsx +21 -0
- package/dist/templates/next-template/src/app/page.tsx +21 -0
- package/dist/templates/next-template/tsconfig.json +26 -0
- package/dist/templates/vite-template/.eslintrc.cjs +11 -0
- package/dist/templates/vite-template/package.json +33 -0
- package/dist/templates/vite-template/src/App.tsx +21 -0
- package/dist/templates/vite-template/src/components/Homepage/Examples.tsx +255 -0
- package/dist/templates/vite-template/src/components/Homepage/Homepage.css +154 -0
- package/dist/templates/vite-template/src/components/Homepage/Homepage.tsx +81 -0
- package/{templates/vite-wagmi-template → dist/templates/vite-template}/src/components/Web3Provider.tsx +29 -28
- package/dist/templates/{vite-wagmi-template → vite-template}/src/constants/chain.ts +1 -1
- package/dist/templates/vite-template/src/constants/index.ts +1 -0
- package/dist/templates/vite-template/src/index.css +183 -0
- package/dist/templates/vite-template/src/main.tsx +12 -0
- package/dist/templates/vite-template/tsconfig.app.json +25 -0
- package/dist/templates/vite-template/tsconfig.json +11 -0
- package/dist/templates/vite-template/tsconfig.node.json +14 -0
- package/dist/templates/vite-template/vite.config.ts +10 -0
- package/package.json +1 -1
- package/src/main.ts +26 -87
- package/templates/next-template/.eslintrc.json +3 -0
- package/templates/next-template/package.json +30 -0
- package/templates/next-template/src/app/components/Homepage/Examples.tsx +257 -0
- package/templates/next-template/src/app/components/Homepage/Homepage.css +154 -0
- package/templates/{next-wagmi-template → next-template}/src/app/components/Homepage/Homepage.tsx +10 -36
- package/{dist/templates/next-wagmi-template → templates/next-template}/src/app/components/Web3Provider.tsx +29 -28
- package/templates/next-template/src/app/components/index.ts +2 -0
- package/templates/{next-wagmi-template → next-template}/src/app/constants/chain.ts +2 -2
- package/templates/next-template/src/app/constants/index.ts +1 -0
- package/templates/next-template/src/app/index.css +184 -0
- package/templates/next-template/src/app/layout.tsx +21 -0
- package/templates/next-template/src/app/page.tsx +21 -0
- package/templates/next-template/tsconfig.json +26 -0
- package/templates/vite-template/.eslintrc.cjs +11 -0
- package/templates/vite-template/package.json +33 -0
- package/templates/vite-template/src/App.tsx +21 -0
- package/templates/vite-template/src/components/Homepage/Examples.tsx +255 -0
- package/templates/vite-template/src/components/Homepage/Homepage.css +154 -0
- package/templates/vite-template/src/components/Homepage/Homepage.tsx +81 -0
- package/{dist/templates/vite-wagmi-template → templates/vite-template}/src/components/Web3Provider.tsx +29 -28
- package/templates/{vite-wagmi-template → vite-template}/src/constants/chain.ts +1 -1
- package/templates/vite-template/src/constants/index.ts +1 -0
- package/templates/vite-template/src/index.css +183 -0
- package/templates/vite-template/src/main.tsx +12 -0
- package/templates/vite-template/tsconfig.app.json +25 -0
- package/templates/vite-template/tsconfig.json +11 -0
- package/templates/vite-template/tsconfig.node.json +14 -0
- package/templates/vite-template/vite.config.ts +10 -0
- package/tsconfig.json +18 -28
- package/dist/templates/next-cosmos-template/.eslintrc.json +0 -3
- package/dist/templates/next-cosmos-template/README.md +0 -60
- package/dist/templates/next-cosmos-template/next.config.mjs +0 -14
- package/dist/templates/next-cosmos-template/package.json +0 -31
- package/dist/templates/next-cosmos-template/public/next.svg +0 -1
- package/dist/templates/next-cosmos-template/public/vercel.svg +0 -1
- package/dist/templates/next-cosmos-template/src/app/components/Homepage/Examples.tsx +0 -177
- package/dist/templates/next-cosmos-template/src/app/components/Homepage/Homepage.css +0 -156
- package/dist/templates/next-cosmos-template/src/app/components/Homepage/Homepage.tsx +0 -110
- package/dist/templates/next-cosmos-template/src/app/components/WalletConnectButton/WalletConnectButton.tsx +0 -26
- package/dist/templates/next-cosmos-template/src/app/components/Web3Provider.tsx +0 -39
- package/dist/templates/next-cosmos-template/src/app/components/index.ts +0 -3
- package/dist/templates/next-cosmos-template/src/app/constants/chain.ts +0 -16
- package/dist/templates/next-cosmos-template/src/app/constants/index.ts +0 -1
- package/dist/templates/next-cosmos-template/src/app/index.css +0 -171
- package/dist/templates/next-cosmos-template/src/app/layout.tsx +0 -21
- package/dist/templates/next-cosmos-template/src/app/page.tsx +0 -17
- package/dist/templates/next-cosmos-template/tsconfig.json +0 -26
- package/dist/templates/next-cosmos-template/yarn.lock +0 -9814
- package/dist/templates/next-wagmi-template/.eslintrc.json +0 -3
- package/dist/templates/next-wagmi-template/package.json +0 -30
- package/dist/templates/next-wagmi-template/src/app/components/Homepage/Examples.tsx +0 -271
- package/dist/templates/next-wagmi-template/src/app/components/Homepage/Homepage.css +0 -156
- package/dist/templates/next-wagmi-template/src/app/components/index.ts +0 -2
- package/dist/templates/next-wagmi-template/src/app/constants/index.ts +0 -1
- package/dist/templates/next-wagmi-template/src/app/index.css +0 -171
- package/dist/templates/next-wagmi-template/src/app/layout.tsx +0 -21
- package/dist/templates/next-wagmi-template/src/app/page.tsx +0 -21
- package/dist/templates/next-wagmi-template/tsconfig.json +0 -26
- package/dist/templates/vite-cosmos-template/.eslintrc.cjs +0 -18
- package/dist/templates/vite-cosmos-template/README.md +0 -72
- package/dist/templates/vite-cosmos-template/index.html +0 -16
- package/dist/templates/vite-cosmos-template/package.json +0 -35
- package/dist/templates/vite-cosmos-template/src/App.tsx +0 -16
- package/dist/templates/vite-cosmos-template/src/components/Homepage/Examples.tsx +0 -177
- package/dist/templates/vite-cosmos-template/src/components/Homepage/Homepage.css +0 -156
- package/dist/templates/vite-cosmos-template/src/components/Homepage/Homepage.tsx +0 -102
- package/dist/templates/vite-cosmos-template/src/components/WalletConnectButton/WalletConnectButton.tsx +0 -26
- package/dist/templates/vite-cosmos-template/src/components/Web3Provider.tsx +0 -45
- package/dist/templates/vite-cosmos-template/src/components/index.ts +0 -4
- package/dist/templates/vite-cosmos-template/src/constants/chain.ts +0 -16
- package/dist/templates/vite-cosmos-template/src/constants/index.ts +0 -1
- package/dist/templates/vite-cosmos-template/src/index.css +0 -171
- package/dist/templates/vite-cosmos-template/src/main.tsx +0 -12
- package/dist/templates/vite-cosmos-template/tsconfig.app.json +0 -27
- package/dist/templates/vite-cosmos-template/tsconfig.json +0 -11
- package/dist/templates/vite-cosmos-template/tsconfig.node.json +0 -14
- package/dist/templates/vite-cosmos-template/vite.config.ts +0 -7
- package/dist/templates/vite-cosmos-template/yarn.lock +0 -9323
- package/dist/templates/vite-wagmi-template/.eslintrc.cjs +0 -18
- package/dist/templates/vite-wagmi-template/package.json +0 -33
- package/dist/templates/vite-wagmi-template/src/App.tsx +0 -22
- package/dist/templates/vite-wagmi-template/src/components/Homepage/Examples.tsx +0 -269
- package/dist/templates/vite-wagmi-template/src/components/Homepage/Homepage.css +0 -156
- package/dist/templates/vite-wagmi-template/src/components/Homepage/Homepage.tsx +0 -106
- package/dist/templates/vite-wagmi-template/src/constants/index.ts +0 -1
- package/dist/templates/vite-wagmi-template/src/index.css +0 -170
- package/dist/templates/vite-wagmi-template/src/main.tsx +0 -12
- package/dist/templates/vite-wagmi-template/tsconfig.app.json +0 -27
- package/dist/templates/vite-wagmi-template/tsconfig.json +0 -11
- package/dist/templates/vite-wagmi-template/tsconfig.node.json +0 -14
- package/dist/templates/vite-wagmi-template/vite.config.ts +0 -10
- package/templates/next-cosmos-template/.eslintrc.json +0 -3
- package/templates/next-cosmos-template/README.md +0 -60
- package/templates/next-cosmos-template/next-env.d.ts +0 -5
- package/templates/next-cosmos-template/next.config.mjs +0 -14
- package/templates/next-cosmos-template/package.json +0 -31
- package/templates/next-cosmos-template/public/next.svg +0 -1
- package/templates/next-cosmos-template/public/sei-logotype.svg +0 -15
- package/templates/next-cosmos-template/public/vercel.svg +0 -1
- package/templates/next-cosmos-template/src/app/components/Homepage/Examples.tsx +0 -177
- package/templates/next-cosmos-template/src/app/components/Homepage/Homepage.css +0 -156
- package/templates/next-cosmos-template/src/app/components/Homepage/Homepage.tsx +0 -110
- package/templates/next-cosmos-template/src/app/components/WalletConnectButton/WalletConnectButton.tsx +0 -26
- package/templates/next-cosmos-template/src/app/components/Web3Provider.tsx +0 -39
- package/templates/next-cosmos-template/src/app/components/index.ts +0 -3
- package/templates/next-cosmos-template/src/app/constants/chain.ts +0 -16
- package/templates/next-cosmos-template/src/app/constants/index.ts +0 -1
- package/templates/next-cosmos-template/src/app/favicon.ico +0 -0
- package/templates/next-cosmos-template/src/app/index.css +0 -171
- package/templates/next-cosmos-template/src/app/layout.tsx +0 -21
- package/templates/next-cosmos-template/src/app/page.tsx +0 -17
- package/templates/next-cosmos-template/tsconfig.json +0 -26
- package/templates/next-cosmos-template/yarn.lock +0 -9814
- package/templates/next-wagmi-template/.eslintrc.json +0 -3
- package/templates/next-wagmi-template/next-env.d.ts +0 -5
- package/templates/next-wagmi-template/package.json +0 -30
- package/templates/next-wagmi-template/public/sei-logotype.svg +0 -15
- package/templates/next-wagmi-template/src/app/components/Homepage/Examples.tsx +0 -271
- package/templates/next-wagmi-template/src/app/components/Homepage/Homepage.css +0 -156
- package/templates/next-wagmi-template/src/app/components/index.ts +0 -2
- package/templates/next-wagmi-template/src/app/constants/index.ts +0 -1
- package/templates/next-wagmi-template/src/app/favicon.ico +0 -0
- package/templates/next-wagmi-template/src/app/index.css +0 -171
- package/templates/next-wagmi-template/src/app/layout.tsx +0 -21
- package/templates/next-wagmi-template/src/app/page.tsx +0 -21
- package/templates/next-wagmi-template/tsconfig.json +0 -26
- package/templates/vite-cosmos-template/.eslintrc.cjs +0 -18
- package/templates/vite-cosmos-template/README.md +0 -72
- package/templates/vite-cosmos-template/favicon.ico +0 -0
- package/templates/vite-cosmos-template/index.html +0 -16
- package/templates/vite-cosmos-template/package.json +0 -35
- package/templates/vite-cosmos-template/public/sei-logotype.svg +0 -15
- package/templates/vite-cosmos-template/src/App.tsx +0 -16
- package/templates/vite-cosmos-template/src/assets/react.svg +0 -1
- package/templates/vite-cosmos-template/src/components/Homepage/Examples.tsx +0 -177
- package/templates/vite-cosmos-template/src/components/Homepage/Homepage.css +0 -156
- package/templates/vite-cosmos-template/src/components/Homepage/Homepage.tsx +0 -102
- package/templates/vite-cosmos-template/src/components/WalletConnectButton/WalletConnectButton.tsx +0 -26
- package/templates/vite-cosmos-template/src/components/Web3Provider.tsx +0 -45
- package/templates/vite-cosmos-template/src/components/index.ts +0 -4
- package/templates/vite-cosmos-template/src/constants/chain.ts +0 -16
- package/templates/vite-cosmos-template/src/constants/index.ts +0 -1
- package/templates/vite-cosmos-template/src/index.css +0 -171
- package/templates/vite-cosmos-template/src/main.tsx +0 -12
- package/templates/vite-cosmos-template/src/vite-env.d.ts +0 -1
- package/templates/vite-cosmos-template/tsconfig.app.json +0 -27
- package/templates/vite-cosmos-template/tsconfig.json +0 -11
- package/templates/vite-cosmos-template/tsconfig.node.json +0 -14
- package/templates/vite-cosmos-template/vite.config.ts +0 -7
- package/templates/vite-cosmos-template/yarn.lock +0 -9323
- package/templates/vite-wagmi-template/.eslintrc.cjs +0 -18
- package/templates/vite-wagmi-template/favicon.ico +0 -0
- package/templates/vite-wagmi-template/package.json +0 -33
- package/templates/vite-wagmi-template/public/sei-logotype.svg +0 -15
- package/templates/vite-wagmi-template/src/App.tsx +0 -22
- package/templates/vite-wagmi-template/src/assets/react.svg +0 -1
- package/templates/vite-wagmi-template/src/components/Homepage/Examples.tsx +0 -269
- package/templates/vite-wagmi-template/src/components/Homepage/Homepage.css +0 -156
- package/templates/vite-wagmi-template/src/components/Homepage/Homepage.tsx +0 -106
- package/templates/vite-wagmi-template/src/constants/index.ts +0 -1
- package/templates/vite-wagmi-template/src/index.css +0 -170
- package/templates/vite-wagmi-template/src/main.tsx +0 -12
- package/templates/vite-wagmi-template/src/vite-env.d.ts +0 -1
- package/templates/vite-wagmi-template/tsconfig.app.json +0 -27
- package/templates/vite-wagmi-template/tsconfig.json +0 -11
- package/templates/vite-wagmi-template/tsconfig.node.json +0 -14
- package/templates/vite-wagmi-template/vite.config.ts +0 -10
- /package/dist/templates/{next-wagmi-template → next-template}/README.md +0 -0
- /package/dist/templates/{next-cosmos-template → next-template}/next-env.d.ts +0 -0
- /package/dist/templates/{next-wagmi-template → next-template}/next.config.mjs +0 -0
- /package/dist/templates/{next-cosmos-template → next-template}/public/sei-logotype.svg +0 -0
- /package/dist/templates/{next-cosmos-template → next-template}/src/app/favicon.ico +0 -0
- /package/dist/templates/{next-wagmi-template → next-template}/yarn.lock +0 -0
- /package/dist/templates/{vite-wagmi-template → vite-template}/README.md +0 -0
- /package/dist/templates/{next-wagmi-template/src/app → vite-template}/favicon.ico +0 -0
- /package/dist/templates/{vite-wagmi-template → vite-template}/index.html +0 -0
- /package/dist/templates/{next-wagmi-template → vite-template}/public/sei-logotype.svg +0 -0
- /package/dist/templates/{vite-cosmos-template → vite-template}/src/assets/react.svg +0 -0
- /package/dist/templates/{vite-cosmos-template → vite-template}/src/vite-env.d.ts +0 -0
- /package/dist/templates/{vite-wagmi-template → vite-template}/yarn.lock +0 -0
- /package/templates/{next-wagmi-template → next-template}/README.md +0 -0
- /package/{dist/templates/next-wagmi-template → templates/next-template}/next-env.d.ts +0 -0
- /package/templates/{next-wagmi-template → next-template}/next.config.mjs +0 -0
- /package/{dist/templates/vite-cosmos-template → templates/next-template}/public/sei-logotype.svg +0 -0
- /package/{dist/templates/vite-cosmos-template → templates/next-template/src/app}/favicon.ico +0 -0
- /package/templates/{next-wagmi-template → next-template}/yarn.lock +0 -0
- /package/templates/{vite-wagmi-template → vite-template}/README.md +0 -0
- /package/{dist/templates/vite-wagmi-template → templates/vite-template}/favicon.ico +0 -0
- /package/templates/{vite-wagmi-template → vite-template}/index.html +0 -0
- /package/{dist/templates/vite-wagmi-template → templates/vite-template}/public/sei-logotype.svg +0 -0
- /package/{dist/templates/vite-wagmi-template → templates/vite-template}/src/assets/react.svg +0 -0
- /package/{dist/templates/vite-wagmi-template → templates/vite-template}/src/vite-env.d.ts +0 -0
- /package/templates/{vite-wagmi-template → vite-template}/yarn.lock +0 -0
package/.yarn/install-state.gz
CHANGED
|
Binary file
|
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,36 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# @sei-js/create-sei
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
5
|
+
[](https://badge.fury.io/js/@sei-js%2Fcreate-sei)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
[](https://sei.io)
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
**Scaffold new Sei applications with pre-configured templates and tooling**
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
Simply run `npx @sei-js/create-sei app` to run the setup wizard and choose the template you want to use.
|
|
12
|
+
[Documentation](https://sei-js.docs.sei.io/create-sei/welcome) • [GitHub](https://github.com/sei-protocol/sei-js) • [NPM](https://www.npmjs.com/package/@sei-js/create-sei) • [Telegram](https://t.me/+LPW_1djQwRQwMzlk)
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
Building on our EVM (Ethereum Virtual Machine) is the easiest way to get your dApp kick-started on Sei! The mature EVM ecosystem provides many tools out of the box to help developers build faster, including deploying smart contracts and other helpful connection libraries.
|
|
14
|
+
</div>
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
- [Wagmi](https://wagmi.sh/core/getting-started) ([Viem](https://viem.sh/)): Recommended
|
|
19
|
-
- [Ethers](https://docs.ethers.org/v6/)
|
|
16
|
+
## 🚀 Quick Start
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
```bash
|
|
19
|
+
npx @sei-js/create-sei app -n my-sei-app
|
|
20
|
+
```
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
## 📚 Documentation
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
For complete documentation, examples, and guides, visit:
|
|
25
|
+
**[sei-js.docs.sei.io/create-sei](https://sei-js.docs.sei.io/create-sei/welcome)**
|
|
27
26
|
|
|
28
|
-
If you think your app might require interaction with native Cosmos modules, you should check the list of [precompiles](https://www.docs.sei.io/dev-interoperability/precompiles/addr) to determine if the same support can be offered by the EVM.
|
|
29
27
|
|
|
30
|
-
Cosmos Applications use
|
|
31
|
-
- [CosmosKit](https://cosmology.zone/products/cosmos-kit)
|
|
32
|
-
- [@sei-js/cosmjs](https://sei-protocol.github.io/sei-js/modules/cosmjs.html)
|
|
33
|
-
- [Cosmjs](https://github.com/cosmos/cosmjs)
|
|
34
|
-
|
|
35
|
-
## Contributing
|
|
36
|
-
We love contributions from the amazing Sei community! If you have a dApp template to contribute, do make a Pull Request into the [sei-js](https://github.com/sei-protocol/sei-js) repository.
|
package/biome.json
ADDED
package/dist/main.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import boxen from 'boxen';
|
|
4
|
-
import
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
import
|
|
7
|
-
import { dirname } from 'path';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { dirname } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
8
|
import { Command } from 'commander';
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
10
|
const __dirname = dirname(__filename);
|
|
@@ -23,15 +23,6 @@ var FrontendScaffolding;
|
|
|
23
23
|
FrontendScaffolding["Vite"] = "vite";
|
|
24
24
|
FrontendScaffolding["Next"] = "next";
|
|
25
25
|
})(FrontendScaffolding || (FrontendScaffolding = {}));
|
|
26
|
-
export var RPCIntegrationType;
|
|
27
|
-
(function (RPCIntegrationType) {
|
|
28
|
-
RPCIntegrationType["EVM"] = "evm";
|
|
29
|
-
RPCIntegrationType["CosmJS"] = "cosmos";
|
|
30
|
-
})(RPCIntegrationType || (RPCIntegrationType = {}));
|
|
31
|
-
export var EVMLibrary;
|
|
32
|
-
(function (EVMLibrary) {
|
|
33
|
-
EVMLibrary["Wagmi"] = "wagmi";
|
|
34
|
-
})(EVMLibrary || (EVMLibrary = {}));
|
|
35
26
|
const promptFramework = async () => {
|
|
36
27
|
const { appFramework } = await inquirer.prompt([
|
|
37
28
|
{
|
|
@@ -43,36 +34,15 @@ const promptFramework = async () => {
|
|
|
43
34
|
]);
|
|
44
35
|
return appFramework;
|
|
45
36
|
};
|
|
46
|
-
const promptRpcIntegrations = async () => {
|
|
47
|
-
const { rpcIntegrationType } = await inquirer.prompt([
|
|
48
|
-
{
|
|
49
|
-
type: 'list',
|
|
50
|
-
name: 'rpcIntegrationType',
|
|
51
|
-
message: 'Select the wallet connection type you want to include:',
|
|
52
|
-
choices: Object.values(RPCIntegrationType)
|
|
53
|
-
}
|
|
54
|
-
]);
|
|
55
|
-
return rpcIntegrationType;
|
|
56
|
-
};
|
|
57
|
-
const promptEVMLibrary = async () => {
|
|
58
|
-
const { evmLibrary } = await inquirer.prompt([
|
|
59
|
-
{
|
|
60
|
-
type: 'list',
|
|
61
|
-
name: 'evmLibrary',
|
|
62
|
-
message: 'Choose your preferred EVM library:',
|
|
63
|
-
choices: Object.values(EVMLibrary)
|
|
64
|
-
}
|
|
65
|
-
]);
|
|
66
|
-
return evmLibrary;
|
|
67
|
-
};
|
|
68
37
|
function isValidDirectoryName(dirName) {
|
|
69
|
-
const illegalRe = /[<>:"
|
|
38
|
+
const illegalRe = /[<>:"/\\|?*]/g;
|
|
70
39
|
const windowsReservedRe = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i;
|
|
71
40
|
const trailingRe = /[. ]+$/;
|
|
72
41
|
const validNpmPackageRe = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
73
42
|
if (typeof dirName !== 'string' || dirName.length === 0) {
|
|
74
43
|
return false;
|
|
75
44
|
}
|
|
45
|
+
// Check for illegal characters, Windows reserved names, trailing spaces/dots
|
|
76
46
|
if (illegalRe.test(dirName) || windowsReservedRe.test(dirName) || trailingRe.test(dirName) || !validNpmPackageRe.test(dirName)) {
|
|
77
47
|
return false;
|
|
78
48
|
}
|
|
@@ -93,20 +63,6 @@ const validateOptions = (options) => {
|
|
|
93
63
|
valid = false;
|
|
94
64
|
}
|
|
95
65
|
}
|
|
96
|
-
if (options.ecosystem) {
|
|
97
|
-
const validEcosystems = Object.values(RPCIntegrationType);
|
|
98
|
-
if (!validEcosystems.includes(options.ecosystem)) {
|
|
99
|
-
console.log(`Invalid Ecosystem '${options.ecosystem}' provided. Framework must be one of: [${validEcosystems.join(', ')}]`);
|
|
100
|
-
valid = false;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (options.library) {
|
|
104
|
-
const validEVMLibraries = Object.values(EVMLibrary);
|
|
105
|
-
if (!validEVMLibraries.includes(options.library)) {
|
|
106
|
-
console.log(`Invalid EVM Library '${options.library}' provided. Framework must be one of: [${validEVMLibraries.join(', ')}]`);
|
|
107
|
-
valid = false;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
66
|
return valid;
|
|
111
67
|
};
|
|
112
68
|
async function runWizard(options) {
|
|
@@ -131,12 +87,8 @@ async function runWizard(options) {
|
|
|
131
87
|
]);
|
|
132
88
|
dAppName = promptResult.dAppName;
|
|
133
89
|
}
|
|
134
|
-
const appFramework = options.framework || await promptFramework();
|
|
135
|
-
|
|
136
|
-
if (appConnectionType == RPCIntegrationType.EVM) {
|
|
137
|
-
appConnectionType = options.library || await promptEVMLibrary();
|
|
138
|
-
}
|
|
139
|
-
const templateName = `${appFramework}-${appConnectionType}-template`;
|
|
90
|
+
const appFramework = options.framework || (await promptFramework());
|
|
91
|
+
const templateName = `${appFramework}-template`;
|
|
140
92
|
const templatePath = path.join(__dirname, 'templates', templateName);
|
|
141
93
|
const dst = path.join(process.cwd(), dAppName);
|
|
142
94
|
await fs.promises.cp(templatePath, dst, { recursive: true });
|
|
@@ -146,10 +98,8 @@ async function runWizard(options) {
|
|
|
146
98
|
program
|
|
147
99
|
.command('app')
|
|
148
100
|
.description('Create a new SEI dApp')
|
|
149
|
-
.option('-n, --name <name>',
|
|
101
|
+
.option('-n, --name <name>', 'Specify the name of your dApp. Name must be a valid package name.')
|
|
150
102
|
.option('-f, --framework <framework>', `Specify the app framework to use: [${Object.values(FrontendScaffolding).join(', ')}]`)
|
|
151
|
-
.option('-e, --ecosystem <ecosystem>', `Specify the ecosystem to use: [${Object.values(RPCIntegrationType).join(', ')}]`)
|
|
152
|
-
.option('-l, --library <library>', `Specify the EVM library to use: [${Object.values(EVMLibrary).join(', ')}]. Only used if ecosystem chosen is 'EVM'`)
|
|
153
103
|
.action(async (options) => {
|
|
154
104
|
try {
|
|
155
105
|
await runWizard(options);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "template-next-sei-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "next lint"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@rainbow-me/rainbowkit": "^2.1.2",
|
|
13
|
+
"@sei-js/evm": "^1.2.0",
|
|
14
|
+
"@tanstack/react-query": "^5.45.1",
|
|
15
|
+
"encoding": "^0.1.13",
|
|
16
|
+
"next": "14.2.4",
|
|
17
|
+
"pino-pretty": "^11.2.1",
|
|
18
|
+
"react": "^18",
|
|
19
|
+
"react-dom": "^18",
|
|
20
|
+
"viem": "^2.15.1",
|
|
21
|
+
"wagmi": "^2.10.2"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^20",
|
|
25
|
+
"@types/react": "^18",
|
|
26
|
+
"@types/react-dom": "^18",
|
|
27
|
+
"eslint-config-next": "14.2.4",
|
|
28
|
+
"typescript": "^5"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { BANK_PRECOMPILE_ABI, BANK_PRECOMPILE_ADDRESS, WASM_PRECOMPILE_ABI, WASM_PRECOMPILE_ADDRESS } from '@sei-js/evm';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { ReadContractParameters, formatEther, fromHex, parseEther, toHex } from 'viem';
|
|
6
|
+
import { useAccount, usePublicClient, useWriteContract } from 'wagmi';
|
|
7
|
+
|
|
8
|
+
import './Homepage.css';
|
|
9
|
+
|
|
10
|
+
function Examples() {
|
|
11
|
+
const [balance, setBalance] = useState('');
|
|
12
|
+
const [supply, setSupply] = useState('');
|
|
13
|
+
const [count, setCount] = useState(0);
|
|
14
|
+
|
|
15
|
+
const publicClient = usePublicClient();
|
|
16
|
+
const { address } = useAccount();
|
|
17
|
+
const { writeContractAsync } = useWriteContract();
|
|
18
|
+
|
|
19
|
+
const formatLargeSeiNumber = (num: string, decimals: number): string => {
|
|
20
|
+
if (num.length > 10) {
|
|
21
|
+
return (
|
|
22
|
+
(Number(num) / 1000000 / 1000000000).toLocaleString(navigator.language, { minimumFractionDigits: decimals, maximumFractionDigits: decimals }) + ' B'
|
|
23
|
+
);
|
|
24
|
+
} else {
|
|
25
|
+
return (Number(num) / 1000000).toLocaleString(navigator.language);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const copyToClipboard = (text: string) => {
|
|
30
|
+
try {
|
|
31
|
+
navigator.clipboard.writeText(text);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
console.error('Failed to copy text: ', err);
|
|
34
|
+
} finally {
|
|
35
|
+
alert('Copied to clipboard!');
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const renderAddressExample = () => {
|
|
40
|
+
return (
|
|
41
|
+
<div className="card">
|
|
42
|
+
<div className="card-header">
|
|
43
|
+
<p className="card__title">Wallet address</p>
|
|
44
|
+
<small className="card__description">
|
|
45
|
+
<a href="https://viem.sh/docs/clients/public.html" target="_blank">
|
|
46
|
+
Viem Public Client
|
|
47
|
+
</a>{' '}
|
|
48
|
+
query example
|
|
49
|
+
</small>
|
|
50
|
+
</div>
|
|
51
|
+
<div className="card-body">
|
|
52
|
+
<div className="content-background space-between">
|
|
53
|
+
{address ? (
|
|
54
|
+
<div>
|
|
55
|
+
<p className="card-footer">{address}</p>
|
|
56
|
+
</div>
|
|
57
|
+
) : (
|
|
58
|
+
<p> --- </p>
|
|
59
|
+
)}
|
|
60
|
+
|
|
61
|
+
<button className="small outline" onClick={() => copyToClipboard(address as string)}>
|
|
62
|
+
Copy
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
<div className="card-footer"></div>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const getBalanceWagmi = async () => {
|
|
72
|
+
if (!address || !publicClient) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
const weiBalance = await publicClient.getBalance({ address });
|
|
76
|
+
const seiBalance = formatEther(weiBalance);
|
|
77
|
+
setBalance(seiBalance);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const renderBalanceExample = () => {
|
|
81
|
+
return (
|
|
82
|
+
<div className="card">
|
|
83
|
+
<div className="card-header">
|
|
84
|
+
<p className="card__title">Wallet balance</p>
|
|
85
|
+
<small className="card__description">
|
|
86
|
+
<a href="https://viem.sh/docs/clients/public.html" target="_blank">
|
|
87
|
+
Viem Public Client
|
|
88
|
+
</a>{' '}
|
|
89
|
+
query example
|
|
90
|
+
</small>
|
|
91
|
+
</div>
|
|
92
|
+
<div className="card-body">
|
|
93
|
+
<div className="content-background space-between">
|
|
94
|
+
<small>SEI</small>
|
|
95
|
+
<p>{balance ? balance : '---'} SEI</p>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
<div className="card-footer">
|
|
99
|
+
<button onClick={getBalanceWagmi}>Fetch balance</button>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Example of using precompiles to query native Sei modules.
|
|
106
|
+
const getBankSupply = async () => {
|
|
107
|
+
if (!publicClient) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const params: ReadContractParameters = {
|
|
112
|
+
address: BANK_PRECOMPILE_ADDRESS,
|
|
113
|
+
abi: BANK_PRECOMPILE_ABI,
|
|
114
|
+
functionName: 'supply',
|
|
115
|
+
args: ['usei']
|
|
116
|
+
};
|
|
117
|
+
try {
|
|
118
|
+
const response = (await publicClient.readContract(params)) as BigInt;
|
|
119
|
+
const supply = formatLargeSeiNumber(response.toString(), 1);
|
|
120
|
+
setSupply(supply);
|
|
121
|
+
} catch (e) {
|
|
122
|
+
console.log(e);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const renderBankSupplyExample = () => {
|
|
127
|
+
return (
|
|
128
|
+
<div className="card">
|
|
129
|
+
<div className="card-header">
|
|
130
|
+
<p className="card__title">Total Sei supply</p>
|
|
131
|
+
<small className="card__description">
|
|
132
|
+
<a href="https://www.docs.sei.io/dev-interoperability/precompiles/bank" target="_blank">
|
|
133
|
+
{' '}
|
|
134
|
+
Bank precompile
|
|
135
|
+
</a>{' '}
|
|
136
|
+
example for querying native Sei modules
|
|
137
|
+
</small>
|
|
138
|
+
</div>
|
|
139
|
+
<div className="card-body">
|
|
140
|
+
<div className="content-background space-between">
|
|
141
|
+
<small>SEI</small>
|
|
142
|
+
<p>{supply}</p>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
<div className="card-footer">
|
|
146
|
+
<button onClick={getBankSupply}>Fetch supply</button>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// Fetch count of a CosmWasm Contract using WASM Precompile
|
|
153
|
+
const fetchCount = async () => {
|
|
154
|
+
if (!publicClient) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const COUNTER_CONTRACT_ADDRESS = 'sei14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sh9m79m';
|
|
159
|
+
|
|
160
|
+
const queryMsg = toHex(JSON.stringify({ get_count: {} }));
|
|
161
|
+
|
|
162
|
+
const params: ReadContractParameters = {
|
|
163
|
+
address: WASM_PRECOMPILE_ADDRESS,
|
|
164
|
+
abi: WASM_PRECOMPILE_ABI,
|
|
165
|
+
functionName: 'query',
|
|
166
|
+
args: [COUNTER_CONTRACT_ADDRESS, queryMsg]
|
|
167
|
+
};
|
|
168
|
+
try {
|
|
169
|
+
const response = (await publicClient?.readContract(params)) as `0x${string}`;
|
|
170
|
+
const { count } = JSON.parse(fromHex(response, 'string'));
|
|
171
|
+
setCount(count);
|
|
172
|
+
} catch (e) {
|
|
173
|
+
console.log(e);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Fetch count of a CosmWasm Contract using WASM Precompile
|
|
178
|
+
const incrementCounter = async () => {
|
|
179
|
+
if (!address || !publicClient) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const COUNTER_CONTRACT_ADDRESS = 'sei14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sh9m79m';
|
|
184
|
+
|
|
185
|
+
const execMsg = toHex(JSON.stringify({ increment: {} }));
|
|
186
|
+
const coins = toHex('[]');
|
|
187
|
+
const params = {
|
|
188
|
+
account: address,
|
|
189
|
+
address: WASM_PRECOMPILE_ADDRESS,
|
|
190
|
+
abi: WASM_PRECOMPILE_ABI,
|
|
191
|
+
functionName: 'execute',
|
|
192
|
+
args: [COUNTER_CONTRACT_ADDRESS, execMsg, coins],
|
|
193
|
+
value: parseEther('0')
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
const estimatedGas = await publicClient.estimateContractGas(params);
|
|
198
|
+
|
|
199
|
+
// Call smart contract execute msg
|
|
200
|
+
await writeContractAsync({ ...params, gas: estimatedGas });
|
|
201
|
+
|
|
202
|
+
// Wait for 1 block to confirm transaction
|
|
203
|
+
setTimeout(() => {}, 400);
|
|
204
|
+
await fetchCount();
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.log(error);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const renderCounterContractExample = () => {
|
|
211
|
+
return (
|
|
212
|
+
<div className="card">
|
|
213
|
+
<div className="card-header">
|
|
214
|
+
<p className="card__title">Smart contract interaction</p>
|
|
215
|
+
<small>
|
|
216
|
+
<a href="https://www.docs.sei.io/dev-interoperability/precompiles/cosmwasm" target="_blank">
|
|
217
|
+
WASM Precompile
|
|
218
|
+
</a>{' '}
|
|
219
|
+
example of CosmWasm smart contract interaction
|
|
220
|
+
</small>
|
|
221
|
+
</div>
|
|
222
|
+
<div className="card-body">
|
|
223
|
+
<div className="content-background space-between">
|
|
224
|
+
<small>Count</small>
|
|
225
|
+
<p>{count}</p>
|
|
226
|
+
<button className="small outline" onClick={incrementCounter}>
|
|
227
|
+
Increase
|
|
228
|
+
</button>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
<div className="card-footer">
|
|
232
|
+
<button onClick={fetchCount}>Fetch count</button>
|
|
233
|
+
</div>
|
|
234
|
+
</div>
|
|
235
|
+
);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
return (
|
|
239
|
+
<div className="container">
|
|
240
|
+
<div className="grid">
|
|
241
|
+
{/* First card */}
|
|
242
|
+
{renderAddressExample()}
|
|
243
|
+
|
|
244
|
+
{/* Second card */}
|
|
245
|
+
{renderBalanceExample()}
|
|
246
|
+
|
|
247
|
+
{/* Third card */}
|
|
248
|
+
{renderBankSupplyExample()}
|
|
249
|
+
|
|
250
|
+
{/* Fourth card */}
|
|
251
|
+
{renderCounterContractExample()}
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export default Examples;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#root {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
min-height: 100vh;
|
|
5
|
+
}
|
|
6
|
+
.app {
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 100%;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.logo {
|
|
12
|
+
width: 20%;
|
|
13
|
+
align-self: center;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.container {
|
|
17
|
+
margin: 0 auto;
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
gap: 3rem;
|
|
21
|
+
width: 100%;
|
|
22
|
+
padding: 1rem;
|
|
23
|
+
height: -webkit-fill-available;
|
|
24
|
+
flex-grow: 1;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.grid {
|
|
29
|
+
width: 100%;
|
|
30
|
+
display: grid;
|
|
31
|
+
grid-template-columns: repeat(1, 1fr);
|
|
32
|
+
gap: 1rem;
|
|
33
|
+
}
|
|
34
|
+
.grid.docs {
|
|
35
|
+
grid-template-columns: repeat(1, 1fr);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.card {
|
|
39
|
+
width: 100%;
|
|
40
|
+
padding: 1.5em;
|
|
41
|
+
border-radius: 1rem;
|
|
42
|
+
background: var(--card);
|
|
43
|
+
color: var(--card-foreground);
|
|
44
|
+
box-shadow: 0px 4px 6px 0px rgba(0, 0, 0, 0.09);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.card.secondary {
|
|
48
|
+
background: transparent;
|
|
49
|
+
border: 1px solid var(--border);
|
|
50
|
+
box-shadow: none;
|
|
51
|
+
}
|
|
52
|
+
.card.intro {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex-direction: column;
|
|
55
|
+
gap: 1rem;
|
|
56
|
+
justify-content: space-between;
|
|
57
|
+
align-items: flex-start;
|
|
58
|
+
}
|
|
59
|
+
.card-header {
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
justify-content: space-between;
|
|
63
|
+
gap: 0.25rem;
|
|
64
|
+
}
|
|
65
|
+
.card-body {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
justify-content: space-between;
|
|
69
|
+
margin: 1.5rem 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.card-footer {
|
|
73
|
+
display: flex;
|
|
74
|
+
flex-direction: row;
|
|
75
|
+
gap: 0.5rem;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.card__title {
|
|
79
|
+
font-size: 1.15rem;
|
|
80
|
+
font-weight: 600;
|
|
81
|
+
}
|
|
82
|
+
.content-background {
|
|
83
|
+
overflow: hidden;
|
|
84
|
+
background: #fafaf9;
|
|
85
|
+
border-radius: 4rem;
|
|
86
|
+
padding: 0 1rem;
|
|
87
|
+
height: 3.5rem;
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.wallet-address {
|
|
93
|
+
text-wrap: anywhere;
|
|
94
|
+
line-break: anywhere;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.space-between {
|
|
98
|
+
justify-content: space-between;
|
|
99
|
+
gap: 1rem;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.hide-on-mobile {
|
|
103
|
+
display: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.hide-on-desktop {
|
|
107
|
+
display: block;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.external-link {
|
|
111
|
+
display: inline-flex;
|
|
112
|
+
gap: 0.25rem;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.get-started {
|
|
116
|
+
text-align: center;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.wallet-connect {
|
|
120
|
+
display: flex;
|
|
121
|
+
gap: 1rem;
|
|
122
|
+
align-items: center;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@media (min-width: 768px) {
|
|
126
|
+
.card.intro {
|
|
127
|
+
grid-column: span 2;
|
|
128
|
+
flex-direction: row;
|
|
129
|
+
align-items: center;
|
|
130
|
+
}
|
|
131
|
+
.hide-on-mobile {
|
|
132
|
+
display: block;
|
|
133
|
+
}
|
|
134
|
+
.hide-on-desktop {
|
|
135
|
+
display: none;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.container {
|
|
139
|
+
max-width: 96rem;
|
|
140
|
+
padding: 2rem;
|
|
141
|
+
}
|
|
142
|
+
.grid {
|
|
143
|
+
grid-template-columns: repeat(2, 1fr);
|
|
144
|
+
}
|
|
145
|
+
.grid.docs {
|
|
146
|
+
grid-template-columns: repeat(2, 1fr);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@media (min-width: 1024px) {
|
|
151
|
+
.container {
|
|
152
|
+
max-width: 80rem;
|
|
153
|
+
}
|
|
154
|
+
}
|