Skip to content
Open

V9 #2186

Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/add-to-devrel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
name: Add issue/PR to project
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected].0
- uses: actions/[email protected].2
with:
# add to DevRel Project #117
project-url: https://github.com/orgs/near/projects/117
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ jobs:
eslint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install modules
run: npm install
- name: Run ESLint
Expand Down
9 changes: 5 additions & 4 deletions .github/workflows/test-contract-rs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@ jobs:
strategy:
matrix:
platform: [ubuntu-latest]
template: [auction, auction-adv]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install modules
run: npm install
- name: Create Contract RS
run: npm run start -- hello-near --frontend none --contract rs
- name: Create Contract RS - ${{ matrix.template }}
run: npm run start -- test-app --frontend none --contract rs --template ${{ matrix.template }}
- name: Install cargo-near
run: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/near/cargo-near/releases/latest/download/cargo-near-installer.sh | sh
- name: Run tests
run: cd hello-near && cargo test
run: cd test-app && cargo test
13 changes: 9 additions & 4 deletions .github/workflows/test-contract-ts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ jobs:
strategy:
matrix:
platform: [ubuntu-latest, macos-latest]
node-version: [18, 20, 22]
node-version: [24, 26]
template: [auction, auction-adv]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
Expand All @@ -16,7 +17,11 @@ jobs:
node-version: ${{ matrix.node-version }}
- name: Install modules
run: npm install
- name: Create Contract TS
run: npm run start -- hello-near --frontend none --contract ts
- name: Create Contract TS - ${{ matrix.template }}
run: npm run start -- test-app --frontend none --contract ts --template ${{ matrix.template }}
- name: Install test app dependencies
working-directory: test-app
run: npm install
- name: Run tests
run: cd hello-near && npm install && npm run test
working-directory: test-app
run: npm run test
7 changes: 4 additions & 3 deletions .github/workflows/test-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ jobs:
matrix:
platform: [ubuntu-latest, macos-latest]
node-version: [18, 20, 22]
frontend: [next-page, next-app, vite-react]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
Expand All @@ -16,7 +17,7 @@ jobs:
node-version: ${{ matrix.node-version }}
- name: Install modules
run: npm install
- name: Create Frontend No Components
run: npm run start -- hello-near --frontend next-page
- name: Create Frontend - ${{ matrix.frontend }}
run: npm run start -- test-app --frontend ${{ matrix.frontend }}
- name: Install
run: cd hello-near && npm install
run: cd test-app && npm install
2 changes: 1 addition & 1 deletion .github/workflows/test-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
platform: [ubuntu-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@types/jest": "^29.5.2",
"@types/ncp": "^2.0.5",
"@types/node": "^20.3.2",
"@types/node-dir": "^0.0.37",
"@types/prompts": "^2.4.4",
"@types/semver": "^7.5.0",
"eslint": "^8.43.0",
Expand Down
2 changes: 2 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { isCargoNearInstalled } from './utils';
config: {
projectName,
contract,
template,
frontend,
install,
},
Expand All @@ -32,6 +33,7 @@ import { isCargoNearInstalled } from './utils';
try {
createSuccess = await createProject({
contract,
template: template || 'auction',
frontend,
templatesDir: path.resolve(__dirname, '../templates'),
projectPath,
Expand Down
15 changes: 7 additions & 8 deletions src/make.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,26 @@ import * as show from './messages';
import { downloadFile } from './utils';
import { CreateContractParams, CreateGatewayParams } from './types';

export async function createProject({ contract, frontend, projectPath, templatesDir }: CreateContractParams & CreateGatewayParams): Promise<boolean> {
export async function createProject({ contract, template, frontend, projectPath, templatesDir }: CreateContractParams & CreateGatewayParams): Promise<boolean> {
if (contract !== 'none') {
await createContract({ contract, projectPath, templatesDir });
} else {
await createContract({ contract, template, projectPath, templatesDir });
} else if (frontend !== 'none') {
await createGateway({ frontend, projectPath, templatesDir });
}

return true;
}

async function createContract({ contract, projectPath, templatesDir }: CreateContractParams) {
await createContractFromTemplate({ contract, projectPath, templatesDir });
async function createContract({ contract, template, projectPath, templatesDir }: CreateContractParams) {
await createContractFromTemplate({ contract, template, projectPath, templatesDir });

if (contract === 'rs') {
await updateTemplateFiles(projectPath);
}
}

async function createContractFromTemplate({ contract, projectPath, templatesDir }: CreateContractParams) {
// contract folder
const sourceContractDir = path.resolve(templatesDir, 'contracts', contract);
async function createContractFromTemplate({ contract, template, projectPath, templatesDir }: CreateContractParams) {
const sourceContractDir = path.resolve(templatesDir, 'contracts', template, contract);
fs.mkdirSync(projectPath, { recursive: true });
await copyDir(sourceContractDir, projectPath);
}
Expand Down
6 changes: 0 additions & 6 deletions src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ const mapContractLanguage = (contract: Contract) => {
return 'Typescript';
case 'rs':
return 'Rust';
case 'py':
return 'Python';
default:
return '';
}
Expand Down Expand Up @@ -104,8 +102,6 @@ export const contractInstructions = (

if (contract === 'ts') {
message += chalk` {blue npm {bold run build}}\n`;
} else if (contract === 'py') {
message += chalk` {blue {bold uvx nearc contract.py --create-venv}}\n`;
} else {
message += chalk` {blue {bold cargo near build}}\n`;
}
Expand All @@ -114,8 +110,6 @@ export const contractInstructions = (

if (contract === 'ts') {
message += chalk` {blue npm {bold run test}}\n`;
} else if (contract === 'py') {
message += chalk` {blue {bold uv run pytest}}\n`;
} else {
message += chalk` {blue {bold cargo near test}}\n`;
}
Expand Down
9 changes: 7 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export type Contract = 'ts' | 'rs' | 'py' |'none';
export const CONTRACTS: Contract[] = ['ts', 'rs', 'py', 'none'];
export type Contract = 'ts' | 'rs' | 'none';
export const CONTRACTS: Contract[] = ['ts', 'rs', 'none'];

export type Template = 'auction' | 'auction-adv';
export const TEMPLATES: Template[] = ['auction', 'auction-adv'];

export type Frontend = 'next-app' | 'next-page' | 'vite-react' | 'none';
export const FRONTENDS: Frontend[] = ['next-app', 'next-page', 'vite-react', 'none'];
Expand All @@ -11,6 +14,7 @@ export type ProjectName = string;

export interface UserConfig {
contract: Contract;
template?: Template;
frontend: Frontend;
projectName: ProjectName;
install: boolean;
Expand All @@ -19,6 +23,7 @@ export interface UserConfig {

export type CreateContractParams = {
contract: Contract,
template: Template,
projectPath: string,
templatesDir: string,
}
Expand Down
42 changes: 34 additions & 8 deletions src/user-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {
App,
Contract,
CONTRACTS,
Template,
TEMPLATES,
Frontend,
FRONTENDS,
ProjectName,
Expand All @@ -17,17 +19,18 @@ import fs from 'fs';
export async function getUserArgs(): Promise<UserConfig> {
program
.argument('[projectName]')
.option('--frontend [next-page|next-app|none]')
.option('--frontend [next-page|next-app|vite-react|none]')
.option('--contract [ts|rs|none]')
.option('--template [auction-adv|auction]')
.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, install } = options;
return { contract, frontend, projectName, install, error: undefined };
const { contract, frontend, template, install } = options;
return { contract, frontend, template, projectName, install, error: undefined };
}

type Choices<T> = { title: string, description?: string, value: T }[];
Expand All @@ -38,10 +41,15 @@ const appChoices: Choices<App> = [
title: 'A Smart Contract', description: 'A smart contract to be deployed in the Near Blockchain', value: 'contract',
},
];

const templateChoices: Choices<Template> = [
{ title: 'Auction', description: 'A simple auction smart contract', value: 'auction' },
{ title: 'Auction (advance)', description: 'An auction contract were users can bid with FT and the winner gets a NFT', value: 'auction-adv' },
];

const contractChoices: Choices<Contract> = [
{ title: 'JS/TS Contract', description: 'A Near contract written in javascript/typescript', value: 'ts' },
{ title: 'TS Contract', description: 'A Near contract written in typescript', value: 'ts' },
{ title: 'Rust Contract', description: 'A Near contract written in Rust', value: 'rs' },
{ title: 'Python Contract', description: 'A Near contract written in Python', value: 'py' },
];

const frontendChoices: Choices<Frontend> = [
Expand All @@ -57,6 +65,13 @@ const appPrompt: PromptObject = {
choices: appChoices,
};

const templatePrompt: PromptObject = {
type: 'select',
name: 'template',
message: 'Select a contract template',
choices: templateChoices,
};

const frontendPrompt: PromptObject = {
type: 'select',
name: 'frontend',
Expand All @@ -68,7 +83,7 @@ const contractPrompt: PromptObject[] = [
{
type: 'select',
name: 'contract',
message: 'Select a smart contract template for your project',
message: 'Select a language for your contract',
choices: contractChoices,
}
];
Expand Down Expand Up @@ -106,12 +121,13 @@ export async function getUserAnswers(): Promise<UserConfig> {
return { frontend: 'none', contract: 'none', projectName: '', install: false, error: show.windowsWarning };
}

// If contract, ask for the language for the contract
// If contract, ask for the template and language
const { template } = await promptUser(templatePrompt);
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, projectName, install, error: undefined };
return { frontend: 'none', contract, template, projectName, install, error: undefined };
}
}

Expand Down Expand Up @@ -164,6 +180,11 @@ const validateUserArgs = (args: UserConfig) => {
return false;
}

if (args.template && !TEMPLATES.includes(args.template)) {
show.argsError(`Invalid template type: ${args.template}`);
return false;
}

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

if (args.contract !== 'none' && !args.template) {
show.argsError('Please specify a template for your contract');
return false;
}

return true;
};
26 changes: 26 additions & 0 deletions templates/contracts/auction-adv/rs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "auction-contract"
description = "Auction Example Part 3"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib", "rlib"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
near-sdk = "5.17"

[dev-dependencies]
near-sdk = { version = "5.17", features = ["unit-testing"] }
near-workspaces = { version = "0.21", features = ["unstable"] }
tokio = { version = "1.12.0", features = ["full"] }
serde_json = "1"

[profile.release]
codegen-units = 1
opt-level = "z"
lto = true
debug = false
panic = "abort"
overflow-checks = true
35 changes: 35 additions & 0 deletions templates/contracts/auction-adv/rs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Auction contract with FTs

This directory contains a Rust contract that is used as part of the [Bidding with FTs](https://docs.near.org/tutorials/auction/bidding-with-fts) section of the auction tutorial.

In this part the contract is adapted so users can bid in fungible tokens (FTs) instead of NEAR tokens. It is a great way to learn how to work with FTs in NEAR.

## How to Build Locally?

Install [`cargo-near`](https://github.com/near/cargo-near) and run:

```bash
cargo near build
```

## How to Test Locally?

```bash
cargo test
```

## How to Deploy?

To deploy manually, install [NEAR CLI](https://docs.near.org/tools/near-cli#installation) and run:

```bash
# Create a new account
near create <contractId> --useFaucet

# Deploy the contract on it
near deploy <contractId> ./target/near/auction-contract.wasm

# Initialize the contract
TWO_MINUTES_FROM_NOW=$(date -v+2M +%s000000000)
near call <contractId> init '{"end_time": "'$TWO_MINUTES_FROM_NOW'", "auctioneer": "<auctioneerAccountId>", "ft_contract": "<ftContractId>", "nft_contract": "<nftContractId>", "token_id": "<tokenId>", "starting_price": "<startingPrice>"}' --accountId <contractId>
```
4 changes: 4 additions & 0 deletions templates/contracts/auction-adv/rs/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[toolchain]
channel = "stable"
components = ["rustfmt"]
targets = ["wasm32-unknown-unknown"]
Loading
Loading