├── airdrop
└── smart-contract
│ ├── .env.example
│ ├── .gitignore
│ ├── assembly
│ ├── __tests__
│ │ └── as-pect.d.ts
│ ├── const
│ │ ├── mrc20-address.ts
│ │ └── addressList.ts
│ ├── tsconfig.json
│ └── contracts
│ │ └── airdrop.ts
│ ├── .eslintrc.cjs
│ ├── asconfig.json
│ ├── workflows
│ └── ci-tests.yml
│ ├── tsconfig.json
│ ├── as-pect.asconfig.json
│ ├── src
│ ├── utils.ts
│ └── airdrop.ts
│ ├── as-pect.config.js
│ ├── package.json
│ └── README.md
├── async-call
├── .gitignore
├── .eslintrc.cjs
├── .env.example
├── asconfig.json
├── assembly
│ ├── tsconfig.json
│ └── contracts
│ │ └── main.ts
├── src
│ ├── listen.ts
│ ├── deploy.ts
│ ├── utils.ts
│ └── call.ts
├── README.md
└── package.json
├── fungible-token
├── smart-contract
│ ├── .env.example
│ ├── .gitignore
│ ├── .eslintrc.cjs
│ ├── assembly
│ │ ├── __tests__
│ │ │ └── as-pect.d.ts
│ │ ├── tsconfig.json
│ │ └── contracts
│ │ │ └── token.ts
│ ├── asconfig.json
│ ├── .github
│ │ └── workflows
│ │ │ └── ci-tests.yml
│ ├── src
│ │ ├── utils.ts
│ │ └── deploy.ts
│ ├── tsconfig.json
│ ├── as-pect.asconfig.json
│ ├── as-pect.config.js
│ ├── package.json
│ └── README.md
└── front
│ └── react
│ ├── src
│ ├── vite-env.d.ts
│ ├── main.tsx
│ ├── App.css
│ ├── index.css
│ ├── assets
│ │ └── react.svg
│ └── App.tsx
│ ├── tsconfig.json
│ ├── .gitignore
│ ├── index.html
│ ├── vite.config.ts
│ ├── tsconfig.node.json
│ ├── tsconfig.app.json
│ ├── eslint.config.js
│ ├── package.json
│ ├── public
│ └── vite.svg
│ └── README.md
├── deferred-call-manager
├── .gitignore
├── assembly
│ ├── __tests__
│ │ ├── massa-example.spec.ts
│ │ └── as-pect.d.ts
│ ├── tsconfig.json
│ ├── serializable
│ │ └── history.ts
│ ├── contracts
│ │ └── main.ts
│ └── internals.ts
├── .eslintrc.cjs
├── .env.example
├── asconfig.json
├── .github
│ └── workflows
│ │ └── ci-tests.yml
├── src
│ ├── stop.ts
│ ├── history.ts
│ ├── serializable
│ │ └── history.ts
│ ├── listen.ts
│ ├── deploy.ts
│ └── utils.ts
├── tsconfig.json
├── as-pect.asconfig.json
├── as-pect.config.js
├── README.md
└── package.json
├── hello-world
├── smart-contract
│ ├── .gitignore
│ ├── .eslintrc.cjs
│ ├── assembly
│ │ ├── __tests__
│ │ │ ├── as-pect.d.ts
│ │ │ └── massa-example.spec.ts
│ │ ├── tsconfig.json
│ │ └── contracts
│ │ │ └── main.ts
│ ├── .env.example
│ ├── asconfig.json
│ ├── .github
│ │ └── workflows
│ │ │ └── ci-tests.yml
│ ├── tsconfig.json
│ ├── as-pect.asconfig.json
│ ├── as-pect.config.js
│ ├── src
│ │ ├── deploy.ts
│ │ ├── utils.ts
│ │ └── call.ts
│ ├── package.json
│ └── README.md
└── front
│ ├── react
│ ├── src
│ │ ├── vite-env.d.ts
│ │ ├── main.tsx
│ │ ├── App.css
│ │ ├── index.css
│ │ ├── App.tsx
│ │ └── assets
│ │ │ └── react.svg
│ ├── tsconfig.json
│ ├── .gitignore
│ ├── index.html
│ ├── vite.config.ts
│ ├── tsconfig.node.json
│ ├── tsconfig.app.json
│ ├── eslint.config.js
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ └── README.md
│ └── vanilla-js
│ ├── .gitignore
│ ├── vite.config.ts
│ ├── package.json
│ ├── javascript.svg
│ ├── index.html
│ ├── public
│ └── vite.svg
│ ├── style.css
│ └── app.js
├── .gitignore
├── .github
├── workflows
│ ├── helloworld-ci.yml
│ └── helloworld-daily-deploy.yml
└── ISSUE_TEMPLATE
│ ├── task.md
│ └── bug.md
├── LICENSE
├── CONTRIBUTING.md
└── README.md
/airdrop/smart-contract/.env.example:
--------------------------------------------------------------------------------
1 | PRIVATE_KEY=
2 |
--------------------------------------------------------------------------------
/async-call/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | .env
4 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/.env.example:
--------------------------------------------------------------------------------
1 | PRIVATE_KEY=
2 |
--------------------------------------------------------------------------------
/deferred-call-manager/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | .env
4 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | .env
4 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | .env
4 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | .env
4 |
--------------------------------------------------------------------------------
/hello-world/front/react/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/async-call/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@massalabs'],
3 | };
4 |
--------------------------------------------------------------------------------
/fungible-token/front/react/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/deferred-call-manager/assembly/__tests__/massa-example.spec.ts:
--------------------------------------------------------------------------------
1 | describe('TODO', () => {});
2 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@massalabs'],
3 | };
4 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@massalabs'],
3 | };
4 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/assembly/__tests__/as-pect.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/deferred-call-manager/assembly/__tests__/as-pect.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/assembly/__tests__/as-pect.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/assembly/__tests__/as-pect.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | node_modules
3 | .DS_Store
4 | ledger.json
5 | yarn.lock
6 | .vscode
7 | screenshots/
8 | .env
9 |
10 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/assembly/const/mrc20-address.ts:
--------------------------------------------------------------------------------
1 | export const mrc20Address =
2 | 'AS1adMwkCyNFf1XDYCkFGjP4CAGTeSRvUmnjN3Chw6mpmSsLuRnJ';
3 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@massalabs'],
3 | rules: {
4 | 'no-console': 'off',
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/deferred-call-manager/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@massalabs'],
3 | rules: {
4 | 'no-console': 'off',
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/fungible-token/front/react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | { "path": "./tsconfig.app.json" },
5 | { "path": "./tsconfig.node.json" }
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/hello-world/front/react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | { "path": "./tsconfig.app.json" },
5 | { "path": "./tsconfig.node.json" }
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/async-call/.env.example:
--------------------------------------------------------------------------------
1 | PRIVATE_KEY=
2 | #default value
3 | #JSON_RPC_URL_PUBLIC="https://buildnet.massa.net/api/v2:33035"
4 | #for local node
5 | #JSON_RPC_URL_PUBLIC="http://localhost:33035/api/v2"
--------------------------------------------------------------------------------
/deferred-call-manager/.env.example:
--------------------------------------------------------------------------------
1 | PRIVATE_KEY=
2 | #default value
3 | #JSON_RPC_URL_PUBLIC="https://buildnet.massa.net/api/v2:33035"
4 | #for local node
5 | #JSON_RPC_URL_PUBLIC="http://localhost:33035/api/v2"
--------------------------------------------------------------------------------
/hello-world/smart-contract/.env.example:
--------------------------------------------------------------------------------
1 | PRIVATE_KEY=
2 | #default value
3 | #JSON_RPC_URL_PUBLIC="https://buildnet.massa.net/api/v2:33035"
4 | #for local node
5 | #JSON_RPC_URL_PUBLIC="http://localhost:33035/api/v2"
--------------------------------------------------------------------------------
/hello-world/front/react/src/main.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import App from './App.tsx'
4 | import './index.css'
5 |
6 | createRoot(document.getElementById('root')!).render(
7 |
8 |
9 | ,
10 | )
11 |
--------------------------------------------------------------------------------
/fungible-token/front/react/src/main.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import App from './App.tsx'
4 | import './index.css'
5 |
6 | createRoot(document.getElementById('root')!).render(
7 |
8 |
9 | ,
10 | )
11 |
--------------------------------------------------------------------------------
/async-call/asconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "targets": {
3 | "release": {
4 | "sourceMap": true,
5 | "optimizeLevel": 3,
6 | "shrinkLevel": 3,
7 | "converge": true,
8 | "noAssert": false,
9 | "exportRuntime": true,
10 | "bindings": false
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/deferred-call-manager/asconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "targets": {
3 | "release": {
4 | "sourceMap": true,
5 | "optimizeLevel": 3,
6 | "shrinkLevel": 3,
7 | "converge": true,
8 | "noAssert": false,
9 | "exportRuntime": true,
10 | "bindings": false
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/asconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "targets": {
3 | "release": {
4 | "sourceMap": true,
5 | "optimizeLevel": 3,
6 | "shrinkLevel": 3,
7 | "converge": true,
8 | "noAssert": false,
9 | "exportRuntime": true,
10 | "bindings": false
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/asconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "targets": {
3 | "release": {
4 | "sourceMap": true,
5 | "optimizeLevel": 3,
6 | "shrinkLevel": 3,
7 | "converge": true,
8 | "noAssert": false,
9 | "exportRuntime": true,
10 | "bindings": false
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/asconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "targets": {
3 | "release": {
4 | "sourceMap": true,
5 | "optimizeLevel": 3,
6 | "shrinkLevel": 3,
7 | "converge": true,
8 | "noAssert": false,
9 | "exportRuntime": true,
10 | "bindings": false
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/async-call/assembly/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "assemblyscript/std/assembly.json",
3 | "include": [
4 | "**/*.ts"
5 | ],
6 | "typedocOptions": {
7 | "exclude": "assembly/**/__tests__",
8 | "excludePrivate": true,
9 | "excludeProtected": true,
10 | "excludeExternals": true,
11 | "includeVersion": true,
12 | "skipErrorChecking": true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/hello-world/front/react/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/fungible-token/front/react/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/hello-world/front/vanilla-js/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/assembly/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "assemblyscript/std/assembly.json",
3 | "include": [
4 | "**/*.ts"
5 | ],
6 | "typedocOptions": {
7 | "exclude": "assembly/**/__tests__",
8 | "excludePrivate": true,
9 | "excludeProtected": true,
10 | "excludeExternals": true,
11 | "includeVersion": true,
12 | "skipErrorChecking": true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/deferred-call-manager/assembly/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "assemblyscript/std/assembly.json",
3 | "include": [
4 | "**/*.ts"
5 | ],
6 | "typedocOptions": {
7 | "exclude": "assembly/**/__tests__",
8 | "excludePrivate": true,
9 | "excludeProtected": true,
10 | "excludeExternals": true,
11 | "includeVersion": true,
12 | "skipErrorChecking": true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/assembly/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "assemblyscript/std/assembly.json",
3 | "include": [
4 | "**/*.ts"
5 | ],
6 | "typedocOptions": {
7 | "exclude": "assembly/**/__tests__",
8 | "excludePrivate": true,
9 | "excludeProtected": true,
10 | "excludeExternals": true,
11 | "includeVersion": true,
12 | "skipErrorChecking": true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/assembly/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "assemblyscript/std/assembly.json",
3 | "include": [
4 | "**/*.ts"
5 | ],
6 | "typedocOptions": {
7 | "exclude": "assembly/**/__tests__",
8 | "excludePrivate": true,
9 | "excludeProtected": true,
10 | "excludeExternals": true,
11 | "includeVersion": true,
12 | "skipErrorChecking": true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/hello-world/front/vanilla-js/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import { nodePolyfills } from "vite-plugin-node-polyfills";
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [nodePolyfills()],
7 | resolve: {
8 | alias: {
9 | lodash: "lodash-es",
10 | },
11 | },
12 | build: {
13 | rollupOptions: {
14 | external: ["lodash"],
15 | },
16 | },
17 | });
18 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/workflows/ci-tests.yml:
--------------------------------------------------------------------------------
1 | name: massa sc ci tests
2 | on: [push]
3 | jobs:
4 | unit-tests:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v3
8 |
9 | - uses: actions/setup-node@v3
10 | with:
11 | node-version: '18'
12 | cache: 'npm'
13 |
14 | - name: Install
15 | run: npm ci
16 |
17 | -name : Run build
18 | run: npm run build
19 |
--------------------------------------------------------------------------------
/deferred-call-manager/.github/workflows/ci-tests.yml:
--------------------------------------------------------------------------------
1 | name: massa sc ci tests
2 | on: [push]
3 | jobs:
4 | unit-tests:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v3
8 |
9 | - uses: actions/setup-node@v3
10 | with:
11 | node-version: '18'
12 | cache: 'npm'
13 |
14 | - name: Install
15 | run: npm ci
16 |
17 | - name: Test
18 | run: npm run test
19 |
--------------------------------------------------------------------------------
/hello-world/front/react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/.github/workflows/ci-tests.yml:
--------------------------------------------------------------------------------
1 | name: massa sc ci tests
2 | on: [push]
3 | jobs:
4 | unit-tests:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v3
8 |
9 | - uses: actions/setup-node@v3
10 | with:
11 | node-version: '18'
12 | cache: 'npm'
13 |
14 | - name: Install
15 | run: npm ci
16 |
17 | - name: Test
18 | run: npm run test
19 |
--------------------------------------------------------------------------------
/fungible-token/front/react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/.github/workflows/ci-tests.yml:
--------------------------------------------------------------------------------
1 | name: massa sc ci tests
2 | on: [push]
3 | jobs:
4 | unit-tests:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - uses: actions/checkout@v3
8 |
9 | - uses: actions/setup-node@v3
10 | with:
11 | node-version: '18'
12 | cache: 'npm'
13 |
14 | - name: Install
15 | run: npm ci
16 |
17 | - name: Test
18 | run: npm run test
19 |
--------------------------------------------------------------------------------
/fungible-token/front/react/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import { nodePolyfills } from "vite-plugin-node-polyfills";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [react(), nodePolyfills()],
8 | resolve: {
9 | alias: {
10 | lodash: "lodash-es",
11 | },
12 | },
13 | build: {
14 | rollupOptions: {
15 | external: ["lodash"],
16 | },
17 | },
18 | });
19 |
--------------------------------------------------------------------------------
/hello-world/front/react/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import { nodePolyfills } from "vite-plugin-node-polyfills";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [react(), nodePolyfills()],
8 | resolve: {
9 | alias: {
10 | lodash: "lodash-es",
11 | },
12 | },
13 | build: {
14 | rollupOptions: {
15 | external: ["lodash"],
16 | },
17 | },
18 | });
19 |
--------------------------------------------------------------------------------
/deferred-call-manager/src/stop.ts:
--------------------------------------------------------------------------------
1 | import { SmartContract } from '@massalabs/massa-web3';
2 | import { getAccountProvider, getContractAddress } from './utils';
3 |
4 | const provider = await getAccountProvider();
5 | const contractAddress = await getContractAddress();
6 |
7 | const contract = new SmartContract(provider, contractAddress);
8 | const operation = await contract.call('stop');
9 |
10 | await operation.waitSpeculativeExecution();
11 | console.log(
12 | `Recursive deferred call successfully stopped. OperationId: ${operation.id}`,
13 | );
14 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/src/utils.ts:
--------------------------------------------------------------------------------
1 | import * as dotenv from 'dotenv';
2 | import { readFileSync } from 'fs';
3 | import { fileURLToPath } from 'url';
4 | import path from 'path';
5 |
6 | dotenv.config();
7 |
8 | export function getScByteCode(folderName: string, fileName: string): Buffer {
9 | // Obtain the current file name and directory paths
10 | const __filename = fileURLToPath(import.meta.url);
11 | const __dirname = path.dirname(path.dirname(__filename));
12 | return readFileSync(path.join(__dirname, folderName, fileName));
13 | }
14 |
--------------------------------------------------------------------------------
/hello-world/front/react/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "lib": ["ES2023"],
5 | "module": "ESNext",
6 | "skipLibCheck": true,
7 |
8 | /* Bundler mode */
9 | "moduleResolution": "bundler",
10 | "allowImportingTsExtensions": true,
11 | "isolatedModules": true,
12 | "moduleDetection": "force",
13 | "noEmit": true,
14 |
15 | /* Linting */
16 | "strict": true,
17 | "noUnusedLocals": true,
18 | "noUnusedParameters": true,
19 | "noFallthroughCasesInSwitch": true
20 | },
21 | "include": ["vite.config.ts"]
22 | }
23 |
--------------------------------------------------------------------------------
/.github/workflows/helloworld-ci.yml:
--------------------------------------------------------------------------------
1 | name: Helloworld CI
2 |
3 | on:
4 | push:
5 | paths:
6 | - hello-world/**
7 |
8 | defaults:
9 | run:
10 | working-directory: ./hello-world/smart-contract
11 |
12 | jobs:
13 | unit-tests:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v3
17 |
18 | - uses: actions/setup-node@v3
19 | with:
20 | node-version: 18
21 |
22 | - name: Install
23 | run: npm ci
24 |
25 | - name: Code quality
26 | run: npm run fmt:check
27 |
28 | - name: Test
29 | run: npm run test
30 |
--------------------------------------------------------------------------------
/fungible-token/front/react/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "lib": ["ES2023"],
5 | "module": "ESNext",
6 | "skipLibCheck": true,
7 |
8 | /* Bundler mode */
9 | "moduleResolution": "bundler",
10 | "allowImportingTsExtensions": true,
11 | "isolatedModules": true,
12 | "moduleDetection": "force",
13 | "noEmit": true,
14 |
15 | /* Linting */
16 | "strict": true,
17 | "noUnusedLocals": true,
18 | "noUnusedParameters": true,
19 | "noFallthroughCasesInSwitch": true
20 | },
21 | "include": ["vite.config.ts"]
22 | }
23 |
--------------------------------------------------------------------------------
/hello-world/front/vanilla-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vanilla-js",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "devDependencies": {
12 | "@types/events": "^3.0.3",
13 | "@types/node": "^22.2.0",
14 | "vite": "^5.4.0",
15 | "vite-plugin-node-polyfills": "^0.22.0"
16 | },
17 | "dependencies": {
18 | "@massalabs/massa-web3": "^5.1.2-dev",
19 | "@massalabs/wallet-provider": "^3.1.2-dev",
20 | "events": "^3.3.0",
21 | "lodash-es": "^4.17.21"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/deferred-call-manager/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "module": "es2022",
5 | "preserveConstEnums": true,
6 | "moduleResolution": "Node",
7 | "strict": true,
8 | "sourceMap": true,
9 | "target": "es2022",
10 | "types": ["node"]
11 | },
12 | "include": ["./src/**/*.ts"], // Update the include path to match the actual location of your TypeScript files
13 | "exclude": ["node_modules"],
14 | "experimentalDecorators": true,
15 | "ts-node": {
16 | "esm": true,
17 | "experimentalSpecifierResolution": "node"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "module": "es2022",
5 | "preserveConstEnums": true,
6 | "moduleResolution": "Node",
7 | "strict": true,
8 | "sourceMap": true,
9 | "target": "es2022",
10 | "types": ["node"]
11 | },
12 | "include": ["./src/**/*.ts"], // Update the include path to match the actual location of your TypeScript files
13 | "exclude": ["node_modules"],
14 | "experimentalDecorators": true,
15 | "ts-node": {
16 | "esm": true,
17 | "experimentalSpecifierResolution": "node"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "module": "es2022",
5 | "preserveConstEnums": true,
6 | "moduleResolution": "Node",
7 | "strict": true,
8 | "sourceMap": true,
9 | "target": "es2022",
10 | "types": ["node"]
11 | },
12 | "include": ["./src/**/*.ts"], // Update the include path to match the actual location of your TypeScript files
13 | "exclude": ["node_modules"],
14 | "experimentalDecorators": true,
15 | "ts-node": {
16 | "esm": true,
17 | "experimentalSpecifierResolution": "node"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/deferred-call-manager/src/history.ts:
--------------------------------------------------------------------------------
1 | import { deserializeObj } from '@massalabs/massa-web3';
2 | import { History } from './serializable/history';
3 | import { getAccountProvider, getContractAddress } from './utils';
4 |
5 | const provider = await getAccountProvider();
6 | const contractAddress = await getContractAddress();
7 |
8 | const keyFilter = 'hist';
9 | const historyKeys = await provider.getStorageKeys(contractAddress, keyFilter);
10 |
11 | const history = await provider.readStorage(contractAddress, historyKeys);
12 |
13 | history.map((data) => {
14 | const execution = deserializeObj(data, 0, History).instance;
15 | console.log('execution', execution);
16 | });
17 |
--------------------------------------------------------------------------------
/fungible-token/front/react/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "isolatedModules": true,
13 | "moduleDetection": "force",
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"]
24 | }
25 |
--------------------------------------------------------------------------------
/hello-world/front/react/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "isolatedModules": true,
13 | "moduleDetection": "force",
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"]
24 | }
25 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/assembly/const/addressList.ts:
--------------------------------------------------------------------------------
1 | export const addressList = [
2 | 'AU1jCffxJFjMQRg1WkoT1gDiFvZGg1WuogiwBWQFZ2LJwEyHPRPZ',
3 | 'AU1rFqhTWvRyuJT3UH5ZZSBjALcAsjXCPPcgUkWaBghYsYicTrB5',
4 | 'AU1x44P7LWJfy3w6bL7fKmH8CxXzZq8a1odg3WKUoq6iqvs5Kcwv',
5 | 'AU1c3YbxDL5vyaJQ8mGQFBEABmmopMWCdhHQpUxcDkVAU4ya666S',
6 | 'AU1SjbSd8u4sutG7fSuxnPgTbiifrHJGN1paopKwDgDkDDTG8iJo',
7 | 'AU1HG96jNJXKVyqeEuwiTFMwfZvX2WVTjTTq8yzxcdYbSmW7n2Hx',
8 | 'AU1i4ey48VhVbG7YyRJHTZ6mkQTj8NESNCbyf8xDgJWbcEmbX8sk',
9 | 'AU12hrZyu1wCYAx8k76J8gu9gNksFzmpCA9ke21bsjV4wG5rpNN1j',
10 | 'AU1U41TqgyhTsWcXntev86FGm3gUD4vM7cKALJGCfyE2UJKZvYC9',
11 | 'AU1vjHCLS3AVApxm4kUCecuTQJuuZRoUbvsszZabLKZi8WUzAzrX',
12 | ];
13 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "module": "es2022",
5 | "preserveConstEnums": true,
6 | "moduleResolution": "Node",
7 | "strict": true,
8 | "sourceMap": true,
9 | "target": "es2022",
10 | "types": ["node"]
11 | },
12 | "include": ["./src/**/*.ts", "assembly/contracts/test-datastore.ts"], // Update the include path to match the actual location of your TypeScript files
13 | "exclude": ["node_modules"],
14 | "experimentalDecorators": true,
15 | "ts-node": {
16 | "esm": true,
17 | "experimentalSpecifierResolution": "node"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/task.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Task
3 | about: Create a new task for the Innovation team to work on
4 | title: ''
5 | assignees: ''
6 |
7 | ---
8 | **Context**
9 | *Describe / explain why we should do this: motivations, context or other info. Keep it brief and simple - PM*
10 |
11 |
12 | **User flow**
13 | *Describe the user flow using user stories so the end result is super clear - PM*
14 |
15 |
16 | **How to**
17 | *List the step-by-step to get it do if needed - PM*
18 |
19 |
20 | **Technical details**
21 | *Give the technical insights so anyone in the team can tackle the tasks - Dev*
22 |
23 | **QA testing**
24 | *Does this task require some QA tests ?*
25 | *If yes, explain how to validate it*
--------------------------------------------------------------------------------
/fungible-token/smart-contract/assembly/contracts/token.ts:
--------------------------------------------------------------------------------
1 | import { u256 } from 'as-bignum/assembly';
2 | import { mrc20Constructor } from '@massalabs/sc-standards/assembly/contracts/MRC20';
3 |
4 | export function constructor(): void {
5 | mrc20Constructor('MassaToken', 'MT', 18, u256.fromU64(1010101010));
6 | }
7 |
8 | export * from '@massalabs/sc-standards/assembly/contracts/MRC20';
9 | export { mint } from '@massalabs/sc-standards/assembly/contracts/MRC20/mintable';
10 | export {
11 | burn,
12 | burnFrom,
13 | } from '@massalabs/sc-standards/assembly/contracts/MRC20/burnable';
14 | export {
15 | setOwner,
16 | onlyOwner,
17 | isOwner,
18 | } from '@massalabs/sc-standards/assembly/contracts/utils/ownership';
19 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/as-pect.asconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "targets": {
3 | "coverage": {
4 | "lib": ["./node_modules/@as-covers/assembly/index.ts"],
5 | "transform": ["@as-covers/transform", "@as-pect/transform"]
6 | },
7 | "noCoverage": {
8 | "transform": ["@as-pect/transform"]
9 | }
10 | },
11 | "options": {
12 | "exportMemory": true,
13 | "outFile": "output.wasm",
14 | "textFile": "output.wat",
15 | "bindings": "raw",
16 | "exportStart": "_start",
17 | "exportRuntime": true,
18 | "use": ["RTRACE=1"],
19 | "debug": true,
20 | "exportTable": true
21 | },
22 | "extends": "./asconfig.json",
23 | "entries": ["./node_modules/@as-pect/assembly/assembly/index.ts"]
24 | }
--------------------------------------------------------------------------------
/deferred-call-manager/as-pect.asconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "targets": {
3 | "coverage": {
4 | "lib": ["./node_modules/@as-covers/assembly/index.ts"],
5 | "transform": ["@as-covers/transform", "@as-pect/transform"]
6 | },
7 | "noCoverage": {
8 | "transform": ["@as-pect/transform"]
9 | }
10 | },
11 | "options": {
12 | "exportMemory": true,
13 | "outFile": "output.wasm",
14 | "textFile": "output.wat",
15 | "bindings": "raw",
16 | "exportStart": "_start",
17 | "exportRuntime": true,
18 | "use": ["RTRACE=1"],
19 | "debug": true,
20 | "exportTable": true
21 | },
22 | "extends": "./asconfig.json",
23 | "entries": ["./node_modules/@as-pect/assembly/assembly/index.ts"]
24 | }
--------------------------------------------------------------------------------
/hello-world/smart-contract/as-pect.asconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "targets": {
3 | "coverage": {
4 | "lib": ["./node_modules/@as-covers/assembly/index.ts"],
5 | "transform": ["@as-covers/transform", "@as-pect/transform"]
6 | },
7 | "noCoverage": {
8 | "transform": ["@as-pect/transform"]
9 | }
10 | },
11 | "options": {
12 | "exportMemory": true,
13 | "outFile": "output.wasm",
14 | "textFile": "output.wat",
15 | "bindings": "raw",
16 | "exportStart": "_start",
17 | "exportRuntime": true,
18 | "use": ["RTRACE=1"],
19 | "debug": true,
20 | "exportTable": true
21 | },
22 | "extends": "./asconfig.json",
23 | "entries": ["./node_modules/@as-pect/assembly/assembly/index.ts"]
24 | }
--------------------------------------------------------------------------------
/airdrop/smart-contract/src/utils.ts:
--------------------------------------------------------------------------------
1 | import * as dotenv from 'dotenv';
2 | import { readFileSync } from 'fs';
3 | import { fileURLToPath } from 'url';
4 | import path from 'path';
5 | import { SCEvent } from '@massalabs/massa-web3';
6 |
7 | dotenv.config();
8 |
9 | export function getScByteCode(folderName: string, fileName: string): Buffer {
10 | // Obtain the current file name and directory paths
11 | const __filename = fileURLToPath(import.meta.url);
12 | const __dirname = path.dirname(path.dirname(__filename));
13 | return readFileSync(path.join(__dirname, folderName, fileName));
14 | }
15 |
16 | export function logEvent(event: SCEvent, i: number): void {
17 | console.log(`'Event nº ${i + 1}: '${event.data.toString()}`);
18 | }
19 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/as-pect.asconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "targets": {
3 | "coverage": {
4 | "lib": ["./node_modules/@as-covers/assembly/index.ts"],
5 | "transform": ["@as-covers/transform", "@as-pect/transform"]
6 | },
7 | "noCoverage": {
8 | "transform": ["@as-pect/transform"]
9 | }
10 | },
11 | "options": {
12 | "exportMemory": true,
13 | "outFile": "output.wasm",
14 | "textFile": "output.wat",
15 | "bindings": "raw",
16 | "exportStart": "_start",
17 | "exportRuntime": true,
18 | "use": ["RTRACE=1"],
19 | "debug": true,
20 | "exportTable": true
21 | },
22 | "extends": "./asconfig.json",
23 | "entries": ["./node_modules/@as-pect/assembly/assembly/index.ts"]
24 | }
--------------------------------------------------------------------------------
/fungible-token/front/react/eslint.config.js:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import reactHooks from 'eslint-plugin-react-hooks'
4 | import reactRefresh from 'eslint-plugin-react-refresh'
5 | import tseslint from 'typescript-eslint'
6 |
7 | export default tseslint.config({
8 | extends: [js.configs.recommended, ...tseslint.configs.recommended],
9 | files: ['**/*.{ts,tsx}'],
10 | ignores: ['dist'],
11 | languageOptions: {
12 | ecmaVersion: 2020,
13 | globals: globals.browser,
14 | },
15 | plugins: {
16 | 'react-hooks': reactHooks,
17 | 'react-refresh': reactRefresh,
18 | },
19 | rules: {
20 | ...reactHooks.configs.recommended.rules,
21 | 'react-refresh/only-export-components': [
22 | 'warn',
23 | { allowConstantExport: true },
24 | ],
25 | },
26 | })
27 |
--------------------------------------------------------------------------------
/hello-world/front/react/eslint.config.js:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import reactHooks from 'eslint-plugin-react-hooks'
4 | import reactRefresh from 'eslint-plugin-react-refresh'
5 | import tseslint from 'typescript-eslint'
6 |
7 | export default tseslint.config({
8 | extends: [js.configs.recommended, ...tseslint.configs.recommended],
9 | files: ['**/*.{ts,tsx}'],
10 | ignores: ['dist'],
11 | languageOptions: {
12 | ecmaVersion: 2020,
13 | globals: globals.browser,
14 | },
15 | plugins: {
16 | 'react-hooks': reactHooks,
17 | 'react-refresh': reactRefresh,
18 | },
19 | rules: {
20 | ...reactHooks.configs.recommended.rules,
21 | 'react-refresh/only-export-components': [
22 | 'warn',
23 | { allowConstantExport: true },
24 | ],
25 | },
26 | })
27 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a bug report to report a bug and help us to improve sc-examples
4 | title: ''
5 | labels: 'issue:bug'
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 |
15 | Steps to reproduce the behavior:
16 | 1. Go to '...'
17 | 2. Click on '....'
18 | 3. Scroll down to '....'
19 | 4. See error
20 |
21 | **Expected behavior**
22 | A clear and concise description of what you expected to happen.
23 |
24 | **Screenshots**
25 | If applicable, add screenshots to help explain your problem.
26 |
27 | **Desktop (please complete the following information):**
28 | - OS: [e.g. MacOS, Windows...]
29 | - Browser [e.g. chrome, safari]
30 | - Version [e.g. 22]
31 |
32 | **Additional context**
33 | Add any other context about the problem here.
34 |
--------------------------------------------------------------------------------
/deferred-call-manager/assembly/serializable/history.ts:
--------------------------------------------------------------------------------
1 | import { Args, Result, Serializable } from '@massalabs/as-types';
2 |
3 | export class History implements Serializable {
4 | constructor(
5 | public period: u64 = 0,
6 | public thread: u8 = 0,
7 | public callId: string = '',
8 | ) {}
9 |
10 | serialize(): StaticArray {
11 | return new Args()
12 | .add(this.period)
13 | .add(this.thread)
14 | .add(this.callId)
15 | .serialize();
16 | }
17 |
18 | deserialize(data: StaticArray, offset: i32): Result {
19 | const args = new Args(data, offset);
20 |
21 | this.period = args.nextU64().expect("Can't deserialize period.");
22 | this.thread = args.nextU8().expect("Can't deserialize thread.");
23 | this.callId = args.nextString().expect("Can't deserialize callId.");
24 |
25 | return new Result(args.offset);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/deferred-call-manager/src/serializable/history.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Args,
3 | IDeserializedResult,
4 | ISerializable,
5 | } from '@massalabs/massa-web3';
6 |
7 | export class History implements ISerializable {
8 | constructor(
9 | public period: bigint = 0n,
10 | public thread: number = 0,
11 | public callId: string = '',
12 | ) {}
13 |
14 | serialize(): Uint8Array {
15 | const data = new Args()
16 | .addU64(this.period)
17 | .addU8(BigInt(this.thread))
18 | .addString(this.callId)
19 | .serialize();
20 | return new Uint8Array(data);
21 | }
22 |
23 | deserialize(data: Uint8Array, offset: number): IDeserializedResult {
24 | const args = new Args(data, offset);
25 |
26 | this.period = args.nextU64();
27 | this.thread = Number(args.nextU8());
28 | this.callId = args.nextString();
29 |
30 | return { instance: this, offset: args.getOffset() };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/async-call/src/listen.ts:
--------------------------------------------------------------------------------
1 | import { EventPoller, SCEvent } from '@massalabs/massa-web3';
2 | import { scheduler } from 'timers/promises';
3 | import { getAccountProvider, getContractAddress } from './utils';
4 |
5 | const provider = await getAccountProvider();
6 | const contractAddress = await getContractAddress();
7 |
8 | let stop = false;
9 |
10 | const onData = async (events: SCEvent[]) => {
11 | for (const event of events) {
12 | console.log(
13 | `Event period: ${event.context.slot.period} thread: ${event.context.slot.thread} -`,
14 | event.data,
15 | );
16 | }
17 | };
18 |
19 | const onError = (error: Error) => {
20 | console.error('Error:', error);
21 | stop = true;
22 | };
23 | const { stopPolling } = EventPoller.start(
24 | provider,
25 | {
26 | smartContractAddress: contractAddress,
27 | },
28 | onData,
29 | onError,
30 | 5000,
31 | );
32 |
33 | while (!stop) {
34 | await scheduler.wait(5000);
35 | }
36 | stopPolling();
37 |
--------------------------------------------------------------------------------
/deferred-call-manager/src/listen.ts:
--------------------------------------------------------------------------------
1 | import { EventPoller, SCEvent } from '@massalabs/massa-web3';
2 | import { scheduler } from 'timers/promises';
3 | import { getAccountProvider, getContractAddress } from './utils';
4 |
5 | const provider = await getAccountProvider();
6 | const contractAddress = await getContractAddress();
7 |
8 | let stop = false;
9 |
10 | const onData = async (events: SCEvent[]) => {
11 | for (const event of events) {
12 | console.log(
13 | `Event period: ${event.context.slot.period} thread: ${event.context.slot.thread} -`,
14 | event.data,
15 | );
16 | }
17 | };
18 |
19 | const onError = (error: Error) => {
20 | console.error('Error:', error);
21 | stop = true;
22 | };
23 | const { stopPolling } = EventPoller.start(
24 | provider,
25 | {
26 | smartContractAddress: contractAddress,
27 | },
28 | onData,
29 | onError,
30 | 5000,
31 | );
32 |
33 | while (!stop) {
34 | await scheduler.wait(5000);
35 | }
36 | stopPolling();
37 |
--------------------------------------------------------------------------------
/hello-world/front/vanilla-js/javascript.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/deferred-call-manager/as-pect.config.js:
--------------------------------------------------------------------------------
1 | import createMockedABI from '@massalabs/massa-as-sdk/vm-mock';
2 |
3 | export default {
4 | /**
5 | * A set of globs passed to the glob package that qualify typescript files for testing.
6 | */
7 | entries: ['assembly/__tests__/**/*.spec.ts'],
8 | /**
9 | * A set of globs passed to the glob package that quality files to be added to each test.
10 | */
11 | include: ['assembly/__tests__/**/*.include.ts'],
12 | /**
13 | * A set of regexp that will disclude source files from testing.
14 | */
15 | disclude: [/node_modules/],
16 | /**
17 | * Add your required AssemblyScript imports here.
18 | */
19 | async instantiate(memory, createImports, instantiate, binary) {
20 | return createMockedABI(memory, createImports, instantiate, binary);
21 | },
22 | /** Enable code coverage. */
23 | // coverage: ["assembly/**/*.ts"],
24 | /**
25 | * Specify if the binary wasm file should be written to the file system.
26 | */
27 | outputBinary: false,
28 | };
29 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/as-pect.config.js:
--------------------------------------------------------------------------------
1 | import createMockedABI from '@massalabs/massa-as-sdk/vm-mock';
2 |
3 | export default {
4 | /**
5 | * A set of globs passed to the glob package that qualify typescript files for testing.
6 | */
7 | entries: ['assembly/__tests__/**/*.spec.ts'],
8 | /**
9 | * A set of globs passed to the glob package that quality files to be added to each test.
10 | */
11 | include: ['assembly/__tests__/**/*.include.ts'],
12 | /**
13 | * A set of regexp that will disclude source files from testing.
14 | */
15 | disclude: [/node_modules/],
16 | /**
17 | * Add your required AssemblyScript imports here.
18 | */
19 | async instantiate(memory, createImports, instantiate, binary) {
20 | return createMockedABI(memory, createImports, instantiate, binary);
21 | },
22 | /** Enable code coverage. */
23 | // coverage: ["assembly/**/*.ts"],
24 | /**
25 | * Specify if the binary wasm file should be written to the file system.
26 | */
27 | outputBinary: false,
28 | };
29 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/as-pect.config.js:
--------------------------------------------------------------------------------
1 | import createMockedABI from '@massalabs/massa-as-sdk/vm-mock';
2 |
3 | export default {
4 | /**
5 | * A set of globs passed to the glob package that qualify typescript files for testing.
6 | */
7 | entries: ['assembly/__tests__/**/*.spec.ts'],
8 | /**
9 | * A set of globs passed to the glob package that quality files to be added to each test.
10 | */
11 | include: ['assembly/__tests__/**/*.include.ts'],
12 | /**
13 | * A set of regexp that will disclude source files from testing.
14 | */
15 | disclude: [/node_modules/],
16 | /**
17 | * Add your required AssemblyScript imports here.
18 | */
19 | async instantiate(memory, createImports, instantiate, binary) {
20 | return createMockedABI(memory, createImports, instantiate, binary);
21 | },
22 | /** Enable code coverage. */
23 | // coverage: ["assembly/**/*.ts"],
24 | /**
25 | * Specify if the binary wasm file should be written to the file system.
26 | */
27 | outputBinary: false,
28 | };
29 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/as-pect.config.js:
--------------------------------------------------------------------------------
1 | import createMockedABI from '@massalabs/massa-as-sdk/vm-mock';
2 |
3 | export default {
4 | /**
5 | * A set of globs passed to the glob package that qualify typescript files for testing.
6 | */
7 | entries: ['assembly/__tests__/**/*.spec.ts'],
8 | /**
9 | * A set of globs passed to the glob package that quality files to be added to each test.
10 | */
11 | include: ['assembly/__tests__/**/*.include.ts'],
12 | /**
13 | * A set of regexp that will disclude source files from testing.
14 | */
15 | disclude: [/node_modules/],
16 | /**
17 | * Add your required AssemblyScript imports here.
18 | */
19 | async instantiate(memory, createImports, instantiate, binary) {
20 | return createMockedABI(memory, createImports, instantiate, binary);
21 | },
22 | /** Enable code coverage. */
23 | // coverage: ["assembly/**/*.ts"],
24 | /**
25 | * Specify if the binary wasm file should be written to the file system.
26 | */
27 | outputBinary: false,
28 | };
29 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/src/deploy.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | import { Account, Args, Mas, Web3Provider } from '@massalabs/massa-web3';
3 | import { getScByteCode } from './utils';
4 |
5 | async function deploy() {
6 | const account = await Account.fromEnv();
7 | const provider = Web3Provider.buildnet(account);
8 |
9 | console.log('Deploying contract...');
10 |
11 | const byteCode = getScByteCode('build', 'token.wasm');
12 | const tokenArgs = new Args()
13 | .addString('Massa Token')
14 | .addString('MAS')
15 | .addU8(9n)
16 | .addU256(120000000000n * 10n ** 9n);
17 |
18 | const contract = await provider.deploySC({
19 | coins: Mas.fromString('1'),
20 | byteCode,
21 | parameter: tokenArgs.serialize(),
22 | });
23 |
24 | console.log('Contract deployed at:', contract.address);
25 |
26 | const events = await provider.getEvents({
27 | smartContractAddress: contract.address,
28 | });
29 |
30 | for (const event of events) {
31 | console.log('Event: ', event.data);
32 | }
33 | }
34 |
35 | deploy();
36 |
--------------------------------------------------------------------------------
/hello-world/front/vanilla-js/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Message App
7 |
8 |
9 |
10 |
11 |
12 |
Message App
13 |
14 |
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/async-call/src/deploy.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | import { Args, Mas, SmartContract } from '@massalabs/massa-web3';
3 | import { getAccountProvider, getScByteCode } from './utils';
4 |
5 | async function deployContract() {
6 | const provider = await getAccountProvider();
7 |
8 | console.log('Deploying contract...');
9 |
10 | const byteCode = getScByteCode('build', 'main.wasm');
11 |
12 | const constructorArgs = new Args().addString('Massa');
13 |
14 | const contract = await SmartContract.deploy(
15 | provider,
16 | byteCode,
17 | constructorArgs,
18 | { coins: Mas.fromString('1') },
19 | );
20 |
21 | console.log('Contract deployed at:', contract.address);
22 | console.log(
23 | `You might want to add the line: \nCONTRACT_ADDRESS="${contract.address}"\n to your .env file`,
24 | );
25 |
26 | const events = await provider.getEvents({
27 | smartContractAddress: contract.address,
28 | });
29 |
30 | for (const event of events) {
31 | console.log('Event message:', event.data);
32 | }
33 | }
34 |
35 | await deployContract();
36 |
--------------------------------------------------------------------------------
/deferred-call-manager/assembly/contracts/main.ts:
--------------------------------------------------------------------------------
1 | import { Context, Storage } from '@massalabs/massa-as-sdk';
2 | import { Args, stringToBytes, u64ToBytes } from '@massalabs/as-types';
3 | import {
4 | cancelCall,
5 | NEXT_CALL_ID_KEY,
6 | registerCall,
7 | TASK_COUNT_KEY,
8 | } from '../internals';
9 |
10 | // Export task function
11 | export { processTask } from '../internals';
12 |
13 | export function constructor(binArgs: StaticArray): void {
14 | assert(Context.isDeployingContract());
15 |
16 | const period = new Args(binArgs).nextU64().expect('Unable to decode period');
17 |
18 | Storage.set(TASK_COUNT_KEY, u64ToBytes(0));
19 | registerCall(period);
20 | }
21 |
22 | export function getNextCallId(_: StaticArray): StaticArray {
23 | assert(Storage.has(NEXT_CALL_ID_KEY), 'No deferred call planned');
24 | return stringToBytes(Storage.get(NEXT_CALL_ID_KEY));
25 | }
26 |
27 | export function stop(_: StaticArray): void {
28 | assert(Storage.has(NEXT_CALL_ID_KEY), 'No deferred call to stop');
29 | cancelCall(Storage.get(NEXT_CALL_ID_KEY));
30 | }
31 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/src/deploy.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | import { Args, Mas } from '@massalabs/massa-web3';
3 | import { getScByteCode, getAccountProvider } from './utils';
4 |
5 | async function deployContract() {
6 | const provider = await getAccountProvider();
7 |
8 | console.log('Deploying contract...');
9 |
10 | const byteCode = getScByteCode('build', 'main.wasm');
11 |
12 | const constructorArgs = new Args().addString('Massa');
13 |
14 | const contract = await provider.deploySC({
15 | coins: Mas.fromString('1'),
16 | byteCode,
17 | parameter: constructorArgs.serialize(),
18 | });
19 |
20 | console.log('Contract deployed at:', contract.address);
21 | console.log(
22 | `You might want to add the line: \nCONTRACT_ADDRESS="${contract.address}"\n to your .env file`,
23 | );
24 |
25 | const events = await provider.getEvents({
26 | smartContractAddress: contract.address,
27 | });
28 |
29 | for (const event of events) {
30 | console.log('Event message:', event.data);
31 | }
32 | }
33 |
34 | await deployContract();
35 |
--------------------------------------------------------------------------------
/hello-world/front/react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "eslint .",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@massalabs/massa-web3": "^5.1.2-dev",
14 | "@massalabs/wallet-provider": "^3.1.2-dev",
15 | "events": "^3.3.0",
16 | "lodash-es": "^4.17.21",
17 | "react": "^18.3.1",
18 | "react-dom": "^18.3.1"
19 | },
20 | "devDependencies": {
21 | "@eslint/js": "^9.8.0",
22 | "@types/events": "^3.0.3",
23 | "@types/node": "^22.2.0",
24 | "@types/react": "^18.3.3",
25 | "@types/react-dom": "^18.3.0",
26 | "@vitejs/plugin-react": "^4.3.1",
27 | "eslint": "^9.8.0",
28 | "eslint-plugin-react-hooks": "^5.1.0-rc.0",
29 | "eslint-plugin-react-refresh": "^0.4.9",
30 | "globals": "^15.9.0",
31 | "typescript": "^5.5.3",
32 | "typescript-eslint": "^8.0.0",
33 | "vite": "^5.4.0",
34 | "vite-plugin-node-polyfills": "^0.22.0"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/fungible-token/front/react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "eslint .",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@massalabs/massa-web3": "^5.1.2-dev",
14 | "@massalabs/wallet-provider": "^3.1.2-dev",
15 | "events": "^3.3.0",
16 | "lodash-es": "^4.17.21",
17 | "react": "^18.3.1",
18 | "react-dom": "^18.3.1"
19 | },
20 | "devDependencies": {
21 | "@eslint/js": "^9.8.0",
22 | "@types/events": "^3.0.3",
23 | "@types/node": "^22.2.0",
24 | "@types/react": "^18.3.3",
25 | "@types/react-dom": "^18.3.0",
26 | "@vitejs/plugin-react": "^4.3.1",
27 | "eslint": "^9.8.0",
28 | "eslint-plugin-react-hooks": "^5.1.0-rc.0",
29 | "eslint-plugin-react-refresh": "^0.4.9",
30 | "globals": "^15.9.0",
31 | "typescript": "^5.5.3",
32 | "typescript-eslint": "^8.0.0",
33 | "vite": "^5.4.0",
34 | "vite-plugin-node-polyfills": "^0.22.0"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Massa
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/.github/workflows/helloworld-daily-deploy.yml:
--------------------------------------------------------------------------------
1 | name: Helloworld Daily Deploy
2 |
3 | on:
4 | push:
5 | paths:
6 | - hello-world/**
7 | workflow_dispatch:
8 | schedule:
9 | - cron: "0 7 * * *"
10 |
11 | jobs:
12 | deploy-hello-world:
13 | defaults:
14 | run:
15 | working-directory: ./hello-world/smart-contract/
16 |
17 | runs-on: ubuntu-latest
18 |
19 | steps:
20 | - name: Checkout code
21 | uses: actions/checkout@v3
22 |
23 | - name: Install node
24 | uses: actions/setup-node@v3
25 | with:
26 | node-version: "18"
27 | cache: "npm"
28 | cache-dependency-path: ./hello-world/smart-contract/package-lock.json
29 |
30 | - name: Install dependencies
31 | run: npm install
32 |
33 | - name: Deploy
34 | run: |
35 | if npm run deploy | grep -q "Contract deployed"; then
36 | echo "Contract successfully deployed!"
37 | else
38 | echo "Failed to deploy contract ..."
39 | exit 1
40 | fi
41 | env:
42 | JSON_RPC_URL_PUBLIC: ${{ secrets.JSON_RPC_URL_PUBLIC }}
43 | WALLET_PRIVATE_KEY: ${{ secrets.WALLET_PRIVATE_KEY }}
44 |
--------------------------------------------------------------------------------
/hello-world/front/react/src/App.css:
--------------------------------------------------------------------------------
1 | .app-container {
2 | display: flex;
3 | justify-content: center;
4 | align-items: center;
5 | min-height: 100vh;
6 | min-width: 100vw;
7 | background-color: #ffffffa9;
8 | font-family: Arial, sans-serif;
9 | }
10 | .card {
11 | background-color: white;
12 | border-radius: 8px;
13 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
14 | padding: 20px;
15 | width: 300px;
16 | box-sizing: border-box;
17 | }
18 | .card-title {
19 | font-size: 24px;
20 | font-weight: bold;
21 | text-align: center;
22 | margin-bottom: 20px;
23 | }
24 | .form {
25 | display: flex;
26 | flex-direction: column;
27 | }
28 |
29 | .input {
30 | width: 100%;
31 | padding: 10px;
32 |
33 | border: 1px solid #ccc;
34 | border-radius: 4px;
35 | box-sizing: border-box;
36 | }
37 |
38 | .button {
39 | width: 100%;
40 | padding: 10px;
41 | background-color: #4b4b4b;
42 | color: white;
43 | border: none;
44 | border-radius: 4px;
45 | cursor: pointer;
46 | font-size: 16px;
47 | margin-top: 10px;
48 | }
49 | .button:hover {
50 | background-color: #7d7d7d;
51 | }
52 | .message {
53 | margin-top: 20px;
54 | font-size: 18px;
55 | font-weight: bold;
56 | text-align: center;
57 | }
58 |
--------------------------------------------------------------------------------
/deferred-call-manager/README.md:
--------------------------------------------------------------------------------
1 | # Deferred Call Manager Contract
2 |
3 | This contract manages deferred function calls, allowing functions to be scheduled for execution at a later time. It provides mechanisms to add, execute, and remove recursive task using deferred calls. The contract schedule next task execution and store the execution infos like slot and callId. Every task schedule its next execution.
4 |
5 | ## Key Functionalities
6 |
7 | - Start a recursive task to execute every given periods.
8 | - Executing the next deferred call and schedule the next one.
9 | - Stop the task recursion by canceling the next planned call.
10 |
11 | This contract is useful for scenarios where a smart contract needs to be recursively call at fixed time interval.
12 | The execution will last until stopped or contract coins are insufficient to next execution storage or deferred call slot booking fee.
13 |
14 | ## Setup
15 |
16 | ```shell
17 | npm i
18 | ```
19 |
20 | Create `.env` and set `PRIVATE_KEY`:
21 |
22 | ```shell
23 | cp .env.example .env
24 | ```
25 |
26 | ## Deploy
27 |
28 | ```shell
29 | npm run deploy
30 | ```
31 |
32 | ## Listen to Events
33 |
34 | ```shell
35 | npm run listen
36 | ```
37 |
38 | ## Get Execution History
39 |
40 | ```shell
41 | npm run history
42 | ```
43 |
--------------------------------------------------------------------------------
/deferred-call-manager/src/deploy.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | import { Args, Mas, SmartContract } from '@massalabs/massa-web3';
3 | import { getAccountProvider, getScByteCode } from './utils';
4 |
5 | async function deployContract() {
6 | const provider = await getAccountProvider();
7 |
8 | console.log('Deploying contract...');
9 |
10 | const byteCode = getScByteCode('build', 'main.wasm');
11 |
12 | // 1 minutes in period of 16 seconds
13 | const periodInSeconds = 16;
14 | const minutes = 1;
15 | const periods = Math.round((minutes * 60) / periodInSeconds);
16 |
17 | const constructorArgs = new Args().addU64(BigInt(periods));
18 |
19 | const contract = await SmartContract.deploy(
20 | provider,
21 | byteCode,
22 | constructorArgs,
23 | { coins: Mas.fromString('1') },
24 | );
25 |
26 | console.log('Contract deployed at:', contract.address);
27 | console.log(
28 | `You might want to add the line: \nCONTRACT_ADDRESS="${contract.address}"\n to your .env file`,
29 | );
30 |
31 | const events = await provider.getEvents({
32 | smartContractAddress: contract.address,
33 | });
34 |
35 | for (const event of events) {
36 | console.log('Event message:', event.data);
37 | }
38 | }
39 |
40 | await deployContract();
41 |
--------------------------------------------------------------------------------
/async-call/src/utils.ts:
--------------------------------------------------------------------------------
1 | import * as dotenv from 'dotenv';
2 | import { readFileSync } from 'fs';
3 | import { fileURLToPath } from 'url';
4 | import path from 'path';
5 | import 'dotenv/config';
6 | import { Account, Web3Provider } from '@massalabs/massa-web3';
7 |
8 | dotenv.config();
9 |
10 | export async function getContractAddress() {
11 | const contractAddress = process.env.CONTRACT_ADDRESS;
12 | if (!contractAddress) {
13 | throw new Error('CONTRACT_ADDRESS is not set in .env file');
14 | }
15 | return contractAddress;
16 | }
17 | export function getScByteCode(folderName: string, fileName: string): Buffer {
18 | // Obtain the current file name and directory paths
19 | const __filename = fileURLToPath(import.meta.url);
20 | const __dirname = path.dirname(path.dirname(__filename));
21 | return readFileSync(path.join(__dirname, folderName, fileName));
22 | }
23 |
24 | export async function getAccountProvider() {
25 | const account = await Account.fromEnv();
26 |
27 | let provider: Web3Provider;
28 | if (process.env.JSON_RPC_URL_PUBLIC) {
29 | const rpcUrl = process.env.JSON_RPC_URL_PUBLIC;
30 | provider = Web3Provider.fromRPCUrl(rpcUrl, account);
31 | } else {
32 | provider = Web3Provider.buildnet(account);
33 | }
34 | return provider;
35 | }
36 |
--------------------------------------------------------------------------------
/deferred-call-manager/src/utils.ts:
--------------------------------------------------------------------------------
1 | import * as dotenv from 'dotenv';
2 | import { readFileSync } from 'fs';
3 | import { fileURLToPath } from 'url';
4 | import path from 'path';
5 | import 'dotenv/config';
6 | import { Account, Web3Provider } from '@massalabs/massa-web3';
7 |
8 | dotenv.config();
9 |
10 | export async function getContractAddress() {
11 | const contractAddress = process.env.CONTRACT_ADDRESS;
12 | if (!contractAddress) {
13 | throw new Error('CONTRACT_ADDRESS is not set in .env file');
14 | }
15 | return contractAddress;
16 | }
17 | export function getScByteCode(folderName: string, fileName: string): Buffer {
18 | // Obtain the current file name and directory paths
19 | const __filename = fileURLToPath(import.meta.url);
20 | const __dirname = path.dirname(path.dirname(__filename));
21 | return readFileSync(path.join(__dirname, folderName, fileName));
22 | }
23 |
24 | export async function getAccountProvider() {
25 | const account = await Account.fromEnv();
26 |
27 | let provider: Web3Provider;
28 | if (process.env.JSON_RPC_URL_PUBLIC) {
29 | const rpcUrl = process.env.JSON_RPC_URL_PUBLIC;
30 | provider = Web3Provider.fromRPCUrl(rpcUrl, account);
31 | } else {
32 | provider = Web3Provider.buildnet(account);
33 | }
34 | return provider;
35 | }
36 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/assembly/__tests__/massa-example.spec.ts:
--------------------------------------------------------------------------------
1 | import { Args, bytesToString, stringToBytes } from '@massalabs/as-types';
2 | import { constructor, setMessage, getMessage } from '../contracts/main';
3 | import {
4 | Address,
5 | resetStorage,
6 | setDeployContext,
7 | } from '@massalabs/massa-as-sdk';
8 |
9 | const USER1_ADDRESS = new Address(
10 | 'AU12UBnqTHDQALpocVBnkPNy7y5CndUJQTLutaVDDFgMJcq5kQiKq',
11 | );
12 |
13 | describe('Hello world', () => {
14 | beforeEach(() => {
15 | // Remove all data from the data store
16 | resetStorage();
17 | // Needed to call the constructor function
18 | setDeployContext(USER1_ADDRESS.toString());
19 | constructor(new Args().add('Massa test').serialize());
20 | });
21 |
22 | test('Update message', () => {
23 | // Here we use Args object to serialize the message
24 | setMessage(new Args().add('Hello, world!').serialize());
25 | const message = getMessage();
26 | expect(message).toStrictEqual(stringToBytes('Hello, world!'));
27 | });
28 |
29 | test('Get message', () => {
30 | const message = getMessage();
31 | // Because the function returns a StaticArray, we need to convert it to a string
32 | expect(bytesToString(message)).toStrictEqual('Massa test');
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/fungible-token/front/react/src/App.css:
--------------------------------------------------------------------------------
1 | .app-container {
2 | display: flex;
3 | justify-content: center;
4 | align-items: center;
5 | min-height: 100vh;
6 | min-width: 100vw;
7 | background-color: #ffffffa9;
8 | font-family: Arial, sans-serif;
9 | }
10 | .card {
11 | background-color: white;
12 | border-radius: 8px;
13 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
14 | padding: 20px;
15 | box-sizing: border-box;
16 | }
17 | .card-title {
18 | font-size: 24px;
19 | font-weight: bold;
20 | text-align: center;
21 | margin-bottom: 20px;
22 | }
23 | .card-sub-title {
24 | font-size: 16px;
25 | font-weight: bold;
26 | text-align: center;
27 | margin-bottom: 20px;
28 | }
29 |
30 | .form {
31 | display: flex;
32 | flex-direction: column;
33 | }
34 |
35 | .input {
36 | width: 100%;
37 | padding: 10px;
38 | border: 1px solid #ccc;
39 | border-radius: 4px;
40 | box-sizing: border-box;
41 | margin-top: 10px;
42 | }
43 |
44 | .button {
45 | width: 100%;
46 | padding: 10px;
47 | background-color: #4b4b4b;
48 | color: white;
49 | border: none;
50 | border-radius: 4px;
51 | cursor: pointer;
52 | font-size: 16px;
53 | margin-top: 10px;
54 | }
55 | .button:hover {
56 | background-color: #7d7d7d;
57 | }
58 | .message {
59 | margin-top: 20px;
60 | font-size: 18px;
61 | font-weight: bold;
62 | text-align: center;
63 | }
64 |
--------------------------------------------------------------------------------
/hello-world/front/react/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fungible-token/front/react/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fungible-token/front/react/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/hello-world/front/react/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/hello-world/front/vanilla-js/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/src/utils.ts:
--------------------------------------------------------------------------------
1 | import * as dotenv from 'dotenv';
2 | import { readFileSync } from 'fs';
3 | import { fileURLToPath } from 'url';
4 | import path from 'path';
5 | import 'dotenv/config';
6 | import { Account, Web3Provider } from '@massalabs/massa-web3';
7 |
8 | dotenv.config();
9 |
10 | export async function getContractAddress() {
11 | const contractAddress = process.env.CONTRACT_ADDRESS;
12 | if (!contractAddress) {
13 | throw new Error('CONTRACT_ADDRESS is not set in .env file');
14 | }
15 | return contractAddress;
16 | }
17 | export function getScByteCode(folderName: string, fileName: string): Buffer {
18 | // Obtain the current file name and directory paths
19 | const __filename = fileURLToPath(import.meta.url);
20 | const __dirname = path.dirname(path.dirname(__filename));
21 | return readFileSync(path.join(__dirname, folderName, fileName));
22 | }
23 |
24 | export async function getAccountProvider() {
25 | const account = await Account.fromEnv().catch((error) => {
26 | console.log('Error getting account:', error);
27 | console.log('This is expected when deploying from the CI pipeline');
28 | console.log('Using WALLET_PRIVATE_KEY from environment variables');
29 | return Account.fromEnv('WALLET_PRIVATE_KEY');
30 | });
31 |
32 | let provider: Web3Provider;
33 | if (process.env.JSON_RPC_URL_PUBLIC) {
34 | const rpcUrl = process.env.JSON_RPC_URL_PUBLIC;
35 | provider = Web3Provider.fromRPCUrl(rpcUrl, account);
36 | } else {
37 | provider = Web3Provider.buildnet(account);
38 | }
39 | return provider;
40 | }
41 |
--------------------------------------------------------------------------------
/hello-world/front/vanilla-js/style.css:
--------------------------------------------------------------------------------
1 | .app-container {
2 | display: flex;
3 | justify-content: center;
4 | align-items: center;
5 | min-height: 100vh;
6 | min-width: 100vw;
7 | font-family: Arial, sans-serif;
8 | }
9 |
10 | .card {
11 | background-color: white;
12 | border-radius: 8px;
13 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
14 | padding: 20px;
15 | width: 300px;
16 | box-sizing: border-box;
17 | }
18 |
19 | .card-title {
20 | font-size: 24px;
21 | font-weight: bold;
22 | text-align: center;
23 | margin-bottom: 20px;
24 | }
25 |
26 | .input {
27 | width: 100%;
28 | padding: 10px;
29 | border: 1px solid #ccc;
30 | border-radius: 4px;
31 | box-sizing: border-box;
32 | margin-bottom: 10px;
33 | }
34 |
35 | .button {
36 | width: 100%;
37 | padding: 10px;
38 | background-color: #4b4b4b;
39 | color: white;
40 | border: none;
41 | border-radius: 4px;
42 | cursor: pointer;
43 | font-size: 16px;
44 | margin-top: 10px;
45 | }
46 |
47 | .button:hover {
48 | background-color: #7d7d7d;
49 | }
50 |
51 | .message {
52 | margin-top: 20px;
53 | font-size: 18px;
54 | font-weight: bold;
55 | text-align: center;
56 | }
57 |
58 | .error {
59 | color: #ff3333;
60 | font-size: 14px;
61 | position: fixed;
62 | bottom: 20px;
63 | left: 0;
64 | right: 0;
65 | text-align: center;
66 | background-color: rgba(255, 200, 200, 0.9);
67 | padding: 10px;
68 | border-radius: 4px;
69 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
70 | transition: opacity 0.3s ease-in-out;
71 | opacity: 0;
72 | }
73 |
74 | .error.visible {
75 | opacity: 1;
76 | }
77 |
--------------------------------------------------------------------------------
/async-call/src/call.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | import {
3 | Args,
4 | Mas,
5 | OperationStatus,
6 | SmartContract,
7 | } from '@massalabs/massa-web3';
8 | import { getAccountProvider, getContractAddress } from './utils';
9 |
10 | async function triggerAsyncHello(message: string) {
11 | const contractAddress = await getContractAddress();
12 | const provider = await getAccountProvider();
13 |
14 | console.log('Will trigger async hello...');
15 |
16 | const contract = new SmartContract(provider, contractAddress);
17 | const operation = await contract.call(
18 | 'asyncHello', // function name
19 | new Args().serialize(), // arguments
20 | {
21 | // options
22 | coins: Mas.fromString('0.01'), // coins
23 | maxGas: BigInt(3_100_000), // gas limit
24 | fee: Mas.fromString('0.01'), // fee
25 | },
26 | );
27 |
28 | console.log(
29 | 'asyncHello function called successfully, operation id:',
30 | operation.id,
31 | );
32 |
33 | console.log('Waiting for operation to be finalized...');
34 | const status = await operation.waitFinalExecution();
35 | console.log('Operation status:', OperationStatus[status]);
36 | if (status !== OperationStatus.Success) {
37 | throw new Error('Operation failed');
38 | }
39 |
40 | const events = await provider.getEvents({
41 | smartContractAddress: contractAddress,
42 | operationId: operation.id,
43 | });
44 |
45 | for (const event of events) {
46 | console.log(
47 | `Event: "${event.data}" received for operation: ${event.context.origin_operation_id}`,
48 | );
49 | }
50 | }
51 |
52 | await triggerAsyncHello('Hello, Massa friends!');
53 |
--------------------------------------------------------------------------------
/async-call/README.md:
--------------------------------------------------------------------------------
1 | # Async Call Example
2 |
3 | This repository contains an example of an asynchronous smart contract using the Massa blockchain framework. The contract demonstrates how to deploy a contract and schedule asynchronous calls. This contract is based on the Hello World example.
4 |
5 | ## Overview
6 |
7 | The main functionalities of the contract include:
8 |
9 | - **Constructor**: Initializes the contract and stores a message.
10 | - **AsyncHello**: A function that triggers itself asynchronously every two periods.
11 | - **SetMessage**: Updates the stored message in the contract.
12 | - **GetMessage**: Retrieves the stored message from the contract.
13 |
14 | ## Getting Started
15 |
16 | ### Prerequisites
17 |
18 | - Node.js
19 | - npm
20 | - Massa SDK
21 |
22 | ### Installation
23 |
24 | 1. Clone the repository:
25 |
26 | ```bash
27 | git clone https://github.com/massalabs/massa-sc-examples.git
28 | cd massa-sc-examples/async-call
29 | ```
30 |
31 | 2. Install the dependencies:
32 |
33 | ```bash
34 | npm install
35 | ```
36 |
37 | ### Building the Contract
38 |
39 | To compile the smart contract, run:
40 |
41 | ```bash
42 | npm run build
43 | ```
44 |
45 | ### Deploying the Contract
46 |
47 | To deploy the contract, run:
48 |
49 | ```bash
50 | npm run deploy
51 | ```
52 |
53 | ### Triggering the Async Call
54 |
55 | The async call is triggered by the `asyncHello` function. The first time it is called, it schedules the next call and so on.
56 |
57 | To trigger the first async call, run:
58 |
59 | ```bash
60 | npm run call
61 | ```
62 |
63 | ### Watching the Events generated by the Async Call
64 |
65 | To watch the events, run:
66 |
67 | ```bash
68 | npm run listen
69 | ```
70 |
71 | ## License
72 |
73 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/assembly/contracts/main.ts:
--------------------------------------------------------------------------------
1 | import { Context, generateEvent, Storage } from '@massalabs/massa-as-sdk';
2 | import { Args, stringToBytes } from '@massalabs/as-types';
3 |
4 | /**
5 | * This function is meant to be called only one time: when the contract is deployed.
6 | *
7 | * @param binaryArgs - Arguments serialized with Args
8 | */
9 | export function constructor(binaryArgs: StaticArray): void {
10 | // This line is important. It ensures that this function can't be called in the future.
11 | // If you remove this check, someone could call your constructor function and reset your smart contract.
12 | if (!Context.isDeployingContract()) return;
13 |
14 | const args = new Args(binaryArgs);
15 |
16 | const message = args
17 | .nextString()
18 | .expect('Name argument is missing or invalid');
19 |
20 | Storage.set(stringToBytes('messageKey'), stringToBytes(message));
21 | generateEvent(`Constructor called with message ${message}`);
22 | }
23 |
24 | /**
25 | * This function updates the message stored in the contract storage.
26 | *
27 | * @param binaryArgs - Arguments serialized with Args
28 | */
29 | export function setMessage(binaryArgs: StaticArray): void {
30 | const args = new Args(binaryArgs);
31 |
32 | const message = args
33 | .nextString()
34 | .expect('Message argument is missing or invalid');
35 |
36 | Storage.set('messageKey', message);
37 | generateEvent(`Message updated to ${message}`);
38 | }
39 |
40 | /**
41 | * This function returns the message stored in the contract storage.
42 | */
43 | export function getMessage(): StaticArray {
44 | const message = Storage.get('messageKey');
45 | // We could also serialize with Args
46 | return stringToBytes(message);
47 | }
48 |
--------------------------------------------------------------------------------
/hello-world/front/react/README.md:
--------------------------------------------------------------------------------
1 | # React + TypeScript + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
10 | ## Expanding the ESLint configuration
11 |
12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 |
14 | - Configure the top-level `parserOptions` property like this:
15 |
16 | ```js
17 | export default tseslint.config({
18 | languageOptions: {
19 | // other options...
20 | parserOptions: {
21 | project: ['./tsconfig.node.json', './tsconfig.app.json'],
22 | tsconfigRootDir: import.meta.dirname,
23 | },
24 | },
25 | })
26 | ```
27 |
28 | - Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
29 | - Optionally add `...tseslint.configs.stylisticTypeChecked`
30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
31 |
32 | ```js
33 | // eslint.config.js
34 | import react from 'eslint-plugin-react'
35 |
36 | export default tseslint.config({
37 | // Set the react version
38 | settings: { react: { version: '18.3' } },
39 | plugins: {
40 | // Add the react plugin
41 | react,
42 | },
43 | rules: {
44 | // other rules...
45 | // Enable its recommended rules
46 | ...react.configs.recommended.rules,
47 | ...react.configs['jsx-runtime'].rules,
48 | },
49 | })
50 | ```
51 |
--------------------------------------------------------------------------------
/fungible-token/front/react/README.md:
--------------------------------------------------------------------------------
1 | # React + TypeScript + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
10 | ## Expanding the ESLint configuration
11 |
12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 |
14 | - Configure the top-level `parserOptions` property like this:
15 |
16 | ```js
17 | export default tseslint.config({
18 | languageOptions: {
19 | // other options...
20 | parserOptions: {
21 | project: ['./tsconfig.node.json', './tsconfig.app.json'],
22 | tsconfigRootDir: import.meta.dirname,
23 | },
24 | },
25 | })
26 | ```
27 |
28 | - Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
29 | - Optionally add `...tseslint.configs.stylisticTypeChecked`
30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
31 |
32 | ```js
33 | // eslint.config.js
34 | import react from 'eslint-plugin-react'
35 |
36 | export default tseslint.config({
37 | // Set the react version
38 | settings: { react: { version: '18.3' } },
39 | plugins: {
40 | // Add the react plugin
41 | react,
42 | },
43 | rules: {
44 | // other rules...
45 | // Enable its recommended rules
46 | ...react.configs.recommended.rules,
47 | ...react.configs['jsx-runtime'].rules,
48 | },
49 | })
50 | ```
51 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-massa-sc",
3 | "version": "0.0.2",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "asp --summary",
8 | "build": "massa-as-compile",
9 | "clean": "rimraf build",
10 | "deploy": "npm run build && tsx src/deploy.ts",
11 | "prettier": "prettier '**/src/**/*.ts' --check && as-prettier --check assembly",
12 | "prettier:fix": "prettier '**/src/**/*.ts' --write && as-prettier --write assembly",
13 | "lint": "eslint .",
14 | "lint:fix": "eslint . --fix",
15 | "fmt:check": "npm run prettier && npm run lint",
16 | "fmt": "npm run prettier:fix && npm run lint:fix"
17 | },
18 | "keywords": [],
19 | "author": "",
20 | "license": "ISC",
21 | "devDependencies": {
22 | "@as-pect/cli": "^8.1.0",
23 | "@assemblyscript/loader": "^0.27.29",
24 | "@massalabs/as-types": "^2.0.0",
25 | "@massalabs/eslint-config": "^0.0.11",
26 | "@massalabs/massa-as-sdk": "^2.5.4",
27 | "@massalabs/massa-sc-compiler": "^0.2.1-dev",
28 | "@massalabs/massa-sc-deployer": "^1.3.0",
29 | "@massalabs/sc-standards": "^1.3.0",
30 | "@massalabs/massa-web3": "^5.1.2-dev",
31 | "@massalabs/prettier-config-as": "^0.0.2",
32 | "@types/node": "^18.11.10",
33 | "assemblyscript": "^0.27.29",
34 | "assemblyscript-prettier": "^1.0.7",
35 | "dotenv": "^16.0.3",
36 | "prettier": "^2.8.1",
37 | "tslib": "^2.4.0",
38 | "tsx": "^4.7.0",
39 | "typescript": "^4.8.4"
40 | },
41 | "overrides": {
42 | "visitor-as": {
43 | "assemblyscript": "$assemblyscript"
44 | }
45 | },
46 | "type": "module",
47 | "prettier": "@massalabs/prettier-config-as",
48 | "engines": {
49 | "node": ">=16"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/async-call/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-massa-sc",
3 | "version": "0.0.2",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "asp --summary",
8 | "build": "massa-as-compile",
9 | "clean": "rimraf build",
10 | "deploy": "npm run build && tsx src/deploy.ts",
11 | "call": "tsx src/call.ts",
12 | "listen": "tsx src/listen.ts",
13 | "prettier": "prettier '**/src/**/*.ts' --check && as-prettier --check assembly",
14 | "prettier:fix": "prettier '**/src/**/*.ts' --write && as-prettier --write assembly",
15 | "lint": "eslint assembly",
16 | "lint:fix": "eslint assembly --fix",
17 | "fmt:check": "npm run prettier && npm run lint",
18 | "fmt": "npm run prettier:fix && npm run lint:fix"
19 | },
20 | "keywords": [],
21 | "author": "",
22 | "license": "ISC",
23 | "devDependencies": {
24 | "@as-pect/cli": "^8.1.0",
25 | "@assemblyscript/loader": "^0.27.29",
26 | "@massalabs/as-types": "^2.0.0",
27 | "@massalabs/eslint-config": "^0.0.11",
28 | "@massalabs/massa-as-sdk": "^3.0.1-dev",
29 | "@massalabs/massa-sc-compiler": "^0.2.1-dev",
30 | "@massalabs/massa-sc-deployer": "^2.2.0",
31 | "@massalabs/massa-web3": "^5.2.0",
32 | "@massalabs/prettier-config-as": "^0.0.2",
33 | "@types/node": "^18.11.10",
34 | "assemblyscript": "^0.27.29",
35 | "assemblyscript-prettier": "^1.0.7",
36 | "dotenv": "^16.0.3",
37 | "prettier": "^2.8.1",
38 | "tslib": "^2.4.0",
39 | "tsx": "^4.7.0",
40 | "typescript": "^4.8.4"
41 | },
42 | "overrides": {
43 | "visitor-as": {
44 | "assemblyscript": "$assemblyscript"
45 | }
46 | },
47 | "type": "module",
48 | "prettier": "@massalabs/prettier-config-as",
49 | "engines": {
50 | "node": ">=16"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-massa-sc",
3 | "version": "0.0.2",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "asp --summary",
8 | "build": "massa-as-compile",
9 | "clean": "rimraf build",
10 | "deploy": "npm run build && tsx src/deploy.ts",
11 | "call": "tsx src/call.ts",
12 | "prettier": "prettier '**/src/**/*.ts' --check && as-prettier --check assembly",
13 | "prettier:fix": "prettier '**/src/**/*.ts' --write && as-prettier --write assembly",
14 | "lint": "eslint assembly",
15 | "lint:fix": "eslint assembly --fix",
16 | "fmt:check": "npm run prettier && npm run lint",
17 | "fmt": "npm run prettier:fix && npm run lint:fix"
18 | },
19 | "keywords": [],
20 | "author": "",
21 | "license": "ISC",
22 | "devDependencies": {
23 | "@as-pect/cli": "^8.1.0",
24 | "@assemblyscript/loader": "^0.27.29",
25 | "@massalabs/as-types": "^2.0.0",
26 | "@massalabs/eslint-config": "^0.0.11",
27 | "@massalabs/massa-as-sdk": "^3.0.1-dev",
28 | "@massalabs/massa-sc-compiler": "^0.2.1-dev",
29 | "@massalabs/massa-sc-deployer": "^2.2.0",
30 | "@massalabs/massa-web3": "^5.2.0",
31 | "@massalabs/prettier-config-as": "^0.0.2",
32 | "@types/node": "^18.11.10",
33 | "assemblyscript": "^0.27.29",
34 | "assemblyscript-prettier": "^1.0.7",
35 | "dotenv": "^16.0.3",
36 | "prettier": "^2.8.1",
37 | "tslib": "^2.4.0",
38 | "tsx": "^4.7.0",
39 | "typescript": "^4.8.4"
40 | },
41 | "overrides": {
42 | "visitor-as": {
43 | "assemblyscript": "$assemblyscript"
44 | },
45 | "esbuild": "0.19.12"
46 | },
47 | "type": "module",
48 | "prettier": "@massalabs/prettier-config-as",
49 | "engines": {
50 | "node": ">=16"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "execute-airdrop",
3 | "version": "0.0.2",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "asp --summary",
8 | "build": "massa-as-compile",
9 | "clean": "rimraf build",
10 | "airdrop": "npm run build && tsx src/airdrop.ts",
11 | "prettier": "prettier '**/src/**/*.ts' --check && as-prettier --check assembly",
12 | "prettier:fix": "prettier '**/src/**/*.ts' --write && as-prettier --write assembly",
13 | "lint": "eslint .",
14 | "lint:fix": "eslint . --fix",
15 | "fmt:check": "npm run prettier && npm run lint",
16 | "fmt": "npm run prettier:fix && npm run lint:fix"
17 | },
18 | "keywords": [],
19 | "author": "",
20 | "license": "ISC",
21 | "devDependencies": {
22 | "@as-pect/cli": "^8.1.0",
23 | "@assemblyscript/loader": "^0.27.29",
24 | "@massalabs/as-types": "^2.0.0",
25 | "@massalabs/eslint-config": "^0.0.11",
26 | "@massalabs/massa-as-sdk": "^2.5.4-dev",
27 | "@massalabs/massa-sc-compiler": "^0.2.1-dev",
28 | "@massalabs/massa-sc-deployer": "^1.3.0",
29 | "@massalabs/prettier-config-as": "^0.0.2",
30 | "@massalabs/sc-standards": "^1.2.3-dev",
31 | "@types/node": "^18.11.10",
32 | "assemblyscript": "^0.27.29",
33 | "assemblyscript-prettier": "^1.0.7",
34 | "dotenv": "^16.0.3",
35 | "prettier": "^2.8.1",
36 | "tslib": "^2.4.0",
37 | "tsx": "^4.7.0",
38 | "typescript": "^4.8.4"
39 | },
40 | "overrides": {
41 | "visitor-as": {
42 | "assemblyscript": "$assemblyscript"
43 | }
44 | },
45 | "type": "module",
46 | "prettier": "@massalabs/prettier-config-as",
47 | "engines": {
48 | "node": ">=16"
49 | },
50 | "dependencies": {
51 | "@massalabs/massa-web3": "^5.0.1-dev.20241127124628"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/deferred-call-manager/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-massa-sc",
3 | "version": "0.0.2",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "asp --summary",
8 | "build": "massa-as-compile",
9 | "clean": "rimraf build",
10 | "deploy": "npm run build && tsx src/deploy.ts",
11 | "listen": "tsx src/listen.ts",
12 | "history": "tsx src/history.ts",
13 | "stop": "tsx src/stop.ts",
14 | "prettier": "prettier '**/src/**/*.ts' --check && as-prettier --check assembly",
15 | "prettier:fix": "prettier '**/src/**/*.ts' --write && as-prettier --write assembly",
16 | "lint": "eslint .",
17 | "lint:fix": "eslint . --fix",
18 | "fmt:check": "npm run prettier && npm run lint",
19 | "fmt": "npm run prettier:fix && npm run lint:fix"
20 | },
21 | "keywords": [],
22 | "author": "",
23 | "license": "ISC",
24 | "devDependencies": {
25 | "@as-pect/cli": "^8.1.0",
26 | "@assemblyscript/loader": "^0.27.29",
27 | "@massalabs/as-types": "^2.0.0",
28 | "@massalabs/eslint-config": "^0.0.11",
29 | "@massalabs/massa-as-sdk": "^3.0.1-dev",
30 | "@massalabs/massa-sc-compiler": "^0.2.1-dev",
31 | "@massalabs/massa-sc-deployer": "^2.2.0",
32 | "@massalabs/massa-web3": "^5.2.0",
33 | "@massalabs/prettier-config-as": "^0.0.2",
34 | "@types/node": "^18.11.10",
35 | "assemblyscript": "^0.27.29",
36 | "assemblyscript-prettier": "^1.0.7",
37 | "dotenv": "^16.0.3",
38 | "prettier": "^2.8.1",
39 | "tslib": "^2.4.0",
40 | "tsx": "^4.7.0",
41 | "typescript": "^4.8.4"
42 | },
43 | "overrides": {
44 | "visitor-as": {
45 | "assemblyscript": "$assemblyscript"
46 | }
47 | },
48 | "type": "module",
49 | "prettier": "@massalabs/prettier-config-as",
50 | "engines": {
51 | "node": ">=16"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to massa-sc-examples
2 | Thank you for considering contributing to massa-sc-examples!
3 |
4 | ## Reporting Bugs
5 | If you discover a bug, please create a [new issue](https://github.com/massalabs/massa-sc-examples/issues/new?assignees=&labels=issue%3Abug&template=bug.md&title=) on our GitHub repository.
6 | In your issue, please include a clear and concise description of the bug, any relevant code snippets, error messages, and steps to reproduce the issue.
7 |
8 | ## Contributing Code
9 | We welcome contributions in the form of bug fixes, enhancements, and new features.
10 |
11 | To contribute code, please follow these steps:
12 |
13 | 1. Fork the massa-sc-examples repository to your own account.
14 | 2. Create a new branch from the `main` branch for your changes.
15 | 3. Make your changes and commit them to your branch.
16 | 4. Push your branch to your fork.
17 | 5. Create a pull request from your branch to the develop branch of the massa-sc-examples repository.
18 |
19 | > **NOTE:** When creating a pull request, please include a clear and concise title and description of your changes, as well as any relevant context or background information.
20 |
21 | ## Code Style
22 | Please ensure that your code follows the existing code style used in the project.
23 | We use the [MassaLabs Prettier configuration](https://github.com/massalabs/prettier-config-as) and [MassaLabs ESLint configuration](https://github.com/massalabs/eslint-config) for formatting and linting.
24 |
25 | You can run the following command to format your code before committing:
26 |
27 | ```sh
28 | npm run fmt
29 | ```
30 |
31 | ## Tests
32 | Please ensure that your changes include any necessary tests in the CI.
33 | We use [as-pect library](https://as-pect.gitbook.io/as-pect/) for unit testing.
34 |
35 | You can run the following command to run the tests:
36 |
37 | ```sh
38 | npm run test
39 | ```
40 |
41 | ## License
42 | By contributing to massa-sc-examples, you agree that your contributions will be licensed under the MIT License.
43 |
--------------------------------------------------------------------------------
/fungible-token/smart-contract/README.md:
--------------------------------------------------------------------------------
1 | # My Massa Smart-contract Project
2 |
3 | ## Build
4 |
5 | By default this will build all files in `assembly/contracts` directory.
6 |
7 | ```shell
8 | npm run build
9 | ```
10 |
11 | ## Deploy a smart contract
12 |
13 | Prerequisites :
14 |
15 | - You must add a `.env` file at the root of the repository with the following keys set to valid values :
16 | - WALLET_SECRET_KEY="wallet_secret_key"
17 | - JSON_RPC_URL_PUBLIC=
18 |
19 | These keys will be the ones used by the deployer script to interact with the blockchain.
20 |
21 | The following command will build contracts in `assembly/contracts` directory and execute the deployment script
22 | `src/deploy.ts`. This script will deploy on the node specified in the `.env` file.
23 |
24 | ```shell
25 | npm run deploy
26 | ```
27 |
28 | You can modify `src/deploy.ts` to change the smart contract being deployed, and to pass arguments to the constructor
29 | function:
30 |
31 | - line 31: specify what contract you want to deploy
32 | - line 33: create the `Args` object to pass to the constructor of the contract you want to deploy
33 |
34 | When the deployment operation is executed on-chain, the
35 | [constructor](https://github.com/massalabs/massa-sc-toolkit/blob/main/packages/sc-project-initializer/commands/init/assembly/contracts/main.ts#L10)
36 | function of the smart contract being deployed will
37 | be called with the arguments provided in the deployment script.
38 |
39 | The deployment script uses [massa-sc-deployer library](https://www.npmjs.com/package/@massalabs/massa-sc-deployer)
40 | to deploy smart contracts.
41 |
42 | You can edit this script and use [massa-web3 library](https://www.npmjs.com/package/@massalabs/massa-web3)
43 | to create advanced deployment procedure.
44 |
45 | For more information, please visit our ReadTheDocs about
46 | [Massa smart-contract development](https://docs.massa.net/en/latest/web3-dev/smart-contracts.html).
47 |
48 | ## Unit tests
49 |
50 | The test framework documentation is available here: [as-pect docs](https://as-pect.gitbook.io/as-pect)
51 |
52 | ```shell
53 | npm run test
54 | ```
55 |
56 | ## Format code
57 |
58 | ```shell
59 | npm run fmt
60 | ```
61 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/assembly/contracts/airdrop.ts:
--------------------------------------------------------------------------------
1 | import { Address, generateEvent, Storage } from '@massalabs/massa-as-sdk';
2 | import { bytesToU32, stringToBytes, u32ToBytes } from '@massalabs/as-types';
3 | import { u256 } from 'as-bignum/assembly';
4 | import { addressList } from '../const/addressList';
5 | import { mrc20Address } from '../const/mrc20-address';
6 | import { TokenWrapper } from '@massalabs/sc-standards/assembly/contracts/FT';
7 | import { getBalanceEntryCost } from '@massalabs/sc-standards/assembly/contracts//FT/token-external';
8 |
9 | const VERSION_KEY = stringToBytes('airdrop_version'); // Key to store the version of the airdrop
10 | const VERSION = u32(1); // Increment this number to run the airdrop again
11 | const AIRDROP_LIMIT = 850; // Maximum number of transfers per block
12 |
13 | export const MRC20_ADDRESS = new Address(mrc20Address);
14 |
15 | /** Update this value to the amount you wish to airdrop at each account */
16 | const TOKEN_AMOUNT = 20; // Amount of tokens to airdrop
17 |
18 | /**
19 | * Main function to run the airdrop. Will be automatically called when executing the contract.
20 | */
21 | export function main(_: StaticArray): void {
22 | checkAndSetAirdropVersion(); // Can be removed if you know what you are doing
23 | validateAddressLimit();
24 |
25 | const coin = new TokenWrapper(MRC20_ADDRESS);
26 | const decimals = coin.decimals();
27 |
28 | const amount = u256.fromU64(TOKEN_AMOUNT) * u256.fromU64(10 ** decimals);
29 |
30 | for (let i = 0; i < addressList.length; i++) {
31 | const cost = getBalanceEntryCost(mrc20Address, addressList[i]);
32 | generateEvent(cost.toString());
33 | coin.transfer(new Address(addressList[i]), amount, cost);
34 | }
35 |
36 | generateEvent('Airdrop done');
37 | }
38 |
39 | function checkAndSetAirdropVersion(): void {
40 | const previousVersion = Storage.has(VERSION_KEY)
41 | ? bytesToU32(Storage.get(VERSION_KEY))
42 | : 0;
43 |
44 | assert(
45 | VERSION > previousVersion,
46 | `Airdrop already done for version ${VERSION}, please increase version number to ${
47 | previousVersion + 1
48 | }`,
49 | );
50 |
51 | Storage.set(VERSION_KEY, u32ToBytes(VERSION));
52 | }
53 |
54 | function validateAddressLimit(): void {
55 | assert(
56 | addressList.length <= AIRDROP_LIMIT,
57 | 'Too many addresses. The number of transfers exceeds the block limit.',
58 | );
59 | }
60 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/README.md:
--------------------------------------------------------------------------------
1 | # My Massa Smart-contract Project
2 |
3 | ## Build
4 |
5 | By default this will build all files in `assembly/contracts` directory.
6 |
7 | ```shell
8 | npm run build
9 | ```
10 |
11 | ## Deploy a smart contract
12 |
13 | Prerequisites :
14 |
15 | - You must add a `.env` file at the root of the repository with the following keys set to valid values :
16 | - WALLET_SECRET_KEY="wallet_secret_key"
17 | - JSON_RPC_URL_PUBLIC=
18 |
19 | These keys will be the ones used by the deployer script to interact with the blockchain.
20 |
21 | The following command will build contracts in `assembly/contracts` directory and execute the deployment script
22 | `src/deploy.ts`. This script will deploy on the node specified in the `.env` file.
23 |
24 | ```shell
25 | npm run deploy
26 | ```
27 |
28 | You can modify `src/deploy.ts` to change the smart contract being deployed, and to pass arguments to the constructor
29 | function:
30 |
31 | - line 31: specify what contract you want to deploy
32 | - line 33: create the `Args` object to pass to the constructor of the contract you want to deploy
33 |
34 | When the deployment operation is executed on-chain, the
35 | [constructor](https://github.com/massalabs/massa-sc-toolkit/blob/main/packages/sc-project-initializer/commands/init/assembly/contracts/main.ts#L10)
36 | function of the smart contract being deployed will
37 | be called with the arguments provided in the deployment script.
38 |
39 | The deployment script uses [massa-sc-deployer library](https://www.npmjs.com/package/@massalabs/massa-sc-deployer)
40 | to deploy smart contracts.
41 |
42 | You can edit this script and use [massa-web3 library](https://www.npmjs.com/package/@massalabs/massa-web3)
43 | to create advanced deployment procedure.
44 |
45 | For more information, please visit our ReadTheDocs about
46 | [Massa smart-contract development](https://docs.massa.net/en/latest/web3-dev/smart-contracts.html).
47 |
48 | ## Call a smart contract
49 |
50 | Prerequisites :
51 |
52 | - You must update the `.env` file at the root of the repository with the key:
53 | - CONTRACT_ADDRESS=
54 | where `` is the address of the smart contract the deployment script has returned.
55 |
56 | The following command will call the `setMessage` function of the smart contract previously deployed.
57 |
58 | ```shell
59 | npm run call
60 | ```
61 |
62 | ## Unit tests
63 |
64 | The test framework documentation is available here: [as-pect docs](https://as-pect.gitbook.io/as-pect)
65 |
66 | ```shell
67 | npm run test
68 | ```
69 |
70 | ## Format code
71 |
72 | ```shell
73 | npm run fmt
74 | ```
75 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/src/airdrop.ts:
--------------------------------------------------------------------------------
1 | import { Account, Mas, MRC20, Web3Provider } from '@massalabs/massa-web3';
2 | import * as dotenv from 'dotenv';
3 | import { getScByteCode, logEvent } from './utils';
4 | import { addressList } from '../assembly/const/addressList';
5 | import { mrc20Address } from '../assembly/const/mrc20-address';
6 |
7 | dotenv.config();
8 |
9 | /* -------------------------------------------------------------------------- */
10 | /* Init Provider */
11 | /* -------------------------------------------------------------------------- */
12 | const account = await Account.fromEnv();
13 | const provider = Web3Provider.buildnet(account);
14 |
15 | /* -------------------------------------------------------------------------- */
16 | /* Init MRC20 */
17 | /* -------------------------------------------------------------------------- */
18 | const mrc20 = new MRC20(provider, mrc20Address);
19 | const mr20Symbol = await mrc20.symbol();
20 | let mrc20Balance = await mrc20.balanceOf(account.address.toString());
21 |
22 | console.log(`My Mas balance: ${await provider.balance()}`);
23 | console.log(`My ${mr20Symbol} balance: ${mrc20Balance}`);
24 |
25 | /* -------------------------------------------------------------------------- */
26 | /* Airdrop */
27 | /* -------------------------------------------------------------------------- */
28 | const operation = await provider.executeSC({
29 | byteCode: getScByteCode('build', 'airdrop.wasm'),
30 | maxCoins: Mas.fromString('10'), // Maximum amount of coins allowed to be spend during the execution
31 | });
32 |
33 | const events = await operation.getFinalEvents();
34 |
35 | for (const [index, event] of events.entries()) {
36 | if (event.data.toString().includes('Error')) {
37 | throw new Error(`Error in event nº ${index + 1}: ${event.data.toString()}`);
38 | }
39 | logEvent(event, index);
40 | }
41 |
42 | /* -------------------------------------------------------------------------- */
43 | /* Final Balances */
44 | /* -------------------------------------------------------------------------- */
45 |
46 | const balances = await mrc20.balancesOf(addressList);
47 | for (const { address, balance } of balances) {
48 | console.log(`Address: ${address}, Balance: ${balance.toString()}`);
49 | }
50 |
51 | mrc20Balance = await mrc20.balanceOf(account.address.toString());
52 |
53 | console.log('My final MAS balance:', (await provider.balance()).toString());
54 | console.log('My final', mr20Symbol, 'balance:', mrc20Balance.toString());
55 |
--------------------------------------------------------------------------------
/hello-world/smart-contract/src/call.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | import 'dotenv/config';
3 | import {
4 | Account,
5 | Args,
6 | Mas,
7 | Web3Provider,
8 | OperationStatus,
9 | SmartContract,
10 | bytesToStr,
11 | } from '@massalabs/massa-web3';
12 | import { getAccountProvider, getContractAddress } from './utils';
13 |
14 | /**
15 | * Call the `setMessage` function of the smart contract previously deployed.
16 | *
17 | * Prerequisites :
18 | * - You must update the `.env` file at the root of the repository with the key:
19 | * - CONTRACT_ADDRESS="contract_address"
20 | * where `"contract_address"` is the address of the smart contract the deployment
21 | * script has returned.
22 | *
23 | * After the `setMessage` function is called, the smart contract will emit an
24 | * event.
25 | * This function will wait for the event to be emitted and then display the
26 | * event data and the origin operation id.
27 | */
28 | async function callSetMessage(message: string) {
29 | const contractAddress = await getContractAddress();
30 | const provider = await getAccountProvider();
31 |
32 | console.log('Calling setMessage function...');
33 |
34 | const helloContract = new SmartContract(provider, contractAddress);
35 | const operation = await helloContract.call(
36 | 'setMessage',
37 | new Args().addString(message).serialize(),
38 | {
39 | coins: Mas.fromString('0.01'),
40 | },
41 | );
42 |
43 | console.log(
44 | 'setMessage function called successfully, operation id:',
45 | operation.id,
46 | );
47 |
48 | console.log('Waiting for operation to be finalized...');
49 | const status = await operation.waitFinalExecution();
50 | console.log('Operation status:', OperationStatus[status]);
51 | if (status !== OperationStatus.Success) {
52 | throw new Error('Operation failed');
53 | }
54 |
55 | const events = await provider.getEvents({
56 | smartContractAddress: contractAddress,
57 | operationId: operation.id,
58 | });
59 |
60 | for (const event of events) {
61 | console.log(
62 | `Event: "${event.data}" received for operation: ${event.context.origin_operation_id}`,
63 | );
64 | }
65 | }
66 |
67 | async function callGetMessage() {
68 | const contractAddress = await getContractAddress();
69 | const provider = await getAccountProvider();
70 |
71 | const helloContract = new SmartContract(provider, contractAddress);
72 | const message = await helloContract.read(
73 | 'getMessage',
74 | new Args().serialize(),
75 | {
76 | coins: Mas.fromString('0.01'),
77 | },
78 | );
79 |
80 | console.log('Message:', bytesToStr(message.value));
81 | }
82 |
83 | await callSetMessage('Hello, Massa friends!');
84 |
85 | await callGetMessage();
86 |
--------------------------------------------------------------------------------
/async-call/assembly/contracts/main.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Context,
3 | generateEvent,
4 | Storage,
5 | asyncCall,
6 | Slot,
7 | } from '@massalabs/massa-as-sdk';
8 | import { Args, stringToBytes } from '@massalabs/as-types';
9 |
10 | // Constants for asyncCall gas and fee
11 | const ASYNC_CALL_GAS: u64 = 2100_000;
12 | const ASYNC_CALL_FEE: u64 = 1;
13 | const MSG_KEY = 'messageKey';
14 | /**
15 | * This function is meant to be called only one time: when the contract is deployed.
16 | *
17 | * @param binaryArgs - Arguments serialized with Args
18 | */
19 | export function constructor(binaryArgs: StaticArray): void {
20 | // This line is important. It ensures that this function can't be called in the future.
21 | // If you remove this check, someone could call your constructor function and reset your smart contract.
22 | if (!Context.isDeployingContract()) return;
23 |
24 | const args = new Args(binaryArgs);
25 |
26 | const message = args
27 | .nextString()
28 | .expect('Name argument is missing or invalid');
29 |
30 | Storage.set(MSG_KEY, message);
31 | generateEvent(`Constructor called with message ${message}`);
32 | }
33 |
34 | /**
35 | * This function auto triggers itself asynchronously,
36 | * it will call itself every 2 periods.
37 | */
38 | export function asyncHello(): void {
39 | generateEvent(`Hello friend!`);
40 |
41 | const currentPeriod = Context.currentPeriod();
42 | const currentThread = Context.currentThread();
43 |
44 | // Schedule the async call for 2 periods in the future
45 | const startSlot = new Slot(currentPeriod + 2, currentThread);
46 | const endSlot = new Slot(currentPeriod + 3, currentThread);
47 |
48 | asyncCall(
49 | Context.callee(), // target: the current contract
50 | 'asyncHello', // functionName: the function to call asynchronously
51 | startSlot, // startSlot: the slot when the call becomes valid
52 | endSlot, // endSlot: the slot when the call expires
53 | ASYNC_CALL_GAS, // maxGas: maximum gas for the call
54 | ASYNC_CALL_FEE, // rawFee: fee for the call
55 | );
56 |
57 | generateEvent(
58 | `Next call scheduled for period ${startSlot.period} thread ${startSlot.thread}`,
59 | );
60 | }
61 |
62 |
63 | /**
64 | * This function updates the message stored in the contract storage.
65 | *
66 | * @param binaryArgs - Arguments serialized with Args
67 | */
68 | export function setMessage(binaryArgs: StaticArray): void {
69 | const args = new Args(binaryArgs);
70 |
71 | const message = args
72 | .nextString()
73 | .expect('Message argument is missing or invalid');
74 |
75 | Storage.set(MSG_KEY, message);
76 | generateEvent(`Message updated to ${message}`);
77 | }
78 |
79 | /**
80 | * This function returns the message stored in the contract storage.
81 | */
82 | export function getMessage(): StaticArray {
83 | return Storage.get(stringToBytes(MSG_KEY));
84 | }
85 |
--------------------------------------------------------------------------------
/deferred-call-manager/assembly/internals.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Args,
3 | bytesToU64,
4 | stringToBytes,
5 | u64ToBytes,
6 | } from '@massalabs/as-types';
7 | import {
8 | balance,
9 | Context,
10 | deferredCallCancel,
11 | deferredCallExists,
12 | deferredCallQuote,
13 | deferredCallRegister,
14 | findCheapestSlot,
15 | generateEvent,
16 | Storage,
17 | } from '@massalabs/massa-as-sdk';
18 | import { History } from './serializable/history';
19 |
20 | export const NEXT_CALL_ID_KEY = 'callId';
21 | export const HISTORY_KEY = stringToBytes('hist');
22 | export const TASK_COUNT_KEY = stringToBytes('idx');
23 |
24 | export function registerCall(period: u64): void {
25 | const initBal = balance();
26 | generateEvent('Current contract balance: ' + initBal.toString());
27 |
28 | const maxGas = 20_000_000;
29 | const paramsSize = 0;
30 | const bookingPeriod = Context.currentPeriod() + period;
31 | const slot = findCheapestSlot(
32 | bookingPeriod,
33 | bookingPeriod,
34 | maxGas,
35 | paramsSize,
36 | );
37 |
38 | const cost = deferredCallQuote(slot, maxGas, paramsSize);
39 | const callId = deferredCallRegister(
40 | Context.callee().toString(),
41 | 'processTask',
42 | slot,
43 | maxGas,
44 | new Args().add(period).serialize(),
45 | // No need to provide coins as processTask is internal function
46 | 0,
47 | );
48 |
49 | const bookingCost = initBal - balance();
50 |
51 | Storage.set(NEXT_CALL_ID_KEY, callId);
52 | generateEvent(
53 | `Deferred call registered. id: ${callId}. Booked slot period: ${bookingPeriod.toString()}.\
54 | Booking cost: ${bookingCost.toString()}, quote: ${cost.toString()}`,
55 | );
56 | }
57 |
58 | function getTaskIndex(): u64 {
59 | return bytesToU64(Storage.get(TASK_COUNT_KEY));
60 | }
61 |
62 | function getHistoryKey(taskIndex: u64): StaticArray {
63 | return HISTORY_KEY.concat(u64ToBytes(taskIndex));
64 | }
65 |
66 | export function processTask(binArgs: StaticArray): void {
67 | assert(
68 | Context.callee() === Context.caller(),
69 | 'The caller must be the contract itself',
70 | );
71 |
72 | const taskIndex = getTaskIndex();
73 | const callId = Storage.get(NEXT_CALL_ID_KEY);
74 |
75 | generateEvent(`Processing task ${taskIndex}. Call id : ${callId}`);
76 |
77 | // Save execution history
78 | const key = getHistoryKey(taskIndex);
79 | Storage.set(
80 | key,
81 | new History(
82 | Context.currentPeriod(),
83 | Context.currentThread(),
84 | callId,
85 | ).serialize(),
86 | );
87 |
88 | // Increment task index
89 | Storage.set(TASK_COUNT_KEY, u64ToBytes(taskIndex + 1));
90 |
91 | const period = new Args(binArgs).nextU64().expect('Unable to decode period');
92 | registerCall(period);
93 | }
94 |
95 | export function cancelCall(callId: string): void {
96 | if (deferredCallExists(callId)) {
97 | deferredCallCancel(callId);
98 | generateEvent('Deferred call canceled. id : ' + callId);
99 | } else {
100 | generateEvent('Deferred call does not exist. id: ' + callId);
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/hello-world/front/vanilla-js/app.js:
--------------------------------------------------------------------------------
1 | import { getWallets, WalletName } from "@massalabs/wallet-provider";
2 | import { Args, bytesToStr, OperationStatus } from "@massalabs/massa-web3";
3 |
4 | const CONTRACT_ADDRESS =
5 | "AS12mFfp7XA8U5QyRPBWNT5V5BLeEMxuoxHft5Ph8y9uGH2SecDXw";
6 |
7 | let provider;
8 |
9 | function showError(message) {
10 | const errorElement = document.getElementById("errorMessage");
11 | errorElement.textContent = message;
12 | errorElement.classList.add("visible");
13 | setTimeout(() => {
14 | errorElement.classList.remove("visible");
15 | }, 3000);
16 | }
17 |
18 | async function initProvider() {
19 | try {
20 | const walletList = await getWallets();
21 | const wallet = walletList.find(
22 | (provider) => provider.name() === WalletName.MassaWallet
23 | );
24 | if (!wallet) {
25 | throw new Error(
26 | "Wallet not detected. To proceed, please install the Massa wallet and configure it for the Buildnet network"
27 | );
28 | }
29 |
30 | const accounts = await wallet.accounts();
31 |
32 | if (accounts.length === 0) {
33 | throw new Error("No accounts found");
34 | }
35 |
36 | provider = accounts[0];
37 | } catch (error) {
38 | showError(error.message);
39 | }
40 | }
41 |
42 | async function getMessage() {
43 | if (!provider) {
44 | showError("No provider found");
45 | return "";
46 | }
47 | try {
48 | const result = await provider.readSC({
49 | func: "getMessage",
50 | target: CONTRACT_ADDRESS,
51 | });
52 |
53 | return bytesToStr(result.value);
54 | } catch (error) {
55 | showError("Failed to get message: " + error.message);
56 | return "";
57 | }
58 | }
59 |
60 | async function setMessage(message) {
61 | if (!provider) {
62 | showError("No provider found");
63 | return;
64 | }
65 |
66 | if (!message) {
67 | showError("Message cannot be empty");
68 | return;
69 | }
70 |
71 | try {
72 | const op = await provider.callSC({
73 | parameter: new Args().addString(message).serialize(),
74 | func: "setMessage",
75 | target: CONTRACT_ADDRESS,
76 | });
77 |
78 | const status = await op.waitSpeculativeExecution();
79 |
80 | if (status !== OperationStatus.SpeculativeSuccess) {
81 | throw new Error("Transaction failed");
82 | }
83 |
84 | updateMessage();
85 | } catch (error) {
86 | showError("Failed to set message: " + error.message);
87 | }
88 | }
89 |
90 | async function updateMessage() {
91 | const messageElement = document.getElementById("message");
92 | messageElement.textContent = await getMessage();
93 | }
94 |
95 | document.addEventListener("DOMContentLoaded", async () => {
96 | await initProvider();
97 |
98 | if (!provider) {
99 | document.querySelector(".app-container").textContent =
100 | "Loading Provider...";
101 | return;
102 | }
103 |
104 | const form = document.getElementById("messageForm");
105 | const inputMessage = document.getElementById("inputMessage");
106 | const getMessageBtn = document.getElementById("getMessageBtn");
107 |
108 | form.addEventListener("submit", async (e) => {
109 | e.preventDefault();
110 | await setMessage(inputMessage.value);
111 | inputMessage.value = "";
112 | });
113 |
114 | getMessageBtn.addEventListener("click", updateMessage);
115 | });
116 |
--------------------------------------------------------------------------------
/airdrop/smart-contract/README.md:
--------------------------------------------------------------------------------
1 | # Execute Airdrop
2 | ---
3 | ## Overview
4 |
5 | `Execute airdrop` is an example designed to demonstrate the use of `executeSc` for executing smart contracts directly on-chain without deployment. This repository showcases an **Airdrop** smart contract, which distributes MRC20 tokens to a predefined list of addresses in a single atomic operation.
6 |
7 | The **Airdrop** smart contract leverages `executeSc` to ensure that the operation is atomic — if any transaction fails, all transactions in the airdrop revert, preventing partial token distribution.
8 |
9 | ---
10 |
11 | ## Prerequisites
12 |
13 | - [Node.js](https://nodejs.org/) (v18+)
14 | - Massa Account
15 | - [Node.js](https://nodejs.org/) (v18+)
16 | - Massa Account
17 | - MRC20 Token Contract (Deployed). Check the [fungible token standard](https://github.com/massalabs/massa-standards/tree/main/smart-contracts/assembly/contracts/FT) for more details.
18 |
19 |
20 | ## Installation
21 |
22 | 1. Install dependencies:
23 | ```bash
24 | npm install
25 | ```
26 |
27 | 2. Configure environment variables by creating a `.env` file:
28 | ```plaintext
29 | PRIVATE_KEY=your_private_key
30 | ```
31 |
32 | 3. Update the `addressList` in `addressList.ts` with the recipient addresses for the airdrop.
33 | 4. Update MRC20 contract address in `assembly/contracts/mrc20-address.ts` contract.
34 | 5. Update token amount in `airdrop.ts` contract.
35 |
36 |
37 | ## Scripts
38 |
39 | Build the smart contracts:
40 | ```bash
41 | npm run build
42 | ```
43 |
44 | Execute the Airdrop smart contract:
45 | ```bash
46 | npm run airdrop
47 | ```
48 |
49 | ## Smart Contracts
50 |
51 | ### Airdrop Contract
52 | - Distributes an `amount`of Tokens tokens to each address in the predefined `addressList`.
53 | - Key Features:
54 | - Validates that the airdrop has not been executed previously (version control).
55 | - Ensures the number of recipients does not exceed block limits.
56 | - **Important**:
57 | - **Version Tracking**: Update the `VERSION` constant in the `airdrop.ts` contract file before executing a new airdrop.
58 | - **MRC20 Contract Address**: Replace the placeholder MRC20 address in the `assembly/contracts/mrc20-address.ts` file with the actual deployed MRC20 address.
59 |
60 |
61 | ## Usage
62 |
63 | ### Executing the Airdrop
64 | 1. Ensure the MRC20 tokens are minted and available in your wallet.
65 | 2. **Update `airdrop.ts`**:
66 | - Set the correct `VERSION` value if running the airdrop for the first time or after modifications.
67 | - Replace the placeholder MRC20 contract address with the actual one.
68 | 3. Run the Airdrop contract:
69 | `npm run airdrop`
70 |
71 | 4. Check the balances of recipient addresses in `addressList` to verify successful distribution.
72 |
73 |
74 | ## Address List
75 |
76 | The recipient addresses for the airdrop are defined in `addressList.ts`. Update this list with your desired addresses before execution. Limited to 850 addresses per airdrop due to block limits.
77 |
78 | ```typescript
79 | export const addressList = [
80 | 'AU1jCffxJFjMQRg1WkoT1gDiFvZGg1WuogiwBWQFZ2LJwEyHPRPZ',
81 | 'AU1rFqhTWvRyuJT3UH5ZZSBjALcAsjXCPPcgUkWaBghYsYicTrB5',
82 | // Add more addresses as needed
83 | ];
84 | ```
85 |
86 |
87 | ## Notes
88 |
89 | - **Atomic Execution**: Leveraging `executeSc` ensures that either all transactions succeed, or none are executed, preventing partial token distributions.
90 | - **Version Control**: Always update the `VERSION` in the Airdrop contract to prevent accidental reruns.
91 | - **MRC20 Contract Address**: Ensure the MRC20 contract address is updated in `assembly/contracts/mrc20-address` before executing the airdrop.
92 |
--------------------------------------------------------------------------------
/hello-world/front/react/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import "./App.css";
3 | import { getWallets, WalletName } from "@massalabs/wallet-provider";
4 | import {
5 | Args,
6 | bytesToStr,
7 | OperationStatus,
8 | Provider,
9 | } from "@massalabs/massa-web3";
10 |
11 | const CONTRACT_ADDRESS =
12 | "AS12mFfp7XA8U5QyRPBWNT5V5BLeEMxuoxHft5Ph8y9uGH2SecDXw";
13 |
14 | function App() {
15 | const [provider, setProvider] = useState();
16 | const [message, setMessage] = useState("");
17 | const [inputMessage, setInputMessage] = useState("");
18 |
19 | const getMessage = async () => {
20 | if (!provider) {
21 | console.log("No provider found");
22 | return "";
23 | }
24 | const result = await provider.readSC({
25 | func: "getMessage",
26 | target: CONTRACT_ADDRESS,
27 | });
28 |
29 | return bytesToStr(result.value);
30 | };
31 |
32 | async function initProvider() {
33 | const walletList = await getWallets();
34 | const wallet = walletList.find(
35 | (provider) => provider.name() === WalletName.MassaWallet
36 | );
37 | if (!wallet) {
38 | console.log("No wallet found");
39 | return;
40 | }
41 |
42 | const accounts = await wallet?.accounts();
43 |
44 | if (accounts.length === 0) {
45 | console.log("No accounts found");
46 | return;
47 | }
48 |
49 | // We use the first account as the provider
50 | const provider = accounts[0];
51 | setProvider(provider);
52 | }
53 |
54 | useEffect(() => {
55 | initProvider();
56 | }, []);
57 |
58 | const handleSubmit = async (e: React.FormEvent) => {
59 | if (!provider) {
60 | alert("No provider found");
61 | return;
62 | }
63 |
64 | e.preventDefault();
65 |
66 | if (!inputMessage) {
67 | alert("Message cannot be empty");
68 | }
69 |
70 | const op = await provider.callSC({
71 | parameter: new Args().addString(inputMessage).serialize(),
72 | func: "setMessage",
73 | target: CONTRACT_ADDRESS,
74 | });
75 |
76 | const status = await op.waitSpeculativeExecution();
77 |
78 | if (status !== OperationStatus.SpeculativeSuccess) {
79 | alert("Failed to set message");
80 | return;
81 | }
82 |
83 | setMessage(await getMessage());
84 | setInputMessage("");
85 | };
86 |
87 | if (!provider) {
88 | return (
89 |
90 |
Loading Provider...
91 |
92 | Please install the Massa wallet and configure it for the Buildnet
93 | network
94 |
95 |
96 | );
97 | }
98 |
99 | return (
100 |
101 |
102 |
Message App
103 |
115 |
121 |
124 |
125 |
126 | );
127 | }
128 |
129 | export default App;
130 |
--------------------------------------------------------------------------------
/fungible-token/front/react/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/hello-world/front/react/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Massa Smart Contract Development
2 |
3 | This repository provides information and resources for developing smart contracts on the Massa blockchain using the latest tooling.
4 |
5 | > **Important Version Information**
6 | >
7 | > This project uses the next version of Massa development tools, which includes significant improvements and new features. If you need to reference older versions or examples, please check the `legacy` folder in this repository.
8 |
9 | ## Current Tooling
10 |
11 | The Massa blockchain ecosystem now uses the following tools for smart contract development:
12 |
13 | - [Massa Smart Contract Toolkit](https://github.com/massalabs/massa-sc-toolkit): A comprehensive toolkit for developing, testing, and deploying smart contracts on Massa.
14 | - [Massa Web3](https://github.com/massalabs/massa-web3/tree/next): A JavaScript library for interacting with the Massa blockchain.
15 | - [Massa wallet-provider](https://github.com/massalabs/wallet-provider/tree/next): A Web3 provider for connecting to the Massa wallet.
16 |
17 | ## Hello World Project
18 |
19 | This repository includes a Hello World project to help you get started with Massa smart contract development. Here's what you need to know:
20 |
21 | 1. **Smart Contract Setup**:
22 |
23 | - Navigate to the `smart-contract` folder.
24 | - Create a `.env` file in this folder.
25 | - Add a private key that owns some coins to the `.env` file.
26 | - **Important**: Be careful not to push the `.env` file to version control.
27 |
28 | 2. **Testing**:
29 |
30 | - Run tests using the command: `npm run test`
31 |
32 | 3. **Deployment**:
33 | - Check the deploy file to understand how contracts are deployed.
34 | - Deploy the contract using: `npm run deploy`
35 |
36 | # Massa Smart Contract Development
37 |
38 | ## Front-end Implementations
39 |
40 | We provide two front-end implementations for interacting with the smart contract:
41 |
42 | 1. **Vanilla JavaScript Version**:
43 |
44 | - Located in the `vanilla-js` folder.
45 | - Setup: Run `npm install`
46 | - Start the development server: `npm run dev`
47 |
48 | 2. **React Version**:
49 | - Located in the `react` folder.
50 | - Setup: Run `npm install`
51 | - Start the development server: `npm run dev`
52 |
53 | Both versions demonstrate the same functionality but use different technologies.
54 |
55 | ### Vite Configuration and Polyfills
56 |
57 | To ensure compatibility with Vite and to provide necessary polyfills, we have done the following:
58 |
59 | 1. Install required dependencies:
60 |
61 | ```
62 | npm install lodash-es
63 | npm install vite-plugin-node-polyfills
64 | ```
65 |
66 | 2. Create a `vite.config.js` file in your project root with the following content:
67 |
68 | ```javascript
69 | import { defineConfig } from "vite";
70 | import { nodePolyfills } from "vite-plugin-node-polyfills";
71 |
72 | export default defineConfig({
73 | plugins: [nodePolyfills()],
74 | resolve: {
75 | alias: {
76 | lodash: "lodash-es",
77 | },
78 | },
79 | build: {
80 | rollupOptions: {
81 | external: ["lodash"],
82 | },
83 | },
84 | });
85 | ```
86 |
87 | This configuration adds the necessary Node.js polyfills and resolves lodash to its ES module version.
88 |
89 | **Use it in your own Vite projects to ensure compatibility with the Massa Web3 library.**
90 |
91 | ## Resources
92 |
93 | - [Massa Documentation](https://docs.massa.net/)
94 | - [Massa Smart Contract Development Guide](https://docs.massa.net/docs/build/smart-contract/intro)
95 | - [Massa Web3 API Reference (legacy version)](https://web3.docs.massa.net/)
96 | - [Massa official website](https://massa.net/)
97 |
98 | ## Legacy Projects
99 |
100 | For reference to older projects and examples, please check the `legacy` folder in this repository. Note that these projects may use outdated tools or approaches and are kept for historical purposes only.
101 |
102 | ## Contributing
103 |
104 | We welcome contributions to improve smart contract development resources for Massa. Please see the [CONTRIBUTING file](CONTRIBUTING.md) for more information on how to contribute.
105 |
106 | ## License
107 |
108 | This repository is licensed under the [MIT License](LICENSE).
109 |
--------------------------------------------------------------------------------
/fungible-token/front/react/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect, useCallback } from "react";
2 | import "./App.css";
3 | import { getWallets, WalletName } from "@massalabs/wallet-provider";
4 | import { MRC20, OperationStatus, Provider } from "@massalabs/massa-web3";
5 |
6 | const CONTRACT_ADDRESS =
7 | "AS12J2t29NT5VyZVQHBCmQFLNFqwpiZZtwcbHQTHWLJtWFXsz3U96";
8 |
9 | function App() {
10 | const [provider, setProvider] = useState();
11 | const [tokenName, setTokenName] = useState("");
12 | const [tokenSymbol, setTokenSymbol] = useState("");
13 | const [totalSupply, setTotalSupply] = useState(0n);
14 | const [userBalance, setUserBalance] = useState(0n);
15 | const [userAddress, setUserAddress] = useState("");
16 | const [mrc20, setMrc20] = useState();
17 | const [recipientAddress, setRecipientAddress] = useState("");
18 | const [transferAmount, setTransferAmount] = useState("");
19 | const [transferStatus, setTransferStatus] = useState("");
20 |
21 | useEffect(() => {
22 | if (provider) {
23 | setMrc20(new MRC20(provider, CONTRACT_ADDRESS));
24 | }
25 | }, [provider]);
26 |
27 | const fetchTokenInfo = useCallback(async () => {
28 | if (!mrc20) {
29 | console.log("MRC20 instance not initialized");
30 | return;
31 | }
32 |
33 | try {
34 | setTokenName(await mrc20.name());
35 | setTokenSymbol(await mrc20.symbol());
36 | setTotalSupply(await mrc20.totalSupply());
37 | setUserBalance(await mrc20.balanceOf(userAddress));
38 | } catch (error) {
39 | console.error("Error fetching token info:", error);
40 | }
41 | }, [mrc20, userAddress]);
42 |
43 | useEffect(() => {
44 | const initProvider = async () => {
45 | const walletList = await getWallets();
46 | const wallet = walletList.find(
47 | (provider) => provider.name() === WalletName.MassaWallet
48 | );
49 | if (!wallet) {
50 | console.log("No wallet found");
51 | return;
52 | }
53 |
54 | const accounts = await wallet?.accounts();
55 |
56 | if (accounts.length === 0) {
57 | console.log("No accounts found");
58 | return;
59 | }
60 |
61 | const provider = accounts[0];
62 | setProvider(provider);
63 | setUserAddress(await provider.address);
64 | };
65 | initProvider();
66 | }, []);
67 |
68 | useEffect(() => {
69 | if (mrc20) {
70 | fetchTokenInfo();
71 | }
72 | }, [fetchTokenInfo, mrc20]);
73 |
74 | const handleTransfer = async (e: React.FormEvent) => {
75 | e.preventDefault();
76 | if (!mrc20) {
77 | setTransferStatus("MRC20 instance not initialized");
78 | return;
79 | }
80 |
81 | try {
82 | const amount = BigInt(transferAmount);
83 | const operation = await mrc20.transfer(recipientAddress, amount);
84 |
85 | setTransferStatus(`Transfer initiated. Operation ID: ${operation.id}`);
86 |
87 | const status = await operation.waitSpeculativeExecution();
88 |
89 | operation.getSpeculativeEvents().then((events) => {
90 | console.log("Speculative events:", events);
91 | });
92 |
93 | if (status === OperationStatus.SpeculativeSuccess) {
94 | setTransferStatus("Transfer successful!");
95 | fetchTokenInfo(); // Refresh token info after transfer
96 | } else {
97 | setTransferStatus("Transfer failed");
98 | }
99 | } catch (error) {
100 | console.error("Transfer error:", error);
101 | setTransferStatus(`Transfer failed: ${error}`);
102 | }
103 | };
104 |
105 | if (!provider) {
106 | return Loading Provider...
;
107 | }
108 |
109 | return (
110 |
111 |
112 |
Token Info DApp
113 |
114 | Deploy your own token with your address to have a positive balance.
115 |
116 |
117 |
118 | Token Name: {tokenName}
119 |
120 |
121 | Token Symbol: {tokenSymbol}
122 |
123 |
124 | Total Supply: {totalSupply.toString()}
125 |
126 |
127 | Your Address: {userAddress}
128 |
129 |
130 | Your Balance: {userBalance.toString()}
131 |
132 |
133 |
136 |
137 |
Transfer Tokens
138 |
157 | {transferStatus &&
{transferStatus}
}
158 |
159 |
160 | );
161 | }
162 |
163 | export default App;
164 |
--------------------------------------------------------------------------------