Skip to content

Commit

Permalink
feat: update contracts (#2136)
Browse files Browse the repository at this point in the history
  • Loading branch information
matiasbenary authored Apr 5, 2024
1 parent 06aa902 commit 86f6799
Show file tree
Hide file tree
Showing 44 changed files with 29,252 additions and 11,552 deletions.
2 changes: 0 additions & 2 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import * as show from './messages';
projectName,
contract,
frontend,
tests,
install,
},
projectPath,
Expand All @@ -25,7 +24,6 @@ import * as show from './messages';
createSuccess = await createProject({
contract,
frontend,
tests,
templatesDir: path.resolve(__dirname, '../templates'),
projectPath,
});
Expand Down
32 changes: 4 additions & 28 deletions src/make.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,23 @@ import fs from 'fs';
import { ncp } from 'ncp';
import path from 'path';

export async function createProject({ contract, frontend, tests, projectPath, templatesDir }: CreateContractParams & CreateGatewayParams): Promise<boolean> {
export async function createProject({ contract, frontend, projectPath, templatesDir }: CreateContractParams & CreateGatewayParams): Promise<boolean> {

if (contract !== 'none') {
await createContract({ contract, tests, projectPath, templatesDir });
await createContract({ contract, projectPath, templatesDir });
} else {
await createGateway({ frontend, projectPath, templatesDir });
}

return true;
}

async function createContract({ contract, tests, projectPath, templatesDir }: CreateContractParams) {
async function createContract({ contract, projectPath, templatesDir }: CreateContractParams) {
// contract folder
const sourceContractDir = path.resolve(templatesDir, 'contracts', contract);
fs.mkdirSync(projectPath, { recursive: true });
await copyDir(sourceContractDir, projectPath);

// copy sandbox-test dir
const targetTestDir = path.resolve(projectPath, `sandbox-${tests}`);
const sourceTestDir = path.resolve(`${templatesDir}/sandbox-tests/sandbox-${tests}`);

fs.mkdirSync(targetTestDir);
await copyDir(sourceTestDir, targetTestDir);

if (contract === 'rs') {
if (tests === 'rs') {
// leave only one test script
fs.unlinkSync(path.resolve(projectPath, 'test-ts.sh'));
fs.renameSync(path.resolve(projectPath, 'test-rs.sh'), path.resolve(projectPath, 'test.sh'));

// add workspace to Cargo.toml
const cargoTomlPath = path.resolve(projectPath, 'Cargo.toml');
const cargoToml = fs.readFileSync(cargoTomlPath).toString();
const cargoTomlWithWorkspace = cargoToml + '\n[workspace]\nmembers = ["sandbox-rs"]';
fs.writeFileSync(cargoTomlPath, cargoTomlWithWorkspace);
} else {
// leave only one test script
fs.unlinkSync(path.resolve(projectPath, 'test-rs.sh'));
fs.renameSync(path.resolve(projectPath, 'test-ts.sh'), path.resolve(projectPath, 'test.sh'));
}
}

}

async function createGateway({ frontend, projectPath, templatesDir }: CreateGatewayParams) {
Expand Down
13 changes: 4 additions & 9 deletions src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,15 @@ ${
${
contract === 'ts'
? chalk`{blue npm {bold run build}}`
: chalk`{blue {bold ./build.sh}}`
: chalk`{blue {bold cargo near build}}`
}
- {inverse Test your contract} in the Sandbox:
${
contract === 'ts'
? chalk`{blue npm {bold run test}}`
: chalk`{blue {bold ./test.sh}}`
}
- {inverse Deploy your contract} to NEAR TestNet with a temporary dev account:
${
contract === 'ts'
? chalk`{blue npm {bold run deploy}}`
: chalk`{blue {bold ./deploy.sh}}`
: chalk`{blue {bold cargo test}}`
}
🧠 Read {bold {greenBright README.md}} to explore further`;

export const gatewayInstructions = (
Expand All @@ -123,7 +118,7 @@ export const argsError = (msg: string) =>
show(chalk`{red Arguments error: {white ${msg}}}
Run {blue npx create-near-app} without arguments, or use:
npx create-near-app <projectName> [--frontend next|vanilla|none] [--contract rs|ts|none --tests rs|ts|none]`);
npx create-near-app <projectName> [--frontend next|vanilla|none] [--contract rs|ts|none]`);

export const unsupportedNodeVersion = (supported: string) =>
show(chalk`{red We support node.js version ${supported} or later}`);
Expand Down
5 changes: 2 additions & 3 deletions src/tracking.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Contract, Frontend, TestingFramework} from './types';
import {Contract, Frontend} from './types';
import chalk from 'chalk';
import mixpanel from 'mixpanel';

Expand All @@ -9,7 +9,7 @@ const tracker = mixpanel.init(MIXPANEL_TOKEN);
export const trackingMessage = chalk`Near collects anonymous information on the commands used. No personal information that could identify you is shared`;

// TODO: track different failures & install usage
export const trackUsage = async (frontend: Frontend, contract: Contract, testing: TestingFramework) => {
export const trackUsage = async (frontend: Frontend, contract: Contract) => {
// prevents logging from CI
if (process.env.NEAR_ENV === 'ci' || process.env.NODE_ENV === 'ci') {
console.log('Mixpanel logging is skipped in CI env');
Expand All @@ -19,7 +19,6 @@ export const trackUsage = async (frontend: Frontend, contract: Contract, testing
const mixPanelProperties = {
frontend,
contract,
testing,
os: process.platform,
nodeVersion: process.versions.node,
timestamp: new Date().toString()
Expand Down
4 changes: 0 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,18 @@ export type Contract = 'ts' | 'rs' | 'none';
export const CONTRACTS: Contract[] = ['ts', 'rs', 'none'];
export type Frontend = 'next-app' | 'next-page' | 'vanilla' | 'none';
export const FRONTENDS: Frontend[] = ['next-app' , 'next-page', 'vanilla', 'none'];
export type TestingFramework = 'rs' | 'ts' | 'none';
export const TESTING_FRAMEWORKS: TestingFramework[] = ['rs', 'ts', 'none'];
export type App = 'contract' | 'gateway';
export const APPS: App[] = ['contract', 'gateway'];
export type ProjectName = string;
export interface UserConfig {
contract: Contract;
frontend: Frontend;
projectName: ProjectName;
tests: TestingFramework;
install: boolean;
}

export type CreateContractParams = {
contract: Contract,
tests: TestingFramework,
projectPath: string,
templatesDir: string,
}
Expand Down
52 changes: 9 additions & 43 deletions src/user-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import {
Frontend,
FRONTENDS,
ProjectName,
TESTING_FRAMEWORKS,
TestingFramework,
UserConfig
} from './types';
import chalk from 'chalk';
Expand All @@ -22,16 +20,15 @@ export async function getUserArgs(): Promise<UserConfig> {
.argument('[projectName]')
.option('--frontend [next|vanilla|none]')
.option('--contract [ts|rs|none]')
.option('--tests [rs|ts|none]')
.option('--install')
.addHelpText('after', 'You can create a frontend or a contract with tests');

program.parse();

const options = program.opts();
const [projectName] = program.args;
const { contract, frontend, tests, install } = options;
return { contract, frontend, projectName, tests, install };
const { contract, frontend, install } = options;
return { contract, frontend, projectName, install };
}

type Choices<T> = { title: string, description?: string, value: T }[];
Expand All @@ -44,10 +41,6 @@ const contractChoices: Choices<Contract> = [
{ title: 'JS/TS Contract', description: 'A Near contract written in javascript/typescript', value: 'ts' },
{ title: 'Rust Contract', description: 'A Near contract written in Rust', value: 'rs' },
];
const testsChoices: Choices<TestingFramework> = [
{ title: 'Tests written in Rust', value: 'rs' },
{ title: 'Tests written in Typescript', value: 'ts' },
];

const frontendChoices: Choices<Frontend> = [
{ title: 'NextJs (Classic)', description: 'A composable app built using Next.js, React and Near components', value: 'next-page' },
Expand Down Expand Up @@ -75,12 +68,6 @@ const contractPrompt: PromptObject[] = [
name: 'contract',
message: 'Select a smart contract template for your project',
choices: contractChoices,
},
{
type: prev => prev === 'rs' ? 'select' : null,
name: 'tests',
message: 'Sandbox Testing: Which language do you prefer to test your contract?',
choices: testsChoices,
}
];

Expand Down Expand Up @@ -110,14 +97,14 @@ export async function getUserAnswers(): Promise<UserConfig> {
if (app === 'gateway') {
// If gateway, ask for the framework to use
const { frontend, projectName, install } = await promptUser([frontendPrompt, namePrompts, npmPrompt]);
return { frontend, contract: 'none', tests: 'none', projectName, install };
return { frontend, contract: 'none', projectName, install };
} else {
// If contract, ask for the language for the contract and tests
let { contract, tests } = await promptUser(contractPrompt);
tests = contract === 'ts' ? 'ts' : tests;
// If contract, ask for the language for the contract
let { contract } = await promptUser(contractPrompt);

const { projectName } = await promptUser(namePrompts);
const install = contract === 'ts' ? (await promptUser(npmPrompt)).install as boolean : false;
return { frontend: 'none', contract, tests, projectName, install };
return { frontend: 'none', contract, projectName, install };
}
}

Expand All @@ -143,13 +130,12 @@ export async function promptAndGetConfig(): Promise<{ config: UserConfig, projec
// Homogenizing terminal args with prompt args
args.contract = args.contract || 'none';
args.frontend = args.frontend || 'none';
args.tests = args.tests || 'none';

if (!validateUserArgs(args)) return;

// track user input
const { frontend, contract, tests } = args;
trackUsage(frontend, contract, tests);
const { frontend, contract } = args;
trackUsage(frontend, contract);

let path = projectPath(args.projectName);

Expand All @@ -174,11 +160,6 @@ const validateUserArgs = (args: UserConfig) => {
return false;
}

if (!TESTING_FRAMEWORKS.includes(args.tests)) {
show.argsError(`Invalid testing framework: ${args.tests}`);
return false;
}

if (!args.projectName) {
show.argsError('Please provide a project name');
return false;
Expand All @@ -190,20 +171,5 @@ const validateUserArgs = (args: UserConfig) => {
return false;
}

if (args.contract !== 'none' && args.tests === 'none') {
show.argsError('Please select a testing framework for your contract');
return false;
}

if (args.frontend !== 'none' && args.tests !== 'none') {
show.argsError('Remove the --tests flag when creating a frontend');
return false;
}

if (args.contract === 'ts' && args.tests === 'rs') {
show.argsError('We currently do not support creating a contract in TS with Rust tests, please create it manually');
return false;
}

return true;
};
2 changes: 0 additions & 2 deletions templates/contracts/rs/.cargo/config

This file was deleted.

1 change: 0 additions & 1 deletion templates/contracts/rs/.gitignore

This file was deleted.

Loading

0 comments on commit 86f6799

Please sign in to comment.