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.
Files changed (52) hide show
  1. package/README.md +2 -0
  2. package/dist/app.js +1 -1
  3. package/dist/make.js +19 -18
  4. package/dist/messages.js +1 -1
  5. package/dist/package-json.js +14 -14
  6. package/dist/tracking.js +1 -1
  7. package/dist/user-input.js +2 -2
  8. package/package.json +2 -2
  9. package/templates/contracts/js/README.md +71 -15
  10. package/templates/contracts/js/build.sh +5 -0
  11. package/templates/contracts/js/deploy.sh +13 -0
  12. package/templates/contracts/js/package.json +3 -3
  13. package/templates/contracts/js/src/contract.ts +9 -24
  14. package/templates/contracts/rust/Cargo.toml +1 -1
  15. package/templates/contracts/rust/README.md +83 -16
  16. package/templates/contracts/rust/build.sh +6 -0
  17. package/templates/contracts/rust/deploy.sh +13 -0
  18. package/templates/frontend/react/{frontend/App.js → App.js} +7 -9
  19. package/templates/frontend/react/{frontend/assets → assets}/favicon.ico +0 -0
  20. package/templates/frontend/react/{frontend/assets → assets}/global.css +0 -0
  21. package/templates/frontend/react/{frontend/assets → assets}/logo-black.svg +0 -0
  22. package/templates/frontend/react/{frontend/assets → assets}/logo-white.svg +0 -0
  23. package/templates/frontend/react/{frontend/index.html → index.html} +0 -0
  24. package/templates/frontend/react/index.js +21 -0
  25. package/templates/frontend/react/{frontend/package.json → package.json} +13 -2
  26. package/templates/frontend/react/{frontend/ui-components.js → ui-components.js} +4 -5
  27. package/templates/frontend/shared/near-interface.js +15 -0
  28. package/templates/frontend/shared/near-wallet.js +109 -0
  29. package/templates/frontend/shared/start.sh +26 -0
  30. package/templates/frontend/vanilla/{frontend/assets → assets}/favicon.ico +0 -0
  31. package/templates/frontend/vanilla/{frontend/assets → assets}/global.css +0 -0
  32. package/templates/frontend/vanilla/{frontend/assets → assets}/logo-black.svg +0 -0
  33. package/templates/frontend/vanilla/{frontend/assets → assets}/logo-white.svg +0 -0
  34. package/templates/frontend/vanilla/index.html +91 -0
  35. package/templates/frontend/vanilla/{frontend/index.js → index.js} +30 -42
  36. package/templates/frontend/vanilla/package.json +29 -0
  37. package/templates/integration-tests/{shared/js-tests → js-tests}/ava.config.cjs +0 -0
  38. package/templates/integration-tests/{shared/js-tests → js-tests}/package.json +1 -1
  39. package/templates/integration-tests/{shared/js-tests → js-tests}/src/main.ava.ts +1 -1
  40. package/templates/integration-tests/{shared/rust-tests → rust-tests}/Cargo.toml +0 -0
  41. package/templates/integration-tests/{shared/rust-tests → rust-tests}/src/tests.rs +0 -0
  42. package/templates/shared/README.md +1 -1
  43. package/templates/shared/{near.gitignore → template.gitignore} +0 -0
  44. package/templates/frontend/react/frontend/index.js +0 -15
  45. package/templates/frontend/react/frontend/near-api.js +0 -51
  46. package/templates/frontend/react/frontend/near-config.js +0 -61
  47. package/templates/frontend/vanilla/frontend/index.html +0 -89
  48. package/templates/frontend/vanilla/frontend/near-api.js +0 -51
  49. package/templates/frontend/vanilla/frontend/near-config.js +0 -62
  50. package/templates/frontend/vanilla/frontend/package.json +0 -18
  51. package/templates/integration-tests/overrides/js-contract/js-tests/src/main.ava.ts +0 -46
  52. 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(projectPath, contract, frontend, install);
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 sourceTemplateDir = `${rootDir}/frontend/${frontend}`;
51
- await copyDir(sourceTemplateDir, projectPath, { verbose, skip: skip.map(f => path_1.default.join(sourceTemplateDir, f)) });
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 = `${rootDir}/shared`;
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 contractSourceDir = `${rootDir}/contracts/${contract}`;
58
- await copyDir(contractSourceDir, `${projectPath}/contract`, {
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(contractSourceDir, f))
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
- let sourceTestSharedDir = path_1.default.resolve(`${rootDir}/integration-tests/shared/${tests}-tests`);
64
- await copyDir(sourceTestSharedDir, `${projectPath}/integration-tests/`, {
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}/near.gitignore`, `${projectPath}/.gitignore`);
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 = ['run', 'deps-install'];
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 run deps-install}}` : 'Then:'}
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:
@@ -51,7 +51,7 @@ const buildContractScript = (contract) => {
51
51
  };
52
52
  case 'rust':
53
53
  return {
54
- 'build:contract': 'cd contract && rustup target add wasm32-unknown-unknown && cargo build --all --target wasm32-unknown-unknown --release',
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': 'npm run build:contract && cd contract && near dev-deploy --wasmFile ./target/wasm32-unknown-unknown/release/hello_near.wasm',
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 { 'deps-install': 'npm install && cd contract && npm install --ignore-scripts && cd ../integration-tests && npm install && cd ../frontend && npm install && cd ..' };
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 { 'deps-install': 'npm install && cd contract && npm install --ignore-scripts && cd ../frontend && npm install && cd ..' };
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 { 'deps-install': 'npm install && cd contract && npm install --ignore-scripts && cd ../integration-tests && npm install && cd ..' };
130
+ return { 'postinstall': 'cd contract && npm install --ignore-scripts && cd ../integration-tests && npm install && cd ..' };
131
131
  }
132
132
  else {
133
- return { 'deps-install': 'npm install && cd contract && npm install --ignore-scripts && cd ..' };
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 { 'deps-install': 'npm install && cd contract && npm install && cd ../integration-tests && npm install && cd ../frontend && npm install && cd ..' };
139
+ return { 'postinstall': 'cd contract && npm install && cd ../integration-tests && npm install && cd ../frontend && npm install && cd ..' };
140
140
  }
141
141
  else {
142
- return { 'deps-install': 'npm install && cd contract && npm install && cd ../frontend && npm install && cd ..' };
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 { 'deps-install': 'npm install && cd contract && npm install && cd ../integration-tests && npm install && cd ..' };
147
+ return { 'postinstall': 'cd contract && npm install && cd ../integration-tests && npm install && cd ..' };
148
148
  }
149
149
  else {
150
- return { 'deps-install': 'npm install && cd contract && npm install && cd ..' };
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 { 'deps-install': 'npm install && cd frontend && npm install && cd ../integration-tests && npm install && cd ..' };
156
+ return { 'postinstall': 'cd frontend && npm install && cd ../integration-tests && npm install && cd ..' };
157
157
  }
158
158
  else {
159
- return { 'deps-install': 'npm install && cd frontend && npm install && cd ..' };
159
+ return { 'postinstall': 'cd frontend && npm install && cd ..' };
160
160
  }
161
161
  }
162
162
  else {
163
163
  if (tests === 'js') {
164
- return { 'deps-install': 'npm install && cd ./integration-tests && npm install && cd ..' };
164
+ return { 'postinstall': 'cd ./integration-tests && npm install && cd ..' };
165
165
  }
166
166
  else {
167
- return { 'deps-install': 'npm install' };
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 & deps-install usage
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') {
@@ -75,13 +75,13 @@ function validateUserArgs(args) {
75
75
  }
76
76
  exports.validateUserArgs = validateUserArgs;
77
77
  const contractChoices = [
78
- { title: 'JavaScript', value: 'js' },
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: 'JavaScript Sandbox Tests', value: 'js' },
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
- A [smart contract] written with [NEAR JavaScript SDK] for an app initialized with [create-near-app]
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
- Quick Start
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
- 1. Install dependencies: `npm install`
11
- 2. Deploy to NEAR TestNet with a temporary dev account: `npm run deploy`
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
- Exploring The Code
14
- ==================
24
+ <br />
15
25
 
16
- 1. The smart contract code is in `src/contract.ts`.
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
- [smart contract]: https://docs.near.org/develop/welcome
22
- [NEAR JavaScript SDK]: https://github.com/near/near-sdk-js
23
- [create-near-app]: https://github.com/near/create-near-app
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>`.
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ echo ">> Building contract"
4
+
5
+ near-sdk-js build src/contract.ts build/hello_near.wasm
@@ -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 build/hello_near.wasm
@@ -4,13 +4,13 @@
4
4
  "license": "(MIT AND Apache-2.0)",
5
5
  "type": "module",
6
6
  "scripts": {
7
- "build": "near-sdk-js build src/contract.ts build/hello_near.wasm",
8
- "deploy": "npm run build && rm -rf neardev && near dev-deploy --wasmFile build/hello_near.wasm && export $(cat ./neardev/dev-account.env) && near call $CONTRACT_NAME init --accountId $CONTRACT_NAME --deposit 1 && echo $CONTRACT_NAME",
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.4.0-5"
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, NearContract, near, call, view } from 'near-sdk-js';
1
+ import { NearBindgen, near, call, view } from 'near-sdk-js';
2
2
 
3
- // The @NearBindgen decorator allows this code to compile to Base64.
4
- @NearBindgen
5
- class MyContract extends NearContract {
6
- greeting: string;
3
+ @NearBindgen({})
4
+ class HelloNear {
5
+ greeting: string = "Hello";
7
6
 
8
- constructor({message="Hello"}:{message: string}) {
9
- //execute the NEAR Contract's constructor
10
- super();
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
- default(){ return new MyContract({message: "Hello"}) }
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
  }
@@ -5,7 +5,7 @@ authors = ["Near Inc <hello@near.org>"]
5
5
  edition = "2021"
6
6
 
7
7
  [lib]
8
- crate-type = ["cdylib", "rlib"]
8
+ crate-type = ["cdylib"]
9
9
 
10
10
  [dependencies]
11
11
  near-sdk = "4.0.0"
@@ -1,24 +1,91 @@
1
- Hello NEAR!
2
- =================================
1
+ # Hello NEAR Contract
3
2
 
4
- A [smart contract] written in [Rust] for an app initialized with [create-near-app]
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
- Quick Start
8
- ===========
8
+ #[near_bindgen]
9
+ #[derive(BorshDeserialize, BorshSerialize)]
10
+ pub struct Contract {
11
+ greeting: String,
12
+ }
9
13
 
10
- Before you compile this code, you will need to install Rust with [correct target]
14
+ impl Default for Contract {
15
+ fn default() -> Self {
16
+ Self{greeting: DEFAULT_GREETING.to_string()}
17
+ }
18
+ }
11
19
 
12
- Exploring The Code
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
- 1. The main smart contract code lives in `src/lib.rs`.
16
- 2. There are two functions to the smart contract: `get_greeting` and `set_greeting`.
17
- 3. Tests: You can run smart contract tests with the `cargo test`.
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
- [smart contract]: https://docs.near.org/develop/welcome
21
- [Rust]: https://www.rust-lang.org/
22
- [create-near-app]: https://github.com/near/create-near-app
23
- [correct target]: https://docs.near.org/develop/prerequisites#rust-and-wasm
24
- [cargo]: https://doc.rust-lang.org/book/ch01-03-hello-cargo.html
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,6 @@
1
+ #!/bin/sh
2
+
3
+ echo ">> Building contract"
4
+
5
+ rustup target add wasm32-unknown-unknown
6
+ cargo build --all --target wasm32-unknown-unknown --release
@@ -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
- getGreetingFromContract()
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 (!window.walletConnection.isSignedIn()) {
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
- setGreetingOnContract(greetingInput.value)
36
- .then(getGreetingFromContract)
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={window.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>
@@ -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
+ });