create-near-app 6.3.1 → 6.4.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 +7 -7
- package/dist/app.js +1 -2
- package/dist/make.js +3 -25
- package/dist/messages.js +5 -9
- package/dist/tracking.js +1 -2
- package/dist/types.js +2 -3
- package/dist/user-input.js +9 -39
- package/package.json +1 -1
- package/templates/contracts/rs/Cargo.toml +17 -8
- package/templates/contracts/rs/README.md +23 -84
- package/templates/contracts/rs/rust-toolchain.toml +2 -2
- package/templates/contracts/rs/src/lib.rs +10 -17
- package/templates/contracts/rs/tests/test_basics.rs +32 -0
- package/templates/contracts/ts/README.md +15 -12
- package/templates/contracts/ts/ava.config.cjs +15 -0
- package/templates/contracts/ts/package.json +9 -5
- package/templates/{sandbox-tests/sandbox-ts/src → contracts/ts/sandbox-ts}/main.ava.ts +6 -7
- package/templates/contracts/ts/src/contract.ts +1 -1
- package/templates/contracts/ts/tsconfig.json +7 -2
- package/templates/frontend/next-app/README.md +10 -1
- package/templates/frontend/next-app/next.config.js +1 -1
- package/templates/frontend/next-app/package.json +16 -21
- package/templates/frontend/next-app/src/app/hello-components/page.js +9 -10
- package/templates/frontend/next-app/src/app/hello-near/page.js +18 -12
- package/templates/frontend/next-app/src/app/layout.js +25 -5
- package/templates/frontend/next-app/src/components/navigation.js +8 -7
- package/templates/frontend/next-app/src/components/vm-component.js +7 -8
- package/templates/frontend/next-app/src/config.js +8 -6
- package/templates/frontend/next-app/src/wallets/near-wallet.js +144 -0
- package/templates/frontend/next-page/README.md +10 -1
- package/templates/frontend/next-page/next.config.js +1 -1
- package/templates/frontend/next-page/package.json +10 -12
- package/templates/frontend/next-page/src/components/cards.js +1 -1
- package/templates/frontend/next-page/src/components/navigation.js +8 -6
- package/templates/frontend/next-page/src/components/vm-component.js +4 -5
- package/templates/frontend/next-page/src/config.js +8 -6
- package/templates/frontend/next-page/src/layout.js +22 -6
- package/templates/frontend/next-page/src/pages/_app.js +3 -3
- package/templates/frontend/next-page/src/pages/_document.js +2 -2
- package/templates/frontend/next-page/src/pages/hello-components/index.js +14 -15
- package/templates/frontend/next-page/src/pages/hello-near/index.js +23 -21
- package/templates/frontend/next-page/src/pages/index.js +4 -4
- package/templates/frontend/next-page/src/wallets/near-wallet.js +143 -0
- package/templates/frontend/next-page/yarn.lock +8439 -0
- package/templates/contracts/rs/.cargo/config +0 -2
- package/templates/contracts/rs/build.sh +0 -3
- package/templates/contracts/rs/deploy.sh +0 -2
- package/templates/contracts/rs/test-rs.sh +0 -9
- package/templates/contracts/rs/test-ts.sh +0 -10
- package/templates/contracts/ts/package-lock.json +0 -5966
- package/templates/frontend/next-app/src/wallets/wallet-selector.js +0 -120
- package/templates/frontend/next-page/package-lock.json +0 -14642
- package/templates/frontend/next-page/src/wallets/wallet-selector.js +0 -120
- package/templates/frontend/vanilla/.babelrc +0 -7
- package/templates/frontend/vanilla/.gitpod.yml +0 -6
- package/templates/frontend/vanilla/README.md +0 -100
- package/templates/frontend/vanilla/package.json +0 -43
- package/templates/frontend/vanilla/src/assets/favicon.ico +0 -0
- package/templates/frontend/vanilla/src/assets/global.css +0 -202
- package/templates/frontend/vanilla/src/assets/logo-black.svg +0 -1
- package/templates/frontend/vanilla/src/assets/logo-white.svg +0 -1
- package/templates/frontend/vanilla/src/components.html +0 -61
- package/templates/frontend/vanilla/src/components.js +0 -59
- package/templates/frontend/vanilla/src/hello-near.html +0 -80
- package/templates/frontend/vanilla/src/hello.js +0 -61
- package/templates/frontend/vanilla/src/index.html +0 -65
- package/templates/frontend/vanilla/src/near-wallet.js +0 -108
- package/templates/frontend/vanilla/webpack.config.js +0 -79
- package/templates/sandbox-tests/sandbox-rs/Cargo.toml +0 -14
- package/templates/sandbox-tests/sandbox-rs/src/tests.rs +0 -65
- package/templates/sandbox-tests/sandbox-ts/ava.config.cjs +0 -9
- package/templates/sandbox-tests/sandbox-ts/package-lock.json +0 -5014
- package/templates/sandbox-tests/sandbox-ts/package.json +0 -17
package/README.md
CHANGED
|
@@ -35,14 +35,15 @@ For testing we use a sandboxed environment. You can write the tests in JavaScrip
|
|
|
35
35
|
|
|
36
36
|
You can create a web application in:
|
|
37
37
|
|
|
38
|
-
- [
|
|
39
|
-
-
|
|
38
|
+
- [Next (Pages Router)](https://nextjs.org/docs/pages/building-your-application/routing)
|
|
39
|
+
- [Next (App Router)](https://nextjs.org/docs/app/building-your-application/routing)
|
|
40
|
+
|
|
40
41
|
|
|
41
42
|
:::
|
|
42
|
-
We strongly recommend you to follow our [web app quickstart](https://docs.near.org/
|
|
43
|
+
We strongly recommend you to follow our [web app quickstart](https://docs.near.org/build/smart-contracts/quickstart) if you are new to NEAR WebApps.
|
|
43
44
|
:::
|
|
44
45
|
|
|
45
|
-
> Consider using `pnpm` to handle the
|
|
46
|
+
> Consider using `pnpm` to handle the frontend, since it is much faster than `npm` and `yarn`.
|
|
46
47
|
|
|
47
48
|
## Using CLI arguments to run `create-near-app`
|
|
48
49
|
|
|
@@ -51,9 +52,8 @@ This CLI supports arguments to skip interactive prompts:
|
|
|
51
52
|
```shell
|
|
52
53
|
npx create-near-app
|
|
53
54
|
<project-name>
|
|
54
|
-
--frontend next|
|
|
55
|
+
--frontend next-app|next-page|none
|
|
55
56
|
--contract js|rs|none
|
|
56
|
-
--tests js|rs|none
|
|
57
57
|
--install
|
|
58
58
|
```
|
|
59
59
|
|
|
@@ -71,7 +71,7 @@ Check out our [documentation](https://docs.near.org) or chat with us on [Discord
|
|
|
71
71
|
To make changes to `create-near-app` itself:
|
|
72
72
|
|
|
73
73
|
* clone the repository (Windows users, [use `git clone -c core.symlinks=true`](https://stackoverflow.com/a/42137273/249801))
|
|
74
|
-
* in your terminal, enter one of the folders inside `templates`, such as `templates/frontend/
|
|
74
|
+
* in your terminal, enter one of the folders inside `templates`, such as `templates/frontend/next-app`
|
|
75
75
|
* now you can run `pnpm install` to install dependencies and `pnpm run dev` to run the local development server, just like you can in a new app created with `create-near-app`
|
|
76
76
|
|
|
77
77
|
|
package/dist/app.js
CHANGED
|
@@ -34,14 +34,13 @@ const show = __importStar(require("./messages"));
|
|
|
34
34
|
const prompt = await (0, user_input_1.promptAndGetConfig)();
|
|
35
35
|
if (prompt === undefined)
|
|
36
36
|
return;
|
|
37
|
-
const { config: { projectName, contract, frontend,
|
|
37
|
+
const { config: { projectName, contract, frontend, install, }, projectPath, } = prompt;
|
|
38
38
|
show.creatingApp();
|
|
39
39
|
let createSuccess;
|
|
40
40
|
try {
|
|
41
41
|
createSuccess = await (0, make_1.createProject)({
|
|
42
42
|
contract,
|
|
43
43
|
frontend,
|
|
44
|
-
tests,
|
|
45
44
|
templatesDir: path_1.default.resolve(__dirname, '../templates'),
|
|
46
45
|
projectPath,
|
|
47
46
|
});
|
package/dist/make.js
CHANGED
|
@@ -32,9 +32,9 @@ const cross_spawn_1 = __importDefault(require("cross-spawn"));
|
|
|
32
32
|
const fs_1 = __importDefault(require("fs"));
|
|
33
33
|
const ncp_1 = require("ncp");
|
|
34
34
|
const path_1 = __importDefault(require("path"));
|
|
35
|
-
async function createProject({ contract, frontend,
|
|
35
|
+
async function createProject({ contract, frontend, projectPath, templatesDir }) {
|
|
36
36
|
if (contract !== 'none') {
|
|
37
|
-
await createContract({ contract,
|
|
37
|
+
await createContract({ contract, projectPath, templatesDir });
|
|
38
38
|
}
|
|
39
39
|
else {
|
|
40
40
|
await createGateway({ frontend, projectPath, templatesDir });
|
|
@@ -42,33 +42,11 @@ async function createProject({ contract, frontend, tests, projectPath, templates
|
|
|
42
42
|
return true;
|
|
43
43
|
}
|
|
44
44
|
exports.createProject = createProject;
|
|
45
|
-
async function createContract({ contract,
|
|
45
|
+
async function createContract({ contract, projectPath, templatesDir }) {
|
|
46
46
|
// contract folder
|
|
47
47
|
const sourceContractDir = path_1.default.resolve(templatesDir, 'contracts', contract);
|
|
48
48
|
fs_1.default.mkdirSync(projectPath, { recursive: true });
|
|
49
49
|
await copyDir(sourceContractDir, projectPath);
|
|
50
|
-
// copy sandbox-test dir
|
|
51
|
-
const targetTestDir = path_1.default.resolve(projectPath, `sandbox-${tests}`);
|
|
52
|
-
const sourceTestDir = path_1.default.resolve(`${templatesDir}/sandbox-tests/sandbox-${tests}`);
|
|
53
|
-
fs_1.default.mkdirSync(targetTestDir);
|
|
54
|
-
await copyDir(sourceTestDir, targetTestDir);
|
|
55
|
-
if (contract === 'rs') {
|
|
56
|
-
if (tests === 'rs') {
|
|
57
|
-
// leave only one test script
|
|
58
|
-
fs_1.default.unlinkSync(path_1.default.resolve(projectPath, 'test-ts.sh'));
|
|
59
|
-
fs_1.default.renameSync(path_1.default.resolve(projectPath, 'test-rs.sh'), path_1.default.resolve(projectPath, 'test.sh'));
|
|
60
|
-
// add workspace to Cargo.toml
|
|
61
|
-
const cargoTomlPath = path_1.default.resolve(projectPath, 'Cargo.toml');
|
|
62
|
-
const cargoToml = fs_1.default.readFileSync(cargoTomlPath).toString();
|
|
63
|
-
const cargoTomlWithWorkspace = cargoToml + '\n[workspace]\nmembers = ["sandbox-rs"]';
|
|
64
|
-
fs_1.default.writeFileSync(cargoTomlPath, cargoTomlWithWorkspace);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
// leave only one test script
|
|
68
|
-
fs_1.default.unlinkSync(path_1.default.resolve(projectPath, 'test-rs.sh'));
|
|
69
|
-
fs_1.default.renameSync(path_1.default.resolve(projectPath, 'test-ts.sh'), path_1.default.resolve(projectPath, 'test.sh'));
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
50
|
}
|
|
73
51
|
async function createGateway({ frontend, projectPath, templatesDir }) {
|
|
74
52
|
const sourceFrontendDir = path_1.default.resolve(`${templatesDir}/frontend/${frontend}`);
|
package/dist/messages.js
CHANGED
|
@@ -30,8 +30,7 @@ const successContractToText = (contract) => contract === 'none'
|
|
|
30
30
|
exports.successContractToText = successContractToText;
|
|
31
31
|
const frontendTemplates = {
|
|
32
32
|
'next-page': 'NextJS (Classic)',
|
|
33
|
-
'next-app': 'NextJS (App Router)'
|
|
34
|
-
vanilla: 'Vanilla-JS',
|
|
33
|
+
'next-app': 'NextJS (App Router)'
|
|
35
34
|
};
|
|
36
35
|
const successFrontendToText = (frontend) => frontend === 'none'
|
|
37
36
|
? ''
|
|
@@ -58,15 +57,12 @@ ${contract === 'ts' && !install
|
|
|
58
57
|
- {inverse Build your contract}:
|
|
59
58
|
${contract === 'ts'
|
|
60
59
|
? (0, chalk_1.default) `{blue npm {bold run build}}`
|
|
61
|
-
: (0, chalk_1.default) `{blue {bold
|
|
60
|
+
: (0, chalk_1.default) `{blue {bold cargo near build}}`}
|
|
62
61
|
- {inverse Test your contract} in the Sandbox:
|
|
63
62
|
${contract === 'ts'
|
|
64
63
|
? (0, chalk_1.default) `{blue npm {bold run test}}`
|
|
65
|
-
: (0, chalk_1.default) `{blue {bold
|
|
66
|
-
|
|
67
|
-
${contract === 'ts'
|
|
68
|
-
? (0, chalk_1.default) `{blue npm {bold run deploy}}`
|
|
69
|
-
: (0, chalk_1.default) `{blue {bold ./deploy.sh}}`}
|
|
64
|
+
: (0, chalk_1.default) `{blue {bold cargo test}}`}
|
|
65
|
+
|
|
70
66
|
🧠 Read {bold {greenBright README.md}} to explore further`;
|
|
71
67
|
exports.contractInstructions = contractInstructions;
|
|
72
68
|
const gatewayInstructions = (projectName, frontend, install) => frontend === 'none'
|
|
@@ -84,7 +80,7 @@ exports.gatewayInstructions = gatewayInstructions;
|
|
|
84
80
|
const argsError = (msg) => (0, exports.show)((0, chalk_1.default) `{red Arguments error: {white ${msg}}}
|
|
85
81
|
|
|
86
82
|
Run {blue npx create-near-app} without arguments, or use:
|
|
87
|
-
npx create-near-app <projectName> [--frontend next|
|
|
83
|
+
npx create-near-app <projectName> [--frontend next-app|next-page] [--contract rs|ts|none]`);
|
|
88
84
|
exports.argsError = argsError;
|
|
89
85
|
const unsupportedNodeVersion = (supported) => (0, exports.show)((0, chalk_1.default) `{red We support node.js version ${supported} or later}`);
|
|
90
86
|
exports.unsupportedNodeVersion = unsupportedNodeVersion;
|
package/dist/tracking.js
CHANGED
|
@@ -10,7 +10,7 @@ const MIXPANEL_TOKEN = '24177ef1ec09ffea5cb6f68909c66a61';
|
|
|
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
12
|
// TODO: track different failures & install usage
|
|
13
|
-
const trackUsage = async (frontend, contract
|
|
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') {
|
|
16
16
|
console.log('Mixpanel logging is skipped in CI env');
|
|
@@ -20,7 +20,6 @@ const trackUsage = async (frontend, contract, testing) => {
|
|
|
20
20
|
const mixPanelProperties = {
|
|
21
21
|
frontend,
|
|
22
22
|
contract,
|
|
23
|
-
testing,
|
|
24
23
|
os: process.platform,
|
|
25
24
|
nodeVersion: process.versions.node,
|
|
26
25
|
timestamp: new Date().toString()
|
package/dist/types.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.APPS = exports.
|
|
3
|
+
exports.APPS = exports.FRONTENDS = exports.CONTRACTS = void 0;
|
|
4
4
|
exports.CONTRACTS = ['ts', 'rs', 'none'];
|
|
5
|
-
exports.FRONTENDS = ['next-app', 'next-page', '
|
|
6
|
-
exports.TESTING_FRAMEWORKS = ['rs', 'ts', 'none'];
|
|
5
|
+
exports.FRONTENDS = ['next-app', 'next-page', 'none'];
|
|
7
6
|
exports.APPS = ['contract', 'gateway'];
|
|
8
7
|
//# sourceMappingURL=types.js.map
|
package/dist/user-input.js
CHANGED
|
@@ -38,16 +38,15 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
38
38
|
async function getUserArgs() {
|
|
39
39
|
commander_1.program
|
|
40
40
|
.argument('[projectName]')
|
|
41
|
-
.option('--frontend [next|
|
|
41
|
+
.option('--frontend [next-page|next-app|none]')
|
|
42
42
|
.option('--contract [ts|rs|none]')
|
|
43
|
-
.option('--tests [rs|ts|none]')
|
|
44
43
|
.option('--install')
|
|
45
44
|
.addHelpText('after', 'You can create a frontend or a contract with tests');
|
|
46
45
|
commander_1.program.parse();
|
|
47
46
|
const options = commander_1.program.opts();
|
|
48
47
|
const [projectName] = commander_1.program.args;
|
|
49
|
-
const { contract, frontend,
|
|
50
|
-
return { contract, frontend, projectName,
|
|
48
|
+
const { contract, frontend, install } = options;
|
|
49
|
+
return { contract, frontend, projectName, install };
|
|
51
50
|
}
|
|
52
51
|
exports.getUserArgs = getUserArgs;
|
|
53
52
|
const appChoices = [
|
|
@@ -58,14 +57,9 @@ const contractChoices = [
|
|
|
58
57
|
{ title: 'JS/TS Contract', description: 'A Near contract written in javascript/typescript', value: 'ts' },
|
|
59
58
|
{ title: 'Rust Contract', description: 'A Near contract written in Rust', value: 'rs' },
|
|
60
59
|
];
|
|
61
|
-
const testsChoices = [
|
|
62
|
-
{ title: 'Tests written in Rust', value: 'rs' },
|
|
63
|
-
{ title: 'Tests written in Typescript', value: 'ts' },
|
|
64
|
-
];
|
|
65
60
|
const frontendChoices = [
|
|
66
61
|
{ title: 'NextJs (Classic)', description: 'A composable app built using Next.js, React and Near components', value: 'next-page' },
|
|
67
62
|
{ title: 'NextJS (App Router)', description: 'A composable app built using Next.js, React and Near components', value: 'next-app' },
|
|
68
|
-
{ title: 'Vanilla JS', description: 'A framework-less web app with limited capabilities.', value: 'vanilla' },
|
|
69
63
|
];
|
|
70
64
|
const appPrompt = {
|
|
71
65
|
type: 'select',
|
|
@@ -85,12 +79,6 @@ const contractPrompt = [
|
|
|
85
79
|
name: 'contract',
|
|
86
80
|
message: 'Select a smart contract template for your project',
|
|
87
81
|
choices: contractChoices,
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
type: prev => prev === 'rs' ? 'select' : null,
|
|
91
|
-
name: 'tests',
|
|
92
|
-
message: 'Sandbox Testing: Which language do you prefer to test your contract?',
|
|
93
|
-
choices: testsChoices,
|
|
94
82
|
}
|
|
95
83
|
];
|
|
96
84
|
const namePrompts = {
|
|
@@ -115,15 +103,14 @@ async function getUserAnswers() {
|
|
|
115
103
|
if (app === 'gateway') {
|
|
116
104
|
// If gateway, ask for the framework to use
|
|
117
105
|
const { frontend, projectName, install } = await promptUser([frontendPrompt, namePrompts, npmPrompt]);
|
|
118
|
-
return { frontend, contract: 'none',
|
|
106
|
+
return { frontend, contract: 'none', projectName, install };
|
|
119
107
|
}
|
|
120
108
|
else {
|
|
121
|
-
// If contract, ask for the language for the contract
|
|
122
|
-
let { contract
|
|
123
|
-
tests = contract === 'ts' ? 'ts' : tests;
|
|
109
|
+
// If contract, ask for the language for the contract
|
|
110
|
+
let { contract } = await promptUser(contractPrompt);
|
|
124
111
|
const { projectName } = await promptUser(namePrompts);
|
|
125
112
|
const install = contract === 'ts' ? (await promptUser(npmPrompt)).install : false;
|
|
126
|
-
return { frontend: 'none', contract,
|
|
113
|
+
return { frontend: 'none', contract, projectName, install };
|
|
127
114
|
}
|
|
128
115
|
}
|
|
129
116
|
exports.getUserAnswers = getUserAnswers;
|
|
@@ -145,12 +132,11 @@ async function promptAndGetConfig() {
|
|
|
145
132
|
// Homogenizing terminal args with prompt args
|
|
146
133
|
args.contract = args.contract || 'none';
|
|
147
134
|
args.frontend = args.frontend || 'none';
|
|
148
|
-
args.tests = args.tests || 'none';
|
|
149
135
|
if (!validateUserArgs(args))
|
|
150
136
|
return;
|
|
151
137
|
// track user input
|
|
152
|
-
const { frontend, contract
|
|
153
|
-
(0, tracking_1.trackUsage)(frontend, contract
|
|
138
|
+
const { frontend, contract } = args;
|
|
139
|
+
(0, tracking_1.trackUsage)(frontend, contract);
|
|
154
140
|
let path = (0, exports.projectPath)(args.projectName);
|
|
155
141
|
if (fs_1.default.existsSync(path)) {
|
|
156
142
|
return show.directoryExists(path);
|
|
@@ -169,10 +155,6 @@ const validateUserArgs = (args) => {
|
|
|
169
155
|
show.argsError(`Invalid contract type: ${args.contract}`);
|
|
170
156
|
return false;
|
|
171
157
|
}
|
|
172
|
-
if (!types_1.TESTING_FRAMEWORKS.includes(args.tests)) {
|
|
173
|
-
show.argsError(`Invalid testing framework: ${args.tests}`);
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
176
158
|
if (!args.projectName) {
|
|
177
159
|
show.argsError('Please provide a project name');
|
|
178
160
|
return false;
|
|
@@ -182,18 +164,6 @@ const validateUserArgs = (args) => {
|
|
|
182
164
|
show.argsError('Please create a contract OR a frontend');
|
|
183
165
|
return false;
|
|
184
166
|
}
|
|
185
|
-
if (args.contract !== 'none' && args.tests === 'none') {
|
|
186
|
-
show.argsError('Please select a testing framework for your contract');
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
if (args.frontend !== 'none' && args.tests !== 'none') {
|
|
190
|
-
show.argsError('Remove the --tests flag when creating a frontend');
|
|
191
|
-
return false;
|
|
192
|
-
}
|
|
193
|
-
if (args.contract === 'ts' && args.tests === 'rs') {
|
|
194
|
-
show.argsError('We currently do not support creating a contract in TS with Rust tests, please create it manually');
|
|
195
|
-
return false;
|
|
196
|
-
}
|
|
197
167
|
return true;
|
|
198
168
|
};
|
|
199
169
|
//# sourceMappingURL=user-input.js.map
|
package/package.json
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
[package]
|
|
2
|
-
name = "
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
name = "contract-rs"
|
|
3
|
+
description = "Hello Near Example"
|
|
4
|
+
version = "0.1.0"
|
|
5
5
|
edition = "2021"
|
|
6
|
+
# TODO: Fill out the repository field to help NEAR ecosystem tools to discover your project.
|
|
7
|
+
# NEP-0330 is automatically implemented for all contracts built with https://github.com/near/cargo-near.
|
|
8
|
+
# Link to the repository will be available via `contract_source_metadata` view-function.
|
|
9
|
+
#repository = "https://github.com/xxx/xxx"
|
|
6
10
|
|
|
7
11
|
[lib]
|
|
8
|
-
crate-type = ["cdylib"]
|
|
12
|
+
crate-type = ["cdylib", "rlib"]
|
|
9
13
|
|
|
14
|
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
10
15
|
[dependencies]
|
|
11
|
-
near-sdk = "
|
|
12
|
-
uint = { version = "0.9.3", default-features = false }
|
|
16
|
+
near-sdk = "5.1.0"
|
|
13
17
|
|
|
14
|
-
[
|
|
15
|
-
|
|
18
|
+
[dev-dependencies]
|
|
19
|
+
near-sdk = { version = "5.1.0", features = ["unit-testing"] }
|
|
20
|
+
near-workspaces = { version = "0.10.0", features = ["unstable"] }
|
|
21
|
+
tokio = { version = "1.12.0", features = ["full"] }
|
|
22
|
+
serde_json = "1"
|
|
16
23
|
|
|
17
24
|
[profile.release]
|
|
18
25
|
codegen-units = 1
|
|
26
|
+
# Tell `rustc` to optimize for small code size.
|
|
19
27
|
opt-level = "z"
|
|
20
28
|
lto = true
|
|
21
29
|
debug = false
|
|
22
30
|
panic = "abort"
|
|
31
|
+
# Opt into extra safety checks on arithmetic operations https://stackoverflow.com/a/64136471/249801
|
|
23
32
|
overflow-checks = true
|
|
@@ -1,100 +1,39 @@
|
|
|
1
|
-
#
|
|
1
|
+
# contract-rs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
cargo-near-new-project-description
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
const DEFAULT_GREETING: &str = "Hello";
|
|
5
|
+
## How to Build Locally?
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
#[derive(BorshDeserialize, BorshSerialize)]
|
|
10
|
-
pub struct Contract {
|
|
11
|
-
greeting: String,
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
impl Default for Contract {
|
|
15
|
-
fn default() -> Self {
|
|
16
|
-
Self { greeting: DEFAULT_GREETING.to_string() }
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
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
|
-
}
|
|
26
|
-
|
|
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
|
-
```
|
|
35
|
-
|
|
36
|
-
<br />
|
|
37
|
-
|
|
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, Test and Deploy
|
|
46
|
-
To build the contract you can execute the `./build.sh` script, which will in turn run:
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
rustup target add wasm32-unknown-unknown
|
|
50
|
-
cargo build --target wasm32-unknown-unknown --release
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Then, run the `./deploy.sh` script, which will in turn run:
|
|
7
|
+
Install [`cargo-near`](https://github.com/near/cargo-near) and run:
|
|
54
8
|
|
|
55
9
|
```bash
|
|
56
|
-
near
|
|
10
|
+
cargo near build
|
|
57
11
|
```
|
|
58
12
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
Once finished, check the `./neardev/dev-account` file to find the address in which the contract was deployed:
|
|
13
|
+
## How to Test Locally?
|
|
62
14
|
|
|
63
15
|
```bash
|
|
64
|
-
|
|
65
|
-
# e.g. dev-1659899566943-21539992274727
|
|
16
|
+
cargo test
|
|
66
17
|
```
|
|
67
18
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
## 2. Retrieve the Greeting
|
|
19
|
+
## How to Deploy?
|
|
71
20
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
`View` methods can be called for **free** by anyone, even people **without a NEAR account**!
|
|
21
|
+
To deploy manually, install [`cargo-near`](https://github.com/near/cargo-near) and run:
|
|
75
22
|
|
|
76
23
|
```bash
|
|
77
|
-
#
|
|
78
|
-
near
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
<br />
|
|
82
|
-
|
|
83
|
-
## 3. Store a New Greeting
|
|
84
|
-
`set_greeting` changes the contract's state, for which it is a `change` method.
|
|
85
|
-
|
|
86
|
-
`Change` methods can only be invoked using a NEAR account, since the account needs to pay GAS for the transaction. In this case, we are asking the account we created in step 1 to sign the transaction.
|
|
24
|
+
# Create a new account
|
|
25
|
+
cargo near create-dev-account
|
|
87
26
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
near call <dev-account> set_greeting '{"greeting":"howdy"}' --accountId <dev-account>
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
**Tip:** If you would like to call `set_greeting` using your own account, first login into NEAR using:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
# Use near-cli to login your NEAR account
|
|
97
|
-
near login
|
|
27
|
+
# Deploy the contract on it
|
|
28
|
+
cargo near deploy <account-id>
|
|
98
29
|
```
|
|
99
|
-
|
|
100
|
-
|
|
30
|
+
## Useful Links
|
|
31
|
+
|
|
32
|
+
- [cargo-near](https://github.com/near/cargo-near) - NEAR smart contract development toolkit for Rust
|
|
33
|
+
- [near CLI](https://docs.near.org/tools/near-cli) - Interact with NEAR blockchain from command line
|
|
34
|
+
- [NEAR Rust SDK Documentation](https://docs.near.org/sdk/rust/introduction)
|
|
35
|
+
- [NEAR Documentation](https://docs.near.org)
|
|
36
|
+
- [NEAR StackOverflow](https://stackoverflow.com/questions/tagged/nearprotocol)
|
|
37
|
+
- [NEAR Discord](https://near.chat)
|
|
38
|
+
- [NEAR Telegram Developers Community Group](https://t.me/neardev)
|
|
39
|
+
- NEAR DevHub: [Telegram](https://t.me/neardevhub), [Twitter](https://twitter.com/neardevhub)
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
// Find all our documentation at https://docs.near.org
|
|
2
|
-
use near_sdk::
|
|
3
|
-
use near_sdk::env::log_str;
|
|
4
|
-
use near_sdk::near_bindgen;
|
|
2
|
+
use near_sdk::{log, near};
|
|
5
3
|
|
|
6
4
|
// Define the contract structure
|
|
7
|
-
#[
|
|
8
|
-
#[derive(BorshDeserialize, BorshSerialize)]
|
|
5
|
+
#[near(contract_state)]
|
|
9
6
|
pub struct Contract {
|
|
10
7
|
greeting: String,
|
|
11
8
|
}
|
|
@@ -13,21 +10,23 @@ pub struct Contract {
|
|
|
13
10
|
// Define the default, which automatically initializes the contract
|
|
14
11
|
impl Default for Contract {
|
|
15
12
|
fn default() -> Self {
|
|
16
|
-
Self {
|
|
13
|
+
Self {
|
|
14
|
+
greeting: "Hello".to_string(),
|
|
15
|
+
}
|
|
17
16
|
}
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
// Implement the contract structure
|
|
21
|
-
#[
|
|
20
|
+
#[near]
|
|
22
21
|
impl Contract {
|
|
23
22
|
// Public method - returns the greeting saved, defaulting to DEFAULT_GREETING
|
|
24
23
|
pub fn get_greeting(&self) -> String {
|
|
25
|
-
|
|
24
|
+
self.greeting.clone()
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
// Public method - accepts a greeting, such as "howdy", and records it
|
|
29
28
|
pub fn set_greeting(&mut self, greeting: String) {
|
|
30
|
-
|
|
29
|
+
log!("Saving greeting: {greeting}");
|
|
31
30
|
self.greeting = greeting;
|
|
32
31
|
}
|
|
33
32
|
}
|
|
@@ -44,19 +43,13 @@ mod tests {
|
|
|
44
43
|
fn get_default_greeting() {
|
|
45
44
|
let contract = Contract::default();
|
|
46
45
|
// this test did not call set_greeting so should return the default "Hello" greeting
|
|
47
|
-
assert_eq!(
|
|
48
|
-
contract.get_greeting(),
|
|
49
|
-
"Hello".to_string()
|
|
50
|
-
);
|
|
46
|
+
assert_eq!(contract.get_greeting(), "Hello");
|
|
51
47
|
}
|
|
52
48
|
|
|
53
49
|
#[test]
|
|
54
50
|
fn set_then_get_greeting() {
|
|
55
51
|
let mut contract = Contract::default();
|
|
56
52
|
contract.set_greeting("howdy".to_string());
|
|
57
|
-
assert_eq!(
|
|
58
|
-
contract.get_greeting(),
|
|
59
|
-
"howdy".to_string()
|
|
60
|
-
);
|
|
53
|
+
assert_eq!(contract.get_greeting(), "howdy");
|
|
61
54
|
}
|
|
62
55
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
use near_sdk::NearToken;
|
|
2
|
+
use serde_json::json;
|
|
3
|
+
|
|
4
|
+
const FIVE_NEAR: NearToken = NearToken::from_near(5);
|
|
5
|
+
|
|
6
|
+
#[tokio::test]
|
|
7
|
+
async fn test_contract_is_operational() -> Result<(), Box<dyn std::error::Error>> {
|
|
8
|
+
let sandbox = near_workspaces::sandbox().await?;
|
|
9
|
+
let contract_wasm = near_workspaces::compile_project("./").await?;
|
|
10
|
+
|
|
11
|
+
let root = sandbox.root_account()?;
|
|
12
|
+
|
|
13
|
+
let user_account = root.create_subaccount("user").transact().await?.unwrap();
|
|
14
|
+
let contract_account = root.create_subaccount("contract").initial_balance(FIVE_NEAR).transact().await?.unwrap();
|
|
15
|
+
|
|
16
|
+
let contract = contract_account.deploy(&contract_wasm).await?.unwrap();
|
|
17
|
+
|
|
18
|
+
let outcome = user_account
|
|
19
|
+
.call(contract.id(), "set_greeting")
|
|
20
|
+
.args_json(json!({"greeting": "Hello World!"}))
|
|
21
|
+
.transact()
|
|
22
|
+
.await?;
|
|
23
|
+
assert!(outcome.is_success());
|
|
24
|
+
|
|
25
|
+
let user_message_outcome = contract
|
|
26
|
+
.view("get_greeting")
|
|
27
|
+
.args_json(json!({}))
|
|
28
|
+
.await?;
|
|
29
|
+
assert_eq!(user_message_outcome.json::<String>()?, "Hello World!");
|
|
30
|
+
|
|
31
|
+
Ok(())
|
|
32
|
+
}
|
|
@@ -30,24 +30,27 @@ class HelloNear {
|
|
|
30
30
|
|
|
31
31
|
<br />
|
|
32
32
|
|
|
33
|
-
## 1. Build and
|
|
34
|
-
You can automatically compile and
|
|
33
|
+
## 1. Build and Test the Contract
|
|
34
|
+
You can automatically compile and test the contract by running:
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
37
|
npm run build
|
|
38
|
-
npm run deploy
|
|
39
38
|
```
|
|
40
39
|
|
|
41
|
-
|
|
40
|
+
<br />
|
|
41
|
+
|
|
42
|
+
## 2. Create an Account and Deploy the Contract
|
|
43
|
+
You can create a new account and deploy the contract by running:
|
|
42
44
|
|
|
43
45
|
```bash
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
near create-account <your-account.testnet> --useFaucet
|
|
47
|
+
near deploy <your-account.testnet> build/release/hello_near.wasm
|
|
46
48
|
```
|
|
47
49
|
|
|
48
50
|
<br />
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
|
|
53
|
+
## 3. Retrieve the Greeting
|
|
51
54
|
|
|
52
55
|
`get_greeting` is a read-only method (aka `view` method).
|
|
53
56
|
|
|
@@ -55,26 +58,26 @@ cat ./neardev/dev-account
|
|
|
55
58
|
|
|
56
59
|
```bash
|
|
57
60
|
# Use near-cli to get the greeting
|
|
58
|
-
near view <
|
|
61
|
+
near view <your-account.testnet> get_greeting
|
|
59
62
|
```
|
|
60
63
|
|
|
61
64
|
<br />
|
|
62
65
|
|
|
63
|
-
##
|
|
66
|
+
## 4. Store a New Greeting
|
|
64
67
|
`set_greeting` changes the contract's state, for which it is a `call` method.
|
|
65
68
|
|
|
66
69
|
`Call` methods can only be invoked using a NEAR account, since the account needs to pay GAS for the transaction.
|
|
67
70
|
|
|
68
71
|
```bash
|
|
69
72
|
# Use near-cli to set a new greeting
|
|
70
|
-
near call <
|
|
73
|
+
near call <your-account.testnet> set_greeting '{"greeting":"howdy"}' --accountId <your-account.testnet>
|
|
71
74
|
```
|
|
72
75
|
|
|
73
|
-
**Tip:** If you would like to call `set_greeting` using
|
|
76
|
+
**Tip:** If you would like to call `set_greeting` using another account, first login into NEAR using:
|
|
74
77
|
|
|
75
78
|
```bash
|
|
76
79
|
# Use near-cli to login your NEAR account
|
|
77
80
|
near login
|
|
78
81
|
```
|
|
79
82
|
|
|
80
|
-
and then use the logged account to sign the transaction: `--accountId <
|
|
83
|
+
and then use the logged account to sign the transaction: `--accountId <another-account>`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require('util').inspect.defaultOptions.depth = 5; // Increase AVA's printing depth
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
timeout: '10000',
|
|
5
|
+
files: ['sandbox-ts/*.ava.ts'],
|
|
6
|
+
failWithoutAssertions: false,
|
|
7
|
+
extensions: {
|
|
8
|
+
js: true,
|
|
9
|
+
ts: 'module'
|
|
10
|
+
},
|
|
11
|
+
require: ['ts-node/register', 'near-workspaces'],
|
|
12
|
+
"nodeArguments": [
|
|
13
|
+
"--import=tsimp"
|
|
14
|
+
]
|
|
15
|
+
};
|