create-near-app 4.0.0 → 4.1.0-rc.0
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/README.md +2 -0
- package/dist/app.js +1 -1
- package/dist/make.js +19 -18
- package/dist/messages.js +1 -1
- package/dist/package-json.js +14 -14
- package/dist/tracking.js +1 -1
- package/dist/user-input.js +2 -2
- package/package.json +2 -2
- package/templates/contracts/js/README.md +71 -15
- package/templates/contracts/js/build.sh +5 -0
- package/templates/contracts/js/deploy.sh +13 -0
- package/templates/contracts/js/package.json +3 -3
- package/templates/contracts/js/src/contract.ts +9 -24
- package/templates/contracts/rust/Cargo.toml +1 -1
- package/templates/contracts/rust/README.md +83 -16
- package/templates/contracts/rust/build.sh +6 -0
- package/templates/contracts/rust/deploy.sh +13 -0
- package/templates/frontend/react/{frontend/App.js → App.js} +7 -9
- package/templates/frontend/react/{frontend/assets → assets}/favicon.ico +0 -0
- package/templates/frontend/react/{frontend/assets → assets}/global.css +0 -0
- package/templates/frontend/react/{frontend/assets → assets}/logo-black.svg +0 -0
- package/templates/frontend/react/{frontend/assets → assets}/logo-white.svg +0 -0
- package/templates/frontend/react/{frontend/index.html → index.html} +0 -0
- package/templates/frontend/react/index.js +21 -0
- package/templates/frontend/react/{frontend/package.json → package.json} +13 -2
- package/templates/frontend/react/{frontend/ui-components.js → ui-components.js} +4 -5
- package/templates/frontend/shared/near-interface.js +15 -0
- package/templates/frontend/shared/near-wallet.js +109 -0
- package/templates/frontend/shared/start.sh +26 -0
- package/templates/frontend/vanilla/{frontend/assets → assets}/favicon.ico +0 -0
- package/templates/frontend/vanilla/{frontend/assets → assets}/global.css +0 -0
- package/templates/frontend/vanilla/{frontend/assets → assets}/logo-black.svg +0 -0
- package/templates/frontend/vanilla/{frontend/assets → assets}/logo-white.svg +0 -0
- package/templates/frontend/vanilla/index.html +91 -0
- package/templates/frontend/vanilla/{frontend/index.js → index.js} +30 -42
- package/templates/frontend/vanilla/package.json +29 -0
- package/templates/integration-tests/{shared/js-tests → js-tests}/ava.config.cjs +0 -0
- package/templates/integration-tests/{shared/js-tests → js-tests}/package.json +1 -1
- package/templates/integration-tests/{shared/js-tests → js-tests}/src/main.ava.ts +1 -1
- package/templates/integration-tests/{shared/rust-tests → rust-tests}/Cargo.toml +0 -0
- package/templates/integration-tests/{shared/rust-tests → rust-tests}/src/tests.rs +0 -0
- package/templates/shared/README.md +1 -1
- package/templates/shared/{near.gitignore → template.gitignore} +0 -0
- package/templates/frontend/react/frontend/index.js +0 -15
- package/templates/frontend/react/frontend/near-api.js +0 -51
- package/templates/frontend/react/frontend/near-config.js +0 -61
- package/templates/frontend/vanilla/frontend/index.html +0 -89
- package/templates/frontend/vanilla/frontend/near-api.js +0 -51
- package/templates/frontend/vanilla/frontend/near-config.js +0 -62
- package/templates/frontend/vanilla/frontend/package.json +0 -18
- package/templates/integration-tests/overrides/js-contract/js-tests/src/main.ava.ts +0 -46
- package/templates/integration-tests/overrides/js-contract/rust-tests/src/tests.rs +0 -74
package/README.md
CHANGED
|
@@ -17,6 +17,8 @@ To create a new NEAR project run this and follow interactive prompts:
|
|
|
17
17
|
|
|
18
18
|
npx create-near-app
|
|
19
19
|
|
|
20
|
+
> If you've previously installed `create-near-app` globally via `npm install -g create-near-app`, please uninstall the package using `npm uninstall -g create-near-app` to ensure that `npx` always uses the latest version.
|
|
21
|
+
|
|
20
22
|
Follow the instructions in the README.md in the project you just created! 🚀
|
|
21
23
|
|
|
22
24
|
You can create contracts written in:
|
package/dist/app.js
CHANGED
|
@@ -57,7 +57,7 @@ const show = __importStar(require("./messages"));
|
|
|
57
57
|
await (0, make_1.runDepsInstall)(projectPath);
|
|
58
58
|
}
|
|
59
59
|
if (createSuccess) {
|
|
60
|
-
show.setupSuccess(
|
|
60
|
+
show.setupSuccess(projectName, contract, frontend, install);
|
|
61
61
|
}
|
|
62
62
|
else {
|
|
63
63
|
show.setupFailed();
|
package/dist/make.js
CHANGED
|
@@ -47,34 +47,35 @@ async function createFiles({ contract, frontend, tests, projectPath, verbose, ro
|
|
|
47
47
|
const skip = ['.cache', 'dist', 'out', 'node_modules'];
|
|
48
48
|
// copy frontend
|
|
49
49
|
if (frontend !== 'none') {
|
|
50
|
-
const
|
|
51
|
-
|
|
50
|
+
const sourceFrontendDir = path_1.default.resolve(`${rootDir}/frontend/${frontend}`);
|
|
51
|
+
const sourceSharedFrontendDir = path_1.default.resolve(`${rootDir}/frontend/shared`);
|
|
52
|
+
const targetFrontendDir = path_1.default.resolve(`${projectPath}/frontend`);
|
|
53
|
+
fs_1.default.mkdirSync(targetFrontendDir, { recursive: true });
|
|
54
|
+
await copyDir(sourceFrontendDir, targetFrontendDir, { verbose, skip: skip.map(f => path_1.default.join(sourceFrontendDir, f)) });
|
|
55
|
+
await copyDir(sourceSharedFrontendDir, targetFrontendDir, { verbose, skip: skip.map(f => path_1.default.join(sourceSharedFrontendDir, f)) });
|
|
52
56
|
}
|
|
53
57
|
// shared files
|
|
54
|
-
const sourceSharedDir =
|
|
58
|
+
const sourceSharedDir = path_1.default.resolve(rootDir, 'shared');
|
|
55
59
|
await copyDir(sourceSharedDir, projectPath, { verbose, skip: skip.map(f => path_1.default.join(sourceSharedDir, f)) });
|
|
56
60
|
// copy contract files
|
|
57
|
-
const
|
|
58
|
-
|
|
61
|
+
const sourceContractDir = path_1.default.resolve(rootDir, 'contracts', contract);
|
|
62
|
+
const targetContractDir = path_1.default.resolve(projectPath, 'contract');
|
|
63
|
+
fs_1.default.mkdirSync(targetContractDir, { recursive: true });
|
|
64
|
+
await copyDir(sourceContractDir, targetContractDir, {
|
|
59
65
|
verbose,
|
|
60
|
-
skip: skip.map(f => path_1.default.join(
|
|
66
|
+
skip: skip.map(f => path_1.default.join(sourceContractDir, f))
|
|
61
67
|
});
|
|
68
|
+
// tests dir
|
|
69
|
+
const targetTestDir = path_1.default.resolve(projectPath, 'integration-tests');
|
|
70
|
+
fs_1.default.mkdirSync(targetTestDir, { recursive: true });
|
|
62
71
|
// copy tests - shared files
|
|
63
|
-
|
|
64
|
-
await copyDir(sourceTestSharedDir,
|
|
72
|
+
const sourceTestSharedDir = path_1.default.resolve(`${rootDir}/integration-tests/${tests}-tests`);
|
|
73
|
+
await copyDir(sourceTestSharedDir, targetTestDir, {
|
|
65
74
|
verbose,
|
|
66
75
|
skip: skip.map(f => path_1.default.join(sourceTestSharedDir, f))
|
|
67
76
|
});
|
|
68
|
-
// copy tests - overrides files
|
|
69
|
-
let sourceTestOverridesDir = path_1.default.resolve(`${rootDir}/integration-tests/overrides/${contract}-contract/${tests}-tests`);
|
|
70
|
-
if (fs_1.default.existsSync(sourceTestOverridesDir)) {
|
|
71
|
-
await copyDir(sourceTestOverridesDir, `${projectPath}/integration-tests/`, {
|
|
72
|
-
verbose,
|
|
73
|
-
skip: skip.map(f => path_1.default.join(sourceTestOverridesDir, f))
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
77
|
// add .gitignore
|
|
77
|
-
await (0, exports.renameFile)(`${projectPath}/
|
|
78
|
+
await (0, exports.renameFile)(`${projectPath}/template.gitignore`, `${projectPath}/.gitignore`);
|
|
78
79
|
}
|
|
79
80
|
exports.createFiles = createFiles;
|
|
80
81
|
const renameFile = async function (oldPath, newPath) {
|
|
@@ -119,7 +120,7 @@ function copyDir(source, dest, { skip, verbose }) {
|
|
|
119
120
|
exports.copyDir = copyDir;
|
|
120
121
|
async function runDepsInstall(projectPath) {
|
|
121
122
|
show.depsInstall();
|
|
122
|
-
const npmCommandArgs = ['
|
|
123
|
+
const npmCommandArgs = ['install'];
|
|
123
124
|
await new Promise((resolve, reject) => (0, cross_spawn_1.default)('npm', npmCommandArgs, {
|
|
124
125
|
cwd: projectPath,
|
|
125
126
|
stdio: 'inherit',
|
package/dist/messages.js
CHANGED
|
@@ -37,7 +37,7 @@ ${contract === 'rust' ? (0, chalk_1.default) `🦀 If you are new to Rust please
|
|
|
37
37
|
- {inverse Navigate to your project}:
|
|
38
38
|
{blue cd {bold ${projectName}}}
|
|
39
39
|
${!install ? (0, chalk_1.default) `- {inverse Install all dependencies}
|
|
40
|
-
{blue npm {bold
|
|
40
|
+
{blue npm {bold install}}` : 'Then:'}
|
|
41
41
|
- {inverse Test your contract} in NEAR SandBox:
|
|
42
42
|
{blue npm {bold test}}
|
|
43
43
|
- {inverse Deploy your contract} to NEAR TestNet with a temporary dev account:
|
package/dist/package-json.js
CHANGED
|
@@ -51,7 +51,7 @@ const buildContractScript = (contract) => {
|
|
|
51
51
|
};
|
|
52
52
|
case 'rust':
|
|
53
53
|
return {
|
|
54
|
-
'build:contract': 'cd contract &&
|
|
54
|
+
'build:contract': 'cd contract && ./build.sh',
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
};
|
|
@@ -64,7 +64,7 @@ const deployScript = (contract) => {
|
|
|
64
64
|
};
|
|
65
65
|
case 'rust':
|
|
66
66
|
return {
|
|
67
|
-
'deploy': '
|
|
67
|
+
'deploy': 'cd contract && ./deploy.sh',
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
};
|
|
@@ -119,52 +119,52 @@ const npmInstallScript = (contract, hasFrontend, tests) => {
|
|
|
119
119
|
case 'assemblyscript':
|
|
120
120
|
if (hasFrontend) {
|
|
121
121
|
if (tests === 'js') {
|
|
122
|
-
return { '
|
|
122
|
+
return { 'postinstall': 'cd contract && npm install --ignore-scripts && cd ../integration-tests && npm install && cd ../frontend && npm install && cd ..' };
|
|
123
123
|
}
|
|
124
124
|
else {
|
|
125
|
-
return { '
|
|
125
|
+
return { 'postinstall': 'cd contract && npm install --ignore-scripts && cd ../frontend && npm install && cd ..' };
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
else {
|
|
129
129
|
if (tests === 'js') {
|
|
130
|
-
return { '
|
|
130
|
+
return { 'postinstall': 'cd contract && npm install --ignore-scripts && cd ../integration-tests && npm install && cd ..' };
|
|
131
131
|
}
|
|
132
132
|
else {
|
|
133
|
-
return { '
|
|
133
|
+
return { 'postinstall': 'cd contract && npm install --ignore-scripts && cd ..' };
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
case 'js':
|
|
137
137
|
if (hasFrontend) {
|
|
138
138
|
if (tests === 'js') {
|
|
139
|
-
return { '
|
|
139
|
+
return { 'postinstall': 'cd contract && npm install && cd ../integration-tests && npm install && cd ../frontend && npm install && cd ..' };
|
|
140
140
|
}
|
|
141
141
|
else {
|
|
142
|
-
return { '
|
|
142
|
+
return { 'postinstall': 'cd contract && npm install && cd ../frontend && npm install && cd ..' };
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
else {
|
|
146
146
|
if (tests === 'js') {
|
|
147
|
-
return { '
|
|
147
|
+
return { 'postinstall': 'cd contract && npm install && cd ../integration-tests && npm install && cd ..' };
|
|
148
148
|
}
|
|
149
149
|
else {
|
|
150
|
-
return { '
|
|
150
|
+
return { 'postinstall': 'cd contract && npm install && cd ..' };
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
case 'rust':
|
|
154
154
|
if (hasFrontend) {
|
|
155
155
|
if (tests === 'js') {
|
|
156
|
-
return { '
|
|
156
|
+
return { 'postinstall': 'cd frontend && npm install && cd ../integration-tests && npm install && cd ..' };
|
|
157
157
|
}
|
|
158
158
|
else {
|
|
159
|
-
return { '
|
|
159
|
+
return { 'postinstall': 'cd frontend && npm install && cd ..' };
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
else {
|
|
163
163
|
if (tests === 'js') {
|
|
164
|
-
return { '
|
|
164
|
+
return { 'postinstall': 'cd ./integration-tests && npm install && cd ..' };
|
|
165
165
|
}
|
|
166
166
|
else {
|
|
167
|
-
return {
|
|
167
|
+
return {};
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
}
|
package/dist/tracking.js
CHANGED
|
@@ -9,7 +9,7 @@ const mixpanel_1 = __importDefault(require("mixpanel"));
|
|
|
9
9
|
const MIXPANEL_TOKEN = 'df164f13212cbb0dfdae991da60e87f2';
|
|
10
10
|
const tracker = mixpanel_1.default.init(MIXPANEL_TOKEN);
|
|
11
11
|
exports.trackingMessage = (0, chalk_1.default) `NEAR collects anonymous information on the commands used. No personal information that could identify you is shared`;
|
|
12
|
-
// TODO: track different failures &
|
|
12
|
+
// TODO: track different failures & install usage
|
|
13
13
|
const trackUsage = async (frontend, contract) => {
|
|
14
14
|
// prevents logging from CI
|
|
15
15
|
if (process.env.NEAR_ENV === 'ci' || process.env.NODE_ENV === 'ci') {
|
package/dist/user-input.js
CHANGED
|
@@ -75,13 +75,13 @@ function validateUserArgs(args) {
|
|
|
75
75
|
}
|
|
76
76
|
exports.validateUserArgs = validateUserArgs;
|
|
77
77
|
const contractChoices = [
|
|
78
|
-
{ title: '
|
|
78
|
+
{ title: 'TypeScript', value: 'js' },
|
|
79
79
|
{ title: 'Rust', value: 'rust' },
|
|
80
80
|
{ title: 'AssemblyScript', value: 'assemblyscript' },
|
|
81
81
|
];
|
|
82
82
|
const testsChoices = [
|
|
83
83
|
{ title: 'Rust Sandbox Tests', value: 'rust' },
|
|
84
|
-
{ title: '
|
|
84
|
+
{ title: 'TypeScript Sandbox Tests', value: 'js' },
|
|
85
85
|
];
|
|
86
86
|
const frontendChoices = [
|
|
87
87
|
{ title: 'React.js', value: 'react' },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-near-app",
|
|
3
|
-
"version": "4.0.0",
|
|
3
|
+
"version": "4.1.0-rc.0",
|
|
4
4
|
"description": "Quickly scaffold your dApp on NEAR Blockchain",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"engines": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"start": "npm run build && node index.js",
|
|
18
18
|
"build": "tsc",
|
|
19
|
-
"test": "npm run build && jest --runInBand",
|
|
19
|
+
"test": "npm run build && FORCE_COLOR=1 jest --runInBand",
|
|
20
20
|
"test-e2e": "npm run build && ./test/e2e.sh",
|
|
21
21
|
"lint": "eslint .",
|
|
22
22
|
"fix": "eslint . --fix",
|
|
@@ -1,23 +1,79 @@
|
|
|
1
|
-
Hello NEAR
|
|
2
|
-
=================================
|
|
1
|
+
# Hello NEAR Contract
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
The smart contract exposes two methods to enable storing and retrieving a greeting in the NEAR network.
|
|
5
4
|
|
|
5
|
+
```ts
|
|
6
|
+
@NearBindgen({})
|
|
7
|
+
class HelloNear {
|
|
8
|
+
greeting: string = "Hello";
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
@view // This method is read-only and can be called for free
|
|
11
|
+
get_greeting(): string {
|
|
12
|
+
return this.greeting;
|
|
13
|
+
}
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
@call // This method changes the state, for which it cost gas
|
|
16
|
+
set_greeting({ greeting }: { greeting: string }): void {
|
|
17
|
+
// Record a log permanently to the blockchain!
|
|
18
|
+
near.log(`Saving greeting ${greeting}`);
|
|
19
|
+
this.greeting = greeting;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
12
23
|
|
|
13
|
-
|
|
14
|
-
==================
|
|
24
|
+
<br />
|
|
15
25
|
|
|
16
|
-
|
|
17
|
-
2. There are two functions to the smart contract: `get_greeting` and `set_greeting`.
|
|
18
|
-
3. Tests: Use integration-tests that `create-near-app` created for you.
|
|
26
|
+
# Quickstart
|
|
19
27
|
|
|
28
|
+
1. Make sure you have installed [node.js](https://nodejs.org/en/download/package-manager/) >= 16.
|
|
29
|
+
2. Install the [`NEAR CLI`](https://github.com/near/near-cli#setup)
|
|
20
30
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
<br />
|
|
32
|
+
|
|
33
|
+
## 1. Build and Deploy the Contract
|
|
34
|
+
You can automatically compile and deploy the contract in the NEAR testnet by running:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm run deploy
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Once finished, check the `neardev/dev-account` file to find the address in which the contract was deployed:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cat ./neardev/dev-account
|
|
44
|
+
# e.g. dev-1659899566943-21539992274727
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
<br />
|
|
48
|
+
|
|
49
|
+
## 2. Retrieve the Greeting
|
|
50
|
+
|
|
51
|
+
`get_greeting` is a read-only method (aka `view` method).
|
|
52
|
+
|
|
53
|
+
`View` methods can be called for **free** by anyone, even people **without a NEAR account**!
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Use near-cli to get the greeting
|
|
57
|
+
near view <dev-account> get_greeting
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
<br />
|
|
61
|
+
|
|
62
|
+
## 3. Store a New Greeting
|
|
63
|
+
`set_greeting` changes the contract's state, for which it is a `call` method.
|
|
64
|
+
|
|
65
|
+
`Call` methods can only be invoked using a NEAR account, since the account needs to pay GAS for the transaction.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Use near-cli to set a new greeting
|
|
69
|
+
near call <dev-account> set_greeting '{"greeting":"howdy"}' --accountId <dev-account>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Tip:** If you would like to call `set_greeting` using your own account, first login into NEAR using:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Use near-cli to login your NEAR account
|
|
76
|
+
near login
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
and then use the logged account to sign the transaction: `--accountId <your-account>`.
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
"license": "(MIT AND Apache-2.0)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"build": "
|
|
8
|
-
"deploy": "
|
|
7
|
+
"build": "./build.sh",
|
|
8
|
+
"deploy": "./deploy.sh",
|
|
9
9
|
"test": "echo use integration-tests"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"near-cli": "^3.4.0",
|
|
13
|
-
"near-sdk-js": "0.
|
|
13
|
+
"near-sdk-js": "0.5.0-0"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"typescript": "^4.7.4"
|
|
@@ -1,33 +1,18 @@
|
|
|
1
|
-
import { NearBindgen,
|
|
1
|
+
import { NearBindgen, near, call, view } from 'near-sdk-js';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
greeting: string;
|
|
3
|
+
@NearBindgen({})
|
|
4
|
+
class HelloNear {
|
|
5
|
+
greeting: string = "Hello";
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.greeting = message;
|
|
7
|
+
@view // This method is read-only and can be called for free
|
|
8
|
+
get_greeting(): string {
|
|
9
|
+
return this.greeting;
|
|
12
10
|
}
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
// @call indicates that this is a 'change method' or a function
|
|
17
|
-
// that changes state on the blockchain. Change methods cost gas.
|
|
18
|
-
// For more info -> https://docs.near.org/docs/concepts/gas
|
|
19
|
-
@call
|
|
12
|
+
@call // This method changes the state, for which it cost gas
|
|
20
13
|
set_greeting({ message }: { message: string }): void {
|
|
14
|
+
// Record a log permanently to the blockchain!
|
|
21
15
|
near.log(`Saving greeting ${message}`);
|
|
22
16
|
this.greeting = message;
|
|
23
17
|
}
|
|
24
|
-
|
|
25
|
-
// @view indicates a 'view method' or a function that returns
|
|
26
|
-
// the current values stored on the blockchain. View calls are free
|
|
27
|
-
// and do not cost gas.
|
|
28
|
-
@view
|
|
29
|
-
get_greeting(): string {
|
|
30
|
-
near.log(`The current greeting is ${this.greeting}`);
|
|
31
|
-
return this.greeting;
|
|
32
|
-
}
|
|
33
18
|
}
|
|
@@ -1,24 +1,91 @@
|
|
|
1
|
-
Hello NEAR
|
|
2
|
-
=================================
|
|
1
|
+
# Hello NEAR Contract
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
The smart contract exposes two methods to enable storing and retrieving a greeting in the NEAR network.
|
|
5
4
|
|
|
5
|
+
```rust
|
|
6
|
+
const DEFAULT_GREETING: &str = "Hello";
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
#[near_bindgen]
|
|
9
|
+
#[derive(BorshDeserialize, BorshSerialize)]
|
|
10
|
+
pub struct Contract {
|
|
11
|
+
greeting: String,
|
|
12
|
+
}
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
impl Default for Contract {
|
|
15
|
+
fn default() -> Self {
|
|
16
|
+
Self{greeting: DEFAULT_GREETING.to_string()}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
11
19
|
|
|
12
|
-
|
|
13
|
-
|
|
20
|
+
#[near_bindgen]
|
|
21
|
+
impl Contract {
|
|
22
|
+
// Public: Returns the stored greeting, defaulting to 'Hello'
|
|
23
|
+
pub fn get_greeting(&self) -> String {
|
|
24
|
+
return self.greeting.clone();
|
|
25
|
+
}
|
|
14
26
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
27
|
+
// Public: Takes a greeting, such as 'howdy', and records it
|
|
28
|
+
pub fn set_greeting(&mut self, greeting: String) {
|
|
29
|
+
// Record a log permanently to the blockchain!
|
|
30
|
+
log!("Saving greeting {}", greeting);
|
|
31
|
+
self.greeting = greeting;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
18
35
|
|
|
36
|
+
<br />
|
|
19
37
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
38
|
+
# Quickstart
|
|
39
|
+
|
|
40
|
+
1. Make sure you have installed [rust](https://rust.org/).
|
|
41
|
+
2. Install the [`NEAR CLI`](https://github.com/near/near-cli#setup)
|
|
42
|
+
|
|
43
|
+
<br />
|
|
44
|
+
|
|
45
|
+
## 1. Build and Deploy the Contract
|
|
46
|
+
You can automatically compile and deploy the contract in the NEAR testnet by running:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
./deploy.sh
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Once finished, check the `neardev/dev-account` file to find the address in which the contract was deployed:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cat ./neardev/dev-account
|
|
56
|
+
# e.g. dev-1659899566943-21539992274727
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
<br />
|
|
60
|
+
|
|
61
|
+
## 2. Retrieve the Greeting
|
|
62
|
+
|
|
63
|
+
`get_greeting` is a read-only method (aka `view` method).
|
|
64
|
+
|
|
65
|
+
`View` methods can be called for **free** by anyone, even people **without a NEAR account**!
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Use near-cli to get the greeting
|
|
69
|
+
near view <dev-account> get_greeting
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
<br />
|
|
73
|
+
|
|
74
|
+
## 3. Store a New Greeting
|
|
75
|
+
`set_greeting` changes the contract's state, for which it is a `change` method.
|
|
76
|
+
|
|
77
|
+
`Change` methods can only be invoked using a NEAR account, since the account needs to pay GAS for the transaction.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Use near-cli to set a new greeting
|
|
81
|
+
near call <dev-account> set_greeting '{"greeting":"howdy"}' --accountId <dev-account>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Tip:** If you would like to call `set_greeting` using your own account, first login into NEAR using:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Use near-cli to login your NEAR account
|
|
88
|
+
near login
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
and then use the logged account to sign the transaction: `--accountId <your-account>`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
|
|
3
|
+
./build.sh
|
|
4
|
+
|
|
5
|
+
if [ $? -ne 0 ]; then
|
|
6
|
+
echo ">> Error building contract"
|
|
7
|
+
exit 1
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
echo ">> Deploying contract"
|
|
11
|
+
|
|
12
|
+
# https://docs.near.org/tools/near-cli#near-dev-deploy
|
|
13
|
+
near dev-deploy --wasmFile ./target/wasm32-unknown-unknown/release/hello_near.wasm
|
|
@@ -3,18 +3,17 @@ import React from 'react';
|
|
|
3
3
|
|
|
4
4
|
import './assets/global.css';
|
|
5
5
|
|
|
6
|
-
import { getGreetingFromContract, setGreetingOnContract } from './near-api';
|
|
7
6
|
import { EducationalText, SignInPrompt, SignOutButton } from './ui-components';
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
export default function App() {
|
|
9
|
+
export default function App({ isSignedIn, contract, wallet }) {
|
|
11
10
|
const [valueFromBlockchain, setValueFromBlockchain] = React.useState();
|
|
12
11
|
|
|
13
12
|
const [uiPleaseWait, setUiPleaseWait] = React.useState(true);
|
|
14
13
|
|
|
15
14
|
// Get blockchian state once on component load
|
|
16
15
|
React.useEffect(() => {
|
|
17
|
-
|
|
16
|
+
contract.getGreeting()
|
|
18
17
|
.then(setValueFromBlockchain)
|
|
19
18
|
.catch(alert)
|
|
20
19
|
.finally(() => {
|
|
@@ -23,19 +22,18 @@ export default function App() {
|
|
|
23
22
|
}, []);
|
|
24
23
|
|
|
25
24
|
/// If user not signed-in with wallet - show prompt
|
|
26
|
-
if (!
|
|
25
|
+
if (!isSignedIn) {
|
|
27
26
|
// Sign-in flow will reload the page later
|
|
28
|
-
return <SignInPrompt greeting={valueFromBlockchain}/>;
|
|
27
|
+
return <SignInPrompt greeting={valueFromBlockchain} onClick={() => wallet.signIn()}/>;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
function changeGreeting(e) {
|
|
32
31
|
e.preventDefault();
|
|
33
32
|
setUiPleaseWait(true);
|
|
34
33
|
const { greetingInput } = e.target.elements;
|
|
35
|
-
|
|
36
|
-
.then(
|
|
34
|
+
contract.setGreeting(greetingInput.value)
|
|
35
|
+
.then(async () => {return contract.getGreeting();})
|
|
37
36
|
.then(setValueFromBlockchain)
|
|
38
|
-
.catch(alert)
|
|
39
37
|
.finally(() => {
|
|
40
38
|
setUiPleaseWait(false);
|
|
41
39
|
});
|
|
@@ -43,7 +41,7 @@ export default function App() {
|
|
|
43
41
|
|
|
44
42
|
return (
|
|
45
43
|
<>
|
|
46
|
-
<SignOutButton accountId={
|
|
44
|
+
<SignOutButton accountId={wallet.accountId} onClick={() => wallet.signOut()}/>
|
|
47
45
|
<main className={uiPleaseWait ? 'please-wait' : ''}>
|
|
48
46
|
<h1>
|
|
49
47
|
The contract says: <span className="greeting">{valueFromBlockchain}</span>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { createRoot } from 'react-dom/client';
|
|
3
|
+
import App from './App';
|
|
4
|
+
import { Wallet } from './near-wallet';
|
|
5
|
+
import { Contract } from './near-interface';
|
|
6
|
+
|
|
7
|
+
const reactRoot = createRoot(document.querySelector('#root'));
|
|
8
|
+
|
|
9
|
+
// create the Wallet and the Contract
|
|
10
|
+
const contractId = process.env.CONTRACT_NAME;
|
|
11
|
+
const wallet = new Wallet({contractId: contractId});
|
|
12
|
+
const contract = new Contract({wallet: wallet});
|
|
13
|
+
|
|
14
|
+
window.onload = wallet.startUp()
|
|
15
|
+
.then((isSignedIn) => {
|
|
16
|
+
reactRoot.render(<App isSignedIn={isSignedIn} contract={contract} wallet={wallet} />);
|
|
17
|
+
})
|
|
18
|
+
.catch(e => {
|
|
19
|
+
reactRoot.render(<div style={{color: 'red'}}>Error: <code>{e.message}</code></div>);
|
|
20
|
+
console.error(e);
|
|
21
|
+
});
|